目录
  1. 1. 总览流水线
  2. 2. STAGE 1: UI层 — 用户输入捕获
    1. 2.1. 数据变换
  3. 3. STAGE 2: 用户输入处理 — processUserInput()
    1. 3.1. 输入到输出的变换
    2. 3.2. 斜杠命令的分叉路径
  4. 4. STAGE 3: 上下文附件注入 — Attachments
    1. 4.1. 消息数组的丰富化
    2. 4.2. 附件来源和注入时机
  5. 5. STAGE 4: System Prompt 组装
    1. 5.1. 三层提示词组装
  6. 6. STAGE 5: Agentic Loop — 上下文压缩管道
    1. 6.1. 每次循环迭代的压缩流水线
    2. 6.2. 压缩决策的Token计算
  7. 7. STAGE 6: 消息规范化 — normalizeMessagesForAPI()
    1. 7.1. 内部消息 → API消息的变换
  8. 8. STAGE 7: API调用 — queryModelWithStreaming()
    1. 8.1. HTTP请求的构建
    2. 8.2. 重试与降级
  9. 9. STAGE 8: 流式响应解析
    1. 9.1. SSE事件流 → 结构化消息
  10. 10. STAGE 9: 工具执行
    1. 10.1. 工具调用分类与执行
    2. 10.2. 循环继续判断
    3. 10.3. 多轮工具调用示例
  11. 11. STAGE 10: 结果输出与持久化
    1. 11.1. 最终处理流水线
    2. 11.2. 进程退出时(useCostSummary hook)
  12. 12. 附录: 完整数据形态变换总结
  13. 13. 附录: 关键源文件索引
【Claude Code源码剖析】17-完整请求处理流水线:从用户提问到模型回答

本文追踪一条用户消息从键盘输入到最终回答输出的完整生命周期
每个阶段都标注数据的变换形态,让你”看见”数据在每一步变成了什么样子


总览流水线

┌──────────────────────────────────────────────────────────────────────────────┐
│ 用户在终端输入: "帮我重构 src/utils.ts" │
└──────────────────────┬───────────────────────────────────────────────────────┘


┌─ STAGE 1 ─────────────────────────────────────────────────────────────────────┐
│ React Ink UI 层 → TextInput 捕获输入 → handlePromptSubmit() │
│ 数据形态: 原始字符串 "帮我重构 src/utils.ts" │
└──────────────────────┬────────────────────────────────────────────────────────┘


┌─ STAGE 2 ─────────────────────────────────────────────────────────────────────┐
│ processUserInput() → 斜杠命令解析 / 图片处理 / 文本规范化 │
│ 数据形态: { messages: [UserMessage], shouldQuery: true, allowedTools: [...] } │
└──────────────────────┬────────────────────────────────────────────────────────┘


┌─ STAGE 3 ─────────────────────────────────────────────────────────────────────┐
│ Attachments 注入 → CLAUDE.md / Memory / IDE选择 / 条件上下文 │
│ 数据形态: messages[] 尾部追加多条 AttachmentMessage │
└──────────────────────┬────────────────────────────────────────────────────────┘


┌─ STAGE 4 ─────────────────────────────────────────────────────────────────────┐
│ System Prompt 组装 → 身份 + 工具描述 + 用户上下文 + 系统上下文 │
│ 数据形态: systemPrompt: string[], userContext: {}, systemContext: {} │
└──────────────────────┬────────────────────────────────────────────────────────┘


┌─ STAGE 5 ─────────────────────────────────────────────────────────────────────┐
│ query() 进入 Agentic Loop → 上下文压缩 / Snip / Microcompact / AutoCompact │
│ 数据形态: messagesForQuery[] (压缩后消息数组) │
└──────────────────────┬────────────────────────────────────────────────────────┘


