universal-llm-client 3.1.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.
Files changed (135) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/README.md +177 -0
  3. package/dist/ai-model.d.ts +87 -0
  4. package/dist/ai-model.d.ts.map +1 -1
  5. package/dist/ai-model.js +99 -0
  6. package/dist/ai-model.js.map +1 -1
  7. package/dist/auditor.d.ts +5 -1
  8. package/dist/auditor.d.ts.map +1 -1
  9. package/dist/auditor.js +9 -0
  10. package/dist/auditor.js.map +1 -1
  11. package/dist/client.d.ts +14 -0
  12. package/dist/client.d.ts.map +1 -1
  13. package/dist/client.js +60 -0
  14. package/dist/client.js.map +1 -1
  15. package/dist/http.d.ts +2 -0
  16. package/dist/http.d.ts.map +1 -1
  17. package/dist/http.js +1 -0
  18. package/dist/http.js.map +1 -1
  19. package/dist/index.d.ts +3 -2
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +12 -2
  22. package/dist/index.js.map +1 -1
  23. package/dist/interfaces.d.ts +186 -6
  24. package/dist/interfaces.d.ts.map +1 -1
  25. package/dist/interfaces.js +14 -0
  26. package/dist/interfaces.js.map +1 -1
  27. package/dist/providers/anthropic.d.ts +56 -0
  28. package/dist/providers/anthropic.d.ts.map +1 -0
  29. package/dist/providers/anthropic.js +524 -0
  30. package/dist/providers/anthropic.js.map +1 -0
  31. package/dist/providers/google.d.ts +5 -0
  32. package/dist/providers/google.d.ts.map +1 -1
  33. package/dist/providers/google.js +81 -4
  34. package/dist/providers/google.js.map +1 -1
  35. package/dist/providers/index.d.ts +1 -0
  36. package/dist/providers/index.d.ts.map +1 -1
  37. package/dist/providers/index.js +1 -0
  38. package/dist/providers/index.js.map +1 -1
  39. package/dist/providers/ollama.d.ts +13 -1
  40. package/dist/providers/ollama.d.ts.map +1 -1
  41. package/dist/providers/ollama.js +72 -10
  42. package/dist/providers/ollama.js.map +1 -1
  43. package/dist/providers/openai.d.ts +4 -0
  44. package/dist/providers/openai.d.ts.map +1 -1
  45. package/dist/providers/openai.js +53 -1
  46. package/dist/providers/openai.js.map +1 -1
  47. package/dist/router.d.ts +50 -0
  48. package/dist/router.d.ts.map +1 -1
  49. package/dist/router.js +319 -0
  50. package/dist/router.js.map +1 -1
  51. package/dist/stream-decoder.d.ts +29 -2
  52. package/dist/stream-decoder.d.ts.map +1 -1
  53. package/dist/stream-decoder.js +39 -11
  54. package/dist/stream-decoder.js.map +1 -1
  55. package/dist/structured-output.d.ts +370 -0
  56. package/dist/structured-output.d.ts.map +1 -0
  57. package/dist/structured-output.js +397 -0
  58. package/dist/structured-output.js.map +1 -0
  59. package/dist/zod-adapter.d.ts +44 -0
  60. package/dist/zod-adapter.d.ts.map +1 -0
  61. package/dist/zod-adapter.js +61 -0
  62. package/dist/zod-adapter.js.map +1 -0
  63. package/package.json +23 -4
  64. package/src/ai-model.ts +350 -0
  65. package/src/auditor.ts +213 -0
  66. package/src/client.ts +402 -0
  67. package/src/debug/debug-google-streaming.ts +97 -0
  68. package/src/debug/debug-tool-execution.ts +86 -0
  69. package/src/debug/test-lmstudio-tools.ts +155 -0
  70. package/src/demos/README.md +47 -0
  71. package/src/demos/basic/universal-llm-examples.ts +161 -0
  72. package/src/demos/mcp/astrid-memory-demo.ts +295 -0
  73. package/src/demos/mcp/astrid-persona-memory.ts +357 -0
  74. package/src/demos/mcp/mcp-mongodb-demo.ts +275 -0
  75. package/src/demos/mcp/simple-astrid-memory.ts +148 -0
  76. package/src/demos/mcp/simple-mcp-demo.ts +68 -0
  77. package/src/demos/mcp/working-mcp-demo.ts +62 -0
  78. package/src/demos/model-alias-demo.ts +0 -0
  79. package/src/demos/tools/RAG_MEMORY_INTEGRATION.md +267 -0
  80. package/src/demos/tools/astrid-memory-demo.ts +270 -0
  81. package/src/demos/tools/astrid-production-memory-clean.ts +785 -0
  82. package/src/demos/tools/astrid-production-memory.ts +558 -0
  83. package/src/demos/tools/basic-translation-test.ts +66 -0
  84. package/src/demos/tools/chromadb-similarity-tuning.ts +390 -0
  85. package/src/demos/tools/clean-multilingual-conversation.ts +209 -0
  86. package/src/demos/tools/clean-translation-test.ts +119 -0
  87. package/src/demos/tools/clean-universal-multilingual-test.ts +131 -0
  88. package/src/demos/tools/complete-rag-demo.ts +369 -0
  89. package/src/demos/tools/complete-tool-demo.ts +132 -0
  90. package/src/demos/tools/demo-tool-calling.ts +124 -0
  91. package/src/demos/tools/dynamic-language-switching-test.ts +251 -0
  92. package/src/demos/tools/hybrid-thinking-test.ts +154 -0
  93. package/src/demos/tools/memory-integration-test.ts +420 -0
  94. package/src/demos/tools/multilingual-memory-system.ts +802 -0
  95. package/src/demos/tools/ondemand-translation-demo.ts +655 -0
  96. package/src/demos/tools/production-tool-demo.ts +245 -0
  97. package/src/demos/tools/revolutionary-multilingual-test.ts +151 -0
  98. package/src/demos/tools/rigorous-language-analysis.ts +218 -0
  99. package/src/demos/tools/test-universal-memory-system.ts +126 -0
  100. package/src/demos/tools/translation-integration-guide.ts +346 -0
  101. package/src/demos/tools/universal-memory-system.ts +560 -0
  102. package/src/http.ts +247 -0
  103. package/src/index.ts +160 -0
  104. package/src/interfaces.ts +657 -0
  105. package/src/mcp.ts +345 -0
  106. package/src/providers/anthropic.ts +762 -0
  107. package/src/providers/google.ts +620 -0
  108. package/src/providers/index.ts +8 -0
  109. package/src/providers/ollama.ts +469 -0
  110. package/src/providers/openai.ts +392 -0
  111. package/src/router.ts +780 -0
  112. package/src/stream-decoder.ts +361 -0
  113. package/src/structured-output.ts +702 -0
  114. package/src/test-scripts/test-advanced-tools.ts +310 -0
  115. package/src/test-scripts/test-google-streaming-enhanced.ts +147 -0
  116. package/src/test-scripts/test-google-streaming.ts +63 -0
  117. package/src/test-scripts/test-google-system-prompt-comprehensive.ts +189 -0
  118. package/src/test-scripts/test-mcp-config.ts +28 -0
  119. package/src/test-scripts/test-mcp-connection.ts +29 -0
  120. package/src/test-scripts/test-system-message-positions.ts +163 -0
  121. package/src/test-scripts/test-system-prompt-improvement-demo.ts +83 -0
  122. package/src/test-scripts/test-tool-calling.ts +231 -0
  123. package/src/tests/ai-model.test.ts +1614 -0
  124. package/src/tests/auditor.test.ts +224 -0
  125. package/src/tests/http.test.ts +200 -0
  126. package/src/tests/interfaces.test.ts +117 -0
  127. package/src/tests/providers/google.test.ts +660 -0
  128. package/src/tests/providers/ollama.test.ts +954 -0
  129. package/src/tests/providers/openai.test.ts +1122 -0
  130. package/src/tests/router.test.ts +254 -0
  131. package/src/tests/stream-decoder.test.ts +179 -0
  132. package/src/tests/structured-output.test.ts +1340 -0
  133. package/src/tests/tools.test.ts +175 -0
  134. package/src/tools.ts +246 -0
  135. package/src/zod-adapter.ts +72 -0
