Skip to content

Align AI chat protocol with Vercel AI SDK — remove custom types and schemas - #1028

Merged
hotlong merged 9 commits into
mainfrom
copilot/remove-custom-protocol-definitions
Apr 1, 2026
Merged

Align AI chat protocol with Vercel AI SDK — remove custom types and schemas#1028
hotlong merged 9 commits into
mainfrom
copilot/remove-custom-protocol-definitions

Conversation

CopilotAI commented Apr 1, 2026

Copy link
Copy Markdown
Contributor

The spec layer defined custom AI chat types (AIMessage, AIToolCall, AIStreamEvent) and Zod schemas (AiChatRequestSchema, AiChatResponseSchema) that duplicate what the Vercel AI SDK already provides. Since the frontend uses @ai-sdk/react/useChat directly, these custom definitions create maintenance burden and potential drift.

Re-export Vercel AI SDK types as canonical

  • ModelMessage replaces AIMessage
  • ToolCallPart replaces AIToolCall
  • ToolResultPart replaces AIToolResult
  • TextStreamPart<ToolSet> replaces AIStreamEvent
  • Deprecated type aliases preserved for downstream migration
// Beforeimporttype{AIMessage,AIStreamEvent}from'@objectstack/spec/contracts';// Afterimporttype{ModelMessage,TextStreamPart,ToolSet}from'ai';// or use deprecated aliases during migration:importtype{AIMessage}from'@objectstack/spec/contracts';// = ModelMessage

Update service contracts

  • IAIService.chat(), streamChat(), chatWithTools() now accept ModelMessage[]
  • LLMAdapter methods updated similarly
  • AIConversation.messages is now ModelMessage[]
  • ChatWithToolsOptions.onToolError callback receives ToolCallPart

Remove redundant chat wire protocol

  • Removed AiChatRequestSchema / AiChatResponseSchema from protocol.zod.ts
  • Removed aiChat from IObjectStackAPI, DEFAULT_AI_ROUTES, and client SDK
  • NLQ, Suggest, Insights schemas retained (ObjectStack-specific)

Migrate packages/services/service-ai to canonical Vercel types

All 8 source files and 4 test files in service-ai have been migrated from deprecated aliases to canonical Vercel AI SDK types with proper structural alignment:

  • ToolRegistry: execute() now accepts ToolCallPart (using toolCallId, toolName, input) and returns ToolExecutionResult (extends ToolResultPart with isError?: boolean for error tracking in the tool-call loop)
  • AIService.chatWithTools(): Constructs proper AssistantModelMessage (content as Array<TextPart | ToolCallPart>) and ToolModelMessage (content as Array<ToolResultPart>)
  • MemoryLLMAdapter.streamChat(): Emits Vercel TextStreamPart<ToolSet> events with { type: 'text-delta', id, text } format
  • Conversation services: Serialize/deserialize ModelMessage discriminated union to/from flat DB columns with backward compatibility for old-format messages
  • Stream helpers: textDeltaPart() and finishPart() utility functions eliminate repeated type casts
  • All 158 service-ai tests updated and passing

Fix documentation

  • Removed AiChatRequest / AiChatResponse references from content/docs/references/api/protocol.mdx

@vercel

vercelBot commented Apr 1, 2026

Copy link
Copy Markdown

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

ProjectDeploymentActionsUpdated (UTC)
objectstack-playReadyReadyPreview, CommentApr 1, 2026 5:02am
specReadyReadyPreview, CommentApr 1, 2026 5:02am

Request Review

…and schemas
- Re-export ModelMessage, ToolCallPart, ToolResultPart, TextStreamPart from 'ai'
- Remove AiChatRequestSchema/AiChatResponseSchema (use Vercel wire protocol)
- Update IAIService/LLMAdapter to use Vercel types
- Deprecate AIMessage, AIToolCall, AIToolResult, AIStreamEvent as aliases
- Remove aiChat from IObjectStackAPI, client SDK, and DEFAULT_AI_ROUTES
- Keep NLQ/Suggest/Insights protocols (ObjectStack-specific)
- Update all tests (6772 pass)
- Update CHANGELOG.md and ROADMAP.md
Agent-Logs-Url: https://github.com/objectstack-ai/spec/sessions/2515d700-01d1-4303-8678-41f0ce9674da
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
CopilotAI changed the title [WIP] Remove custom AI chat protocol and type definitionsAlign AI chat protocol with Vercel AI SDK — remove custom types and schemasApr 1, 2026
CopilotAI requested a review from hotlongApril 1, 2026 02:56
Copilot stopped work on behalf of hotlong due to an error April 1, 2026 02:56
@hotlong

