@axlsdk/axl 0.24.1 → 0.24.2

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/index.js CHANGED
@@ -120,12 +120,14 @@ function preserveErrorCause(error, cause) {
120
120
  });
121
121
  return error;
122
122
  }
123
+ var TOOL_FAILURE_MARKER = /* @__PURE__ */ Symbol.for("axl.toolFailure.v1");
123
124
  var ToolFailure = class extends AxlError {
124
125
  modelMessage;
125
126
  constructor(options) {
126
127
  super(options.code ?? "TOOL_FAILURE", options.message);
127
128
  this.name = "ToolFailure";
128
129
  this.modelMessage = options.modelMessage;
130
+ Object.defineProperty(this, TOOL_FAILURE_MARKER, { value: true });
129
131
  if (options.cause !== void 0) {
130
132
  Object.defineProperty(this, "cause", {
131
133
  configurable: true,
@@ -135,6 +137,13 @@ var ToolFailure = class extends AxlError {
135
137
  }
136
138
  }
137
139
  };
140
+ function isToolFailureError(error) {
141
+ try {
142
+ return error instanceof ToolFailure || typeof error === "object" && error !== null && error[TOOL_FAILURE_MARKER] === true && typeof error.modelMessage === "string";
143
+ } catch {
144
+ return false;
145
+ }
146
+ }
138
147
  var ToolModelOutputError = class extends AxlError {
139
148
  toolName;
140
149
  cause;
@@ -316,7 +325,7 @@ var sharedGuard = typeof installedGuard === "object" && installedGuard !== null
316
325
  var buildPath = typeof __AXL_BUILD_PATH__ === "string" ? __AXL_BUILD_PATH__ : "<source>";
317
326
  var thisCopy = {
318
327
  path: buildPath.startsWith("file:") ? fileURLToPath(buildPath) : buildPath,
319
- version: true ? "0.24.1" : "unknown"
328
+ version: true ? "0.24.2" : "unknown"
320
329
  };
321
330
  function warnCrossCopy(other, joined) {
322
331
  if (other === thisCopy) return;
@@ -417,10 +426,16 @@ var AccountingScope = class {
417
426
  reasons = /* @__PURE__ */ new Map();
418
427
  breakdown = { generation: 0, judging: 0, external: 0 };
419
428
  provenance = /* @__PURE__ */ new Map();
429
+ modelCalls = /* @__PURE__ */ new Map();
430
+ modelTiming = /* @__PURE__ */ new Map();
431
+ diagnosticTokens = { input: 0, output: 0, reasoning: 0 };
432
+ agentCalls = 0;
433
+ captureTimingSamples;
420
434
  constructor(options) {
421
435
  this.parent = options.parent;
422
436
  this.purpose = options.purpose;
423
437
  this.admission = options.admission;
438
+ this.captureTimingSamples = options.captureTimingSamples === true;
424
439
  }
425
440
  get isFinalized() {
426
441
  return this.finalized;
@@ -449,7 +464,7 @@ var AccountingScope = class {
449
464
  else this.byKind.delete(op.kind);
450
465
  this.denied += 1;
451
466
  }
452
- recordSettled(op, cost, provenance, usage) {
467
+ recordSettled(op, cost, provenance, usage, timing) {
453
468
  this.seen.add(op.id);
454
469
  this.openOps.delete(op.id);
455
470
  this.settled += 1;
@@ -458,13 +473,57 @@ var AccountingScope = class {
458
473
  else this.breakdown[op.purpose] += cost;
459
474
  this.provenance.set(provenance, (this.provenance.get(provenance) ?? 0) + cost);
460
475
  if (usage) this.addUsage(usage);
476
+ this.recordAgentCall(op, usage, timing);
461
477
  }
462
- recordUnknown(op, reason, usage) {
478
+ recordUnknown(op, reason, usage, timing) {
463
479
  this.seen.add(op.id);
464
480
  this.openOps.delete(op.id);
465
481
  this.unknown += 1;
466
482
  this.reasons.set(reason, (this.reasons.get(reason) ?? 0) + 1);
467
483
  if (usage) this.addUsage(usage);
484
+ this.recordAgentCall(op, usage, timing);
485
+ }
486
+ recordAgentCall(op, usage, timing) {
487
+ if (!op.agentCall) return;
488
+ this.agentCalls++;
489
+ const model = op.diagnosticModelUri ?? op.model;
490
+ if (!model) return;
491
+ this.modelCalls.set(model, (this.modelCalls.get(model) ?? 0) + 1);
492
+ if (usage) {
493
+ const finite = (value) => typeof value === "number" && Number.isFinite(value) ? value : 0;
494
+ this.diagnosticTokens.input += finite(usage.inputTokens);
495
+ this.diagnosticTokens.output += finite(usage.outputTokens);
496
+ this.diagnosticTokens.reasoning += finite(usage.reasoningTokens);
497
+ }
498
+ if (!timing) return;
499
+ let bucket = this.modelTiming.get(model);
500
+ if (!bucket) {
501
+ bucket = {
502
+ calls: 0,
503
+ queuedMs: 0,
504
+ retryMs: 0,
505
+ wireMs: 0,
506
+ ...this.captureTimingSamples ? { samples: [] } : {}
507
+ };
508
+ this.modelTiming.set(model, bucket);
509
+ }
510
+ bucket.calls++;
511
+ bucket.queuedMs += timing.queuedMs;
512
+ bucket.retryMs += timing.retryMs;
513
+ bucket.wireMs += timing.wireMs;
514
+ bucket.samples?.push(timing);
515
+ if (timing.firstTokenMs != null) {
516
+ bucket.firstTokenMs = (bucket.firstTokenMs ?? 0) + timing.firstTokenMs;
517
+ bucket.firstTokenCalls = (bucket.firstTokenCalls ?? 0) + 1;
518
+ }
519
+ }
520
+ toDiagnostics() {
521
+ return {
522
+ modelCallCounts: Object.fromEntries(this.modelCalls),
523
+ tokens: { ...this.diagnosticTokens },
524
+ agentCalls: this.agentCalls,
525
+ modelTiming: Object.fromEntries(this.modelTiming)
526
+ };
468
527
  }
469
528
  hasSeen(id) {
470
529
  return this.seen.has(id);
@@ -536,14 +595,14 @@ function settleOperationUp(start, op, outcome) {
536
595
  if (scope.isFinalized) return;
537
596
  switch (outcome.outcome) {
538
597
  case "settled":
539
- scope.recordSettled(op, outcome.cost, outcome.provenance, outcome.usage);
598
+ scope.recordSettled(op, outcome.cost, outcome.provenance, outcome.usage, outcome.timing);
540
599
  if (scope.admission && !chargedControllers.has(scope.admission)) {
541
600
  chargedControllers.add(scope.admission);
542
601
  recordSpend(scope.admission, outcome.cost);
543
602
  }
544
603
  break;
545
604
  case "unknown":
546
- scope.recordUnknown(op, outcome.reason, outcome.usage);
605
+ scope.recordUnknown(op, outcome.reason, outcome.usage, outcome.timing);
547
606
  break;
548
607
  case "retracted":
549
608
  scope.recordRetracted(op);
@@ -595,6 +654,8 @@ function openOperation(descriptor) {
595
654
  kind: descriptor.kind,
596
655
  purpose: scope.purpose,
597
656
  model: descriptor.model,
657
+ diagnosticModelUri: descriptor.diagnosticModelUri,
658
+ agentCall: descriptor.agentCall === true,
598
659
  dispatched: false,
599
660
  dispatchObservable: false
600
661
  };
@@ -635,25 +696,31 @@ function openOperation(descriptor) {
635
696
  outcome: "settled",
636
697
  cost: input.cost,
637
698
  provenance: input.provenance ?? "adapter_reported",
638
- usage: input.usage
699
+ usage: input.usage,
700
+ timing: input.timing
639
701
  });
640
702
  return;
641
703
  }
642
704
  if (input.cost !== void 0 || input.usage !== void 0) {
643
- finish({ outcome: "unknown", reason: "unpriced_model", usage: input.usage });
705
+ finish({
706
+ outcome: "unknown",
707
+ reason: "unpriced_model",
708
+ usage: input.usage,
709
+ timing: input.timing
710
+ });
644
711
  return;
645
712
  }
646
- handle.settleFailure();
713
+ handle.settleFailure(void 0, input.timing);
647
714
  },
648
715
  settleUnknown(reason, usage) {
649
716
  finish({ outcome: "unknown", reason, usage });
650
717
  },
651
- settleFailure(usage) {
718
+ settleFailure(usage, timing) {
652
719
  if (op.dispatchObservable && !op.dispatched) {
653
- finish({ outcome: "settled", cost: 0, provenance: "adapter_reported", usage });
720
+ finish({ outcome: "settled", cost: 0, provenance: "adapter_reported", usage, timing });
654
721
  return;
655
722
  }
656
- finish({ outcome: "unknown", reason: "usage_missing", usage });
723
+ finish({ outcome: "unknown", reason: "usage_missing", usage, timing });
657
724
  },
658
725
  run(fn) {
659
726
  return runWithDispatchAdmission(handle.dispatchAdmission, fn);
@@ -666,7 +733,8 @@ async function runInAccountingScope(options, fn) {
666
733
  const scope = new AccountingScope({
667
734
  parent,
668
735
  purpose: options.purpose ?? parent?.purpose ?? "generation",
669
- admission: options.admission
736
+ admission: options.admission,
737
+ captureTimingSamples: options.captureTimingSamples
670
738
  });
671
739
  const inheritedGuard = sharedGuard.storage.getStore();
672
740
  const enclosingGuard = inheritedGuard && (inheritedGuard.isActive?.() ?? true) ? inheritedGuard : void 0;
@@ -684,7 +752,8 @@ async function runInAccountingScope(options, fn) {
684
752
  "The active @axlsdk/axl accounting scope uses an incompatible loaded copy; paid work was refused before dispatch."
685
753
  )
686
754
  },
687
- accounting: scope.toAccounting()
755
+ accounting: scope.toAccounting(),
756
+ diagnostics: scope.toDiagnostics()
688
757
  };
689
758
  }
690
759
  const markUninstrumented = () => {
@@ -708,10 +777,18 @@ async function runInAccountingScope(options, fn) {
708
777
  () => accountingStorage.run(scope, fn)
709
778
  );
710
779
  scope.finalize();
711
- return { outcome: { status: "fulfilled", value }, accounting: scope.toAccounting() };
780
+ return {
781
+ outcome: { status: "fulfilled", value },
782
+ accounting: scope.toAccounting(),
783
+ diagnostics: scope.toDiagnostics()
784
+ };
712
785
  } catch (error) {
713
786
  scope.finalize();
714
- return { outcome: { status: "rejected", error }, accounting: scope.toAccounting() };
787
+ return {
788
+ outcome: { status: "rejected", error },
789
+ accounting: scope.toAccounting(),
790
+ diagnostics: scope.toDiagnostics()
791
+ };
715
792
  }
716
793
  }
717
794
  function validateReportedCost(amountUsd) {
@@ -1090,10 +1167,12 @@ function toolArgumentIssues(error) {
1090
1167
  }
1091
1168
  return [{ path: [], code: "invalid_arguments", message: "Tool arguments are invalid." }];
1092
1169
  }
1093
- var TOOL_INTERNALS = /* @__PURE__ */ new WeakMap();
1170
+ var TOOL_INTERNALS = /* @__PURE__ */ Symbol.for("axl.tool.internals.v1");
1094
1171
  function getToolInternals(tool2) {
1095
- const internals = TOOL_INTERNALS.get(tool2);
1096
- if (!internals) throw new Error(`Tool "${tool2.name}" was not created by tool()`);
1172
+ const internals = tool2[TOOL_INTERNALS];
1173
+ if (!internals || typeof internals.prepareInput !== "function" || typeof internals.executePrepared !== "function") {
1174
+ throw new Error(`Tool "${tool2.name}" was not created by a compatible tool()`);
1175
+ }
1097
1176
  return internals;
1098
1177
  }
1099
1178
  function prepareToolInput(tool2, input) {
@@ -1194,9 +1273,11 @@ function tool(config) {
1194
1273
  },
1195
1274
  _execute: execute
1196
1275
  };
1197
- TOOL_INTERNALS.set(instance, {
1198
- prepareInput,
1199
- executePrepared
1276
+ Object.defineProperty(instance, TOOL_INTERNALS, {
1277
+ value: {
1278
+ prepareInput,
1279
+ executePrepared
1280
+ }
1200
1281
  });
1201
1282
  return instance;
1202
1283
  }
@@ -1227,6 +1308,7 @@ async function resolveApiKey(source) {
1227
1308
  // src/providers/default-endpoints.ts
1228
1309
  var OPENAI_DEFAULT_BASE_URL = "https://api.openai.com/v1";
1229
1310
  var ANTHROPIC_DEFAULT_BASE_URL = "https://api.anthropic.com/v1";
1311
+ var GEMINI_DEFAULT_BASE_URL = "https://generativelanguage.googleapis.com/v1beta";
1230
1312
 
1231
1313
  // src/providers/rate-limiter.ts
1232
1314
  function sanitizeRateLimitConfig(config) {
@@ -1624,12 +1706,36 @@ var anthropicQuotaDialect = makeDialect(
1624
1706
  return "unknown";
1625
1707
  }
1626
1708
  );
1709
+ var geminiQuotaDialect = makeDialect([], (error) => {
1710
+ if (error.code === "quota_exceeded") return "spend_cap";
1711
+ if (Array.isArray(error.details)) {
1712
+ for (const detail of error.details) {
1713
+ if (typeof detail !== "object" || detail === null) continue;
1714
+ const violations = detail.violations;
1715
+ if (!Array.isArray(violations)) continue;
1716
+ if (violations.some((violation) => {
1717
+ if (typeof violation !== "object" || violation === null) return false;
1718
+ const id = violation.quotaId;
1719
+ return typeof id === "string" && /perday|daily|spend|billing/i.test(id);
1720
+ }))
1721
+ return "spend_cap";
1722
+ }
1723
+ }
1724
+ const message = error.message;
1725
+ if (typeof message === "string" && /monthly spending cap|spend(?:-based|ing)? (?:cap|limit)|prepay(?:ment)? credits? (?:are )?depleted/i.test(
1726
+ message
1727
+ )) {
1728
+ return "spend_cap";
1729
+ }
1730
+ return "unknown";
1731
+ });
1627
1732
  var DIALECTS = /* @__PURE__ */ new Map([
1628
1733
  ["openai", { origin: new URL(OPENAI_DEFAULT_BASE_URL).origin, dialect: openaiQuotaDialect }],
1629
1734
  [
1630
1735
  "anthropic",
1631
1736
  { origin: new URL(ANTHROPIC_DEFAULT_BASE_URL).origin, dialect: anthropicQuotaDialect }
1632
- ]
1737
+ ],
1738
+ ["google", { origin: new URL(GEMINI_DEFAULT_BASE_URL).origin, dialect: geminiQuotaDialect }]
1633
1739
  ]);
1634
1740
  function quotaDialectFor(family, origin) {
1635
1741
  const entry = DIALECTS.get(family);
@@ -5820,7 +5926,7 @@ var GEMINI_PRICING = {
5820
5926
  },
5821
5927
  "gemini-3.8-flash": { input: 75e-8, cached: 75e-9, output: 375e-8 }
5822
5928
  };
5823
- var CANONICAL_GEMINI_BASE_URL = "https://generativelanguage.googleapis.com/v1beta";
5929
+ var CANONICAL_GEMINI_BASE_URL = GEMINI_DEFAULT_BASE_URL;
5824
5930
  function isValidTokenCount2(value) {
5825
5931
  return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
5826
5932
  }
@@ -6177,10 +6283,7 @@ var GeminiProvider = class {
6177
6283
  axlRateGovernors;
6178
6284
  constructor(options = {}) {
6179
6285
  this.apiKeySource = options.apiKey ?? process.env.GOOGLE_API_KEY ?? process.env.GEMINI_API_KEY ?? "";
6180
- this.baseUrl = (options.baseUrl ?? "https://generativelanguage.googleapis.com/v1beta").replace(
6181
- /\/$/,
6182
- ""
6183
- );
6286
+ this.baseUrl = (options.baseUrl ?? GEMINI_DEFAULT_BASE_URL).replace(/\/$/, "");
6184
6287
  assertSafeProviderBaseUrl(
6185
6288
  this.baseUrl,
6186
6289
  "Google provider",
@@ -11379,6 +11482,34 @@ function toAccountingUsage(usage) {
11379
11482
  cacheWriteTokens: usage.cache_write_tokens ?? 0
11380
11483
  };
11381
11484
  }
11485
+ function safeTiming(response) {
11486
+ try {
11487
+ const timing = response.timing;
11488
+ if (!timing) return void 0;
11489
+ const queuedMs = timing.queuedMs;
11490
+ const retryMs = timing.retryMs;
11491
+ const wireMs = timing.wireMs;
11492
+ if (![queuedMs, retryMs, wireMs].every((value) => Number.isFinite(value) && value >= 0)) {
11493
+ return void 0;
11494
+ }
11495
+ const attempts = timing.attempts;
11496
+ const ttfbMs = timing.ttfbMs;
11497
+ const rateLimitRetries = timing.rateLimitRetries;
11498
+ const firstTokenMs = timing.firstTokenMs;
11499
+ const valid = (value) => typeof value === "number" && Number.isFinite(value) && value >= 0;
11500
+ return {
11501
+ queuedMs,
11502
+ retryMs,
11503
+ wireMs,
11504
+ ...valid(attempts) ? { attempts } : {},
11505
+ ...valid(ttfbMs) ? { ttfbMs } : {},
11506
+ ...valid(rateLimitRetries) ? { rateLimitRetries } : {},
11507
+ ...valid(firstTokenMs) ? { firstTokenMs } : {}
11508
+ };
11509
+ } catch {
11510
+ return void 0;
11511
+ }
11512
+ }
11382
11513
  function composeLifecycle(caller, onDispatch) {
11383
11514
  return {
11384
11515
  onDispatch() {
@@ -11572,7 +11703,13 @@ var CaptureRecorder = class {
11572
11703
  }
11573
11704
  };
11574
11705
  function openProviderOperation(raw, kind, options) {
11575
- const handle = openOperation({ kind, model: options.model, provider: raw.name });
11706
+ const handle = openOperation({
11707
+ kind,
11708
+ model: options.model,
11709
+ diagnosticModelUri: options.accountingModelUri,
11710
+ provider: raw.name,
11711
+ agentCall: options.accountingModelUri !== void 0
11712
+ });
11576
11713
  if (handle && raw.reportsRequestLifecycle === true) handle.markDispatchObservable();
11577
11714
  return handle;
11578
11715
  }
@@ -11589,7 +11726,8 @@ function createScopedProvider(raw) {
11589
11726
  handle.settle({
11590
11727
  cost: response.cost,
11591
11728
  provenance: response.costProvenance,
11592
- usage: toAccountingUsage(response.usage)
11729
+ usage: toAccountingUsage(response.usage),
11730
+ timing: safeTiming(response)
11593
11731
  });
11594
11732
  recorder?.end({ response });
11595
11733
  return response;
@@ -11644,7 +11782,8 @@ function createScopedProvider(raw) {
11644
11782
  handle?.settle({
11645
11783
  cost: result.value.cost,
11646
11784
  provenance: result.value.costProvenance,
11647
- usage: toAccountingUsage(result.value.usage)
11785
+ usage: toAccountingUsage(result.value.usage),
11786
+ timing: safeTiming(result.value)
11648
11787
  });
11649
11788
  settled = true;
11650
11789
  recorder?.end({
@@ -12077,13 +12216,6 @@ function eventError(error) {
12077
12216
  return { name: "Error", message: "Unknown thrown value" };
12078
12217
  }
12079
12218
  }
12080
- function isToolFailure(error) {
12081
- try {
12082
- return error instanceof ToolFailure;
12083
- } catch {
12084
- return false;
12085
- }
12086
- }
12087
12219
  function cancellation(phase, error, result) {
12088
12220
  let reason;
12089
12221
  try {
@@ -12099,7 +12231,7 @@ function cancellation(phase, error, result) {
12099
12231
  }
12100
12232
  function failed(phase, error, options = {}) {
12101
12233
  let modelMessage;
12102
- if (isToolFailure(error)) {
12234
+ if (isToolFailureError(error)) {
12103
12235
  try {
12104
12236
  modelMessage = typeof error.modelMessage === "string" ? error.modelMessage : void 0;
12105
12237
  } catch {
@@ -13787,6 +13919,7 @@ ${appendedSchemaText}`;
13787
13919
  const turnStart = Date.now();
13788
13920
  const chatOptions = {
13789
13921
  model,
13922
+ accountingModelUri: effectiveModelUri,
13790
13923
  temperature: options?.temperature ?? agent2._config.temperature,
13791
13924
  tools: toolDefs.length > 0 ? toolDefs : void 0,
13792
13925
  maxTokens: options?.maxTokens ?? agent2._config.maxTokens ?? 4096,
@@ -20541,8 +20674,9 @@ var AxlRuntime = class extends EventEmitter2 {
20541
20674
  * new paid operations once known spend reaches the limit. Already-dispatched
20542
20675
  * work still settles and is still counted.
20543
20676
  *
20544
- * `metadata`, `modelTiming` and `traces` remain EVENT-derived and therefore
20545
- * depend on trace configuration; `accounting` never does.
20677
+ * Model metadata and timing share the settlement scope with accounting, so
20678
+ * they cross runtimes and compatible ESM/CJS copies. Workflow names and
20679
+ * captured traces still come from this runtime's events.
20546
20680
  */
20547
20681
  async trackOutcome(fn, options) {
20548
20682
  const parentScope = costScopeStorage.getStore();
@@ -20551,49 +20685,11 @@ var AxlRuntime = class extends EventEmitter2 {
20551
20685
  trackedIds: /* @__PURE__ */ new Set(),
20552
20686
  parent: parentScope
20553
20687
  };
20554
- const modelCalls = /* @__PURE__ */ new Map();
20555
- const modelTiming = /* @__PURE__ */ new Map();
20556
- const captureTimingSamples = options?.captureTimingSamples === true;
20557
20688
  const workflowCalls = /* @__PURE__ */ new Map();
20558
- const tokens = { input: 0, output: 0, reasoning: 0 };
20559
- let agentCalls = 0;
20560
20689
  const capturedTraces = options?.captureTraces ? [] : void 0;
20561
20690
  const listener = (event) => {
20562
20691
  if (!scope.trackedIds.has(event.executionId)) return;
20563
20692
  scope.totalCost += eventCostContribution(event);
20564
- if (event.type === "agent_call_end") {
20565
- if (event.model) modelCalls.set(event.model, (modelCalls.get(event.model) ?? 0) + 1);
20566
- agentCalls++;
20567
- if (event.tokens) {
20568
- tokens.input += event.tokens.input ?? 0;
20569
- tokens.output += event.tokens.output ?? 0;
20570
- tokens.reasoning += event.tokens.reasoning ?? 0;
20571
- }
20572
- const failed2 = event.data?.error != null;
20573
- if (event.model && event.timing && !failed2) {
20574
- const t = event.timing;
20575
- let bucket = modelTiming.get(event.model);
20576
- if (!bucket) {
20577
- bucket = {
20578
- calls: 0,
20579
- queuedMs: 0,
20580
- retryMs: 0,
20581
- wireMs: 0,
20582
- ...captureTimingSamples ? { samples: [] } : {}
20583
- };
20584
- modelTiming.set(event.model, bucket);
20585
- }
20586
- bucket.calls++;
20587
- bucket.samples?.push(t);
20588
- bucket.queuedMs += t.queuedMs;
20589
- bucket.retryMs += t.retryMs;
20590
- bucket.wireMs += t.wireMs;
20591
- if (t.firstTokenMs != null) {
20592
- bucket.firstTokenMs = (bucket.firstTokenMs ?? 0) + t.firstTokenMs;
20593
- bucket.firstTokenCalls = (bucket.firstTokenCalls ?? 0) + 1;
20594
- }
20595
- }
20596
- }
20597
20693
  if (event.type === "workflow_start" && event.workflow) {
20598
20694
  workflowCalls.set(event.workflow, (workflowCalls.get(event.workflow) ?? 0) + 1);
20599
20695
  }
@@ -20619,9 +20715,14 @@ var AxlRuntime = class extends EventEmitter2 {
20619
20715
  this.on("trace", listener);
20620
20716
  let outcome;
20621
20717
  let accounting;
20718
+ let diagnostics;
20622
20719
  try {
20623
- ({ outcome, accounting } = await runInAccountingScope(
20624
- { purpose: options?.purpose, admission: options?.admission },
20720
+ ({ outcome, accounting, diagnostics } = await runInAccountingScope(
20721
+ {
20722
+ purpose: options?.purpose,
20723
+ admission: options?.admission,
20724
+ captureTimingSamples: options?.captureTimingSamples
20725
+ },
20625
20726
  () => (
20626
20727
  // Capture wraps the cost scope rather than the other way round so a
20627
20728
  // record can never be written for an operation the accounting scope
@@ -20645,13 +20746,13 @@ var AxlRuntime = class extends EventEmitter2 {
20645
20746
  return {
20646
20747
  ...outcome,
20647
20748
  accounting,
20648
- ...modelTiming.size > 0 ? { modelTiming: Object.fromEntries(modelTiming) } : {},
20749
+ ...Object.keys(diagnostics.modelTiming).length > 0 ? { modelTiming: diagnostics.modelTiming } : {},
20649
20750
  ...capturedTraces ? { traces: capturedTraces } : {},
20650
20751
  metadata: {
20651
- models: [...modelCalls.keys()],
20652
- modelCallCounts: modelCalls.size > 0 ? Object.fromEntries(modelCalls) : void 0,
20653
- tokens,
20654
- agentCalls,
20752
+ models: Object.keys(diagnostics.modelCallCounts),
20753
+ modelCallCounts: Object.keys(diagnostics.modelCallCounts).length > 0 ? diagnostics.modelCallCounts : void 0,
20754
+ tokens: diagnostics.tokens,
20755
+ agentCalls: diagnostics.agentCalls,
20655
20756
  workflows: [...workflowCalls.keys()],
20656
20757
  workflowCallCounts: workflowCalls.size > 0 ? Object.fromEntries(workflowCalls) : void 0
20657
20758
  }