Feature Summary
- Provide Elixir APIs (
Codex.start_thread/2, Codex.resume_thread/3) that mirror the Python client's thread lifecycle semantics. - Preserve thread metadata (IDs, continuation tokens, default options) and guarantee compatibility with existing fixtures and golden transcripts.
- Ensure thread construction remains stateless and side-effect free until a turn is executed.
Subagent Perspectives
Subagent Astra (API Strategist)
- Align function signatures with idiomatic Elixir while retaining Python parity (
start_thread(options), resume_thread(thread_id, options)). - Introduce
%Codex.Thread{} struct with explicit fields: thread_id, codex_opts, thread_opts, metadata, labels. - Support keyword and map inputs by funneling through
Codex.Options.new/1 and Codex.Thread.Options.new/1. - Document usage with doctests that mirror Python README examples for starting and resuming sessions.
Subagent Borealis (Concurrency Specialist)
- Keep thread factories pure; avoid GenServer interactions inside
start_* to maintain fast, deterministic construction. - Ensure resumed threads validate continuation tokens synchronously and emit telemetry on mismatch.
- Plan for thread struct immutability—mutating per-turn overrides should clone structs to avoid shared state hazards.
Subagent Cypher (Test Architect)
- Author unit tests for option coercion and struct validation, including malformed thread IDs and missing API keys.
- Add characterization tests comparing Python-generated thread metadata JSON with Elixir serialization.
- Create integration test harness that resumes a thread using recorded fixtures to verify continuity of run IDs.
Implementation Tasks
- Build option constructors with guard clauses and meaningful error tuples.
- Implement metadata hydration (
Codex.Thread.Metadata.from_json/1) using typed structs. - Wire resume validation to call lightweight Python parity fixture until codex-rs addition arrives.
TDD Entry Points
- Write failing doctest for
Codex.start_thread/1 returning %Codex.Thread{thread_id: nil}. - Add ExUnit case asserting resumed thread populates metadata from fixture.
- Implement code to satisfy tests, then refactor struct modules into dedicated namespace.
Risks & Mitigations
- Mismatch with Python metadata: lock fixture schema and add contract test; fail fast on unexpected keys.
- State mutation bugs: enforce
%Codex.Thread{} as @enforce_keys; use put_in/2 copies for updates.
Open Questions
- Should thread labels and metadata be stored as
map() or keyword list? Await parity confirmation from Python audit. - How do we expose continuation tokens to callers? Decide whether to surface in struct or keep private.