@@ -0,0 +1,397 @@
1
+ /**
2
+ * Structured Output Core Types
3
+ *
4
+ * Core types for structured output support in universal-llm-client.
5
+ * Zero-dependency — works with raw JSON Schema and optional validate functions.
6
+ *
7
+ * For Zod integration, use the `universal-llm-client/zod` entrypoint.
8
+ *
9
+ * @module structured-output
10
+ */
11
+ /**
12
+ * Custom error class for structured output validation failures.
13
+ *
14
+ * Thrown when:
15
+ * - JSON parsing of LLM response fails
16
+ * - Schema validation fails
17
+ *
18
+ * Features:
19
+ * - `rawOutput` property containing the original LLM response
20
+ * - `cause` property for the underlying error
21
+ *
22
+ * @example
23
+ * ```typescript
24
+ * try {
25
+ * const result = await model.generateStructured(schema, messages);
26
+ * } catch (error) {
27
+ * if (error instanceof StructuredOutputError) {
28
+ * console.log('Raw LLM output:', error.rawOutput);
29
+ * console.log('Cause:', error.cause);
30
+ * }
31
+ * }
32
+ * ```
33
+ */
34
+ export class StructuredOutputError extends Error {
35
+ /** The raw output from the LLM that failed validation */
36
+ rawOutput;
37
+ /** The underlying cause (e.g., validation error) */
38
+ cause;
39
+ constructor(message, options) {
40
+ super(message);
41
+ this.rawOutput = options.rawOutput;
42
+ this.cause = options.cause;
43
+ // Maintains proper stack trace for where error was thrown (only available in V8)
44
+ if (Error.captureStackTrace) {
45
+ Error.captureStackTrace(this, StructuredOutputError);
46
+ }
47
+ }
48
+ }
49
+ // ============================================================================
50
+ // Type Guards
51
+ // ============================================================================
52
+ /**
53
+ * Type guard to check if a structured output result is successful.
54
+ */
55
+ export function isStructuredOutputSuccess(result) {
56
+ return result.ok === true;
57
+ }
58
+ /**
59
+ * Type guard to check if a structured output result is a failure.
60
+ */
61
+ export function isStructuredOutputFailure(result) {
62
+ return result.ok === false;
63
+ }
64
+ // ============================================================================
65
+ // Schema Conversion Utilities
66
+ // ============================================================================
67
+ /**
68
+ * Normalize a raw JSON Schema.
69
+ *
70
+ * Currently passes through without modification.
71
+ * Future versions may add normalization for provider compatibility.
72
+ *
73
+ * @param schema The JSON Schema to normalize
74
+ * @returns Normalized JSON Schema
75
+ */
76
+ export function normalizeJsonSchema(schema) {
77
+ // Deep clone to avoid mutating the input
78
+ return JSON.parse(JSON.stringify(schema));
79
+ }
80
+ /**
81
+ * Get the JSON Schema from a SchemaConfig or StructuredOutputOptions.
82
+ *
83
+ * @param options The structured output options
84
+ * @returns JSON Schema
85
+ */
86
+ export function getJsonSchema(options) {
87
+ if (options.schemaConfig) {
88
+ return normalizeJsonSchema(options.schemaConfig.jsonSchema);
89
+ }
90
+ if (options.jsonSchema) {
91
+ return normalizeJsonSchema(options.jsonSchema);
92
+ }
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);
100
+ }
101
+ /**
102
+ * Features that some providers don't support.
103
+ * These are removed when transforming schemas for those providers.
104
+ */
105
+ const GOOGLE_UNSUPPORTED_FEATURES = [
106
+ 'pattern',
107
+ 'minLength',
108
+ 'maxLength',
109
+ 'minimum',
110
+ 'maximum',
111
+ 'exclusiveMinimum',
112
+ 'exclusiveMaximum',
113
+ // Google doesn't support additionalProperties in response schema
114
+ 'additionalProperties',
115
+ ];
116
+ /**
117
+ * Strip unsupported features from a JSON Schema for a specific provider.
118
+ *
119
+ * Google/Gemini doesn't support certain JSON Schema features like pattern, min/max.
120
+ * This function removes those recursively.
121
+ *
122
+ * @param schema The JSON Schema to transform
123
+ * @param provider The target provider
124
+ * @returns Cleaned JSON Schema
125
+ */
126
+ export function stripUnsupportedFeatures(schema, provider) {
127
+ // Only Google needs transformation currently
128
+ if (provider !== 'google') {
129
+ return schema;
130
+ }
131
+ // Deep clone to avoid mutating input
132
+ const result = JSON.parse(JSON.stringify(schema));
133
+ // Remove unsupported top-level properties
134
+ for (const feature of GOOGLE_UNSUPPORTED_FEATURES) {
135
+ delete result[feature];
136
+ }
137
+ // Recursively clean nested schemas
138
+ if (result.properties) {
139
+ for (const key of Object.keys(result.properties)) {
140
+ if (result.properties[key]) {
141
+ result.properties[key] = stripUnsupportedFeatures(result.properties[key], provider);
142
+ }
143
+ }
144
+ }
145
+ if (result['items']) {
146
+ if (Array.isArray(result['items'])) {
147
+ result['items'] = result['items'].map(item => stripUnsupportedFeatures(item, provider));
148
+ }
149
+ else {
150
+ result['items'] = stripUnsupportedFeatures(result['items'], provider);
151
+ }
152
+ }
153
+ // Handle oneOf, anyOf, allOf
154
+ for (const key of ['oneOf', 'anyOf', 'allOf']) {
155
+ const schemas = result[key];
156
+ if (Array.isArray(schemas)) {
157
+ result[key] = schemas.map(s => stripUnsupportedFeatures(s, provider));
158
+ }
159
+ }
160
+ return result;
161
+ }
162
+ /**
163
+ * Convert structured output options to a provider-specific schema.
164
+ *
165
+ * This function:
166
+ * 1. Extracts/converts the JSON Schema from options
167
+ * 2. Applies provider-specific transformations (e.g., removing unsupported features for Google)
168
+ * 3. Adds name/description for LLM guidance
169
+ */
170
+ export function convertToProviderSchema(provider, options) {
171
+ // Get the JSON Schema
172
+ const jsonSchema = getJsonSchema(options);
173
+ // Apply provider-specific transformations
174
+ const schema = stripUnsupportedFeatures(jsonSchema, provider);
175
+ // Generate a default name if not provided (some providers require it)
176
+ const name = options.name ?? options.schemaConfig?.name ?? 'response';
177
+ return {
178
+ schema,
179
+ name,
180
+ description: options.description ?? options.schemaConfig?.description,
181
+ };
182
+ }
183
+ // ============================================================================
184
+ // Validation Functions
185
+ // ============================================================================
186
+ /**
187
+ * Parse and validate structured output from raw LLM response text.
188
+ *
189
+ * This function:
190
+ * 1. Parses JSON from the raw output string
191
+ * 2. Validates using the SchemaConfig's validate function (if provided)
192
+ * 3. Throws StructuredOutputError on failure
193
+ *
194
+ * @param config The schema configuration with optional validator
195
+ * @param rawOutput The raw string output from the LLM
196
+ * @returns The validated and typed data
197
+ * @throws StructuredOutputError if JSON parsing fails or validation fails
198
+ */
199
+ export function parseStructured(config, rawOutput) {
200
+ // Step 1: Parse JSON
201
+ let parsed;
202
+ try {
203
+ parsed = JSON.parse(rawOutput);
204
+ }
205
+ catch (error) {
206
+ // JSON parsing failed - wrap in StructuredOutputError
207
+ const syntaxError = error instanceof SyntaxError
208
+ ? error
209
+ : new SyntaxError(String(error));
210
+ throw new StructuredOutputError(`Failed to parse JSON: ${syntaxError.message}`, { rawOutput, cause: syntaxError });
211
+ }
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
+ }
221
+ }
222
+ // No validator — return as-is (unsafe cast, user chose to skip validation)
223
+ return parsed;
224
+ }
225
+ /**
226
+ * Try to parse and validate structured output, returning a result object.
227
+ *
228
+ * This is the non-throwing variant of `parseStructured`. Instead of throwing
229
+ * on validation failure, it returns a result object with `ok: false` and
230
+ * the error details.
231
+ *
232
+ * @param config The schema configuration with optional validator
233
+ * @param rawOutput The raw string output from the LLM
234
+ * @returns A result object: `{ ok: true, value }` on success, `{ ok: false, error, rawOutput }` on failure
235
+ */
236
+ export function tryParseStructured(config, rawOutput) {
237
+ try {
238
+ const value = parseStructured(config, rawOutput);
239
+ return { ok: true, value };
240
+ }
241
+ catch (error) {
242
+ if (error instanceof StructuredOutputError) {
243
+ return {
244
+ ok: false,
245
+ error,
246
+ rawOutput,
247
+ };
248
+ }
249
+ // Re-throw unexpected errors
250
+ throw error;
251
+ }
252
+ }
253
+ /**
254
+ * Validate already-parsed data using a SchemaConfig's validator.
255
+ *
256
+ * This is useful when you have already parsed JSON and need to validate it.
257
+ *
258
+ * @param config The schema configuration with optional validator
259
+ * @param data The parsed data to validate
260
+ * @param rawOutput Optional raw output string for error messages
261
+ * @returns The validated and typed data
262
+ * @throws StructuredOutputError if validation fails
263
+ */
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
+ }
274
+ }
275
+ return data;
276
+ }
277
+ // ============================================================================
278
+ // Streaming JSON Parsing
279
+ // ============================================================================
280
+ /**
281
+ * Incremental JSON parser for streaming structured output.
282
+ *
283
+ * Allows parsing partial JSON as it streams in, returning validated partial
284
+ * objects when possible. Useful for structured output streaming where you
285
+ * want to see partial results before the complete JSON arrives.
286
+ */
287
+ export class StreamingJsonParser {
288
+ buffer = '';
289
+ validateFn;
290
+ constructor(config) {
291
+ this.validateFn = config.validate;
292
+ }
293
+ /**
294
+ * Feed a chunk of JSON text to the parser.
295
+ * Returns a validated partial object if the current buffer can be parsed
296
+ * as valid JSON that passes validation, or undefined if not yet valid.
297
+ */
298
+ feed(chunk) {
299
+ this.buffer += chunk;
300
+ // Try to parse as complete JSON first
301
+ try {
302
+ const parsed = JSON.parse(this.buffer);
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
+ }
311
+ }
312
+ return { partial: parsed, complete: true };
313
+ }
314
+ catch {
315
+ // Not yet valid complete JSON
316
+ }
317
+ // Try to create a valid partial by closing braces
318
+ const partialResult = this.tryParsePartial();
319
+ return { partial: partialResult, complete: false };
320
+ }
321
+ /**
322
+ * Get the current buffer content.
323
+ */
324
+ getBuffer() {
325
+ return this.buffer;
326
+ }
327
+ /**
328
+ * Reset the parser state.
329
+ */
330
+ reset() {
331
+ this.buffer = '';
332
+ }
333
+ /**
334
+ * Attempt to parse partial JSON by adding closing brackets.
335
+ */
336
+ tryParsePartial() {
337
+ // Count unclosed brackets and braces
338
+ let braceCount = 0;
339
+ let bracketCount = 0;
340
+ let inString = false;
341
+ let escaped = false;
342
+ for (let i = 0; i < this.buffer.length; i++) {
343
+ const char = this.buffer[i];
344
+ if (escaped) {
345
+ escaped = false;
346
+ continue;
347
+ }
348
+ if (char === '\\' && inString) {
349
+ escaped = true;
350
+ continue;
351
+ }
352
+ if (char === '"') {
353
+ inString = !inString;
354
+ continue;
355
+ }
356
+ if (inString)
357
+ continue;
358
+ if (char === '{')
359
+ braceCount++;
360
+ else if (char === '}')
361
+ braceCount--;
362
+ else if (char === '[')
363
+ bracketCount++;
364
+ else if (char === ']')
365
+ bracketCount--;
366
+ }
367
+ // Build closing sequence
368
+ let closing = '';
369
+ while (bracketCount > 0) {
370
+ closing += ']';
371
+ bracketCount--;
372
+ }
373
+ while (braceCount > 0) {
374
+ closing += '}';
375
+ braceCount--;
376
+ }
377
+ // Try parsing with closing
378
+ const candidate = this.buffer + closing;
379
+ try {
380
+ const parsed = JSON.parse(candidate);
381
+ if (this.validateFn) {
382
+ try {
383
+ return this.validateFn(parsed);
384
+ }
385
+ catch {
386
+ // Partial validation failed — that's expected for partials
387
+ }
388
+ }
389
+ return parsed;
390
+ }
391
+ catch {
392
+ // Silently fail for partial JSON
393
+ }
394
+ return undefined;
395
+ }
396
+ }
397
+ //# sourceMappingURL=structured-output.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"structured-output.js","sourceRoot":"","sources":["../src/structured-output.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAiIH;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IAC5C,yDAAyD;IACzC,SAAS,CAAS;IAElC,oDAAoD;IAC3B,KAAK,CAAS;IAEvC,YAAY,OAAe,EAAE,OAAqC;QAC9D,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;QACnC,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;QAE3B,iFAAiF;QACjF,IAAI,KAAK,CAAC,iBAAiB,EAAE,CAAC;YAC1B,KAAK,CAAC,iBAAiB,CAAC,IAAI,EAAE,qBAAqB,CAAC,CAAC;QACzD,CAAC;IACL,CAAC;CACJ;AA2GD,+EAA+E;AAC/E,cAAc;AACd,+EAA+E;AAE/E;;GAEG;AACH,MAAM,UAAU,yBAAyB,CACrC,MAAiC;IAEjC,OAAO,MAAM,CAAC,EAAE,KAAK,IAAI,CAAC;AAC9B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,yBAAyB,CACrC,MAAiC;IAEjC,OAAO,MAAM,CAAC,EAAE,KAAK,KAAK,CAAC;AAC/B,CAAC;AAED,+EAA+E;AAC/E,8BAA8B;AAC9B,+EAA+E;AAE/E;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAAkB;IAClD,yCAAyC;IACzC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAe,CAAC;AAC5D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAI,OAAmC;IAChE,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;QACvB,OAAO,mBAAmB,CAAC,OAAO,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;IAChE,CAAC;IACD,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;QACrB,OAAO,mBAAmB,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACnD,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;AAC1E,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,uBAAuB,CAAI,MAAuB;IAC9D,OAAO,mBAAmB,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;AAClD,CAAC;AAED;;;GAGG;AACH,MAAM,2BAA2B,GAAG;IAChC,SAAS;IACT,WAAW;IACX,WAAW;IACX,SAAS;IACT,SAAS;IACT,kBAAkB;IAClB,kBAAkB;IAClB,iEAAiE;IACjE,sBAAsB;CAChB,CAAC;AAEX;;;;;;;;;GASG;AACH,MAAM,UAAU,wBAAwB,CACpC,MAAkB,EAClB,QAAwB;IAExB,6CAA6C;IAC7C,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACxB,OAAO,MAAM,CAAC;IAClB,CAAC;IAED,qCAAqC;IACrC,MAAM,MAAM,GAAe,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IAE9D,0CAA0C;IAC1C,KAAK,MAAM,OAAO,IAAI,2BAA2B,EAAE,CAAC;QAChD,OAAQ,MAAkC,CAAC,OAAO,CAAC,CAAC;IACxD,CAAC;IAED,mCAAmC;IACnC,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QACpB,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC;YAC/C,IAAI,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBACzB,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,wBAAwB,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAC;YACxF,CAAC;QACL,CAAC;IACL,CAAC;IAED,IAAI,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;QAClB,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;YAChC,MAAkC,CAAC,OAAO,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,wBAAwB,CAAC,IAAkB,EAAE,QAAQ,CAAC,CAAC,CAAC;QACvI,CAAC;aAAM,CAAC;YACJ,MAAM,CAAC,OAAO,CAAC,GAAG,wBAAwB,CAAC,MAAM,CAAC,OAAO,CAAe,EAAE,QAAQ,CAAC,CAAC;QACxF,CAAC;IACL,CAAC;IAED,6BAA6B;IAC7B,KAAK,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAU,EAAE,CAAC;QACrD,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YACxB,MAAkC,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,wBAAwB,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC;QACvG,CAAC;IACL,CAAC;IAED,OAAO,MAAM,CAAC;AAClB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,uBAAuB,CACnC,QAAwB,EACxB,OAAmC;IAEnC,sBAAsB;IACtB,MAAM,UAAU,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;IAE1C,0CAA0C;IAC1C,MAAM,MAAM,GAAG,wBAAwB,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IAE9D,sEAAsE;IACtE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,YAAY,EAAE,IAAI,IAAI,UAAU,CAAC;IAEtE,OAAO;QACH,MAAM;QACN,IAAI;QACJ,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,YAAY,EAAE,WAAW;KACxE,CAAC;AACN,CAAC;AAED,+EAA+E;AAC/E,uBAAuB;AACvB,+EAA+E;AAE/E;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,eAAe,CAC3B,MAAuB,EACvB,SAAiB;IAEjB,qBAAqB;IACrB,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACD,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IACnC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,sDAAsD;QACtD,MAAM,WAAW,GAAG,KAAK,YAAY,WAAW;YAC5C,CAAC,CAAC,KAAK;YACP,CAAC,CAAC,IAAI,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QACrC,MAAM,IAAI,qBAAqB,CAC3B,yBAAyB,WAAW,CAAC,OAAO,EAAE,EAC9C,EAAE,SAAS,EAAE,KAAK,EAAE,WAAW,EAAE,CACpC,CAAC;IACN,CAAC;IAED,4CAA4C;IAC5C,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;QAClB,IAAI,CAAC;YACD,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACnC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,MAAM,eAAe,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YAClF,MAAM,IAAI,qBAAqB,CAC3B,sBAAsB,eAAe,CAAC,OAAO,EAAE,EAC/C,EAAE,SAAS,EAAE,KAAK,EAAE,eAAe,EAAE,CACxC,CAAC;QACN,CAAC;IACL,CAAC;IAED,2EAA2E;IAC3E,OAAO,MAAW,CAAC;AACvB,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,kBAAkB,CAC9B,MAAuB,EACvB,SAAiB;IAEjB,IAAI,CAAC;QACD,MAAM,KAAK,GAAG,eAAe,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QACjD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IAC/B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,IAAI,KAAK,YAAY,qBAAqB,EAAE,CAAC;YACzC,OAAO;gBACH,EAAE,EAAE,KAAK;gBACT,KAAK;gBACL,SAAS;aACZ,CAAC;QACN,CAAC;QACD,6BAA6B;QAC7B,MAAM,KAAK,CAAC;IAChB,CAAC;AACL,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,wBAAwB,CACpC,MAAuB,EACvB,IAAa,EACb,SAAkB;IAElB,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;QAClB,IAAI,CAAC;YACD,OAAO,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACjC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,MAAM,OAAO,GAAG,SAAS,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YAClD,MAAM,eAAe,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YAClF,MAAM,IAAI,qBAAqB,CAC3B,sBAAsB,eAAe,CAAC,OAAO,EAAE,EAC/C,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,CACjD,CAAC;QACN,CAAC;IACL,CAAC;IACD,OAAO,IAAS,CAAC;AACrB,CAAC;AAED,+EAA+E;AAC/E,yBAAyB;AACzB,+EAA+E;AAE/E;;;;;;GAMG;AACH,MAAM,OAAO,mBAAmB;IACpB,MAAM,GAAG,EAAE,CAAC;IACH,UAAU,CAAwB;IAEnD,YAAY,MAAuB;QAC/B,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,QAAQ,CAAC;IACtC,CAAC;IAED;;;;OAIG;IACH,IAAI,CAAC,KAAa;QACd,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC;QAErB,sCAAsC;QACtC,IAAI,CAAC;YACD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACvC,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;gBAClB,IAAI,CAAC;oBACD,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;oBAC1C,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;gBAClD,CAAC;gBAAC,MAAM,CAAC;oBACL,uEAAuE;gBAC3E,CAAC;YACL,CAAC;YACD,OAAO,EAAE,OAAO,EAAE,MAAW,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;QACpD,CAAC;QAAC,MAAM,CAAC;YACL,8BAA8B;QAClC,CAAC;QAED,kDAAkD;QAClD,MAAM,aAAa,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;QAC7C,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IACvD,CAAC;IAED;;OAEG;IACH,SAAS;QACL,OAAO,IAAI,CAAC,MAAM,CAAC;IACvB,CAAC;IAED;;OAEG;IACH,KAAK;QACD,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;IACrB,CAAC;IAED;;OAEG;IACK,eAAe;QACnB,qCAAqC;QACrC,IAAI,UAAU,GAAG,CAAC,CAAC;QACnB,IAAI,YAAY,GAAG,CAAC,CAAC;QACrB,IAAI,QAAQ,GAAG,KAAK,CAAC;QACrB,IAAI,OAAO,GAAG,KAAK,CAAC;QAEpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC1C,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YAE5B,IAAI,OAAO,EAAE,CAAC;gBACV,OAAO,GAAG,KAAK,CAAC;gBAChB,SAAS;YACb,CAAC;YAED,IAAI,IAAI,KAAK,IAAI,IAAI,QAAQ,EAAE,CAAC;gBAC5B,OAAO,GAAG,IAAI,CAAC;gBACf,SAAS;YACb,CAAC;YAED,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;gBACf,QAAQ,GAAG,CAAC,QAAQ,CAAC;gBACrB,SAAS;YACb,CAAC;YAED,IAAI,QAAQ;gBAAE,SAAS;YAEvB,IAAI,IAAI,KAAK,GAAG;gBAAE,UAAU,EAAE,CAAC;iBAC1B,IAAI,IAAI,KAAK,GAAG;gBAAE,UAAU,EAAE,CAAC;iBAC/B,IAAI,IAAI,KAAK,GAAG;gBAAE,YAAY,EAAE,CAAC;iBACjC,IAAI,IAAI,KAAK,GAAG;gBAAE,YAAY,EAAE,CAAC;QAC1C,CAAC;QAED,yBAAyB;QACzB,IAAI,OAAO,GAAG,EAAE,CAAC;QACjB,OAAO,YAAY,GAAG,CAAC,EAAE,CAAC;YACtB,OAAO,IAAI,GAAG,CAAC;YACf,YAAY,EAAE,CAAC;QACnB,CAAC;QACD,OAAO,UAAU,GAAG,CAAC,EAAE,CAAC;YACpB,OAAO,IAAI,GAAG,CAAC;YACf,UAAU,EAAE,CAAC;QACjB,CAAC;QAED,2BAA2B;QAC3B,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC;QACxC,IAAI,CAAC;YACD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;YACrC,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;gBAClB,IAAI,CAAC;oBACD,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;gBACnC,CAAC;gBAAC,MAAM,CAAC;oBACL,2DAA2D;gBAC/D,CAAC;YACL,CAAC;YACD,OAAO,MAAW,CAAC;QACvB,CAAC;QAAC,MAAM,CAAC;YACL,iCAAiC;QACrC,CAAC;QAED,OAAO,SAAS,CAAC;IACrB,CAAC;CACJ"}
@@ -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": "3.1.0",
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",
@@ -29,10 +29,19 @@
29
29
  "./http": {
30
30
  "import": "./dist/http.js",
31
31
  "types": "./dist/http.d.ts"
32
+ },
33
+ "./structured-output": {
34
+ "import": "./dist/structured-output.js",
35
+ "types": "./dist/structured-output.d.ts"
36
+ },
37
+ "./zod": {
38
+ "import": "./dist/zod-adapter.js",
39
+ "types": "./dist/zod-adapter.d.ts"
32
40
  }