┌─ STAGE 6 ─────────────────────────────────────────────────────────────────────┐
│ normalizeMessagesForAPI() → 过滤/重排/合并为 API 兼容格式 │
│ 数据形态: (UserMessage|AssistantMessage)[] — 仅 user/assistant 交替 │
└──────────────────────┬────────────────────────────────────────────────────────┘


┌─ STAGE 7 ─────────────────────────────────────────────────────────────────────┐
│ queryModelWithStreaming() → @anthropic-ai/sdk → HTTP POST /v1/messages │
│ 数据形态: BetaMessageStreamParams JSON → Server-Sent Events 流 │
└──────────────────────┬────────────────────────────────────────────────────────┘


┌─ STAGE 8 ─────────────────────────────────────────────────────────────────────┐
│ Stream 解析 → AssistantMessage 构建 → thinking / text / tool_use 提取 │
│ 数据形态: StreamEvent[] → AssistantMessage { content: ContentBlock[] } │
└──────────────────────┬────────────────────────────────────────────────────────┘


┌─ STAGE 9 ─────────────────────────────────────────────────────────────────────┐
│ Tool Execution → 权限检查 → 并行/串行执行 → tool_result 注入 │
│ 数据形态: ToolUseBlock[] → 执行 → UserMessage[tool_result] 追加到 messages │
└──────────────────────┬────────────────────────────────────────────────────────┘

┌────┴────┐
│ 有tool_use│──→ 回到 STAGE 5(继续循环)
│ stop_reason│
│ ="end_turn"│──→ 进入 STAGE 10
└─────────┘


┌─ STAGE 10 ────────────────────────────────────────────────────────────────────┐
│ 结果输出 → 成本统计 → 会话持久化 → UI渲染 │
│ 数据形态: 最终文本 + 成本报告 + 写入 transcript │
└───────────────────────────────────────────────────────────────────────────────┘

STAGE 1: UI层 — 用户输入捕获

源文件: src/screens/Repl.tsx, src/hooks/useHandlePromptSubmit.ts

数据变换

用户键入:    "帮我重构 src/utils.ts"


React Ink TextInput组件捕获 onSubmit 回调


handlePromptSubmit({ input, pastedContents, ideSelection })


传入数据:
{
input: "帮我重构 src/utils.ts", // 原始字符串
pastedContents: {}, // 粘贴的图片/文本 (此例为空)
ideSelection: undefined, // IDE选中内容 (此例无)
}

关键操作:

  • 如果用户有粘贴的图片/文本,pastedContents 会包含 { id: number, type: 'text'|'image', content: string }
  • 如果连接了 IDE(如 VSCode),ideSelection 会包含当前选中的代码片段
  • 输入队列 (messageQueueManager) 支持排队:用户可以在模型还在回答时继续输入

STAGE 2: 用户输入处理 — processUserInput()

源文件: src/utils/processUserInput/processUserInput.ts (606行)

输入到输出的变换

输入: "帮我重构 src/utils.ts"

├── 1. 斜杠命令检测: 是否以 / 开头?
│ ├── "/compact" → 本地执行compact, shouldQuery=false
│ ├── "/model opus" → 切换模型, shouldQuery=false
│ └── 不是斜杠命令 → 继续

├── 2. 特殊关键词检测
│ └── 包含 "ultraplan"? → 替换为ultraplan流程

├── 3. 图片处理
│ └── pastedContents中的图片 → base64编码 → ImageBlockParam

├── 4. processTextPrompt()
│ └── 纯文本 → 创建 UserMessage 对象

└── 5. UserPromptSubmit Hooks 执行
└── 可能被hook阻断(如安全策略拦截)

输出:
{
messages: [
{
type: "user",
uuid: "a1b2c3d4-...",
timestamp: "2026-04-08T...",
message: {
role: "user",
content: "帮我重构 src/utils.ts" // ← 用户原文
},
isMeta: false,
isVisibleInTranscriptOnly: false,
}
],
shouldQuery: true, // 需要调用API
allowedTools: undefined, // 无特殊工具限制
model: undefined, // 使用默认模型
}

