读类型
ContextMessageAssistantMessageAssistantMessageEvent
02 · 模型接口
这一章读 packages/ai:它把 agent 的内部状态压成统一 Context,
再把不同厂商的 stream 翻译成 pi 标准事件。provider 层负责翻译,agent loop 层负责执行。
目标不是记住某个厂商 API,而是理解 pi 如何把不同模型统一到同一个 agent loop 里。
ContextMessageAssistantMessageAssistantMessageEventstreamSimple() 不直接调用 OpenAI。model.api 找 provider。Context -> payloadresponse.* -> pi eventtoolCall -> toolResult -> Context普通 LLM 请求通常只问模型一次;agent 请求会把模型输出、工具执行和工具结果组成循环。
Context 是给 provider 的统一请求包;Provider 是厂商适配器;
AssistantMessageEvent 是模型流式输出的标准事件。三者先按这个粗粒度理解,不需要一开始背所有字段。
agent 内部可以很复杂,但 provider 只接收统一的 Context。
export interface Context {
systemPrompt?: string;
messages: Message[];
tools?: Tool[];
}
export type Message =
| UserMessage
| AssistantMessage
| ToolResultMessage;
systemPrompt 是本轮系统提示词。messages 是模型能看到的历史。tools 是模型可调用工具定义。Context 之前是 agent 内部结构,之后是具体 provider 的 API payload。新手第一遍只要抓住三个字段:
systemPrompt、messages、tools。
assistant message 的内容可以是 text、thinking 和 toolCall。
export interface AssistantMessage {
role: "assistant";
content: (
TextContent |
ThinkingContent |
ToolCall
)[];
usage: Usage;
stopReason: StopReason;
}
text_start / text_delta / text_endthinking_start / thinking_delta / thinking_endtoolcall_start / toolcall_delta / toolcall_enddone / error创建一个还没完成的 assistant message,让 agent loop 和 UI 知道输出开始了。
不断追加片段。文本、thinking 和工具参数都可能分多段返回。
当前内容块完成。对 toolCall 来说,参数到这里才适合解析和校验。
它根据 model.api 找 provider,不关心厂商请求细节。
export function streamSimple(model, context, options) {
const provider = resolveApiProvider(model.api);
return provider.streamSimple(
model,
context,
withEnvApiKey(model, options)
);
}
model.api 决定进入哪个 provider。OpenAI 返回自己的 response.* 事件,pi 在 shared adapter 里翻译成标准事件。
response.output_item.added + reasoningresponse.reasoning_text.deltaresponse.output_item.done + reasoningresponse.output_item.added + messageresponse.output_text.deltaresponse.output_item.done + messageresponse.output_item.added + function_callresponse.function_call_arguments.deltaresponse.output_item.done + function_calltoolcall_start 表示模型开始生成一次工具请求;
toolcall_delta 是参数 JSON 的增量片段;
toolcall_end 表示工具名和参数已经完整。工具不能在 delta 阶段执行。
模型发出 toolCall 后还不知道工具结果,必须通过下一轮上下文告诉它。
assistant: toolCall(read README.md)
-> pi 本地执行 read
-> toolResult: README.md 内容
-> Context.messages
-> 下一次 streamAssistantResponse()
-> 模型继续回答
ToolResultMessage。toolCall;agent loop 负责执行工具,并把
toolResult 放回上下文。
toolCall 不是工具已经执行了,只是 assistant message 里的一段结构化请求。
toolResult 不是日志,而是下一轮模型请求必须携带的上下文。
provider 不应该知道 CLI、TUI 或 session 文件,它只做请求和事件翻译。
这一章已经把模型层主线走完,后续可以进入更细的 agent loop 和工具执行。
Context 是 agent 和 provider 的边界。Message 的三种角色。toolcall_start/delta/end 的意义。toolResult 的上下文作用。runLoop()。beforeToolCall 和 afterToolCall。