universal-llm-client 4.0.0 → 4.1.0
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/dist/ai-model.d.ts +20 -22
- package/dist/ai-model.d.ts.map +1 -1
- package/dist/ai-model.js +26 -23
- package/dist/ai-model.js.map +1 -1
- package/dist/client.d.ts +5 -5
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +17 -9
- package/dist/client.js.map +1 -1
- package/dist/http.d.ts +2 -0
- package/dist/http.d.ts.map +1 -1
- package/dist/http.js +1 -0
- package/dist/http.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/interfaces.d.ts +49 -11
- package/dist/interfaces.d.ts.map +1 -1
- package/dist/interfaces.js +14 -0
- package/dist/interfaces.js.map +1 -1
- package/dist/providers/anthropic.d.ts +56 -0
- package/dist/providers/anthropic.d.ts.map +1 -0
- package/dist/providers/anthropic.js +524 -0
- package/dist/providers/anthropic.js.map +1 -0
- package/dist/providers/google.d.ts +5 -0
- package/dist/providers/google.d.ts.map +1 -1
- package/dist/providers/google.js +64 -8
- package/dist/providers/google.js.map +1 -1
- package/dist/providers/index.d.ts +1 -0
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js +1 -0
- package/dist/providers/index.js.map +1 -1
- package/dist/providers/ollama.d.ts.map +1 -1
- package/dist/providers/ollama.js +38 -11
- package/dist/providers/ollama.js.map +1 -1
- package/dist/providers/openai.d.ts.map +1 -1
- package/dist/providers/openai.js +9 -7
- package/dist/providers/openai.js.map +1 -1
- package/dist/router.d.ts +13 -33
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +33 -57
- package/dist/router.js.map +1 -1
- package/dist/stream-decoder.d.ts +29 -2
- package/dist/stream-decoder.d.ts.map +1 -1
- package/dist/stream-decoder.js +39 -11
- package/dist/stream-decoder.js.map +1 -1
- package/dist/structured-output.d.ts +84 -181
- package/dist/structured-output.d.ts.map +1 -1
- package/dist/structured-output.js +79 -187
- package/dist/structured-output.js.map +1 -1
- package/dist/zod-adapter.d.ts +44 -0
- package/dist/zod-adapter.d.ts.map +1 -0
- package/dist/zod-adapter.js +61 -0
- package/dist/zod-adapter.js.map +1 -0
- package/package.json +9 -1
- package/src/ai-model.ts +350 -0
- package/src/auditor.ts +213 -0
- package/src/client.ts +402 -0
- package/src/debug/debug-google-streaming.ts +97 -0
- package/src/debug/debug-tool-execution.ts +86 -0
- package/src/debug/test-lmstudio-tools.ts +155 -0
- package/src/demos/README.md +47 -0
- package/src/demos/basic/universal-llm-examples.ts +161 -0
- package/src/demos/mcp/astrid-memory-demo.ts +295 -0
- package/src/demos/mcp/astrid-persona-memory.ts +357 -0
- package/src/demos/mcp/mcp-mongodb-demo.ts +275 -0
- package/src/demos/mcp/simple-astrid-memory.ts +148 -0
- package/src/demos/mcp/simple-mcp-demo.ts +68 -0
- package/src/demos/mcp/working-mcp-demo.ts +62 -0
- package/src/demos/model-alias-demo.ts +0 -0
- package/src/demos/tools/RAG_MEMORY_INTEGRATION.md +267 -0
- package/src/demos/tools/astrid-memory-demo.ts +270 -0
- package/src/demos/tools/astrid-production-memory-clean.ts +785 -0
- package/src/demos/tools/astrid-production-memory.ts +558 -0
- package/src/demos/tools/basic-translation-test.ts +66 -0
- package/src/demos/tools/chromadb-similarity-tuning.ts +390 -0
- package/src/demos/tools/clean-multilingual-conversation.ts +209 -0
- package/src/demos/tools/clean-translation-test.ts +119 -0
- package/src/demos/tools/clean-universal-multilingual-test.ts +131 -0
- package/src/demos/tools/complete-rag-demo.ts +369 -0
- package/src/demos/tools/complete-tool-demo.ts +132 -0
- package/src/demos/tools/demo-tool-calling.ts +124 -0
- package/src/demos/tools/dynamic-language-switching-test.ts +251 -0
- package/src/demos/tools/hybrid-thinking-test.ts +154 -0
- package/src/demos/tools/memory-integration-test.ts +420 -0
- package/src/demos/tools/multilingual-memory-system.ts +802 -0
- package/src/demos/tools/ondemand-translation-demo.ts +655 -0
- package/src/demos/tools/production-tool-demo.ts +245 -0
- package/src/demos/tools/revolutionary-multilingual-test.ts +151 -0
- package/src/demos/tools/rigorous-language-analysis.ts +218 -0
- package/src/demos/tools/test-universal-memory-system.ts +126 -0
- package/src/demos/tools/translation-integration-guide.ts +346 -0
- package/src/demos/tools/universal-memory-system.ts +560 -0
- package/src/http.ts +247 -0
- package/src/index.ts +160 -0
- package/src/interfaces.ts +657 -0
- package/src/mcp.ts +345 -0
- package/src/providers/anthropic.ts +762 -0
- package/src/providers/google.ts +620 -0
- package/src/providers/index.ts +8 -0
- package/src/providers/ollama.ts +469 -0
- package/src/providers/openai.ts +392 -0
- package/src/router.ts +780 -0
- package/src/stream-decoder.ts +361 -0
- package/src/structured-output.ts +702 -0
- package/src/test-scripts/test-advanced-tools.ts +310 -0
- package/src/test-scripts/test-google-streaming-enhanced.ts +147 -0
- package/src/test-scripts/test-google-streaming.ts +63 -0
- package/src/test-scripts/test-google-system-prompt-comprehensive.ts +189 -0
- package/src/test-scripts/test-mcp-config.ts +28 -0
- package/src/test-scripts/test-mcp-connection.ts +29 -0
- package/src/test-scripts/test-system-message-positions.ts +163 -0
- package/src/test-scripts/test-system-prompt-improvement-demo.ts +83 -0
- package/src/test-scripts/test-tool-calling.ts +231 -0
- package/src/tests/ai-model.test.ts +1614 -0
- package/src/tests/auditor.test.ts +224 -0
- package/src/tests/http.test.ts +200 -0
- package/src/tests/interfaces.test.ts +117 -0
- package/src/tests/providers/google.test.ts +660 -0
- package/src/tests/providers/ollama.test.ts +954 -0
- package/src/tests/providers/openai.test.ts +1122 -0
- package/src/tests/router.test.ts +254 -0
- package/src/tests/stream-decoder.test.ts +179 -0
- package/src/tests/structured-output.test.ts +1340 -0
- package/src/tests/tools.test.ts +175 -0
- package/src/tools.ts +246 -0
- package/src/zod-adapter.ts +72 -0
|
@@ -2,32 +2,31 @@
|
|
|
2
2
|
* Structured Output Core Types
|
|
3
3
|
*
|
|
4
4
|
* Core types for structured output support in universal-llm-client.
|
|
5
|
-
*
|
|
5
|
+
* Zero-dependency — works with raw JSON Schema and optional validate functions.
|
|
6
|
+
*
|
|
7
|
+
* For Zod integration, use the `universal-llm-client/zod` entrypoint.
|
|
6
8
|
*
|
|
7
9
|
* @module structured-output
|
|
8
10
|
*/
|
|
9
|
-
import { z } from 'zod';
|
|
10
11
|
/**
|
|
11
12
|
* Custom error class for structured output validation failures.
|
|
12
13
|
*
|
|
13
14
|
* Thrown when:
|
|
14
15
|
* - JSON parsing of LLM response fails
|
|
15
|
-
* -
|
|
16
|
+
* - Schema validation fails
|
|
16
17
|
*
|
|
17
18
|
* Features:
|
|
18
19
|
* - `rawOutput` property containing the original LLM response
|
|
19
|
-
* - `cause` property for the underlying error
|
|
20
|
+
* - `cause` property for the underlying error
|
|
20
21
|
*
|
|
21
22
|
* @example
|
|
22
23
|
* ```typescript
|
|
23
24
|
* try {
|
|
24
|
-
* const result = await model.generateStructured(
|
|
25
|
+
* const result = await model.generateStructured(schema, messages);
|
|
25
26
|
* } catch (error) {
|
|
26
27
|
* if (error instanceof StructuredOutputError) {
|
|
27
28
|
* console.log('Raw LLM output:', error.rawOutput);
|
|
28
|
-
*
|
|
29
|
-
* console.log('Validation issues:', error.cause.issues);
|
|
30
|
-
* }
|
|
29
|
+
* console.log('Cause:', error.cause);
|
|
31
30
|
* }
|
|
32
31
|
* }
|
|
33
32
|
* ```
|
|
@@ -35,7 +34,7 @@ import { z } from 'zod';
|
|
|
35
34
|
export class StructuredOutputError extends Error {
|
|
36
35
|
/** The raw output from the LLM that failed validation */
|
|
37
36
|
rawOutput;
|
|
38
|
-
/** The underlying cause (e.g.,
|
|
37
|
+
/** The underlying cause (e.g., validation error) */
|
|
39
38
|
cause;
|
|
40
39
|
constructor(message, options) {
|
|
41
40
|
super(message);
|
|
@@ -52,39 +51,12 @@ export class StructuredOutputError extends Error {
|
|
|
52
51
|
// ============================================================================
|
|
53
52
|
/**
|
|
54
53
|
* Type guard to check if a structured output result is successful.
|
|
55
|
-
*
|
|
56
|
-
* @param result The result to check
|
|
57
|
-
* @returns true if the result is successful
|
|
58
|
-
*
|
|
59
|
-
* @example
|
|
60
|
-
* ```typescript
|
|
61
|
-
* const result = await model.tryParseStructured(UserSchema, messages);
|
|
62
|
-
*
|
|
63
|
-
* if (isStructuredOutputSuccess(result)) {
|
|
64
|
-
* console.log('User:', result.value.name);
|
|
65
|
-
* } else {
|
|
66
|
-
* console.log('Error:', result.error.message);
|
|
67
|
-
* }
|
|
68
|
-
* ```
|
|
69
54
|
*/
|
|
70
55
|
export function isStructuredOutputSuccess(result) {
|
|
71
56
|
return result.ok === true;
|
|
72
57
|
}
|
|
73
58
|
/**
|
|
74
59
|
* Type guard to check if a structured output result is a failure.
|
|
75
|
-
*
|
|
76
|
-
* @param result The result to check
|
|
77
|
-
* @returns true if the result is a failure
|
|
78
|
-
*
|
|
79
|
-
* @example
|
|
80
|
-
* ```typescript
|
|
81
|
-
* const result = await model.tryParseStructured(UserSchema, messages);
|
|
82
|
-
*
|
|
83
|
-
* if (isStructuredOutputFailure(result)) {
|
|
84
|
-
* console.log('Error:', result.error.message);
|
|
85
|
-
* console.log('Raw:', result.rawOutput);
|
|
86
|
-
* }
|
|
87
|
-
* ```
|
|
88
60
|
*/
|
|
89
61
|
export function isStructuredOutputFailure(result) {
|
|
90
62
|
return result.ok === false;
|
|
@@ -92,36 +64,6 @@ export function isStructuredOutputFailure(result) {
|
|
|
92
64
|
// ============================================================================
|
|
93
65
|
// Schema Conversion Utilities
|
|
94
66
|
// ============================================================================
|
|
95
|
-
/**
|
|
96
|
-
* Convert a Zod schema to JSON Schema.
|
|
97
|
-
*
|
|
98
|
-
* Uses Zod 4's native `z.toJSONSchema()` for conversion.
|
|
99
|
-
* Handles all Zod types including objects, arrays, primitives, enums, and nested structures.
|
|
100
|
-
*
|
|
101
|
-
* @param schema The Zod schema to convert
|
|
102
|
-
* @returns JSON Schema representation
|
|
103
|
-
*
|
|
104
|
-
* @example
|
|
105
|
-
* ```typescript
|
|
106
|
-
* const UserSchema = z.object({
|
|
107
|
-
* name: z.string(),
|
|
108
|
-
* age: z.number(),
|
|
109
|
-
* });
|
|
110
|
-
*
|
|
111
|
-
* const jsonSchema = zodToJsonSchema(UserSchema);
|
|
112
|
-
* // { type: 'object', properties: { name: { type: 'string' }, ... }, required: ['name', 'age'] }
|
|
113
|
-
* ```
|
|
114
|
-
*/
|
|
115
|
-
export function zodToJsonSchema(schema) {
|
|
116
|
-
const result = z.toJSONSchema(schema, {
|
|
117
|
-
target: 'draft-07',
|
|
118
|
-
unrepresentable: 'any',
|
|
119
|
-
});
|
|
120
|
-
// Cast to our JSONSchema type and clean up
|
|
121
|
-
const cleanResult = result;
|
|
122
|
-
delete cleanResult.$schema;
|
|
123
|
-
return cleanResult;
|
|
124
|
-
}
|
|
125
67
|
/**
|
|
126
68
|
* Normalize a raw JSON Schema.
|
|
127
69
|
*
|
|
@@ -136,21 +78,25 @@ export function normalizeJsonSchema(schema) {
|
|
|
136
78
|
return JSON.parse(JSON.stringify(schema));
|
|
137
79
|
}
|
|
138
80
|
/**
|
|
139
|
-
* Get the JSON Schema from
|
|
140
|
-
*
|
|
141
|
-
* Converts Zod schema to JSON Schema if necessary, or normalizes raw JSON Schema.
|
|
81
|
+
* Get the JSON Schema from a SchemaConfig or StructuredOutputOptions.
|
|
142
82
|
*
|
|
143
83
|
* @param options The structured output options
|
|
144
84
|
* @returns JSON Schema
|
|
145
85
|
*/
|
|
146
86
|
export function getJsonSchema(options) {
|
|
147
|
-
if (options.
|
|
148
|
-
return
|
|
87
|
+
if (options.schemaConfig) {
|
|
88
|
+
return normalizeJsonSchema(options.schemaConfig.jsonSchema);
|
|
149
89
|
}
|
|
150
90
|
if (options.jsonSchema) {
|
|
151
91
|
return normalizeJsonSchema(options.jsonSchema);
|
|
152
92
|
}
|
|
153
|
-
throw new Error('Either
|
|
93
|
+
throw new Error('Either schemaConfig or jsonSchema must be provided');
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Get the JSON Schema from a SchemaConfig directly.
|
|
97
|
+
*/
|
|
98
|
+
export function getJsonSchemaFromConfig(config) {
|
|
99
|
+
return normalizeJsonSchema(config.jsonSchema);
|
|
154
100
|
}
|
|
155
101
|
/**
|
|
156
102
|
* Features that some providers don't support.
|
|
@@ -176,18 +122,6 @@ const GOOGLE_UNSUPPORTED_FEATURES = [
|
|
|
176
122
|
* @param schema The JSON Schema to transform
|
|
177
123
|
* @param provider The target provider
|
|
178
124
|
* @returns Cleaned JSON Schema
|
|
179
|
-
*
|
|
180
|
-
* @example
|
|
181
|
-
* ```typescript
|
|
182
|
-
* const schema = {
|
|
183
|
-
* type: 'string',
|
|
184
|
-
* pattern: '^[a-z]+$',
|
|
185
|
-
* minLength: 1,
|
|
186
|
-
* };
|
|
187
|
-
*
|
|
188
|
-
* const cleaned = stripUnsupportedFeatures(schema, 'google');
|
|
189
|
-
* // { type: 'string' } - pattern and minLength removed
|
|
190
|
-
* ```
|
|
191
125
|
*/
|
|
192
126
|
export function stripUnsupportedFeatures(schema, provider) {
|
|
193
127
|
// Only Google needs transformation currently
|
|
@@ -208,12 +142,12 @@ export function stripUnsupportedFeatures(schema, provider) {
|
|
|
208
142
|
}
|
|
209
143
|
}
|
|
210
144
|
}
|
|
211
|
-
if (result
|
|
212
|
-
if (Array.isArray(result
|
|
213
|
-
result
|
|
145
|
+
if (result['items']) {
|
|
146
|
+
if (Array.isArray(result['items'])) {
|
|
147
|
+
result['items'] = result['items'].map(item => stripUnsupportedFeatures(item, provider));
|
|
214
148
|
}
|
|
215
149
|
else {
|
|
216
|
-
result
|
|
150
|
+
result['items'] = stripUnsupportedFeatures(result['items'], provider);
|
|
217
151
|
}
|
|
218
152
|
}
|
|
219
153
|
// Handle oneOf, anyOf, allOf
|
|
@@ -232,35 +166,18 @@ export function stripUnsupportedFeatures(schema, provider) {
|
|
|
232
166
|
* 1. Extracts/converts the JSON Schema from options
|
|
233
167
|
* 2. Applies provider-specific transformations (e.g., removing unsupported features for Google)
|
|
234
168
|
* 3. Adds name/description for LLM guidance
|
|
235
|
-
*
|
|
236
|
-
* @param provider The target provider
|
|
237
|
-
* @param options The structured output options
|
|
238
|
-
* @returns Provider-ready schema with name and description
|
|
239
|
-
*
|
|
240
|
-
* @example
|
|
241
|
-
* ```typescript
|
|
242
|
-
* const result = convertToProviderSchema('openai', {
|
|
243
|
-
* schema: z.object({ name: z.string() }),
|
|
244
|
-
* name: 'User',
|
|
245
|
-
* description: 'A user object',
|
|
246
|
-
* });
|
|
247
|
-
*
|
|
248
|
-
* // result.schema - JSON Schema
|
|
249
|
-
* // result.name - 'User'
|
|
250
|
-
* // result.description - 'A user object'
|
|
251
|
-
* ```
|
|
252
169
|
*/
|
|
253
170
|
export function convertToProviderSchema(provider, options) {
|
|
254
|
-
// Get the JSON Schema
|
|
171
|
+
// Get the JSON Schema
|
|
255
172
|
const jsonSchema = getJsonSchema(options);
|
|
256
173
|
// Apply provider-specific transformations
|
|
257
174
|
const schema = stripUnsupportedFeatures(jsonSchema, provider);
|
|
258
175
|
// Generate a default name if not provided (some providers require it)
|
|
259
|
-
const name = options.name ?? 'response';
|
|
176
|
+
const name = options.name ?? options.schemaConfig?.name ?? 'response';
|
|
260
177
|
return {
|
|
261
178
|
schema,
|
|
262
179
|
name,
|
|
263
|
-
description: options.description,
|
|
180
|
+
description: options.description ?? options.schemaConfig?.description,
|
|
264
181
|
};
|
|
265
182
|
}
|
|
266
183
|
// ============================================================================
|
|
@@ -271,22 +188,15 @@ export function convertToProviderSchema(provider, options) {
|
|
|
271
188
|
*
|
|
272
189
|
* This function:
|
|
273
190
|
* 1. Parses JSON from the raw output string
|
|
274
|
-
* 2. Validates the
|
|
191
|
+
* 2. Validates using the SchemaConfig's validate function (if provided)
|
|
275
192
|
* 3. Throws StructuredOutputError on failure
|
|
276
193
|
*
|
|
277
|
-
* @param
|
|
194
|
+
* @param config The schema configuration with optional validator
|
|
278
195
|
* @param rawOutput The raw string output from the LLM
|
|
279
196
|
* @returns The validated and typed data
|
|
280
|
-
* @throws StructuredOutputError if JSON parsing fails or
|
|
281
|
-
*
|
|
282
|
-
* @example
|
|
283
|
-
* ```typescript
|
|
284
|
-
* const schema = z.object({ name: z.string(), age: z.number() });
|
|
285
|
-
* const rawOutput = '{"name": "Alice", "age": 30}';
|
|
286
|
-
* const result = parseStructured(schema, rawOutput); // { name: "Alice", age: 30 }
|
|
287
|
-
* ```
|
|
197
|
+
* @throws StructuredOutputError if JSON parsing fails or validation fails
|
|
288
198
|
*/
|
|
289
|
-
export function parseStructured(
|
|
199
|
+
export function parseStructured(config, rawOutput) {
|
|
290
200
|
// Step 1: Parse JSON
|
|
291
201
|
let parsed;
|
|
292
202
|
try {
|
|
@@ -299,13 +209,18 @@ export function parseStructured(schema, rawOutput) {
|
|
|
299
209
|
: new SyntaxError(String(error));
|
|
300
210
|
throw new StructuredOutputError(`Failed to parse JSON: ${syntaxError.message}`, { rawOutput, cause: syntaxError });
|
|
301
211
|
}
|
|
302
|
-
// Step 2: Validate
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
212
|
+
// Step 2: Validate if validator is provided
|
|
213
|
+
if (config.validate) {
|
|
214
|
+
try {
|
|
215
|
+
return config.validate(parsed);
|
|
216
|
+
}
|
|
217
|
+
catch (error) {
|
|
218
|
+
const validationError = error instanceof Error ? error : new Error(String(error));
|
|
219
|
+
throw new StructuredOutputError(`Validation failed: ${validationError.message}`, { rawOutput, cause: validationError });
|
|
220
|
+
}
|
|
307
221
|
}
|
|
308
|
-
return
|
|
222
|
+
// No validator — return as-is (unsafe cast, user chose to skip validation)
|
|
223
|
+
return parsed;
|
|
309
224
|
}
|
|
310
225
|
/**
|
|
311
226
|
* Try to parse and validate structured output, returning a result object.
|
|
@@ -314,31 +229,13 @@ export function parseStructured(schema, rawOutput) {
|
|
|
314
229
|
* on validation failure, it returns a result object with `ok: false` and
|
|
315
230
|
* the error details.
|
|
316
231
|
*
|
|
317
|
-
* @param
|
|
232
|
+
* @param config The schema configuration with optional validator
|
|
318
233
|
* @param rawOutput The raw string output from the LLM
|
|
319
234
|
* @returns A result object: `{ ok: true, value }` on success, `{ ok: false, error, rawOutput }` on failure
|
|
320
|
-
*
|
|
321
|
-
* @example
|
|
322
|
-
* ```typescript
|
|
323
|
-
* const schema = z.object({ name: z.string(), age: z.number() });
|
|
324
|
-
*
|
|
325
|
-
* // Success case
|
|
326
|
-
* const result1 = tryParseStructured(schema, '{"name": "Alice", "age": 30}');
|
|
327
|
-
* if (result1.ok) {
|
|
328
|
-
* console.log(result1.value.name); // "Alice"
|
|
329
|
-
* }
|
|
330
|
-
*
|
|
331
|
-
* // Failure case
|
|
332
|
-
* const result2 = tryParseStructured(schema, 'invalid json');
|
|
333
|
-
* if (!result2.ok) {
|
|
334
|
-
* console.log(result2.error.message); // Error message
|
|
335
|
-
* console.log(result2.rawOutput); // Original output
|
|
336
|
-
* }
|
|
337
|
-
* ```
|
|
338
235
|
*/
|
|
339
|
-
export function tryParseStructured(
|
|
236
|
+
export function tryParseStructured(config, rawOutput) {
|
|
340
237
|
try {
|
|
341
|
-
const value = parseStructured(
|
|
238
|
+
const value = parseStructured(config, rawOutput);
|
|
342
239
|
return { ok: true, value };
|
|
343
240
|
}
|
|
344
241
|
catch (error) {
|
|
@@ -354,31 +251,28 @@ export function tryParseStructured(schema, rawOutput) {
|
|
|
354
251
|
}
|
|
355
252
|
}
|
|
356
253
|
/**
|
|
357
|
-
* Validate already-parsed data
|
|
254
|
+
* Validate already-parsed data using a SchemaConfig's validator.
|
|
358
255
|
*
|
|
359
|
-
* This is useful when you have already parsed JSON and need to validate
|
|
360
|
-
* it against a schema, with optional raw output for error messages.
|
|
256
|
+
* This is useful when you have already parsed JSON and need to validate it.
|
|
361
257
|
*
|
|
362
|
-
* @param
|
|
258
|
+
* @param config The schema configuration with optional validator
|
|
363
259
|
* @param data The parsed data to validate
|
|
364
260
|
* @param rawOutput Optional raw output string for error messages
|
|
365
261
|
* @returns The validated and typed data
|
|
366
|
-
* @throws StructuredOutputError if
|
|
367
|
-
*
|
|
368
|
-
* @example
|
|
369
|
-
* ```typescript
|
|
370
|
-
* const schema = z.object({ name: z.string(), age: z.number() });
|
|
371
|
-
* const data = JSON.parse('{"name": "Alice", "age": 30}');
|
|
372
|
-
* const result = validateStructuredOutput(schema, data); // { name: "Alice", age: 30 }
|
|
373
|
-
* ```
|
|
262
|
+
* @throws StructuredOutputError if validation fails
|
|
374
263
|
*/
|
|
375
|
-
export function validateStructuredOutput(
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
264
|
+
export function validateStructuredOutput(config, data, rawOutput) {
|
|
265
|
+
if (config.validate) {
|
|
266
|
+
try {
|
|
267
|
+
return config.validate(data);
|
|
268
|
+
}
|
|
269
|
+
catch (error) {
|
|
270
|
+
const rawData = rawOutput ?? JSON.stringify(data);
|
|
271
|
+
const validationError = error instanceof Error ? error : new Error(String(error));
|
|
272
|
+
throw new StructuredOutputError(`Validation failed: ${validationError.message}`, { rawOutput: rawData, cause: validationError });
|
|
273
|
+
}
|
|
380
274
|
}
|
|
381
|
-
return
|
|
275
|
+
return data;
|
|
382
276
|
}
|
|
383
277
|
// ============================================================================
|
|
384
278
|
// Streaming JSON Parsing
|
|
@@ -392,32 +286,30 @@ export function validateStructuredOutput(schema, data, rawOutput) {
|
|
|
392
286
|
*/
|
|
393
287
|
export class StreamingJsonParser {
|
|
394
288
|
buffer = '';
|
|
395
|
-
|
|
396
|
-
constructor(
|
|
397
|
-
this.
|
|
289
|
+
validateFn;
|
|
290
|
+
constructor(config) {
|
|
291
|
+
this.validateFn = config.validate;
|
|
398
292
|
}
|
|
399
293
|
/**
|
|
400
294
|
* Feed a chunk of JSON text to the parser.
|
|
401
295
|
* Returns a validated partial object if the current buffer can be parsed
|
|
402
|
-
* as valid JSON that passes
|
|
403
|
-
*
|
|
404
|
-
* For partial objects, this attempts to:
|
|
405
|
-
* 1. Add closing braces/brackets to make valid JSON
|
|
406
|
-
* 2. Fill in missing required fields with null/empty values
|
|
407
|
-
* 3. Validate against schema
|
|
408
|
-
*
|
|
409
|
-
* @param chunk Text chunk from the stream
|
|
410
|
-
* @returns Validated partial object or undefined
|
|
296
|
+
* as valid JSON that passes validation, or undefined if not yet valid.
|
|
411
297
|
*/
|
|
412
298
|
feed(chunk) {
|
|
413
299
|
this.buffer += chunk;
|
|
414
300
|
// Try to parse as complete JSON first
|
|
415
301
|
try {
|
|
416
302
|
const parsed = JSON.parse(this.buffer);
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
303
|
+
if (this.validateFn) {
|
|
304
|
+
try {
|
|
305
|
+
const validated = this.validateFn(parsed);
|
|
306
|
+
return { partial: validated, complete: true };
|
|
307
|
+
}
|
|
308
|
+
catch {
|
|
309
|
+
// Validation failed on complete JSON — return parsed but not validated
|
|
310
|
+
}
|
|
420
311
|
}
|
|
312
|
+
return { partial: parsed, complete: true };
|
|
421
313
|
}
|
|
422
314
|
catch {
|
|
423
315
|
// Not yet valid complete JSON
|
|
@@ -486,10 +378,15 @@ export class StreamingJsonParser {
|
|
|
486
378
|
const candidate = this.buffer + closing;
|
|
487
379
|
try {
|
|
488
380
|
const parsed = JSON.parse(candidate);
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
381
|
+
if (this.validateFn) {
|
|
382
|
+
try {
|
|
383
|
+
return this.validateFn(parsed);
|
|
384
|
+
}
|
|
385
|
+
catch {
|
|
386
|
+
// Partial validation failed — that's expected for partials
|
|
387
|
+
}
|
|
492
388
|
}
|
|
389
|
+
return parsed;
|
|
493
390
|
}
|
|
494
391
|
catch {
|
|
495
392
|
// Silently fail for partial JSON
|
|
@@ -497,9 +394,4 @@ export class StreamingJsonParser {
|
|
|
497
394
|
return undefined;
|
|
498
395
|
}
|
|
499
396
|
}
|
|
500
|
-
// ============================================================================
|
|
501
|
-
// Re-exports for Convenience
|
|
502
|
-
// ============================================================================
|
|
503
|
-
// Re-export Zod for users who need it
|
|
504
|
-
export { z } from 'zod';
|
|
505
397
|
//# sourceMappingURL=structured-output.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"structured-output.js","sourceRoot":"","sources":["../src/structured-output.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"structured-output.js","sourceRoot":"","sources":["../src/structured-output.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zod Adapter for Universal LLM Client
|
|
3
|
+
*
|
|
4
|
+
* Optional entrypoint for projects that use Zod for schema validation.
|
|
5
|
+
* Import from 'universal-llm-client/zod' to use.
|
|
6
|
+
*
|
|
7
|
+
* @module universal-llm-client/zod
|
|
8
|
+
*/
|
|
9
|
+
import { z } from 'zod';
|
|
10
|
+
import type { SchemaConfig } from './structured-output.js';
|
|
11
|
+
/**
|
|
12
|
+
* Create a SchemaConfig from a Zod schema.
|
|
13
|
+
*
|
|
14
|
+
* This bridges Zod's type-safe schema definitions to the library's
|
|
15
|
+
* generic SchemaConfig interface, using Zod 4's native `z.toJSONSchema()`.
|
|
16
|
+
*
|
|
17
|
+
* @template T The type inferred from the Zod schema
|
|
18
|
+
* @param schema The Zod schema
|
|
19
|
+
* @param options Optional name and description for LLM guidance
|
|
20
|
+
* @returns SchemaConfig ready for use with generateStructured, etc.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* import { fromZod } from 'universal-llm-client/zod';
|
|
25
|
+
* import { z } from 'zod';
|
|
26
|
+
*
|
|
27
|
+
* const UserSchema = z.object({
|
|
28
|
+
* name: z.string(),
|
|
29
|
+
* age: z.number(),
|
|
30
|
+
* });
|
|
31
|
+
*
|
|
32
|
+
* const config = fromZod(UserSchema, { name: 'User' });
|
|
33
|
+
*
|
|
34
|
+
* const user = await model.generateStructured(config, messages);
|
|
35
|
+
* // user.name: string, user.age: number (fully typed)
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export declare function fromZod<T>(schema: z.ZodType<T>, options?: {
|
|
39
|
+
name?: string;
|
|
40
|
+
description?: string;
|
|
41
|
+
}): SchemaConfig<T>;
|
|
42
|
+
export { z } from 'zod';
|
|
43
|
+
export type { SchemaConfig } from './structured-output.js';
|
|
44
|
+
//# sourceMappingURL=zod-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zod-adapter.d.ts","sourceRoot":"","sources":["../src/zod-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAE3D;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,OAAO,CAAC,CAAC,EACrB,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EACpB,OAAO,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GAClD,YAAY,CAAC,CAAC,CAAC,CAuBjB;AAGD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,YAAY,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zod Adapter for Universal LLM Client
|
|
3
|
+
*
|
|
4
|
+
* Optional entrypoint for projects that use Zod for schema validation.
|
|
5
|
+
* Import from 'universal-llm-client/zod' to use.
|
|
6
|
+
*
|
|
7
|
+
* @module universal-llm-client/zod
|
|
8
|
+
*/
|
|
9
|
+
import { z } from 'zod';
|
|
10
|
+
/**
|
|
11
|
+
* Create a SchemaConfig from a Zod schema.
|
|
12
|
+
*
|
|
13
|
+
* This bridges Zod's type-safe schema definitions to the library's
|
|
14
|
+
* generic SchemaConfig interface, using Zod 4's native `z.toJSONSchema()`.
|
|
15
|
+
*
|
|
16
|
+
* @template T The type inferred from the Zod schema
|
|
17
|
+
* @param schema The Zod schema
|
|
18
|
+
* @param options Optional name and description for LLM guidance
|
|
19
|
+
* @returns SchemaConfig ready for use with generateStructured, etc.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* import { fromZod } from 'universal-llm-client/zod';
|
|
24
|
+
* import { z } from 'zod';
|
|
25
|
+
*
|
|
26
|
+
* const UserSchema = z.object({
|
|
27
|
+
* name: z.string(),
|
|
28
|
+
* age: z.number(),
|
|
29
|
+
* });
|
|
30
|
+
*
|
|
31
|
+
* const config = fromZod(UserSchema, { name: 'User' });
|
|
32
|
+
*
|
|
33
|
+
* const user = await model.generateStructured(config, messages);
|
|
34
|
+
* // user.name: string, user.age: number (fully typed)
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export function fromZod(schema, options) {
|
|
38
|
+
// Convert Zod schema to JSON Schema using Zod 4's native method
|
|
39
|
+
const rawJsonSchema = z.toJSONSchema(schema, {
|
|
40
|
+
target: 'draft-07',
|
|
41
|
+
unrepresentable: 'any',
|
|
42
|
+
});
|
|
43
|
+
// Clean up — remove $schema since providers don't need it
|
|
44
|
+
const jsonSchema = { ...rawJsonSchema };
|
|
45
|
+
delete jsonSchema.$schema;
|
|
46
|
+
return {
|
|
47
|
+
jsonSchema: jsonSchema,
|
|
48
|
+
validate: (data) => {
|
|
49
|
+
const result = schema.safeParse(data);
|
|
50
|
+
if (!result.success) {
|
|
51
|
+
throw result.error;
|
|
52
|
+
}
|
|
53
|
+
return result.data;
|
|
54
|
+
},
|
|
55
|
+
name: options?.name,
|
|
56
|
+
description: options?.description,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
// Re-export z for convenience (users importing from /zod likely want it)
|
|
60
|
+
export { z } from 'zod';
|
|
61
|
+
//# sourceMappingURL=zod-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zod-adapter.js","sourceRoot":"","sources":["../src/zod-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,UAAU,OAAO,CACnB,MAAoB,EACpB,OAAiD;IAEjD,gEAAgE;IAChE,MAAM,aAAa,GAAG,CAAC,CAAC,YAAY,CAAC,MAAM,EAAE;QACzC,MAAM,EAAE,UAAU;QAClB,eAAe,EAAE,KAAK;KACzB,CAAC,CAAC;IAEH,0DAA0D;IAC1D,MAAM,UAAU,GAAG,EAAE,GAAG,aAAa,EAA6B,CAAC;IACnE,OAAO,UAAU,CAAC,OAAO,CAAC;IAE1B,OAAO;QACH,UAAU,EAAE,UAAyD;QACrE,QAAQ,EAAE,CAAC,IAAa,EAAK,EAAE;YAC3B,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YACtC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;gBAClB,MAAM,MAAM,CAAC,KAAK,CAAC;YACvB,CAAC;YACD,OAAO,MAAM,CAAC,IAAI,CAAC;QACvB,CAAC;QACD,IAAI,EAAE,OAAO,EAAE,IAAI;QACnB,WAAW,EAAE,OAAO,EAAE,WAAW;KACpC,CAAC;AACN,CAAC;AAED,yEAAyE;AACzE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "universal-llm-client",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.1.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A universal LLM client with transparent provider failover, streaming tool execution, pluggable reasoning, and native observability.",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -33,10 +33,15 @@
|
|
|
33
33
|
"./structured-output": {
|
|
34
34
|
"import": "./dist/structured-output.js",
|
|
35
35
|
"types": "./dist/structured-output.d.ts"
|
|
36
|
+
},
|
|
37
|
+
"./zod": {
|
|
38
|
+
"import": "./dist/zod-adapter.js",
|
|
39
|
+
"types": "./dist/zod-adapter.d.ts"
|
|
36
40
|
}
|
|
37
41
|
},
|
|
38
42
|
"files": [
|
|
39
43
|
"dist",
|
|
44
|
+
"src",
|
|
40
45
|
"README.md",
|
|
41
46
|
"CHANGELOG.md",
|
|
42
47
|
"LICENSE"
|
|
@@ -89,6 +94,9 @@
|
|
|
89
94
|
"peerDependenciesMeta": {
|
|
90
95
|
"@modelcontextprotocol/sdk": {
|
|
91
96
|
"optional": true
|
|
97
|
+
},
|
|
98
|
+
"zod": {
|
|
99
|
+
"optional": true
|
|
92
100
|
}
|
|
93
101
|
},
|
|
94
102
|
"engines": {
|