斜杠命令的分叉路径

如果用户输入是 /compact:

输出:
{
messages: [SystemMessage("已执行compact...")],
shouldQuery: false, // ← 不需要API调用,本地处理完毕
resultText: "Compacted conversation...",
}

STAGE 3: 上下文附件注入 — Attachments

源文件: src/utils/attachments.ts (3998行), src/query.ts

消息数组的丰富化

在用户消息被追加到 messages[] 后,进入 query() 循环之前和每次迭代开始时,系统自动注入上下文附件:

messages[] 当前状态:
[
...历史消息...,
UserMessage("帮我重构 src/utils.ts"), // ← STAGE 2 创建的
]


▼ getAttachmentMessages() 注入

messages[] 变为:
[
...历史消息...,
UserMessage("帮我重构 src/utils.ts"),

// ↓ 自动注入的附件消息 ↓
AttachmentMessage({ // CLAUDE.md 项目指令
type: "attachment",
origin: "memory",
content: "# Project Rules\n- Use TypeScript strict mode\n..."
}),
AttachmentMessage({ // 自动记忆 (MEMORY.md)
type: "attachment",
origin: "auto_memory",
content: "## Context\n- 上次讨论了性能优化\n..."
}),
AttachmentMessage({ // 相关记忆 (sideQuery发现的)
type: "attachment",
origin: "relevant_memory",
content: "## 相关: src/utils.ts 的历史修改记录\n..."
}),
AttachmentMessage({ // TODO列表状态
type: "attachment",
origin: "todo",
content: "<todos>[{\"id\":1,\"content\":\"重构utils\",\"status\":\"in_progress\"}]</todos>"
}),
AttachmentMessage({ // 条件规则 (如果匹配)
type: "attachment",
origin: "conditional_rule",
content: "当处理 TypeScript 文件时: 确保运行 tsc --noEmit 检查类型"
}),
]

附件来源和注入时机

附件类型 来源 注入条件
memory .claude/CLAUDE.md + 各级目录 每次查询,首次注入
auto_memory ~/.claude/MEMORY.md 每次查询
relevant_memory sideQuery 异步预取 首次有意义的查询
todo 内存中的 TODO 状态 TODO列表非空时
conditional_rule CLAUDE.md 中的条件规则 路径/内容模式匹配时
ide_selection VSCode/JetBrains IDE有选中内容时
diagnostic LSP 诊断 编辑相关文件时
skill_listing 可用技能列表 首次查询
plan 计划文件内容 有活跃计划时
task_context 后台任务状态 多Agent模式

STAGE 4: System Prompt 组装

源文件: src/utils/queryContext.ts, src/constants/prompts.ts, src/context.ts

三层提示词组装

fetchSystemPromptParts() 并行获取:
├── getSystemPrompt(tools, model, dirs, mcpClients)
├── getUserContext()
└── getSystemContext()

最终 System Prompt 的结构:

systemPrompt = [
// ─── Part 1: 核心身份提示 (getSystemPrompt) ───
"You are Claude, an AI assistant made by Anthropic...",

// ─── Part 2: 工具描述 ───
"You have access to the following tools:\n"
+ "- BashTool: Execute shell commands...\n"
+ "- FileReadTool: Read file contents...\n"
+ "- FileEditTool: Edit files with search/replace...\n"
+ "- GrepTool: Search with ripgrep...\n"
+ "- GlobTool: Find files by pattern...\n"
+ ... // 所有已注册工具的描述

// ─── Part 3: Memory Mechanics (如果有) ───
"(可选) How to use MEMORY.md...",

// ─── Part 4: 追加系统提示 (appendSystemPrompt) ───
"(可选) 用户或SDK提供的额外指令",
]

