@synova-cloud/sdk 1.6.0 → 1.7.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/README.md +131 -7
- package/dist/index.cjs +558 -108
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +451 -77
- package/dist/index.d.ts +451 -77
- package/dist/index.js +537 -109
- package/dist/index.js.map +1 -1
- package/package.json +16 -1
package/README.md
CHANGED
|
@@ -174,6 +174,95 @@ if (response.type === 'image') {
|
|
|
174
174
|
}
|
|
175
175
|
```
|
|
176
176
|
|
|
177
|
+
#### Structured Output (Typed Responses)
|
|
178
|
+
|
|
179
|
+
Get typed and validated responses from LLMs using JSON Schema.
|
|
180
|
+
|
|
181
|
+
First, install optional peer dependencies:
|
|
182
|
+
```bash
|
|
183
|
+
npm install class-validator class-transformer
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Define a response class with decorators:
|
|
187
|
+
```typescript
|
|
188
|
+
import { IsString, IsArray, IsNumber, Min, Max } from 'class-validator';
|
|
189
|
+
import { Description, Example, ArrayItems } from '@synova-cloud/sdk';
|
|
190
|
+
|
|
191
|
+
class TopicDto {
|
|
192
|
+
@IsString()
|
|
193
|
+
@Description('Article title for SEO')
|
|
194
|
+
@Example('10 Ways to Improve SQL Performance')
|
|
195
|
+
title: string;
|
|
196
|
+
|
|
197
|
+
@IsString()
|
|
198
|
+
@Description('Short description')
|
|
199
|
+
description: string;
|
|
200
|
+
|
|
201
|
+
@IsArray()
|
|
202
|
+
@ArrayItems(String)
|
|
203
|
+
@Description('SEO keywords')
|
|
204
|
+
keywords: string[];
|
|
205
|
+
|
|
206
|
+
@IsNumber()
|
|
207
|
+
@Min(1)
|
|
208
|
+
@Max(10)
|
|
209
|
+
@Description('Priority from 1 to 10')
|
|
210
|
+
priority: number;
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
Execute with `responseClass` to get typed response:
|
|
215
|
+
```typescript
|
|
216
|
+
const topic = await client.prompts.execute('prm_abc123', {
|
|
217
|
+
provider: 'openai',
|
|
218
|
+
model: 'gpt-4o',
|
|
219
|
+
responseClass: TopicDto,
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
// topic is typed as TopicDto
|
|
223
|
+
console.log(topic.title); // string
|
|
224
|
+
console.log(topic.keywords); // string[]
|
|
225
|
+
console.log(topic.priority); // number
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
Works with `executeByTag` and `executeByVersion` too:
|
|
229
|
+
```typescript
|
|
230
|
+
const topic = await client.prompts.executeByTag('prm_abc123', 'production', {
|
|
231
|
+
provider: 'openai',
|
|
232
|
+
model: 'gpt-4o',
|
|
233
|
+
responseClass: TopicDto,
|
|
234
|
+
});
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
Disable validation if needed:
|
|
238
|
+
```typescript
|
|
239
|
+
const topic = await client.prompts.execute('prm_abc123', {
|
|
240
|
+
provider: 'openai',
|
|
241
|
+
model: 'gpt-4o',
|
|
242
|
+
responseClass: TopicDto,
|
|
243
|
+
validate: false, // Skip class-validator validation
|
|
244
|
+
});
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
**Available Schema Decorators:**
|
|
248
|
+
|
|
249
|
+
| Decorator | Description |
|
|
250
|
+
|-----------|-------------|
|
|
251
|
+
| `@Description(text)` | Adds description to help LLM |
|
|
252
|
+
| `@Example(...values)` | Adds example values |
|
|
253
|
+
| `@Default(value)` | Sets default value |
|
|
254
|
+
| `@ArrayItems(Type)` | Sets array item type |
|
|
255
|
+
| `@Format(format)` | Sets string format (email, uri, uuid, date-time) |
|
|
256
|
+
| `@Nullable()` | Marks as nullable |
|
|
257
|
+
| `@SchemaMin(n)` | Minimum number value |
|
|
258
|
+
| `@SchemaMax(n)` | Maximum number value |
|
|
259
|
+
| `@SchemaMinLength(n)` | Minimum string length |
|
|
260
|
+
| `@SchemaMaxLength(n)` | Maximum string length |
|
|
261
|
+
| `@SchemaPattern(regex)` | Regex pattern for string |
|
|
262
|
+
| `@SchemaMinItems(n)` | Minimum array length |
|
|
263
|
+
| `@SchemaMaxItems(n)` | Maximum array length |
|
|
264
|
+
| `@SchemaEnum(values)` | Allowed enum values |
|
|
265
|
+
|
|
177
266
|
### Models
|
|
178
267
|
|
|
179
268
|
#### List All Models
|
|
@@ -268,28 +357,48 @@ console.log(response.content);
|
|
|
268
357
|
|
|
269
358
|
## Error Handling
|
|
270
359
|
|
|
271
|
-
The SDK provides typed errors for different failure scenarios
|
|
360
|
+
The SDK provides typed errors for different failure scenarios:
|
|
272
361
|
|
|
273
362
|
```typescript
|
|
274
363
|
import {
|
|
275
364
|
SynovaCloudSdk,
|
|
276
|
-
|
|
277
|
-
|
|
365
|
+
ExecutionSynovaError,
|
|
366
|
+
ValidationSynovaError,
|
|
278
367
|
AuthSynovaError,
|
|
279
368
|
NotFoundSynovaError,
|
|
280
369
|
RateLimitSynovaError,
|
|
281
370
|
ServerSynovaError,
|
|
282
371
|
TimeoutSynovaError,
|
|
283
372
|
NetworkSynovaError,
|
|
373
|
+
ApiSynovaError,
|
|
284
374
|
} from '@synova-cloud/sdk';
|
|
285
375
|
|
|
286
376
|
try {
|
|
287
377
|
const response = await client.prompts.execute('prm_abc123', {
|
|
288
378
|
provider: 'openai',
|
|
289
379
|
model: 'gpt-4o',
|
|
290
|
-
|
|
380
|
+
responseClass: TopicDto,
|
|
291
381
|
});
|
|
292
382
|
} catch (error) {
|
|
383
|
+
// LLM execution error (rate limit, invalid key, context too long, etc.)
|
|
384
|
+
if (error instanceof ExecutionSynovaError) {
|
|
385
|
+
console.error(`LLM error [${error.code}]: ${error.message}`);
|
|
386
|
+
console.error(`Provider: ${error.provider}`);
|
|
387
|
+
console.error(`Retryable: ${error.retryable}`);
|
|
388
|
+
if (error.retryAfterMs) {
|
|
389
|
+
console.error(`Retry after: ${error.retryAfterMs}ms`);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
// Validation error (response doesn't match class-validator constraints)
|
|
394
|
+
if (error instanceof ValidationSynovaError) {
|
|
395
|
+
console.error('Validation failed:');
|
|
396
|
+
for (const v of error.violations) {
|
|
397
|
+
console.error(` ${v.property}: ${Object.values(v.constraints).join(', ')}`);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
// API errors
|
|
293
402
|
if (error instanceof AuthSynovaError) {
|
|
294
403
|
console.error('Invalid API key');
|
|
295
404
|
} else if (error instanceof NotFoundSynovaError) {
|
|
@@ -303,10 +412,8 @@ try {
|
|
|
303
412
|
} else if (error instanceof NetworkSynovaError) {
|
|
304
413
|
console.error(`Network error: ${error.message}`);
|
|
305
414
|
} else if (error instanceof ApiSynovaError) {
|
|
306
|
-
// All API errors have these properties:
|
|
307
415
|
console.error(`API error [${error.code}]: ${error.message}`);
|
|
308
416
|
console.error(`Request ID: ${error.requestId}`);
|
|
309
|
-
console.error(`Details:`, error.details);
|
|
310
417
|
}
|
|
311
418
|
}
|
|
312
419
|
```
|
|
@@ -413,8 +520,9 @@ import type {
|
|
|
413
520
|
ISynovaGetPromptOptions,
|
|
414
521
|
// Execution
|
|
415
522
|
ISynovaExecuteOptions,
|
|
523
|
+
ISynovaExecuteTypedOptions,
|
|
416
524
|
ISynovaExecuteResponse,
|
|
417
|
-
|
|
525
|
+
ISynovaExecutionUsage,
|
|
418
526
|
ISynovaExecutionError,
|
|
419
527
|
// Messages
|
|
420
528
|
ISynovaMessage,
|
|
@@ -435,6 +543,13 @@ import type {
|
|
|
435
543
|
ISynovaModelsResponse,
|
|
436
544
|
ISynovaListModelsOptions,
|
|
437
545
|
TSynovaModelType,
|
|
546
|
+
// Schema
|
|
547
|
+
IJsonSchema,
|
|
548
|
+
TJsonSchemaType,
|
|
549
|
+
TJsonSchemaFormat,
|
|
550
|
+
TClassConstructor,
|
|
551
|
+
// Errors
|
|
552
|
+
IValidationViolation,
|
|
438
553
|
} from '@synova-cloud/sdk';
|
|
439
554
|
```
|
|
440
555
|
|
|
@@ -452,6 +567,15 @@ const client = new SynovaCloudSdk('your-api-key');
|
|
|
452
567
|
|
|
453
568
|
- Node.js 18+ (uses native `fetch`)
|
|
454
569
|
|
|
570
|
+
### Optional Peer Dependencies
|
|
571
|
+
|
|
572
|
+
For structured output with typed responses:
|
|
573
|
+
```bash
|
|
574
|
+
npm install class-validator class-transformer
|
|
575
|
+
```
|
|
576
|
+
|
|
577
|
+
These are optional - the SDK works without them, but `responseClass` feature requires them.
|
|
578
|
+
|
|
455
579
|
## License
|
|
456
580
|
|
|
457
581
|
MIT
|