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>
85 lines
2.3 KiB
Markdown
85 lines
2.3 KiB
Markdown
# Plexum-openai-provider
|
|
|
|
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 mode.
|
|
|
|
## Status
|
|
|
|
**v0.1**: subprocess-per-turn, JSONL stream parsing, per-workspace
|
|
session continuity via `codex exec resume <thread_id>`. Single model
|
|
`codex` advertised by default; operator can override.
|
|
|
|
## Auth
|
|
|
|
No API key in this plugin's config. The `codex` CLI handles auth via
|
|
`~/.codex/` (ChatGPT login OR `OPENAI_API_KEY`). Run `codex login`
|
|
once (or set env) and this plugin just shells out.
|
|
|
|
## Install
|
|
|
|
```bash
|
|
cd ~/Plexum-openai-provider
|
|
./scripts/install.sh
|
|
```
|
|
|
|
Operator notes in `~/.plexum/plugins/plexum-openai-provider/config.json`:
|
|
|
|
```json
|
|
{
|
|
"binary": "/home/<you>/.local/bin/codex",
|
|
"extra_args": []
|
|
}
|
|
```
|
|
|
|
(absolute path is required when the daemon runs under systemd —
|
|
systemd doesn't inherit shell PATH).
|
|
|
|
Then `.plugins.allow += ["plexum-openai-provider"]` and:
|
|
|
|
```bash
|
|
plexum agent-add --model codex my-agent
|
|
systemctl --user restart plexum
|
|
plexum say --agent-id my-agent --session-id $(plexum new-session --agent-id my-agent) "hello"
|
|
```
|
|
|
|
## How it works
|
|
|
|
Per Plexum turn:
|
|
|
|
```
|
|
codex exec [resume <thread_id>] \
|
|
--skip-git-repo-check \
|
|
--dangerously-bypass-approvals-and-sandbox \
|
|
--json \
|
|
[--model <m>] \
|
|
"<last user message>"
|
|
```
|
|
|
|
cwd = `<agent workspace>`, stdin = `/dev/null` (codex would otherwise
|
|
hang waiting for additional input). Codex emits JSONL:
|
|
|
|
```jsonl
|
|
{"type":"thread.started","thread_id":"..."}
|
|
{"type":"turn.started"}
|
|
{"type":"item.completed","item":{"id":"...","type":"agent_message","text":"..."}}
|
|
{"type":"turn.completed","usage":{"input_tokens":...,...}}
|
|
```
|
|
|
|
`thread.started.thread_id` is captured into
|
|
`<workspace>/.plexum-codex-session` so the next turn passes
|
|
`exec resume <id>` instead of `exec`. `item.completed` of type
|
|
`agent_message` becomes `text_delta`; `turn.completed.usage` populates
|
|
the canonical Usage on `message_end`.
|
|
|
|
## ChatGPT account vs API key
|
|
|
|
ChatGPT-account installs only support the default model; explicit
|
|
`--model gpt-5-codex` etc. returns `400 invalid_request_error`. With
|
|
an API key install, operator can declare more model ids via
|
|
`config.supported_models` + `config.model_args`.
|
|
|
|
## License
|
|
|
|
Same as Plexum.
|