Skip to content

feat(create-agent-app): --chat variant — the one-day multimodal chat app, CI-enforced (#188 wave 3)#199

Merged
drewstone merged 1 commit into
mainfrom
feat/scaffold-chat-variant
Jul 15, 2026
Merged

feat(create-agent-app): --chat variant — the one-day multimodal chat app, CI-enforced (#188 wave 3)#199
drewstone merged 1 commit into
mainfrom
feat/scaffold-chat-variant

Conversation

@drewstone

Copy link
Copy Markdown
Contributor

What

create-agent-app --chat scaffolds the examples/chat-app.md assembly as a runnable Cloudflare Workers product — the finish line of #188: scaffold → deployed multimodal chat app in one day, and CI proves the claim stays true.

The generated app (create-agent-app/template-chat/)

Piece File What it composes
DATA surface agent.config.ts + prompts/system.md (Text module) name, system prompt, model default + effort, harness, renderable ask kinds
Composer src/chat.ts createAppAuth (drizzle/D1, memoryAdapter comment) + createChatStore + createChatTurnRoutes (turn/replay/interactions) + createUploadRoute + thread CRUD handlers
Sandbox lane src/sandbox.ts config-driven SandboxRuntimeConfigensureWorkspaceSandbox + streamSandboxPrompt + createSandboxChatProducer; upload sink (box.fs); sidecar connection for asks. No mock fallback — missing creds fail loud
Schema src/db/schema.ts + migrations/0001_init.sql better-auth tables + createChatTables() + the /stream turn-buffer DDL; wrangler.toml carries the D1 binding + migrations_dir (R2 commented off)
HTTP src/worker.ts + public/index.html routing only + an honest dependency-free dev chat page (auth, threads, attach → parts, NDJSON streaming); CUSTOMIZE ⑤ points the real UI at /web-react
Breadcrumbs AGENTS.md / CLAUDE.md / CUSTOMIZE.md / README.md the base template's checklist voice, chat-variant contract

The CI enforcement (two layers)

  1. The generated app ships its own e2e test (template-chat/tests/chat-turn.e2e.test.ts): executes the REAL migrations/0001_init.sql into better-sqlite3, signs up through the real better-auth drizzle adapter, uploads a file (inline data: part), POSTs a turn whose only fake is the sandbox event feed (canonical sidecar events through the real createSandboxChatProducer bridge), consumes the NDJSON stream (text deltas, reasoning, tool_call/tool_result, usage), asserts user+assistant rows persisted with typed parts + the usage receipt, then replays the buffered turn. Plus: fail-closed 401 before any row, and a turn-buffer-DDL-matches-TURN_EVENTS_MIGRATION_SQL drift gate.
  2. The repo gate (tests/create-agent-app-chat.test.ts) scaffolds --chat into tmp, installs agent-app as a copy of the published payload (the fix(create-agent-app): repair template deps/types, harden scaffold CI, scope npm name (#188) #195 hardening — undeclared deps cannot leak through the repo's node_modules), links only what the generated package.json declares, typechecks the generated app, checks engine pins against agent-app's peer floors, and runs the generated app's own vitest suite. If any shell factory drifts, CI reds here first.

Repo-side changes

  • create-agent-app/index.mjs: --chat flag + help text (default template unchanged; base suite still green).
  • create-agent-app/package.json: template-chat added to files, description covers both variants.
  • @cloudflare/workers-types devDep (offline typecheck of the generated worker), knip/vitest excludes for the new template tree.

Verification

  • pnpm typecheck clean, pnpm test 2484/2484 green (includes both scaffold gates), heap-bumped pnpm build green.
  • Generated app on a clean scaffold: tsc --noEmit clean, own suite 4/4 green in ~1s.

🤖 Generated with Claude Code

…modal chat app

Scaffolds the examples/chat-app.md assembly as a runnable Cloudflare
Workers product: createAppAuth over drizzle/D1, createChatTables +
createChatStore, createChatTurnRoutes with the config-driven sandbox
producer lane, createUploadRoute (inline vs sandbox path split), the
/interactions answer endpoints, a D1 migration the generated app's own
e2e test executes for real, and a dependency-free dev chat page.

The generated app ships tests/chat-turn.e2e.test.ts: fake sandbox
producer -> POST turn -> NDJSON stream consumed -> user+assistant rows
persisted with typed parts + usage receipt -> buffered replay. The
repo-side gate (tests/create-agent-app-chat.test.ts) scaffolds into tmp,
links the real dist offline, typechecks the generated app, and runs its
suite — CI reds if the template ever drifts from the framework (#188
wave 3).

@tangletools tangletools left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Auto-approved drewstone PR — 80c3cb1f

This PR was opened by the trusted drewstone account.
The full PR reviewer audit still runs separately and will publish findings if it detects issues.

tangletools · auto-approval · reason: drewstone_author · 2026-07-15T20:02:55Z

@drewstone
drewstone merged commit fac17e9 into main Jul 15, 2026
1 check passed
drewstone added a commit that referenced this pull request Jul 17, 2026
…cument upload's sole consumer (#202)

Audit simplification pass. No behavior change, no export added or removed —
honest labeling of the single-consumer surface the over-engineering audit flagged.

- turnLock/contextGate/beforeTurn/onRawEvent: @experimental + single-consumer
  (gtm, #200) JSDoc. They stay FLAT top-level options (not grouped under a
  `hooks` object): that regroup would break gtm's shipped createChatTurnRoutes
  call for no mechanism gain, and this package's exports are additive-only.
  lifecycle/heartbeat stay stable (generically useful).
- createUploadRoute: kept, NOT deleted. Its sole consumer is the `--chat`
  scaffold (the shipped reference multimodal path, PR #199). Documented that the
  four fleet apps (gtm/tax/legal/insurance) keep their own durable-vault upload
  routes (KV / encrypted R2) — a different persistence model — and shouldn't
  route through it.
- Docs (AGENTS.md/CLAUDE.md module map, ARCHITECTURE.md) reflect both.
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.

2 participants