// 缓存键前缀部分:
userContext = {
"Current directory": "/home/user/project",
"Date": "2026-04-08",
"Platform": "Linux x86_64",
"Shell": "/bin/bash",
"Model": "claude-sonnet-4-20250514",
"Editor": "VSCode",
...
}

systemContext = {
"(内部指令,不对用户可见)": "...",
...
}

完成后的数据形态:

{
systemPrompt: SystemPrompt, // string[] 包装为不透明类型
userContext: { [k: string]: string },
systemContext: { [k: string]: string },
}

STAGE 5: Agentic Loop — 上下文压缩管道

源文件: src/query.ts (1730行) — queryLoop() 函数

每次循环迭代的压缩流水线

进入 while(true) 循环后,消息在送往 API 前经过 4级压缩

messages[] (完整历史)

├── Step 5.1: getMessagesAfterCompactBoundary()
│ └── 如果有 compact_boundary → 只取之后的消息
│ 数据变化: [100条] → [12条](丢弃已压缩的历史)

├── Step 5.2: applyToolResultBudget()
│ └── 超长的 tool_result 被截断/替换为 "[content replaced, id=xxx]"
│ 数据变化: 某个2MB的文件读取结果 → 替换为占位符

├── Step 5.3: snipCompactIfNeeded() [HISTORY_SNIP feature]
│ └── 老旧的中间对话段被"剪掉",保留头尾
│ 数据变化: [12条] → [8条](中间4条被snip)

├── Step 5.4: microcompact()
│ └── 同一文件的多次Read/Edit → 只保留最新结果
│ 数据变化: 3次对utils.ts的Read结果 → 只保留最后1次

├── Step 5.5: applyCollapsesIfNeeded() [CONTEXT_COLLAPSE feature]
│ └── 已完成的工具调用链 → 收缩为摘要
│ 数据变化: [Read→Edit→Read→Edit] → [Summary: "编辑了utils.ts两次"]

└── Step 5.6: autocompact (如果上下文过大)
└── tokenCountWithEstimation() > threshold → 调用API压缩
数据变化: [180K tokens] → compact summary [20K tokens]

messagesForQuery[] (压缩后,准备送往API)

压缩决策的Token计算

// tokenCountWithEstimation() 的计算逻辑:
const currentTokens =
lastAPIResponse.usage.input_tokens // 上次API返回的输入token
+ lastAPIResponse.usage.output_tokens // 上次输出token
+ lastAPIResponse.usage.cache_*_tokens // 缓存token
+ roughEstimate(newMessagesSinceLastAPI) // 新消息的粗估 (chars/4)

// 自动compact触发条件:
if (currentTokens > contextWindow * 0.9) {
// 触发compact → 调用一次API,生成对话摘要
}

STAGE 6: 消息规范化 — normalizeMessagesForAPI()

源文件: src/utils/messages.ts (5513行中的一部分)

内部消息 → API消息的变换

Claude Code 内部有 7+ 种消息类型,但 API 只接受 userassistant 交替的序列:

内部 messages[]:
[
{ type: "user", message: {role:"user", content:"帮我重构..."} },
{ type: "attachment", origin: "memory", content: "CLAUDE.md..." },
{ type: "attachment", origin: "todo", content: "<todos>..." },
{ type: "assistant", message: {role:"assistant", content:[...]} },
{ type: "user", toolUseResult: {...} }, // tool_result
{ type: "progress", content: "..." }, // 进度消息
{ type: "system", subtype: "local_command", content: "..." },
]

│ normalizeMessagesForAPI()


API messages[]:
[
{
role: "user",
content: [
{ type: "text", text: "帮我重构 src/utils.ts" },
// attachment被合并进前一个user消息
{ type: "text", text: "[CLAUDE.md内容]" },
{ type: "text", text: "[TODO内容]" },
]
},
{
role: "assistant",
content: [
{ type: "thinking", thinking: "..." },
{ type: "text", text: "我来看一下..." },
{ type: "tool_use", id: "tu_1", name: "FileReadTool", input: {...} },
]
},
{
role: "user",
content: [
{ type: "tool_result", tool_use_id: "tu_1", content: "文件内容..." },
]
},
]

