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