robotrock 0.8.4 → 0.9.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.
@@ -1,633 +0,0 @@
1
- // src/agent-telemetry-from-otel.ts
2
- import { trace } from "@opentelemetry/api";
3
-
4
- // src/schemas/index.ts
5
- import { z as z2 } from "zod";
6
-
7
- // ../core/src/utils/safe-url.ts
8
- var BLOCKED_HOSTNAMES = /* @__PURE__ */ new Set([
9
- "localhost",
10
- "metadata.google.internal",
11
- "metadata.goog"
12
- ]);
13
- function normalizeHostname(hostname) {
14
- return hostname.toLowerCase().replace(/^\[|\]$/g, "");
15
- }
16
- function isBlockedIpv4(host) {
17
- const match = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/.exec(host);
18
- if (!match) {
19
- return false;
20
- }
21
- const octets = match.slice(1, 5).map((part) => Number(part));
22
- if (octets.some((octet) => Number.isNaN(octet) || octet < 0 || octet > 255)) {
23
- return true;
24
- }
25
- const [a, b, _c, _d] = octets;
26
- if (a === void 0 || b === void 0) {
27
- return true;
28
- }
29
- if (a === 127 || a === 0) return true;
30
- if (a === 10) return true;
31
- if (a === 169 && b === 254) return true;
32
- if (a === 192 && b === 168) return true;
33
- if (a === 172 && b >= 16 && b <= 31) return true;
34
- if (a === 100 && b >= 64 && b <= 127) return true;
35
- return false;
36
- }
37
- function ipv4FromNumericHost(host) {
38
- if (/^\d+$/.test(host)) {
39
- const num = Number(host);
40
- if (!Number.isFinite(num) || num < 0 || num > 4294967295) {
41
- return null;
42
- }
43
- const a = num >>> 24 & 255;
44
- const b = num >>> 16 & 255;
45
- const c = num >>> 8 & 255;
46
- const d = num & 255;
47
- return `${a}.${b}.${c}.${d}`;
48
- }
49
- const hexMatch = /^0x([0-9a-f]{1,8})$/i.exec(host);
50
- if (hexMatch) {
51
- const num = Number.parseInt(hexMatch[1], 16);
52
- if (!Number.isFinite(num) || num < 0 || num > 4294967295) {
53
- return null;
54
- }
55
- const a = num >>> 24 & 255;
56
- const b = num >>> 16 & 255;
57
- const c = num >>> 8 & 255;
58
- const d = num & 255;
59
- return `${a}.${b}.${c}.${d}`;
60
- }
61
- return null;
62
- }
63
- function isBlockedIpv4Mapped(host) {
64
- const mappedDotted = /^::ffff:(\d{1,3}(?:\.\d{1,3}){3})$/i.exec(host);
65
- if (mappedDotted) {
66
- return isBlockedIpv4(mappedDotted[1]);
67
- }
68
- const mappedHex = /^::ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/i.exec(host);
69
- if (mappedHex) {
70
- const high = Number.parseInt(mappedHex[1], 16);
71
- const low = Number.parseInt(mappedHex[2], 16);
72
- if (Number.isFinite(high) && Number.isFinite(low)) {
73
- const a = high >> 8 & 255;
74
- const b = high & 255;
75
- const c = low >> 8 & 255;
76
- const d = low & 255;
77
- return isBlockedIpv4(`${a}.${b}.${c}.${d}`);
78
- }
79
- }
80
- return false;
81
- }
82
- function isBlockedIpv6(host) {
83
- if (host === "::1" || host === "0:0:0:0:0:0:0:1") {
84
- return true;
85
- }
86
- if (host.startsWith("fc") || host.startsWith("fd")) {
87
- return true;
88
- }
89
- if (host.startsWith("fe80:")) {
90
- return true;
91
- }
92
- if (isBlockedIpv4Mapped(host)) {
93
- return true;
94
- }
95
- return false;
96
- }
97
- function isBlockedHostname(hostname) {
98
- const host = normalizeHostname(hostname);
99
- if (!host) {
100
- return true;
101
- }
102
- if (BLOCKED_HOSTNAMES.has(host)) {
103
- return true;
104
- }
105
- if (host.endsWith(".localhost") || host.endsWith(".local")) {
106
- return true;
107
- }
108
- const numericIpv4 = ipv4FromNumericHost(host);
109
- if (numericIpv4 && isBlockedIpv4(numericIpv4)) {
110
- return true;
111
- }
112
- return isBlockedIpv4(host) || isBlockedIpv6(host);
113
- }
114
- function isPublicHttpUrl(urlString) {
115
- let url;
116
- try {
117
- url = new URL(urlString);
118
- } catch {
119
- return false;
120
- }
121
- if (url.protocol !== "http:" && url.protocol !== "https:") {
122
- return false;
123
- }
124
- if (url.username || url.password) {
125
- return false;
126
- }
127
- return !isBlockedHostname(url.hostname);
128
- }
129
- var PUBLIC_HTTP_URL_ERROR = "URL must be a public http:// or https:// address";
130
-
131
- // ../core/src/schemas/task.ts
132
- import { z } from "zod";
133
-
134
- // ../core/src/schemas/context-urls.ts
135
- function resolveLinkUrl(value) {
136
- return value.startsWith("http://") || value.startsWith("https://") ? value : `https://${value}`;
137
- }
138
- function widgetType(ui, field) {
139
- const fieldUi = ui?.[field];
140
- if (typeof fieldUi !== "object" || fieldUi === null) {
141
- return void 0;
142
- }
143
- const widget = fieldUi["ui:widget"];
144
- return typeof widget === "string" ? widget : void 0;
145
- }
146
- function validateUrlValue(value, widget) {
147
- if (widget === "image" || widget === "link") {
148
- if (typeof value !== "string") {
149
- return PUBLIC_HTTP_URL_ERROR;
150
- }
151
- const url = widget === "link" ? resolveLinkUrl(value) : value;
152
- if (!isPublicHttpUrl(url)) {
153
- return PUBLIC_HTTP_URL_ERROR;
154
- }
155
- return null;
156
- }
157
- if (widget === "attachments" && Array.isArray(value)) {
158
- for (const item of value) {
159
- if (typeof item !== "object" || item === null) {
160
- continue;
161
- }
162
- const url = item.url;
163
- if (typeof url === "string" && !isPublicHttpUrl(resolveLinkUrl(url))) {
164
- return PUBLIC_HTTP_URL_ERROR;
165
- }
166
- }
167
- }
168
- return null;
169
- }
170
- function validateContextPublicUrls(context) {
171
- if (!context?.data) {
172
- return null;
173
- }
174
- for (const [field, value] of Object.entries(context.data)) {
175
- const widget = widgetType(context.ui, field);
176
- if (!widget) {
177
- continue;
178
- }
179
- const error = validateUrlValue(value, widget);
180
- if (error) {
181
- return `context.data.${field}: ${error}`;
182
- }
183
- }
184
- return null;
185
- }
186
-
187
- // ../core/src/schemas/task.ts
188
- var safeUrlSchema = z.string().refine((url) => isPublicHttpUrl(url), {
189
- message: PUBLIC_HTTP_URL_ERROR
190
- });
191
- var jsonSchema7Schema = z.custom(
192
- (val) => typeof val === "object" && val !== null,
193
- { message: "Must be a valid JSON Schema object" }
194
- );
195
- var uiSchemaSchema = z.custom((val) => typeof val === "object" && val !== null, {
196
- message: "Must be a valid UiSchema object"
197
- });
198
- var webhookHandlerSchema = z.object({
199
- type: z.literal("webhook"),
200
- url: safeUrlSchema,
201
- headers: z.record(z.string(), z.string())
202
- });
203
- var triggerHandlerSchema = webhookHandlerSchema.extend({
204
- type: z.literal("trigger"),
205
- tokenId: z.string().min(1)
206
- });
207
- var handlerSchema = z.discriminatedUnion("type", [webhookHandlerSchema, triggerHandlerSchema]);
208
- var taskActionSchema = z.object({
209
- id: z.string().min(1),
210
- title: z.string().min(1),
211
- description: z.string().optional(),
212
- schema: jsonSchema7Schema.optional(),
213
- ui: uiSchemaSchema.optional(),
214
- data: z.record(z.string(), z.unknown()).optional(),
215
- // Optional handlers for this action - if present, must have at least 1
216
- handlers: z.array(handlerSchema).min(1).optional()
217
- });
218
- var uiFieldSchemaSchema = z.object({
219
- "ui:widget": z.string().optional(),
220
- "ui:title": z.string().optional(),
221
- "ui:description": z.string().optional(),
222
- "ui:options": z.record(z.string(), z.unknown()).optional(),
223
- items: z.lazy(() => z.record(z.string(), uiFieldSchemaSchema)).optional()
224
- }).passthrough();
225
- var contextUiSchema = z.record(z.string(), uiFieldSchemaSchema).optional();
226
- var contextDataSchema = z.object({
227
- data: z.record(z.string(), z.unknown()),
228
- ui: contextUiSchema
229
- }).optional();
230
- var taskContextObjectSchema = z.object({
231
- /** Source application id; omitted tasks are grouped in the default inbox. */
232
- app: z.string().min(1).optional(),
233
- type: z.string().min(1),
234
- name: z.string().min(1),
235
- description: z.string().optional(),
236
- validUntil: z.string().optional(),
237
- context: contextDataSchema,
238
- version: z.literal(2).optional(),
239
- actions: z.array(taskActionSchema).min(1, "At least one action is required")
240
- });
241
- function refineContextPublicUrls(data, ctx) {
242
- const error = validateContextPublicUrls(data.context);
243
- if (error) {
244
- ctx.addIssue({
245
- code: z.ZodIssueCode.custom,
246
- message: error,
247
- path: ["context"]
248
- });
249
- }
250
- }
251
- var taskContextSchema = taskContextObjectSchema.superRefine(
252
- refineContextPublicUrls
253
- );
254
- var assignToSchema = z.object({
255
- users: z.array(z.string().email()).optional(),
256
- groups: z.array(z.string().min(1)).optional()
257
- }).refine(
258
- (data) => {
259
- const groups = data.groups ?? [];
260
- if (groups.includes("all") && groups.length > 1) {
261
- return false;
262
- }
263
- return true;
264
- },
265
- { message: 'Cannot combine "all" with other group slugs' }
266
- );
267
- var threadUpdateMessageSchema = z.string().min(1).max(500);
268
- var threadUpdateStatuses = [
269
- "info",
270
- "queued",
271
- "running",
272
- "waiting",
273
- "succeeded",
274
- "failed",
275
- "cancelled"
276
- ];
277
- var threadUpdateStatusSchema = z.enum(threadUpdateStatuses);
278
- var threadUpdateInputSchema = z.object({
279
- message: threadUpdateMessageSchema,
280
- status: threadUpdateStatusSchema.optional()
281
- });
282
- var taskPriorities = ["low", "normal", "high", "urgent"];
283
- var taskPrioritySchema = z.enum(taskPriorities);
284
- var nonNegativeInt = z.number().int().nonnegative();
285
- var agentCostTokensSchema = z.object({
286
- input: nonNegativeInt.optional(),
287
- output: nonNegativeInt.optional(),
288
- total: nonNegativeInt.optional()
289
- });
290
- var agentCostSchema = z.object({
291
- tokens: agentCostTokensSchema.optional(),
292
- eur: z.number().nonnegative().optional(),
293
- usd: z.number().nonnegative().optional()
294
- });
295
- var AGENT_INFO_MAX_KEYS = 32;
296
- var AGENT_TOOL_CALLS_MAX_KEYS = 64;
297
- var AGENT_OTEL_SPANS_MAX = 32;
298
- var agentToolCallsSchema = z.record(z.string().min(1), nonNegativeInt);
299
- var agentOtelSpanStatusSchema = z.enum(["ok", "error"]);
300
- var agentOtelSpanSummarySchema = z.object({
301
- name: z.string().min(1),
302
- durationMs: z.number().nonnegative(),
303
- status: agentOtelSpanStatusSchema
304
- });
305
- var agentOtelSchema = z.object({
306
- traceId: z.string().min(1),
307
- spanId: z.string().min(1).optional(),
308
- rootDurationMs: z.number().nonnegative().optional(),
309
- spans: z.array(agentOtelSpanSummarySchema).max(AGENT_OTEL_SPANS_MAX).optional()
310
- });
311
- var agentTelemetrySchema = z.object({
312
- /** Agent or app version (semver, git SHA, deploy tag — caller-defined). */
313
- version: z.string().min(1).optional(),
314
- /** Total tool invocations. When omitted but `toolCalls` is set, the sum of counts is used. */
315
- toolCallCount: nonNegativeInt.optional(),
316
- /** Per-tool invocation counts keyed by tool name. */
317
- toolCalls: agentToolCallsSchema.optional(),
318
- cost: agentCostSchema.optional(),
319
- /** Free-form metadata for experiments (model, prompt variant, etc.). */
320
- info: z.record(z.string(), z.unknown()).optional(),
321
- /** Structured OpenTelemetry span snapshot for feedback analysis. */
322
- otel: agentOtelSchema.optional()
323
- }).refine(
324
- (data) => {
325
- const keys = data.info ? Object.keys(data.info) : [];
326
- return keys.length <= AGENT_INFO_MAX_KEYS;
327
- },
328
- { message: `agent.info may contain at most ${AGENT_INFO_MAX_KEYS} keys` }
329
- ).refine(
330
- (data) => {
331
- const keys = data.toolCalls ? Object.keys(data.toolCalls) : [];
332
- return keys.length <= AGENT_TOOL_CALLS_MAX_KEYS;
333
- },
334
- {
335
- message: `agent.toolCalls may contain at most ${AGENT_TOOL_CALLS_MAX_KEYS} tool names`
336
- }
337
- );
338
- var createTaskBodySchema = taskContextObjectSchema.extend({
339
- assignTo: assignToSchema.optional(),
340
- /**
341
- * Groups related tasks together. When omitted, the server generates one and
342
- * returns it so the caller can reuse it on later tasks in the same thread.
343
- */
344
- threadId: z.string().min(1).optional(),
345
- /**
346
- * Optional thread priority. When set, applies to the whole thread and
347
- * overwrites any previous priority. Omit on later tasks to leave unchanged.
348
- */
349
- priority: taskPrioritySchema.optional(),
350
- /**
351
- * Optional initial status update logged against the task's thread. Shows in
352
- * the inbox status bar and the thread update log.
353
- */
354
- update: threadUpdateInputSchema.optional(),
355
- /** Agent telemetry (version, cost, tool calls) — not shown in inbox UI. */
356
- agent: agentTelemetrySchema.optional()
357
- }).superRefine(refineContextPublicUrls);
358
-
359
- // src/schemas/index.ts
360
- var safeUrlSchema2 = z2.string().refine((url) => isPublicHttpUrl(url), {
361
- message: PUBLIC_HTTP_URL_ERROR
362
- });
363
- var jsonSchema7Schema2 = z2.custom(
364
- (val) => typeof val === "object" && val !== null,
365
- { message: "Must be a valid JSON Schema object" }
366
- );
367
- var uiSchemaSchema2 = z2.custom((val) => typeof val === "object" && val !== null, {
368
- message: "Must be a valid UiSchema object"
369
- });
370
- var webhookHandlerSchema2 = z2.object({
371
- type: z2.literal("webhook"),
372
- url: safeUrlSchema2,
373
- headers: z2.record(z2.string(), z2.string())
374
- });
375
- var triggerHandlerSchema2 = webhookHandlerSchema2.extend({
376
- type: z2.literal("trigger"),
377
- tokenId: z2.string().min(1)
378
- });
379
- var handlerSchema2 = z2.discriminatedUnion("type", [webhookHandlerSchema2, triggerHandlerSchema2]);
380
- var taskActionSchema2 = z2.object({
381
- id: z2.string().min(1),
382
- title: z2.string().min(1),
383
- description: z2.string().optional(),
384
- schema: jsonSchema7Schema2.optional(),
385
- ui: uiSchemaSchema2.optional(),
386
- data: z2.record(z2.string(), z2.unknown()).optional(),
387
- handlers: z2.array(handlerSchema2).min(1).optional()
388
- });
389
- var uiFieldSchemaSchema2 = z2.object({
390
- "ui:widget": z2.string().optional(),
391
- "ui:title": z2.string().optional(),
392
- "ui:description": z2.string().optional(),
393
- "ui:options": z2.record(z2.string(), z2.unknown()).optional(),
394
- items: z2.lazy(() => z2.record(z2.string(), uiFieldSchemaSchema2)).optional()
395
- }).passthrough();
396
- var contextUiSchema2 = z2.record(z2.string(), uiFieldSchemaSchema2).optional();
397
- var contextDataSchema2 = z2.object({
398
- data: z2.record(z2.string(), z2.unknown()),
399
- ui: contextUiSchema2
400
- }).optional();
401
- var taskContextObjectSchema2 = z2.object({
402
- app: z2.string().min(1).optional(),
403
- type: z2.string().min(1),
404
- name: z2.string().min(1),
405
- description: z2.string().optional(),
406
- validUntil: z2.string().optional(),
407
- context: contextDataSchema2,
408
- version: z2.literal(2).optional(),
409
- actions: z2.array(taskActionSchema2).min(1, "At least one action is required")
410
- });
411
- function refineContextPublicUrls2(data, ctx) {
412
- const error = validateContextPublicUrls(data.context);
413
- if (error) {
414
- ctx.addIssue({
415
- code: z2.ZodIssueCode.custom,
416
- message: error,
417
- path: ["context"]
418
- });
419
- }
420
- }
421
- var taskContextSchema2 = taskContextObjectSchema2.superRefine(
422
- refineContextPublicUrls2
423
- );
424
- var assignToSchema2 = z2.object({
425
- users: z2.array(z2.string().email()).optional(),
426
- groups: z2.array(z2.string().min(1)).optional()
427
- }).refine(
428
- (data) => {
429
- const groups = data.groups ?? [];
430
- if (groups.includes("all") && groups.length > 1) {
431
- return false;
432
- }
433
- return true;
434
- },
435
- { message: 'Cannot combine "all" with other group slugs' }
436
- );
437
- var threadUpdateMessageSchema2 = z2.string().min(1).max(500);
438
- var threadUpdateStatuses2 = [
439
- "info",
440
- "queued",
441
- "running",
442
- "waiting",
443
- "succeeded",
444
- "failed",
445
- "cancelled"
446
- ];
447
- var threadUpdateStatusSchema2 = z2.enum(threadUpdateStatuses2);
448
- var threadUpdateInputSchema2 = z2.object({
449
- message: threadUpdateMessageSchema2,
450
- status: threadUpdateStatusSchema2.optional()
451
- });
452
- var taskPriorities2 = ["low", "normal", "high", "urgent"];
453
- var taskPrioritySchema2 = z2.enum(taskPriorities2);
454
- var nonNegativeInt2 = z2.number().int().nonnegative();
455
- var agentCostTokensSchema2 = z2.object({
456
- input: nonNegativeInt2.optional(),
457
- output: nonNegativeInt2.optional(),
458
- total: nonNegativeInt2.optional()
459
- });
460
- var agentCostSchema2 = z2.object({
461
- tokens: agentCostTokensSchema2.optional(),
462
- eur: z2.number().nonnegative().optional(),
463
- usd: z2.number().nonnegative().optional()
464
- });
465
- var AGENT_INFO_MAX_KEYS2 = 32;
466
- var AGENT_TOOL_CALLS_MAX_KEYS2 = 64;
467
- var AGENT_OTEL_SPANS_MAX2 = 32;
468
- var agentToolCallsSchema2 = z2.record(z2.string().min(1), nonNegativeInt2);
469
- var agentOtelSpanStatusSchema2 = z2.enum(["ok", "error"]);
470
- var agentOtelSpanSummarySchema2 = z2.object({
471
- name: z2.string().min(1),
472
- durationMs: z2.number().nonnegative(),
473
- status: agentOtelSpanStatusSchema2
474
- });
475
- var agentOtelSchema2 = z2.object({
476
- traceId: z2.string().min(1),
477
- spanId: z2.string().min(1).optional(),
478
- rootDurationMs: z2.number().nonnegative().optional(),
479
- spans: z2.array(agentOtelSpanSummarySchema2).max(AGENT_OTEL_SPANS_MAX2).optional()
480
- });
481
- var agentTelemetrySchema2 = z2.object({
482
- version: z2.string().min(1).optional(),
483
- toolCallCount: nonNegativeInt2.optional(),
484
- toolCalls: agentToolCallsSchema2.optional(),
485
- cost: agentCostSchema2.optional(),
486
- info: z2.record(z2.string(), z2.unknown()).optional(),
487
- otel: agentOtelSchema2.optional()
488
- }).refine(
489
- (data) => {
490
- const keys = data.info ? Object.keys(data.info) : [];
491
- return keys.length <= AGENT_INFO_MAX_KEYS2;
492
- },
493
- { message: `agent.info may contain at most ${AGENT_INFO_MAX_KEYS2} keys` }
494
- ).refine(
495
- (data) => {
496
- const keys = data.toolCalls ? Object.keys(data.toolCalls) : [];
497
- return keys.length <= AGENT_TOOL_CALLS_MAX_KEYS2;
498
- },
499
- {
500
- message: `agent.toolCalls may contain at most ${AGENT_TOOL_CALLS_MAX_KEYS2} tool names`
501
- }
502
- );
503
- var createTaskBodySchema2 = taskContextObjectSchema2.extend({
504
- assignTo: assignToSchema2.optional(),
505
- /**
506
- * Groups related tasks together. When omitted, the server generates one and
507
- * returns it so the caller can reuse it on later tasks in the same thread.
508
- */
509
- threadId: z2.string().min(1).optional(),
510
- /**
511
- * Optional thread priority. When set, applies to the whole thread and
512
- * overwrites any previous priority. Omit on later tasks to leave unchanged.
513
- */
514
- priority: taskPrioritySchema2.optional(),
515
- /**
516
- * Optional initial status update logged against the task's thread. Shows in
517
- * the inbox status bar and the thread update log.
518
- */
519
- update: threadUpdateInputSchema2.optional(),
520
- agent: agentTelemetrySchema2.optional()
521
- }).superRefine(refineContextPublicUrls2);
522
-
523
- // src/agent-telemetry-from-otel.ts
524
- var AGENT_INFO_MAX_KEYS3 = 32;
525
- function sumToolCalls(toolCalls) {
526
- return Object.values(toolCalls).reduce((sum, count) => sum + count, 0);
527
- }
528
- function isValidTraceId(traceId) {
529
- return typeof traceId === "string" && traceId.length > 0 && traceId !== "00000000000000000000000000000000";
530
- }
531
- function resolveSpanContext(span) {
532
- const active = span ?? trace.getActiveSpan();
533
- const ctx = active?.spanContext();
534
- if (!ctx || !isValidTraceId(ctx.traceId)) {
535
- return void 0;
536
- }
537
- return { traceId: ctx.traceId, spanId: ctx.spanId };
538
- }
539
- function countErrorSpans(spans) {
540
- if (!spans) return 0;
541
- return spans.filter((entry) => entry.status === "error").length;
542
- }
543
- function buildInfo(options, spanCtx) {
544
- const info = { ...options.extraInfo };
545
- if (spanCtx) {
546
- info.traceId = spanCtx.traceId;
547
- info.spanId = spanCtx.spanId;
548
- }
549
- if (options.runStartedAt != null) {
550
- const durationMs = Date.now() - options.runStartedAt;
551
- if (durationMs >= 0) {
552
- info.durationMs = durationMs;
553
- }
554
- }
555
- const errorCount = countErrorSpans(options.otel?.spans);
556
- if (errorCount > 0) {
557
- info.errorCount = errorCount;
558
- }
559
- const keys = Object.keys(info);
560
- if (keys.length === 0) {
561
- return void 0;
562
- }
563
- if (keys.length > AGENT_INFO_MAX_KEYS3) {
564
- const trimmed = {};
565
- for (const key of keys.slice(0, AGENT_INFO_MAX_KEYS3)) {
566
- trimmed[key] = info[key];
567
- }
568
- return trimmed;
569
- }
570
- return info;
571
- }
572
- function buildOtelBlock(options, spanCtx) {
573
- const traceId = options.otel?.traceId ?? spanCtx?.traceId;
574
- if (!isValidTraceId(traceId)) {
575
- return void 0;
576
- }
577
- const spans = options.otel?.spans;
578
- const rootDurationMs = options.otel?.rootDurationMs ?? (options.runStartedAt != null ? Math.max(0, Date.now() - options.runStartedAt) : void 0);
579
- const block = { traceId };
580
- const spanId = options.otel?.spanId ?? spanCtx?.spanId;
581
- if (spanId) {
582
- block.spanId = spanId;
583
- }
584
- if (rootDurationMs != null) {
585
- block.rootDurationMs = rootDurationMs;
586
- }
587
- if (spans && spans.length > 0) {
588
- block.spans = spans;
589
- }
590
- return block;
591
- }
592
- function agentTelemetryFromOtel(options = {}) {
593
- const spanCtx = resolveSpanContext(options.span);
594
- const telemetry = {};
595
- if (options.version) {
596
- telemetry.version = options.version;
597
- }
598
- if (options.toolCalls && Object.keys(options.toolCalls).length > 0) {
599
- telemetry.toolCalls = options.toolCalls;
600
- }
601
- if (options.toolCallCount !== void 0) {
602
- telemetry.toolCallCount = options.toolCallCount;
603
- } else if (telemetry.toolCalls) {
604
- const sum = sumToolCalls(telemetry.toolCalls);
605
- if (sum > 0) {
606
- telemetry.toolCallCount = sum;
607
- }
608
- }
609
- if (options.cost) {
610
- telemetry.cost = options.cost;
611
- }
612
- const info = buildInfo(options, spanCtx);
613
- if (info) {
614
- telemetry.info = info;
615
- }
616
- const otel = buildOtelBlock(options, spanCtx);
617
- if (otel) {
618
- telemetry.otel = otel;
619
- }
620
- return agentTelemetrySchema2.parse(telemetry);
621
- }
622
- function toolCallsFromOtelSpans(spans) {
623
- const counts = {};
624
- for (const span of spans) {
625
- counts[span.name] = (counts[span.name] ?? 0) + 1;
626
- }
627
- return counts;
628
- }
629
- export {
630
- agentTelemetryFromOtel,
631
- toolCallsFromOtelSpans
632
- };
633
- //# sourceMappingURL=index.js.map