From 3e9a991c4779639dc3b1db30b6501ac87f18e344 Mon Sep 17 00:00:00 2001 From: Brian Love Date: Mon, 6 Jul 2026 17:24:17 -0700 Subject: [PATCH 01/23] =?UTF-8?q?docs(spec):=20App=20mode=20on=20the=20lan?= =?UTF-8?q?gchain=20canonical=20demo=20=E2=80=94=20itinerary=20cockpit?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Design for porting the ag-ui App-mode map/itinerary cockpit to examples/chat (langgraph), single shared agent. Key divergence: itinerary lives in graph state (per-thread checkpoint) alongside messages, synced client-authoritatively via input.state + updateState; no localStorage. Local-first; deploy deferred. --- ...aph-canonical-app-mode-itinerary-design.md | 145 ++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 docs/superpowers/specs/2026-07-06-langgraph-canonical-app-mode-itinerary-design.md diff --git a/docs/superpowers/specs/2026-07-06-langgraph-canonical-app-mode-itinerary-design.md b/docs/superpowers/specs/2026-07-06-langgraph-canonical-app-mode-itinerary-design.md new file mode 100644 index 000000000..5b43f10df --- /dev/null +++ b/docs/superpowers/specs/2026-07-06-langgraph-canonical-app-mode-itinerary-design.md @@ -0,0 +1,145 @@ +# App Mode on the LangChain Canonical Demo — Itinerary Cockpit (Design) + +**Date:** 2026-07-06 +**Status:** Approved design, pending spec review → implementation plan +**Owner:** Brian Love +**Branch:** `feat/langgraph-app-mode-itinerary` + +## Goal + +Bring the App-mode map cockpit — the travel-itinerary trip planner currently exclusive to `examples/ag-ui` — to the **langchain canonical demo** (`examples/chat`, backed by `@threadplane/langgraph`). This proves the langgraph adapter reaches App-mode feature parity with ag-ui, using a single shared agent. + +The one deliberate architectural divergence from ag-ui: **the itinerary lives in the langgraph graph state (checkpointed per thread) alongside `messages`**, rather than in a frontend-only store. This showcases langgraph's durable per-thread state. + +## Scope + +**In scope (this effort — local parity):** +- Full App-mode cockpit in `examples/chat`: map background, floating itinerary overlay, `appMode` toggle, map-compatible routing (sidebar/popup), welcome suggestions, app-mode promo. +- Itinerary as first-class langgraph graph state, synced client-authoritatively (see State Design). +- Backend: extend the existing `chat` graph (bind client tools + inject itinerary context) — **no second agent/graph**. +- Google Maps key wired into `examples/chat` locally via the `inject-env` `GENERATED_KEYS` mechanism. +- Verification: unit tests at each seam + `examples/chat` e2e for the App-mode cockpit + a live Chrome-MCP smoke against the running langgraph stack (real LLM). + +**Explicit non-goals (deferred / rejected):** +- **Deployment** — no Vercel Maps key, no update to the deployed langgraph graph, no prod smoke. Local-first; deploy is a follow-up. +- **Shared library extraction** — the itinerary/map surface is **duplicated** into `examples/chat`, not promoted to a lib. This follows the standalone-examples convention (examples own their code; never share across examples). +- **Server-side geocoding** — geocoding stays in the browser (Maps JS geocoder). No server Google Geocoding key. +- **Second agent / dedicated itinerary graph** — rejected; App mode is a pure layout over the single shared `chat` agent. + +## Architecture Overview + +App mode is a **presentational layer** over the same agent that powers plain chat. The single `chat` graph gains: +1. an `itinerary` key in its `State` (checkpointed per thread), and +2. the ability to bind frontend-declared client tools (`threadplane-middleware`'s `bind_client_tools`) and to see the current itinerary in the `generate` node's context. + +The frontend keeps a live `ItineraryStore` (Angular signals) as the **working copy** driving the map/panel; the graph checkpoint is the **durable record**, synced from the client. + +``` +User / Agent edits ──▶ ItineraryStore (signals, live) + │ map + panel render from this instantly + ▼ + submit(): input.state.itinerary = store.stops() ─┐ (turn start: model sees the trip) + updateState({ itinerary }) after run / on edit ─┴─▶ langgraph checkpoint (durable, per thread) + ▲ + thread switch ────┘ hydrate store from agent.values().itinerary + new thread ───────── initialValues seed (Paris) +``` + +## State Design (the core decision) + +### Graph state shape (`examples/chat/python/src/graph.py`) + +The current `State` is extended with a flat itinerary list that mirrors the frontend `ItineraryStop` shape exactly (so the panel/map render logic ports 1:1): + +```python +from typing_extensions import TypedDict, NotRequired +from typing import Annotated, Optional + +class Stop(TypedDict): + id: str + day: int + place: str + note: NotRequired[str] + lat: NotRequired[float] + lng: NotRequired[float] + +class State(TypedDict): + messages: Annotated[list, add_messages] + model: Optional[str] + reasoning_effort: Optional[str] + gen_ui_mode: Optional[str] + itinerary: list[Stop] # NEW — plain key = last-write-wins overwrite +``` + +- **Flat list, day-as-field.** Grouping-by-day stays a pure frontend view (`days()` computed). Matches the store's canonical shape. +- **Plain (non-`Annotated`) key → last-write-wins.** The client always sends the full list (via `input.state` and `updateState`), so an append-style reducer would only duplicate entries. Overwrite is correct for a single agent. +- **Seed** (3 Paris stops) moves server-side conceptually but is delivered through the frontend `initialValues` for a new thread; the graph tolerates an absent/empty `itinerary`. + +### Ownership & mutation model: client tools + state sync + +Mutations run in the **browser** (reusing the ag-ui client tools almost verbatim — browser geocoding, compute-next-stops), and the result is synced into the durable checkpoint: + +1. **Turn start** — the shell's `submit` wrapper injects `state.itinerary = store.stops()` (the identical mechanism already used for `model`/`reasoning_effort`/`gen_ui_mode`). The `generate` node folds a compact summary into context, so the model always sees the current trip. **`get_itinerary` is removed** (no read round-trip). +2. **During a turn** — the model calls `add_stop` / `move_stop` / `clear_day` (client tools). The browser executes them: geocodes, updates the `ItineraryStore` (live map/panel), returns the result as the tool message. +3. **Sync to checkpoint** — after a run settles, the shell calls `agent.updateState({ itinerary: store.stops() })` to capture the agent's edits. Direct user panel edits (drag-reorder, add, clear) between runs call the same `updateState` immediately (no active run to conflict with). +4. **Hydration** — switching threads seeds the store from `agent.values().itinerary` (server truth). A brand-new thread uses `provideAgent`'s `initialValues` (the Paris seed). + +**localStorage is dropped** — the checkpoint is now the durable store; `initialValues` covers first paint. Consequence: a brand-new thread always opens on the Paris seed (predictable for a demo), and the itinerary is **per thread** — switching threads swaps the map. + +### Ephemeral UI state stays frontend + +`recentlyChangedId` (agent-edit pulse) and `focusedStopId` (map focus) are transient view concerns — they remain frontend signals and are **not** persisted to graph state. + +### Verified enabling APIs (`@threadplane/langgraph`) + +- `agent.values(): Signal` — current graph state values (the `values` stream mode is already enabled). Frontend renders the itinerary from `values().itinerary`. +- `agent.updateState(values, signal, { asNode })` — writes a checkpoint as if a node produced the values. Used for the client → checkpoint sync. +- `provideAgent(..., { initialValues })` — first-paint seed before `values` streams. +- `mergeClientTools` / `createClientToolsCapability` (TS) + `threadplane.middleware.langgraph.bind_client_tools` (Python) — the frontend-client-tool binding path, already used by ag-ui. + +## Backend Changes (`examples/chat/python`) + +Additive to the existing `chat` graph — plain chat is unaffected when no client-tool catalog is sent. + +- Add `threadplane-middleware>=0.0.1` to `pyproject.toml`. +- `State` gains the `itinerary: list[Stop]` key (above). +- `generate` node: when `state["itinerary"]` is non-empty, inject a compact JSON summary into the system context so the model reasons over the current trip. +- `generate` node: bind the frontend client-tool catalog via `bind_client_tools` (only affects runs where the App-mode frontend sends the catalog), composing with the existing server tools (`search_documents`, `request_approval`, `research`, `gen_ui_tool`). +- No new graph, no new `graph_id` in `langgraph.json`. + +## Frontend Changes (`examples/chat/angular`) + +### Duplicated surface (ported from `examples/ag-ui`, `@threadplane/ag-ui` → `@threadplane/langgraph`) + +~1,300 LOC copied and re-wired (agent import, `submit` state field, `values`/`updateState` sync): +`map-canvas.component`, `itinerary-panel.component` (+spec), `itinerary-store` (localStorage removed; hydrate-from-values added), `map-bounds` (+spec), `geocoding.service` (+spec), `google-maps-loader`, `client-tools` (get_itinerary dropped; results sync to checkpoint), `day-card.component`, `clear-day-confirm.component`, plus `modes/app-mode-promo.component` and `modes/welcome-suggestions` App-mode variants. + +### Shell reconciliation (`shell/demo-shell.component`) — layout ① + +- Add an `appMode` toggle to the toolbar + `hasMapsKey` gate (from `environment.googleMapsApiKey`). +- **In App mode:** the thread sidenav auto-collapses to the hamburger drawer (demo-shell already has drawer mode + hamburger). The map renders full-bleed background, the itinerary floats as a left overlay, chat is the right rail (sidebar) / bubble (popup). Faithful to ag-ui's cockpit; reuses demo-shell's existing drawer machinery. +- Port ag-ui-shell's `appMode` param-sync effect (persist to URL; App mode valid in sidebar/popup; coerce `embed → sidebar` when App mode is on), coexisting with demo-shell's `/:threadId` route matcher. +- `submit` wrapper extended to inject `state.itinerary`; post-run hook calls `updateState`. + +### Config + +- `environment.ts` / `environment.development.ts`: add `googleMapsApiKey` + `googleMapsMapId` from `GENERATED_KEYS` (port the `inject-env` wiring from ag-ui). Local `.env` only. +- `app.config.ts`: `provideAgent(...)` gains `initialValues: { itinerary: SEED }`; wire the itinerary client-tools registry. + +## Testing Strategy + +- **Unit (vitest):** `itinerary-store` hydrate-from-values + no-localStorage; `map-bounds`; `geocoding.service`; the `submit`-wrapper injects `state.itinerary`; `updateState` called on run-settle and on user edit; App-mode routing coercion (`embed → sidebar`). +- **Backend (pytest):** `generate` binds client tools when catalog present and not otherwise; itinerary context injected when `state["itinerary"]` non-empty; plain-chat path unchanged. +- **e2e (`examples/chat` Playwright):** App-mode cockpit renders (map + overlay + right-rail chat); sidenav collapses to drawer in App mode; per-thread itinerary swaps on thread switch. (Map tiles gated on a local Maps key — assert DOM/layout, not tile pixels, per the Maps-canvas harness lesson.) +- **Live gate (Chrome MCP):** against the running `:4200` + `:2024` stack with a real LLM — drive "add the Eiffel Tower to day 2", confirm the pin + panel update live, reload mid-thread and confirm the trip restores from the checkpoint. + +## Risks & Mitigations + +- **Client-tool payload key alignment** (TS `client_tools` vs Python `bind_client_tools` reading `state["tools"]`): de-risk with a tiny spike early — send the itinerary catalog from `examples/chat` and confirm the model can call `add_stop`. The mechanism is proven in ag-ui; only the langgraph-adapter payload shape needs confirming. +- **`updateState` vs active run**: only call post-run (run settled) for agent edits; user edits occur between runs. Never call during an active run. +- **Shell coexistence**: the appMode param-sync effect and the `/:threadId` matcher both navigate — port ag-ui's `untracked(mode)` + absolute-`/sidebar` discipline to avoid the bootstrap `→ /embed` bounce. +- **Maps key footgun** (worktree has no local `.env`): symlink the main-checkout `.env` into the worktree root before serving (per the established runbook). + +## Open Questions + +None blocking. Deploy wiring, lib extraction, and server geocoding are explicit non-goals for this effort. From dcacffbfca43dff6cd0f0a47aff6936301580b57 Mon Sep 17 00:00:00 2001 From: Brian Love Date: Mon, 6 Jul 2026 21:49:02 -0700 Subject: [PATCH 02/23] =?UTF-8?q?docs(spec):=20drop=20seed=20data=20?= =?UTF-8?q?=E2=80=94=20empty=20start,=20agent=20builds=20the=20plan?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No seed/seeding: a fresh thread starts empty; users prompt the agent (via welcome suggestions) to generate a trip plan. Adds a first-class Planner behavior & prompt-tuning section (recommend + populate app state via client tools), empty-state CTA, and empty-thread live gate. --- ...aph-canonical-app-mode-itinerary-design.md | 33 ++++++++++++------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/docs/superpowers/specs/2026-07-06-langgraph-canonical-app-mode-itinerary-design.md b/docs/superpowers/specs/2026-07-06-langgraph-canonical-app-mode-itinerary-design.md index 5b43f10df..a82260531 100644 --- a/docs/superpowers/specs/2026-07-06-langgraph-canonical-app-mode-itinerary-design.md +++ b/docs/superpowers/specs/2026-07-06-langgraph-canonical-app-mode-itinerary-design.md @@ -11,6 +11,8 @@ Bring the App-mode map cockpit — the travel-itinerary trip planner currently e The one deliberate architectural divergence from ag-ui: **the itinerary lives in the langgraph graph state (checkpointed per thread) alongside `messages`**, rather than in a frontend-only store. This showcases langgraph's durable per-thread state. +The demo starts **empty** — there is no seed data. Users explore and prompt the agent (typically via a welcome suggestion) to generate a trip plan; the agent both **recommends** places and **populates the app state** as it goes, building the itinerary/map live. + ## Scope **In scope (this effort — local parity):** @@ -42,7 +44,7 @@ User / Agent edits ──▶ ItineraryStore (signals, live) updateState({ itinerary }) after run / on edit ─┴─▶ langgraph checkpoint (durable, per thread) ▲ thread switch ────┘ hydrate store from agent.values().itinerary - new thread ───────── initialValues seed (Paris) + new thread ───────── empty itinerary → prompt-to-plan (agent populates live) ``` ## State Design (the core decision) @@ -73,7 +75,7 @@ class State(TypedDict): - **Flat list, day-as-field.** Grouping-by-day stays a pure frontend view (`days()` computed). Matches the store's canonical shape. - **Plain (non-`Annotated`) key → last-write-wins.** The client always sends the full list (via `input.state` and `updateState`), so an append-style reducer would only duplicate entries. Overwrite is correct for a single agent. -- **Seed** (3 Paris stops) moves server-side conceptually but is delivered through the frontend `initialValues` for a new thread; the graph tolerates an absent/empty `itinerary`. +- **No seed data, no seeding concept.** A fresh thread starts with an empty `itinerary` (`[]`). The user drives plan creation by prompting the agent; the agent populates the itinerary via the client tools. The graph tolerates an absent/empty `itinerary` everywhere. ### Ownership & mutation model: client tools + state sync @@ -82,9 +84,9 @@ Mutations run in the **browser** (reusing the ag-ui client tools almost verbatim 1. **Turn start** — the shell's `submit` wrapper injects `state.itinerary = store.stops()` (the identical mechanism already used for `model`/`reasoning_effort`/`gen_ui_mode`). The `generate` node folds a compact summary into context, so the model always sees the current trip. **`get_itinerary` is removed** (no read round-trip). 2. **During a turn** — the model calls `add_stop` / `move_stop` / `clear_day` (client tools). The browser executes them: geocodes, updates the `ItineraryStore` (live map/panel), returns the result as the tool message. 3. **Sync to checkpoint** — after a run settles, the shell calls `agent.updateState({ itinerary: store.stops() })` to capture the agent's edits. Direct user panel edits (drag-reorder, add, clear) between runs call the same `updateState` immediately (no active run to conflict with). -4. **Hydration** — switching threads seeds the store from `agent.values().itinerary` (server truth). A brand-new thread uses `provideAgent`'s `initialValues` (the Paris seed). +4. **Hydration** — switching threads loads the store from `agent.values().itinerary` (server truth). A brand-new thread starts **empty** (no seed) and shows the prompt-to-plan empty state until the user asks the agent to build a plan. -**localStorage is dropped** — the checkpoint is now the durable store; `initialValues` covers first paint. Consequence: a brand-new thread always opens on the Paris seed (predictable for a demo), and the itinerary is **per thread** — switching threads swaps the map. +**localStorage is dropped** — the checkpoint is now the durable store. Consequence: a brand-new thread opens on an **empty** map + itinerary with a prompt-to-plan empty state, and the itinerary is **per thread** — switching threads swaps the map to that thread's plan. ### Ephemeral UI state stays frontend @@ -94,7 +96,7 @@ Mutations run in the **browser** (reusing the ag-ui client tools almost verbatim - `agent.values(): Signal` — current graph state values (the `values` stream mode is already enabled). Frontend renders the itinerary from `values().itinerary`. - `agent.updateState(values, signal, { asNode })` — writes a checkpoint as if a node produced the values. Used for the client → checkpoint sync. -- `provideAgent(..., { initialValues })` — first-paint seed before `values` streams. +- `provideAgent(..., { initialValues })` — available for first-paint defaults; here it is omitted or `{ itinerary: [] }` (no seed data). - `mergeClientTools` / `createClientToolsCapability` (TS) + `threadplane.middleware.langgraph.bind_client_tools` (Python) — the frontend-client-tool binding path, already used by ag-ui. ## Backend Changes (`examples/chat/python`) @@ -107,12 +109,21 @@ Additive to the existing `chat` graph — plain chat is unaffected when no clien - `generate` node: bind the frontend client-tool catalog via `bind_client_tools` (only affects runs where the App-mode frontend sends the catalog), composing with the existing server tools (`search_documents`, `request_approval`, `research`, `gen_ui_tool`). - No new graph, no new `graph_id` in `langgraph.json`. +### Planner behavior & prompt tuning + +With no seed data, the whole experience depends on the agent turning a request into a populated plan. The prompt/tool tuning is a first-class deliverable, not an afterthought: + +- **System prompt (App-mode / planner framing):** when the itinerary client tools are bound, the `generate` node's system context casts the agent as a trip-planning assistant that, given a request, (1) **recommends** concrete places (with a one-line note each) grouped into days, and (2) **populates the app state** by calling `add_stop` for each recommendation and `day_card` to surface a day — rather than only describing the plan in prose. It revises via `move_stop` / `clear_day` when the user asks. The current `state["itinerary"]` (possibly empty) is injected so the agent knows what already exists and only adds what's missing. +- **Tool descriptions:** tuned so the model reliably *acts* (calls `add_stop` as it recommends) instead of narrating. Descriptions are the primary steering; the system framing above is light supplemental coaching, warranted here because there is no seed to imply the pattern. +- **Welcome suggestions** are concrete trip-planning starters that both invite exploration and trigger plan generation — e.g. "Plan a long weekend in Paris", "3 days in Tokyo with great food", "A week on the California coast". Selecting one sends the prompt and the agent builds the plan live. +- **Definition of done for the prompt:** a cold thread + one welcome suggestion yields multiple `add_stop` calls that populate the map + panel with recommended, geocoded stops across days — verified in the live Chrome-MCP gate. + ## Frontend Changes (`examples/chat/angular`) ### Duplicated surface (ported from `examples/ag-ui`, `@threadplane/ag-ui` → `@threadplane/langgraph`) ~1,300 LOC copied and re-wired (agent import, `submit` state field, `values`/`updateState` sync): -`map-canvas.component`, `itinerary-panel.component` (+spec), `itinerary-store` (localStorage removed; hydrate-from-values added), `map-bounds` (+spec), `geocoding.service` (+spec), `google-maps-loader`, `client-tools` (get_itinerary dropped; results sync to checkpoint), `day-card.component`, `clear-day-confirm.component`, plus `modes/app-mode-promo.component` and `modes/welcome-suggestions` App-mode variants. +`map-canvas.component` (neutral default view when empty; fit-to-bounds once stops exist), `itinerary-panel.component` (+spec; **empty-state CTA** — "Ask the assistant to plan a trip" — shown when there are no stops), `itinerary-store` (localStorage **and** the `SEED` constant removed; empty initial state; hydrate-from-`values` added), `map-bounds` (+spec), `geocoding.service` (+spec), `google-maps-loader`, `client-tools` (get_itinerary dropped; results sync to checkpoint), `day-card.component`, `clear-day-confirm.component`, plus `modes/app-mode-promo.component` and `modes/welcome-suggestions` retuned to trip-planning starters. ### Shell reconciliation (`shell/demo-shell.component`) — layout ① @@ -124,14 +135,14 @@ Additive to the existing `chat` graph — plain chat is unaffected when no clien ### Config - `environment.ts` / `environment.development.ts`: add `googleMapsApiKey` + `googleMapsMapId` from `GENERATED_KEYS` (port the `inject-env` wiring from ag-ui). Local `.env` only. -- `app.config.ts`: `provideAgent(...)` gains `initialValues: { itinerary: SEED }`; wire the itinerary client-tools registry. +- `app.config.ts`: `provideAgent(...)` wires the itinerary client-tools registry; **no seed** (omit `initialValues`, or pass `{ itinerary: [] }`). ## Testing Strategy -- **Unit (vitest):** `itinerary-store` hydrate-from-values + no-localStorage; `map-bounds`; `geocoding.service`; the `submit`-wrapper injects `state.itinerary`; `updateState` called on run-settle and on user edit; App-mode routing coercion (`embed → sidebar`). -- **Backend (pytest):** `generate` binds client tools when catalog present and not otherwise; itinerary context injected when `state["itinerary"]` non-empty; plain-chat path unchanged. -- **e2e (`examples/chat` Playwright):** App-mode cockpit renders (map + overlay + right-rail chat); sidenav collapses to drawer in App mode; per-thread itinerary swaps on thread switch. (Map tiles gated on a local Maps key — assert DOM/layout, not tile pixels, per the Maps-canvas harness lesson.) -- **Live gate (Chrome MCP):** against the running `:4200` + `:2024` stack with a real LLM — drive "add the Eiffel Tower to day 2", confirm the pin + panel update live, reload mid-thread and confirm the trip restores from the checkpoint. +- **Unit (vitest):** `itinerary-store` starts empty (no `SEED`) + hydrate-from-`values` + no-localStorage; `map-bounds`; `geocoding.service`; the `submit`-wrapper injects `state.itinerary`; `updateState` called on run-settle and on user edit; empty-state CTA renders with zero stops; App-mode routing coercion (`embed → sidebar`). +- **Backend (pytest):** `generate` binds client tools when catalog present and not otherwise; itinerary context injected when `state["itinerary"]` non-empty and tolerated when empty/absent; the planner framing is applied only when the catalog is bound; plain-chat path unchanged. +- **e2e (`examples/chat` Playwright):** App-mode cockpit renders (map + overlay + right-rail chat); a fresh thread shows the empty-state prompt-to-plan; sidenav collapses to drawer in App mode; per-thread itinerary swaps on thread switch. (Map tiles gated on a local Maps key — assert DOM/layout, not tile pixels, per the Maps-canvas harness lesson.) +- **Live gate (Chrome MCP):** against the running `:4200` + `:2024` stack with a real LLM — start from an **empty** thread, send a planning suggestion ("plan 3 days in Tokyo"), confirm the agent recommends stops and populates the map/panel live via multiple `add_stop` calls, then reload mid-thread and confirm the plan restores from the checkpoint. ## Risks & Mitigations From 3c24c09313860ef8adcb2b0e251f5f8e6b919e94 Mon Sep 17 00:00:00 2001 From: Brian Love Date: Mon, 6 Jul 2026 22:34:40 -0700 Subject: [PATCH 03/23] =?UTF-8?q?docs(plan):=20implementation=20plan=20?= =?UTF-8?q?=E2=80=94=20App=20mode=20on=20the=20langchain=20canonical=20dem?= =?UTF-8?q?o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 16 tasks across 5 phases (spike → backend state/planner → frontend port → shell/wiring → verify). TDD, subagent-executable, local-first. --- ...-langgraph-canonical-app-mode-itinerary.md | 1049 +++++++++++++++++ 1 file changed, 1049 insertions(+) create mode 100644 docs/superpowers/plans/2026-07-06-langgraph-canonical-app-mode-itinerary.md diff --git a/docs/superpowers/plans/2026-07-06-langgraph-canonical-app-mode-itinerary.md b/docs/superpowers/plans/2026-07-06-langgraph-canonical-app-mode-itinerary.md new file mode 100644 index 000000000..22e0b589e --- /dev/null +++ b/docs/superpowers/plans/2026-07-06-langgraph-canonical-app-mode-itinerary.md @@ -0,0 +1,1049 @@ +# App Mode on the LangChain Canonical Demo — Itinerary Cockpit — Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Port the App-mode map/itinerary cockpit from `examples/ag-ui` to the langchain canonical demo (`examples/chat`, `@threadplane/langgraph`), storing the itinerary in the langgraph graph state alongside `messages`, with a single shared agent and no seed data. + +**Architecture:** App mode is a presentational layer over the existing `chat` graph. The graph gains an `itinerary` state channel (per-thread checkpoint) plus frontend-client-tool binding. The Angular `ItineraryStore` is the live working copy (signals → map/panel); the checkpoint is the durable record, synced client-authoritatively via `state.itinerary` on `submit` + `agent.updateState({ itinerary })` after a run and on user edits. The agent recommends places AND populates app state via client tools; the demo starts empty and the user prompts a plan. + +**Tech Stack:** Angular (zoneless, signals), `@threadplane/langgraph` + `@threadplane/chat`, `@angular/google-maps`, LangGraph (Python) + `threadplane-middleware`, Vitest, Playwright, pytest. + +**Design spec:** `docs/superpowers/specs/2026-07-06-langgraph-canonical-app-mode-itinerary-design.md` + +**Execution context:** Work on branch `feat/langgraph-app-mode-itinerary` in the **main checkout** (not a worktree) — the running dev servers (`:4200` examples-chat-angular, `:2024` langgraph `chat` graph) already serve it, which the Chrome-MCP live gate (Task 16) depends on. Leave the pre-existing unrelated dirty files (`libs/chat/.../markdown-table*`) untouched; never `git add` them. + +**Source of truth to copy from:** `examples/ag-ui/angular/src/app/` and `examples/ag-ui/python/`. **Target:** `examples/chat/angular/src/app/` and `examples/chat/python/`. + +**Conventions:** SPDX header `// SPDX-License-Identifier: MIT` on new TS files (match neighbors). Commit after each task. Run unit tests from the repo root. + +--- + +## Phase 0 — De-risk the client-tool round trip + +### Task 1: Spike — prove the langgraph client-tool payload reaches the graph + +**Goal:** Determine which state key the langgraph run payload lands the frontend client-tool catalog in, wire the backend minimally, and prove the model can call a frontend tool that routes away from the server `ToolNode`. + +**Files:** +- Read: `packages/threadplane-middleware/src/threadplane/middleware/langgraph/` (all `.py`) +- Modify: `examples/chat/python/pyproject.toml` +- Modify: `examples/chat/python/src/graph.py` +- Test: `examples/chat/python/tests/test_client_tools_spike.py` (create) + +- [ ] **Step 1: Read the middleware to find the state key + names contract** + +Read every `.py` under `packages/threadplane-middleware/src/threadplane/middleware/langgraph/`. Determine: +- the exact signature of `bind_client_tools(llm, server_tools, state)` and **which `state[...]` key** it reads the client catalog from (candidates: `state["client_tools"]` or `state["tools"]`); +- the exact signature and return of `client_tool_names(state)`. + +Record the key name — call it `` below. (ag-ui populates `state["tools"]` via `ag-ui-langgraph`; the langgraph adapter's TS `mergeClientTools` sets `client_tools` in the run payload, so the langgraph server merges it into state under whatever key matches the graph's `State` channel. The channel name in `State` MUST match the payload key the SDK sends: `client_tools`.) + +- [ ] **Step 2: Add the middleware dependency** + +In `examples/chat/python/pyproject.toml`, add to `[project].dependencies`: + +```toml + "threadplane-middleware>=0.0.1", +``` + +Then install: `cd examples/chat/python && uv sync` — Expected: resolves `threadplane-middleware` from the workspace. + +- [ ] **Step 3: Write a failing test for client-tool routing** + +Create `examples/chat/python/tests/test_client_tools_spike.py`: + +```python +import pytest + + +@pytest.mark.smoke +def test_state_has_client_tools_channel(): + from src.graph import State + ann = State.__annotations__ + assert "client_tools" in ann, "State must carry the frontend client-tool catalog channel" + + +@pytest.mark.smoke +def test_all_client_tool_turn_routes_away_from_server_tools(): + # A turn whose only tool_calls are client tools must NOT route to the + # server ToolNode (which has no implementation for them); the browser + # executes them, so the graph terminates the server loop. + from langchain_core.messages import AIMessage + from src.graph import should_continue + + state = { + "messages": [AIMessage(content="", tool_calls=[ + {"name": "add_stop", "args": {"day": 1, "place": "Louvre"}, "id": "t1"}, + ])], + "client_tools": [{"name": "add_stop"}], + } + assert should_continue(state) != "tools" +``` + +- [ ] **Step 4: Run the test to verify it fails** + +Run: `cd examples/chat/python && uv run pytest tests/test_client_tools_spike.py -v` +Expected: FAIL — `State` has no `client_tools` and/or `should_continue` routes to `tools`. + +- [ ] **Step 5: Add the `client_tools` channel to `State` and bind client tools** + +In `examples/chat/python/src/graph.py`, extend `State` (currently lines 365-369) so it retains the catalog across the graph: + +```python +class State(TypedDict): + messages: Annotated[list, add_messages] + model: Optional[str] + reasoning_effort: Optional[str] + gen_ui_mode: Optional[str] + client_tools: Optional[list] # frontend client-tool catalog (langgraph run payload) + itinerary: list # NEW — see Task 2 (declared here so the channel exists) +``` + +Add the import near the other `threadplane`/langgraph imports at the top of the file: + +```python +from threadplane.middleware.langgraph import bind_client_tools, client_tool_names +``` + +Replace the `bind_tools` call (lines 405-407) so the frontend catalog is appended when present: + +```python + llm = bind_client_tools( + ChatOpenAI(**kwargs), + [search_documents, request_approval, research, gen_ui_tool], + state, + ) +``` + +> If Step 1 found the middleware reads a key other than `client_tools`, name the `State` channel to match what the middleware reads AND what the SDK sends. If they differ, add a tiny normalization at the top of `generate`: `state = {**state, "": state.get("client_tools") or state.get("") or []}` and document it in a comment. Prefer a single key end-to-end. + +- [ ] **Step 6: Update `should_continue` to route all-client-tool turns away from the server ToolNode** + +Find `should_continue` in `examples/chat/python/src/graph.py` (the router after `generate`). Mirror the ag-ui pattern: + +```python +def should_continue(state: State) -> Literal["tools", "attach_citations"]: + last = state["messages"][-1] + if not (isinstance(last, AIMessage) and last.tool_calls): + return "attach_citations" + client = client_tool_names(state) + if all(tc["name"] in client for tc in last.tool_calls): + # Every call is a frontend client tool → the browser executes them; + # the server tool loop terminates. + return "attach_citations" + return "tools" +``` + +Keep the existing terminal target name if the chat graph uses something other than `attach_citations` (e.g. the node that precedes `generate_title`/`END`). Match the existing return literals exactly. + +- [ ] **Step 7: Run the test to verify it passes** + +Run: `cd examples/chat/python && uv run pytest tests/test_client_tools_spike.py -v` +Expected: PASS (both tests). + +- [ ] **Step 8: Live round-trip proof against the running graph** + +With `langgraph dev` on `:2024`, send a run that includes a client-tool catalog and a planning prompt, and confirm the model emits an `add_stop` tool call: + +```bash +cd examples/chat/python +uv run python - <<'PY' +import asyncio, json +from langgraph_sdk import get_client + +async def main(): + client = get_client(url="http://localhost:2024") + thread = await client.threads.create() + catalog = [{"name": "add_stop", + "description": "Add a stop to a day of the trip itinerary.", + "parameters": {"type": "object", + "properties": {"day": {"type": "integer"}, "place": {"type": "string"}}, + "required": ["day", "place"]}}] + saw_add_stop = False + async for chunk in client.runs.stream( + thread["thread_id"], "chat", + input={"messages": [{"role": "user", "content": "Plan 2 days in Paris. Add stops."}], + "client_tools": catalog, "itinerary": []}, + stream_mode=["messages-tuple", "values"], + ): + if "add_stop" in json.dumps(chunk.data): + saw_add_stop = True + print("SAW add_stop tool call:", saw_add_stop) + assert saw_add_stop, "model did not call the frontend client tool — payload key mismatch" + +asyncio.run(main()) +PY +``` + +Expected: `SAW add_stop tool call: True`. If False, the catalog key is not reaching the model — revisit Step 1/Step 5 (key alignment) before proceeding. This is the gate for the whole approach. + +- [ ] **Step 9: Commit** + +```bash +git add examples/chat/python/pyproject.toml examples/chat/python/uv.lock examples/chat/python/src/graph.py examples/chat/python/tests/test_client_tools_spike.py +git commit -m "feat(chat-graph): spike client-tool binding + client-tool-aware routing (#itinerary)" +``` + +--- + +## Phase 1 — Backend: itinerary state, context injection, planner framing + +### Task 2: Itinerary state channel + `Stop` shape + +**Files:** +- Modify: `examples/chat/python/src/graph.py` +- Test: `examples/chat/python/tests/test_itinerary_state.py` (create) + +- [ ] **Step 1: Write the failing test** + +Create `examples/chat/python/tests/test_itinerary_state.py`: + +```python +import pytest + + +@pytest.mark.smoke +def test_state_declares_itinerary_channel(): + from src.graph import State + assert "itinerary" in State.__annotations__ + + +@pytest.mark.smoke +def test_stop_shape(): + from src.graph import Stop + ann = Stop.__annotations__ + for key in ("id", "day", "place"): + assert key in ann, f"Stop must declare {key}" +``` + +- [ ] **Step 2: Run to verify it fails** + +Run: `cd examples/chat/python && uv run pytest tests/test_itinerary_state.py -v` +Expected: FAIL — `Stop` not defined. + +- [ ] **Step 3: Define `Stop` and confirm the `itinerary` channel** + +In `examples/chat/python/src/graph.py`, ensure `NotRequired` is imported (`from typing_extensions import TypedDict, NotRequired`) and add above `State`: + +```python +class Stop(TypedDict): + id: str + day: int + place: str + note: NotRequired[str] + lat: NotRequired[float] + lng: NotRequired[float] +``` + +Change the `itinerary` channel added in Task 1 to the typed shape: + +```python + itinerary: list[Stop] # per-thread checkpoint; last-write-wins (plain key) +``` + +- [ ] **Step 4: Run to verify it passes** + +Run: `cd examples/chat/python && uv run pytest tests/test_itinerary_state.py -v` +Expected: PASS. + +- [ ] **Step 5: Commit** + +```bash +git add examples/chat/python/src/graph.py examples/chat/python/tests/test_itinerary_state.py +git commit -m "feat(chat-graph): add itinerary Stop state channel" +``` + +### Task 3: Inject itinerary context + planner framing into `generate` + +**Files:** +- Modify: `examples/chat/python/src/graph.py` +- Test: `examples/chat/python/tests/test_planner_framing.py` (create) + +- [ ] **Step 1: Write the failing test** + +Create `examples/chat/python/tests/test_planner_framing.py`: + +```python +import pytest +from src.graph import build_system_prompt # helper introduced in Step 3 + + +@pytest.mark.smoke +def test_planner_framing_only_when_client_tools_present(): + plain = build_system_prompt(gen_ui_mode="json-render", client_tools=[], itinerary=[]) + assert "trip-planning" not in plain.lower() + + app = build_system_prompt( + gen_ui_mode="json-render", + client_tools=[{"name": "add_stop"}], + itinerary=[], + ) + assert "trip-planning" in app.lower() + assert "add_stop" in app # instructs the model to populate state via the tool + + +@pytest.mark.smoke +def test_current_itinerary_is_injected_when_present(): + app = build_system_prompt( + gen_ui_mode="json-render", + client_tools=[{"name": "add_stop"}], + itinerary=[{"id": "a", "day": 1, "place": "Louvre"}], + ) + assert "Louvre" in app +``` + +- [ ] **Step 2: Run to verify it fails** + +Run: `cd examples/chat/python && uv run pytest tests/test_planner_framing.py -v` +Expected: FAIL — `build_system_prompt` not defined. + +- [ ] **Step 3: Extract `build_system_prompt` and call it from `generate`** + +In `examples/chat/python/src/graph.py`, add a module-level constant and helper (place the constant near `SYSTEM_PROMPT`, the helper just above `generate`): + +```python +_PLANNER_FRAMING = ( + "\n\n--- APP MODE: TRIP PLANNER ---\n" + "You are a trip-planning assistant driving a live map cockpit. When the user " + "asks for a plan, RECOMMEND concrete places (a short note each) grouped into " + "days, and POPULATE the itinerary by calling `add_stop` for each recommendation " + "(then `day_card` to recap a day). Revise with `move_stop`/`reorder_stop`/`clear_day`. " + "Do NOT just describe the plan in prose — call the tools so the map and panel update. " + "Only add stops that are not already present." +) + + +def build_system_prompt(gen_ui_mode: str, client_tools: list, itinerary: list) -> str: + system = SYSTEM_PROMPT + if gen_ui_mode == "a2ui": + system = system + "\n\n--- A2UI v1 SCHEMA ---\n" + A2UI_V1_SCHEMA_PROMPT + ( + "\n\nWhen rendering UI in a2ui mode, emit envelopes in this order: " + "surfaceUpdate FIRST, then beginRendering, then any dataModelUpdate entries." + ) + if client_tools: + system = system + _PLANNER_FRAMING + if itinerary: + import json as _json + system = system + ( + "\n\nCURRENT ITINERARY (do not re-add existing stops):\n" + + _json.dumps(itinerary, ensure_ascii=False) + ) + return system +``` + +In `generate`, replace the inline system assembly (lines ~408-417) with: + +```python + system = build_system_prompt( + gen_ui_mode=gen_ui_mode, + client_tools=state.get("client_tools") or [], + itinerary=state.get("itinerary") or [], + ) + messages = [SystemMessage(content=system)] + state["messages"] +``` + +Preserve the existing a2ui partial-handler wiring that follows. + +- [ ] **Step 4: Run to verify it passes** + +Run: `cd examples/chat/python && uv run pytest tests/test_planner_framing.py -v` +Expected: PASS. + +- [ ] **Step 5: Full backend smoke + graph import** + +Run: `cd examples/chat/python && uv run pytest tests/ -m smoke -v` +Expected: PASS (existing smokes + the new ones; `src.graph.graph` still imports). + +- [ ] **Step 6: Commit** + +```bash +git add examples/chat/python/src/graph.py examples/chat/python/tests/test_planner_framing.py +git commit -m "feat(chat-graph): planner framing + itinerary context injection when client tools present" +``` + +--- + +## Phase 2 — Frontend: Maps key plumbing + ported services/store + +### Task 4: Google Maps key env + inject-env for examples/chat + +**Files:** +- Create: `examples/chat/angular/scripts/inject-env.mjs` +- Create: `examples/chat/angular/src/environments/generated-keys.ts` +- Modify: `examples/chat/angular/src/environments/environment.ts` +- Modify: `examples/chat/angular/src/environments/environment.development.ts` +- Modify: `examples/chat/angular/project.json` +- Modify: `examples/chat/angular/.gitignore` (or repo root `.gitignore`) + +- [ ] **Step 1: Copy the inject-env script** + +```bash +mkdir -p examples/chat/angular/scripts +cp examples/ag-ui/angular/scripts/inject-env.mjs examples/chat/angular/scripts/inject-env.mjs +``` + +Open the copy and confirm `repoRoot = resolve(__dirname, '../../../..')` still resolves to the repo root from `examples/chat/angular/scripts/` (same depth as ag-ui — it does). No edit needed. + +- [ ] **Step 2: Add the committed stub** + +Create `examples/chat/angular/src/environments/generated-keys.ts`: + +```typescript +// SPDX-License-Identifier: MIT +// Committed stub. Regenerated as generated-keys.local.ts at build time by +// scripts/inject-env.mjs and swapped in via project.json fileReplacements. +// Ships empty (CI has no key); local/preview builds get the real value. +export const GENERATED_KEYS = { + googleMaps: '', + googleMapsMapId: '', +} as const; +``` + +- [ ] **Step 3: Add the Maps fields to both environments** + +In `examples/chat/angular/src/environments/environment.ts` add the import at top and the two fields to the object: + +```typescript +import { GENERATED_KEYS } from './generated-keys'; +``` +```typescript + googleMapsApiKey: GENERATED_KEYS.googleMaps, + googleMapsMapId: GENERATED_KEYS.googleMapsMapId, +``` + +Repeat the identical import + two fields in `environment.development.ts`. + +- [ ] **Step 4: Wire the project.json target + fileReplacements** + +In `examples/chat/angular/project.json`, mirror ag-ui: +- Add an `inject-env` target that runs `node examples/chat/angular/scripts/inject-env.mjs`. +- Add `"inject-env"` to `dependsOn` of both `build` and `serve`. +- In build `configurations.production.fileReplacements` and `configurations.development.fileReplacements`, add: + +```json +{ "replace": "examples/chat/angular/src/environments/generated-keys.ts", + "with": "examples/chat/angular/src/environments/generated-keys.local.ts" } +``` + +Copy the exact target/option shapes from `examples/ag-ui/angular/project.json` (targets `inject-env`, `build`, `serve`) so option names match this repo's Nx executors. + +- [ ] **Step 5: Gitignore the generated file** + +Ensure `examples/chat/angular/src/environments/generated-keys.local.ts` is gitignored (add the path to the repo-root `.gitignore` if a glob doesn't already cover `generated-keys.local.ts`). Verify: `git check-ignore examples/chat/angular/src/environments/generated-keys.local.ts` prints the path. + +- [ ] **Step 6: Generate + typecheck** + +```bash +GOOGLE_MAPS_API_KEY=$(grep -E '^GOOGLE_MAPS_API_KEY=' .env | head -1 | cut -d= -f2- | tr -d '"') +GOOGLE_MAPS_MAP_ID=86d464ea7d5306034fe2a254 \ + node examples/chat/angular/scripts/inject-env.mjs +grep -oE 'googleMaps:\s*"[^"]*"' examples/chat/angular/src/environments/generated-keys.local.ts +``` +Expected: prints `googleMaps: ""` with non-empty length. + +- [ ] **Step 7: Commit** + +```bash +git add examples/chat/angular/scripts/inject-env.mjs examples/chat/angular/src/environments/generated-keys.ts examples/chat/angular/src/environments/environment.ts examples/chat/angular/src/environments/environment.development.ts examples/chat/angular/project.json .gitignore +git commit -m "feat(examples-chat): wire Google Maps key via inject-env (local only)" +``` + +### Task 5: Port map utilities + services (no behavior change) + +**Files:** +- Create (copy): `examples/chat/angular/src/app/{map-bounds.ts,map-bounds.spec.ts,geocoding.service.ts,geocoding.service.spec.ts,google-maps-loader.ts}` +- Test: the copied specs + +- [ ] **Step 1: Copy the standalone files verbatim** + +```bash +cd examples/chat/angular/src/app +cp ../../../../ag-ui/angular/src/app/map-bounds.ts . +cp ../../../../ag-ui/angular/src/app/map-bounds.spec.ts . +cp ../../../../ag-ui/angular/src/app/geocoding.service.ts . +cp ../../../../ag-ui/angular/src/app/geocoding.service.spec.ts . +cp ../../../../ag-ui/angular/src/app/google-maps-loader.ts . +``` + +These have no `@threadplane/ag-ui` imports (only `@angular/core`, `../environments/environment`, `google.maps` types) — no edits needed. `google-maps-loader.ts` imports `../environments/environment`, which now carries `googleMapsApiKey` (Task 4). + +- [ ] **Step 2: Run the copied unit tests** + +Run: `npx nx test examples-chat-angular -- map-bounds geocoding` +(If the project uses a direct vitest invocation, run from `examples/chat/angular`: `npx vitest run src/app/map-bounds.spec.ts src/app/geocoding.service.spec.ts`.) +Expected: PASS. + +- [ ] **Step 3: Commit** + +```bash +git add examples/chat/angular/src/app/map-bounds.ts examples/chat/angular/src/app/map-bounds.spec.ts examples/chat/angular/src/app/geocoding.service.ts examples/chat/angular/src/app/geocoding.service.spec.ts examples/chat/angular/src/app/google-maps-loader.ts +git commit -m "feat(examples-chat): port map-bounds, geocoding, google-maps-loader" +``` + +### Task 6: Port `ItineraryStore` — drop SEED + localStorage, add value hydration + +**Files:** +- Create (copy + edit): `examples/chat/angular/src/app/itinerary-store.ts` +- Create (copy + edit): `examples/chat/angular/src/app/itinerary-store.spec.ts` + +- [ ] **Step 1: Copy the store + spec** + +```bash +cd examples/chat/angular/src/app +cp ../../../../ag-ui/angular/src/app/itinerary-store.ts . +cp ../../../../ag-ui/angular/src/app/itinerary-store.spec.ts . +``` + +- [ ] **Step 2: Write failing tests for empty-start + hydration** + +Replace any seed/localStorage assertions in `itinerary-store.spec.ts` and add: + +```typescript +import { ItineraryStore } from './itinerary-store'; + +describe('ItineraryStore — server-state model', () => { + it('starts empty (no seed)', () => { + const store = new ItineraryStore(); + expect(store.stops()).toEqual([]); + expect(store.days()).toEqual([]); + }); + + it('hydrates from a server itinerary snapshot', () => { + const store = new ItineraryStore(); + store.hydrate([{ id: 'x', day: 1, place: 'Louvre' }]); + expect(store.stops().map((s) => s.place)).toEqual(['Louvre']); + }); + + it('does not touch localStorage on update', () => { + const spy = vi.spyOn(Storage.prototype, 'setItem'); + const store = new ItineraryStore(); + store.add(1, 'Eiffel Tower'); + expect(spy).not.toHaveBeenCalled(); + spy.mockRestore(); + }); +}); +``` + +(Keep the existing add/move/reorder/clearDay behavior tests — those still pass unchanged.) + +- [ ] **Step 3: Run to verify it fails** + +Run from `examples/chat/angular`: `npx vitest run src/app/itinerary-store.spec.ts` +Expected: FAIL — store seeds from SEED / calls localStorage / no `hydrate`. + +- [ ] **Step 4: Edit the store** + +In `examples/chat/angular/src/app/itinerary-store.ts`: +- Delete the `SEED` constant (lines ~21-25) and the `ITINERARY_STORAGE_KEY` constant. +- Change the `stops` signal initializer from `signal(this.hydrate())` to `signal([])`. +- Replace the private `hydrate()` (localStorage read) and `update()` (localStorage write) with: + +```typescript + /** Replace the working copy from a server state snapshot (thread switch / + * values stream). Public — the shell calls it when agent.values() changes. */ + hydrate(stops: ItineraryStop[]): void { + this.stops.set(stops ?? []); + } + + private update(next: ItineraryStop[]): void { + this.stops.set(next); + } +``` +- In `reset()`, replace `this.update([...SEED])` with `this.update([])`. +- Remove the now-unused `try/catch`/`localStorage` code. + +- [ ] **Step 5: Run to verify it passes** + +Run: `npx vitest run src/app/itinerary-store.spec.ts` +Expected: PASS. + +- [ ] **Step 6: Commit** + +```bash +git add examples/chat/angular/src/app/itinerary-store.ts examples/chat/angular/src/app/itinerary-store.spec.ts +git commit -m "feat(examples-chat): port ItineraryStore — empty start, value hydration, no localStorage" +``` + +### Task 7: Port itinerary UI components (day-card, clear-day-confirm, itinerary-panel, map-canvas) + +**Files:** +- Create (copy verbatim): `day-card.component.ts`, `clear-day-confirm.component.ts` +- Create (copy + edit): `itinerary-panel.component.ts` (+ `.spec.ts`), `map-canvas.component.ts` + +- [ ] **Step 1: Copy all four (+ panel spec)** + +```bash +cd examples/chat/angular/src/app +cp ../../../../ag-ui/angular/src/app/day-card.component.ts . +cp ../../../../ag-ui/angular/src/app/clear-day-confirm.component.ts . +cp ../../../../ag-ui/angular/src/app/itinerary-panel.component.ts . +cp ../../../../ag-ui/angular/src/app/itinerary-panel.component.spec.ts . +cp ../../../../ag-ui/angular/src/app/map-canvas.component.ts . +``` + +`day-card.component.ts` (uses `@threadplane/chat` `ViewProps`) and `clear-day-confirm.component.ts` (uses `@threadplane/render`) need **no edits**. `map-canvas.component.ts` has no `@threadplane` imports — no edits. + +- [ ] **Step 2: Swap the agent import in `itinerary-panel.component.ts`** + +Change the import (line ~3): + +```typescript +import { injectAgent } from '@threadplane/langgraph'; +import { DEMO_AGENT_REF } from './shell/agent-ref'; +``` +(Remove the `import { ITINERARY_AGENT } from './client-tools';` line.) Then replace `injectAgent(ITINERARY_AGENT)` with `injectAgent(DEMO_AGENT_REF)`. If the panel used any `ItineraryState`-typed field off the agent, `DemoState` from `./shell/agent-ref` is the langgraph analogue — retype accordingly. Keep everything else (drag-drop, store binding) identical. + +- [ ] **Step 3: Point the empty-state at "ask to plan"** + +In `itinerary-panel.component.ts` template, the empty-state (rendered when `store.days().length === 0`) must read as a prompt-to-plan CTA. Ensure a block like: + +```html +@if (store.days().length === 0) { +
+

