nexus-agents 10.2.0 → 11.0.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 +4 -1
- package/dist/{ast-rule-runner-RI7ZJ4ZI.js → ast-rule-runner-RL6XHXJB.js} +5 -5
- package/dist/{child-mcp-config-73BX4OTR.js → child-mcp-config-ADRNVJJB.js} +5 -5
- package/dist/{chunk-TDUXUVUU.js → chunk-3LE73MVE.js} +2 -2
- package/dist/{chunk-FNHVTDHZ.js → chunk-63YC42C2.js} +3 -3
- package/dist/{chunk-U37AITDA.js → chunk-6JMULY2R.js} +2 -2
- package/dist/{chunk-LP5ISXKM.js → chunk-6Y55UUWK.js} +5 -5
- package/dist/{chunk-QM5W3T3O.js → chunk-A7XALVN3.js} +2 -2
- package/dist/{chunk-JGY5HMWI.js → chunk-AX5DBV3M.js} +2 -2
- package/dist/{chunk-VLOPXV47.js → chunk-BHH3PKI6.js} +7 -7
- package/dist/{chunk-TW6PJYTP.js → chunk-C73VZSC5.js} +1 -1
- package/dist/chunk-C73VZSC5.js.map +1 -0
- package/dist/{chunk-LWOX65CP.js → chunk-CH6IBWXH.js} +31 -31
- package/dist/chunk-CH6IBWXH.js.map +1 -0
- package/dist/{chunk-RIYFVDYN.js → chunk-CSDGNGAG.js} +2 -2
- package/dist/{chunk-WD4DENPC.js → chunk-CXRZQ4NH.js} +3 -3
- package/dist/{chunk-SS53PZO6.js → chunk-DYV7XS26.js} +5 -5
- package/dist/{chunk-WKFPKPEM.js → chunk-EBOAFTOG.js} +458 -134
- package/dist/chunk-EBOAFTOG.js.map +1 -0
- package/dist/chunk-FMIALWCD.js +1046 -0
- package/dist/chunk-FMIALWCD.js.map +1 -0
- package/dist/{chunk-GAX75XCV.js → chunk-G2OI3KA4.js} +2 -2
- package/dist/{chunk-QG3VDSWD.js → chunk-GU2HV6KI.js} +3 -3
- package/dist/{chunk-2TA6KTRF.js → chunk-HBEZ2J4F.js} +16 -18
- package/dist/{chunk-2TA6KTRF.js.map → chunk-HBEZ2J4F.js.map} +1 -1
- package/dist/{chunk-QRC3QLUQ.js → chunk-HL3EHBKJ.js} +1086 -14
- package/dist/chunk-HL3EHBKJ.js.map +1 -0
- package/dist/{chunk-3UWT434E.js → chunk-I2THTVA4.js} +17 -10
- package/dist/chunk-I2THTVA4.js.map +1 -0
- package/dist/{chunk-OMSKBBL7.js → chunk-JKLXFENK.js} +18 -19
- package/dist/chunk-JKLXFENK.js.map +1 -0
- package/dist/{chunk-2DYCHHWW.js → chunk-KSSPY5KX.js} +4 -4
- package/dist/{chunk-23QA6GQD.js → chunk-LAUBKK25.js} +7 -7
- package/dist/{chunk-7EV3QAKO.js → chunk-MTB5BXYJ.js} +2 -2
- package/dist/{chunk-XSAUVC6D.js → chunk-NLFCAEEK.js} +2 -2
- package/dist/{chunk-PXYSAG5B.js → chunk-NVE262E3.js} +2 -2
- package/dist/{chunk-V26YQQK4.js → chunk-NY7IMAG5.js} +2 -2
- package/dist/{chunk-KLSNDPU6.js → chunk-NZA7EIZO.js} +17 -32
- package/dist/chunk-NZA7EIZO.js.map +1 -0
- package/dist/{chunk-XDUTAUK3.js → chunk-OKMSQJQJ.js} +75 -61
- package/dist/chunk-OKMSQJQJ.js.map +1 -0
- package/dist/{chunk-KASBBKAQ.js → chunk-OYAHRYFI.js} +54 -54
- package/dist/chunk-OYAHRYFI.js.map +1 -0
- package/dist/{chunk-GX5ZHZR2.js → chunk-PYAR3CVN.js} +7 -7
- package/dist/{chunk-EJ5EBTAV.js → chunk-QKWZZM2D.js} +2 -2
- package/dist/{chunk-FWQSOPBA.js → chunk-RR2Y2HVZ.js} +6 -6
- package/dist/{chunk-UE7A2XHM.js → chunk-RUHKJC3X.js} +2 -2
- package/dist/{chunk-D6E3LJGP.js → chunk-S4QYN2AV.js} +4 -4
- package/dist/{chunk-J44RKRGQ.js → chunk-TW4R2Q55.js} +4 -4
- package/dist/{chunk-QS5HGPCN.js → chunk-TWQEUAUG.js} +2 -2
- package/dist/{chunk-JPFRRNRR.js → chunk-U7HL7FGS.js} +2 -2
- package/dist/{chunk-JUUGLXSN.js → chunk-WAPGSEIM.js} +5 -5
- package/dist/{chunk-LXYT2P2Y.js → chunk-WILZPMEM.js} +3 -3
- package/dist/{chunk-4JJI34RV.js → chunk-WTMLF7QR.js} +3 -3
- package/dist/{chunk-SX2XWCGA.js → chunk-YIZ25Y4C.js} +22 -7
- package/dist/chunk-YIZ25Y4C.js.map +1 -0
- package/dist/{cli-auth-probe-A7ANEHJ7.js → cli-auth-probe-GUK3NXW3.js} +2 -2
- package/dist/{cli-circuit-breaker-62YOQQT3.js → cli-circuit-breaker-CDJKHR7R.js} +5 -5
- package/dist/{cli-readiness-O6EOQV4L.js → cli-readiness-7I5BYWLA.js} +9 -9
- package/dist/cli-server-gateway-626TKNQJ.js +34 -0
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +81 -1216
- package/dist/cli.js.map +1 -1
- package/dist/{codebase-search-VMKI7FW4.js → codebase-search-YVO7BC33.js} +2 -2
- package/dist/{composite-router-YPZ3D5Y6.js → composite-router-YWSL4Y62.js} +4 -4
- package/dist/{consensus-vote-RNQQUBXO.js → consensus-vote-IRD5B3SC.js} +21 -22
- package/dist/{consensus-vote-types-DexdhOdB.d.ts → consensus-vote-types-C8RWaoxp.d.ts} +9 -8
- package/dist/{context-retriever-HVPLM6DH.js → context-retriever-CBOMGQAP.js} +11 -11
- package/dist/{doctor-deep-UZQTD65D.js → doctor-deep-2N3BHH6I.js} +5 -5
- package/dist/doctor-gateway-report-MRPZ7S34.js +20 -0
- package/dist/{doctor-live-QFLT5SDB.js → doctor-live-JBXIFI7A.js} +18 -16
- package/dist/doctor-live-JBXIFI7A.js.map +1 -0
- package/dist/{expert-bridge-O3UZXLGB.js → expert-bridge-TOMOJTMC.js} +6 -6
- package/dist/factory-H6IIGGFG.js +31 -0
- package/dist/factory-OLT24RLU.js +17 -0
- package/dist/{improvement-review-7IABFAU3.js → improvement-review-GFIINOQR.js} +8 -8
- package/dist/index.d.ts +69 -77
- package/dist/index.js +66 -57
- package/dist/index.js.map +1 -1
- package/dist/{init-opencode-RYPBCM4P.js → init-opencode-HXXKEIQF.js} +7 -7
- package/dist/issue-triage-ENNKQYKQ.js +20 -0
- package/dist/{learning-persistence-FB4U5AX2.js → learning-persistence-X24OOBYY.js} +3 -3
- package/dist/{model-config-helpers-QNV3KD2W.js → model-config-helpers-QFWX2QAO.js} +4 -4
- package/dist/{openai-compat-adapter-GPZDIR3D.js → openai-compat-adapter-N5WWPBGN.js} +7 -7
- package/dist/{outcome-store-adapter-WRONSTUD.js → outcome-store-adapter-Y6MS4JJK.js} +4 -4
- package/dist/{pr-reviewer-helpers-7SMNNDFJ.js → pr-reviewer-helpers-I6XFNU74.js} +6 -6
- package/dist/{registry-command-U7K6HIBK.js → registry-command-W7UHEQ6D.js} +4 -4
- package/dist/{repo-security-plan-LFWLVEL2.js → repo-security-plan-MENT6MS6.js} +5 -5
- package/dist/research-helpers-synthesize-BX4W3OA7.js +16 -0
- package/dist/{routing-memory-OCIVXKOU.js → routing-memory-7VHOAFNA.js} +4 -4
- package/dist/{session-memory-4LMEWO3X.js → session-memory-3EYP3GNQ.js} +5 -5
- package/dist/setup-config-VN2IOJ7S.js +13 -0
- package/dist/{setup-custom-api-QEPUCHOX.js → setup-custom-api-U3IGIJI7.js} +6 -6
- package/dist/setup-data-dir-UWOXXYFS.js +34 -0
- package/dist/{tool-memory-EFGFXF65.js → tool-memory-YYFE4EXT.js} +8 -8
- package/dist/{tool-memory-registry-adapters-FO6JVQSX.js → tool-memory-registry-adapters-IIORYBCC.js} +3 -3
- package/dist/unified-registry-IEPJHJHO.js +35 -0
- package/dist/{weather-report-PMYQ3WBW.js → weather-report-PJZFHSB7.js} +4 -4
- package/dist/weather-report-PJZFHSB7.js.map +1 -0
- package/node_modules/express-rate-limit/dist/index.cjs +9 -7
- package/node_modules/express-rate-limit/dist/index.mjs +9 -7
- package/node_modules/express-rate-limit/package.json +9 -9
- package/package.json +1 -1
- package/dist/chunk-3UWT434E.js.map +0 -1
- package/dist/chunk-KASBBKAQ.js.map +0 -1
- package/dist/chunk-KLSNDPU6.js.map +0 -1
- package/dist/chunk-LWOX65CP.js.map +0 -1
- package/dist/chunk-OMSKBBL7.js.map +0 -1
- package/dist/chunk-QRC3QLUQ.js.map +0 -1
- package/dist/chunk-SX2XWCGA.js.map +0 -1
- package/dist/chunk-TW6PJYTP.js.map +0 -1
- package/dist/chunk-UZJ6IPJR.js +0 -1057
- package/dist/chunk-UZJ6IPJR.js.map +0 -1
- package/dist/chunk-WKFPKPEM.js.map +0 -1
- package/dist/chunk-XDUTAUK3.js.map +0 -1
- package/dist/doctor-gateway-report-LRBPPJD4.js +0 -20
- package/dist/doctor-live-QFLT5SDB.js.map +0 -1
- package/dist/factory-KCKQQAEH.js +0 -31
- package/dist/factory-LUKUIB6C.js +0 -17
- package/dist/issue-triage-YBVJVAUU.js +0 -20
- package/dist/research-helpers-synthesize-X6MVAAKT.js +0 -16
- package/dist/setup-config-YNNNR4AE.js +0 -13
- package/dist/setup-data-dir-XM5DWH7R.js +0 -35
- package/dist/unified-registry-KLNC24HA.js +0 -36
- /package/dist/{ast-rule-runner-RI7ZJ4ZI.js.map → ast-rule-runner-RL6XHXJB.js.map} +0 -0
- /package/dist/{child-mcp-config-73BX4OTR.js.map → child-mcp-config-ADRNVJJB.js.map} +0 -0
- /package/dist/{chunk-TDUXUVUU.js.map → chunk-3LE73MVE.js.map} +0 -0
- /package/dist/{chunk-FNHVTDHZ.js.map → chunk-63YC42C2.js.map} +0 -0
- /package/dist/{chunk-U37AITDA.js.map → chunk-6JMULY2R.js.map} +0 -0
- /package/dist/{chunk-LP5ISXKM.js.map → chunk-6Y55UUWK.js.map} +0 -0
- /package/dist/{chunk-QM5W3T3O.js.map → chunk-A7XALVN3.js.map} +0 -0
- /package/dist/{chunk-JGY5HMWI.js.map → chunk-AX5DBV3M.js.map} +0 -0
- /package/dist/{chunk-VLOPXV47.js.map → chunk-BHH3PKI6.js.map} +0 -0
- /package/dist/{chunk-RIYFVDYN.js.map → chunk-CSDGNGAG.js.map} +0 -0
- /package/dist/{chunk-WD4DENPC.js.map → chunk-CXRZQ4NH.js.map} +0 -0
- /package/dist/{chunk-SS53PZO6.js.map → chunk-DYV7XS26.js.map} +0 -0
- /package/dist/{chunk-GAX75XCV.js.map → chunk-G2OI3KA4.js.map} +0 -0
- /package/dist/{chunk-QG3VDSWD.js.map → chunk-GU2HV6KI.js.map} +0 -0
- /package/dist/{chunk-2DYCHHWW.js.map → chunk-KSSPY5KX.js.map} +0 -0
- /package/dist/{chunk-23QA6GQD.js.map → chunk-LAUBKK25.js.map} +0 -0
- /package/dist/{chunk-7EV3QAKO.js.map → chunk-MTB5BXYJ.js.map} +0 -0
- /package/dist/{chunk-XSAUVC6D.js.map → chunk-NLFCAEEK.js.map} +0 -0
- /package/dist/{chunk-PXYSAG5B.js.map → chunk-NVE262E3.js.map} +0 -0
- /package/dist/{chunk-V26YQQK4.js.map → chunk-NY7IMAG5.js.map} +0 -0
- /package/dist/{chunk-GX5ZHZR2.js.map → chunk-PYAR3CVN.js.map} +0 -0
- /package/dist/{chunk-EJ5EBTAV.js.map → chunk-QKWZZM2D.js.map} +0 -0
- /package/dist/{chunk-FWQSOPBA.js.map → chunk-RR2Y2HVZ.js.map} +0 -0
- /package/dist/{chunk-UE7A2XHM.js.map → chunk-RUHKJC3X.js.map} +0 -0
- /package/dist/{chunk-D6E3LJGP.js.map → chunk-S4QYN2AV.js.map} +0 -0
- /package/dist/{chunk-J44RKRGQ.js.map → chunk-TW4R2Q55.js.map} +0 -0
- /package/dist/{chunk-QS5HGPCN.js.map → chunk-TWQEUAUG.js.map} +0 -0
- /package/dist/{chunk-JPFRRNRR.js.map → chunk-U7HL7FGS.js.map} +0 -0
- /package/dist/{chunk-JUUGLXSN.js.map → chunk-WAPGSEIM.js.map} +0 -0
- /package/dist/{chunk-LXYT2P2Y.js.map → chunk-WILZPMEM.js.map} +0 -0
- /package/dist/{chunk-4JJI34RV.js.map → chunk-WTMLF7QR.js.map} +0 -0
- /package/dist/{cli-auth-probe-A7ANEHJ7.js.map → cli-auth-probe-GUK3NXW3.js.map} +0 -0
- /package/dist/{cli-circuit-breaker-62YOQQT3.js.map → cli-circuit-breaker-CDJKHR7R.js.map} +0 -0
- /package/dist/{cli-readiness-O6EOQV4L.js.map → cli-readiness-7I5BYWLA.js.map} +0 -0
- /package/dist/{codebase-search-VMKI7FW4.js.map → cli-server-gateway-626TKNQJ.js.map} +0 -0
- /package/dist/{composite-router-YPZ3D5Y6.js.map → codebase-search-YVO7BC33.js.map} +0 -0
- /package/dist/{consensus-vote-RNQQUBXO.js.map → composite-router-YWSL4Y62.js.map} +0 -0
- /package/dist/{context-retriever-HVPLM6DH.js.map → consensus-vote-IRD5B3SC.js.map} +0 -0
- /package/dist/{doctor-deep-UZQTD65D.js.map → context-retriever-CBOMGQAP.js.map} +0 -0
- /package/dist/{doctor-gateway-report-LRBPPJD4.js.map → doctor-deep-2N3BHH6I.js.map} +0 -0
- /package/dist/{expert-bridge-O3UZXLGB.js.map → doctor-gateway-report-MRPZ7S34.js.map} +0 -0
- /package/dist/{factory-KCKQQAEH.js.map → expert-bridge-TOMOJTMC.js.map} +0 -0
- /package/dist/{factory-LUKUIB6C.js.map → factory-H6IIGGFG.js.map} +0 -0
- /package/dist/{improvement-review-7IABFAU3.js.map → factory-OLT24RLU.js.map} +0 -0
- /package/dist/{issue-triage-YBVJVAUU.js.map → improvement-review-GFIINOQR.js.map} +0 -0
- /package/dist/{init-opencode-RYPBCM4P.js.map → init-opencode-HXXKEIQF.js.map} +0 -0
- /package/dist/{learning-persistence-FB4U5AX2.js.map → issue-triage-ENNKQYKQ.js.map} +0 -0
- /package/dist/{model-config-helpers-QNV3KD2W.js.map → learning-persistence-X24OOBYY.js.map} +0 -0
- /package/dist/{openai-compat-adapter-GPZDIR3D.js.map → model-config-helpers-QFWX2QAO.js.map} +0 -0
- /package/dist/{pr-reviewer-helpers-7SMNNDFJ.js.map → openai-compat-adapter-N5WWPBGN.js.map} +0 -0
- /package/dist/{outcome-store-adapter-WRONSTUD.js.map → outcome-store-adapter-Y6MS4JJK.js.map} +0 -0
- /package/dist/{repo-security-plan-LFWLVEL2.js.map → pr-reviewer-helpers-I6XFNU74.js.map} +0 -0
- /package/dist/{registry-command-U7K6HIBK.js.map → registry-command-W7UHEQ6D.js.map} +0 -0
- /package/dist/{research-helpers-synthesize-X6MVAAKT.js.map → repo-security-plan-MENT6MS6.js.map} +0 -0
- /package/dist/{routing-memory-OCIVXKOU.js.map → research-helpers-synthesize-BX4W3OA7.js.map} +0 -0
- /package/dist/{session-memory-4LMEWO3X.js.map → routing-memory-7VHOAFNA.js.map} +0 -0
- /package/dist/{setup-config-YNNNR4AE.js.map → session-memory-3EYP3GNQ.js.map} +0 -0
- /package/dist/{setup-data-dir-XM5DWH7R.js.map → setup-config-VN2IOJ7S.js.map} +0 -0
- /package/dist/{setup-custom-api-QEPUCHOX.js.map → setup-custom-api-U3IGIJI7.js.map} +0 -0
- /package/dist/{tool-memory-EFGFXF65.js.map → setup-data-dir-UWOXXYFS.js.map} +0 -0
- /package/dist/{tool-memory-registry-adapters-FO6JVQSX.js.map → tool-memory-YYFE4EXT.js.map} +0 -0
- /package/dist/{unified-registry-KLNC24HA.js.map → tool-memory-registry-adapters-IIORYBCC.js.map} +0 -0
- /package/dist/{weather-report-PMYQ3WBW.js.map → unified-registry-IEPJHJHO.js.map} +0 -0
|
@@ -7,13 +7,13 @@ import {
|
|
|
7
7
|
getModelSelectionShadowFile,
|
|
8
8
|
isPersistenceEnabled,
|
|
9
9
|
isStrategyDistillationEnabled
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-RUHKJC3X.js";
|
|
11
11
|
import {
|
|
12
12
|
findRepoRoot,
|
|
13
13
|
getNexusDataDir,
|
|
14
14
|
nexusDataPath,
|
|
15
15
|
parseBoolEnv
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-CH6IBWXH.js";
|
|
17
17
|
import {
|
|
18
18
|
CLI_NAMES,
|
|
19
19
|
CliNameSchema,
|
|
@@ -2182,13 +2182,13 @@ function lookupCanonicalPricing(model) {
|
|
|
2182
2182
|
const entry2 = registry.getEntry(matched.id);
|
|
2183
2183
|
return {
|
|
2184
2184
|
pricing: toPricing(matched.pricing),
|
|
2185
|
-
source: entry2.pricing === void 0 ? "in-tree" : entry2
|
|
2185
|
+
source: entry2.pricing === void 0 ? "in-tree" : pricingSourceOf(entry2)
|
|
2186
2186
|
};
|
|
2187
2187
|
}
|
|
2188
2188
|
const entry = registry.getEntry(model);
|
|
2189
2189
|
return {
|
|
2190
2190
|
pricing: toPricing(entry.pricing),
|
|
2191
|
-
source: registry.getEntry(entry.resolvedFrom ?? entry.id)
|
|
2191
|
+
source: pricingSourceOf(registry.getEntry(entry.resolvedFrom ?? entry.id))
|
|
2192
2192
|
};
|
|
2193
2193
|
}
|
|
2194
2194
|
function calculateCost(model, inputTokens, outputTokens) {
|
|
@@ -4928,9 +4928,14 @@ function routingArmDisplaySlot(armId) {
|
|
|
4928
4928
|
case "api:custom-openai":
|
|
4929
4929
|
return "opencode";
|
|
4930
4930
|
default:
|
|
4931
|
-
return armId
|
|
4931
|
+
return armId;
|
|
4932
4932
|
}
|
|
4933
4933
|
}
|
|
4934
|
+
function routingArmCliSlot(armId) {
|
|
4935
|
+
if (isCliName(armId)) return armId;
|
|
4936
|
+
const parsed = ApiArmIdSchema.safeParse(armId);
|
|
4937
|
+
return parsed.success ? routingArmDisplaySlot(parsed.data) : void 0;
|
|
4938
|
+
}
|
|
4934
4939
|
var API_ENDPOINT_ID_PATTERN = /^[a-z0-9][a-z0-9._-]{0,63}$/;
|
|
4935
4940
|
var EndpointArmIdSchema = z3.templateLiteral([
|
|
4936
4941
|
"api:",
|
|
@@ -4941,7 +4946,7 @@ function isEndpointArmId(value) {
|
|
|
4941
4946
|
}
|
|
4942
4947
|
var UNKNOWN_ENDPOINT_ARM_DISPLAY_SLOT = "opencode";
|
|
4943
4948
|
function observedArmDisplaySlot(armId) {
|
|
4944
|
-
return
|
|
4949
|
+
return routingArmCliSlot(armId) ?? UNKNOWN_ENDPOINT_ARM_DISPLAY_SLOT;
|
|
4945
4950
|
}
|
|
4946
4951
|
|
|
4947
4952
|
// src/cli-adapters/types-capability.ts
|
|
@@ -4974,6 +4979,9 @@ var CLI_VERSION_REQUIREMENTS = {
|
|
|
4974
4979
|
var DEFAULT_CAPABILITIES = buildCliCapabilityProfiles();
|
|
4975
4980
|
|
|
4976
4981
|
// src/learning/routing-decision-mappers.ts
|
|
4982
|
+
function recordedArm(armId) {
|
|
4983
|
+
return routingArmCliSlot(armId) ?? armId;
|
|
4984
|
+
}
|
|
4977
4985
|
function mapFeedbackRoutingDecision(decision, context) {
|
|
4978
4986
|
return {
|
|
4979
4987
|
id: context.id,
|
|
@@ -4982,9 +4990,9 @@ function mapFeedbackRoutingDecision(decision, context) {
|
|
|
4982
4990
|
routerType: context.routerType,
|
|
4983
4991
|
routerTypeMeasured: context.routerTypeMeasured,
|
|
4984
4992
|
query: context.query ?? "",
|
|
4985
|
-
selectedModel:
|
|
4993
|
+
selectedModel: recordedArm(decision.cliName),
|
|
4986
4994
|
confidence: decision.confidence,
|
|
4987
|
-
selectedTier: decision.preferenceTier
|
|
4995
|
+
selectedTier: routingArmCliSlot(decision.cliName) === void 0 ? void 0 : decision.preferenceTier
|
|
4988
4996
|
};
|
|
4989
4997
|
}
|
|
4990
4998
|
function mapObserverRoutingDecision(decision, context) {
|
|
@@ -4992,10 +5000,10 @@ function mapObserverRoutingDecision(decision, context) {
|
|
|
4992
5000
|
timestamp: context.timestamp,
|
|
4993
5001
|
taskId: context.taskId,
|
|
4994
5002
|
taskDescription: context.query.length > 100 ? context.query.substring(0, 100) + "..." : context.query,
|
|
4995
|
-
selectedCli:
|
|
5003
|
+
selectedCli: recordedArm(decision.cliName),
|
|
4996
5004
|
confidence: decision.confidence,
|
|
4997
5005
|
reason: decision.reason,
|
|
4998
|
-
alternatives: decision.alternatives.map(
|
|
5006
|
+
alternatives: decision.alternatives.map(recordedArm),
|
|
4999
5007
|
stagesExecuted: decision.stagesExecuted,
|
|
5000
5008
|
decisionTimeMs: decision.decisionTimeMs,
|
|
5001
5009
|
withinBudget: decision.withinBudget,
|
|
@@ -5011,8 +5019,8 @@ function mapStoredRoutingDecision(decision, context) {
|
|
|
5011
5019
|
timestamp: context.timestamp,
|
|
5012
5020
|
routerType: context.routerType,
|
|
5013
5021
|
routerTypeMeasured: context.routerTypeMeasured,
|
|
5014
|
-
selectedModel:
|
|
5015
|
-
alternativeModels: decision.alternatives.map(
|
|
5022
|
+
selectedModel: recordedArm(decision.cliName),
|
|
5023
|
+
alternativeModels: decision.alternatives.map(recordedArm),
|
|
5016
5024
|
confidence: decision.confidence,
|
|
5017
5025
|
reason: decision.reason,
|
|
5018
5026
|
taskProfile: {
|
|
@@ -5803,7 +5811,7 @@ function computeCostDetail(modelId, inputTokens, outputTokens) {
|
|
|
5803
5811
|
return {
|
|
5804
5812
|
costUsd: roundToMicroUsd(costUsd),
|
|
5805
5813
|
priced: true,
|
|
5806
|
-
...getDefaultRegistry().getEntry(entry.resolvedFrom ?? entry.id)
|
|
5814
|
+
...pricingSourceOf(getDefaultRegistry().getEntry(entry.resolvedFrom ?? entry.id)) === "manifest" ? { declared: true } : {},
|
|
5807
5815
|
resolvedId,
|
|
5808
5816
|
...provenance,
|
|
5809
5817
|
...entry.pricingProvenance !== void 0 ? { pricingProvenance: entry.pricingProvenance } : {}
|
|
@@ -6060,7 +6068,7 @@ function adapterReadiness(adapter, options) {
|
|
|
6060
6068
|
const ceiling = resolveClassGuardMs("interactive");
|
|
6061
6069
|
const requested = options.timeoutMs ?? ceiling;
|
|
6062
6070
|
const timeoutMs = Number.isFinite(requested) && requested > 0 ? Math.min(requested, ceiling) : ceiling;
|
|
6063
|
-
const flight = import("./cli-readiness-
|
|
6071
|
+
const flight = import("./cli-readiness-7I5BYWLA.js").then(({ probeServes }) => probeServes(adapter, timeoutMs)).finally(() => readinessFlights.delete(adapter));
|
|
6064
6072
|
readinessFlights.set(adapter, flight);
|
|
6065
6073
|
return flight;
|
|
6066
6074
|
}
|
|
@@ -6070,7 +6078,7 @@ async function servesListedModel(adapter, modelId, cli) {
|
|
|
6070
6078
|
const models = await adapter.listModels();
|
|
6071
6079
|
if (models.length === 0) return "unknown";
|
|
6072
6080
|
const requestedKey = canonicalModelKey(modelId);
|
|
6073
|
-
const findCanonicalModel2 = cli === "codex" ? (await import("./model-config-helpers-
|
|
6081
|
+
const findCanonicalModel2 = cli === "codex" ? (await import("./model-config-helpers-QFWX2QAO.js")).findCanonicalModel : void 0;
|
|
6074
6082
|
const requestedEntry = requestedKey === null ? findCanonicalModel2?.("codex", modelId) : void 0;
|
|
6075
6083
|
const listed = models.some((model) => {
|
|
6076
6084
|
const listedEntry = findCanonicalModel2?.("codex", model.id);
|
|
@@ -6715,6 +6723,9 @@ var DEFAULT_REQUEST_LIMITS = {
|
|
|
6715
6723
|
};
|
|
6716
6724
|
var RATE_LIMIT_WINDOW_MS = 6e4;
|
|
6717
6725
|
function getDefaultConfig(cli) {
|
|
6726
|
+
if (!isCliName(cli)) {
|
|
6727
|
+
return { tokenLimit: Infinity, requestLimit: Infinity, windowMs: RATE_LIMIT_WINDOW_MS };
|
|
6728
|
+
}
|
|
6718
6729
|
const envPrefix = `NEXUS_${cli.toUpperCase()}`;
|
|
6719
6730
|
const tokenEnv = process.env[`${envPrefix}_TOKEN_LIMIT`];
|
|
6720
6731
|
const requestEnv = process.env[`${envPrefix}_REQUEST_LIMIT`];
|
|
@@ -7364,6 +7375,237 @@ function mapModelErrorToCategory(error) {
|
|
|
7364
7375
|
}
|
|
7365
7376
|
}
|
|
7366
7377
|
|
|
7378
|
+
// src/adapters/sdk/gateway-catalog.ts
|
|
7379
|
+
var catalogs = /* @__PURE__ */ new Map();
|
|
7380
|
+
var owners = /* @__PURE__ */ new Map();
|
|
7381
|
+
function retainGatewayCatalog(arm, owner) {
|
|
7382
|
+
let retained = owners.get(arm);
|
|
7383
|
+
if (retained === void 0) {
|
|
7384
|
+
retained = /* @__PURE__ */ new Set();
|
|
7385
|
+
owners.set(arm, retained);
|
|
7386
|
+
}
|
|
7387
|
+
retained.add(owner);
|
|
7388
|
+
}
|
|
7389
|
+
function releaseGatewayCatalog(arm, owner) {
|
|
7390
|
+
const retained = owners.get(arm);
|
|
7391
|
+
if (retained?.delete(owner) !== true) return;
|
|
7392
|
+
if (retained.size > 0) return;
|
|
7393
|
+
owners.delete(arm);
|
|
7394
|
+
clearGatewayCatalog(arm);
|
|
7395
|
+
}
|
|
7396
|
+
function setGatewayCatalog(arm, modelIds) {
|
|
7397
|
+
if (modelIds.length === 0) {
|
|
7398
|
+
throw new Error(
|
|
7399
|
+
`Gateway catalogue for ${arm} is empty; an arm with no model is not registrable`
|
|
7400
|
+
);
|
|
7401
|
+
}
|
|
7402
|
+
catalogs.set(arm, [...modelIds]);
|
|
7403
|
+
}
|
|
7404
|
+
function getGatewayCatalog(arm) {
|
|
7405
|
+
return catalogs.get(arm);
|
|
7406
|
+
}
|
|
7407
|
+
function clearGatewayCatalog(arm) {
|
|
7408
|
+
catalogs.delete(arm);
|
|
7409
|
+
}
|
|
7410
|
+
|
|
7411
|
+
// src/adapters/gateway-arm-adapter.ts
|
|
7412
|
+
function createGatewayArmAdapter(armId, models, deps) {
|
|
7413
|
+
if (models.length === 0) {
|
|
7414
|
+
throw new ConfigError(`Gateway arm ${armId} has no models; nothing to register`);
|
|
7415
|
+
}
|
|
7416
|
+
return new GatewayArmAdapter(armId, models, deps);
|
|
7417
|
+
}
|
|
7418
|
+
function ownsGatewayCircuitAdmission(adapter, armId, registry) {
|
|
7419
|
+
return adapter instanceof GatewayArmAdapter && adapter.gatewayArm === armId && adapter.getCircuitBreakerRegistry() === registry;
|
|
7420
|
+
}
|
|
7421
|
+
var GatewayArmAdapter = class {
|
|
7422
|
+
constructor(armId, models, deps) {
|
|
7423
|
+
this.armId = armId;
|
|
7424
|
+
this.models = models;
|
|
7425
|
+
this.deps = deps;
|
|
7426
|
+
retainGatewayCatalog(armId, this);
|
|
7427
|
+
}
|
|
7428
|
+
armId;
|
|
7429
|
+
models;
|
|
7430
|
+
deps;
|
|
7431
|
+
selectedAt = /* @__PURE__ */ new Date();
|
|
7432
|
+
resolvedDelegate;
|
|
7433
|
+
/**
|
|
7434
|
+
* The gateway-arm marker (#4392 step 4, `isGatewayModelAdapter`): a
|
|
7435
|
+
* telemetry writer that is handed this wrapper prices its calls by the
|
|
7436
|
+
* arm's `NEXUS_GATEWAY_COST` declaration, never the delegate's list price.
|
|
7437
|
+
*/
|
|
7438
|
+
get gatewayArm() {
|
|
7439
|
+
return this.armId;
|
|
7440
|
+
}
|
|
7441
|
+
// --- IModelAdapter (forwarded to the delegate) ---
|
|
7442
|
+
get providerId() {
|
|
7443
|
+
return this.requireDelegate().providerId;
|
|
7444
|
+
}
|
|
7445
|
+
get modelId() {
|
|
7446
|
+
return this.requireDelegate().modelId;
|
|
7447
|
+
}
|
|
7448
|
+
get capabilities() {
|
|
7449
|
+
return this.requireDelegate().capabilities;
|
|
7450
|
+
}
|
|
7451
|
+
/**
|
|
7452
|
+
* Both halves of the breaker contract, as `base-adapter.ts` records them
|
|
7453
|
+
* for the CLI slots on the same shared registry. The success half matters
|
|
7454
|
+
* (#6403 review): in the closed state `recordSuccess` zeroes the failure
|
|
7455
|
+
* count, which is what makes the threshold mean CONSECUTIVE failures, and
|
|
7456
|
+
* in half-open it is what closes the circuit again. Without it a long-lived
|
|
7457
|
+
* process counted scattered blips for its whole lifetime and, once open,
|
|
7458
|
+
* sat half-open forever with any single error re-opening it.
|
|
7459
|
+
*/
|
|
7460
|
+
async complete(request) {
|
|
7461
|
+
const resolved = this.resolveDelegate();
|
|
7462
|
+
if (!resolved.ok) {
|
|
7463
|
+
return err(new ModelError(resolved.error.message, { code: ErrorCode.MODEL_UNAVAILABLE }));
|
|
7464
|
+
}
|
|
7465
|
+
const delegate = resolved.value;
|
|
7466
|
+
const breaker = this.deps.circuitBreakerRegistry.getArmBreaker(this.armId);
|
|
7467
|
+
const admission = breaker.canExecute();
|
|
7468
|
+
if (!admission.ok) {
|
|
7469
|
+
return err(
|
|
7470
|
+
new ModelError(admission.error.message, {
|
|
7471
|
+
code: ErrorCode.MODEL_UNAVAILABLE,
|
|
7472
|
+
cause: admission.error,
|
|
7473
|
+
retryable: false
|
|
7474
|
+
})
|
|
7475
|
+
);
|
|
7476
|
+
}
|
|
7477
|
+
const result = await delegate.complete(request);
|
|
7478
|
+
if (result.ok) {
|
|
7479
|
+
breaker.recordSuccess();
|
|
7480
|
+
} else if (isCallerCancelled(result.error)) {
|
|
7481
|
+
breaker.releaseHalfOpenProbe();
|
|
7482
|
+
} else {
|
|
7483
|
+
this.recordFailure(result.error, delegate.providerId);
|
|
7484
|
+
}
|
|
7485
|
+
return result;
|
|
7486
|
+
}
|
|
7487
|
+
stream(request) {
|
|
7488
|
+
return this.requireDelegate().stream(request);
|
|
7489
|
+
}
|
|
7490
|
+
countTokens(text) {
|
|
7491
|
+
return this.requireDelegate().countTokens(text);
|
|
7492
|
+
}
|
|
7493
|
+
validateConfig() {
|
|
7494
|
+
const resolved = this.resolveDelegate();
|
|
7495
|
+
return resolved.ok ? resolved.value.validateConfig() : resolved;
|
|
7496
|
+
}
|
|
7497
|
+
/** The whole catalogue, not the delegate alone — that is what the arm fronts. */
|
|
7498
|
+
listModels() {
|
|
7499
|
+
return Promise.resolve(this.models.map((m) => ({ id: m.modelId })));
|
|
7500
|
+
}
|
|
7501
|
+
// --- IResilientAdapter ---
|
|
7502
|
+
/**
|
|
7503
|
+
* `source: 'api'` always; `degraded` while the arm's breaker is open. There
|
|
7504
|
+
* is no `unavailable`: the arm exists only once discovery succeeded.
|
|
7505
|
+
*/
|
|
7506
|
+
getHealth() {
|
|
7507
|
+
return {
|
|
7508
|
+
source: "api",
|
|
7509
|
+
state: this.deps.circuitBreakerRegistry.isArmOpen(this.armId) ? "degraded" : "healthy",
|
|
7510
|
+
selectedAt: this.selectedAt,
|
|
7511
|
+
failoverCount: 0
|
|
7512
|
+
};
|
|
7513
|
+
}
|
|
7514
|
+
/** Nothing to re-detect: the catalogue is fixed at registration. */
|
|
7515
|
+
refresh() {
|
|
7516
|
+
return Promise.resolve();
|
|
7517
|
+
}
|
|
7518
|
+
/** A gateway arm has no CLI to prefer; said at debug so a caller can see it was ignored. */
|
|
7519
|
+
setPreferredCli(cli) {
|
|
7520
|
+
this.deps.logger.debug("setPreferredCli ignored on a gateway arm", { arm: this.armId, cli });
|
|
7521
|
+
}
|
|
7522
|
+
/** The arm never fails over, so the callback is never invoked. */
|
|
7523
|
+
onFailover() {
|
|
7524
|
+
return () => void 0;
|
|
7525
|
+
}
|
|
7526
|
+
getCircuitBreakerRegistry() {
|
|
7527
|
+
return this.deps.circuitBreakerRegistry;
|
|
7528
|
+
}
|
|
7529
|
+
/**
|
|
7530
|
+
* No listeners or timers are held; the breaker outlives the arm on purpose
|
|
7531
|
+
* (a re-registered gateway keeps its failure history). The shared catalogue
|
|
7532
|
+
* stays while any registry owns a live wrapper for this endpoint. Repeated
|
|
7533
|
+
* disposal is harmless, and a wrapper retained before replacement prevents
|
|
7534
|
+
* disposal of the earlier wrapper from clearing the endpoint's metadata.
|
|
7535
|
+
*/
|
|
7536
|
+
dispose() {
|
|
7537
|
+
releaseGatewayCatalog(this.armId, this);
|
|
7538
|
+
}
|
|
7539
|
+
// --- Private ---
|
|
7540
|
+
/** Resolve lazily after bootstrap, and pin a successful default to this arm. */
|
|
7541
|
+
resolveDelegate() {
|
|
7542
|
+
if (this.resolvedDelegate !== void 0) return ok(this.resolvedDelegate);
|
|
7543
|
+
const resolved = resolveGatewayDefault(process.env, this.deps.logger);
|
|
7544
|
+
if (resolved.kind !== "resolved") {
|
|
7545
|
+
return err(new ConfigError(`Gateway arm ${this.armId} has no chat default`));
|
|
7546
|
+
}
|
|
7547
|
+
const delegate = this.models.find((model) => model === resolved.adapter);
|
|
7548
|
+
if (delegate === void 0) {
|
|
7549
|
+
return err(new ConfigError(`Gateway default does not belong to arm ${this.armId}`));
|
|
7550
|
+
}
|
|
7551
|
+
this.resolvedDelegate = delegate;
|
|
7552
|
+
return ok(delegate);
|
|
7553
|
+
}
|
|
7554
|
+
/** Metadata and streaming interfaces cannot carry a Result error. */
|
|
7555
|
+
requireDelegate() {
|
|
7556
|
+
const resolved = this.resolveDelegate();
|
|
7557
|
+
if (!resolved.ok) throw resolved.error;
|
|
7558
|
+
return resolved.value;
|
|
7559
|
+
}
|
|
7560
|
+
/**
|
|
7561
|
+
* `ResilientAdapter.recordBreakerFailure`, keyed on the ARM (#3423, #5359):
|
|
7562
|
+
* a transient rate limit is recorded by the telemetry branch and exempt from
|
|
7563
|
+
* the breaker (it would double-count, and open a breaker on a condition that
|
|
7564
|
+
* clears within the minute); a DURABLE capacity cap is counted even though it
|
|
7565
|
+
* is rate-limit-shaped, because it never clears; everything else counts.
|
|
7566
|
+
* Every rate-limit-shaped failure, durable or not, is a telemetry event.
|
|
7567
|
+
*/
|
|
7568
|
+
recordFailure(error, provider) {
|
|
7569
|
+
const breaker = this.deps.circuitBreakerRegistry.getArmBreaker(this.armId);
|
|
7570
|
+
const category = mapModelErrorToCategory(error);
|
|
7571
|
+
const rateLimitLike = category === "rate_limit" || isRateLimitLikeError(error);
|
|
7572
|
+
if (rateLimitLike) this.recordRateLimit(error, provider);
|
|
7573
|
+
if (isDurableCapacityError(error)) {
|
|
7574
|
+
breaker.recordFailure(category);
|
|
7575
|
+
this.deps.logger.warn("Durable capacity cap recorded to gateway arm breaker", {
|
|
7576
|
+
arm: this.armId,
|
|
7577
|
+
provider,
|
|
7578
|
+
category
|
|
7579
|
+
});
|
|
7580
|
+
return;
|
|
7581
|
+
}
|
|
7582
|
+
if (rateLimitLike) {
|
|
7583
|
+
breaker.releaseHalfOpenProbe();
|
|
7584
|
+
return;
|
|
7585
|
+
}
|
|
7586
|
+
breaker.recordFailure(category);
|
|
7587
|
+
this.deps.logger.warn("Gateway arm failure recorded to circuit breaker", {
|
|
7588
|
+
arm: this.armId,
|
|
7589
|
+
provider,
|
|
7590
|
+
category
|
|
7591
|
+
});
|
|
7592
|
+
}
|
|
7593
|
+
/** The telemetry branch of `ResilientAdapter.complete`, for the exempted case. */
|
|
7594
|
+
recordRateLimit(error, provider) {
|
|
7595
|
+
const rlError = toRateLimitError(error, provider);
|
|
7596
|
+
recordRateLimitEvent({
|
|
7597
|
+
provider,
|
|
7598
|
+
timestamp: getTimeProvider().now(),
|
|
7599
|
+
retryAfterMs: rlError.retryAfterMs
|
|
7600
|
+
});
|
|
7601
|
+
this.deps.logger.warn("Rate limit detected on gateway arm", {
|
|
7602
|
+
arm: this.armId,
|
|
7603
|
+
provider,
|
|
7604
|
+
retryAfterMs: rlError.retryAfterMs
|
|
7605
|
+
});
|
|
7606
|
+
}
|
|
7607
|
+
};
|
|
7608
|
+
|
|
7367
7609
|
// src/cli-adapters/model-to-cli-adapter.ts
|
|
7368
7610
|
var DEFAULT_CONTEXT_WINDOW = FALLBACK_CONTEXT_WINDOW;
|
|
7369
7611
|
var NEUTRAL_CAPABILITIES = {
|
|
@@ -7403,16 +7645,26 @@ var ModelToCliAdapter = class {
|
|
|
7403
7645
|
* Per-instance, so one arm's exhaustion never speaks for another's.
|
|
7404
7646
|
*/
|
|
7405
7647
|
capacityTracker;
|
|
7648
|
+
/** Exact admission ownership; other API adapters still need the integration's gate. */
|
|
7649
|
+
ownsCircuitAdmission(registry) {
|
|
7650
|
+
return ownsGatewayCircuitAdmission(this.modelAdapter, this.name, registry);
|
|
7651
|
+
}
|
|
7406
7652
|
constructor(modelAdapter, config) {
|
|
7407
7653
|
this.modelAdapter = modelAdapter;
|
|
7408
7654
|
this.name = config.name;
|
|
7409
|
-
|
|
7655
|
+
const entry = routingArmCliSlot(config.name) === void 0 ? getDefaultRegistry().getEntry(modelAdapter.modelId) : void 0;
|
|
7656
|
+
this.capabilities = config.capabilities ?? {
|
|
7657
|
+
...NEUTRAL_CAPABILITIES,
|
|
7658
|
+
...entry?.qualityScores,
|
|
7659
|
+
contextWindow: entry?.contextWindow ?? DEFAULT_CONTEXT_WINDOW
|
|
7660
|
+
};
|
|
7410
7661
|
this.capacityTracker = createCapacityTracker(config.name);
|
|
7411
7662
|
}
|
|
7412
7663
|
/** Build a single-turn CompletionRequest from a CliTask. */
|
|
7413
7664
|
toCompletionRequest(task, options) {
|
|
7414
7665
|
const request = {
|
|
7415
|
-
messages: [{ role: "user", content: task.content }]
|
|
7666
|
+
messages: [{ role: "user", content: task.content }],
|
|
7667
|
+
...options?.signal !== void 0 ? { signal: options.signal } : {}
|
|
7416
7668
|
};
|
|
7417
7669
|
if (task.systemPrompt !== void 0) {
|
|
7418
7670
|
request.systemPrompt = task.systemPrompt;
|
|
@@ -7501,7 +7753,7 @@ var ModelToCliAdapter = class {
|
|
|
7501
7753
|
}
|
|
7502
7754
|
async execute(task, options) {
|
|
7503
7755
|
const gatewayArm = this.gatewayArmField().gatewayArm;
|
|
7504
|
-
const breaker = gatewayArm !== void 0 && this.modelAdapter.providerId === `cli-${this.name}` ? (await import("./cli-circuit-breaker-
|
|
7756
|
+
const breaker = gatewayArm !== void 0 && this.modelAdapter.providerId === `cli-${this.name}` ? (await import("./cli-circuit-breaker-CDJKHR7R.js")).getDefaultCliCircuitBreakerRegistry().getArmBreaker(breakerKeys.forArm({ name: this.name, gatewayArm })) : void 0;
|
|
7505
7757
|
const result = await this.modelAdapter.complete(this.toCompletionRequest(task, options));
|
|
7506
7758
|
if (!result.ok) {
|
|
7507
7759
|
const cliError = this.toCliError(result.error);
|
|
@@ -7576,7 +7828,7 @@ var ModelToCliAdapter = class {
|
|
|
7576
7828
|
return {
|
|
7577
7829
|
id: this.modelAdapter.modelId,
|
|
7578
7830
|
name: this.modelAdapter.modelId,
|
|
7579
|
-
contextWindow: DEFAULT_CONTEXT_WINDOW
|
|
7831
|
+
contextWindow: routingArmCliSlot(this.name) === void 0 ? this.capabilities.contextWindow : DEFAULT_CONTEXT_WINDOW
|
|
7580
7832
|
};
|
|
7581
7833
|
}
|
|
7582
7834
|
/** Delegate to the model adapter's listModels surface when present (#2529). */
|
|
@@ -7630,6 +7882,11 @@ var GatewaySlotArm = class {
|
|
|
7630
7882
|
arm: typeof arm === "string" && isEndpointArmId(arm) ? arm : void 0
|
|
7631
7883
|
};
|
|
7632
7884
|
}
|
|
7885
|
+
/** Endpoint this slot may serve, including an undecided CLI-or-gateway target. */
|
|
7886
|
+
get gatewayEndpoint() {
|
|
7887
|
+
const arm = this.deps.gatewayModel.gatewayArm;
|
|
7888
|
+
return typeof arm === "string" && isEndpointArmId(arm) ? arm : void 0;
|
|
7889
|
+
}
|
|
7633
7890
|
/** The CLI's subprocess adapter; undefined when its binary is not on PATH. */
|
|
7634
7891
|
get cliBinaryAdapter() {
|
|
7635
7892
|
return this.deps.cliAdapter;
|
|
@@ -7726,6 +7983,9 @@ var GatewaySlotArm = class {
|
|
|
7726
7983
|
await this.gatewayAdapter.dispose();
|
|
7727
7984
|
}
|
|
7728
7985
|
};
|
|
7986
|
+
function gatewaySlotEndpointOf(adapter) {
|
|
7987
|
+
return adapter instanceof GatewaySlotArm ? adapter.gatewayEndpoint : void 0;
|
|
7988
|
+
}
|
|
7729
7989
|
function gatewayServedSlotOf(adapter) {
|
|
7730
7990
|
return adapter instanceof GatewaySlotArm ? adapter.gatewayServedSlot : void 0;
|
|
7731
7991
|
}
|
|
@@ -7769,23 +8029,6 @@ function buildGatewaySlotRouterArm(cli, createCli, isAvailable, logger16) {
|
|
|
7769
8029
|
});
|
|
7770
8030
|
}
|
|
7771
8031
|
|
|
7772
|
-
// src/adapters/sdk/gateway-catalog.ts
|
|
7773
|
-
var catalogs = /* @__PURE__ */ new Map();
|
|
7774
|
-
function setGatewayCatalog(arm, modelIds) {
|
|
7775
|
-
if (modelIds.length === 0) {
|
|
7776
|
-
throw new Error(
|
|
7777
|
-
`Gateway catalogue for ${arm} is empty; an arm with no model is not registrable`
|
|
7778
|
-
);
|
|
7779
|
-
}
|
|
7780
|
-
catalogs.set(arm, [...modelIds]);
|
|
7781
|
-
}
|
|
7782
|
-
function getGatewayCatalog(arm) {
|
|
7783
|
-
return catalogs.get(arm);
|
|
7784
|
-
}
|
|
7785
|
-
function clearGatewayCatalog(arm) {
|
|
7786
|
-
catalogs.delete(arm);
|
|
7787
|
-
}
|
|
7788
|
-
|
|
7789
8032
|
// src/cli-adapters/budget-arm-cost.ts
|
|
7790
8033
|
function estimateRegistryCostUsd(slot, inputTokens, outputTokens) {
|
|
7791
8034
|
const pricing = getModelPricing(getDefaultModelForCli(slot));
|
|
@@ -7947,8 +8190,9 @@ var DEFAULT_OPTIONS = {
|
|
|
7947
8190
|
// #4196: per-task-class cost ceilings default OFF (no ceiling configured).
|
|
7948
8191
|
taskClassCostCeilings: {}
|
|
7949
8192
|
};
|
|
7950
|
-
function latencyOf(
|
|
7951
|
-
|
|
8193
|
+
function latencyOf(arm) {
|
|
8194
|
+
const slot = routingArmCliSlot(arm);
|
|
8195
|
+
return slot === void 0 ? void 0 : DEFAULT_COST_MODELS[slot]?.avgLatencyMs;
|
|
7952
8196
|
}
|
|
7953
8197
|
var BudgetRouter = class {
|
|
7954
8198
|
adapters;
|
|
@@ -8064,7 +8308,7 @@ var BudgetRouter = class {
|
|
|
8064
8308
|
const adapter = selected === null ? null : selected.adapter;
|
|
8065
8309
|
const armCostUsd = selected === null ? void 0 : budgetCostOfArm(selected, estimatedInputTokens, estimatedOutputTokens);
|
|
8066
8310
|
const estimatedCostUsd = armCostUsd ?? 0;
|
|
8067
|
-
const estimatedLatencyMs = selected === null ? void 0 : latencyOf(
|
|
8311
|
+
const estimatedLatencyMs = selected === null ? void 0 : latencyOf(selected.arm);
|
|
8068
8312
|
const currentBudget = this.getSessionBudget();
|
|
8069
8313
|
const withinBudget = armCostUsd !== void 0 && this.checkConstraints(budget, estimatedTokens, estimatedCostUsd);
|
|
8070
8314
|
const warnings = generateBudgetWarnings(
|
|
@@ -8245,8 +8489,8 @@ var BudgetRouter = class {
|
|
|
8245
8489
|
}
|
|
8246
8490
|
selectAdapterWithinBudget(budget, estimatedTokens) {
|
|
8247
8491
|
const sortedAdapters = [...this.adapters].sort((a, b) => {
|
|
8248
|
-
const capA =
|
|
8249
|
-
const capB =
|
|
8492
|
+
const capA = this.capabilitiesOf(a[0], a[1]);
|
|
8493
|
+
const capB = this.capabilitiesOf(b[0], b[1]);
|
|
8250
8494
|
return capB.cost - capA.cost;
|
|
8251
8495
|
});
|
|
8252
8496
|
const unpricedArms = [];
|
|
@@ -8259,19 +8503,25 @@ var BudgetRouter = class {
|
|
|
8259
8503
|
unpricedArms.push({ arm, reason });
|
|
8260
8504
|
continue;
|
|
8261
8505
|
}
|
|
8262
|
-
if (this.admitsCandidate(budget, estimatedTokens,
|
|
8506
|
+
if (this.admitsCandidate(budget, estimatedTokens, { arm, adapter }, estimatedCost)) {
|
|
8263
8507
|
return { selected: { arm, adapter }, unpricedArms };
|
|
8264
8508
|
}
|
|
8265
8509
|
}
|
|
8266
8510
|
return { selected: null, unpricedArms };
|
|
8267
8511
|
}
|
|
8512
|
+
/** Slot profiles apply only to vendor arms; endpoints supply their own profile. */
|
|
8513
|
+
capabilitiesOf(arm, adapter) {
|
|
8514
|
+
const slot = routingArmCliSlot(arm);
|
|
8515
|
+
return slot === void 0 ? adapter.capabilities : DEFAULT_CAPABILITIES[slot];
|
|
8516
|
+
}
|
|
8268
8517
|
/** The four per-candidate admission checks of `selectAdapterWithinBudget`. */
|
|
8269
|
-
admitsCandidate(budget, estimatedTokens,
|
|
8270
|
-
const caps =
|
|
8518
|
+
admitsCandidate(budget, estimatedTokens, target, estimatedCost) {
|
|
8519
|
+
const caps = this.capabilitiesOf(target.arm, target.adapter);
|
|
8271
8520
|
const withinTokenBudget = budget.maxTokens === void 0 || estimatedTokens <= budget.maxTokens;
|
|
8272
8521
|
const withinCostBudget = budget.maxCostUsd === void 0 || estimatedCost <= budget.maxCostUsd;
|
|
8273
8522
|
const withinContextWindow = estimatedTokens <= caps.contextWindow;
|
|
8274
|
-
const
|
|
8523
|
+
const latency = latencyOf(target.arm);
|
|
8524
|
+
const withinLatencyBudget = budget.maxLatencyMs === void 0 || latency === void 0 || latency <= budget.maxLatencyMs;
|
|
8275
8525
|
return withinTokenBudget && withinCostBudget && withinContextWindow && withinLatencyBudget;
|
|
8276
8526
|
}
|
|
8277
8527
|
checkConstraints(budget, estimatedTokens, estimatedCostUsd) {
|
|
@@ -8473,6 +8723,15 @@ function generateReasoning(best, ranked, savings) {
|
|
|
8473
8723
|
}
|
|
8474
8724
|
return parts.join(". ");
|
|
8475
8725
|
}
|
|
8726
|
+
function adjustProfileForTask(profile, taskProfile) {
|
|
8727
|
+
if (taskProfile.taskType === "architecture" || taskProfile.reasoningComplexity > 7) {
|
|
8728
|
+
return { ...profile, qualityScore: Math.min(profile.qualityScore * 1.2, 10) };
|
|
8729
|
+
}
|
|
8730
|
+
if (taskProfile.taskType === "bulk_operations" || taskProfile.contextRequired < 1e3) {
|
|
8731
|
+
return { ...profile, averageLatencyMs: profile.averageLatencyMs * 0.8 };
|
|
8732
|
+
}
|
|
8733
|
+
return profile;
|
|
8734
|
+
}
|
|
8476
8735
|
|
|
8477
8736
|
// src/cli-adapters/topsis-router.ts
|
|
8478
8737
|
var WEIGHT_SUM_TOLERANCE = 0.01;
|
|
@@ -13498,8 +13757,8 @@ function getOutcomeStore() {
|
|
|
13498
13757
|
async function attachOutcomeStoreToRegistry(store) {
|
|
13499
13758
|
try {
|
|
13500
13759
|
const { getMemoryRegistry } = await import("./dist-RRRU2OKU.js");
|
|
13501
|
-
const { OutcomeStoreAdapter } = await import("./outcome-store-adapter-
|
|
13502
|
-
const { ensureSharedMemoryRegistry } = await import("./tool-memory-registry-adapters-
|
|
13760
|
+
const { OutcomeStoreAdapter } = await import("./outcome-store-adapter-Y6MS4JJK.js");
|
|
13761
|
+
const { ensureSharedMemoryRegistry } = await import("./tool-memory-registry-adapters-IIORYBCC.js");
|
|
13503
13762
|
ensureSharedMemoryRegistry();
|
|
13504
13763
|
getMemoryRegistry().attach("outcomes", new OutcomeStoreAdapter(store));
|
|
13505
13764
|
} catch {
|
|
@@ -13706,9 +13965,10 @@ function getPipelineEventBus() {
|
|
|
13706
13965
|
var PRIMARY_REWARD = 0.85;
|
|
13707
13966
|
var SECONDARY_REWARD = 0.6;
|
|
13708
13967
|
var OTHER_REWARD = 0.35;
|
|
13968
|
+
var ENDPOINT_REWARD = 0.5;
|
|
13709
13969
|
var SYNTHETIC_MARKER = "synthetic:warm-up";
|
|
13710
13970
|
var CLI_NAMES2 = ["claude", "gemini", "codex", "opencode"];
|
|
13711
|
-
function generateSyntheticPriors() {
|
|
13971
|
+
function generateSyntheticPriors(armNames = []) {
|
|
13712
13972
|
const totals = /* @__PURE__ */ new Map();
|
|
13713
13973
|
for (const cli of CLI_NAMES2) {
|
|
13714
13974
|
totals.set(cli, 0);
|
|
@@ -13730,6 +13990,11 @@ function generateSyntheticPriors() {
|
|
|
13730
13990
|
for (const [cli, total] of totals) {
|
|
13731
13991
|
priors.set(cli, total / count);
|
|
13732
13992
|
}
|
|
13993
|
+
for (const arm of armNames.filter(
|
|
13994
|
+
(name) => isEndpointArmId(name) && routingArmCliSlot(name) === void 0
|
|
13995
|
+
)) {
|
|
13996
|
+
priors.set(arm, ENDPOINT_REWARD);
|
|
13997
|
+
}
|
|
13733
13998
|
return priors;
|
|
13734
13999
|
}
|
|
13735
14000
|
function buildSyntheticOutcomes(timestamp) {
|
|
@@ -13803,7 +14068,7 @@ function warmStartBandit(bandit, logger16, options = {}) {
|
|
|
13803
14068
|
});
|
|
13804
14069
|
}
|
|
13805
14070
|
}
|
|
13806
|
-
bandit.seedPriors(generateSyntheticPriors(), replayed === 0 ? 3 : 1);
|
|
14071
|
+
bandit.seedPriors(generateSyntheticPriors(bandit.getArmNames()), replayed === 0 ? 3 : 1);
|
|
13807
14072
|
if (replayed === 0) {
|
|
13808
14073
|
fallbackUsed = true;
|
|
13809
14074
|
const fallback = options.persist === false ? memoryFallback() : persistedFallback(logger16);
|
|
@@ -13874,15 +14139,6 @@ function budgetUtilizationForTask(task, budgetRouter, rawConstraints) {
|
|
|
13874
14139
|
}
|
|
13875
14140
|
|
|
13876
14141
|
// src/cli-adapters/composite-router-helpers.ts
|
|
13877
|
-
function adjustProfileForTask(profile, taskProfile) {
|
|
13878
|
-
if (taskProfile.taskType === "architecture" || taskProfile.reasoningComplexity > 7) {
|
|
13879
|
-
return { ...profile, qualityScore: Math.min(profile.qualityScore * 1.2, 10) };
|
|
13880
|
-
}
|
|
13881
|
-
if (taskProfile.taskType === "bulk_operations" || taskProfile.contextRequired < 1e3) {
|
|
13882
|
-
return { ...profile, averageLatencyMs: profile.averageLatencyMs * 0.8 };
|
|
13883
|
-
}
|
|
13884
|
-
return profile;
|
|
13885
|
-
}
|
|
13886
14142
|
function taskProfileToBanditContext(profile, budgetUtilization) {
|
|
13887
14143
|
return {
|
|
13888
14144
|
taskComplexity: profile.reasoningComplexity / 10,
|
|
@@ -13930,7 +14186,10 @@ function filterByPreferenceTier(candidates, tier) {
|
|
|
13930
14186
|
const strongModels = deriveStrongClis();
|
|
13931
14187
|
const weakModels = deriveWeakClis();
|
|
13932
14188
|
const preferred = tier === "strong" ? strongModels : weakModels;
|
|
13933
|
-
const filtered = candidates.filter((c) =>
|
|
14189
|
+
const filtered = candidates.filter((c) => {
|
|
14190
|
+
const slot = routingArmCliSlot(c);
|
|
14191
|
+
return slot === void 0 || preferred.includes(slot);
|
|
14192
|
+
});
|
|
13934
14193
|
return filtered.length > 0 ? filtered : candidates;
|
|
13935
14194
|
}
|
|
13936
14195
|
function cliTaskToTask(cliTask) {
|
|
@@ -14001,7 +14260,7 @@ function adjustProfileWithStageScores(profiles, stageScores) {
|
|
|
14001
14260
|
});
|
|
14002
14261
|
}
|
|
14003
14262
|
function buildAdjustedProfiles(taskProfile, candidates, options) {
|
|
14004
|
-
const candidateSlots = new Set(candidates.map(
|
|
14263
|
+
const candidateSlots = new Set(candidates.map(routingArmCliSlot));
|
|
14005
14264
|
const profiles = DEFAULT_MODEL_PROFILES.filter((p) => candidateSlots.has(p.cliName));
|
|
14006
14265
|
let adjusted = profiles.map((p) => adjustProfileForTask(p, taskProfile));
|
|
14007
14266
|
if (options?.stageScores !== void 0 && options.stageScores.size > 0) {
|
|
@@ -14024,15 +14283,17 @@ function applyTopsisRanking(taskProfile, candidates, topsisRouter, options) {
|
|
|
14024
14283
|
taskProfile.reasoningComplexity
|
|
14025
14284
|
);
|
|
14026
14285
|
const adjustedProfiles = buildAdjustedProfiles(taskProfile, candidates, options);
|
|
14286
|
+
if (adjustedProfiles.length === 0) return { ranking: candidates, topScore: 1 };
|
|
14027
14287
|
const result = router.selectModel({ profiles: adjustedProfiles });
|
|
14028
|
-
const
|
|
14029
|
-
const scoreOf = (arm) => scoreMap.get(routingArmDisplaySlot(arm)) ?? 0;
|
|
14288
|
+
const scoreOf = (arm) => result.scores.find((score) => score.cliName === routingArmCliSlot(arm))?.closenessScore ?? 0;
|
|
14030
14289
|
const ranking = [...candidates].sort((a, b) => scoreOf(b) - scoreOf(a));
|
|
14031
14290
|
const topArm = ranking[0];
|
|
14032
14291
|
const topScore = topArm !== void 0 ? scoreOf(topArm) : 1;
|
|
14033
|
-
const scoresByArm = new Map(
|
|
14292
|
+
const scoresByArm = new Map(
|
|
14293
|
+
candidates.filter((arm) => routingArmCliSlot(arm) !== void 0).map((arm) => [arm, scoreOf(arm)])
|
|
14294
|
+
);
|
|
14034
14295
|
const threshold = topScore * (1 - TOPSIS_TOLERANCE_BAND_PERCENT);
|
|
14035
|
-
const toleranceBandSize =
|
|
14296
|
+
const toleranceBandSize = [...scoresByArm.values()].filter((score) => score >= threshold).length;
|
|
14036
14297
|
return { ranking, topScore, toleranceBandSize, scoresByArm };
|
|
14037
14298
|
}
|
|
14038
14299
|
function defaultPreferenceStageResult(candidates) {
|
|
@@ -14052,8 +14313,8 @@ function defaultZeroRouterStageResult(candidates) {
|
|
|
14052
14313
|
function filterByDifficultyTier(candidates, tier) {
|
|
14053
14314
|
const preferred = deriveTierToClis()[tier];
|
|
14054
14315
|
const sortedCandidates = [...candidates].sort((a, b) => {
|
|
14055
|
-
const aIndex = preferred.
|
|
14056
|
-
const bIndex = preferred.
|
|
14316
|
+
const aIndex = preferred.findIndex((slot) => slot === routingArmCliSlot(a));
|
|
14317
|
+
const bIndex = preferred.findIndex((slot) => slot === routingArmCliSlot(b));
|
|
14057
14318
|
const aPos = aIndex === -1 ? preferred.length : aIndex;
|
|
14058
14319
|
const bPos = bIndex === -1 ? preferred.length : bIndex;
|
|
14059
14320
|
return aPos - bPos;
|
|
@@ -14064,7 +14325,9 @@ function applyZeroRouterFilter(task, candidates, zeroRouter) {
|
|
|
14064
14325
|
if (zeroRouter === void 0 || candidates.length === 0) {
|
|
14065
14326
|
return defaultZeroRouterStageResult(candidates);
|
|
14066
14327
|
}
|
|
14067
|
-
const
|
|
14328
|
+
const slots = candidates.map(routingArmCliSlot).filter((slot) => slot !== void 0);
|
|
14329
|
+
if (slots.length === 0) return defaultZeroRouterStageResult(candidates);
|
|
14330
|
+
const decision = zeroRouter.routeByDifficulty(task, slots);
|
|
14068
14331
|
const difficultyEstimate = decision.difficulty;
|
|
14069
14332
|
const difficultyTier = decision.tier;
|
|
14070
14333
|
const filteredCandidates = filterByDifficultyTier(candidates, difficultyTier);
|
|
@@ -14099,7 +14362,7 @@ function buildDecisionFields(ctx) {
|
|
|
14099
14362
|
const alternatives = ctx.topsisRanking.filter((c) => c !== ctx.selectedCli);
|
|
14100
14363
|
if (ctx.topsisScoresByArm === void 0) return { confidence, reason, alternatives };
|
|
14101
14364
|
const alternativeScores = new Map(
|
|
14102
|
-
alternatives.map((arm) => [arm, ctx.topsisScoresByArm?.get(arm) ?? 0])
|
|
14365
|
+
alternatives.filter((arm) => ctx.topsisScoresByArm?.has(arm) === true).map((arm) => [arm, ctx.topsisScoresByArm?.get(arm) ?? 0])
|
|
14103
14366
|
);
|
|
14104
14367
|
return { confidence, reason, alternatives, alternativeScores };
|
|
14105
14368
|
}
|
|
@@ -17697,7 +17960,10 @@ function buildWeatherCostSection(cfg, deps, includePipelineJoins = false) {
|
|
|
17697
17960
|
}
|
|
17698
17961
|
|
|
17699
17962
|
// src/mcp/tools/weather-report-arms.ts
|
|
17700
|
-
var ROUTED_ARMS = [
|
|
17963
|
+
var ROUTED_ARMS = [
|
|
17964
|
+
...CLI_NAMES,
|
|
17965
|
+
...ApiArmIdSchema.options
|
|
17966
|
+
];
|
|
17701
17967
|
var SLOT_ARMS = new Map(
|
|
17702
17968
|
CLI_NAMES.map((slot) => [
|
|
17703
17969
|
slot,
|
|
@@ -18275,11 +18541,21 @@ function getFallbackChainForCategory(category, bucketType, registry = DEFAULT_FA
|
|
|
18275
18541
|
|
|
18276
18542
|
// src/cli-adapters/composite-router-scoring-stages.ts
|
|
18277
18543
|
function armsToSlots(candidates) {
|
|
18278
|
-
return [
|
|
18544
|
+
return [
|
|
18545
|
+
...new Set(
|
|
18546
|
+
candidates.flatMap((arm) => {
|
|
18547
|
+
const slot = routingArmCliSlot(arm);
|
|
18548
|
+
return slot === void 0 ? [] : [slot];
|
|
18549
|
+
})
|
|
18550
|
+
)
|
|
18551
|
+
];
|
|
18279
18552
|
}
|
|
18280
18553
|
function keepArmsForSlots(candidates, survivingSlots) {
|
|
18281
18554
|
const slotSet = new Set(survivingSlots);
|
|
18282
|
-
return candidates.filter((arm) =>
|
|
18555
|
+
return candidates.filter((arm) => {
|
|
18556
|
+
const slot = routingArmCliSlot(arm);
|
|
18557
|
+
return slot === void 0 || slotSet.has(slot);
|
|
18558
|
+
});
|
|
18283
18559
|
}
|
|
18284
18560
|
var DEFAULT_COMPLEXITY = "moderate";
|
|
18285
18561
|
function extractComplexityFromSignals(signals) {
|
|
@@ -18371,7 +18647,14 @@ async function runQualityConstraintStage(candidates, stagesExecuted, deps) {
|
|
|
18371
18647
|
if (!deps.config.enableQualityConstraint || deps.qualityConstraintStage === void 0) {
|
|
18372
18648
|
return { eligible: candidates, filtered: /* @__PURE__ */ new Map(), usedFallback: false };
|
|
18373
18649
|
}
|
|
18374
|
-
const
|
|
18650
|
+
const slots = armsToSlots(candidates);
|
|
18651
|
+
if (candidates.some((arm) => routingArmCliSlot(arm) === void 0)) {
|
|
18652
|
+
stagesExecuted.push("quality-constraint:endpoint-unmeasured");
|
|
18653
|
+
}
|
|
18654
|
+
if (slots.length === 0) {
|
|
18655
|
+
return { eligible: candidates, filtered: /* @__PURE__ */ new Map(), usedFallback: false };
|
|
18656
|
+
}
|
|
18657
|
+
const ctx = createRoutingContext("", slots);
|
|
18375
18658
|
const result = await deps.qualityConstraintStage.route(ctx);
|
|
18376
18659
|
stagesExecuted.push("quality-constraint");
|
|
18377
18660
|
if (!result.ok) {
|
|
@@ -18478,7 +18761,7 @@ function runZeroRouterStage(task, candidates, stagesExecuted, deps) {
|
|
|
18478
18761
|
return result;
|
|
18479
18762
|
}
|
|
18480
18763
|
function runTopsisStage(taskProfile, candidates, stagesExecuted, deps, options) {
|
|
18481
|
-
if (!deps.config.enableTopsisRanking || deps.topsisRouter === void 0) {
|
|
18764
|
+
if (!deps.config.enableTopsisRanking || deps.topsisRouter === void 0 || armsToSlots(candidates).length === 0) {
|
|
18482
18765
|
return { ranking: candidates, score: void 0 };
|
|
18483
18766
|
}
|
|
18484
18767
|
const topsisOptions = {
|
|
@@ -18536,10 +18819,10 @@ function runLatencyStage(candidates, stagesExecuted, deps) {
|
|
|
18536
18819
|
}
|
|
18537
18820
|
const scores = deps.latencyTracker.getScores(armsToSlots(candidates));
|
|
18538
18821
|
stagesExecuted.push("latency-scoring");
|
|
18539
|
-
const scoreOf = (arm) => scores.find((s) => s.cli ===
|
|
18822
|
+
const scoreOf = (arm) => scores.find((s) => s.cli === routingArmCliSlot(arm))?.score ?? 0;
|
|
18540
18823
|
const sortedCandidates = [...candidates].sort((a, b) => scoreOf(b) - scoreOf(a));
|
|
18541
18824
|
const topArm = sortedCandidates[0];
|
|
18542
|
-
const topScore = topArm !== void 0 ? scores.find((s) => s.cli ===
|
|
18825
|
+
const topScore = topArm !== void 0 ? scores.find((s) => s.cli === routingArmCliSlot(topArm))?.score : void 0;
|
|
18543
18826
|
deps.logger.debug("Latency scoring applied", {
|
|
18544
18827
|
scores: scores.map((s) => ({
|
|
18545
18828
|
cli: s.cli,
|
|
@@ -18647,6 +18930,7 @@ function getPerformanceDataForCategory(taskContent) {
|
|
|
18647
18930
|
const summary = getOutcomeStore().summarize({ category: match.category });
|
|
18648
18931
|
const result = /* @__PURE__ */ new Map();
|
|
18649
18932
|
for (const [cli, stats] of summary.byCli) {
|
|
18933
|
+
if (!isCliName(cli)) continue;
|
|
18650
18934
|
result.set(cli, {
|
|
18651
18935
|
successRate: stats.successRate,
|
|
18652
18936
|
sampleCount: stats.count
|
|
@@ -18754,9 +19038,18 @@ function applyCategoryOverride(task, candidates, stagesExecuted) {
|
|
|
18754
19038
|
if (match === null) return ok(candidates);
|
|
18755
19039
|
const override = CATEGORY_CHAIN_OVERRIDES[match.category];
|
|
18756
19040
|
if (override === void 0) return ok(candidates);
|
|
19041
|
+
if (!isCategoryFailClosed(match.category) && candidates.some((arm) => routingArmCliSlot(arm) === void 0)) {
|
|
19042
|
+
stagesExecuted.push("category-override:endpoint-unmeasured");
|
|
19043
|
+
}
|
|
18757
19044
|
const overrideSet = new Set(override);
|
|
18758
|
-
const orderIndex = (arm) =>
|
|
18759
|
-
|
|
19045
|
+
const orderIndex = (arm) => {
|
|
19046
|
+
const slot = routingArmCliSlot(arm);
|
|
19047
|
+
return slot === void 0 ? override.length : override.indexOf(slot);
|
|
19048
|
+
};
|
|
19049
|
+
const filtered = candidates.filter((arm) => {
|
|
19050
|
+
const slot = routingArmCliSlot(arm);
|
|
19051
|
+
return slot === void 0 ? !isCategoryFailClosed(match.category) : overrideSet.has(slot);
|
|
19052
|
+
}).sort((a, b) => orderIndex(a) - orderIndex(b));
|
|
18760
19053
|
if (filtered.length === 0) {
|
|
18761
19054
|
if (isCategoryFailClosed(match.category)) {
|
|
18762
19055
|
stagesExecuted.push("category-override:fail-closed");
|
|
@@ -18779,8 +19072,9 @@ function applyCategoryOverride(task, candidates, stagesExecuted) {
|
|
|
18779
19072
|
return ok(filtered);
|
|
18780
19073
|
}
|
|
18781
19074
|
function applyLinUCBFloorOverride(linucbCli, topsisRanking, opts) {
|
|
18782
|
-
|
|
18783
|
-
|
|
19075
|
+
const slot = routingArmCliSlot(linucbCli);
|
|
19076
|
+
if (opts.perfData === void 0 || slot === void 0) return linucbCli;
|
|
19077
|
+
const cliPerf = opts.perfData.get(slot);
|
|
18784
19078
|
if (cliPerf === void 0 || cliPerf.sampleCount < 20 || cliPerf.successRate >= 0.5) {
|
|
18785
19079
|
return linucbCli;
|
|
18786
19080
|
}
|
|
@@ -18878,11 +19172,13 @@ function buildPipelineResult(p) {
|
|
|
18878
19172
|
preferenceScore: p.prefResult.preferenceScore,
|
|
18879
19173
|
preferenceTier: p.prefResult.preferenceTier,
|
|
18880
19174
|
topsisRanking: p.topsisResult.ranking,
|
|
18881
|
-
|
|
19175
|
+
// An endpoint did not participate in TOPSIS; do not report a CLI score.
|
|
19176
|
+
topsisScore: routingArmCliSlot(p.selectedCli) === void 0 ? void 0 : p.topsisResult.score,
|
|
18882
19177
|
topsisScoresByArm: p.topsisResult.scoresByArm,
|
|
18883
19178
|
selectedCli: p.selectedCli,
|
|
18884
19179
|
ucbScore: p.linucbResult.ucbScore,
|
|
18885
|
-
|
|
19180
|
+
// Endpoint latency is unmeasured; the stage's best CLI score is not its own.
|
|
19181
|
+
latencyScore: routingArmCliSlot(p.selectedCli) === void 0 ? void 0 : p.latencyResult.latencyScore,
|
|
18886
19182
|
memoryRecommendation: p.memoryResult.recommendation,
|
|
18887
19183
|
memoryConfidence: p.memoryResult.memoryConfidence,
|
|
18888
19184
|
...stageScores.size > 0 ? { stageScores } : {},
|
|
@@ -19181,8 +19477,8 @@ function buildDefaultModelSources(adapters, opts = {}) {
|
|
|
19181
19477
|
}
|
|
19182
19478
|
for (const [key, adapter] of adapters) {
|
|
19183
19479
|
if (hasListModels(adapter)) {
|
|
19184
|
-
const
|
|
19185
|
-
sources.push(adapterSource(
|
|
19480
|
+
const sourceName = routingArmCliSlot(key) ?? key;
|
|
19481
|
+
sources.push(adapterSource(sourceName, adapter));
|
|
19186
19482
|
}
|
|
19187
19483
|
}
|
|
19188
19484
|
return sources;
|
|
@@ -19437,12 +19733,10 @@ var PendingRoutingOutcomes = class {
|
|
|
19437
19733
|
try {
|
|
19438
19734
|
if (!isRouteModelShadowEnabled() || decision.difficultyTier === void 0) return void 0;
|
|
19439
19735
|
if (task.model !== void 0) return void 0;
|
|
19736
|
+
const slot = routingArmCliSlot(decision.cliName);
|
|
19737
|
+
if (slot === void 0) return void 0;
|
|
19440
19738
|
logModelSelectionReadinessOnce(this.logger);
|
|
19441
|
-
const comparison = computeModelSelectionShadow(
|
|
19442
|
-
routingArmDisplaySlot(decision.cliName),
|
|
19443
|
-
decision.difficultyTier,
|
|
19444
|
-
decision.model
|
|
19445
|
-
);
|
|
19739
|
+
const comparison = computeModelSelectionShadow(slot, decision.difficultyTier, decision.model);
|
|
19446
19740
|
this.logger.debug("Model-selection shadow computed (#4197)", {
|
|
19447
19741
|
cli: comparison.cli,
|
|
19448
19742
|
tier: comparison.tier,
|
|
@@ -19536,12 +19830,14 @@ function recordZeroRouterOutcome(task, success, qualityScore, deps, attribution)
|
|
|
19536
19830
|
return;
|
|
19537
19831
|
}
|
|
19538
19832
|
const { difficulty, selectedCli } = attribution;
|
|
19833
|
+
const slot = routingArmCliSlot(selectedCli);
|
|
19834
|
+
if (slot === void 0) return;
|
|
19539
19835
|
const outcome = buildDifficultyOutcome(
|
|
19540
19836
|
task.content,
|
|
19541
19837
|
difficulty,
|
|
19542
19838
|
// Difficulty calibration is slot-level; collapse an api:* arm to its
|
|
19543
19839
|
// display slot here (the bandit retains the distinct arm). (#3422)
|
|
19544
|
-
|
|
19840
|
+
slot,
|
|
19545
19841
|
success,
|
|
19546
19842
|
qualityScore
|
|
19547
19843
|
);
|
|
@@ -19575,8 +19871,8 @@ function getCachedCliSuccessRate(cli) {
|
|
|
19575
19871
|
function rewardSuccessRate(arm) {
|
|
19576
19872
|
const own = getCachedCliSuccessRate(arm);
|
|
19577
19873
|
if (own !== void 0) return own;
|
|
19578
|
-
const slot =
|
|
19579
|
-
return slot === arm ? void 0 : getCachedCliSuccessRate(slot);
|
|
19874
|
+
const slot = routingArmCliSlot(arm);
|
|
19875
|
+
return slot === void 0 || slot === arm ? void 0 : getCachedCliSuccessRate(slot);
|
|
19580
19876
|
}
|
|
19581
19877
|
function computeQualityReward(cli, success, durationMs) {
|
|
19582
19878
|
if (!success) return 0.1;
|
|
@@ -19603,12 +19899,16 @@ function computeQualityReward(cli, success, durationMs) {
|
|
|
19603
19899
|
// src/cli-adapters/composite-router-metrics.ts
|
|
19604
19900
|
function recordDecisionToMetrics(decision, traceId, deps) {
|
|
19605
19901
|
if (deps.metricsCollector === void 0) return;
|
|
19606
|
-
const selectedModel =
|
|
19902
|
+
const selectedModel = routingArmCliSlot(decision.cliName);
|
|
19903
|
+
if (selectedModel === void 0) return;
|
|
19607
19904
|
deps.metricsCollector.recordDecision({
|
|
19608
19905
|
timestamp: getTimeProvider().nowIso(),
|
|
19609
19906
|
traceId,
|
|
19610
19907
|
selectedModel,
|
|
19611
|
-
alternativeModels: decision.alternatives.
|
|
19908
|
+
alternativeModels: decision.alternatives.flatMap((arm) => {
|
|
19909
|
+
const slot = routingArmCliSlot(arm);
|
|
19910
|
+
return slot === void 0 ? [] : [slot];
|
|
19911
|
+
}),
|
|
19612
19912
|
isExploration: decision.ucbScore !== void 0 && decision.ucbScore > 0.5,
|
|
19613
19913
|
taskType: decision.taskProfile.taskType,
|
|
19614
19914
|
contextTokens: decision.taskProfile.contextRequired,
|
|
@@ -19836,9 +20136,8 @@ var CompositeRouter = class _CompositeRouter {
|
|
|
19836
20136
|
type: "routing.decision",
|
|
19837
20137
|
timestamp: getTimeProvider().now(),
|
|
19838
20138
|
taskId: taskDescription.slice(0, 100),
|
|
19839
|
-
//
|
|
19840
|
-
|
|
19841
|
-
selectedModel: routingArmDisplaySlot(decision.cliName),
|
|
20139
|
+
// Built-in vendor arms retain slot display; endpoints retain their own identity.
|
|
20140
|
+
selectedModel: routingArmCliSlot(decision.cliName) ?? decision.cliName,
|
|
19842
20141
|
reasoning: decision.reason,
|
|
19843
20142
|
decisionPath: decision.stagesExecuted
|
|
19844
20143
|
});
|
|
@@ -19874,7 +20173,7 @@ var CompositeRouter = class _CompositeRouter {
|
|
|
19874
20173
|
*/
|
|
19875
20174
|
async consultUnifiedContext(task) {
|
|
19876
20175
|
try {
|
|
19877
|
-
const { getContextForTask, inferTaskCategory } = await import("./context-retriever-
|
|
20176
|
+
const { getContextForTask, inferTaskCategory } = await import("./context-retriever-CBOMGQAP.js");
|
|
19878
20177
|
const ctx = await getContextForTask({
|
|
19879
20178
|
task: task.content,
|
|
19880
20179
|
category: inferTaskCategory(task.content),
|
|
@@ -19936,8 +20235,10 @@ var CompositeRouter = class _CompositeRouter {
|
|
|
19936
20235
|
const durationMs = getTimeProvider().now() - startTime;
|
|
19937
20236
|
const success = executeResult.ok;
|
|
19938
20237
|
this.autoRecordFeedback(decision, task, success, durationMs);
|
|
20238
|
+
const routedSlot = routingArmCliSlot(decision.cliName);
|
|
19939
20239
|
const routed = {
|
|
19940
|
-
|
|
20240
|
+
// A gateway endpoint has no routed CLI; routedArm carries its identity.
|
|
20241
|
+
...routedSlot !== void 0 && { routedCli: routedSlot },
|
|
19941
20242
|
routedArm: decision.cliName,
|
|
19942
20243
|
routedDurationMs: armDurationMs
|
|
19943
20244
|
};
|
|
@@ -19946,10 +20247,17 @@ var CompositeRouter = class _CompositeRouter {
|
|
|
19946
20247
|
}
|
|
19947
20248
|
autoRecordFeedback(decision, task, success, durationMs) {
|
|
19948
20249
|
const arm = decision.cliName;
|
|
19949
|
-
const slot =
|
|
20250
|
+
const slot = routingArmCliSlot(arm);
|
|
19950
20251
|
const reward = computeQualityReward(arm, success, durationMs);
|
|
19951
20252
|
this.recordOutcome(arm, task, reward, success);
|
|
19952
20253
|
this.recordExecutedDifficultyOutcome(decision, task, success);
|
|
20254
|
+
this.logger.debug("Auto-recorded feedback", {
|
|
20255
|
+
cli: arm,
|
|
20256
|
+
success,
|
|
20257
|
+
durationMs,
|
|
20258
|
+
reward
|
|
20259
|
+
});
|
|
20260
|
+
if (slot === void 0) return;
|
|
19953
20261
|
if (this.latencyTracker !== void 0) {
|
|
19954
20262
|
this.latencyTracker.record(slot, durationMs, success);
|
|
19955
20263
|
}
|
|
@@ -19977,12 +20285,6 @@ var CompositeRouter = class _CompositeRouter {
|
|
|
19977
20285
|
{ metricsCollector: this.metricsCollector, logger: this.logger }
|
|
19978
20286
|
);
|
|
19979
20287
|
}
|
|
19980
|
-
this.logger.debug("Auto-recorded feedback", {
|
|
19981
|
-
cli: arm,
|
|
19982
|
-
success,
|
|
19983
|
-
durationMs,
|
|
19984
|
-
reward
|
|
19985
|
-
});
|
|
19986
20288
|
}
|
|
19987
20289
|
/** Task type inference keywords. */
|
|
19988
20290
|
static TASK_TYPE_KEYWORDS = [
|
|
@@ -20065,9 +20367,10 @@ var CompositeRouter = class _CompositeRouter {
|
|
|
20065
20367
|
return this.cliNames;
|
|
20066
20368
|
}
|
|
20067
20369
|
const sourcesWithModels = new Set(all.map((m) => m.source));
|
|
20068
|
-
const filtered = this.cliNames.filter(
|
|
20069
|
-
|
|
20070
|
-
|
|
20370
|
+
const filtered = this.cliNames.filter((name) => {
|
|
20371
|
+
const slot = routingArmCliSlot(name);
|
|
20372
|
+
return slot === void 0 || sourcesWithModels.has(slot);
|
|
20373
|
+
});
|
|
20071
20374
|
if (filtered.length === 0) {
|
|
20072
20375
|
this.logger.info(
|
|
20073
20376
|
"AvailableModelsCache filtered out all CLIs; falling back to all (possible stale/misconfigured cache)",
|
|
@@ -20139,7 +20442,8 @@ var CompositeRouter = class _CompositeRouter {
|
|
|
20139
20442
|
decisionTimeMs,
|
|
20140
20443
|
billingMode: this.config.billingMode
|
|
20141
20444
|
});
|
|
20142
|
-
const
|
|
20445
|
+
const modelSlot = routingArmCliSlot(params.selectedCli);
|
|
20446
|
+
const model = isRouteModelSelectionEnabled() && params.difficultyTier !== void 0 && modelSlot !== void 0 ? resolveModelForTier(modelSlot, params.difficultyTier) : void 0;
|
|
20143
20447
|
return ok({
|
|
20144
20448
|
adapter: selectedAdapter,
|
|
20145
20449
|
cliName: params.selectedCli,
|
|
@@ -20163,7 +20467,8 @@ var CompositeRouter = class _CompositeRouter {
|
|
|
20163
20467
|
}
|
|
20164
20468
|
updateStats(selectedCli, decisionTimeMs) {
|
|
20165
20469
|
this.totalDecisions++;
|
|
20166
|
-
|
|
20470
|
+
const slot = routingArmCliSlot(selectedCli);
|
|
20471
|
+
if (slot !== void 0) this.decisionsPerCli[slot]++;
|
|
20167
20472
|
this.totalDecisionTimeMs += decisionTimeMs;
|
|
20168
20473
|
}
|
|
20169
20474
|
/**
|
|
@@ -20191,9 +20496,10 @@ var CompositeRouter = class _CompositeRouter {
|
|
|
20191
20496
|
}
|
|
20192
20497
|
recordOutcome(cliName, task, reward, success) {
|
|
20193
20498
|
recordBanditOutcome(cliName, task, reward, this.getOutcomeDependencies());
|
|
20194
|
-
|
|
20499
|
+
const slot = routingArmCliSlot(cliName);
|
|
20500
|
+
if (this.config.enableStrategyDistillation && this.distilledRuleStage !== void 0 && success !== void 0 && slot !== void 0) {
|
|
20195
20501
|
this.distilledRuleStage.recordOutcome({
|
|
20196
|
-
selectedCli:
|
|
20502
|
+
selectedCli: slot,
|
|
20197
20503
|
task: task.content,
|
|
20198
20504
|
success
|
|
20199
20505
|
});
|
|
@@ -20456,10 +20762,7 @@ function loadManifestOverlay(options) {
|
|
|
20456
20762
|
return mergeOverlays(user, operator);
|
|
20457
20763
|
}
|
|
20458
20764
|
function mergeOverlays(lower, higher) {
|
|
20459
|
-
const
|
|
20460
|
-
for (const entry of lower.entries) byId.set(entry.id, entry);
|
|
20461
|
-
for (const entry of higher.entries) byId.set(entry.id, entry);
|
|
20462
|
-
const entries = [...byId.values()];
|
|
20765
|
+
const entries = [...lower.entries, ...higher.entries];
|
|
20463
20766
|
const merged = {
|
|
20464
20767
|
entries,
|
|
20465
20768
|
rejections: [...lower.rejections, ...higher.rejections],
|
|
@@ -20760,6 +21063,10 @@ function loadGeneratedRegistryEntries(options) {
|
|
|
20760
21063
|
}
|
|
20761
21064
|
|
|
20762
21065
|
// src/config/model-registry.ts
|
|
21066
|
+
var pricingSources = /* @__PURE__ */ new WeakMap();
|
|
21067
|
+
function pricingSourceOf(entry) {
|
|
21068
|
+
return (entry.pricing === void 0 ? void 0 : pricingSources.get(entry.pricing)) ?? entry.source;
|
|
21069
|
+
}
|
|
20763
21070
|
var ModelRegistry = class {
|
|
20764
21071
|
byId = /* @__PURE__ */ new Map();
|
|
20765
21072
|
byAlias = /* @__PURE__ */ new Map();
|
|
@@ -20875,9 +21182,22 @@ var ModelRegistry = class {
|
|
|
20875
21182
|
}
|
|
20876
21183
|
loadEntries(entries) {
|
|
20877
21184
|
for (const entry of entries) {
|
|
20878
|
-
|
|
20879
|
-
if (entry.
|
|
20880
|
-
|
|
21185
|
+
const merged = { ...entry };
|
|
21186
|
+
if (entry.pricing === void 0) {
|
|
21187
|
+
const lower = this.byId.get(entry.id);
|
|
21188
|
+
if (lower?.pricing !== void 0) {
|
|
21189
|
+
merged.pricing = lower.pricing;
|
|
21190
|
+
if (lower.pricingProvenance !== void 0) {
|
|
21191
|
+
merged.pricingProvenance = lower.pricingProvenance;
|
|
21192
|
+
}
|
|
21193
|
+
}
|
|
21194
|
+
} else {
|
|
21195
|
+
merged.pricing = { ...entry.pricing };
|
|
21196
|
+
pricingSources.set(merged.pricing, entry.source);
|
|
21197
|
+
}
|
|
21198
|
+
this.byId.set(entry.id, merged);
|
|
21199
|
+
if (merged.aliases !== void 0) {
|
|
21200
|
+
for (const alias of merged.aliases) {
|
|
20881
21201
|
this.byAlias.set(alias, entry.id);
|
|
20882
21202
|
if (alias !== entry.id) this.byId.delete(alias);
|
|
20883
21203
|
}
|
|
@@ -20956,7 +21276,7 @@ function setDefaultRegistry(registry) {
|
|
|
20956
21276
|
}
|
|
20957
21277
|
async function reloadDefaultRegistry() {
|
|
20958
21278
|
globalRegistry = buildDefaultRegistry();
|
|
20959
|
-
const { resetGlobalRegistry } = await import("./unified-registry-
|
|
21279
|
+
const { resetGlobalRegistry } = await import("./unified-registry-IEPJHJHO.js");
|
|
20960
21280
|
resetGlobalRegistry();
|
|
20961
21281
|
return globalRegistry;
|
|
20962
21282
|
}
|
|
@@ -20978,12 +21298,12 @@ var VENDOR_TO_CLI_SLOT = {
|
|
|
20978
21298
|
};
|
|
20979
21299
|
function ownerOfEntry(entry) {
|
|
20980
21300
|
if (isCliName2(entry.cliName)) return entry.cliName;
|
|
20981
|
-
const
|
|
21301
|
+
const owners2 = /* @__PURE__ */ new Set();
|
|
20982
21302
|
for (const key of [entry.id, ...entry.aliases ?? []]) {
|
|
20983
21303
|
const owner = inTreeOwner(key);
|
|
20984
|
-
if (owner !== void 0)
|
|
21304
|
+
if (owner !== void 0) owners2.add(owner);
|
|
20985
21305
|
}
|
|
20986
|
-
return
|
|
21306
|
+
return owners2.size === 1 ? [...owners2][0] : void 0;
|
|
20987
21307
|
}
|
|
20988
21308
|
function slotOfEntry(entry) {
|
|
20989
21309
|
return ownerOfEntry(entry) ?? VENDOR_TO_CLI_SLOT[entry.vendor] ?? "opencode";
|
|
@@ -21310,7 +21630,7 @@ export {
|
|
|
21310
21630
|
isCliName,
|
|
21311
21631
|
ApiArmIdSchema,
|
|
21312
21632
|
apiArmId,
|
|
21313
|
-
|
|
21633
|
+
routingArmCliSlot,
|
|
21314
21634
|
isEndpointArmId,
|
|
21315
21635
|
CLI_VERSION_REQUIREMENTS,
|
|
21316
21636
|
DEFAULT_CAPABILITIES,
|
|
@@ -21413,20 +21733,17 @@ export {
|
|
|
21413
21733
|
CircuitBreakerRegistry,
|
|
21414
21734
|
mapCliErrorToCategory,
|
|
21415
21735
|
mapModelErrorToCategory,
|
|
21736
|
+
setGatewayCatalog,
|
|
21737
|
+
createGatewayArmAdapter,
|
|
21738
|
+
ModelToCliAdapter,
|
|
21416
21739
|
createModelToCliAdapter,
|
|
21740
|
+
gatewaySlotEndpointOf,
|
|
21417
21741
|
gatewayServedSlotOf,
|
|
21418
21742
|
cliBinaryAdapterOf,
|
|
21419
21743
|
resolveGatewayServedSlot,
|
|
21420
21744
|
decideSlotServing,
|
|
21421
21745
|
isDisabledSlotUnserved,
|
|
21422
21746
|
buildGatewaySlotRouterArm,
|
|
21423
|
-
createOpenRouterModelsSource,
|
|
21424
|
-
isDynamicModelsEnabled,
|
|
21425
|
-
buildDefaultModelSources,
|
|
21426
|
-
resolveOwnerCli,
|
|
21427
|
-
resolveCliSlot,
|
|
21428
|
-
getTokenEstimator,
|
|
21429
|
-
estimateTokens,
|
|
21430
21747
|
computeTokenCost,
|
|
21431
21748
|
priceBasisOf,
|
|
21432
21749
|
recordUsageEvent,
|
|
@@ -21437,12 +21754,19 @@ export {
|
|
|
21437
21754
|
gatewayEndpointRejection,
|
|
21438
21755
|
gatewayCostStatus,
|
|
21439
21756
|
resolveGatewayCostDeclaration,
|
|
21757
|
+
gatewayCostGap,
|
|
21440
21758
|
describeGatewayCostDeclaration,
|
|
21441
21759
|
warnIfGatewayCostUndeclared,
|
|
21442
|
-
|
|
21443
|
-
clearGatewayCatalog,
|
|
21760
|
+
budgetCostOfArm,
|
|
21444
21761
|
gatewayCostDetail,
|
|
21445
21762
|
servedCostDetail,
|
|
21763
|
+
createOpenRouterModelsSource,
|
|
21764
|
+
isDynamicModelsEnabled,
|
|
21765
|
+
buildDefaultModelSources,
|
|
21766
|
+
resolveOwnerCli,
|
|
21767
|
+
resolveCliSlot,
|
|
21768
|
+
getTokenEstimator,
|
|
21769
|
+
estimateTokens,
|
|
21446
21770
|
ModelRegistry,
|
|
21447
21771
|
getDefaultRegistry,
|
|
21448
21772
|
setDefaultRegistry,
|
|
@@ -21623,4 +21947,4 @@ export {
|
|
|
21623
21947
|
AgentCapability,
|
|
21624
21948
|
OrchestratorError
|
|
21625
21949
|
};
|
|
21626
|
-
//# sourceMappingURL=chunk-
|
|
21950
|
+
//# sourceMappingURL=chunk-EBOAFTOG.js.map
|