Skip to content

Commit b019edb

Browse files
committed
docs: add AI SDK contract phase plans
1 parent 2e51f3a commit b019edb

2 files changed

Lines changed: 460 additions & 0 deletions

File tree

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
# AI SDK Contract Standardization: Phase 1 Foundation
2+
3+
> **Status:** Implemented on branch `codex/ai-sdk-contract-phase-1` and published in PR [#171](https://github.com/NickB03/polymorph/pull/171).
4+
5+
**Goal:** Establish AI SDK-native contracts as the primary chat/runtime boundary without breaking the current product surfaces for research UX, canvas, image generation, citations, guest chat, or authenticated chat.
6+
7+
## Original Phase 1 Intent
8+
9+
Phase 1 was intentionally foundation-first:
10+
11+
- introduce an agent-owned contract surface for chat tools and UI messages
12+
- treat validated AI SDK `UIMessage` envelopes as the canonical transport and persistence shape
13+
- replace bespoke continuation and rendering glue where AI SDK-native flows now exist
14+
- preserve product-specific behavior that still differentiates the app:
15+
- research mode UX
16+
- citations / link previews
17+
- canvas artifacts and progress events
18+
- image generation
19+
20+
This phase was not intended to finish the full standardization. It was intended to create the contract boundary that phase 2 can build on.
21+
22+
## Verified Implemented Scope
23+
24+
### 1. Shared chat-agent contract landed
25+
26+
The repo now has a dedicated `lib/agents/chat/` surface:
27+
28+
- [contract.ts](/Users/nick/.codex/worktrees/3a35/vana-v2/lib/agents/chat/contract.ts)
29+
- [toolset.ts](/Users/nick/.codex/worktrees/3a35/vana-v2/lib/agents/chat/toolset.ts)
30+
- [message-contract.ts](/Users/nick/.codex/worktrees/3a35/vana-v2/lib/agents/chat/message-contract.ts)
31+
- [ui-types.ts](/Users/nick/.codex/worktrees/3a35/vana-v2/lib/agents/chat/ui-types.ts)
32+
- [specialists.ts](/Users/nick/.codex/worktrees/3a35/vana-v2/lib/agents/chat/specialists.ts)
33+
34+
What this changed:
35+
36+
- `ChatAgentTools` is now the shared tool contract instead of `researcher` being the implicit global owner.
37+
- `createChatValidationContract()` validates incoming UI messages against a shared metadata + data-part schema.
38+
- `ChatAgentUIMessage` / `ChatAgentUITools` are now inferred from the shared contract.
39+
- a specialist fixture and registry surface now exist so the next phase can add a live specialist without another contract rewrite.
40+
41+
### 2. Researcher now composes from the shared contract
42+
43+
[researcher.ts](/Users/nick/.codex/worktrees/3a35/vana-v2/lib/agents/researcher.ts) no longer defines the global tool contract itself.
44+
45+
What remains bespoke in `researcher.ts` after phase 1:
46+
47+
- search-mode prompt selection
48+
- request-local search pacing
49+
- mode-specific active tool lists
50+
- eval-mode exclusion of interactive tools
51+
52+
That is acceptable for phase 1. It keeps runtime behavior intact while moving the type and validation boundary into `lib/agents/chat/`.
53+
54+
### 3. Canonical `UIMessage` persistence landed
55+
56+
The `messages` table now stores the canonical message envelope directly:
57+
58+
- [schema.ts](/Users/nick/.codex/worktrees/3a35/vana-v2/lib/db/schema.ts)
59+
- [0020_chat_ui_message_contract.sql](/Users/nick/.codex/worktrees/3a35/vana-v2/drizzle/0020_chat_ui_message_contract.sql)
60+
- [message-mapping.ts](/Users/nick/.codex/worktrees/3a35/vana-v2/lib/utils/message-mapping.ts)
61+
62+
What changed:
63+
64+
- `messages.ui_message` was added as `jsonb`
65+
- DB writes now persist the full canonical `UIMessage`
66+
- DB reads now prefer `ui_message` as the source of truth and only fall back to legacy part reconstruction when necessary
67+
68+
This is the most important structural change in phase 1. New features no longer need to depend on legacy per-part reconstruction as the primary contract.
69+
70+
### 4. Transport and continuation moved closer to AI SDK-native flows
71+
72+
The chat transport now prefers canonical `messages` payloads:
73+
74+
- [route.ts](/Users/nick/.codex/worktrees/3a35/vana-v2/app/api/chat/route.ts)
75+
- [chat-request.ts](/Users/nick/.codex/worktrees/3a35/vana-v2/components/chat-request.ts)
76+
- [prepare-messages.ts](/Users/nick/.codex/worktrees/3a35/vana-v2/lib/streaming/helpers/prepare-messages.ts)
77+
- [create-chat-stream-response.ts](/Users/nick/.codex/worktrees/3a35/vana-v2/lib/streaming/create-chat-stream-response.ts)
78+
- [create-ephemeral-chat-stream-response.ts](/Users/nick/.codex/worktrees/3a35/vana-v2/lib/streaming/create-ephemeral-chat-stream-response.ts)
79+
80+
What changed:
81+
82+
- request normalization now prefers `messages`
83+
- the legacy single `message` shape remains only as a compatibility fallback when `messages` is absent
84+
- guest and authenticated paths both validate normalized messages before model conversion
85+
- continuation now flows through validated message state instead of the earlier custom rewrite path being the default
86+
87+
### 5. Tool rendering was reduced to a registry seam
88+
89+
Rendering logic moved out of the global message renderer into a dedicated tool-part helper:
90+
91+
- [tool-part-registry.tsx](/Users/nick/.codex/worktrees/3a35/vana-v2/components/tool-ui/tool-part-registry.tsx)
92+
- [render-message.tsx](/Users/nick/.codex/worktrees/3a35/vana-v2/components/render-message.tsx)
93+
94+
What changed:
95+
96+
- `displayOptionList` and `displayQuestionWizard` interactive flows now resolve through the tool-part registry seam
97+
- research-mode suppression for citations / link previews is still preserved
98+
- generic tool output rendering remains available through the existing Tool UI registry
99+
100+
This is still not the final per-tool folder model, but it is no longer a large inline special-case block inside `render-message.tsx`.
101+
102+
### 6. Client auto-continuation now uses AI SDK-native completion checks
103+
104+
[chat.tsx](/Users/nick/.codex/worktrees/3a35/vana-v2/components/chat.tsx) now uses:
105+
106+
- `lastAssistantMessageIsCompleteWithToolCalls`
107+
- `addToolOutput`
108+
109+
This replaced the previous custom “fire once, rewrite request, continue” path as the normal continuation mechanism for interactive tools.
110+
111+
## Acceptance Criteria Status
112+
113+
- [x] A shared chat-agent contract exists and owns tool typing plus UI message validation.
114+
- [x] Canonical `UIMessage` storage exists and is preferred on round-trip reads.
115+
- [x] Interactive tool continuations now follow AI SDK-native completion flow in the client.
116+
- [x] Rendering is thinner than before and has a dedicated tool-part registry seam.
117+
- [x] A specialist surface exists and includes one proof fixture.
118+
- [x] Existing search, fetch, citations, guest/auth chat, canvas, and image-generation behavior still has an integration path after the migration.
119+
- [ ] A new community pattern can be dropped in with only local adapters.
120+
- Not proven yet. Phase 2 must ship the first real portability proof.
121+
- [ ] All remaining runtime ownership is agent-local.
122+
- Not finished yet. `app/api/chat/route.ts`, `create-chat-stream-response.ts`, and `researcher.ts` still coordinate too much.
123+
124+
## Validation Run
125+
126+
The phase 1 branch was verified with:
127+
128+
- `bun run typecheck`
129+
- `bun run test -- app/api/chat/__tests__/route.test.ts lib/streaming/helpers/__tests__/prepare-messages.test.ts lib/streaming/helpers/__tests__/prepare-tool-result-messages.test.ts components/chat.test.tsx components/chat-request.test.ts lib/actions/__tests__/chat.test.ts lib/utils/__tests__/message-mapping-ui-message.test.ts lib/agents/chat/__tests__/specialists.test.ts`
130+
131+
## Known Gaps And Explicit Non-Goals
132+
133+
Phase 1 intentionally did **not** complete the following:
134+
135+
- split the remaining runtime into explicit agent-owned server wrappers
136+
- convert the current flat `lib/tools/*` surface into per-tool contracts
137+
- ship a live specialist with real orchestration and renderer support
138+
- prove community portability by porting an external AI SDK pattern end to end
139+
- remove legacy compatibility paths for older stored messages
140+
141+
Those are phase 2 concerns, not phase 1 defects.
142+
143+
## Phase 2 Handoff
144+
145+
Phase 2 should treat this branch state as the baseline and should not revisit the phase 1 contract decision.
146+
147+
Phase 2 should:
148+
149+
- make the shared chat-agent contract the default path for new work
150+
- modularize real tool verticals behind local contracts
151+
- adopt canonical `ui_message` storage as the normal persisted read/write path
152+
- ship one live specialist
153+
- prove that one external AI SDK/community pattern ports in without core runtime surgery
154+
- write detailed phase 3 planning only after phase 2 acceptance criteria pass
155+
156+
The phase 2 execution document is [2026-04-23-ai-sdk-contract-standardization-phase-2.md](/Users/nick/.codex/worktrees/3a35/vana-v2/docs/superpowers/plans/2026-04-23-ai-sdk-contract-standardization-phase-2.md).

0 commit comments

Comments
 (0)