No trip yet.

+

Ask the assistant to plan one — try a suggestion in the chat.

+
+} +``` +If the ag-ui panel already has an empty state with different copy, update the copy to the above (no seed implies this is the default view users see first). + +- [ ] **Step 4: Run the panel spec** + +Run from `examples/chat/angular`: `npx vitest run src/app/itinerary-panel.component.spec.ts` +Expected: PASS (fix any `ITINERARY_AGENT`/provider references in the spec to `DEMO_AGENT_REF`; provide the agent via the same TestBed pattern the chat specs use — see `shell/demo-shell.component.spec.ts` for the langgraph agent test harness). + +- [ ] **Step 5: Typecheck the app** + +Run: `npx nx build examples-chat-angular --configuration development` (or `npx tsc -p examples/chat/angular/tsconfig.app.json --noEmit`). +Expected: no type errors from the ported components. (Components not yet referenced by routes/shell are fine; this just proves they compile.) + +- [ ] **Step 6: Commit** + +```bash +git add examples/chat/angular/src/app/day-card.component.ts examples/chat/angular/src/app/clear-day-confirm.component.ts examples/chat/angular/src/app/itinerary-panel.component.ts examples/chat/angular/src/app/itinerary-panel.component.spec.ts examples/chat/angular/src/app/map-canvas.component.ts +git commit -m "feat(examples-chat): port itinerary panel/map/day-card/clear-day UI (langgraph agent)" +``` + +### Task 8: Port client tools — drop `get_itinerary`, target the demo agent + +**Files:** +- Create (copy + edit): `examples/chat/angular/src/app/client-tools.ts` +- Test: `examples/chat/angular/src/app/client-tools.spec.ts` (create) + +- [ ] **Step 1: Copy client-tools** + +```bash +cp examples/ag-ui/angular/src/app/client-tools.ts examples/chat/angular/src/app/client-tools.ts +``` + +- [ ] **Step 2: Edit for the chat/langgraph demo** + +In `examples/chat/angular/src/app/client-tools.ts`: +- **Remove** the `ITINERARY_AGENT` export and the `ItineraryState` interface and the `createAgentRef` import — the chat demo already owns `DEMO_AGENT_REF`/`DemoState` in `./shell/agent-ref`. Keep imports: `tools, action, view, ask, type ClientToolRegistry` from `@threadplane/chat`. +- **Remove** the `get_itinerary` tool entirely (the model sees the itinerary via injected context now; no read round-trip). +- Keep `add_stop`, `move_stop`, `reorder_stop`, `clear_day`, `day_card` unchanged. +- Keep `CLEAR_DAY_SCHEMA` and `itineraryClientTools()`. + +- [ ] **Step 3: Write a failing test** + +Create `examples/chat/angular/src/app/client-tools.spec.ts`: + +```typescript +import { TestBed } from '@angular/core/testing'; +import { ItineraryStore } from './itinerary-store'; +import { GeocodingService } from './geocoding.service'; +import { itineraryClientTools } from './client-tools'; + +describe('itineraryClientTools (langgraph demo)', () => { + beforeEach(() => TestBed.configureTestingModule({ providers: [ItineraryStore, GeocodingService] })); + + it('exposes mutation tools but NOT get_itinerary', () => { + const registry = TestBed.runInInjectionContext(() => itineraryClientTools()); + const names = Object.keys(registry as Record); + expect(names).toContain('add_stop'); + expect(names).toContain('clear_day'); + expect(names).not.toContain('get_itinerary'); + }); +}); +``` + +- [ ] **Step 4: Run — fail then pass** + +Run: `npx vitest run src/app/client-tools.spec.ts` (from `examples/chat/angular`). +Expected: FAIL before the `get_itinerary` removal, PASS after. (If registry key introspection differs, adapt the assertion to the `ClientToolRegistry` shape observed in `libs/chat` client-tools tests.) + +- [ ] **Step 5: Commit** + +```bash +git add examples/chat/angular/src/app/client-tools.ts examples/chat/angular/src/app/client-tools.spec.ts +git commit -m "feat(examples-chat): port itinerary client tools (drop get_itinerary, use demo agent)" +``` + +--- + +## Phase 3 — Shell + agent wiring + +### Task 9: App state sync — submit injects `state.itinerary`, `updateState` persists + +**Files:** +- Modify: `examples/chat/angular/src/app/shell/demo-shell.component.ts` +- Test: `examples/chat/angular/src/app/shell/demo-shell.component.spec.ts` + +- [ ] **Step 1: Write failing tests for the sync** + +Add to `demo-shell.component.spec.ts` (follow the file's existing TestBed + agent-stub pattern): + +```typescript +it('injects the current itinerary into submit state', async () => { + // Arrange: store has one stop; spy on the underlying agent.submit. + // Act: call shell.agent.submit({ messages: [...] }) + // Assert: the orig submit received input.state.itinerary === store.stops() +}); + +it('pushes the itinerary to the checkpoint after a run settles', () => { + // Arrange: spy on agent.updateState. + // Act: simulate run-end (the refreshOnRunEnd / running() → false transition). + // Assert: updateState called with { itinerary: store.stops() }. +}); +``` + +Fill these in against the concrete stub the spec already uses for `injectAgent(DEMO_AGENT_REF)`. If the spec stubs the agent via a provider, extend that stub with `submit` + `updateState` spies and a `running`/`values` signal. + +- [ ] **Step 2: Run to verify it fails** + +Run: `npx vitest run src/app/shell/demo-shell.component.spec.ts` +Expected: FAIL. + +- [ ] **Step 3: Extend the submit wrapper + add the sync effects** + +In `demo-shell.component.ts`: +- Inject the store: add `protected readonly itinerary = inject(ItineraryStore);` (and provide `ItineraryStore` in the component `providers` array, or app-level — Task 12 sets app-level; component-level is fine here for the shell that owns it). Import `ItineraryStore` from `../itinerary-store`. +- In the `submit` wrapper (lines 393-424), add `itinerary: this.itinerary.stops(),` into the `state: { ... }` object alongside `model/reasoning_effort/gen_ui_mode`. +- After the wrapper, add sync effects: + +```typescript +constructor() { + // ...existing constructor body... + + // Hydrate the working copy from server state on thread switch / values stream. + effect(() => { + const v = this.agent.values() as { itinerary?: ItineraryStop[] } | null | undefined; + if (v && Array.isArray(v.itinerary)) this.itinerary.hydrate(v.itinerary); + }); + + // Persist the working copy to the checkpoint when a run settles. + let wasRunning = false; + effect(() => { + const running = this.agent.running(); + if (wasRunning && !running) { + void this.agent.updateState?.({ itinerary: this.itinerary.stops() }); + } + wasRunning = running; + }); +} +``` + +Import `ItineraryStop` from `../itinerary-store`. If `agent.running` isn't the exact signal name, use the run-state signal the chat agent exposes (check `libs/langgraph` agent type — `refreshOnRunEnd` is already imported by this shell, so an equivalent run-end hook exists; prefer wiring the `updateState` into that hook if cleaner). + +- [ ] **Step 4: Add the user-edit sync** + +Direct user edits (drag-reorder/add/clear in the panel) must also persist. In `itinerary-panel.component.ts`, after each user-initiated store mutation, call `this.agent.updateState?.({ itinerary: this.store.stops() })` (the panel already injects the agent from Task 7). Guard so it only fires for `source: 'user'` mutations (agent edits are captured by the run-settle effect). Add a focused panel spec asserting `updateState` is called on a user drag-drop. + +- [ ] **Step 5: Run to verify it passes** + +Run: `npx vitest run src/app/shell/demo-shell.component.spec.ts src/app/itinerary-panel.component.spec.ts` +Expected: PASS. + +- [ ] **Step 6: Commit** + +```bash +git add examples/chat/angular/src/app/shell/demo-shell.component.ts examples/chat/angular/src/app/shell/demo-shell.component.spec.ts examples/chat/angular/src/app/itinerary-panel.component.ts examples/chat/angular/src/app/itinerary-panel.component.spec.ts +git commit -m "feat(examples-chat): sync itinerary — submit state + updateState on run-settle and user edit" +``` + +### Task 10: App-mode signal + toggle + map-compatible routing + +**Files:** +- Modify: `examples/chat/angular/src/app/shell/demo-shell.component.ts` (+ `.html`/template, `.css`) +- Modify: `examples/chat/angular/src/app/shell/palette-persistence.service.ts` (reuse for appMode persistence — or the existing persistence service the shell uses) +- Test: `demo-shell.component.spec.ts` + +- [ ] **Step 1: Write failing tests for appMode routing** + +Add to `demo-shell.component.spec.ts` (port the ag-ui-shell semantics): + +```typescript +it('coerces embed → sidebar when App mode turns on', () => { + // set mode embed, call onAppModeChange('on'); expect navigation to /sidebar and appMode()==='on' +}); +it('turning App mode off keeps the current route', () => { + // mode sidebar + appMode on; onAppModeChange('off'); route stays /sidebar, appMode()==='off' +}); +it('selecting embed while App mode is on turns App mode off', () => { + // appMode on; onModeChange('embed'); expect appMode()==='off' +}); +``` + +- [ ] **Step 2: Run to verify it fails** + +Run: `npx vitest run src/app/shell/demo-shell.component.spec.ts` +Expected: FAIL — no `appMode`. + +- [ ] **Step 3: Port the appMode state + handlers from ag-ui-shell** + +Into `demo-shell.component.ts`, port from `examples/ag-ui/angular/src/app/shell/ag-ui-shell.component.ts`: +- `readonly appMode = signal<'on' | 'off'>(this.initialAppMode());` +- `readonly hasMapsKey = (environment.googleMapsApiKey as string).length > 0;` +- `initialAppMode()`, `onAppModeChange(v)`, and the embed-coercion in `onModeChange` (see ag-ui-shell lines 100-104, 207-235). +- The knob param-sync effect's `appmode` entry (ag-ui-shell lines 191, 201-203): include `appmode` in the query object and coerce `embed → sidebar` when App mode is on. Adapt to demo-shell's existing router/effect (demo-shell parses URL via `urlState()`/`parseUrl()` and navigates via `onModeChange` — keep those; add the appMode coercion in the same navigate path). +- Persist appMode via the shell's persistence service (`write('appMode', ...)`, read in `initialAppMode`). + +Import `environment` from `../../environments/environment`. + +- [ ] **Step 4: Add the toggle to the toolbar template** + +In the demo-shell template, add the App-mode toggle button between the segmented mode buttons and the model field (port markup from `ag-ui-shell.component.html` lines ~18-28), bound to `appMode()`/`hasMapsKey`/`onAppModeChange`. Add the toggle's CSS from `ag-ui-shell.component.css` (`.ag-ui-shell__app-toggle*`), renamed to the `demo-shell__` prefix. + +- [ ] **Step 5: Run to verify it passes** + +Run: `npx vitest run src/app/shell/demo-shell.component.spec.ts` +Expected: PASS. + +- [ ] **Step 6: Commit** + +```bash +git add examples/chat/angular/src/app/shell/ +git commit -m "feat(examples-chat): App-mode toggle + map-compatible routing (embed↔sidebar coercion)" +``` + +### Task 11: App-mode layout — map background + itinerary overlay + sidenav→drawer (layout ①) + +**Files:** +- Modify: `examples/chat/angular/src/app/shell/demo-shell.component.html` +- Modify: `examples/chat/angular/src/app/shell/demo-shell.component.css` +- Modify: `examples/chat/angular/src/app/shell/demo-shell.component.ts` + +- [ ] **Step 1: Force the thread sidenav to drawer in App mode** + +In `demo-shell.component.ts`, make `sidenavMode` (computed, line ~274) return `'drawer'` when `this.appMode() === 'on'` (so the thread sidenav collapses to the hamburger drawer and the map owns the background): + +```typescript +readonly sidenavMode = computed(() => { + if (this.appMode() === 'on') return 'drawer'; + if (this.viewportIsNarrow()) return 'drawer'; // keep existing narrow-viewport rule + return this.storedDesktopMode(); +}); +``` +(Preserve the existing viewport/preference logic; add the appMode branch first.) + +- [ ] **Step 2: Add the app-body layout branch to the template** + +In `demo-shell.component.html`, wrap the `.demo-shell__main` region with an appMode branch, porting `ag-ui-shell.component.html`'s `@if (appMode() === 'on')` block: + +```html +@if (appMode() === 'on') { +
+ + +
+ + @if (agent.interrupt && agent.interrupt()) { +
+ +
+ } +
+
+} @else { + +} +``` +Add `MapCanvasComponent` and `ItineraryPanelComponent` to the component `imports` array. Keep the `` / palette markup outside this branch (the sidenav is still present but in drawer mode). + +- [ ] **Step 3: Port the app-body CSS** + +Into `demo-shell.component.css`, port `.ag-ui-shell__app-body`, `.ag-ui-shell__map` (full-bleed background), `.ag-ui-shell__itinerary-overlay` (floating left overlay), renamed to `demo-shell__`. Ensure `.demo-shell__map` is `position:absolute; inset:0;` behind the overlay + chat rail, and the itinerary overlay floats above it (left, with a max-width). Chat renders as the right rail via the existing sidebar/popup mode components. + +- [ ] **Step 4: Verify build + a rendering unit check** + +Run: `npx nx build examples-chat-angular --configuration development` +Expected: builds. Add/extend a demo-shell spec asserting that with `appMode() === 'on'` the template renders `app-map-canvas` and forces `sidenavMode() === 'drawer'`. +Run: `npx vitest run src/app/shell/demo-shell.component.spec.ts` → PASS. + +- [ ] **Step 5: Commit** + +```bash +git add examples/chat/angular/src/app/shell/ +git commit -m "feat(examples-chat): App-mode cockpit layout (map bg + itinerary overlay + sidenav→drawer)" +``` + +### Task 12: Wire client tools + store into the app; mode components render the cockpit + +**Files:** +- Modify: `examples/chat/angular/src/app/app.config.ts` +- Modify: `examples/chat/angular/src/app/shell/demo-shell.component.ts` +- Modify: `examples/chat/angular/src/app/modes/sidebar-mode.component.ts`, `popup-mode.component.ts`, `embed-mode.component.ts` +- Create (copy + edit): `examples/chat/angular/src/app/modes/app-mode-promo.component.ts` (+ spec), retune `welcome-suggestions*` + +- [ ] **Step 1: Provide the store + maps loader in app.config** + +In `examples/chat/angular/src/app/app.config.ts` add to `providers`: + +```typescript +import { inject, provideEnvironmentInitializer } from '@angular/core'; +import { ItineraryStore } from './itinerary-store'; +import { GoogleMapsLoader } from './google-maps-loader'; +// ... + ItineraryStore, + provideEnvironmentInitializer(() => inject(GoogleMapsLoader).ensureLoaded()), +``` +Do **not** add a seed / `initialValues` — the demo starts empty. Keep the existing `LANGGRAPH_THREADS_CONFIG`/`provideChat` providers. + +- [ ] **Step 2: Expose the client-tools registry on the shell** + +In `demo-shell.component.ts` add: + +```typescript +import { itineraryClientTools } from '../client-tools'; +// field: +readonly clientTools = itineraryClientTools(); // built in injection context +``` + +- [ ] **Step 3: Bind the map/itinerary + clientTools in the mode components** + +Port the ag-ui mode composition into the chat modes: +- `sidebar-mode.component.ts`: bind `[clientTools]="shell.clientTools"` on the `` (inject the shell via `inject(DemoShell)`), and when `shell.appMode() === 'on'` render `` in the sidebar content slot (see `examples/ag-ui/angular/src/app/modes/sidebar-mode.component.ts` for the exact slot/`@if` structure). Import `MapCanvasComponent`, `AppModePromoComponent`. +- `popup-mode.component.ts`: bind `[clientTools]` on ``; the map renders as the shell background (Task 11), the popup floats over it. +- `embed-mode.component.ts`: bind `[clientTools]` (embed is not an App-mode layout, but the tools remain available so a user in embed can still ask for a plan — harmless; the itinerary just isn't visualized). + +- [ ] **Step 4: Port the app-mode promo + retune welcome suggestions** + +```bash +cp examples/ag-ui/angular/src/app/modes/app-mode-promo.component.ts examples/chat/angular/src/app/modes/app-mode-promo.component.ts +cp examples/ag-ui/angular/src/app/modes/app-mode-promo.component.spec.ts examples/chat/angular/src/app/modes/app-mode-promo.component.spec.ts 2>/dev/null || true +``` +No `@threadplane/ag-ui` import there — no edit beyond confirming the promo image asset path resolves (copy any referenced asset from `examples/ag-ui/angular/src/assets` into `examples/chat/angular/src/assets` if missing). + +Retune `examples/chat/angular/src/app/modes/welcome-suggestions.ts` to trip-planning starters: + +```typescript +export const WELCOME_SUGGESTIONS = [ + 'Plan a long weekend in Paris', + '3 days in Tokyo with great food', + 'A week on the California coast', +] as const; +``` +(Match the existing export name/shape in that file; only change the content to planning prompts. Update `welcome-suggestions.component.spec.ts` expectations accordingly.) + +- [ ] **Step 5: Build + unit tests** + +Run: `npx nx build examples-chat-angular --configuration development` +Run: `npx vitest run src/app/modes` (from `examples/chat/angular`) +Expected: builds; mode + promo + welcome specs PASS. + +- [ ] **Step 6: Commit** + +```bash +git add examples/chat/angular/src/app/app.config.ts examples/chat/angular/src/app/shell/demo-shell.component.ts examples/chat/angular/src/app/modes/ examples/chat/angular/src/assets +git commit -m "feat(examples-chat): wire client tools + cockpit into modes; planner welcome suggestions" +``` + +--- + +## Phase 4 — Verify + +### Task 13: Cross-cutting gates (lint / typecheck / unit / build) + +- [ ] **Step 1: Frontend gates** + +```bash +npx nx lint examples-chat-angular +npx nx test examples-chat-angular +npx nx build examples-chat-angular --configuration development +``` +Expected: lint clean (fix any aliased-input eslint-disable needs), all unit specs green, build succeeds. + +- [ ] **Step 2: Backend gates** + +```bash +cd examples/chat/python && uv run pytest tests/ -v +``` +Expected: all pass (spike + itinerary-state + planner-framing + pre-existing). + +- [ ] **Step 3: Commit any fixups** + +```bash +git add -A -- examples/chat +git commit -m "chore(examples-chat): gate fixups (lint/typecheck/test)" --allow-empty +``` + +### Task 14: e2e — App-mode cockpit on examples/chat + +**Files:** +- Create: `examples/chat/angular/e2e/app-mode-itinerary.spec.ts` + +- [ ] **Step 1: Write the e2e spec** + +Using the existing `examples/chat/angular/e2e/test-helpers.ts` (`openDemo`, `messageInput`, `sendButton`, `selectToolbarDropdown`), create `app-mode-itinerary.spec.ts` asserting (no reliance on map tiles — DOM/layout only, per the Maps-canvas harness lesson): + +```typescript +import { test, expect } from '@playwright/test'; +import { openDemo } from './test-helpers'; + +test('App mode shows the cockpit with an empty prompt-to-plan state', async ({ page }) => { + await openDemo(page, '/sidebar?appmode=on'); + await expect(page.locator('app-map-canvas')).toBeVisible(); + await expect(page.locator('app-itinerary-panel')).toContainText(/plan/i); + // sidenav collapsed to drawer in App mode → hamburger present, panel not pinned + await expect(page.locator('.demo-shell__hamburger')).toBeVisible(); +}); + +test('embed turns App mode off (coercion)', async ({ page }) => { + await openDemo(page, '/sidebar?appmode=on'); + await page.getByRole('button', { name: 'Embed' }).click(); + await expect(page).toHaveURL(/\/embed/); + await expect(page.locator('app-map-canvas')).toHaveCount(0); +}); +``` +(If `openDemo` can't pass query params, extend it to accept `/sidebar?appmode=on`, mirroring the ag-ui `openDemo(page, '/?appmode=on')` helper.) + +- [ ] **Step 2: Run the e2e (kill stale servers first)** + +Per the examples-chat e2e runbook, free `:4200`/`:2024` of stale listeners, then: +```bash +npx nx e2e examples-chat-angular -- --grep "App mode" +``` +Expected: the two specs pass. (These run keyless-capable — the panel + layout render regardless of Maps tiles.) + +- [ ] **Step 3: Commit** + +```bash +git add examples/chat/angular/e2e/app-mode-itinerary.spec.ts examples/chat/angular/e2e/test-helpers.ts +git commit -m "test(examples-chat): e2e App-mode cockpit (empty state + embed coercion)" +``` + +### Task 15: Live Chrome-MCP gate — empty → planning prompt → populated → reload restores + +**Manual/controller task (no file changes). Uses the running `:4200` + `:2024` stack + a real LLM (OPENAI_API_KEY in `.env`).** + +- [ ] **Step 1:** Ensure the chat stack serves the fresh bundle with a Maps key: restart `examples-chat-angular` serve with `GOOGLE_MAPS_API_KEY` exported (and `GOOGLE_MAPS_MAP_ID=86d464ea7d5306034fe2a254`); confirm `generated-keys.local.ts` has a non-empty key. Symlink the root `.env` into the checkout if serving from a worktree. +- [ ] **Step 2:** In Chrome MCP, open `http://localhost:4200/sidebar?appmode=on`. Probe DOM (not screenshots) to confirm `app-map-canvas` + `app-itinerary-panel` mount and the panel shows the empty prompt-to-plan state. +- [ ] **Step 3:** Send "Plan 3 days in Tokyo with great food". Confirm via `ng.getComponent` / DOM that the agent issues multiple `add_stop` calls and the itinerary panel + map pins populate live across days. +- [ ] **Step 4:** Reload the page mid-thread; confirm the itinerary restores from the checkpoint (`agent.values().itinerary` hydrates the panel/map) — proving per-thread durable state. +- [ ] **Step 5:** Start a new thread; confirm it opens empty (no seed). Record findings; if any layer fails, root-cause before merge (systematic-debugging). + +### Task 16: Final review + branch finish + +- [ ] **Step 1:** Dispatch a final code-review subagent over the whole diff (spec compliance + code quality). +- [ ] **Step 2:** Confirm the standing no-persist constraint: scan `git diff origin/main...HEAD` for the excluded competitor product name (per the session rule) — it must return nothing. +- [ ] **Step 3:** Use superpowers:finishing-a-development-branch to open the PR (local parity; deploy is a follow-up noted in the PR body). + +--- + +## Notes for the executor + +- **DRY/YAGNI:** the ported components are near-verbatim; do not refactor them. Only the documented edits (agent import, empty-state, store hydration, client-tool trimming) are in scope. +- **Standalone-examples convention:** everything lives in `examples/chat`; never import across examples or extract to a lib. +- **No brand-name churn:** do not rename existing `@threadplane/*` imports beyond the `ag-ui → langgraph` swap in `itinerary-panel`. +- **Maps footgun:** a keyless bundle silently disables the map (no error). Verify `generated-keys.local.ts` before every live check. +- **If the spike (Task 1) fails the live proof:** stop and reconcile the client-tool payload key before building the frontend — the whole cockpit depends on it. From 74d45e2b6ce9f1fd6faf6bb916f6b0f5a4681695 Mon Sep 17 00:00:00 2001 From: Brian Love Date: Mon, 6 Jul 2026 22:41:57 -0700 Subject: [PATCH 04/23] feat(chat-graph): spike client-tool binding + client-tool-aware routing (#itinerary) Co-Authored-By: Claude Opus 4.8 --- examples/chat/python/pyproject.toml | 1 + examples/chat/python/src/graph.py | 44 ++++++++++++++++--- .../python/tests/test_client_tools_spike.py | 21 +++++++++ examples/chat/python/uv.lock | 15 +++++++ 4 files changed, 74 insertions(+), 7 deletions(-) create mode 100644 examples/chat/python/tests/test_client_tools_spike.py diff --git a/examples/chat/python/pyproject.toml b/examples/chat/python/pyproject.toml index 961c196f1..a1c9056b3 100644 --- a/examples/chat/python/pyproject.toml +++ b/examples/chat/python/pyproject.toml @@ -7,6 +7,7 @@ dependencies = [ "langchain-openai>=0.3", "langgraph-api>=0.8.7", "python-dotenv>=1.0", + "threadplane-middleware>=0.0.1", ] [tool.uv] diff --git a/examples/chat/python/src/graph.py b/examples/chat/python/src/graph.py index 48e0c4c6d..43ab19539 100644 --- a/examples/chat/python/src/graph.py +++ b/examples/chat/python/src/graph.py @@ -42,6 +42,8 @@ from langgraph_sdk import get_client from langsmith import traceable +from threadplane.middleware.langgraph import bind_client_tools, client_tool_names + from src.streaming.a2ui_partial_handler import A2uiPartialHandler from src.streaming.envelope_tool import render_a2ui_surface from src.streaming.envelope_normalizer import normalize_envelope_args @@ -367,6 +369,18 @@ class State(TypedDict): model: Optional[str] reasoning_effort: Optional[str] gen_ui_mode: Optional[str] + # Frontend client-tool catalog. The @threadplane/langgraph SDK path + # (mergeClientTools) sends the browser-declared tool stubs under + # ``client_tools`` in the run payload; the threadplane-middleware + # ``_catalog`` reads ``state["tools"]`` first and falls back to + # ``state["client_tools"]`` — so this channel name feeds the middleware + # directly with no normalization needed. The channel must exist here so + # the catalog survives the generate → should_continue path. + client_tools: Optional[list] + # Trip itinerary the frontend client tools (add_stop/move_stop/...) + # mutate. Declared now so the channel exists; typed properly in a + # later task. + itinerary: list async def generate(state: State, config: RunnableConfig) -> dict: @@ -402,8 +416,14 @@ async def generate(state: State, config: RunnableConfig) -> dict: # libs/chat/src/lib/a2ui/envelope-normalizer.ts) to canonicalize the # four observed argument shapes (envelopes / envelope / positional / # flat). The spike showed 80-93% canonical even without strict. - llm = ChatOpenAI(**kwargs).bind_tools( + # bind_client_tools appends the frontend client-tool catalog stubs (read + # from state["client_tools"], sent by the @threadplane/langgraph SDK + # mergeClientTools path) to the server tool list so the model can call any + # browser-declared tool by name (add_stop/move_stop/clear_day/day_card). + llm = bind_client_tools( + ChatOpenAI(**kwargs), [search_documents, request_approval, research, gen_ui_tool], + state, ) # Append A2UI v1 schema to system prompt when in a2ui mode, so the parent # LLM knows how to construct the envelopes directly. @@ -427,13 +447,23 @@ async def generate(state: State, config: RunnableConfig) -> dict: def should_continue(state: State) -> Literal["tools", "attach_citations"]: - """Conditional edge from generate: route to tools node when any - tool_call is present (GenUI tools, search, approval, research), - otherwise route to attach_citations terminal post-process.""" + """Conditional edge from generate: route to the server ToolNode when any + SERVER tool_call is present (GenUI tools, search, approval, research). + + A turn whose calls are ALL frontend client tools must END (route to the + terminal attach_citations post-process) so the browser can execute them + and re-run with the resulting ToolMessage — the server ToolNode has no + implementation for client tools and would otherwise error. Turns with no + tool calls also terminate at attach_citations (a no-op without search + results). Mixed server+client turns keep the 'tools' route. + """ last = state["messages"][-1] - if isinstance(last, AIMessage) and last.tool_calls: - return "tools" - return "attach_citations" + if not (isinstance(last, AIMessage) and last.tool_calls): + return "attach_citations" + client = client_tool_names(state) + if all(tc["name"] in client for tc in last.tool_calls): + return "attach_citations" + return "tools" def after_tools(state: State) -> Literal["emit_generated_surface", "generate"]: diff --git a/examples/chat/python/tests/test_client_tools_spike.py b/examples/chat/python/tests/test_client_tools_spike.py new file mode 100644 index 000000000..1885ccf8f --- /dev/null +++ b/examples/chat/python/tests/test_client_tools_spike.py @@ -0,0 +1,21 @@ +import pytest + + +@pytest.mark.smoke +def test_state_has_client_tools_channel(): + from src.graph import State + ann = State.__annotations__ + assert "client_tools" in ann, "State must carry the frontend client-tool catalog channel" + + +@pytest.mark.smoke +def test_all_client_tool_turn_routes_away_from_server_tools(): + from langchain_core.messages import AIMessage + from src.graph import should_continue + state = { + "messages": [AIMessage(content="", tool_calls=[ + {"name": "add_stop", "args": {"day": 1, "place": "Louvre"}, "id": "t1"}, + ])], + "client_tools": [{"name": "add_stop"}], + } + assert should_continue(state) != "tools" diff --git a/examples/chat/python/uv.lock b/examples/chat/python/uv.lock index 060f09728..758c13d2e 100644 --- a/examples/chat/python/uv.lock +++ b/examples/chat/python/uv.lock @@ -288,6 +288,7 @@ dependencies = [ { name = "langgraph" }, { name = "langgraph-api" }, { name = "python-dotenv" }, + { name = "threadplane-middleware" }, ] [package.dev-dependencies] @@ -303,6 +304,7 @@ requires-dist = [ { name = "langgraph", specifier = ">=0.3" }, { name = "langgraph-api", specifier = ">=0.8.7" }, { name = "python-dotenv", specifier = ">=1.0" }, + { name = "threadplane-middleware", specifier = ">=0.0.1" }, ] [package.metadata.requires-dev] @@ -1488,6 +1490,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d7/c1/eb8f9debc45d3b7918a32ab756658a0904732f75e555402972246b0b8e71/tenacity-9.1.4-py3-none-any.whl", hash = "sha256:6095a360c919085f28c6527de529e76a06ad89b23659fa881ae0649b867a9d55", size = 28926, upload-time = "2026-02-07T10:45:32.24Z" }, ] +[[package]] +name = "threadplane-middleware" +version = "0.0.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "langchain-core" }, + { name = "langgraph" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/01/5f/fee360e3547bede9388bb72a9ad20ca811935582b989c78dafeaae57558a/threadplane_middleware-0.0.1.tar.gz", hash = "sha256:60c931d0248ed2e701a3aa1330c6fd647e611a949500269c5ba82f3607102cef", size = 95505, upload-time = "2026-06-16T20:55:18.335Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/72/55/28e6b752f3f53f2c5d2c2fa3ef27ac62a255a3b29376384f2dfc96d8acb0/threadplane_middleware-0.0.1-py3-none-any.whl", hash = "sha256:c14e49d506e8bd3078f54df381c150d390f2d129f844694d8f5154a2cd8710ea", size = 4315, upload-time = "2026-06-16T20:55:19.044Z" }, +] + [[package]] name = "tiktoken" version = "0.12.0" From e23fb54a2f02c77f7dc3f1f6f37c665775193642 Mon Sep 17 00:00:00 2001 From: Brian Love Date: Mon, 6 Jul 2026 22:47:33 -0700 Subject: [PATCH 05/23] feat(chat-graph): add itinerary Stop state channel Co-Authored-By: Claude Opus 4.8 --- examples/chat/python/src/graph.py | 18 +++++++++++++----- .../chat/python/tests/test_itinerary_state.py | 15 +++++++++++++++ 2 files changed, 28 insertions(+), 5 deletions(-) create mode 100644 examples/chat/python/tests/test_itinerary_state.py diff --git a/examples/chat/python/src/graph.py b/examples/chat/python/src/graph.py index 43ab19539..e2ae4adee 100644 --- a/examples/chat/python/src/graph.py +++ b/examples/chat/python/src/graph.py @@ -23,7 +23,7 @@ import json import os from typing import Annotated, Literal, Optional -from typing_extensions import TypedDict +from typing_extensions import TypedDict, NotRequired from langgraph.graph import StateGraph, END from langgraph.graph.message import add_messages @@ -364,6 +364,15 @@ def _as_text(content) -> str: return "" +class Stop(TypedDict): + id: str + day: int + place: str + note: NotRequired[str] + lat: NotRequired[float] + lng: NotRequired[float] + + class State(TypedDict): messages: Annotated[list, add_messages] model: Optional[str] @@ -376,11 +385,10 @@ class State(TypedDict): # ``state["client_tools"]`` — so this channel name feeds the middleware # directly with no normalization needed. The channel must exist here so # the catalog survives the generate → should_continue path. - client_tools: Optional[list] + client_tools: Optional[list[dict]] # Trip itinerary the frontend client tools (add_stop/move_stop/...) - # mutate. Declared now so the channel exists; typed properly in a - # later task. - itinerary: list + # mutate. per-thread checkpoint; last-write-wins (plain key) + itinerary: list[Stop] async def generate(state: State, config: RunnableConfig) -> dict: diff --git a/examples/chat/python/tests/test_itinerary_state.py b/examples/chat/python/tests/test_itinerary_state.py new file mode 100644 index 000000000..76f26ebad --- /dev/null +++ b/examples/chat/python/tests/test_itinerary_state.py @@ -0,0 +1,15 @@ +import pytest + + +@pytest.mark.smoke +def test_state_declares_itinerary_channel(): + from src.graph import State + assert "itinerary" in State.__annotations__ + + +@pytest.mark.smoke +def test_stop_shape(): + from src.graph import Stop + ann = Stop.__annotations__ + for key in ("id", "day", "place"): + assert key in ann, f"Stop must declare {key}" From cdaeeeac69619c80a9a21c7debdb11ed91f53106 Mon Sep 17 00:00:00 2001 From: Brian Love Date: Mon, 6 Jul 2026 22:50:08 -0700 Subject: [PATCH 06/23] feat(chat-graph): planner framing + itinerary context injection when client tools present --- examples/chat/python/src/graph.py | 45 +++++++++++++++---- .../chat/python/tests/test_planner_framing.py | 26 +++++++++++ 2 files changed, 63 insertions(+), 8 deletions(-) create mode 100644 examples/chat/python/tests/test_planner_framing.py diff --git a/examples/chat/python/src/graph.py b/examples/chat/python/src/graph.py index e2ae4adee..7fe553f1f 100644 --- a/examples/chat/python/src/graph.py +++ b/examples/chat/python/src/graph.py @@ -182,6 +182,16 @@ async def generate_title(state: "State", config: RunnableConfig) -> dict: "ask for a UI / form / card / interactive surface." ) +_PLANNER_FRAMING = ( + "\n\n--- APP MODE: TRIP PLANNER ---\n" + "You are a trip-planning assistant driving a live map cockpit. When the user " + "asks for a plan, RECOMMEND concrete places (a short note each) grouped into " + "days, and POPULATE the itinerary by calling `add_stop` for each recommendation " + "(then `day_card` to recap a day). Revise with `move_stop`/`reorder_stop`/`clear_day`. " + "Do NOT just describe the plan in prose — call the tools so the map and panel update. " + "Only add stops that are not already present." +) + # Reasoning-capable model prefixes. We only attach the ``reasoning`` # parameter when the model name suggests reasoning support; setting it # on a non-reasoning model would be ignored anyway. @@ -391,6 +401,25 @@ class State(TypedDict): itinerary: list[Stop] +def build_system_prompt(gen_ui_mode: str, client_tools: list, itinerary: list) -> str: + system = SYSTEM_PROMPT + if gen_ui_mode == "a2ui": + system = system + "\n\n--- A2UI v1 SCHEMA ---\n" + A2UI_V1_SCHEMA_PROMPT + ( + "\n\nWhen rendering UI in a2ui mode, emit envelopes in this order: " + "surfaceUpdate FIRST, then beginRendering, then any dataModelUpdate " + "entries. This lets the client mount the surface as early as possible." + ) + if client_tools: + system = system + _PLANNER_FRAMING + if itinerary: + import json as _json + system = system + ( + "\n\nCURRENT ITINERARY (do not re-add existing stops):\n" + + _json.dumps(itinerary, ensure_ascii=False) + ) + return system + + async def generate(state: State, config: RunnableConfig) -> dict: model_name = state.get("model") or "gpt-5-mini" kwargs = {"model": model_name, "streaming": True} @@ -434,14 +463,14 @@ async def generate(state: State, config: RunnableConfig) -> dict: state, ) # Append A2UI v1 schema to system prompt when in a2ui mode, so the parent - # LLM knows how to construct the envelopes directly. - system = SYSTEM_PROMPT - if gen_ui_mode == "a2ui": - system = SYSTEM_PROMPT + "\n\n--- A2UI v1 SCHEMA ---\n" + A2UI_V1_SCHEMA_PROMPT + ( - "\n\nWhen rendering UI in a2ui mode, emit envelopes in this order: " - "surfaceUpdate FIRST, then beginRendering, then any dataModelUpdate " - "entries. This lets the client mount the surface as early as possible." - ) + # LLM knows how to construct the envelopes directly. When the frontend + # client-tool catalog is present (App mode), also inject the trip-planner + # framing + the current itinerary so the model populates state via the tools. + system = build_system_prompt( + gen_ui_mode=gen_ui_mode, + client_tools=state.get("client_tools") or [], + itinerary=state.get("itinerary") or [], + ) messages = [SystemMessage(content=system)] + state["messages"] # When in a2ui mode, attach the partial-envelope sideband handler so # the parent LLM's tool_call_chunks for render_a2ui_surface are diff --git a/examples/chat/python/tests/test_planner_framing.py b/examples/chat/python/tests/test_planner_framing.py new file mode 100644 index 000000000..a80427208 --- /dev/null +++ b/examples/chat/python/tests/test_planner_framing.py @@ -0,0 +1,26 @@ +import pytest +from src.graph import build_system_prompt # helper introduced in Step 3 + + +@pytest.mark.smoke +def test_planner_framing_only_when_client_tools_present(): + plain = build_system_prompt(gen_ui_mode="json-render", client_tools=[], itinerary=[]) + assert "trip-planning" not in plain.lower() + + app = build_system_prompt( + gen_ui_mode="json-render", + client_tools=[{"name": "add_stop"}], + itinerary=[], + ) + assert "trip-planning" in app.lower() + assert "add_stop" in app # instructs the model to populate state via the tool + + +@pytest.mark.smoke +def test_current_itinerary_is_injected_when_present(): + app = build_system_prompt( + gen_ui_mode="json-render", + client_tools=[{"name": "add_stop"}], + itinerary=[{"id": "a", "day": 1, "place": "Louvre"}], + ) + assert "Louvre" in app From de8f706e862711aacbbaa12ca97af742f73a30cf Mon Sep 17 00:00:00 2001 From: Brian Love Date: Mon, 6 Jul 2026 22:53:23 -0700 Subject: [PATCH 07/23] feat(examples-chat): wire Google Maps key via inject-env (local only) Mirrors examples/ag-ui/angular: inject-env.mjs reads GOOGLE_MAPS_API_KEY/ GOOGLE_MAPS_MAP_ID from the repo-root .env and writes a gitignored generated-keys.local.ts, swapped in via project.json fileReplacements. Ships empty in CI; local/preview builds get the real value. --- .gitignore | 2 ++ examples/chat/angular/project.json | 25 +++++++++++++- examples/chat/angular/scripts/inject-env.mjs | 34 +++++++++++++++++++ .../environments/environment.development.ts | 4 +++ .../angular/src/environments/environment.ts | 4 +++ .../src/environments/generated-keys.ts | 8 +++++ 6 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 examples/chat/angular/scripts/inject-env.mjs create mode 100644 examples/chat/angular/src/environments/generated-keys.ts diff --git a/.gitignore b/.gitignore index 5d3296a11..856009b4a 100644 --- a/.gitignore +++ b/.gitignore @@ -65,3 +65,5 @@ libs/licensing/src/lib/license-public-key.generated.ts # AG-UI example generated API keys (injected from .env at build time) examples/ag-ui/angular/src/environments/generated-keys.local.ts +# Chat example generated API keys (injected from .env at build time) +examples/chat/angular/src/environments/generated-keys.local.ts diff --git a/examples/chat/angular/project.json b/examples/chat/angular/project.json index 3f4dd626b..140dc0e75 100644 --- a/examples/chat/angular/project.json +++ b/examples/chat/angular/project.json @@ -5,8 +5,18 @@ "projectType": "application", "prefix": "app", "targets": { + "inject-env": { + "executor": "nx:run-commands", + "options": { + "command": "node examples/chat/angular/scripts/inject-env.mjs", + "cwd": "{workspaceRoot}" + } + }, "build": { "executor": "@angular/build:application", + "dependsOn": [ + "inject-env" + ], "outputs": [ "{options.outputPath.base}" ], @@ -49,7 +59,13 @@ "maximumError": "16kb" } ], - "outputHashing": "all" + "outputHashing": "all", + "fileReplacements": [ + { + "replace": "examples/chat/angular/src/environments/generated-keys.ts", + "with": "examples/chat/angular/src/environments/generated-keys.local.ts" + } + ] }, "production-debug": { "define": { @@ -80,6 +96,10 @@ { "replace": "examples/chat/angular/src/environments/environment.ts", "with": "examples/chat/angular/src/environments/environment.development.ts" + }, + { + "replace": "examples/chat/angular/src/environments/generated-keys.ts", + "with": "examples/chat/angular/src/environments/generated-keys.local.ts" } ] } @@ -89,6 +109,9 @@ "serve": { "continuous": true, "executor": "@angular/build:dev-server", + "dependsOn": [ + "inject-env" + ], "options": { "port": 4200 }, diff --git a/examples/chat/angular/scripts/inject-env.mjs b/examples/chat/angular/scripts/inject-env.mjs new file mode 100644 index 000000000..93500c617 --- /dev/null +++ b/examples/chat/angular/scripts/inject-env.mjs @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: MIT +import { readFileSync, writeFileSync, existsSync } from 'node:fs'; +import { resolve, dirname } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const repoRoot = resolve(__dirname, '../../../..'); + +function readDotEnv() { + const envPath = resolve(repoRoot, '.env'); + if (!existsSync(envPath)) return {}; + const raw = readFileSync(envPath, 'utf8'); + const out = {}; + for (const line of raw.split('\n')) { + const m = line.match(/^([A-Z_][A-Z0-9_]*)=(.*)$/); + if (m) out[m[1]] = m[2].replace(/^"|"$/g, ''); + } + return out; +} + +const env = { ...readDotEnv(), ...process.env }; +const key = env.GOOGLE_MAPS_API_KEY ?? ''; +const mapId = env.GOOGLE_MAPS_MAP_ID ?? ''; + +const targetPath = resolve(__dirname, '../src/environments/generated-keys.local.ts'); +const contents = `// SPDX-License-Identifier: MIT +// AUTO-GENERATED by scripts/inject-env.mjs. Do not edit by hand. +export const GENERATED_KEYS = { + googleMaps: ${JSON.stringify(key)}, + googleMapsMapId: ${JSON.stringify(mapId)}, +} as const; +`; +writeFileSync(targetPath, contents); +console.log(`[inject-env] wrote generated-keys.local.ts (key length: ${key.length}, mapId: ${mapId ? 'set' : 'unset'})`); diff --git a/examples/chat/angular/src/environments/environment.development.ts b/examples/chat/angular/src/environments/environment.development.ts index bd0292040..ace45c0ac 100644 --- a/examples/chat/angular/src/environments/environment.development.ts +++ b/examples/chat/angular/src/environments/environment.development.ts @@ -5,6 +5,8 @@ * Points to a local LangGraph server started with: * cd examples/chat/python && langgraph dev */ +import { GENERATED_KEYS } from './generated-keys'; + export const environment = { production: false, langGraphApiUrl: 'http://localhost:2024', @@ -14,4 +16,6 @@ export const environment = { sampleRate: 1, }, license: undefined as string | undefined, + googleMapsApiKey: GENERATED_KEYS.googleMaps, + googleMapsMapId: GENERATED_KEYS.googleMapsMapId, }; diff --git a/examples/chat/angular/src/environments/environment.ts b/examples/chat/angular/src/environments/environment.ts index 8fd11d49c..f955cb942 100644 --- a/examples/chat/angular/src/environments/environment.ts +++ b/examples/chat/angular/src/environments/environment.ts @@ -7,6 +7,8 @@ * which injects x-api-key server-side and proxies to the shared * cockpit-dev LangGraph Cloud assistant. */ +import { GENERATED_KEYS } from './generated-keys'; + export const environment = { production: true, langGraphApiUrl: '/api', @@ -17,4 +19,6 @@ export const environment = { sampleRate: 1, }, license: undefined as string | undefined, + googleMapsApiKey: GENERATED_KEYS.googleMaps, + googleMapsMapId: GENERATED_KEYS.googleMapsMapId, }; diff --git a/examples/chat/angular/src/environments/generated-keys.ts b/examples/chat/angular/src/environments/generated-keys.ts new file mode 100644 index 000000000..7da7b6554 --- /dev/null +++ b/examples/chat/angular/src/environments/generated-keys.ts @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: MIT +// Committed stub. Regenerated as generated-keys.local.ts at build time by +// scripts/inject-env.mjs and swapped in via project.json fileReplacements. +// Ships empty (CI has no key); local/preview builds get the real value. +export const GENERATED_KEYS = { + googleMaps: '', + googleMapsMapId: '', +} as const; From e55515c7daf84cc69b25c6ef3d7676e0fda7dcdf Mon Sep 17 00:00:00 2001 From: Brian Love Date: Mon, 6 Jul 2026 22:55:16 -0700 Subject: [PATCH 08/23] feat(examples-chat): port map-bounds, geocoding, google-maps-loader --- .../angular/src/app/geocoding.service.spec.ts | 49 +++++++++++++++ .../chat/angular/src/app/geocoding.service.ts | 27 +++++++++ .../angular/src/app/google-maps-loader.ts | 59 +++++++++++++++++++ .../chat/angular/src/app/map-bounds.spec.ts | 37 ++++++++++++ examples/chat/angular/src/app/map-bounds.ts | 26 ++++++++ 5 files changed, 198 insertions(+) create mode 100644 examples/chat/angular/src/app/geocoding.service.spec.ts create mode 100644 examples/chat/angular/src/app/geocoding.service.ts create mode 100644 examples/chat/angular/src/app/google-maps-loader.ts create mode 100644 examples/chat/angular/src/app/map-bounds.spec.ts create mode 100644 examples/chat/angular/src/app/map-bounds.ts diff --git a/examples/chat/angular/src/app/geocoding.service.spec.ts b/examples/chat/angular/src/app/geocoding.service.spec.ts new file mode 100644 index 000000000..d8501107b --- /dev/null +++ b/examples/chat/angular/src/app/geocoding.service.spec.ts @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: MIT +import { describe, it, expect, beforeEach, afterEach } from 'vitest'; +import { TestBed } from '@angular/core/testing'; +import { GeocodingService } from './geocoding.service'; + +beforeEach(() => { + (globalThis as any).google = { + maps: { + Geocoder: class { + async geocode({ address }: { address: string }) { + if (address === 'fail') throw new Error('boom'); + if (address === 'empty') return { results: [] }; + return { + results: [ + { geometry: { location: { lat: () => 48.85, lng: () => 2.35 } } }, + ], + }; + } + }, + }, + }; +}); + +afterEach(() => { + delete (globalThis as any).google; +}); + +describe('GeocodingService', () => { + it('resolves an address to { lat, lng }', async () => { + const svc = TestBed.inject(GeocodingService); + expect(await svc.geocode('Louvre')).toEqual({ lat: 48.85, lng: 2.35 }); + }); + + it('returns null when geocoding throws', async () => { + const svc = TestBed.inject(GeocodingService); + expect(await svc.geocode('fail')).toBeNull(); + }); + + it('returns null when there are no results', async () => { + const svc = TestBed.inject(GeocodingService); + expect(await svc.geocode('empty')).toBeNull(); + }); + + it('returns null when google.maps is not loaded', async () => { + delete (globalThis as any).google; + const svc = TestBed.inject(GeocodingService); + expect(await svc.geocode('Louvre')).toBeNull(); + }); +}); diff --git a/examples/chat/angular/src/app/geocoding.service.ts b/examples/chat/angular/src/app/geocoding.service.ts new file mode 100644 index 000000000..a3c20069f --- /dev/null +++ b/examples/chat/angular/src/app/geocoding.service.ts @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: MIT +/// +import { Injectable } from '@angular/core'; + +/** + * Wraps the Google Maps Geocoder to resolve a place string to coordinates. + * Returns null on any failure — Maps not loaded, no results, or a thrown + * error — so callers can add a stop with no pin rather than break. + */ +@Injectable({ providedIn: 'root' }) +export class GeocodingService { + private geocoder: google.maps.Geocoder | null = null; + + async geocode(address: string): Promise<{ lat: number; lng: number } | null> { + const g = (globalThis as { google?: typeof google }).google; + if (!g?.maps?.Geocoder) return null; + try { + this.geocoder ??= new g.maps.Geocoder(); + const { results } = await this.geocoder.geocode({ address }); + const first = results?.[0]; + if (!first) return null; + return { lat: first.geometry.location.lat(), lng: first.geometry.location.lng() }; + } catch { + return null; + } + } +} diff --git a/examples/chat/angular/src/app/google-maps-loader.ts b/examples/chat/angular/src/app/google-maps-loader.ts new file mode 100644 index 000000000..297899eef --- /dev/null +++ b/examples/chat/angular/src/app/google-maps-loader.ts @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: MIT +import { Injectable, signal } from '@angular/core'; +import { environment } from '../environments/environment'; + +/** + * Loads the Google Maps JS API on demand and exposes a `loaded` signal. + * + * Why this exists: `` (from `@angular/google-maps`) THROWS in its + * constructor when `window.google` is absent ("Namespace google not found…", + * dev-mode only). The Maps script loads asynchronously, so rendering the map + * before it resolves aborts the host component's change-detection pass — which + * (on a fresh load with App mode persisted on) blanks the whole shell. The fix + * is the documented `@angular/google-maps` contract: only render `` + * once the API is present. Consumers gate their template on `loaded()` and call + * `ensureLoaded()` once. + */ +@Injectable({ providedIn: 'root' }) +export class GoogleMapsLoader { + /** Becomes true once `window.google.maps` is available. */ + readonly loaded = signal(false); + private started = false; + + /** Idempotent: injects the Maps script once (if a key is present) and flips + * `loaded` when ready. Safe to call from multiple components. */ + ensureLoaded(): void { + if (this.loaded() || this.started) return; + const w = globalThis as { google?: { maps?: unknown }; document?: Document }; + if (w.google?.maps) { + this.loaded.set(true); + return; + } + this.started = true; + + const key = (environment.googleMapsApiKey as string) ?? ''; + if (!key) return; // No key → map stays gated off (the toolbar toggle is also disabled). + + const doc = w.document; + if (!doc) return; + + const existing = doc.querySelector('script[data-google-maps]'); + if (existing) { + // A load is already in flight (e.g. a prior instance). Poll for readiness. + const poll = setInterval(() => { + if ((globalThis as { google?: { maps?: unknown } }).google?.maps) { + clearInterval(poll); + this.loaded.set(true); + } + }, 100); + return; + } + + const script = doc.createElement('script'); + script.src = `https://maps.googleapis.com/maps/api/js?key=${encodeURIComponent(key)}&libraries=geocoding,marker`; + script.async = true; + script.setAttribute('data-google-maps', ''); + script.addEventListener('load', () => this.loaded.set(true)); + doc.head.appendChild(script); + } +} diff --git a/examples/chat/angular/src/app/map-bounds.spec.ts b/examples/chat/angular/src/app/map-bounds.spec.ts new file mode 100644 index 000000000..7b33800b5 --- /dev/null +++ b/examples/chat/angular/src/app/map-bounds.spec.ts @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: MIT +import { describe, it, expect } from 'vitest'; +import { computeBounds } from './map-bounds'; + +describe('computeBounds', () => { + it('returns null for an empty list', () => { + expect(computeBounds([])).toBeNull(); + }); + + it('returns null when no stop has coordinates', () => { + expect(computeBounds([{ lat: null, lng: null }, { lat: undefined, lng: undefined }])).toBeNull(); + }); + + it('returns a degenerate box for a single stop', () => { + expect(computeBounds([{ lat: 48.86, lng: 2.35 }])).toEqual({ + north: 48.86, south: 48.86, east: 2.35, west: 2.35, + }); + }); + + it('returns min/max extents for multiple stops', () => { + const b = computeBounds([ + { lat: 48.86, lng: 2.35 }, + { lat: 48.80, lng: 2.40 }, + { lat: 48.90, lng: 2.30 }, + ]); + expect(b).toEqual({ north: 48.90, south: 48.80, east: 2.40, west: 2.30 }); + }); + + it('ignores stops missing coordinates', () => { + const b = computeBounds([ + { lat: 48.86, lng: 2.35 }, + { lat: null, lng: null }, + { lat: 48.90, lng: 2.40 }, + ]); + expect(b).toEqual({ north: 48.90, south: 48.86, east: 2.40, west: 2.35 }); + }); +}); diff --git a/examples/chat/angular/src/app/map-bounds.ts b/examples/chat/angular/src/app/map-bounds.ts new file mode 100644 index 000000000..d0a091fed --- /dev/null +++ b/examples/chat/angular/src/app/map-bounds.ts @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MIT + +/** A geographic bounding box (LatLngBoundsLiteral-compatible). */ +export interface Bounds { + north: number; + south: number; + east: number; + west: number; +} + +/** Smallest box containing every stop that has coordinates, or null if none do. */ +export function computeBounds( + stops: ReadonlyArray<{ lat?: number | null; lng?: number | null }>, +): Bounds | null { + let north = -Infinity, south = Infinity, east = -Infinity, west = Infinity; + let found = false; + for (const s of stops) { + if (s.lat == null || s.lng == null) continue; + found = true; + north = Math.max(north, s.lat); + south = Math.min(south, s.lat); + east = Math.max(east, s.lng); + west = Math.min(west, s.lng); + } + return found ? { north, south, east, west } : null; +} From 0f37460be5193f03b39254fd11acd3625b479b99 Mon Sep 17 00:00:00 2001 From: Brian Love Date: Mon, 6 Jul 2026 22:57:59 -0700 Subject: [PATCH 09/23] =?UTF-8?q?feat(examples-chat):=20port=20ItinerarySt?= =?UTF-8?q?ore=20=E2=80=94=20empty=20start,=20value=20hydration,=20no=20lo?= =?UTF-8?q?calStorage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../angular/src/app/itinerary-store.spec.ts | 162 ++++++++++++++++++ .../chat/angular/src/app/itinerary-store.ts | 118 +++++++++++++ 2 files changed, 280 insertions(+) create mode 100644 examples/chat/angular/src/app/itinerary-store.spec.ts create mode 100644 examples/chat/angular/src/app/itinerary-store.ts diff --git a/examples/chat/angular/src/app/itinerary-store.spec.ts b/examples/chat/angular/src/app/itinerary-store.spec.ts new file mode 100644 index 000000000..1fab775af --- /dev/null +++ b/examples/chat/angular/src/app/itinerary-store.spec.ts @@ -0,0 +1,162 @@ +// SPDX-License-Identifier: MIT +import { describe, it, expect, vi } from 'vitest'; +import { ItineraryStore } from './itinerary-store'; + +describe('ItineraryStore', () => { + it('add appends a stop', () => { + const s = new ItineraryStore(); + s.add(2, 'Sainte-Chapelle', 'morning'); + expect(s.stops().some((x) => x.place === 'Sainte-Chapelle')).toBe(true); + }); + + it('move matches place case-insensitively and returns the stop', () => { + const s = new ItineraryStore(); + s.add(1, 'Louvre'); + const moved = s.move('louvre', 2); + expect(moved?.day).toBe(2); + expect(s.move('atlantis', 1)).toBeUndefined(); + }); + + it('clearDay removes only stops for that day', () => { + const s = new ItineraryStore(); + s.add(1, 'Louvre'); + s.add(1, 'Eiffel Tower'); + s.add(2, "Musée d'Orsay"); + const removed = s.clearDay(1); + expect(removed).toBe(2); + expect(s.stops().every((x) => x.day !== 1)).toBe(true); + // day 2 stop still exists + expect(s.stops().some((x) => x.day === 2)).toBe(true); + }); + + it('remove deletes the stop with the given id', () => { + const s = new ItineraryStore(); + s.add(1, 'Louvre'); + s.add(1, 'Eiffel Tower'); + const first = s.stops()[0]; + s.remove(first.id); + expect(s.stops().find((x) => x.id === first.id)).toBeUndefined(); + expect(s.stops().length).toBe(1); + }); + + it('reset clears all stops', () => { + const s = new ItineraryStore(); + s.add(3, 'Versailles'); + s.reset(); + expect(s.stops().length).toBe(0); + }); +}); + +describe('ItineraryStore — server-state model', () => { + it('starts empty (no seed)', () => { + const store = new ItineraryStore(); + expect(store.stops()).toEqual([]); + expect(store.days()).toEqual([]); + }); + + it('hydrates from a server itinerary snapshot', () => { + const store = new ItineraryStore(); + store.hydrate([{ id: 'x', day: 1, place: 'Louvre' }]); + expect(store.stops().map((s) => s.place)).toEqual(['Louvre']); + }); + + it('does not touch localStorage on update', () => { + const spy = vi.spyOn(Storage.prototype, 'setItem'); + const store = new ItineraryStore(); + store.add(1, 'Eiffel Tower'); + expect(spy).not.toHaveBeenCalled(); + spy.mockRestore(); + }); +}); + +describe('reorder', () => { + it('moves a stop to a new index within the same day', () => { + const s = new ItineraryStore(); + s.add(1, 'Louvre'); + s.add(1, 'Eiffel Tower'); + const eiffel = s.stops().find((x) => x.place === 'Eiffel Tower')!; + s.reorder(eiffel.id, 1, 0); + const day1 = s.days().find((g) => g.day === 1)!; + expect(day1.stops.map((x) => x.place)).toEqual(['Eiffel Tower', 'Louvre']); + }); + + it('moves a stop across days at a specific index', () => { + const s = new ItineraryStore(); + s.add(1, 'Louvre'); + s.add(1, 'Eiffel Tower'); + s.add(2, "Musée d'Orsay"); + const orsay = s.stops().find((x) => x.place === "Musée d'Orsay")!; + s.reorder(orsay.id, 1, 0); + const day1 = s.days().find((g) => g.day === 1)!; + expect(day1.stops[0].place).toBe("Musée d'Orsay"); + expect(day1.stops[0].day).toBe(1); + }); + + it('reorder by unknown id is a no-op', () => { + const s = new ItineraryStore(); + s.add(1, 'Louvre'); + const before = s.stops(); + s.reorder('does-not-exist', 1, 0); + expect(s.stops()).toEqual(before); + }); +}); + +describe('recentlyChangedId', () => { + it('is null initially', () => { + const s = new ItineraryStore(); + expect(s.recentlyChangedId()).toBeNull(); + }); + + it('is set after an agent-source add', () => { + const s = new ItineraryStore(); + const added = s.add(3, 'Sacré-Cœur'); + expect(s.recentlyChangedId()).toBe(added.id); + }); + + it('is NOT set after a user-source add', () => { + const s = new ItineraryStore(); + s.add(3, 'Sacré-Cœur', undefined, { source: 'user' }); + expect(s.recentlyChangedId()).toBeNull(); + }); + + it('clears 1600ms after the change', async () => { + vi.useFakeTimers(); + const s = new ItineraryStore(); + s.add(3, 'Sacré-Cœur'); + expect(s.recentlyChangedId()).not.toBeNull(); + vi.advanceTimersByTime(1600); + expect(s.recentlyChangedId()).toBeNull(); + vi.useRealTimers(); + }); +}); + +describe('focus', () => { + it('focus sets and clears focusedStopId', () => { + const s = new ItineraryStore(); + s.add(1, 'Louvre'); + const id = s.stops()[0].id; + expect(s.focusedStopId()).toBeNull(); + s.focus(id); + expect(s.focusedStopId()).toBe(id); + s.focus(null); + expect(s.focusedStopId()).toBeNull(); + }); +}); + +describe('coordinates', () => { + it('add accepts optional lat/lng via opts.coords', () => { + const s = new ItineraryStore(); + const added = s.add(2, 'Sacré-Cœur', undefined, { + coords: { lat: 48.8867, lng: 2.3431 }, + }); + expect(added.lat).toBeCloseTo(48.8867, 3); + expect(added.lng).toBeCloseTo(2.3431, 3); + }); + + it('add without coords leaves lat/lng undefined', () => { + const s = new ItineraryStore(); + const added = s.add(2, 'Somewhere'); + expect(added.lat).toBeUndefined(); + expect(added.lng).toBeUndefined(); + }); +}); diff --git a/examples/chat/angular/src/app/itinerary-store.ts b/examples/chat/angular/src/app/itinerary-store.ts new file mode 100644 index 000000000..33b809738 --- /dev/null +++ b/examples/chat/angular/src/app/itinerary-store.ts @@ -0,0 +1,118 @@ +// SPDX-License-Identifier: MIT +import { computed, signal } from '@angular/core'; + +export interface ItineraryStop { + id: string; + day: number; + place: string; + note?: string; + lat?: number; + lng?: number; +} + +export interface MutationOptions { + source?: 'user' | 'agent'; + coords?: { lat: number; lng: number }; +} + +const PULSE_MS = 1600; + +/** Working copy of the itinerary: the user edits it in the panel, the agent + * edits it through client tools. Both write the same signals, so either's + * changes render immediately. The graph checkpoint is the durable record — + * the shell calls `hydrate()` from a server state snapshot on thread switch. */ +export class ItineraryStore { + readonly stops = signal([]); + readonly days = computed(() => { + const byDay = new Map(); + for (const s of this.stops()) byDay.set(s.day, [...(byDay.get(s.day) ?? []), s]); + return [...byDay.entries()] + .sort(([a], [b]) => a - b) + .map(([day, stops]) => ({ day, stops })); + }); + readonly recentlyChangedId = signal(null); + readonly focusedStopId = signal(null); + private pulseTimer: ReturnType | null = null; + + focus(id: string | null): void { + this.focusedStopId.set(id); + } + + add(day: number, place: string, note?: string, opts?: MutationOptions): ItineraryStop { + const stop: ItineraryStop = { + id: crypto.randomUUID(), + day, + place, + ...(note ? { note } : {}), + ...(opts?.coords ? { lat: opts.coords.lat, lng: opts.coords.lng } : {}), + }; + this.update([...this.stops(), stop]); + this.flagChanged(stop.id, opts); + return stop; + } + + move(place: string, toDay: number, opts?: MutationOptions): ItineraryStop | undefined { + const target = this.stops().find((s) => s.place.toLowerCase() === place.toLowerCase()); + if (!target) return undefined; + const moved = { ...target, day: toDay }; + this.update(this.stops().map((s) => (s.id === target.id ? moved : s))); + this.flagChanged(moved.id, opts); + return moved; + } + + reorder(stopId: string, toDay: number, toIndex: number, opts?: MutationOptions): void { + const current = this.stops(); + const target = current.find((s) => s.id === stopId); + if (!target) return; + const without = current.filter((s) => s.id !== stopId); + const dayStops = without.filter((s) => s.day === toDay); + const others = without.filter((s) => s.day !== toDay); + const clampedIndex = Math.max(0, Math.min(toIndex, dayStops.length)); + const newDayStops = [ + ...dayStops.slice(0, clampedIndex), + { ...target, day: toDay }, + ...dayStops.slice(clampedIndex), + ]; + this.update([...others, ...newDayStops]); + this.flagChanged(stopId, opts); + } + + remove(id: string, opts?: MutationOptions): void { + this.update(this.stops().filter((s) => s.id !== id)); + this.flagChanged(id, opts); + } + + clearDay(day: number, opts?: MutationOptions): number { + const removed = this.stops().filter((s) => s.day === day).length; + this.update(this.stops().filter((s) => s.day !== day)); + if (removed > 0) this.flagChanged(null, opts); + return removed; + } + + reset(opts?: MutationOptions): void { + this.update([]); + this.flagChanged(null, opts); + } + + private flagChanged(id: string | null, opts?: MutationOptions): void { + if (opts?.source === 'user') return; + if (this.pulseTimer) clearTimeout(this.pulseTimer); + this.recentlyChangedId.set(id); + if (id !== null) { + this.pulseTimer = setTimeout(() => { + this.recentlyChangedId.set(null); + this.pulseTimer = null; + }, PULSE_MS); + } + } + + /** Replace the working copy from a server state snapshot (thread switch / + * values stream). Public — the shell calls it when agent.values() changes. */ + hydrate(stops: ItineraryStop[]): void { + this.stops.set(stops ?? []); + } + + private update(next: ItineraryStop[]): void { + this.stops.set(next); + } +} From 662c94a4ea9af7b260769d5b87fc8fb0f1aa49ce Mon Sep 17 00:00:00 2001 From: Brian Love Date: Mon, 6 Jul 2026 23:03:07 -0700 Subject: [PATCH 10/23] feat(examples-chat): port itinerary panel/map/day-card/clear-day UI (langgraph agent) Co-Authored-By: Claude Opus 4.8 --- .../src/app/clear-day-confirm.component.ts | 99 ++++ .../angular/src/app/day-card.component.ts | 72 +++ .../src/app/itinerary-panel.component.spec.ts | 89 +++ .../src/app/itinerary-panel.component.ts | 533 ++++++++++++++++++ .../angular/src/app/map-canvas.component.ts | 256 +++++++++ 5 files changed, 1049 insertions(+) create mode 100644 examples/chat/angular/src/app/clear-day-confirm.component.ts create mode 100644 examples/chat/angular/src/app/day-card.component.ts create mode 100644 examples/chat/angular/src/app/itinerary-panel.component.spec.ts create mode 100644 examples/chat/angular/src/app/itinerary-panel.component.ts create mode 100644 examples/chat/angular/src/app/map-canvas.component.ts diff --git a/examples/chat/angular/src/app/clear-day-confirm.component.ts b/examples/chat/angular/src/app/clear-day-confirm.component.ts new file mode 100644 index 000000000..2500da8e8 --- /dev/null +++ b/examples/chat/angular/src/app/clear-day-confirm.component.ts @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: MIT +import { ChangeDetectionStrategy, Component, computed, inject, input } from '@angular/core'; +import { injectRenderHost } from '@threadplane/render'; +import { ItineraryStore } from './itinerary-store'; + +/** + * The interactive component for the `clear_day` client tool (an `ask`). The + * model fills `day`; the user confirms or cancels. Because an ask emits the + * tool result and the handler layer cannot intercept it, the mutation happens + * HERE: Clear writes the shared `ItineraryStore` (so the panel updates live) + * and then announces the outcome via `injectRenderHost().result(...)`, which + * becomes the tool result that resumes the run. Cancel never touches the store. + * + * Once the ask resolves, the adapter writes the emitted value back onto the + * local tool call, so this component re-renders with `cleared`/`removed` as + * props (chat-tool-views spreads `{...args, ...result, status}` into it). When + * `cleared()` is defined we render a FROZEN line with no buttons; the live + * interactive card only shows while `cleared()` is still undefined. + */ +@Component({ + selector: 'app-clear-day-confirm', + standalone: true, + changeDetection: ChangeDetectionStrategy.OnPush, + template: ` + @if (cleared() === undefined) { +
+

Clear all {{ count() }} stops on day {{ day() }}?

+
+ + +
+
+ } @else if (cleared() === true) { +
+

Day {{ day() }} cleared — {{ removed() }} removed ✓

+
+ } @else { +
+

Kept day {{ day() }} — clear cancelled

+
+ } + `, + styles: [ + ` + .cdc { + border: 1px solid var(--tplane-chat-separator, #e5e7eb); + border-radius: 12px; + padding: 16px; + max-width: 360px; + } + .cdc--resolved .cdc__summary { + margin: 0; + opacity: 0.85; + } + .cdc__summary { + margin: 0 0 12px; + } + .cdc__actions { + display: flex; + gap: 8px; + } + .cdc__btn { + padding: 6px 14px; + border-radius: 8px; + border: 1px solid var(--tplane-chat-separator, #e5e7eb); + background: transparent; + color: inherit; + cursor: pointer; + } + .cdc__btn--primary { + background: var(--tplane-chat-accent, #2563eb); + color: #fff; + border-color: transparent; + } + `, + ], +}) +export class ClearDayConfirmComponent { + readonly day = input.required(); + /** Spread back onto props after the ask resolves (undefined while interactive). */ + readonly cleared = input(undefined); + readonly removed = input(undefined); + private readonly store = inject(ItineraryStore); + private readonly host = injectRenderHost(); + + protected readonly count = computed( + () => this.store.stops().filter((s) => s.day === this.day()).length, + ); + + protected clear(): void { + const day = this.day(); + const removed = this.store.clearDay(day); + this.host.result({ cleared: true, day, removed }); + } + + protected cancel(): void { + this.host.result({ cleared: false, day: this.day() }); + } +} diff --git a/examples/chat/angular/src/app/day-card.component.ts b/examples/chat/angular/src/app/day-card.component.ts new file mode 100644 index 000000000..7a536164c --- /dev/null +++ b/examples/chat/angular/src/app/day-card.component.ts @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: MIT +import { ChangeDetectionStrategy, Component, input } from '@angular/core'; +import type { ViewProps } from '@threadplane/chat'; +import { z } from 'zod/v4'; + +/** + * Schema for the `day_card` view tool — co-located with the component so the + * inputs and the schema shape can be kept in sync at a glance. + * `client-tools.ts` imports this schema to pass to `view(…, DAY_CARD_SCHEMA, …)`. + */ +export const DAY_CARD_SCHEMA = z.object({ + day: z.number().int().min(1), + places: z.array(z.string()), +}); + +/** Input types derived directly from the `day_card` schema — guarantees this + * component stays compatible with the view() check at compile time. */ +type Inputs = ViewProps; + +/** + * A frontend-owned view rendered for the `day_card` client tool. The model + * fills `day` and `places`; this card recaps one itinerary day after an edit. + */ +@Component({ + selector: 'app-day-card', + standalone: true, + changeDetection: ChangeDetectionStrategy.OnPush, + template: ` +
+
Day {{ day() }}
+
    + @for (p of places(); track p) { +
  • {{ p }}
  • + } @empty { +
  • No stops
  • + } +
+
+ `, + styles: [ + ` + .dc { + border: 1px solid var(--tplane-chat-separator, #e5e7eb); + border-radius: 12px; + padding: 16px; + max-width: 280px; + } + .dc__head { + font-weight: 600; + margin-bottom: 8px; + } + .dc__list { + list-style: none; + margin: 0; + padding: 0; + display: flex; + flex-direction: column; + gap: 4px; + } + .dc__item { + opacity: 0.9; + } + .dc__item--empty { + opacity: 0.5; + } + `, + ], +}) +export class DayCardComponent { + readonly day = input.required(); + readonly places = input([]); +} diff --git a/examples/chat/angular/src/app/itinerary-panel.component.spec.ts b/examples/chat/angular/src/app/itinerary-panel.component.spec.ts new file mode 100644 index 000000000..663e03c55 --- /dev/null +++ b/examples/chat/angular/src/app/itinerary-panel.component.spec.ts @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: MIT +import { describe, it, expect, beforeEach } from 'vitest'; +import { TestBed } from '@angular/core/testing'; +import { provideAgent, FakeStreamTransport } from '@threadplane/langgraph'; +import { DEMO_AGENT_REF } from './shell/agent-ref'; +import { ItineraryPanelComponent } from './itinerary-panel.component'; +import { ItineraryStore } from './itinerary-store'; + +// Bind the DEMO_AGENT_REF token to an in-process fake LangGraph agent so +// injectAgent(DEMO_AGENT_REF) in the panel resolves without a backend. +const fakeAgentProvider = provideAgent(DEMO_AGENT_REF, { + assistantId: 'fake', + transport: new FakeStreamTransport(), +}); + +describe('ItineraryPanelComponent — agent-edit pulse', () => { + beforeEach(() => localStorage.clear()); + + it('applies .itin__stop--pulse to the row matching recentlyChangedId', async () => { + TestBed.configureTestingModule({ + providers: [ + ItineraryStore, + ...fakeAgentProvider, + ], + }); + const store = TestBed.inject(ItineraryStore); + const added = store.add(3, 'Sacré-Cœur'); // agent source by default + + const fixture = TestBed.createComponent(ItineraryPanelComponent); + fixture.detectChanges(); + + const rows = fixture.nativeElement.querySelectorAll('.itin__stop'); + const pulsing = Array.from(rows).filter((el: any) => + el.classList.contains('itin__stop--pulse'), + ); + expect(pulsing.length).toBe(1); + expect((pulsing[0] as HTMLElement).textContent).toContain('Sacré-Cœur'); + // satisfy lint + expect(added.id).toBeDefined(); + }); + + it('toggles the itin--collapsed host class via the collapse button', () => { + TestBed.configureTestingModule({ + providers: [ + ItineraryStore, + ...fakeAgentProvider, + ], + }); + + const fixture = TestBed.createComponent(ItineraryPanelComponent); + fixture.detectChanges(); + + const host = fixture.nativeElement as HTMLElement; + expect(host.classList.contains('itin--collapsed')).toBe(false); + + const toggle = host.querySelector('.itin__collapse') as HTMLButtonElement; + expect(toggle).toBeTruthy(); + + toggle.click(); + fixture.detectChanges(); + expect(host.classList.contains('itin--collapsed')).toBe(true); + + toggle.click(); + fixture.detectChanges(); + expect(host.classList.contains('itin--collapsed')).toBe(false); + }); + + it('highlights the focused row', () => { + TestBed.configureTestingModule({ + providers: [ + ItineraryStore, + ...fakeAgentProvider, + ], + }); + const store = TestBed.inject(ItineraryStore); + // The chat-demo store starts empty, so seed a stop before focusing it. + const stop = store.add(1, 'Louvre'); + store.focus(stop.id); + + const fixture = TestBed.createComponent(ItineraryPanelComponent); + fixture.detectChanges(); + + const rows = fixture.nativeElement.querySelectorAll('.itin__stop'); + const pulsing = Array.from(rows).filter((el: any) => + el.classList.contains('itin__stop--pulse'), + ); + expect(pulsing.length).toBe(1); + }); +}); diff --git a/examples/chat/angular/src/app/itinerary-panel.component.ts b/examples/chat/angular/src/app/itinerary-panel.component.ts new file mode 100644 index 000000000..ef3a4ec29 --- /dev/null +++ b/examples/chat/angular/src/app/itinerary-panel.component.ts @@ -0,0 +1,533 @@ +// SPDX-License-Identifier: MIT +import { ChangeDetectionStrategy, Component, computed, inject, signal } from '@angular/core'; +import { CdkDragDrop, DragDropModule } from '@angular/cdk/drag-drop'; +import { injectAgent } from '@threadplane/langgraph'; +import { DEMO_AGENT_REF } from './shell/agent-ref'; +import { ItineraryStop, ItineraryStore } from './itinerary-store'; + +@Component({ + selector: 'app-itinerary-panel', + standalone: true, + imports: [DragDropModule], + changeDetection: ChangeDetectionStrategy.OnPush, + host: { + class: 'itin', + role: 'region', + 'aria-label': 'Trip itinerary', + '[class.itin--collapsed]': 'collapsed()', + }, + template: ` +
+

+ Trip itinerary + · {{ totalLabel() }} +

+
+ + +
+ @if (menuOpen()) { + + } +
+ +
+ @for (g of store.days(); track g.day) { +
+
+

Day {{ g.day }}

+ {{ g.stops.length }} stop{{ g.stops.length === 1 ? '' : 's' }} + +
+
    + @for (s of g.stops; track s.id; let i = $index) { +
  • + drag_indicator + {{ i + 1 }} + + {{ s.place }} + @if (s.note) { {{ s.note }} } + + +
  • + } +
+ @if (composer() === g.day) { +
+ +
+ } +
+ } @empty { +
+ +

No trip yet

+

Ask the assistant to plan one — try a suggestion in the chat.

+
+ + +
+
+ } +
+ + @if (showFooterAdd()) { + + } + `, + styles: [ + ` + :host { + display: block; + padding: 16px; + font-size: var(--tplane-chat-font-size-sm); + color: var(--tplane-chat-text); + font-family: var(--tplane-chat-font-family); + position: relative; + } + .itin__head { + display: flex; + align-items: center; + justify-content: space-between; + gap: 8px; + margin-bottom: 16px; + position: relative; + } + .itin__title { + margin: 0; + font-size: 1rem; + color: var(--tplane-chat-text); + display: flex; + align-items: baseline; + gap: 6px; + } + .itin__total { + font-size: 0.8rem; + color: var(--tplane-chat-text-muted); + font-weight: normal; + } + .itin__overflow { + font-family: 'Material Symbols Outlined', sans-serif; + font-size: 18px; + background: transparent; + border: none; + color: var(--tplane-chat-text-muted); + cursor: pointer; + padding: 4px; + border-radius: var(--tplane-chat-radius-card); + line-height: 1; + } + .itin__overflow:hover { + background: var(--tplane-chat-surface-alt); + color: var(--tplane-chat-text); + } + .itin__menu { + position: absolute; + top: 100%; + right: 0; + background: var(--tplane-chat-bg); + border: 1px solid var(--tplane-chat-separator); + border-radius: var(--tplane-chat-radius-card); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08); + z-index: 10; + min-width: 160px; + } + .itin__menu-item { + display: block; + width: 100%; + text-align: left; + background: transparent; + border: none; + color: var(--tplane-chat-text); + padding: 8px 12px; + cursor: pointer; + font: inherit; + } + .itin__menu-item:hover { + background: var(--tplane-chat-surface-alt); + } + .itin__day { + margin-bottom: 14px; + } + .itin__day-head { + display: flex; + align-items: center; + gap: 8px; + margin-bottom: 6px; + } + .itin__day-title { + margin: 0; + font-size: 0.85rem; + font-weight: 600; + color: var(--tplane-chat-text); + } + .itin__day-count { + font-size: 0.75rem; + color: var(--tplane-chat-text-muted); + } + .itin__day-add { + font-family: inherit; + font-size: 0.75rem; + background: transparent; + border: 1px dashed var(--tplane-chat-separator); + color: var(--tplane-chat-text-muted); + border-radius: var(--tplane-chat-radius-card); + padding: 2px 8px; + cursor: pointer; + margin-left: auto; + display: inline-flex; + align-items: center; + gap: 4px; + } + .itin__day-add:hover, .itin__day-add.is-active { + color: var(--tplane-chat-text); + border-color: var(--tplane-chat-text); + } + .itin__icon { + font-family: 'Material Symbols Outlined', sans-serif; + font-size: 16px; + line-height: 1; + vertical-align: -3px; + } + .itin__stops { + list-style: none; + margin: 0; + padding: 0; + display: flex; + flex-direction: column; + gap: 4px; + } + .itin__stop { + display: flex; + align-items: center; + gap: 6px; + padding: 8px 10px; + border: 1px solid var(--tplane-chat-separator); + border-radius: var(--tplane-chat-radius-card); + background: var(--tplane-chat-bg); + transition: box-shadow 200ms ease, transform 200ms ease; + } + .itin__handle { + font-family: 'Material Symbols Outlined', sans-serif; + font-size: 16px; + color: var(--tplane-chat-text-muted); + cursor: grab; + opacity: 0; + transition: opacity 100ms ease; + line-height: 1; + flex: none; + } + .itin__stop:hover .itin__handle { opacity: 1; } + .itin__index { + flex: none; + width: 22px; + height: 22px; + border-radius: 6px; + background: var(--tplane-chat-text); + color: var(--tplane-chat-bg); + display: inline-flex; + align-items: center; + justify-content: center; + font-size: 0.7rem; + font-weight: 600; + } + .itin__place { + flex: 1 1 auto; + min-width: 0; + display: flex; + flex-direction: column; + gap: 1px; + } + .itin__place-name { + color: var(--tplane-chat-text); + font-weight: 500; + } + .itin__note { + color: var(--tplane-chat-text-muted); + font-size: 0.8rem; + } + .itin__remove { + flex: none; + font-family: 'Material Symbols Outlined', sans-serif; + font-size: 16px; + background: transparent; + border: none; + color: var(--tplane-chat-text-muted); + cursor: pointer; + padding: 4px; + line-height: 1; + opacity: 0; + transition: opacity 100ms ease; + border-radius: 4px; + } + .itin__stop:hover .itin__remove { opacity: 0.7; } + .itin__remove:hover { opacity: 1 !important; color: var(--tplane-chat-text); } + .itin__composer { + margin-top: 6px; + } + .itin__composer-input { + width: 100%; + padding: 8px 10px; + border: 1px solid var(--tplane-chat-text); + border-radius: var(--tplane-chat-radius-card); + background: var(--tplane-chat-bg); + color: var(--tplane-chat-text); + font-family: inherit; + font-size: inherit; + box-sizing: border-box; + } + .itin__add-day-btn { + margin-top: 12px; + font-family: inherit; + font-size: 0.8rem; + background: transparent; + border: 1px dashed var(--tplane-chat-separator); + color: var(--tplane-chat-text-muted); + border-radius: var(--tplane-chat-radius-card); + padding: 6px 12px; + cursor: pointer; + width: 100%; + display: inline-flex; + align-items: center; + justify-content: center; + gap: 4px; + } + .itin__add-day-btn:hover { + color: var(--tplane-chat-text); + border-color: var(--tplane-chat-text); + } + .itin__empty { + display: flex; + flex-direction: column; + align-items: center; + text-align: center; + gap: 8px; + padding: 24px 8px; + color: var(--tplane-chat-text-muted); + } + .itin__empty-icon { + font-family: 'Material Symbols Outlined', sans-serif; + font-size: 48px; + color: var(--tplane-chat-text-muted); + line-height: 1; + } + .itin__empty-title { + margin: 0; + font-size: 0.95rem; + color: var(--tplane-chat-text); + font-weight: 500; + } + .itin__empty-sub { + margin: 0; + font-size: 0.8rem; + } + .itin__empty-chips { + display: flex; + flex-wrap: wrap; + gap: 6px; + justify-content: center; + margin-top: 4px; + } + .itin__empty-chip { + font-family: inherit; + font-size: 0.8rem; + background: transparent; + border: 1px solid var(--tplane-chat-separator); + color: var(--tplane-chat-text); + border-radius: 999px; + padding: 4px 12px; + cursor: pointer; + } + .itin__empty-chip:hover { + background: var(--tplane-chat-surface-alt); + border-color: var(--tplane-chat-text); + } + .itin__stop.cdk-drag-preview { + box-shadow: + 0 5px 5px -3px rgba(0, 0, 0, 0.2), + 0 8px 10px 1px rgba(0, 0, 0, 0.14), + 0 3px 14px 2px rgba(0, 0, 0, 0.12); + background: var(--tplane-chat-bg); + } + .itin__stop.cdk-drag-placeholder { + opacity: 0.3; + } + .itin__stops.cdk-drop-list-dragging .itin__stop:not(.cdk-drag-placeholder) { + transition: transform 200ms cubic-bezier(0, 0, 0.2, 1); + } + @keyframes itinPulse { + 0% { box-shadow: 0 0 0 0 var(--tplane-chat-primary); transform: scale(1); } + 20% { box-shadow: 0 0 0 3px color-mix(in srgb, var(--tplane-chat-primary) 50%, transparent); transform: scale(1.015); } + 100% { box-shadow: 0 0 0 0 transparent; transform: scale(1); } + } + .itin__stop--pulse { + animation: itinPulse 1600ms ease-out; + } + @media (prefers-reduced-motion: reduce) { + .itin__stop--pulse { + animation: none; + } + } + .itin__handle.cdk-keyboard-focused, + .itin__handle:focus-visible { + opacity: 1; + outline: 2px solid var(--tplane-chat-text); + outline-offset: 2px; + border-radius: 4px; + } + .itin__head-actions { + display: flex; + align-items: center; + gap: 2px; + } + .itin__collapse { + font-family: 'Material Symbols Outlined', sans-serif; + font-size: 18px; + background: transparent; + border: none; + color: var(--tplane-chat-text-muted); + cursor: pointer; + padding: 4px; + line-height: 1; + border-radius: var(--tplane-chat-radius-card); + } + .itin__collapse:hover { + background: var(--tplane-chat-surface-alt); + color: var(--tplane-chat-text); + } + :host(.itin--collapsed) [cdkDropListGroup], + :host(.itin--collapsed) .itin__add-day-btn { + display: none; + } + :host(.itin--collapsed) .itin__head { + margin-bottom: 0; + } + `, + ], +}) +export class ItineraryPanelComponent { + protected readonly store = inject(ItineraryStore); + protected readonly menuOpen = signal(false); + protected readonly collapsed = signal(false); + protected readonly composer = signal(null); + protected readonly composerText = signal(''); + protected readonly totalLabel = computed(() => { + const n = this.store.stops().length; + return `${n} stop${n === 1 ? '' : 's'}`; + }); + protected readonly showFooterAdd = computed(() => this.store.days().length > 0); + private readonly agent = injectAgent(DEMO_AGENT_REF); + + protected suggestion(prompt: string): void { + void this.agent.submit({ message: prompt }); + } + + protected toggleMenu(): void { + this.menuOpen.update((v) => !v); + } + + protected toggleCollapsed(): void { + this.collapsed.update((v) => !v); + } + + protected reset(): void { + this.store.reset({ source: 'user' }); + this.menuOpen.set(false); + } + + protected openComposer(day: number): void { + this.composer.set(day); + this.composerText.set(''); + } + + protected commitComposer(event: Event, day: number): void { + event.preventDefault(); + const text = this.composerText().trim(); + if (text) { + this.store.add(day, text, undefined, { source: 'user' }); + } + this.composer.set(null); + this.composerText.set(''); + } + + protected addNewDay(): void { + const maxDay = Math.max(0, ...this.store.days().map((g) => g.day)); + this.openComposer(maxDay + 1); + } + + protected remove(id: string): void { + this.store.remove(id, { source: 'user' }); + } + + protected onRowClick(id: string, event: Event): void { + const target = event.target as HTMLElement; + if (target.closest('.itin__handle') || target.closest('.itin__remove')) return; + this.store.focus(id); + } + + protected onDrop(event: CdkDragDrop, toDay: number): void { + const stop = event.item.data as ItineraryStop; + this.store.reorder(stop.id, toDay, event.currentIndex, { source: 'user' }); + } +} diff --git a/examples/chat/angular/src/app/map-canvas.component.ts b/examples/chat/angular/src/app/map-canvas.component.ts new file mode 100644 index 000000000..3a3f39a65 --- /dev/null +++ b/examples/chat/angular/src/app/map-canvas.component.ts @@ -0,0 +1,256 @@ +// SPDX-License-Identifier: MIT +/// +import { + ChangeDetectionStrategy, + Component, + DestroyRef, + ElementRef, + afterNextRender, + computed, + effect, + inject, + signal, + viewChild, + viewChildren, +} from '@angular/core'; +import { GoogleMap, MapInfoWindow, MapAdvancedMarker, MapPolyline } from '@angular/google-maps'; +import { ItineraryStop, ItineraryStore } from './itinerary-store'; +import { computeBounds } from './map-bounds'; +import { GoogleMapsLoader } from './google-maps-loader'; +import { environment } from '../environments/environment'; + +const DAY_COLORS = ['#ef4444', '#3b82f6', '#10b981', '#f59e0b', '#8b5cf6', '#ec4899', '#06b6d4', '#84cc16']; +const PARIS_CENTER: google.maps.LatLngLiteral = { lat: 48.8566, lng: 2.3522 }; + +@Component({ + selector: 'app-map-canvas', + standalone: true, + imports: [GoogleMap, MapInfoWindow, MapAdvancedMarker, MapPolyline], + changeDetection: ChangeDetectionStrategy.OnPush, + template: ` + + @if (loader.loaded()) { + + @for (m of markerViews(); track m.id) { + + } + @for (line of polylines(); track line.day) { + + } + + @if (focused(); as f) { +
+ {{ f.place }} + @if (f.note) { +
{{ f.note }}
+ } + +
+ } +
+
+ } + `, + styles: [ + ` + :host { display: block; width: 100%; height: 100%; } + .info { font-family: var(--tplane-chat-font-family, sans-serif); font-size: 0.85rem; color: #111; } + .info__note { color: #555; margin: 4px 0 8px; } + .info__remove { + font: inherit; cursor: pointer; padding: 4px 10px; + border: 1px solid #ddd; border-radius: 6px; background: #fff; color: #111; + } + .info__remove:hover { background: #f4f4f4; } + `, + ], +}) +export class MapCanvasComponent { + protected readonly store = inject(ItineraryStore); + protected readonly loader = inject(GoogleMapsLoader); + private readonly hostRef = inject>(ElementRef); + private readonly destroyRef = inject(DestroyRef); + protected readonly center = signal(PARIS_CENTER); + protected readonly zoom = signal(12); + // A mapId is REQUIRED for advanced markers; a mapId map ignores inline JSON + // `styles`, so the dark theme is a cloud-based map style tied to this id. + // DEMO_MAP_ID lets a fresh clone run (light map) with no Console setup. + protected readonly mapId = environment.googleMapsMapId || 'DEMO_MAP_ID'; + protected readonly mapOptions: google.maps.MapOptions = { + mapId: this.mapId, + disableDefaultUI: true, + zoomControl: true, + clickableIcons: false, + }; + // AdvancedMarkerElement is NOT clickable by default (unlike the legacy + // Marker) — without gmpClickable it never fires click/gmp-click, so the + // wrapper's (mapClick) output stays silent and the info window can't open. + protected readonly advancedMarkerOptions: google.maps.marker.AdvancedMarkerElementOptions = { + gmpClickable: true, + }; + + private readonly googleMap = viewChild(GoogleMap); + private readonly infoWindow = viewChild(MapInfoWindow); + private readonly markers = viewChildren(MapAdvancedMarker); + + protected readonly stopsWithCoords = computed(() => + this.store.stops().filter((s) => s.lat != null && s.lng != null), + ); + + /** One marker view per coord'd stop. The pin
is built here (not in a + * template method) so it is recreated only when stops change — not on every + * change-detection pass (e.g. focus pans), which would cause flicker. */ + protected readonly markerViews = computed(() => + this.stopsWithCoords().map((s) => ({ + id: s.id, + stop: s, + position: { lat: s.lat!, lng: s.lng! }, + content: this.makePin(s.day), + })), + ); + + protected readonly focused = computed( + () => this.store.stops().find((s) => s.id === this.store.focusedStopId()) ?? null, + ); + + constructor() { + this.loader.ensureLoaded(); + + effect(() => { + const f = this.focused(); + if (!f || f.lat == null || f.lng == null) return; + const idx = this.stopsWithCoords().findIndex((s) => s.id === f.id); + const marker = this.markers()[idx]; + const win = this.infoWindow(); + if (idx >= 0 && marker && win) { + this.center.set({ lat: f.lat, lng: f.lng }); + win.open(marker); + } + }); + + // Frame the map to all stops on structural change (add/remove/geocode). + // Reads googleMap() so it re-runs once the map mounts behind the loader gate. + // Keyed on stopsWithCoords() only — NOT focus — so panning to a focused stop + // and reframing to all stops never fight (they fire on different signals). + effect(() => { + const map = this.googleMap(); + this.stopsWithCoords(); // re-frame on structural change (add/remove/geocode) + if (map) this.frameToBounds(map); // null while is behind the loader gate + }); + + // The map lives in the chat-sidebar's flex content slot, whose width changes + // when the drawer pushes it (and on mode toggles). Google Maps caches its + // viewport size at construction, so without a resize event the tiles render + // grey and fitBounds frames the stale size. Re-sync on every container resize. + afterNextRender(() => { + const ro = new ResizeObserver(() => { + const map = this.googleMap(); + if (!map?.googleMap) return; + google.maps.event.trigger(map.googleMap, 'resize'); + this.frameToBounds(map); + }); + ro.observe(this.hostRef.nativeElement); + this.destroyRef.onDestroy(() => ro.disconnect()); + }); + } + + /** Frame the map to all coord'd stops (>=2: fitBounds; 1: center+zoom; 0: Paris). */ + private frameToBounds(map: GoogleMap): void { + const stops = this.stopsWithCoords(); + if (stops.length === 0) { + this.center.set(PARIS_CENTER); + this.zoom.set(12); + return; + } + if (stops.length === 1) { + this.center.set({ lat: stops[0].lat!, lng: stops[0].lng! }); + this.zoom.set(13); + return; + } + const b = computeBounds(stops); + if (b) map.fitBounds(b, this.fitPadding()); + } + + /** + * fitBounds padding (px per side) that reserves the App-mode panels floating + * over the full-bleed map, so a stop never frames *underneath* them — the + * reported bug was the rightmost marker hiding under the open chat rail. + * + * Measured live (not hardcoded) so it adapts to the chat drawer's open/closed + * state and the responsive panel widths: + * - left = our floating itinerary overlay card's footprint + * - right = the chat sidebar drawer's footprint (the gap its push leaves + * between `.chat-sidebar__content` and the map's right edge) + * Falls back to a uniform base when the panels aren't present (unit tests, + * non-App-mode layouts), preserving the prior behavior. + */ + private fitPadding(): google.maps.Padding { + const BASE = 48; + const GAP = 24; + const pad: google.maps.Padding = { top: BASE, right: BASE, bottom: BASE, left: BASE }; + const mapRect = this.hostRef.nativeElement.getBoundingClientRect(); + if (mapRect.width === 0) return pad; // not laid out (e.g. jsdom) — uniform + + const overlay = document.querySelector('.ag-ui-shell__itinerary-overlay'); + if (overlay) { + const r = overlay.getBoundingClientRect(); + if (r.width > 0) pad.left = Math.max(BASE, Math.round(r.right - mapRect.left + GAP)); + } + const content = document.querySelector('.chat-sidebar__content'); + if (content) { + const occupied = mapRect.right - content.getBoundingClientRect().right; + if (occupied > 1) pad.right = Math.max(BASE, Math.round(occupied + GAP)); + } + return pad; + } + + protected onMarkerClick(s: ItineraryStop): void { + this.store.focus(s.id); + } + + protected removeFocused(): void { + const f = this.focused(); + if (!f) return; + this.store.remove(f.id, { source: 'user' }); + this.store.focus(null); + this.infoWindow()?.close(); + } + + protected readonly polylines = computed(() => { + const byDay = new Map(); + for (const s of this.stopsWithCoords()) byDay.set(s.day, [...(byDay.get(s.day) ?? []), s]); + return [...byDay.entries()] + .filter(([, stops]) => stops.length >= 2) + .map(([day, stops]) => ({ day, path: stops.map((s) => ({ lat: s.lat!, lng: s.lng! })) })); + }); + + private makePin(day: number): HTMLElement { + const el = document.createElement('div'); + el.style.cssText = + 'width:16px;height:16px;border-radius:50%;border:2px solid #fff;' + + `box-shadow:0 1px 3px rgba(0,0,0,.4);background:${DAY_COLORS[(day - 1) % DAY_COLORS.length]};`; + return el; + } + + protected polylineOptions(day: number): google.maps.PolylineOptions { + return { + strokeColor: DAY_COLORS[(day - 1) % DAY_COLORS.length], + strokeOpacity: 0.7, + strokeWeight: 3, + }; + } +} From cc953105533a49f37ab2322a1142721fd1932a67 Mon Sep 17 00:00:00 2001 From: Brian Love Date: Mon, 6 Jul 2026 23:06:11 -0700 Subject: [PATCH 11/23] feat(examples-chat): port itinerary client tools (drop get_itinerary, use demo agent) Copies examples/ag-ui/angular/src/app/client-tools.ts into examples/chat/angular, removing the get_itinerary tool, ITINERARY_AGENT ref, and ItineraryState interface since the chat demo's DEMO_AGENT_REF/DemoState already covers agent typing and the model now sees itinerary state via injected graph-state context instead of a read round-trip. Co-Authored-By: Claude Opus 4.8 --- .../chat/angular/src/app/client-tools.spec.ts | 17 +++++ examples/chat/angular/src/app/client-tools.ts | 69 +++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 examples/chat/angular/src/app/client-tools.spec.ts create mode 100644 examples/chat/angular/src/app/client-tools.ts diff --git a/examples/chat/angular/src/app/client-tools.spec.ts b/examples/chat/angular/src/app/client-tools.spec.ts new file mode 100644 index 000000000..979f38804 --- /dev/null +++ b/examples/chat/angular/src/app/client-tools.spec.ts @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: MIT +import { TestBed } from '@angular/core/testing'; +import { ItineraryStore } from './itinerary-store'; +import { GeocodingService } from './geocoding.service'; +import { itineraryClientTools } from './client-tools'; + +describe('itineraryClientTools (langgraph demo)', () => { + beforeEach(() => TestBed.configureTestingModule({ providers: [ItineraryStore, GeocodingService] })); + + it('exposes mutation tools but NOT get_itinerary', () => { + const registry = TestBed.runInInjectionContext(() => itineraryClientTools()); + const names = Object.keys(registry as Record); + expect(names).toContain('add_stop'); + expect(names).toContain('clear_day'); + expect(names).not.toContain('get_itinerary'); + }); +}); diff --git a/examples/chat/angular/src/app/client-tools.ts b/examples/chat/angular/src/app/client-tools.ts new file mode 100644 index 000000000..b24f9c700 --- /dev/null +++ b/examples/chat/angular/src/app/client-tools.ts @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: MIT +import { inject } from '@angular/core'; +import { tools, action, view, ask, type ClientToolRegistry } from '@threadplane/chat'; +import { z } from 'zod/v4'; +import { ItineraryStore } from './itinerary-store'; +import { GeocodingService } from './geocoding.service'; +import { DayCardComponent, DAY_CARD_SCHEMA } from './day-card.component'; +import { ClearDayConfirmComponent } from './clear-day-confirm.component'; + +/** Schema for the `clear_day` ask tool — exported in case consumers want to + * derive types from it (e.g. `ViewProps`). */ +export const CLEAR_DAY_SCHEMA = z.object({ day: z.number().int().min(1) }); + +/** Client tools over the frontend-owned itinerary. Call inside an injection + * context (e.g. a field initializer in App). The descriptions are the ONLY + * steering the model gets — no system-prompt coaching (by design). */ +export function itineraryClientTools(): ClientToolRegistry { + const store = inject(ItineraryStore); + const geocoding = inject(GeocodingService); + return tools({ + add_stop: action( + 'Add a stop to a day of the trip itinerary. Afterwards, show the updated day with day_card.', + z.object({ day: z.number().int().min(1), place: z.string(), note: z.string().optional() }), + async ({ day, place, note }) => { + const coords = (await geocoding.geocode(place)) ?? undefined; + return { added: store.add(day, place, note, coords ? { coords } : undefined) }; + }, + ), + move_stop: action( + 'Move an existing stop (matched by place name) to another day. Afterwards, show the updated day with day_card.', + z.object({ place: z.string(), toDay: z.number().int().min(1) }), + async ({ place, toDay }) => { + const target = store.stops().find((s) => s.place.toLowerCase() === place.toLowerCase()); + if (!target) { + return { error: `No stop named "${place}" — call get_itinerary to see what exists.` }; + } + const toDayStops = store.stops().filter((s) => s.day === toDay && s.id !== target.id); + store.reorder(target.id, toDay, toDayStops.length); + return { moved: { ...target, day: toDay } }; + }, + ), + reorder_stop: action( + 'Reorder a stop within or across days. Use after the user describes a sequence change (e.g., "put Louvre first", "move Eiffel to day 2 second"). `toIndex` is zero-based within the target day.', + z.object({ + place: z.string(), + toDay: z.number().int().min(1), + toIndex: z.number().int().min(0), + }), + async ({ place, toDay, toIndex }) => { + const target = store.stops().find((s) => s.place.toLowerCase() === place.toLowerCase()); + if (!target) { + return { error: `No stop named "${place}" — call get_itinerary to see what exists.` }; + } + store.reorder(target.id, toDay, toIndex); + return { reordered: { ...target, day: toDay, toIndex } }; + }, + ), + clear_day: ask( + 'Ask the user to confirm clearing every stop on a day, then clear it if they accept.', + CLEAR_DAY_SCHEMA, + ClearDayConfirmComponent, + ), + day_card: view( + "Show the user a visual recap card for one itinerary day. Call it after add_stop or move_stop with the day's full updated place list.", + DAY_CARD_SCHEMA, + DayCardComponent, + ), + }); +} From d5bae8acd11ca1308f12a1322c7c1db8066bdbfe Mon Sep 17 00:00:00 2001 From: Brian Love Date: Tue, 7 Jul 2026 09:50:20 -0700 Subject: [PATCH 12/23] =?UTF-8?q?feat(examples-chat):=20sync=20itinerary?= =?UTF-8?q?=20=E2=80=94=20submit=20state=20+=20value=20hydration=20+=20SDK?= =?UTF-8?q?=20checkpoint=20push?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/chat/angular/src/app/app.config.ts | 5 + .../app/shell/demo-shell.component.spec.ts | 116 +++++++++++++++++- .../src/app/shell/demo-shell.component.ts | 103 +++++++++++++++- 3 files changed, 221 insertions(+), 3 deletions(-) diff --git a/examples/chat/angular/src/app/app.config.ts b/examples/chat/angular/src/app/app.config.ts index d75ac3c38..2aacae82c 100644 --- a/examples/chat/angular/src/app/app.config.ts +++ b/examples/chat/angular/src/app/app.config.ts @@ -5,6 +5,7 @@ import { provideThreadplaneTelemetry } from '@threadplane/telemetry/browser'; import { LANGGRAPH_THREADS_CONFIG, LANGGRAPH_CLIENT_OPTIONS } from '@threadplane/langgraph'; import { provideChat } from '@threadplane/chat'; import { e2eClientOptions } from './shell/e2e-overrides'; +import { ItineraryStore } from './itinerary-store'; import { routes } from './app.routes'; import { environment } from '../environments/environment'; @@ -32,5 +33,9 @@ export const appConfig: ApplicationConfig = { provideChat({ license: environment.license, }), + // App-wide singleton so DemoShell, the itinerary panel, and the map cockpit + // all read/write ONE working copy of the itinerary. Provided at root (not at + // the component) so routed children share the same instance. + ItineraryStore, ], }; diff --git a/examples/chat/angular/src/app/shell/demo-shell.component.spec.ts b/examples/chat/angular/src/app/shell/demo-shell.component.spec.ts index edaea21e5..43600a9e2 100644 --- a/examples/chat/angular/src/app/shell/demo-shell.component.spec.ts +++ b/examples/chat/angular/src/app/shell/demo-shell.component.spec.ts @@ -2,8 +2,16 @@ import { signal } from '@angular/core'; import { describe, it, expect, beforeEach } from 'vitest'; import { TestBed } from '@angular/core/testing'; import { provideRouter, Router, NavigationEnd } from '@angular/router'; -import { LangGraphThreadsAdapter } from '@threadplane/langgraph'; -import { DemoShell } from './demo-shell.component'; +import { + LangGraphThreadsAdapter, + LANGGRAPH_THREADS_CONFIG, + provideAgent, + FakeStreamTransport, + type AgentTransport, +} from '@threadplane/langgraph'; +import { DemoShell, shouldSyncCheckpoint, extractItinerary } from './demo-shell.component'; +import { DEMO_AGENT_REF } from './agent-ref'; +import { ItineraryStore, type ItineraryStop } from '../itinerary-store'; function createThreadsAdapterMock() { const threads = signal([]); @@ -35,6 +43,7 @@ describe('DemoShell — mode signal', () => { TestBed.configureTestingModule({ providers: [ threadsAdapterProvider, + ItineraryStore, provideRouter([ { path: 'embed', component: DemoShell }, { path: 'popup', component: DemoShell }, @@ -77,6 +86,7 @@ describe('DemoShell — toolbar layout', () => { TestBed.configureTestingModule({ providers: [ threadsAdapterProvider, + ItineraryStore, provideRouter([ { path: 'embed', component: DemoShell }, { path: '', pathMatch: 'full', redirectTo: 'embed' }, @@ -93,6 +103,7 @@ describe('DemoShell — toolbar layout', () => { TestBed.configureTestingModule({ providers: [ threadsAdapterProvider, + ItineraryStore, provideRouter([ { path: 'embed', component: DemoShell }, { path: '', pathMatch: 'full', redirectTo: 'embed' }, @@ -116,6 +127,7 @@ describe('DemoShell — toolbar dropdowns use chat-select', () => { TestBed.configureTestingModule({ providers: [ threadsAdapterProvider, + ItineraryStore, provideRouter([ { path: 'embed', component: DemoShell }, { path: '', pathMatch: 'full', redirectTo: 'embed' }, @@ -143,6 +155,7 @@ describe('DemoShell — URL thread sync', () => { TestBed.configureTestingModule({ providers: [ threadsAdapterProvider, + ItineraryStore, provideRouter([ { path: 'embed', component: DemoShell }, { path: 'embed/:threadId', component: DemoShell }, @@ -255,6 +268,7 @@ describe('DemoShell — URL knob hydration', () => { TestBed.configureTestingModule({ providers: [ threadsAdapterProvider, + ItineraryStore, provideRouter([ { path: 'embed', component: DemoShell }, { path: 'embed/:threadId', component: DemoShell }, @@ -372,3 +386,101 @@ describe('DemoShell — URL knob hydration', () => { expect(router.url).toContain('model=gpt-5-nano'); }); }); + +// ── Itinerary ↔ checkpoint sync (Task 9) ──────────────────────────────────── + +/** A FakeStreamTransport that records the payload of the most recent + * submit so a spec can assert the shell's state injection. */ +class CapturingTransport extends FakeStreamTransport { + lastPayload: unknown = undefined; + override async *stream( + assistantId: string, + threadId: string | null, + payload: unknown, + signal: AbortSignal, + options?: Parameters[4], + ) { + this.lastPayload = payload; + yield* super.stream(assistantId, threadId, payload, signal, options); + } +} + +describe('shouldSyncCheckpoint — push-gate predicate', () => { + it('pushes when settled, has a thread, and content changed', () => { + expect(shouldSyncCheckpoint(false, 'thread-1', '[1]', '[0]')).toBe(true); + }); + + it('never pushes while a run is loading (mid-run guard)', () => { + expect(shouldSyncCheckpoint(true, 'thread-1', '[1]', '[0]')).toBe(false); + }); + + it('never pushes without a thread id', () => { + expect(shouldSyncCheckpoint(false, null, '[1]', '[0]')).toBe(false); + }); + + it('skips when the content already matches lastSynced (echo-loop guard)', () => { + expect(shouldSyncCheckpoint(false, 'thread-1', '[1]', '[1]')).toBe(false); + }); +}); + +describe('extractItinerary — value → stops', () => { + it('returns the itinerary array from a state value', () => { + const stops: ItineraryStop[] = [{ id: 'x', day: 1, place: 'Louvre' }]; + expect(extractItinerary({ itinerary: stops })).toEqual(stops); + }); + + it('returns null when no itinerary present', () => { + expect(extractItinerary({ messages: [] })).toBeNull(); + expect(extractItinerary(undefined)).toBeNull(); + expect(extractItinerary({ itinerary: 'not-an-array' })).toBeNull(); + }); +}); + +describe('DemoShell — submit injects itinerary into state', () => { + beforeEach(() => { + localStorage.clear(); + TestBed.configureTestingModule({ + providers: [ + threadsAdapterProvider, + ItineraryStore, + { provide: LANGGRAPH_THREADS_CONFIG, useValue: { apiUrl: 'http://localhost:2024' } }, + provideRouter([ + { path: 'embed', component: DemoShell }, + { path: '', pathMatch: 'full', redirectTo: 'embed' }, + { path: '**', redirectTo: 'embed' }, + ]), + ], + }); + }); + + it('forwards store.stops() as state.itinerary on submit', async () => { + const capturing = new CapturingTransport(); + const store = new ItineraryStore(); + // Override the component-scoped agent so its transport is capturable, + // and share the SAME store instance the shell injects. + TestBed.overrideComponent(DemoShell, { + set: { + providers: [ + { provide: ItineraryStore, useValue: store }, + ...provideAgent(DEMO_AGENT_REF, { + assistantId: 'fake', + transport: capturing, + }), + ], + }, + }); + + const fx = TestBed.createComponent(DemoShell); + fx.detectChanges(); + const shell = fx.componentInstance as unknown as { + agent: { submit: (i: unknown) => Promise }; + }; + + store.add(1, 'Louvre'); + await shell.agent.submit({ messages: [{ role: 'user', content: 'hi' }] }); + + const payload = capturing.lastPayload as { itinerary?: ItineraryStop[] }; + expect(payload.itinerary).toEqual(store.stops()); + expect(payload.itinerary?.[0].place).toBe('Louvre'); + }); +}); diff --git a/examples/chat/angular/src/app/shell/demo-shell.component.ts b/examples/chat/angular/src/app/shell/demo-shell.component.ts index 5ae9debdd..b2f445389 100644 --- a/examples/chat/angular/src/app/shell/demo-shell.component.ts +++ b/examples/chat/angular/src/app/shell/demo-shell.component.ts @@ -13,8 +13,16 @@ import { import { Router, RouterOutlet, NavigationEnd } from '@angular/router'; import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop'; import { filter, map, startWith } from 'rxjs/operators'; -import { injectAgent, provideAgent, LangGraphThreadsAdapter, refreshOnRunEnd } from '@threadplane/langgraph'; +import { + injectAgent, + provideAgent, + LangGraphThreadsAdapter, + LANGGRAPH_THREADS_CONFIG, + createLangGraphClient, + refreshOnRunEnd, +} from '@threadplane/langgraph'; import { DEMO_AGENT_REF, type DemoState } from './agent-ref'; +import { ItineraryStore, type ItineraryStop } from '../itinerary-store'; import { ThreadplaneTelemetryService } from '@threadplane/telemetry/browser'; import { ChatInterruptPanelComponent, @@ -65,6 +73,40 @@ function parseUrl(url: string): { mode: DemoMode; threadId: string | null } { return { mode, threadId }; } +// ── Itinerary ↔ checkpoint sync helpers (Task 9) ──────────────────────────── +// Extracted as pure functions so the sync decisions are unit-testable without +// driving the agent's derived `value()`/`isLoading()` signals (which the fake +// transport harness can't emit). The effects below stay thin wrappers. + +/** + * Decide whether to push the working itinerary to the durable checkpoint. + * Returns true only when a run has SETTLED (not loading), a thread exists, + * and the content actually changed since the last sync. The `json === lastJson` + * check is the echo-loop guard: hydration stamps `lastSyncedItinerary` with the + * incoming server JSON, so the re-fired push effect sees "no change" and skips — + * making hydrate→push→hydrate converge immediately. + */ +export function shouldSyncCheckpoint( + isLoading: boolean, + threadId: string | null, + json: string, + lastJson: string, +): boolean { + if (isLoading) return false; + if (!threadId) return false; + return json !== lastJson; +} + +/** Pull the itinerary array out of a graph-state `value()` snapshot, or null + * when the state has no (well-formed) itinerary to hydrate from. */ +export function extractItinerary(value: unknown): ItineraryStop[] | null { + if (value && typeof value === 'object') { + const itin = (value as { itinerary?: unknown }).itinerary; + if (Array.isArray(itin)) return itin as ItineraryStop[]; + } + return null; +} + @Component({ selector: 'demo-shell', standalone: true, @@ -115,6 +157,21 @@ export class DemoShell { protected readonly projectsSvc = inject(ProjectsService); private readonly telemetry = inject(ThreadplaneTelemetryService); + /** Shared working copy of the itinerary — an app-wide singleton (provided in + * app.config.ts) so this shell, the panel, and the map read/write ONE store. */ + protected readonly itinerary = inject(ItineraryStore); + + /** Out-of-band SDK client used to push the working itinerary to the durable + * checkpoint (`threads.updateState`) between runs. `LANGGRAPH_THREADS_CONFIG` + * is optional so knob/routing unit tests that don't provide it still run. */ + private readonly lgClient = createLangGraphClient( + inject(LANGGRAPH_THREADS_CONFIG, { optional: true })?.apiUrl ?? environment.langGraphApiUrl, + ); + + /** JSON of the last itinerary we synced (either pushed OR hydrated). Breaks + * the hydrate→push→hydrate echo loop — see `shouldSyncCheckpoint`. */ + private lastSyncedItinerary = ''; + constructor() { // Reflect the chosen theme onto so the // global stylesheet's scoped --a2ui-* overrides activate. Runs on @@ -180,6 +237,49 @@ export class DemoShell { // needing a manual thread switch or reload. refreshOnRunEnd(this.agent, () => this.threadsSvc.refresh()); + // ── Itinerary ↔ checkpoint sync (Task 9) ──────────────────────────────── + // The checkpoint (per-thread graph state) is the durable record; the + // ItineraryStore is the live working copy. We sync client-authoritatively. + + // (2) Hydrate the store from the checkpoint on reload / thread switch. + // Reads the agent's graph-state value(); when it carries an itinerary + // array, replaces the working copy. Stamps lastSyncedItinerary with the + // incoming JSON so the push effect below sees "no change" and skips — + // this is the other half of the echo-loop guard. + effect(() => { + const incoming = extractItinerary(this.agent.value()); + if (incoming === null) return; + const json = JSON.stringify(incoming); + if (json === this.lastSyncedItinerary) return; + this.lastSyncedItinerary = json; + this.itinerary.hydrate(incoming); + }); + + // (3) Push the working copy to the checkpoint at run-settle and on user + // edits between runs. Run-gated (never mid-run) + debounced (~500ms). + // Depends on stops(), isLoading() (so it re-fires when a run SETTLES), and + // threadIdState(). Errors are swallowed — this is a best-effort sync. + effect((onCleanup) => { + const stops = this.itinerary.stops(); + const isLoading = this.agent.isLoading(); + const tid = threadIdState(); + const json = JSON.stringify(stops); + if (!shouldSyncCheckpoint(isLoading, tid, json, this.lastSyncedItinerary)) return; + const timer = setTimeout(() => { + void (async () => { + try { + await this.lgClient.threads.updateState(tid as string, { + values: { itinerary: stops }, + }); + this.lastSyncedItinerary = json; + } catch { + // best-effort: a failed checkpoint push must not break the UI. + } + })(); + }, 500); + onCleanup(() => clearTimeout(timer)); + }); + if (typeof window !== 'undefined') { const onResize = () => this.viewportWidth.set(window.innerWidth); window.addEventListener('resize', onResize); @@ -415,6 +515,7 @@ export class DemoShell { model: this.model(), reasoning_effort: this.effort(), gen_ui_mode: this.genUiMode(), + itinerary: this.itinerary.stops(), }, }, opts, From 2ab792e0ac9b6bb217c871ba939e6bf9a69732de Mon Sep 17 00:00:00 2001 From: Brian Love Date: Tue, 7 Jul 2026 09:53:04 -0700 Subject: [PATCH 13/23] fix(examples-chat): import vitest globals in client-tools.spec (build compiles specs) tsconfig.app.json includes src/**/*.ts, so spec files are type-checked in the AOT build; the T8 client-tools.spec relied on ambient describe/it/expect and broke the build. Import them explicitly, matching sibling specs. --- examples/chat/angular/src/app/client-tools.spec.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/chat/angular/src/app/client-tools.spec.ts b/examples/chat/angular/src/app/client-tools.spec.ts index 979f38804..1d12359d7 100644 --- a/examples/chat/angular/src/app/client-tools.spec.ts +++ b/examples/chat/angular/src/app/client-tools.spec.ts @@ -1,4 +1,5 @@ // SPDX-License-Identifier: MIT +import { describe, it, expect, beforeEach } from 'vitest'; import { TestBed } from '@angular/core/testing'; import { ItineraryStore } from './itinerary-store'; import { GeocodingService } from './geocoding.service'; From 62b456f77884cbc50e4ea2c746f3a5ad6bb4f55f Mon Sep 17 00:00:00 2001 From: Brian Love Date: Tue, 7 Jul 2026 09:57:43 -0700 Subject: [PATCH 14/23] =?UTF-8?q?feat(examples-chat):=20App-mode=20toggle?= =?UTF-8?q?=20+=20map-compatible=20routing=20(embed=E2=86=94sidebar=20coer?= =?UTF-8?q?cion)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 --- .../src/app/shell/demo-shell.component.css | 41 ++++++++++ .../src/app/shell/demo-shell.component.html | 14 ++++ .../app/shell/demo-shell.component.spec.ts | 81 +++++++++++++++++++ .../src/app/shell/demo-shell.component.ts | 78 ++++++++++++++++++ .../app/shell/palette-persistence.service.ts | 2 + 5 files changed, 216 insertions(+) diff --git a/examples/chat/angular/src/app/shell/demo-shell.component.css b/examples/chat/angular/src/app/shell/demo-shell.component.css index 36b56921a..24c9344b5 100644 --- a/examples/chat/angular/src/app/shell/demo-shell.component.css +++ b/examples/chat/angular/src/app/shell/demo-shell.component.css @@ -177,3 +177,44 @@ .demo-shell ::ng-deep .chat-sidebar__panel { top: 0; } + +/* App-mode toggle: pill button in the toolbar. Enabled only when a Google + * Maps key is configured (App mode renders the map cockpit). */ +.demo-shell__app-toggle { + display: inline-flex; + align-items: center; + gap: 6px; + padding: 4px 10px 4px 8px; + border-radius: 999px; + border: 1px solid var(--tplane-chat-separator); + background: transparent; + color: var(--tplane-chat-text-muted); + cursor: pointer; + font: inherit; + font-size: var(--tplane-chat-font-size-sm); + flex: 0 0 auto; +} +.demo-shell__app-toggle:disabled { + opacity: 0.4; + cursor: not-allowed; +} +.demo-shell__app-toggle.is-on { + color: var(--tplane-chat-on-primary); + background: var(--tplane-chat-primary); + border-color: var(--tplane-chat-primary); +} +.demo-shell__app-toggle-icon { + font-family: 'Material Symbols Outlined', sans-serif; + font-size: 16px; + line-height: 1; +} +.demo-shell__app-toggle-thumb { + display: inline-block; + width: 8px; + height: 8px; + border-radius: 50%; + background: var(--tplane-chat-text-muted); +} +.demo-shell__app-toggle.is-on .demo-shell__app-toggle-thumb { + background: var(--tplane-chat-on-primary); +} diff --git a/examples/chat/angular/src/app/shell/demo-shell.component.html b/examples/chat/angular/src/app/shell/demo-shell.component.html index 721b3dc45..5d3dd7134 100644 --- a/examples/chat/angular/src/app/shell/demo-shell.component.html +++ b/examples/chat/angular/src/app/shell/demo-shell.component.html @@ -21,6 +21,20 @@ }
+ +
{ }); }); +describe('DemoShell — App mode routing', () => { + beforeEach(() => { + localStorage.clear(); + TestBed.configureTestingModule({ + providers: [ + threadsAdapterProvider, + ItineraryStore, + provideRouter([ + { path: 'embed', component: DemoShell }, + { path: 'popup', component: DemoShell }, + { path: 'sidebar', component: DemoShell }, + { path: '', pathMatch: 'full', redirectTo: 'embed' }, + { path: '**', redirectTo: 'embed' }, + ]), + ], + }); + }); + + it('coerces embed → sidebar when App mode turns on', async () => { + const router = TestBed.inject(Router); + await router.navigateByUrl('/embed'); + const fx = TestBed.createComponent(DemoShell); + fx.detectChanges(); + + const cmp = fx.componentInstance as unknown as { + appMode: () => 'on' | 'off'; + onAppModeChange(v: 'on' | 'off'): void; + }; + expect(cmp.appMode()).toBe('off'); + + cmp.onAppModeChange('on'); + fx.detectChanges(); + await new Promise((resolve) => setTimeout(resolve, 0)); + + expect(cmp.appMode()).toBe('on'); + expect(router.url).toContain('/sidebar'); + }); + + it('turning App mode off keeps the current route', async () => { + const router = TestBed.inject(Router); + await router.navigateByUrl('/sidebar'); + const fx = TestBed.createComponent(DemoShell); + fx.detectChanges(); + + const cmp = fx.componentInstance as unknown as { + appMode: { (): 'on' | 'off'; set(v: 'on' | 'off'): void }; + onAppModeChange(v: 'on' | 'off'): void; + }; + cmp.appMode.set('on'); + fx.detectChanges(); + + cmp.onAppModeChange('off'); + fx.detectChanges(); + await new Promise((resolve) => setTimeout(resolve, 0)); + + expect(cmp.appMode()).toBe('off'); + expect(router.url).toContain('/sidebar'); + expect(router.url).not.toContain('/embed'); + }); + + it('selecting embed while App mode on turns App mode off', async () => { + const router = TestBed.inject(Router); + await router.navigateByUrl('/sidebar'); + const fx = TestBed.createComponent(DemoShell); + fx.detectChanges(); + + const cmp = fx.componentInstance as unknown as { + appMode: { (): 'on' | 'off'; set(v: 'on' | 'off'): void }; + onModeChange(next: string): void; + }; + cmp.appMode.set('on'); + fx.detectChanges(); + + cmp.onModeChange('embed'); + fx.detectChanges(); + await new Promise((resolve) => setTimeout(resolve, 0)); + + expect(cmp.appMode()).toBe('off'); + }); +}); + // ── Itinerary ↔ checkpoint sync (Task 9) ──────────────────────────────────── /** A FakeStreamTransport that records the payload of the most recent diff --git a/examples/chat/angular/src/app/shell/demo-shell.component.ts b/examples/chat/angular/src/app/shell/demo-shell.component.ts index b2f445389..fd863241d 100644 --- a/examples/chat/angular/src/app/shell/demo-shell.component.ts +++ b/examples/chat/angular/src/app/shell/demo-shell.component.ts @@ -310,6 +310,38 @@ export class DemoShell { protected readonly mode = computed(() => this.urlState().mode); + /** Whether the Google Maps key is configured — App mode needs the map, + * so the toggle is disabled without it. */ + readonly hasMapsKey = (environment.googleMapsApiKey as string).length > 0; + + /** App mode: a presentational layer valid only in popup/sidebar (embed's + * full-bleed chat would cover the map). Persisted across reloads and + * mirrored to the `appmode` query param so shared links restore it. */ + readonly appMode = signal<'on' | 'off'>(this.initialAppMode()); + + /** Mode parsed from the REAL browser path. Available immediately at + * bootstrap (unlike router.url, which reads '/' before the initial + * navigation settles), so App mode restores against the right route. */ + private locationMode(): DemoMode { + const path = this.document.defaultView?.location.pathname ?? ''; + const seg = path.split('/').filter(Boolean)[0]; + return (MODES as readonly string[]).includes(seg) ? (seg as DemoMode) : 'embed'; + } + + /** App mode persists across reloads, but it can only run in popup/sidebar — + * embed is full-chat with no background for the map. Reads the `appmode` + * query param from the real browser URL (available at bootstrap, unlike + * ActivatedRoute), falling back to persistence. Starts off when the value + * isn't 'on' OR the current route is embed (e.g. a hand-typed + * /embed?appmode=on). */ + private initialAppMode(): 'on' | 'off' { + const search = this.document.defaultView?.location.search ?? ''; + const raw = (new URLSearchParams(search).get('appmode') ?? + this.persistence.read('appMode')) as 'on' | 'off' | null; + if (raw !== 'on') return 'off'; + return this.locationMode() === 'embed' ? 'off' : 'on'; + } + /** * Source of truth for the model picker. The shell owns it; the * patched submit injects it into state on every send. @@ -528,6 +560,13 @@ export class DemoShell { protected readonly _demoState: DemoState = this.agent.value(); protected onModeChange(next: DemoMode | string): void { + // Embed can't coexist with App mode (its full-bleed chat covers the + // map), so selecting Embed while App mode is on turns App mode off. + // Popup and Sidebar layer over the map, so they leave App mode alone. + if (next === 'embed' && this.appMode() === 'on') { + this.appMode.set('off'); + this.persistence.write('appMode', 'off'); + } // Preserve the active thread across mode switches: /embed/abc → // /popup/abc keeps the conversation visible in the new chrome. // Preserve query params so knob state survives the mode hop. @@ -538,6 +577,45 @@ export class DemoShell { ); } + /** + * Toggle App mode. Enabling it needs a background area for the map — + * embed has none, so it coerces to the sidebar cockpit; popup/sidebar + * keep their current presentation. Unlike ag-ui-shell (which has a + * knob→URL effect that resolves routing), demo-shell is URL-as-truth, + * so this handler both navigates AND writes `appmode` to the query + * itself (merging so knob params survive). + */ + onAppModeChange(v: 'on' | 'off'): void { + this.persistence.write('appMode', v); + if (v === 'on' && this.mode() === 'embed') { + // Navigate to the sidebar cockpit first (preserving query so the + // active thread + knobs survive), then flip the signal + stamp + // appmode=on into the URL. + const id = this.threadIdSignal(); + void this.router + .navigate(id ? ['/', 'sidebar', id] : ['/', 'sidebar'], { + queryParamsHandling: 'preserve', + }) + .then(() => { + this.appMode.set('on'); + void this.router.navigate([], { + queryParams: { appmode: 'on' }, + queryParamsHandling: 'merge', + replaceUrl: true, + }); + }); + return; + } + // popup/sidebar (or turning off): keep the current route, just update + // the appmode query param. 'off' → null drops it from the URL. + this.appMode.set(v); + void this.router.navigate([], { + queryParams: { appmode: v === 'off' ? null : 'on' }, + queryParamsHandling: 'merge', + replaceUrl: true, + }); + } + /** Build the full knob → URL-value mapping. Default values become * null so Angular's router drops them from the resulting URL when * used with queryParamsHandling: 'merge'. */ diff --git a/examples/chat/angular/src/app/shell/palette-persistence.service.ts b/examples/chat/angular/src/app/shell/palette-persistence.service.ts index 3abc1553c..b233be266 100644 --- a/examples/chat/angular/src/app/shell/palette-persistence.service.ts +++ b/examples/chat/angular/src/app/shell/palette-persistence.service.ts @@ -12,6 +12,7 @@ interface PaletteState { sidenavMode?: 'expanded' | 'collapsed' | null; selectedProjectId?: string | null; colorScheme?: 'light' | 'dark' | null; + appMode?: 'on' | 'off' | null; } type PaletteKey = keyof PaletteState; @@ -30,6 +31,7 @@ const ALLOWED = { theme: new Set(['default-dark', 'default-light', 'material-dark', 'material-light']), colorScheme: new Set(['light', 'dark']), sidenavMode: new Set(['expanded', 'collapsed']), + appMode: new Set(['on', 'off']), } as const satisfies Partial>>; type EnumKey = keyof typeof ALLOWED; From 7d941ad687408a625b283be5c68914c0725cd87f Mon Sep 17 00:00:00 2001 From: Brian Love Date: Tue, 7 Jul 2026 10:02:10 -0700 Subject: [PATCH 15/23] =?UTF-8?q?feat(examples-chat):=20App-mode=20cockpit?= =?UTF-8?q?=20layout=20(map=20bg=20+=20itinerary=20overlay=20+=20sidenav?= =?UTF-8?q?=E2=86=92drawer)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 --- .../src/app/shell/demo-shell.component.css | 36 ++++++++++++++++ .../src/app/shell/demo-shell.component.html | 41 +++++++++++++----- .../app/shell/demo-shell.component.spec.ts | 43 +++++++++++++++++++ .../src/app/shell/demo-shell.component.ts | 15 +++++-- 4 files changed, 121 insertions(+), 14 deletions(-) diff --git a/examples/chat/angular/src/app/shell/demo-shell.component.css b/examples/chat/angular/src/app/shell/demo-shell.component.css index 24c9344b5..21ddf0766 100644 --- a/examples/chat/angular/src/app/shell/demo-shell.component.css +++ b/examples/chat/angular/src/app/shell/demo-shell.component.css @@ -218,3 +218,39 @@ .demo-shell__app-toggle.is-on .demo-shell__app-toggle-thumb { background: var(--tplane-chat-on-primary); } + +/* App-mode layout: full-bleed map with the itinerary panel floating as an + * overlay card (top-left) and the chat sidebar alongside via router-outlet. */ +.demo-shell__app-body { + flex: 1 1 auto; + min-height: 0; + position: relative; + display: flex; +} +/* Popup mode only: the map is the full-bleed backdrop with the chat bubble + floating over it. (Sidebar mode renders the map inside the chat-sidebar's + flex content slot instead — see SidebarMode, Task 12 — so it gets its + column there.) */ +.demo-shell__map { + position: absolute; + inset: 0; +} +.demo-shell__itinerary-overlay { + position: absolute; + top: 16px; + left: 16px; + width: min(360px, 36vw); + max-height: calc(100vh - 120px); + overflow-y: auto; + background: var(--tplane-chat-bg); + border: 1px solid var(--tplane-chat-separator); + border-radius: var(--tplane-chat-radius-card); + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.25); + z-index: 10; +} +.demo-shell__app-body .demo-shell__main { + position: relative; + z-index: 5; + flex: 1 1 auto; + min-width: 0; +} diff --git a/examples/chat/angular/src/app/shell/demo-shell.component.html b/examples/chat/angular/src/app/shell/demo-shell.component.html index 5d3dd7134..a44f6e31f 100644 --- a/examples/chat/angular/src/app/shell/demo-shell.component.html +++ b/examples/chat/angular/src/app/shell/demo-shell.component.html @@ -123,17 +123,38 @@ -
- - @if (agent.interrupt && agent.interrupt()) { -
- + @if (appMode() === 'on') { +
+ + @if (mode() === 'popup') { + + } + +
+ + @if (agent.interrupt && agent.interrupt()) { +
+ +
+ }
- } -
+
+ } @else { +
+ + @if (agent.interrupt && agent.interrupt()) { +
+ +
+ } +
+ } { }); }); +describe('DemoShell — App-mode cockpit layout', () => { + beforeEach(() => { + localStorage.clear(); + TestBed.configureTestingModule({ + providers: [ + threadsAdapterProvider, + ItineraryStore, + provideRouter([ + { path: 'embed', component: DemoShell }, + { path: 'popup', component: DemoShell }, + { path: 'sidebar', component: DemoShell }, + { path: '', pathMatch: 'full', redirectTo: 'embed' }, + { path: '**', redirectTo: 'embed' }, + ]), + ], + }); + }); + + it('renders the map backdrop + itinerary overlay and forces drawer sidenav in popup App mode', async () => { + const router = TestBed.inject(Router); + await router.navigateByUrl('/popup'); + const fx = TestBed.createComponent(DemoShell); + fx.detectChanges(); + + const cmp = fx.componentInstance as unknown as { + appMode: { (): 'on' | 'off'; set(v: 'on' | 'off'): void }; + sidenavMode: () => string; + }; + + cmp.appMode.set('on'); + fx.detectChanges(); + + // App mode collapses the sidenav to its hamburger drawer. + expect(cmp.sidenavMode()).toBe('drawer'); + + // Popup App mode renders the full-bleed map backdrop + floating itinerary. + const el = fx.nativeElement as HTMLElement; + expect(el.querySelector('.demo-shell__app-body')).toBeTruthy(); + expect(el.querySelector('app-map-canvas')).toBeTruthy(); + expect(el.querySelector('app-itinerary-panel')).toBeTruthy(); + }); +}); + // ── Itinerary ↔ checkpoint sync (Task 9) ──────────────────────────────────── /** A FakeStreamTransport that records the payload of the most recent diff --git a/examples/chat/angular/src/app/shell/demo-shell.component.ts b/examples/chat/angular/src/app/shell/demo-shell.component.ts index fd863241d..a35bbe785 100644 --- a/examples/chat/angular/src/app/shell/demo-shell.component.ts +++ b/examples/chat/angular/src/app/shell/demo-shell.component.ts @@ -41,6 +41,8 @@ import { } from '@threadplane/chat'; import { PalettePersistence } from './palette-persistence.service'; import { ProjectsService } from './projects.service'; +import { MapCanvasComponent } from '../map-canvas.component'; +import { ItineraryPanelComponent } from '../itinerary-panel.component'; import { DEMO_AGENT } from './shell-tokens'; import { createCanonicalDemoRuntimeTelemetrySink } from './runtime-telemetry'; import { environment } from '../../environments/environment'; @@ -117,6 +119,8 @@ export function extractItinerary(value: unknown): ItineraryStop[] | null { ChatSidenavScrimComponent, ChatHistorySearchPaletteComponent, ChatSelectComponent, + MapCanvasComponent, + ItineraryPanelComponent, ], changeDetection: ChangeDetectionStrategy.OnPush, templateUrl: './demo-shell.component.html', @@ -402,10 +406,13 @@ export class DemoShell { (this.persistence.read('sidenavMode') as 'expanded' | 'collapsed' | null) ?? 'expanded', ); - /** Computed sidenav mode: viewport forces drawer below 768px, else user preference. */ - protected readonly sidenavMode = computed(() => - this.viewportWidth() >= 768 ? this.storedDesktopMode() : 'drawer', - ); + /** Computed sidenav mode: App mode forces drawer (the cockpit reclaims the + * full width for the map + overlay), then viewport forces drawer below + * 768px, else user preference. */ + protected readonly sidenavMode = computed(() => { + if (this.appMode() === 'on') return 'drawer'; + return this.viewportWidth() >= 768 ? this.storedDesktopMode() : 'drawer'; + }); /** Active threads filtered by the selected project (or all when none selected). */ protected readonly visibleThreads = computed(() => { From 77ababf3fc5a1689b9a990865f76ba862c6de644 Mon Sep 17 00:00:00 2001 From: Brian Love Date: Tue, 7 Jul 2026 10:08:10 -0700 Subject: [PATCH 16/23] feat(examples-chat): wire client tools + cockpit into modes; context-aware welcome suggestions Co-Authored-By: Claude Opus 4.8 --- .../chat/angular/public/app-mode-preview.jpg | Bin 0 -> 366429 bytes examples/chat/angular/src/app/app.config.ts | 12 +- .../modes/app-mode-promo.component.spec.ts | 39 ++++++ .../src/app/modes/app-mode-promo.component.ts | 123 ++++++++++++++++++ .../src/app/modes/embed-mode.component.ts | 3 +- .../src/app/modes/popup-mode.component.ts | 21 ++- .../src/app/modes/sidebar-mode.component.ts | 31 +++-- .../welcome-suggestions.component.spec.ts | 23 +++- .../modes/welcome-suggestions.component.ts | 29 +++-- .../src/app/modes/welcome-suggestions.ts | 49 +++++++ .../src/app/shell/demo-shell.component.ts | 6 + 11 files changed, 304 insertions(+), 32 deletions(-) create mode 100644 examples/chat/angular/public/app-mode-preview.jpg create mode 100644 examples/chat/angular/src/app/modes/app-mode-promo.component.spec.ts create mode 100644 examples/chat/angular/src/app/modes/app-mode-promo.component.ts diff --git a/examples/chat/angular/public/app-mode-preview.jpg b/examples/chat/angular/public/app-mode-preview.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b2f000ff0c2d7212b5f8922430f9dd9712d5c2b5 GIT binary patch literal 366429 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%0AF)7iT?nOLI={lOa!?hQg+hc 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%0Do9!f$ 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�E9vI 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Π%pY49fj_7$u3py(gz74`%ThoNe~yi6fc%^ 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�juw$z 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 literal 0 HcmV?d00001 diff --git a/examples/chat/angular/src/app/app.config.ts b/examples/chat/angular/src/app/app.config.ts index 2aacae82c..b1103d0c6 100644 --- a/examples/chat/angular/src/app/app.config.ts +++ b/examples/chat/angular/src/app/app.config.ts @@ -1,11 +1,18 @@ // SPDX-License-Identifier: MIT -import { ApplicationConfig, provideBrowserGlobalErrorListeners, provideZonelessChangeDetection } from '@angular/core'; +import { + ApplicationConfig, + inject, + provideBrowserGlobalErrorListeners, + provideEnvironmentInitializer, + provideZonelessChangeDetection, +} from '@angular/core'; import { provideRouter, withComponentInputBinding } from '@angular/router'; import { provideThreadplaneTelemetry } from '@threadplane/telemetry/browser'; import { LANGGRAPH_THREADS_CONFIG, LANGGRAPH_CLIENT_OPTIONS } from '@threadplane/langgraph'; import { provideChat } from '@threadplane/chat'; import { e2eClientOptions } from './shell/e2e-overrides'; import { ItineraryStore } from './itinerary-store'; +import { GoogleMapsLoader } from './google-maps-loader'; import { routes } from './app.routes'; import { environment } from '../environments/environment'; @@ -37,5 +44,8 @@ export const appConfig: ApplicationConfig = { // all read/write ONE working copy of the itinerary. Provided at root (not at // the component) so routed children share the same instance. ItineraryStore, + // Eagerly kick off the Google Maps JS API load at bootstrap so the map + // canvas can mount as soon as App mode turns on (no per-component wait). + provideEnvironmentInitializer(() => inject(GoogleMapsLoader).ensureLoaded()), ], }; diff --git a/examples/chat/angular/src/app/modes/app-mode-promo.component.spec.ts b/examples/chat/angular/src/app/modes/app-mode-promo.component.spec.ts new file mode 100644 index 000000000..860a73c34 --- /dev/null +++ b/examples/chat/angular/src/app/modes/app-mode-promo.component.spec.ts @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: MIT +import { describe, it, expect } from 'vitest'; +import { TestBed } from '@angular/core/testing'; +import { AppModePromoComponent } from './app-mode-promo.component'; + +function setup(hasMapsKey: boolean) { + TestBed.configureTestingModule({ imports: [AppModePromoComponent] }); + const fixture = TestBed.createComponent(AppModePromoComponent); + fixture.componentRef.setInput('hasMapsKey', hasMapsKey); + fixture.detectChanges(); + return fixture; +} + +describe('AppModePromoComponent', () => { + it('renders the headline, four capability pills, and the CTA', () => { + const el: HTMLElement = setup(true).nativeElement; + expect(el.textContent).toContain('See your trip come alive on a live map'); + expect(el.querySelectorAll('.promo__pill').length).toBe(4); + const cta = el.querySelector('.promo__cta') as HTMLButtonElement | null; + expect(cta).toBeTruthy(); + expect(cta!.disabled).toBe(false); + }); + + it('emits enable when the CTA is clicked', () => { + const fixture = setup(true); + let emitted = 0; + fixture.componentInstance.enable.subscribe(() => (emitted += 1)); + (fixture.nativeElement.querySelector('.promo__cta') as HTMLButtonElement).click(); + expect(emitted).toBe(1); + }); + + it('disables the CTA and shows the key note when hasMapsKey is false', () => { + const el: HTMLElement = setup(false).nativeElement; + const cta = el.querySelector('.promo__cta') as HTMLButtonElement | null; + expect(cta!.disabled).toBe(true); + expect(el.textContent).toContain('GOOGLE_MAPS_API_KEY'); + expect(cta!.title).toBe('Set GOOGLE_MAPS_API_KEY to enable'); + }); +}); diff --git a/examples/chat/angular/src/app/modes/app-mode-promo.component.ts b/examples/chat/angular/src/app/modes/app-mode-promo.component.ts new file mode 100644 index 000000000..b4f6a57d1 --- /dev/null +++ b/examples/chat/angular/src/app/modes/app-mode-promo.component.ts @@ -0,0 +1,123 @@ +// SPDX-License-Identifier: MIT +import { ChangeDetectionStrategy, Component, input, output } from '@angular/core'; + +/** + * Marketing hero shown in sidebar mode while App mode is off. Sells the + * App-mode map cockpit and the Threadplane primitives behind it, with a CTA + * that enables App mode. + * + * Isolated contract — no shell coupling: + * - `hasMapsKey`: whether GOOGLE_MAPS_API_KEY is configured (gates the CTA). + * - `enable`: emitted when the user clicks the CTA. + */ +@Component({ + selector: 'app-mode-promo', + standalone: true, + changeDetection: ChangeDetectionStrategy.OnPush, + template: ` +

+ Preview of the App-mode map cockpit +
+
+ + + Built with Threadplane + +

See your trip come alive on a live map

+

A map cockpit where the agent edits your itinerary in real time.

+
    +
  • Client tools
  • +
  • Generative UI
  • +
  • Human-in-the-loop
  • +
  • Shared state
  • +
+
+
+ + @if (!hasMapsKey()) { +

Set GOOGLE_MAPS_API_KEY to enable

+ } +
+
+
+ `, + styles: [` + :host { display: block; width: 100%; } + .promo { + position: relative; + width: min(780px, 100%); + margin: 0 auto; + aspect-ratio: 16 / 10; + border-radius: var(--tplane-chat-radius-card, 12px); + overflow: hidden; + background: #0e1626; + border: 1px solid var(--tplane-chat-separator, rgba(255, 255, 255, 0.12)); + animation: promo-rise 320ms ease both; + } + .promo__img { + position: absolute; inset: 0; + width: 100%; height: 100%; + object-fit: cover; display: block; + } + .promo__caption { + position: absolute; left: 0; right: 0; bottom: 0; + display: flex; flex-wrap: wrap; align-items: center; gap: 16px; + padding: 16px 20px; + background: rgba(8, 15, 28, 0.96); + border-top: 1px solid rgba(255, 255, 255, 0.12); + } + .promo__copy { flex: 1 1 320px; min-width: 0; } + .promo__eyebrow { + display: inline-flex; align-items: center; gap: 6px; + background: rgba(37, 99, 235, 0.18); color: #93b4f5; + font-size: 12px; padding: 3px 10px; border-radius: 8px; margin-bottom: 9px; + } + .promo__title { font-size: 20px; font-weight: 600; color: #f2f5fb; line-height: 1.3; margin: 0 0 4px; } + .promo__subtitle { font-size: 13px; color: #9aa6bd; line-height: 1.5; margin: 0 0 12px; } + .promo__pills { display: flex; flex-wrap: wrap; gap: 8px; list-style: none; margin: 0; padding: 0; } + .promo__pill { + display: inline-flex; align-items: center; gap: 6px; + background: rgba(255, 255, 255, 0.06); border: 1px solid rgba(255, 255, 255, 0.1); + color: #c2cbdc; font-size: 12px; padding: 5px 10px; border-radius: 8px; + } + .promo__action { flex: 0 0 auto; display: flex; flex-direction: column; align-items: flex-start; gap: 6px; } + .promo__cta { + display: inline-flex; align-items: center; gap: 8px; + background: var(--tplane-chat-primary, #2563eb); color: var(--tplane-chat-on-primary, #fff); + border: none; font: inherit; font-size: 14px; font-weight: 600; + padding: 11px 18px; border-radius: 8px; cursor: pointer; + } + .promo__cta:disabled { opacity: 0.5; cursor: not-allowed; } + .promo__cta:focus-visible { outline: 2px solid var(--tplane-chat-text); outline-offset: 2px; } + .promo__cta:hover:not(:disabled) { filter: brightness(1.08); } + .promo__note { font-size: 12px; color: #9aa6bd; margin: 0; } + .promo__note code { font-family: var(--tplane-chat-font-mono, monospace); } + .promo__icon { font-family: 'Material Symbols Outlined', sans-serif; font-size: 18px; line-height: 1; } + .promo__icon--sm { font-size: 15px; } + @keyframes promo-rise { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } } + @media (prefers-reduced-motion: reduce) { .promo { animation: none; } } + `], +}) +export class AppModePromoComponent { + /** Whether GOOGLE_MAPS_API_KEY is configured; gates the CTA. */ + readonly hasMapsKey = input(false); + /** Emitted when the user clicks the "Enable app mode" CTA. */ + readonly enable = output(); +} diff --git a/examples/chat/angular/src/app/modes/embed-mode.component.ts b/examples/chat/angular/src/app/modes/embed-mode.component.ts index 3d10fb88d..6c43525c0 100644 --- a/examples/chat/angular/src/app/modes/embed-mode.component.ts +++ b/examples/chat/angular/src/app/modes/embed-mode.component.ts @@ -13,12 +13,13 @@ import { WelcomeSuggestionsComponent } from './welcome-suggestions.component'; template: ` - + `, styles: [` diff --git a/examples/chat/angular/src/app/modes/popup-mode.component.ts b/examples/chat/angular/src/app/modes/popup-mode.component.ts index 273b0f8f7..4eeb8e1e7 100644 --- a/examples/chat/angular/src/app/modes/popup-mode.component.ts +++ b/examples/chat/angular/src/app/modes/popup-mode.component.ts @@ -4,27 +4,36 @@ import { ChatPopupComponent, a2uiBasicCatalog } from '@threadplane/chat'; import { DemoShell } from '../shell/demo-shell.component'; import { DEMO_AGENT } from '../shell/shell-tokens'; import { WelcomeSuggestionsComponent } from './welcome-suggestions.component'; +import { AppModePromoComponent } from './app-mode-promo.component'; @Component({ selector: 'popup-mode', standalone: true, - imports: [ChatPopupComponent, WelcomeSuggestionsComponent], + imports: [ChatPopupComponent, WelcomeSuggestionsComponent, AppModePromoComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: ` - + `, styles: [` @@ -33,8 +42,6 @@ import { WelcomeSuggestionsComponent } from './welcome-suggestions.component'; display: grid; place-items: center; height: 100%; - color: #8a92a3; - font-size: 14px; } `], }) diff --git a/examples/chat/angular/src/app/modes/sidebar-mode.component.ts b/examples/chat/angular/src/app/modes/sidebar-mode.component.ts index a58c3481c..233ba1ae7 100644 --- a/examples/chat/angular/src/app/modes/sidebar-mode.component.ts +++ b/examples/chat/angular/src/app/modes/sidebar-mode.component.ts @@ -3,16 +3,19 @@ import { Component, ChangeDetectionStrategy, inject } from '@angular/core'; import { ChatSidebarComponent, a2uiBasicCatalog } from '@threadplane/chat'; import { DemoShell } from '../shell/demo-shell.component'; import { DEMO_AGENT } from '../shell/shell-tokens'; +import { MapCanvasComponent } from '../map-canvas.component'; +import { AppModePromoComponent } from './app-mode-promo.component'; import { WelcomeSuggestionsComponent } from './welcome-suggestions.component'; @Component({ selector: 'sidebar-mode', standalone: true, - imports: [ChatSidebarComponent, WelcomeSuggestionsComponent], + imports: [ChatSidebarComponent, MapCanvasComponent, AppModePromoComponent, WelcomeSuggestionsComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: ` {{ shell.currentThreadTitle() }} - - + + @if (shell.appMode() === 'on') { + + } @else { + + } + `, styles: [` :host { display: block; flex: 1; min-height: 0; position: relative; } + /* The map fills the chat-sidebar content slot (which is flex:1 at threaded + * height); [pushContent] applies the right-margin push for the open drawer. */ + .sidebar-mode__map { display: block; height: 100%; } /* Projected into chat-sidebar's default content slot so [pushContent] * applies its right-margin push to this background when the panel * opens. Sized to fill the visible area below the toolbar. */ @@ -39,8 +54,6 @@ import { WelcomeSuggestionsComponent } from './welcome-suggestions.component'; display: grid; place-items: center; height: 100%; - color: #8a92a3; - font-size: 14px; } `], }) diff --git a/examples/chat/angular/src/app/modes/welcome-suggestions.component.spec.ts b/examples/chat/angular/src/app/modes/welcome-suggestions.component.spec.ts index 8437191e2..22670c63c 100644 --- a/examples/chat/angular/src/app/modes/welcome-suggestions.component.spec.ts +++ b/examples/chat/angular/src/app/modes/welcome-suggestions.component.spec.ts @@ -2,7 +2,7 @@ import { describe, it, expect, beforeEach } from 'vitest'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { WelcomeSuggestionsComponent } from './welcome-suggestions.component'; -import { FEATURED_SUGGESTIONS, MORE_SUGGESTIONS } from './welcome-suggestions'; +import { FEATURED_SUGGESTIONS, MORE_SUGGESTIONS, ITINERARY_SUGGESTIONS } from './welcome-suggestions'; describe('WelcomeSuggestionsComponent', () => { let fx: ComponentFixture; @@ -32,8 +32,8 @@ describe('WelcomeSuggestionsComponent', () => { expect(trigger.textContent).toContain('More prompts'); }); - it('merges FEATURED_SUGGESTIONS[1..] + MORE_SUGGESTIONS into dropdown options', () => { - const opts = fx.componentInstance['moreOptions'] as { value: string; label: string }[]; + it('merges FEATURED_SUGGESTIONS[1..] + MORE_SUGGESTIONS into dropdown options (appModeOn=false)', () => { + const opts = fx.componentInstance['moreOptions']() as { value: string; label: string }[]; const expectedLen = FEATURED_SUGGESTIONS.length - 1 + MORE_SUGGESTIONS.length; expect(opts.length).toBe(expectedLen); expect(opts[0].label).toBe(FEATURED_SUGGESTIONS[1].label); @@ -42,6 +42,23 @@ describe('WelcomeSuggestionsComponent', () => { expect(opts[moreStart].label).toBe(MORE_SUGGESTIONS[0].label); }); + it('features the trip-planning starters when appModeOn is true', () => { + fx.componentRef.setInput('appModeOn', true); + fx.detectChanges(); + // Featured chip becomes the first itinerary prompt. + const label = fx.nativeElement.querySelector( + 'chat-welcome-suggestion .chat-welcome-suggestion__label', + ) as HTMLElement; + expect(label.textContent?.trim()).toBe(ITINERARY_SUGGESTIONS[0].label); + // The remaining itinerary prompts lead the "More prompts" set, followed by + // this demo's existing capability prompts (preserved, not replaced). + const opts = fx.componentInstance['moreOptions']() as { value: string; label: string }[]; + expect(opts[0].label).toBe(ITINERARY_SUGGESTIONS[1].label); + const labels = opts.map((o) => o.label); + expect(labels).toContain(FEATURED_SUGGESTIONS[0].label); + expect(labels).toContain(MORE_SUGGESTIONS[0].label); + }); + it('emits (selected) with the featured value when the chip is clicked', () => { let captured: string | null = null; fx.componentInstance.selected.subscribe((v) => (captured = v)); diff --git a/examples/chat/angular/src/app/modes/welcome-suggestions.component.ts b/examples/chat/angular/src/app/modes/welcome-suggestions.component.ts index b6c867e36..d5b508786 100644 --- a/examples/chat/angular/src/app/modes/welcome-suggestions.component.ts +++ b/examples/chat/angular/src/app/modes/welcome-suggestions.component.ts @@ -1,11 +1,11 @@ // SPDX-License-Identifier: MIT -import { ChangeDetectionStrategy, Component, output } from '@angular/core'; +import { ChangeDetectionStrategy, Component, computed, input, output } from '@angular/core'; import { ChatWelcomeSuggestionComponent, ChatSelectComponent, type ChatSelectOption, } from '@threadplane/chat'; -import { FEATURED_SUGGESTIONS, MORE_SUGGESTIONS } from './welcome-suggestions'; +import { suggestionsForAppMode } from './welcome-suggestions'; /** * Demo-side composition that renders the welcome-state suggestion surface @@ -26,13 +26,13 @@ import { FEATURED_SUGGESTIONS, MORE_SUGGESTIONS } from './welcome-suggestions';
(); - protected readonly featuredOne = FEATURED_SUGGESTIONS[0]; - protected readonly moreOptions: readonly ChatSelectOption[] = [ - ...FEATURED_SUGGESTIONS.slice(1), - ...MORE_SUGGESTIONS, - ].map((s) => ({ value: s.value, label: s.label, description: s.description })); + /** + * When true, lead with the trip-planning starters (App mode / map cockpit on + * screen). When false, keep this demo's broad capability prompts (plain chat). + * Passed by each mode from `shell.appMode()`. + */ + readonly appModeOn = input(false); + + private readonly suggestions = computed(() => suggestionsForAppMode(this.appModeOn())); + protected readonly featuredOne = computed(() => this.suggestions().featured); + protected readonly moreOptions = computed(() => + this.suggestions().more.map((s) => ({ value: s.value, label: s.label, description: s.description })), + ); } diff --git a/examples/chat/angular/src/app/modes/welcome-suggestions.ts b/examples/chat/angular/src/app/modes/welcome-suggestions.ts index 0900df128..8af0cf2e4 100644 --- a/examples/chat/angular/src/app/modes/welcome-suggestions.ts +++ b/examples/chat/angular/src/app/modes/welcome-suggestions.ts @@ -141,3 +141,52 @@ export const WELCOME_SUGGESTIONS: readonly WelcomeSuggestion[] = [ ...FEATURED_SUGGESTIONS, ...MORE_SUGGESTIONS, ]; + +/** + * Trip-planning starters featured when App mode is on (the map cockpit is on + * screen) — they seed an itinerary the agent then builds out via the frontend + * client tools, so they match what the user is looking at. Plain chat keeps the + * broad capability prompts above (see `suggestionsForAppMode`). + */ +export const ITINERARY_SUGGESTIONS: readonly WelcomeSuggestion[] = [ + { + label: 'Plan a long weekend in Paris', + value: 'Plan a long weekend in Paris', + description: 'Agent builds a day-by-day itinerary you watch appear on the map.', + }, + { + label: '3 days in Tokyo with great food', + value: '3 days in Tokyo with great food', + description: 'Streams a food-forward trip and plots each stop live.', + }, + { + label: 'A week on the California coast', + value: 'A week on the California coast', + description: 'Lays out a multi-day route the agent edits on the cockpit map.', + }, +]; + +/** + * Pick the featured chip + "More prompts" set for the current context. + * + * - App mode ON (map cockpit visible): feature the trip-planning starters — + * they drive the itinerary panel + map. The broad capability prompts trail. + * - App mode OFF (plain chat): keep this demo's EXISTING capability surface + * (GenUI / streaming / tool-use + citations, then the "More prompts" set). + */ +export function suggestionsForAppMode(appModeOn: boolean): { + readonly featured: WelcomeSuggestion; + readonly more: readonly WelcomeSuggestion[]; +} { + if (appModeOn) { + const [featured, ...restItinerary] = ITINERARY_SUGGESTIONS; + return { + featured, + more: [...restItinerary, ...FEATURED_SUGGESTIONS, ...MORE_SUGGESTIONS], + }; + } + return { + featured: FEATURED_SUGGESTIONS[0], + more: [...FEATURED_SUGGESTIONS.slice(1), ...MORE_SUGGESTIONS], + }; +} diff --git a/examples/chat/angular/src/app/shell/demo-shell.component.ts b/examples/chat/angular/src/app/shell/demo-shell.component.ts index a35bbe785..2926e8f8c 100644 --- a/examples/chat/angular/src/app/shell/demo-shell.component.ts +++ b/examples/chat/angular/src/app/shell/demo-shell.component.ts @@ -23,6 +23,7 @@ import { } from '@threadplane/langgraph'; import { DEMO_AGENT_REF, type DemoState } from './agent-ref'; import { ItineraryStore, type ItineraryStop } from '../itinerary-store'; +import { itineraryClientTools } from '../client-tools'; import { ThreadplaneTelemetryService } from '@threadplane/telemetry/browser'; import { ChatInterruptPanelComponent, @@ -165,6 +166,11 @@ export class DemoShell { * app.config.ts) so this shell, the panel, and the map read/write ONE store. */ protected readonly itinerary = inject(ItineraryStore); + /** Frontend-owned itinerary client tools, forwarded to the chat mode + * components (`[clientTools]`) so the agent can read/mutate the panel. + * Built here (an injection context) since the registry injects the store. */ + readonly clientTools = itineraryClientTools(); + /** Out-of-band SDK client used to push the working itinerary to the durable * checkpoint (`threads.updateState`) between runs. `LANGGRAPH_THREADS_CONFIG` * is optional so knob/routing unit tests that don't provide it still run. */ From c81c7b874c0fd28bc9d66e49c78fac6fb8875277 Mon Sep 17 00:00:00 2001 From: Brian Love Date: Tue, 7 Jul 2026 10:10:12 -0700 Subject: [PATCH 17/23] fix(examples-chat): drop dangling get_itinerary reference in client-tool error strings get_itinerary was removed (the model sees the itinerary via injected graph context); the move_stop/reorder_stop 'not found' errors no longer point at a nonexistent tool. --- examples/chat/angular/src/app/client-tools.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/chat/angular/src/app/client-tools.ts b/examples/chat/angular/src/app/client-tools.ts index b24f9c700..3c8a0f065 100644 --- a/examples/chat/angular/src/app/client-tools.ts +++ b/examples/chat/angular/src/app/client-tools.ts @@ -32,7 +32,7 @@ export function itineraryClientTools(): ClientToolRegistry { async ({ place, toDay }) => { const target = store.stops().find((s) => s.place.toLowerCase() === place.toLowerCase()); if (!target) { - return { error: `No stop named "${place}" — call get_itinerary to see what exists.` }; + return { error: `No stop named "${place}" — check the current itinerary.` }; } const toDayStops = store.stops().filter((s) => s.day === toDay && s.id !== target.id); store.reorder(target.id, toDay, toDayStops.length); @@ -49,7 +49,7 @@ export function itineraryClientTools(): ClientToolRegistry { async ({ place, toDay, toIndex }) => { const target = store.stops().find((s) => s.place.toLowerCase() === place.toLowerCase()); if (!target) { - return { error: `No stop named "${place}" — call get_itinerary to see what exists.` }; + return { error: `No stop named "${place}" — check the current itinerary.` }; } store.reorder(target.id, toDay, toIndex); return { reordered: { ...target, day: toDay, toIndex } }; From 6318ac37e481a178e988a3d946c10770b825e65c Mon Sep 17 00:00:00 2001 From: Brian Love Date: Tue, 7 Jul 2026 10:13:12 -0700 Subject: [PATCH 18/23] test(examples-chat): e2e App-mode cockpit (empty state + embed coercion) --- .../angular/e2e/app-mode-itinerary.spec.ts | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 examples/chat/angular/e2e/app-mode-itinerary.spec.ts diff --git a/examples/chat/angular/e2e/app-mode-itinerary.spec.ts b/examples/chat/angular/e2e/app-mode-itinerary.spec.ts new file mode 100644 index 000000000..c6c5c3660 --- /dev/null +++ b/examples/chat/angular/e2e/app-mode-itinerary.spec.ts @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: MIT +// App-mode itinerary cockpit — structural e2e. These assert layout/DOM, NOT +// map tiles (the WebGL/vector map does not render reliably in the automated +// browser, and the bundle is keyless in CI). App mode is reached via the +// URL (`?appmode=on`), which is honored regardless of the Maps key, so these +// run in keyless CI. +import { test, expect } from '@playwright/test'; +import { openDemo } from './test-helpers'; + +test.describe('App mode — itinerary cockpit', () => { + test('shows the cockpit with an empty prompt-to-plan state', async ({ page }) => { + await openDemo(page, '/sidebar?appmode=on'); + + // The map canvas (in the sidebar content slot) and the floating itinerary + // overlay both mount in App mode. + await expect(page.locator('app-map-canvas')).toBeAttached(); + await expect(page.locator('app-itinerary-panel')).toBeVisible(); + + // Empty start (no seed) → the panel invites the user to ask for a plan. + await expect(page.locator('app-itinerary-panel')).toContainText(/plan/i); + + // Layout ①: the thread sidenav collapses to the hamburger drawer in App mode. + await expect(page.locator('.demo-shell__hamburger')).toBeVisible(); + }); + + test('selecting Embed turns App mode off (coercion)', async ({ page }) => { + await openDemo(page, '/sidebar?appmode=on'); + await expect(page.locator('app-map-canvas')).toBeAttached(); + + await page.getByRole('button', { name: 'Embed', exact: true }).click(); + + // Embed can't coexist with the map → route drops to /embed and the cockpit + // tears down. + await expect(page).toHaveURL(/\/embed/); + await expect(page.locator('app-map-canvas')).toHaveCount(0); + await expect(page.locator('app-itinerary-panel')).toHaveCount(0); + }); +}); From f3f29edea718bc0f5c3b5a062bbdc98163b77a0a Mon Sep 17 00:00:00 2001 From: Brian Love Date: Tue, 7 Jul 2026 10:29:00 -0700 Subject: [PATCH 19/23] fix(examples-chat): reliably persist itinerary to checkpoint (retry mid-run 409) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The live gate caught that reload lost the trip: the client-tool resume loop keeps the agent loading for the whole plan, so the run-gated updateState push never fired with the final itinerary and the checkpoint kept the empty list sent at first submit. Drop the isLoading gate and retry the updateState on the 409 a mid-run write returns until the run settles, so the final itinerary always lands. Also guard hydration so a behind/empty server snapshot can't wipe a populated local working copy mid-plan. Verified live: plan → reload restores. --- .../app/shell/demo-shell.component.spec.ts | 12 ++-- .../src/app/shell/demo-shell.component.ts | 57 ++++++++++++------- 2 files changed, 39 insertions(+), 30 deletions(-) diff --git a/examples/chat/angular/src/app/shell/demo-shell.component.spec.ts b/examples/chat/angular/src/app/shell/demo-shell.component.spec.ts index 9e03fee7d..d8ff3b60a 100644 --- a/examples/chat/angular/src/app/shell/demo-shell.component.spec.ts +++ b/examples/chat/angular/src/app/shell/demo-shell.component.spec.ts @@ -530,20 +530,16 @@ class CapturingTransport extends FakeStreamTransport { } describe('shouldSyncCheckpoint — push-gate predicate', () => { - it('pushes when settled, has a thread, and content changed', () => { - expect(shouldSyncCheckpoint(false, 'thread-1', '[1]', '[0]')).toBe(true); - }); - - it('never pushes while a run is loading (mid-run guard)', () => { - expect(shouldSyncCheckpoint(true, 'thread-1', '[1]', '[0]')).toBe(false); + it('pushes when a thread exists and content changed', () => { + expect(shouldSyncCheckpoint('thread-1', '[1]', '[0]')).toBe(true); }); it('never pushes without a thread id', () => { - expect(shouldSyncCheckpoint(false, null, '[1]', '[0]')).toBe(false); + expect(shouldSyncCheckpoint(null, '[1]', '[0]')).toBe(false); }); it('skips when the content already matches lastSynced (echo-loop guard)', () => { - expect(shouldSyncCheckpoint(false, 'thread-1', '[1]', '[1]')).toBe(false); + expect(shouldSyncCheckpoint('thread-1', '[1]', '[1]')).toBe(false); }); }); diff --git a/examples/chat/angular/src/app/shell/demo-shell.component.ts b/examples/chat/angular/src/app/shell/demo-shell.component.ts index 2926e8f8c..1b7664e2a 100644 --- a/examples/chat/angular/src/app/shell/demo-shell.component.ts +++ b/examples/chat/angular/src/app/shell/demo-shell.component.ts @@ -83,19 +83,21 @@ function parseUrl(url: string): { mode: DemoMode; threadId: string | null } { /** * Decide whether to push the working itinerary to the durable checkpoint. - * Returns true only when a run has SETTLED (not loading), a thread exists, - * and the content actually changed since the last sync. The `json === lastJson` - * check is the echo-loop guard: hydration stamps `lastSyncedItinerary` with the - * incoming server JSON, so the re-fired push effect sees "no change" and skips — - * making hydrate→push→hydrate converge immediately. + * Returns true when a thread exists and the itinerary changed since the last + * sync. The `json === lastJson` check is the echo-loop guard: hydration stamps + * `lastSyncedItinerary` with the incoming server JSON, so the re-fired push + * effect sees "no change" and skips — making hydrate→push→hydrate converge. + * + * Run-state is intentionally NOT gated. The client-tool resume loop keeps the + * agent loading for the whole plan, so a run-gated push never fires with the + * final itinerary; instead the push attempts anyway and retries on the 409 a + * mid-run `updateState` returns, until the run settles (see the push effect). */ export function shouldSyncCheckpoint( - isLoading: boolean, threadId: string | null, json: string, lastJson: string, ): boolean { - if (isLoading) return false; if (!threadId) return false; return json !== lastJson; } @@ -259,6 +261,11 @@ export class DemoShell { effect(() => { const incoming = extractItinerary(this.agent.value()); if (incoming === null) return; + // Don't let a behind/empty server snapshot wipe a populated local working + // copy: during a plan the client tools fill the store before the checkpoint + // catches up via the push below. Adopt an empty server itinerary only when + // the store is itself empty (a genuine thread switch / fresh load). + if (incoming.length === 0 && untracked(() => this.itinerary.stops()).length > 0) return; const json = JSON.stringify(incoming); if (json === this.lastSyncedItinerary) return; this.lastSyncedItinerary = json; @@ -271,23 +278,29 @@ export class DemoShell { // threadIdState(). Errors are swallowed — this is a best-effort sync. effect((onCleanup) => { const stops = this.itinerary.stops(); - const isLoading = this.agent.isLoading(); const tid = threadIdState(); const json = JSON.stringify(stops); - if (!shouldSyncCheckpoint(isLoading, tid, json, this.lastSyncedItinerary)) return; - const timer = setTimeout(() => { - void (async () => { - try { - await this.lgClient.threads.updateState(tid as string, { - values: { itinerary: stops }, - }); - this.lastSyncedItinerary = json; - } catch { - // best-effort: a failed checkpoint push must not break the UI. - } - })(); - }, 500); - onCleanup(() => clearTimeout(timer)); + if (!shouldSyncCheckpoint(tid, json, this.lastSyncedItinerary)) return; + // Debounce, then push. A mid-run write returns 409 (the client-tool resume + // loop is streaming); retry until the run settles so the FINAL itinerary + // always lands in the checkpoint. onCleanup cancels a superseded attempt. + let cancelled = false; + const attempt = async (): Promise => { + if (cancelled) return; + try { + await this.lgClient.threads.updateState(tid as string, { + values: { itinerary: stops }, + }); + this.lastSyncedItinerary = json; + } catch { + if (!cancelled) setTimeout(() => void attempt(), 1500); + } + }; + const timer = setTimeout(() => void attempt(), 1200); + onCleanup(() => { + cancelled = true; + clearTimeout(timer); + }); }); if (typeof window !== 'undefined') { From 3fb99b4652e2697005b244711a24dc83c89f65cd Mon Sep 17 00:00:00 2001 From: Brian Love Date: Tue, 7 Jul 2026 10:34:49 -0700 Subject: [PATCH 20/23] fix(examples-chat): retry checkpoint push only on 409, capped (review) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Address final-review findings: the retry now discriminates — only a mid-run 409 (conflict) is retried, and only up to MAX_PUSH_RETRIES, so a persistently failing thread (404/auth/500) can't spin an unbounded background loop. Track the retry timer, and correct the now-stale run-gated/500ms comment. Adds isConflict unit tests. --- .../app/shell/demo-shell.component.spec.ts | 18 +++++++++- .../src/app/shell/demo-shell.component.ts | 36 +++++++++++++------ 2 files changed, 43 insertions(+), 11 deletions(-) diff --git a/examples/chat/angular/src/app/shell/demo-shell.component.spec.ts b/examples/chat/angular/src/app/shell/demo-shell.component.spec.ts index d8ff3b60a..29b756440 100644 --- a/examples/chat/angular/src/app/shell/demo-shell.component.spec.ts +++ b/examples/chat/angular/src/app/shell/demo-shell.component.spec.ts @@ -9,7 +9,7 @@ import { FakeStreamTransport, type AgentTransport, } from '@threadplane/langgraph'; -import { DemoShell, shouldSyncCheckpoint, extractItinerary } from './demo-shell.component'; +import { DemoShell, shouldSyncCheckpoint, extractItinerary, isConflict } from './demo-shell.component'; import { DEMO_AGENT_REF } from './agent-ref'; import { ItineraryStore, type ItineraryStop } from '../itinerary-store'; @@ -543,6 +543,22 @@ describe('shouldSyncCheckpoint — push-gate predicate', () => { }); }); +describe('isConflict — retry only the mid-run 409', () => { + it('is true for a 409 status', () => { + expect(isConflict({ status: 409 })).toBe(true); + }); + + it('is true when the message mentions 409/conflict', () => { + expect(isConflict(new Error('Request failed: 409 Conflict'))).toBe(true); + }); + + it('is false for other errors (terminal — do not retry)', () => { + expect(isConflict({ status: 404 })).toBe(false); + expect(isConflict(new Error('Unauthorized'))).toBe(false); + expect(isConflict(null)).toBe(false); + }); +}); + describe('extractItinerary — value → stops', () => { it('returns the itinerary array from a state value', () => { const stops: ItineraryStop[] = [{ id: 'x', day: 1, place: 'Louvre' }]; diff --git a/examples/chat/angular/src/app/shell/demo-shell.component.ts b/examples/chat/angular/src/app/shell/demo-shell.component.ts index 1b7664e2a..48d8bfb61 100644 --- a/examples/chat/angular/src/app/shell/demo-shell.component.ts +++ b/examples/chat/angular/src/app/shell/demo-shell.component.ts @@ -112,6 +112,19 @@ export function extractItinerary(value: unknown): ItineraryStop[] | null { return null; } +/** Cap on checkpoint-push retries — a backstop so a persistently-failing thread + * can't spin an unbounded background retry loop. */ +export const MAX_PUSH_RETRIES = 20; + +/** A mid-run `updateState` returns HTTP 409 (the client-tool resume loop is + * streaming); that is the ONLY error worth retrying. Any other failure + * (404/auth/500) is terminal for this best-effort sync. */ +export function isConflict(err: unknown): boolean { + const status = (err as { status?: number })?.status; + if (status === 409) return true; + return /\b409\b|conflict/i.test(String((err as { message?: string })?.message ?? err)); +} + @Component({ selector: 'demo-shell', standalone: true, @@ -272,19 +285,20 @@ export class DemoShell { this.itinerary.hydrate(incoming); }); - // (3) Push the working copy to the checkpoint at run-settle and on user - // edits between runs. Run-gated (never mid-run) + debounced (~500ms). - // Depends on stops(), isLoading() (so it re-fires when a run SETTLES), and - // threadIdState(). Errors are swallowed — this is a best-effort sync. + // (3) Push the working copy to the durable checkpoint on every change. + // NOT run-gated: the client-tool resume loop keeps the agent loading for + // the whole plan, so a mid-run write returns 409 — retry ONLY that (bounded + // by MAX_PUSH_RETRIES) until the run settles so the final itinerary always + // lands. Debounced ~1200ms; onCleanup cancels a superseded attempt. Any + // non-conflict error is terminal — this is a best-effort sync, not a queue. effect((onCleanup) => { const stops = this.itinerary.stops(); const tid = threadIdState(); const json = JSON.stringify(stops); if (!shouldSyncCheckpoint(tid, json, this.lastSyncedItinerary)) return; - // Debounce, then push. A mid-run write returns 409 (the client-tool resume - // loop is streaming); retry until the run settles so the FINAL itinerary - // always lands in the checkpoint. onCleanup cancels a superseded attempt. let cancelled = false; + let retries = 0; + let timer: ReturnType; const attempt = async (): Promise => { if (cancelled) return; try { @@ -292,11 +306,13 @@ export class DemoShell { values: { itinerary: stops }, }); this.lastSyncedItinerary = json; - } catch { - if (!cancelled) setTimeout(() => void attempt(), 1500); + } catch (err) { + if (!cancelled && isConflict(err) && retries++ < MAX_PUSH_RETRIES) { + timer = setTimeout(() => void attempt(), 1500); + } } }; - const timer = setTimeout(() => void attempt(), 1200); + timer = setTimeout(() => void attempt(), 1200); onCleanup(() => { cancelled = true; clearTimeout(timer); From f8e1383d4f278dc48fe6f1813630231a78cf6466 Mon Sep 17 00:00:00 2001 From: Brian Love Date: Tue, 7 Jul 2026 11:28:19 -0700 Subject: [PATCH 21/23] feat(examples-chat): dark map via colorScheme, drop cloud-style dependency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The map's dark theme was a cloud-based map style bound to a specific GCP Map ID — brittle (lives in the Console, tied to one project/billing acct, invisible to git). Replace it with an in-code colorScheme: DARK on the vector map, which keeps AdvancedMarkers, works with any mapId (incl. the DEMO_MAP_ID fallback), and is version-controlled + project-independent. Kept as a plain string so the field carries no runtime google.maps reference (map-canvas builds under jsdom in the shell specs). --- .../angular/src/app/map-canvas.component.ts | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/examples/chat/angular/src/app/map-canvas.component.ts b/examples/chat/angular/src/app/map-canvas.component.ts index 3a3f39a65..155cf0dda 100644 --- a/examples/chat/angular/src/app/map-canvas.component.ts +++ b/examples/chat/angular/src/app/map-canvas.component.ts @@ -86,16 +86,24 @@ export class MapCanvasComponent { private readonly destroyRef = inject(DestroyRef); protected readonly center = signal(PARIS_CENTER); protected readonly zoom = signal(12); - // A mapId is REQUIRED for advanced markers; a mapId map ignores inline JSON - // `styles`, so the dark theme is a cloud-based map style tied to this id. - // DEMO_MAP_ID lets a fresh clone run (light map) with no Console setup. + // A mapId is REQUIRED for advanced markers. The dark theme is applied IN CODE + // via `colorScheme: DARK` below — NOT a cloud-based map style — so there is no + // Google Cloud Console style setup to maintain and ANY mapId works. + // DEMO_MAP_ID lets a fresh clone run with no Console setup at all. protected readonly mapId = environment.googleMapsMapId || 'DEMO_MAP_ID'; - protected readonly mapOptions: google.maps.MapOptions = { + protected readonly mapOptions = { mapId: this.mapId, + // Dark map in code — no cloud-style dependency. 'DARK' is the runtime value + // of the google.maps.ColorScheme enum; kept as a plain string so this field + // initializer holds no runtime `google.maps` reference (map-canvas builds + // under jsdom in the shell specs, before the Maps API loads). The whole + // literal is cast so it typechecks regardless of the installed + // @types/google.maps version; the live Maps JS from Google's CDN honors it. + colorScheme: 'DARK', disableDefaultUI: true, zoomControl: true, clickableIcons: false, - }; + } as google.maps.MapOptions; // AdvancedMarkerElement is NOT clickable by default (unlike the legacy // Marker) — without gmpClickable it never fires click/gmp-click, so the // wrapper's (mapClick) output stays silent and the info window can't open. From eee067b5ed7717951961acbb7ade223713d5ae1f Mon Sep 17 00:00:00 2001 From: Brian Love Date: Tue, 7 Jul 2026 11:49:28 -0700 Subject: [PATCH 22/23] feat(examples-chat): map light/dark follows the app color scheme The map now tracks the app's light/dark toggle (the the shell reflects), not the gen-UI mode. mapColorScheme is derived from a MutationObserver-backed signal; since Google's colorScheme is init-only, the template remounts via a scheme-keyed @for when it flips. --- .../src/app/map-canvas.component.spec.ts | 23 ++++++++ .../angular/src/app/map-canvas.component.ts | 53 ++++++++++++++----- 2 files changed, 62 insertions(+), 14 deletions(-) create mode 100644 examples/chat/angular/src/app/map-canvas.component.spec.ts diff --git a/examples/chat/angular/src/app/map-canvas.component.spec.ts b/examples/chat/angular/src/app/map-canvas.component.spec.ts new file mode 100644 index 000000000..34b686270 --- /dev/null +++ b/examples/chat/angular/src/app/map-canvas.component.spec.ts @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: MIT +import { describe, it, expect, afterEach } from 'vitest'; +import { readAppColorScheme } from './map-canvas.component'; + +describe('readAppColorScheme — map follows the app light/dark toggle', () => { + afterEach(() => document.documentElement.removeAttribute('data-color-scheme')); + + it("reads 'light' from ", () => { + document.documentElement.setAttribute('data-color-scheme', 'light'); + expect(readAppColorScheme()).toBe('light'); + }); + + it("reads 'dark' from ", () => { + document.documentElement.setAttribute('data-color-scheme', 'dark'); + expect(readAppColorScheme()).toBe('dark'); + }); + + it("defaults to 'dark' when the attribute is absent or unknown", () => { + expect(readAppColorScheme()).toBe('dark'); + document.documentElement.setAttribute('data-color-scheme', 'sepia'); + expect(readAppColorScheme()).toBe('dark'); + }); +}); diff --git a/examples/chat/angular/src/app/map-canvas.component.ts b/examples/chat/angular/src/app/map-canvas.component.ts index 155cf0dda..bc622df3c 100644 --- a/examples/chat/angular/src/app/map-canvas.component.ts +++ b/examples/chat/angular/src/app/map-canvas.component.ts @@ -22,6 +22,13 @@ import { environment } from '../environments/environment'; const DAY_COLORS = ['#ef4444', '#3b82f6', '#10b981', '#f59e0b', '#8b5cf6', '#ec4899', '#06b6d4', '#84cc16']; const PARIS_CENTER: google.maps.LatLngLiteral = { lat: 48.8566, lng: 2.3522 }; +/** The app's active light/dark scheme, read from the `` + * attribute the demo shell reflects (NOT the gen-UI mode). Defaults to 'dark' + * (the app default) when the attribute is absent. */ +export function readAppColorScheme(): 'light' | 'dark' { + return document.documentElement.getAttribute('data-color-scheme') === 'light' ? 'light' : 'dark'; +} + @Component({ selector: 'app-map-canvas', standalone: true, @@ -32,12 +39,15 @@ const PARIS_CENTER: google.maps.LatLngLiteral = { lat: 48.8566, lng: 2.3522 }; throws "Namespace google not found" when window.google is absent, which would abort the host shell's render on a fresh load with App mode on. --> @if (loader.loaded()) { + + @for (scheme of [mapColorScheme()]; track scheme) { @for (m of markerViews(); track m.id) { + } } `, styles: [ @@ -86,24 +97,32 @@ export class MapCanvasComponent { private readonly destroyRef = inject(DestroyRef); protected readonly center = signal(PARIS_CENTER); protected readonly zoom = signal(12); - // A mapId is REQUIRED for advanced markers. The dark theme is applied IN CODE - // via `colorScheme: DARK` below — NOT a cloud-based map style — so there is no - // Google Cloud Console style setup to maintain and ANY mapId works. - // DEMO_MAP_ID lets a fresh clone run with no Console setup at all. + // A mapId is REQUIRED for advanced markers. The map theme is applied IN CODE + // via `colorScheme` — NOT a cloud-based map style — so there is no Google Cloud + // Console style to maintain and ANY mapId works. DEMO_MAP_ID lets a fresh clone + // run with no Console setup at all. protected readonly mapId = environment.googleMapsMapId || 'DEMO_MAP_ID'; - protected readonly mapOptions = { + + // Follow the app's light/dark toggle (the the shell + // reflects) — NOT the gen-UI mode. Seeded synchronously so the first paint + // themes correctly; a MutationObserver (afterNextRender) keeps it live. + private readonly appColorScheme = signal<'light' | 'dark'>(readAppColorScheme()); + protected readonly mapColorScheme = computed<'LIGHT' | 'DARK'>(() => + this.appColorScheme() === 'light' ? 'LIGHT' : 'DARK', + ); + + protected readonly mapOptions = computed(() => ({ mapId: this.mapId, - // Dark map in code — no cloud-style dependency. 'DARK' is the runtime value - // of the google.maps.ColorScheme enum; kept as a plain string so this field - // initializer holds no runtime `google.maps` reference (map-canvas builds - // under jsdom in the shell specs, before the Maps API loads). The whole - // literal is cast so it typechecks regardless of the installed - // @types/google.maps version; the live Maps JS from Google's CDN honors it. - colorScheme: 'DARK', + // colorScheme is INIT-ONLY on a Google map, so the template remounts + // when mapColorScheme() flips (see the keyed @for). Plain string + // = the google.maps.ColorScheme enum's runtime value, so this holds no + // runtime `google.maps` reference (map-canvas builds under jsdom). Cast for + // @types/google.maps version independence; the live Maps JS honors it. + colorScheme: this.mapColorScheme(), disableDefaultUI: true, zoomControl: true, clickableIcons: false, - } as google.maps.MapOptions; + } as google.maps.MapOptions)); // AdvancedMarkerElement is NOT clickable by default (unlike the legacy // Marker) — without gmpClickable it never fires click/gmp-click, so the // wrapper's (mapClick) output stays silent and the info window can't open. @@ -173,6 +192,12 @@ export class MapCanvasComponent { }); ro.observe(this.hostRef.nativeElement); this.destroyRef.onDestroy(() => ro.disconnect()); + + // Live-follow the app's light/dark toggle. colorScheme is init-only, so the + // template @for remounts when this signal flips. + const mo = new MutationObserver(() => this.appColorScheme.set(readAppColorScheme())); + mo.observe(document.documentElement, { attributes: true, attributeFilter: ['data-color-scheme'] }); + this.destroyRef.onDestroy(() => mo.disconnect()); }); } From c7210deeb176a0764a48e1a5579a778b44f33e81 Mon Sep 17 00:00:00 2001 From: Brian Love Date: Wed, 8 Jul 2026 16:29:28 -0700 Subject: [PATCH 23/23] Add markdown blockquote table e2e coverage --- .../chat/angular/e2e/fixtures/markdown.json | 8 +++++++ .../angular/e2e/markdown-surfaces.spec.ts | 23 +++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/examples/chat/angular/e2e/fixtures/markdown.json b/examples/chat/angular/e2e/fixtures/markdown.json index 4fa49a08e..8c98155b0 100644 --- a/examples/chat/angular/e2e/fixtures/markdown.json +++ b/examples/chat/angular/e2e/fixtures/markdown.json @@ -12,6 +12,14 @@ "match": { "userMessage": "respond with a bullet list" }, "response": { "content": "Three things:\n\n- alpha\n- beta\n- gamma" } }, + { + "match": { + "userMessage": "Give me a blockquote with two lines, then a markdown table with columns issue, expected behavior, verification." + }, + "response": { + "content": "> First quoted line\n> Second quoted line\n\n| Issue | Expected behavior | Verification |\n| --- | --- | --- |\n| Blockquote nesting | Both quoted lines render inside one blockquote | Inspect for one `
` with no stray quoted paragraph |\n| Table streaming | Rows remain inside the same table while content streams | Inspect for one `` with body rows |\n| Parser recovery | Final DOM has no raw pipe paragraphs | Confirm no paragraph text contains `|` delimiters |" + } + }, { "match": { "userMessage": "respond with the markdown checklist kitchen sink" }, "response": { diff --git a/examples/chat/angular/e2e/markdown-surfaces.spec.ts b/examples/chat/angular/e2e/markdown-surfaces.spec.ts index ae8f343a6..fe8223261 100644 --- a/examples/chat/angular/e2e/markdown-surfaces.spec.ts +++ b/examples/chat/angular/e2e/markdown-surfaces.spec.ts @@ -55,6 +55,29 @@ test('markdown checklist matrix: rich markdown renders with escaped html', async await expect(bubble).toContainText(""); }); +test('blockquote followed by table stays in one rendered markdown surface', async ({ page }) => { + const bubble = await sendPromptAndWait( + page, + 'Give me a blockquote with two lines, then a markdown table with columns issue, expected behavior, verification.', + ); + + await expect(bubble.locator('blockquote')).toHaveCount(1); + await expect(bubble.locator('blockquote')).toContainText('First quoted line'); + await expect(bubble.locator('blockquote')).toContainText('Second quoted line'); + await expect(bubble.locator('table')).toHaveCount(1); + await expect(bubble.locator('thead th')).toHaveText([ + 'Issue', + 'Expected behavior', + 'Verification', + ]); + await expect(bubble.locator('tbody tr')).toHaveCount(3); + await expect.poll(async () => tableColumnsAlign(bubble)).toBe(true); + await expect( + bubble.locator('p').filter({ hasText: /\|/ }), + 'table rows should not render as raw pipe paragraphs', + ).toHaveCount(0); +}); + async function tableColumnsAlign(bubble: Locator): Promise { const table = bubble.locator('table').first(); return table.evaluate((el) => {