diff --git "a/docs/06-SystemPrompt\344\270\216OutputStyle\346\263\250\345\205\245.md" "b/docs/06-SystemPrompt\344\270\216OutputStyle\346\263\250\345\205\245.md" index be6201a..b15e0eb 100644 --- "a/docs/06-SystemPrompt\344\270\216OutputStyle\346\263\250\345\205\245.md" +++ "b/docs/06-SystemPrompt\344\270\216OutputStyle\346\263\250\345\205\245.md" @@ -1,6 +1,6 @@ # 第 6 章:System Prompt 与 Output Style 注入 — 精密控制模型行为的提示词体系 -> 本章是《深入 Claude Code 源码》系列第 6 章。我们将深入 `constants/prompts.ts`(914 行,commit `290fdc94`)这个核心文件,揭示 Claude Code 如何通过精心设计的 System Prompt 架构,在「精确控制模型行为」和「最大化 Prompt Cache 命中率」之间取得平衡。 +> 本章是《深入 Claude Code 源码》系列第 6 章。我们将深入 `constants/prompts.ts`(914 行)这个核心文件,揭示 Claude Code 如何通过精心设计的 System Prompt 架构,在「精确控制模型行为」和「最大化 Prompt Cache 命中率」之间取得平衡。 ## 为什么 System Prompt 值得单独一篇? diff --git "a/docs/09-Thinking-Effort-\344\270\216-Advisor.md" "b/docs/09-Thinking-Effort-\344\270\216-Advisor.md" index 135e04d..0e63f94 100644 --- "a/docs/09-Thinking-Effort-\344\270\216-Advisor.md" +++ "b/docs/09-Thinking-Effort-\344\270\216-Advisor.md" @@ -935,10 +935,11 @@ export function shouldEnablePromptSuggestion(): boolean { 整个文件最值得划重点的是 `generateSuggestion()` 的实现策略(`promptSuggestion.ts:294-352`):它不开一个全新的轻量请求,而是把主对话当前的 `cacheSafeParams` 原样复制一份,只把 `SUGGESTION_PROMPT`(258-287 行)作为一条 **user message** 追加进去(`promptSuggestion.ts:319-321`:`promptMessages: [createUserMessage({ content: prompt })]`),让模型从用户视角接龙——刻意不动 `system` 字段就是为了不破坏主对话的 cache 前缀。 -为什么这么绕?因为 Anthropic 的 Prompt Cache 是**前缀严格匹配**的——任何一个参数(包括 `system`、`tools`、`temperature`、甚至 `thinking` / `effort`)和主请求不一致,就会触发一次完整的 cache write 而不是 cache hit。代码注释里直接写了教训: +为什么这么绕?因为 Anthropic 的 Prompt Cache 是**前缀严格匹配**的——任何一个参数(包括 `system`、`tools`、`temperature`、甚至 `thinking` / `effort`)和主请求不一致,就会触发一次完整的 cache write 而不是 cache hit。源码里的代码注释(`services/PromptSuggestion/promptSuggestion.ts:313`)直接写了教训,下面是它的中文转述: ```typescript -// PR #18143 复盘:早期版本把建议请求的 effort 强行降到 'low' 节省成本, +// 改写自 services/PromptSuggestion/promptSuggestion.ts:313 的英文注释: +// 早期版本把建议请求的 effort 强行降到 'low' 节省成本, // 结果 cache write 量飙升 45x,主对话的 cache hit rate 从 92.7% 跌到 61%。 // 节省的那点 effort 钱远抵不上 cache miss 多花的钱。 ``` diff --git "a/docs/18-MCP\345\215\217\350\256\256\345\256\236\347\216\260.md" "b/docs/18-MCP\345\215\217\350\256\256\345\256\236\347\216\260.md" index b58b591..3bddc7c 100644 --- "a/docs/18-MCP\345\215\217\350\256\256\345\256\236\347\216\260.md" +++ "b/docs/18-MCP\345\215\217\350\256\256\345\256\236\347\216\260.md" @@ -975,8 +975,6 @@ Channel 通知的注册逻辑尤其值得关注——它经过多层门控(`ga --- ---- - ## 下一章预告 [第 19 章:权限系统与远程权限回灌 — AI 安全的最后一道防线](./19-权限系统与远程权限回灌.md) diff --git "a/docs/19-\346\235\203\351\231\220\347\263\273\347\273\237\344\270\216\350\277\234\347\250\213\346\235\203\351\231\220\345\233\236\347\201\214.md" "b/docs/19-\346\235\203\351\231\220\347\263\273\347\273\237\344\270\216\350\277\234\347\250\213\346\235\203\351\231\220\345\233\236\347\201\214.md" index a7853be..8665981 100644 --- "a/docs/19-\346\235\203\351\231\220\347\263\273\347\273\237\344\270\216\350\277\234\347\250\213\346\235\203\351\231\220\345\233\236\347\201\214.md" +++ "b/docs/19-\346\235\203\351\231\220\347\263\273\347\273\237\344\270\216\350\277\234\347\250\213\346\235\203\351\231\220\345\233\236\347\201\214.md" @@ -945,8 +945,6 @@ async recheckPermission() { --- ---- - ## 下一章预告 [第 20 章:Hooks 系统 — 用 Shell 命令扩展 AI 行为](./20-Hooks系统.md) diff --git "a/docs/27-\347\273\204\344\273\266\344\270\216\350\256\276\350\256\241\347\263\273\347\273\237.md" "b/docs/27-\347\273\204\344\273\266\344\270\216\350\256\276\350\256\241\347\263\273\347\273\237.md" index 897e7bc..d09b09e 100644 --- "a/docs/27-\347\273\204\344\273\266\344\270\216\350\256\276\350\256\241\347\263\273\347\273\237.md" +++ "b/docs/27-\347\273\204\344\273\266\344\270\216\350\256\276\350\256\241\347\263\273\347\273\237.md" @@ -521,8 +521,6 @@ interface Tool { --- ---- - ## 下一章预告 [第 28 章:Keybindings、Vim 模式与 Voice 输入 — 终端输入层的三种解释](./28-Keybindings-Vim与Voice输入.md) diff --git "a/docs/28-Keybindings-Vim\344\270\216Voice\350\276\223\345\205\245.md" "b/docs/28-Keybindings-Vim\344\270\216Voice\350\276\223\345\205\245.md" index 9602901..eb3ab29 100644 --- "a/docs/28-Keybindings-Vim\344\270\216Voice\350\276\223\345\205\245.md" +++ "b/docs/28-Keybindings-Vim\344\270\216Voice\350\276\223\345\205\245.md" @@ -618,8 +618,6 @@ Keybindings 是按键派发的基础设施,但 Vim 的 Escape 故意绕过这 --- ---- - ## 下一章预告 [第 29 章:Buddy 宠物 — 在 PromptInput 边上养一只随机生成的小动物](./29-Buddy宠物.md) diff --git "a/docs/29-Buddy\345\256\240\347\211\251.md" "b/docs/29-Buddy\345\256\240\347\211\251.md" index 71d9601..0b830a1 100644 --- "a/docs/29-Buddy\345\256\240\347\211\251.md" +++ "b/docs/29-Buddy\345\256\240\347\211\251.md" @@ -351,7 +351,7 @@ case 'companion_intro': 发现入口的设计在 `useBuddyNotification.tsx`。`buddy/useBuddyNotification.tsx:12-21` 给出两个判断函数 `isBuddyTeaserWindow()` 和 `isBuddyLive()`,它们都先有一道 `if ('external' === 'ant') return true` 的字面量比较,然后用 `new Date()` 拿到当前时间,分别比较年月日。`isBuddyTeaserWindow` 返回 `d.getFullYear() === 2026 && d.getMonth() === 3 && d.getDate() <= 7`——2026 年 4 月 1 日到 7 日;`isBuddyLive` 返回 `d.getFullYear() > 2026 || (d.getFullYear() === 2026 && d.getMonth() >= 3)`——2026 年 4 月及之后。 -两个判断都走 **本地日期**——`getFullYear() / getMonth() / getDate()`,不是 `getUTC*`。源码注释里把理由写明白了: +两个判断都走 **本地日期**——`getFullYear() / getMonth() / getDate()`,不是 `getUTC*`。源码注释(`buddy/useBuddyNotification.tsx:9-10`)里把理由写明白了: > Local date, not UTC — 24h rolling wave across timezones. Sustained Twitter buzz instead of a single UTC-midnight spike, gentler on soul-gen load. diff --git "a/docs/32-\345\221\275\344\273\244\347\263\273\347\273\237\345\205\250\346\231\257.md" "b/docs/32-\345\221\275\344\273\244\347\263\273\347\273\237\345\205\250\346\231\257.md" index ee59fa3..43ca949 100644 --- "a/docs/32-\345\221\275\344\273\244\347\263\273\347\273\237\345\205\250\346\231\257.md" +++ "b/docs/32-\345\221\275\344\273\244\347\263\273\347\273\237\345\205\250\346\231\257.md" @@ -168,7 +168,7 @@ switch (command.type) { `commands.ts` 是整个命令系统的**聚合枢纽**。它将来自六个不同来源的命令合并为一个统一的列表。 -聚合枢纽本身有多大?`commands.ts` 当前 754 行(`commands.ts:1-754`),向上挂接了 `commands/` 目录——这个目录在 commit `290fdc9` 上是 86 个一级子目录 + 15 个一级 `.ts/.tsx` 文件 = 101 个一级条目,合计 207 个源码文件。这 101 个一级条目基本是一对一地各自承载一个内建命令(少数文件只是辅助模块,如 `createMovedToPluginCommand.ts`)。换句话说,下面这套 `loadAllCommands()` 加载机制要把这 207 个文件、连同来自磁盘 Skill / Plugin / Bundled / Workflow 的命令,统一收编进同一份 `Command[]` 列表里(MCP Skill 不走 `loadAllCommands()`,而是由 SkillTool 在执行时通过 `AppState.mcp.commands` 并入,详见 §4.3 与 §6.1)。 +聚合枢纽本身有多大?`commands.ts` 当前 754 行(`commands.ts:1-754`),向上挂接了 `commands/` 目录——这个目录在当前快照上是 86 个一级子目录 + 15 个一级 `.ts/.tsx` 文件 = 101 个一级条目,合计 207 个源码文件。这 101 个一级条目基本是一对一地各自承载一个内建命令(少数文件只是辅助模块,如 `createMovedToPluginCommand.ts`)。换句话说,下面这套 `loadAllCommands()` 加载机制要把这 207 个文件、连同来自磁盘 Skill / Plugin / Bundled / Workflow 的命令,统一收编进同一份 `Command[]` 列表里(MCP Skill 不走 `loadAllCommands()`,而是由 SkillTool 在执行时通过 `AppState.mcp.commands` 并入,详见 §4.3 与 §6.1)。 ### 2.1 内建命令:静态导入 + Feature Gate diff --git "a/docs/33-\347\212\266\346\200\201\347\256\241\347\220\206\344\270\216\350\267\250\350\277\233\347\250\213\346\241\245.md" "b/docs/33-\347\212\266\346\200\201\347\256\241\347\220\206\344\270\216\350\267\250\350\277\233\347\250\213\346\241\245.md" index f43bf6c..8161092 100644 --- "a/docs/33-\347\212\266\346\200\201\347\256\241\347\220\206\344\270\216\350\267\250\350\277\233\347\250\213\346\241\245.md" +++ "b/docs/33-\347\212\266\346\200\201\347\256\241\347\220\206\344\270\216\350\267\250\350\277\233\347\250\213\346\241\245.md" @@ -814,8 +814,6 @@ export async function readBridgePointerAcrossWorktrees( --- ---- - ## 下一章预告 [第 34 章:架构模式总结 — 可迁移到你自己项目的设计模式](./34-架构模式总结.md)