feat: consolidate course into 21 lessons

This commit is contained in:
Haoran
2026-07-31 03:15:58 +08:00
parent 4bc33ec858
commit 2d69019342
200 changed files with 7338 additions and 10829 deletions

View File

@@ -2,7 +2,7 @@
[English](README.md) · [中文](README.zh.md) · [日本語](README.ja.md)
`s01` → [s02](../s02_tool_use/) → s03 → s04 → ... → s20 → s21 → s22
`s01` → [s02](../s02_tool_use/) → s03 → s04 → ... → s20 → s21
> *"One loop & Bash is all you need"* — ツール一つ + ループ一つ = 一つの Agent。
>
> **Harness レイヤー**: ループ — モデルと現実世界をつなぐ最初の架け橋。
@@ -113,7 +113,7 @@ def agent_loop(messages):
## 試してみよう
> **教育デモの注意**: このコードはモデルが生成したシェルコマンドを実行します。プロジェクトファイルへの影響を避けるため、一時テストディレクトリで実行してください。s03 で本格的な権限システムを説明します。
> **安全上の注意**: このコードはモデルが生成したシェルコマンドを実行します。プロジェクトファイルへの影響を避けるため、一時テストディレクトリで実行してください。s03 で権限制御を追加します。
**準備**(初回のみ):
@@ -145,63 +145,5 @@ python s01_agent_loop/code.py
→ s02 Tool Use5 つの本格的なツールを与えたらどうなる? モデルは複数のツールを同時に呼び出すか? 並列実行で競合は起きないか?
<details>
<summary>CC ソースコードを深掘り</summary>
> 以下は CC ソースコード `src/query.ts`1729 行の検証に基づく。核心的な違いは二つCC はループ継続の判断に `stop_reason` フィールドを頼らず、コンテンツに `tool_use` ブロックが含まれるかをチェックする(ストリーミングレスポンスでは `stop_reason` が信頼できないため。CC には本番環境向けのより多くの終了パスとリカバリ戦略がある。
**教育版の 30 行 `while True` が CC の 1729 行の核心。** 以下の各項目は、すべてその核心の上に積み重ねられた保護機構である。
<details>
<summary>一、ループ構造の違い</summary>
教育版は `response.stop_reason` をチェックする。CC はこれをループ継続の唯一の根拠として使わない — ストリーミングレスポンスでは、`stop_reason` がまだ更新されていなくても、コンテンツに既に `tool_use` ブロックが含まれている可能性がある。CC は `needsFollowUp` フラグを使用する:ストリーミングメッセージの受信時(`query.ts:830-834`)に、`tool_use` ブロックが検出されると `true` に設定される。`QueryEngine.ts``message_delta` から実際の `stop_reason` を取得して他の処理に利用するが、query loop 自体は `needsFollowUp` に依存する。
```typescript
// query.ts:554-558
// stop_reason === 'tool_use' is unreliable.
// Set during streaming whenever a tool_use block arrives.
let needsFollowUp = false
```
</details>
<details>
<summary>二、State オブジェクト 10 フィールド(教育版は messages のみ使用)</summary>
| # | フィールド | 用途 | 対応章 |
|---|-----------|------|--------|
| 1 | `messages` | 現在のイテレーションのメッセージ配列 | s01 |
| 2 | `toolUseContext` | ツール、シグナル、権限コンテキスト | s02 |
| 3 | `autoCompactTracking` | 圧縮状態の追跡 | s08 |
| 4 | `maxOutputTokensRecoveryCount` | トークンリカバリ試行回数(上限 3 | s11 |
| 5 | `hasAttemptedReactiveCompact` | 今回のラウンドでリアクティブ圧縮を試みたか | s08 |
| 6 | `maxOutputTokensOverride` | 8K→64K へのアップグレード上書き | s11 |
| 7 | `pendingToolUseSummary` | バックグラウンド Haiku 生成のツール使用要約 | s08 |
| 8 | `stopHookActive` | 停止フックがブロッキングエラーを発生させたか | s04 |
| 9 | `turnCount` | ターン数maxTurns チェック用) | s01 |
| 10 | `transition` | 前回の継続理由 | s11 |
> 注:`taskBudgetRemaining``query.ts:291`)は loop-local のローカル変数であり、State には含まれない。ソースコメントには明確に "Loop-local (not on State)" と書かれている。
</details>
<details>
<summary>三、複数の終了パスと継続パス</summary>
教育版には 1 つの終了パスしかないモデルがツールを呼ばなければ終了。本番版には複数の終了・継続パスがあり、blocking limit、prompt too long、model error、abort、hook stop、max turns、token budget continuation、reactive compact retry など多くのシナリオをカバーしている。各シナリオには対応するリカバリまたは終了戦略がある。
</details>
<details>
<summary>四、ストリーミングツール実行と QueryEngine</summary>
CC の `StreamingToolExecutor``query.ts:561`は、モデルがまだ生成中にツールの実行を開始できるconcurrency-safe なツールは並列、それ以外は排他実行)。`QueryEngine.ts` はさらに、コスト超過や構造化出力の検証失敗などの保護を追加する。教育版はこれらを実装しない — 目標は概念の明確さであり、極限のパフォーマンスではない。
</details>
**一言で**: query.ts の 1729 行の核心は 30 行の `while True`。複雑なフィールドや終了パスはすべて保護機構だ。まず核心のループを理解すれば、その後のすべては自然に理解できる。
</details>
<!-- translation-sync: zh@v1, en@v1, ja@v1 -->

