@axlsdk/axl 0.24.1 → 0.24.3
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 +228 -117
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +17 -15
- package/dist/index.d.ts +17 -15
- package/dist/index.js +228 -117
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
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", {
|
|
@@ -352,12 +358,14 @@ function preserveErrorCause(error, cause) {
|
|
|
352
358
|
});
|
|
353
359
|
return error;
|
|
354
360
|
}
|
|
361
|
+
var TOOL_FAILURE_MARKER = /* @__PURE__ */ Symbol.for("axl.toolFailure.v1");
|
|
355
362
|
var ToolFailure = class extends AxlError {
|
|
356
363
|
modelMessage;
|
|
357
364
|
constructor(options) {
|
|
358
365
|
super(options.code ?? "TOOL_FAILURE", options.message);
|
|
359
366
|
this.name = "ToolFailure";
|
|
360
367
|
this.modelMessage = options.modelMessage;
|
|
368
|
+
Object.defineProperty(this, TOOL_FAILURE_MARKER, { value: true });
|
|
361
369
|
if (options.cause !== void 0) {
|
|
362
370
|
Object.defineProperty(this, "cause", {
|
|
363
371
|
configurable: true,
|
|
@@ -367,6 +375,13 @@ var ToolFailure = class extends AxlError {
|
|
|
367
375
|
}
|
|
368
376
|
}
|
|
369
377
|
};
|
|
378
|
+
function isToolFailureError(error) {
|
|
379
|
+
try {
|
|
380
|
+
return error instanceof ToolFailure || typeof error === "object" && error !== null && error[TOOL_FAILURE_MARKER] === true && typeof error.modelMessage === "string";
|
|
381
|
+
} catch {
|
|
382
|
+
return false;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
370
385
|
var ToolModelOutputError = class extends AxlError {
|
|
371
386
|
toolName;
|
|
372
387
|
cause;
|
|
@@ -548,7 +563,7 @@ var sharedGuard = typeof installedGuard === "object" && installedGuard !== null
|
|
|
548
563
|
var buildPath = typeof __AXL_BUILD_PATH__ === "string" ? __AXL_BUILD_PATH__ : "<source>";
|
|
549
564
|
var thisCopy = {
|
|
550
565
|
path: buildPath.startsWith("file:") ? (0, import_node_url.fileURLToPath)(buildPath) : buildPath,
|
|
551
|
-
version: true ? "0.24.
|
|
566
|
+
version: true ? "0.24.3" : "unknown"
|
|
552
567
|
};
|
|
553
568
|
function warnCrossCopy(other, joined) {
|
|
554
569
|
if (other === thisCopy) return;
|
|
@@ -649,10 +664,16 @@ var AccountingScope = class {
|
|
|
649
664
|
reasons = /* @__PURE__ */ new Map();
|
|
650
665
|
breakdown = { generation: 0, judging: 0, external: 0 };
|
|
651
666
|
provenance = /* @__PURE__ */ new Map();
|
|
667
|
+
modelCalls = /* @__PURE__ */ new Map();
|
|
668
|
+
modelTiming = /* @__PURE__ */ new Map();
|
|
669
|
+
diagnosticTokens = { input: 0, output: 0, reasoning: 0 };
|
|
670
|
+
agentCalls = 0;
|
|
671
|
+
captureTimingSamples;
|
|
652
672
|
constructor(options) {
|
|
653
673
|
this.parent = options.parent;
|
|
654
674
|
this.purpose = options.purpose;
|
|
655
675
|
this.admission = options.admission;
|
|
676
|
+
this.captureTimingSamples = options.captureTimingSamples === true;
|
|
656
677
|
}
|
|
657
678
|
get isFinalized() {
|
|
658
679
|
return this.finalized;
|
|
@@ -681,7 +702,7 @@ var AccountingScope = class {
|
|
|
681
702
|
else this.byKind.delete(op.kind);
|
|
682
703
|
this.denied += 1;
|
|
683
704
|
}
|
|
684
|
-
recordSettled(op, cost, provenance, usage) {
|
|
705
|
+
recordSettled(op, cost, provenance, usage, timing) {
|
|
685
706
|
this.seen.add(op.id);
|
|
686
707
|
this.openOps.delete(op.id);
|
|
687
708
|
this.settled += 1;
|
|
@@ -690,13 +711,57 @@ var AccountingScope = class {
|
|
|
690
711
|
else this.breakdown[op.purpose] += cost;
|
|
691
712
|
this.provenance.set(provenance, (this.provenance.get(provenance) ?? 0) + cost);
|
|
692
713
|
if (usage) this.addUsage(usage);
|
|
714
|
+
this.recordAgentCall(op, usage, timing);
|
|
693
715
|
}
|
|
694
|
-
recordUnknown(op, reason, usage) {
|
|
716
|
+
recordUnknown(op, reason, usage, timing) {
|
|
695
717
|
this.seen.add(op.id);
|
|
696
718
|
this.openOps.delete(op.id);
|
|
697
719
|
this.unknown += 1;
|
|
698
720
|
this.reasons.set(reason, (this.reasons.get(reason) ?? 0) + 1);
|
|
699
721
|
if (usage) this.addUsage(usage);
|
|
722
|
+
this.recordAgentCall(op, usage, timing);
|
|
723
|
+
}
|
|
724
|
+
recordAgentCall(op, usage, timing) {
|
|
725
|
+
if (!op.agentCall) return;
|
|
726
|
+
this.agentCalls++;
|
|
727
|
+
const model = op.diagnosticModelUri ?? op.model;
|
|
728
|
+
if (!model) return;
|
|
729
|
+
this.modelCalls.set(model, (this.modelCalls.get(model) ?? 0) + 1);
|
|
730
|
+
if (usage) {
|
|
731
|
+
const finite = (value) => typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
732
|
+
this.diagnosticTokens.input += finite(usage.inputTokens);
|
|
733
|
+
this.diagnosticTokens.output += finite(usage.outputTokens);
|
|
734
|
+
this.diagnosticTokens.reasoning += finite(usage.reasoningTokens);
|
|
735
|
+
}
|
|
736
|
+
if (!timing) return;
|
|
737
|
+
let bucket = this.modelTiming.get(model);
|
|
738
|
+
if (!bucket) {
|
|
739
|
+
bucket = {
|
|
740
|
+
calls: 0,
|
|
741
|
+
queuedMs: 0,
|
|
742
|
+
retryMs: 0,
|
|
743
|
+
wireMs: 0,
|
|
744
|
+
...this.captureTimingSamples ? { samples: [] } : {}
|
|
745
|
+
};
|
|
746
|
+
this.modelTiming.set(model, bucket);
|
|
747
|
+
}
|
|
748
|
+
bucket.calls++;
|
|
749
|
+
bucket.queuedMs += timing.queuedMs;
|
|
750
|
+
bucket.retryMs += timing.retryMs;
|
|
751
|
+
bucket.wireMs += timing.wireMs;
|
|
752
|
+
bucket.samples?.push(timing);
|
|
753
|
+
if (timing.firstTokenMs != null) {
|
|
754
|
+
bucket.firstTokenMs = (bucket.firstTokenMs ?? 0) + timing.firstTokenMs;
|
|
755
|
+
bucket.firstTokenCalls = (bucket.firstTokenCalls ?? 0) + 1;
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
toDiagnostics() {
|
|
759
|
+
return {
|
|
760
|
+
modelCallCounts: Object.fromEntries(this.modelCalls),
|
|
761
|
+
tokens: { ...this.diagnosticTokens },
|
|
762
|
+
agentCalls: this.agentCalls,
|
|
763
|
+
modelTiming: Object.fromEntries(this.modelTiming)
|
|
764
|
+
};
|
|
700
765
|
}
|
|
701
766
|
hasSeen(id) {
|
|
702
767
|
return this.seen.has(id);
|
|
@@ -768,14 +833,14 @@ function settleOperationUp(start, op, outcome) {
|
|
|
768
833
|
if (scope.isFinalized) return;
|
|
769
834
|
switch (outcome.outcome) {
|
|
770
835
|
case "settled":
|
|
771
|
-
scope.recordSettled(op, outcome.cost, outcome.provenance, outcome.usage);
|
|
836
|
+
scope.recordSettled(op, outcome.cost, outcome.provenance, outcome.usage, outcome.timing);
|
|
772
837
|
if (scope.admission && !chargedControllers.has(scope.admission)) {
|
|
773
838
|
chargedControllers.add(scope.admission);
|
|
774
839
|
recordSpend(scope.admission, outcome.cost);
|
|
775
840
|
}
|
|
776
841
|
break;
|
|
777
842
|
case "unknown":
|
|
778
|
-
scope.recordUnknown(op, outcome.reason, outcome.usage);
|
|
843
|
+
scope.recordUnknown(op, outcome.reason, outcome.usage, outcome.timing);
|
|
779
844
|
break;
|
|
780
845
|
case "retracted":
|
|
781
846
|
scope.recordRetracted(op);
|
|
@@ -827,6 +892,8 @@ function openOperation(descriptor) {
|
|
|
827
892
|
kind: descriptor.kind,
|
|
828
893
|
purpose: scope.purpose,
|
|
829
894
|
model: descriptor.model,
|
|
895
|
+
diagnosticModelUri: descriptor.diagnosticModelUri,
|
|
896
|
+
agentCall: descriptor.agentCall === true,
|
|
830
897
|
dispatched: false,
|
|
831
898
|
dispatchObservable: false
|
|
832
899
|
};
|
|
@@ -867,25 +934,31 @@ function openOperation(descriptor) {
|
|
|
867
934
|
outcome: "settled",
|
|
868
935
|
cost: input.cost,
|
|
869
936
|
provenance: input.provenance ?? "adapter_reported",
|
|
870
|
-
usage: input.usage
|
|
937
|
+
usage: input.usage,
|
|
938
|
+
timing: input.timing
|
|
871
939
|
});
|
|
872
940
|
return;
|
|
873
941
|
}
|
|
874
942
|
if (input.cost !== void 0 || input.usage !== void 0) {
|
|
875
|
-
finish({
|
|
943
|
+
finish({
|
|
944
|
+
outcome: "unknown",
|
|
945
|
+
reason: "unpriced_model",
|
|
946
|
+
usage: input.usage,
|
|
947
|
+
timing: input.timing
|
|
948
|
+
});
|
|
876
949
|
return;
|
|
877
950
|
}
|
|
878
|
-
handle.settleFailure();
|
|
951
|
+
handle.settleFailure(void 0, input.timing);
|
|
879
952
|
},
|
|
880
953
|
settleUnknown(reason, usage) {
|
|
881
954
|
finish({ outcome: "unknown", reason, usage });
|
|
882
955
|
},
|
|
883
|
-
settleFailure(usage) {
|
|
956
|
+
settleFailure(usage, timing) {
|
|
884
957
|
if (op.dispatchObservable && !op.dispatched) {
|
|
885
|
-
finish({ outcome: "settled", cost: 0, provenance: "adapter_reported", usage });
|
|
958
|
+
finish({ outcome: "settled", cost: 0, provenance: "adapter_reported", usage, timing });
|
|
886
959
|
return;
|
|
887
960
|
}
|
|
888
|
-
finish({ outcome: "unknown", reason: "usage_missing", usage });
|
|
961
|
+
finish({ outcome: "unknown", reason: "usage_missing", usage, timing });
|
|
889
962
|
},
|
|
890
963
|
run(fn) {
|
|
891
964
|
return runWithDispatchAdmission(handle.dispatchAdmission, fn);
|
|
@@ -898,7 +971,8 @@ async function runInAccountingScope(options, fn) {
|
|
|
898
971
|
const scope = new AccountingScope({
|
|
899
972
|
parent,
|
|
900
973
|
purpose: options.purpose ?? parent?.purpose ?? "generation",
|
|
901
|
-
admission: options.admission
|
|
974
|
+
admission: options.admission,
|
|
975
|
+
captureTimingSamples: options.captureTimingSamples
|
|
902
976
|
});
|
|
903
977
|
const inheritedGuard = sharedGuard.storage.getStore();
|
|
904
978
|
const enclosingGuard = inheritedGuard && (inheritedGuard.isActive?.() ?? true) ? inheritedGuard : void 0;
|
|
@@ -916,7 +990,8 @@ async function runInAccountingScope(options, fn) {
|
|
|
916
990
|
"The active @axlsdk/axl accounting scope uses an incompatible loaded copy; paid work was refused before dispatch."
|
|
917
991
|
)
|
|
918
992
|
},
|
|
919
|
-
accounting: scope.toAccounting()
|
|
993
|
+
accounting: scope.toAccounting(),
|
|
994
|
+
diagnostics: scope.toDiagnostics()
|
|
920
995
|
};
|
|
921
996
|
}
|
|
922
997
|
const markUninstrumented = () => {
|
|
@@ -940,10 +1015,18 @@ async function runInAccountingScope(options, fn) {
|
|
|
940
1015
|
() => accountingStorage.run(scope, fn)
|
|
941
1016
|
);
|
|
942
1017
|
scope.finalize();
|
|
943
|
-
return {
|
|
1018
|
+
return {
|
|
1019
|
+
outcome: { status: "fulfilled", value },
|
|
1020
|
+
accounting: scope.toAccounting(),
|
|
1021
|
+
diagnostics: scope.toDiagnostics()
|
|
1022
|
+
};
|
|
944
1023
|
} catch (error) {
|
|
945
1024
|
scope.finalize();
|
|
946
|
-
return {
|
|
1025
|
+
return {
|
|
1026
|
+
outcome: { status: "rejected", error },
|
|
1027
|
+
accounting: scope.toAccounting(),
|
|
1028
|
+
diagnostics: scope.toDiagnostics()
|
|
1029
|
+
};
|
|
947
1030
|
}
|
|
948
1031
|
}
|
|
949
1032
|
function validateReportedCost(amountUsd) {
|
|
@@ -1322,10 +1405,12 @@ function toolArgumentIssues(error) {
|
|
|
1322
1405
|
}
|
|
1323
1406
|
return [{ path: [], code: "invalid_arguments", message: "Tool arguments are invalid." }];
|
|
1324
1407
|
}
|
|
1325
|
-
var TOOL_INTERNALS = /* @__PURE__ */
|
|
1408
|
+
var TOOL_INTERNALS = /* @__PURE__ */ Symbol.for("axl.tool.internals.v1");
|
|
1326
1409
|
function getToolInternals(tool2) {
|
|
1327
|
-
const internals = TOOL_INTERNALS
|
|
1328
|
-
if (!internals
|
|
1410
|
+
const internals = tool2[TOOL_INTERNALS];
|
|
1411
|
+
if (!internals || typeof internals.prepareInput !== "function" || typeof internals.executePrepared !== "function") {
|
|
1412
|
+
throw new Error(`Tool "${tool2.name}" was not created by a compatible tool()`);
|
|
1413
|
+
}
|
|
1329
1414
|
return internals;
|
|
1330
1415
|
}
|
|
1331
1416
|
function prepareToolInput(tool2, input) {
|
|
@@ -1372,8 +1457,7 @@ function tool(config) {
|
|
|
1372
1457
|
} catch (err) {
|
|
1373
1458
|
if (options?.signal?.aborted) options.signal.throwIfAborted();
|
|
1374
1459
|
if (isAbortError(err)) throw err;
|
|
1375
|
-
|
|
1376
|
-
rethrowEventStreamOverflow(err);
|
|
1460
|
+
rethrowUnrecoverable(err);
|
|
1377
1461
|
lastError = err instanceof Error ? err : new Error(String(err));
|
|
1378
1462
|
if (attempt === maxAttempts) break;
|
|
1379
1463
|
if (retryPolicy.on && !retryPolicy.on(lastError)) {
|
|
@@ -1426,9 +1510,11 @@ function tool(config) {
|
|
|
1426
1510
|
},
|
|
1427
1511
|
_execute: execute
|
|
1428
1512
|
};
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1513
|
+
Object.defineProperty(instance, TOOL_INTERNALS, {
|
|
1514
|
+
value: {
|
|
1515
|
+
prepareInput,
|
|
1516
|
+
executePrepared
|
|
1517
|
+
}
|
|
1432
1518
|
});
|
|
1433
1519
|
return instance;
|
|
1434
1520
|
}
|
|
@@ -1459,6 +1545,7 @@ async function resolveApiKey(source) {
|
|
|
1459
1545
|
// src/providers/default-endpoints.ts
|
|
1460
1546
|
var OPENAI_DEFAULT_BASE_URL = "https://api.openai.com/v1";
|
|
1461
1547
|
var ANTHROPIC_DEFAULT_BASE_URL = "https://api.anthropic.com/v1";
|
|
1548
|
+
var GEMINI_DEFAULT_BASE_URL = "https://generativelanguage.googleapis.com/v1beta";
|
|
1462
1549
|
|
|
1463
1550
|
// src/providers/rate-limiter.ts
|
|
1464
1551
|
function sanitizeRateLimitConfig(config) {
|
|
@@ -1856,12 +1943,36 @@ var anthropicQuotaDialect = makeDialect(
|
|
|
1856
1943
|
return "unknown";
|
|
1857
1944
|
}
|
|
1858
1945
|
);
|
|
1946
|
+
var geminiQuotaDialect = makeDialect([], (error) => {
|
|
1947
|
+
if (error.code === "quota_exceeded") return "spend_cap";
|
|
1948
|
+
if (Array.isArray(error.details)) {
|
|
1949
|
+
for (const detail of error.details) {
|
|
1950
|
+
if (typeof detail !== "object" || detail === null) continue;
|
|
1951
|
+
const violations = detail.violations;
|
|
1952
|
+
if (!Array.isArray(violations)) continue;
|
|
1953
|
+
if (violations.some((violation) => {
|
|
1954
|
+
if (typeof violation !== "object" || violation === null) return false;
|
|
1955
|
+
const id = violation.quotaId;
|
|
1956
|
+
return typeof id === "string" && /perday|daily|spend|billing/i.test(id);
|
|
1957
|
+
}))
|
|
1958
|
+
return "spend_cap";
|
|
1959
|
+
}
|
|
1960
|
+
}
|
|
1961
|
+
const message = error.message;
|
|
1962
|
+
if (typeof message === "string" && /monthly spending cap|spend(?:-based|ing)? (?:cap|limit)|prepay(?:ment)? credits? (?:are )?depleted/i.test(
|
|
1963
|
+
message
|
|
1964
|
+
)) {
|
|
1965
|
+
return "spend_cap";
|
|
1966
|
+
}
|
|
1967
|
+
return "unknown";
|
|
1968
|
+
});
|
|
1859
1969
|
var DIALECTS = /* @__PURE__ */ new Map([
|
|
1860
1970
|
["openai", { origin: new URL(OPENAI_DEFAULT_BASE_URL).origin, dialect: openaiQuotaDialect }],
|
|
1861
1971
|
[
|
|
1862
1972
|
"anthropic",
|
|
1863
1973
|
{ origin: new URL(ANTHROPIC_DEFAULT_BASE_URL).origin, dialect: anthropicQuotaDialect }
|
|
1864
|
-
]
|
|
1974
|
+
],
|
|
1975
|
+
["google", { origin: new URL(GEMINI_DEFAULT_BASE_URL).origin, dialect: geminiQuotaDialect }]
|
|
1865
1976
|
]);
|
|
1866
1977
|
function quotaDialectFor(family, origin) {
|
|
1867
1978
|
const entry = DIALECTS.get(family);
|
|
@@ -6052,7 +6163,7 @@ var GEMINI_PRICING = {
|
|
|
6052
6163
|
},
|
|
6053
6164
|
"gemini-3.8-flash": { input: 75e-8, cached: 75e-9, output: 375e-8 }
|
|
6054
6165
|
};
|
|
6055
|
-
var CANONICAL_GEMINI_BASE_URL =
|
|
6166
|
+
var CANONICAL_GEMINI_BASE_URL = GEMINI_DEFAULT_BASE_URL;
|
|
6056
6167
|
function isValidTokenCount2(value) {
|
|
6057
6168
|
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
6058
6169
|
}
|
|
@@ -6409,10 +6520,7 @@ var GeminiProvider = class {
|
|
|
6409
6520
|
axlRateGovernors;
|
|
6410
6521
|
constructor(options = {}) {
|
|
6411
6522
|
this.apiKeySource = options.apiKey ?? process.env.GOOGLE_API_KEY ?? process.env.GEMINI_API_KEY ?? "";
|
|
6412
|
-
this.baseUrl = (options.baseUrl ??
|
|
6413
|
-
/\/$/,
|
|
6414
|
-
""
|
|
6415
|
-
);
|
|
6523
|
+
this.baseUrl = (options.baseUrl ?? GEMINI_DEFAULT_BASE_URL).replace(/\/$/, "");
|
|
6416
6524
|
assertSafeProviderBaseUrl(
|
|
6417
6525
|
this.baseUrl,
|
|
6418
6526
|
"Google provider",
|
|
@@ -11611,6 +11719,34 @@ function toAccountingUsage(usage) {
|
|
|
11611
11719
|
cacheWriteTokens: usage.cache_write_tokens ?? 0
|
|
11612
11720
|
};
|
|
11613
11721
|
}
|
|
11722
|
+
function safeTiming(response) {
|
|
11723
|
+
try {
|
|
11724
|
+
const timing = response.timing;
|
|
11725
|
+
if (!timing) return void 0;
|
|
11726
|
+
const queuedMs = timing.queuedMs;
|
|
11727
|
+
const retryMs = timing.retryMs;
|
|
11728
|
+
const wireMs = timing.wireMs;
|
|
11729
|
+
if (![queuedMs, retryMs, wireMs].every((value) => Number.isFinite(value) && value >= 0)) {
|
|
11730
|
+
return void 0;
|
|
11731
|
+
}
|
|
11732
|
+
const attempts = timing.attempts;
|
|
11733
|
+
const ttfbMs = timing.ttfbMs;
|
|
11734
|
+
const rateLimitRetries = timing.rateLimitRetries;
|
|
11735
|
+
const firstTokenMs = timing.firstTokenMs;
|
|
11736
|
+
const valid = (value) => typeof value === "number" && Number.isFinite(value) && value >= 0;
|
|
11737
|
+
return {
|
|
11738
|
+
queuedMs,
|
|
11739
|
+
retryMs,
|
|
11740
|
+
wireMs,
|
|
11741
|
+
...valid(attempts) ? { attempts } : {},
|
|
11742
|
+
...valid(ttfbMs) ? { ttfbMs } : {},
|
|
11743
|
+
...valid(rateLimitRetries) ? { rateLimitRetries } : {},
|
|
11744
|
+
...valid(firstTokenMs) ? { firstTokenMs } : {}
|
|
11745
|
+
};
|
|
11746
|
+
} catch {
|
|
11747
|
+
return void 0;
|
|
11748
|
+
}
|
|
11749
|
+
}
|
|
11614
11750
|
function composeLifecycle(caller, onDispatch) {
|
|
11615
11751
|
return {
|
|
11616
11752
|
onDispatch() {
|
|
@@ -11804,7 +11940,13 @@ var CaptureRecorder = class {
|
|
|
11804
11940
|
}
|
|
11805
11941
|
};
|
|
11806
11942
|
function openProviderOperation(raw, kind, options) {
|
|
11807
|
-
const handle = openOperation({
|
|
11943
|
+
const handle = openOperation({
|
|
11944
|
+
kind,
|
|
11945
|
+
model: options.model,
|
|
11946
|
+
diagnosticModelUri: options.accountingModelUri,
|
|
11947
|
+
provider: raw.name,
|
|
11948
|
+
agentCall: options.accountingModelUri !== void 0
|
|
11949
|
+
});
|
|
11808
11950
|
if (handle && raw.reportsRequestLifecycle === true) handle.markDispatchObservable();
|
|
11809
11951
|
return handle;
|
|
11810
11952
|
}
|
|
@@ -11821,7 +11963,8 @@ function createScopedProvider(raw) {
|
|
|
11821
11963
|
handle.settle({
|
|
11822
11964
|
cost: response.cost,
|
|
11823
11965
|
provenance: response.costProvenance,
|
|
11824
|
-
usage: toAccountingUsage(response.usage)
|
|
11966
|
+
usage: toAccountingUsage(response.usage),
|
|
11967
|
+
timing: safeTiming(response)
|
|
11825
11968
|
});
|
|
11826
11969
|
recorder?.end({ response });
|
|
11827
11970
|
return response;
|
|
@@ -11876,7 +12019,8 @@ function createScopedProvider(raw) {
|
|
|
11876
12019
|
handle?.settle({
|
|
11877
12020
|
cost: result.value.cost,
|
|
11878
12021
|
provenance: result.value.costProvenance,
|
|
11879
|
-
usage: toAccountingUsage(result.value.usage)
|
|
12022
|
+
usage: toAccountingUsage(result.value.usage),
|
|
12023
|
+
timing: safeTiming(result.value)
|
|
11880
12024
|
});
|
|
11881
12025
|
settled = true;
|
|
11882
12026
|
recorder?.end({
|
|
@@ -12309,13 +12453,6 @@ function eventError(error) {
|
|
|
12309
12453
|
return { name: "Error", message: "Unknown thrown value" };
|
|
12310
12454
|
}
|
|
12311
12455
|
}
|
|
12312
|
-
function isToolFailure(error) {
|
|
12313
|
-
try {
|
|
12314
|
-
return error instanceof ToolFailure;
|
|
12315
|
-
} catch {
|
|
12316
|
-
return false;
|
|
12317
|
-
}
|
|
12318
|
-
}
|
|
12319
12456
|
function cancellation(phase, error, result) {
|
|
12320
12457
|
let reason;
|
|
12321
12458
|
try {
|
|
@@ -12331,7 +12468,7 @@ function cancellation(phase, error, result) {
|
|
|
12331
12468
|
}
|
|
12332
12469
|
function failed(phase, error, options = {}) {
|
|
12333
12470
|
let modelMessage;
|
|
12334
|
-
if (
|
|
12471
|
+
if (isToolFailureError(error)) {
|
|
12335
12472
|
try {
|
|
12336
12473
|
modelMessage = typeof error.modelMessage === "string" ? error.modelMessage : void 0;
|
|
12337
12474
|
} catch {
|
|
@@ -12456,8 +12593,7 @@ async function executeAcceptedTool(options) {
|
|
|
12456
12593
|
}
|
|
12457
12594
|
}
|
|
12458
12595
|
} catch (error) {
|
|
12459
|
-
|
|
12460
|
-
if (isAdmissionDeniedError(error)) throw error;
|
|
12596
|
+
rethrowUnrecoverable(error);
|
|
12461
12597
|
const abort = cancellationError(signal, error);
|
|
12462
12598
|
if (abort !== void 0) return cancellation("handler", abort);
|
|
12463
12599
|
return failed("handler", error, { attempts });
|
|
@@ -14019,6 +14155,7 @@ ${appendedSchemaText}`;
|
|
|
14019
14155
|
const turnStart = Date.now();
|
|
14020
14156
|
const chatOptions = {
|
|
14021
14157
|
model,
|
|
14158
|
+
accountingModelUri: effectiveModelUri,
|
|
14022
14159
|
temperature: options?.temperature ?? agent2._config.temperature,
|
|
14023
14160
|
tools: toolDefs.length > 0 ? toolDefs : void 0,
|
|
14024
14161
|
maxTokens: options?.maxTokens ?? agent2._config.maxTokens ?? 4096,
|
|
@@ -14722,7 +14859,8 @@ ${appendedSchemaText}`;
|
|
|
14722
14859
|
metadata: this.metadata
|
|
14723
14860
|
});
|
|
14724
14861
|
} catch (err) {
|
|
14725
|
-
|
|
14862
|
+
rethrowUnrecoverable(err);
|
|
14863
|
+
if (this.currentSignal?.aborted) throw err;
|
|
14726
14864
|
validateErr = err;
|
|
14727
14865
|
const reason = err instanceof Error ? err.message : String(err);
|
|
14728
14866
|
validateResult = { valid: false, reason: `Validator error: ${reason}` };
|
|
@@ -15313,15 +15451,13 @@ ${summaryResponse.content}`
|
|
|
15313
15451
|
reject(new QuorumNotMet(quorum, successCount, results));
|
|
15314
15452
|
}
|
|
15315
15453
|
}).catch((err) => {
|
|
15316
|
-
if (
|
|
15317
|
-
|
|
15318
|
-
|
|
15319
|
-
|
|
15320
|
-
|
|
15321
|
-
}
|
|
15454
|
+
if (settled) return;
|
|
15455
|
+
if (isUnrecoverableError(err) || parentSignal2?.aborted) {
|
|
15456
|
+
settled = true;
|
|
15457
|
+
controller.abort();
|
|
15458
|
+
reject(err);
|
|
15322
15459
|
return;
|
|
15323
15460
|
}
|
|
15324
|
-
if (settled) return;
|
|
15325
15461
|
const isAbort = err instanceof DOMException && err.name === "AbortError";
|
|
15326
15462
|
if (isAbort) {
|
|
15327
15463
|
completedCount++;
|
|
@@ -15344,7 +15480,8 @@ ${summaryResponse.content}`
|
|
|
15344
15480
|
const parentSignal = this.currentSignal;
|
|
15345
15481
|
const promises = Array.from({ length: n }, (_, i) => {
|
|
15346
15482
|
const run = () => fn(i).then((value) => ({ ok: true, value })).catch((err) => {
|
|
15347
|
-
|
|
15483
|
+
rethrowUnrecoverable(err);
|
|
15484
|
+
if (parentSignal?.aborted) throw err;
|
|
15348
15485
|
return {
|
|
15349
15486
|
ok: false,
|
|
15350
15487
|
error: err instanceof Error ? err.message : String(err)
|
|
@@ -15468,6 +15605,7 @@ ${summaryResponse.content}`
|
|
|
15468
15605
|
async verify(fn, schema, options) {
|
|
15469
15606
|
const maxRetries = options?.retries ?? 3;
|
|
15470
15607
|
let lastRetry = void 0;
|
|
15608
|
+
const scopeSignal = this.currentSignal;
|
|
15471
15609
|
const emitVerifyOutcome = (passed, attempts, lastError) => {
|
|
15472
15610
|
this.emitEvent({
|
|
15473
15611
|
type: "verify",
|
|
@@ -15490,25 +15628,24 @@ ${summaryResponse.content}`
|
|
|
15490
15628
|
try {
|
|
15491
15629
|
validateResult = await options.validate(parsed, { metadata: this.metadata });
|
|
15492
15630
|
} catch (err) {
|
|
15493
|
-
|
|
15631
|
+
rethrowUnrecoverable(err);
|
|
15632
|
+
if (scopeSignal?.aborted) throw err;
|
|
15494
15633
|
const reason = err instanceof Error ? err.message : String(err);
|
|
15495
15634
|
validateResult = { valid: false, reason: `Validator error: ${reason}` };
|
|
15496
15635
|
}
|
|
15497
15636
|
if (!validateResult.valid) {
|
|
15637
|
+
scopeSignal?.throwIfAborted();
|
|
15498
15638
|
const errorMsg = validateResult.reason ?? "Validation failed";
|
|
15499
15639
|
lastRetry = { error: errorMsg, output: rawOutput, parsed };
|
|
15500
|
-
if (attempt === maxRetries)
|
|
15501
|
-
emitVerifyOutcome(false, attempt + 1, errorMsg);
|
|
15502
|
-
if (options?.fallback !== void 0) return options.fallback;
|
|
15503
|
-
throw new ValidationError(parsed, errorMsg, maxRetries);
|
|
15504
|
-
}
|
|
15640
|
+
if (attempt === maxRetries) throw new ValidationError(parsed, errorMsg, maxRetries);
|
|
15505
15641
|
continue;
|
|
15506
15642
|
}
|
|
15507
15643
|
}
|
|
15508
15644
|
emitVerifyOutcome(true, attempt + 1);
|
|
15509
15645
|
return parsed;
|
|
15510
15646
|
} catch (err) {
|
|
15511
|
-
|
|
15647
|
+
rethrowUnrecoverable(err);
|
|
15648
|
+
if (scopeSignal?.aborted) throw err;
|
|
15512
15649
|
if (err instanceof ValidationError) {
|
|
15513
15650
|
lastRetry = {
|
|
15514
15651
|
error: err.reason,
|
|
@@ -15575,7 +15712,8 @@ ${summaryResponse.content}`
|
|
|
15575
15712
|
const unpriced = this.budgetContext.unpriced;
|
|
15576
15713
|
return { value, budgetExceeded: exceeded, totalCost, unpriced };
|
|
15577
15714
|
} catch (err) {
|
|
15578
|
-
|
|
15715
|
+
rethrowUnrecoverable(err);
|
|
15716
|
+
if (parentSignal?.aborted) throw err;
|
|
15579
15717
|
if (this.budgetContext.exceeded) {
|
|
15580
15718
|
return {
|
|
15581
15719
|
value: null,
|
|
@@ -15584,14 +15722,6 @@ ${summaryResponse.content}`
|
|
|
15584
15722
|
unpriced: this.budgetContext.unpriced
|
|
15585
15723
|
};
|
|
15586
15724
|
}
|
|
15587
|
-
if (err instanceof DOMException && err.name === "AbortError" && controller) {
|
|
15588
|
-
return {
|
|
15589
|
-
value: null,
|
|
15590
|
-
budgetExceeded: true,
|
|
15591
|
-
totalCost: this.budgetContext.totalCost,
|
|
15592
|
-
unpriced: this.budgetContext.unpriced
|
|
15593
|
-
};
|
|
15594
|
-
}
|
|
15595
15725
|
throw err;
|
|
15596
15726
|
} finally {
|
|
15597
15727
|
if (parentBudget) {
|
|
@@ -15707,7 +15837,8 @@ ${summaryResponse.content}`
|
|
|
15707
15837
|
return;
|
|
15708
15838
|
}
|
|
15709
15839
|
} catch (err) {
|
|
15710
|
-
|
|
15840
|
+
rethrowUnrecoverable(err);
|
|
15841
|
+
if (parentSignal?.aborted) throw err;
|
|
15711
15842
|
remaining--;
|
|
15712
15843
|
lastError = err instanceof Error ? err : new Error(`Validator error: ${String(err)}`);
|
|
15713
15844
|
if (remaining === 0 && !settled) {
|
|
@@ -15727,7 +15858,7 @@ ${summaryResponse.content}`
|
|
|
15727
15858
|
controller.abort();
|
|
15728
15859
|
resolve2(value);
|
|
15729
15860
|
}).catch((err) => {
|
|
15730
|
-
if (
|
|
15861
|
+
if (isUnrecoverableError(err)) {
|
|
15731
15862
|
if (!settled) {
|
|
15732
15863
|
settled = true;
|
|
15733
15864
|
controller.abort();
|
|
@@ -15736,6 +15867,12 @@ ${summaryResponse.content}`
|
|
|
15736
15867
|
throw err;
|
|
15737
15868
|
}
|
|
15738
15869
|
if (settled) return;
|
|
15870
|
+
if (parentSignal?.aborted) {
|
|
15871
|
+
settled = true;
|
|
15872
|
+
controller.abort();
|
|
15873
|
+
reject(err);
|
|
15874
|
+
return;
|
|
15875
|
+
}
|
|
15739
15876
|
if (err instanceof DOMException && err.name === "AbortError") {
|
|
15740
15877
|
remaining--;
|
|
15741
15878
|
if (remaining === 0 && !settled) {
|
|
@@ -15794,7 +15931,7 @@ ${summaryResponse.content}`
|
|
|
15794
15931
|
results[idx] = { ok: true, value };
|
|
15795
15932
|
successCount++;
|
|
15796
15933
|
} catch (err) {
|
|
15797
|
-
if (
|
|
15934
|
+
if (isUnrecoverableError(err)) {
|
|
15798
15935
|
settled = true;
|
|
15799
15936
|
controller?.abort();
|
|
15800
15937
|
reject(err);
|
|
@@ -15803,6 +15940,12 @@ ${summaryResponse.content}`
|
|
|
15803
15940
|
if (settled) {
|
|
15804
15941
|
return;
|
|
15805
15942
|
}
|
|
15943
|
+
if (parentSignal?.aborted) {
|
|
15944
|
+
settled = true;
|
|
15945
|
+
controller?.abort();
|
|
15946
|
+
reject(err);
|
|
15947
|
+
return;
|
|
15948
|
+
}
|
|
15806
15949
|
if (err instanceof DOMException && err.name === "AbortError" && controller?.signal.aborted) {
|
|
15807
15950
|
completedCount++;
|
|
15808
15951
|
return;
|
|
@@ -20764,8 +20907,9 @@ var AxlRuntime = class extends import_node_events2.EventEmitter {
|
|
|
20764
20907
|
* new paid operations once known spend reaches the limit. Already-dispatched
|
|
20765
20908
|
* work still settles and is still counted.
|
|
20766
20909
|
*
|
|
20767
|
-
*
|
|
20768
|
-
*
|
|
20910
|
+
* Model metadata and timing share the settlement scope with accounting, so
|
|
20911
|
+
* they cross runtimes and compatible ESM/CJS copies. Workflow names and
|
|
20912
|
+
* captured traces still come from this runtime's events.
|
|
20769
20913
|
*/
|
|
20770
20914
|
async trackOutcome(fn, options) {
|
|
20771
20915
|
const parentScope = costScopeStorage.getStore();
|
|
@@ -20774,49 +20918,11 @@ var AxlRuntime = class extends import_node_events2.EventEmitter {
|
|
|
20774
20918
|
trackedIds: /* @__PURE__ */ new Set(),
|
|
20775
20919
|
parent: parentScope
|
|
20776
20920
|
};
|
|
20777
|
-
const modelCalls = /* @__PURE__ */ new Map();
|
|
20778
|
-
const modelTiming = /* @__PURE__ */ new Map();
|
|
20779
|
-
const captureTimingSamples = options?.captureTimingSamples === true;
|
|
20780
20921
|
const workflowCalls = /* @__PURE__ */ new Map();
|
|
20781
|
-
const tokens = { input: 0, output: 0, reasoning: 0 };
|
|
20782
|
-
let agentCalls = 0;
|
|
20783
20922
|
const capturedTraces = options?.captureTraces ? [] : void 0;
|
|
20784
20923
|
const listener = (event) => {
|
|
20785
20924
|
if (!scope.trackedIds.has(event.executionId)) return;
|
|
20786
20925
|
scope.totalCost += eventCostContribution(event);
|
|
20787
|
-
if (event.type === "agent_call_end") {
|
|
20788
|
-
if (event.model) modelCalls.set(event.model, (modelCalls.get(event.model) ?? 0) + 1);
|
|
20789
|
-
agentCalls++;
|
|
20790
|
-
if (event.tokens) {
|
|
20791
|
-
tokens.input += event.tokens.input ?? 0;
|
|
20792
|
-
tokens.output += event.tokens.output ?? 0;
|
|
20793
|
-
tokens.reasoning += event.tokens.reasoning ?? 0;
|
|
20794
|
-
}
|
|
20795
|
-
const failed2 = event.data?.error != null;
|
|
20796
|
-
if (event.model && event.timing && !failed2) {
|
|
20797
|
-
const t = event.timing;
|
|
20798
|
-
let bucket = modelTiming.get(event.model);
|
|
20799
|
-
if (!bucket) {
|
|
20800
|
-
bucket = {
|
|
20801
|
-
calls: 0,
|
|
20802
|
-
queuedMs: 0,
|
|
20803
|
-
retryMs: 0,
|
|
20804
|
-
wireMs: 0,
|
|
20805
|
-
...captureTimingSamples ? { samples: [] } : {}
|
|
20806
|
-
};
|
|
20807
|
-
modelTiming.set(event.model, bucket);
|
|
20808
|
-
}
|
|
20809
|
-
bucket.calls++;
|
|
20810
|
-
bucket.samples?.push(t);
|
|
20811
|
-
bucket.queuedMs += t.queuedMs;
|
|
20812
|
-
bucket.retryMs += t.retryMs;
|
|
20813
|
-
bucket.wireMs += t.wireMs;
|
|
20814
|
-
if (t.firstTokenMs != null) {
|
|
20815
|
-
bucket.firstTokenMs = (bucket.firstTokenMs ?? 0) + t.firstTokenMs;
|
|
20816
|
-
bucket.firstTokenCalls = (bucket.firstTokenCalls ?? 0) + 1;
|
|
20817
|
-
}
|
|
20818
|
-
}
|
|
20819
|
-
}
|
|
20820
20926
|
if (event.type === "workflow_start" && event.workflow) {
|
|
20821
20927
|
workflowCalls.set(event.workflow, (workflowCalls.get(event.workflow) ?? 0) + 1);
|
|
20822
20928
|
}
|
|
@@ -20842,9 +20948,14 @@ var AxlRuntime = class extends import_node_events2.EventEmitter {
|
|
|
20842
20948
|
this.on("trace", listener);
|
|
20843
20949
|
let outcome;
|
|
20844
20950
|
let accounting;
|
|
20951
|
+
let diagnostics;
|
|
20845
20952
|
try {
|
|
20846
|
-
({ outcome, accounting } = await runInAccountingScope(
|
|
20847
|
-
{
|
|
20953
|
+
({ outcome, accounting, diagnostics } = await runInAccountingScope(
|
|
20954
|
+
{
|
|
20955
|
+
purpose: options?.purpose,
|
|
20956
|
+
admission: options?.admission,
|
|
20957
|
+
captureTimingSamples: options?.captureTimingSamples
|
|
20958
|
+
},
|
|
20848
20959
|
() => (
|
|
20849
20960
|
// Capture wraps the cost scope rather than the other way round so a
|
|
20850
20961
|
// record can never be written for an operation the accounting scope
|
|
@@ -20868,13 +20979,13 @@ var AxlRuntime = class extends import_node_events2.EventEmitter {
|
|
|
20868
20979
|
return {
|
|
20869
20980
|
...outcome,
|
|
20870
20981
|
accounting,
|
|
20871
|
-
...modelTiming.
|
|
20982
|
+
...Object.keys(diagnostics.modelTiming).length > 0 ? { modelTiming: diagnostics.modelTiming } : {},
|
|
20872
20983
|
...capturedTraces ? { traces: capturedTraces } : {},
|
|
20873
20984
|
metadata: {
|
|
20874
|
-
models:
|
|
20875
|
-
modelCallCounts:
|
|
20876
|
-
tokens,
|
|
20877
|
-
agentCalls,
|
|
20985
|
+
models: Object.keys(diagnostics.modelCallCounts),
|
|
20986
|
+
modelCallCounts: Object.keys(diagnostics.modelCallCounts).length > 0 ? diagnostics.modelCallCounts : void 0,
|
|
20987
|
+
tokens: diagnostics.tokens,
|
|
20988
|
+
agentCalls: diagnostics.agentCalls,
|
|
20878
20989
|
workflows: [...workflowCalls.keys()],
|
|
20879
20990
|
workflowCallCounts: workflowCalls.size > 0 ? Object.fromEntries(workflowCalls) : void 0
|
|
20880
20991
|
}
|