Skip to main content

Module chat

Module chat 

Source
Expand description

The browser interview: magi plan for somebody holding a phone.

crate::plan is an interview that works by handing over the terminal - stdin, stdout and stderr inherited, the agent’s own UI in front of the operator, no timeout. That is the right design and it is not changing. It is also unavailable to the operator who is away from the machine, which is most of the time this repository’s operator wants to plan something: there is no terminal in a browser to hand over.

So this module is the same interview, arrived at from the other side. magi does host the conversation here, because there is nothing else that can: each operator message is one headless crate::agent::invoke, and the transcript lives in a JSON file the phone reads. The end state is identical to magi plan’s - a task file checked by plan::review_draft and filed in crate::queue - which is deliberate. Two planning paths that accept different task files would be two products.

§A turn is cheap because the CLI remembers

The thing that makes a turn-per-request affordable is SeatState: a second crate::agent::invoke with the same seat resumes the CLI’s own conversation (claude --resume, opencode run -s, agy --conversation), so a turn sends the operator’s new sentence and nothing else. The model already has the repository it read and the questions it asked. magi does not re-send the transcript when the CLI can resume - that would pay for the whole conversation again on every message, and it would let magi’s idea of the history drift from the model’s. [transcript] exists only for the case where resuming is genuinely impossible, and [turn] says when.

§Shape

The same split as crate::queue and crate::ask: Chat is data plus pure helpers, Chats owns all I/O and is constructed with its root, so every test below drives a real store in a temp directory and none of them touch the operator’s home. One conversation is one JSON file, written atomically, because magi web and a future magi chat are separate processes and a rename is the only cross-process atomic write that needs no coordination between them.

Structs§

Chat
One planning conversation.
Chats
A conversation store on disk.
Turn
One message in the conversation.

Enums§

ChatStatus
Where a conversation is in its life.
Who
Who said something.

Constants§

MAGI_NOTE
Prefix on an agent turn that magi wrote rather than an agent.
SCHEMA
On-disk format for a conversation. Bumped when a field’s meaning changes.

Functions§

briefing
The briefing the agent is opened with.
build
Construct a conversation record in memory, without writing it anywhere.
derived_background
The background block a derived conversation opens with: the whole prior transcript, framed so the leader does not mistake it for instructions about the repository this new conversation is actually about.
draft_problems
Is this conversation’s draft fileable, and if not, what is wrong with it?
extract_draft
Pull the task draft out of an agent reply, if it wrote one.
file_draft
Validate the draft with plan::review_draft and queue it.
first_turn
Take the first agent turn of a conversation created by open.
open
build, then persist. No first agent turn is taken.
record
Append the operator’s turn and flush it, without invoking anything.
respond
The agent’s half of a turn: invoke, append, flush.
say
One operator turn and one agent turn, appended.
start
Open a conversation and take the first agent turn.