3 Commits

Author SHA1 Message Date
a27f6bd067 feat(codex): plexum-host MCP exposure + real consume mirror
Three-part wiring so codex agents get full dynamic-tool consume
support:

1. mcp-host subcommand in the plugin binary (routes argv[1] to
   mcpbridge.Run). Reads PLEXUM_MCP_SOCKET / PLEXUM_MCP_AGENT_ID
   from env, baked into codex's `mcp add --env` registration.

2. EnsureCodexMCPRegistered registers a per-agent stable server
   name (plexum-host-<sanitised>) lazily on first turn. Stable
   per-agent socket path via StableSocketPath so codex's
   registration entry and the per-turn bridge listener agree.

3. Post-turn ParseRolloutToolCalls + EmitCodexToolCalls walks the
   matching rollout-*-<thread_id>.jsonl and emits canonical events
   for every function_call + function_call_output pair using
   codex's REAL call_X ids. dynamic.jsonl now has block_ids that
   match codex's session, so consume mirror has real targets.

4. MutateCodexSession rewrites those response_item entries on
   consume: function_call.arguments → "{}" (heavy), output → marker.
   E2E verified: codex resume sees "...(tool called)" instead of
   the original output.
2026-06-01 20:14:06 +01:00
e1c4add9fe fix(runner): write thread id atomically (tmp+rename)
Aligns with anthropic-contractor: a crash mid-write leaves a stale
.plexum-codex-session.tmp instead of an empty real file that would
make the next turn start fresh and lose conversation thread.
2026-06-01 13:45:11 +01:00
33de696653 feat: Plexum-openai-provider v0.1 — OpenAI codex CLI as backend
Plexum ProviderPlugin that wraps the local `codex` CLI binary
(OpenAI Codex CLI ≥ 0.135). Same CLI-driven pattern as
Plexum-gemini-provider and Plexum-anthropic-provider's contractor.

internal/runner/ (~200 LOC):
- Per Plexum turn, fork:
    codex exec [resume <thread_id>] \
      --skip-git-repo-check \
      --dangerously-bypass-approvals-and-sandbox \
      --json \
      [--model <m>] \
      "<last user msg>"
  in agent workspace, with stdin = /dev/null (codex would otherwise
  block waiting for additional input).
- Stream-parses JSONL events:
    thread.started        → save thread_id to .plexum-codex-session
    item.completed        → if type==agent_message, emit text_delta
    turn.completed        → capture usage (input/output/cached/reasoning)
    error / turn.failed   → emit canonical EventError
- Other event types (turn.started, item.started, reasoning, etc.)
  logged at debug, don't produce user-facing events for v1

cmd/plexum-openai-provider-plugin/ implements ProviderPluginWithAgent
(needs AgentContext.Workspace as cwd).

Model surface:
  default: ["codex"]  (no --model flag → CLI default; only thing
                       ChatGPT-account installs support)
  override via config.supported_models + config.model_args for
  API-key installs that want gpt-5 / o3 / etc.

HostConfig (all optional):
  binary           default "codex" (operator should set abs path for
                   systemd PATH)
  extra_args       appended before the prompt
  supported_models override the advertised model list
  model_args       map plexum id → CLI --model value

No api_key field — codex CLI handles auth via ~/.codex/ state
(ChatGPT login OR OPENAI_API_KEY env).

End-to-end verified against local install (ChatGPT login):

1. CLI turn 1:        "OpenAI built me."
2. CLI turn 2 (resume): "I said: 'OpenAI built me.'" (multi-turn ✓)
3. Fabric channel e2e: alice → cx agent → codex CLI → outbound REST →
   seq=23: "Use list comprehensions for concise, readable filtering and
            transformation of iterables."

Known: when daemon runs under systemd PATH doesn't include nvm/local
bin dirs; operator must set absolute binary path in config.json.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-31 20:44:42 +01:00