@tanstack/ai 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -25
- package/dist/esm/activities/chat/index.d.ts +11 -10
- package/dist/esm/activities/chat/index.js +9 -9
- package/dist/esm/activities/chat/index.js.map +1 -1
- package/dist/esm/activities/chat/tools/schema-converter.d.ts +116 -0
- package/dist/esm/activities/chat/tools/schema-converter.js +115 -0
- package/dist/esm/activities/chat/tools/schema-converter.js.map +1 -0
- package/dist/esm/activities/chat/tools/tool-calls.js +23 -34
- package/dist/esm/activities/chat/tools/tool-calls.js.map +1 -1
- package/dist/esm/activities/chat/tools/tool-definition.d.ts +18 -14
- package/dist/esm/activities/chat/tools/tool-definition.js.map +1 -1
- package/dist/esm/index.d.ts +2 -2
- package/dist/esm/index.js +5 -4
- package/dist/esm/stream-to-response.d.ts +28 -21
- package/dist/esm/stream-to-response.js +24 -17
- package/dist/esm/stream-to-response.js.map +1 -1
- package/dist/esm/types.d.ts +44 -25
- package/package.json +3 -6
- package/src/activities/chat/index.ts +36 -28
- package/src/activities/chat/tools/schema-converter.ts +332 -0
- package/src/activities/chat/tools/tool-calls.ts +47 -53
- package/src/activities/chat/tools/tool-definition.ts +33 -29
- package/src/index.ts +5 -2
- package/src/stream-to-response.ts +59 -44
- package/src/types.ts +47 -26
- package/dist/esm/activities/chat/tools/zod-converter.d.ts +0 -69
- package/dist/esm/activities/chat/tools/zod-converter.js +0 -99
- package/dist/esm/activities/chat/tools/zod-converter.js.map +0 -1
- package/src/activities/chat/tools/zod-converter.ts +0 -235
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream-to-response.js","sources":["../../src/stream-to-response.ts"],"sourcesContent":["import type { StreamChunk } from './types'\n\n/**\n * Collect all text content from a StreamChunk async iterable and return as a string.\n *\n * This function consumes the entire stream, accumulating content from 'content' type chunks,\n * and returns the final concatenated text.\n *\n * @param stream - AsyncIterable of StreamChunks from chat()\n * @returns Promise<string> - The accumulated text content\n *\n * @example\n * ```typescript\n * const stream = chat({\n * adapter: openaiText(),\n * model: 'gpt-4o',\n * messages: [{ role: 'user', content: 'Hello!' }]\n * });\n * const text = await streamToText(stream);\n * console.log(text); // \"Hello! How can I help you today?\"\n * ```\n */\nexport async function streamToText(\n stream: AsyncIterable<StreamChunk>,\n): Promise<string> {\n let accumulatedContent = ''\n\n for await (const chunk of stream) {\n if (chunk.type === 'content' && chunk.delta) {\n accumulatedContent += chunk.delta\n }\n }\n\n return accumulatedContent\n}\n\n/**\n * Convert a StreamChunk async iterable to a ReadableStream in Server-Sent Events format\n *\n * This creates a ReadableStream that emits chunks in SSE format:\n * - Each chunk is prefixed with \"data: \"\n * - Each chunk is followed by \"\\n\\n\"\n * - Stream ends with \"data: [DONE]\\n\\n\"\n *\n * @param stream - AsyncIterable of StreamChunks from chat()\n * @param abortController - Optional AbortController to abort when stream is cancelled\n * @returns ReadableStream in Server-Sent Events format\n *\n * @example\n * ```typescript\n * const stream = chat({ adapter: openaiText(), model: \"gpt-4o\", messages: [...] });\n * const readableStream = toServerSentEventsStream(stream);\n * // Use with Response, or any API that accepts ReadableStream\n * ```\n */\nexport function toServerSentEventsStream(\n stream: AsyncIterable<StreamChunk>,\n abortController?: AbortController,\n): ReadableStream<Uint8Array> {\n const encoder = new TextEncoder()\n\n return new ReadableStream({\n async start(controller) {\n try {\n for await (const chunk of stream) {\n // Check if stream was cancelled/aborted\n if (abortController?.signal.aborted) {\n break\n }\n\n // Send each chunk as Server-Sent Events format\n controller.enqueue(\n encoder.encode(`data: ${JSON.stringify(chunk)}\\n\\n`),\n )\n }\n\n // Send completion marker\n controller.enqueue(encoder.encode('data: [DONE]\\n\\n'))\n controller.close()\n } catch (error: any) {\n // Don't send error if aborted\n if (abortController?.signal.aborted) {\n controller.close()\n return\n }\n\n // Send error chunk\n controller.enqueue(\n encoder.encode(\n `data: ${JSON.stringify({\n type: 'error',\n error: {\n message: error.message || 'Unknown error occurred',\n code: error.code,\n },\n })}\\n\\n`,\n ),\n )\n controller.close()\n }\n },\n cancel() {\n // When the ReadableStream is cancelled (e.g., client disconnects),\n // abort the underlying stream\n if (abortController) {\n abortController.abort()\n }\n },\n })\n}\n\n/**\n * Convert a StreamChunk async iterable to a ReadableStream in HTTP stream format (newline-delimited JSON)\n *\n * This creates a ReadableStream that emits chunks as newline-delimited JSON:\n * - Each chunk is JSON.stringify'd and followed by \"\\n\"\n * - No SSE formatting (no \"data: \" prefix)\n *\n * This format is compatible with `fetchHttpStream` connection adapter.\n *\n * @param stream - AsyncIterable of StreamChunks from chat()\n * @param abortController - Optional AbortController to abort when stream is cancelled\n * @returns ReadableStream in HTTP stream format (newline-delimited JSON)\n *\n * @example\n * ```typescript\n * const stream = chat({ adapter: openaiText(), model: \"gpt-4o\", messages: [...] });\n * const readableStream = toHttpStream(stream);\n * // Use with Response for HTTP streaming (not SSE)\n * return new Response(readableStream, {\n * headers: { 'Content-Type': 'application/x-ndjson' }\n * });\n * ```\n */\nexport function toHttpStream(\n stream: AsyncIterable<StreamChunk>,\n abortController?: AbortController,\n): ReadableStream<Uint8Array> {\n const encoder = new TextEncoder()\n\n return new ReadableStream({\n async start(controller) {\n try {\n for await (const chunk of stream) {\n // Check if stream was cancelled/aborted\n if (abortController?.signal.aborted) {\n break\n }\n\n // Send each chunk as newline-delimited JSON\n controller.enqueue(encoder.encode(`${JSON.stringify(chunk)}\\n`))\n }\n\n controller.close()\n } catch (error: any) {\n // Don't send error if aborted\n if (abortController?.signal.aborted) {\n controller.close()\n return\n }\n\n // Send error chunk\n controller.enqueue(\n encoder.encode(\n `${JSON.stringify({\n type: 'error',\n error: {\n message: error.message || 'Unknown error occurred',\n code: error.code,\n },\n })}\\n`,\n ),\n )\n controller.close()\n }\n },\n cancel() {\n // When the ReadableStream is cancelled (e.g., client disconnects),\n // abort the underlying stream\n if (abortController) {\n abortController.abort()\n }\n },\n })\n}\n\n/**\n * Create a streaming HTTP response from a StreamChunk async iterable\n * Includes proper headers for Server-Sent Events\n *\n * @deprecated Use `toServerSentEventsStream` instead. This function will be removed in a future version.\n *\n * @param stream - AsyncIterable of StreamChunks from chat()\n * @param init - Optional Response initialization options\n * @param abortController - Optional AbortController to abort when client disconnects\n * @returns Response object with SSE headers and streaming body\n *\n * @example\n * ```typescript\n * export async function POST(request: Request) {\n * const { messages } = await request.json();\n * const abortController = new AbortController();\n * const stream = chat({\n * adapter: openaiText(),\n * model: \"gpt-4o\",\n * messages,\n * options: { abortSignal: abortController.signal }\n * });\n * return toStreamResponse(stream, undefined, abortController);\n * }\n * ```\n */\nexport function toStreamResponse(\n stream: AsyncIterable<StreamChunk>,\n init?: ResponseInit & { abortController?: AbortController },\n): Response {\n if (typeof console !== 'undefined') {\n console.warn(\n '`toStreamResponse` is deprecated. Use `toServerSentEventsStream` instead. Example:\\n' +\n ' const readableStream = toServerSentEventsStream(stream, abortController);\\n' +\n ' return new Response(readableStream, {\\n' +\n \" headers: { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', Connection: 'keep-alive' }\\n\" +\n ' });',\n )\n }\n\n const { headers, abortController, ...responseInit } = init ?? {}\n return new Response(toServerSentEventsStream(stream, abortController), {\n ...responseInit,\n headers: {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n Connection: 'keep-alive',\n ...(headers || {}),\n },\n })\n}\n"],"names":[],"mappings":"AAsBA,eAAsB,aACpB,QACiB;AACjB,MAAI,qBAAqB;AAEzB,mBAAiB,SAAS,QAAQ;AAChC,QAAI,MAAM,SAAS,aAAa,MAAM,OAAO;AAC3C,4BAAsB,MAAM;AAAA,IAC9B;AAAA,EACF;AAEA,SAAO;AACT;AAqBO,SAAS,yBACd,QACA,iBAC4B;AAC5B,QAAM,UAAU,IAAI,YAAA;AAEpB,SAAO,IAAI,eAAe;AAAA,IACxB,MAAM,MAAM,YAAY;AACtB,UAAI;AACF,yBAAiB,SAAS,QAAQ;AAEhC,cAAI,iBAAiB,OAAO,SAAS;AACnC;AAAA,UACF;AAGA,qBAAW;AAAA,YACT,QAAQ,OAAO,SAAS,KAAK,UAAU,KAAK,CAAC;AAAA;AAAA,CAAM;AAAA,UAAA;AAAA,QAEvD;AAGA,mBAAW,QAAQ,QAAQ,OAAO,kBAAkB,CAAC;AACrD,mBAAW,MAAA;AAAA,MACb,SAAS,OAAY;AAEnB,YAAI,iBAAiB,OAAO,SAAS;AACnC,qBAAW,MAAA;AACX;AAAA,QACF;AAGA,mBAAW;AAAA,UACT,QAAQ;AAAA,YACN,SAAS,KAAK,UAAU;AAAA,cACtB,MAAM;AAAA,cACN,OAAO;AAAA,gBACL,SAAS,MAAM,WAAW;AAAA,gBAC1B,MAAM,MAAM;AAAA,cAAA;AAAA,YACd,CACD,CAAC;AAAA;AAAA;AAAA,UAAA;AAAA,QACJ;AAEF,mBAAW,MAAA;AAAA,MACb;AAAA,IACF;AAAA,IACA,SAAS;AAGP,UAAI,iBAAiB;AACnB,wBAAgB,MAAA;AAAA,MAClB;AAAA,IACF;AAAA,EAAA,CACD;AACH;AAyBO,SAAS,aACd,QACA,iBAC4B;AAC5B,QAAM,UAAU,IAAI,YAAA;AAEpB,SAAO,IAAI,eAAe;AAAA,IACxB,MAAM,MAAM,YAAY;AACtB,UAAI;AACF,yBAAiB,SAAS,QAAQ;AAEhC,cAAI,iBAAiB,OAAO,SAAS;AACnC;AAAA,UACF;AAGA,qBAAW,QAAQ,QAAQ,OAAO,GAAG,KAAK,UAAU,KAAK,CAAC;AAAA,CAAI,CAAC;AAAA,QACjE;AAEA,mBAAW,MAAA;AAAA,MACb,SAAS,OAAY;AAEnB,YAAI,iBAAiB,OAAO,SAAS;AACnC,qBAAW,MAAA;AACX;AAAA,QACF;AAGA,mBAAW;AAAA,UACT,QAAQ;AAAA,YACN,GAAG,KAAK,UAAU;AAAA,cAChB,MAAM;AAAA,cACN,OAAO;AAAA,gBACL,SAAS,MAAM,WAAW;AAAA,gBAC1B,MAAM,MAAM;AAAA,cAAA;AAAA,YACd,CACD,CAAC;AAAA;AAAA,UAAA;AAAA,QACJ;AAEF,mBAAW,MAAA;AAAA,MACb;AAAA,IACF;AAAA,IACA,SAAS;AAGP,UAAI,iBAAiB;AACnB,wBAAgB,MAAA;AAAA,MAClB;AAAA,IACF;AAAA,EAAA,CACD;AACH;AA4BO,SAAS,iBACd,QACA,MACU;AACV,MAAI,OAAO,YAAY,aAAa;AAClC,YAAQ;AAAA,MACN;AAAA,IAAA;AAAA,EAMJ;AAEA,QAAM,EAAE,SAAS,iBAAiB,GAAG,aAAA,IAAiB,QAAQ,CAAA;AAC9D,SAAO,IAAI,SAAS,yBAAyB,QAAQ,eAAe,GAAG;AAAA,IACrE,GAAG;AAAA,IACH,SAAS;AAAA,MACP,gBAAgB;AAAA,MAChB,iBAAiB;AAAA,MACjB,YAAY;AAAA,MACZ,GAAI,WAAW,CAAA;AAAA,IAAC;AAAA,EAClB,CACD;AACH;"}
|
|
1
|
+
{"version":3,"file":"stream-to-response.js","sources":["../../src/stream-to-response.ts"],"sourcesContent":["import type { StreamChunk } from './types'\n\n/**\n * Collect all text content from a StreamChunk async iterable and return as a string.\n *\n * This function consumes the entire stream, accumulating content from 'content' type chunks,\n * and returns the final concatenated text.\n *\n * @param stream - AsyncIterable of StreamChunks from chat()\n * @returns Promise<string> - The accumulated text content\n *\n * @example\n * ```typescript\n * const stream = chat({\n * adapter: openaiText(),\n * model: 'gpt-4o',\n * messages: [{ role: 'user', content: 'Hello!' }]\n * });\n * const text = await streamToText(stream);\n * console.log(text); // \"Hello! How can I help you today?\"\n * ```\n */\nexport async function streamToText(\n stream: AsyncIterable<StreamChunk>,\n): Promise<string> {\n let accumulatedContent = ''\n\n for await (const chunk of stream) {\n if (chunk.type === 'content' && chunk.delta) {\n accumulatedContent += chunk.delta\n }\n }\n\n return accumulatedContent\n}\n\n/**\n * Convert a StreamChunk async iterable to a ReadableStream in Server-Sent Events format\n *\n * This creates a ReadableStream that emits chunks in SSE format:\n * - Each chunk is prefixed with \"data: \"\n * - Each chunk is followed by \"\\n\\n\"\n * - Stream ends with \"data: [DONE]\\n\\n\"\n *\n * @param stream - AsyncIterable of StreamChunks from chat()\n * @param abortController - Optional AbortController to abort when stream is cancelled\n * @returns ReadableStream in Server-Sent Events format\n */\nexport function toServerSentEventsStream(\n stream: AsyncIterable<StreamChunk>,\n abortController?: AbortController,\n): ReadableStream<Uint8Array> {\n const encoder = new TextEncoder()\n\n return new ReadableStream({\n async start(controller) {\n try {\n for await (const chunk of stream) {\n // Check if stream was cancelled/aborted\n if (abortController?.signal.aborted) {\n break\n }\n\n // Send each chunk as Server-Sent Events format\n controller.enqueue(\n encoder.encode(`data: ${JSON.stringify(chunk)}\\n\\n`),\n )\n }\n\n // Send completion marker\n controller.enqueue(encoder.encode('data: [DONE]\\n\\n'))\n controller.close()\n } catch (error: any) {\n // Don't send error if aborted\n if (abortController?.signal.aborted) {\n controller.close()\n return\n }\n\n // Send error chunk\n controller.enqueue(\n encoder.encode(\n `data: ${JSON.stringify({\n type: 'error',\n error: {\n message: error.message || 'Unknown error occurred',\n code: error.code,\n },\n })}\\n\\n`,\n ),\n )\n controller.close()\n }\n },\n cancel() {\n // When the ReadableStream is cancelled (e.g., client disconnects),\n // abort the underlying stream\n if (abortController) {\n abortController.abort()\n }\n },\n })\n}\n\n/**\n * Convert a StreamChunk async iterable to a Response in Server-Sent Events format\n *\n * This creates a Response that emits chunks in SSE format:\n * - Each chunk is prefixed with \"data: \"\n * - Each chunk is followed by \"\\n\\n\"\n * - Stream ends with \"data: [DONE]\\n\\n\"\n *\n * @param stream - AsyncIterable of StreamChunks from chat()\n * @param init - Optional Response initialization options (including `abortController`)\n * @returns Response in Server-Sent Events format\n *\n * @example\n * ```typescript\n * const stream = chat({ adapter: openaiText(), model: \"gpt-4o\", messages: [...] });\n * return toServerSentEventsResponse(stream, { abortController });\n * ```\n */\nexport function toServerSentEventsResponse(\n stream: AsyncIterable<StreamChunk>,\n init?: ResponseInit & { abortController?: AbortController },\n): Response {\n const { headers, abortController, ...responseInit } = init ?? {}\n\n // Start with default SSE headers\n const mergedHeaders = new Headers({\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n Connection: 'keep-alive',\n })\n\n // Override with user headers if provided, handling all HeadersInit forms:\n // Headers instance, string[][], or plain object\n if (headers) {\n const userHeaders = new Headers(headers)\n userHeaders.forEach((value, key) => {\n mergedHeaders.set(key, value)\n })\n }\n\n return new Response(toServerSentEventsStream(stream, abortController), {\n ...responseInit,\n headers: mergedHeaders,\n })\n}\n\n/**\n * Convert a StreamChunk async iterable to a ReadableStream in HTTP stream format (newline-delimited JSON)\n *\n * This creates a ReadableStream that emits chunks as newline-delimited JSON:\n * - Each chunk is JSON.stringify'd and followed by \"\\n\"\n * - No SSE formatting (no \"data: \" prefix)\n *\n * This format is compatible with `fetchHttpStream` connection adapter.\n *\n * @param stream - AsyncIterable of StreamChunks from chat()\n * @param abortController - Optional AbortController to abort when stream is cancelled\n * @returns ReadableStream in HTTP stream format (newline-delimited JSON)\n *\n * @example\n * ```typescript\n * const stream = chat({ adapter: openaiText(), model: \"gpt-4o\", messages: [...] });\n * const readableStream = toHttpStream(stream);\n * // Use with Response for HTTP streaming (not SSE)\n * return new Response(readableStream, {\n * headers: { 'Content-Type': 'application/x-ndjson' }\n * });\n * ```\n */\nexport function toHttpStream(\n stream: AsyncIterable<StreamChunk>,\n abortController?: AbortController,\n): ReadableStream<Uint8Array> {\n const encoder = new TextEncoder()\n\n return new ReadableStream({\n async start(controller) {\n try {\n for await (const chunk of stream) {\n // Check if stream was cancelled/aborted\n if (abortController?.signal.aborted) {\n break\n }\n\n // Send each chunk as newline-delimited JSON\n controller.enqueue(encoder.encode(`${JSON.stringify(chunk)}\\n`))\n }\n\n controller.close()\n } catch (error: any) {\n // Don't send error if aborted\n if (abortController?.signal.aborted) {\n controller.close()\n return\n }\n\n // Send error chunk\n controller.enqueue(\n encoder.encode(\n `${JSON.stringify({\n type: 'error',\n error: {\n message: error.message || 'Unknown error occurred',\n code: error.code,\n },\n })}\\n`,\n ),\n )\n controller.close()\n }\n },\n cancel() {\n // When the ReadableStream is cancelled (e.g., client disconnects),\n // abort the underlying stream\n if (abortController) {\n abortController.abort()\n }\n },\n })\n}\n\n/**\n * Convert a StreamChunk async iterable to a Response in HTTP stream format (newline-delimited JSON)\n *\n * This creates a Response that emits chunks in HTTP stream format:\n * - Each chunk is JSON.stringify'd and followed by \"\\n\"\n * - No SSE formatting (no \"data: \" prefix)\n *\n * This format is compatible with `fetchHttpStream` connection adapter.\n *\n * @param stream - AsyncIterable of StreamChunks from chat()\n * @param init - Optional Response initialization options (including `abortController`)\n * @returns Response in HTTP stream format (newline-delimited JSON)\n *\n * @example\n * ```typescript\n * const stream = chat({ adapter: openaiText(), model: \"gpt-4o\", messages: [...] });\n * return toHttpResponse(stream, { abortController });\n * ```\n */\nexport function toHttpResponse(\n stream: AsyncIterable<StreamChunk>,\n init?: ResponseInit & { abortController?: AbortController },\n): Response {\n return new Response(toHttpStream(stream, init?.abortController), {\n ...init,\n })\n}\n"],"names":[],"mappings":"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"}
|
package/dist/esm/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { StandardJSONSchemaV1 } from '@standard-schema/spec';
|
|
2
2
|
/**
|
|
3
3
|
* Tool call states - track the lifecycle of a tool call
|
|
4
4
|
*/
|
|
@@ -9,17 +9,17 @@ export type ToolCallState = 'awaiting-input' | 'input-streaming' | 'input-comple
|
|
|
9
9
|
export type ToolResultState = 'streaming' | 'complete' | 'error';
|
|
10
10
|
/**
|
|
11
11
|
* JSON Schema type for defining tool input/output schemas as raw JSON Schema objects.
|
|
12
|
-
* This allows tools to be defined without
|
|
12
|
+
* This allows tools to be defined without schema libraries when you have JSON Schema definitions available.
|
|
13
13
|
*/
|
|
14
14
|
export interface JSONSchema {
|
|
15
15
|
type?: string | Array<string>;
|
|
16
16
|
properties?: Record<string, JSONSchema>;
|
|
17
17
|
items?: JSONSchema | Array<JSONSchema>;
|
|
18
18
|
required?: Array<string>;
|
|
19
|
-
enum?: Array<
|
|
20
|
-
const?:
|
|
19
|
+
enum?: Array<unknown>;
|
|
20
|
+
const?: unknown;
|
|
21
21
|
description?: string;
|
|
22
|
-
default?:
|
|
22
|
+
default?: unknown;
|
|
23
23
|
$ref?: string;
|
|
24
24
|
$defs?: Record<string, JSONSchema>;
|
|
25
25
|
definitions?: Record<string, JSONSchema>;
|
|
@@ -48,19 +48,26 @@ export interface JSONSchema {
|
|
|
48
48
|
minProperties?: number;
|
|
49
49
|
maxProperties?: number;
|
|
50
50
|
title?: string;
|
|
51
|
-
examples?: Array<
|
|
51
|
+
examples?: Array<unknown>;
|
|
52
52
|
[key: string]: any;
|
|
53
53
|
}
|
|
54
54
|
/**
|
|
55
|
-
* Union type for schema input - can be
|
|
55
|
+
* Union type for schema input - can be any Standard JSON Schema compliant schema or a plain JSONSchema object.
|
|
56
|
+
*
|
|
57
|
+
* Standard JSON Schema compliant libraries include:
|
|
58
|
+
* - Zod v4.2+ (natively supports StandardJSONSchemaV1)
|
|
59
|
+
* - ArkType v2.1.28+ (natively supports StandardJSONSchemaV1)
|
|
60
|
+
* - Valibot v1.2+ (via `toStandardJsonSchema()` from `@valibot/to-json-schema`)
|
|
61
|
+
*
|
|
62
|
+
* @see https://standardschema.dev/json-schema
|
|
56
63
|
*/
|
|
57
|
-
export type SchemaInput =
|
|
64
|
+
export type SchemaInput = StandardJSONSchemaV1<any, any> | JSONSchema;
|
|
58
65
|
/**
|
|
59
66
|
* Infer the TypeScript type from a schema.
|
|
60
|
-
* For
|
|
61
|
-
* For JSONSchema, returns `any` since we can't infer types from JSON Schema at compile time.
|
|
67
|
+
* For Standard JSON Schema compliant schemas, extracts the input type.
|
|
68
|
+
* For plain JSONSchema, returns `any` since we can't infer types from JSON Schema at compile time.
|
|
62
69
|
*/
|
|
63
|
-
export type InferSchemaType<T> = T extends
|
|
70
|
+
export type InferSchemaType<T> = T extends StandardJSONSchemaV1<infer TInput, unknown> ? TInput : unknown;
|
|
64
71
|
export interface ToolCall {
|
|
65
72
|
id: string;
|
|
66
73
|
type: 'function';
|
|
@@ -234,12 +241,14 @@ export type ConstrainedModelMessage<TInputModalitiesTypes extends InputModalitie
|
|
|
234
241
|
* Tools allow the model to interact with external systems, APIs, or perform computations.
|
|
235
242
|
* The model will decide when to call tools based on the user's request and the tool descriptions.
|
|
236
243
|
*
|
|
237
|
-
* Tools can use
|
|
244
|
+
* Tools can use any Standard JSON Schema compliant library (Zod, ArkType, Valibot, etc.)
|
|
245
|
+
* or plain JSON Schema objects for runtime validation and type safety.
|
|
238
246
|
*
|
|
239
247
|
* @see https://platform.openai.com/docs/guides/function-calling
|
|
240
248
|
* @see https://docs.anthropic.com/claude/docs/tool-use
|
|
249
|
+
* @see https://standardschema.dev/json-schema
|
|
241
250
|
*/
|
|
242
|
-
export interface Tool<TInput extends SchemaInput =
|
|
251
|
+
export interface Tool<TInput extends SchemaInput = SchemaInput, TOutput extends SchemaInput = SchemaInput, TName extends string = string> {
|
|
243
252
|
/**
|
|
244
253
|
* Unique name of the tool (used by the model to call it).
|
|
245
254
|
*
|
|
@@ -261,16 +270,16 @@ export interface Tool<TInput extends SchemaInput = z.ZodType, TOutput extends Sc
|
|
|
261
270
|
/**
|
|
262
271
|
* Schema describing the tool's input parameters.
|
|
263
272
|
*
|
|
264
|
-
* Can be
|
|
273
|
+
* Can be any Standard JSON Schema compliant schema (Zod, ArkType, Valibot, etc.) or a plain JSON Schema object.
|
|
265
274
|
* Defines the structure and types of arguments the tool accepts.
|
|
266
275
|
* The model will generate arguments matching this schema.
|
|
267
|
-
*
|
|
276
|
+
* Standard JSON Schema compliant schemas are converted to JSON Schema for LLM providers.
|
|
268
277
|
*
|
|
269
|
-
* @see https://
|
|
278
|
+
* @see https://standardschema.dev/json-schema
|
|
270
279
|
* @see https://json-schema.org/
|
|
271
280
|
*
|
|
272
281
|
* @example
|
|
273
|
-
* // Using Zod schema
|
|
282
|
+
* // Using Zod v4+ schema (natively supports Standard JSON Schema)
|
|
274
283
|
* import { z } from 'zod';
|
|
275
284
|
* z.object({
|
|
276
285
|
* location: z.string().describe("City name or coordinates"),
|
|
@@ -278,7 +287,15 @@ export interface Tool<TInput extends SchemaInput = z.ZodType, TOutput extends Sc
|
|
|
278
287
|
* })
|
|
279
288
|
*
|
|
280
289
|
* @example
|
|
281
|
-
* // Using JSON Schema
|
|
290
|
+
* // Using ArkType (natively supports Standard JSON Schema)
|
|
291
|
+
* import { type } from 'arktype';
|
|
292
|
+
* type({
|
|
293
|
+
* location: 'string',
|
|
294
|
+
* unit: "'celsius' | 'fahrenheit'"
|
|
295
|
+
* })
|
|
296
|
+
*
|
|
297
|
+
* @example
|
|
298
|
+
* // Using plain JSON Schema
|
|
282
299
|
* {
|
|
283
300
|
* type: 'object',
|
|
284
301
|
* properties: {
|
|
@@ -292,15 +309,16 @@ export interface Tool<TInput extends SchemaInput = z.ZodType, TOutput extends Sc
|
|
|
292
309
|
/**
|
|
293
310
|
* Optional schema for validating tool output.
|
|
294
311
|
*
|
|
295
|
-
* Can be
|
|
296
|
-
* If provided with a
|
|
297
|
-
* being sent back to the model. This catches bugs in tool
|
|
298
|
-
* and ensures consistent output formatting.
|
|
312
|
+
* Can be any Standard JSON Schema compliant schema or a plain JSON Schema object.
|
|
313
|
+
* If provided with a Standard Schema compliant schema, tool results will be validated
|
|
314
|
+
* against this schema before being sent back to the model. This catches bugs in tool
|
|
315
|
+
* implementations and ensures consistent output formatting.
|
|
299
316
|
*
|
|
300
317
|
* Note: This is client-side validation only - not sent to LLM providers.
|
|
301
|
-
* Note: JSON Schema output validation is not performed at runtime.
|
|
318
|
+
* Note: Plain JSON Schema output validation is not performed at runtime.
|
|
302
319
|
*
|
|
303
320
|
* @example
|
|
321
|
+
* // Using Zod
|
|
304
322
|
* z.object({
|
|
305
323
|
* temperature: z.number(),
|
|
306
324
|
* conditions: z.string(),
|
|
@@ -502,12 +520,13 @@ export interface TextOptions<TProviderOptionsSuperset extends Record<string, any
|
|
|
502
520
|
modelOptions?: TProviderOptionsForModel;
|
|
503
521
|
request?: Request | RequestInit;
|
|
504
522
|
/**
|
|
505
|
-
*
|
|
523
|
+
* Schema for structured output.
|
|
506
524
|
* When provided, the adapter should use the provider's native structured output API
|
|
507
525
|
* to ensure the response conforms to this schema.
|
|
508
526
|
* The schema will be converted to JSON Schema format before being sent to the provider.
|
|
527
|
+
* Supports any Standard JSON Schema compliant library (Zod, ArkType, Valibot, etc.).
|
|
509
528
|
*/
|
|
510
|
-
outputSchema?:
|
|
529
|
+
outputSchema?: SchemaInput;
|
|
511
530
|
/**
|
|
512
531
|
* Conversation ID for correlating client and server-side devtools events.
|
|
513
532
|
* When provided, server-side events will be linked to the client conversation in devtools.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/ai",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Core TanStack AI library - Open source AI SDK",
|
|
5
5
|
"author": "Tanner Linsley",
|
|
6
6
|
"license": "MIT",
|
|
@@ -46,13 +46,10 @@
|
|
|
46
46
|
"@tanstack/devtools-event-client": "^0.4.0",
|
|
47
47
|
"partial-json": "^0.1.7"
|
|
48
48
|
},
|
|
49
|
-
"peerDependencies": {
|
|
50
|
-
"@alcyone-labs/zod-to-json-schema": "^4.0.0",
|
|
51
|
-
"zod": "^3.0.0 || ^4.0.0"
|
|
52
|
-
},
|
|
53
49
|
"devDependencies": {
|
|
50
|
+
"@standard-schema/spec": "^1.1.0",
|
|
54
51
|
"@vitest/coverage-v8": "4.0.14",
|
|
55
|
-
"zod": "^4.
|
|
52
|
+
"zod": "^4.2.0"
|
|
56
53
|
},
|
|
57
54
|
"scripts": {
|
|
58
55
|
"build": "vite build",
|
|
@@ -8,20 +8,25 @@
|
|
|
8
8
|
import { aiEventClient } from '../../event-client.js'
|
|
9
9
|
import { streamToText } from '../../stream-to-response.js'
|
|
10
10
|
import { ToolCallManager, executeToolCalls } from './tools/tool-calls'
|
|
11
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
convertSchemaToJsonSchema,
|
|
13
|
+
isStandardSchema,
|
|
14
|
+
parseWithStandardSchema,
|
|
15
|
+
} from './tools/schema-converter'
|
|
12
16
|
import { maxIterations as maxIterationsStrategy } from './agent-loop-strategies'
|
|
13
17
|
import type {
|
|
14
18
|
ApprovalRequest,
|
|
15
19
|
ClientToolRequest,
|
|
16
20
|
ToolResult,
|
|
17
21
|
} from './tools/tool-calls'
|
|
18
|
-
import type { z } from 'zod'
|
|
19
22
|
import type { AnyTextAdapter } from './adapter'
|
|
20
23
|
import type {
|
|
21
24
|
AgentLoopStrategy,
|
|
22
25
|
ConstrainedModelMessage,
|
|
23
26
|
DoneStreamChunk,
|
|
27
|
+
InferSchemaType,
|
|
24
28
|
ModelMessage,
|
|
29
|
+
SchemaInput,
|
|
25
30
|
StreamChunk,
|
|
26
31
|
TextOptions,
|
|
27
32
|
Tool,
|
|
@@ -44,12 +49,12 @@ export const kind = 'text' as const
|
|
|
44
49
|
* Types are extracted directly from the adapter (which has pre-resolved generics).
|
|
45
50
|
*
|
|
46
51
|
* @template TAdapter - The text adapter type (created by a provider function)
|
|
47
|
-
* @template TSchema - Optional
|
|
52
|
+
* @template TSchema - Optional Standard Schema for structured output
|
|
48
53
|
* @template TStream - Whether to stream the output (default: true)
|
|
49
54
|
*/
|
|
50
55
|
export interface TextActivityOptions<
|
|
51
56
|
TAdapter extends AnyTextAdapter,
|
|
52
|
-
TSchema extends
|
|
57
|
+
TSchema extends SchemaInput | undefined,
|
|
53
58
|
TStream extends boolean,
|
|
54
59
|
> {
|
|
55
60
|
/** The text adapter to use (created by a provider function like openaiText('gpt-4o')) */
|
|
@@ -82,11 +87,13 @@ export interface TextActivityOptions<
|
|
|
82
87
|
/** Unique conversation identifier for tracking */
|
|
83
88
|
conversationId?: TextOptions['conversationId']
|
|
84
89
|
/**
|
|
85
|
-
* Optional
|
|
90
|
+
* Optional Standard Schema for structured output.
|
|
86
91
|
* When provided, the activity will:
|
|
87
92
|
* 1. Run the full agentic loop (executing tools as needed)
|
|
88
93
|
* 2. Once complete, return a Promise with the parsed output matching the schema
|
|
89
94
|
*
|
|
95
|
+
* Supports any Standard Schema compliant library (Zod v4+, ArkType, Valibot, etc.)
|
|
96
|
+
*
|
|
90
97
|
* @example
|
|
91
98
|
* ```ts
|
|
92
99
|
* const result = await chat({
|
|
@@ -104,7 +111,7 @@ export interface TextActivityOptions<
|
|
|
104
111
|
* When false, returns a Promise<string> with the collected text content.
|
|
105
112
|
*
|
|
106
113
|
* Note: If outputSchema is provided, this option is ignored and the result
|
|
107
|
-
* is always a Promise<
|
|
114
|
+
* is always a Promise<InferSchemaType<TSchema>>.
|
|
108
115
|
*
|
|
109
116
|
* @default true
|
|
110
117
|
*
|
|
@@ -140,7 +147,7 @@ export interface TextActivityOptions<
|
|
|
140
147
|
*/
|
|
141
148
|
export function createChatOptions<
|
|
142
149
|
TAdapter extends AnyTextAdapter,
|
|
143
|
-
TSchema extends
|
|
150
|
+
TSchema extends SchemaInput | undefined = undefined,
|
|
144
151
|
TStream extends boolean = true,
|
|
145
152
|
>(
|
|
146
153
|
options: TextActivityOptions<TAdapter, TSchema, TStream>,
|
|
@@ -154,15 +161,15 @@ export function createChatOptions<
|
|
|
154
161
|
|
|
155
162
|
/**
|
|
156
163
|
* Result type for the text activity.
|
|
157
|
-
* - If outputSchema is provided: Promise<
|
|
164
|
+
* - If outputSchema is provided: Promise<InferSchemaType<TSchema>>
|
|
158
165
|
* - If stream is false: Promise<string>
|
|
159
166
|
* - Otherwise (stream is true, default): AsyncIterable<StreamChunk>
|
|
160
167
|
*/
|
|
161
168
|
export type TextActivityResult<
|
|
162
|
-
TSchema extends
|
|
169
|
+
TSchema extends SchemaInput | undefined,
|
|
163
170
|
TStream extends boolean = true,
|
|
164
|
-
> = TSchema extends
|
|
165
|
-
? Promise<
|
|
171
|
+
> = TSchema extends SchemaInput
|
|
172
|
+
? Promise<InferSchemaType<TSchema>>
|
|
166
173
|
: TStream extends false
|
|
167
174
|
? Promise<string>
|
|
168
175
|
: AsyncIterable<StreamChunk>
|
|
@@ -366,14 +373,14 @@ class TextEngine<
|
|
|
366
373
|
const { temperature, topP, maxTokens, metadata, modelOptions } = this.params
|
|
367
374
|
const tools = this.params.tools
|
|
368
375
|
|
|
369
|
-
// Convert tool schemas
|
|
376
|
+
// Convert tool schemas to JSON Schema before passing to adapter
|
|
370
377
|
const toolsWithJsonSchemas = tools?.map((tool) => ({
|
|
371
378
|
...tool,
|
|
372
379
|
inputSchema: tool.inputSchema
|
|
373
|
-
?
|
|
380
|
+
? convertSchemaToJsonSchema(tool.inputSchema)
|
|
374
381
|
: undefined,
|
|
375
382
|
outputSchema: tool.outputSchema
|
|
376
|
-
?
|
|
383
|
+
? convertSchemaToJsonSchema(tool.outputSchema)
|
|
377
384
|
: undefined,
|
|
378
385
|
}))
|
|
379
386
|
|
|
@@ -968,7 +975,7 @@ class TextEngine<
|
|
|
968
975
|
*/
|
|
969
976
|
export function chat<
|
|
970
977
|
TAdapter extends AnyTextAdapter,
|
|
971
|
-
TSchema extends
|
|
978
|
+
TSchema extends SchemaInput | undefined = undefined,
|
|
972
979
|
TStream extends boolean = true,
|
|
973
980
|
>(
|
|
974
981
|
options: TextActivityOptions<TAdapter, TSchema, TStream>,
|
|
@@ -980,7 +987,7 @@ export function chat<
|
|
|
980
987
|
return runAgenticStructuredOutput(
|
|
981
988
|
options as unknown as TextActivityOptions<
|
|
982
989
|
AnyTextAdapter,
|
|
983
|
-
|
|
990
|
+
SchemaInput,
|
|
984
991
|
boolean
|
|
985
992
|
>,
|
|
986
993
|
) as TextActivityResult<TSchema, TStream>
|
|
@@ -1046,9 +1053,9 @@ function runNonStreamingText(
|
|
|
1046
1053
|
* 2. Once complete, call adapter.structuredOutput with the conversation context
|
|
1047
1054
|
* 3. Validate and return the structured result
|
|
1048
1055
|
*/
|
|
1049
|
-
async function runAgenticStructuredOutput<TSchema extends
|
|
1056
|
+
async function runAgenticStructuredOutput<TSchema extends SchemaInput>(
|
|
1050
1057
|
options: TextActivityOptions<AnyTextAdapter, TSchema, boolean>,
|
|
1051
|
-
): Promise<
|
|
1058
|
+
): Promise<InferSchemaType<TSchema>> {
|
|
1052
1059
|
const { adapter, outputSchema, ...textOptions } = options
|
|
1053
1060
|
const model = adapter.model
|
|
1054
1061
|
|
|
@@ -1060,8 +1067,8 @@ async function runAgenticStructuredOutput<TSchema extends z.ZodType>(
|
|
|
1060
1067
|
const engine = new TextEngine({
|
|
1061
1068
|
adapter,
|
|
1062
1069
|
params: { ...textOptions, model } as TextOptions<
|
|
1063
|
-
Record<string,
|
|
1064
|
-
Record<string,
|
|
1070
|
+
Record<string, unknown>,
|
|
1071
|
+
Record<string, unknown>
|
|
1065
1072
|
>,
|
|
1066
1073
|
})
|
|
1067
1074
|
|
|
@@ -1081,8 +1088,8 @@ async function runAgenticStructuredOutput<TSchema extends z.ZodType>(
|
|
|
1081
1088
|
...structuredTextOptions
|
|
1082
1089
|
} = textOptions
|
|
1083
1090
|
|
|
1084
|
-
// Convert the
|
|
1085
|
-
const jsonSchema =
|
|
1091
|
+
// Convert the schema to JSON Schema before passing to the adapter
|
|
1092
|
+
const jsonSchema = convertSchemaToJsonSchema(outputSchema)
|
|
1086
1093
|
if (!jsonSchema) {
|
|
1087
1094
|
throw new Error('Failed to convert output schema to JSON Schema')
|
|
1088
1095
|
}
|
|
@@ -1098,15 +1105,16 @@ async function runAgenticStructuredOutput<TSchema extends z.ZodType>(
|
|
|
1098
1105
|
outputSchema: jsonSchema,
|
|
1099
1106
|
})
|
|
1100
1107
|
|
|
1101
|
-
// Validate the result against the
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1108
|
+
// Validate the result against the schema if it's a Standard Schema
|
|
1109
|
+
if (isStandardSchema(outputSchema)) {
|
|
1110
|
+
return parseWithStandardSchema<InferSchemaType<TSchema>>(
|
|
1111
|
+
outputSchema,
|
|
1112
|
+
result.data,
|
|
1106
1113
|
)
|
|
1107
1114
|
}
|
|
1108
1115
|
|
|
1109
|
-
return
|
|
1116
|
+
// For plain JSON Schema, return the data as-is
|
|
1117
|
+
return result.data as InferSchemaType<TSchema>
|
|
1110
1118
|
}
|
|
1111
1119
|
|
|
1112
1120
|
// Re-export adapter types
|