Copy link
Copy Markdown
Contributor

@copilot 评估是否已经完成了任务中要求的所有开发,继续

@hotlong

Copy link
Copy Markdown
Contributor

@copilot 继续

CopilotAIand others added 6 commits April 1, 2026 04:39
…AI SDK types
- toolCalls: {id, name, arguments} → {type, toolCallId, toolName, input}
- AIMessage → ModelMessage
- AIStreamEvent → TextStreamPart<ToolSet>
- AIToolCall → ToolCallPart
- textDelta → text
- toolCall?.name → toolName
- streamChat yields updated to Vercel AI SDK format
- onToolError assertions: name → toolName
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
… types
- AIMessage → ModelMessage
- AIToolCall → ToolCallPart
- Tool call objects: { id, name, arguments } → { type: 'tool-call', toolCallId, toolName, input }
- Tool result access: result.content → (result.output as any).value
- Assistant message assertions: .toolCalls → content-based ToolCallPart filtering
- Tool message assertions: .toolCallId/.content → content[0].toolCallId/.output.value
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
- Update objectql-conversation-service.test.ts to use ModelMessage
- Export ToolExecutionResult from tools/index.ts and service index
- Fix comment referencing AIMessage in ai-routes.ts
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
- Extract extractOutputText() helper to deduplicate error text extraction
- Replace any casts with proper type guards in objectql-conversation-service
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>

CopilotAI commented Apr 1, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot 继续

All remaining work is now complete in commit bcf879f:

  1. service-ai fully migrated — All 8 source files and 4 test files now use canonical Vercel AI SDK types (ModelMessage, ToolCallPart, ToolResultPart, TextStreamPart<ToolSet>). Zero references to deprecated aliases remain. All 158 tests pass.

  2. Documentation fixed — Removed AiChatRequest/AiChatResponse references from protocol.mdx.

  3. Code review feedback addressed — Extracted textDeltaPart()/finishPart() helpers, improved type narrowing in tests, removed redundant Array.isArray() checks.

@hotlong
hotlong marked this pull request as ready for review April 1, 2026 05:02
CopilotAI review requested due to automatic review settings April 1, 2026 05:02
@hotlong
hotlong merged commit 37c0f8e into mainApr 1, 2026
3 of 4 checks passed

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR aligns ObjectStack’s AI chat contracts and related runtime/service code with the canonical Vercel AI SDK (ai) message/tool/streaming types, removing the duplicated “AiChat” wire protocol and migrating downstream usage to Vercel’s discriminated unions.

Changes:

  • Re-export Vercel AI SDK types in @objectstack/spec/contracts and update IAIService / LLMAdapter signatures to use ModelMessage[] and TextStreamPart<ToolSet>.
  • Remove AiChatRequestSchema / AiChatResponseSchema and the aiChat method/route/client surface area from the ObjectStack protocol layer.
  • Migrate @objectstack/service-ai tool calling, conversation persistence, and streaming helpers to Vercel AI SDK message/part shapes.

Reviewed changes

