Skip to content

feat(ai-agent): question, plan and result cards in the AI sidebar - #25

Merged
Suharshit merged 5 commits into
feat/ai-design-turn-enginefrom
feat/ai-agent-cards
Sep 15, 2026
Merged

Suharshit merged 5 commits into
feat/ai-design-turn-enginefrom
feat/ai-agent-cards

Conversation

@Suharshit

Copy link
Copy Markdown
Owner

Stacked on #23 (#21 → #22 → #23 → this). The base is feat/ai-design-turn-engine, so this diff shows step 4 only. After the PR below it merges, change this PR's base to main.

Why

Step 3 made the design agent conversational, but the sidebar still showed its questions and plans as plain text, so users had to type answers and approvals. This is step 4 of the AI sessions plan: dedicated cards with real controls.

What

  • QuestionsCard:
    • numbered questions, each with its short "why"
    • option chips (aria-pressed) plus a free-text answer per question; a typed answer wins over a chip
    • Send answers, disabled until something is answered, and Skip, plan with assumptions
    • once sent, the card stays read-only with the chosen answers
  • PlanCard:
    • summary
    • key decisions highlighted (choice, rationale, alternatives considered)
    • components with role labels, folded after 6 behind "Show all N"
    • key flows and assumptions
    • Draw this plan, with an "or describe changes below" hint
  • ResultCard: what was added to the canvas, with a collapsible list of the decisions.
  • Which card is active: only the newest non-failed assistant reply is interactive, and only while no turn is pending, which mirrors the server's rules for open questions and the plan to draw. The composer placeholder changes while questions or a plan are open.
  • useAiSession.sendTurn: sends message, answers, generate and skip. The optimistic user message matches what the server stores (answers paired with their questions, the fixed generate and skip texts). Messages now expose kind and payload.
  • Shared code: TurnInput, the generate and skip texts and the payload readers moved into the client-safe lib/ai/agent-schema.ts, and session-turns.ts uses them instead of its own copies. Question and plan payloads also store the agent's short reply, shown as the card intro; older messages show none.

Verification

  • pnpm typecheck and pnpm lint pass.
  • 29 static render checks (react-dom/server):
    • open vs answered questions: chips, inputs, disabled send, skip, labelled groups, pressed chip, typed answer, no controls once answered
    • plan sections: highlighted decisions, the alternatives line only when there are alternatives, 6 of 8 components with show-all, flows, assumptions
    • the draw button only on the interactive plan, and empty sections omitted
    • the result card
    • the payload readers, including step 2 results without decisions
  • 15 database turn checks pass after the shared-reader refactor.
  • Live flow through the Trigger worker (gemini-3.5-flash-lite): message → 3 questions (15.8s), skip → plan with 9 components and 3 decisions (12.3s), generate → "Added 9 components and 8 connections to the canvas." (12.6s).
  • Not checked in a browser: clicking chips, typing answers, send, skip and draw with a signed-in user.

🤖 Generated with Claude Code

Suharshit and others added 4 commits September 15, 2026 22:16
The AI sidebar kept its chat in React state only, so a reload lost the
transcript and any in-flight run. This adds the storage layer the
multi-turn design agent will build on (not wired to the UI yet).

- AiSession / AiMessage Prisma models + additive migration; sessions
  cascade with their project, messages cascade with their session
- lib/ai/session-store.ts: 7-day sliding expiry, 10 sessions per user
  per project, 60 messages per session; reads ignore expired rows
- GET/POST /api/projects/[projectId]/ai-sessions and
  GET/DELETE /api/projects/[projectId]/ai-sessions/[sessionId],
  private to the session's creator
- Daily Vercel Cron cleanup at /api/cron/ai-sessions/cleanup,
  gated by CRON_SECRET (public in proxy.ts)

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A reload no longer loses the chat or an in-flight run. Generation is
still one-shot; this changes persistence and resume only.

- POST /api/projects/[projectId]/ai-sessions/[sessionId]/turns stores
  the prompt and a PENDING reply carrying the run id (replaces
  POST /api/ai/design, which is removed)
- Replies are settled from runs.retrieve whenever a session is read, so
  a turn is saved even if the tab closed mid-run; concurrent reads
  settle once
- useAiSession replaces useDesignAgent: reopens the last chat, resumes
  pending runs via Realtime with a 4s polling fallback, stores new chats
  lazily on the first message
- Sidebar session bar with saved-chat history (delete, expiry) and
  New chat