关键变换规则:

  1. attachment 消息 → 合并到前一个 user 消息的 content 数组中
  2. progress 消息 → 完全丢弃(仅UI用)
  3. system 消息 → 完全丢弃(API不接受)
  4. isVirtual 消息 → 过滤掉(仅UI显示用)
  5. 连续相同角色的消息 → 合并(API要求交替)
  6. 不可用工具的引用 → 过滤掉(防止API报错)

STAGE 7: API调用 — queryModelWithStreaming()

源文件: src/services/api/claude.ts (3420行)

HTTP请求的构建

queryModelWithStreaming()
└── queryModel()
└── withRetry() // 重试逻辑
└── anthropic.beta.messages.create({...})

实际发送到 Anthropic API 的 JSON:

{
"model": "claude-sonnet-4-20250514",
"max_tokens": 8000,
"system": [
{
"type": "text",
"text": "You are Claude, an AI assistant...",
"cache_control": { "type": "ephemeral" }
}
],
"messages": [
{
"role": "user",
"content": [
{ "type": "text", "text": "帮我重构 src/utils.ts" },
{ "type": "text", "text": "# Project Rules\n..." }
]
}
],
"tools": [
{
"name": "BashTool",
"description": "Execute shell commands...",
"input_schema": { "type": "object", "properties": {...} }
},
...
],
"stream": true,
"metadata": { "user_id": "user_xxx" },
"betas": ["interleaved-thinking-2025-05-14", "..."]
}

cache_control 分布:

System Prompt      ← cache_control: ephemeral (第1个断点)
User Context ← cache_control: ephemeral (第2个断点)
Tool Definitions ← cache_control: ephemeral (第3个断点)
最后2条user消息 ← cache_control: ephemeral (第4个断点)

这确保 system prompt + tool 定义在多轮对话中被缓存(cache_read 只要普通价格的 10%)。

重试与降级

请求失败?
├── 429 (Rate Limit) → 指数退避重试,最多4次
├── 529 (Overloaded) → 更长退避,最多6次
├── 401 (Auth Error) → OAuth token刷新后重试
├── 网络超时 → 非流式降级 (executeNonStreamingRequest)
├── prompt_too_long → 触发 reactiveCompact(紧急压缩后重试)
└── max_output_tokens → 自动扩容到 64k 重试(最多3次)

STAGE 8: 流式响应解析

源文件: src/services/api/claude.ts — handleMessageFromStream

SSE事件流 → 结构化消息

API返回的 Server-Sent Events 流:

event: message_start
data: {"type":"message_start","message":{"id":"msg_01...","model":"claude-sonnet-4-...",...}}

event: content_block_start
data: {"type":"content_block_start","index":0,"content_block":{"type":"thinking","thinking":""}}

event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"thinking_delta","thinking":"让我分析..."}}
... (多个delta)

event: content_block_stop
data: {"type":"content_block_stop","index":0}

event: content_block_start
data: {"type":"content_block_start","index":1,"content_block":{"type":"text","text":""}}

event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"text_delta","text":"我来看看"}}

event: content_block_start
data: {"type":"content_block_start","index":2,"content_block":{"type":"tool_use","id":"tu_abc","name":"FileReadTool","input":{}}}

event: content_block_delta
data: {"type":"content_block_delta","index":2,"delta":{"type":"input_json_delta","partial_json":"{\"file_path\":\""}}

event: message_delta
data: {"type":"message_delta","delta":{"stop_reason":"tool_use"},"usage":{"output_tokens":150}}

event: message_stop
data: {"type":"message_stop"}

解析后得到:

AssistantMessage = {
type: "assistant",
uuid: "e5f6g7h8-...",
timestamp: "2026-04-08T...",
message: {
id: "msg_01...",
role: "assistant",
model: "claude-sonnet-4-20250514",
content: [
{
type: "thinking",
thinking: "让我分析一下用户的请求。他们想重构src/utils.ts..."
},
{
type: "text",
text: "我来看看 src/utils.ts 的内容:"
},
{
type: "tool_use",
id: "tu_abc",
name: "FileReadTool",
input: { "file_path": "src/utils.ts" }
}
],
stop_reason: "tool_use", // ← 因为有工具调用,不是"end_turn"
usage: {
input_tokens: 15234,
output_tokens: 150,
cache_creation_input_tokens: 3200,
cache_read_input_tokens: 12000,
}
}
}

同步操作(流式接收期间):

  • 每个 text_delta → 实时渲染到终端 (React Ink <Markdown>)
  • 每个 thinking_delta → 渲染到思考展示区(如果启用)
  • 每个 input_json_delta → StreamingToolExecutor 实时解析JSON
  • message_start → 重置当前消息usage计数器
  • message_deltaaccumulateUsage() 累加token使用量

STAGE 9: 工具执行

源文件: src/services/tools/toolOrchestration.ts, src/services/tools/toolExecution.ts

工具调用分类与执行

从 AssistantMessage.content 提取 tool_use blocks:
[
{ type: "tool_use", id: "tu_abc", name: "FileReadTool", input: { file_path: "src/utils.ts" } }
]

▼ partitionToolCalls()

将工具调用分为:
├── 只读批次 (isConcurrencySafe=true): FileReadTool, GrepTool, GlobTool
│ └── 并行执行,最大并发度 10
└── 写入批次 (isConcurrencySafe=false): FileEditTool, BashTool
└── 严格串行执行


▼ 对每个工具调用:

┌─ 权限检查 ────────────────────────────────────────────┐
│ canUseTool(FileReadTool, {file_path:"src/utils.ts"}) │
│ │
│ 检查流程: │
│ 1. 是否在 allowedTools 中? │
│ 2. settings.json 的权限规则匹配? │
│ 3. 权限模式: │
│ ├── plan模式 → 自动拒绝写操作 │
│ ├── auto模式 → yoloClassifier判断 → 低风险自动允许 │
│ └── default模式 → 弹出UI询问用户 │
│ │
│ 结果: { behavior: "allow" | "deny", ... } │
└──────────────────────┬─────────────────────────────────┘
│ allow

┌─ 工具执行 ────────────────────────────────────────────┐
│ FileReadTool.call({file_path: "src/utils.ts"}) │
│ │
│ 内部流程: │
│ 1. expandPath("src/utils.ts") → "/home/user/.../src/utils.ts"
│ 2. 检查文件大小 (≤ 256KB) │
│ 3. readFileSyncCached(path) → 文件内容 │
│ 4. addLineNumbers({content, startLine: 1}) │
│ 5. 返回: " 1→import { foo } from...\n 2→..." │
└──────────────────────┬─────────────────────────────────┘


工具结果注入为 UserMessage (tool_result):

{
type: "user",
message: {
role: "user",
content: [
{
type: "tool_result",
tool_use_id: "tu_abc",
content: " 1→import { foo } from 'bar'\n 2→...(文件内容)...",
is_error: false,
}
]
},
toolUseResult: "...(同上)...",
sourceToolAssistantUUID: "e5f6g7h8-...",
}

循环继续判断

stop_reason 判断:
├── "tool_use" → messages中追加tool_result → 回到 STAGE 5 继续循环
├── "end_turn" → 模型完成回答 → 进入 STAGE 10
├── "max_tokens" → 输出被截断 → 尝试扩容重试(最多3次)
└── "stop_sequence" → 自定义停止序列 → 进入 STAGE 10

多轮工具调用示例

一个典型的重构请求可能产生 4-8 轮循环:

