Add Codex JSON sessions and usage limits
This commit is contained in:
1 parent
0862b47f76
commit
6a0202b1b5
14 files changed
+1173
-52
No files matched your search
@@ -1,6 +1,6 @@
|
||||
# ai-app — plan
|
||||
|
||||
A phone interface to AI coding sessions — Claude Code and llama.cpp — built
|
||||
A phone interface to AI coding sessions — Codex, Claude Code and llama.cpp — built
|
||||
to replace the Claude app for day-to-day use. Two motivations: local models
|
||||
need a front end at all, and owning the client means fixing what the official
|
||||
app gets wrong (it won't deliver a typed message until the turn fully
|
||||
@@ -29,11 +29,12 @@ Android app (Compose)
|
||||
backend (Rust/Axum, desktop)
|
||||
├─ SessionManager ── Session ── Driver (trait)
|
||||
│ ├─ ClaudeDriver (claude stream-json over stdio)
|
||||
│ ├─ CodexDriver (codex exec --json, one process per turn)
|
||||
│ ├─ LlamaDriver (llama-server over HTTP)
|
||||
│ └─ EchoDriver (the test rig)
|
||||
│ each driver's process is spawned through a Transport,
|
||||
│ locally or as `ssh host …`, decided by the setup it names
|
||||
├─ usage.rs (Anthropic OAuth usage endpoint, per machine)
|
||||
├─ usage.rs (provider usage meters, per machine)
|
||||
├─ models.rs (HuggingFace browsing and GGUF downloads)
|
||||
├─ files.rs (the file explorer's half of the backend)
|
||||
└─ config.ron + per-session transcript files
|
||||
@@ -79,7 +80,7 @@ axum 0.8, axum-server + rustls, tokio, serde, clap, tracing. Rust edition
|
||||
- `config.rs` — the persisted schema.
|
||||
- `setups.rs` — machines and provider discovery.
|
||||
- `files.rs` — the file explorer (`EXPLORER.md`).
|
||||
- `usage.rs` — Anthropic usage polling, per machine.
|
||||
- `usage.rs` — provider usage polling, per machine.
|
||||
- `models.rs` — HuggingFace browsing and GGUF downloads.
|
||||
- `media.rs` — the image media-type/extension table, shared by the four
|
||||
places that must agree: storing an upload, serving it back, handing one to
|
||||
@@ -87,7 +88,8 @@ axum 0.8, axum-server + rustls, tokio, serde, clap, tracing. Rust edition
|
||||
- `session/mod.rs` — `SessionManager`, the live registry; every mutation
|
||||
funnels through it so in-memory and on-disk state cannot come apart.
|
||||
- `session/driver.rs` — the `Driver` trait and the common event model.
|
||||
- `session/claude.rs`, `session/llama.rs`, `session/echo.rs` — the drivers.
|
||||
- `session/claude.rs`, `session/codex.rs`, `session/llama.rs`,
|
||||
`session/echo.rs` — the drivers.
|
||||
- `session/transcript.rs` — the append-only JSONL event log per session,
|
||||
with monotonically increasing sequence numbers (the phone's resume cursor).
|
||||
- `session/transport.rs`, `ssh.rs` — running a driver's command locally or
|
||||
@@ -146,9 +148,10 @@ server is going away and means to come back) and `stop` (the session is being
|
||||
deleted, so the process must not survive). Every driver owes exactly one of
|
||||
the two.
|
||||
|
||||
`send_user_message` during a run is the point of the whole app: the dialect
|
||||
queues it for injection at the next tool boundary rather than the end of the
|
||||
turn.
|
||||
`send_user_message` during a run is the point of the whole app: a dialect with
|
||||
a live input channel injects it at the next tool boundary. A turn-at-a-time
|
||||
dialect persists it and starts the next turn as soon as the current process
|
||||
ends.
|
||||
|
||||
### Claude driver specifics
|
||||
|
||||
@@ -190,6 +193,34 @@ is the rule behind the import refusal, the single `ClaudeDriver::launch`
|
||||
entry point, and the `Exited` correction below; two CLIs on one session file
|
||||
duplicate the conversation into it and bill the second for re-reading it all.
|
||||
|
||||
### Codex driver specifics (2026-09-07)
|
||||
|
||||
Codex uses `codex exec --json`, whose stdout is JSONL: `thread.started`, turn
|
||||
boundaries, item start/completion records, and the final token usage. The
|
||||
driver translates those records into the same events as every other session
|
||||
and persists the reported thread id. Later turns run `codex exec resume <id>
|
||||
--json`; model, effort and attachments remain launch arguments owned by the
|
||||
driver rather than branches in routes or screens.
|
||||
|
||||
One `exec` process is one turn and exits normally at its end. The session
|
||||
therefore owns a sequence of child processes rather than one permanently idle
|
||||
child: a clean exit after `turn.completed` means `idle`, while an exit before a
|
||||
turn boundary is an error. A process in flight still uses `process.json` plus
|
||||
detached stdout/stderr logs, so it survives and is adopted across a backend
|
||||
restart exactly like the long-lived CLI. Messages received during a turn are
|
||||
persisted and start later turns in order. The JSON exec surface has no stdin
|
||||
steering or interactive approval protocol, so it cannot inject a message at a
|
||||
tool boundary or answer a question inside the same process; those limits are
|
||||
reported rather than guessed around.
|
||||
|
||||
Codex subscription limits come from the CLI's `account/rateLimits/read`
|
||||
app-server request on the machine whose setup runs Codex. This keeps login and
|
||||
token refresh inside the CLI. Its primary and secondary windows are normalized
|
||||
into the existing usage snapshot shape, under provider name `codex`, so the
|
||||
phone and auto-resume need no Codex branch. This is the CLI's local protocol
|
||||
and is treated defensively for the same reason as Claude's undocumented usage
|
||||
endpoint: missing fields or a refusal degrade to an unavailable snapshot.
|
||||
|
||||
### The llama driver
|
||||
|
||||
One `llama-server` per session, started through the same `Transport` as any
|
||||
|
||||
Reference in new issue
Block a user