527 lines
18 KiB
Markdown
527 lines
18 KiB
Markdown
|
|
# Claude Code 数据流与生命周期
|
|||
|
|
|
|||
|
|
## 1. 启动流程
|
|||
|
|
|
|||
|
|
### 1.1 完整启动序列
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
终端执行: bun run dev (→ bun run src/entrypoints/cli.tsx)
|
|||
|
|
│
|
|||
|
|
├── Phase 0: 预加载
|
|||
|
|
│ ├── globalThis.MACRO 注入 (版本号、构建信息)
|
|||
|
|
│ ├── process.env 初始化 (COREPACK_ENABLE_AUTO_PIN, NODE_OPTIONS)
|
|||
|
|
│ └── Ablation baseline 环境变量设置
|
|||
|
|
│
|
|||
|
|
├── Phase 1: 快速路径路由
|
|||
|
|
│ ├── --version → console.log(MACRO.VERSION) → 退出
|
|||
|
|
│ ├── --dump-system-prompt → 渲染系统提示词 → 退出
|
|||
|
|
│ ├── --claude-in-chrome-mcp → 启动 Chrome MCP Server
|
|||
|
|
│ ├── --chrome-native-host → 启动 Chrome Native Host
|
|||
|
|
│ └── --computer-use-mcp → 启动 Computer Use MCP
|
|||
|
|
│
|
|||
|
|
├── Phase 2: CLI 初始化 (cli.tsx main())
|
|||
|
|
│ ├── import startupProfiler → profileCheckpoint('cli_entry')
|
|||
|
|
│ ├── import commander → 解析命令行参数
|
|||
|
|
│ ├── import enableConfigs() → 加载用户配置
|
|||
|
|
│ ├── 注册所有 Command (commands.ts, 60+)
|
|||
|
|
│ ├── 挂载 hook 系统
|
|||
|
|
│ └── commander.parse() → 路由到对应命令
|
|||
|
|
│
|
|||
|
|
├── Phase 3: REPL 启动 (默认模式)
|
|||
|
|
│ ├── import main.tsx → 启动 Ink 渲染器
|
|||
|
|
│ │ ├── 注册 bun:bundle polyfill (entry.ts)
|
|||
|
|
│ │ └── import App.tsx
|
|||
|
|
│ │
|
|||
|
|
│ ├── <App> 组件挂载
|
|||
|
|
│ │ ├── 检查环境 (Bun版本/终端能力)
|
|||
|
|
│ │ ├── 加载认证状态 (auth.ts)
|
|||
|
|
│ │ ├── 初始化 AppStore (createStore)
|
|||
|
|
│ │ ├── 运行 preflightChecks (网络可达性)
|
|||
|
|
│ │ └── 加载 MCP 服务端配置
|
|||
|
|
│ │
|
|||
|
|
│ └── 进入 REPL 主循环
|
|||
|
|
│ ├── 加载历史会话 (sessionRestore.ts)
|
|||
|
|
│ ├── 显示欢迎信息和系统提示
|
|||
|
|
│ └── 等待用户输入
|
|||
|
|
│
|
|||
|
|
└── Phase 4: UI 就绪
|
|||
|
|
├── VirtualMessageList 渲染历史消息
|
|||
|
|
├── StatusLine 显示模型/成本/快捷键
|
|||
|
|
└── TextInput 获得焦点,等待输入
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 1.2 启动优化策略
|
|||
|
|
|
|||
|
|
- **延迟加载**: `cli.tsx` 中的 `await import()` 确保快速路径不加载不必要模块
|
|||
|
|
- **Feature Flag DCE**: `feature('PROACTIVE')` 在构建时消除死代码
|
|||
|
|
- **Profile Checkpoint**: `startupProfiler.ts` 记录各阶段耗时
|
|||
|
|
- **预连接**: `apiPreconnect.ts` 在启动时预建立 HTTPS 连接
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 2. 对话循环(核心数据流)
|
|||
|
|
|
|||
|
|
### 2.1 主循环
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
用户输入 "帮我重构这个函数"
|
|||
|
|
│
|
|||
|
|
├── Step 1: 输入处理 (handlePromptSubmit.ts)
|
|||
|
|
│ ├── 解析 @file / @agent 等提及
|
|||
|
|
│ ├── 处理剪贴板图片粘贴
|
|||
|
|
│ ├── 处理引用消息 (↑ 历史选取)
|
|||
|
|
│ └── 构建 UserMessage { role: 'user', content: [...] }
|
|||
|
|
│
|
|||
|
|
├── Step 2: 预处理 Hooks (hooks.ts, 164KB)
|
|||
|
|
│ ├── UserPromptSubmit hook: 修改/拦截用户输入
|
|||
|
|
│ ├── 注入 CLAUDE.md 系统上下文
|
|||
|
|
│ ├── 加载 MEMORY.md 记忆内容
|
|||
|
|
│ └── 加载 Skills 和 MCP 指令
|
|||
|
|
│
|
|||
|
|
├── Step 3: 构建 Query (QueryEngine.ts)
|
|||
|
|
│ ├── 构建 System Prompt:
|
|||
|
|
│ │ ├── 基础系统提示词 (constants/prompts.ts, 55KB)
|
|||
|
|
│ │ ├── 环境信息 (OS/Shell/Git/日期)
|
|||
|
|
│ │ ├── 工具清单 (所有可用工具的 name + description + schema)
|
|||
|
|
│ │ ├── CLAUDE.md 内容 (项目级 + 用户级)
|
|||
|
|
│ │ ├── MEMORY.md 内容 (自动记忆)
|
|||
|
|
│ │ └── MCP 服务端提供的上下文
|
|||
|
|
│ │
|
|||
|
|
│ ├── 构建 Messages:
|
|||
|
|
│ │ ├── 历史消息 (截断至 Token 预算)
|
|||
|
|
│ │ ├── 当前 UserMessage
|
|||
|
|
│ │ └── Tool Results (若有待回传)
|
|||
|
|
│ │
|
|||
|
|
│ └── 选择模型: getMainLoopModel() → Claude Opus/Sonnet/Haiku
|
|||
|
|
│
|
|||
|
|
├── Step 4: API 调用
|
|||
|
|
│ ├── POST https://api.anthropic.com/v1/messages
|
|||
|
|
│ ├── Headers: x-api-key, anthropic-version, ...
|
|||
|
|
│ ├── Body: { model, system, messages, tools, max_tokens, ... }
|
|||
|
|
│ ├── Stream: true (SSE 流式响应)
|
|||
|
|
│ │
|
|||
|
|
│ └── 处理响应流 (server-sent events)
|
|||
|
|
│ ├── message_start → 新消息开始
|
|||
|
|
│ ├── content_block_start → 文本块/工具调用块开始
|
|||
|
|
│ ├── content_block_delta → 增量内容 (text_delta / input_json_delta)
|
|||
|
|
│ ├── content_block_stop → 块结束
|
|||
|
|
│ ├── message_delta → 用量/结束原因
|
|||
|
|
│ └── message_stop → 消息完成
|
|||
|
|
│
|
|||
|
|
├── Step 5: 响应处理
|
|||
|
|
│ ├── 解析 content_block 类型:
|
|||
|
|
│ │ ├── text → 实时渲染 Markdown (打字机效果)
|
|||
|
|
│ │ ├── tool_use → 进入工具调用流程 (见 Step 6)
|
|||
|
|
│ │ └── thinking → 渲染扩展思考 (可选展示)
|
|||
|
|
│ │
|
|||
|
|
│ └── 更新会话状态:
|
|||
|
|
│ ├── 追加 AssistantMessage 到消息列表
|
|||
|
|
│ ├── 更新 Token 使用量 / 成本
|
|||
|
|
│ └── 持久化到 sessionStorage
|
|||
|
|
│
|
|||
|
|
├── Step 6: 工具调用循环 (Tool Use Loop)
|
|||
|
|
│ ├── 解析 tool_use 参数 (JSON → Zod 校验)
|
|||
|
|
│ ├── 权限检查 (useCanUseTool)
|
|||
|
|
│ │ ├── 需要用户确认 → 弹出权限 UI → 等待用户决策
|
|||
|
|
│ │ │ ├── 批准 → 继续
|
|||
|
|
│ │ │ └── 拒绝 → 返回拒绝消息
|
|||
|
|
│ │ └── 自动批准 → 继续
|
|||
|
|
│ │
|
|||
|
|
│ ├── 执行工具:
|
|||
|
|
│ │ ├── 触发 PreToolUse hooks
|
|||
|
|
│ │ ├── tool.toolUseOutput(params)
|
|||
|
|
│ │ │ ├── BashTool: spawn 子进程 + 流式输出
|
|||
|
|
│ │ │ ├── FileEditTool: 读取文件 + 字符串替换 + 写回
|
|||
|
|
│ │ │ ├── AgentTool: fork 子 Agent + 等待完成
|
|||
|
|
│ │ │ └── WebFetchTool: HTTP GET + HTML→Markdown + AI 提取
|
|||
|
|
│ │ └── 触发 PostToolUse hooks
|
|||
|
|
│ │
|
|||
|
|
│ ├── 构建 ToolResult:
|
|||
|
|
│ │ { role: 'user', content: [{ type: 'tool_result', tool_use_id, content }] }
|
|||
|
|
│ │
|
|||
|
|
│ ├── 回传模型 (回到 Step 4)
|
|||
|
|
│ │ 模型收到工具结果后继续生成回复或调用更多工具
|
|||
|
|
│ │
|
|||
|
|
│ └── 循环终止条件:
|
|||
|
|
│ ├── 模型仅返回 text (不再调用工具)
|
|||
|
|
│ ├── 达到最大工具轮次
|
|||
|
|
│ ├── 用户手动中断 (Ctrl+C)
|
|||
|
|
│ └── Token 预算用尽 (触发自动压缩)
|
|||
|
|
│
|
|||
|
|
├── Step 7: 响应完成
|
|||
|
|
│ ├── 触发 Stop hooks
|
|||
|
|
│ ├── 自动内存提取 (extractMemories)
|
|||
|
|
│ ├── 文件历史快照 (fileHistoryMakeSnapshot)
|
|||
|
|
│ ├── 更新会话标题 (sessionTitle.ts)
|
|||
|
|
│ └── 统计记录 (成本/时间/工具调用次数)
|
|||
|
|
│
|
|||
|
|
└── 回到 Step 1: 等待下一条用户输入
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2.2 流式渲染管道
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
API SSE Stream
|
|||
|
|
│
|
|||
|
|
▼
|
|||
|
|
Stream Processor (query.ts)
|
|||
|
|
│ 解析 SSE events, 拼接 JSON fragments
|
|||
|
|
▼
|
|||
|
|
Message Builder (messages.ts)
|
|||
|
|
│ 构建 Message 对象树
|
|||
|
|
▼
|
|||
|
|
React State Update (useReplBridge.tsx)
|
|||
|
|
│ setState(newMessage) → React re-render
|
|||
|
|
▼
|
|||
|
|
Ink Reconciler (ink/reconciler.ts)
|
|||
|
|
│ Virtual DOM diff
|
|||
|
|
▼
|
|||
|
|
Node → ANSI Renderer (ink/render-node-to-output.ts)
|
|||
|
|
│ React 元素 → ANSI 字符串
|
|||
|
|
▼
|
|||
|
|
Screen Buffer (ink/screen.ts)
|
|||
|
|
│ 计算 diff, 仅输出变化部分
|
|||
|
|
▼
|
|||
|
|
Terminal Output (ink/output.ts)
|
|||
|
|
│ process.stdout.write(ansiString)
|
|||
|
|
▼
|
|||
|
|
用户终端
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 3. Task 生命周期
|
|||
|
|
|
|||
|
|
### 3.1 主会话任务
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
用户连接 REPL
|
|||
|
|
│
|
|||
|
|
├── 创建 LocalMainSessionTask
|
|||
|
|
│ ├── status: 'pending'
|
|||
|
|
│ ├── 开始首次对话 → status: 'running'
|
|||
|
|
│ │ ├── 每次对话循环 (QueryEngine)
|
|||
|
|
│ │ └── 工具执行 (Bash/Agent/...)
|
|||
|
|
│ │
|
|||
|
|
│ └── 结束条件:
|
|||
|
|
│ ├── 用户退出 (Ctrl+C / /exit) → status: 'completed'
|
|||
|
|
│ ├── 崩溃/异常 → status: 'failed'
|
|||
|
|
│ └── 用户中断 (Ctrl+C during run) → status: 'cancelled'
|
|||
|
|
│
|
|||
|
|
└── 会话持久化 (sessionStorage.ts)
|
|||
|
|
└── ~/.claude/projects/<repo>/<session-id>.jsonl
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3.2 子 Agent 任务
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
AgentTool.toolUseOutput()
|
|||
|
|
│
|
|||
|
|
├── 创建 LocalAgentTask 或 RemoteAgentTask
|
|||
|
|
│ ├── status: 'pending'
|
|||
|
|
│ ├── 分配工具子集 (根据 subagent_type)
|
|||
|
|
│ │ ├── general-purpose → 全部工具
|
|||
|
|
│ │ ├── explore → Glob + Grep + Read (只读)
|
|||
|
|
│ │ └── plan → 仅计划工具
|
|||
|
|
│ │
|
|||
|
|
│ ├── 构建独立系统提示词 (Agent 角色描述)
|
|||
|
|
│ │
|
|||
|
|
│ └── 开始执行:
|
|||
|
|
│ ├── status: 'running'
|
|||
|
|
│ ├── 独立对话循环 (独立的 QueryEngine)
|
|||
|
|
│ │ ├── 上下文隔离 (不共享主会话消息)
|
|||
|
|
│ │ └── 消耗独立 Token 预算
|
|||
|
|
│ │
|
|||
|
|
│ ├── run_in_background: true
|
|||
|
|
│ │ ├── 后台执行,不阻塞
|
|||
|
|
│ │ └── 完成时通过 notification 通知
|
|||
|
|
│ │
|
|||
|
|
│ └── run_in_background: false (默认)
|
|||
|
|
│ ├── 前台阻塞等待
|
|||
|
|
│ └── 完成时返回结果给调用者
|
|||
|
|
│
|
|||
|
|
└── 结果归并:
|
|||
|
|
├── 成功 → 提取关键产出 + 清理临时上下文
|
|||
|
|
└── 失败 → 错误信息 + 部分产出
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3.3 Shell 后台任务
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
BashTool 长时间命令
|
|||
|
|
│
|
|||
|
|
├── 创建 LocalShellTask
|
|||
|
|
│ ├── 后台执行: spawn(command, { detached: true })
|
|||
|
|
│ ├── 实时输出: stdout/stderr → stream
|
|||
|
|
│ │ └── UI 实时显示在 TaskListV2 面板
|
|||
|
|
│ │
|
|||
|
|
│ └── 完成: exitCode + 完整输出
|
|||
|
|
│
|
|||
|
|
└── 生命周期管理:
|
|||
|
|
├── 用户可随时取消: task.kill()
|
|||
|
|
├── 超时自动终止: setTimeout(kill, timeout)
|
|||
|
|
└── 退出清理: gracefulShutdown 等待所有任务完成
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 4. 会话持久化与恢复
|
|||
|
|
|
|||
|
|
### 4.1 会话存储结构
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
~/.claude/
|
|||
|
|
├── projects/
|
|||
|
|
│ └── <project_hash>/
|
|||
|
|
│ ├── <session_id>.jsonl # 完整对话记录 (JSONL)
|
|||
|
|
│ ├── <session_id>.meta.json # 会话元数据
|
|||
|
|
│ └── memory/
|
|||
|
|
│ └── MEMORY.md # 自动记忆索引
|
|||
|
|
│
|
|||
|
|
├── settings.json # 用户全局设置
|
|||
|
|
├── credentials.json # API Key 等凭证 (加密)
|
|||
|
|
└── stats/
|
|||
|
|
└── usage.json # 用量统计
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 4.2 会话恢复流程
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
claude --resume (或 /resume 命令)
|
|||
|
|
│
|
|||
|
|
├── listSessionsImpl() 列出所有历史会话
|
|||
|
|
│ └── 解析 <session_id>.meta.json → 标题/时间/模型
|
|||
|
|
│
|
|||
|
|
├── ResumeConversation 界面
|
|||
|
|
│ └── 用户选择要恢复的会话
|
|||
|
|
│
|
|||
|
|
├── sessionRestore.ts 加载会话
|
|||
|
|
│ ├── 读取 .jsonl 文件
|
|||
|
|
│ ├── 解析所有 Message 对象
|
|||
|
|
│ ├── 重建 AppState (消息列表/任务状态)
|
|||
|
|
│ └── 恢复上下文 (模型/配置/权限模式)
|
|||
|
|
│
|
|||
|
|
└── 继续对话 (从上次中断处)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 4.3 会话导出
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
ExportDialog
|
|||
|
|
├── Markdown: 渲染对话为 .md 文件
|
|||
|
|
├── JSON: 原始 JSON 格式
|
|||
|
|
├── HTML: 静态 HTML 页面 (含样式)
|
|||
|
|
└── PNG: 终端截图 (通过 ansiToPng, 215KB)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 5. Bridge 模式数据流
|
|||
|
|
|
|||
|
|
### 5.1 Bridge 连接流程
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
本地 Claude Code (Client) 远程环境 (Server)
|
|||
|
|
│ │
|
|||
|
|
├── claude remote-control │
|
|||
|
|
│ (启动 Bridge 监听) │
|
|||
|
|
│ │
|
|||
|
|
├── WebSocket/TCP 连接 ────────────────►│
|
|||
|
|
│ ├── 鉴权 (JWT/TrustedDevice)
|
|||
|
|
│ ├── 环境信息交换
|
|||
|
|
│ ◄── Handshake OK ────────────────│ ├── 创建工作目录
|
|||
|
|
│ │
|
|||
|
|
├── 会话同步 (replBridge.ts, 102KB) │
|
|||
|
|
│ ├── 发送 AppState 快照 ───────────►│ ├── 应用状态到远程
|
|||
|
|
│ ├── 发送用户消息 ──────────────────►│ ├── 执行查询
|
|||
|
|
│ │ │ ├── 工具调用在远程执行
|
|||
|
|
│ │ ◄── 流式响应 ────────────────│ ├── 文件操作在远程执行
|
|||
|
|
│ │ │
|
|||
|
|
│ ◄── 状态同步 ────────────────────│ ├── 远程文件变化回传
|
|||
|
|
│ ◄── 进度通知 ────────────────────│ │
|
|||
|
|
│ │
|
|||
|
|
└── 双向同步维持 │
|
|||
|
|
├── 心跳 (keep-alive) │
|
|||
|
|
├── 断线重连 (replBridgeTransport) │
|
|||
|
|
└── 会话恢复 (sessionRunner) │
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 5.2 Bridge 状态机
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
DISCONNECTED
|
|||
|
|
│ (用户触发连接)
|
|||
|
|
▼
|
|||
|
|
CONNECTING
|
|||
|
|
│ (WebSocket 连接建立)
|
|||
|
|
├── 成功 → HANDSHAKE
|
|||
|
|
└── 失败 → DISCONNECTED (显示错误, 可重试)
|
|||
|
|
|
|||
|
|
HANDSHAKE
|
|||
|
|
│ (JWT 验证 + 设备信任)
|
|||
|
|
├── 成功 → CONNECTED
|
|||
|
|
└── 失败 → DISCONNECTED (认证错误)
|
|||
|
|
|
|||
|
|
CONNECTED
|
|||
|
|
│ (会话同步初始化)
|
|||
|
|
▼
|
|||
|
|
SYNCED
|
|||
|
|
│ (正常双向通信)
|
|||
|
|
├── 断线 → RECONNECTING
|
|||
|
|
└── 用户断开 → DISCONNECTED
|
|||
|
|
|
|||
|
|
RECONNECTING
|
|||
|
|
├── 重连成功 → SYNCED
|
|||
|
|
└── 超时 → DISCONNECTED
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 6. Memory 系统数据流
|
|||
|
|
|
|||
|
|
### 6.1 记忆生命周期
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
会话启动
|
|||
|
|
│
|
|||
|
|
├── memdir.loadMemoryPrompt()
|
|||
|
|
│ ├── 扫描 ~/.claude/projects/<project>/memory/
|
|||
|
|
│ ├── 读取 MEMORY.md 索引
|
|||
|
|
│ ├── 读取每个 .md 记忆文件
|
|||
|
|
│ │ ├── 解析 frontmatter (name/description/type)
|
|||
|
|
│ │ └── 提取正文内容
|
|||
|
|
│ │
|
|||
|
|
│ └── findRelevantMemories()
|
|||
|
|
│ ├── 基于当前会话上下文匹配相关记忆
|
|||
|
|
│ └── 按新鲜度排序 (memoryAge)
|
|||
|
|
│
|
|||
|
|
├── 拼入 System Prompt
|
|||
|
|
│ └── "# Memory\n... (相关记忆内容) ..."
|
|||
|
|
│
|
|||
|
|
└── 会话中
|
|||
|
|
├── 模型使用 Write 工具 → 写入新的 .md 文件
|
|||
|
|
│ └── 更新 MEMORY.md 索引
|
|||
|
|
│
|
|||
|
|
├── extractMemories 服务 → 自动从对话中提取
|
|||
|
|
│ └── 后台异步写入
|
|||
|
|
│
|
|||
|
|
└── 会话结束
|
|||
|
|
└── 记忆文件保持不变 (跨会话持久化)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 6.2 四种记忆类型
|
|||
|
|
|
|||
|
|
```markdown
|
|||
|
|
---
|
|||
|
|
name: <名称>
|
|||
|
|
description: <一行描述>
|
|||
|
|
type: user | feedback | project | reference
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
<内容>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
| 类型 | 用途 | 示例 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| **user** | 用户角色/偏好/知识 | "用户是资深 Go 开发者" |
|
|||
|
|
| **feedback** | 用户反馈的行为规范 | "不要 mock 数据库测试" |
|
|||
|
|
| **project** | 项目上下文/目标 | "下周四冻结合并" |
|
|||
|
|
| **reference** | 外部系统指针 | "Bug 在 Linear INGEST 项目里" |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 7. Hook 系统
|
|||
|
|
|
|||
|
|
### 7.1 可用 Hook 事件
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
interface Hooks {
|
|||
|
|
// 事件触发型
|
|||
|
|
UserPromptSubmit: (messages) => messages // 用户提交前
|
|||
|
|
PreToolUse: (toolName, params) => params // 工具执行前
|
|||
|
|
PostToolUse: (toolName, result) => void // 工具执行后
|
|||
|
|
Stop: (session) => void // 对话完成
|
|||
|
|
|
|||
|
|
// 通知型
|
|||
|
|
Notification: (event) => void // 各类事件通知
|
|||
|
|
SessionStart: (info) => void // 会话启动
|
|||
|
|
|
|||
|
|
// 配置型 (settings.json)
|
|||
|
|
// "hooks": { "PreToolUse": [{ "matcher": "Bash", "command": "..." }] }
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 7.2 Hook 执行流程
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
事件触发
|
|||
|
|
│
|
|||
|
|
├── 加载 hooks 配置 (hooks.ts)
|
|||
|
|
│ ├── settings.json 中的 hooks 数组
|
|||
|
|
│ └── 项目级 .claude/settings.json
|
|||
|
|
│
|
|||
|
|
├── 匹配规则
|
|||
|
|
│ ├── matcher: 工具名/正则/通配符
|
|||
|
|
│ └── 仅匹配的 hook 执行
|
|||
|
|
│
|
|||
|
|
└── 执行
|
|||
|
|
├── shell command hooks: spawn(command, args)
|
|||
|
|
├── 内置 hooks: 调用内部函数
|
|||
|
|
└── 超时控制: 长时间 hook 被终止
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 8. 工具结果存储
|
|||
|
|
|
|||
|
|
`toolResultStorage.ts` (39KB) 负责工具调用结果(特别是大文件)的存储策略:
|
|||
|
|
|
|||
|
|
- **小结果** (< 阈值): 直接存在消息对象中
|
|||
|
|
- **大结果**: 写入临时文件,消息中只存文件引用路径
|
|||
|
|
- **图片结果**: 存为 Base64 或文件引用,带缩放缓存
|
|||
|
|
- **清理**: 会话关闭时自动清理临时文件
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 9. 错误处理与恢复
|
|||
|
|
|
|||
|
|
### 9.1 API 错误分类
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
API 错误
|
|||
|
|
├── 可重试错误 (retryable)
|
|||
|
|
│ ├── 429 Rate Limit → 指数退避重试
|
|||
|
|
│ ├── 5xx Server Error → 线性退避重试
|
|||
|
|
│ └── 网络超时 → 立即重试 (最多3次)
|
|||
|
|
│
|
|||
|
|
├── 不可重试错误
|
|||
|
|
│ ├── 401 Unauthorized → 提示检查 API Key
|
|||
|
|
│ ├── 403 Forbidden → 提示检查权限
|
|||
|
|
│ ├── 400 Bad Request → 显示错误详情
|
|||
|
|
│ └── Token 超限 → 触发自动压缩
|
|||
|
|
│
|
|||
|
|
└── 流式中断
|
|||
|
|
├── SSE 连接断开 → 尝试重连 + 部分结果
|
|||
|
|
└── 解析错误 → 丢弃损坏chunk,继续
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 9.2 对话崩溃恢复
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
异常发生
|
|||
|
|
│
|
|||
|
|
├── conversationRecovery.ts
|
|||
|
|
│ ├── 自动保存当前状态 (crash snapshot)
|
|||
|
|
│ ├── 标记会话为 interrupted
|
|||
|
|
│ └── 下次启动时提示恢复
|
|||
|
|
│
|
|||
|
|
└── 用户重启 Claude Code
|
|||
|
|
├── 检测到未完成会话
|
|||
|
|
├── 显示 ResumeConversation 界面
|
|||
|
|
└── 从崩溃点恢复对话 (最多丢失最后一条消息)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
*本文档基于 2026-06-11 源码状态生成*
|