Skip to content

Implement #4: Context and Conversation Management#35

Merged
yagop merged 8 commits into
mainfrom
issue-4-04-context
Jun 14, 2026
Merged

Implement #4: Context and Conversation Management#35
yagop merged 8 commits into
mainfrom
issue-4-04-context

Conversation

@yagop

@yagop yagop commented Jun 14, 2026

Copy link
Copy Markdown
Owner

Closes #4

Chapter 4 teaches the stateful layer over the stateless Messages API: conversation history, the system prompt, token counting + rolling-window trimming, history summarization, prompt caching, and persisted per-user Telegram sessions. Authored by the write-chapter ultracode Workflow (1 doc agent + 6 implement/review pipeline pairs), then verified end-to-end.

Definition of done

  • Chapter at chapters/04-context.md, <=120 lines, <=4 main-line H2s plus an optional closer
  • Every sample runnable with bun run, imported via <<< @/examples/04-context/file.ts, <=35 lines, comment:code <=0.30
  • One-home rule held: no prose sentence restates an inline code comment
  • Friendliness floor held: reader addressed as "you"; intro + the History/Per-user sections open warm
  • Samples use only real @anthropic-ai/sdk surface; ASCII punctuation only
  • Optional material lives in asides (a :::warning, a :::tip, and one comparison table); the main line reads complete without them
  • Linked from README.md and the .vitepress/config.ts sidebar; bun x vitepress build passes
  • Caching sample actually shows a non-zero cache_read_input_tokens

Verification (run live against an Anthropic-compatible gateway)

Chapter budget:

wc -l chapters/04-context.md   -> 68   (<=120)
grep -c '^## '                 -> 4    (<=4 main-line H2s)

Sample budgets (all <=35 lines, comment:code <=0.30):

multi-turn.ts         30 lines  ratio 0.158
system-prompt.ts      28 lines  ratio 0.158
token-counter.ts      31 lines  ratio 0.200
summarize-history.ts  35 lines  ratio 0.100
prompt-cache.ts       21 lines  ratio 0.231
telegram-sessions.ts  35 lines  ratio 0.032

bunx tsc --noEmit clean; bun x vitepress@2.0.0-alpha.17 build passes (chapter 4 renders, all six snippet imports resolve). Each sample was run, not just typechecked:

  • multi-turn.ts - history survives across 3 turns; turn 3 recalls "teal" from turn 1; ends history holds 6 messages across 3 turns.
  • system-prompt.ts - the pirate persona ("...Arr!") holds across both turns, string system then block-array system.
  • token-counter.ts - counting against GLM-4.6; with a small demo threshold the rolling window trims in pairs and holds at window=3 msgs instead of growing.
  • summarize-history.ts - history is 78 tokens; threshold 30 -> compacted 4 turns into 2, replaced by one injected user/assistant summary pair.
  • prompt-cache.ts - two identical requests: request 1 created=0 read=0, request 2 created=0 read=6272. The non-zero cache_read_input_tokens=6272 on the second request is the cache hit. (Note: the gateway used for this run does not surface cache_creation_input_tokens, so it reads as 0 here via a ?? 0 guard; on Anthropic direct, request 1 reports the creation count. The DoD field, cache_read_input_tokens, is non-zero as required.)
  • telegram-sessions.ts - long-running poller (cannot run to completion). Boot-smoked: deserializes a seeded sessions.json into its per-chat.id Map at startup and long-polls getUpdates cleanly; type-checked and snippet resolves in the build. The transient sessions.json artifact was removed so examples/04-context/ ships exactly the six .ts files.

Review flags

None - the Workflow returned all six samples as fully compliant (no flagged files).

Chapter 4 plus its examples/04-context/ samples: multi-turn history,
system prompts, token counting + rolling-window trim, history
summarization, prompt caching, and persisted per-user Telegram sessions.
Wires the chapter into the VitePress sidebar and README.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
yagop and others added 7 commits June 14, 2026 21:57
The 35-line sample cap, with no readability counter-rule and no
formatter, pushed the implement/review agents to golf samples that did
not fit - collapsing fetch helpers into one chained expression, using
the comma operator to sequence side effects - purely to hit the count.

- Appendix B: readability outranks line count (one statement per line,
  no comma operators, no statement stacking); soft target 35, hard cap 45
  to leave room for the standalone-file boilerplate readable code needs.
- Appendix A review agent: a correct-but-dense one-liner is now a defect
  to re-expand, not a pass.
- Step 7 verify: spot-check readability, aim <=35 / hard cap 45.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Expand the one-line arrow (chained `(await fetch(...)).json()`) into a
normal multi-line async function: one statement per line, 41 lines.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Apply the no-golf convention to the two remaining compressed samples,
harmonizing both on the telegram-bot.ts helper style (a multi-line,
de-chained `async function`):

- telegram-stream.ts: expand the `stream.on('text')` body (drop the
  `;`-stacked statements and the `(last = now), edit(...)` comma operator
  into one statement per line), split `let text='', last=0`, de-chain the
  one-line `tg` arrow, hoist `const model`. 44 lines.
- telegram-sessions.ts: collapse the over-expanded fetch options back to
  the shared inline helper shape and hoist `const model`. 40 lines.

Both still run (boot-smoked), tsc is clean, and the docs build renders
the de-golfed snippets.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Increase the example code budget in the write-chapter skill (aim <=70,
hard cap 100 lines, comment:code <=0.40) and note that verbose, explicit
code is welcome. Regenerate examples/03-repl-telegram/telegram-stream.ts
from scratch in that style: expanded fetch/stream option objects,
multi-line type definitions, named intermediates, braced guards, and
section blank lines. 89 lines, behavior unchanged.

Runs (boot-smoked), tsc clean, docs build renders the verbose snippet.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Rewrite from scratch in the verbose style now allowed by the raised code
budget: expanded fetch/create option objects, multi-line Update type, a
named persist() function, an explicit load-from-disk loop, and braced
guards. 76 lines, behavior unchanged. Comments kept minimal (one helper
note) so the chapter-4 prose stays the single home for the session
concept (one-home rule).

Boot-smoked (loads a seeded sessions.json into the Map and polls), tsc
clean, docs build renders the verbose snippet.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… for(;;)

Add a loop-idiom convention to the write-chapter skill: for unbounded
produce-then-consume loops prefer an async generator (async function* +
for await...of), else while (true), never for (;;).

Refactor all three Telegram samples to a shared pollUpdates() generator
that long-polls getUpdates and yields one update at a time, consumed with
a top-level for await loop. This separates transport (poll + offset) from
handling and matches the for await...of style the REPLs already use.
Rename the per-file helper to tg() across all three for consistency.

All three boot-smoked, tsc clean, docs build renders the generator.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@yagop yagop merged commit 8a9d9b5 into main Jun 14, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Chapter 4: Context and Conversation Management

1 participant