@synova-cloud/sdk 1.6.0 → 1.8.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/index.js CHANGED
@@ -1,3 +1,12 @@
1
+ import 'reflect-metadata';
2
+
3
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
4
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
5
+ }) : x)(function(x) {
6
+ if (typeof require !== "undefined") return require.apply(this, arguments);
7
+ throw Error('Dynamic require of "' + x + '" is not supported');
8
+ });
9
+
1
10
  // src/errors/index.ts
2
11
  var SynovaError = class extends Error {
3
12
  constructor(message) {
@@ -69,9 +78,34 @@ var NetworkSynovaError = class extends SynovaError {
69
78
  this.cause = cause;
70
79
  }
71
80
  };
81
+ var ExecutionSynovaError = class extends SynovaError {
82
+ code;
83
+ provider;
84
+ retryable;
85
+ retryAfterMs;
86
+ details;
87
+ constructor(error) {
88
+ super(error.message);
89
+ this.name = "ExecutionSynovaError";
90
+ this.code = error.code;
91
+ this.provider = error.provider;
92
+ this.retryable = error.retryable;
93
+ this.retryAfterMs = error.retryAfterMs;
94
+ this.details = error.details;
95
+ }
96
+ };
97
+ var ValidationSynovaError = class extends SynovaError {
98
+ violations;
99
+ constructor(violations) {
100
+ const message = `Validation failed: ${violations.map((v) => v.property).join(", ")}`;
101
+ super(message);
102
+ this.name = "ValidationSynovaError";
103
+ this.violations = violations;
104
+ }
105
+ };
72
106
 
73
107
  // src/version.ts
74
- var SDK_VERSION = "1.6.0" ;
108
+ var SDK_VERSION = "1.8.0" ;
75
109
 
76
110
  // src/utils/http.ts
77
111
  var HttpClient = class {
@@ -282,6 +316,451 @@ var HttpClient = class {
282
316
  }
283
317
  };
284
318
 
319
+ // src/schema/types.ts
320
+ var SCHEMA_METADATA_KEYS = {
321
+ // Metadata
322
+ DESCRIPTION: "synova:schema:description",
323
+ EXAMPLES: "synova:schema:examples",
324
+ DEFAULT: "synova:schema:default",
325
+ // Type helpers
326
+ FORMAT: "synova:schema:format",
327
+ ARRAY_ITEM_TYPE: "synova:schema:arrayItemType",
328
+ NULLABLE: "synova:schema:nullable",
329
+ ENUM: "synova:schema:enum",
330
+ // String constraints
331
+ MIN_LENGTH: "synova:schema:minLength",
332
+ MAX_LENGTH: "synova:schema:maxLength",
333
+ PATTERN: "synova:schema:pattern",
334
+ // Number constraints
335
+ MINIMUM: "synova:schema:minimum",
336
+ MAXIMUM: "synova:schema:maximum",
337
+ EXCLUSIVE_MINIMUM: "synova:schema:exclusiveMinimum",
338
+ EXCLUSIVE_MAXIMUM: "synova:schema:exclusiveMaximum",
339
+ MULTIPLE_OF: "synova:schema:multipleOf",
340
+ // Array constraints
341
+ MIN_ITEMS: "synova:schema:minItems",
342
+ MAX_ITEMS: "synova:schema:maxItems",
343
+ UNIQUE_ITEMS: "synova:schema:uniqueItems"
344
+ };
345
+ function createMetadataDecorator(key, value) {
346
+ return function(target, propertyKey) {
347
+ Reflect.defineMetadata(key, value, target, propertyKey);
348
+ };
349
+ }
350
+ function Description(description) {
351
+ return createMetadataDecorator(SCHEMA_METADATA_KEYS.DESCRIPTION, description);
352
+ }
353
+ function Example(...examples) {
354
+ return createMetadataDecorator(SCHEMA_METADATA_KEYS.EXAMPLES, examples);
355
+ }
356
+ function Default(value) {
357
+ return createMetadataDecorator(SCHEMA_METADATA_KEYS.DEFAULT, value);
358
+ }
359
+ function ArrayItems(itemType) {
360
+ return createMetadataDecorator(SCHEMA_METADATA_KEYS.ARRAY_ITEM_TYPE, itemType);
361
+ }
362
+ function Format(format) {
363
+ return createMetadataDecorator(SCHEMA_METADATA_KEYS.FORMAT, format);
364
+ }
365
+ function Nullable() {
366
+ return createMetadataDecorator(SCHEMA_METADATA_KEYS.NULLABLE, true);
367
+ }
368
+ function SchemaMinLength(length) {
369
+ return createMetadataDecorator(SCHEMA_METADATA_KEYS.MIN_LENGTH, length);
370
+ }
371
+ function SchemaMaxLength(length) {
372
+ return createMetadataDecorator(SCHEMA_METADATA_KEYS.MAX_LENGTH, length);
373
+ }
374
+ function SchemaPattern(pattern) {
375
+ return createMetadataDecorator(SCHEMA_METADATA_KEYS.PATTERN, pattern);
376
+ }
377
+ function SchemaMin(value) {
378
+ return createMetadataDecorator(SCHEMA_METADATA_KEYS.MINIMUM, value);
379
+ }
380
+ function SchemaMax(value) {
381
+ return createMetadataDecorator(SCHEMA_METADATA_KEYS.MAXIMUM, value);
382
+ }
383
+ function ExclusiveMin(value) {
384
+ return createMetadataDecorator(SCHEMA_METADATA_KEYS.EXCLUSIVE_MINIMUM, value);
385
+ }
386
+ function ExclusiveMax(value) {
387
+ return createMetadataDecorator(SCHEMA_METADATA_KEYS.EXCLUSIVE_MAXIMUM, value);
388
+ }
389
+ function MultipleOf(value) {
390
+ return createMetadataDecorator(SCHEMA_METADATA_KEYS.MULTIPLE_OF, value);
391
+ }
392
+ function SchemaMinItems(count) {
393
+ return createMetadataDecorator(SCHEMA_METADATA_KEYS.MIN_ITEMS, count);
394
+ }
395
+ function SchemaMaxItems(count) {
396
+ return createMetadataDecorator(SCHEMA_METADATA_KEYS.MAX_ITEMS, count);
397
+ }
398
+ function SchemaUniqueItems() {
399
+ return createMetadataDecorator(SCHEMA_METADATA_KEYS.UNIQUE_ITEMS, true);
400
+ }
401
+ function SchemaEnum(values) {
402
+ return createMetadataDecorator(SCHEMA_METADATA_KEYS.ENUM, values);
403
+ }
404
+ function getSchemaMetadata(key, target, propertyKey) {
405
+ return Reflect.getMetadata(key, target, propertyKey);
406
+ }
407
+
408
+ // src/schema/class-schema.ts
409
+ var ClassSchema = class {
410
+ /**
411
+ * Generate JSON Schema from a class
412
+ */
413
+ static generate(targetClass, options = {}) {
414
+ const { additionalProperties = false } = options;
415
+ const properties = this.getProperties(targetClass);
416
+ const required = this.getRequiredProperties(targetClass, properties);
417
+ return {
418
+ type: "object",
419
+ properties,
420
+ required: required.length > 0 ? required : void 0,
421
+ additionalProperties
422
+ };
423
+ }
424
+ /**
425
+ * Get all properties with their schemas
426
+ */
427
+ static getProperties(targetClass) {
428
+ const properties = {};
429
+ const prototype = targetClass.prototype;
430
+ const classValidatorProperties = this.getClassValidatorProperties(targetClass);
431
+ const decoratorProperties = this.getDecoratorProperties(prototype);
432
+ const allProperties = /* @__PURE__ */ new Set([...classValidatorProperties, ...decoratorProperties]);
433
+ for (const propertyName of allProperties) {
434
+ properties[propertyName] = this.getPropertySchema(targetClass, propertyName);
435
+ }
436
+ return properties;
437
+ }
438
+ /**
439
+ * Get property names from class-validator metadata
440
+ */
441
+ static getClassValidatorProperties(targetClass) {
442
+ try {
443
+ const { getMetadataStorage } = __require("class-validator");
444
+ const metadataStorage = getMetadataStorage();
445
+ const targetMetadatas = metadataStorage.getTargetValidationMetadatas(
446
+ targetClass,
447
+ "",
448
+ true,
449
+ false
450
+ );
451
+ const propertyNames = targetMetadatas.map((m) => m.propertyName);
452
+ return [...new Set(propertyNames)];
453
+ } catch {
454
+ return [];
455
+ }
456
+ }
457
+ /**
458
+ * Get property names from our decorator metadata
459
+ */
460
+ static getDecoratorProperties(prototype) {
461
+ const properties = [];
462
+ const ownKeys = Reflect.ownKeys(prototype);
463
+ for (const key of ownKeys) {
464
+ if (typeof key === "string" && key !== "constructor") {
465
+ for (const metaKey of Object.values(SCHEMA_METADATA_KEYS)) {
466
+ if (Reflect.hasMetadata(metaKey, prototype, key)) {
467
+ properties.push(key);
468
+ break;
469
+ }
470
+ }
471
+ }
472
+ }
473
+ return properties;
474
+ }
475
+ /**
476
+ * Get JSON Schema for a single property
477
+ */
478
+ static getPropertySchema(targetClass, propertyName) {
479
+ const prototype = targetClass.prototype;
480
+ const schema = {};
481
+ const designType = Reflect.getMetadata("design:type", prototype, propertyName);
482
+ const baseSchema = this.getBaseTypeSchema(designType, targetClass, propertyName);
483
+ Object.assign(schema, baseSchema);
484
+ this.applyClassValidatorConstraints(schema, targetClass, propertyName);
485
+ this.applyDecoratorMetadata(schema, prototype, propertyName);
486
+ const isNullable = getSchemaMetadata(
487
+ SCHEMA_METADATA_KEYS.NULLABLE,
488
+ prototype,
489
+ propertyName
490
+ );
491
+ if (isNullable && schema.type && typeof schema.type === "string") {
492
+ schema.type = [schema.type, "null"];
493
+ }
494
+ return schema;
495
+ }
496
+ /**
497
+ * Get base schema from TypeScript type
498
+ */
499
+ static getBaseTypeSchema(designType, targetClass, propertyName) {
500
+ if (designType === String) {
501
+ return { type: "string" };
502
+ }
503
+ if (designType === Number) {
504
+ return { type: "number" };
505
+ }
506
+ if (designType === Boolean) {
507
+ return { type: "boolean" };
508
+ }
509
+ if (designType === Array) {
510
+ const itemType = getSchemaMetadata(
511
+ SCHEMA_METADATA_KEYS.ARRAY_ITEM_TYPE,
512
+ targetClass.prototype,
513
+ propertyName
514
+ );
515
+ return {
516
+ type: "array",
517
+ items: this.getArrayItemSchema(itemType)
518
+ };
519
+ }
520
+ if (designType === Object) {
521
+ return { type: "object" };
522
+ }
523
+ if (typeof designType === "function" && designType.prototype) {
524
+ return this.generate(designType);
525
+ }
526
+ return { type: "string" };
527
+ }
528
+ /**
529
+ * Get schema for array items
530
+ */
531
+ static getArrayItemSchema(itemType) {
532
+ if (!itemType) {
533
+ return { type: "string" };
534
+ }
535
+ if (itemType === String) {
536
+ return { type: "string" };
537
+ }
538
+ if (itemType === Number) {
539
+ return { type: "number" };
540
+ }
541
+ if (itemType === Boolean) {
542
+ return { type: "boolean" };
543
+ }
544
+ return this.generate(itemType);
545
+ }
546
+ /**
547
+ * Apply class-validator constraints to schema
548
+ */
549
+ static applyClassValidatorConstraints(schema, targetClass, propertyName) {
550
+ try {
551
+ const { getMetadataStorage } = __require("class-validator");
552
+ const metadataStorage = getMetadataStorage();
553
+ const targetMetadatas = metadataStorage.getTargetValidationMetadatas(
554
+ targetClass,
555
+ "",
556
+ true,
557
+ false
558
+ );
559
+ const propertyMetadatas = targetMetadatas.filter(
560
+ (m) => m.propertyName === propertyName
561
+ );
562
+ for (const metadata of propertyMetadatas) {
563
+ this.applyValidationConstraint(schema, metadata);
564
+ }
565
+ } catch {
566
+ }
567
+ }
568
+ /**
569
+ * Apply a single class-validator constraint
570
+ */
571
+ static applyValidationConstraint(schema, metadata) {
572
+ const constraintType = metadata.name || metadata.type || "";
573
+ const constraints = metadata.constraints || [];
574
+ switch (constraintType) {
575
+ case "isString":
576
+ schema.type = "string";
577
+ break;
578
+ case "isNumber":
579
+ case "isInt":
580
+ schema.type = constraintType === "isInt" ? "integer" : "number";
581
+ break;
582
+ case "isBoolean":
583
+ schema.type = "boolean";
584
+ break;
585
+ case "isArray":
586
+ schema.type = "array";
587
+ break;
588
+ case "isEnum":
589
+ if (constraints[0]) {
590
+ schema.enum = Object.values(constraints[0]);
591
+ }
592
+ break;
593
+ case "minLength":
594
+ schema.minLength = constraints[0];
595
+ break;
596
+ case "maxLength":
597
+ schema.maxLength = constraints[0];
598
+ break;
599
+ case "min":
600
+ schema.minimum = constraints[0];
601
+ break;
602
+ case "max":
603
+ schema.maximum = constraints[0];
604
+ break;
605
+ case "isEmail":
606
+ schema.format = "email";
607
+ break;
608
+ case "isUrl":
609
+ case "isURL":
610
+ schema.format = "uri";
611
+ break;
612
+ case "isUUID":
613
+ schema.format = "uuid";
614
+ break;
615
+ case "isDateString":
616
+ case "isISO8601":
617
+ schema.format = "date-time";
618
+ break;
619
+ case "matches":
620
+ if (constraints[0] instanceof RegExp) {
621
+ schema.pattern = constraints[0].source;
622
+ } else if (typeof constraints[0] === "string") {
623
+ schema.pattern = constraints[0];
624
+ }
625
+ break;
626
+ case "arrayMinSize":
627
+ schema.minItems = constraints[0];
628
+ break;
629
+ case "arrayMaxSize":
630
+ schema.maxItems = constraints[0];
631
+ break;
632
+ case "arrayUnique":
633
+ schema.uniqueItems = true;
634
+ break;
635
+ }
636
+ }
637
+ /**
638
+ * Apply our decorator metadata to schema.
639
+ * Our decorators take precedence over class-validator if both are used.
640
+ */
641
+ static applyDecoratorMetadata(schema, prototype, propertyName) {
642
+ const description = getSchemaMetadata(
643
+ SCHEMA_METADATA_KEYS.DESCRIPTION,
644
+ prototype,
645
+ propertyName
646
+ );
647
+ if (description) schema.description = description;
648
+ const examples = getSchemaMetadata(
649
+ SCHEMA_METADATA_KEYS.EXAMPLES,
650
+ prototype,
651
+ propertyName
652
+ );
653
+ if (examples) schema.examples = examples;
654
+ const defaultValue = getSchemaMetadata(
655
+ SCHEMA_METADATA_KEYS.DEFAULT,
656
+ prototype,
657
+ propertyName
658
+ );
659
+ if (defaultValue !== void 0) schema.default = defaultValue;
660
+ const format = getSchemaMetadata(SCHEMA_METADATA_KEYS.FORMAT, prototype, propertyName);
661
+ if (format) schema.format = format;
662
+ const enumValues = getSchemaMetadata(
663
+ SCHEMA_METADATA_KEYS.ENUM,
664
+ prototype,
665
+ propertyName
666
+ );
667
+ if (enumValues) schema.enum = enumValues;
668
+ const minLength = getSchemaMetadata(
669
+ SCHEMA_METADATA_KEYS.MIN_LENGTH,
670
+ prototype,
671
+ propertyName
672
+ );
673
+ if (minLength !== void 0) schema.minLength = minLength;
674
+ const maxLength = getSchemaMetadata(
675
+ SCHEMA_METADATA_KEYS.MAX_LENGTH,
676
+ prototype,
677
+ propertyName
678
+ );
679
+ if (maxLength !== void 0) schema.maxLength = maxLength;
680
+ const pattern = getSchemaMetadata(
681
+ SCHEMA_METADATA_KEYS.PATTERN,
682
+ prototype,
683
+ propertyName
684
+ );
685
+ if (pattern) schema.pattern = pattern;
686
+ const minimum = getSchemaMetadata(
687
+ SCHEMA_METADATA_KEYS.MINIMUM,
688
+ prototype,
689
+ propertyName
690
+ );
691
+ if (minimum !== void 0) schema.minimum = minimum;
692
+ const maximum = getSchemaMetadata(
693
+ SCHEMA_METADATA_KEYS.MAXIMUM,
694
+ prototype,
695
+ propertyName
696
+ );
697
+ if (maximum !== void 0) schema.maximum = maximum;
698
+ const exclusiveMinimum = getSchemaMetadata(
699
+ SCHEMA_METADATA_KEYS.EXCLUSIVE_MINIMUM,
700
+ prototype,
701
+ propertyName
702
+ );
703
+ if (exclusiveMinimum !== void 0) schema.exclusiveMinimum = exclusiveMinimum;
704
+ const exclusiveMaximum = getSchemaMetadata(
705
+ SCHEMA_METADATA_KEYS.EXCLUSIVE_MAXIMUM,
706
+ prototype,
707
+ propertyName
708
+ );
709
+ if (exclusiveMaximum !== void 0) schema.exclusiveMaximum = exclusiveMaximum;
710
+ const multipleOf = getSchemaMetadata(
711
+ SCHEMA_METADATA_KEYS.MULTIPLE_OF,
712
+ prototype,
713
+ propertyName
714
+ );
715
+ if (multipleOf !== void 0) schema.multipleOf = multipleOf;
716
+ const minItems = getSchemaMetadata(
717
+ SCHEMA_METADATA_KEYS.MIN_ITEMS,
718
+ prototype,
719
+ propertyName
720
+ );
721
+ if (minItems !== void 0) schema.minItems = minItems;
722
+ const maxItems = getSchemaMetadata(
723
+ SCHEMA_METADATA_KEYS.MAX_ITEMS,
724
+ prototype,
725
+ propertyName
726
+ );
727
+ if (maxItems !== void 0) schema.maxItems = maxItems;
728
+ const uniqueItems = getSchemaMetadata(
729
+ SCHEMA_METADATA_KEYS.UNIQUE_ITEMS,
730
+ prototype,
731
+ propertyName
732
+ );
733
+ if (uniqueItems) schema.uniqueItems = uniqueItems;
734
+ }
735
+ /**
736
+ * Get required properties (properties without @IsOptional)
737
+ */
738
+ static getRequiredProperties(targetClass, properties) {
739
+ const required = [];
740
+ try {
741
+ const { getMetadataStorage } = __require("class-validator");
742
+ const metadataStorage = getMetadataStorage();
743
+ const targetMetadatas = metadataStorage.getTargetValidationMetadatas(
744
+ targetClass,
745
+ "",
746
+ true,
747
+ false
748
+ );
749
+ for (const propertyName of Object.keys(properties)) {
750
+ const isOptional = targetMetadatas.some(
751
+ (m) => m.propertyName === propertyName && (m.type === "isOptional" || m.type === "conditionalValidation")
752
+ );
753
+ if (!isOptional) {
754
+ required.push(propertyName);
755
+ }
756
+ }
757
+ } catch {
758
+ required.push(...Object.keys(properties));
759
+ }
760
+ return required;
761
+ }
762
+ };
763
+
285
764
  // src/resources/prompts.ts
286
765
  var PromptsResource = class {
287
766
  constructor(http) {
@@ -289,22 +768,6 @@ var PromptsResource = class {
289
768
  }
290
769
  /**
291
770
  * Get a prompt by ID (returns version with 'latest' tag)
292
- *
293
- * @param promptId - The prompt ID (e.g., 'prm_abc123')
294
- * @param options - Optional settings
295
- * @returns The prompt data
296
- *
297
- * @example
298
- * ```ts
299
- * // Get default (latest) version
300
- * const prompt = await client.prompts.get('prm_abc123');
301
- *
302
- * // Get by specific tag
303
- * const production = await client.prompts.get('prm_abc123', { tag: 'production' });
304
- *
305
- * // Get specific version
306
- * const v2 = await client.prompts.get('prm_abc123', { version: '2.0.0' });
307
- * ```
308
771
  */
309
772
  async get(promptId, options) {
310
773
  if (options?.version) {
@@ -325,38 +788,23 @@ var PromptsResource = class {
325
788
  path: `/api/v1/prompts/${promptId}/tags/${tag}`
326
789
  });
327
790
  }
791
+ async execute(promptId, options) {
792
+ if ("responseClass" in options && options.responseClass) {
793
+ return this.executeTyped(promptId, options);
794
+ }
795
+ return this.executeRaw(promptId, options);
796
+ }
797
+ async executeByTag(promptId, tag, options) {
798
+ return this.execute(promptId, { ...options, tag });
799
+ }
800
+ async executeByVersion(promptId, version, options) {
801
+ return this.execute(promptId, { ...options, version });
802
+ }
328
803
  /**
329
- * Execute a prompt with 'latest' tag
330
- *
331
- * @param promptId - The prompt ID
332
- * @param options - Execution options including provider, model and variables
333
- * @returns The execution response
334
- *
335
- * @example
336
- * ```ts
337
- * const result = await client.prompts.execute('prm_abc123', {
338
- * provider: 'openai',
339
- * model: 'gpt-4o',
340
- * variables: { topic: 'TypeScript' },
341
- * });
342
- *
343
- * if (result.type === 'message') {
344
- * console.log(result.content);
345
- * }
346
- *
347
- * // Image generation
348
- * const imageResult = await client.prompts.execute('prm_image123', {
349
- * provider: 'google',
350
- * model: 'gemini-2.0-flash-exp',
351
- * variables: { style: 'modern' },
352
- * });
353
- *
354
- * if (imageResult.type === 'image') {
355
- * console.log('Generated images:', imageResult.files);
356
- * }
357
- * ```
804
+ * Execute raw request without typed response
805
+ * @throws {ExecutionSynovaError} If LLM returns an error
358
806
  */
359
- async execute(promptId, options) {
807
+ async executeRaw(promptId, options) {
360
808
  const body = {
361
809
  provider: options.provider,
362
810
  model: options.model
@@ -370,79 +818,60 @@ var PromptsResource = class {
370
818
  if (options.metadata !== void 0) body.metadata = options.metadata;
371
819
  if (options.parameters !== void 0) body.parameters = options.parameters;
372
820
  if (options.responseSchema !== void 0) body.responseSchema = options.responseSchema;
373
- return this.http.request({
821
+ if (options.sessionId !== void 0) body.sessionId = options.sessionId;
822
+ const response = await this.http.request({
374
823
  method: "POST",
375
824
  path: `/api/v1/prompts/${promptId}/run`,
376
825
  body
377
826
  });
827
+ if (response.type === "error" && response.error) {
828
+ throw new ExecutionSynovaError(response.error);
829
+ }
830
+ return response;
378
831
  }
379
832
  /**
380
- * Execute a prompt by tag
381
- *
382
- * @param promptId - The prompt ID
383
- * @param tag - The tag (e.g., 'latest', 'production', 'staging')
384
- * @param options - Execution options
385
- * @returns The execution response
386
- *
387
- * @example
388
- * ```ts
389
- * const result = await client.prompts.executeByTag('prm_abc123', 'production', {
390
- * provider: 'openai',
391
- * model: 'gpt-4o',
392
- * variables: { topic: 'TypeScript' },
393
- * });
394
- * ```
833
+ * Execute with typed response class
395
834
  */
396
- async executeByTag(promptId, tag, options) {
397
- return this.http.request({
398
- method: "POST",
399
- path: `/api/v1/prompts/${promptId}/run`,
400
- body: {
401
- tag,
402
- provider: options.provider,
403
- model: options.model,
404
- apiKey: options.apiKey,
405
- azureEndpoint: options.azureEndpoint,
406
- variables: options.variables,
407
- messages: options.messages,
408
- metadata: options.metadata,
409
- parameters: options.parameters
410
- }
835
+ async executeTyped(promptId, options) {
836
+ const { responseClass, validate = true, ...executeOptions } = options;
837
+ const responseSchema = ClassSchema.generate(responseClass);
838
+ const response = await this.executeRaw(promptId, {
839
+ ...executeOptions,
840
+ responseSchema
411
841
  });
842
+ const object = response.object;
843
+ if (validate) {
844
+ await this.validateObject(object, responseClass);
845
+ }
846
+ return object;
412
847
  }
413
848
  /**
414
- * Execute a prompt by version
415
- *
416
- * @param promptId - The prompt ID
417
- * @param version - The semantic version (e.g., '1.0.0', '2.1.0')
418
- * @param options - Execution options
419
- * @returns The execution response
420
- *
421
- * @example
422
- * ```ts
423
- * const result = await client.prompts.executeByVersion('prm_abc123', '1.2.0', {
424
- * provider: 'openai',
425
- * model: 'gpt-4o',
426
- * variables: { topic: 'TypeScript' },
427
- * });
428
- * ```
849
+ * Validate object using class-validator
429
850
  */
430
- async executeByVersion(promptId, version, options) {
431
- return this.http.request({
432
- method: "POST",
433
- path: `/api/v1/prompts/${promptId}/run`,
434
- body: {
435
- version,
436
- provider: options.provider,
437
- model: options.model,
438
- apiKey: options.apiKey,
439
- azureEndpoint: options.azureEndpoint,
440
- variables: options.variables,
441
- messages: options.messages,
442
- metadata: options.metadata,
443
- parameters: options.parameters
851
+ async validateObject(object, responseClass) {
852
+ try {
853
+ const { plainToInstance } = __require("class-transformer");
854
+ const { validate } = __require("class-validator");
855
+ const instance = plainToInstance(responseClass, object);
856
+ const errors = await validate(instance);
857
+ if (errors.length > 0) {
858
+ const violations = errors.map(
859
+ (error) => ({
860
+ property: error.property,
861
+ constraints: error.constraints || {},
862
+ value: error.value
863
+ })
864
+ );
865
+ throw new ValidationSynovaError(violations);
444
866
  }
445
- });
867
+ } catch (error) {
868
+ if (error instanceof ValidationSynovaError) {
869
+ throw error;
870
+ }
871
+ console.warn(
872
+ "[Synova SDK] Validation skipped: class-validator or class-transformer not installed. Install them with: npm install class-validator class-transformer"
873
+ );
874
+ }
446
875
  }
447
876
  };
448
877
 
@@ -574,6 +1003,137 @@ var FilesResource = class {
574
1003
  }
575
1004
  };
576
1005
 
1006
+ // src/resources/spans.ts
1007
+ var SpansResource = class {
1008
+ constructor(http) {
1009
+ this.http = http;
1010
+ }
1011
+ /**
1012
+ * Create a new span within a trace
1013
+ *
1014
+ * @param traceId - The trace ID to create span in
1015
+ * @param options - Span creation options
1016
+ * @returns Created span
1017
+ */
1018
+ async create(traceId, options) {
1019
+ const body = {
1020
+ type: options.type
1021
+ };
1022
+ if (options.parentSpanId !== void 0) body.parentSpanId = options.parentSpanId;
1023
+ if (options.name !== void 0) body.name = options.name;
1024
+ if (options.input !== void 0) body.input = options.input;
1025
+ if (options.toolName !== void 0) body.toolName = options.toolName;
1026
+ if (options.toolArguments !== void 0) body.toolArguments = options.toolArguments;
1027
+ if (options.metadata !== void 0) body.metadata = options.metadata;
1028
+ return this.http.request({
1029
+ method: "POST",
1030
+ path: `/api/v1/traces/${traceId}/spans`,
1031
+ body
1032
+ });
1033
+ }
1034
+ /**
1035
+ * End/complete a span
1036
+ *
1037
+ * @param spanId - The span ID to end
1038
+ * @param options - Span end options
1039
+ * @returns Updated span
1040
+ */
1041
+ async end(spanId, options) {
1042
+ const body = {};
1043
+ if (options?.status !== void 0) body.status = options.status;
1044
+ if (options?.level !== void 0) body.level = options.level;
1045
+ if (options?.statusMessage !== void 0) body.statusMessage = options.statusMessage;
1046
+ if (options?.output !== void 0) body.output = options.output;
1047
+ if (options?.toolResult !== void 0) body.toolResult = options.toolResult;
1048
+ if (options?.durationMs !== void 0) body.durationMs = options.durationMs;
1049
+ return this.http.request({
1050
+ method: "PATCH",
1051
+ path: `/api/v1/spans/${spanId}`,
1052
+ body
1053
+ });
1054
+ }
1055
+ /**
1056
+ * Wrap an async function with automatic span tracking
1057
+ *
1058
+ * @param options - Span options (traceId, type, name, etc.)
1059
+ * @param input - Input data to record in span
1060
+ * @param fn - Async function to execute
1061
+ * @returns Result of the function
1062
+ *
1063
+ * @example
1064
+ * ```ts
1065
+ * const result = await client.spans.wrap(
1066
+ * { traceId: 'trc_123', type: 'retriever', name: 'vector_search' },
1067
+ * { query: 'how to...', topK: 5 },
1068
+ * async () => vectorDb.search(query),
1069
+ * );
1070
+ * ```
1071
+ */
1072
+ async wrap(options, input, fn) {
1073
+ const span = await this.create(options.traceId, {
1074
+ type: options.type,
1075
+ name: options.name,
1076
+ parentSpanId: options.parentSpanId,
1077
+ input,
1078
+ metadata: options.metadata
1079
+ });
1080
+ try {
1081
+ const result = await fn();
1082
+ await this.end(span.id, {
1083
+ status: "completed",
1084
+ output: result
1085
+ });
1086
+ return result;
1087
+ } catch (error) {
1088
+ await this.end(span.id, {
1089
+ status: "error",
1090
+ statusMessage: error instanceof Error ? error.message : String(error)
1091
+ });
1092
+ throw error;
1093
+ }
1094
+ }
1095
+ /**
1096
+ * Wrap a tool function with automatic span tracking
1097
+ *
1098
+ * @param options - Tool span options (traceId, toolName, etc.)
1099
+ * @param args - Tool arguments to record
1100
+ * @param fn - Tool function to execute
1101
+ * @returns Result of the tool
1102
+ *
1103
+ * @example
1104
+ * ```ts
1105
+ * const weather = await client.spans.wrapTool(
1106
+ * { traceId: 'trc_123', toolName: 'fetch_weather', parentSpanId: 'spn_abc' },
1107
+ * { city: 'NYC' },
1108
+ * async (args) => fetchWeather(args.city),
1109
+ * );
1110
+ * ```
1111
+ */
1112
+ async wrapTool(options, args, fn) {
1113
+ const span = await this.create(options.traceId, {
1114
+ type: "tool",
1115
+ toolName: options.toolName,
1116
+ toolArguments: args,
1117
+ parentSpanId: options.parentSpanId,
1118
+ metadata: options.metadata
1119
+ });
1120
+ try {
1121
+ const result = await fn(args);
1122
+ await this.end(span.id, {
1123
+ status: "completed",
1124
+ toolResult: result
1125
+ });
1126
+ return result;
1127
+ } catch (error) {
1128
+ await this.end(span.id, {
1129
+ status: "error",
1130
+ statusMessage: error instanceof Error ? error.message : String(error)
1131
+ });
1132
+ throw error;
1133
+ }
1134
+ }
1135
+ };
1136
+
577
1137
  // src/client.ts
578
1138
  var DEFAULT_BASE_URL = "https://api.synova.cloud";
579
1139
  var DEFAULT_TIMEOUT = 3e4;
@@ -594,6 +1154,7 @@ var SynovaCloudSdk = class {
594
1154
  prompts;
595
1155
  models;
596
1156
  files;
1157
+ spans;
597
1158
  http;
598
1159
  /**
599
1160
  * Create a new Synova Cloud SDK client
@@ -622,9 +1183,10 @@ var SynovaCloudSdk = class {
622
1183
  this.prompts = new PromptsResource(this.http);
623
1184
  this.models = new ModelsResource(this.http);
624
1185
  this.files = new FilesResource(this.http);
1186
+ this.spans = new SpansResource(this.http);
625
1187
  }
626
1188
  };
627
1189
 
628
- export { ApiSynovaError, AuthSynovaError, NetworkSynovaError, NotFoundSynovaError, RateLimitSynovaError, ServerSynovaError, SynovaCloudSdk, SynovaError, TimeoutSynovaError };
1190
+ export { ApiSynovaError, ArrayItems, AuthSynovaError, ClassSchema, Default, Description, Example, ExclusiveMax, ExclusiveMin, ExecutionSynovaError, Format, MultipleOf, NetworkSynovaError, NotFoundSynovaError, Nullable, RateLimitSynovaError, SCHEMA_METADATA_KEYS, SchemaEnum, SchemaMax, SchemaMaxItems, SchemaMaxLength, SchemaMin, SchemaMinItems, SchemaMinLength, SchemaPattern, SchemaUniqueItems, ServerSynovaError, SynovaCloudSdk, SynovaError, TimeoutSynovaError, ValidationSynovaError };
629
1191
  //# sourceMappingURL=index.js.map
630
1192
  //# sourceMappingURL=index.js.map