@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.
Files changed (29) hide show
  1. package/README.md +0 -25
  2. package/dist/esm/activities/chat/index.d.ts +11 -10
  3. package/dist/esm/activities/chat/index.js +9 -9
  4. package/dist/esm/activities/chat/index.js.map +1 -1
  5. package/dist/esm/activities/chat/tools/schema-converter.d.ts +116 -0
  6. package/dist/esm/activities/chat/tools/schema-converter.js +115 -0
  7. package/dist/esm/activities/chat/tools/schema-converter.js.map +1 -0
  8. package/dist/esm/activities/chat/tools/tool-calls.js +23 -34
  9. package/dist/esm/activities/chat/tools/tool-calls.js.map +1 -1
  10. package/dist/esm/activities/chat/tools/tool-definition.d.ts +18 -14
  11. package/dist/esm/activities/chat/tools/tool-definition.js.map +1 -1
  12. package/dist/esm/index.d.ts +2 -2
  13. package/dist/esm/index.js +5 -4
  14. package/dist/esm/stream-to-response.d.ts +28 -21
  15. package/dist/esm/stream-to-response.js +24 -17
  16. package/dist/esm/stream-to-response.js.map +1 -1
  17. package/dist/esm/types.d.ts +44 -25
  18. package/package.json +3 -6
  19. package/src/activities/chat/index.ts +36 -28
  20. package/src/activities/chat/tools/schema-converter.ts +332 -0
  21. package/src/activities/chat/tools/tool-calls.ts +47 -53
  22. package/src/activities/chat/tools/tool-definition.ts +33 -29
  23. package/src/index.ts +5 -2
  24. package/src/stream-to-response.ts +59 -44
  25. package/src/types.ts +47 -26
  26. package/dist/esm/activities/chat/tools/zod-converter.d.ts +0 -69
  27. package/dist/esm/activities/chat/tools/zod-converter.js +0 -99
  28. package/dist/esm/activities/chat/tools/zod-converter.js.map +0 -1
  29. package/src/activities/chat/tools/zod-converter.ts +0 -235
