@synova-cloud/sdk 1.7.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/README.md +122 -2
- package/dist/index.cjs +135 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +205 -3
- package/dist/index.d.ts +205 -3
- package/dist/index.js +135 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -263,6 +263,116 @@ const topic = await client.prompts.execute('prm_abc123', {
|
|
|
263
263
|
| `@SchemaMaxItems(n)` | Maximum array length |
|
|
264
264
|
| `@SchemaEnum(values)` | Allowed enum values |
|
|
265
265
|
|
|
266
|
+
### Observability
|
|
267
|
+
|
|
268
|
+
Track and group your LLM calls using traces and spans. Each execution creates a span, and multiple spans can be grouped into a trace using `sessionId`.
|
|
269
|
+
|
|
270
|
+
#### Session-Based Tracing
|
|
271
|
+
|
|
272
|
+
Use `sessionId` to group related calls (e.g., a conversation) into a single trace:
|
|
273
|
+
|
|
274
|
+
```typescript
|
|
275
|
+
const sessionId = 'chat_user123_conv1';
|
|
276
|
+
|
|
277
|
+
// First message - creates new trace
|
|
278
|
+
const response1 = await client.prompts.execute('prm_abc123', {
|
|
279
|
+
provider: 'openai',
|
|
280
|
+
model: 'gpt-4o',
|
|
281
|
+
sessionId,
|
|
282
|
+
variables: { topic: 'TypeScript' },
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
console.log(response1.traceId); // trc_xxx
|
|
286
|
+
console.log(response1.spanId); // spn_xxx
|
|
287
|
+
|
|
288
|
+
// Follow-up - same sessionId = same trace, new span
|
|
289
|
+
const response2 = await client.prompts.execute('prm_abc123', {
|
|
290
|
+
provider: 'openai',
|
|
291
|
+
model: 'gpt-4o',
|
|
292
|
+
sessionId,
|
|
293
|
+
messages: [
|
|
294
|
+
{ role: 'assistant', content: response1.content },
|
|
295
|
+
{ role: 'user', content: 'Tell me more' },
|
|
296
|
+
],
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
// response2.traceId === response1.traceId (same trace)
|
|
300
|
+
// response2.spanId !== response1.spanId (new span)
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
#### Response Properties
|
|
304
|
+
|
|
305
|
+
Every execution returns observability IDs:
|
|
306
|
+
|
|
307
|
+
| Property | Type | Description |
|
|
308
|
+
|----------|------|-------------|
|
|
309
|
+
| `spanDataId` | `string` | Execution data ID (messages, response, usage) |
|
|
310
|
+
| `traceId` | `string` | Trace ID (groups related calls) |
|
|
311
|
+
| `spanId` | `string` | Span ID (this specific call) |
|
|
312
|
+
|
|
313
|
+
#### Custom Span Tracking
|
|
314
|
+
|
|
315
|
+
Track tool calls, retrieval operations, and custom logic as spans within a trace.
|
|
316
|
+
|
|
317
|
+
**Manual approach:**
|
|
318
|
+
|
|
319
|
+
```typescript
|
|
320
|
+
// Create span
|
|
321
|
+
const span = await client.spans.create(traceId, {
|
|
322
|
+
type: 'tool',
|
|
323
|
+
toolName: 'fetch_weather',
|
|
324
|
+
toolArguments: { city: 'NYC' },
|
|
325
|
+
parentSpanId: generationSpanId,
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
// Execute
|
|
329
|
+
const weather = await fetchWeather('NYC');
|
|
330
|
+
|
|
331
|
+
// End span
|
|
332
|
+
await client.spans.end(span.id, {
|
|
333
|
+
status: 'completed',
|
|
334
|
+
toolResult: weather,
|
|
335
|
+
});
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
**Wrapper approach:**
|
|
339
|
+
|
|
340
|
+
```typescript
|
|
341
|
+
// wrapTool() - for tools
|
|
342
|
+
const weather = await client.spans.wrapTool(
|
|
343
|
+
{ traceId, toolName: 'fetch_weather', parentSpanId },
|
|
344
|
+
{ city: 'NYC' },
|
|
345
|
+
async (args) => fetchWeather(args.city),
|
|
346
|
+
);
|
|
347
|
+
|
|
348
|
+
// wrap() - for custom/retriever/embedding
|
|
349
|
+
const docs = await client.spans.wrap(
|
|
350
|
+
{ traceId, type: 'retriever', name: 'vector_search' },
|
|
351
|
+
{ query: 'how to...', topK: 5 },
|
|
352
|
+
async () => vectorDb.search(query),
|
|
353
|
+
);
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
Wrappers automatically handle errors and set `status: 'error'` with message.
|
|
357
|
+
|
|
358
|
+
#### Span Types
|
|
359
|
+
|
|
360
|
+
| Type | Use Case |
|
|
361
|
+
|------|----------|
|
|
362
|
+
| `generation` | LLM calls (auto-created by `execute()`) |
|
|
363
|
+
| `tool` | Tool/function calls |
|
|
364
|
+
| `retriever` | RAG document retrieval |
|
|
365
|
+
| `embedding` | Embedding generation |
|
|
366
|
+
| `custom` | Any custom operation |
|
|
367
|
+
|
|
368
|
+
#### Viewing Traces
|
|
369
|
+
|
|
370
|
+
View your traces in the [Synova Cloud Dashboard](https://app.synova.cloud) under the Observability section. Each trace shows:
|
|
371
|
+
- All spans (LLM calls) in the session
|
|
372
|
+
- Input/output for each span
|
|
373
|
+
- Token usage and latency
|
|
374
|
+
- Error details if any
|
|
375
|
+
|
|
266
376
|
### Models
|
|
267
377
|
|
|
268
378
|
#### List All Models
|
|
@@ -519,15 +629,25 @@ import type {
|
|
|
519
629
|
ISynovaPromptVariable,
|
|
520
630
|
ISynovaGetPromptOptions,
|
|
521
631
|
// Execution
|
|
522
|
-
ISynovaExecuteOptions,
|
|
632
|
+
ISynovaExecuteOptions, // includes sessionId
|
|
523
633
|
ISynovaExecuteTypedOptions,
|
|
524
|
-
ISynovaExecuteResponse,
|
|
634
|
+
ISynovaExecuteResponse, // includes spanDataId, traceId, spanId
|
|
525
635
|
ISynovaExecutionUsage,
|
|
526
636
|
ISynovaExecutionError,
|
|
527
637
|
// Messages
|
|
528
638
|
ISynovaMessage,
|
|
529
639
|
TSynovaMessageRole,
|
|
530
640
|
TSynovaResponseType,
|
|
641
|
+
// Spans
|
|
642
|
+
ISynovaSpan,
|
|
643
|
+
ISynovaSpanData,
|
|
644
|
+
ISynovaCreateSpanOptions,
|
|
645
|
+
ISynovaEndSpanOptions,
|
|
646
|
+
ISynovaWrapOptions,
|
|
647
|
+
ISynovaWrapToolOptions,
|
|
648
|
+
TSynovaSpanType,
|
|
649
|
+
TSynovaSpanStatus,
|
|
650
|
+
TSynovaSpanLevel,
|
|
531
651
|
// Files
|
|
532
652
|
ISynovaFileAttachment,
|
|
533
653
|
ISynovaFileThumbnails,
|
package/dist/index.cjs
CHANGED
|
@@ -107,7 +107,7 @@ var ValidationSynovaError = class extends SynovaError {
|
|
|
107
107
|
};
|
|
108
108
|
|
|
109
109
|
// src/version.ts
|
|
110
|
-
var SDK_VERSION = "1.
|
|
110
|
+
var SDK_VERSION = "1.8.0" ;
|
|
111
111
|
|
|
112
112
|
// src/utils/http.ts
|
|
113
113
|
var HttpClient = class {
|
|
@@ -820,6 +820,7 @@ var PromptsResource = class {
|
|
|
820
820
|
if (options.metadata !== void 0) body.metadata = options.metadata;
|
|
821
821
|
if (options.parameters !== void 0) body.parameters = options.parameters;
|
|
822
822
|
if (options.responseSchema !== void 0) body.responseSchema = options.responseSchema;
|
|
823
|
+
if (options.sessionId !== void 0) body.sessionId = options.sessionId;
|
|
823
824
|
const response = await this.http.request({
|
|
824
825
|
method: "POST",
|
|
825
826
|
path: `/api/v1/prompts/${promptId}/run`,
|
|
@@ -1004,6 +1005,137 @@ var FilesResource = class {
|
|
|
1004
1005
|
}
|
|
1005
1006
|
};
|
|
1006
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
|
+
|
|
1007
1139
|
// src/client.ts
|
|
1008
1140
|
var DEFAULT_BASE_URL = "https://api.synova.cloud";
|
|
1009
1141
|
var DEFAULT_TIMEOUT = 3e4;
|
|
@@ -1024,6 +1156,7 @@ var SynovaCloudSdk = class {
|
|
|
1024
1156
|
prompts;
|
|
1025
1157
|
models;
|
|
1026
1158
|
files;
|
|
1159
|
+
spans;
|
|
1027
1160
|
http;
|
|
1028
1161
|
/**
|
|
1029
1162
|
* Create a new Synova Cloud SDK client
|
|
@@ -1052,6 +1185,7 @@ var SynovaCloudSdk = class {
|
|
|
1052
1185
|
this.prompts = new PromptsResource(this.http);
|
|
1053
1186
|
this.models = new ModelsResource(this.http);
|
|
1054
1187
|
this.files = new FilesResource(this.http);
|
|
1188
|
+
this.spans = new SpansResource(this.http);
|
|
1055
1189
|
}
|
|
1056
1190
|
};
|
|
1057
1191
|
|