@deepagents/devtool 0.0.0-stage → 7.0.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 +100 -2
- package/dist/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +44 -0
- package/dist/index.js.map +7 -0
- package/dist/traces/file-trace-adapter.d.ts +53 -0
- package/dist/traces/file-trace-adapter.d.ts.map +1 -0
- package/dist/traces/http.d.ts +4 -0
- package/dist/traces/http.d.ts.map +1 -0
- package/dist/traces/index.d.ts +11 -0
- package/dist/traces/index.d.ts.map +1 -0
- package/dist/traces/index.js +474 -0
- package/dist/traces/index.js.map +7 -0
- package/dist/ui/assets/chat-BGxkfkmM.js +3591 -0
- package/dist/ui/assets/chunk-YOKDWASO-DZenLjDt.js +142 -0
- package/dist/ui/assets/highlighted-body-KPVGNVTW-DQLM-Ya_.js +1 -0
- package/dist/ui/assets/index-BgkaRF27.css +2 -0
- package/dist/ui/assets/index-hTsvNY6P.js +273 -0
- package/dist/ui/assets/mermaid-HWGCJPDP-D2O5qlT-.js +1 -0
- package/dist/ui/index.html +21 -0
- package/package.json +76 -4
|
@@ -0,0 +1,474 @@
|
|
|
1
|
+
// packages/devtool/host/src/traces/index.ts
|
|
2
|
+
import { OpenTelemetry } from "@ai-sdk/otel";
|
|
3
|
+
import { SpanKind, SpanStatusCode } from "@opentelemetry/api";
|
|
4
|
+
import { ExportResultCode } from "@opentelemetry/core";
|
|
5
|
+
import {
|
|
6
|
+
BasicTracerProvider,
|
|
7
|
+
SimpleSpanProcessor
|
|
8
|
+
} from "@opentelemetry/sdk-trace-base";
|
|
9
|
+
import {
|
|
10
|
+
ATTR_GEN_AI_AGENT_NAME as ATTR_GEN_AI_AGENT_NAME2,
|
|
11
|
+
ATTR_SESSION_ID as ATTR_SESSION_ID2,
|
|
12
|
+
ATTR_USER_ID as ATTR_USER_ID2
|
|
13
|
+
} from "@opentelemetry/semantic-conventions/incubating";
|
|
14
|
+
import { appendFileSync, mkdirSync } from "node:fs";
|
|
15
|
+
import { dirname, resolve } from "node:path";
|
|
16
|
+
import { pathToFileURL } from "node:url";
|
|
17
|
+
|
|
18
|
+
// packages/devtool/host/src/traces/file-trace-adapter.ts
|
|
19
|
+
import {
|
|
20
|
+
ATTR_GEN_AI_AGENT_NAME,
|
|
21
|
+
ATTR_GEN_AI_INPUT_MESSAGES,
|
|
22
|
+
ATTR_GEN_AI_OPERATION_NAME,
|
|
23
|
+
ATTR_GEN_AI_OUTPUT_MESSAGES,
|
|
24
|
+
ATTR_GEN_AI_REQUEST_MODEL,
|
|
25
|
+
ATTR_GEN_AI_RESPONSE_FINISH_REASONS,
|
|
26
|
+
ATTR_GEN_AI_TOOL_CALL_ARGUMENTS,
|
|
27
|
+
ATTR_GEN_AI_TOOL_CALL_RESULT,
|
|
28
|
+
ATTR_GEN_AI_TOOL_NAME,
|
|
29
|
+
ATTR_GEN_AI_USAGE_INPUT_TOKENS,
|
|
30
|
+
ATTR_GEN_AI_USAGE_OUTPUT_TOKENS,
|
|
31
|
+
ATTR_SESSION_ID,
|
|
32
|
+
ATTR_USER_ID
|
|
33
|
+
} from "@opentelemetry/semantic-conventions/incubating";
|
|
34
|
+
import { readFile } from "node:fs/promises";
|
|
35
|
+
import { fileURLToPath } from "node:url";
|
|
36
|
+
var AGENT_PATH = "deepagents.agent.path";
|
|
37
|
+
var RECORD_INPUTS = "deepagents.record.inputs";
|
|
38
|
+
var RECORD_OUTPUTS = "deepagents.record.outputs";
|
|
39
|
+
var SPAN_STATUS = "deepagents.span.status";
|
|
40
|
+
var SPAN_TYPE = "deepagents.span.type";
|
|
41
|
+
var STREAM_ID = "deepagents.stream.id";
|
|
42
|
+
var ERROR = "STATUS_CODE_ERROR";
|
|
43
|
+
var FileTraceAdapter = class {
|
|
44
|
+
#path;
|
|
45
|
+
constructor(path) {
|
|
46
|
+
this.#path = fileURLToPath(path);
|
|
47
|
+
}
|
|
48
|
+
async list({ chatId, userId }) {
|
|
49
|
+
return (await this.#project()).filter((trace) => trace.chatId === chatId && trace.userId === userId).sort(
|
|
50
|
+
(left, right) => (right.startedAt ?? "").localeCompare(left.startedAt ?? "")
|
|
51
|
+
).map(({ spans: _spans, ...summary }) => summary);
|
|
52
|
+
}
|
|
53
|
+
async get({ chatId, userId }, traceId) {
|
|
54
|
+
return (await this.#project()).find(
|
|
55
|
+
(trace) => trace.id === traceId && trace.chatId === chatId && trace.userId === userId
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
async #project() {
|
|
59
|
+
return [
|
|
60
|
+
...Map.groupBy(await readSpans(this.#path), (span) => span.trace_id)
|
|
61
|
+
].map(([traceId, spans]) => projectTrace(traceId, spans)).filter((trace) => trace !== void 0);
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
function projectTrace(traceId, spans) {
|
|
65
|
+
const context = readContext(spans);
|
|
66
|
+
if (!context) return void 0;
|
|
67
|
+
const root = spans.find(
|
|
68
|
+
(span) => span.attributes[SPAN_TYPE] === "operation" && span.attributes[ATTR_GEN_AI_OPERATION_NAME] === "invoke_agent"
|
|
69
|
+
);
|
|
70
|
+
const visible = spans.filter((span) => spanType(span)).sort((left, right) => left.start_time.localeCompare(right.start_time));
|
|
71
|
+
const byId = new Map(spans.map((span) => [span.span_id, span]));
|
|
72
|
+
const generationByStep = new Map(
|
|
73
|
+
spans.flatMap(
|
|
74
|
+
(span) => span.attributes[SPAN_TYPE] === "languageModel" && span.parent_span_id ? [[span.parent_span_id, span.span_id]] : []
|
|
75
|
+
)
|
|
76
|
+
);
|
|
77
|
+
const projected = visible.map(
|
|
78
|
+
(span) => projectSpan(span, byId, generationByStep, context.agentName)
|
|
79
|
+
);
|
|
80
|
+
return {
|
|
81
|
+
id: traceId,
|
|
82
|
+
...context,
|
|
83
|
+
workflowName: context.agentName,
|
|
84
|
+
startedAt: root?.start_time ?? spans[0]?.start_time ?? null,
|
|
85
|
+
endedAt: root?.end_time ?? null,
|
|
86
|
+
status: root ? spanStatus(root) : "running",
|
|
87
|
+
stepCount: projected.filter(({ type }) => type === "generation").length,
|
|
88
|
+
finishReason: firstString(root?.attributes[ATTR_GEN_AI_RESPONSE_FINISH_REASONS]) ?? null,
|
|
89
|
+
usage: readUsage(root?.attributes) ?? sumUsage(visible),
|
|
90
|
+
recording: {
|
|
91
|
+
inputs: recordingState(
|
|
92
|
+
root?.attributes[RECORD_INPUTS],
|
|
93
|
+
spans.some(
|
|
94
|
+
({ attributes }) => has(
|
|
95
|
+
attributes,
|
|
96
|
+
ATTR_GEN_AI_INPUT_MESSAGES,
|
|
97
|
+
ATTR_GEN_AI_TOOL_CALL_ARGUMENTS
|
|
98
|
+
)
|
|
99
|
+
)
|
|
100
|
+
),
|
|
101
|
+
outputs: recordingState(
|
|
102
|
+
root?.attributes[RECORD_OUTPUTS],
|
|
103
|
+
spans.some(
|
|
104
|
+
({ attributes }) => has(
|
|
105
|
+
attributes,
|
|
106
|
+
ATTR_GEN_AI_OUTPUT_MESSAGES,
|
|
107
|
+
ATTR_GEN_AI_TOOL_CALL_RESULT
|
|
108
|
+
)
|
|
109
|
+
)
|
|
110
|
+
)
|
|
111
|
+
},
|
|
112
|
+
spans: projected
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
function projectSpan(span, byId, generationByStep, agentName) {
|
|
116
|
+
const type = spanType(span);
|
|
117
|
+
const input = jsonAttribute(
|
|
118
|
+
span.attributes,
|
|
119
|
+
type === "function" ? ATTR_GEN_AI_TOOL_CALL_ARGUMENTS : ATTR_GEN_AI_INPUT_MESSAGES
|
|
120
|
+
);
|
|
121
|
+
const output = jsonAttribute(
|
|
122
|
+
span.attributes,
|
|
123
|
+
type === "function" ? ATTR_GEN_AI_TOOL_CALL_RESULT : ATTR_GEN_AI_OUTPUT_MESSAGES
|
|
124
|
+
);
|
|
125
|
+
const usage = readUsage(span.attributes);
|
|
126
|
+
const exceptions = span.events.filter(({ name }) => name === "exception").map(({ attributes }) => attributes);
|
|
127
|
+
const error = span.status.code === ERROR || exceptions.length ? { ...span.status, exceptions } : void 0;
|
|
128
|
+
return {
|
|
129
|
+
id: span.span_id,
|
|
130
|
+
traceId: span.trace_id,
|
|
131
|
+
parentId: visibleParent(span, byId, generationByStep),
|
|
132
|
+
startedAt: span.start_time,
|
|
133
|
+
endedAt: span.end_time,
|
|
134
|
+
status: spanStatus(span),
|
|
135
|
+
type,
|
|
136
|
+
name: type === "agent" ? agentName : String(
|
|
137
|
+
span.attributes[type === "generation" ? ATTR_GEN_AI_REQUEST_MODEL : ATTR_GEN_AI_TOOL_NAME] ?? span.name
|
|
138
|
+
),
|
|
139
|
+
...input === void 0 ? {} : { input },
|
|
140
|
+
...output === void 0 ? {} : { output },
|
|
141
|
+
...usage === void 0 ? {} : { usage },
|
|
142
|
+
...error === void 0 ? {} : { error },
|
|
143
|
+
data: {
|
|
144
|
+
name: span.name,
|
|
145
|
+
kind: span.kind,
|
|
146
|
+
attributes: span.attributes,
|
|
147
|
+
events: span.events,
|
|
148
|
+
status: span.status
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
function visibleParent(span, byId, generationByStep) {
|
|
153
|
+
if (!span.parent_span_id) return null;
|
|
154
|
+
const parent = byId.get(span.parent_span_id);
|
|
155
|
+
if (!parent) return null;
|
|
156
|
+
if (parent.attributes[SPAN_TYPE] !== "step") return span.parent_span_id;
|
|
157
|
+
return span.attributes[SPAN_TYPE] === "tool" ? generationByStep.get(parent.span_id) ?? parent.parent_span_id ?? null : parent.parent_span_id || null;
|
|
158
|
+
}
|
|
159
|
+
function readContext(spans) {
|
|
160
|
+
const attributes = spans.find(
|
|
161
|
+
({ attributes: attributes2 }) => [
|
|
162
|
+
ATTR_SESSION_ID,
|
|
163
|
+
ATTR_USER_ID,
|
|
164
|
+
STREAM_ID,
|
|
165
|
+
ATTR_GEN_AI_AGENT_NAME,
|
|
166
|
+
AGENT_PATH
|
|
167
|
+
].every((key) => typeof attributes2[key] === "string")
|
|
168
|
+
)?.attributes;
|
|
169
|
+
if (!attributes) return void 0;
|
|
170
|
+
return {
|
|
171
|
+
chatId: attributes[ATTR_SESSION_ID],
|
|
172
|
+
userId: attributes[ATTR_USER_ID],
|
|
173
|
+
streamId: attributes[STREAM_ID],
|
|
174
|
+
agentName: attributes[ATTR_GEN_AI_AGENT_NAME],
|
|
175
|
+
agentPath: attributes[AGENT_PATH]
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
function spanType(span) {
|
|
179
|
+
return {
|
|
180
|
+
operation: "agent",
|
|
181
|
+
languageModel: "generation",
|
|
182
|
+
tool: "function"
|
|
183
|
+
}[String(span.attributes[SPAN_TYPE])];
|
|
184
|
+
}
|
|
185
|
+
function readUsage(attributes) {
|
|
186
|
+
const inputTokens = attributes?.[ATTR_GEN_AI_USAGE_INPUT_TOKENS];
|
|
187
|
+
const outputTokens = attributes?.[ATTR_GEN_AI_USAGE_OUTPUT_TOKENS];
|
|
188
|
+
return typeof inputTokens === "number" && typeof outputTokens === "number" ? { inputTokens, outputTokens } : void 0;
|
|
189
|
+
}
|
|
190
|
+
function sumUsage(spans) {
|
|
191
|
+
return spans.reduce(
|
|
192
|
+
(total, span) => {
|
|
193
|
+
const usage = readUsage(span.attributes);
|
|
194
|
+
return usage ? {
|
|
195
|
+
inputTokens: total.inputTokens + usage.inputTokens,
|
|
196
|
+
outputTokens: total.outputTokens + usage.outputTokens
|
|
197
|
+
} : total;
|
|
198
|
+
},
|
|
199
|
+
{ inputTokens: 0, outputTokens: 0 }
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
function jsonAttribute(attributes, key) {
|
|
203
|
+
const value = attributes[key];
|
|
204
|
+
if (typeof value !== "string") return void 0;
|
|
205
|
+
try {
|
|
206
|
+
return JSON.parse(value);
|
|
207
|
+
} catch {
|
|
208
|
+
return value;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
function has(attributes, ...keys) {
|
|
212
|
+
return keys.some((key) => Object.hasOwn(attributes, key));
|
|
213
|
+
}
|
|
214
|
+
function recordingState(policy, observed) {
|
|
215
|
+
return policy === true || policy !== false && observed ? "recorded" : "not-recorded";
|
|
216
|
+
}
|
|
217
|
+
function spanStatus(span) {
|
|
218
|
+
if (span.attributes[SPAN_STATUS] === "cancelled") return "cancelled";
|
|
219
|
+
return span.status.code === ERROR ? "failed" : "completed";
|
|
220
|
+
}
|
|
221
|
+
function firstString(value) {
|
|
222
|
+
return Array.isArray(value) && typeof value[0] === "string" ? value[0] : void 0;
|
|
223
|
+
}
|
|
224
|
+
async function readSpans(path) {
|
|
225
|
+
let contents;
|
|
226
|
+
try {
|
|
227
|
+
contents = await readFile(path, "utf8");
|
|
228
|
+
} catch (error) {
|
|
229
|
+
if (isRecord(error) && error.code === "ENOENT") return [];
|
|
230
|
+
throw error;
|
|
231
|
+
}
|
|
232
|
+
const lines = contents.split("\n");
|
|
233
|
+
if (lines.at(-1) === "") lines.pop();
|
|
234
|
+
return lines.flatMap((line, index) => {
|
|
235
|
+
if (!line.trim()) return [];
|
|
236
|
+
let span;
|
|
237
|
+
try {
|
|
238
|
+
span = JSON.parse(line);
|
|
239
|
+
} catch (error) {
|
|
240
|
+
if (index === lines.length - 1 && !contents.endsWith("\n")) return [];
|
|
241
|
+
throw error;
|
|
242
|
+
}
|
|
243
|
+
if (!span || typeof span.trace_id !== "string" || typeof span.span_id !== "string" || !Number.isFinite(Date.parse(span.start_time)) || !isRecord(span.attributes)) {
|
|
244
|
+
throw new TypeError(`Invalid Halo trace record in "${path}"`);
|
|
245
|
+
}
|
|
246
|
+
return [span];
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
function isRecord(value) {
|
|
250
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// packages/devtool/host/src/traces/http.ts
|
|
254
|
+
import { Hono } from "hono";
|
|
255
|
+
import { HTTPException } from "hono/http-exception";
|
|
256
|
+
import {
|
|
257
|
+
projectHttp
|
|
258
|
+
} from "@deepagents/experimental/zukhruf/http";
|
|
259
|
+
var TRACES_PATH = "/traces";
|
|
260
|
+
var NO_STORE = { "cache-control": "no-store" };
|
|
261
|
+
function tracesHttp(definition) {
|
|
262
|
+
return projectHttp(definition, (plugin, runtime) => ({
|
|
263
|
+
capabilities: { traces: { path: TRACES_PATH } },
|
|
264
|
+
authenticatedRoutes: traceRoutes(plugin.traces, runtime)
|
|
265
|
+
}));
|
|
266
|
+
}
|
|
267
|
+
function traceRoutes(reader, runtime) {
|
|
268
|
+
const app = new Hono();
|
|
269
|
+
app.get(`${TRACES_PATH}/:chatId`, async (context) => {
|
|
270
|
+
const conversation = await requireConversation(runtime, {
|
|
271
|
+
chatId: context.req.param("chatId"),
|
|
272
|
+
userId: context.get("userId")
|
|
273
|
+
});
|
|
274
|
+
return context.json(
|
|
275
|
+
await Promise.all(
|
|
276
|
+
(await reader.list(conversation)).map(
|
|
277
|
+
(trace) => withDurableStatus(runtime, trace)
|
|
278
|
+
)
|
|
279
|
+
),
|
|
280
|
+
200,
|
|
281
|
+
NO_STORE
|
|
282
|
+
);
|
|
283
|
+
});
|
|
284
|
+
app.get(`${TRACES_PATH}/:chatId/:traceId`, async (context) => {
|
|
285
|
+
const conversation = await requireConversation(runtime, {
|
|
286
|
+
chatId: context.req.param("chatId"),
|
|
287
|
+
userId: context.get("userId")
|
|
288
|
+
});
|
|
289
|
+
const traceId = context.req.param("traceId");
|
|
290
|
+
const trace = await reader.get(conversation, traceId);
|
|
291
|
+
if (!trace) {
|
|
292
|
+
throw new HTTPException(404, {
|
|
293
|
+
message: "Trace not found",
|
|
294
|
+
cause: {
|
|
295
|
+
code: "traces/trace-not-found",
|
|
296
|
+
detail: `Trace ${traceId} does not exist in conversation ${conversation.chatId}`
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
return context.json(await withDurableStatus(runtime, trace), 200, NO_STORE);
|
|
301
|
+
});
|
|
302
|
+
return app;
|
|
303
|
+
}
|
|
304
|
+
async function requireConversation(runtime, conversation) {
|
|
305
|
+
const owned = (await runtime.listHistory(conversation.userId)).some(
|
|
306
|
+
(item) => item.chatId === conversation.chatId && item.userId === conversation.userId
|
|
307
|
+
);
|
|
308
|
+
if (owned) return conversation;
|
|
309
|
+
throw new HTTPException(404, {
|
|
310
|
+
message: "Conversation not found",
|
|
311
|
+
cause: {
|
|
312
|
+
code: "traces/conversation-not-found",
|
|
313
|
+
detail: `Conversation ${conversation.chatId} does not exist`
|
|
314
|
+
}
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
async function withDurableStatus(runtime, trace) {
|
|
318
|
+
const turn = await runtime.observe({ chatId: trace.chatId, userId: trace.userId }).status(trace.streamId);
|
|
319
|
+
return { ...trace, status: turn?.status ?? trace.status };
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// packages/devtool/host/src/traces/index.ts
|
|
323
|
+
var CALL_ID = "deepagents.call.id";
|
|
324
|
+
var RECORD_INPUTS2 = "deepagents.record.inputs";
|
|
325
|
+
var RECORD_OUTPUTS2 = "deepagents.record.outputs";
|
|
326
|
+
var SPAN_STATUS2 = "deepagents.span.status";
|
|
327
|
+
var SPAN_TYPE2 = "deepagents.span.type";
|
|
328
|
+
function fileTelemetry(options) {
|
|
329
|
+
const path = resolve(options.path);
|
|
330
|
+
return {
|
|
331
|
+
name: `file-telemetry:${pathToFileURL(path).href}`,
|
|
332
|
+
create: () => {
|
|
333
|
+
const calls = /* @__PURE__ */ new Map();
|
|
334
|
+
const provider = new BasicTracerProvider({
|
|
335
|
+
spanProcessors: [
|
|
336
|
+
new SimpleSpanProcessor(
|
|
337
|
+
fileExporter(path, calls, options.onWriteError)
|
|
338
|
+
)
|
|
339
|
+
]
|
|
340
|
+
});
|
|
341
|
+
return {
|
|
342
|
+
traces: new FileTraceAdapter(pathToFileURL(path)),
|
|
343
|
+
telemetry: (context) => openTelemetry(provider, context, calls),
|
|
344
|
+
work: () => Promise.resolve({
|
|
345
|
+
[Symbol.asyncDispose]: async () => {
|
|
346
|
+
await provider.shutdown();
|
|
347
|
+
calls.clear();
|
|
348
|
+
}
|
|
349
|
+
})
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
function fileExporter(path, calls, onWriteError) {
|
|
355
|
+
let initialized = false;
|
|
356
|
+
return {
|
|
357
|
+
export(spans, done) {
|
|
358
|
+
try {
|
|
359
|
+
if (!initialized) {
|
|
360
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
361
|
+
initialized = true;
|
|
362
|
+
}
|
|
363
|
+
appendFileSync(
|
|
364
|
+
path,
|
|
365
|
+
`${spans.map((span) => JSON.stringify(flattenSpan(span, calls))).join("\n")}
|
|
366
|
+
`
|
|
367
|
+
);
|
|
368
|
+
done({ code: ExportResultCode.SUCCESS });
|
|
369
|
+
} catch (error) {
|
|
370
|
+
try {
|
|
371
|
+
Promise.resolve(onWriteError?.(error)).catch(() => {
|
|
372
|
+
});
|
|
373
|
+
} catch {
|
|
374
|
+
}
|
|
375
|
+
done({
|
|
376
|
+
code: ExportResultCode.FAILED,
|
|
377
|
+
error: error instanceof Error ? error : new Error(String(error))
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
},
|
|
381
|
+
shutdown: () => Promise.resolve()
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
function openTelemetry(provider, context, calls) {
|
|
385
|
+
const telemetry = new OpenTelemetry({
|
|
386
|
+
tracer: provider.getTracer("@deepagents/devtool/traces"),
|
|
387
|
+
usage: true,
|
|
388
|
+
providerMetadata: true,
|
|
389
|
+
enrichSpan: ({ spanType: spanType2, callId }) => {
|
|
390
|
+
const call = calls.get(callId);
|
|
391
|
+
return {
|
|
392
|
+
[ATTR_SESSION_ID2]: context.conversation.chatId,
|
|
393
|
+
[ATTR_USER_ID2]: context.conversation.userId,
|
|
394
|
+
[ATTR_GEN_AI_AGENT_NAME2]: context.agentName,
|
|
395
|
+
"deepagents.stream.id": context.streamId,
|
|
396
|
+
"deepagents.agent.path": context.agentPath,
|
|
397
|
+
[CALL_ID]: callId,
|
|
398
|
+
[SPAN_TYPE2]: spanType2,
|
|
399
|
+
...call ? {
|
|
400
|
+
[RECORD_INPUTS2]: call.recordInputs,
|
|
401
|
+
[RECORD_OUTPUTS2]: call.recordOutputs
|
|
402
|
+
} : {}
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
});
|
|
406
|
+
const onStart = telemetry.onStart.bind(telemetry);
|
|
407
|
+
telemetry.onStart = (event) => {
|
|
408
|
+
calls.set(event.callId, {
|
|
409
|
+
recordInputs: event.recordInputs !== false,
|
|
410
|
+
recordOutputs: event.recordOutputs !== false
|
|
411
|
+
});
|
|
412
|
+
onStart(event);
|
|
413
|
+
};
|
|
414
|
+
const onAbort = telemetry.onAbort.bind(telemetry);
|
|
415
|
+
telemetry.onAbort = (event) => {
|
|
416
|
+
const call = calls.get(event.callId);
|
|
417
|
+
if (call) call.status = "cancelled";
|
|
418
|
+
onAbort(event);
|
|
419
|
+
};
|
|
420
|
+
return telemetry;
|
|
421
|
+
}
|
|
422
|
+
function flattenSpan(span, calls) {
|
|
423
|
+
const context = span.spanContext();
|
|
424
|
+
const callId = span.attributes[CALL_ID];
|
|
425
|
+
const call = typeof callId === "string" ? calls.get(callId) : void 0;
|
|
426
|
+
const flattened = {
|
|
427
|
+
trace_id: context.traceId,
|
|
428
|
+
span_id: context.spanId,
|
|
429
|
+
parent_span_id: span.parentSpanContext?.spanId ?? "",
|
|
430
|
+
trace_state: context.traceState?.serialize() ?? "",
|
|
431
|
+
name: span.name,
|
|
432
|
+
kind: `SPAN_KIND_${SpanKind[span.kind]}`,
|
|
433
|
+
start_time: timestamp(span.startTime),
|
|
434
|
+
end_time: timestamp(span.endTime),
|
|
435
|
+
status: {
|
|
436
|
+
code: `STATUS_CODE_${SpanStatusCode[span.status.code]}`,
|
|
437
|
+
message: span.status.message ?? ""
|
|
438
|
+
},
|
|
439
|
+
resource: { attributes: span.resource.attributes },
|
|
440
|
+
scope: span.instrumentationScope,
|
|
441
|
+
attributes: haloAttributes(span, call),
|
|
442
|
+
events: span.events.map((event) => ({
|
|
443
|
+
name: event.name,
|
|
444
|
+
timestamp: timestamp(event.time),
|
|
445
|
+
attributes: event.attributes ?? {}
|
|
446
|
+
}))
|
|
447
|
+
};
|
|
448
|
+
if (span.attributes[SPAN_TYPE2] === "operation" && typeof callId === "string")
|
|
449
|
+
calls.delete(callId);
|
|
450
|
+
return flattened;
|
|
451
|
+
}
|
|
452
|
+
function haloAttributes(span, call) {
|
|
453
|
+
const attributes = span.attributes;
|
|
454
|
+
const kind = {
|
|
455
|
+
operation: "AGENT",
|
|
456
|
+
step: "CHAIN",
|
|
457
|
+
languageModel: "LLM",
|
|
458
|
+
tool: "TOOL"
|
|
459
|
+
}[String(attributes["deepagents.span.type"])];
|
|
460
|
+
return {
|
|
461
|
+
...attributes,
|
|
462
|
+
"openinference.span.kind": kind,
|
|
463
|
+
...call?.status ? { [SPAN_STATUS2]: call.status } : {}
|
|
464
|
+
};
|
|
465
|
+
}
|
|
466
|
+
function timestamp([seconds, nanoseconds]) {
|
|
467
|
+
return `${new Date(seconds * 1e3).toISOString().slice(0, -5)}.${String(nanoseconds).padStart(9, "0")}Z`;
|
|
468
|
+
}
|
|
469
|
+
export {
|
|
470
|
+
FileTraceAdapter,
|
|
471
|
+
fileTelemetry,
|
|
472
|
+
tracesHttp
|
|
473
|
+
};
|
|
474
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/traces/index.ts", "../../src/traces/file-trace-adapter.ts", "../../src/traces/http.ts"],
|
|
4
|
+
"sourcesContent": ["import { OpenTelemetry } from '@ai-sdk/otel';\nimport { type HrTime, SpanKind, SpanStatusCode } from '@opentelemetry/api';\nimport { ExportResultCode } from '@opentelemetry/core';\nimport {\n BasicTracerProvider,\n type ReadableSpan,\n SimpleSpanProcessor,\n type SpanExporter,\n} from '@opentelemetry/sdk-trace-base';\nimport {\n ATTR_GEN_AI_AGENT_NAME,\n ATTR_SESSION_ID,\n ATTR_USER_ID,\n} from '@opentelemetry/semantic-conventions/incubating';\nimport { appendFileSync, mkdirSync } from 'node:fs';\nimport { dirname, resolve } from 'node:path';\nimport { pathToFileURL } from 'node:url';\n\nimport type { FileTelemetryOptions } from '@deepagents/context/telemetry/file';\nimport type {\n AgentPluginDefinition,\n AgentPluginToolContext,\n} from '@deepagents/experimental/zukhruf';\n\nimport { FileTraceAdapter } from './file-trace-adapter.ts';\nimport type { AgentTraceReader } from './file-trace-adapter.ts';\n\nexport * from './file-trace-adapter.ts';\nexport { tracesHttp } from './http.ts';\n\nconst CALL_ID = 'deepagents.call.id';\nconst RECORD_INPUTS = 'deepagents.record.inputs';\nconst RECORD_OUTPUTS = 'deepagents.record.outputs';\nconst SPAN_STATUS = 'deepagents.span.status';\nconst SPAN_TYPE = 'deepagents.span.type';\n\ninterface TraceCallState {\n recordInputs: boolean;\n recordOutputs: boolean;\n status?: 'cancelled';\n}\n\nexport interface FileTelemetryInstance {\n readonly traces: AgentTraceReader;\n}\n\n/** AI SDK OpenTelemetry spans persisted in Halo's flat JSONL format. */\nexport function fileTelemetry(\n options: FileTelemetryOptions,\n): AgentPluginDefinition<FileTelemetryInstance> {\n const path = resolve(options.path);\n return {\n name: `file-telemetry:${pathToFileURL(path).href}`,\n create: () => {\n const calls = new Map<string, TraceCallState>();\n const provider = new BasicTracerProvider({\n spanProcessors: [\n new SimpleSpanProcessor(\n fileExporter(path, calls, options.onWriteError),\n ),\n ],\n });\n return {\n traces: new FileTraceAdapter(pathToFileURL(path)),\n telemetry: (context: AgentPluginToolContext) =>\n openTelemetry(provider, context, calls),\n work: () =>\n Promise.resolve({\n [Symbol.asyncDispose]: async () => {\n await provider.shutdown();\n calls.clear();\n },\n }),\n };\n },\n };\n}\n\nfunction fileExporter(\n path: string,\n calls: Map<string, TraceCallState>,\n onWriteError?: FileTelemetryOptions['onWriteError'],\n): SpanExporter {\n let initialized = false;\n return {\n export(spans, done) {\n try {\n if (!initialized) {\n mkdirSync(dirname(path), { recursive: true });\n initialized = true;\n }\n appendFileSync(\n path,\n `${spans\n .map((span) => JSON.stringify(flattenSpan(span, calls)))\n .join('\\n')}\\n`,\n );\n done({ code: ExportResultCode.SUCCESS });\n } catch (error) {\n try {\n Promise.resolve(onWriteError?.(error)).catch(() => {});\n } catch {\n // Telemetry must never affect the observed operation.\n }\n done({\n code: ExportResultCode.FAILED,\n error: error instanceof Error ? error : new Error(String(error)),\n });\n }\n },\n shutdown: () => Promise.resolve(),\n };\n}\n\nfunction openTelemetry(\n provider: BasicTracerProvider,\n context: AgentPluginToolContext,\n calls: Map<string, TraceCallState>,\n) {\n const telemetry = new OpenTelemetry({\n tracer: provider.getTracer('@deepagents/devtool/traces'),\n usage: true,\n providerMetadata: true,\n enrichSpan: ({ spanType, callId }) => {\n const call = calls.get(callId);\n return {\n [ATTR_SESSION_ID]: context.conversation.chatId,\n [ATTR_USER_ID]: context.conversation.userId,\n [ATTR_GEN_AI_AGENT_NAME]: context.agentName,\n 'deepagents.stream.id': context.streamId,\n 'deepagents.agent.path': context.agentPath,\n [CALL_ID]: callId,\n [SPAN_TYPE]: spanType,\n ...(call\n ? {\n [RECORD_INPUTS]: call.recordInputs,\n [RECORD_OUTPUTS]: call.recordOutputs,\n }\n : {}),\n };\n },\n });\n const onStart = telemetry.onStart.bind(telemetry);\n telemetry.onStart = (event) => {\n calls.set(event.callId, {\n recordInputs: event.recordInputs !== false,\n recordOutputs: event.recordOutputs !== false,\n });\n onStart(event);\n };\n const onAbort = telemetry.onAbort.bind(telemetry);\n telemetry.onAbort = (event) => {\n const call = calls.get(event.callId);\n if (call) call.status = 'cancelled';\n onAbort(event);\n };\n return telemetry;\n}\n\nfunction flattenSpan(span: ReadableSpan, calls: Map<string, TraceCallState>) {\n const context = span.spanContext();\n const callId = span.attributes[CALL_ID];\n const call = typeof callId === 'string' ? calls.get(callId) : undefined;\n const flattened = {\n trace_id: context.traceId,\n span_id: context.spanId,\n parent_span_id: span.parentSpanContext?.spanId ?? '',\n trace_state: context.traceState?.serialize() ?? '',\n name: span.name,\n kind: `SPAN_KIND_${SpanKind[span.kind]}`,\n start_time: timestamp(span.startTime),\n end_time: timestamp(span.endTime),\n status: {\n code: `STATUS_CODE_${SpanStatusCode[span.status.code]}`,\n message: span.status.message ?? '',\n },\n resource: { attributes: span.resource.attributes },\n scope: span.instrumentationScope,\n attributes: haloAttributes(span, call),\n events: span.events.map((event) => ({\n name: event.name,\n timestamp: timestamp(event.time),\n attributes: event.attributes ?? {},\n })),\n };\n if (span.attributes[SPAN_TYPE] === 'operation' && typeof callId === 'string')\n calls.delete(callId);\n return flattened;\n}\n\nfunction haloAttributes(span: ReadableSpan, call?: TraceCallState) {\n const attributes = span.attributes;\n const kind = {\n operation: 'AGENT',\n step: 'CHAIN',\n languageModel: 'LLM',\n tool: 'TOOL',\n }[String(attributes['deepagents.span.type'])];\n return {\n ...attributes,\n 'openinference.span.kind': kind,\n ...(call?.status ? { [SPAN_STATUS]: call.status } : {}),\n };\n}\n\nfunction timestamp([seconds, nanoseconds]: HrTime): string {\n return `${new Date(seconds * 1_000).toISOString().slice(0, -5)}.${String(nanoseconds).padStart(9, '0')}Z`;\n}\n", "import {\n ATTR_GEN_AI_AGENT_NAME,\n ATTR_GEN_AI_INPUT_MESSAGES,\n ATTR_GEN_AI_OPERATION_NAME,\n ATTR_GEN_AI_OUTPUT_MESSAGES,\n ATTR_GEN_AI_REQUEST_MODEL,\n ATTR_GEN_AI_RESPONSE_FINISH_REASONS,\n ATTR_GEN_AI_TOOL_CALL_ARGUMENTS,\n ATTR_GEN_AI_TOOL_CALL_RESULT,\n ATTR_GEN_AI_TOOL_NAME,\n ATTR_GEN_AI_USAGE_INPUT_TOKENS,\n ATTR_GEN_AI_USAGE_OUTPUT_TOKENS,\n ATTR_SESSION_ID,\n ATTR_USER_ID,\n} from '@opentelemetry/semantic-conventions/incubating';\nimport { readFile } from 'node:fs/promises';\nimport { fileURLToPath } from 'node:url';\n\nimport type { ConversationId } from '@deepagents/experimental/zukhruf';\n\nconst AGENT_PATH = 'deepagents.agent.path';\nconst RECORD_INPUTS = 'deepagents.record.inputs';\nconst RECORD_OUTPUTS = 'deepagents.record.outputs';\nconst SPAN_STATUS = 'deepagents.span.status';\nconst SPAN_TYPE = 'deepagents.span.type';\nconst STREAM_ID = 'deepagents.stream.id';\nconst ERROR = 'STATUS_CODE_ERROR';\n\nexport type RecordingState = 'recorded' | 'not-recorded';\n\nexport interface AgentTraceSummary {\n id: string;\n chatId: string;\n userId: string;\n streamId: string;\n agentName: string;\n agentPath: string;\n workflowName: string;\n startedAt: string | null;\n endedAt: string | null;\n status: 'running' | 'completed' | 'failed' | 'cancelled';\n stepCount: number;\n finishReason: string | null;\n usage: { inputTokens: number; outputTokens: number };\n recording: { inputs: RecordingState; outputs: RecordingState };\n}\n\nexport interface AgentTraceSpan {\n id: string;\n traceId: string;\n parentId: string | null;\n startedAt: string;\n endedAt: string | null;\n status: 'running' | 'completed' | 'failed' | 'cancelled';\n type: string;\n name: string;\n input?: unknown;\n output?: unknown;\n usage?: unknown;\n error?: unknown;\n data: Record<string, unknown>;\n}\n\nexport type AgentTrace = AgentTraceSummary & { spans: AgentTraceSpan[] };\n\nexport interface AgentTraceReader {\n list(conversation: ConversationId): Promise<AgentTraceSummary[]>;\n get(\n conversation: ConversationId,\n traceId: string,\n ): Promise<AgentTrace | undefined>;\n}\n\ninterface FlatSpan {\n trace_id: string;\n span_id: string;\n parent_span_id: string;\n name: string;\n kind: string;\n start_time: string;\n end_time: string;\n status: { code: string; message: string };\n attributes: Record<string, unknown>;\n events: Array<{ name: string; attributes: Record<string, unknown> }>;\n}\n\nexport class FileTraceAdapter implements AgentTraceReader {\n readonly #path: string;\n\n constructor(path: URL) {\n this.#path = fileURLToPath(path);\n }\n\n async list({ chatId, userId }: ConversationId): Promise<AgentTraceSummary[]> {\n return (await this.#project())\n .filter((trace) => trace.chatId === chatId && trace.userId === userId)\n .sort((left, right) =>\n (right.startedAt ?? '').localeCompare(left.startedAt ?? ''),\n )\n .map(({ spans: _spans, ...summary }) => summary);\n }\n\n async get(\n { chatId, userId }: ConversationId,\n traceId: string,\n ): Promise<AgentTrace | undefined> {\n return (await this.#project()).find(\n (trace) =>\n trace.id === traceId &&\n trace.chatId === chatId &&\n trace.userId === userId,\n );\n }\n\n async #project(): Promise<AgentTrace[]> {\n return [\n ...Map.groupBy(await readSpans(this.#path), (span) => span.trace_id),\n ]\n .map(([traceId, spans]) => projectTrace(traceId, spans))\n .filter((trace) => trace !== undefined);\n }\n}\n\nfunction projectTrace(\n traceId: string,\n spans: FlatSpan[],\n): AgentTrace | undefined {\n const context = readContext(spans);\n if (!context) return undefined;\n const root = spans.find(\n (span) =>\n span.attributes[SPAN_TYPE] === 'operation' &&\n span.attributes[ATTR_GEN_AI_OPERATION_NAME] === 'invoke_agent',\n );\n const visible = spans\n .filter((span) => spanType(span))\n .sort((left, right) => left.start_time.localeCompare(right.start_time));\n const byId = new Map(spans.map((span) => [span.span_id, span]));\n const generationByStep = new Map(\n spans.flatMap((span) =>\n span.attributes[SPAN_TYPE] === 'languageModel' && span.parent_span_id\n ? [[span.parent_span_id, span.span_id]]\n : [],\n ),\n );\n const projected = visible.map((span) =>\n projectSpan(span, byId, generationByStep, context.agentName),\n );\n return {\n id: traceId,\n ...context,\n workflowName: context.agentName,\n startedAt: root?.start_time ?? spans[0]?.start_time ?? null,\n endedAt: root?.end_time ?? null,\n status: root ? spanStatus(root) : 'running',\n stepCount: projected.filter(({ type }) => type === 'generation').length,\n finishReason:\n firstString(root?.attributes[ATTR_GEN_AI_RESPONSE_FINISH_REASONS]) ??\n null,\n usage: readUsage(root?.attributes) ?? sumUsage(visible),\n recording: {\n inputs: recordingState(\n root?.attributes[RECORD_INPUTS],\n spans.some(({ attributes }) =>\n has(\n attributes,\n ATTR_GEN_AI_INPUT_MESSAGES,\n ATTR_GEN_AI_TOOL_CALL_ARGUMENTS,\n ),\n ),\n ),\n outputs: recordingState(\n root?.attributes[RECORD_OUTPUTS],\n spans.some(({ attributes }) =>\n has(\n attributes,\n ATTR_GEN_AI_OUTPUT_MESSAGES,\n ATTR_GEN_AI_TOOL_CALL_RESULT,\n ),\n ),\n ),\n },\n spans: projected,\n };\n}\n\nfunction projectSpan(\n span: FlatSpan,\n byId: ReadonlyMap<string, FlatSpan>,\n generationByStep: ReadonlyMap<string, string>,\n agentName: string,\n): AgentTraceSpan {\n const type = spanType(span) as 'agent' | 'generation' | 'function';\n const input = jsonAttribute(\n span.attributes,\n type === 'function'\n ? ATTR_GEN_AI_TOOL_CALL_ARGUMENTS\n : ATTR_GEN_AI_INPUT_MESSAGES,\n );\n const output = jsonAttribute(\n span.attributes,\n type === 'function'\n ? ATTR_GEN_AI_TOOL_CALL_RESULT\n : ATTR_GEN_AI_OUTPUT_MESSAGES,\n );\n const usage = readUsage(span.attributes);\n const exceptions = span.events\n .filter(({ name }) => name === 'exception')\n .map(({ attributes }) => attributes);\n const error =\n span.status.code === ERROR || exceptions.length\n ? { ...span.status, exceptions }\n : undefined;\n return {\n id: span.span_id,\n traceId: span.trace_id,\n parentId: visibleParent(span, byId, generationByStep),\n startedAt: span.start_time,\n endedAt: span.end_time,\n status: spanStatus(span),\n type,\n name:\n type === 'agent'\n ? agentName\n : String(\n span.attributes[\n type === 'generation'\n ? ATTR_GEN_AI_REQUEST_MODEL\n : ATTR_GEN_AI_TOOL_NAME\n ] ?? span.name,\n ),\n ...(input === undefined ? {} : { input }),\n ...(output === undefined ? {} : { output }),\n ...(usage === undefined ? {} : { usage }),\n ...(error === undefined ? {} : { error }),\n data: {\n name: span.name,\n kind: span.kind,\n attributes: span.attributes,\n events: span.events,\n status: span.status,\n },\n };\n}\n\nfunction visibleParent(\n span: FlatSpan,\n byId: ReadonlyMap<string, FlatSpan>,\n generationByStep: ReadonlyMap<string, string>,\n): string | null {\n if (!span.parent_span_id) return null;\n const parent = byId.get(span.parent_span_id);\n if (!parent) return null;\n if (parent.attributes[SPAN_TYPE] !== 'step') return span.parent_span_id;\n return span.attributes[SPAN_TYPE] === 'tool'\n ? (generationByStep.get(parent.span_id) ?? parent.parent_span_id ?? null)\n : parent.parent_span_id || null;\n}\n\nfunction readContext(spans: FlatSpan[]) {\n const attributes = spans.find(({ attributes }) =>\n [\n ATTR_SESSION_ID,\n ATTR_USER_ID,\n STREAM_ID,\n ATTR_GEN_AI_AGENT_NAME,\n AGENT_PATH,\n ].every((key) => typeof attributes[key] === 'string'),\n )?.attributes;\n if (!attributes) return undefined;\n return {\n chatId: attributes[ATTR_SESSION_ID] as string,\n userId: attributes[ATTR_USER_ID] as string,\n streamId: attributes[STREAM_ID] as string,\n agentName: attributes[ATTR_GEN_AI_AGENT_NAME] as string,\n agentPath: attributes[AGENT_PATH] as string,\n };\n}\n\nfunction spanType(\n span: FlatSpan,\n): 'agent' | 'generation' | 'function' | undefined {\n return {\n operation: 'agent',\n languageModel: 'generation',\n tool: 'function',\n }[String(span.attributes[SPAN_TYPE])] as ReturnType<typeof spanType>;\n}\n\nfunction readUsage(attributes: Record<string, unknown> | undefined) {\n const inputTokens = attributes?.[ATTR_GEN_AI_USAGE_INPUT_TOKENS];\n const outputTokens = attributes?.[ATTR_GEN_AI_USAGE_OUTPUT_TOKENS];\n return typeof inputTokens === 'number' && typeof outputTokens === 'number'\n ? { inputTokens, outputTokens }\n : undefined;\n}\n\nfunction sumUsage(spans: FlatSpan[]) {\n return spans.reduce(\n (total, span) => {\n const usage = readUsage(span.attributes);\n return usage\n ? {\n inputTokens: total.inputTokens + usage.inputTokens,\n outputTokens: total.outputTokens + usage.outputTokens,\n }\n : total;\n },\n { inputTokens: 0, outputTokens: 0 },\n );\n}\n\nfunction jsonAttribute(attributes: Record<string, unknown>, key: string) {\n const value = attributes[key];\n if (typeof value !== 'string') return undefined;\n try {\n return JSON.parse(value);\n } catch {\n return value;\n }\n}\n\nfunction has(attributes: Record<string, unknown>, ...keys: string[]) {\n return keys.some((key) => Object.hasOwn(attributes, key));\n}\n\nfunction recordingState(policy: unknown, observed: boolean): RecordingState {\n return policy === true || (policy !== false && observed)\n ? 'recorded'\n : 'not-recorded';\n}\n\nfunction spanStatus(span: FlatSpan): 'completed' | 'failed' | 'cancelled' {\n if (span.attributes[SPAN_STATUS] === 'cancelled') return 'cancelled';\n return span.status.code === ERROR ? 'failed' : 'completed';\n}\n\nfunction firstString(value: unknown): string | undefined {\n return Array.isArray(value) && typeof value[0] === 'string'\n ? value[0]\n : undefined;\n}\n\nasync function readSpans(path: string): Promise<FlatSpan[]> {\n let contents: string;\n try {\n contents = await readFile(path, 'utf8');\n } catch (error) {\n if (isRecord(error) && error.code === 'ENOENT') return [];\n throw error;\n }\n const lines = contents.split('\\n');\n if (lines.at(-1) === '') lines.pop();\n return lines.flatMap((line, index) => {\n if (!line.trim()) return [];\n let span: FlatSpan;\n try {\n span = JSON.parse(line);\n } catch (error) {\n if (index === lines.length - 1 && !contents.endsWith('\\n')) return [];\n throw error;\n }\n if (\n !span ||\n typeof span.trace_id !== 'string' ||\n typeof span.span_id !== 'string' ||\n !Number.isFinite(Date.parse(span.start_time)) ||\n !isRecord(span.attributes)\n ) {\n throw new TypeError(`Invalid Halo trace record in \"${path}\"`);\n }\n return [span];\n });\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n", "import { Hono } from 'hono';\nimport { HTTPException } from 'hono/http-exception';\n\nimport type {\n AgentPluginDefinition,\n ConversationId,\n} from '@deepagents/experimental/zukhruf';\nimport {\n type HttpEnv,\n type HttpRuntime,\n projectHttp,\n} from '@deepagents/experimental/zukhruf/http';\n\nimport type {\n AgentTraceReader,\n AgentTraceSummary,\n} from './file-trace-adapter.ts';\nimport type { FileTelemetryInstance } from './index.ts';\n\nconst TRACES_PATH = '/traces';\nconst NO_STORE = { 'cache-control': 'no-store' } as const;\n\nexport function tracesHttp(\n definition: AgentPluginDefinition<FileTelemetryInstance>,\n) {\n return projectHttp(definition, (plugin, runtime) => ({\n capabilities: { traces: { path: TRACES_PATH } },\n authenticatedRoutes: traceRoutes(plugin.traces, runtime),\n }));\n}\n\nfunction traceRoutes(reader: AgentTraceReader, runtime: HttpRuntime) {\n const app = new Hono<HttpEnv>();\n app.get(`${TRACES_PATH}/:chatId`, async (context) => {\n const conversation = await requireConversation(runtime, {\n chatId: context.req.param('chatId'),\n userId: context.get('userId'),\n });\n return context.json(\n await Promise.all(\n (await reader.list(conversation)).map((trace) =>\n withDurableStatus(runtime, trace),\n ),\n ),\n 200,\n NO_STORE,\n );\n });\n app.get(`${TRACES_PATH}/:chatId/:traceId`, async (context) => {\n const conversation = await requireConversation(runtime, {\n chatId: context.req.param('chatId'),\n userId: context.get('userId'),\n });\n const traceId = context.req.param('traceId');\n const trace = await reader.get(conversation, traceId);\n if (!trace) {\n throw new HTTPException(404, {\n message: 'Trace not found',\n cause: {\n code: 'traces/trace-not-found',\n detail: `Trace ${traceId} does not exist in conversation ${conversation.chatId}`,\n },\n });\n }\n return context.json(await withDurableStatus(runtime, trace), 200, NO_STORE);\n });\n return app;\n}\n\nasync function requireConversation(\n runtime: Pick<HttpRuntime, 'listHistory'>,\n conversation: ConversationId,\n): Promise<ConversationId> {\n const owned = (await runtime.listHistory(conversation.userId)).some(\n (item) =>\n item.chatId === conversation.chatId &&\n item.userId === conversation.userId,\n );\n if (owned) return conversation;\n throw new HTTPException(404, {\n message: 'Conversation not found',\n cause: {\n code: 'traces/conversation-not-found',\n detail: `Conversation ${conversation.chatId} does not exist`,\n },\n });\n}\n\nasync function withDurableStatus<Trace extends AgentTraceSummary>(\n runtime: Pick<HttpRuntime, 'observe'>,\n trace: Trace,\n): Promise<Trace> {\n const turn = await runtime\n .observe({ chatId: trace.chatId, userId: trace.userId })\n .status(trace.streamId);\n return { ...trace, status: turn?.status ?? trace.status };\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["ATTR_GEN_AI_AGENT_NAME", "ATTR_SESSION_ID", "ATTR_USER_ID", "attributes", "RECORD_INPUTS", "RECORD_OUTPUTS", "SPAN_STATUS", "SPAN_TYPE", "spanType", "ATTR_SESSION_ID", "ATTR_USER_ID", "ATTR_GEN_AI_AGENT_NAME"]
|
|
7
|
+
}
|