From 2b9fec513c2b328aab0f80441ed79477bc3f3e65 Mon Sep 17 00:00:00 2001 From: yagop Date: Wed, 17 Jun 2026 09:29:42 +0000 Subject: [PATCH 1/2] chapters: redraw the flowcharts with Unicode box-drawing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that the commit hook permits non-ASCII inside fenced blocks, redraw the four ASCII diagrams with box-drawing characters for a cleaner picture: - ch1: request/response boxes (┌─┐ │ └─┘) - char-swap, widths unchanged. - ch2: streaming event sequence - │/▼ connectors. - ch3: the read/build/call/emit loop - → arrows, │/▼ realigned under "call Claude". - ch5: the tool round-trip - redrawn as a vertical │/▼ flow (also fixes the orphaned two-line "->" version that was on main). All four render aligned; tsc and vitepress build pass. Co-Authored-By: Claude Opus 4.8 --- chapters/01-sdk-first-request.md | 24 ++++++++++++------------ chapters/02-streaming.md | 20 ++++++++++---------- chapters/03-repl-telegram.md | 9 ++++----- chapters/05-tools.md | 15 +++++++++++++-- 4 files changed, 39 insertions(+), 29 deletions(-) diff --git a/chapters/01-sdk-first-request.md b/chapters/01-sdk-first-request.md index a7b130b..508d800 100644 --- a/chapters/01-sdk-first-request.md +++ b/chapters/01-sdk-first-request.md @@ -6,18 +6,18 @@ Everything in this chapter is a single round trip: you send a JSON body, you get ```text your code - | - v - +-------------------------------------------------+ - | REQUEST POST /v1/messages | - | model, max_tokens, messages, system? | - +-------------------------------------------------+ - | - v - +-------------------------------------------------+ - | RESPONSE Message | - | content[], stop_reason, usage | - +-------------------------------------------------+ + │ + ▼ + ┌─────────────────────────────────────────────────┐ + │ REQUEST POST /v1/messages │ + │ model, max_tokens, messages, system? │ + └─────────────────────────────────────────────────┘ + │ + ▼ + ┌─────────────────────────────────────────────────┐ + │ RESPONSE Message │ + │ content[], stop_reason, usage │ + └─────────────────────────────────────────────────┘ ``` Prerequisites: Bun installed and your API credentials in a `.env` file at the project root (the next section explains which variables). No earlier chapters required. diff --git a/chapters/02-streaming.md b/chapters/02-streaming.md index fe62be4..428566f 100644 --- a/chapters/02-streaming.md +++ b/chapters/02-streaming.md @@ -28,20 +28,20 @@ The streaming and blocking paths converge on one shape: a fully typed `Anthropic ```text message_start usage.input_tokens - | - v + │ + ▼ content_block_start index, type (e.g. text) - | - v + │ + ▼ content_block_delta text_delta / input_json_delta (repeats) - | - v + │ + ▼ content_block_stop index - | - v + │ + ▼ message_delta stop_reason + usage.output_tokens - | - v + │ + ▼ message_stop ``` diff --git a/chapters/03-repl-telegram.md b/chapters/03-repl-telegram.md index 415ce64..24ddcc5 100644 --- a/chapters/03-repl-telegram.md +++ b/chapters/03-repl-telegram.md @@ -3,11 +3,10 @@ 💬 So far each script asked Claude one fixed question and exited. Now you'll hand the keyboard to a real person. A coding agent is, at heart, a loop: read input, build messages, call Claude, emit output, repeat. The Claude call stays the same; only the I/O around it changes - so in this chapter you wrap that one call in two different frontends, a terminal REPL and a Telegram bot. ```text - read input -> build messages -> call Claude -> emit output -> repeat - | - v - stop_reason 'end_turn' - ends the turn + read input → build messages → call Claude → emit output → repeat + │ + ▼ + stop_reason 'end_turn' ends the turn ``` You already have `new Anthropic()`, the env vars, and the content-array narrowing from Chapter 1, plus `stream()`, `.on('text')`, and `finalMessage()` from Chapter 2. Here you only add the input/output plumbing. The one new env var is `TELEGRAM_BOT_TOKEN`, which lives in `.env` next to your Anthropic credentials - Bun auto-loads it, and as always the key comes from the environment; never hardcode it. diff --git a/chapters/05-tools.md b/chapters/05-tools.md index 2b3f9dc..b09fe73 100644 --- a/chapters/05-tools.md +++ b/chapters/05-tools.md @@ -27,8 +27,19 @@ Notice that you find the call by narrowing `response.content` to the block whose Catching the call is half the round-trip; now you close it. The flow is a fixed five-step dance, and it is worth holding the whole shape in your head before you read the code: ```text -create(tools) -> stop_reason 'tool_use' -> run the tool locally - -> create again with a tool_result -> final text answer + create() with tools + │ + ▼ + stop_reason: 'tool_use' + │ + ▼ + run the tool locally + │ + ▼ + create() with the tool_result + │ + ▼ + final text answer ``` When `stop_reason === 'tool_use'`, you append the assistant's content **verbatim** as an assistant turn, run the tool yourself, then send a new `user` turn whose `content` is a `tool_result` block - an `Anthropic.ToolResultBlockParam` that echoes the `tool_use_id` exactly. That echo is the rule that binds request to answer: every `tool_use` block in a turn needs a matching `tool_result`, or the next `create` call rejects the array. From 576c9e00ea764b5382d9d17cf9184d71c8d0cd1a Mon Sep 17 00:00:00 2001 From: yagop Date: Wed, 17 Jun 2026 09:37:17 +0000 Subject: [PATCH 2/2] ch5: center the tool round-trip diagram MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The vertical │/▼ flow was left-aligned at each node's first character, so the arrows did not sit under the nodes. Center the nodes around a common column and put the connectors on that center line. Co-Authored-By: Claude Opus 4.8 --- chapters/05-tools.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/chapters/05-tools.md b/chapters/05-tools.md index b09fe73..5229125 100644 --- a/chapters/05-tools.md +++ b/chapters/05-tools.md @@ -27,19 +27,19 @@ Notice that you find the call by narrowing `response.content` to the block whose Catching the call is half the round-trip; now you close it. The flow is a fixed five-step dance, and it is worth holding the whole shape in your head before you read the code: ```text - create() with tools - │ - ▼ - stop_reason: 'tool_use' - │ - ▼ - run the tool locally - │ - ▼ + create() with tools + │ + ▼ + stop_reason: 'tool_use' + │ + ▼ + run the tool locally + │ + ▼ create() with the tool_result - │ - ▼ - final text answer + │ + ▼ + final text answer ``` When `stop_reason === 'tool_use'`, you append the assistant's content **verbatim** as an assistant turn, run the tool yourself, then send a new `user` turn whose `content` is a `tool_result` block - an `Anthropic.ToolResultBlockParam` that echoes the `tool_use_id` exactly. That echo is the rule that binds request to answer: every `tool_use` block in a turn needs a matching `tool_result`, or the next `create` call rejects the array.