View File

@@ -2,7 +2,7 @@
[English](README.md) · [中文](README.zh.md) · [日本語](README.ja.md)
`s01` → [s02](../s02_tool_use/) → s03 → s04 → ... → s20 → s21 → s22
`s01` → [s02](../s02_tool_use/) → s03 → s04 → ... → s20 → s21
> *"One loop & Bash is all you need"* — One tool + one loop = one Agent.
>
> **Harness Layer**: The Loop — the first bridge between the model and the real world.
@@ -113,7 +113,7 @@ Under 30 lines — that's the minimal runnable agent harness kernel. It's not in
## Try It
> **Teaching demo notice**: The code executes shell commands generated by the model. Run it in a temporary test directory to avoid affecting your project files. s03 covers the real permission system.
> **Safety notice**: The code executes shell commands generated by the model. Run it in a temporary test directory to avoid affecting your project files. s03 adds permission controls.
**Setup** (first run):
@@ -145,63 +145,5 @@ Right now the model only has bash — reading files requires `cat`, writing file
→ s02 Tool Use: What happens when we give it 5 proper tools? Will the model call multiple tools at once? Will parallel tool executions step on each other?
<details>
<summary>Dive into CC Source Code</summary>
> The following is based on a review of CC source code `src/query.ts` (1729 lines). The core differences are twofold: CC doesn't rely on the `stop_reason` field to decide whether to continue the loop — instead it checks whether the content contains `tool_use` blocks (because `stop_reason` is unreliable in streaming responses); CC has more exit paths and recovery strategies for production-grade protection.
**The 30-line `while True` from the teaching version IS the core of CC's 1729 lines.** Everything below is a protection mechanism layered on top of that core.
<details>
<summary>1. Loop Structure Differences</summary>
The teaching version checks `response.stop_reason`. CC doesn't use it as the sole signal for loop continuation — in streaming responses, `stop_reason` may not have updated yet even though `tool_use` blocks are already present. CC uses a `needsFollowUp` flag: during streaming message reception (`query.ts:830-834`), it's set to `true` whenever a `tool_use` block is detected. `QueryEngine.ts` captures the real `stop_reason` from `message_delta` for other logic, but the query loop itself relies on `needsFollowUp`.
```typescript
// query.ts:554-558
// stop_reason === 'tool_use' is unreliable.
// Set during streaming whenever a tool_use block arrives.
let needsFollowUp = false
```
</details>
<details>
<summary>2. State Object — 10 Fields (Teaching Version Only Uses messages)</summary>
| # | Field | Purpose | Chapter |
|---|-------|---------|---------|
| 1 | `messages` | Message array for the current iteration | s01 |
| 2 | `toolUseContext` | Tool, signal, and permission context | s02 |
| 3 | `autoCompactTracking` | Compaction state tracking | s08 |
| 4 | `maxOutputTokensRecoveryCount` | Token recovery attempt count (max 3) | s11 |
| 5 | `hasAttemptedReactiveCompact` | Whether reactive compaction was attempted this round | s08 |
| 6 | `maxOutputTokensOverride` | 8K→64K upgrade override | s11 |
| 7 | `pendingToolUseSummary` | Background Haiku-generated tool use summary | s08 |
| 8 | `stopHookActive` | Whether the stop hook produced a blocking error | s04 |
| 9 | `turnCount` | Turn count (for maxTurns check) | s01 |
| 10 | `transition` | Last continue reason | s11 |
> Note: `taskBudgetRemaining` (`query.ts:291`) is a loop-local variable, not on State. The source comment explicitly says "Loop-local (not on State)".
</details>
<details>
<summary>3. Multiple Exit and Continue Paths</summary>
The teaching version has only 1 exit path (model doesn't call a tool → done). The production version has multiple exit and continue paths, covering blocking limit, prompt too long, model error, abort, hook stop, max turns, token budget continuation, reactive compact retry, and more. Each scenario has a corresponding recovery or exit strategy.
</details>
<details>
<summary>4. Streaming Tool Execution and QueryEngine</summary>
CC's `StreamingToolExecutor` (`query.ts:561`) allows tools to begin parallel execution while the model is still generating (concurrency-safe tools run in parallel, others run exclusively). `QueryEngine.ts` adds additional protections for cost overruns, structured output validation failures, and more. The teaching version doesn't implement these — the goal is conceptual clarity, not peak performance.
</details>
**In one sentence**: The core of query.ts's 1729 lines is a 30-line `while True`. All the complex fields and exit paths are protection mechanisms. Understand the core loop first, and everything that follows unfolds naturally.
</details>
<!-- translation-sync: zh@v1, en@v1, ja@v1 -->

View File

@@ -2,7 +2,7 @@
[English](README.md) · [中文](README.zh.md) · [日本語](README.ja.md)
`s01` → [s02](../s02_tool_use/) → s03 → s04 → ... → s20 → s21 → s22
`s01` → [s02](../s02_tool_use/) → s03 → s04 → ... → s20 → s21
> *"One loop & Bash is all you need"* — 一个工具 + 一个循环 = 一个 Agent。
>
> **Harness 层**: 循环 — 模型与真实世界的第一道连接。
@@ -113,7 +113,7 @@ def agent_loop(messages):
## 试一下
> **教学 demo 提示**:代码会执行模型生成的 shell 命令。建议在一个临时测试目录中运行避免影响你的项目文件。s03 会讲真正的权限系统
> **安全提示**:代码会执行模型生成的 shell 命令。建议在一个临时测试目录中运行避免影响你的项目文件。s03 会加入权限控制
**准备**(首次运行):
@@ -145,63 +145,5 @@ python s01_agent_loop/code.py
s02 Tool Use → 给它 5 个真正的工具,会发生什么?模型会不会一次调用多个工具?几个工具同时跑会不会互相踩?
<details>
<summary>深入 CC 源码</summary>
> 以下内容基于 CC 源码 `src/query.ts`1729 行的核查。核心差异就两个CC 不看 `stop_reason` 字段而是检查内容里有没有 tool_use 块(因为流式响应中 stop_reason 不可靠CC 有更多的退出路径和恢复策略做生产级保护。
**教学版的 30 行 `while True` 就是 CC 1729 行的核心。** 下面每一项都是在这个核心上叠加的保护机制。
<details>
<summary>一、循环结构差异</summary>
教学版检查 `response.stop_reason`。CC 不把它作为循环继续的唯一依据——流式响应中 `stop_reason` 可能还没更新但内容里已经有 `tool_use` 块了。CC 用 `needsFollowUp` 标志:接收到流式消息时(`query.ts:830-834`),只要检测到 `tool_use` 块就设为 `true``QueryEngine.ts` 会从 `message_delta` 捕获真实 `stop_reason` 用于其他逻辑,但 query loop 本身靠 `needsFollowUp` 决定是否继续。
```typescript
// query.ts:554-558
// stop_reason === 'tool_use' is unreliable.
// Set during streaming whenever a tool_use block arrives.
let needsFollowUp = false
```
</details>
<details>
<summary>二、State 对象 10 字段(教学版只用 messages</summary>
| # | 字段 | 用途 | 对应章节 |
|---|------|------|---------|
| 1 | `messages` | 当前迭代的消息数组 | s01 |
| 2 | `toolUseContext` | 工具、信号、权限上下文 | s02 |
| 3 | `autoCompactTracking` | 压缩状态追踪 | s08 |
| 4 | `maxOutputTokensRecoveryCount` | token 恢复尝试次数(上限 3 | s11 |
| 5 | `hasAttemptedReactiveCompact` | 本轮是否已尝试响应式压缩 | s08 |
| 6 | `maxOutputTokensOverride` | 8K→64K 的升级覆盖 | s11 |
| 7 | `pendingToolUseSummary` | 后台 Haiku 生成的 tool use 摘要 | s08 |
| 8 | `stopHookActive` | 停止钩子是否产生阻塞错误 | s04 |
| 9 | `turnCount` | 轮次计数maxTurns 检查) | s01 |
| 10 | `transition` | 上一次继续原因 | s11 |
> 注:`taskBudgetRemaining``query.ts:291`)是 loop-local 局部变量,不在 State 上。源码注释明确写了 "Loop-local (not on State)"。
</details>
<details>
<summary>三、多条退出和继续路径</summary>
教学版只有 1 条退出路径(模型不调工具就结束)。生产版有多条退出和继续路径,覆盖 blocking limit、prompt too long、model error、abort、hook stop、max turns、token budget continuation、reactive compact retry 等场景。每种场景都有对应的恢复或退出策略。
</details>
<details>
<summary>四、流式工具执行和 QueryEngine</summary>
CC 的 `StreamingToolExecutor``query.ts:561`)让工具在模型还在生成时就开始并行执行(根据工具是否 concurrency-safe 决定并发或独占)。`QueryEngine.ts` 额外加了费用超限、结构化输出验证失败等保护。教学版不实现这些——目标是概念清晰,不是性能极致。
</details>
**一句话**1729 行的 query.ts 核心就是 30 行 `while True`。所有复杂字段和退出路径都是保护机制。先理解核心循环,后面的一切自然展开。
</details>
<!-- translation-sync: zh@v1, en@v0, ja@v0 -->

View File

@@ -19,8 +19,8 @@ The entire secret of an AI coding agent in one pattern:
(loop continues)
This is the core loop: feed tool results back to the model
until the model decides to stop. Production agents layer
policy, hooks, and lifecycle controls on top.
until the model decides to stop. Later chapters add policy,
hooks, and lifecycle controls around it.
Usage:
pip install anthropic python-dotenv