mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-10 17:29:41 +02:00
feat(cli): add codeman agent — session-to-session verbs for every CLI mode
The agent skill teaches the session verbs to claude only (Codeman seeds its preamble for local claude sessions). An opencode, codex, pi or gemini agent has the same environment — CODEMAN_MUX, CODEMAN_SESSION_ID and CODEMAN_API_URL are exported into every pane — and nothing that teaches it the verbs, so `codeman agent ls|spawn|send|wait|read|interrupt|rm` packages them as commands. It is a client of the server, like `codeman tui`, and stays out of `codeman session` (which drives the in-process SessionManager). No new route and no second transport: everything goes through CODEMAN_API_URL, so auth, ownership and the per-session waiter cap apply unchanged. Credentials and the Basic header come from src/codeman-credentials.ts, in the same order attach and the TUI use. Invariants, each in test/cli-agent.test.ts: - Refuses outside a Codeman session (CODEMAN_MUX=1 + CODEMAN_API_URL); never guesses a URL. - `send` takes the prompt as ONE argument (an unquoted multi-line `$(…)` would otherwise be split by the shell and re-joined into one line), transmits printable text plus Enter only, and refuses multi-line input loudly instead of letting sendInput weld the lines. No resend loop of its own: the server's SubmitVerifier owns the swallowed-Enter case. ESC exists only as `interrupt`, which never appends Enter. - `rm` fails closed: empty id, an unprovable self id, or a prefix match in either direction refuses. - Nothing mode-shaped in the CLI: the readiness mark `spawn` waits for comes from the registry (new `capabilities.composerReadyMark`: claude's composer hint `shift+tab`, deepseek's `❯`), `read` relies on the route's own answer dispatch, and a `stop`/`blocked` the session cannot fire is the server's 400, passed through. A `/wait` timeout is a 200 with `timedOut`: exit 2 with a neutral line, not an error. A worker that dies during spawn's readiness wait is exit 3, like every other wait. - `X-Codeman-Agent-Origin` rides only spawn's quick-start, the one request that may create a case directory; every other verb leaves it off. Server-side, test/routes/agent-case-marker-routes.test.ts pins that a POST /api/sessions on an existing workingDir is never labelled, header or not, and that quick-start labels only a directory it creates. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
6d862d5323
commit
0481db569d
@@ -466,6 +466,10 @@ geometry was read. The capture runs synchronous tmux calls on the server; the
|
||||
| `tail=<bytes>` | Keep the newest `<bytes>` of the result (`truncationReason: 'tail'` when it cut). |
|
||||
| `lines=<n>` | With `full=1` only: read at most `<n>` lines of tmux history above the visible frame. An integer of at least 1, clamped to the configured history limit; absent or malformed, the whole limit (100,000 lines by default), as before. `truncated` and `truncationReason` describe byte cuts only, not this bound. Without it a full capture reads all of that history before `tail` cuts it, so a client that keeps a fixed number of lines (the tile grid sends its xterm's scrollback plus its rows) should send it. |
|
||||
|
||||
## The `codeman agent` CLI (client over these endpoints)
|
||||
|
||||
`codeman agent ls|spawn|send|wait|read|interrupt|rm` (`src/cli-agent.ts`) is the command-line client for the endpoints above, for agents in modes that never receive the claude-only skill preamble. It adds no route: `spawn` is `POST /api/v1/quick-start` (+ `wait-output` on the mode's `capabilities.composerReadyMark` from the CLI registry, where it declares one), `send` is `POST …/input` with `clientId`+`seq` (and `wait`/`waitTimeout` for `--wait` / `--until <signals>`; `delivered:false` without `duplicate` and `wait.ended` both exit 3 — the CLI never reports a dead worker as done), `wait` is `GET …/wait` (`--until`) or `GET …/wait-output` (`--match`, `from=buffer` by default), `read` is `GET …/last-response` or `GET …/terminal?tail=`, `interrupt` is `POST …/input` with a bare `\u001b`, `rm` is `DELETE …/sessions/:id`. Every call carries `X-Codeman-Parent-Session`; only `spawn`'s quick-start carries `X-Codeman-Agent-Origin: codeman-agent-cli` (the agent-scratch label must never reach a request that cannot create the case directory). Basic auth comes from `CODEMAN_PASSWORD` or the data dir's `.env`. Server-side error codes are shown verbatim (`INVALID_INPUT: until=stop …` on a hook-less mode is not hidden); exit codes are `0` ok, `1` error, `2` timeout, `3` the session exited, `4` refused by a client-side guard. See the README section "`codeman agent`" for the guards and `test/cli-agent.test.ts` for the pinned behaviour.
|
||||
|
||||
## Session lineage (`parentSessionId`)
|
||||
|
||||
A create request may name the session that spawned it, which the web UI draws as a
|
||||
|
||||
Reference in New Issue
Block a user