@khanglvm/llm-router 2.3.5 → 2.3.6
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/CHANGELOG.md +5 -0
- package/README.md +1 -0
- package/package.json +1 -1
- package/src/cli/router-module.js +5 -2
- package/src/node/coding-tool-config.js +270 -31
- package/src/node/web-console-client.js +20 -20
- package/src/node/web-console-server.js +12 -1
- package/src/shared/coding-tool-bindings.js +133 -0
|
@@ -1488,7 +1488,8 @@ export async function startWebConsoleServer(options = {}, deps = {}) {
|
|
|
1488
1488
|
const endpointUrl = buildAmpClientEndpointUrl(settings);
|
|
1489
1489
|
try {
|
|
1490
1490
|
const state = await readFactoryDroidRoutingState({
|
|
1491
|
-
endpointUrl
|
|
1491
|
+
endpointUrl,
|
|
1492
|
+
config
|
|
1492
1493
|
});
|
|
1493
1494
|
return {
|
|
1494
1495
|
...state,
|
|
@@ -1512,6 +1513,13 @@ export async function startWebConsoleServer(options = {}, deps = {}) {
|
|
|
1512
1513
|
missionValidatorModel: "",
|
|
1513
1514
|
reasoningEffort: ""
|
|
1514
1515
|
},
|
|
1516
|
+
bindingIds: {
|
|
1517
|
+
defaultModel: "",
|
|
1518
|
+
missionOrchestratorModel: "",
|
|
1519
|
+
missionWorkerModel: "",
|
|
1520
|
+
missionValidatorModel: "",
|
|
1521
|
+
reasoningEffort: ""
|
|
1522
|
+
},
|
|
1515
1523
|
endpointUrl,
|
|
1516
1524
|
error: error instanceof Error ? error.message : String(error)
|
|
1517
1525
|
};
|
|
@@ -1551,6 +1559,7 @@ export async function startWebConsoleServer(options = {}, deps = {}) {
|
|
|
1551
1559
|
endpointUrl: nextEndpointUrl,
|
|
1552
1560
|
apiKey: nextMasterKey,
|
|
1553
1561
|
bindings,
|
|
1562
|
+
config: nextConfig,
|
|
1554
1563
|
captureBackup: false
|
|
1555
1564
|
});
|
|
1556
1565
|
if (endpointOrKeyChanged) {
|
|
@@ -3487,6 +3496,7 @@ export async function startWebConsoleServer(options = {}, deps = {}) {
|
|
|
3487
3496
|
endpointUrl,
|
|
3488
3497
|
apiKey,
|
|
3489
3498
|
bindings,
|
|
3499
|
+
config: nextConfig,
|
|
3490
3500
|
captureBackup: true
|
|
3491
3501
|
});
|
|
3492
3502
|
addLog("success", "Factory Droid routing enabled.", patchResult.baseUrl);
|
|
@@ -3537,6 +3547,7 @@ export async function startWebConsoleServer(options = {}, deps = {}) {
|
|
|
3537
3547
|
endpointUrl,
|
|
3538
3548
|
apiKey,
|
|
3539
3549
|
bindings,
|
|
3550
|
+
config: configState.normalizedConfig,
|
|
3540
3551
|
captureBackup: false
|
|
3541
3552
|
});
|
|
3542
3553
|
addLog("success", "Factory Droid model bindings updated.", patchResult.bindings.defaultModel || "Default");
|
|
@@ -64,6 +64,139 @@ export const FACTORY_DROID_REASONING_EFFORT_VALUES = Object.freeze([
|
|
|
64
64
|
"high"
|
|
65
65
|
]);
|
|
66
66
|
|
|
67
|
+
function stripFactoryDroidRouterModelIdPrefix(value) {
|
|
68
|
+
const normalized = String(value || "").trim();
|
|
69
|
+
if (normalized.startsWith("custom:")) return normalized.slice("custom:".length).trim();
|
|
70
|
+
return normalized;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function sanitizeFactoryDroidRouterModelIdPart(value) {
|
|
74
|
+
return String(value || "")
|
|
75
|
+
.trim()
|
|
76
|
+
.replace(/[/:]+/g, "-")
|
|
77
|
+
.replace(/\s+/g, "-")
|
|
78
|
+
.replace(/[^A-Za-z0-9._-]+/g, "-")
|
|
79
|
+
.replace(/-+/g, "-")
|
|
80
|
+
.replace(/^-+|-+$/g, "");
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function formatFactoryDroidDisplayNameBase(value) {
|
|
84
|
+
const normalized = String(value || "").trim();
|
|
85
|
+
if (!normalized) return "";
|
|
86
|
+
if (/^gpt(?=[-\s.]|$)/i.test(normalized)) return `GPT${normalized.slice(3)}`;
|
|
87
|
+
if (/^glm(?=[-\s.]|$)/i.test(normalized)) return `GLM${normalized.slice(3)}`;
|
|
88
|
+
if (/^claude(?=[-\s.]|$)/i.test(normalized)) return `Claude${normalized.slice(6)}`;
|
|
89
|
+
return normalized;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function isFactoryDroidRouterModelId(value) {
|
|
93
|
+
const normalized = stripFactoryDroidRouterModelIdPrefix(value);
|
|
94
|
+
return normalized.startsWith("llm-");
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export function parseFactoryDroidRouterModelId(value) {
|
|
98
|
+
const normalized = stripFactoryDroidRouterModelIdPrefix(value);
|
|
99
|
+
if (!normalized.startsWith("llm-")) return null;
|
|
100
|
+
|
|
101
|
+
if (normalized.startsWith("llm-alias:")) {
|
|
102
|
+
const aliasId = normalized.slice("llm-alias:".length).trim();
|
|
103
|
+
return aliasId
|
|
104
|
+
? {
|
|
105
|
+
kind: "alias",
|
|
106
|
+
aliasId,
|
|
107
|
+
routeRef: aliasId
|
|
108
|
+
}
|
|
109
|
+
: null;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (normalized.startsWith("llm-alias-")) {
|
|
113
|
+
const aliasId = normalized.slice("llm-alias-".length).trim();
|
|
114
|
+
return aliasId
|
|
115
|
+
? {
|
|
116
|
+
kind: "alias",
|
|
117
|
+
aliasId,
|
|
118
|
+
routeRef: ""
|
|
119
|
+
}
|
|
120
|
+
: null;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const body = normalized.slice("llm-".length);
|
|
124
|
+
const separatorIndex = body.indexOf(":");
|
|
125
|
+
if (separatorIndex <= 0) return null;
|
|
126
|
+
|
|
127
|
+
const providerId = body.slice(0, separatorIndex).trim();
|
|
128
|
+
const modelId = body.slice(separatorIndex + 1).trim();
|
|
129
|
+
if (!providerId || !modelId) return null;
|
|
130
|
+
|
|
131
|
+
return {
|
|
132
|
+
kind: "model",
|
|
133
|
+
providerId,
|
|
134
|
+
modelId,
|
|
135
|
+
routeRef: `${providerId}/${modelId}`
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export function resolveFactoryDroidRouterModelRef(value) {
|
|
140
|
+
const normalized = String(value || "").trim();
|
|
141
|
+
if (!normalized) return "";
|
|
142
|
+
return parseFactoryDroidRouterModelId(normalized)?.routeRef || normalized;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export function buildFactoryDroidRouterModelId(modelRef, { kind = "" } = {}) {
|
|
146
|
+
const normalizedModelRef = String(modelRef || "").trim();
|
|
147
|
+
if (!normalizedModelRef) return "";
|
|
148
|
+
if (normalizedModelRef.startsWith("custom:llm-")) {
|
|
149
|
+
const parsed = parseFactoryDroidRouterModelId(normalizedModelRef);
|
|
150
|
+
return parsed?.routeRef
|
|
151
|
+
? buildFactoryDroidRouterModelId(parsed.routeRef, { kind: parsed.kind })
|
|
152
|
+
: normalizedModelRef;
|
|
153
|
+
}
|
|
154
|
+
if (normalizedModelRef.startsWith("llm-")) {
|
|
155
|
+
const parsed = parseFactoryDroidRouterModelId(normalizedModelRef);
|
|
156
|
+
return parsed?.routeRef
|
|
157
|
+
? buildFactoryDroidRouterModelId(parsed.routeRef, { kind: parsed.kind })
|
|
158
|
+
: `custom:${normalizedModelRef}`;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const explicitKind = String(kind || "").trim().toLowerCase();
|
|
162
|
+
if (explicitKind === "alias") {
|
|
163
|
+
const aliasId = sanitizeFactoryDroidRouterModelIdPart(normalizedModelRef);
|
|
164
|
+
return aliasId ? `custom:llm-alias-${aliasId}` : "";
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (explicitKind === "model") {
|
|
168
|
+
const separatorIndex = normalizedModelRef.indexOf("/");
|
|
169
|
+
if (separatorIndex <= 0 || separatorIndex >= normalizedModelRef.length - 1) return "";
|
|
170
|
+
const providerId = normalizedModelRef.slice(0, separatorIndex).trim();
|
|
171
|
+
const modelId = normalizedModelRef.slice(separatorIndex + 1).trim();
|
|
172
|
+
const providerSlug = sanitizeFactoryDroidRouterModelIdPart(providerId);
|
|
173
|
+
const modelSlug = sanitizeFactoryDroidRouterModelIdPart(modelId);
|
|
174
|
+
return providerSlug && modelSlug ? `custom:llm-${providerSlug}-${modelSlug}` : "";
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (!normalizedModelRef.includes("/")) {
|
|
178
|
+
return buildFactoryDroidRouterModelId(normalizedModelRef, { kind: "alias" });
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return buildFactoryDroidRouterModelId(normalizedModelRef, { kind: "model" });
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export function buildFactoryDroidRouterDisplayName(modelRef, { kind = "" } = {}) {
|
|
185
|
+
const normalizedModelRef = String(modelRef || "").trim();
|
|
186
|
+
if (!normalizedModelRef) return "";
|
|
187
|
+
|
|
188
|
+
const explicitKind = String(kind || "").trim().toLowerCase();
|
|
189
|
+
const inferredKind = explicitKind || (normalizedModelRef.includes("/") ? "model" : "alias");
|
|
190
|
+
if (inferredKind === "alias") {
|
|
191
|
+
return `[LLM Alias] ${formatFactoryDroidDisplayNameBase(normalizedModelRef)}`;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const modelName = normalizedModelRef.includes("/")
|
|
195
|
+
? normalizedModelRef.slice(normalizedModelRef.indexOf("/") + 1).trim()
|
|
196
|
+
: normalizedModelRef;
|
|
197
|
+
return `[LLM] ${formatFactoryDroidDisplayNameBase(modelName)}`;
|
|
198
|
+
}
|
|
199
|
+
|
|
67
200
|
export function normalizeFactoryDroidReasoningEffort(value) {
|
|
68
201
|
const normalized = String(value || "").trim().toLowerCase();
|
|
69
202
|
return FACTORY_DROID_REASONING_EFFORT_VALUES.includes(normalized) ? normalized : "";
|