@synova-cloud/sdk 1.5.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 CHANGED
@@ -119,6 +119,29 @@ const response = await client.prompts.execute('prm_abc123', {
119
119
  });
120
120
  ```
121
121
 
122
+ #### With Your Own API Key
123
+
124
+ You can pass your own LLM provider API key directly in the request:
125
+
126
+ ```typescript
127
+ // OpenAI, Anthropic, Google, DeepSeek
128
+ const response = await client.prompts.execute('prm_abc123', {
129
+ provider: 'openai',
130
+ model: 'gpt-4o',
131
+ apiKey: 'sk-your-openai-key',
132
+ variables: { topic: 'TypeScript' },
133
+ });
134
+
135
+ // Azure OpenAI (requires endpoint)
136
+ const response = await client.prompts.execute('prm_abc123', {
137
+ provider: 'azure_openai',
138
+ model: 'my-gpt4-deployment',
139
+ apiKey: 'your-azure-key',
140
+ azureEndpoint: 'https://my-resource.openai.azure.com',
141
+ variables: { topic: 'TypeScript' },
142
+ });
143
+ ```
144
+
122
145
  #### With Conversation History
123
146
 
124
147
  ```typescript
@@ -151,6 +174,95 @@ if (response.type === 'image') {
151
174
  }
152
175
  ```
153
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
+
154
266
  ### Models
155
267
 
156
268
  #### List All Models
@@ -243,116 +355,50 @@ const response = await client.prompts.execute('prm_vision123', {
243
355
  console.log(response.content);
244
356
  ```
245
357
 
246
- ### LLM Provider Keys
247
-
248
- Manage API keys for LLM providers (OpenAI, Anthropic, Google, Azure, etc.).
249
-
250
- #### List Keys
251
-
252
- ```typescript
253
- const { items, total } = await client.llmProviderKeys.list();
254
-
255
- for (const key of items) {
256
- console.log(`${key.provider}: ${key.maskedKey} (default: ${key.isDefault})`);
257
- if (key.label) {
258
- console.log(` Label: ${key.label}`);
259
- }
260
- }
261
- ```
262
-
263
- #### Get Key by ID
264
-
265
- ```typescript
266
- const key = await client.llmProviderKeys.get('lpk_abc123');
267
-
268
- console.log(`Provider: ${key.provider}`);
269
- console.log(`Default: ${key.isDefault}`);
270
- console.log(`Label: ${key.label}`);
271
- ```
272
-
273
- #### Create Key
274
-
275
- ```typescript
276
- // Create OpenAI key
277
- const key = await client.llmProviderKeys.create({
278
- provider: 'openai',
279
- apiKey: 'sk-...',
280
- label: 'Production Key',
281
- defaultModel: 'gpt-4o',
282
- });
283
-
284
- // Create Azure OpenAI key
285
- const azureKey = await client.llmProviderKeys.create({
286
- provider: 'azure_openai',
287
- apiKey: 'your-azure-key',
288
- azure: {
289
- endpoint: 'https://my-resource.openai.azure.com',
290
- },
291
- label: 'Azure Production',
292
- });
293
- ```
294
-
295
- The first key created for a provider is automatically set as the default.
296
-
297
- #### Set Default Key
298
-
299
- ```typescript
300
- // Set a different key as the default for its provider
301
- const key = await client.llmProviderKeys.setDefault('lpk_abc123');
302
- console.log(`${key.id} is now the default for ${key.provider}`);
303
- ```
304
-
305
- #### Delete Key
306
-
307
- ```typescript
308
- await client.llmProviderKeys.delete('lpk_abc123');
309
- ```
310
-
311
- If you delete the default key and other keys exist for that provider, the next key becomes the new default.
312
-
313
- #### Use Specific Key in Execution
314
-
315
- ```typescript
316
- // Execute with a specific API key
317
- const response = await client.prompts.execute('prm_abc123', {
318
- provider: 'openai',
319
- model: 'gpt-4o',
320
- apiKeyId: 'lpk_abc123', // Use this specific key
321
- variables: { name: 'World' },
322
- });
323
-
324
- // Or omit apiKeyId to use the default key for the provider
325
- const response = await client.prompts.execute('prm_abc123', {
326
- provider: 'openai',
327
- model: 'gpt-4o',
328
- variables: { name: 'World' },
329
- });
330
- ```
331
-
332
358
  ## Error Handling
333
359
 
334
- The SDK provides typed errors for different failure scenarios. All API errors extend `ApiSynovaError` and include full error details:
360
+ The SDK provides typed errors for different failure scenarios:
335
361
 
336
362
  ```typescript
337
363
  import {
338
364
  SynovaCloudSdk,
339
- SynovaError,
340
- ApiSynovaError,
365
+ ExecutionSynovaError,
366
+ ValidationSynovaError,
341
367
  AuthSynovaError,
342
368
  NotFoundSynovaError,
343
369
  RateLimitSynovaError,
344
370
  ServerSynovaError,
345
371
  TimeoutSynovaError,
346
372
  NetworkSynovaError,
373
+ ApiSynovaError,
347
374
  } from '@synova-cloud/sdk';
348
375
 
349
376
  try {
350
377
  const response = await client.prompts.execute('prm_abc123', {
351
378
  provider: 'openai',
352
379
  model: 'gpt-4o',
353
- variables: { name: 'World' },
380
+ responseClass: TopicDto,
354
381
  });
355
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
356
402
  if (error instanceof AuthSynovaError) {
357
403
  console.error('Invalid API key');
358
404
  } else if (error instanceof NotFoundSynovaError) {
@@ -366,10 +412,8 @@ try {
366
412
  } else if (error instanceof NetworkSynovaError) {
367
413
  console.error(`Network error: ${error.message}`);
368
414
  } else if (error instanceof ApiSynovaError) {
369
- // All API errors have these properties:
370
415
  console.error(`API error [${error.code}]: ${error.message}`);
371
416
  console.error(`Request ID: ${error.requestId}`);
372
- console.error(`Details:`, error.details);
373
417
  }
374
418
  }
375
419
  ```
@@ -476,8 +520,9 @@ import type {
476
520
  ISynovaGetPromptOptions,
477
521
  // Execution
478
522
  ISynovaExecuteOptions,
523
+ ISynovaExecuteTypedOptions,
479
524
  ISynovaExecuteResponse,
480
- ISynovaUsage,
525
+ ISynovaExecutionUsage,
481
526
  ISynovaExecutionError,
482
527
  // Messages
483
528
  ISynovaMessage,
@@ -498,12 +543,13 @@ import type {
498
543
  ISynovaModelsResponse,
499
544
  ISynovaListModelsOptions,
500
545
  TSynovaModelType,
501
- // LLM Provider Keys
502
- TSynovaLlmProvider,
503
- ISynovaAzureConfig,
504
- ISynovaLlmProviderKey,
505
- ISynovaLlmProviderKeyListResponse,
506
- ISynovaCreateLlmProviderKeyOptions,
546
+ // Schema
547
+ IJsonSchema,
548
+ TJsonSchemaType,
549
+ TJsonSchemaFormat,
550
+ TClassConstructor,
551
+ // Errors
552
+ IValidationViolation,
507
553
  } from '@synova-cloud/sdk';
508
554
  ```
509
555
 
@@ -521,6 +567,15 @@ const client = new SynovaCloudSdk('your-api-key');
521
567
 
522
568
  - Node.js 18+ (uses native `fetch`)
523
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
+
524
579
  ## License
525
580
 
526
581
  MIT