@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,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
|
-
}
|