@x12i/ai-dispatcher 3.2.0 → 3.3.1
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/README.md +22 -17
- package/dist/index.cjs +412 -106
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +22 -6
- package/dist/index.d.ts +22 -6
- package/dist/index.js +405 -104
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -123,7 +123,7 @@ async function openTrack(settings, model) {
|
|
|
123
123
|
try {
|
|
124
124
|
tokenCounter = await loadTokenizer(tokenizer);
|
|
125
125
|
const framing = framingFor(settings);
|
|
126
|
-
const
|
|
126
|
+
const resolved2 = resolveSettings({
|
|
127
127
|
files: [],
|
|
128
128
|
env: {},
|
|
129
129
|
factory: {
|
|
@@ -138,8 +138,8 @@ async function openTrack(settings, model) {
|
|
|
138
138
|
});
|
|
139
139
|
const approvals = settings.approvals;
|
|
140
140
|
const client = createCoreClient({
|
|
141
|
-
config:
|
|
142
|
-
explanation:
|
|
141
|
+
config: resolved2.config,
|
|
142
|
+
explanation: resolved2.explanation,
|
|
143
143
|
...approvals && approvals.length > 0 ? { policy: { approvals: [...approvals] } } : {},
|
|
144
144
|
...tokenCounter ? { tokenCounter } : {},
|
|
145
145
|
warn: () => void 0
|
|
@@ -193,10 +193,10 @@ async function encodeRequestText(request, track) {
|
|
|
193
193
|
if (typeof request.input === "string") {
|
|
194
194
|
request.input = await encodeString(track, request.input);
|
|
195
195
|
} else if (Array.isArray(request.input)) {
|
|
196
|
-
for (let
|
|
197
|
-
const item = request.input[
|
|
196
|
+
for (let index2 = 0; index2 < request.input.length; index2 += 1) {
|
|
197
|
+
const item = request.input[index2];
|
|
198
198
|
if (typeof item === "string") {
|
|
199
|
-
request.input[
|
|
199
|
+
request.input[index2] = await encodeString(track, item);
|
|
200
200
|
} else if (item) {
|
|
201
201
|
await encodeContentRecord(item, track);
|
|
202
202
|
}
|
|
@@ -393,9 +393,9 @@ function walk(current, tokens) {
|
|
|
393
393
|
}
|
|
394
394
|
if (Array.isArray(current)) {
|
|
395
395
|
if (!/^\d+$/.test(head)) return [];
|
|
396
|
-
const
|
|
397
|
-
if (
|
|
398
|
-
return walk(current[
|
|
396
|
+
const index2 = Number(head);
|
|
397
|
+
if (index2 >= current.length) return [];
|
|
398
|
+
return walk(current[index2], rest);
|
|
399
399
|
}
|
|
400
400
|
if (!isRecord2(current) || !Object.prototype.hasOwnProperty.call(current, head)) return [];
|
|
401
401
|
return walk(current[head], rest);
|
|
@@ -430,9 +430,9 @@ function collectParents(current, tokens) {
|
|
|
430
430
|
}
|
|
431
431
|
if (Array.isArray(current)) {
|
|
432
432
|
if (!/^\d+$/.test(head)) return [];
|
|
433
|
-
const
|
|
434
|
-
if (
|
|
435
|
-
return collectParents(current[
|
|
433
|
+
const index2 = Number(head);
|
|
434
|
+
if (index2 >= current.length) return [];
|
|
435
|
+
return collectParents(current[index2], rest);
|
|
436
436
|
}
|
|
437
437
|
if (!isRecord2(current) || !Object.prototype.hasOwnProperty.call(current, head)) return [];
|
|
438
438
|
return collectParents(current[head], rest);
|
|
@@ -446,8 +446,8 @@ function deletePointer(root, pointer) {
|
|
|
446
446
|
for (const parent of parents) {
|
|
447
447
|
if (Array.isArray(parent)) {
|
|
448
448
|
if (!/^\d+$/.test(last)) continue;
|
|
449
|
-
const
|
|
450
|
-
if (
|
|
449
|
+
const index2 = Number(last);
|
|
450
|
+
if (index2 < parent.length) parent.splice(index2, 1);
|
|
451
451
|
continue;
|
|
452
452
|
}
|
|
453
453
|
if (isRecord2(parent) && Object.prototype.hasOwnProperty.call(parent, last)) {
|
|
@@ -479,6 +479,38 @@ function extractStreamReasoningText(event, response) {
|
|
|
479
479
|
}
|
|
480
480
|
return firstConcatenatedText(event, response.streamReasoningPaths);
|
|
481
481
|
}
|
|
482
|
+
function readReportedEffort(root) {
|
|
483
|
+
if (!isRecord3(root)) return void 0;
|
|
484
|
+
const fromRoot = effortOn(root.reasoning) ?? namedEffort(root.reasoning_effort);
|
|
485
|
+
if (fromRoot) return fromRoot;
|
|
486
|
+
if (Array.isArray(root.choices)) {
|
|
487
|
+
for (const choice of root.choices) {
|
|
488
|
+
if (!isRecord3(choice)) continue;
|
|
489
|
+
const message = isRecord3(choice.message) ? choice.message : void 0;
|
|
490
|
+
const fromMessage = message ? effortOn(message.reasoning) ?? namedEffort(message.reasoning_effort) : void 0;
|
|
491
|
+
if (fromMessage) return fromMessage;
|
|
492
|
+
const fromChoice = effortOn(choice.reasoning) ?? namedEffort(choice.reasoning_effort);
|
|
493
|
+
if (fromChoice) return fromChoice;
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
if (Array.isArray(root.output)) {
|
|
497
|
+
for (const item of root.output) {
|
|
498
|
+
if (!isRecord3(item) || item.type !== "reasoning") continue;
|
|
499
|
+
const effort = namedEffort(item.effort);
|
|
500
|
+
if (effort) return effort;
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
return void 0;
|
|
504
|
+
}
|
|
505
|
+
function effortOn(value) {
|
|
506
|
+
if (!isRecord3(value)) return void 0;
|
|
507
|
+
return namedEffort(value.effort);
|
|
508
|
+
}
|
|
509
|
+
function namedEffort(value) {
|
|
510
|
+
if (typeof value !== "string") return void 0;
|
|
511
|
+
const trimmed = value.trim();
|
|
512
|
+
return trimmed || void 0;
|
|
513
|
+
}
|
|
482
514
|
function readReasoningTokens(root, paths) {
|
|
483
515
|
for (const path of paths) {
|
|
484
516
|
const absolute = firstNumber(root, [path]);
|
|
@@ -563,7 +595,10 @@ function splitThinkTags(text) {
|
|
|
563
595
|
// src/apply-resolution.ts
|
|
564
596
|
function applyResolution(response, prepared) {
|
|
565
597
|
const result = response;
|
|
566
|
-
if (prepared.resolution)
|
|
598
|
+
if (prepared.resolution) {
|
|
599
|
+
const reportedEffort = readReportedEffort(response.raw?.response);
|
|
600
|
+
result.reasoningResolution = reportedEffort ? { ...prepared.resolution, reportedEffort } : prepared.resolution;
|
|
601
|
+
}
|
|
567
602
|
if (prepared.cacheResolution) result.cacheResolution = prepared.cacheResolution;
|
|
568
603
|
if (prepared.cacheWarnings?.length) {
|
|
569
604
|
result.warnings = [...result.warnings, ...prepared.cacheWarnings];
|
|
@@ -946,9 +981,7 @@ function isRecord5(value) {
|
|
|
946
981
|
|
|
947
982
|
// src/prepare-request.ts
|
|
948
983
|
import {
|
|
949
|
-
|
|
950
|
-
mergeReasoningBody,
|
|
951
|
-
resolveReasoning
|
|
984
|
+
mergeReasoningBody
|
|
952
985
|
} from "@x12i/ai-profiles";
|
|
953
986
|
|
|
954
987
|
// src/cache-apply.ts
|
|
@@ -1032,38 +1065,38 @@ function placeBedrockBreakpoint(body, ttl) {
|
|
|
1032
1065
|
function markMessages(body, field, markerKey, markerValue, textType) {
|
|
1033
1066
|
const messages = body[field];
|
|
1034
1067
|
if (!Array.isArray(messages)) return { body, placed: false };
|
|
1035
|
-
const
|
|
1036
|
-
if (
|
|
1037
|
-
const marked = markMessage(messages[
|
|
1068
|
+
const index2 = stableMessageIndex(messages);
|
|
1069
|
+
if (index2 < 0) return { body, placed: false };
|
|
1070
|
+
const marked = markMessage(messages[index2], markerKey, markerValue, textType);
|
|
1038
1071
|
if (!marked) return { body, placed: false };
|
|
1039
1072
|
const next = messages.slice();
|
|
1040
|
-
next[
|
|
1073
|
+
next[index2] = marked;
|
|
1041
1074
|
return { placed: true, body: { ...body, [field]: next } };
|
|
1042
1075
|
}
|
|
1043
1076
|
function markInput(body, markerKey, markerValue, textType) {
|
|
1044
1077
|
if (!Array.isArray(body.input)) return { body, placed: false };
|
|
1045
|
-
const
|
|
1046
|
-
if (
|
|
1047
|
-
const marked = markMessage(body.input[
|
|
1078
|
+
const index2 = stableInputIndex(body.input);
|
|
1079
|
+
if (index2 < 0) return { body, placed: false };
|
|
1080
|
+
const marked = markMessage(body.input[index2], markerKey, markerValue, textType);
|
|
1048
1081
|
if (!marked) return { body, placed: false };
|
|
1049
1082
|
const next = body.input.slice();
|
|
1050
|
-
next[
|
|
1083
|
+
next[index2] = marked;
|
|
1051
1084
|
return { placed: true, body: { ...body, input: next } };
|
|
1052
1085
|
}
|
|
1053
1086
|
function stableMessageIndex(messages) {
|
|
1054
1087
|
let lastSystem = -1;
|
|
1055
|
-
for (let
|
|
1056
|
-
const message = messages[
|
|
1057
|
-
if (isPlainRecord(message) && message.role === "system" && hasText(message.content)) lastSystem =
|
|
1088
|
+
for (let index2 = 0; index2 < messages.length; index2 += 1) {
|
|
1089
|
+
const message = messages[index2];
|
|
1090
|
+
if (isPlainRecord(message) && message.role === "system" && hasText(message.content)) lastSystem = index2;
|
|
1058
1091
|
}
|
|
1059
1092
|
return lastSystem;
|
|
1060
1093
|
}
|
|
1061
1094
|
function stableInputIndex(items) {
|
|
1062
1095
|
let lastStable = -1;
|
|
1063
|
-
for (let
|
|
1064
|
-
const item = items[
|
|
1096
|
+
for (let index2 = 0; index2 < items.length; index2 += 1) {
|
|
1097
|
+
const item = items[index2];
|
|
1065
1098
|
if (!isPlainRecord(item) || !hasText(item.content)) continue;
|
|
1066
|
-
if (item.role === "system" || item.role === "developer") lastStable =
|
|
1099
|
+
if (item.role === "system" || item.role === "developer") lastStable = index2;
|
|
1067
1100
|
}
|
|
1068
1101
|
return lastStable;
|
|
1069
1102
|
}
|
|
@@ -1080,10 +1113,10 @@ function markContent(content, markerKey, markerValue, textType) {
|
|
|
1080
1113
|
}
|
|
1081
1114
|
if (!Array.isArray(content)) return void 0;
|
|
1082
1115
|
const parts = content.map((part) => isPlainRecord(part) ? { ...part } : part);
|
|
1083
|
-
for (let
|
|
1084
|
-
const part = parts[
|
|
1116
|
+
for (let index2 = parts.length - 1; index2 >= 0; index2 -= 1) {
|
|
1117
|
+
const part = parts[index2];
|
|
1085
1118
|
if (!isPlainRecord(part) || typeof part.text !== "string" || !part.text.trim()) continue;
|
|
1086
|
-
parts[
|
|
1119
|
+
parts[index2] = { ...part, [markerKey]: markerValue };
|
|
1087
1120
|
return parts;
|
|
1088
1121
|
}
|
|
1089
1122
|
return void 0;
|
|
@@ -1239,11 +1272,11 @@ function resolveCloudflarePromptCache(args) {
|
|
|
1239
1272
|
warnings: []
|
|
1240
1273
|
};
|
|
1241
1274
|
}
|
|
1242
|
-
const
|
|
1243
|
-
const ttl =
|
|
1275
|
+
const resolved2 = applyProfile({ input, mode, key, requestedTtl, resolutionBase, model, profile });
|
|
1276
|
+
const ttl = resolved2.plan.ttl ?? requestedTtl;
|
|
1244
1277
|
return {
|
|
1245
|
-
...
|
|
1246
|
-
plan: { ...
|
|
1278
|
+
...resolved2,
|
|
1279
|
+
plan: { ...resolved2.plan, gateway: gatewayDirective(false, ttl, key) }
|
|
1247
1280
|
};
|
|
1248
1281
|
}
|
|
1249
1282
|
function applyProfile(args) {
|
|
@@ -1450,22 +1483,22 @@ function restoreCloudflareModel(model, prefix) {
|
|
|
1450
1483
|
return `${prefix}${model}`;
|
|
1451
1484
|
}
|
|
1452
1485
|
function createCloudflareProviderAdapter(options = {}, packer) {
|
|
1453
|
-
const
|
|
1486
|
+
const resolved2 = resolveCloudflareOptions(options, packer);
|
|
1454
1487
|
return {
|
|
1455
1488
|
compile(request, call) {
|
|
1456
|
-
return compileCloudflareRequest(request,
|
|
1489
|
+
return compileCloudflareRequest(request, resolved2, call, false);
|
|
1457
1490
|
},
|
|
1458
1491
|
async run(request, call) {
|
|
1459
1492
|
const requestId = request.id ?? "cloudflare";
|
|
1460
1493
|
try {
|
|
1461
|
-
return await runCloudflare(request,
|
|
1494
|
+
return await runCloudflare(request, resolved2, call, requestId);
|
|
1462
1495
|
} catch (error) {
|
|
1463
1496
|
if (error instanceof AiDispatcherError && isConfigError(error.code)) throw error;
|
|
1464
1497
|
return failedResponse(request, requestId, error, "chat");
|
|
1465
1498
|
}
|
|
1466
1499
|
},
|
|
1467
1500
|
executeStreamingChat(request, call) {
|
|
1468
|
-
return streamCloudflare(request,
|
|
1501
|
+
return streamCloudflare(request, resolved2, call);
|
|
1469
1502
|
}
|
|
1470
1503
|
};
|
|
1471
1504
|
}
|
|
@@ -2613,6 +2646,261 @@ function isRecord6(value) {
|
|
|
2613
2646
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2614
2647
|
}
|
|
2615
2648
|
|
|
2649
|
+
// src/resolve-effort.ts
|
|
2650
|
+
import {
|
|
2651
|
+
AIProfilesError,
|
|
2652
|
+
resolveReasoning
|
|
2653
|
+
} from "@x12i/ai-profiles";
|
|
2654
|
+
|
|
2655
|
+
// src/catalog-efforts.ts
|
|
2656
|
+
import { createRequire } from "module";
|
|
2657
|
+
import { readFileSync } from "fs";
|
|
2658
|
+
import { dirname, join } from "path";
|
|
2659
|
+
import { loadBundledModelsCatalog } from "@x12i/ai-profiles";
|
|
2660
|
+
var index;
|
|
2661
|
+
function normalize(value) {
|
|
2662
|
+
return value.trim().toLowerCase();
|
|
2663
|
+
}
|
|
2664
|
+
function addKey(keys, key, row) {
|
|
2665
|
+
const normalized = normalize(key);
|
|
2666
|
+
if (!normalized) return;
|
|
2667
|
+
const existing = keys.get(normalized);
|
|
2668
|
+
if (!existing) {
|
|
2669
|
+
keys.set(normalized, row);
|
|
2670
|
+
return;
|
|
2671
|
+
}
|
|
2672
|
+
if (existing === "ambiguous") return;
|
|
2673
|
+
if (existing.modelId !== row.modelId) keys.set(normalized, "ambiguous");
|
|
2674
|
+
}
|
|
2675
|
+
function loadAssignmentAliases() {
|
|
2676
|
+
const require2 = createRequire(import.meta.url);
|
|
2677
|
+
const entry = require2.resolve("@x12i/ai-profiles");
|
|
2678
|
+
const path = join(dirname(entry), "data", "reasoning-directives.json");
|
|
2679
|
+
const document = JSON.parse(readFileSync(path, "utf8"));
|
|
2680
|
+
return document.assignments ?? [];
|
|
2681
|
+
}
|
|
2682
|
+
function effortList(entry) {
|
|
2683
|
+
const reasoning = entry.openrouter.reasoning;
|
|
2684
|
+
const modelId = entry.openrouter.modelId;
|
|
2685
|
+
if (!reasoning || !Object.prototype.hasOwnProperty.call(reasoning, "supportedEfforts")) {
|
|
2686
|
+
return { kind: "unspecified", modelId };
|
|
2687
|
+
}
|
|
2688
|
+
if (reasoning.supportedEfforts === null) return { kind: "any", modelId };
|
|
2689
|
+
if (Array.isArray(reasoning.supportedEfforts)) {
|
|
2690
|
+
return { kind: "listed", modelId, efforts: reasoning.supportedEfforts };
|
|
2691
|
+
}
|
|
2692
|
+
return { kind: "unspecified", modelId };
|
|
2693
|
+
}
|
|
2694
|
+
function buildIndex() {
|
|
2695
|
+
const catalog = loadBundledModelsCatalog();
|
|
2696
|
+
const keys = /* @__PURE__ */ new Map();
|
|
2697
|
+
const byCatalogId = /* @__PURE__ */ new Map();
|
|
2698
|
+
for (const entry of catalog.models) {
|
|
2699
|
+
const row = effortList(entry);
|
|
2700
|
+
byCatalogId.set(normalize(entry.openrouter.modelId), row);
|
|
2701
|
+
addKey(keys, entry.openrouter.modelId, row);
|
|
2702
|
+
if (entry.openrouter.canonicalSlug) addKey(keys, entry.openrouter.canonicalSlug, row);
|
|
2703
|
+
addKey(keys, `${entry.direct.provider}/${entry.direct.modelId}`, row);
|
|
2704
|
+
addKey(keys, `openrouter/${entry.openrouter.modelId}`, row);
|
|
2705
|
+
addKey(keys, entry.direct.modelId, row);
|
|
2706
|
+
}
|
|
2707
|
+
for (const assignment of loadAssignmentAliases()) {
|
|
2708
|
+
const row = byCatalogId.get(normalize(assignment.catalogModelId));
|
|
2709
|
+
if (!row) continue;
|
|
2710
|
+
for (const alias of assignment.aliases ?? []) addKey(keys, alias, row);
|
|
2711
|
+
}
|
|
2712
|
+
return keys;
|
|
2713
|
+
}
|
|
2714
|
+
function lookupCatalogEfforts(model) {
|
|
2715
|
+
if (!index) index = buildIndex();
|
|
2716
|
+
const direct = index.get(normalize(model));
|
|
2717
|
+
if (direct && direct !== "ambiguous") return direct;
|
|
2718
|
+
const gateway = normalize(model);
|
|
2719
|
+
if (gateway.startsWith("openrouter/")) {
|
|
2720
|
+
const stripped = index.get(gateway.slice("openrouter/".length));
|
|
2721
|
+
if (stripped && stripped !== "ambiguous") return stripped;
|
|
2722
|
+
}
|
|
2723
|
+
return void 0;
|
|
2724
|
+
}
|
|
2725
|
+
|
|
2726
|
+
// src/resolve-effort.ts
|
|
2727
|
+
var EMPTY_RESPONSE = {
|
|
2728
|
+
reasoningTextPaths: [],
|
|
2729
|
+
streamReasoningKeys: [],
|
|
2730
|
+
streamReasoningPaths: [],
|
|
2731
|
+
stripFromHistoryPaths: [],
|
|
2732
|
+
stripThinkTags: false
|
|
2733
|
+
};
|
|
2734
|
+
var MAPPER_EFFORTS = ["high", "xhigh", "max", "medium", "low", "minimal"];
|
|
2735
|
+
function isRecord7(value) {
|
|
2736
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2737
|
+
}
|
|
2738
|
+
function readBodyEffort(body) {
|
|
2739
|
+
const reasoning = body.reasoning;
|
|
2740
|
+
if (isRecord7(reasoning) && typeof reasoning.effort === "string") return reasoning.effort;
|
|
2741
|
+
const fields = body.additionalModelRequestFields;
|
|
2742
|
+
if (!isRecord7(fields)) return void 0;
|
|
2743
|
+
const output = fields.output_config;
|
|
2744
|
+
if (isRecord7(output) && typeof output.effort === "string") return output.effort;
|
|
2745
|
+
return void 0;
|
|
2746
|
+
}
|
|
2747
|
+
function writeBodyEffort(body, effort) {
|
|
2748
|
+
const reasoning = body.reasoning;
|
|
2749
|
+
if (isRecord7(reasoning) && typeof reasoning.effort === "string") {
|
|
2750
|
+
reasoning.effort = effort;
|
|
2751
|
+
return true;
|
|
2752
|
+
}
|
|
2753
|
+
const fields = body.additionalModelRequestFields;
|
|
2754
|
+
if (!isRecord7(fields)) return false;
|
|
2755
|
+
const output = fields.output_config;
|
|
2756
|
+
if (isRecord7(output) && typeof output.effort === "string") {
|
|
2757
|
+
output.effort = effort;
|
|
2758
|
+
return true;
|
|
2759
|
+
}
|
|
2760
|
+
return false;
|
|
2761
|
+
}
|
|
2762
|
+
function unsupported(model, effort, supported) {
|
|
2763
|
+
return new AiDispatcherError(
|
|
2764
|
+
"EFFORT_UNSUPPORTED",
|
|
2765
|
+
`Model '${model}' does not accept reasoning effort '${effort}'. Supported efforts: ${supported.join(", ")}.`,
|
|
2766
|
+
{ model, effort, supportedEfforts: [...supported] }
|
|
2767
|
+
);
|
|
2768
|
+
}
|
|
2769
|
+
function ignoredDirective() {
|
|
2770
|
+
return {
|
|
2771
|
+
outcome: "ignored",
|
|
2772
|
+
body: {},
|
|
2773
|
+
response: {
|
|
2774
|
+
reasoningTextPaths: [...EMPTY_RESPONSE.reasoningTextPaths],
|
|
2775
|
+
streamReasoningKeys: [...EMPTY_RESPONSE.streamReasoningKeys],
|
|
2776
|
+
streamReasoningPaths: [...EMPTY_RESPONSE.streamReasoningPaths],
|
|
2777
|
+
stripFromHistoryPaths: [...EMPTY_RESPONSE.stripFromHistoryPaths],
|
|
2778
|
+
stripThinkTags: EMPTY_RESPONSE.stripThinkTags
|
|
2779
|
+
}
|
|
2780
|
+
};
|
|
2781
|
+
}
|
|
2782
|
+
function toDispatcherError(error) {
|
|
2783
|
+
return new AiDispatcherError(error.code, error.message, error.details);
|
|
2784
|
+
}
|
|
2785
|
+
function resolveMapping(input, ignoreUnknown) {
|
|
2786
|
+
try {
|
|
2787
|
+
return resolveReasoning({
|
|
2788
|
+
target: input.target,
|
|
2789
|
+
model: input.model,
|
|
2790
|
+
effort: input.effort
|
|
2791
|
+
});
|
|
2792
|
+
} catch (error) {
|
|
2793
|
+
if (!(error instanceof AIProfilesError)) throw error;
|
|
2794
|
+
if (ignoreUnknown && (error.code === "UNKNOWN_MODEL" || error.code === "REASONING_MAPPING_MISSING")) {
|
|
2795
|
+
return ignoredDirective();
|
|
2796
|
+
}
|
|
2797
|
+
if (error.code === "INVALID_EFFORT") return "bad-key";
|
|
2798
|
+
if (error.code === "REASONING_MAPPING_INVALID" && error.message.includes("missing effort")) return "bad-key";
|
|
2799
|
+
throw toDispatcherError(error);
|
|
2800
|
+
}
|
|
2801
|
+
}
|
|
2802
|
+
function mappingOrThrow(input, ignoreUnknown) {
|
|
2803
|
+
const mapped = resolveMapping(input, ignoreUnknown);
|
|
2804
|
+
if (mapped === "bad-key") {
|
|
2805
|
+
throw new AiDispatcherError(
|
|
2806
|
+
"INVALID_EFFORT",
|
|
2807
|
+
`Invalid reasoning effort '${input.effort}'.`,
|
|
2808
|
+
{ target: input.target, effort: input.effort, model: input.model }
|
|
2809
|
+
);
|
|
2810
|
+
}
|
|
2811
|
+
return mapped;
|
|
2812
|
+
}
|
|
2813
|
+
function sendAsWritten(directive, effort, target) {
|
|
2814
|
+
if (directive.outcome === "ignored") return directive;
|
|
2815
|
+
const copy = structuredClone(directive);
|
|
2816
|
+
const wrote = writeBodyEffort(copy.body, effort);
|
|
2817
|
+
if (!wrote && target !== "bedrock") {
|
|
2818
|
+
const reasoning = isRecord7(copy.body.reasoning) ? copy.body.reasoning : {};
|
|
2819
|
+
copy.body = { ...copy.body, reasoning: { ...reasoning, effort } };
|
|
2820
|
+
}
|
|
2821
|
+
copy.outcome = "applied";
|
|
2822
|
+
return copy;
|
|
2823
|
+
}
|
|
2824
|
+
function directiveForListedEffort(input) {
|
|
2825
|
+
const direct = resolveMapping(input, input.ignoreUnknown);
|
|
2826
|
+
if (direct !== "bad-key") {
|
|
2827
|
+
if (direct.outcome === "ignored") return direct;
|
|
2828
|
+
const sent = readBodyEffort(direct.body);
|
|
2829
|
+
if (sent === input.effort) {
|
|
2830
|
+
if (direct.outcome === "degraded") {
|
|
2831
|
+
const copy = structuredClone(direct);
|
|
2832
|
+
copy.outcome = "applied";
|
|
2833
|
+
return copy;
|
|
2834
|
+
}
|
|
2835
|
+
return direct;
|
|
2836
|
+
}
|
|
2837
|
+
if (sent) return sendAsWritten(direct, input.effort, input.target);
|
|
2838
|
+
}
|
|
2839
|
+
const proxies = MAPPER_EFFORTS.filter((candidate) => {
|
|
2840
|
+
if (candidate === input.effort) return false;
|
|
2841
|
+
if (input.supported === null) return true;
|
|
2842
|
+
return input.supported.includes(candidate);
|
|
2843
|
+
});
|
|
2844
|
+
for (const proxy of proxies) {
|
|
2845
|
+
const mapped = resolveMapping({ ...input, effort: proxy }, input.ignoreUnknown);
|
|
2846
|
+
if (mapped === "bad-key" || mapped.outcome === "ignored") continue;
|
|
2847
|
+
if (!readBodyEffort(mapped.body)) continue;
|
|
2848
|
+
return sendAsWritten(mapped, input.effort, input.target);
|
|
2849
|
+
}
|
|
2850
|
+
return mappingOrThrow(input, input.ignoreUnknown);
|
|
2851
|
+
}
|
|
2852
|
+
function sentOf(directive) {
|
|
2853
|
+
if (directive.outcome === "ignored") return void 0;
|
|
2854
|
+
return readBodyEffort(directive.body);
|
|
2855
|
+
}
|
|
2856
|
+
function resolved(directive) {
|
|
2857
|
+
const sentEffort = sentOf(directive);
|
|
2858
|
+
return sentEffort ? { directive, sentEffort } : { directive };
|
|
2859
|
+
}
|
|
2860
|
+
function resolveEffortDirective(input) {
|
|
2861
|
+
const effort = input.effort.trim();
|
|
2862
|
+
const row = lookupCatalogEfforts(input.model);
|
|
2863
|
+
if (!row) {
|
|
2864
|
+
return resolved(mappingOrThrow(input, input.ignoreUnknown));
|
|
2865
|
+
}
|
|
2866
|
+
if (row.kind === "unspecified") {
|
|
2867
|
+
const directive2 = mappingOrThrow({ ...input, effort }, input.ignoreUnknown);
|
|
2868
|
+
const sent = sentOf(directive2);
|
|
2869
|
+
if (!input.degrade && directive2.outcome === "degraded" && sent && sent !== effort) {
|
|
2870
|
+
throw new AiDispatcherError(
|
|
2871
|
+
"EFFORT_UNSUPPORTED",
|
|
2872
|
+
`Model '${input.model}' does not accept reasoning effort '${effort}' unless degradeReasoningEffort is set.`,
|
|
2873
|
+
{ model: input.model, effort, catalogModelId: row.modelId }
|
|
2874
|
+
);
|
|
2875
|
+
}
|
|
2876
|
+
return resolved(directive2);
|
|
2877
|
+
}
|
|
2878
|
+
const supported = row.kind === "listed" ? row.efforts : null;
|
|
2879
|
+
const allowed = supported === null || supported.includes(effort);
|
|
2880
|
+
if (!allowed && supported) {
|
|
2881
|
+
if (!input.degrade) throw unsupported(input.model, effort, supported);
|
|
2882
|
+
const mapped = resolveMapping({ ...input, effort }, input.ignoreUnknown);
|
|
2883
|
+
if (mapped === "bad-key") throw unsupported(input.model, effort, supported);
|
|
2884
|
+
if (mapped.outcome === "ignored") return { directive: mapped };
|
|
2885
|
+
const sent = readBodyEffort(mapped.body);
|
|
2886
|
+
if (!sent || !supported.includes(sent)) throw unsupported(input.model, effort, supported);
|
|
2887
|
+
if (sent !== effort) {
|
|
2888
|
+
const copy = structuredClone(mapped);
|
|
2889
|
+
copy.outcome = "degraded";
|
|
2890
|
+
return { directive: copy, sentEffort: sent };
|
|
2891
|
+
}
|
|
2892
|
+
return { directive: mapped, sentEffort: sent };
|
|
2893
|
+
}
|
|
2894
|
+
const directive = directiveForListedEffort({
|
|
2895
|
+
target: input.target,
|
|
2896
|
+
model: input.model,
|
|
2897
|
+
effort,
|
|
2898
|
+
ignoreUnknown: input.ignoreUnknown,
|
|
2899
|
+
supported
|
|
2900
|
+
});
|
|
2901
|
+
return resolved(directive);
|
|
2902
|
+
}
|
|
2903
|
+
|
|
2616
2904
|
// src/prepare-request.ts
|
|
2617
2905
|
function prepareDispatchRequest(params) {
|
|
2618
2906
|
const cloned = cloneRequest(params.request);
|
|
@@ -2622,11 +2910,13 @@ function prepareDispatchRequest(params) {
|
|
|
2622
2910
|
applyDispatchGate(cloned);
|
|
2623
2911
|
const provider = params.provider;
|
|
2624
2912
|
const reasoningEffort = cloned.reasoningEffort;
|
|
2913
|
+
const degradeReasoningEffort = cloned.degradeReasoningEffort === true;
|
|
2625
2914
|
const bedrockControls = cloned.bedrockControls;
|
|
2626
2915
|
const cachePolicy = cloned.cache;
|
|
2627
2916
|
const cloudflareRequest = cloned.cloudflare;
|
|
2628
2917
|
delete cloned.provider;
|
|
2629
2918
|
delete cloned.reasoningEffort;
|
|
2919
|
+
delete cloned.degradeReasoningEffort;
|
|
2630
2920
|
delete cloned.bedrockControls;
|
|
2631
2921
|
delete cloned.cache;
|
|
2632
2922
|
delete cloned.cloudflare;
|
|
@@ -2644,6 +2934,7 @@ function prepareDispatchRequest(params) {
|
|
|
2644
2934
|
const requestedModel = cloned.model ?? defaultModelFor(provider, params.options) ?? "";
|
|
2645
2935
|
const explicit = hasExplicitControl(provider, cloned, bedrockControls);
|
|
2646
2936
|
let directive;
|
|
2937
|
+
let sentEffort;
|
|
2647
2938
|
let catalogPrefix;
|
|
2648
2939
|
if (!explicit && reasoningEffort !== void 0) {
|
|
2649
2940
|
if (!requestedModel) {
|
|
@@ -2655,13 +2946,29 @@ function prepareDispatchRequest(params) {
|
|
|
2655
2946
|
if (provider === "cloudflare") {
|
|
2656
2947
|
const query = cloudflareCatalogQuery(requestedModel);
|
|
2657
2948
|
catalogPrefix = query.prefix;
|
|
2658
|
-
|
|
2949
|
+
const resolved2 = resolveEffortDirective({
|
|
2950
|
+
target: query.target,
|
|
2951
|
+
model: query.model,
|
|
2952
|
+
effort: reasoningEffort,
|
|
2953
|
+
ignoreUnknown: true,
|
|
2954
|
+
degrade: degradeReasoningEffort
|
|
2955
|
+
});
|
|
2956
|
+
directive = resolved2.directive;
|
|
2957
|
+
sentEffort = resolved2.sentEffort;
|
|
2659
2958
|
} else if (isReasoningTarget(provider)) {
|
|
2660
|
-
|
|
2959
|
+
const resolved2 = resolveEffortDirective({
|
|
2960
|
+
target: provider,
|
|
2961
|
+
model: requestedModel,
|
|
2962
|
+
effort: reasoningEffort,
|
|
2963
|
+
ignoreUnknown: false,
|
|
2964
|
+
degrade: degradeReasoningEffort
|
|
2965
|
+
});
|
|
2966
|
+
directive = resolved2.directive;
|
|
2967
|
+
sentEffort = resolved2.sentEffort;
|
|
2661
2968
|
}
|
|
2662
2969
|
}
|
|
2663
2970
|
if (provider === "openrouter") {
|
|
2664
|
-
applyNestedReasoning(cloned, reasoningEffort);
|
|
2971
|
+
applyNestedReasoning(cloned, reasoningEffort, degradeReasoningEffort);
|
|
2665
2972
|
}
|
|
2666
2973
|
if (directive?.model) {
|
|
2667
2974
|
cloned.model = provider === "cloudflare" ? restoreCloudflareModel(directive.model, catalogPrefix) : directive.model;
|
|
@@ -2722,6 +3029,7 @@ function prepareDispatchRequest(params) {
|
|
|
2722
3029
|
}
|
|
2723
3030
|
const resolution = reasoningEffort !== void 0 || explicit ? buildResolution({
|
|
2724
3031
|
requestedEffort: reasoningEffort,
|
|
3032
|
+
sentEffort: explicit ? explicitSentEffort(provider, cloned, bedrockControls) : sentEffort,
|
|
2725
3033
|
target: provider,
|
|
2726
3034
|
requestedModel,
|
|
2727
3035
|
effectiveModel,
|
|
@@ -2754,29 +3062,6 @@ function noteUnplacedCache(resolution, warnings, target, model) {
|
|
|
2754
3062
|
details: { target, model }
|
|
2755
3063
|
});
|
|
2756
3064
|
}
|
|
2757
|
-
function resolveCatalog(input, ignoreUnknown) {
|
|
2758
|
-
try {
|
|
2759
|
-
return resolveReasoning(input);
|
|
2760
|
-
} catch (error) {
|
|
2761
|
-
if (error instanceof AIProfilesError) {
|
|
2762
|
-
if (ignoreUnknown && (error.code === "UNKNOWN_MODEL" || error.code === "REASONING_MAPPING_MISSING")) {
|
|
2763
|
-
return {
|
|
2764
|
-
outcome: "ignored",
|
|
2765
|
-
body: {},
|
|
2766
|
-
response: {
|
|
2767
|
-
reasoningTextPaths: [],
|
|
2768
|
-
streamReasoningKeys: [],
|
|
2769
|
-
streamReasoningPaths: [],
|
|
2770
|
-
stripFromHistoryPaths: [],
|
|
2771
|
-
stripThinkTags: false
|
|
2772
|
-
}
|
|
2773
|
-
};
|
|
2774
|
-
}
|
|
2775
|
-
throw new AiDispatcherError(error.code, error.message, error.details);
|
|
2776
|
-
}
|
|
2777
|
-
throw error;
|
|
2778
|
-
}
|
|
2779
|
-
}
|
|
2780
3065
|
function isReasoningTarget(provider) {
|
|
2781
3066
|
return provider === "openrouter" || provider === "bedrock" || provider === "openai";
|
|
2782
3067
|
}
|
|
@@ -2784,6 +3069,15 @@ function hasExplicitControl(provider, request, bedrockControls) {
|
|
|
2784
3069
|
if (provider === "bedrock") return bedrockControls?.additionalModelRequestFields !== void 0;
|
|
2785
3070
|
return request.reasoning !== void 0;
|
|
2786
3071
|
}
|
|
3072
|
+
function explicitSentEffort(provider, request, bedrockControls) {
|
|
3073
|
+
if (provider === "bedrock") {
|
|
3074
|
+
const output = bedrockControls?.additionalModelRequestFields?.output_config;
|
|
3075
|
+
if (isRecord8(output) && typeof output.effort === "string") return output.effort;
|
|
3076
|
+
return void 0;
|
|
3077
|
+
}
|
|
3078
|
+
if (isRecord8(request.reasoning) && typeof request.reasoning.effort === "string") return request.reasoning.effort;
|
|
3079
|
+
return void 0;
|
|
3080
|
+
}
|
|
2787
3081
|
function buildResolution(params) {
|
|
2788
3082
|
return {
|
|
2789
3083
|
target: params.target,
|
|
@@ -2791,19 +3085,20 @@ function buildResolution(params) {
|
|
|
2791
3085
|
effectiveModel: params.effectiveModel,
|
|
2792
3086
|
bypassed: params.bypassed,
|
|
2793
3087
|
...params.requestedEffort ? { requestedEffort: params.requestedEffort } : {},
|
|
3088
|
+
...params.sentEffort ? { sentEffort: params.sentEffort } : {},
|
|
2794
3089
|
...params.outcome ? { outcome: params.outcome } : {}
|
|
2795
3090
|
};
|
|
2796
3091
|
}
|
|
2797
|
-
function applyNestedReasoning(request, parentEffort) {
|
|
3092
|
+
function applyNestedReasoning(request, parentEffort, degrade) {
|
|
2798
3093
|
const serverTools = request.serverTools;
|
|
2799
3094
|
if (!serverTools) return;
|
|
2800
|
-
if (serverTools.fusion) serverTools.fusion = settleNested(serverTools.fusion, "fusion", parentEffort);
|
|
3095
|
+
if (serverTools.fusion) serverTools.fusion = settleNested(serverTools.fusion, "fusion", parentEffort, degrade);
|
|
2801
3096
|
if (serverTools.advisor) {
|
|
2802
|
-
serverTools.advisor = Array.isArray(serverTools.advisor) ? serverTools.advisor.map((advisor) => settleNested(advisor, "advisor", parentEffort)) : settleNested(serverTools.advisor, "advisor", parentEffort);
|
|
3097
|
+
serverTools.advisor = Array.isArray(serverTools.advisor) ? serverTools.advisor.map((advisor) => settleNested(advisor, "advisor", parentEffort, degrade)) : settleNested(serverTools.advisor, "advisor", parentEffort, degrade);
|
|
2803
3098
|
}
|
|
2804
|
-
if (serverTools.subagent) serverTools.subagent = settleNested(serverTools.subagent, "subagent", parentEffort);
|
|
3099
|
+
if (serverTools.subagent) serverTools.subagent = settleNested(serverTools.subagent, "subagent", parentEffort, degrade);
|
|
2805
3100
|
}
|
|
2806
|
-
function settleNested(policy, kind, parentEffort) {
|
|
3101
|
+
function settleNested(policy, kind, parentEffort, degrade) {
|
|
2807
3102
|
const current = policy;
|
|
2808
3103
|
const childEffort = current.reasoningEffort;
|
|
2809
3104
|
const next = { ...current };
|
|
@@ -2813,12 +3108,18 @@ function settleNested(policy, kind, parentEffort) {
|
|
|
2813
3108
|
if (!effort) return next;
|
|
2814
3109
|
const model = kind === "fusion" ? next.judgeModel : next.model;
|
|
2815
3110
|
if (!model) return next;
|
|
2816
|
-
const directive =
|
|
3111
|
+
const directive = resolveEffortDirective({
|
|
3112
|
+
target: "openrouter",
|
|
3113
|
+
model,
|
|
3114
|
+
effort,
|
|
3115
|
+
ignoreUnknown: false,
|
|
3116
|
+
degrade
|
|
3117
|
+
}).directive;
|
|
2817
3118
|
if (directive.model) {
|
|
2818
3119
|
if (kind === "fusion") next.judgeModel = directive.model;
|
|
2819
3120
|
else next.model = directive.model;
|
|
2820
3121
|
}
|
|
2821
|
-
if (
|
|
3122
|
+
if (isRecord8(directive.body.reasoning)) next.reasoning = directive.body.reasoning;
|
|
2822
3123
|
return next;
|
|
2823
3124
|
}
|
|
2824
3125
|
function applyPromptPrefix(request, prefix) {
|
|
@@ -2855,10 +3156,10 @@ function prefixMessages(messages, prefix) {
|
|
|
2855
3156
|
return false;
|
|
2856
3157
|
}
|
|
2857
3158
|
function prefixInputItems(items, prefix) {
|
|
2858
|
-
for (let
|
|
2859
|
-
const item = items[
|
|
3159
|
+
for (let index2 = 0; index2 < items.length; index2 += 1) {
|
|
3160
|
+
const item = items[index2];
|
|
2860
3161
|
if (typeof item === "string") {
|
|
2861
|
-
items[
|
|
3162
|
+
items[index2] = prefix + item;
|
|
2862
3163
|
return true;
|
|
2863
3164
|
}
|
|
2864
3165
|
if (!item || item.role === "system") continue;
|
|
@@ -2868,7 +3169,7 @@ function prefixInputItems(items, prefix) {
|
|
|
2868
3169
|
}
|
|
2869
3170
|
if (!Array.isArray(item.content)) continue;
|
|
2870
3171
|
for (const part of item.content) {
|
|
2871
|
-
if (!
|
|
3172
|
+
if (!isRecord8(part) || typeof part.text !== "string") continue;
|
|
2872
3173
|
if (part.type === "text" || part.type === "input_text") {
|
|
2873
3174
|
part.text = prefix + part.text;
|
|
2874
3175
|
return true;
|
|
@@ -2929,7 +3230,7 @@ var ROLE_STAMP_FIELDS = ["role", "roleLayer", "roleDigest", "profileChoice"];
|
|
|
2929
3230
|
function applyRoleStamp(request) {
|
|
2930
3231
|
const stamp = request.role;
|
|
2931
3232
|
delete request.role;
|
|
2932
|
-
if (!
|
|
3233
|
+
if (!isRecord8(stamp)) return;
|
|
2933
3234
|
const identity = {};
|
|
2934
3235
|
for (const field of ROLE_STAMP_FIELDS) {
|
|
2935
3236
|
const value = stamp[field];
|
|
@@ -2944,8 +3245,8 @@ function applyRoleStamp(request) {
|
|
|
2944
3245
|
}
|
|
2945
3246
|
function absorbOverrideMetadata(request) {
|
|
2946
3247
|
const overrides = request.rawOpenRouterOverrides;
|
|
2947
|
-
if (!
|
|
2948
|
-
if (
|
|
3248
|
+
if (!isRecord8(overrides) || !Object.prototype.hasOwnProperty.call(overrides, "metadata")) return;
|
|
3249
|
+
if (isRecord8(overrides.metadata)) {
|
|
2949
3250
|
const current = { ...request.metadata ?? {} };
|
|
2950
3251
|
const extra = {};
|
|
2951
3252
|
for (const [key, value] of Object.entries(overrides.metadata)) {
|
|
@@ -2990,7 +3291,7 @@ function hasOwnKeys(value) {
|
|
|
2990
3291
|
function hasStreamMetadata(directive) {
|
|
2991
3292
|
return directive.response.streamReasoningKeys.length > 0 || directive.response.streamReasoningPaths.length > 0;
|
|
2992
3293
|
}
|
|
2993
|
-
function
|
|
3294
|
+
function isRecord8(value) {
|
|
2994
3295
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2995
3296
|
}
|
|
2996
3297
|
function readEnv2(name) {
|
|
@@ -3141,22 +3442,22 @@ import {
|
|
|
3141
3442
|
var DEFAULT_BASE_URL2 = "https://api.openai.com/v1";
|
|
3142
3443
|
var DEFAULT_TIMEOUT_MS2 = 12e4;
|
|
3143
3444
|
function createOpenAiProviderAdapter(options = {}, packer) {
|
|
3144
|
-
const
|
|
3445
|
+
const resolved2 = resolveOpenAiOptions(options, packer);
|
|
3145
3446
|
return {
|
|
3146
3447
|
compile(request, call) {
|
|
3147
|
-
return compileOpenAiRequest(request,
|
|
3448
|
+
return compileOpenAiRequest(request, resolved2, call, false);
|
|
3148
3449
|
},
|
|
3149
3450
|
async run(request, call) {
|
|
3150
3451
|
const requestId = request.id ?? "openai";
|
|
3151
3452
|
try {
|
|
3152
|
-
return await runOpenAi(request,
|
|
3453
|
+
return await runOpenAi(request, resolved2, call, requestId);
|
|
3153
3454
|
} catch (error) {
|
|
3154
3455
|
if (error instanceof AiDispatcherError && isConfigError2(error.code)) throw error;
|
|
3155
3456
|
return failedResponse2(request, requestId, error);
|
|
3156
3457
|
}
|
|
3157
3458
|
},
|
|
3158
3459
|
executeStreamingChat(request, call) {
|
|
3159
|
-
return streamOpenAi(request,
|
|
3460
|
+
return streamOpenAi(request, resolved2, call);
|
|
3160
3461
|
}
|
|
3161
3462
|
};
|
|
3162
3463
|
}
|
|
@@ -3313,7 +3614,7 @@ async function runOpenAi(request, options, call, requestId) {
|
|
|
3313
3614
|
let response;
|
|
3314
3615
|
for (let iteration = 0; iteration <= maxIterations; iteration += 1) {
|
|
3315
3616
|
response = await sendWithRetries2(active, options, timeoutFor2(request, options));
|
|
3316
|
-
const calls = functionCalls(
|
|
3617
|
+
const calls = functionCalls(isRecord9(response) ? response : {});
|
|
3317
3618
|
if (!calls.length) break;
|
|
3318
3619
|
if (!calls.every((item) => resolveExecutor2(item.name, request, options))) {
|
|
3319
3620
|
return normalizeOpenAiResponse({
|
|
@@ -3333,7 +3634,7 @@ async function runOpenAi(request, options, call, requestId) {
|
|
|
3333
3634
|
results.push(await executeOpenAiTool(item, request, options));
|
|
3334
3635
|
}
|
|
3335
3636
|
functionUsage.push(...results);
|
|
3336
|
-
const record2 =
|
|
3637
|
+
const record2 = isRecord9(response) ? response : {};
|
|
3337
3638
|
active = {
|
|
3338
3639
|
...active,
|
|
3339
3640
|
body: clean2({
|
|
@@ -3448,7 +3749,7 @@ async function* streamOpenAi(request, options, call) {
|
|
|
3448
3749
|
throw failure;
|
|
3449
3750
|
}
|
|
3450
3751
|
for await (const event of parseSse2(response)) {
|
|
3451
|
-
if (!
|
|
3752
|
+
if (!isRecord9(event)) continue;
|
|
3452
3753
|
if (event.type === "response.output_text.delta" && typeof event.delta === "string" && event.delta) {
|
|
3453
3754
|
text += event.delta;
|
|
3454
3755
|
yield { type: "stream.text.delta", requestId, data: { text: event.delta } };
|
|
@@ -3467,7 +3768,7 @@ async function* streamOpenAi(request, options, call) {
|
|
|
3467
3768
|
argumentsDelta: event.delta
|
|
3468
3769
|
}
|
|
3469
3770
|
};
|
|
3470
|
-
} else if (event.type === "response.completed" &&
|
|
3771
|
+
} else if (event.type === "response.completed" && isRecord9(event.response)) {
|
|
3471
3772
|
const usage = normalizeUsage2(event.response.usage);
|
|
3472
3773
|
if (usage) yield { type: "stream.usage", requestId, data: { usage } };
|
|
3473
3774
|
} else if (event.type === "error") {
|
|
@@ -3561,7 +3862,7 @@ function isConfigError2(code) {
|
|
|
3561
3862
|
}
|
|
3562
3863
|
function asTerminalError2(error) {
|
|
3563
3864
|
if (error instanceof AiDispatcherError && error.code === "PROVIDER_RETRYABLE") {
|
|
3564
|
-
const status =
|
|
3865
|
+
const status = isRecord9(error.details) ? error.details.status : void 0;
|
|
3565
3866
|
if (status === 429) return new AiDispatcherError("PROVIDER_RATE_LIMITED", error.message, error.details);
|
|
3566
3867
|
return new AiDispatcherError("PROVIDER_GATEWAY_UNREACHABLE", error.message, error.details);
|
|
3567
3868
|
}
|
|
@@ -3569,7 +3870,7 @@ function asTerminalError2(error) {
|
|
|
3569
3870
|
return new AiDispatcherError("PROVIDER_REQUEST_FAILED", error instanceof Error ? error.message : String(error));
|
|
3570
3871
|
}
|
|
3571
3872
|
function normalizeOpenAiResponse(params) {
|
|
3572
|
-
const record2 =
|
|
3873
|
+
const record2 = isRecord9(params.response) ? params.response : {};
|
|
3573
3874
|
const text = answerText2(record2);
|
|
3574
3875
|
const calls = params.functionTools ?? functionCalls(record2);
|
|
3575
3876
|
const usage = normalizeUsage2(record2.usage);
|
|
@@ -3596,9 +3897,9 @@ function answerText2(response) {
|
|
|
3596
3897
|
if (Array.isArray(output)) {
|
|
3597
3898
|
const parts = [];
|
|
3598
3899
|
for (const item of output) {
|
|
3599
|
-
if (!
|
|
3900
|
+
if (!isRecord9(item) || item.type === "reasoning" || item.type !== "message" || !Array.isArray(item.content)) continue;
|
|
3600
3901
|
for (const part of item.content) {
|
|
3601
|
-
if (
|
|
3902
|
+
if (isRecord9(part) && part.type === "output_text" && typeof part.text === "string") parts.push(part.text);
|
|
3602
3903
|
}
|
|
3603
3904
|
}
|
|
3604
3905
|
if (parts.length > 0) return parts.join("");
|
|
@@ -3609,7 +3910,7 @@ function functionCalls(response) {
|
|
|
3609
3910
|
if (!Array.isArray(response.output)) return [];
|
|
3610
3911
|
const calls = [];
|
|
3611
3912
|
for (const item of response.output) {
|
|
3612
|
-
if (!
|
|
3913
|
+
if (!isRecord9(item) || item.type !== "function_call") continue;
|
|
3613
3914
|
const name = typeof item.name === "string" ? item.name : "function";
|
|
3614
3915
|
const callId = typeof item.call_id === "string" ? item.call_id : name;
|
|
3615
3916
|
let args = item.arguments;
|
|
@@ -3641,7 +3942,7 @@ function toolUsage(calls) {
|
|
|
3641
3942
|
};
|
|
3642
3943
|
}
|
|
3643
3944
|
function normalizeUsage2(usage) {
|
|
3644
|
-
if (!
|
|
3945
|
+
if (!isRecord9(usage)) return void 0;
|
|
3645
3946
|
const inputTokens = numberValue2(usage.input_tokens);
|
|
3646
3947
|
const outputTokens = numberValue2(usage.output_tokens);
|
|
3647
3948
|
const totalTokens = numberValue2(usage.total_tokens) ?? (inputTokens !== void 0 || outputTokens !== void 0 ? (inputTokens ?? 0) + (outputTokens ?? 0) : void 0);
|
|
@@ -3693,16 +3994,16 @@ function modelOf2(compiled) {
|
|
|
3693
3994
|
return typeof compiled.body.model === "string" ? compiled.body.model : "";
|
|
3694
3995
|
}
|
|
3695
3996
|
function messageFrom2(body) {
|
|
3696
|
-
if (!
|
|
3997
|
+
if (!isRecord9(body)) return void 0;
|
|
3697
3998
|
if (typeof body.message === "string") return body.message;
|
|
3698
|
-
if (
|
|
3999
|
+
if (isRecord9(body.error) && typeof body.error.message === "string") return body.error.message;
|
|
3699
4000
|
return void 0;
|
|
3700
4001
|
}
|
|
3701
4002
|
function numberValue2(value) {
|
|
3702
4003
|
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
3703
4004
|
}
|
|
3704
4005
|
function attachProviderMetadata(body, request, packer) {
|
|
3705
|
-
const fromBody =
|
|
4006
|
+
const fromBody = isRecord9(body.metadata) ? body.metadata : void 0;
|
|
3706
4007
|
const packed = packProviderRecord2(request.metadata, request.agentId, fromBody, packer);
|
|
3707
4008
|
if (packed.wire) return { body: { ...body, metadata: packed.wire }, ...packed.warning ? { warning: packed.warning } : {} };
|
|
3708
4009
|
if (body.metadata === void 0) return { body, ...packed.warning ? { warning: packed.warning } : {} };
|
|
@@ -3776,7 +4077,7 @@ function readEnv3(name) {
|
|
|
3776
4077
|
if (typeof process === "undefined") return void 0;
|
|
3777
4078
|
return process.env[name];
|
|
3778
4079
|
}
|
|
3779
|
-
function
|
|
4080
|
+
function isRecord9(value) {
|
|
3780
4081
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3781
4082
|
}
|
|
3782
4083
|
|
|
@@ -3960,7 +4261,7 @@ function callOf(call) {
|
|
|
3960
4261
|
}
|
|
3961
4262
|
function attachCompileMeta(prepared, compiled) {
|
|
3962
4263
|
const record2 = compiled;
|
|
3963
|
-
const headers =
|
|
4264
|
+
const headers = isRecord10(record2.headers) ? redactHeaders(record2.headers) : void 0;
|
|
3964
4265
|
const inputResolution = prepared.inputTrack ? visibleInputResolution(prepared.inputTrack) : void 0;
|
|
3965
4266
|
return {
|
|
3966
4267
|
...record2,
|
|
@@ -3996,7 +4297,7 @@ function log(options, event, prepared, entrypoint, streaming) {
|
|
|
3996
4297
|
if (event.endsWith("compiled")) options.logger?.debug?.(event, payload);
|
|
3997
4298
|
else options.logger?.info?.(event, payload);
|
|
3998
4299
|
}
|
|
3999
|
-
function
|
|
4300
|
+
function isRecord10(value) {
|
|
4000
4301
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4001
4302
|
}
|
|
4002
4303
|
|