@@ -1,235 +0,0 @@
1
- import { toJSONSchema } from 'zod'
2
- import type { z } from 'zod'
3
- import type { SchemaInput } from '../../../types'
4
-
5
- /**
6
- * Check if a value is a Zod schema by looking for Zod-specific internals.
7
- * Zod schemas have a `_zod` property that contains metadata.
8
- */
9
- function isZodSchema(schema: unknown): schema is z.ZodType {
10
- return (
11
- typeof schema === 'object' &&
12
- schema !== null &&
13
- '_zod' in schema &&
14
- typeof (schema as any)._zod === 'object'
15
- )
16
- }
17
-
18
- /**
19
- * Transform a JSON schema to be compatible with OpenAI's structured output requirements.
20
- * OpenAI requires:
21
- * - All properties must be in the `required` array
22
- * - Optional fields should have null added to their type union
23
- * - additionalProperties must be false for objects
24
- *
25
- * @param schema - JSON schema to transform
26
- * @param originalRequired - Original required array (to know which fields were optional)
27
- * @returns Transformed schema compatible with OpenAI structured output
28
- */
29
- function makeStructuredOutputCompatible(
30
- schema: Record<string, any>,
31
- originalRequired: Array<string> = [],
32
- ): Record<string, any> {
33
- const result = { ...schema }
34
-
35
- // Handle object types
36
- if (result.type === 'object' && result.properties) {
37
- const properties = { ...result.properties }
38
- const allPropertyNames = Object.keys(properties)
39
-
40
- // Transform each property
41
- for (const propName of allPropertyNames) {
42
- const prop = properties[propName]
43
- const wasOptional = !originalRequired.includes(propName)
44
-
45
- // Recursively transform nested objects/arrays
46
- if (prop.type === 'object' && prop.properties) {
47
- properties[propName] = makeStructuredOutputCompatible(
48
- prop,
49
- prop.required || [],
50
- )
51
- } else if (prop.type === 'array' && prop.items) {
52
- properties[propName] = {
53
- ...prop,
54
- items: makeStructuredOutputCompatible(
55
- prop.items,
56
- prop.items.required || [],
57
- ),
58
- }
59
- } else if (wasOptional) {
60
- // Make optional fields nullable by adding null to the type
61
- if (prop.type && !Array.isArray(prop.type)) {
62
- properties[propName] = {
63
- ...prop,
64
- type: [prop.type, 'null'],
65
- }
66
- } else if (Array.isArray(prop.type) && !prop.type.includes('null')) {
67
- properties[propName] = {
68
- ...prop,
69
- type: [...prop.type, 'null'],
70
- }
71
- }
72
- }
73
- }
74
-
75
- result.properties = properties
76
- // ALL properties must be required for OpenAI structured output
77
- result.required = allPropertyNames
78
- // additionalProperties must be false
79
- result.additionalProperties = false
80
- }
81
-
82
- // Handle array types with object items
83
- if (result.type === 'array' && result.items) {
84
- result.items = makeStructuredOutputCompatible(
85
- result.items,
86
- result.items.required || [],
87
- )
88
- }
89
-
90
- return result
91
- }
92
-
93
- /**
94
- * Options for schema conversion
95
- */
96
- export interface ConvertSchemaOptions {
97
- /**
98
- * When true, transforms the schema to be compatible with OpenAI's structured output requirements:
99
- * - All properties are added to the `required` array
100
- * - Optional fields get null added to their type union
101
- * - additionalProperties is set to false for all objects
102
- *
103
- * @default false
104
- */
105
- forStructuredOutput?: boolean
106
- }
107
-
108
- /**
109
- * Converts a schema (Zod or JSONSchema) to JSON Schema format compatible with LLM providers.
110
- * If the input is already a JSONSchema object, it is returned as-is.
111
- * If the input is a Zod schema, it is converted to JSON Schema.
112
- *
113
- * @param schema - Zod schema or JSONSchema object to convert
114
- * @param options - Conversion options
115
- * @returns JSON Schema object that can be sent to LLM providers
116
- *
117
- * @example
118
- * ```typescript
119
- * import { z } from 'zod';
120
- *
121
- * // Using Zod schema
122
- * const zodSchema = z.object({
123
- * location: z.string().describe('City name'),
124
- * unit: z.enum(['celsius', 'fahrenheit']).optional()
125
- * });
126
- *
127
- * const jsonSchema = convertZodToJsonSchema(zodSchema);
128
- * // Returns:
129
- * // {
130
- * // type: 'object',
131
- * // properties: {
132
- * // location: { type: 'string', description: 'City name' },
133
- * // unit: { type: 'string', enum: ['celsius', 'fahrenheit'] }
134
- * // },
135
- * // required: ['location']
136
- * // }
137
- *
138
- * // For OpenAI structured output (all fields required, optional fields nullable)
139
- * const structuredSchema = convertZodToJsonSchema(zodSchema, { forStructuredOutput: true });
140
- * // Returns:
141
- * // {
142
- * // type: 'object',
143
- * // properties: {
144
- * // location: { type: 'string', description: 'City name' },
145
- * // unit: { type: ['string', 'null'], enum: ['celsius', 'fahrenheit'] }
146
- * // },
147
- * // required: ['location', 'unit'],
148
- * // additionalProperties: false
149
- * // }
150
- *
151
- * // Using JSONSchema directly (passes through unchanged)
152
- * const rawSchema = {
153
- * type: 'object',
154
- * properties: { location: { type: 'string' } },
155
- * required: ['location']
156
- * };
157
- * const result = convertZodToJsonSchema(rawSchema);
158
- * // Returns the same object
159
- * ```
160
- */
161
- export function convertZodToJsonSchema(
162
- schema: SchemaInput | undefined,
163
- options: ConvertSchemaOptions = {},
164
- ): Record<string, any> | undefined {
165
- if (!schema) return undefined
166
-
167
- const { forStructuredOutput = false } = options
168
-
169
- // If it's not a Zod schema, assume it's already a JSONSchema and pass through
170
- if (!isZodSchema(schema)) {
171
- // Still apply structured output transformation if requested
172
- if (forStructuredOutput && typeof schema === 'object') {
173
- return makeStructuredOutputCompatible(
174
- schema,
175
- (schema as any).required || [],
176
- )
177
- }
178
- return schema
179
- }
180
-
181
- // Use Alcyone Labs fork which is compatible with Zod v4
182
- const jsonSchema = toJSONSchema(schema, {
183
- target: 'openapi-3.0',
184
- reused: 'ref',
185
- })
186
-
187
- // Remove $schema property as it's not needed for LLM providers
188
- let result = jsonSchema
189
- if (typeof result === 'object' && '$schema' in result) {
190
- const { $schema, ...rest } = result
191
- result = rest
192
- }
193
-
194
- // Ensure object schemas always have type: "object"
195
- // This fixes cases where zod-to-json-schema doesn't set type for empty objects
196
- if (typeof result === 'object') {
197
- // Check if the input schema is a ZodObject by inspecting its internal structure
198
- const isZodObject =
199
- typeof schema === 'object' &&
200
- 'def' in schema &&
201
- schema.def.type === 'object'
202
-
203
- // If we know it's a ZodObject but result doesn't have type, set it
204
- if (isZodObject && !result.type) {
205
- result.type = 'object'
206
- }
207
-
208
- // If result is completely empty (no keys), it's likely an empty object schema
209
- if (Object.keys(result).length === 0) {
210
- result.type = 'object'
211
- }
212
-
213
- // If it has properties (even empty), it should be an object type
214
- if ('properties' in result && !result.type) {
215
- result.type = 'object'
216
- }
217
-
218
- // Ensure properties exists for object types (even if empty)
219
- if (result.type === 'object' && !('properties' in result)) {
220
- result.properties = {}
221
- }
222
-
223
- // Ensure required exists for object types (even if empty array)
224
- if (result.type === 'object' && !('required' in result)) {
225
- result.required = []
226
- }
227
-
228
- // Apply structured output transformation if requested
229
- if (forStructuredOutput) {
230
- result = makeStructuredOutputCompatible(result, result.required || [])
231
- }
232
- }
233
-
234
- return result
235
- }