@grafana/sigil-sdk-js 0.5.0 → 0.6.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 +9 -3
- package/dist/cache-diagnostics.d.ts +15 -0
- package/dist/cache-diagnostics.d.ts.map +1 -0
- package/dist/cache-diagnostics.js +15 -0
- package/dist/cache-diagnostics.js.map +1 -0
- package/dist/client.d.ts +5 -4
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +172 -53
- package/dist/client.js.map +1 -1
- package/dist/config.js +1 -1
- package/dist/config.js.map +1 -1
- package/dist/content_capture.d.ts +3 -4
- package/dist/content_capture.d.ts.map +1 -1
- package/dist/content_capture.js +7 -9
- package/dist/content_capture.js.map +1 -1
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +29 -2
- package/dist/context.js.map +1 -1
- package/dist/core.d.ts +13 -0
- package/dist/core.d.ts.map +1 -0
- package/dist/core.js +12 -0
- package/dist/core.js.map +1 -0
- package/dist/exporters/http.js +6 -1
- package/dist/exporters/http.js.map +1 -1
- package/dist/frameworks/vercel-ai-sdk/hooks.d.ts.map +1 -1
- package/dist/frameworks/vercel-ai-sdk/hooks.js +70 -39
- package/dist/frameworks/vercel-ai-sdk/hooks.js.map +1 -1
- package/dist/frameworks/vercel-ai-sdk/index.d.ts +1 -1
- package/dist/frameworks/vercel-ai-sdk/index.d.ts.map +1 -1
- package/dist/frameworks/vercel-ai-sdk/index.js +1 -1
- package/dist/frameworks/vercel-ai-sdk/index.js.map +1 -1
- package/dist/frameworks/vercel-ai-sdk/mapping.d.ts +9 -1
- package/dist/frameworks/vercel-ai-sdk/mapping.d.ts.map +1 -1
- package/dist/frameworks/vercel-ai-sdk/mapping.js +56 -0
- package/dist/frameworks/vercel-ai-sdk/mapping.js.map +1 -1
- package/dist/frameworks/vercel-ai-sdk/types.d.ts +6 -0
- package/dist/frameworks/vercel-ai-sdk/types.d.ts.map +1 -1
- package/dist/hooks.js +4 -1
- package/dist/hooks.js.map +1 -1
- package/dist/index.d.ts +1 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -10
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +13 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +13 -2
- package/dist/utils.js.map +1 -1
- package/package.json +9 -9
package/README.md
CHANGED
|
@@ -8,6 +8,12 @@ Sigil records normalized LLM generation and tool-execution telemetry using your
|
|
|
8
8
|
pnpm add @grafana/sigil-sdk-js
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
+
For low-dependency runtimes that only need the core `SigilClient` and generation export APIs, use the slim core package:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pnpm add @grafana/sigil-sdk-js-core
|
|
15
|
+
```
|
|
16
|
+
|
|
11
17
|
For a Grafana Cloud setup walkthrough (where to find the endpoint URL, instance ID, and API token), refer to the [Grafana Cloud setup guide](https://grafana.com/docs/grafana-cloud/machine-learning/ai-observability/get-started/grafana-cloud/).
|
|
12
18
|
|
|
13
19
|
## Validation
|
|
@@ -368,12 +374,12 @@ auth: {
|
|
|
368
374
|
},
|
|
369
375
|
```
|
|
370
376
|
|
|
371
|
-
##
|
|
377
|
+
## Wiring custom env vars
|
|
372
378
|
|
|
373
|
-
The SDK
|
|
379
|
+
The SDK only auto-loads `SIGIL_*` env vars (`SIGIL_ENDPOINT`, `SIGIL_PROTOCOL`, `SIGIL_AUTH_MODE`, `SIGIL_AUTH_TOKEN`, etc.) when you call `new SigilClient()`. For any other env var (for example one your secret manager exposes under a different name), read it in your app and pass the value into the config:
|
|
374
380
|
|
|
375
381
|
```ts
|
|
376
|
-
const generationBearerToken = (process.env.
|
|
382
|
+
const generationBearerToken = (process.env.MY_APP_SIGIL_TOKEN ?? "").trim();
|
|
377
383
|
|
|
378
384
|
const client = new SigilClient({
|
|
379
385
|
generationExport: {
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { GenerationRecorder } from './types.js';
|
|
2
|
+
/** Reserved generation metadata keys (Sigil docs/guides/cache-diagnostics.md). */
|
|
3
|
+
export declare const CACHE_DIAGNOSTICS_MISS_REASON_KEY = "sigil.cache_diagnostics.miss_reason";
|
|
4
|
+
export declare const CACHE_DIAGNOSTICS_MISSED_INPUT_TOKENS_KEY = "sigil.cache_diagnostics.missed_input_tokens";
|
|
5
|
+
export declare const CACHE_DIAGNOSTICS_PREVIOUS_MESSAGE_ID_KEY = "sigil.cache_diagnostics.previous_message_id";
|
|
6
|
+
export type CacheDiagnosticsOptions = {
|
|
7
|
+
missedInputTokens?: number;
|
|
8
|
+
previousMessageId?: string;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Stamp `sigil.cache_diagnostics.*` metadata on a generation recorder.
|
|
12
|
+
* Call before `end()`, typically after the provider response is available.
|
|
13
|
+
*/
|
|
14
|
+
export declare function setCacheDiagnostics(rec: GenerationRecorder | null | undefined, missReason: string, opts?: CacheDiagnosticsOptions): void;
|
|
15
|
+
//# sourceMappingURL=cache-diagnostics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache-diagnostics.d.ts","sourceRoot":"","sources":["../src/cache-diagnostics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD,kFAAkF;AAClF,eAAO,MAAM,iCAAiC,wCAAwC,CAAC;AACvF,eAAO,MAAM,yCAAyC,gDAAgD,CAAC;AACvG,eAAO,MAAM,yCAAyC,gDAAgD,CAAC;AAEvG,MAAM,MAAM,uBAAuB,GAAG;IACpC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,kBAAkB,GAAG,IAAI,GAAG,SAAS,EAC1C,UAAU,EAAE,MAAM,EAClB,IAAI,CAAC,EAAE,uBAAuB,GAC7B,IAAI,CAKN"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Reserved generation metadata keys (Sigil docs/guides/cache-diagnostics.md). */
|
|
2
|
+
export const CACHE_DIAGNOSTICS_MISS_REASON_KEY = 'sigil.cache_diagnostics.miss_reason';
|
|
3
|
+
export const CACHE_DIAGNOSTICS_MISSED_INPUT_TOKENS_KEY = 'sigil.cache_diagnostics.missed_input_tokens';
|
|
4
|
+
export const CACHE_DIAGNOSTICS_PREVIOUS_MESSAGE_ID_KEY = 'sigil.cache_diagnostics.previous_message_id';
|
|
5
|
+
/**
|
|
6
|
+
* Stamp `sigil.cache_diagnostics.*` metadata on a generation recorder.
|
|
7
|
+
* Call before `end()`, typically after the provider response is available.
|
|
8
|
+
*/
|
|
9
|
+
export function setCacheDiagnostics(rec, missReason, opts) {
|
|
10
|
+
if (rec === null || rec === undefined) {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
rec.setCacheDiagnostics(missReason, opts);
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=cache-diagnostics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache-diagnostics.js","sourceRoot":"","sources":["../src/cache-diagnostics.ts"],"names":[],"mappings":"AAEA,kFAAkF;AAClF,MAAM,CAAC,MAAM,iCAAiC,GAAG,qCAAqC,CAAC;AACvF,MAAM,CAAC,MAAM,yCAAyC,GAAG,6CAA6C,CAAC;AACvG,MAAM,CAAC,MAAM,yCAAyC,GAAG,6CAA6C,CAAC;AAOvG;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CACjC,GAA0C,EAC1C,UAAkB,EAClB,IAA8B;IAE9B,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACtC,OAAO;IACT,CAAC;IACD,GAAG,CAAC,mBAAmB,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;AAC5C,CAAC"}
|
package/dist/client.d.ts
CHANGED
|
@@ -108,18 +108,19 @@ export declare class SigilClient {
|
|
|
108
108
|
internalEnqueueGeneration(generation: Generation): void;
|
|
109
109
|
internalLogWarn(message: string, error?: unknown): void;
|
|
110
110
|
internalResolveGenerationContentCaptureMode(seed: GenerationStart): ContentCaptureMode;
|
|
111
|
-
|
|
111
|
+
internalResolveEmbeddingContentCaptureMode(seed: EmbeddingStart): ContentCaptureMode;
|
|
112
|
+
internalResolveToolContentCaptureMode(seed: ToolExecutionStart): ContentCaptureMode;
|
|
112
113
|
internalHasGenerationSanitizer(): boolean;
|
|
113
114
|
internalSanitizeGeneration(generation: Generation): Generation;
|
|
114
|
-
internalStartGenerationSpan(seed: GenerationStart, mode: GenerationMode, startedAt: Date): Span;
|
|
115
|
+
internalStartGenerationSpan(seed: GenerationStart, mode: GenerationMode, startedAt: Date, contentCaptureMode: ContentCaptureMode): Span;
|
|
115
116
|
internalStartEmbeddingSpan(seed: EmbeddingStart, startedAt: Date): Span;
|
|
116
117
|
internalStartToolExecutionSpan(seed: ToolExecutionStart, startedAt: Date): Span;
|
|
117
118
|
internalApplyTraceContextFromSpan(span: Span, generation: Generation): void;
|
|
118
119
|
internalSyncGenerationSpan(span: Span, generation: Generation): void;
|
|
119
120
|
internalClearSpanConversationTitle(span: Span): void;
|
|
120
121
|
internalFinalizeGenerationSpan(span: Span, generation: Generation, callError: string | undefined, validationError: Error | undefined, enqueueError: Error | undefined, firstTokenAt: Date | undefined, precomputedCallErrorCategory?: string): void;
|
|
121
|
-
internalFinalizeEmbeddingSpan(span: Span, seed: EmbeddingStart, result: EmbeddingResult, hasResult: boolean, callError: Error | undefined, localError: Error | undefined, startedAt: Date, completedAt: Date): void;
|
|
122
|
-
internalFinalizeToolExecutionSpan(span: Span, toolExecution: ToolExecution, localError: Error | undefined): Error | undefined;
|
|
122
|
+
internalFinalizeEmbeddingSpan(span: Span, seed: EmbeddingStart, result: EmbeddingResult, hasResult: boolean, callError: Error | undefined, localError: Error | undefined, startedAt: Date, completedAt: Date, contentCaptureMode?: ContentCaptureMode): void;
|
|
123
|
+
internalFinalizeToolExecutionSpan(span: Span, toolExecution: ToolExecution, localError: Error | undefined, contentCaptureMode?: ContentCaptureMode): Error | undefined;
|
|
123
124
|
private recordGenerationMetrics;
|
|
124
125
|
private recordEmbeddingMetrics;
|
|
125
126
|
private recordTokenUsage;
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/client.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { metrics, SpanKind, SpanStatusCode, trace, } from '@opentelemetry/api';
|
|
1
|
+
import { context, metrics, SpanKind, SpanStatusCode, trace, } from '@opentelemetry/api';
|
|
2
|
+
import { CACHE_DIAGNOSTICS_MISS_REASON_KEY, CACHE_DIAGNOSTICS_MISSED_INPUT_TOKENS_KEY, CACHE_DIAGNOSTICS_PREVIOUS_MESSAGE_ID_KEY, } from './cache-diagnostics.js';
|
|
2
3
|
import { defaultLogger, mergeConfig } from './config.js';
|
|
3
4
|
import { callContentCaptureResolver, resolveClientContentCaptureMode, resolveContentCaptureMode, shouldIncludeToolContent, stampContentCaptureMetadata, stripContent, } from './content_capture.js';
|
|
4
5
|
import { agentNameFromContext, agentVersionFromContext, conversationIdFromContext, conversationTitleFromContext, userIdFromContext, } from './context.js';
|
|
@@ -449,9 +450,16 @@ export class SigilClient {
|
|
|
449
450
|
const clientMode = resolveClientContentCaptureMode(resolveContentCaptureMode(resolverMode, this.config.contentCapture));
|
|
450
451
|
return resolveContentCaptureMode(seed.contentCapture ?? 'default', clientMode);
|
|
451
452
|
}
|
|
452
|
-
|
|
453
|
+
internalResolveEmbeddingContentCaptureMode(seed) {
|
|
454
|
+
// Mirror generation resolution so a per-call resolver can hide
|
|
455
|
+
// gen_ai.embeddings.input_texts without changing the client default.
|
|
456
|
+
const resolverMode = callContentCaptureResolver(this.config.contentCaptureResolver, seed.metadata);
|
|
457
|
+
return resolveClientContentCaptureMode(resolveContentCaptureMode(resolverMode, this.config.contentCapture));
|
|
458
|
+
}
|
|
459
|
+
internalResolveToolContentCaptureMode(seed) {
|
|
453
460
|
const resolverMode = callContentCaptureResolver(this.config.contentCaptureResolver, undefined);
|
|
454
|
-
|
|
461
|
+
const clientMode = resolveClientContentCaptureMode(resolveContentCaptureMode(resolverMode, this.config.contentCapture));
|
|
462
|
+
return resolveContentCaptureMode(seed.contentCapture ?? 'default', clientMode);
|
|
455
463
|
}
|
|
456
464
|
internalHasGenerationSanitizer() {
|
|
457
465
|
return this.config.generationSanitizer !== undefined;
|
|
@@ -467,16 +475,23 @@ export class SigilClient {
|
|
|
467
475
|
}
|
|
468
476
|
return cloneGeneration(sanitized);
|
|
469
477
|
}
|
|
470
|
-
internalStartGenerationSpan(seed, mode, startedAt) {
|
|
478
|
+
internalStartGenerationSpan(seed, mode, startedAt, contentCaptureMode) {
|
|
471
479
|
const operationName = seed.operationName ?? defaultOperationNameForMode(mode);
|
|
472
480
|
const span = this.tracer.startSpan(generationSpanName(operationName, seed.model.name), {
|
|
473
481
|
kind: SpanKind.CLIENT,
|
|
474
482
|
startTime: startedAt,
|
|
475
483
|
});
|
|
484
|
+
// metadata_only and full_with_metadata_spans both drop the title from
|
|
485
|
+
// the span. Under full_with_metadata_spans the proto payload still
|
|
486
|
+
// carries the title — it is rebuilt from `seed.conversationTitle` in
|
|
487
|
+
// end(), so we only zero the value sent to the span here.
|
|
488
|
+
const spanTitle = contentCaptureMode === 'metadata_only' || contentCaptureMode === 'full_with_metadata_spans'
|
|
489
|
+
? undefined
|
|
490
|
+
: seed.conversationTitle;
|
|
476
491
|
setGenerationSpanAttributes(span, {
|
|
477
492
|
id: seed.id,
|
|
478
493
|
conversationId: seed.conversationId,
|
|
479
|
-
conversationTitle:
|
|
494
|
+
conversationTitle: spanTitle,
|
|
480
495
|
userId: seed.userId,
|
|
481
496
|
agentName: seed.agentName,
|
|
482
497
|
agentVersion: seed.agentVersion,
|
|
@@ -559,16 +574,23 @@ export class SigilClient {
|
|
|
559
574
|
else {
|
|
560
575
|
span.setStatus({ code: SpanStatusCode.OK });
|
|
561
576
|
}
|
|
562
|
-
|
|
577
|
+
const spanCtx = trace.setSpan(context.active(), span);
|
|
578
|
+
context.with(spanCtx, () => {
|
|
579
|
+
this.recordGenerationMetrics(generation, errorType, errorCategory, firstTokenAt);
|
|
580
|
+
});
|
|
563
581
|
span.end(generation.completedAt);
|
|
564
582
|
}
|
|
565
|
-
internalFinalizeEmbeddingSpan(span, seed, result, hasResult, callError, localError, startedAt, completedAt) {
|
|
583
|
+
internalFinalizeEmbeddingSpan(span, seed, result, hasResult, callError, localError, startedAt, completedAt, contentCaptureMode = 'default') {
|
|
566
584
|
span.updateName(embeddingSpanName(seed.model.name));
|
|
567
|
-
setEmbeddingEndSpanAttributes(span, result, hasResult, this.config.embeddingCapture);
|
|
568
|
-
|
|
585
|
+
setEmbeddingEndSpanAttributes(span, result, hasResult, this.config.embeddingCapture, contentCaptureMode);
|
|
586
|
+
// Redact span-side error text under both stripped modes. Embeddings have
|
|
587
|
+
// no proto export, so the raw provider error never escapes the span
|
|
588
|
+
// path; matches the generation full_with_metadata_spans contract.
|
|
589
|
+
const redactSpanErrors = contentCaptureMode === 'metadata_only' || contentCaptureMode === 'full_with_metadata_spans';
|
|
590
|
+
if (callError !== undefined && !redactSpanErrors) {
|
|
569
591
|
span.recordException(callError);
|
|
570
592
|
}
|
|
571
|
-
if (localError !== undefined) {
|
|
593
|
+
if (localError !== undefined && !redactSpanErrors) {
|
|
572
594
|
span.recordException(localError);
|
|
573
595
|
}
|
|
574
596
|
let errorType = '';
|
|
@@ -576,12 +598,18 @@ export class SigilClient {
|
|
|
576
598
|
if (callError !== undefined) {
|
|
577
599
|
errorType = 'provider_call_error';
|
|
578
600
|
errorCategory = errorCategoryFromError(callError, true);
|
|
579
|
-
span.setStatus({
|
|
601
|
+
span.setStatus({
|
|
602
|
+
code: SpanStatusCode.ERROR,
|
|
603
|
+
message: redactSpanErrors ? errorCategory : callError.message,
|
|
604
|
+
});
|
|
580
605
|
}
|
|
581
606
|
else if (localError !== undefined) {
|
|
582
607
|
errorType = 'validation_error';
|
|
583
608
|
errorCategory = 'sdk_error';
|
|
584
|
-
span.setStatus({
|
|
609
|
+
span.setStatus({
|
|
610
|
+
code: SpanStatusCode.ERROR,
|
|
611
|
+
message: redactSpanErrors ? errorCategory : localError.message,
|
|
612
|
+
});
|
|
585
613
|
}
|
|
586
614
|
else {
|
|
587
615
|
span.setStatus({ code: SpanStatusCode.OK });
|
|
@@ -590,10 +618,13 @@ export class SigilClient {
|
|
|
590
618
|
span.setAttribute(spanAttrErrorType, errorType);
|
|
591
619
|
span.setAttribute(spanAttrErrorCategory, errorCategory);
|
|
592
620
|
}
|
|
593
|
-
|
|
621
|
+
const spanCtx = trace.setSpan(context.active(), span);
|
|
622
|
+
context.with(spanCtx, () => {
|
|
623
|
+
this.recordEmbeddingMetrics(seed, result, startedAt, completedAt, errorType, errorCategory);
|
|
624
|
+
});
|
|
594
625
|
span.end(completedAt);
|
|
595
626
|
}
|
|
596
|
-
internalFinalizeToolExecutionSpan(span, toolExecution, localError) {
|
|
627
|
+
internalFinalizeToolExecutionSpan(span, toolExecution, localError, contentCaptureMode = 'default') {
|
|
597
628
|
setToolSpanAttributes(span, toolExecution);
|
|
598
629
|
if (toolExecution.includeContent) {
|
|
599
630
|
const argumentsResult = serializeToolContent(toolExecution.arguments);
|
|
@@ -611,22 +642,41 @@ export class SigilClient {
|
|
|
611
642
|
span.setAttribute(spanAttrToolCallResult, resultValue.value);
|
|
612
643
|
}
|
|
613
644
|
}
|
|
645
|
+
// Tools have no proto export; under both stripped modes the span must
|
|
646
|
+
// not echo raw provider exception text via recordException events or the
|
|
647
|
+
// status description.
|
|
648
|
+
const redactSpanErrors = contentCaptureMode === 'metadata_only' || contentCaptureMode === 'full_with_metadata_spans';
|
|
614
649
|
if (toolExecution.callError !== undefined) {
|
|
615
|
-
|
|
650
|
+
const errorCategory = errorCategoryFromError(toolExecution.callError, true);
|
|
651
|
+
if (!redactSpanErrors) {
|
|
652
|
+
span.recordException(new Error(toolExecution.callError));
|
|
653
|
+
}
|
|
616
654
|
span.setAttribute(spanAttrErrorType, 'tool_execution_error');
|
|
617
|
-
span.setAttribute(spanAttrErrorCategory,
|
|
618
|
-
span.setStatus({
|
|
655
|
+
span.setAttribute(spanAttrErrorCategory, errorCategory);
|
|
656
|
+
span.setStatus({
|
|
657
|
+
code: SpanStatusCode.ERROR,
|
|
658
|
+
message: redactSpanErrors ? errorCategory : toolExecution.callError,
|
|
659
|
+
});
|
|
619
660
|
}
|
|
620
661
|
else if (localError !== undefined) {
|
|
621
|
-
|
|
662
|
+
const errorCategory = errorCategoryFromError(localError, true);
|
|
663
|
+
if (!redactSpanErrors) {
|
|
664
|
+
span.recordException(localError);
|
|
665
|
+
}
|
|
622
666
|
span.setAttribute(spanAttrErrorType, 'tool_execution_error');
|
|
623
|
-
span.setAttribute(spanAttrErrorCategory,
|
|
624
|
-
span.setStatus({
|
|
667
|
+
span.setAttribute(spanAttrErrorCategory, errorCategory);
|
|
668
|
+
span.setStatus({
|
|
669
|
+
code: SpanStatusCode.ERROR,
|
|
670
|
+
message: redactSpanErrors ? errorCategory : localError.message,
|
|
671
|
+
});
|
|
625
672
|
}
|
|
626
673
|
else {
|
|
627
674
|
span.setStatus({ code: SpanStatusCode.OK });
|
|
628
675
|
}
|
|
629
|
-
|
|
676
|
+
const spanCtx = trace.setSpan(context.active(), span);
|
|
677
|
+
context.with(spanCtx, () => {
|
|
678
|
+
this.recordToolExecutionMetrics(toolExecution, localError ?? (toolExecution.callError !== undefined ? new Error(toolExecution.callError) : undefined));
|
|
679
|
+
});
|
|
630
680
|
span.end(toolExecution.completedAt);
|
|
631
681
|
return localError;
|
|
632
682
|
}
|
|
@@ -634,11 +684,10 @@ export class SigilClient {
|
|
|
634
684
|
const startedMs = generation.startedAt.getTime();
|
|
635
685
|
const completedMs = generation.completedAt.getTime();
|
|
636
686
|
const durationSeconds = Math.max(0, (completedMs - startedMs) / 1_000);
|
|
687
|
+
const identityAttributes = metricIdentityAttributes(generation.model.provider, generation.model.name, generation.agentName, generation.agentVersion);
|
|
637
688
|
this.operationDurationHistogram.record(durationSeconds, {
|
|
638
689
|
[spanAttrOperationName]: generation.operationName,
|
|
639
|
-
|
|
640
|
-
[spanAttrRequestModel]: generation.model.name,
|
|
641
|
-
[spanAttrAgentName]: generation.agentName ?? '',
|
|
690
|
+
...identityAttributes,
|
|
642
691
|
[spanAttrErrorType]: errorType,
|
|
643
692
|
[spanAttrErrorCategory]: errorCategory,
|
|
644
693
|
});
|
|
@@ -651,37 +700,30 @@ export class SigilClient {
|
|
|
651
700
|
this.recordTokenUsage(generation, metricTokenTypeReasoning, usage.reasoningTokens);
|
|
652
701
|
}
|
|
653
702
|
this.toolCallsHistogram.record(countToolCallParts(generation.output ?? []), {
|
|
654
|
-
|
|
655
|
-
[spanAttrRequestModel]: generation.model.name,
|
|
656
|
-
[spanAttrAgentName]: generation.agentName ?? '',
|
|
703
|
+
...identityAttributes,
|
|
657
704
|
});
|
|
658
705
|
if (generation.operationName === 'streamText' && firstTokenAt !== undefined) {
|
|
659
706
|
const ttftSeconds = (firstTokenAt.getTime() - startedMs) / 1_000;
|
|
660
707
|
if (ttftSeconds >= 0) {
|
|
661
708
|
this.ttftHistogram.record(ttftSeconds, {
|
|
662
|
-
|
|
663
|
-
[spanAttrRequestModel]: generation.model.name,
|
|
664
|
-
[spanAttrAgentName]: generation.agentName ?? '',
|
|
709
|
+
...identityAttributes,
|
|
665
710
|
});
|
|
666
711
|
}
|
|
667
712
|
}
|
|
668
713
|
}
|
|
669
714
|
recordEmbeddingMetrics(seed, result, startedAt, completedAt, errorType, errorCategory) {
|
|
670
715
|
const durationSeconds = Math.max(0, (completedAt.getTime() - startedAt.getTime()) / 1_000);
|
|
716
|
+
const identityAttributes = metricIdentityAttributes(seed.model.provider, seed.model.name, seed.agentName, seed.agentVersion);
|
|
671
717
|
this.operationDurationHistogram.record(durationSeconds, {
|
|
672
718
|
[spanAttrOperationName]: defaultEmbeddingOperationName,
|
|
673
|
-
|
|
674
|
-
[spanAttrRequestModel]: seed.model.name,
|
|
675
|
-
[spanAttrAgentName]: seed.agentName ?? '',
|
|
719
|
+
...identityAttributes,
|
|
676
720
|
[spanAttrErrorType]: errorType,
|
|
677
721
|
[spanAttrErrorCategory]: errorCategory,
|
|
678
722
|
});
|
|
679
723
|
if (result.inputTokens !== undefined && result.inputTokens !== 0) {
|
|
680
724
|
this.tokenUsageHistogram.record(result.inputTokens, {
|
|
681
725
|
[spanAttrOperationName]: defaultEmbeddingOperationName,
|
|
682
|
-
|
|
683
|
-
[spanAttrRequestModel]: seed.model.name,
|
|
684
|
-
[spanAttrAgentName]: seed.agentName ?? '',
|
|
726
|
+
...identityAttributes,
|
|
685
727
|
[metricAttrTokenType]: metricTokenTypeInput,
|
|
686
728
|
});
|
|
687
729
|
}
|
|
@@ -692,9 +734,7 @@ export class SigilClient {
|
|
|
692
734
|
}
|
|
693
735
|
this.tokenUsageHistogram.record(value, {
|
|
694
736
|
[spanAttrOperationName]: generation.operationName,
|
|
695
|
-
|
|
696
|
-
[spanAttrRequestModel]: generation.model.name,
|
|
697
|
-
[spanAttrAgentName]: generation.agentName ?? '',
|
|
737
|
+
...metricIdentityAttributes(generation.model.provider, generation.model.name, generation.agentName, generation.agentVersion),
|
|
698
738
|
[metricAttrTokenType]: tokenType,
|
|
699
739
|
});
|
|
700
740
|
}
|
|
@@ -706,10 +746,8 @@ export class SigilClient {
|
|
|
706
746
|
const errorCategory = finalError === undefined ? '' : errorCategoryFromError(finalError, true);
|
|
707
747
|
this.operationDurationHistogram.record(durationSeconds, {
|
|
708
748
|
[spanAttrOperationName]: 'execute_tool',
|
|
709
|
-
[spanAttrProviderName]: (toolExecution.requestProvider ?? '').trim(),
|
|
710
|
-
[spanAttrRequestModel]: (toolExecution.requestModel ?? '').trim(),
|
|
711
749
|
[spanAttrToolName]: toolExecution.toolName.trim(),
|
|
712
|
-
|
|
750
|
+
...metricIdentityAttributes(toolExecution.requestProvider ?? '', toolExecution.requestModel ?? '', toolExecution.agentName, toolExecution.agentVersion),
|
|
713
751
|
[spanAttrErrorType]: errorType,
|
|
714
752
|
[spanAttrErrorCategory]: errorCategory,
|
|
715
753
|
});
|
|
@@ -811,6 +849,7 @@ class GenerationRecorderImpl {
|
|
|
811
849
|
callError;
|
|
812
850
|
localError;
|
|
813
851
|
firstTokenAt;
|
|
852
|
+
extraMetadata;
|
|
814
853
|
constructor(client, seed, defaultMode) {
|
|
815
854
|
this.client = client;
|
|
816
855
|
this.seed = cloneGenerationStart(seed);
|
|
@@ -857,7 +896,7 @@ class GenerationRecorderImpl {
|
|
|
857
896
|
this.mode = this.seed.mode ?? defaultMode;
|
|
858
897
|
this.startedAt = this.seed.startedAt ?? this.client.internalNow();
|
|
859
898
|
this.contentCaptureMode = this.client.internalResolveGenerationContentCaptureMode(this.seed);
|
|
860
|
-
this.span = this.client.internalStartGenerationSpan(this.seed, this.mode, this.startedAt);
|
|
899
|
+
this.span = this.client.internalStartGenerationSpan(this.seed, this.mode, this.startedAt, this.contentCaptureMode);
|
|
861
900
|
}
|
|
862
901
|
setResult(result) {
|
|
863
902
|
if (this.ended) {
|
|
@@ -880,6 +919,28 @@ class GenerationRecorderImpl {
|
|
|
880
919
|
}
|
|
881
920
|
this.firstTokenAt = new Date(firstTokenAt);
|
|
882
921
|
}
|
|
922
|
+
setCacheDiagnostics(missReason, opts) {
|
|
923
|
+
if (this.ended) {
|
|
924
|
+
return;
|
|
925
|
+
}
|
|
926
|
+
const trimmed = missReason.trim();
|
|
927
|
+
if (trimmed.length === 0) {
|
|
928
|
+
return;
|
|
929
|
+
}
|
|
930
|
+
if (this.extraMetadata === undefined) {
|
|
931
|
+
this.extraMetadata = {};
|
|
932
|
+
}
|
|
933
|
+
delete this.extraMetadata[CACHE_DIAGNOSTICS_MISSED_INPUT_TOKENS_KEY];
|
|
934
|
+
delete this.extraMetadata[CACHE_DIAGNOSTICS_PREVIOUS_MESSAGE_ID_KEY];
|
|
935
|
+
this.extraMetadata[CACHE_DIAGNOSTICS_MISS_REASON_KEY] = trimmed;
|
|
936
|
+
if (opts?.missedInputTokens !== undefined) {
|
|
937
|
+
this.extraMetadata[CACHE_DIAGNOSTICS_MISSED_INPUT_TOKENS_KEY] = String(opts.missedInputTokens);
|
|
938
|
+
}
|
|
939
|
+
const prev = opts?.previousMessageId?.trim();
|
|
940
|
+
if (prev !== undefined && prev.length > 0) {
|
|
941
|
+
this.extraMetadata[CACHE_DIAGNOSTICS_PREVIOUS_MESSAGE_ID_KEY] = prev;
|
|
942
|
+
}
|
|
943
|
+
}
|
|
883
944
|
end() {
|
|
884
945
|
if (this.ended) {
|
|
885
946
|
return;
|
|
@@ -917,7 +978,7 @@ class GenerationRecorderImpl {
|
|
|
917
978
|
startedAt: new Date(this.startedAt),
|
|
918
979
|
completedAt: new Date(this.result?.completedAt ?? this.client.internalNow()),
|
|
919
980
|
tags: mergeStringRecords(this.seed.tags, this.result?.tags),
|
|
920
|
-
metadata: mergeUnknownRecords(this.seed.metadata, this.result?.metadata),
|
|
981
|
+
metadata: mergeUnknownRecords(mergeUnknownRecords(this.seed.metadata, this.result?.metadata), this.extraMetadata),
|
|
921
982
|
artifacts: this.result?.artifacts?.map(cloneArtifact),
|
|
922
983
|
callError: this.callError,
|
|
923
984
|
};
|
|
@@ -965,8 +1026,20 @@ class GenerationRecorderImpl {
|
|
|
965
1026
|
}
|
|
966
1027
|
}
|
|
967
1028
|
const validationError = validateGeneration(validationTarget);
|
|
968
|
-
|
|
969
|
-
|
|
1029
|
+
// full_with_metadata_spans: proto export keeps the title, but the span
|
|
1030
|
+
// path must drop it. Pass a shallow copy with the title cleared so the
|
|
1031
|
+
// in-memory generation (the proto payload) stays untouched.
|
|
1032
|
+
const spanGeneration = effectiveContentCaptureMode === 'full_with_metadata_spans'
|
|
1033
|
+
? { ...generation, conversationTitle: '' }
|
|
1034
|
+
: generation;
|
|
1035
|
+
this.client.internalSyncGenerationSpan(this.span, spanGeneration);
|
|
1036
|
+
if (effectiveContentCaptureMode === 'metadata_only' &&
|
|
1037
|
+
this.contentCaptureMode !== 'metadata_only' &&
|
|
1038
|
+
this.contentCaptureMode !== 'full_with_metadata_spans') {
|
|
1039
|
+
// Sanitizer fallback downgrades effective mode to metadata_only.
|
|
1040
|
+
// Skipped when the original mode already left the attribute absent at
|
|
1041
|
+
// start time (metadata_only / full_with_metadata_spans) so the
|
|
1042
|
+
// start-span omission isn't re-emitted here as an empty value.
|
|
970
1043
|
this.client.internalClearSpanConversationTitle(this.span);
|
|
971
1044
|
}
|
|
972
1045
|
this.client.internalApplyTraceContextFromSpan(this.span, generation);
|
|
@@ -986,7 +1059,24 @@ class GenerationRecorderImpl {
|
|
|
986
1059
|
this.client.internalLogWarn('sigil generation enqueue failed', enqueueError);
|
|
987
1060
|
}
|
|
988
1061
|
}
|
|
989
|
-
|
|
1062
|
+
// Under metadata_only stripContent already replaced generation.callError
|
|
1063
|
+
// with the category, so the span path can read it back from the
|
|
1064
|
+
// generation. Under full_with_metadata_spans generation.callError stays
|
|
1065
|
+
// raw for the gRPC export, so we substitute the precomputed category for
|
|
1066
|
+
// the span path here.
|
|
1067
|
+
let finalCallError;
|
|
1068
|
+
if (this.callError === undefined) {
|
|
1069
|
+
finalCallError = undefined;
|
|
1070
|
+
}
|
|
1071
|
+
else if (effectiveContentCaptureMode === 'metadata_only') {
|
|
1072
|
+
finalCallError = generation.callError;
|
|
1073
|
+
}
|
|
1074
|
+
else if (effectiveContentCaptureMode === 'full_with_metadata_spans') {
|
|
1075
|
+
finalCallError = callErrorCategory.length > 0 ? callErrorCategory : 'sdk_error';
|
|
1076
|
+
}
|
|
1077
|
+
else {
|
|
1078
|
+
finalCallError = this.callError;
|
|
1079
|
+
}
|
|
990
1080
|
this.client.internalFinalizeGenerationSpan(this.span, generation, finalCallError, validationError, enqueueError, this.firstTokenAt, callErrorCategory.length > 0 ? callErrorCategory : undefined);
|
|
991
1081
|
}
|
|
992
1082
|
getError() {
|
|
@@ -998,6 +1088,7 @@ class EmbeddingRecorderImpl {
|
|
|
998
1088
|
seed;
|
|
999
1089
|
startedAt;
|
|
1000
1090
|
span;
|
|
1091
|
+
contentCaptureMode;
|
|
1001
1092
|
ended = false;
|
|
1002
1093
|
callError;
|
|
1003
1094
|
result;
|
|
@@ -1007,6 +1098,7 @@ class EmbeddingRecorderImpl {
|
|
|
1007
1098
|
this.client = client;
|
|
1008
1099
|
this.seed = cloneEmbeddingStart(seed);
|
|
1009
1100
|
this.startedAt = this.seed.startedAt ?? this.client.internalNow();
|
|
1101
|
+
this.contentCaptureMode = this.client.internalResolveEmbeddingContentCaptureMode(this.seed);
|
|
1010
1102
|
this.span = this.client.internalStartEmbeddingSpan(this.seed, this.startedAt);
|
|
1011
1103
|
}
|
|
1012
1104
|
setCallError(error) {
|
|
@@ -1033,7 +1125,7 @@ class EmbeddingRecorderImpl {
|
|
|
1033
1125
|
if (localError === undefined) {
|
|
1034
1126
|
localError = validateEmbeddingResult(normalizedResult);
|
|
1035
1127
|
}
|
|
1036
|
-
this.client.internalFinalizeEmbeddingSpan(this.span, this.seed, normalizedResult, this.hasResult, this.callError, localError, this.startedAt, completedAt);
|
|
1128
|
+
this.client.internalFinalizeEmbeddingSpan(this.span, this.seed, normalizedResult, this.hasResult, this.callError, localError, this.startedAt, completedAt, this.contentCaptureMode);
|
|
1037
1129
|
this.localError = localError;
|
|
1038
1130
|
}
|
|
1039
1131
|
getError() {
|
|
@@ -1046,6 +1138,7 @@ class ToolExecutionRecorderImpl {
|
|
|
1046
1138
|
startedAt;
|
|
1047
1139
|
span;
|
|
1048
1140
|
resolvedIncludeContent;
|
|
1141
|
+
toolMode;
|
|
1049
1142
|
ended = false;
|
|
1050
1143
|
result;
|
|
1051
1144
|
callError;
|
|
@@ -1077,7 +1170,16 @@ class ToolExecutionRecorderImpl {
|
|
|
1077
1170
|
this.seed.agentVersion = fromConfig;
|
|
1078
1171
|
}
|
|
1079
1172
|
}
|
|
1080
|
-
|
|
1173
|
+
// Under metadata_only or full_with_metadata_spans, the start-time tool
|
|
1174
|
+
// span must not carry any content-bearing seed field. Tools have no
|
|
1175
|
+
// proto export, so dropping these on the seed is the only redaction
|
|
1176
|
+
// surface.
|
|
1177
|
+
this.toolMode = this.client.internalResolveToolContentCaptureMode(this.seed);
|
|
1178
|
+
if (this.toolMode === 'metadata_only' || this.toolMode === 'full_with_metadata_spans') {
|
|
1179
|
+
this.seed.conversationTitle = undefined;
|
|
1180
|
+
this.seed.toolDescription = undefined;
|
|
1181
|
+
}
|
|
1182
|
+
this.resolvedIncludeContent = shouldIncludeToolContent(this.toolMode, this.seed.includeContent ?? false);
|
|
1081
1183
|
this.startedAt = this.seed.startedAt ?? this.client.internalNow();
|
|
1082
1184
|
this.span = this.client.internalStartToolExecutionSpan(this.seed, this.startedAt);
|
|
1083
1185
|
}
|
|
@@ -1125,7 +1227,7 @@ class ToolExecutionRecorderImpl {
|
|
|
1125
1227
|
else {
|
|
1126
1228
|
this.client.internalRecordToolExecution(toolExecution);
|
|
1127
1229
|
}
|
|
1128
|
-
this.localError = this.client.internalFinalizeToolExecutionSpan(this.span, toolExecution, this.localError);
|
|
1230
|
+
this.localError = this.client.internalFinalizeToolExecutionSpan(this.span, toolExecution, this.localError, this.toolMode);
|
|
1129
1231
|
}
|
|
1130
1232
|
getError() {
|
|
1131
1233
|
return this.localError;
|
|
@@ -1180,6 +1282,17 @@ function toolSpanName(toolName) {
|
|
|
1180
1282
|
}
|
|
1181
1283
|
return `execute_tool ${normalized}`;
|
|
1182
1284
|
}
|
|
1285
|
+
function metricIdentityAttributes(provider, model, agentName, agentVersion) {
|
|
1286
|
+
const attributes = {
|
|
1287
|
+
[spanAttrProviderName]: provider.trim(),
|
|
1288
|
+
[spanAttrRequestModel]: model.trim(),
|
|
1289
|
+
[spanAttrAgentName]: agentName?.trim() ?? '',
|
|
1290
|
+
};
|
|
1291
|
+
if (notEmpty(agentVersion)) {
|
|
1292
|
+
attributes[spanAttrAgentVersion] = agentVersion.trim();
|
|
1293
|
+
}
|
|
1294
|
+
return attributes;
|
|
1295
|
+
}
|
|
1183
1296
|
function setGenerationSpanAttributes(span, generation) {
|
|
1184
1297
|
span.setAttribute(spanAttrOperationName, generation.operationName);
|
|
1185
1298
|
span.setAttribute(spanAttrSDKName, sdkName);
|
|
@@ -1309,7 +1422,7 @@ function setEmbeddingStartSpanAttributes(span, start) {
|
|
|
1309
1422
|
span.setAttribute(spanAttrRequestEncodingFormats, [start.encodingFormat]);
|
|
1310
1423
|
}
|
|
1311
1424
|
}
|
|
1312
|
-
function setEmbeddingEndSpanAttributes(span, result, hasResult, captureConfig) {
|
|
1425
|
+
function setEmbeddingEndSpanAttributes(span, result, hasResult, captureConfig, contentCaptureMode = 'default') {
|
|
1313
1426
|
if (hasResult) {
|
|
1314
1427
|
span.setAttribute(spanAttrEmbeddingInputCount, result.inputCount);
|
|
1315
1428
|
}
|
|
@@ -1322,7 +1435,10 @@ function setEmbeddingEndSpanAttributes(span, result, hasResult, captureConfig) {
|
|
|
1322
1435
|
if (result.dimensions !== undefined) {
|
|
1323
1436
|
span.setAttribute(spanAttrEmbeddingDimCount, result.dimensions);
|
|
1324
1437
|
}
|
|
1325
|
-
|
|
1438
|
+
// Embeddings have no proto export; full_with_metadata_spans matches
|
|
1439
|
+
// metadata_only for input-text span attributes.
|
|
1440
|
+
const omitInputTexts = contentCaptureMode === 'metadata_only' || contentCaptureMode === 'full_with_metadata_spans';
|
|
1441
|
+
if (captureConfig.captureInput && result.inputTexts !== undefined && !omitInputTexts) {
|
|
1326
1442
|
const texts = captureEmbeddingInputTexts(result.inputTexts, captureConfig.maxInputItems, captureConfig.maxTextLength);
|
|
1327
1443
|
if (texts.length > 0) {
|
|
1328
1444
|
span.setAttribute(spanAttrEmbeddingInputTexts, texts);
|
|
@@ -1438,7 +1554,10 @@ function baseURLFromAPIEndpoint(endpoint, insecure) {
|
|
|
1438
1554
|
}
|
|
1439
1555
|
if (trimmed.startsWith('http://') || trimmed.startsWith('https://')) {
|
|
1440
1556
|
const parsed = new URL(trimmed);
|
|
1441
|
-
|
|
1557
|
+
// Preserve a path prefix so prefix-mounted Sigil deployments
|
|
1558
|
+
// (https://host/sigil) route /api/v1/conversations/... under the prefix.
|
|
1559
|
+
const path = parsed.pathname.replace(/\/+$/, '');
|
|
1560
|
+
return `${parsed.protocol}//${parsed.host}${path}`;
|
|
1442
1561
|
}
|
|
1443
1562
|
const withoutScheme = trimmed.startsWith('grpc://') ? trimmed.slice('grpc://'.length) : trimmed;
|
|
1444
1563
|
const host = withoutScheme.split('/')[0]?.trim();
|