Copilot reviewed 27 out of 28 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
ROADMAP.mdBumps “Last Updated” date to reflect protocol changes.
pnpm-lock.yamlLocks new ai dependency and its transitive packages.
packages/spec/src/contracts/llm-adapter.tsSwitches adapter contract to Vercel ModelMessage + TextStreamPart<ToolSet>.
packages/spec/src/contracts/llm-adapter.test.tsUpdates contract tests to compile against Vercel stream/message types.
packages/spec/src/contracts/ai-service.tsRe-exports canonical Vercel types; preserves deprecated aliases; updates service contracts.
packages/spec/src/contracts/ai-service.test.tsUpdates contract tests for Vercel message/stream/tool-part shapes.
packages/spec/src/api/protocol.zod.tsRemoves AiChat request/response schemas and aiChat from protocol interface.
packages/spec/src/api/protocol.test.tsRemoves AiChat schema validation assertions.
packages/spec/src/api/plugin-rest-api.zod.tsRemoves aiChat from default AI REST route registration.
packages/spec/src/api/plugin-rest-api.test.tsUpdates expectations for removed aiChat endpoint.
packages/spec/package.jsonAdds ai dependency to spec for type re-exports.
packages/services/service-ai/src/tools/tool-registry.tsMigrates tool execution to ToolCallPart input + ToolResultPart output (ToolExecutionResult).
packages/services/service-ai/src/tools/index.tsExports ToolExecutionResult type.
packages/services/service-ai/src/routes/ai-routes.tsUpdates route typing/casts to ModelMessage.
packages/services/service-ai/src/routes/agent-routes.tsUpdates agent chat route message typing to ModelMessage.
packages/services/service-ai/src/index.tsRe-exports new tool execution result type.
packages/services/service-ai/src/conversation/objectql-conversation-service.tsSerializes/deserializes Vercel ModelMessage union into flat DB columns.
packages/services/service-ai/src/conversation/in-memory-conversation-service.tsUpdates conversation message type to ModelMessage.
packages/services/service-ai/src/ai-service.tsMigrates chat/tool-call loop + streaming helpers to Vercel message/stream part formats.
packages/services/service-ai/src/agent-runtime.tsUpdates system message construction to ModelMessage.
packages/services/service-ai/src/adapters/memory-adapter.tsStreams Vercel TextStreamPart<ToolSet> and handles non-string message content safely.
packages/services/service-ai/src/tests/objectql-conversation-service.test.tsUpdates persistence tests for Vercel message union shapes.
packages/services/service-ai/src/tests/chatbot-features.test.tsUpdates tool-calling tests to Vercel tool-call/tool-result parts.
packages/services/service-ai/src/tests/auth-and-toolcalling.test.tsUpdates streaming/tool-loop tests to Vercel stream parts + tool call parts.
packages/services/service-ai/src/tests/ai-service.test.tsUpdates AIService + ToolRegistry tests to new types and stream part fields.
packages/client/src/index.tsRemoves client ai.chat() method and associated exported types.
content/docs/references/api/protocol.mdxRemoves AiChat protocol docs and references in TypeScript usage snippet.
CHANGELOG.mdDocuments the migration/removal and new ai dependency.
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

Comment on lines 71 to 75
/**
* Validate that `raw` is a well-formed AIMessage.
* Validate that `raw` is a well-formed message.
* Returns null on success, or an error string on failure.
*/
function validateMessage(raw: unknown): string | null {

CopilotAIApr 1, 2026

Copy link

Choose a reason for hiding this comment

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

validateMessage() is still written for the old flat message shape (it assumes content is always a string). With the switch to Vercel ModelMessage, assistant.content can be an array of parts (including tool-call parts) and tool.content is an array of tool-result parts, so this validator will reject valid tool-calling conversations and/or force unsafe casts downstream. Please update validation to be role-aware (system/user: string; assistant: string | parts[]; tool: tool-result parts[]) or validate against Vercel AI SDK message structures before invoking aiService/conversationService.

Copilot uses AI. Check for mistakes.
Comment on lines +126 to 128
"ai": "^6.0.142",
"zod": "^4.3.6"
},

CopilotAIApr 1, 2026

Copy link

Choose a reason for hiding this comment

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

Adding ai as a direct dependency pulls in transitive packages with stricter Node engine requirements (e.g. @vercel/oidc declares node >= 20 in the lockfile). This is inconsistent with the repo/package engines (node >=18) and can break installs in engine-strict environments or cause runtime incompatibilities. Consider (a) verifying the project’s supported Node version and bumping engines.node accordingly, or (b) switching to an ai version whose transitive deps support Node 18, or (c) moving ai to a peer dependency (with clear install guidance) since it’s only needed for type re-exports.

Suggested change
"ai": "^6.0.142",
"zod": "^4.3.6"
},
"zod": "^4.3.6"
},
"peerDependencies": {
"ai": "^6.0.142"
},

Copilot uses AI. Check for mistakes.
Comment threadpnpm-lock.yaml
Comment on lines +3453 to +3456
'@vercel/oidc@3.1.0':
resolution: {integrity: sha512-Fw28YZpRnA3cAHHDlkt7xQHiJ0fcL+NRcIqsocZQUSmbzeIKRpwttJjik5ZGanXP+vlA4SbTg+AbA3bP363l+w==}
engines: {node: '>= 20'}

CopilotAIApr 1, 2026

Copy link

Choose a reason for hiding this comment

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

This lockfile now includes @vercel/oidc@3.1.0 with engines: { node: '>= 20' } as a transitive dependency of ai. That conflicts with the repo’s declared Node support (>=18) and may fail CI or consumer installs when engines are enforced. Please either align the repo/package engines.node to >=20 or adjust the ai dependency strategy/version to avoid pulling Node>=20-only transitive deps.

Copilot uses AI. Check for mistakes.
Sign up for freeto 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.

AI chat协议与数据结构完全对齐Vercel/ai(移除自定义协议与类型定义)

3 participants

@hotlong