轮次1: Read src/utils.ts                         → tool_use → 继续
轮次2: Read tests/utils.test.ts → tool_use → 继续
轮次3: Edit src/utils.ts (重构代码) → tool_use → 继续
轮次4: Bash("npm test") → tool_use → 继续
轮次5: 发现测试失败, Edit tests/utils.test.ts → tool_use → 继续
轮次6: Bash("npm test") → tool_use → 继续
轮次7: 测试通过, 文本回复"重构完成" → end_turn → 结束

STAGE 10: 结果输出与持久化

源文件: src/QueryEngine.ts, src/cost-tracker.ts, src/costHook.ts

最终处理流水线

模型回答 stop_reason="end_turn"

├── 1. 成本计算
│ calculateUSDCost("claude-sonnet-4-...", usage)
│ → $0.08 (假设值)

├── 2. 累加到会话成本
│ addToTotalSessionCost(0.08, 1200, {"claude-sonnet-4-...": usage})
│ → OpenTelemetry 上报

├── 3. Stop Hooks 执行
│ └── executeStopFailureHooks() → 检查模型是否遵循了指令

├── 4. 会话持久化
│ recordTranscript(messages)
│ → ~/.claude/projects/<hash>/sessions/<id>.jsonl

├── 5. 生成SDK结果消息
│ yield {
│ type: "result",
│ subtype: "success",
│ result: "重构已完成。我对 src/utils.ts 做了以下修改...",
│ duration_ms: 45000,
│ duration_api_ms: 12000,
│ total_cost_usd: 0.08,
│ usage: { input_tokens: 45000, output_tokens: 1200, ... },
│ num_turns: 7,
│ }

└── 6. UI渲染最终回答
React Ink <Markdown> 组件渲染模型的文本回复
终端显示: "重构已完成。我对 src/utils.ts 做了以下修改..."

进程退出时(useCostSummary hook)

process.exit 触发:
├── formatTotalCost() → "Total cost: $0.08\n Duration: 12s API, 45s wall..."
├── saveCurrentSessionCosts()
│ ├── git diff --stat → +45 -20 lines
│ └── setProjectConfig(sessionKey, { cost, duration, linesAdded, ... })
└── 输出到 stderr (灰色文本)

附录: 完整数据形态变换总结

阶段 数据形态 大小参考
STAGE 1 原始字符串 "帮我重构 src/utils.ts" ~20 bytes
STAGE 2 { messages: [UserMessage], shouldQuery: true } ~200 bytes
STAGE 3 messages[] + 多条 AttachmentMessage ~5-50 KB
STAGE 4 systemPrompt + userContext + systemContext ~10-30 KB
STAGE 5 messagesForQuery[] (压缩后) ~20-200K tokens
STAGE 6 (User|Assistant)[] API格式 ~同上
STAGE 7 HTTP JSON body → SSE stream ~根据上下文大小
STAGE 8 AssistantMessage (结构化) ~0.5-4K tokens output
STAGE 9 tool_result 注入 → 回到 STAGE 5 ~根据工具输出
STAGE 10 最终文本 + 成本报告 + 持久化 渲染到终端

附录: 关键源文件索引

阶段 核心文件 行数
STAGE 1 src/screens/Repl.tsx UI入口
STAGE 2 src/utils/processUserInput/processUserInput.ts 606
STAGE 3 src/utils/attachments.ts 3998
STAGE 4 src/utils/queryContext.ts + src/constants/prompts.ts + src/context.ts 180+大
STAGE 5 src/query.ts 1730
STAGE 6 src/utils/messages.ts (normalizeMessagesForAPI) 5513中
STAGE 7 src/services/api/claude.ts 3420
STAGE 8 src/services/api/claude.ts (streaming部分) 同上
STAGE 9 src/services/tools/toolOrchestration.ts + toolExecution.ts 189+
STAGE 10 src/QueryEngine.ts + src/cost-tracker.ts 1296+324
打赏
  • 微信
  • 支付宝

评论