agentv 3.11.1 → 3.13.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.
Files changed (122) hide show
  1. package/README.md +15 -12
  2. package/dist/{agentv-provider-MIDKLYIH-6LIYKQRP.js → agentv-provider-NFFLXG5M-TJAWCWCX.js} +1 -2
  3. package/dist/{chunk-CKMAM2GD.js → chunk-6H4IAXQH.js} +435 -198
  4. package/dist/chunk-6H4IAXQH.js.map +1 -0
  5. package/dist/{chunk-OYD2NB55.js → chunk-7OHZAFND.js} +120 -29
  6. package/dist/chunk-7OHZAFND.js.map +1 -0
  7. package/dist/{chunk-V2S5CZU3.js → chunk-DJU4C6NS.js} +914 -529
  8. package/dist/chunk-DJU4C6NS.js.map +1 -0
  9. package/dist/{chunk-BAUNAXHT.js → chunk-XOSNETAV.js} +1 -1
  10. package/dist/cli.js +4 -6
  11. package/dist/cli.js.map +1 -1
  12. package/dist/{dist-VUPMLHIV.js → dist-SMKOBBFB.js} +3 -8
  13. package/dist/{esm-OJ2BXJK4-YKEI3Z7E.js → esm-5Q4BZALM-5REQWAUV.js} +2 -3
  14. package/dist/{esm-OJ2BXJK4-YKEI3Z7E.js.map → esm-5Q4BZALM-5REQWAUV.js.map} +1 -1
  15. package/dist/{esm-UYZ3HJBU.js → esm-CZAWIY6F.js} +2 -2
  16. package/dist/index.js +4 -6
  17. package/dist/{interactive-FZJANO4A.js → interactive-RV664PCR.js} +4 -6
  18. package/dist/{interactive-FZJANO4A.js.map → interactive-RV664PCR.js.map} +1 -1
  19. package/dist/{otlp-json-file-exporter-VN67MK3S-RQIM6EHY.js → otlp-json-file-exporter-77FDBRSY-EZAPHWP6.js} +1 -2
  20. package/dist/{src-PXDA7QIS.js → src-ML4D2MC2.js} +2 -2
  21. package/package.json +1 -1
  22. package/dist/chunk-2QFWRIYL.js +0 -186
  23. package/dist/chunk-2QFWRIYL.js.map +0 -1
  24. package/dist/chunk-2RMPO6LY.js +0 -747
  25. package/dist/chunk-2RMPO6LY.js.map +0 -1
  26. package/dist/chunk-3Q7WIXT4.js +0 -4846
  27. package/dist/chunk-3Q7WIXT4.js.map +0 -1
  28. package/dist/chunk-73O2DCJP.js +0 -1274
  29. package/dist/chunk-73O2DCJP.js.map +0 -1
  30. package/dist/chunk-AUKF3Y3W.js +0 -212
  31. package/dist/chunk-AUKF3Y3W.js.map +0 -1
  32. package/dist/chunk-BRH7SIDP.js +0 -133
  33. package/dist/chunk-BRH7SIDP.js.map +0 -1
  34. package/dist/chunk-BXM4I3BM.js +0 -526
  35. package/dist/chunk-BXM4I3BM.js.map +0 -1
  36. package/dist/chunk-CKMAM2GD.js.map +0 -1
  37. package/dist/chunk-FHTURHTY.js +0 -546
  38. package/dist/chunk-FHTURHTY.js.map +0 -1
  39. package/dist/chunk-GJFXQQWG.js +0 -21
  40. package/dist/chunk-GJFXQQWG.js.map +0 -1
  41. package/dist/chunk-HKMLG4KF.js +0 -38
  42. package/dist/chunk-HKMLG4KF.js.map +0 -1
  43. package/dist/chunk-JGU3PVA4.js +0 -133
  44. package/dist/chunk-JGU3PVA4.js.map +0 -1
  45. package/dist/chunk-JK6V4KVD.js +0 -114
  46. package/dist/chunk-JK6V4KVD.js.map +0 -1
  47. package/dist/chunk-LHU5FGVZ.js +0 -4804
  48. package/dist/chunk-LHU5FGVZ.js.map +0 -1
  49. package/dist/chunk-OL2WGI6E.js +0 -149
  50. package/dist/chunk-OL2WGI6E.js.map +0 -1
  51. package/dist/chunk-ONETZL6N.js +0 -15
  52. package/dist/chunk-ONETZL6N.js.map +0 -1
  53. package/dist/chunk-OYD2NB55.js.map +0 -1
  54. package/dist/chunk-QV4UGEN6.js +0 -320
  55. package/dist/chunk-QV4UGEN6.js.map +0 -1
  56. package/dist/chunk-QXLDKGF3.js +0 -46
  57. package/dist/chunk-QXLDKGF3.js.map +0 -1
  58. package/dist/chunk-U6VEM66A.js +0 -63
  59. package/dist/chunk-U6VEM66A.js.map +0 -1
  60. package/dist/chunk-UALXHIMX.js +0 -48
  61. package/dist/chunk-UALXHIMX.js.map +0 -1
  62. package/dist/chunk-UGXG73VF.js +0 -55
  63. package/dist/chunk-UGXG73VF.js.map +0 -1
  64. package/dist/chunk-UHP5KEDL.js +0 -38
  65. package/dist/chunk-UHP5KEDL.js.map +0 -1
  66. package/dist/chunk-V2S5CZU3.js.map +0 -1
  67. package/dist/chunk-WVSXFZWP.js +0 -204
  68. package/dist/chunk-WVSXFZWP.js.map +0 -1
  69. package/dist/chunk-XSUMCWKO.js +0 -30
  70. package/dist/chunk-XSUMCWKO.js.map +0 -1
  71. package/dist/chunk-XUO7ZEHU.js +0 -181
  72. package/dist/chunk-XUO7ZEHU.js.map +0 -1
  73. package/dist/chunk-YSGUX5JT.js +0 -1002
  74. package/dist/chunk-YSGUX5JT.js.map +0 -1
  75. package/dist/dist-3PCP5TNF-RYMVLILE.js +0 -25785
  76. package/dist/dist-3PCP5TNF-RYMVLILE.js.map +0 -1
  77. package/dist/dist-BOIN5LC5-T5UWUK43.js +0 -76113
  78. package/dist/dist-BOIN5LC5-T5UWUK43.js.map +0 -1
  79. package/dist/dist-LXPDQOBI-4V5J2WDS.js +0 -13
  80. package/dist/dist-LXPDQOBI-4V5J2WDS.js.map +0 -1
  81. package/dist/dist-es-4WSJUIYR-XKIX65IH.js +0 -69
  82. package/dist/dist-es-4WSJUIYR-XKIX65IH.js.map +0 -1
  83. package/dist/dist-es-7K7MKRME-CCMAZOQC.js +0 -355
  84. package/dist/dist-es-7K7MKRME-CCMAZOQC.js.map +0 -1
  85. package/dist/dist-es-B2RTOKRI-VWZHK5RE.js +0 -191
  86. package/dist/dist-es-B2RTOKRI-VWZHK5RE.js.map +0 -1
  87. package/dist/dist-es-HHZ4FAXA-CRERHWKB.js +0 -164
  88. package/dist/dist-es-HHZ4FAXA-CRERHWKB.js.map +0 -1
  89. package/dist/dist-es-HVS3RPMX-AYJ3DW4L.js +0 -355
  90. package/dist/dist-es-HVS3RPMX-AYJ3DW4L.js.map +0 -1
  91. package/dist/dist-es-L6R4FPI5-IKIRYN45.js +0 -472
  92. package/dist/dist-es-L6R4FPI5-IKIRYN45.js.map +0 -1
  93. package/dist/dist-es-SRVEB5QV-Q4CTC2HX.js +0 -24
  94. package/dist/dist-es-TRIVUKV4-2J47CDXR.js +0 -85
  95. package/dist/dist-es-TRIVUKV4-2J47CDXR.js.map +0 -1
  96. package/dist/dist-es-UEEUAV34-IZQDTAMW.js +0 -16
  97. package/dist/esm-UYZ3HJBU.js.map +0 -1
  98. package/dist/event-streams-NZADSH5J-6MOSNEV3.js +0 -247
  99. package/dist/event-streams-NZADSH5J-6MOSNEV3.js.map +0 -1
  100. package/dist/loadSso-IQZ5NB6C-DZJTORO3.js +0 -738
  101. package/dist/loadSso-IQZ5NB6C-DZJTORO3.js.map +0 -1
  102. package/dist/multipart-parser-IPYBIGNL-LFMNMM6D.js +0 -387
  103. package/dist/multipart-parser-IPYBIGNL-LFMNMM6D.js.map +0 -1
  104. package/dist/otlp-json-file-exporter-VN67MK3S-RQIM6EHY.js.map +0 -1
  105. package/dist/signin-2ANR4DVS-K5VGBEJF.js +0 -556
  106. package/dist/signin-2ANR4DVS-K5VGBEJF.js.map +0 -1
  107. package/dist/simple-trace-file-exporter-XWZTIZR2-4JKATE5G.js +0 -10
  108. package/dist/simple-trace-file-exporter-XWZTIZR2-4JKATE5G.js.map +0 -1
  109. package/dist/src-SLOMUG7K-CV5JG263.js +0 -1408
  110. package/dist/src-SLOMUG7K-CV5JG263.js.map +0 -1
  111. package/dist/sso-oidc-HVCDATR2-CYP3BM5O.js +0 -708
  112. package/dist/sso-oidc-HVCDATR2-CYP3BM5O.js.map +0 -1
  113. package/dist/sts-X7JGSP4H-PDAAYDDH.js +0 -2917
  114. package/dist/sts-X7JGSP4H-PDAAYDDH.js.map +0 -1
  115. package/dist/undici-VAR2VUJI-6PAOUXZC.js +0 -23388
  116. package/dist/undici-VAR2VUJI-6PAOUXZC.js.map +0 -1
  117. /package/dist/{agentv-provider-MIDKLYIH-6LIYKQRP.js.map → agentv-provider-NFFLXG5M-TJAWCWCX.js.map} +0 -0
  118. /package/dist/{chunk-BAUNAXHT.js.map → chunk-XOSNETAV.js.map} +0 -0
  119. /package/dist/{dist-VUPMLHIV.js.map → dist-SMKOBBFB.js.map} +0 -0
  120. /package/dist/{dist-es-SRVEB5QV-Q4CTC2HX.js.map → esm-CZAWIY6F.js.map} +0 -0
  121. /package/dist/{dist-es-UEEUAV34-IZQDTAMW.js.map → otlp-json-file-exporter-77FDBRSY-EZAPHWP6.js.map} +0 -0
  122. /package/dist/{src-PXDA7QIS.js.map → src-ML4D2MC2.js.map} +0 -0
@@ -1,4 +1,7 @@
1
1
  import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
2
+ import {
3
+ require_token_error
4
+ } from "./chunk-HQDCIXVH.js";
2
5
  import {
3
6
  AISDKError,
4
7
  APICallError,
@@ -147,9 +150,6 @@ import {
147
150
  withoutTrailingSlash,
148
151
  zodSchema
149
152
  } from "./chunk-BJV6MDBE.js";
150
- import {
151
- require_token_error
152
- } from "./chunk-HQDCIXVH.js";
153
153
  import {
154
154
  SpanStatusCode,
155
155
  context,
@@ -14856,12 +14856,6 @@ function parseExecutionDefaults(raw, configPath) {
14856
14856
  } else if (obj.verbose !== void 0) {
14857
14857
  logWarning(`Invalid execution.verbose in ${configPath}, expected boolean`);
14858
14858
  }
14859
- const traceFile = obj.trace_file;
14860
- if (typeof traceFile === "string" && traceFile.trim().length > 0) {
14861
- result.trace_file = traceFile.trim();
14862
- } else if (traceFile !== void 0) {
14863
- logWarning(`Invalid execution.trace_file in ${configPath}, expected non-empty string`);
14864
- }
14865
14859
  if (typeof obj.keep_workspaces === "boolean") {
14866
14860
  result.keep_workspaces = obj.keep_workspaces;
14867
14861
  } else if (obj.keep_workspaces !== void 0) {
@@ -21644,7 +21638,7 @@ async function loadSdkModules() {
21644
21638
  try {
21645
21639
  [piCodingAgentModule, piAiModule] = await Promise.all([
21646
21640
  import("@mariozechner/pi-coding-agent"),
21647
- import("./dist-BOIN5LC5-T5UWUK43.js")
21641
+ import("@mariozechner/pi-ai")
21648
21642
  ]);
21649
21643
  } catch {
21650
21644
  if (await promptInstall()) {
@@ -21652,7 +21646,7 @@ async function loadSdkModules() {
21652
21646
  execSync("bun add @mariozechner/pi-coding-agent", { stdio: "inherit" });
21653
21647
  [piCodingAgentModule, piAiModule] = await Promise.all([
21654
21648
  import("@mariozechner/pi-coding-agent"),
21655
- import("./dist-BOIN5LC5-T5UWUK43.js")
21649
+ import("@mariozechner/pi-ai")
21656
21650
  ]);
21657
21651
  } else {
21658
21652
  throw new Error(
@@ -23614,10 +23608,26 @@ function extractJsonBlob(text2) {
23614
23608
  const match = text2.match(/\{[\s\S]*\}/);
23615
23609
  return match?.[0];
23616
23610
  }
23611
+ function repairSchemaNearBooleanFields(text2) {
23612
+ return text2.replace(
23613
+ /("passed"\s*:\s*)(?:"([^"]+)"|([A-Za-z_][A-Za-z0-9_-]*))/gi,
23614
+ (_match, prefix, quotedValue, bareValue) => {
23615
+ const value = (quotedValue ?? bareValue ?? "").trim().toLowerCase();
23616
+ if (value === "true") {
23617
+ return `${prefix}true`;
23618
+ }
23619
+ if (value === "false") {
23620
+ return `${prefix}false`;
23621
+ }
23622
+ return `${prefix}false`;
23623
+ }
23624
+ );
23625
+ }
23617
23626
  function parseJsonFromText(text2) {
23618
23627
  const cleaned = typeof text2 === "string" ? text2.replace(/```json\n?|```/g, "").trim() : "";
23619
23628
  const blob = extractJsonBlob(cleaned) ?? cleaned;
23620
- return JSON.parse(blob);
23629
+ const repaired = repairSchemaNearBooleanFields(blob);
23630
+ return JSON.parse(repaired);
23621
23631
  }
23622
23632
  function isNonEmptyString(value) {
23623
23633
  return typeof value === "string" && value.trim().length > 0;
@@ -24416,7 +24426,7 @@ ${context2.fileChanges}`;
24416
24426
  async evaluateWithRubrics(context2, graderProvider, rubrics) {
24417
24427
  if (!rubrics || rubrics.length === 0) {
24418
24428
  throw new Error(
24419
- `No rubrics found for evaluator "${context2.evaluator?.name ?? "llm-grader"}". Run "agentv generate rubrics" first.`
24429
+ `No rubrics found for evaluator "${context2.evaluator?.name ?? "llm-grader"}". Add rubric criteria under assertions or use the agentv-eval-writer skill for authoring help.`
24420
24430
  );
24421
24431
  }
24422
24432
  const hasScoreRanges = rubrics.some((r) => r.score_ranges && r.score_ranges.length > 0);
@@ -28654,7 +28664,7 @@ async function runEvaluation(options) {
28654
28664
  if (!cliModel) {
28655
28665
  throw new Error('--grader-target "agentv" requires --model (e.g., "openai:gpt-5-mini")');
28656
28666
  }
28657
- const { AgentvProvider: AgentvProvider2 } = await import("./agentv-provider-MIDKLYIH-6LIYKQRP.js");
28667
+ const { AgentvProvider: AgentvProvider2 } = await import("./agentv-provider-NFFLXG5M-TJAWCWCX.js");
28658
28668
  return new AgentvProvider2("agentv", { model: cliModel, temperature: 0 });
28659
28669
  }
28660
28670
  const overrideTarget = resolveTargetByName(cliGraderTarget);
@@ -30717,8 +30727,6 @@ var AgentVConfigSchema = external_exports2.object({
30717
30727
  agentTimeoutMs: external_exports2.number().int().min(0).optional(),
30718
30728
  /** Enable verbose logging */
30719
30729
  verbose: external_exports2.boolean().optional(),
30720
- /** Write human-readable trace JSONL to this path (supports {timestamp} placeholder) */
30721
- traceFile: external_exports2.string().optional(),
30722
30730
  /** Always keep temp workspaces after eval */
30723
30731
  keepWorkspaces: external_exports2.boolean().optional(),
30724
30732
  /** Write OTLP JSON trace to this path (supports {timestamp} placeholder) */
@@ -30978,11 +30986,11 @@ var OtelTraceExporter = class {
30978
30986
  async init() {
30979
30987
  try {
30980
30988
  const [sdkTraceNode, resourcesMod, semconvMod, api, coreMod] = await Promise.all([
30981
- import("./src-PXDA7QIS.js"),
30982
- import("./esm-UYZ3HJBU.js"),
30989
+ import("./src-ML4D2MC2.js"),
30990
+ import("./esm-CZAWIY6F.js"),
30983
30991
  import("./esm-RVQPUGWH.js"),
30984
30992
  import("./esm-R77SNOF5.js"),
30985
- import("./esm-OJ2BXJK4-YKEI3Z7E.js").catch(() => null)
30993
+ import("./esm-5Q4BZALM-5REQWAUV.js").catch(() => null)
30986
30994
  ]);
30987
30995
  const { NodeTracerProvider: Provider, SimpleSpanProcessor } = sdkTraceNode;
30988
30996
  const { resourceFromAttributes } = resourcesMod;
@@ -31001,17 +31009,11 @@ var OtelTraceExporter = class {
31001
31009
  processors.push(new SimpleSpanProcessor(exporter));
31002
31010
  }
31003
31011
  if (this.options.otlpFilePath) {
31004
- const { OtlpJsonFileExporter: OtlpJsonFileExporter2 } = await import("./otlp-json-file-exporter-VN67MK3S-RQIM6EHY.js");
31012
+ const { OtlpJsonFileExporter: OtlpJsonFileExporter2 } = await import("./otlp-json-file-exporter-77FDBRSY-EZAPHWP6.js");
31005
31013
  processors.push(
31006
31014
  new SimpleSpanProcessor(new OtlpJsonFileExporter2(this.options.otlpFilePath))
31007
31015
  );
31008
31016
  }
31009
- if (this.options.traceFilePath) {
31010
- const { SimpleTraceFileExporter: SimpleTraceFileExporter2 } = await import("./simple-trace-file-exporter-XWZTIZR2-4JKATE5G.js");
31011
- processors.push(
31012
- new SimpleSpanProcessor(new SimpleTraceFileExporter2(this.options.traceFilePath))
31013
- );
31014
- }
31015
31017
  if (processors.length === 0) {
31016
31018
  return false;
31017
31019
  }
@@ -31071,6 +31073,17 @@ var OtelTraceExporter = class {
31071
31073
  if (result.durationMs != null)
31072
31074
  rootSpan.setAttribute("agentv.trace.duration_ms", result.durationMs);
31073
31075
  if (result.costUsd != null) rootSpan.setAttribute("agentv.trace.cost_usd", result.costUsd);
31076
+ if (result.tokenUsage) {
31077
+ if (result.tokenUsage.input != null) {
31078
+ rootSpan.setAttribute("agentv.trace.token_input", result.tokenUsage.input);
31079
+ }
31080
+ if (result.tokenUsage.output != null) {
31081
+ rootSpan.setAttribute("agentv.trace.token_output", result.tokenUsage.output);
31082
+ }
31083
+ if (result.tokenUsage.cached != null) {
31084
+ rootSpan.setAttribute("agentv.trace.token_cached", result.tokenUsage.cached);
31085
+ }
31086
+ }
31074
31087
  if (result.trace) {
31075
31088
  const t = result.trace;
31076
31089
  rootSpan.setAttribute("agentv.trace.event_count", t.eventCount);
@@ -31173,6 +31186,7 @@ var OtelTraceExporter = class {
31173
31186
  tracer.startActiveSpan(
31174
31187
  spanName,
31175
31188
  { startTime: startHr },
31189
+ parentCtx,
31176
31190
  (span) => {
31177
31191
  if (isAssistant) {
31178
31192
  span.setAttribute("gen_ai.operation.name", "chat");
@@ -31205,6 +31219,7 @@ var OtelTraceExporter = class {
31205
31219
  tracer.startActiveSpan(
31206
31220
  `execute_tool ${tc.tool}`,
31207
31221
  {},
31222
+ msgCtx,
31208
31223
  (toolSpan) => {
31209
31224
  toolSpan.setAttribute("gen_ai.tool.name", tc.tool);
31210
31225
  if (tc.id) toolSpan.setAttribute("gen_ai.tool.call.id", tc.id);
@@ -31245,8 +31260,12 @@ var OtelStreamingObserver = class {
31245
31260
  rootSpan = null;
31246
31261
  // biome-ignore lint/suspicious/noExplicitAny: OTel context loaded dynamically
31247
31262
  rootCtx = null;
31263
+ observedChildSpans = false;
31264
+ pendingMetrics = null;
31248
31265
  /** Create root eval span immediately (visible in backend right away) */
31249
31266
  startEvalCase(testId, target, evalSet) {
31267
+ this.pendingMetrics = null;
31268
+ this.observedChildSpans = false;
31250
31269
  const ctx = this.parentCtx ?? this.api.context.active();
31251
31270
  this.rootSpan = this.tracer.startSpan("agentv.eval", void 0, ctx);
31252
31271
  this.rootSpan.setAttribute("gen_ai.operation.name", "evaluate");
@@ -31259,8 +31278,9 @@ var OtelStreamingObserver = class {
31259
31278
  /** Create and immediately export a tool span */
31260
31279
  onToolCall(name21, input, output, _durationMs, toolCallId) {
31261
31280
  if (!this.rootCtx) return;
31281
+ this.observedChildSpans = true;
31262
31282
  this.api.context.with(this.rootCtx, () => {
31263
- const span = this.tracer.startSpan(`execute_tool ${name21}`);
31283
+ const span = this.tracer.startSpan(`execute_tool ${name21}`, void 0, this.rootCtx);
31264
31284
  span.setAttribute("gen_ai.tool.name", name21);
31265
31285
  if (toolCallId) span.setAttribute("gen_ai.tool.call.id", toolCallId);
31266
31286
  if (this.captureContent) {
@@ -31281,8 +31301,9 @@ var OtelStreamingObserver = class {
31281
31301
  /** Create and immediately export an LLM span */
31282
31302
  onLlmCall(model, tokenUsage) {
31283
31303
  if (!this.rootCtx) return;
31304
+ this.observedChildSpans = true;
31284
31305
  this.api.context.with(this.rootCtx, () => {
31285
- const span = this.tracer.startSpan(`chat ${model}`);
31306
+ const span = this.tracer.startSpan(`chat ${model}`, void 0, this.rootCtx);
31286
31307
  span.setAttribute("gen_ai.operation.name", "chat");
31287
31308
  span.setAttribute("gen_ai.request.model", model);
31288
31309
  span.setAttribute("gen_ai.response.model", model);
@@ -31297,10 +31318,53 @@ var OtelStreamingObserver = class {
31297
31318
  span.end();
31298
31319
  });
31299
31320
  }
31321
+ /** Record final execution metrics before the root span is finalized. */
31322
+ recordEvalMetrics(result) {
31323
+ this.pendingMetrics = result;
31324
+ }
31300
31325
  /** Finalize root span with score/verdict after evaluation completes */
31301
31326
  finalizeEvalCase(score, error) {
31302
31327
  if (!this.rootSpan) return;
31303
31328
  this.rootSpan.setAttribute("agentv.score", score);
31329
+ if (this.pendingMetrics?.durationMs != null) {
31330
+ this.rootSpan.setAttribute("agentv.trace.duration_ms", this.pendingMetrics.durationMs);
31331
+ }
31332
+ if (this.pendingMetrics?.costUsd != null) {
31333
+ this.rootSpan.setAttribute("agentv.trace.cost_usd", this.pendingMetrics.costUsd);
31334
+ }
31335
+ if (this.pendingMetrics?.tokenUsage) {
31336
+ if (this.pendingMetrics.tokenUsage.input != null) {
31337
+ this.rootSpan.setAttribute(
31338
+ "agentv.trace.token_input",
31339
+ this.pendingMetrics.tokenUsage.input
31340
+ );
31341
+ }
31342
+ if (this.pendingMetrics.tokenUsage.output != null) {
31343
+ this.rootSpan.setAttribute(
31344
+ "agentv.trace.token_output",
31345
+ this.pendingMetrics.tokenUsage.output
31346
+ );
31347
+ }
31348
+ if (this.pendingMetrics.tokenUsage.cached != null) {
31349
+ this.rootSpan.setAttribute(
31350
+ "agentv.trace.token_cached",
31351
+ this.pendingMetrics.tokenUsage.cached
31352
+ );
31353
+ }
31354
+ }
31355
+ if (this.pendingMetrics?.trace) {
31356
+ this.rootSpan.setAttribute("agentv.trace.event_count", this.pendingMetrics.trace.eventCount);
31357
+ this.rootSpan.setAttribute(
31358
+ "agentv.trace.tool_names",
31359
+ Object.keys(this.pendingMetrics.trace.toolCalls).sort().join(",")
31360
+ );
31361
+ if (this.pendingMetrics.trace.llmCallCount != null) {
31362
+ this.rootSpan.setAttribute(
31363
+ "agentv.trace.llm_call_count",
31364
+ this.pendingMetrics.trace.llmCallCount
31365
+ );
31366
+ }
31367
+ }
31304
31368
  if (error) {
31305
31369
  this.rootSpan.setStatus({ code: this.api.SpanStatusCode.ERROR, message: error });
31306
31370
  } else {
@@ -31309,6 +31373,33 @@ var OtelStreamingObserver = class {
31309
31373
  this.rootSpan.end();
31310
31374
  this.rootSpan = null;
31311
31375
  this.rootCtx = null;
31376
+ this.observedChildSpans = false;
31377
+ this.pendingMetrics = null;
31378
+ }
31379
+ /** Backfill child spans from the completed result when the provider emitted no live callbacks. */
31380
+ completeFromResult(result) {
31381
+ this.recordEvalMetrics({
31382
+ durationMs: result.durationMs,
31383
+ costUsd: result.costUsd,
31384
+ tokenUsage: result.tokenUsage,
31385
+ trace: result.trace
31386
+ });
31387
+ if (this.observedChildSpans || !this.rootCtx) {
31388
+ return;
31389
+ }
31390
+ const model = result.output.find((msg) => msg.role === "assistant")?.metadata?.model ?? result.target ?? "unknown";
31391
+ this.onLlmCall(String(model), result.tokenUsage);
31392
+ for (const message of result.output) {
31393
+ for (const toolCall of message.toolCalls ?? []) {
31394
+ this.onToolCall(
31395
+ toolCall.tool,
31396
+ toolCall.input,
31397
+ toolCall.output,
31398
+ toolCall.durationMs ?? 0,
31399
+ toolCall.id
31400
+ );
31401
+ }
31402
+ }
31312
31403
  }
31313
31404
  /** Return the active eval span's trace ID and span ID for Braintrust trace bridging */
31314
31405
  getActiveSpanIds() {
@@ -31499,4 +31590,4 @@ export {
31499
31590
  OtelStreamingObserver,
31500
31591
  createAgentKernel
31501
31592
  };
31502
- //# sourceMappingURL=chunk-OYD2NB55.js.map
31593
+ //# sourceMappingURL=chunk-7OHZAFND.js.map