- Limits moved to lib/ai/session-limits.ts for client use;
  formatRelativeTime extracted to lib/relative-time.ts

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Each turn is still one design-agent run, but the agent now keeps a
requirements brief, asks up to 3 rounds of clarifying questions when
an unknown would change the architecture, proposes a plan (components,
flows, decisions with rationale and alternatives, assumptions), and
only draws the diagram once the plan is approved.

- lib/ai/agent-schema.ts: brief, question, plan, turn-analysis and
  run-result schemas; list limits trimmed in code rather than enforced
  as maxItems, which models don't reliably honour
- lib/ai/prompts.ts, lib/ai/design-agent-engine.ts: analyze/plan/
  generate on generateText + Output.object; code-enforced decision
  rules; per-step thinking level (Gemini 3) or budget (Gemini 2.x);
  one retry on schema mismatch; per-call timeouts
- design-agent task: single attempt, maxDuration 300s
- Turns route accepts message, answers, generate and skip; stored
  replies are validated run output (QUESTIONS / PLAN / RESULT) and run
  failures are shown as friendly messages

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The AI Architect chat now renders the design agent's turns as cards
instead of plain text, so users answer, skip and approve with buttons.

- QuestionsCard: option chips and a free-text answer per question,
  Send answers and Skip; read-only with the chosen answers once sent
- PlanCard: summary, highlighted key decisions with rationale and
  alternatives, components (folded after 6), flows, assumptions, and
  Draw this plan
- ResultCard: canvas summary with collapsible decisions
- Only the newest non-failed reply is interactive, and only while no
  turn is pending, mirroring the server's rules
- useAiSession.sendTurn sends message, answers, generate and skip,
  with optimistic user text matching what the server stores
- TurnInput, the generate/skip texts and payload readers now live in
  the client-safe agent-schema and are shared with the server; question
  and plan payloads also store the agent's reply

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Sep 15, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
draftly Ready Ready Preview Sep 15, 2026 6:58pm UTC

@coderabbitai

coderabbitai Bot commented Sep 15, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 0d22e3f0-a81e-4769-ba18-1bea3940025c

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@Suharshit
Suharshit merged commit ceab34e into feat/ai-design-turn-engine Sep 15, 2026
5 checks passed
Suharshit added a commit that referenced this pull request Sep 15, 2026
GitHub main has steps 1-3 only; steps 4-6 were merged into stacked base branches. Content matches local exactly; a stacked merge into main conflicts in 11 files, so main needs a sync commit whose tree is the stack head.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Suharshit added a commit that referenced this pull request Sep 15, 2026
* feat(ai-agent): multi-turn design agent - clarify, plan, then generate

Each turn is still one design-agent run, but the agent now keeps a
requirements brief, asks up to 3 rounds of clarifying questions when
an unknown would change the architecture, proposes a plan (components,
flows, decisions with rationale and alternatives, assumptions), and
only draws the diagram once the plan is approved.

- lib/ai/agent-schema.ts: brief, question, plan, turn-analysis and
  run-result schemas; list limits trimmed in code rather than enforced
  as maxItems, which models don't reliably honour
- lib/ai/prompts.ts, lib/ai/design-agent-engine.ts: analyze/plan/
  generate on generateText + Output.object; code-enforced decision
  rules; per-step thinking level (Gemini 3) or budget (Gemini 2.x);
  one retry on schema mismatch; per-call timeouts
