-
-
Notifications
You must be signed in to change notification settings - Fork 113
feat: Add Z.AI adapter (@tanstack/ai-zai) and update examples
#227
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Add new @tanstack/ai-zai package with Z.AI adapter implementation. Includes: - Text adapter for GLM-4.7, GLM-4.6V and GLM-4.6 models - Streaming chat completions with content and tool call chunks - Error handling and type safety - Integration with existing TanStack AI ecosystem - Tests and documentation
- Replace unsafe type assertions with proper type guards and checks - Simplify error handling logic in mapZAIErrorToStreamChunk - Update README with clearer OpenAI compatibility details - Add proper type constraints for ZAITextAdapter model types - Clean up request header and signal handling
…ion tools Implement tool support for Z.AI with web search and function tools, including tool conversion utilities and type definitions. Add subpath export for tools in package.json and update documentation with new features. Add summarization adapter with streaming support and update README with examples for web search, thinking mode, and tool streaming features. Move API key utility to shared client utils.
- Add zai provider to model selection in vue and svelte examples - Include zai-text in chat server implementations - Update package.json dependencies for zai integration - Remove unused ZAITextOptionsMinimal interface - Add tools entry point in ai-zai vite config
📝 WalkthroughWalkthroughAdds a new Changes
Sequence Diagram(s)sequenceDiagram
participant User as App / Client
participant Adapter as ZAITextAdapter
participant ClientAPI as OpenAI Client (Z.AI endpoint)
participant Parser as Stream Processor
User->>Adapter: call chatStream(options)
Adapter->>Adapter: map options → ZAI request
Adapter->>ClientAPI: POST /chat/completions (stream=true)
ClientAPI-->>Adapter: stream of completion chunks
Adapter->>Parser: process chunks (accumulate deltas, detect tool_calls)
Parser-->>Adapter: emit StreamChunk events (content, tool_call, done/error)
Adapter-->>User: yield StreamChunk stream
Estimated code review effort🎯 4 (Complex) | ⏱️ ~55 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
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. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 7
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
examples/ts-svelte-chat/src/routes/api/chat/+server.ts (1)
27-29: Missing ZAI_API_KEY environment variable setup.Other adapters have their API keys populated from SvelteKit's environment variables (lines 27-29), but Z.AI is missing. The adapter will fail at runtime if
process.env.ZAI_API_KEYisn't set externally.Proposed fix
if (env.OPENAI_API_KEY) process.env.OPENAI_API_KEY = env.OPENAI_API_KEY if (env.ANTHROPIC_API_KEY) process.env.ANTHROPIC_API_KEY = env.ANTHROPIC_API_KEY if (env.GEMINI_API_KEY) process.env.GEMINI_API_KEY = env.GEMINI_API_KEY +if (env.ZAI_API_KEY) process.env.ZAI_API_KEY = env.ZAI_API_KEYAlso applies to: 50-53
🤖 Fix all issues with AI agents
In `@examples/ts-react-chat/src/lib/model-selection.ts`:
- Around line 94-98: Fix the label typo in the model entry where provider: 'zai'
and model: 'glm-4.6' by changing label from 'Z.A.I - GLM-4.6' to 'Z.AI -
GLM-4.6' so it matches the other Z.AI entries; update the label property in that
object within model-selection.ts.
In `@examples/ts-svelte-chat/src/lib/model-selection.ts`:
- Line 1: The Provider union includes 'zai' but MODEL_OPTIONS does not; add Z.AI
model option objects to the MODEL_OPTIONS array (same shape as other entries:
label, value, provider) so the 'zai' provider appears in the UI selector. Insert
the new Z.AI entries alongside the existing providers (e.g., after the Ollama
section) and ensure each entry sets provider: 'zai' and uses unique value
strings matching the Z.AI model identifiers used elsewhere.
In `@packages/typescript/ai-zai/src/adapters/text.ts`:
- Around line 187-198: The loop handling messages where message.role === 'tool'
currently sets tool_call_id to an empty string when message.toolCallId is
missing, which can cause API errors; update the handling in the messages
iteration (the branch that builds objects with role: 'tool' and tool_call_id) to
validate message.toolCallId and either throw an explicit error or log a warning
and skip the message instead of using an empty string, ensuring the constructed
tool result always includes a valid tool_call_id.
In `@packages/typescript/ai-zai/src/text/text-provider-options.ts`:
- Around line 93-96: The JSDoc for the effort property is out of sync with the
ReasoningEffort type: update the comment on the effort?: ReasoningEffort
declaration to list the actual allowed values (including 'minimal') or remove
'minimal' from the ReasoningEffort type so both match; locate the
ReasoningEffort type definition and the effort property in
text-provider-options.ts and make the two consistent.
In `@packages/typescript/ai-zai/tests/zai-adapter.test.ts`:
- Around line 231-252: The adapter currently drops image parts unconditionally;
update ZAITextAdapter.convertMessagesToInput to check the target model's
capabilities (use the model-meta.ts lookup for model id 'glm-4.6v' or the
adapter's modelId) and only strip image/video parts for text-only models; when
the model's meta contentTypes includes 'image' or 'video', preserve and pass
through those parts in the converted message payload (and add a test case for
'glm-4.6v' that asserts image parts are kept).
In `@testing/panel/.env.example`:
- Line 22: The file ending with the line "# OLLAMA_HOST=http://localhost:11434"
is missing a trailing newline; open the testing/panel/.env.example file and add
a single blank line (a newline character) at EOF so the file ends with an empty
line.
- Around line 5-7: Update the example comment for Z.AI API key to point users
directly to the API key management page: replace the URL comment line
referencing "https://docs.z.ai/" with "https://z.ai/manage-apikey/apikey-list"
(or optionally "https://docs.z.ai/api-reference/" if you prefer linking to
docs); leave the ZAI_API_KEY variable name intact so the example env key remains
unchanged.
🧹 Nitpick comments (13)
packages/typescript/ai-zai/src/text/text-provider-options.ts (1)
168-184: Consider naming consistency foracceptLanguage.This property uses camelCase while other properties throughout the file use snake_case (e.g.,
previous_response_id,parallel_tool_calls,tool_choice). If this is intentional becauseacceptLanguageis a client-side header config rather than an API body parameter, consider adding a brief comment to clarify.💡 Suggested clarification
/** * Accept-Language header for Z.AI API. + * (Client-side configuration, not sent in request body) * `@default` 'en-US,en' */ acceptLanguage?: stringAlternatively, rename for consistency:
- acceptLanguage?: string + accept_language?: stringpackages/typescript/ai-zai/README.md (1)
17-17: Minor grammar fix: hyphenate compound modifier.Per static analysis, "AI specific" should be hyphenated when used as a compound modifier.
📝 Suggested fix
-- Supports Zhipu AI specific features like **Web Search**, **Thinking Mode**, and **Tool Streaming** +- Supports Zhipu AI-specific features like **Web Search**, **Thinking Mode**, and **Tool Streaming**packages/typescript/ai-zai/src/tools/function-tool.ts (1)
24-31: Note on theas anycast.The cast on line 29 is necessary due to OpenAI SDK's strict
FunctionParameterstype. This is acceptable for an adapter conversion layer. If stricter type safety is desired in the future, consider creating a dedicated type that matches OpenAI's expectations exactly.packages/typescript/ai-zai/src/message-types.ts (1)
36-52: Consider the empty interface lint warnings.The static analyzer flags
ZAIVideoMetadata,ZAIDocumentMetadata, andZAITextMetadataas empty interfaces equivalent to{}. While this is technically true, these interfaces serve as explicit type placeholders inZAIMessageMetadataByModalityand allow future extension via declaration merging.If declaration merging isn't needed, you could use type aliases instead:
♻️ Optional: Convert to type aliases
-/** - * Metadata for Z.AI video content parts. - * Note: Video support in Z.AI may vary; check current API capabilities. - */ -export interface ZAIVideoMetadata {} +/** + * Metadata for Z.AI video content parts. + * Note: Video support in Z.AI may vary; check current API capabilities. + */ +export type ZAIVideoMetadata = Record<string, never> -/** - * Metadata for Z.AI document content parts. - * Note: Direct document support may vary; PDFs often need to be converted to images. - */ -export interface ZAIDocumentMetadata {} +/** + * Metadata for Z.AI document content parts. + * Note: Direct document support may vary; PDFs often need to be converted to images. + */ +export type ZAIDocumentMetadata = Record<string, never> -/** - * Metadata for Z.AI text content parts. - * Currently no specific metadata options for text in Z.AI. - */ -export interface ZAITextMetadata {} +/** + * Metadata for Z.AI text content parts. + * Currently no specific metadata options for text in Z.AI. + */ +export type ZAITextMetadata = Record<string, never>If you intend to support declaration merging for future extensibility, keeping interfaces is valid—just suppress the lint rule for these lines.
packages/typescript/ai-zai/tests/model-meta.test.ts (1)
11-22: Consider strengthening the type coverage test.The current test validates that specific model names are valid
Keys, but the assertions on lines 17 and 21 don't add meaningful runtime verification—they're effectively testing constants.A more robust approach would be to verify completeness by checking that the number of type-safe keys matches the runtime model count:
Optional enhancement
it('ZAIModelMap includes all supported models', () => { type Keys = keyof ZAIModelMap const a: Keys = 'glm-4.7' const b: Keys = 'glm-4.6v' const c: Keys = 'glm-4.6' - expect([a, b, c].length).toBe(3) + // Verify all models are accounted for + const typeSafeModels: Keys[] = [a, b, c] + expect(typeSafeModels.length).toBe(ZAI_CHAT_MODELS.length) // `@ts-expect-error` invalid model name is not part of Keys const _invalid: Keys = 'not-a-real-model' - expect(_invalid).toBe('not-a-real-model') + // ts-expect-error above is the actual test; runtime assertion is optional + void _invalid })examples/ts-svelte-chat/src/routes/api/chat/+server.ts (1)
106-106: Consider a more targeted type assertion.The
as anycast discards all type information. While dynamic provider selection makes full type safety challenging, a union type or generic approach would preserve some safety.Alternative approach
- const options = adapterConfig[provider]() as any + const options = adapterConfig[provider]()If the type errors persist, consider typing
adapterConfigwith a return type union or usingReturnType<typeof adapterConfig[Provider]>.packages/typescript/ai-zai/tests/zai-adapter.integration.test.ts (1)
324-380: Consider reducingas anycasts for type safety.Multiple tests use
as anycasts (lines 290, 353). While acceptable for integration tests, consider:
- Extending the adapter's type definitions to support
abortControllerin options- Using type guards instead of casts where possible
This is optional cleanup that could improve maintainability.
examples/ts-solid-chat/src/routes/api.chat.ts (1)
52-74: Consider adding ZAI_API_KEY validation for consistent error messaging.The Anthropic branch validates the API key and returns a user-friendly error (lines 55-66), but the Z.AI branch relies on the adapter to throw. While functional, this creates inconsistent error experiences.
♻️ Optional: Add similar API key check for zai
if (provider === 'zai') { + if (!process.env.ZAI_API_KEY) { + return new Response( + JSON.stringify({ + error: + 'ZAI_API_KEY not configured. Please add it to .env or .env.local', + }), + { + status: 500, + headers: { 'Content-Type': 'application/json' }, + }, + ) + } adapter = zaiText(model) } else {packages/typescript/ai-zai/src/tools/web-search-tool.ts (2)
3-12: Type aliasWebSearchToolappears redundant.The type alias
WebSearchTool = ZaiWebSearchToolon line 12 adds no semantic value. Consider removing it to reduce API surface, or if it's intended as a public-facing alias with different semantics, add a clarifying comment.
17-25: Unsafe type cast ontool.metadatawithout validation.The cast
tool.metadata as ZaiWebSearchTool['web_search']on line 20 assumes the metadata conforms to the expected shape. If a genericToolwith different metadata is passed, this produces an invalidZaiWebSearchToolsilently.Consider adding a type guard or runtime check:
♻️ Suggested improvement
+function isWebSearchMetadata( + metadata: unknown, +): metadata is ZaiWebSearchTool['web_search'] { + if (metadata === undefined) return true + if (typeof metadata !== 'object' || metadata === null) return false + const m = metadata as Record<string, unknown> + return ( + (m.enable === undefined || typeof m.enable === 'boolean') && + (m.search_query === undefined || typeof m.search_query === 'string') && + (m.search_result === undefined || typeof m.search_result === 'boolean') + ) +} + export function convertWebSearchToolToAdapterFormat( tool: Tool, ): ZaiWebSearchTool { - const metadata = tool.metadata as ZaiWebSearchTool['web_search'] + const metadata = isWebSearchMetadata(tool.metadata) ? tool.metadata : undefined return { type: 'web_search', web_search: metadata, } }packages/typescript/ai-zai/src/model-meta.ts (1)
199-218: Consider DRY improvement for repeated provider options type.The same intersection type (
ZAIBaseOptions & ZAIReasoningOptions & ...) is repeated for all three models inZAIModelMap. If all models share identical provider options, consider extracting a type alias:♻️ Suggested simplification
+type ZAICommonProviderOptions = ZAIBaseOptions & + ZAIReasoningOptions & + ZAIStructuredOutputOptions & + ZAIToolsOptions & + ZAIStreamingOptions & + ZAIMetadataOptions + export type ZAIModelMap = { - [GLM_4_7.name]: ZAIBaseOptions & - ZAIReasoningOptions & - ZAIStructuredOutputOptions & - ZAIToolsOptions & - ZAIStreamingOptions & - ZAIMetadataOptions - [GLM_4_6V.name]: ZAIBaseOptions & - ZAIReasoningOptions & - ZAIStructuredOutputOptions & - ZAIToolsOptions & - ZAIStreamingOptions & - ZAIMetadataOptions - [GLM_4_6.name]: ZAIBaseOptions & - ZAIReasoningOptions & - ZAIStructuredOutputOptions & - ZAIToolsOptions & - ZAIStreamingOptions & - ZAIMetadataOptions + [GLM_4_7.name]: ZAICommonProviderOptions + [GLM_4_6V.name]: ZAICommonProviderOptions + [GLM_4_6.name]: ZAICommonProviderOptions }This also future-proofs the code: if model-specific options diverge later, you can selectively override individual entries.
packages/typescript/ai-zai/src/adapters/text.ts (2)
111-117: Consider avoiding double type casting.The
as anyfollowed by property assignment and thenas StreamChunkis fragile. IfmapZAIErrorToStreamChunkalready returns a properly typed error chunk, consider having it accept the additional metadata as parameters.♻️ Suggested approach
} catch (error: unknown) { - const chunk = mapZAIErrorToStreamChunk(error) as any - chunk.id = fallbackId - chunk.model = options.model - chunk.timestamp = timestamp - yield chunk as StreamChunk + yield { + ...mapZAIErrorToStreamChunk(error), + id: fallbackId, + model: options.model, + timestamp, + } as StreamChunk }
304-342: Other finish reasons are mapped to 'stop'.The logic maps
finish_reasonto either'tool_calls'or'stop', but the API may return other values like'length'(max tokens reached) or'content_filter'. Consider preserving the original finish reason when it's not a tool call scenario.♻️ Preserve original finish reason
if (choice.finish_reason) { const isToolTurn = choice.finish_reason === 'tool_calls' || toolCallsInProgress.size > 0 if (isToolTurn) { for (const [index, toolCall] of toolCallsInProgress) { yield { type: 'tool_call', id: responseId, model: responseModel, timestamp, index, toolCall: { id: toolCall.id, type: 'function', function: { name: toolCall.name, arguments: toolCall.arguments, }, }, } } } yield { type: 'done', id: responseId, model: responseModel, timestamp, - finishReason: isToolTurn ? 'tool_calls' : 'stop', + finishReason: isToolTurn ? 'tool_calls' : (choice.finish_reason || 'stop'), usage: chunk.usage ? { promptTokens: chunk.usage.prompt_tokens || 0, completionTokens: chunk.usage.completion_tokens || 0, totalTokens: chunk.usage.total_tokens || 0, } : undefined, } }
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (40)
examples/ts-group-chat/chat-server/claude-service.tsexamples/ts-group-chat/package.jsonexamples/ts-react-chat/package.jsonexamples/ts-react-chat/src/lib/model-selection.tsexamples/ts-react-chat/src/routes/api.tanchat.tsexamples/ts-solid-chat/package.jsonexamples/ts-solid-chat/src/routes/api.chat.tsexamples/ts-svelte-chat/package.jsonexamples/ts-svelte-chat/src/lib/model-selection.tsexamples/ts-svelte-chat/src/routes/api/chat/+server.tsexamples/ts-vue-chat/package.jsonexamples/ts-vue-chat/src/lib/model-selection.tsexamples/ts-vue-chat/vite.config.tspackages/typescript/ai-zai/CHANGELOG.mdpackages/typescript/ai-zai/README.mdpackages/typescript/ai-zai/package.jsonpackages/typescript/ai-zai/src/adapters/index.tspackages/typescript/ai-zai/src/adapters/summarize.tspackages/typescript/ai-zai/src/adapters/text.tspackages/typescript/ai-zai/src/index.tspackages/typescript/ai-zai/src/message-types.tspackages/typescript/ai-zai/src/model-meta.tspackages/typescript/ai-zai/src/text/text-provider-options.tspackages/typescript/ai-zai/src/tools/function-tool.tspackages/typescript/ai-zai/src/tools/index.tspackages/typescript/ai-zai/src/tools/tool-choice.tspackages/typescript/ai-zai/src/tools/tool-converter.tspackages/typescript/ai-zai/src/tools/web-search-tool.tspackages/typescript/ai-zai/src/utils/client.tspackages/typescript/ai-zai/src/utils/conversion.tspackages/typescript/ai-zai/tests/model-meta.test.tspackages/typescript/ai-zai/tests/zai-adapter.integration.test.tspackages/typescript/ai-zai/tests/zai-adapter.test.tspackages/typescript/ai-zai/tests/zai-factory.test.tspackages/typescript/ai-zai/tsconfig.jsonpackages/typescript/ai-zai/vite.config.tstesting/panel/.env.exampletesting/panel/package.jsontesting/panel/src/lib/model-selection.tstesting/panel/src/routes/api.chat.ts
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Use tree-shakeable adapter architecture for provider implementations - export specialized adapters (text, embedding, summarize, image) as separate imports from/adapterssubpath rather than monolithic adapters
Use Zod for runtime schema validation and type inference, particularly for tool input/output definitions withtoolDefinition()and Zod schema inference
Implement isomorphic tool system usingtoolDefinition()with.server()and.client()implementations for dual-environment execution
Use type-safe per-model configuration with provider options typed based on selected model to ensure compile-time safety
Implement stream processing with StreamProcessor for handling chunked responses and support partial JSON parsing for streaming AI responses
Files:
examples/ts-group-chat/chat-server/claude-service.tsexamples/ts-svelte-chat/src/lib/model-selection.tspackages/typescript/ai-zai/src/tools/index.tstesting/panel/src/lib/model-selection.tspackages/typescript/ai-zai/src/tools/tool-choice.tspackages/typescript/ai-zai/tests/zai-factory.test.tspackages/typescript/ai-zai/tests/zai-adapter.test.tsexamples/ts-vue-chat/vite.config.tspackages/typescript/ai-zai/src/tools/function-tool.tsexamples/ts-react-chat/src/lib/model-selection.tspackages/typescript/ai-zai/src/message-types.tsexamples/ts-vue-chat/src/lib/model-selection.tspackages/typescript/ai-zai/src/tools/web-search-tool.tsexamples/ts-solid-chat/src/routes/api.chat.tspackages/typescript/ai-zai/src/utils/conversion.tspackages/typescript/ai-zai/src/tools/tool-converter.tsexamples/ts-react-chat/src/routes/api.tanchat.tspackages/typescript/ai-zai/src/index.tstesting/panel/src/routes/api.chat.tspackages/typescript/ai-zai/src/utils/client.tspackages/typescript/ai-zai/src/adapters/summarize.tspackages/typescript/ai-zai/tests/zai-adapter.integration.test.tspackages/typescript/ai-zai/src/text/text-provider-options.tsexamples/ts-svelte-chat/src/routes/api/chat/+server.tspackages/typescript/ai-zai/src/adapters/text.tspackages/typescript/ai-zai/vite.config.tspackages/typescript/ai-zai/src/adapters/index.tspackages/typescript/ai-zai/src/model-meta.tspackages/typescript/ai-zai/tests/model-meta.test.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use camelCase for function and variable names throughout the codebase
Files:
examples/ts-group-chat/chat-server/claude-service.tsexamples/ts-svelte-chat/src/lib/model-selection.tspackages/typescript/ai-zai/src/tools/index.tstesting/panel/src/lib/model-selection.tspackages/typescript/ai-zai/src/tools/tool-choice.tspackages/typescript/ai-zai/tests/zai-factory.test.tspackages/typescript/ai-zai/tests/zai-adapter.test.tsexamples/ts-vue-chat/vite.config.tspackages/typescript/ai-zai/src/tools/function-tool.tsexamples/ts-react-chat/src/lib/model-selection.tspackages/typescript/ai-zai/src/message-types.tsexamples/ts-vue-chat/src/lib/model-selection.tspackages/typescript/ai-zai/src/tools/web-search-tool.tsexamples/ts-solid-chat/src/routes/api.chat.tspackages/typescript/ai-zai/src/utils/conversion.tspackages/typescript/ai-zai/src/tools/tool-converter.tsexamples/ts-react-chat/src/routes/api.tanchat.tspackages/typescript/ai-zai/src/index.tstesting/panel/src/routes/api.chat.tspackages/typescript/ai-zai/src/utils/client.tspackages/typescript/ai-zai/src/adapters/summarize.tspackages/typescript/ai-zai/tests/zai-adapter.integration.test.tspackages/typescript/ai-zai/src/text/text-provider-options.tsexamples/ts-svelte-chat/src/routes/api/chat/+server.tspackages/typescript/ai-zai/src/adapters/text.tspackages/typescript/ai-zai/vite.config.tspackages/typescript/ai-zai/src/adapters/index.tspackages/typescript/ai-zai/src/model-meta.tspackages/typescript/ai-zai/tests/model-meta.test.ts
examples/**
📄 CodeRabbit inference engine (CLAUDE.md)
Examples are not built by Nx and should be run independently from their directories with
pnpm devorpnpm install && pnpm dev
Files:
examples/ts-group-chat/chat-server/claude-service.tsexamples/ts-svelte-chat/src/lib/model-selection.tsexamples/ts-react-chat/package.jsonexamples/ts-vue-chat/vite.config.tsexamples/ts-react-chat/src/lib/model-selection.tsexamples/ts-vue-chat/src/lib/model-selection.tsexamples/ts-solid-chat/src/routes/api.chat.tsexamples/ts-react-chat/src/routes/api.tanchat.tsexamples/ts-group-chat/package.jsonexamples/ts-svelte-chat/package.jsonexamples/ts-vue-chat/package.jsonexamples/ts-solid-chat/package.jsonexamples/ts-svelte-chat/src/routes/api/chat/+server.ts
**/*.test.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Write unit tests using Vitest alongside source files with
.test.tsnaming convention
Files:
packages/typescript/ai-zai/tests/zai-factory.test.tspackages/typescript/ai-zai/tests/zai-adapter.test.tspackages/typescript/ai-zai/tests/zai-adapter.integration.test.tspackages/typescript/ai-zai/tests/model-meta.test.ts
packages/typescript/*/src/index.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Export tree-shakeable adapters with clear subpath exports in package.json (e.g.,
@tanstack/ai/adapters,@tanstack/ai-openai/adapters) to minimize bundle size
Files:
packages/typescript/ai-zai/src/index.ts
packages/typescript/*/src/adapters/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Create individual adapter implementations for each provider capability (text, embed, summarize, image) with separate exports to enable tree-shaking
Files:
packages/typescript/ai-zai/src/adapters/summarize.tspackages/typescript/ai-zai/src/adapters/text.tspackages/typescript/ai-zai/src/adapters/index.ts
packages/typescript/*/src/model-meta.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Maintain model metadata files that define provider options and capabilities per model for per-model type safety
Files:
packages/typescript/ai-zai/src/model-meta.ts
🧠 Learnings (19)
📓 Common learnings
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to packages/typescript/*/src/index.ts : Export tree-shakeable adapters with clear subpath exports in package.json (e.g., `tanstack/ai/adapters`, `tanstack/ai-openai/adapters`) to minimize bundle size
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to packages/typescript/*/src/adapters/*.ts : Create individual adapter implementations for each provider capability (text, embed, summarize, image) with separate exports to enable tree-shaking
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Implement framework integrations using the headless `tanstack/ai-client` for state management with framework-specific hooks (useChat) on top
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to **/*.{ts,tsx} : Use tree-shakeable adapter architecture for provider implementations - export specialized adapters (text, embedding, summarize, image) as separate imports from `/adapters` subpath rather than monolithic adapters
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to **/*.{ts,tsx} : Implement stream processing with StreamProcessor for handling chunked responses and support partial JSON parsing for streaming AI responses
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to **/*.{ts,tsx} : Use type-safe per-model configuration with provider options typed based on selected model to ensure compile-time safety
Applied to files:
examples/ts-svelte-chat/src/lib/model-selection.tstesting/panel/src/lib/model-selection.tsexamples/ts-vue-chat/vite.config.tsexamples/ts-react-chat/src/lib/model-selection.tsexamples/ts-vue-chat/src/lib/model-selection.tspackages/typescript/ai-zai/src/text/text-provider-options.tsexamples/ts-svelte-chat/src/routes/api/chat/+server.tspackages/typescript/ai-zai/src/model-meta.ts
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to packages/typescript/*/src/model-meta.ts : Maintain model metadata files that define provider options and capabilities per model for per-model type safety
Applied to files:
examples/ts-svelte-chat/src/lib/model-selection.tstesting/panel/src/lib/model-selection.tsexamples/ts-vue-chat/vite.config.tsexamples/ts-react-chat/src/lib/model-selection.tspackages/typescript/ai-zai/src/message-types.tsexamples/ts-vue-chat/src/lib/model-selection.tsexamples/ts-solid-chat/src/routes/api.chat.tspackages/typescript/ai-zai/src/tools/tool-converter.tspackages/typescript/ai-zai/src/index.tspackages/typescript/ai-zai/src/text/text-provider-options.tsexamples/ts-svelte-chat/src/routes/api/chat/+server.tspackages/typescript/ai-zai/src/adapters/index.tspackages/typescript/ai-zai/src/model-meta.tspackages/typescript/ai-zai/tests/model-meta.test.ts
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to packages/typescript/*/src/adapters/*.ts : Create individual adapter implementations for each provider capability (text, embed, summarize, image) with separate exports to enable tree-shaking
Applied to files:
examples/ts-svelte-chat/src/lib/model-selection.tspackages/typescript/ai-zai/src/tools/index.tstesting/panel/src/lib/model-selection.tspackages/typescript/ai-zai/tests/zai-factory.test.tspackages/typescript/ai-zai/tests/zai-adapter.test.tsexamples/ts-vue-chat/vite.config.tspackages/typescript/ai-zai/src/tools/function-tool.tsexamples/ts-react-chat/src/lib/model-selection.tsexamples/ts-vue-chat/src/lib/model-selection.tspackages/typescript/ai-zai/src/tools/web-search-tool.tsexamples/ts-solid-chat/src/routes/api.chat.tspackages/typescript/ai-zai/src/tools/tool-converter.tsexamples/ts-react-chat/src/routes/api.tanchat.tspackages/typescript/ai-zai/src/index.tspackages/typescript/ai-zai/package.jsonpackages/typescript/ai-zai/README.mdtesting/panel/src/routes/api.chat.tspackages/typescript/ai-zai/src/adapters/summarize.tspackages/typescript/ai-zai/tests/zai-adapter.integration.test.tspackages/typescript/ai-zai/src/text/text-provider-options.tspackages/typescript/ai-zai/tsconfig.jsonexamples/ts-svelte-chat/src/routes/api/chat/+server.tspackages/typescript/ai-zai/src/adapters/text.tspackages/typescript/ai-zai/src/adapters/index.tspackages/typescript/ai-zai/CHANGELOG.md
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to **/*.{ts,tsx} : Use tree-shakeable adapter architecture for provider implementations - export specialized adapters (text, embedding, summarize, image) as separate imports from `/adapters` subpath rather than monolithic adapters
Applied to files:
examples/ts-svelte-chat/src/lib/model-selection.tspackages/typescript/ai-zai/tests/zai-factory.test.tspackages/typescript/ai-zai/tests/zai-adapter.test.tsexamples/ts-vue-chat/vite.config.tsexamples/ts-solid-chat/src/routes/api.chat.tspackages/typescript/ai-zai/src/tools/tool-converter.tsexamples/ts-react-chat/src/routes/api.tanchat.tspackages/typescript/ai-zai/src/index.tspackages/typescript/ai-zai/package.jsontesting/panel/src/routes/api.chat.tspackages/typescript/ai-zai/src/adapters/summarize.tspackages/typescript/ai-zai/tests/zai-adapter.integration.test.tspackages/typescript/ai-zai/src/text/text-provider-options.tsexamples/ts-svelte-chat/src/routes/api/chat/+server.tspackages/typescript/ai-zai/src/adapters/text.tspackages/typescript/ai-zai/src/adapters/index.tspackages/typescript/ai-zai/CHANGELOG.md
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Ensure provider-agnostic design where the core AI SDK remains independent of any specific AI provider implementation
Applied to files:
examples/ts-svelte-chat/src/lib/model-selection.tstesting/panel/src/lib/model-selection.tsexamples/ts-react-chat/src/lib/model-selection.tsexamples/ts-vue-chat/src/lib/model-selection.ts
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to packages/typescript/*/src/index.ts : Export tree-shakeable adapters with clear subpath exports in package.json (e.g., `tanstack/ai/adapters`, `tanstack/ai-openai/adapters`) to minimize bundle size
Applied to files:
packages/typescript/ai-zai/src/tools/index.tstesting/panel/package.jsonexamples/ts-react-chat/package.jsonpackages/typescript/ai-zai/src/tools/tool-choice.tspackages/typescript/ai-zai/tests/zai-adapter.test.tspackages/typescript/ai-zai/src/tools/web-search-tool.tsexamples/ts-solid-chat/src/routes/api.chat.tspackages/typescript/ai-zai/src/tools/tool-converter.tsexamples/ts-react-chat/src/routes/api.tanchat.tspackages/typescript/ai-zai/src/index.tspackages/typescript/ai-zai/package.jsonpackages/typescript/ai-zai/README.mdexamples/ts-group-chat/package.jsonpackages/typescript/ai-zai/src/adapters/summarize.tsexamples/ts-svelte-chat/package.jsonpackages/typescript/ai-zai/tests/zai-adapter.integration.test.tspackages/typescript/ai-zai/tsconfig.jsonexamples/ts-vue-chat/package.jsonexamples/ts-solid-chat/package.jsonexamples/ts-svelte-chat/src/routes/api/chat/+server.tspackages/typescript/ai-zai/src/adapters/text.tspackages/typescript/ai-zai/vite.config.tspackages/typescript/ai-zai/src/adapters/index.tspackages/typescript/ai-zai/CHANGELOG.md
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to **/*.{ts,tsx} : Implement isomorphic tool system using `toolDefinition()` with `.server()` and `.client()` implementations for dual-environment execution
Applied to files:
packages/typescript/ai-zai/src/tools/index.tspackages/typescript/ai-zai/src/tools/tool-choice.tspackages/typescript/ai-zai/src/tools/function-tool.tspackages/typescript/ai-zai/src/tools/web-search-tool.tspackages/typescript/ai-zai/src/tools/tool-converter.ts
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to packages/*/package.json : Use `workspace:*` protocol for internal package dependencies in package.json (e.g., `"tanstack/ai": "workspace:*"`)
Applied to files:
testing/panel/package.jsonexamples/ts-react-chat/package.jsonpackages/typescript/ai-zai/package.jsonexamples/ts-group-chat/package.jsonexamples/ts-svelte-chat/package.jsonexamples/ts-vue-chat/package.jsonexamples/ts-solid-chat/package.json
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Use Nx workspace with affected commands to optimize testing and building only changed packages and their dependents
Applied to files:
testing/panel/package.jsonexamples/ts-svelte-chat/package.json
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to **/*.{ts,tsx} : Use Zod for runtime schema validation and type inference, particularly for tool input/output definitions with `toolDefinition()` and Zod schema inference
Applied to files:
packages/typescript/ai-zai/src/tools/tool-choice.tsexamples/ts-vue-chat/vite.config.tspackages/typescript/ai-zai/src/tools/function-tool.tspackages/typescript/ai-zai/src/tools/web-search-tool.tspackages/typescript/ai-zai/src/utils/conversion.tspackages/typescript/ai-zai/src/tools/tool-converter.tspackages/typescript/ai-zai/tests/zai-adapter.integration.test.tspackages/typescript/ai-zai/src/text/text-provider-options.tspackages/typescript/ai-zai/tsconfig.jsonpackages/typescript/ai-zai/CHANGELOG.md
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to **/*.{ts,tsx} : Implement stream processing with StreamProcessor for handling chunked responses and support partial JSON parsing for streaming AI responses
Applied to files:
packages/typescript/ai-zai/tests/zai-adapter.test.tspackages/typescript/ai-zai/src/utils/conversion.tstesting/panel/src/routes/api.chat.tspackages/typescript/ai-zai/tests/zai-adapter.integration.test.tspackages/typescript/ai-zai/src/adapters/text.ts
📚 Learning: 2025-12-27T20:22:51.232Z
Learnt from: harry-whorlow
Repo: TanStack/ai PR: 117
File: packages/typescript/ai-ollama/src/meta/model-meta-gpt-oss.ts:92-97
Timestamp: 2025-12-27T20:22:51.232Z
Learning: In the ai-ollama package's model-meta files (packages/typescript/ai-ollama/src/meta/model-meta-*.ts), capability-related comments follow a standard template format across all files for consistency, even if the comment text doesn't precisely match individual model capabilities. This is an intentional design choice to maintain uniformity across the codebase.
Applied to files:
examples/ts-react-chat/src/lib/model-selection.tspackages/typescript/ai-zai/src/message-types.tsexamples/ts-vue-chat/src/lib/model-selection.tspackages/typescript/ai-zai/README.mdpackages/typescript/ai-zai/src/text/text-provider-options.tspackages/typescript/ai-zai/src/model-meta.tspackages/typescript/ai-zai/tests/model-meta.test.ts
📚 Learning: 2025-12-27T21:39:29.563Z
Learnt from: harry-whorlow
Repo: TanStack/ai PR: 117
File: packages/typescript/ai-ollama/src/meta/model-meta-llama-guard3.ts:70-75
Timestamp: 2025-12-27T21:39:29.563Z
Learning: The standard template comments in ai-ollama model-meta files (like "Models with text, image, audio, video (no document)") should not be modified to match individual model capabilities, as they are intentionally kept uniform across all model-meta-*.ts files for consistency, regardless of what each specific model actually supports.
Applied to files:
packages/typescript/ai-zai/src/message-types.tspackages/typescript/ai-zai/src/model-meta.tspackages/typescript/ai-zai/tests/model-meta.test.ts
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Maintain type safety through multimodal content support (image, audio, video, document) with model capability awareness
Applied to files:
packages/typescript/ai-zai/src/message-types.ts
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Implement framework integrations using the headless `tanstack/ai-client` for state management with framework-specific hooks (useChat) on top
Applied to files:
examples/ts-solid-chat/src/routes/api.chat.tsexamples/ts-react-chat/src/routes/api.tanchat.tspackages/typescript/ai-zai/README.mdtesting/panel/src/routes/api.chat.tspackages/typescript/ai-zai/CHANGELOG.md
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to .eslintrc* : Use ESLint with custom TanStack config for linting all TypeScript and JavaScript files
Applied to files:
packages/typescript/ai-zai/package.jsonexamples/ts-svelte-chat/package.jsonpackages/typescript/ai-zai/tsconfig.jsonpackages/typescript/ai-zai/vite.config.ts
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to **/*.test.ts : Write unit tests using Vitest alongside source files with `.test.ts` naming convention
Applied to files:
packages/typescript/ai-zai/tests/zai-adapter.integration.test.tspackages/typescript/ai-zai/tsconfig.jsonpackages/typescript/ai-zai/vite.config.tspackages/typescript/ai-zai/tests/model-meta.test.ts
📚 Learning: 2025-12-27T19:49:03.849Z
Learnt from: harry-whorlow
Repo: TanStack/ai PR: 117
File: packages/typescript/ai-ollama/src/meta/model-meta-deepseek-coder-v2.ts:7-18
Timestamp: 2025-12-27T19:49:03.849Z
Learning: For Ollama model metadata in the ai-ollama package, always consult https://ollama.com/library/ as the authoritative source for model specifications (size, context window, capabilities) rather than other documentation sources.
Applied to files:
packages/typescript/ai-zai/src/model-meta.ts
🧬 Code graph analysis (15)
examples/ts-svelte-chat/src/lib/model-selection.ts (1)
examples/ts-vue-chat/src/lib/model-selection.ts (1)
Provider(1-1)
testing/panel/src/lib/model-selection.ts (1)
examples/ts-react-chat/src/lib/model-selection.ts (1)
Provider(1-1)
packages/typescript/ai-zai/tests/zai-adapter.test.ts (1)
packages/typescript/ai-zai/src/adapters/text.ts (1)
ZAITextAdapter(56-412)
examples/ts-vue-chat/vite.config.ts (2)
examples/ts-svelte-chat/src/lib/model-selection.ts (1)
Provider(1-1)examples/ts-vue-chat/src/lib/model-selection.ts (1)
Provider(1-1)
packages/typescript/ai-zai/src/tools/function-tool.ts (2)
packages/python/tanstack-ai/src/tanstack_ai/tool_utils.py (1)
tool(12-65)packages/typescript/ai/src/types.ts (1)
JSONSchema(25-64)
examples/ts-react-chat/src/lib/model-selection.ts (1)
testing/panel/src/lib/model-selection.ts (1)
Provider(1-1)
examples/ts-vue-chat/src/lib/model-selection.ts (1)
examples/ts-svelte-chat/src/lib/model-selection.ts (1)
Provider(1-1)
packages/typescript/ai-zai/src/tools/web-search-tool.ts (1)
packages/python/tanstack-ai/src/tanstack_ai/tool_utils.py (1)
tool(12-65)
examples/ts-solid-chat/src/routes/api.chat.ts (3)
packages/typescript/ai-anthropic/src/index.ts (1)
anthropicText(8-8)packages/typescript/ai/src/index.ts (2)
chat(3-3)maxIterations(68-68)examples/ts-solid-chat/src/lib/guitar-tools.ts (1)
serverTools(130-136)
packages/typescript/ai-zai/src/utils/conversion.ts (2)
packages/typescript/ai-zai/src/tools/tool-converter.ts (1)
convertToolsToProviderFormat(12-24)packages/typescript/ai/src/types.ts (1)
StreamChunk(740-748)
packages/typescript/ai-zai/src/adapters/summarize.ts (4)
packages/typescript/ai-zai/src/adapters/text.ts (1)
ZAITextAdapterConfig(31-43)packages/typescript/ai-zai/src/model-meta.ts (1)
ZAI_CHAT_MODELS(193-197)packages/typescript/ai/src/types.ts (1)
StreamChunk(740-748)packages/typescript/ai-zai/src/utils/client.ts (1)
getZAIApiKeyFromEnv(13-30)
packages/typescript/ai-zai/tests/zai-adapter.integration.test.ts (4)
packages/typescript/ai/src/activities/chat/stream/processor.ts (1)
process(387-410)packages/typescript/ai/src/types.ts (1)
StreamChunk(740-748)packages/typescript/ai-zai/src/adapters/index.ts (1)
createZAIChat(23-39)packages/typescript/ai-svelte/src/create-chat.svelte.ts (1)
messages(121-123)
examples/ts-svelte-chat/src/routes/api/chat/+server.ts (3)
examples/ts-svelte-chat/src/lib/model-selection.ts (1)
Provider(1-1)examples/ts-vue-chat/src/lib/model-selection.ts (1)
Provider(1-1)packages/typescript/ai/src/index.ts (1)
createChatOptions(13-13)
packages/typescript/ai-zai/src/adapters/index.ts (3)
packages/typescript/ai-zai/src/model-meta.ts (1)
ZAI_CHAT_MODELS(193-197)packages/typescript/ai-zai/src/adapters/text.ts (1)
ZAITextAdapter(56-412)packages/typescript/ai-zai/src/utils/client.ts (1)
getZAIApiKeyFromEnv(13-30)
packages/typescript/ai-zai/src/model-meta.ts (1)
packages/typescript/ai-zai/src/text/text-provider-options.ts (6)
ZAIBaseOptions(4-76)ZAIReasoningOptions(86-114)ZAIStructuredOutputOptions(116-122)ZAIToolsOptions(124-151)ZAIStreamingOptions(153-166)ZAIMetadataOptions(168-184)
🪛 Biome (2.1.2)
packages/typescript/ai-zai/src/message-types.ts
[error] 40-40: An empty interface is equivalent to {}.
Safe fix: Use a type alias instead.
(lint/suspicious/noEmptyInterface)
[error] 46-46: An empty interface is equivalent to {}.
Safe fix: Use a type alias instead.
(lint/suspicious/noEmptyInterface)
[error] 52-52: An empty interface is equivalent to {}.
Safe fix: Use a type alias instead.
(lint/suspicious/noEmptyInterface)
🪛 dotenv-linter (4.0.0)
testing/panel/.env.example
[warning] 22-22: [EndingBlankLine] No blank line at the end of the file
(EndingBlankLine)
🪛 LanguageTool
packages/typescript/ai-zai/README.md
[grammar] ~17-~17: Use a hyphen to join words.
Context: ...OpenAI-style tools - Supports Zhipu AI specific features like Web Search, *...
(QB_NEW_EN_HYPHEN)
🪛 markdownlint-cli2 (0.18.1)
packages/typescript/ai-zai/README.md
8-8: Bare URL used
(MD034, no-bare-urls)
297-297: Bare URL used
(MD034, no-bare-urls)
298-298: Bare URL used
(MD034, no-bare-urls)
299-299: Bare URL used
(MD034, no-bare-urls)
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
…TextAdapter add support for image and video content in messages when model supports it update documentation for model capabilities and tool types add test case for image content preservation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In `@packages/typescript/ai-zai/src/adapters/text.ts`:
- Around line 401-412: Missing null checks: accessing part.source.value for
image/video parts can throw if part.source is undefined; update the branches
that handle part.type === 'image' and part.type === 'video' (the code that calls
parts.push with image_url/video_url) to guard on part.source (and
part.source.value) before referencing it, e.g., only push when part.source &&
part.source.value (or use optional chaining like part.source?.value) and
otherwise skip the part or use a safe fallback, keeping the existing checks for
capabilities.image/capabilities.video intact.
In `@packages/typescript/ai-zai/src/model-meta.ts`:
- Around line 152-161: The GLM_4_6 metadata is inconsistent: the comment says
"Released September 2025" but the object property knowledge_cutoff is
'2024-09-01'; update the metadata so they match (e.g., set
GLM_4_6.knowledge_cutoff to '2025-09-01' if the release date is correct) or
alternatively change the comment to "Released September 2024" to match the
existing knowledge_cutoff; modify the GLM_4_6 definition and its surrounding
comment accordingly.
♻️ Duplicate comments (1)
testing/panel/.env.example (1)
22-22: Add a blank line at EOF.The missing newline at the end of the file violates the dotenv-linter convention and was flagged in previous reviews.
📝 Proposed fix
# Ollama (local) # OLLAMA_HOST=http://localhost:11434 +
🧹 Nitpick comments (6)
packages/typescript/ai-zai/src/text/text-provider-options.ts (3)
29-33: Consider stronger typing forvariables.Using
Record<string, any>reduces type safety. If the prompt template variables have a known structure, consider using a more specific type or generic parameter. If truly dynamic,Record<string, unknown>is slightly safer as it requires explicit type narrowing.♻️ Suggested improvement
prompt?: { id: string version?: string - variables?: Record<string, any> + variables?: Record<string, unknown> }
80-88: Consider exporting helper types for consumer use.
ReasoningEffortandReasoningSummaryare used in the exportedZAIReasoningOptionsinterface but aren't exported themselves. Consumers building type-safe configurations may need to reference these types directly.♻️ Suggested improvement
/** * Level of effort to expend on reasoning. */ -type ReasoningEffort = 'none' | 'minimal' | 'low' | 'medium' | 'high' +export type ReasoningEffort = 'none' | 'minimal' | 'low' | 'medium' | 'high' /** * Detail level for the reasoning summary. */ -type ReasoningSummary = 'auto' | 'detailed' +export type ReasoningSummary = 'auto' | 'detailed'
175-191: Minor naming inconsistency.
acceptLanguageuses camelCase while other properties in this file use snake_case (e.g.,previous_response_id,parallel_tool_calls). Consider usingaccept_languagefor consistency with the OpenAI-style API convention used elsewhere, unless this specifically maps to an HTTP header pattern in the Z.AI API.packages/typescript/ai-zai/src/tools/tool-converter.ts (1)
19-27: Consider extracting the magic string'web_search'to a constant.The hardcoded string
'web_search'at line 21 could lead to subtle bugs if the tool name changes or is misspelled elsewhere. Consider defining a constant (e.g.,WEB_SEARCH_TOOL_NAME) that can be shared across the codebase for consistency.♻️ Suggested refactor
+const WEB_SEARCH_TOOL_NAME = 'web_search' as const + export function convertToolsToProviderFormat( tools: Array<Tool>, ): Array<ZaiTool> { return tools.map((tool) => { // Handle special tool names - if (tool.name === 'web_search') { + if (tool.name === WEB_SEARCH_TOOL_NAME) { return convertWebSearchToolToAdapterFormat(tool) } // Default to function tool return convertFunctionToolToAdapterFormat(tool) }) }packages/typescript/ai-zai/src/adapters/text.ts (2)
111-117: Avoidas anycast when constructing error chunks.The
as anycast at line 112 followed by property mutations loses type safety. Consider constructing a properly typed error chunk directly instead of mutating a converted result.♻️ Suggested improvement
} catch (error: unknown) { - const chunk = mapZAIErrorToStreamChunk(error) as any - chunk.id = fallbackId - chunk.model = options.model - chunk.timestamp = timestamp - yield chunk as StreamChunk + const errorChunk = mapZAIErrorToStreamChunk(error) + yield { + ...errorChunk, + id: fallbackId, + model: options.model, + timestamp, + } as StreamChunk }
155-161: Consider extending the request type to avoidas anycasts.The conditional additions of
toolsandstopuseas anycasts. While these work, they could be avoided by using a type intersection or explicitly typing the request object to include these optional fields.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (13)
packages/typescript/ai-zai/src/adapters/index.tspackages/typescript/ai-zai/src/adapters/summarize.tspackages/typescript/ai-zai/src/adapters/text.tspackages/typescript/ai-zai/src/model-meta.tspackages/typescript/ai-zai/src/text/text-provider-options.tspackages/typescript/ai-zai/src/tools/function-tool.tspackages/typescript/ai-zai/src/tools/tool-choice.tspackages/typescript/ai-zai/src/tools/tool-converter.tspackages/typescript/ai-zai/src/tools/web-search-tool.tspackages/typescript/ai-zai/src/utils/client.tspackages/typescript/ai-zai/src/utils/conversion.tspackages/typescript/ai-zai/tests/zai-adapter.test.tstesting/panel/.env.example
🚧 Files skipped from review as they are similar to previous changes (3)
- packages/typescript/ai-zai/src/tools/web-search-tool.ts
- packages/typescript/ai-zai/src/adapters/summarize.ts
- packages/typescript/ai-zai/src/utils/client.ts
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Use tree-shakeable adapter architecture for provider implementations - export specialized adapters (text, embedding, summarize, image) as separate imports from/adapterssubpath rather than monolithic adapters
Use Zod for runtime schema validation and type inference, particularly for tool input/output definitions withtoolDefinition()and Zod schema inference
Implement isomorphic tool system usingtoolDefinition()with.server()and.client()implementations for dual-environment execution
Use type-safe per-model configuration with provider options typed based on selected model to ensure compile-time safety
Implement stream processing with StreamProcessor for handling chunked responses and support partial JSON parsing for streaming AI responses
Files:
packages/typescript/ai-zai/src/tools/tool-converter.tspackages/typescript/ai-zai/src/utils/conversion.tspackages/typescript/ai-zai/src/tools/tool-choice.tspackages/typescript/ai-zai/src/text/text-provider-options.tspackages/typescript/ai-zai/src/tools/function-tool.tspackages/typescript/ai-zai/src/adapters/index.tspackages/typescript/ai-zai/src/model-meta.tspackages/typescript/ai-zai/src/adapters/text.tspackages/typescript/ai-zai/tests/zai-adapter.test.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use camelCase for function and variable names throughout the codebase
Files:
packages/typescript/ai-zai/src/tools/tool-converter.tspackages/typescript/ai-zai/src/utils/conversion.tspackages/typescript/ai-zai/src/tools/tool-choice.tspackages/typescript/ai-zai/src/text/text-provider-options.tspackages/typescript/ai-zai/src/tools/function-tool.tspackages/typescript/ai-zai/src/adapters/index.tspackages/typescript/ai-zai/src/model-meta.tspackages/typescript/ai-zai/src/adapters/text.tspackages/typescript/ai-zai/tests/zai-adapter.test.ts
packages/typescript/*/src/adapters/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Create individual adapter implementations for each provider capability (text, embed, summarize, image) with separate exports to enable tree-shaking
Files:
packages/typescript/ai-zai/src/adapters/index.tspackages/typescript/ai-zai/src/adapters/text.ts
packages/typescript/*/src/model-meta.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Maintain model metadata files that define provider options and capabilities per model for per-model type safety
Files:
packages/typescript/ai-zai/src/model-meta.ts
**/*.test.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Write unit tests using Vitest alongside source files with
.test.tsnaming convention
Files:
packages/typescript/ai-zai/tests/zai-adapter.test.ts
🧠 Learnings (12)
📓 Common learnings
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to packages/typescript/*/src/adapters/*.ts : Create individual adapter implementations for each provider capability (text, embed, summarize, image) with separate exports to enable tree-shaking
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to packages/typescript/*/src/index.ts : Export tree-shakeable adapters with clear subpath exports in package.json (e.g., `tanstack/ai/adapters`, `tanstack/ai-openai/adapters`) to minimize bundle size
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Implement framework integrations using the headless `tanstack/ai-client` for state management with framework-specific hooks (useChat) on top
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to packages/typescript/*/src/adapters/*.ts : Create individual adapter implementations for each provider capability (text, embed, summarize, image) with separate exports to enable tree-shaking
Applied to files:
packages/typescript/ai-zai/src/tools/tool-converter.tspackages/typescript/ai-zai/src/text/text-provider-options.tspackages/typescript/ai-zai/src/tools/function-tool.tspackages/typescript/ai-zai/src/adapters/index.tspackages/typescript/ai-zai/src/model-meta.tspackages/typescript/ai-zai/src/adapters/text.tspackages/typescript/ai-zai/tests/zai-adapter.test.ts
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to **/*.{ts,tsx} : Implement isomorphic tool system using `toolDefinition()` with `.server()` and `.client()` implementations for dual-environment execution
Applied to files:
packages/typescript/ai-zai/src/tools/tool-converter.tspackages/typescript/ai-zai/src/utils/conversion.tspackages/typescript/ai-zai/src/tools/tool-choice.tspackages/typescript/ai-zai/src/tools/function-tool.ts
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to packages/typescript/*/src/index.ts : Export tree-shakeable adapters with clear subpath exports in package.json (e.g., `tanstack/ai/adapters`, `tanstack/ai-openai/adapters`) to minimize bundle size
Applied to files:
packages/typescript/ai-zai/src/tools/tool-converter.tspackages/typescript/ai-zai/src/tools/function-tool.tspackages/typescript/ai-zai/src/adapters/index.tspackages/typescript/ai-zai/src/adapters/text.tspackages/typescript/ai-zai/tests/zai-adapter.test.ts
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to **/*.{ts,tsx} : Use Zod for runtime schema validation and type inference, particularly for tool input/output definitions with `toolDefinition()` and Zod schema inference
Applied to files:
packages/typescript/ai-zai/src/tools/tool-converter.tspackages/typescript/ai-zai/src/utils/conversion.tspackages/typescript/ai-zai/src/tools/tool-choice.tspackages/typescript/ai-zai/src/tools/function-tool.ts
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to packages/typescript/*/src/model-meta.ts : Maintain model metadata files that define provider options and capabilities per model for per-model type safety
Applied to files:
packages/typescript/ai-zai/src/tools/tool-converter.tspackages/typescript/ai-zai/src/text/text-provider-options.tspackages/typescript/ai-zai/src/model-meta.ts
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to **/*.{ts,tsx} : Use tree-shakeable adapter architecture for provider implementations - export specialized adapters (text, embedding, summarize, image) as separate imports from `/adapters` subpath rather than monolithic adapters
Applied to files:
packages/typescript/ai-zai/src/tools/tool-converter.tspackages/typescript/ai-zai/src/text/text-provider-options.tspackages/typescript/ai-zai/src/adapters/index.tspackages/typescript/ai-zai/src/adapters/text.tspackages/typescript/ai-zai/tests/zai-adapter.test.ts
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to **/*.{ts,tsx} : Implement stream processing with StreamProcessor for handling chunked responses and support partial JSON parsing for streaming AI responses
Applied to files:
packages/typescript/ai-zai/src/utils/conversion.tspackages/typescript/ai-zai/src/adapters/text.tspackages/typescript/ai-zai/tests/zai-adapter.test.ts
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to **/*.{ts,tsx} : Use type-safe per-model configuration with provider options typed based on selected model to ensure compile-time safety
Applied to files:
packages/typescript/ai-zai/src/text/text-provider-options.tspackages/typescript/ai-zai/src/model-meta.ts
📚 Learning: 2025-12-27T20:22:51.232Z
Learnt from: harry-whorlow
Repo: TanStack/ai PR: 117
File: packages/typescript/ai-ollama/src/meta/model-meta-gpt-oss.ts:92-97
Timestamp: 2025-12-27T20:22:51.232Z
Learning: In the ai-ollama package's model-meta files (packages/typescript/ai-ollama/src/meta/model-meta-*.ts), capability-related comments follow a standard template format across all files for consistency, even if the comment text doesn't precisely match individual model capabilities. This is an intentional design choice to maintain uniformity across the codebase.
Applied to files:
packages/typescript/ai-zai/src/text/text-provider-options.tspackages/typescript/ai-zai/src/model-meta.ts
📚 Learning: 2025-12-27T21:39:29.563Z
Learnt from: harry-whorlow
Repo: TanStack/ai PR: 117
File: packages/typescript/ai-ollama/src/meta/model-meta-llama-guard3.ts:70-75
Timestamp: 2025-12-27T21:39:29.563Z
Learning: The standard template comments in ai-ollama model-meta files (like "Models with text, image, audio, video (no document)") should not be modified to match individual model capabilities, as they are intentionally kept uniform across all model-meta-*.ts files for consistency, regardless of what each specific model actually supports.
Applied to files:
packages/typescript/ai-zai/src/model-meta.ts
📚 Learning: 2025-12-27T19:49:03.849Z
Learnt from: harry-whorlow
Repo: TanStack/ai PR: 117
File: packages/typescript/ai-ollama/src/meta/model-meta-deepseek-coder-v2.ts:7-18
Timestamp: 2025-12-27T19:49:03.849Z
Learning: For Ollama model metadata in the ai-ollama package, always consult https://ollama.com/library/ as the authoritative source for model specifications (size, context window, capabilities) rather than other documentation sources.
Applied to files:
packages/typescript/ai-zai/src/model-meta.ts
🧬 Code graph analysis (4)
packages/typescript/ai-zai/src/utils/conversion.ts (2)
packages/typescript/ai-zai/src/tools/tool-converter.ts (1)
convertToolsToProviderFormat(16-28)packages/typescript/ai/src/types.ts (1)
StreamChunk(740-748)
packages/typescript/ai-zai/src/adapters/index.ts (3)
packages/typescript/ai-zai/src/model-meta.ts (1)
ZAI_CHAT_MODELS(193-197)packages/typescript/ai-zai/src/adapters/text.ts (1)
ZAITextAdapter(56-462)packages/typescript/ai-zai/src/utils/client.ts (1)
getZAIApiKeyFromEnv(13-30)
packages/typescript/ai-zai/src/model-meta.ts (1)
packages/typescript/ai-zai/src/text/text-provider-options.ts (6)
ZAIBaseOptions(4-76)ZAIReasoningOptions(93-121)ZAIStructuredOutputOptions(123-129)ZAIToolsOptions(131-158)ZAIStreamingOptions(160-173)ZAIMetadataOptions(175-191)
packages/typescript/ai-zai/tests/zai-adapter.test.ts (4)
packages/typescript/ai-zai/src/adapters/index.ts (1)
ZAITextAdapter(5-5)packages/typescript/ai-zai/src/adapters/text.ts (1)
ZAITextAdapter(56-462)packages/typescript/ai/src/types.ts (2)
TextOptions(565-650)StreamChunk(740-748)packages/typescript/ai-svelte/src/create-chat.svelte.ts (1)
messages(121-123)
🪛 dotenv-linter (4.0.0)
testing/panel/.env.example
[warning] 22-22: [EndingBlankLine] No blank line at the end of the file
(EndingBlankLine)
🔇 Additional comments (25)
testing/panel/.env.example (1)
5-7: Nice fix—Z.AI URL now points directly to the API key management page.This addresses the previous feedback and makes it easier for users to obtain their API keys.
packages/typescript/ai-zai/src/text/text-provider-options.ts (4)
123-129: LGTM!Clean interface that appropriately reuses OpenAI's
ResponseTextConfigtype for structured output configuration.
131-158: LGTM!The tools options interface is well-structured. The explicit string literals in
tool_choicealongside the OpenAI type provide good documentation of common options while supporting complex tool choice configurations.
160-173: LGTM!Streaming options are clearly defined with appropriate defaults documented.
193-203: LGTM!The composite interface pattern aligns well with the tree-shakeable adapter architecture guidelines. Consumers can use granular option interfaces or the full
ZAITextOptionsas needed. Based on learnings, this modular approach supports per-model type safety.packages/typescript/ai-zai/src/tools/tool-choice.ts (1)
1-26: LGTM!Clean and well-documented type definitions for tool selection. The union type correctly combines literal modes (
'auto','none') with specific tool configurations.packages/typescript/ai-zai/src/model-meta.ts (3)
66-107: LGTM!Well-structured model metadata with proper
as const satisfiespattern for type-safe per-model configuration. The GLM-4.7 flagship model definition correctly captures context window, output limits, and supported capabilities.
109-150: LGTM!GLM-4.6V multimodal model correctly declares
['text', 'image', 'video']input support, enabling the adapter to conditionally preserve image/video content for this model.
193-236: LGTM!Exports are well-organized:
ZAI_CHAT_MODELSas a readonly array,ZAIModelMapfor per-model provider options,ZAIModelInputModalitiesByNamefor capability lookups, andZAI_MODEL_METAas the complete registry. This follows the model-meta pattern for type-safe per-model configuration. Based on learnings.packages/typescript/ai-zai/tests/zai-adapter.test.ts (7)
1-50: LGTM!Clean test setup with proper OpenAI SDK mocking. The
openAIStatepattern effectively captures constructor options and mock function calls for verification.
52-77: LGTM!Constructor tests properly verify:
- Default Z.AI base URL (
https://api.z.ai/api/paas/v4)- Custom baseURL override
- Default
Accept-Languageheader- API key validation (rejecting
Bearerprefix and whitespace)
79-148: LGTM!Options mapping tests thoroughly cover:
- Standard parameters (
maxTokens→max_tokens,temperature,topP)- Streaming defaults (
stream: true,stream_options)- Tool conversion to OpenAI function format with
additionalProperties: false- Stop sequences from
modelOptions.stopSequences
150-229: LGTM!Message conversion tests cover key scenarios: simple messages, system prompts concatenation, tool results with
tool_call_id, and multi-turn conversations.
231-283: Good addition of multimodal test coverage.Line 231-252 verifies text-only models (
glm-4.7) filter out image parts, while Line 254-283 confirms multimodal models (glm-4.6v) preserve image content with proper OpenAI format conversion (image_url). This addresses the capability-aware content handling.
286-343: LGTM!Error handling tests properly verify:
- Network errors yield error chunks (non-throwing behavior)
- Empty message arrays are handled gracefully
- Malformed stream chunks don't cause crashes
345-466: LGTM!Streaming behavior tests comprehensively cover:
- Content delta accumulation with progressive
contentfield- Tool call argument accumulation across chunks
- Proper
donechunk emission withfinishReasonandusage- Request headers passthrough to the underlying client
packages/typescript/ai-zai/src/tools/function-tool.ts (1)
1-35: LGTM!Clean tool conversion with defensive JSON Schema normalization. Setting
additionalProperties: falseby default ensures stricter validation, and the fallback to an empty object schema handles tools without explicit input schemas.packages/typescript/ai-zai/src/utils/conversion.ts (2)
9-15: LGTM!The double cast (
as unknown as) is appropriately documented. This is necessary becauseZaiToolincludesWebSearchToolwhich extends beyond OpenAI's type definitions.
17-54: LGTM!Robust error-to-stream-chunk conversion with thorough extraction of error message and code from various error object shapes (nested
error.error, direct properties, numeric status codes, and plain strings).packages/typescript/ai-zai/src/tools/tool-converter.ts (1)
1-11: LGTM on type definitions and imports.The
ZaiToolunion type is well-documented and correctly represents the two tool formats supported by Z.AI. The imports are minimal and appropriate for the module's purpose.packages/typescript/ai-zai/src/adapters/index.ts (2)
33-66: LGTM on factory functions.Both
createZAIChatandzaiTextprovide clean, well-documented APIs for instantiating the adapter. The separation between explicit API key (createZAIChat) and environment-based (zaiText) is a good pattern that supports both server-side and development workflows. TheapiKeyvalidation at line 38-40 is good defensive coding.Based on learnings, this aligns with the tree-shakeable adapter architecture guidelines.
3-3: Type-only import may cause issues withtypeofusage.Line 3 imports
ZAI_CHAT_MODELSas a type-only import (import type), but line 17 usestypeof ZAI_CHAT_MODELSwhich requires the value to be available at compile time for type inference. This works in TypeScript becausetypeofin type position only needs the type information, but the intent could be clearer by importing the value directly if it's used for type derivation.Verify this compiles correctly:
#!/bin/bash # Check if the file compiles without errors cd packages/typescript/ai-zai cat src/adapters/index.ts | head -20 # Check for any TypeScript errors in this file npx tsc --noEmit src/adapters/index.ts 2>&1 | head -20 || trueAlso applies to: 17-17
packages/typescript/ai-zai/src/adapters/text.ts (3)
56-83: LGTM on class structure and constructor.The generic type parameters provide good per-model type safety with
ResolveProviderOptionsandResolveInputModalities. The constructor properly delegates client creation tocreateZAIClient, keeping the adapter focused on its core responsibility. This aligns with the tree-shakeable adapter architecture guidelines.
196-209: Good fix for the missingtoolCallIdvalidation.The code now properly throws an error when
toolCallIdis missing instead of using an empty string fallback. This prevents silent API failures and provides clear error messaging for debugging.
427-461: LGTM on request header and abort signal helpers.Both
getRequestHeadersandgetAbortSignalproperly handle multiple input formats with appropriate type guards. The fallback chain ingetAbortSignalcorrectly prioritizesabortController.signaloverrequest.signal, which aligns with the TanStack AI conventions noted in the comments.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
| if (!toolCallsInProgress.has(index)) { | ||
| toolCallsInProgress.set(index, { | ||
| id: toolCallDelta.id || '', | ||
| name: toolCallDelta.function?.name || '', | ||
| arguments: '', | ||
| }) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Empty string fallback for tool call id may cause issues.
Similar to the now-fixed toolCallId issue, initializing the tool call id with an empty string (line 304) could propagate invalid data. If the stream never provides the ID, the emitted tool_call chunk will have an empty id, which may cause issues when the tool result needs to be sent back.
🔧 Consider adding validation or logging
if (!toolCallsInProgress.has(index)) {
toolCallsInProgress.set(index, {
- id: toolCallDelta.id || '',
+ id: toolCallDelta.id ?? '',
name: toolCallDelta.function?.name || '',
arguments: '',
})
}Additionally, consider validating that toolCall.id is non-empty before emitting the tool_call chunk at lines 325-341.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if (!toolCallsInProgress.has(index)) { | |
| toolCallsInProgress.set(index, { | |
| id: toolCallDelta.id || '', | |
| name: toolCallDelta.function?.name || '', | |
| arguments: '', | |
| }) | |
| } | |
| if (!toolCallsInProgress.has(index)) { | |
| toolCallsInProgress.set(index, { | |
| id: toolCallDelta.id ?? '', | |
| name: toolCallDelta.function?.name || '', | |
| arguments: '', | |
| }) | |
| } |
| } else if (part.type === 'image' && capabilities.image) { | ||
| parts.push({ | ||
| type: 'image_url', | ||
| image_url: { url: part.source.value }, | ||
| }) | ||
| } else if (part.type === 'video' && capabilities.video) { | ||
| // Assuming Z.AI accepts video_url with the same structure as image_url | ||
| // Using 'any' cast because OpenAI types don't include video_url yet | ||
| parts.push({ | ||
| type: 'video_url', | ||
| video_url: { url: part.source.value }, | ||
| } as any) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing null check for part.source could cause runtime errors.
Lines 404 and 411 access part.source.value without verifying that part.source exists. If a content part has type: 'image' but no source property, this will throw a TypeError.
🔧 Add defensive null checks
- } else if (part.type === 'image' && capabilities.image) {
+ } else if (part.type === 'image' && capabilities.image && part.source?.value) {
parts.push({
type: 'image_url',
image_url: { url: part.source.value },
})
- } else if (part.type === 'video' && capabilities.video) {
+ } else if (part.type === 'video' && capabilities.video && part.source?.value) {
// Assuming Z.AI accepts video_url with the same structure as image_url
// Using 'any' cast because OpenAI types don't include video_url yet
parts.push({
type: 'video_url',
video_url: { url: part.source.value },
} as any)
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| } else if (part.type === 'image' && capabilities.image) { | |
| parts.push({ | |
| type: 'image_url', | |
| image_url: { url: part.source.value }, | |
| }) | |
| } else if (part.type === 'video' && capabilities.video) { | |
| // Assuming Z.AI accepts video_url with the same structure as image_url | |
| // Using 'any' cast because OpenAI types don't include video_url yet | |
| parts.push({ | |
| type: 'video_url', | |
| video_url: { url: part.source.value }, | |
| } as any) | |
| } else if (part.type === 'image' && capabilities.image && part.source?.value) { | |
| parts.push({ | |
| type: 'image_url', | |
| image_url: { url: part.source.value }, | |
| }) | |
| } else if (part.type === 'video' && capabilities.video && part.source?.value) { | |
| // Assuming Z.AI accepts video_url with the same structure as image_url | |
| // Using 'any' cast because OpenAI types don't include video_url yet | |
| parts.push({ | |
| type: 'video_url', | |
| video_url: { url: part.source.value }, | |
| } as any) | |
| } |
🤖 Prompt for AI Agents
In `@packages/typescript/ai-zai/src/adapters/text.ts` around lines 401 - 412,
Missing null checks: accessing part.source.value for image/video parts can throw
if part.source is undefined; update the branches that handle part.type ===
'image' and part.type === 'video' (the code that calls parts.push with
image_url/video_url) to guard on part.source (and part.source.value) before
referencing it, e.g., only push when part.source && part.source.value (or use
optional chaining like part.source?.value) and otherwise skip the part or use a
safe fallback, keeping the existing checks for
capabilities.image/capabilities.video intact.
| /** | ||
| * GLM-4.6: Previous flagship model | ||
| * Released September 2025 | ||
| * Enhanced coding and reasoning capabilities | ||
| */ | ||
| const GLM_4_6 = { | ||
| name: 'glm-4.6', | ||
| context_window: 128_000, | ||
| max_output_tokens: 128_000, | ||
| knowledge_cutoff: '2024-09-01', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inconsistent dates in GLM-4.6 metadata.
The comment states "Released September 2025" but knowledge_cutoff is set to '2024-09-01'. Please verify and align these values.
🤖 Prompt for AI Agents
In `@packages/typescript/ai-zai/src/model-meta.ts` around lines 152 - 161, The
GLM_4_6 metadata is inconsistent: the comment says "Released September 2025" but
the object property knowledge_cutoff is '2024-09-01'; update the metadata so
they match (e.g., set GLM_4_6.knowledge_cutoff to '2025-09-01' if the release
date is correct) or alternatively change the comment to "Released September
2024" to match the existing knowledge_cutoff; modify the GLM_4_6 definition and
its surrounding comment accordingly.
This PR introduces a new community adapter for Z.AI (Zhipu AI), enabling seamless integration with GLM-4 models in the TanStack AI ecosystem. It also updates all example chat applications to demonstrate and verify the new adapter.
Changes:
1. New Package:
@tanstack/ai-zaiglm-4.7(Flagship, high reasoning)glm-4.6(Balanced)glm-4.6v(Multimodal vision)reasoning,tools, andstreaming.zai-factory.test.ts,model-meta.test.ts)zai-adapter.integration.test.ts) covering streaming, multi-turn chat, tool calling, and error handling.2. Example Projects Updated
All example chat applications have been updated to support the
zaiprovider and model selection:examples/ts-react-chat:zaiprovider tomodel-selection.ts.@tanstack/ai-zaidependency.examples/ts-vue-chat:zaiprovider support invite.config.ts(API handler).examples/ts-svelte-chat:+server.tsto includezaiTextadapter configuration.ZAI_API_KEY.examples/ts-solid-chat:api.chat.tsto dynamically switch between Anthropic and Z.AI providers.examples/ts-group-chat:claude-service.tsto fallback to Z.AI ifZAI_API_KEYis present.3. Infrastructure & Config
testing/panel: Updated the testing panel to support Z.AI specific features (Thinking mode toggle, Web Search toggle).package.jsonfiles are correctly linked to the workspace version of@tanstack/ai-zai.Verification:
pnpm build).pnpm run test:prpasses (Sherif, Knip, ESLint, Types, Lib tests).zai-adapter.integration.test.tspasses with valid API key.Checklist:
model-meta.ts.index.ts.Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.