lib/acp/src/root.zig

daab053ee43316e1809a84551d573ddd1e5bf3d2

 1 //! A coding agent often runs as a separate program: the caller starts it, sends it a prompt, and
 2 //! reads back its progress and its reply. The package is a client for such agents: it runs the
 3 //! agent as a child process and exchanges messages with it over the child's standard input and
 4 //! output, one JSON message per line. A caller starts the agent, opens a session, sends prompts,
 5 //! and gets back the reply text and the reason the agent stopped. The line reader the client uses
 6 //! is also exported on its own, for any program that reads newline-separated messages from a pipe
 7 //! within a fixed memory budget.
 8 //!
 9 //! The agent's process, and every process it starts, has to stop when the caller says so. Every
10 //! message the agent sends has to be recorded exactly and in order before anything acts on it. Each
11 //! request the agent makes to run a tool has to be answered by the caller's rules. Memory has to
12 //! stay bounded whatever the agent sends.
13 //!
14 //! The agent is another program: it can write a line of any length, send any number of progress
15 //! messages, and stream a reply of any size. The agent starts programs of its own to run tools, and
16 //! stopping the agent alone would leave those programs running. While a prompt is in flight, the
17 //! agent's final response arrives after a stream of progress messages and requests of its own, and
18 //! each one has to be handled in order before the response can be read. A record written after the
19 //! client acts can fall behind what the agent saw: a permission answer sent first has already
20 //! reached the agent when the recording of it fails.
21 //!
22 //! The Agent Client Protocol (https://agentclientprotocol.com/) defines the messages. The client
23 //! sends `initialize`, `session/new`, `session/prompt` and `session/cancel`, and it handles the
24 //! agent's `session/update` notifications and `session/request_permission` requests. JSON-RPC 2.0
25 //! (https://www.jsonrpc.org/specification) supplies the message format: every message carries
26 //! `"jsonrpc":"2.0"`, each request carries a numeric id that its response repeats, and the client
27 //! answers a request it does not handle with error code -32601, "method not found". The client
28 //! speaks version 1 of the protocol, and its tests replay one message of each of the eleven kinds
29 //! of session update that version defines.
30 //!
31 //! The client owns the agent's process: it starts the agent in a process group of its own with
32 //! standard error discarded. To cancel or tear down, the client signals the whole group to
33 //! terminate and then to die, so the tools the agent started stop with it, and teardown also waits
34 //! for the agent to exit.
35 //!
36 //! The client runs one request at a time: each call writes its request and then handles the agent's
37 //! messages until the matching response arrives.
38 //!
39 //! Input is bounded by one buffer sized from the caller's line limit (`ReaderLimits`) and allocated
40 //! before the agent starts. A line longer than that limit stops reading for good, before any JSON
41 //! is parsed. The line limit bounds the reader's buffer alone: the JSON the client parses, the
42 //! updates it builds and the reply it collects come from the caller's allocator. Traffic is bounded
43 //! by caller limits (`TransferLimits`) on each outgoing message, each incoming update, the number
44 //! of updates, and the size and chunk count of one prompt's reply, and a zero limit is refused. At
45 //! a reply limit the client keeps what fit, records which update it left out, asks the agent to
46 //! stop with one `session/cancel`, and still returns the agent's final response.
47 //!
48 //! The client hands every message it acts on to a set of callbacks the caller supplies (an
49 //! *observer*, `Observer`) and waits for each call to return before it goes on, so the caller
50 //! records each message first. Each update the client passes on carries a nonzero number the caller
51 //! picks for this client (a *transport epoch*), and the caller records each change of that number
52 //! before it starts a client. The client also numbers the updates from 1 in arrival order (an
53 //! *update sequence*) for its whole life, and passes on the exact line the agent sent with each
54 //! one. A client with no observer fails with `error.MissingDurableObserver` at the first update or
55 //! permission request. The observer may answer each permission request, and every decision reaches
56 //! the observer before the answer reaches the agent. When the callbacks give no answer, the client
57 //! checks two caller lists (a *permission policy*, `PermissionPolicy`), tool kinds and tool-title
58 //! prefixes, and it rejects every request that neither list allows. The client tells the agent it
59 //! offers no client capabilities, and it answers any other request from the agent with "method not
60 //! found".
61 
62 pub const client = @import("client.zig");
63 pub const protocol = @import("protocol.zig");
64 pub const reader = @import("reader/root.zig");
65 
66 pub const Client = client.Client;
67 pub const ClientInfo = client.ClientInfo;
68 pub const EnvVariable = client.EnvVariable;
69 pub const Initialize = protocol.Initialize;
70 pub const McpServer = client.McpServer;
71 pub const Modes = protocol.Modes;
72 pub const Observer = client.Observer;
73 pub const Options = client.Options;
74 pub const TransferLimits = client.TransferLimits;
75 pub const PermissionReply = client.PermissionReply;
76 pub const PermissionPolicy = client.PermissionPolicy;
77 pub const PermissionRequest = protocol.PermissionRequest;
78 pub const PromptBlobResource = protocol.PromptBlobResource;
79 pub const PromptContent = protocol.PromptContent;
80 pub const PromptMedia = protocol.PromptMedia;
81 pub const PromptResourceLink = protocol.PromptResourceLink;
82 pub const PromptResult = protocol.PromptResult;
83 pub const Overflow = protocol.Overflow;
84 pub const OverflowKind = protocol.OverflowKind;
85 pub const PromptTextResource = protocol.PromptTextResource;
86 pub const ReaderCapacity = reader.Capacity;
87 pub const ReaderExhaustion = reader.Exhaustion;
88 pub const ReaderLimits = reader.Limits;
89 pub const ReaderPoll = reader.Poll;
90 pub const ReaderStatus = reader.Status;
91 pub const ReaderStorage = reader.Storage;
92 pub const Update = protocol.Update;
93 pub const UpdateKind = protocol.UpdateKind;
94 pub const default_reader_limits = reader.default_limits;