33
41
  },
34
42
  "files": [
35
43
  "dist",
44
+ "src",
36
45
  "README.md",
37
46
  "CHANGELOG.md",
38
47
  "LICENSE"
@@ -46,7 +55,10 @@
46
55
  "test": "bun test",
47
56
  "typecheck": "tsc --noEmit",
48
57
  "lint": "tsc --noEmit --strict",
49
- "prepack": "bun run build"
58
+ "prepack": "bun run build",
59
+ "docs:dev": "vitepress dev docs",
60
+ "docs:build": "vitepress build docs",
61
+ "docs:preview": "vitepress preview docs"
50
62
  },
51
63
  "keywords": [
52
64
  "llm",
@@ -70,14 +82,21 @@
70
82
  "devDependencies": {
71
83
  "@types/node": "^22.0.0",
72
84
  "rimraf": "^6.0.1",
73
- "typescript": "^5.8.3"
85
+ "typescript": "^5.8.3",
86
+ "vitepress": "^1.6.4",
87
+ "vue": "^3.5.30",
88
+ "zod": "^4.0.0"
74
89
  },
75
90
  "peerDependencies": {
76
- "@modelcontextprotocol/sdk": ">=1.24.0"
91
+ "@modelcontextprotocol/sdk": ">=1.24.0",
92
+ "zod": "^4.0.0"
77
93
  },
78
94
  "peerDependenciesMeta": {
79
95
  "@modelcontextprotocol/sdk": {
80
96
  "optional": true
97
+ },
98
+ "zod": {
99
+ "optional": true
81
100
  }
82
101
  },
83
102
  "engines": {