@telemetry-dev/bedrock 0.1.2 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents.mjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{internal-handlers-CJPJo9q3.mjs → internal-handlers-B47qvHGh.mjs} +59 -10
- package/package.json +4 -4
- package/src/agent-handlers.ts +46 -0
- package/src/agents.ts +7 -0
- package/src/converse.ts +53 -0
- package/src/index.ts +7 -0
- package/src/internal-handlers.ts +25 -2
- package/src/internal.ts +123 -3
- package/src/invoke-model.ts +68 -4
package/dist/agents.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { r as createInstrumentedSend, t as AGENT_HANDLERS } from "./internal-handlers-
|
|
1
|
+
import { r as createInstrumentedSend, t as AGENT_HANDLERS } from "./internal-handlers-B47qvHGh.mjs";
|
|
2
2
|
import { BedrockAgentRuntimeClient } from "@aws-sdk/client-bedrock-agent-runtime";
|
|
3
3
|
//#region src/agents.ts
|
|
4
4
|
const WRAPPED = /* @__PURE__ */ new WeakSet();
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as RUNTIME_HANDLERS, r as createInstrumentedSend } from "./internal-handlers-
|
|
1
|
+
import { n as RUNTIME_HANDLERS, r as createInstrumentedSend } from "./internal-handlers-B47qvHGh.mjs";
|
|
2
2
|
import { BedrockRuntimeClient } from "@aws-sdk/client-bedrock-runtime";
|
|
3
3
|
//#region src/index.ts
|
|
4
4
|
const WRAPPED = /* @__PURE__ */ new WeakSet();
|
|
@@ -195,7 +195,7 @@ function parseJson(value) {
|
|
|
195
195
|
return;
|
|
196
196
|
}
|
|
197
197
|
}
|
|
198
|
-
function wrapAsyncIterable(iterable, state, span, t0, baseFields) {
|
|
198
|
+
function wrapAsyncIterable(iterable, state, span, t0, baseFields, trackOutputChunks = true) {
|
|
199
199
|
if (!iterable || !isAsyncIterable(iterable)) {
|
|
200
200
|
endSpan(span, baseFields);
|
|
201
201
|
return iterable;
|
|
@@ -213,11 +213,13 @@ function wrapAsyncIterable(iterable, state, span, t0, baseFields) {
|
|
|
213
213
|
let completed = false;
|
|
214
214
|
try {
|
|
215
215
|
for await (const event of iterable) {
|
|
216
|
+
const receivedAt = performance.now();
|
|
216
217
|
if (!first) {
|
|
217
218
|
first = true;
|
|
218
|
-
updateSpan(span, { timeToFirstChunkMs:
|
|
219
|
+
updateSpan(span, { timeToFirstChunkMs: receivedAt - t0 });
|
|
219
220
|
}
|
|
220
|
-
safe(() => state.feed(event));
|
|
221
|
+
const stateHasOutput = safe(() => state.feed(event));
|
|
222
|
+
if (trackOutputChunks && (stateHasOutput ?? bedrockEventHasOutput(event))) safe(() => span.recordOutputChunk?.(receivedAt));
|
|
221
223
|
yield event;
|
|
222
224
|
}
|
|
223
225
|
completed = true;
|
|
@@ -239,6 +241,43 @@ function wrapAsyncIterable(iterable, state, span, t0, baseFields) {
|
|
|
239
241
|
STREAM_FINALIZER?.register(wrapped, finishAbandoned, unregisterToken);
|
|
240
242
|
return wrapped;
|
|
241
243
|
}
|
|
244
|
+
function bedrockEventHasOutput(event) {
|
|
245
|
+
const record = isRecord(event) ? event : void 0;
|
|
246
|
+
if (!record) return false;
|
|
247
|
+
const output = isRecord(record.output) ? record.output : void 0;
|
|
248
|
+
if (typeof output?.text === "string" && output.text.length > 0) return true;
|
|
249
|
+
const block = isRecord(record.contentBlockDelta) ? record.contentBlockDelta : void 0;
|
|
250
|
+
const delta = isRecord(block?.delta) ? block.delta : void 0;
|
|
251
|
+
const reasoning = isRecord(delta?.reasoningContent) ? delta.reasoningContent : void 0;
|
|
252
|
+
const toolUse = isRecord(delta?.toolUse) ? delta.toolUse : void 0;
|
|
253
|
+
if (typeof delta?.text === "string" && delta.text.length > 0 || typeof reasoning?.text === "string" && reasoning.text.length > 0 || typeof toolUse?.input === "string" && toolUse.input.length > 0) return true;
|
|
254
|
+
const raw = (isRecord(record.chunk) ? record.chunk : void 0)?.bytes;
|
|
255
|
+
if (raw === void 0) return false;
|
|
256
|
+
const text = typeof raw === "string" ? raw : raw instanceof Uint8Array ? new TextDecoder().decode(raw) : void 0;
|
|
257
|
+
if (!text) return false;
|
|
258
|
+
const parsed = parseJson(text);
|
|
259
|
+
if (parsed === void 0) return text.length > 0;
|
|
260
|
+
if (!isRecord(parsed)) return false;
|
|
261
|
+
const parsedDelta = isRecord(parsed.delta) ? parsed.delta : void 0;
|
|
262
|
+
const contentDelta = isRecord(parsed.contentBlockDelta ?? parsed.content_block_delta) ? parsed.contentBlockDelta ?? parsed.content_block_delta : void 0;
|
|
263
|
+
const nested = isRecord(contentDelta) && isRecord(contentDelta.delta) ? contentDelta.delta : void 0;
|
|
264
|
+
const generations = Array.isArray(parsed.generations) ? parsed.generations : [];
|
|
265
|
+
const generation = isRecord(generations[0]) ? generations[0] : void 0;
|
|
266
|
+
const outputs = Array.isArray(parsed.outputs) ? parsed.outputs : [];
|
|
267
|
+
const firstOutput = isRecord(outputs[0]) ? outputs[0] : void 0;
|
|
268
|
+
return [
|
|
269
|
+
parsed.outputText,
|
|
270
|
+
parsed.generation,
|
|
271
|
+
parsed.completion,
|
|
272
|
+
parsed.text,
|
|
273
|
+
parsedDelta?.text,
|
|
274
|
+
parsedDelta?.thinking,
|
|
275
|
+
parsedDelta?.partial_json,
|
|
276
|
+
nested?.text,
|
|
277
|
+
firstOutput?.text,
|
|
278
|
+
generation?.text
|
|
279
|
+
].some((value) => typeof value === "string" && value.length > 0);
|
|
280
|
+
}
|
|
242
281
|
function isAsyncIterable(value) {
|
|
243
282
|
return Object(value) === value && Symbol.asyncIterator in Object(value);
|
|
244
283
|
}
|
|
@@ -1016,15 +1055,19 @@ var InvokeModelStreamState = class {
|
|
|
1016
1055
|
error;
|
|
1017
1056
|
errorFields;
|
|
1018
1057
|
feed(event) {
|
|
1019
|
-
if (!isRecord(event)) return;
|
|
1058
|
+
if (!isRecord(event)) return false;
|
|
1020
1059
|
const streamError = modeledStreamError(event);
|
|
1021
1060
|
if (streamError) {
|
|
1022
1061
|
this.error = streamError.error;
|
|
1023
1062
|
this.errorFields = streamError.fields;
|
|
1024
|
-
return;
|
|
1063
|
+
return false;
|
|
1064
|
+
}
|
|
1065
|
+
const chunk = isRecord(event.chunk) ? event.chunk : void 0;
|
|
1066
|
+
const parsed = parseJson(chunk?.bytes);
|
|
1067
|
+
if (parsed === void 0) {
|
|
1068
|
+
const raw = chunk?.bytes;
|
|
1069
|
+
return (typeof raw === "string" || raw instanceof Uint8Array) && raw.length > 0;
|
|
1025
1070
|
}
|
|
1026
|
-
const parsed = parseJson((isRecord(event.chunk) ? event.chunk : void 0)?.bytes);
|
|
1027
|
-
if (parsed === void 0) return;
|
|
1028
1071
|
this.chunks.push(parsed);
|
|
1029
1072
|
this.text += textFromProviderChunk(parsed);
|
|
1030
1073
|
if (isRecord(parsed)) {
|
|
@@ -1044,6 +1087,7 @@ var InvokeModelStreamState = class {
|
|
|
1044
1087
|
cacheCreationInputTokens: numberValue(messageUsage?.cache_creation_input_tokens) ?? this.usage?.cacheCreationInputTokens
|
|
1045
1088
|
});
|
|
1046
1089
|
}
|
|
1090
|
+
return providerChunkHasOutput(parsed);
|
|
1047
1091
|
}
|
|
1048
1092
|
finish() {
|
|
1049
1093
|
return mergeFields(omitUndefined({
|
|
@@ -1069,6 +1113,11 @@ function textFromProviderChunk(value) {
|
|
|
1069
1113
|
const generation = Array.isArray(value.generations) && isRecord(value.generations[0]) ? value.generations[0] : void 0;
|
|
1070
1114
|
return stringValue(value.outputText) ?? stringValue(value.generation) ?? stringValue(value.completion) ?? stringValue(value.text) ?? stringValue(delta?.text) ?? stringValue(nestedDelta?.text) ?? (Array.isArray(value.outputs) && isRecord(value.outputs[0]) ? stringValue(value.outputs[0].text) : void 0) ?? stringValue(generation?.text) ?? "";
|
|
1071
1115
|
}
|
|
1116
|
+
function providerChunkHasOutput(value) {
|
|
1117
|
+
if (!isRecord(value)) return false;
|
|
1118
|
+
const delta = isRecord(value.delta) ? value.delta : void 0;
|
|
1119
|
+
return textFromProviderChunk(value).length > 0 || typeof delta?.thinking === "string" && delta.thinking.length > 0 || typeof delta?.partial_json === "string" && delta.partial_json.length > 0;
|
|
1120
|
+
}
|
|
1072
1121
|
//#endregion
|
|
1073
1122
|
//#region src/internal-handlers.ts
|
|
1074
1123
|
const RUNTIME_HANDLERS = {
|
|
@@ -1194,7 +1243,7 @@ const AGENT_HANDLERS = {
|
|
|
1194
1243
|
}
|
|
1195
1244
|
return {
|
|
1196
1245
|
...response,
|
|
1197
|
-
stream: wrapAsyncIterable(response.stream, new RagStreamState(), span, t0, base)
|
|
1246
|
+
stream: wrapAsyncIterable(response.stream, new RagStreamState(), span, t0, base, false)
|
|
1198
1247
|
};
|
|
1199
1248
|
}
|
|
1200
1249
|
},
|
|
@@ -1210,7 +1259,7 @@ const AGENT_HANDLERS = {
|
|
|
1210
1259
|
}
|
|
1211
1260
|
return {
|
|
1212
1261
|
...response,
|
|
1213
|
-
responseStream: wrapAsyncIterable(response.responseStream, new FlowStreamState(), span, t0, awsMetadataFields(response.$metadata))
|
|
1262
|
+
responseStream: wrapAsyncIterable(response.responseStream, new FlowStreamState(), span, t0, awsMetadataFields(response.$metadata), false)
|
|
1214
1263
|
};
|
|
1215
1264
|
}
|
|
1216
1265
|
}
|
|
@@ -1228,7 +1277,7 @@ function streamAgentResult(key) {
|
|
|
1228
1277
|
}
|
|
1229
1278
|
return {
|
|
1230
1279
|
...response,
|
|
1231
|
-
[key]: wrapAsyncIterable(response[key], new AgentStreamState(options), span, t0, base)
|
|
1280
|
+
[key]: wrapAsyncIterable(response[key], new AgentStreamState(options), span, t0, base, false)
|
|
1232
1281
|
};
|
|
1233
1282
|
};
|
|
1234
1283
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@telemetry-dev/bedrock",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "AWS Bedrock instrumentation for telemetry.dev: Converse, InvokeModel, and Bedrock Agents spans for AWS SDK v3 clients.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"aws",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"license": "MIT",
|
|
17
17
|
"repository": {
|
|
18
18
|
"type": "git",
|
|
19
|
-
"url": "git+https://github.com/telemetry-dev/telemetry.
|
|
19
|
+
"url": "git+https://github.com/telemetry-dev/telemetry.git",
|
|
20
20
|
"directory": "packages/bedrock"
|
|
21
21
|
},
|
|
22
22
|
"files": [
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"@smithy/eventstream-codec": "^4.2.5",
|
|
50
50
|
"@smithy/protocol-http": "^5.3.10",
|
|
51
51
|
"@smithy/types": "^4.12.0",
|
|
52
|
-
"@telemetry-dev/sdk": "^0.1.
|
|
52
|
+
"@telemetry-dev/sdk": "^0.1.5",
|
|
53
53
|
"@types/node": "^25.5.0",
|
|
54
54
|
"@typescript/native-preview": "7.0.0-dev.20260328.1",
|
|
55
55
|
"typescript": "^6.0.2",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"peerDependencies": {
|
|
60
60
|
"@aws-sdk/client-bedrock-agent-runtime": ">=3.600.0 <4",
|
|
61
61
|
"@aws-sdk/client-bedrock-runtime": ">=3.600.0 <4",
|
|
62
|
-
"@telemetry-dev/sdk": "^0.1.
|
|
62
|
+
"@telemetry-dev/sdk": "^0.1.5"
|
|
63
63
|
},
|
|
64
64
|
"peerDependenciesMeta": {
|
|
65
65
|
"@aws-sdk/client-bedrock-agent-runtime": {
|
package/src/agent-handlers.ts
CHANGED
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
|
|
21
21
|
export function agentInputMessages<T>(inputText: T): JsonValue {
|
|
22
22
|
const text = stringValue(inputText);
|
|
23
|
+
|
|
23
24
|
return text ? [{ role: "user", parts: [{ type: "text", content: text }] }] : undefined;
|
|
24
25
|
}
|
|
25
26
|
|
|
@@ -63,35 +64,47 @@ export class AgentStreamState implements StreamState {
|
|
|
63
64
|
|
|
64
65
|
feed<T>(event: T): void {
|
|
65
66
|
const raw: unknown = event;
|
|
67
|
+
|
|
66
68
|
if (!isRecord(raw)) return;
|
|
67
69
|
const streamError = modeledStreamError(raw);
|
|
70
|
+
|
|
68
71
|
if (streamError) {
|
|
69
72
|
this.error = streamError.error;
|
|
70
73
|
this.errorFields = streamError.fields;
|
|
74
|
+
|
|
71
75
|
return;
|
|
72
76
|
}
|
|
77
|
+
|
|
73
78
|
const chunk = isRecord(raw.chunk) ? raw.chunk : undefined;
|
|
74
79
|
const bytes = chunk?.bytes;
|
|
80
|
+
|
|
75
81
|
if (bytes !== undefined) this.text += bytesToString(bytes) ?? "";
|
|
76
82
|
const attribution = isRecord(chunk?.attribution) ? chunk.attribution : undefined;
|
|
77
83
|
const citations = arrayValue<unknown>(attribution?.citations);
|
|
84
|
+
|
|
78
85
|
if (citations) this.citationCount += citations.length;
|
|
79
86
|
|
|
80
87
|
const files = isRecord(raw.files) ? arrayValue<JsonValue>(raw.files.files) : undefined;
|
|
88
|
+
|
|
81
89
|
if (files) this.outputFiles.push(...files.map(sanitizeOutputFile));
|
|
82
90
|
|
|
83
91
|
const returnControl = isRecord(raw.returnControl) ? raw.returnControl : undefined;
|
|
92
|
+
|
|
84
93
|
if (returnControl) this.returnControl = returnControl;
|
|
85
94
|
|
|
86
95
|
const traceEvent = isRecord(raw.trace) ? raw.trace : undefined;
|
|
96
|
+
|
|
87
97
|
if (traceEvent) {
|
|
88
98
|
this.traceEventCount += 1;
|
|
99
|
+
|
|
89
100
|
if (this.options.captureAgentTrace) this.traces.push(traceEvent);
|
|
90
101
|
collectTrace(traceEvent, (usage) => this.addUsage(usage));
|
|
91
102
|
const failure = findKey(traceEvent, "failureTrace");
|
|
103
|
+
|
|
92
104
|
if (isRecord(failure))
|
|
93
105
|
this.failureReason = stringValue(failure.failureReason) ?? this.failureReason;
|
|
94
106
|
const guardrail = findKey(traceEvent, "guardrailTrace");
|
|
107
|
+
|
|
95
108
|
if (isRecord(guardrail))
|
|
96
109
|
this.guardrailAction = stringValue(guardrail.action) ?? this.guardrailAction;
|
|
97
110
|
}
|
|
@@ -108,6 +121,7 @@ export class AgentStreamState implements StreamState {
|
|
|
108
121
|
agent_trace:
|
|
109
122
|
this.options.captureAgentTrace && this.traces.length > 0 ? this.traces : undefined,
|
|
110
123
|
});
|
|
124
|
+
|
|
111
125
|
return mergeFields(
|
|
112
126
|
omitUndefined({
|
|
113
127
|
output: this.returnControl
|
|
@@ -124,14 +138,18 @@ export class AgentStreamState implements StreamState {
|
|
|
124
138
|
}
|
|
125
139
|
private addUsage<T>(value: T): void {
|
|
126
140
|
const raw: unknown = value;
|
|
141
|
+
|
|
127
142
|
if (!isRecord(raw)) return;
|
|
128
143
|
const inputTokens = numberValue(raw.inputTokens);
|
|
129
144
|
const outputTokens = numberValue(raw.outputTokens);
|
|
130
145
|
const totalTokens = numberValue(raw.totalTokens);
|
|
146
|
+
|
|
131
147
|
if (inputTokens !== undefined)
|
|
132
148
|
this.usage.inputTokens = (this.usage.inputTokens ?? 0) + inputTokens;
|
|
149
|
+
|
|
133
150
|
if (outputTokens !== undefined)
|
|
134
151
|
this.usage.outputTokens = (this.usage.outputTokens ?? 0) + outputTokens;
|
|
152
|
+
|
|
135
153
|
if (totalTokens !== undefined)
|
|
136
154
|
this.usage.totalTokens = (this.usage.totalTokens ?? 0) + totalTokens;
|
|
137
155
|
else if (inputTokens !== undefined || outputTokens !== undefined) {
|
|
@@ -142,7 +160,9 @@ export class AgentStreamState implements StreamState {
|
|
|
142
160
|
|
|
143
161
|
function sanitizeOutputFile<T>(value: T): JsonValue {
|
|
144
162
|
const raw: unknown = value;
|
|
163
|
+
|
|
145
164
|
if (!isRecord(raw)) return undefined;
|
|
165
|
+
|
|
146
166
|
return omitUndefined({
|
|
147
167
|
name: stringValue(raw.name),
|
|
148
168
|
type: stringValue(raw.type),
|
|
@@ -161,6 +181,7 @@ export function retrieveResponseFields<T>(output: T): SpanFields {
|
|
|
161
181
|
const raw: unknown = output;
|
|
162
182
|
const result = isRecord(raw) ? raw : {};
|
|
163
183
|
const retrievalResults = arrayValue<unknown>(result.retrievalResults);
|
|
184
|
+
|
|
164
185
|
return mergeFields(awsMetadataFields(result.$metadata), {
|
|
165
186
|
output: retrievalResults,
|
|
166
187
|
metadata: omitUndefined({
|
|
@@ -174,17 +195,21 @@ export function ragModel(input: JsonRecord): string | undefined {
|
|
|
174
195
|
const config = isRecord(input.retrieveAndGenerateConfiguration)
|
|
175
196
|
? input.retrieveAndGenerateConfiguration
|
|
176
197
|
: undefined;
|
|
198
|
+
|
|
177
199
|
const kb = isRecord(config?.knowledgeBaseConfiguration)
|
|
178
200
|
? config?.knowledgeBaseConfiguration
|
|
179
201
|
: undefined;
|
|
202
|
+
|
|
180
203
|
const external = isRecord(config?.externalSourcesConfiguration)
|
|
181
204
|
? config?.externalSourcesConfiguration
|
|
182
205
|
: undefined;
|
|
206
|
+
|
|
183
207
|
return stringValue(kb?.modelArn) ?? stringValue(external?.modelArn);
|
|
184
208
|
}
|
|
185
209
|
|
|
186
210
|
export function ragRequestFields(input: JsonRecord): SpanFields {
|
|
187
211
|
const text = isRecord(input.input) ? stringValue(input.input.text) : undefined;
|
|
212
|
+
|
|
188
213
|
return omitUndefined({
|
|
189
214
|
provider: PROVIDER,
|
|
190
215
|
model: ragModel(input),
|
|
@@ -197,6 +222,7 @@ export function ragResponseFields<T>(output: T): SpanFields {
|
|
|
197
222
|
const raw: unknown = output;
|
|
198
223
|
const result = isRecord(raw) ? raw : {};
|
|
199
224
|
const text = isRecord(result.output) ? stringValue(result.output.text) : undefined;
|
|
225
|
+
|
|
200
226
|
return mergeFields(awsMetadataFields(result.$metadata), {
|
|
201
227
|
output: text ? [{ role: "assistant", parts: [{ type: "text", content: text }] }] : undefined,
|
|
202
228
|
metadata: omitUndefined({
|
|
@@ -216,15 +242,20 @@ export class RagStreamState implements StreamState {
|
|
|
216
242
|
|
|
217
243
|
feed<T>(event: T): void {
|
|
218
244
|
const raw: unknown = event;
|
|
245
|
+
|
|
219
246
|
if (!isRecord(raw)) return;
|
|
220
247
|
const streamError = modeledStreamError(raw);
|
|
248
|
+
|
|
221
249
|
if (streamError) {
|
|
222
250
|
this.error = streamError.error;
|
|
223
251
|
this.errorFields = streamError.fields;
|
|
252
|
+
|
|
224
253
|
return;
|
|
225
254
|
}
|
|
255
|
+
|
|
226
256
|
const output = isRecord(raw.output) ? raw.output : undefined;
|
|
227
257
|
this.text += stringValue(output?.text) ?? "";
|
|
258
|
+
|
|
228
259
|
if (raw.citation) this.citationCount += 1;
|
|
229
260
|
const guardrail = isRecord(raw.guardrail) ? raw.guardrail : undefined;
|
|
230
261
|
this.guardrailAction = stringValue(guardrail?.action) ?? this.guardrailAction;
|
|
@@ -263,18 +294,25 @@ export class FlowStreamState implements StreamState {
|
|
|
263
294
|
|
|
264
295
|
feed<T>(event: T): void {
|
|
265
296
|
const raw: unknown = event;
|
|
297
|
+
|
|
266
298
|
if (!isRecord(raw)) return;
|
|
267
299
|
const streamError = modeledStreamError(raw);
|
|
300
|
+
|
|
268
301
|
if (streamError) {
|
|
269
302
|
this.error = streamError.error;
|
|
270
303
|
this.errorFields = streamError.fields;
|
|
304
|
+
|
|
271
305
|
return;
|
|
272
306
|
}
|
|
307
|
+
|
|
273
308
|
const output = isRecord(raw.flowOutputEvent) ? raw.flowOutputEvent : undefined;
|
|
309
|
+
|
|
274
310
|
if (output) this.outputs.push(output.content);
|
|
311
|
+
|
|
275
312
|
const inputRequest = isRecord(raw.flowMultiTurnInputRequestEvent)
|
|
276
313
|
? raw.flowMultiTurnInputRequestEvent
|
|
277
314
|
: undefined;
|
|
315
|
+
|
|
278
316
|
if (inputRequest) this.outputs.push(inputRequest.content);
|
|
279
317
|
const completion = isRecord(raw.flowCompletionEvent) ? raw.flowCompletionEvent : undefined;
|
|
280
318
|
this.completionReason = stringValue(completion?.completionReason) ?? this.completionReason;
|
|
@@ -302,12 +340,15 @@ export function ragName(input: JsonRecord): string {
|
|
|
302
340
|
|
|
303
341
|
function collectTrace<T>(value: T, onUsage: <TUsage>(usage: TUsage) => void): void {
|
|
304
342
|
const raw: unknown = value;
|
|
343
|
+
|
|
305
344
|
if (!isRecord(raw)) return;
|
|
306
345
|
const output = isRecord(raw.modelInvocationOutput) ? raw.modelInvocationOutput : undefined;
|
|
346
|
+
|
|
307
347
|
if (output) {
|
|
308
348
|
const metadata = isRecord(output.metadata) ? output.metadata : undefined;
|
|
309
349
|
onUsage(metadata?.usage);
|
|
310
350
|
}
|
|
351
|
+
|
|
311
352
|
for (const child of Object.values(raw)) {
|
|
312
353
|
if (isRecord(child)) collectTrace(child, onUsage);
|
|
313
354
|
else if (Array.isArray(child)) child.forEach((item) => collectTrace(item, onUsage));
|
|
@@ -316,11 +357,16 @@ function collectTrace<T>(value: T, onUsage: <TUsage>(usage: TUsage) => void): vo
|
|
|
316
357
|
|
|
317
358
|
function findKey<T>(value: T, key: string): JsonValue {
|
|
318
359
|
const raw: unknown = value;
|
|
360
|
+
|
|
319
361
|
if (!isRecord(raw)) return undefined;
|
|
362
|
+
|
|
320
363
|
if (raw[key] !== undefined) return raw[key];
|
|
364
|
+
|
|
321
365
|
for (const child of Object.values(raw)) {
|
|
322
366
|
const found = findKey(child, key);
|
|
367
|
+
|
|
323
368
|
if (found !== undefined) return found;
|
|
324
369
|
}
|
|
370
|
+
|
|
325
371
|
return undefined;
|
|
326
372
|
}
|
package/src/agents.ts
CHANGED
|
@@ -28,6 +28,7 @@ export function wrapBedrockAgents<T extends WrappableBedrockAgentClient>(
|
|
|
28
28
|
writable: true,
|
|
29
29
|
});
|
|
30
30
|
WRAPPED.add(client as object);
|
|
31
|
+
|
|
31
32
|
return client;
|
|
32
33
|
}
|
|
33
34
|
|
|
@@ -37,13 +38,16 @@ export function instrumentBedrockAgents(options: BedrockInstrumentationOptions =
|
|
|
37
38
|
const hadOwn = Object.prototype.hasOwnProperty.call(proto, "send");
|
|
38
39
|
const original = proto.send;
|
|
39
40
|
const instrumentedSend = createInstrumentedSend(original, options, AGENT_HANDLERS);
|
|
41
|
+
|
|
40
42
|
const wrapper = function telemetryDevBedrockAgentSend(
|
|
41
43
|
this: WrappableBedrockAgentClient,
|
|
42
44
|
...args: unknown[]
|
|
43
45
|
) {
|
|
44
46
|
if (WRAPPED.has(this as object)) return original.apply(this, args);
|
|
47
|
+
|
|
45
48
|
return instrumentedSend.apply(this, args);
|
|
46
49
|
};
|
|
50
|
+
|
|
47
51
|
ORIGINAL = { proto, hadOwn, value: original, wrapper };
|
|
48
52
|
Object.defineProperty(proto, "send", {
|
|
49
53
|
configurable: true,
|
|
@@ -54,9 +58,12 @@ export function instrumentBedrockAgents(options: BedrockInstrumentationOptions =
|
|
|
54
58
|
|
|
55
59
|
export function uninstrumentBedrockAgents(): void {
|
|
56
60
|
const original = ORIGINAL;
|
|
61
|
+
|
|
57
62
|
if (!original) return;
|
|
63
|
+
|
|
58
64
|
if (Object.getOwnPropertyDescriptor(original.proto, "send")?.value !== original.wrapper) return;
|
|
59
65
|
ORIGINAL = undefined;
|
|
66
|
+
|
|
60
67
|
if (original.hadOwn) {
|
|
61
68
|
Object.defineProperty(original.proto, "send", {
|
|
62
69
|
configurable: true,
|