mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-11-14 02:29:33 +01:00
docs(story-mode): restructure the API section
Eleven batches of findings had grown it by accretion. It now reads in parts: the routes, where turns start and end, how background work joins back, and what a page, an event and a panel carry. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
f464548541
commit
50de4f16b3
1 file changed
+24
-9
+24
-9
@@ -1052,22 +1052,37 @@ Lists are capped (300 files and 50 commits per repository) while the counts stay
|
||||
|
||||
## Story Mode (experimental)
|
||||
|
||||
`GET /api/sessions/:id/story[?turn=<id>]` is what Story Mode reads (the opt-in header button, App Settings → Header buttons → Story Mode, per device, off by default). It draws one turn of a Claude Code session as a comic page. **Experimental:** the payload shape may still change in a minor release; it is not part of the stable `/api/v1` contract yet.
|
||||
What Story Mode reads (the opt-in header button, App Settings → Header buttons → Story Mode, per device, off by default; on phones, Session Options → Story). It draws one turn of a Claude Code session as a comic page. **Experimental:** the payload shape may still change in a minor release; it is not part of the stable `/api/v1` contract yet.
|
||||
|
||||
Read-only. The session is resolved like every session route (ownership via `findSessionOrFail`; another user's session is `404`), and the file read is the session's own transcript, never one the request names: the path the Claude hook reported for it, else `<conversation id>.jsonl` under the Claude projects directory. Only the tail of the transcript is read (8 MB, widened in steps to 64 MB while that tail holds no prompt to start the turn), and file contents, original files and images never leave the server.
|
||||
### Routes
|
||||
|
||||
`data` is one of:
|
||||
- `GET /api/sessions/:id/story[?turn=<id>]`: one turn as a page. `data` is `{ supported: true, turns, page }`: `turns` lists up to 60 turns, oldest first (`{ id, at, prompt, origin, complete, interrupted, superseded?, toolCalls }`), and `page` is the newest turn, or the one `turn=<id>` names, or `null` when there is none (an unknown id included).
|
||||
- `GET /api/sessions/:id/story/helpers/:agentId`: one helper (an Agent call, `agentId` from its event's `helper.agentId`) drawn from its own transcript, `<conversation>/subagents/agent-<agentId>.jsonl` beside the session's. `data` is `{ supported: true, helper: { agentId, type?, description?, finished? }, page }`, the same page shape, or `page: null` while the helper has written nothing yet. `agentId` must match `[A-Za-z0-9_-]{1,64}` (`400` otherwise).
|
||||
|
||||
- `{ supported: false, reason }`: the session's CLI does not write a Claude Code transcript (registry `capabilities.transcript` is not `claude-jsonl`), or the session is remote or Docker, whose transcript is not on this host.
|
||||
- `{ supported: true, turns, page }`: `turns` lists up to 60 turns, oldest first (`{ id, at, prompt, origin, complete, interrupted, toolCalls }`; `origin` is `human`, `task`, `peer` or `system`). `page` is the newest turn, or the one `turn=<id>` names, or `null` when there is none (an unknown id included).
|
||||
Both answer `{ supported: false, reason }` for a session they cannot draw: its CLI writes no Claude Code transcript (registry `capabilities.transcript` is not `claude-jsonl`), or it is remote or Docker, whose transcript is not on this host. Both are read-only. The session resolves like every session route (ownership via `findSessionOrFail`; another user's session is `404`), and the file read is the session's own transcript, never one the request names: the path the Claude hook reported, else `<conversation id>.jsonl` under the Claude projects directory. Only its tail is read (8 MB, widened in steps to 64 MB while that tail holds no prompt to start the turn); file contents, original files and images never leave the server. A transcript that cannot be read is a `500` with `OPERATION_FAILED`.
|
||||
|
||||
Responses carry a weak `ETag` with `Cache-Control: no-cache`; a request with a matching `If-None-Match` gets a `304` without the page being rebuilt, which is what keeps a live view's frequent refetches cheap.
|
||||
Responses carry a weak `ETag` with `Cache-Control: no-cache`; a matching `If-None-Match` gets a `304` without the page being rebuilt, which keeps a live view's frequent refetches cheap.
|
||||
|
||||
`GET /api/sessions/:id/story/helpers/:agentId` draws one helper (an Agent call; its `agentId` is on the main page's event as `helper.agentId`) from the helper's own transcript, `<conversation>/subagents/agent-<agentId>.jsonl` beside the session's. `data` is `{ supported: true, helper: { agentId, type?, description?, finished? }, page }`, the same page shape as above, or `page: null` while the helper has written nothing yet. `agentId` must match `[A-Za-z0-9_-]{1,64}` (`400` otherwise).
|
||||
### Turns: where they start and end
|
||||
|
||||
A `page` carries the turn's summary fields plus `events` (one per prompt, sentence Claude wrote and tool call, with `intent`, `ok` when the call returned, `edit` hunks in Claude Code's own `structuredPatch` shape, the tail of `output`, `helper`, `tests` counts, and `files` for the files a Bash call printed with `cat`/`head`/`tail`, as the command named them), `panels` (each `{ kind, events, caption: { story, director }, balloon?, files?, ... }`, at most 12 per page, indices into `events`), `filesChanged`, `added`, `removed`, `helpers`, `helpersRunning`, `partial` (the turn began before the part that was read) and `truncated` (older outputs were dropped to keep the page small). A transcript that cannot be read is a `500` with `OPERATION_FAILED`.
|
||||
A turn is one prompt and everything Claude did for it. `origin` says who sent the prompt: `human`, `task` (a background job reporting back), `peer` (another session) or `system`.
|
||||
|
||||
A helper started in the background (`helper.background`) carries `helper.running: true` until its `<task-notification>` arrives; that notification starts a turn of its own (origin `task`), whose prompt event carries the helper's answer as `output`, and the answer, tool count and duration are joined back onto the helper in the turn that started it. Claude Code times such a turn from the prompt that started the chain; Story Mode caps a turn's `durationMs` at the turn's own span. A helper started as a teammate (`status: teammate_spawned`) is a background helper too, and its `<teammate-message>` reports join it by name. A prompt that arrives while Claude works (typed, a background job's report, a message from another session) is written by current Claude Code builds as a `queued_command` attachment, not a user line; it joins the running turn, a prompt event carrying `origin` (`human`, `task`, `peer`, `system`), and a report that lands mid-turn is an event with intent `notice` rather than a new mission panel. A Bash call that writes files through here-documents (`cat > f <<'EOF'`) carries them as `edits` (whole-file edits, counted in `filesChanged`), and its label leaves the bodies out; `headline` is the part of a one-liner that decided its intent. The advisor (a server tool) is an event with tool `Advisor` and intent `helper`; its answer is encrypted in the transcript. `tests` may carry `errors` (pytest's collection errors). A prompt written twice under one `promptId` (a typed `/compact`, then its command record) is one turn. In plan mode the plan file under `~/.claude/plans/` is planning (intent `plan`, its numbered steps as `todos`), not a code change, and `ExitPlanMode`'s result carries the plan (the event's `output`) and your answer (`Approved` / `Sent back`). A slash command is a prompt event with tool `Command`; a local one (`/compact`, `/model`) ends its turn at its own output (`<local-command-stdout>`, kept as the event's `output`), and a compaction that lands between turns belongs to the turn after it. A turn ends at `turn_duration`, or at the Stop hook's `stop_hook_summary` (unless it prevented the stop) in sessions that never write `turn_duration`, timed then by its own span.
|
||||
- **Start.** A user line with a prompt starts a turn. A prompt that arrives while Claude works (typed, a background job's report, a message from another session) is written by current Claude Code builds as a `queued_command` attachment, not a user line; it joins the running turn. A prompt written twice under one `promptId` (a typed `/compact`, then its command record) is one turn. A slash command is a prompt event with tool `Command`.
|
||||
- **End.** At `turn_duration`; at the Stop hook's `stop_hook_summary` (unless it prevented the stop) in sessions that never write `turn_duration`; at an interrupt; for a local slash command (`/compact`, `/model`), at its own output (`<local-command-stdout>`, kept as the prompt event's `output`). A turn still open when the next prompt starts has ended too, and is marked `superseded`.
|
||||
- **Duration.** `durationMs` is `turn_duration`'s, capped at the turn's own span (Claude Code times a turn a background job started from the prompt that started the whole chain); a turn with no `turn_duration` is timed by its span.
|
||||
- A compaction that lands between turns belongs to the turn after it; one mid-turn stays where it is.
|
||||
|
||||
### Background work
|
||||
|
||||
A helper started in the background (`run_in_background`, or as a teammate: `status: teammate_spawned`) has `helper.background` and `helper.running: true` until it reports back. A `<task-notification>` (matched by tool call) or a `<teammate-message>` (matched by name) joins the answer, tool count and duration back onto the helper in the turn that started it. A report that arrives after that turn ended starts a turn of its own (origin `task`) whose prompt event carries the report as `output` and the helper as `helper`; one that lands mid-turn is an event with intent `notice` instead of a new mission. `page.helpersRunning` counts the helpers still out.
|
||||
|
||||
### A page
|
||||
|
||||
A `page` carries the turn's summary fields plus:
|
||||
|
||||
- `events`: one per prompt, sentence Claude wrote and tool call. Each has `intent`, `tool`, `label` and, when the call returned, `ok` (`false` when the result was flagged as an error, or reported failed tests or lint problems a pipe kept from the exit code). Depending on the call: `edit` (an Edit/Write, hunks in Claude Code's own `structuredPatch` shape), `edits` (files a Bash call wrote through here-documents or `printf`/`echo` redirects, or that Claude Code says it changed), the tail of `output`, `tests` (`{ passed, failed, errors? }`), `helper`, `files` (files a Bash call printed with `cat`/`head`/`tail`), `headline` (the part of a one-liner that decided its intent), `commits`, `ships` (`push` / `pr`), `question` and, for prompts, `origin`. The advisor (a server tool) is an event with tool `Advisor` and intent `helper`; its answer is encrypted in the transcript. In plan mode the plan file under `~/.claude/plans/` is planning (intent `plan`, its numbered steps as `todos`), and `ExitPlanMode`'s result carries the plan (`output`) and your answer (`Approved` / `Sent back`).
|
||||
- `panels`: at most 12, each `{ kind, events, caption: { story, director }, balloon?, files?, notes?, helpers?, todos?, tests?, ok?, rounds?, question?, live? }`, with `events` as indices into `events`. Kinds: `mission`, `investigate`, `research`, `plan`, `backup`, `fix`, `check`, `loop` (fix and check rounds folded), `run`, `save`, `ask`, `compact`, `montage` (quieter panels folded to fit) and `complete`.
|
||||
- `filesChanged`, `added`, `removed` (summed per edit), `helpers`, `helpersRunning`, `durationMs`, `partial` (the turn began before the part that was read) and `truncated` (older outputs were dropped to keep the page small).
|
||||
|
||||
## Git worktrees of a case
|
||||
|
||||
|
||||
Reference in new issue
Block a user