- design-agent task: single attempt, maxDuration 300s
- Turns route accepts message, answers, generate and skip; stored
  replies are validated run output (QUESTIONS / PLAN / RESULT) and run
  failures are shown as friendly messages

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* feat(ai-agent): question, plan and result cards in the AI sidebar (#25)

* feat(ai-sessions): add persistent storage for AI design sessions

The AI sidebar kept its chat in React state only, so a reload lost the
transcript and any in-flight run. This adds the storage layer the
multi-turn design agent will build on (not wired to the UI yet).

- AiSession / AiMessage Prisma models + additive migration; sessions
  cascade with their project, messages cascade with their session
- lib/ai/session-store.ts: 7-day sliding expiry, 10 sessions per user
  per project, 60 messages per session; reads ignore expired rows
- GET/POST /api/projects/[projectId]/ai-sessions and
  GET/DELETE /api/projects/[projectId]/ai-sessions/[sessionId],
  private to the session's creator
- Daily Vercel Cron cleanup at /api/cron/ai-sessions/cleanup,
  gated by CRON_SECRET (public in proxy.ts)

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* feat(ai-sessions): run the AI Architect chat on stored sessions

A reload no longer loses the chat or an in-flight run. Generation is
still one-shot; this changes persistence and resume only.

- POST /api/projects/[projectId]/ai-sessions/[sessionId]/turns stores
  the prompt and a PENDING reply carrying the run id (replaces
  POST /api/ai/design, which is removed)
- Replies are settled from runs.retrieve whenever a session is read, so
  a turn is saved even if the tab closed mid-run; concurrent reads
  settle once
- useAiSession replaces useDesignAgent: reopens the last chat, resumes
  pending runs via Realtime with a 4s polling fallback, stores new chats
  lazily on the first message
- Sidebar session bar with saved-chat history (delete, expiry) and
  New chat
- Limits moved to lib/ai/session-limits.ts for client use;
  formatRelativeTime extracted to lib/relative-time.ts

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* feat(ai-agent): multi-turn design agent - clarify, plan, then generate

Each turn is still one design-agent run, but the agent now keeps a
requirements brief, asks up to 3 rounds of clarifying questions when
an unknown would change the architecture, proposes a plan (components,
flows, decisions with rationale and alternatives, assumptions), and
only draws the diagram once the plan is approved.

- lib/ai/agent-schema.ts: brief, question, plan, turn-analysis and
  run-result schemas; list limits trimmed in code rather than enforced
  as maxItems, which models don't reliably honour
- lib/ai/prompts.ts, lib/ai/design-agent-engine.ts: analyze/plan/
  generate on generateText + Output.object; code-enforced decision
  rules; per-step thinking level (Gemini 3) or budget (Gemini 2.x);
  one retry on schema mismatch; per-call timeouts
- design-agent task: single attempt, maxDuration 300s
- Turns route accepts message, answers, generate and skip; stored
  replies are validated run output (QUESTIONS / PLAN / RESULT) and run
  failures are shown as friendly messages

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* feat(ai-agent): question, plan and result cards in the AI sidebar

The AI Architect chat now renders the design agent's turns as cards
instead of plain text, so users answer, skip and approve with buttons.

- QuestionsCard: option chips and a free-text answer per question,
  Send answers and Skip; read-only with the chosen answers once sent
- PlanCard: summary, highlighted key decisions with rationale and
  alternatives, components (folded after 6), flows, assumptions, and
  Draw this plan
- ResultCard: canvas summary with collapsible decisions
- Only the newest non-failed reply is interactive, and only while no
  turn is pending, mirroring the server's rules
- useAiSession.sendTurn sends message, answers, generate and skip,
  with optimistic user text matching what the server stores
- TurnInput, the generate/skip texts and payload readers now live in
  the client-safe agent-schema and are shared with the server; question
  and plan payloads also store the agent's reply

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Suharshit added a commit that referenced this pull request Sep 15, 2026
* feat(ai-sessions): add persistent storage for AI design sessions

The AI sidebar kept its chat in React state only, so a reload lost the
transcript and any in-flight run. This adds the storage layer the
multi-turn design agent will build on (not wired to the UI yet).

- AiSession / AiMessage Prisma models + additive migration; sessions
  cascade with their project, messages cascade with their session
- lib/ai/session-store.ts: 7-day sliding expiry, 10 sessions per user
  per project, 60 messages per session; reads ignore expired rows
- GET/POST /api/projects/[projectId]/ai-sessions and
  GET/DELETE /api/projects/[projectId]/ai-sessions/[sessionId],
  private to the session's creator
- Daily Vercel Cron cleanup at /api/cron/ai-sessions/cleanup,
  gated by CRON_SECRET (public in proxy.ts)

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* feat(ai-sessions): run the AI Architect chat on stored sessions

A reload no longer loses the chat or an in-flight run. Generation is
still one-shot; this changes persistence and resume only.

- POST /api/projects/[projectId]/ai-sessions/[sessionId]/turns stores
  the prompt and a PENDING reply carrying the run id (replaces
  POST /api/ai/design, which is removed)
- Replies are settled from runs.retrieve whenever a session is read, so
  a turn is saved even if the tab closed mid-run; concurrent reads
  settle once
- useAiSession replaces useDesignAgent: reopens the last chat, resumes
  pending runs via Realtime with a 4s polling fallback, stores new chats
  lazily on the first message
- Sidebar session bar with saved-chat history (delete, expiry) and
  New chat
- Limits moved to lib/ai/session-limits.ts for client use;
  formatRelativeTime extracted to lib/relative-time.ts

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* feat(ai-agent): multi-turn design agent - clarify, plan, then generate

Each turn is still one design-agent run, but the agent now keeps a
requirements brief, asks up to 3 rounds of clarifying questions when
an unknown would change the architecture, proposes a plan (components,
flows, decisions with rationale and alternatives, assumptions), and
only draws the diagram once the plan is approved.

- lib/ai/agent-schema.ts: brief, question, plan, turn-analysis and
  run-result schemas; list limits trimmed in code rather than enforced
  as maxItems, which models don't reliably honour
- lib/ai/prompts.ts, lib/ai/design-agent-engine.ts: analyze/plan/
  generate on generateText + Output.object; code-enforced decision
  rules; per-step thinking level (Gemini 3) or budget (Gemini 2.x);
  one retry on schema mismatch; per-call timeouts
- design-agent task: single attempt, maxDuration 300s
- Turns route accepts message, answers, generate and skip; stored
  replies are validated run output (QUESTIONS / PLAN / RESULT) and run
  failures are shown as friendly messages

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* feat(ai-agent): question, plan and result cards in the AI sidebar

The AI Architect chat now renders the design agent's turns as cards
instead of plain text, so users answer, skip and approve with buttons.

- QuestionsCard: option chips and a free-text answer per question,
  Send answers and Skip; read-only with the chosen answers once sent
- PlanCard: summary, highlighted key decisions with rationale and
  alternatives, components (folded after 6), flows, assumptions, and
  Draw this plan
- ResultCard: canvas summary with collapsible decisions
- Only the newest non-failed reply is interactive, and only while no
  turn is pending, mirroring the server's rules
- useAiSession.sendTurn sends message, answers, generate and skip,
  with optimistic user text matching what the server stores
- TurnInput, the generate/skip texts and payload readers now live in
  the client-safe agent-schema and are shared with the server; question
  and plan payloads also store the agent's reply

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* feat(ai-agent): canvas-aware generation with roles, async edges and repair

The design agent now sees what is already on the canvas, so follow-up
requests extend the existing design instead of redrawing it, and
generated diagrams match the starter templates' visual conventions.

- lib/ai/canvas-summary.ts: compact canvas listing with refs (ex-N),
  kinds, used connection points, connections and notes, passed to the
  analyze, plan and generate steps
- Generation schema: role + kicker instead of legacy dark colorId,
  sync/async delivery (async edges dashed); edges may reference
  existing components by ref
- buildCanvasGraph: resolves refs, folds redrawn or repeated components
  into the existing/first node, drops unknown and duplicate links, and
  assigns connection points counting existing edges
- lib/ai/graph-validation.ts + one repair call: duplicate/redrawn
  components, unknown refs, self loops, repeated links, >4 connections,
  unconnected components, missing plan components
- Shared NODE_ROLES / getRoleFill and SHAPE_KICKERS in types/canvas.ts
  (starter templates use them)
- Plan text no longer shows internal canvas refs

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* docs(ai-sessions): document AI design sessions in context files and README

Brings the tracked docs in line with AI sessions steps 1-5. Docs only.
docs.md is gitignored, so its matching refresh stays local.

- context/architecture-context.md: AI Design Agent section (turn = run,
  turn steps, code-enforced rules, settle on read, reliability, model
  config) and invariants 5-9
- context/project-overview.md: canvas snapshots in Vercel Blob (was
  "filesystem"); chat cards and canvas-aware generation
- context/ui-context.md: AI sidebar session bar, saved chats and cards
  follow the paper conventions
- context/progress-tracker.md: step 6 entry and current goal
- README.md: local AI design agent setup

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* feat(spec): generate a Markdown technical spec from the canvas

The Specs tab now turns the current canvas into a Markdown technical
spec that downloads automatically: an overview, key decisions
highlighted as callouts, one Mermaid diagram section per group of
connected components, a component reference, connections, and risks.

- spec-agent Trigger task: reads the room, builds the spec graph in
  code, makes one structured model call for the prose (sanitised
  against the graph, internal refs stripped), renders the Markdown in
  code; aborts on an empty or oversized canvas
- Stored on read like AI turns: GET /api/projects/[id]/spec uploads a
  finished run to private Vercel Blob and records it on Project
  (guarded on the run id); POST starts a run (409 while one is
  pending); GET .../spec/markdown downloads the file
- Decisions recorded in the user's AI design sessions are included and
  tagged as recorded
- Migration: TaskRun.kind (DESIGN or SPEC) and Project spec fields
- useSpecGenerator and SpecPanel replace the placeholder Specs tab
- Shared lib/ai/model.ts, lib/ai/run-failure.ts and lib/canvas-room.ts
  used by both agents

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* docs(tracker): record stacked merges of #25-#27 and the main sync need

GitHub main has steps 1-3 only; steps 4-6 were merged into stacked base branches. Content matches local exactly; a stacked merge into main conflicts in 11 files, so main needs a sync commit whose tree is the stack head.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* docs(tracker): record merging the AI stack into main

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>

This branch was successfully deployed

1 active deployment
Preview — 2d2d1092 Deployed Sep 15, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant