@axlsdk/axl 0.24.2 → 0.25.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/dist/index.cjs CHANGED
@@ -343,6 +343,12 @@ function isEventStreamOverflowError(error) {
343
343
  function rethrowEventStreamOverflow(error) {
344
344
  if (isEventStreamOverflowError(error)) throw error;
345
345
  }
346
+ function isUnrecoverableError(error) {
347
+ return isEventStreamOverflowError(error) || isAdmissionDeniedError(error);
348
+ }
349
+ function rethrowUnrecoverable(error) {
350
+ if (isUnrecoverableError(error)) throw error;
351
+ }
346
352
  function preserveErrorCause(error, cause) {
347
353
  if (cause === void 0 || cause === error || "cause" in error) return error;
348
354
  Object.defineProperty(error, "cause", {
@@ -419,7 +425,7 @@ var TimeoutError = class extends AxlError {
419
425
  constructor(operation, timeoutMs, breakdown, agent2) {
420
426
  super(
421
427
  "TIMEOUT",
422
- `${operation} exceeded timeout of ${timeoutMs}ms` + (breakdown ? ` (elapsed ${breakdown.elapsedMs}ms: queued ${breakdown.queuedMs}ms, retries ${breakdown.retryMs}ms, wire ${breakdown.wireMs}ms, other ${breakdown.otherMs}ms)` : "") + (agent2 ? ` for agent '${agent2}'` : "")
428
+ `${operation} exceeded timeout of ${timeoutMs}ms` + (breakdown ? ` (elapsed ${breakdown.elapsedMs}ms: queued ${breakdown.queuedMs}ms, retries ${breakdown.retryMs}ms, wire ${breakdown.wireMs}ms, other ${breakdown.otherMs}ms, charged ${breakdown.chargedMs}ms)` : "") + (agent2 ? ` for agent '${agent2}'` : "")
423
429
  );
424
430
  this.name = "TimeoutError";
425
431
  if (breakdown) this.breakdown = breakdown;
@@ -557,7 +563,7 @@ var sharedGuard = typeof installedGuard === "object" && installedGuard !== null
557
563
  var buildPath = typeof __AXL_BUILD_PATH__ === "string" ? __AXL_BUILD_PATH__ : "<source>";
558
564
  var thisCopy = {
559
565
  path: buildPath.startsWith("file:") ? (0, import_node_url.fileURLToPath)(buildPath) : buildPath,
560
- version: true ? "0.24.2" : "unknown"
566
+ version: true ? "0.25.0" : "unknown"
561
567
  };
562
568
  function warnCrossCopy(other, joined) {
563
569
  if (other === thisCopy) return;
@@ -1451,8 +1457,7 @@ function tool(config) {
1451
1457
  } catch (err) {
1452
1458
  if (options?.signal?.aborted) options.signal.throwIfAborted();
1453
1459
  if (isAbortError(err)) throw err;
1454
- if (isAdmissionDeniedError(err)) throw err;
1455
- rethrowEventStreamOverflow(err);
1460
+ rethrowUnrecoverable(err);
1456
1461
  lastError = err instanceof Error ? err : new Error(String(err));
1457
1462
  if (attempt === maxAttempts) break;
1458
1463
  if (retryPolicy.on && !retryPolicy.on(lastError)) {
@@ -1542,6 +1547,41 @@ var OPENAI_DEFAULT_BASE_URL = "https://api.openai.com/v1";
1542
1547
  var ANTHROPIC_DEFAULT_BASE_URL = "https://api.anthropic.com/v1";
1543
1548
  var GEMINI_DEFAULT_BASE_URL = "https://generativelanguage.googleapis.com/v1beta";
1544
1549
 
1550
+ // src/ask-clock.ts
1551
+ var import_node_async_hooks2 = require("async_hooks");
1552
+ var askClockStorage = new import_node_async_hooks2.AsyncLocalStorage();
1553
+ function runWithAskClock(fn) {
1554
+ const tracker = { pausedMs: 0, activePauses: 0 };
1555
+ const enclosing = askClockStorage.getStore() ?? [];
1556
+ return askClockStorage.run([...enclosing, tracker], fn);
1557
+ }
1558
+ function currentAskClock() {
1559
+ return askClockStorage.getStore()?.at(-1);
1560
+ }
1561
+ function pausedAskClockMs(tracker, now = Date.now()) {
1562
+ return tracker.pausedMs + (tracker.activePauses > 0 && tracker.pauseStartedAt !== void 0 ? now - tracker.pauseStartedAt : 0);
1563
+ }
1564
+ async function pauseAskClocks(wait) {
1565
+ const trackers = askClockStorage.getStore();
1566
+ if (!trackers || trackers.length === 0) return wait();
1567
+ const startedAt = Date.now();
1568
+ for (const tracker of trackers) {
1569
+ if (tracker.activePauses++ === 0) tracker.pauseStartedAt = startedAt;
1570
+ }
1571
+ try {
1572
+ return await wait();
1573
+ } finally {
1574
+ const finishedAt = Date.now();
1575
+ for (const tracker of trackers) {
1576
+ tracker.activePauses--;
1577
+ if (tracker.activePauses === 0 && tracker.pauseStartedAt !== void 0) {
1578
+ tracker.pausedMs += finishedAt - tracker.pauseStartedAt;
1579
+ tracker.pauseStartedAt = void 0;
1580
+ }
1581
+ }
1582
+ }
1583
+ }
1584
+
1545
1585
  // src/providers/rate-limiter.ts
1546
1586
  function sanitizeRateLimitConfig(config) {
1547
1587
  const limits = {};
@@ -2604,7 +2644,7 @@ async function fetchWithRetry(input, init, opts) {
2604
2644
  let headersAt = 0;
2605
2645
  const waitSelfImposed = async (wait) => {
2606
2646
  const start = Date.now();
2607
- await wait();
2647
+ await pauseAskClocks(wait);
2608
2648
  const waited = Date.now() - start;
2609
2649
  queuedMs += waited;
2610
2650
  if (dispatches > 0) queuedAfterFirstDispatchMs += waited;
@@ -9229,7 +9269,7 @@ var TranscriptionProviderRegistry = class {
9229
9269
  };
9230
9270
 
9231
9271
  // src/context.ts
9232
- var import_node_async_hooks2 = require("async_hooks");
9272
+ var import_node_async_hooks3 = require("async_hooks");
9233
9273
  var import_node_crypto = require("crypto");
9234
9274
  var import_zod2 = require("zod");
9235
9275
 
@@ -12588,8 +12628,7 @@ async function executeAcceptedTool(options) {
12588
12628
  }
12589
12629
  }
12590
12630
  } catch (error) {
12591
- rethrowEventStreamOverflow(error);
12592
- if (isAdmissionDeniedError(error)) throw error;
12631
+ rethrowUnrecoverable(error);
12593
12632
  const abort = cancellationError(signal, error);
12594
12633
  if (abort !== void 0) return cancellation("handler", abort);
12595
12634
  return failed("handler", error, { attempts });
@@ -12762,9 +12801,8 @@ function recordToolSpanOutcome(span, outcome) {
12762
12801
  }
12763
12802
 
12764
12803
  // src/context.ts
12765
- var signalStorage = new import_node_async_hooks2.AsyncLocalStorage();
12766
- var hardSignalStorage = new import_node_async_hooks2.AsyncLocalStorage();
12767
- var timeoutTrackerStorage = new import_node_async_hooks2.AsyncLocalStorage();
12804
+ var signalStorage = new import_node_async_hooks3.AsyncLocalStorage();
12805
+ var hardSignalStorage = new import_node_async_hooks3.AsyncLocalStorage();
12768
12806
  var MAX_TIMER_DELAY_MS = 2147483647;
12769
12807
  function composeAbortSignals(...signals) {
12770
12808
  const active = signals.filter((signal) => signal !== void 0);
@@ -12796,9 +12834,6 @@ function raceWithAbortSignal(promise, signal) {
12796
12834
  );
12797
12835
  });
12798
12836
  }
12799
- function pausedHumanWaitMs(tracker, now = Date.now()) {
12800
- return tracker.humanWaitMs + (tracker.activeHumanWaits > 0 && tracker.humanWaitStartedAt !== void 0 ? now - tracker.humanWaitStartedAt : 0);
12801
- }
12802
12837
  var DEFAULT_BRANCH_DRAIN_TIMEOUT_MS = 5e3;
12803
12838
  function resolveBranchDrainTimeoutMs(value) {
12804
12839
  const resolved = value === void 0 ? DEFAULT_BRANCH_DRAIN_TIMEOUT_MS : value;
@@ -12869,7 +12904,7 @@ function parseHumanDecision(value) {
12869
12904
  }
12870
12905
  return invalid3();
12871
12906
  }
12872
- var askStorage = new import_node_async_hooks2.AsyncLocalStorage();
12907
+ var askStorage = new import_node_async_hooks3.AsyncLocalStorage();
12873
12908
  var inlineSchemaCache = /* @__PURE__ */ new WeakMap();
12874
12909
  function zodToJsonSchema(schema) {
12875
12910
  const cached = inlineSchemaCache.get(schema);
@@ -13806,10 +13841,7 @@ var WorkflowContext = class _WorkflowContext {
13806
13841
  return hardAskSignal ? hardSignalStorage.run(hardAskSignal, runWithAskSignal) : runWithAskSignal();
13807
13842
  }
13808
13843
  async executeAgentCall(agent2, input, options, handoffMessages, usageCapture, sessionHistory = normalizeSessionHistory(this.sessionHistory)) {
13809
- const tracker = { humanWaitMs: 0, activeHumanWaits: 0 };
13810
- const enclosing = timeoutTrackerStorage.getStore() ?? [];
13811
- return timeoutTrackerStorage.run(
13812
- [...enclosing, tracker],
13844
+ return runWithAskClock(
13813
13845
  () => this.executeAgentCallImpl(
13814
13846
  agent2,
13815
13847
  input,
@@ -14084,7 +14116,7 @@ ${appendedSchemaText}`;
14084
14116
  );
14085
14117
  }
14086
14118
  const startTime = Date.now();
14087
- const timeoutTracker = timeoutTrackerStorage.getStore()?.at(-1);
14119
+ const askClock = currentAskClock();
14088
14120
  const timingTotals = { turns: 0, queuedMs: 0, retryMs: 0, wireMs: 0 };
14089
14121
  const currentMessages = [...messages];
14090
14122
  let turns = 0;
@@ -14101,13 +14133,16 @@ ${appendedSchemaText}`;
14101
14133
  while (turns < maxTurns) {
14102
14134
  this.currentSignal?.throwIfAborted();
14103
14135
  const now = Date.now();
14104
- const elapsedMs = now - startTime - (timeoutTracker ? pausedHumanWaitMs(timeoutTracker, now) : 0);
14105
- if (elapsedMs > timeoutMs) {
14136
+ const elapsedMs = now - startTime;
14137
+ const pausedMs = askClock ? pausedAskClockMs(askClock, now) : 0;
14138
+ const chargedMs = Math.max(0, elapsedMs - Math.min(pausedMs, Math.max(0, elapsedMs)));
14139
+ if (chargedMs > timeoutMs) {
14106
14140
  throw new TimeoutError(
14107
14141
  "ctx.ask()",
14108
14142
  timeoutMs,
14109
14143
  timingTotals.turns > 0 ? {
14110
14144
  elapsedMs,
14145
+ chargedMs,
14111
14146
  queuedMs: timingTotals.queuedMs,
14112
14147
  retryMs: timingTotals.retryMs,
14113
14148
  wireMs: timingTotals.wireMs,
@@ -14855,7 +14890,8 @@ ${appendedSchemaText}`;
14855
14890
  metadata: this.metadata
14856
14891
  });
14857
14892
  } catch (err) {
14858
- rethrowEventStreamOverflow(err);
14893
+ rethrowUnrecoverable(err);
14894
+ if (this.currentSignal?.aborted) throw err;
14859
14895
  validateErr = err;
14860
14896
  const reason = err instanceof Error ? err.message : String(err);
14861
14897
  validateResult = { valid: false, reason: `Validator error: ${reason}` };
@@ -15446,15 +15482,13 @@ ${summaryResponse.content}`
15446
15482
  reject(new QuorumNotMet(quorum, successCount, results));
15447
15483
  }
15448
15484
  }).catch((err) => {
15449
- if (isEventStreamOverflowError(err)) {
15450
- if (!settled) {
15451
- settled = true;
15452
- controller.abort();
15453
- reject(err);
15454
- }
15485
+ if (settled) return;
15486
+ if (isUnrecoverableError(err) || parentSignal2?.aborted) {
15487
+ settled = true;
15488
+ controller.abort();
15489
+ reject(err);
15455
15490
  return;
15456
15491
  }
15457
- if (settled) return;
15458
15492
  const isAbort = err instanceof DOMException && err.name === "AbortError";
15459
15493
  if (isAbort) {
15460
15494
  completedCount++;
@@ -15477,7 +15511,8 @@ ${summaryResponse.content}`
15477
15511
  const parentSignal = this.currentSignal;
15478
15512
  const promises = Array.from({ length: n }, (_, i) => {
15479
15513
  const run = () => fn(i).then((value) => ({ ok: true, value })).catch((err) => {
15480
- rethrowEventStreamOverflow(err);
15514
+ rethrowUnrecoverable(err);
15515
+ if (parentSignal?.aborted) throw err;
15481
15516
  return {
15482
15517
  ok: false,
15483
15518
  error: err instanceof Error ? err.message : String(err)
@@ -15601,6 +15636,7 @@ ${summaryResponse.content}`
15601
15636
  async verify(fn, schema, options) {
15602
15637
  const maxRetries = options?.retries ?? 3;
15603
15638
  let lastRetry = void 0;
15639
+ const scopeSignal = this.currentSignal;
15604
15640
  const emitVerifyOutcome = (passed, attempts, lastError) => {
15605
15641
  this.emitEvent({
15606
15642
  type: "verify",
@@ -15623,25 +15659,24 @@ ${summaryResponse.content}`
15623
15659
  try {
15624
15660
  validateResult = await options.validate(parsed, { metadata: this.metadata });
15625
15661
  } catch (err) {
15626
- rethrowEventStreamOverflow(err);
15662
+ rethrowUnrecoverable(err);
15663
+ if (scopeSignal?.aborted) throw err;
15627
15664
  const reason = err instanceof Error ? err.message : String(err);
15628
15665
  validateResult = { valid: false, reason: `Validator error: ${reason}` };
15629
15666
  }
15630
15667
  if (!validateResult.valid) {
15668
+ scopeSignal?.throwIfAborted();
15631
15669
  const errorMsg = validateResult.reason ?? "Validation failed";
15632
15670
  lastRetry = { error: errorMsg, output: rawOutput, parsed };
15633
- if (attempt === maxRetries) {
15634
- emitVerifyOutcome(false, attempt + 1, errorMsg);
15635
- if (options?.fallback !== void 0) return options.fallback;
15636
- throw new ValidationError(parsed, errorMsg, maxRetries);
15637
- }
15671
+ if (attempt === maxRetries) throw new ValidationError(parsed, errorMsg, maxRetries);
15638
15672
  continue;
15639
15673
  }
15640
15674
  }
15641
15675
  emitVerifyOutcome(true, attempt + 1);
15642
15676
  return parsed;
15643
15677
  } catch (err) {
15644
- rethrowEventStreamOverflow(err);
15678
+ rethrowUnrecoverable(err);
15679
+ if (scopeSignal?.aborted) throw err;
15645
15680
  if (err instanceof ValidationError) {
15646
15681
  lastRetry = {
15647
15682
  error: err.reason,
@@ -15708,7 +15743,8 @@ ${summaryResponse.content}`
15708
15743
  const unpriced = this.budgetContext.unpriced;
15709
15744
  return { value, budgetExceeded: exceeded, totalCost, unpriced };
15710
15745
  } catch (err) {
15711
- rethrowEventStreamOverflow(err);
15746
+ rethrowUnrecoverable(err);
15747
+ if (parentSignal?.aborted) throw err;
15712
15748
  if (this.budgetContext.exceeded) {
15713
15749
  return {
15714
15750
  value: null,
@@ -15717,14 +15753,6 @@ ${summaryResponse.content}`
15717
15753
  unpriced: this.budgetContext.unpriced
15718
15754
  };
15719
15755
  }
15720
- if (err instanceof DOMException && err.name === "AbortError" && controller) {
15721
- return {
15722
- value: null,
15723
- budgetExceeded: true,
15724
- totalCost: this.budgetContext.totalCost,
15725
- unpriced: this.budgetContext.unpriced
15726
- };
15727
- }
15728
15756
  throw err;
15729
15757
  } finally {
15730
15758
  if (parentBudget) {
@@ -15840,7 +15868,8 @@ ${summaryResponse.content}`
15840
15868
  return;
15841
15869
  }
15842
15870
  } catch (err) {
15843
- rethrowEventStreamOverflow(err);
15871
+ rethrowUnrecoverable(err);
15872
+ if (parentSignal?.aborted) throw err;
15844
15873
  remaining--;
15845
15874
  lastError = err instanceof Error ? err : new Error(`Validator error: ${String(err)}`);
15846
15875
  if (remaining === 0 && !settled) {
@@ -15860,7 +15889,7 @@ ${summaryResponse.content}`
15860
15889
  controller.abort();
15861
15890
  resolve2(value);
15862
15891
  }).catch((err) => {
15863
- if (isEventStreamOverflowError(err)) {
15892
+ if (isUnrecoverableError(err)) {
15864
15893
  if (!settled) {
15865
15894
  settled = true;
15866
15895
  controller.abort();
@@ -15869,6 +15898,12 @@ ${summaryResponse.content}`
15869
15898
  throw err;
15870
15899
  }
15871
15900
  if (settled) return;
15901
+ if (parentSignal?.aborted) {
15902
+ settled = true;
15903
+ controller.abort();
15904
+ reject(err);
15905
+ return;
15906
+ }
15872
15907
  if (err instanceof DOMException && err.name === "AbortError") {
15873
15908
  remaining--;
15874
15909
  if (remaining === 0 && !settled) {
@@ -15927,7 +15962,7 @@ ${summaryResponse.content}`
15927
15962
  results[idx] = { ok: true, value };
15928
15963
  successCount++;
15929
15964
  } catch (err) {
15930
- if (isEventStreamOverflowError(err)) {
15965
+ if (isUnrecoverableError(err)) {
15931
15966
  settled = true;
15932
15967
  controller?.abort();
15933
15968
  reject(err);
@@ -15936,6 +15971,12 @@ ${summaryResponse.content}`
15936
15971
  if (settled) {
15937
15972
  return;
15938
15973
  }
15974
+ if (parentSignal?.aborted) {
15975
+ settled = true;
15976
+ controller?.abort();
15977
+ reject(err);
15978
+ return;
15979
+ }
15939
15980
  if (err instanceof DOMException && err.name === "AbortError" && controller?.signal.aborted) {
15940
15981
  completedCount++;
15941
15982
  return;
@@ -15971,12 +16012,7 @@ ${summaryResponse.content}`
15971
16012
  }
15972
16013
  // ── ctx.awaitHuman() ──────────────────────────────────────────────────
15973
16014
  async awaitHuman(options) {
15974
- const trackers = timeoutTrackerStorage.getStore();
15975
- const startedAt = Date.now();
15976
- for (const tracker of trackers ?? []) {
15977
- if (tracker.activeHumanWaits++ === 0) tracker.humanWaitStartedAt = startedAt;
15978
- }
15979
- try {
16015
+ return pauseAskClocks(async () => {
15980
16016
  if (this.spanManager) {
15981
16017
  return await this.spanManager.withSpanAsync(
15982
16018
  "axl.ctx.awaitHuman",
@@ -15993,16 +16029,7 @@ ${summaryResponse.content}`
15993
16029
  );
15994
16030
  }
15995
16031
  return await this._awaitHumanImpl(options);
15996
- } finally {
15997
- const finishedAt = Date.now();
15998
- for (const tracker of trackers ?? []) {
15999
- tracker.activeHumanWaits--;
16000
- if (tracker.activeHumanWaits === 0 && tracker.humanWaitStartedAt !== void 0) {
16001
- tracker.humanWaitMs += finishedAt - tracker.humanWaitStartedAt;
16002
- tracker.humanWaitStartedAt = void 0;
16003
- }
16004
- }
16005
- }
16032
+ });
16006
16033
  }
16007
16034
  async _awaitHumanImpl(options) {
16008
16035
  const branchSignal = this.currentSignal;
@@ -16999,7 +17026,7 @@ function workflow(config) {
16999
17026
  // src/runtime.ts
17000
17027
  var import_node_events2 = require("events");
17001
17028
  var import_node_crypto4 = require("crypto");
17002
- var import_node_async_hooks3 = require("async_hooks");
17029
+ var import_node_async_hooks4 = require("async_hooks");
17003
17030
  var import_node_fs3 = require("fs");
17004
17031
  var import_node_path3 = require("path");
17005
17032
 
@@ -19179,7 +19206,7 @@ function assertNoRemovedObservationCallbacks(options) {
19179
19206
  `runtime.createContext() no longer accepts ${removed.join(", ")}. Observe ctx.events or use runtime.stream() instead. See docs/migration/stream-first-observation.md.`
19180
19207
  );
19181
19208
  }
19182
- var costScopeStorage = new import_node_async_hooks3.AsyncLocalStorage();
19209
+ var costScopeStorage = new import_node_async_hooks4.AsyncLocalStorage();
19183
19210
  function forwardAbortSignal(external, internal) {
19184
19211
  if (!external) return () => {
19185
19212
  };