mirror of
https://github.com/shareAI-lab/analysis_claude_code.git
synced 2026-09-20 12:13:38 +08:00
feat: consolidate course into 21 lessons
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
[English](README.md) · [中文](README.zh.md) · [日本語](README.ja.md)
|
||||
|
||||
s01 → s02 → s03 → s04 → s05 → `s06` → [s07](../s07_skill_loading/) → s08 → ... → s20 → s21 → s22
|
||||
s01 → s02 → s03 → s04 → s05 → `s06` → [s07](../s07_skill_loading/) → s08 → ... → s20 → s21
|
||||
|
||||
> *"大きなタスクは小さく、小さなタスクごとにクリーンなコンテキスト"* — Subagent は独立した messages[] を使い、メイン会話を汚染しない。
|
||||
>
|
||||
@@ -131,59 +131,5 @@ Agent はタスクを分割できるようになった。しかし各タスク
|
||||
|
||||
→ s07 Skill Loading:スキルをオンデマンドで注入する。system prompt にドキュメントを積み上げるのではなく、必要なときだけ読み込む。ファイルを読むのと同じくらい自然に。
|
||||
|
||||
<details>
|
||||
<summary>CC ソースコードを深掘り</summary>
|
||||
|
||||
> 以下は CC ソースコード `AgentTool.tsx`、`runAgent.ts`、`forkSubagent.ts`、`forkedAgent.ts` の完全分析に基づく。
|
||||
|
||||
### 一、一つのパターンではなく三つ
|
||||
|
||||
教育版は「新規 messages[]」のみを取り上げる。CC には実際に三つの実行モードがある:
|
||||
|
||||
| モード | トリガー | コンテキスト |
|
||||
|--------|---------|-------------|
|
||||
| **Normal Subagent** | `subagent_type` 指定時(normal path) | 新規 messages[]、プロンプトのみ |
|
||||
| **Fork Subagent** | `subagent_type` 未指定、fork gate 有効時 | `buildForkedMessages()` でキャッシュフレンドリーなプレフィックスを構築、プロンプトキャッシュを共有 |
|
||||
| **General-Purpose** | `subagent_type` 未指定、fork gate 無効時 | Normal と同じ |
|
||||
|
||||
### 二、Fork モード:プロンプトキャッシュの共有のため
|
||||
|
||||
これは教育版にはない核心概念。Fork モード(`forkSubagent.ts:60-71`)は新規コンテキストを作成せず、`buildForkedMessages()`(`forkSubagent.ts:107-168`)でキャッシュフレンドリーなメッセージプレフィックスを構築する。親の assistant message を保持し、placeholder tool results を生成する。目的は隔離ではなく、Anthropic API のプロンプトキャッシュをヒットさせること:親子 Agent の system prompt、tools、messages プレフィックスがバイトレベルで一致するため、API 側で再計算が不要になる。
|
||||
|
||||
キャッシュヒットの五つの重要コンポーネント(`forkedAgent.ts:57-68`):system prompt、tools、model、messages プレフィックス、thinking config、バイトレベルで一致する必要がある。
|
||||
|
||||
### 三、コンテキスト隔離の精密な粒度
|
||||
|
||||
`createSubagentContext()`(`forkedAgent.ts:345-462`)はサブエージェントの `ToolUseContext` を作成:
|
||||
|
||||
| フィールド | 挙動 |
|
||||
|-----------|------|
|
||||
| `abortController` | 新しい子コントローラ、親の abort は下に伝播 |
|
||||
| `setAppState` | デフォルトは no-op、ただし sync agent は `shareSetAppState` で共有(`runAgent.ts:697-714`) |
|
||||
| `readFileState` | **親からクローン**(同じファイルの再読み込みを回避) |
|
||||
| `queryTracking` | 新しい chainId、`depth = parentDepth + 1` |
|
||||
|
||||
サブエージェントは完全に隔離されているわけではない。ファイル読み取り状態は共有される。UI と通知の隔離度は実行パスにより異なる(sync/async/fork/teammate でそれぞれ異なる)。
|
||||
|
||||
### 四、再帰 Fork 防護
|
||||
|
||||
教育版は「サブエージェントに task ツールなし」で再帰防止を表現する。実際の実装はより精密:`isInForkChild()`(`forkSubagent.ts:78-89`)が会話履歴内の `FORK_BOILERPLATE_TAG` をチェックする。しかし `constants/tools.ts:36-46` では `Agent` ツールが全エージェントの無効セットにデフォルト設定(`USER_TYPE === 'ant'` 時は例外)、`forkSubagent.ts:73-89` は fork child 向けの専用再帰保護があり、`agentToolUtils.ts:100-110` は teammate シナリオで特別な許可がある。単純な「サブエージェントの再 spawn 禁止」ではない。
|
||||
|
||||
### 五、Permission Bubbling
|
||||
|
||||
Fork Agent の `permissionMode: 'bubble'`(`forkSubagent.ts:67`)は、サブエージェントの権限プロンプトが親ターミナルにバブルアップすることを意味する。ユーザーはメインターミナルでサブエージェントの操作を承認する。
|
||||
|
||||
### 六、Async vs Sync
|
||||
|
||||
教育版は同期サブエージェントのみ(親が子の完了を待つ)を示す。CC は非同期パスもサポート(`AgentTool.tsx:686-764`):`run_in_background: true` の場合、サブエージェントは非同期で起動し、`{ status: 'async_launched' }` を直ちに親に返し、完了時に通知機構で親に知らせる。実際のトリガーは `run_in_background` だけでなく、auto-background、assistant force async、coordinator/proactive パスもある。
|
||||
|
||||
### 教育版の簡略化は意図的
|
||||
|
||||
- 三つのモード → 一つ(新規 messages):概念的に明確
|
||||
- プロンプトキャッシュ共有 → 省略:教育版は API 層の最適化を扱わない
|
||||
- 再帰 fork 防護 → 「サブエージェントに task ツールなし」に簡略化
|
||||
- Async → 省略(s13 に委ねる):s06 はまず同期モデルを理解する
|
||||
|
||||
</details>
|
||||
|
||||
<!-- translation-sync: zh@v1, en@v1, ja@v1 -->
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
[English](README.md) · [中文](README.zh.md) · [日本語](README.ja.md)
|
||||
|
||||
s01 → s02 → s03 → s04 → s05 → `s06` → [s07](../s07_skill_loading/) → s08 → ... → s20 → s21 → s22
|
||||
s01 → s02 → s03 → s04 → s05 → `s06` → [s07](../s07_skill_loading/) → s08 → ... → s20 → s21
|
||||
|
||||
> *"Break large tasks small, each with clean context"* — Subagent uses an independent messages[], no pollution in the main conversation.
|
||||
>
|
||||
@@ -131,59 +131,5 @@ The Agent can now break tasks apart. But different tasks require different knowl
|
||||
|
||||
→ s07 Skill Loading: Inject skills on demand instead of piling documents into the system prompt. Load only when needed, as natural as reading a file.
|
||||
|
||||
<details>
|
||||
<summary>Dive into CC Source Code</summary>
|
||||
|
||||
> The following is based on a complete analysis of CC source code `AgentTool.tsx`, `runAgent.ts`, `forkSubagent.ts`, and `forkedAgent.ts`.
|
||||
|
||||
### 1. Not One Pattern, but Three
|
||||
|
||||
The teaching version covers only "fresh messages[]". CC actually has three execution modes:
|
||||
|
||||
| Mode | Trigger | Context |
|
||||
|------|---------|---------|
|
||||
| **Normal Subagent** | `subagent_type` specified (normal path) | Truly fresh messages[], only the prompt |
|
||||
| **Fork Subagent** | No `subagent_type`, fork gate enabled | Constructs cache-friendly prefix via `buildForkedMessages()`, shares prompt cache |
|
||||
| **General-Purpose** | No `subagent_type`, fork gate disabled | Same as Normal |
|
||||
|
||||
### 2. Fork Mode: Sharing Prompt Cache
|
||||
|
||||
This is a core concept the teaching version omits. Fork mode (`forkSubagent.ts:60-71`) doesn't create a fresh context. Instead, it constructs a cache-friendly message prefix via `buildForkedMessages()` (`forkSubagent.ts:107-168`), preserving the parent assistant message and generating placeholder tool results. The goal isn't isolation, but making the Anthropic API's prompt cache hit: parent and child Agent's system prompt, tools, and message prefix are byte-identical, so the API doesn't need to recompute.
|
||||
|
||||
Five key components for cache hit (`forkedAgent.ts:57-68`): system prompt, tools, model, message prefix, thinking config, must be byte-identical.
|
||||
|
||||
### 3. Context Isolation's Precise Granularity
|
||||
|
||||
`createSubagentContext()` (`forkedAgent.ts:345-462`) creates the sub-Agent's `ToolUseContext`:
|
||||
|
||||
| Field | Behavior |
|
||||
|-------|----------|
|
||||
| `abortController` | New child controller; parent abort propagates down |
|
||||
| `setAppState` | Default no-op; but sync agents share via `shareSetAppState` (`runAgent.ts:697-714`) |
|
||||
| `readFileState` | **Cloned from parent** (avoids re-reading same files) |
|
||||
| `queryTracking` | New chainId, `depth = parentDepth + 1` |
|
||||
|
||||
The sub-Agent isn't fully isolated: file read state is shared. The degree of UI and notification isolation varies by execution path (sync/async/fork/teammate differ).
|
||||
|
||||
### 4. Recursive Fork Protection
|
||||
|
||||
The teaching version uses "sub-Agent has no task tool" for recursion protection. The real implementation is more nuanced: `isInForkChild()` (`forkSubagent.ts:78-89`) checks for `FORK_BOILERPLATE_TAG` in history. But `constants/tools.ts:36-46` defaults `Agent` to all agents' disabled set (with `USER_TYPE === 'ant'` exception); `forkSubagent.ts:73-89` has fork-child-specific recursion protection; `agentToolUtils.ts:100-110` has special allowances in teammate scenarios. Not simply "no further sub-Agents."
|
||||
|
||||
### 5. Permission Bubbling
|
||||
|
||||
Fork Agent's `permissionMode: 'bubble'` (`forkSubagent.ts:67`) means the sub-Agent's permission prompts bubble up to the parent terminal: the user approves sub-Agent operations in the main terminal.
|
||||
|
||||
### 6. Async vs Sync
|
||||
|
||||
The teaching version only shows synchronous sub-Agents (parent waits for child to finish). CC also supports async paths (`AgentTool.tsx:686-764`): when `run_in_background: true`, the sub-Agent launches asynchronously, returning `{ status: 'async_launched' }` immediately to the parent, and notifies the parent when complete. Actual triggers go beyond `run_in_background`, including auto-background, assistant force async, and coordinator/proactive paths.
|
||||
|
||||
### Teaching Version Simplifications Are Intentional
|
||||
|
||||
- Three modes → one (fresh messages): conceptually clear
|
||||
- Prompt cache sharing → omitted: teaching version doesn't involve API-layer optimization
|
||||
- Recursive fork protection → simplified to "sub-Agent has no task tool"
|
||||
- Async → omitted (left for s13): s06 focuses on the synchronous model first
|
||||
|
||||
</details>
|
||||
|
||||
<!-- translation-sync: zh@v1, en@v1, ja@v1 -->
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
[English](README.md) · [中文](README.zh.md) · [日本語](README.ja.md)
|
||||
|
||||
s01 → s02 → s03 → s04 → s05 → `s06` → [s07](../s07_skill_loading/) → s08 → ... → s20 → s21 → s22
|
||||
s01 → s02 → s03 → s04 → s05 → `s06` → [s07](../s07_skill_loading/) → s08 → ... → s20 → s21
|
||||
|
||||
> *"大任务拆小, 每个小任务干净的上下文"* — Subagent 用独立 messages[], 不污染主对话。
|
||||
>
|
||||
@@ -135,59 +135,5 @@ Agent 现在能拆任务了。但每个任务需要的知识不一样:改前
|
||||
|
||||
s07 Skill Loading → 技能按需注入,不在 system prompt 里堆文档。用到的时候才加载,和读文件一样自然。
|
||||
|
||||
<details>
|
||||
<summary>深入 CC 源码</summary>
|
||||
|
||||
> 以下基于 CC 源码 `AgentTool.tsx`、`runAgent.ts`、`forkSubagent.ts`、`forkedAgent.ts` 的完整分析。
|
||||
|
||||
### 一、不是一种模式,是三种
|
||||
|
||||
教学版只讲了"全新的 messages[]"。CC 实际有三种执行模式:
|
||||
|
||||
| 模式 | 触发条件 | 上下文 |
|
||||
|------|---------|--------|
|
||||
| **Normal Subagent** | 指定了 `subagent_type`(normal path) | 全新 messages[],只有 prompt |
|
||||
| **Fork Subagent** | 没指定 `subagent_type`,fork gate 开启 | 通过 `buildForkedMessages()` 构造 cache-friendly 前缀,共享 prompt cache |
|
||||
| **General-Purpose** | 没指定 `subagent_type`,fork gate 关闭 | 同 Normal |
|
||||
|
||||
### 二、Fork 模式:为了共享 Prompt Cache
|
||||
|
||||
这是教学版没有的核心概念。Fork 模式(`forkSubagent.ts:60-71`)不创建全新上下文,而是通过 `buildForkedMessages()`(`forkSubagent.ts:107-168`)构造 cache-friendly 消息前缀,保留父 assistant message 并生成 placeholder tool results。目的不是隔离,而是让 Anthropic API 的 prompt cache 命中:父子 Agent 的 system prompt、tools、messages 前缀完全一致,API 端不需要重算。
|
||||
|
||||
缓存命中的五个关键组件(`forkedAgent.ts:57-68`):system prompt、tools、model、messages 前缀、thinking config,必须字节级一致。
|
||||
|
||||
### 三、Context Isolation 的精确粒度
|
||||
|
||||
`createSubagentContext()`(`forkedAgent.ts:345-462`)创建子 Agent 的 `ToolUseContext`:
|
||||
|
||||
| 字段 | 行为 |
|
||||
|------|------|
|
||||
| `abortController` | 新的 child controller,父 abort 向下传播 |
|
||||
| `setAppState` | 默认 no-op;但 sync agent 通过 `shareSetAppState` 共享(`runAgent.ts:697-714`) |
|
||||
| `readFileState` | **从父克隆**(避免重复读相同文件) |
|
||||
| `queryTracking` | 新 chainId,`depth = parentDepth + 1` |
|
||||
|
||||
子 Agent 不是完全隔离的:文件读取状态是共享的。UI 和通知的隔离程度取决于执行路径(sync/async/fork/teammate 各不同)。
|
||||
|
||||
### 四、递归 Fork 防护
|
||||
|
||||
教学版用"子 Agent 不给 task 工具"表达递归保护。真实实现更精细:`isInForkChild()`(`forkSubagent.ts:78-89`)检查对话历史中是否有 `FORK_BOILERPLATE_TAG`,有就拒绝。但 `constants/tools.ts:36-46` 中 `Agent` 工具默认在所有 agent 的禁用集合里,`USER_TYPE === 'ant'` 时例外;`forkSubagent.ts:73-89` 针对 fork child 有专门的递归保护;`agentToolUtils.ts:100-110` 在 teammate 场景下有特殊放行。不是简单的"禁止新的子 Agent"。
|
||||
|
||||
### 五、Permission Bubbling
|
||||
|
||||
Fork Agent 的 `permissionMode: 'bubble'`(`forkSubagent.ts:67`)意味着子 Agent 的权限弹窗冒泡到父终端,用户在主终端里审批子 Agent 的操作。
|
||||
|
||||
### 六、Async vs Sync
|
||||
|
||||
教学版只展示了同步子 Agent(父等着子跑完)。CC 还支持异步路径(`AgentTool.tsx:686-764`):`run_in_background: true` 时异步启动,返回 `{ status: 'async_launched' }` 立即给父 Agent,子 Agent 完成后通过通知机制告知父 Agent。实际触发条件不止 `run_in_background`,还有 auto-background、assistant force async、coordinator/proactive 等路径。
|
||||
|
||||
### 教学版的简化是刻意的
|
||||
|
||||
- 三种模式 → 一种(fresh messages):概念清晰
|
||||
- Prompt cache 共享 → 省略:教学版不涉及 API 层优化
|
||||
- 递归 fork 防护 → 简化为"子 Agent 无 task 工具"
|
||||
- Async → 省略(留给 s13):s06 先理解同步模型
|
||||
|
||||
</details>
|
||||
|
||||
<!-- translation-sync: zh@v1, en@v0, ja@v0 -->
|
||||
|
||||
Reference in New Issue
Block a user