weflayr 0.24.0 → 0.26.1
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 +2 -2
- package/dist/package.json +51 -0
- package/dist/{api → src/api}/generated/facade.gen.d.ts +86 -12
- package/dist/{api → src/api}/generated/facade.gen.js +4 -2
- package/dist/src/api/generated/index.d.ts +2 -0
- package/dist/{api → src/api}/generated/index.js +3 -1
- package/dist/{api → src/api}/generated/sdk.gen.d.ts +11 -3
- package/dist/{api → src/api}/generated/sdk.gen.js +34 -4
- package/{src/api/generated/types.gen.ts → dist/src/api/generated/types.gen.d.ts} +436 -153
- package/dist/{api → src/api}/makeEndpoint.js +1 -3
- package/dist/src/auto-instrument.d.ts +42 -0
- package/dist/src/auto-instrument.js +156 -0
- package/dist/src/index.d.ts +9 -0
- package/dist/src/index.js +49 -0
- package/dist/src/instrumentation/anthropic/get_cache_and_reasoning_telemetry.d.ts +20 -0
- package/dist/src/instrumentation/anthropic/get_cache_and_reasoning_telemetry.js +114 -0
- package/dist/src/instrumentation/anthropic/get_cache_config_telemetry.d.ts +28 -0
- package/dist/src/instrumentation/anthropic/get_cache_config_telemetry.js +92 -0
- package/dist/src/instrumentation/anthropic/get_streaming_accumulation_telemetry.d.ts +25 -0
- package/dist/src/instrumentation/anthropic/get_streaming_accumulation_telemetry.js +141 -0
- package/dist/src/instrumentation/anthropic/get_structured_output_schema_telemetry.d.ts +9 -0
- package/dist/src/instrumentation/anthropic/get_structured_output_schema_telemetry.js +17 -0
- package/dist/src/instrumentation/anthropic/get_tool_definitions_telemetry.d.ts +15 -0
- package/dist/src/instrumentation/anthropic/get_tool_definitions_telemetry.js +50 -0
- package/dist/src/instrumentation/anthropic/set_telemetry_attributes.d.ts +15 -0
- package/dist/src/instrumentation/anthropic/set_telemetry_attributes.js +39 -0
- package/dist/src/instrumentation/bedrock/get_cache_config_telemetry.d.ts +22 -0
- package/dist/src/instrumentation/bedrock/get_cache_config_telemetry.js +97 -0
- package/dist/src/instrumentation/bedrock/get_cache_telemetry.d.ts +22 -0
- package/dist/src/instrumentation/bedrock/get_cache_telemetry.js +102 -0
- package/dist/src/instrumentation/bedrock/get_input_message_content_telemetry.d.ts +15 -0
- package/dist/src/instrumentation/bedrock/get_input_message_content_telemetry.js +91 -0
- package/dist/src/instrumentation/bedrock/get_model_id_telemetry.d.ts +21 -0
- package/dist/src/instrumentation/bedrock/get_model_id_telemetry.js +54 -0
- package/dist/src/instrumentation/bedrock/get_reasoning_output_telemetry.d.ts +19 -0
- package/dist/src/instrumentation/bedrock/get_reasoning_output_telemetry.js +81 -0
- package/dist/src/instrumentation/bedrock/get_streaming_output_message_telemetry.d.ts +27 -0
- package/dist/src/instrumentation/bedrock/get_streaming_output_message_telemetry.js +126 -0
- package/dist/src/instrumentation/bedrock/get_tool_call_output_telemetry.d.ts +17 -0
- package/dist/src/instrumentation/bedrock/get_tool_call_output_telemetry.js +85 -0
- package/dist/src/instrumentation/bedrock/get_tool_definitions_telemetry.d.ts +15 -0
- package/dist/src/instrumentation/bedrock/get_tool_definitions_telemetry.js +68 -0
- package/dist/src/instrumentation/bedrock/set_telemetry_attributes.d.ts +18 -0
- package/dist/src/instrumentation/bedrock/set_telemetry_attributes.js +47 -0
- package/dist/src/instrumentation/cohere/get_chat_telemetry.d.ts +23 -0
- package/dist/src/instrumentation/cohere/get_chat_telemetry.js +77 -0
- package/dist/src/instrumentation/cohere/get_embeddings_telemetry.d.ts +18 -0
- package/dist/src/instrumentation/cohere/get_embeddings_telemetry.js +88 -0
- package/dist/src/instrumentation/cohere/get_structured_output_schema_telemetry.d.ts +12 -0
- package/dist/src/instrumentation/cohere/get_structured_output_schema_telemetry.js +18 -0
- package/dist/src/instrumentation/cohere/get_tool_call_output_telemetry.d.ts +31 -0
- package/dist/src/instrumentation/cohere/get_tool_call_output_telemetry.js +106 -0
- package/dist/src/instrumentation/cohere/get_tool_definitions_telemetry.d.ts +27 -0
- package/dist/src/instrumentation/cohere/get_tool_definitions_telemetry.js +75 -0
- package/dist/src/instrumentation/cohere/set_telemetry_attributes.d.ts +17 -0
- package/dist/src/instrumentation/cohere/set_telemetry_attributes.js +44 -0
- package/dist/src/instrumentation/elevenlabs/full_instrumentation.d.ts +28 -0
- package/dist/src/instrumentation/elevenlabs/full_instrumentation.js +209 -0
- package/dist/src/instrumentation/google/get_audio_telemetry.d.ts +9 -0
- package/dist/src/instrumentation/google/get_audio_telemetry.js +28 -0
- package/dist/src/instrumentation/google/get_cache_operations_telemetry.d.ts +23 -0
- package/dist/src/instrumentation/google/get_cache_operations_telemetry.js +154 -0
- package/dist/src/instrumentation/google/get_cache_telemetry.d.ts +16 -0
- package/{src → dist/src}/instrumentation/google/get_cache_telemetry.js +18 -19
- package/dist/src/instrumentation/google/get_embeddings_telemetry.d.ts +12 -0
- package/dist/src/instrumentation/google/get_embeddings_telemetry.js +85 -0
- package/dist/src/instrumentation/google/get_provider_name.d.ts +11 -0
- package/{src → dist/src}/instrumentation/google/get_provider_name.js +11 -12
- package/{src/instrumentation/google/get_reasoning_telemetry.js → dist/src/instrumentation/google/get_reasoning_telemetry.d.ts} +1 -11
- package/dist/src/instrumentation/google/get_reasoning_telemetry.js +21 -0
- package/dist/src/instrumentation/google/get_structured_output_schema_telemetry.d.ts +12 -0
- package/dist/src/instrumentation/google/get_structured_output_schema_telemetry.js +19 -0
- package/dist/src/instrumentation/google/set_telemetry_attributes.d.ts +18 -0
- package/dist/src/instrumentation/google/set_telemetry_attributes.js +98 -0
- package/dist/src/instrumentation/openai/get_audio_telemetry.d.ts +25 -0
- package/dist/src/instrumentation/openai/get_audio_telemetry.js +123 -0
- package/dist/src/instrumentation/openai/get_bedrock_mantle_telemetry.d.ts +35 -0
- package/dist/src/instrumentation/openai/get_bedrock_mantle_telemetry.js +148 -0
- package/dist/src/instrumentation/openai/get_cache_and_reasoning_telemetry.d.ts +27 -0
- package/dist/src/instrumentation/openai/get_cache_and_reasoning_telemetry.js +72 -0
- package/dist/src/instrumentation/openai/get_cache_config_telemetry.d.ts +28 -0
- package/dist/src/instrumentation/openai/get_cache_config_telemetry.js +91 -0
- package/dist/src/instrumentation/openai/get_embeddings_telemetry.d.ts +18 -0
- package/dist/src/instrumentation/openai/get_embeddings_telemetry.js +86 -0
- package/dist/src/instrumentation/openai/get_streaming_usage.d.ts +21 -0
- package/dist/src/instrumentation/openai/get_streaming_usage.js +74 -0
- package/dist/src/instrumentation/openai/get_structured_output_schema_telemetry.d.ts +12 -0
- package/dist/src/instrumentation/openai/get_structured_output_schema_telemetry.js +20 -0
- package/dist/src/instrumentation/openai/set_telemetry_attributes.d.ts +17 -0
- package/dist/src/instrumentation/openai/set_telemetry_attributes.js +47 -0
- package/dist/src/instrumentation/shared/get_structured_output_schema_telemetry.d.ts +35 -0
- package/dist/src/instrumentation/shared/get_structured_output_schema_telemetry.js +76 -0
- package/dist/src/instrumentation/vercel/full_instrumentation.d.ts +3 -0
- package/dist/src/instrumentation/vercel/full_instrumentation.js +54 -0
- package/dist/src/instrumentation/vercel/get_cache_creation_telemetry.d.ts +22 -0
- package/dist/src/instrumentation/vercel/get_cache_creation_telemetry.js +66 -0
- package/dist/src/instrumentation/vercel/get_structured_output_schema_telemetry.d.ts +24 -0
- package/dist/src/instrumentation/vercel/get_structured_output_schema_telemetry.js +84 -0
- package/dist/src/logger.d.ts +1 -0
- package/dist/src/logger.js +6 -0
- package/dist/src/otel/exporter.d.ts +19 -0
- package/dist/src/otel/exporter.js +94 -0
- package/dist/src/otel/propagation.d.ts +46 -0
- package/dist/src/otel/propagation.js +110 -0
- package/dist/src/otel/span-filter.d.ts +3 -0
- package/dist/src/otel/span-filter.js +61 -0
- package/dist/src/otel/span-processor.d.ts +55 -0
- package/dist/src/otel/span-processor.js +169 -0
- package/dist/src/otel/vercel-ai-sdk-span-filter.d.ts +12 -0
- package/dist/src/otel/vercel-ai-sdk-span-filter.js +88 -0
- package/dist/src/setup.d.ts +50 -0
- package/dist/src/setup.js +155 -0
- package/package.json +12 -5
- package/.prettierignore +0 -2
- package/.prettierrc.json +0 -7
- package/LICENSE-MIT +0 -21
- package/NOTICE +0 -12
- package/dist/api/generated/index.d.ts +0 -2
- package/dist/api/generated/types.gen.d.ts +0 -1005
- package/eslint.config.mjs +0 -36
- package/index.d.ts +0 -170
- package/openapi-ts.config.mjs +0 -9
- package/scripts/generate_facade.mjs +0 -86
- package/src/api/caseConversion.ts +0 -58
- package/src/api/generated/client/client.gen.ts +0 -277
- package/src/api/generated/client/index.ts +0 -27
- package/src/api/generated/client/types.gen.ts +0 -218
- package/src/api/generated/client/utils.gen.ts +0 -316
- package/src/api/generated/client.gen.ts +0 -16
- package/src/api/generated/core/auth.gen.ts +0 -48
- package/src/api/generated/core/bodySerializer.gen.ts +0 -82
- package/src/api/generated/core/params.gen.ts +0 -178
- package/src/api/generated/core/pathSerializer.gen.ts +0 -171
- package/src/api/generated/core/queryKeySerializer.gen.ts +0 -117
- package/src/api/generated/core/serverSentEvents.gen.ts +0 -242
- package/src/api/generated/core/types.gen.ts +0 -110
- package/src/api/generated/core/utils.gen.ts +0 -140
- package/src/api/generated/facade.gen.ts +0 -104
- package/src/api/generated/index.ts +0 -4
- package/src/api/generated/sdk.gen.ts +0 -175
- package/src/api/index.ts +0 -45
- package/src/api/makeEndpoint.ts +0 -54
- package/src/auto-instrument.js +0 -172
- package/src/index.js +0 -19
- package/src/instrumentation/anthropic/get_cache_and_reasoning_telemetry.js +0 -118
- package/src/instrumentation/anthropic/get_cache_config_telemetry.js +0 -90
- package/src/instrumentation/anthropic/get_streaming_stop_reason_telemetry.js +0 -121
- package/src/instrumentation/anthropic/get_tool_definitions_telemetry.js +0 -55
- package/src/instrumentation/anthropic/set_telemetry_attributes.js +0 -39
- package/src/instrumentation/bedrock/get_cache_config_telemetry.js +0 -106
- package/src/instrumentation/bedrock/get_cache_telemetry.js +0 -109
- package/src/instrumentation/bedrock/get_input_message_content_telemetry.js +0 -94
- package/src/instrumentation/bedrock/get_streaming_output_message_telemetry.js +0 -87
- package/src/instrumentation/bedrock/set_telemetry_attributes.js +0 -40
- package/src/instrumentation/cohere/get_chat_telemetry.js +0 -88
- package/src/instrumentation/cohere/get_embeddings_telemetry.js +0 -107
- package/src/instrumentation/cohere/set_telemetry_attributes.js +0 -32
- package/src/instrumentation/elevenlabs/full_instrumentation.js +0 -236
- package/src/instrumentation/google/get_audio_telemetry.js +0 -30
- package/src/instrumentation/google/get_cache_operations_telemetry.js +0 -171
- package/src/instrumentation/google/get_embeddings_telemetry.js +0 -99
- package/src/instrumentation/google/set_telemetry_attributes.js +0 -104
- package/src/instrumentation/openai/get_audio_telemetry.js +0 -149
- package/src/instrumentation/openai/get_cache_and_reasoning_telemetry.js +0 -71
- package/src/instrumentation/openai/get_cache_config_telemetry.js +0 -63
- package/src/instrumentation/openai/get_embeddings_telemetry.js +0 -107
- package/src/instrumentation/openai/get_streaming_usage.js +0 -81
- package/src/instrumentation/openai/set_telemetry_attributes.js +0 -41
- package/src/instrumentation/vercel/full_instrumentation.js +0 -52
- package/src/instrumentation/vercel/get_cache_creation_telemetry.js +0 -70
- package/src/logger.js +0 -8
- package/src/otel/exporter.js +0 -108
- package/src/otel/propagation.js +0 -146
- package/src/otel/span-filter.js +0 -69
- package/src/otel/span-processor.js +0 -170
- package/src/otel/vercel-ai-sdk-span-filter.js +0 -79
- package/src/setup.js +0 -167
- package/tests/api/index.test.js +0 -437
- package/tests/index.test.js +0 -884
- package/tests/instrumentation/anthropic/get_cache_and_reasoning_telemetry.test.js +0 -181
- package/tests/instrumentation/anthropic/get_cache_config_telemetry.test.js +0 -92
- package/tests/instrumentation/anthropic/get_streaming_stop_reason_telemetry.test.js +0 -117
- package/tests/instrumentation/anthropic/get_tool_definitions_telemetry.test.js +0 -97
- package/tests/instrumentation/bedrock/get_cache_config_telemetry.test.js +0 -107
- package/tests/instrumentation/bedrock/get_cache_telemetry.test.js +0 -118
- package/tests/instrumentation/bedrock/get_input_message_content_telemetry.test.js +0 -89
- package/tests/instrumentation/bedrock/get_streaming_output_message_telemetry.test.js +0 -87
- package/tests/instrumentation/cohere/get_chat_telemetry.test.js +0 -148
- package/tests/instrumentation/cohere/get_embeddings_telemetry.test.js +0 -132
- package/tests/instrumentation/elevenlabs/full_instrumentation.test.js +0 -258
- package/tests/instrumentation/google/get_cache_operations_telemetry.test.js +0 -130
- package/tests/instrumentation/google/get_embeddings_telemetry.test.js +0 -128
- package/tests/instrumentation/google/get_reasoning_telemetry.test.js +0 -41
- package/tests/instrumentation/google/set_telemetry_attributes.test.js +0 -219
- package/tests/instrumentation/openai/get_audio_telemetry.test.js +0 -170
- package/tests/instrumentation/openai/get_cache_and_reasoning_telemetry.test.js +0 -83
- package/tests/instrumentation/openai/get_cache_config_telemetry.test.js +0 -83
- package/tests/instrumentation/openai/get_embeddings_telemetry.test.js +0 -145
- package/tests/instrumentation/openai/get_streaming_usage.test.js +0 -105
- package/tests/instrumentation/vercel/full_instrumentation.test.js +0 -16
- package/tests/instrumentation/vercel/get_cache_creation_telemetry.test.js +0 -96
- package/tests/otel/vercel-ai-sdk-span-filter.test.js +0 -159
- package/tsconfig.json +0 -18
- /package/dist/{api → src/api}/caseConversion.d.ts +0 -0
- /package/dist/{api → src/api}/caseConversion.js +0 -0
- /package/dist/{api → src/api}/generated/client/client.gen.d.ts +0 -0
- /package/dist/{api → src/api}/generated/client/client.gen.js +0 -0
- /package/dist/{api → src/api}/generated/client/index.d.ts +0 -0
- /package/dist/{api → src/api}/generated/client/index.js +0 -0
- /package/dist/{api → src/api}/generated/client/types.gen.d.ts +0 -0
- /package/dist/{api → src/api}/generated/client/types.gen.js +0 -0
- /package/dist/{api → src/api}/generated/client/utils.gen.d.ts +0 -0
- /package/dist/{api → src/api}/generated/client/utils.gen.js +0 -0
- /package/dist/{api → src/api}/generated/client.gen.d.ts +0 -0
- /package/dist/{api → src/api}/generated/client.gen.js +0 -0
- /package/dist/{api → src/api}/generated/core/auth.gen.d.ts +0 -0
- /package/dist/{api → src/api}/generated/core/auth.gen.js +0 -0
- /package/dist/{api → src/api}/generated/core/bodySerializer.gen.d.ts +0 -0
- /package/dist/{api → src/api}/generated/core/bodySerializer.gen.js +0 -0
- /package/dist/{api → src/api}/generated/core/params.gen.d.ts +0 -0
- /package/dist/{api → src/api}/generated/core/params.gen.js +0 -0
- /package/dist/{api → src/api}/generated/core/pathSerializer.gen.d.ts +0 -0
- /package/dist/{api → src/api}/generated/core/pathSerializer.gen.js +0 -0
- /package/dist/{api → src/api}/generated/core/queryKeySerializer.gen.d.ts +0 -0
- /package/dist/{api → src/api}/generated/core/queryKeySerializer.gen.js +0 -0
- /package/dist/{api → src/api}/generated/core/serverSentEvents.gen.d.ts +0 -0
- /package/dist/{api → src/api}/generated/core/serverSentEvents.gen.js +0 -0
- /package/dist/{api → src/api}/generated/core/types.gen.d.ts +0 -0
- /package/dist/{api → src/api}/generated/core/types.gen.js +0 -0
- /package/dist/{api → src/api}/generated/core/utils.gen.d.ts +0 -0
- /package/dist/{api → src/api}/generated/core/utils.gen.js +0 -0
- /package/dist/{api → src/api}/generated/types.gen.js +0 -0
- /package/dist/{api → src/api}/index.d.ts +0 -0
- /package/dist/{api → src/api}/index.js +0 -0
- /package/dist/{api → src/api}/makeEndpoint.d.ts +0 -0
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Streamed-accumulation gap filling for the Anthropic chat span.
|
|
4
|
+
*
|
|
5
|
+
* `@traceloop/instrumentation-anthropic` accumulates a streamed response into a
|
|
6
|
+
* result object but drops two things on the way:
|
|
7
|
+
* - the `message_delta` chunk's `delta.stop_reason`, so streamed spans format
|
|
8
|
+
* their output message with an empty `finish_reason`, and
|
|
9
|
+
* - the `content_block_delta` chunks' `input_json_delta` fragments, so a
|
|
10
|
+
* streamed tool call's `tool_call` part carries no `arguments`.
|
|
11
|
+
*
|
|
12
|
+
* `_streamingWrapPromise(client, moduleExports, { span, type, promise })`
|
|
13
|
+
* returns `new moduleExports.APIPromise(...)` whose parse step wraps the real
|
|
14
|
+
* SDK stream with the instrumentor's accumulating iterator. This complement
|
|
15
|
+
* hands it a patched `moduleExports` whose APIPromise interposes on that parse
|
|
16
|
+
* step, observing the chunks (outside the accumulating iterator, so every chunk
|
|
17
|
+
* is seen before the iterator finishes) to capture both — which are then
|
|
18
|
+
* injected into the accumulated result just before `_endSpan` formats the
|
|
19
|
+
* output message.
|
|
20
|
+
*/
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
exports.AnthropicStreamingAccumulationInstrumentor = void 0;
|
|
23
|
+
class AnthropicStreamingAccumulationInstrumentor {
|
|
24
|
+
// [instrumentation, methodName, originalFunction] for uninstrument().
|
|
25
|
+
_patched = [];
|
|
26
|
+
// span -> what upstream's accumulator dropped from that span's stream.
|
|
27
|
+
_gapsBySpan = new WeakMap();
|
|
28
|
+
// No-op (and never throws) if the instrumentor's internals have changed shape —
|
|
29
|
+
// the worst case is an unenriched streamed span, never a crash.
|
|
30
|
+
instrument(instrumentation) {
|
|
31
|
+
if (!instrumentation)
|
|
32
|
+
return;
|
|
33
|
+
const gapsBySpan = this._gapsBySpan;
|
|
34
|
+
function gapsFor(span) {
|
|
35
|
+
let gaps = gapsBySpan.get(span);
|
|
36
|
+
if (!gaps) {
|
|
37
|
+
gaps = { toolArgumentsJsonByIndex: new Map() };
|
|
38
|
+
gapsBySpan.set(span, gaps);
|
|
39
|
+
}
|
|
40
|
+
return gaps;
|
|
41
|
+
}
|
|
42
|
+
async function* observeDroppedChunks(stream, span) {
|
|
43
|
+
for await (const chunk of stream) {
|
|
44
|
+
try {
|
|
45
|
+
if (chunk &&
|
|
46
|
+
chunk.type === 'message_delta' &&
|
|
47
|
+
chunk.delta &&
|
|
48
|
+
chunk.delta.stop_reason != null) {
|
|
49
|
+
gapsFor(span).stopReason = chunk.delta.stop_reason;
|
|
50
|
+
}
|
|
51
|
+
if (chunk &&
|
|
52
|
+
chunk.type === 'content_block_delta' &&
|
|
53
|
+
chunk.delta &&
|
|
54
|
+
chunk.delta.type === 'input_json_delta' &&
|
|
55
|
+
typeof chunk.delta.partial_json === 'string') {
|
|
56
|
+
const argumentsByIndex = gapsFor(span).toolArgumentsJsonByIndex;
|
|
57
|
+
argumentsByIndex.set(chunk.index, (argumentsByIndex.get(chunk.index) ?? '') + chunk.delta.partial_json);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
// Never break the caller's stream over an enrichment failure.
|
|
62
|
+
}
|
|
63
|
+
yield chunk;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
const streamOriginal = instrumentation._streamingWrapPromise;
|
|
67
|
+
if (typeof streamOriginal === 'function') {
|
|
68
|
+
instrumentation._streamingWrapPromise = function streamObservingDroppedChunks(client, moduleExports, opts) {
|
|
69
|
+
const span = opts && opts.span;
|
|
70
|
+
if (!span || !moduleExports || typeof moduleExports.APIPromise !== 'function') {
|
|
71
|
+
return streamOriginal.call(this, client, moduleExports, opts);
|
|
72
|
+
}
|
|
73
|
+
class APIPromiseObservingDroppedChunks extends moduleExports.APIPromise {
|
|
74
|
+
constructor(promiseClient, responsePromise, parseResponse) {
|
|
75
|
+
super(promiseClient, responsePromise, async (parseClient, props) => {
|
|
76
|
+
const stream = await parseResponse(parseClient, props);
|
|
77
|
+
try {
|
|
78
|
+
if (stream &&
|
|
79
|
+
typeof stream[Symbol.asyncIterator] === 'function' &&
|
|
80
|
+
typeof stream.constructor === 'function') {
|
|
81
|
+
return new stream.constructor(() => observeDroppedChunks(stream, span), stream.controller);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
// Fall through to the unobserved stream.
|
|
86
|
+
}
|
|
87
|
+
return stream;
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
// The SDK's module exports are non-writable, so the override is an own
|
|
92
|
+
// defined property shadowing the inherited one.
|
|
93
|
+
const patchedModuleExports = Object.create(moduleExports, {
|
|
94
|
+
APIPromise: { value: APIPromiseObservingDroppedChunks, configurable: true },
|
|
95
|
+
});
|
|
96
|
+
return streamOriginal.call(this, client, patchedModuleExports, opts);
|
|
97
|
+
};
|
|
98
|
+
this._patched.push([instrumentation, '_streamingWrapPromise', streamOriginal]);
|
|
99
|
+
}
|
|
100
|
+
const endSpanOriginal = instrumentation._endSpan;
|
|
101
|
+
if (typeof endSpanOriginal === 'function') {
|
|
102
|
+
instrumentation._endSpan = function endSpanWithDroppedChunks(args) {
|
|
103
|
+
try {
|
|
104
|
+
const gaps = args && args.span && gapsBySpan.get(args.span);
|
|
105
|
+
if (gaps && args.result) {
|
|
106
|
+
if (gaps.stopReason != null && args.result.stop_reason == null) {
|
|
107
|
+
args.result.stop_reason = gaps.stopReason;
|
|
108
|
+
}
|
|
109
|
+
for (const [index, argumentsJson] of gaps.toolArgumentsJsonByIndex) {
|
|
110
|
+
const block = Array.isArray(args.result.content) && args.result.content[index];
|
|
111
|
+
// Only fill the gap: a block whose input upstream DID accumulate
|
|
112
|
+
// (a future version) is left alone.
|
|
113
|
+
if (block &&
|
|
114
|
+
block.type === 'tool_use' &&
|
|
115
|
+
(!block.input || !Object.keys(block.input).length)) {
|
|
116
|
+
try {
|
|
117
|
+
block.input = JSON.parse(argumentsJson);
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
// Truncated argument JSON: leave the block as upstream built it.
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
// Never break span finalization over an enrichment failure.
|
|
128
|
+
}
|
|
129
|
+
return endSpanOriginal.call(this, args);
|
|
130
|
+
};
|
|
131
|
+
this._patched.push([instrumentation, '_endSpan', endSpanOriginal]);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
uninstrument() {
|
|
135
|
+
for (const [owner, methodName, original] of this._patched) {
|
|
136
|
+
owner[methodName] = original;
|
|
137
|
+
}
|
|
138
|
+
this._patched = [];
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
exports.AnthropicStreamingAccumulationInstrumentor = AnthropicStreamingAccumulationInstrumentor;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured-output schema location for Anthropic requests.
|
|
3
|
+
*
|
|
4
|
+
* Anthropic pins an answer to a JSON schema with
|
|
5
|
+
* `output_config: { format: { type: 'json_schema', schema } }`. The traceloop
|
|
6
|
+
* instrumentor records neither that field nor the older top-level
|
|
7
|
+
* `output_format` - and Anthropic bills the schema as input.
|
|
8
|
+
*/
|
|
9
|
+
export declare function readStructuredOutputSchema(params: any): unknown;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Structured-output schema location for Anthropic requests.
|
|
4
|
+
*
|
|
5
|
+
* Anthropic pins an answer to a JSON schema with
|
|
6
|
+
* `output_config: { format: { type: 'json_schema', schema } }`. The traceloop
|
|
7
|
+
* instrumentor records neither that field nor the older top-level
|
|
8
|
+
* `output_format` - and Anthropic bills the schema as input.
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.readStructuredOutputSchema = readStructuredOutputSchema;
|
|
12
|
+
function readStructuredOutputSchema(params) {
|
|
13
|
+
const format = params && params.output_config && params.output_config.format;
|
|
14
|
+
if (!format || format.type !== 'json_schema')
|
|
15
|
+
return undefined;
|
|
16
|
+
return format.schema;
|
|
17
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool-definitions enrichment for the Anthropic chat span.
|
|
3
|
+
*
|
|
4
|
+
* `@traceloop/instrumentation-anthropic` records the request model/temperature
|
|
5
|
+
* attributes in `startSpan({ type, params })` but never the request's `tools`,
|
|
6
|
+
* so tool-using calls carry no `gen_ai.tool.definitions`. Wrap `startSpan` to
|
|
7
|
+
* stamp them in the same `{name, description, input_schema}` shape the request
|
|
8
|
+
* uses. The span processor strips the attribute when message-content capture is
|
|
9
|
+
* disabled.
|
|
10
|
+
*/
|
|
11
|
+
export declare class AnthropicToolDefinitionsInstrumentor {
|
|
12
|
+
private _patched;
|
|
13
|
+
instrument(instrumentation: any): void;
|
|
14
|
+
uninstrument(): void;
|
|
15
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Tool-definitions enrichment for the Anthropic chat span.
|
|
4
|
+
*
|
|
5
|
+
* `@traceloop/instrumentation-anthropic` records the request model/temperature
|
|
6
|
+
* attributes in `startSpan({ type, params })` but never the request's `tools`,
|
|
7
|
+
* so tool-using calls carry no `gen_ai.tool.definitions`. Wrap `startSpan` to
|
|
8
|
+
* stamp them in the same `{name, description, input_schema}` shape the request
|
|
9
|
+
* uses. The span processor strips the attribute when message-content capture is
|
|
10
|
+
* disabled.
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.AnthropicToolDefinitionsInstrumentor = void 0;
|
|
14
|
+
class AnthropicToolDefinitionsInstrumentor {
|
|
15
|
+
// [instrumentation, methodName, originalFunction] for uninstrument().
|
|
16
|
+
_patched = [];
|
|
17
|
+
// No-op (and never throws) if the instrumentor's internals have changed shape —
|
|
18
|
+
// the worst case is missing tool definitions, never a crash.
|
|
19
|
+
instrument(instrumentation) {
|
|
20
|
+
if (!instrumentation)
|
|
21
|
+
return;
|
|
22
|
+
const startSpanOriginal = instrumentation.startSpan;
|
|
23
|
+
if (typeof startSpanOriginal !== 'function')
|
|
24
|
+
return;
|
|
25
|
+
instrumentation.startSpan = function startSpanWithToolDefinitions(request) {
|
|
26
|
+
const span = startSpanOriginal.call(this, request);
|
|
27
|
+
try {
|
|
28
|
+
const tools = request && request.params && request.params.tools;
|
|
29
|
+
if (Array.isArray(tools) && tools.length) {
|
|
30
|
+
// cache_control is dropped from the stamped definitions — the
|
|
31
|
+
// breakpoint is captured separately in cache_config.
|
|
32
|
+
const definitions = tools.map(({ cache_control: _cacheControl, ...definition }) => definition);
|
|
33
|
+
span.setAttribute('gen_ai.tool.definitions', JSON.stringify(definitions));
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
// Never break span creation over an enrichment failure.
|
|
38
|
+
}
|
|
39
|
+
return span;
|
|
40
|
+
};
|
|
41
|
+
this._patched.push([instrumentation, 'startSpan', startSpanOriginal]);
|
|
42
|
+
}
|
|
43
|
+
uninstrument() {
|
|
44
|
+
for (const [owner, methodName, original] of this._patched) {
|
|
45
|
+
owner[methodName] = original;
|
|
46
|
+
}
|
|
47
|
+
this._patched = [];
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
exports.AnthropicToolDefinitionsInstrumentor = AnthropicToolDefinitionsInstrumentor;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Anthropic telemetry complement — the registered orchestrator.
|
|
3
|
+
*
|
|
4
|
+
* Wires the weflayr-supplied patches the traceloop Anthropic instrumentor
|
|
5
|
+
* misses: cached-prompt token counts on the chat span (it reads them off the
|
|
6
|
+
* response but writes no `gen_ai.usage.cache_*` attribute), the request's tool
|
|
7
|
+
* definitions and structured-output schema, and the streamed stop reason and
|
|
8
|
+
* tool-call arguments (its stream accumulator drops both).
|
|
9
|
+
*/
|
|
10
|
+
export declare class AnthropicTelemetryInstrumentor {
|
|
11
|
+
private _subInstrumentors;
|
|
12
|
+
constructor();
|
|
13
|
+
instrument(instrumentation: any): void;
|
|
14
|
+
uninstrument(): void;
|
|
15
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Anthropic telemetry complement — the registered orchestrator.
|
|
4
|
+
*
|
|
5
|
+
* Wires the weflayr-supplied patches the traceloop Anthropic instrumentor
|
|
6
|
+
* misses: cached-prompt token counts on the chat span (it reads them off the
|
|
7
|
+
* response but writes no `gen_ai.usage.cache_*` attribute), the request's tool
|
|
8
|
+
* definitions and structured-output schema, and the streamed stop reason and
|
|
9
|
+
* tool-call arguments (its stream accumulator drops both).
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.AnthropicTelemetryInstrumentor = void 0;
|
|
13
|
+
const get_structured_output_schema_telemetry_1 = require("../shared/get_structured_output_schema_telemetry");
|
|
14
|
+
const get_cache_config_telemetry_1 = require("./get_cache_config_telemetry");
|
|
15
|
+
const get_cache_and_reasoning_telemetry_1 = require("./get_cache_and_reasoning_telemetry");
|
|
16
|
+
const get_streaming_accumulation_telemetry_1 = require("./get_streaming_accumulation_telemetry");
|
|
17
|
+
const get_tool_definitions_telemetry_1 = require("./get_tool_definitions_telemetry");
|
|
18
|
+
const get_structured_output_schema_telemetry_2 = require("./get_structured_output_schema_telemetry");
|
|
19
|
+
class AnthropicTelemetryInstrumentor {
|
|
20
|
+
_subInstrumentors;
|
|
21
|
+
constructor() {
|
|
22
|
+
this._subInstrumentors = [
|
|
23
|
+
new get_cache_and_reasoning_telemetry_1.AnthropicPromptCachingInstrumentor(),
|
|
24
|
+
new get_cache_config_telemetry_1.AnthropicCacheConfigInstrumentor(),
|
|
25
|
+
new get_streaming_accumulation_telemetry_1.AnthropicStreamingAccumulationInstrumentor(),
|
|
26
|
+
new get_tool_definitions_telemetry_1.AnthropicToolDefinitionsInstrumentor(),
|
|
27
|
+
new get_structured_output_schema_telemetry_1.TraceloopStructuredOutputSchemaInstrumentor(get_structured_output_schema_telemetry_2.readStructuredOutputSchema),
|
|
28
|
+
];
|
|
29
|
+
}
|
|
30
|
+
instrument(instrumentation) {
|
|
31
|
+
for (const sub of this._subInstrumentors)
|
|
32
|
+
sub.instrument(instrumentation);
|
|
33
|
+
}
|
|
34
|
+
uninstrument() {
|
|
35
|
+
for (const sub of this._subInstrumentors)
|
|
36
|
+
sub.uninstrument();
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
exports.AnthropicTelemetryInstrumentor = AnthropicTelemetryInstrumentor;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Request-side prompt-caching config capture for Bedrock invoke_model spans.
|
|
3
|
+
*
|
|
4
|
+
* Bedrock callers opt into caching in the request body, in the model vendor's
|
|
5
|
+
* own schema: Anthropic-on-Bedrock bodies carry `cache_control` blocks (the
|
|
6
|
+
* native Anthropic shape), Amazon Nova bodies carry `cachePoint` blocks (the
|
|
7
|
+
* Converse shape) — on system entries, message content blocks or tool
|
|
8
|
+
* definitions, each with an optional raw `ttl` string ("5m"/"1h"). The
|
|
9
|
+
* traceloop instrumentor never records them.
|
|
10
|
+
*
|
|
11
|
+
* Wrap the instrumentor's `_startSpan({ params })` (params.body is the raw
|
|
12
|
+
* request JSON) to stamp every breakpoint found as `weflayr.cache.breakpoints`.
|
|
13
|
+
* Bedrock responses report no TTL split of the written tokens; the worker
|
|
14
|
+
* derives it from these breakpoints when they all share one TTL.
|
|
15
|
+
*/
|
|
16
|
+
import { type CacheBreakpoint } from '../anthropic/get_cache_config_telemetry';
|
|
17
|
+
export declare function extractBedrockCacheBreakpoints(body: any): CacheBreakpoint[];
|
|
18
|
+
export declare class BedrockCacheConfigInstrumentor {
|
|
19
|
+
private _patched;
|
|
20
|
+
instrument(instrumentation: any): void;
|
|
21
|
+
uninstrument(): void;
|
|
22
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Request-side prompt-caching config capture for Bedrock invoke_model spans.
|
|
4
|
+
*
|
|
5
|
+
* Bedrock callers opt into caching in the request body, in the model vendor's
|
|
6
|
+
* own schema: Anthropic-on-Bedrock bodies carry `cache_control` blocks (the
|
|
7
|
+
* native Anthropic shape), Amazon Nova bodies carry `cachePoint` blocks (the
|
|
8
|
+
* Converse shape) — on system entries, message content blocks or tool
|
|
9
|
+
* definitions, each with an optional raw `ttl` string ("5m"/"1h"). The
|
|
10
|
+
* traceloop instrumentor never records them.
|
|
11
|
+
*
|
|
12
|
+
* Wrap the instrumentor's `_startSpan({ params })` (params.body is the raw
|
|
13
|
+
* request JSON) to stamp every breakpoint found as `weflayr.cache.breakpoints`.
|
|
14
|
+
* Bedrock responses report no TTL split of the written tokens; the worker
|
|
15
|
+
* derives it from these breakpoints when they all share one TTL.
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.BedrockCacheConfigInstrumentor = void 0;
|
|
19
|
+
exports.extractBedrockCacheBreakpoints = extractBedrockCacheBreakpoints;
|
|
20
|
+
const get_cache_config_telemetry_1 = require("../anthropic/get_cache_config_telemetry");
|
|
21
|
+
const BREAKPOINTS_ATTR = 'weflayr.cache.breakpoints';
|
|
22
|
+
// A breakpoint as location + the raw `cachePoint` `ttl` string, omitted when
|
|
23
|
+
// the request sets none.
|
|
24
|
+
function _cachePointEntry(location, cachePoint) {
|
|
25
|
+
const ttl = cachePoint && cachePoint.ttl;
|
|
26
|
+
return ttl ? { location, ttl: String(ttl) } : { location };
|
|
27
|
+
}
|
|
28
|
+
// The first `cachePoint` among a list of blocks (attached to a content block,
|
|
29
|
+
// or standing alone as its own block), or undefined.
|
|
30
|
+
function _cachePointOfBlocks(blocks) {
|
|
31
|
+
if (!Array.isArray(blocks))
|
|
32
|
+
return undefined;
|
|
33
|
+
const block = blocks.find((entry) => entry && entry.cachePoint != null);
|
|
34
|
+
return block && block.cachePoint;
|
|
35
|
+
}
|
|
36
|
+
// Every cache breakpoint in an InvokeModel request body, as location + the
|
|
37
|
+
// raw `ttl` string (omitted when the breakpoint sets none): the
|
|
38
|
+
// Anthropic-on-Bedrock `cache_control` shape and the Nova `cachePoint` shape
|
|
39
|
+
// (which never overlap in one body).
|
|
40
|
+
function extractBedrockCacheBreakpoints(body) {
|
|
41
|
+
const breakpoints = (0, get_cache_config_telemetry_1.extractCacheBreakpoints)(body);
|
|
42
|
+
const systemCachePoint = _cachePointOfBlocks(body.system);
|
|
43
|
+
if (systemCachePoint != null) {
|
|
44
|
+
breakpoints.push(_cachePointEntry('system', systemCachePoint));
|
|
45
|
+
}
|
|
46
|
+
(body.messages || []).forEach((message, index) => {
|
|
47
|
+
const cachePoint = _cachePointOfBlocks(message && message.content);
|
|
48
|
+
if (cachePoint != null) {
|
|
49
|
+
breakpoints.push(_cachePointEntry(`messages[${index}]`, cachePoint));
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
const tools = (body.toolConfig && body.toolConfig.tools) || [];
|
|
53
|
+
tools.forEach((tool, index) => {
|
|
54
|
+
if (tool && tool.cachePoint != null) {
|
|
55
|
+
breakpoints.push(_cachePointEntry(`tools[${index}]`, tool.cachePoint));
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
return breakpoints;
|
|
59
|
+
}
|
|
60
|
+
class BedrockCacheConfigInstrumentor {
|
|
61
|
+
// [instrumentation, methodName, originalFunction] for uninstrument().
|
|
62
|
+
_patched = [];
|
|
63
|
+
// No-op (and never throws) if the instrumentor's internals have changed shape —
|
|
64
|
+
// the worst case is missing cache-config capture, never a crash.
|
|
65
|
+
instrument(instrumentation) {
|
|
66
|
+
if (!instrumentation)
|
|
67
|
+
return;
|
|
68
|
+
const startSpanOriginal = instrumentation._startSpan;
|
|
69
|
+
if (typeof startSpanOriginal !== 'function')
|
|
70
|
+
return;
|
|
71
|
+
instrumentation._startSpan = function startSpanWithCacheConfig(request) {
|
|
72
|
+
const span = startSpanOriginal.call(this, request);
|
|
73
|
+
try {
|
|
74
|
+
const rawBody = request && request.params && request.params.input && request.params.input.body;
|
|
75
|
+
if (typeof rawBody === 'string' || rawBody instanceof Uint8Array) {
|
|
76
|
+
const body = JSON.parse(typeof rawBody === 'string' ? rawBody : new TextDecoder().decode(rawBody));
|
|
77
|
+
const breakpoints = extractBedrockCacheBreakpoints(body || {});
|
|
78
|
+
if (breakpoints.length) {
|
|
79
|
+
span.setAttribute(BREAKPOINTS_ATTR, JSON.stringify(breakpoints));
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
// Never break span creation over an enrichment failure.
|
|
85
|
+
}
|
|
86
|
+
return span;
|
|
87
|
+
};
|
|
88
|
+
this._patched.push([instrumentation, '_startSpan', startSpanOriginal]);
|
|
89
|
+
}
|
|
90
|
+
uninstrument() {
|
|
91
|
+
for (const [owner, methodName, original] of this._patched) {
|
|
92
|
+
owner[methodName] = original;
|
|
93
|
+
}
|
|
94
|
+
this._patched = [];
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
exports.BedrockCacheConfigInstrumentor = BedrockCacheConfigInstrumentor;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cached-prompt token enrichment complement for the Bedrock invoke_model path.
|
|
3
|
+
*
|
|
4
|
+
* `@traceloop/instrumentation-bedrock` records `gen_ai.usage.{input,output}_tokens`
|
|
5
|
+
* off the InvokeModel response body but never reads its cache-token counts, so
|
|
6
|
+
* spans for prompt-cache hits carry no cached-token figures. Amazon Nova's native
|
|
7
|
+
* InvokeModel response includes `usage.cacheReadInputTokenCount` /
|
|
8
|
+
* `usage.cacheWriteInputTokenCount` (Anthropic-on-Bedrock responses carry the
|
|
9
|
+
* native `usage.cache_read_input_tokens` / `cache_creation_input_tokens`);
|
|
10
|
+
* this maps them to the
|
|
11
|
+
* `gen_ai.usage.cache_read_input_tokens` / `cache_creation_input_tokens`
|
|
12
|
+
* attributes the worker reads, matching the Python SDK.
|
|
13
|
+
*
|
|
14
|
+
* It wraps the instrumentor instance's `_wrapPromise(span, promise, modelId)`,
|
|
15
|
+
* which resolves the send promise and enriches the span before ending it,
|
|
16
|
+
* letting us read the decoded body off the same response while the span is open.
|
|
17
|
+
*/
|
|
18
|
+
export declare class BedrockPromptCachingInstrumentor {
|
|
19
|
+
private _patched;
|
|
20
|
+
instrument(instrumentation: any): void;
|
|
21
|
+
uninstrument(): void;
|
|
22
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Cached-prompt token enrichment complement for the Bedrock invoke_model path.
|
|
4
|
+
*
|
|
5
|
+
* `@traceloop/instrumentation-bedrock` records `gen_ai.usage.{input,output}_tokens`
|
|
6
|
+
* off the InvokeModel response body but never reads its cache-token counts, so
|
|
7
|
+
* spans for prompt-cache hits carry no cached-token figures. Amazon Nova's native
|
|
8
|
+
* InvokeModel response includes `usage.cacheReadInputTokenCount` /
|
|
9
|
+
* `usage.cacheWriteInputTokenCount` (Anthropic-on-Bedrock responses carry the
|
|
10
|
+
* native `usage.cache_read_input_tokens` / `cache_creation_input_tokens`);
|
|
11
|
+
* this maps them to the
|
|
12
|
+
* `gen_ai.usage.cache_read_input_tokens` / `cache_creation_input_tokens`
|
|
13
|
+
* attributes the worker reads, matching the Python SDK.
|
|
14
|
+
*
|
|
15
|
+
* It wraps the instrumentor instance's `_wrapPromise(span, promise, modelId)`,
|
|
16
|
+
* which resolves the send promise and enriches the span before ending it,
|
|
17
|
+
* letting us read the decoded body off the same response while the span is open.
|
|
18
|
+
*/
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
exports.BedrockPromptCachingInstrumentor = void 0;
|
|
21
|
+
const CACHE_READ_INPUT_TOKENS_ATTR = 'gen_ai.usage.cache_read_input_tokens';
|
|
22
|
+
const CACHE_CREATION_INPUT_TOKENS_ATTR = 'gen_ai.usage.cache_creation_input_tokens';
|
|
23
|
+
// Stamp cache counts from a `usage` object onto the span: Nova's camelCase
|
|
24
|
+
// count fields, or Anthropic-on-Bedrock's native snake_case ones.
|
|
25
|
+
function _setCacheFromUsage(span, usage) {
|
|
26
|
+
if (!usage || !span || !span.isRecording || !span.isRecording())
|
|
27
|
+
return;
|
|
28
|
+
const read = usage.cacheReadInputTokenCount ?? usage.cache_read_input_tokens;
|
|
29
|
+
const write = usage.cacheWriteInputTokenCount ?? usage.cache_creation_input_tokens;
|
|
30
|
+
if (typeof read === 'number' && read) {
|
|
31
|
+
span.setAttribute(CACHE_READ_INPUT_TOKENS_ATTR, read);
|
|
32
|
+
}
|
|
33
|
+
if (typeof write === 'number' && write) {
|
|
34
|
+
span.setAttribute(CACHE_CREATION_INPUT_TOKENS_ATTR, write);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function _setCacheTokens(span, response) {
|
|
38
|
+
if (!span || !span.isRecording || !span.isRecording())
|
|
39
|
+
return;
|
|
40
|
+
const body = response && response.body;
|
|
41
|
+
// Only the non-streaming InvokeModel response buffers its body as bytes; a
|
|
42
|
+
// response stream is an async iterable whose usage arrives in a trailing chunk
|
|
43
|
+
// handled by the streaming wrap below, so skip it here (and never consume the
|
|
44
|
+
// caller's stream).
|
|
45
|
+
if (!body || typeof body[Symbol.asyncIterator] === 'function')
|
|
46
|
+
return;
|
|
47
|
+
try {
|
|
48
|
+
_setCacheFromUsage(span, JSON.parse(new TextDecoder().decode(body)).usage);
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
// Never break span enrichment over a parse failure.
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
class BedrockPromptCachingInstrumentor {
|
|
55
|
+
// [instrumentation, methodName, originalFunction] for uninstrument().
|
|
56
|
+
_patched = [];
|
|
57
|
+
// No-op (and never throws) if the instrumentor's internals have changed shape —
|
|
58
|
+
// the worst case is missing cached-token counts, never a crash.
|
|
59
|
+
instrument(instrumentation) {
|
|
60
|
+
if (!instrumentation)
|
|
61
|
+
return;
|
|
62
|
+
// Non-streamed: enrich the buffered InvokeModel response body.
|
|
63
|
+
const wrapPromiseOriginal = instrumentation._wrapPromise;
|
|
64
|
+
if (typeof wrapPromiseOriginal === 'function') {
|
|
65
|
+
instrumentation._wrapPromise = function wrapPromiseWithCache(span, promise, modelId) {
|
|
66
|
+
// Stamp cache tokens off the response, then hand the same response to the
|
|
67
|
+
// original handler (which decodes the still-buffered body for input/output
|
|
68
|
+
// tokens). Resolving to the original response keeps behaviour identical.
|
|
69
|
+
const enriched = Promise.resolve(promise).then((response) => {
|
|
70
|
+
_setCacheTokens(span, response);
|
|
71
|
+
return response;
|
|
72
|
+
});
|
|
73
|
+
return wrapPromiseOriginal.call(this, span, enriched, modelId);
|
|
74
|
+
};
|
|
75
|
+
this._patched.push([instrumentation, '_wrapPromise', wrapPromiseOriginal]);
|
|
76
|
+
}
|
|
77
|
+
// Streamed: the instrumentor processes the trailing metadata chunk via
|
|
78
|
+
// `_handleNovaStreamingMetadata(span, parsedResponse)` (reading
|
|
79
|
+
// `parsedResponse.metadata.usage` for input/output) but never its cache counts.
|
|
80
|
+
const metadataOriginal = instrumentation._handleNovaStreamingMetadata;
|
|
81
|
+
if (typeof metadataOriginal === 'function') {
|
|
82
|
+
instrumentation._handleNovaStreamingMetadata = function handleMetadataWithCache(span, parsedResponse) {
|
|
83
|
+
try {
|
|
84
|
+
const usage = parsedResponse && parsedResponse.metadata && parsedResponse.metadata.usage;
|
|
85
|
+
_setCacheFromUsage(span, usage);
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
// Never break the caller's stream over an enrichment failure.
|
|
89
|
+
}
|
|
90
|
+
return metadataOriginal.call(this, span, parsedResponse);
|
|
91
|
+
};
|
|
92
|
+
this._patched.push([instrumentation, '_handleNovaStreamingMetadata', metadataOriginal]);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
uninstrument() {
|
|
96
|
+
for (const [owner, methodName, original] of this._patched) {
|
|
97
|
+
owner[methodName] = original;
|
|
98
|
+
}
|
|
99
|
+
this._patched = [];
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
exports.BedrockPromptCachingInstrumentor = BedrockPromptCachingInstrumentor;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Input message content for Bedrock invoke_model spans the instrumentor misses.
|
|
3
|
+
*
|
|
4
|
+
* `@traceloop/instrumentation-bedrock` parses the request body per model vendor,
|
|
5
|
+
* so a call whose model id has no recognizable vendor (e.g. an invalid model —
|
|
6
|
+
* exactly the error spans) gets no `gen_ai.input.messages`. Wrap the
|
|
7
|
+
* instrumentor's `_startSpan({ params })` to stamp the input messages from the
|
|
8
|
+
* request body whenever the instrumentor did not. The span processor strips the
|
|
9
|
+
* attribute when message-content capture is disabled.
|
|
10
|
+
*/
|
|
11
|
+
export declare class BedrockInputMessageContentInstrumentor {
|
|
12
|
+
private _patched;
|
|
13
|
+
instrument(instrumentation: any): void;
|
|
14
|
+
uninstrument(): void;
|
|
15
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Input message content for Bedrock invoke_model spans the instrumentor misses.
|
|
4
|
+
*
|
|
5
|
+
* `@traceloop/instrumentation-bedrock` parses the request body per model vendor,
|
|
6
|
+
* so a call whose model id has no recognizable vendor (e.g. an invalid model —
|
|
7
|
+
* exactly the error spans) gets no `gen_ai.input.messages`. Wrap the
|
|
8
|
+
* instrumentor's `_startSpan({ params })` to stamp the input messages from the
|
|
9
|
+
* request body whenever the instrumentor did not. The span processor strips the
|
|
10
|
+
* attribute when message-content capture is disabled.
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.BedrockInputMessageContentInstrumentor = void 0;
|
|
14
|
+
function _contentToParts(content) {
|
|
15
|
+
if (typeof content === 'string') {
|
|
16
|
+
return [{ type: 'text', content }];
|
|
17
|
+
}
|
|
18
|
+
if (Array.isArray(content)) {
|
|
19
|
+
return content
|
|
20
|
+
.filter((block) => block && typeof block.text === 'string')
|
|
21
|
+
.map((block) => ({ type: 'text', content: block.text }));
|
|
22
|
+
}
|
|
23
|
+
return [];
|
|
24
|
+
}
|
|
25
|
+
// Messages in the role+parts shape from an InvokeModel JSON body — the
|
|
26
|
+
// `messages` schema (Nova, Anthropic-on-Bedrock) or the flat `inputText` /
|
|
27
|
+
// `prompt` schemas (Titan, legacy).
|
|
28
|
+
function _inputMessagesFromRequestBody(rawBody) {
|
|
29
|
+
if (typeof rawBody !== 'string')
|
|
30
|
+
return [];
|
|
31
|
+
let body;
|
|
32
|
+
try {
|
|
33
|
+
body = JSON.parse(rawBody);
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return [];
|
|
37
|
+
}
|
|
38
|
+
if (!body || typeof body !== 'object')
|
|
39
|
+
return [];
|
|
40
|
+
if (Array.isArray(body.messages)) {
|
|
41
|
+
return body.messages
|
|
42
|
+
.filter((message) => message && typeof message === 'object')
|
|
43
|
+
.map((message) => ({
|
|
44
|
+
role: String(message.role || ''),
|
|
45
|
+
parts: _contentToParts(message.content),
|
|
46
|
+
}));
|
|
47
|
+
}
|
|
48
|
+
const prompt = body.inputText || body.prompt;
|
|
49
|
+
if (typeof prompt === 'string') {
|
|
50
|
+
return [{ role: 'user', parts: [{ type: 'text', content: prompt }] }];
|
|
51
|
+
}
|
|
52
|
+
return [];
|
|
53
|
+
}
|
|
54
|
+
class BedrockInputMessageContentInstrumentor {
|
|
55
|
+
// [instrumentation, methodName, originalFunction] for uninstrument().
|
|
56
|
+
_patched = [];
|
|
57
|
+
// No-op (and never throws) if the instrumentor's internals have changed shape —
|
|
58
|
+
// the worst case is missing input messages, never a crash.
|
|
59
|
+
instrument(instrumentation) {
|
|
60
|
+
if (!instrumentation)
|
|
61
|
+
return;
|
|
62
|
+
const original = instrumentation._startSpan;
|
|
63
|
+
if (typeof original !== 'function')
|
|
64
|
+
return;
|
|
65
|
+
instrumentation._startSpan = function startSpanWithInputMessages(request) {
|
|
66
|
+
const span = original.call(this, request);
|
|
67
|
+
try {
|
|
68
|
+
const attributes = span && span.attributes;
|
|
69
|
+
if (attributes && attributes['gen_ai.input.messages'] == null) {
|
|
70
|
+
const body = request && request.params && request.params.input && request.params.input.body;
|
|
71
|
+
const messages = _inputMessagesFromRequestBody(body);
|
|
72
|
+
if (messages.length) {
|
|
73
|
+
span.setAttribute('gen_ai.input.messages', JSON.stringify(messages));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
// Never break span creation over an enrichment failure.
|
|
79
|
+
}
|
|
80
|
+
return span;
|
|
81
|
+
};
|
|
82
|
+
this._patched.push([instrumentation, '_startSpan', original]);
|
|
83
|
+
}
|
|
84
|
+
uninstrument() {
|
|
85
|
+
for (const [owner, methodName, original] of this._patched) {
|
|
86
|
+
owner[methodName] = original;
|
|
87
|
+
}
|
|
88
|
+
this._patched = [];
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
exports.BedrockInputMessageContentInstrumentor = BedrockInputMessageContentInstrumentor;
|