From 4f46021cbd82681b2c988d97e7d048a781452b35 Mon Sep 17 00:00:00 2001 From: Paulo Fidalgo Date: Fri, 17 Jul 2026 11:28:52 +0100 Subject: [PATCH] docs(readme): generalize public usage Remove comparison-specific positioning, selected model identifiers, and host-application assumptions from the public documentation and gem metadata. Require callers to choose the live smoke model explicitly and add the shared Ethos Link and Reviato attribution used by the other public gems. --- CHANGELOG.md | 4 ++- CONTRIBUTING.md | 6 ++-- README.md | 58 ++++++++++++++++++++++--------------- Rakefile | 3 +- ruby_llm-codex.gemspec | 6 ++-- test/codex_provider_test.rb | 4 +-- 6 files changed, 47 insertions(+), 34 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e77ea9a..5394fc9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Add a local Codex CLI provider for RubyLLM plain-text and structured-output - experiments. + requests. - Add isolated execution defaults, timeout handling, and process-group cleanup. - Add live smoke coverage for plain-text and structured-output requests. - Add CI, Conventional Commit checks, changelog validation, and tag-driven @@ -24,3 +24,5 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 during completion-only runs. - Align the documented Ruby requirement, CI matrix, syntax target, and locked development dependencies on Ruby 3.3 or newer. +- Generalize documentation examples and live smoke configuration for public + reuse. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1ea6ff6..6482f6c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -21,11 +21,11 @@ bundle exec lefthook install bundle exec rake ``` -The authenticated smoke test is separate because it invokes the real Codex CLI -and consumes subscription allowance: +The authenticated smoke test is separate because it invokes the real Codex CLI. +Choose a model available to your configured account: ```bash -bundle exec rake codex:smoke +CODEX_MODEL=your-model bundle exec rake codex:smoke ``` Run it inside an appropriate process and memory boundary when changing process diff --git a/README.md b/README.md index 5a7ce0e..a616781 100644 --- a/README.md +++ b/README.md @@ -4,18 +4,17 @@ [![Gem Version](https://badge.fury.io/rb/ruby_llm-codex.svg)](https://rubygems.org/gems/ruby_llm-codex) [![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) -This small adapter lets RubyLLM invoke the official local Codex CLI as a -provider. Codex reuses the ChatGPT login stored by `codex login`, so these runs -consume your Codex subscription allowance rather than OpenAI API credits. +This adapter lets RubyLLM invoke the official local Codex CLI as a provider. It +supports text completions and structured output through RubyLLM's familiar chat +interface. -The intended use is controlled prompt comparison, especially structured-output -experiments. It is not intended to turn a personal ChatGPT subscription into a -public API. +Authentication is handled by the Codex CLI using the account configured by +`codex login`; the gem does not accept or store an OpenAI API key. -This measures **Codex harness output**, not a raw model API response. Codex adds -its own base agent instructions and runtime behavior. RubyLLM system messages -are layered in as Codex developer instructions, which is the closest supported -mapping but not an identical wire-level experiment. +Responses come from the **Codex agent harness**, not directly from a raw model +API. Codex applies its own base instructions and runtime behavior. RubyLLM system +messages are passed as Codex developer instructions, which is the closest +supported mapping but not an identical wire-level request. ## Requirements @@ -56,16 +55,15 @@ Require the gem and use Codex as an explicit RubyLLM provider: ```ruby require "ruby_llm-codex" -class ResultSchema < RubyLLM::Schema +class SummarySchema < RubyLLM::Schema string :summary - integer :score end -response = RubyLLM.chat(model: "gpt-5.6-luna", provider: :codex) - .with_instructions("Evaluate the supplied text consistently.") - .with_schema(ResultSchema) +response = RubyLLM.chat(model: ENV.fetch("CODEX_MODEL"), provider: :codex) + .with_instructions("Return a concise summary.") + .with_schema(SummarySchema) .with_thinking(effort: :medium) - .ask("The text to evaluate") + .ask("The text to summarize") pp response.content ``` @@ -90,7 +88,7 @@ By default every request: - passes RubyLLM's JSON schema through `--output-schema`. This prevents local `AGENTS.md`, plugins, MCP servers, repository contents, and -saved session history from quietly affecting a comparison. +saved session history from quietly affecting a request. ## Configuration @@ -101,7 +99,7 @@ To deliberately let Codex inspect a repository or use selected configuration: ```ruby chat.with_params( codex: { - working_directory: Rails.root.to_s, + working_directory: "/path/to/project", sandbox: "read-only", ignore_user_config: false, ephemeral: true, @@ -143,9 +141,9 @@ instructions. Those settings, plus `features.shell_snapshot` and execution backend for your application. - Temperature is rejected because this Codex path does not expose it. - Fresh `codex exec` process per RubyLLM completion. This prioritizes isolation - and simple comparisons over throughput. + and predictable behavior over throughput. - Multi-turn RubyLLM histories are serialized into a role-labelled transcript. - One-shot `with_instructions(...).ask(...)` experiments have the cleanest + One-shot `with_instructions(...).ask(...)` requests have the most direct semantic mapping. If you later need streaming, persistent threads, or high throughput, replace @@ -162,7 +160,7 @@ client while keeping the same RubyLLM provider surface. explicitly disables Codex shell snapshots, which are unnecessary for its completion-only execution and previously caused runaway Bash processes. - **Local instructions affect output:** keep `ignore_user_config: true` and do - not set a working directory when you need isolated comparisons. + not set a working directory when you need isolated requests. ## Development @@ -185,11 +183,12 @@ The default Rake task runs the unit suite and Standard Ruby. CI runs the same gate on Ruby 3.3, 3.4, and 4.0.3, then validates commit messages and git-cliff changelog generation. -The authenticated smoke task is intentionally separate because it consumes -Codex subscription allowance: +The authenticated smoke task is intentionally separate because it sends real +requests through the configured Codex account. Choose a model available to that +account: ```bash -bundle exec rake codex:smoke +CODEX_MODEL=your-model bundle exec rake codex:smoke ``` When changing process lifecycle or shell execution, run that task inside a @@ -244,3 +243,14 @@ the [Code of Conduct](CODE_OF_CONDUCT.md). Security reports should follow ## License MIT License. See [LICENSE](LICENSE). + +## About + +Made by the team at [Ethos Link](https://www.ethos-link.com) — practical +software for growing businesses. We build tools for hospitality operators who +need clear workflows, fast onboarding, and real human support. + +We also build [Reviato](https://www.reviato.com), “Capture. Interpret. Act.”. +Turn guest feedback into clear next steps for your team. Collect private +appraisals, spot patterns across reviews, and act before small issues turn into +public ones. diff --git a/Rakefile b/Rakefile index 5e8548d..4ec8d51 100644 --- a/Rakefile +++ b/Rakefile @@ -144,7 +144,8 @@ namespace :codex do desc "Run live plain-text and structured-output smoke tests through Codex CLI" task :smoke do cli_path = ENV.fetch("CODEX_BIN", "codex") - model = ENV.fetch("CODEX_MODEL", "gpt-5.4") + model = ENV["CODEX_MODEL"] + raise "Set CODEX_MODEL to a model available in your Codex account" if model.nil? || model.empty? timeout = Float(ENV.fetch("CODEX_TIMEOUT", RubyLLM::Providers::Codex::DEFAULT_TIMEOUT)) version_output, version_status = Open3.capture2e(cli_path, "--version") raise "Could not run #{cli_path.inspect}: #{version_output.strip}" unless version_status.success? diff --git a/ruby_llm-codex.gemspec b/ruby_llm-codex.gemspec index 5ce915e..efac0c8 100644 --- a/ruby_llm-codex.gemspec +++ b/ruby_llm-codex.gemspec @@ -9,9 +9,9 @@ Gem::Specification.new do |spec| spec.email = ["devel@ethos-link.com"] spec.summary = "Use a local, ChatGPT-authenticated Codex CLI as a RubyLLM provider" spec.description = <<~TEXT.strip - A small RubyLLM provider for controlled model comparisons. It invokes the - official Codex CLI, reuses local ChatGPT authentication, and maps RubyLLM - structured-output schemas to Codex output schemas. + A RubyLLM provider that invokes the official Codex CLI, reuses local ChatGPT + authentication, and maps RubyLLM structured-output schemas to Codex output + schemas. TEXT spec.homepage = "https://github.com/ethos-link/ruby_llm-codex" spec.license = "MIT" diff --git a/test/codex_provider_test.rb b/test/codex_provider_test.rb index b1bb5d2..85651a3 100644 --- a/test/codex_provider_test.rb +++ b/test/codex_provider_test.rb @@ -109,7 +109,7 @@ def test_provider_options_are_forwarded_with_explicit_precedence .with_params( codex: { working_directory: @directory, - profile: "experiment", + profile: "custom-profile", codex_home:, sandbox: "read-only", ignore_user_config: false, @@ -122,7 +122,7 @@ def test_provider_options_are_forwarded_with_explicit_precedence assert_equal @directory, invocation.fetch("working_directory") assert_equal File.expand_path(codex_home), invocation.fetch("codex_home") - assert_equal "experiment", invocation.fetch("profile") + assert_equal "custom-profile", invocation.fetch("profile") assert_equal "read-only", invocation.fetch("sandbox") refute invocation.fetch("ignore_user_config") refute invocation.fetch("ephemeral")