claude-scionos 4.2.0 → 4.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.fr.md +7 -6
- package/README.md +7 -6
- package/index.js +22 -11
- package/package.json +4 -4
- package/src/proxy.js +43 -5
- package/src/routerlab.js +42 -18
package/README.fr.md
CHANGED
|
@@ -54,7 +54,7 @@ npx claude-scionos auth login
|
|
|
54
54
|
npx claude-scionos auth login --service llm
|
|
55
55
|
npx claude-scionos auth test
|
|
56
56
|
npx claude-scionos --strategy aws
|
|
57
|
-
npx claude-scionos --service llm --strategy claude-
|
|
57
|
+
npx claude-scionos --service llm --strategy claude-gpt
|
|
58
58
|
npx claude-scionos --strategy aws --no-prompt -p "Résume ce dépôt"
|
|
59
59
|
```
|
|
60
60
|
|
|
@@ -64,17 +64,18 @@ npx claude-scionos --strategy aws --no-prompt -p "Résume ce dépôt"
|
|
|
64
64
|
- `--service llm` bascule le lanceur vers `https://llm.routerlab.ch`
|
|
65
65
|
- `llm` est prévu pour un accès sur invitation
|
|
66
66
|
- les tokens enregistrés avec `auth login --service llm` sont stockés séparément du token RouterLab par défaut
|
|
67
|
-
- `llm` expose pour l'instant `claude-
|
|
68
|
-
- `routerlab` expose aussi `claude-gpt-5.
|
|
67
|
+
- `llm` expose pour l'instant `claude-gpt`, `claude-qwen3.6-plus`, `claude-minimax-m2.7` et `claude-glm-5.1`
|
|
68
|
+
- `routerlab` expose aussi `claude-gpt`, `claude-minimax-m2.7` et `claude-glm-5.1`
|
|
69
69
|
|
|
70
70
|
## Stratégies
|
|
71
71
|
|
|
72
72
|
- `default` : utilise Claude Code normalement sans proxy local
|
|
73
73
|
- `aws` : remappe les familles de modèles Claude vers les variantes Claude AWS de RouterLab
|
|
74
|
-
- `claude-
|
|
75
|
-
|
|
76
|
-
- `claude-gpt-5.4` : force toutes les requêtes vers `claude-gpt-5.4`
|
|
74
|
+
- `claude-gpt` : mappe les requêtes Claude vers la famille `claude-gpt`
|
|
75
|
+
`claude-gpt-5.5 ==> claude-opus-4.7`, `claude-gpt-5.4 ==> claude-sonnet-4.6`, `claude-gpt-5.4-mini ==> claude-gpt-5.4-mini`
|
|
77
76
|
- `claude-qwen3.6-plus` : force toutes les requêtes vers `claude-qwen3.6-plus`
|
|
77
|
+
- `claude-minimax-m2.7` : force toutes les requêtes vers `claude-minimax-m2.7`
|
|
78
|
+
- `claude-glm-5.1` : force toutes les requêtes vers `claude-glm-5.1`
|
|
78
79
|
|
|
79
80
|
Utilise `--list-strategies` pour voir les stratégies disponibles pour le service choisi et leur disponibilité réelle quand un token est disponible.
|
|
80
81
|
|
package/README.md
CHANGED
|
@@ -54,7 +54,7 @@ npx claude-scionos auth login
|
|
|
54
54
|
npx claude-scionos auth login --service llm
|
|
55
55
|
npx claude-scionos auth test
|
|
56
56
|
npx claude-scionos --strategy aws
|
|
57
|
-
npx claude-scionos --service llm --strategy claude-
|
|
57
|
+
npx claude-scionos --service llm --strategy claude-gpt
|
|
58
58
|
npx claude-scionos --strategy aws --no-prompt -p "Summarize this repo"
|
|
59
59
|
```
|
|
60
60
|
|
|
@@ -64,17 +64,18 @@ npx claude-scionos --strategy aws --no-prompt -p "Summarize this repo"
|
|
|
64
64
|
- `--service llm` switches the launcher to `https://llm.routerlab.ch`
|
|
65
65
|
- `llm` is intended for invitation-only access
|
|
66
66
|
- Tokens stored with `auth login --service llm` are kept separate from the default RouterLab token
|
|
67
|
-
- `llm` currently exposes `claude-
|
|
68
|
-
- `routerlab` also exposes `claude-gpt-5.
|
|
67
|
+
- `llm` currently exposes `claude-gpt`, `claude-qwen3.6-plus`, `claude-minimax-m2.7`, and `claude-glm-5.1`
|
|
68
|
+
- `routerlab` also exposes `claude-gpt`, `claude-minimax-m2.7`, and `claude-glm-5.1`
|
|
69
69
|
|
|
70
70
|
## Strategies
|
|
71
71
|
|
|
72
72
|
- `default`: use Claude Code normally without the local proxy
|
|
73
73
|
- `aws`: remap Claude model families to RouterLab AWS-backed Claude variants
|
|
74
|
-
- `claude-
|
|
75
|
-
|
|
76
|
-
- `claude-gpt-5.4`: force all requests to `claude-gpt-5.4`
|
|
74
|
+
- `claude-gpt`: map Claude requests to the `claude-gpt` family
|
|
75
|
+
`claude-gpt-5.5 ==> claude-opus-4.7`, `claude-gpt-5.4 ==> claude-sonnet-4.6`, `claude-gpt-5.4-mini ==> claude-gpt-5.4-mini`
|
|
77
76
|
- `claude-qwen3.6-plus`: force all requests to `claude-qwen3.6-plus`
|
|
77
|
+
- `claude-minimax-m2.7`: force all requests to `claude-minimax-m2.7`
|
|
78
|
+
- `claude-glm-5.1`: force all requests to `claude-glm-5.1`
|
|
78
79
|
|
|
79
80
|
Use `--list-strategies` to see the strategies available for the selected service and their live availability when a token is available.
|
|
80
81
|
|
package/index.js
CHANGED
|
@@ -118,7 +118,7 @@ function showHelp() {
|
|
|
118
118
|
console.log(chalk.gray("Examples"));
|
|
119
119
|
console.log(` ${chalk.cyan("claude-scionos --strategy aws")}`);
|
|
120
120
|
console.log(` ${chalk.cyan("claude-scionos auth login --service llm")}`);
|
|
121
|
-
console.log(` ${chalk.cyan("claude-scionos --service llm --strategy claude-
|
|
121
|
+
console.log(` ${chalk.cyan("claude-scionos --service llm --strategy claude-gpt")}`);
|
|
122
122
|
console.log(` ${chalk.cyan('claude-scionos --strategy aws --no-prompt -p "Summarize this repo"')}`);
|
|
123
123
|
console.log(` ${chalk.cyan("claude-scionos auth test")}`);
|
|
124
124
|
console.log("");
|
|
@@ -159,11 +159,15 @@ function getStrategyIndicator(strategyValue, modelIds, serviceValue) {
|
|
|
159
159
|
}
|
|
160
160
|
|
|
161
161
|
function getStrategyMenuLabel(strategyValue) {
|
|
162
|
-
|
|
162
|
+
const strategy = getServiceStrategies(DEFAULT_SERVICE)
|
|
163
|
+
.concat(getServiceStrategies('llm'))
|
|
164
|
+
.find((entry) => entry.value === strategyValue || entry.aliases?.includes(strategyValue));
|
|
165
|
+
|
|
166
|
+
if (strategy?.value === 'aws') {
|
|
163
167
|
return '💰 aws 50%';
|
|
164
168
|
}
|
|
165
169
|
|
|
166
|
-
return strategyValue;
|
|
170
|
+
return strategy?.selectionName || strategy?.name || strategyValue;
|
|
167
171
|
}
|
|
168
172
|
|
|
169
173
|
function normalizeStrategyValue(strategy) {
|
|
@@ -427,7 +431,9 @@ async function resolveStrategyChoice(parsed, modelIds, serviceConfig) {
|
|
|
427
431
|
};
|
|
428
432
|
|
|
429
433
|
if (parsed.strategy) {
|
|
430
|
-
const strategy = getServiceStrategies(serviceConfig.value).find((entry) =>
|
|
434
|
+
const strategy = getServiceStrategies(serviceConfig.value).find((entry) => (
|
|
435
|
+
entry.value === parsed.strategy || entry.aliases?.includes(parsed.strategy)
|
|
436
|
+
));
|
|
431
437
|
if (!strategy) {
|
|
432
438
|
throw new Error(`Unknown strategy "${parsed.strategy}". Use --list-strategies to inspect the supported values.`);
|
|
433
439
|
}
|
|
@@ -442,12 +448,13 @@ async function resolveStrategyChoice(parsed, modelIds, serviceConfig) {
|
|
|
442
448
|
const strategyChoices = getStrategyChoices(modelIds, serviceConfig.value).map((choice) => {
|
|
443
449
|
const launchReadiness = assessStrategyLaunch(choice.value, modelIds, serviceConfig.value);
|
|
444
450
|
const disabled = hasVerifiedModelIds(modelIds) && !launchReadiness.ready ? launchReadiness.note : false;
|
|
451
|
+
const menuLabel = getStrategyMenuLabel(choice.value);
|
|
445
452
|
return {
|
|
446
453
|
...choice,
|
|
447
454
|
disabled,
|
|
448
|
-
name: `${getStrategyIndicator(choice.value, modelIds, serviceConfig.value)} ${
|
|
449
|
-
short:
|
|
450
|
-
description:
|
|
455
|
+
name: `${getStrategyIndicator(choice.value, modelIds, serviceConfig.value)} ${menuLabel}`,
|
|
456
|
+
short: menuLabel,
|
|
457
|
+
description: choice.description
|
|
451
458
|
};
|
|
452
459
|
});
|
|
453
460
|
|
|
@@ -455,9 +462,12 @@ async function resolveStrategyChoice(parsed, modelIds, serviceConfig) {
|
|
|
455
462
|
throw new Error(`No launchable strategy is available on ${serviceConfig.availabilityLabel}.`);
|
|
456
463
|
}
|
|
457
464
|
|
|
458
|
-
const spacedStrategyChoices =
|
|
459
|
-
|
|
460
|
-
|
|
465
|
+
const spacedStrategyChoices = [
|
|
466
|
+
new Separator(' '),
|
|
467
|
+
...strategyChoices.flatMap((choice, index) => (
|
|
468
|
+
index === strategyChoices.length - 1 ? [choice] : [choice, new Separator(' ')]
|
|
469
|
+
))
|
|
470
|
+
];
|
|
461
471
|
|
|
462
472
|
const selected = await select({
|
|
463
473
|
message: 'Select Model Strategy:',
|
|
@@ -472,7 +482,7 @@ function showStrategies(modelIds = null, serviceConfig) {
|
|
|
472
482
|
const strategies = listStrategies(modelIds, serviceConfig.value);
|
|
473
483
|
showSection('Strategies', strategies.map((strategy) => {
|
|
474
484
|
const indicator = getStrategyIndicator(strategy.value, modelIds, serviceConfig.value);
|
|
475
|
-
return `${indicator} ${chalk.white(getStrategyMenuLabel(strategy.value))} ${chalk.gray(`(${strategy.value})`)}\n ${strategy.description}`;
|
|
485
|
+
return `${indicator} ${chalk.white(getStrategyMenuLabel(strategy.value))} ${chalk.gray(`(${strategy.value})`)}\n ${[strategy.description, strategy.availability.note].filter(Boolean).join(' ')}`;
|
|
476
486
|
}));
|
|
477
487
|
}
|
|
478
488
|
|
|
@@ -694,6 +704,7 @@ async function main() {
|
|
|
694
704
|
}
|
|
695
705
|
|
|
696
706
|
const proxyInfo = await startProxyServer(modelChoice, token, {
|
|
707
|
+
availableModels: validation.models,
|
|
697
708
|
baseUrl: resolveServiceBaseUrl(serviceConfig.value),
|
|
698
709
|
debug: isDebug,
|
|
699
710
|
onDebug: (message) => console.log(chalk.yellow(message)),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-scionos",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.3.1",
|
|
4
4
|
"description": "RouterLab launcher, strategy proxy and secure token wrapper for Claude Code CLI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
@@ -43,12 +43,12 @@
|
|
|
43
43
|
},
|
|
44
44
|
"private": false,
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@inquirer/prompts": "^8.4.
|
|
46
|
+
"@inquirer/prompts": "^8.4.2"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@eslint/js": "^10.0.1",
|
|
50
|
-
"eslint": "^10.2.
|
|
50
|
+
"eslint": "^10.2.1",
|
|
51
51
|
"globals": "^17.5.0",
|
|
52
|
-
"vitest": "^4.1.
|
|
52
|
+
"vitest": "^4.1.5"
|
|
53
53
|
}
|
|
54
54
|
}
|
package/src/proxy.js
CHANGED
|
@@ -52,9 +52,42 @@ function buildProxyRequestOptions(url, method, upstreamHeaders, validToken, body
|
|
|
52
52
|
};
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
function
|
|
55
|
+
function getPreferredClaudeGptModel(requestedModel = '') {
|
|
56
|
+
if (requestedModel.includes('haiku') || requestedModel.includes('mini')) {
|
|
57
|
+
return 'claude-gpt-5.4-mini';
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (requestedModel.includes('opus')) {
|
|
61
|
+
return 'claude-gpt-5.5';
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return 'claude-gpt-5.4';
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function resolveMappedModel(targetModel, requestedModel = '', availableModels = []) {
|
|
56
68
|
if (targetModel !== 'aws') {
|
|
57
|
-
|
|
69
|
+
if (targetModel !== 'claude-gpt') {
|
|
70
|
+
return targetModel;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const preferredModel = getPreferredClaudeGptModel(requestedModel);
|
|
74
|
+
const availableClaudeGptModels = Array.isArray(availableModels)
|
|
75
|
+
? availableModels.filter((model) => model.startsWith('claude-gpt-'))
|
|
76
|
+
: [];
|
|
77
|
+
|
|
78
|
+
if (availableClaudeGptModels.length === 0) {
|
|
79
|
+
return preferredModel;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (availableClaudeGptModels.includes(preferredModel)) {
|
|
83
|
+
return preferredModel;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return (
|
|
87
|
+
availableClaudeGptModels.find((model) => model === 'claude-gpt-5.4')
|
|
88
|
+
?? availableClaudeGptModels[0]
|
|
89
|
+
?? preferredModel
|
|
90
|
+
);
|
|
58
91
|
}
|
|
59
92
|
|
|
60
93
|
if (requestedModel.includes('haiku')) {
|
|
@@ -94,7 +127,7 @@ function isAllowedProxyRoute(req) {
|
|
|
94
127
|
}
|
|
95
128
|
|
|
96
129
|
async function handleMessageRequest(req, res, options) {
|
|
97
|
-
const {baseUrl, debug, onDebug, onError, targetModel, validToken} = options;
|
|
130
|
+
const {availableModels = [], baseUrl, debug, onDebug, onError, targetModel, validToken} = options;
|
|
98
131
|
const chunks = [];
|
|
99
132
|
const maxSize = 100 * 1024 * 1024;
|
|
100
133
|
let totalSize = 0;
|
|
@@ -122,9 +155,13 @@ async function handleMessageRequest(req, res, options) {
|
|
|
122
155
|
}
|
|
123
156
|
|
|
124
157
|
if (bodyJson?.model) {
|
|
125
|
-
const
|
|
158
|
+
const preferredModel = resolveMappedModel(targetModel, bodyJson.model);
|
|
159
|
+
const newModel = resolveMappedModel(targetModel, bodyJson.model, availableModels);
|
|
126
160
|
if (debug) {
|
|
127
161
|
onDebug(`[Proxy] Swapping model ${bodyJson.model} -> ${newModel}`);
|
|
162
|
+
if (preferredModel !== newModel) {
|
|
163
|
+
onDebug(`[Proxy] Fallback applied because ${preferredModel} is not available for this token`);
|
|
164
|
+
}
|
|
128
165
|
}
|
|
129
166
|
|
|
130
167
|
bodyJson.model = newModel;
|
|
@@ -216,6 +253,7 @@ async function forwardRequest(req, res, options) {
|
|
|
216
253
|
|
|
217
254
|
function startProxyServer(targetModel, validToken, options = {}) {
|
|
218
255
|
const {
|
|
256
|
+
availableModels = [],
|
|
219
257
|
baseUrl = BASE_URL,
|
|
220
258
|
debug = false,
|
|
221
259
|
onDebug = () => {},
|
|
@@ -236,6 +274,7 @@ function startProxyServer(targetModel, validToken, options = {}) {
|
|
|
236
274
|
}
|
|
237
275
|
|
|
238
276
|
handleMessageRequest(req, res, {
|
|
277
|
+
availableModels,
|
|
239
278
|
baseUrl,
|
|
240
279
|
debug,
|
|
241
280
|
onDebug,
|
|
@@ -261,4 +300,3 @@ export {
|
|
|
261
300
|
resolveMappedModel,
|
|
262
301
|
startProxyServer,
|
|
263
302
|
};
|
|
264
|
-
|
package/src/routerlab.js
CHANGED
|
@@ -15,7 +15,7 @@ const SERVICES = {
|
|
|
15
15
|
secureStorageAccount: 'routerlab-token',
|
|
16
16
|
secureStorageLabel: 'RouterLab Token',
|
|
17
17
|
secureStorageFileName: 'routerlab-token.secure.txt',
|
|
18
|
-
strategyValues: ['default', 'aws', 'claude-gpt
|
|
18
|
+
strategyValues: ['default', 'aws', 'claude-gpt', 'claude-minimax-m2.7', 'claude-glm-5.1'],
|
|
19
19
|
},
|
|
20
20
|
llm: {
|
|
21
21
|
value: 'llm',
|
|
@@ -28,7 +28,7 @@ const SERVICES = {
|
|
|
28
28
|
secureStorageAccount: 'routerlab-llm-token',
|
|
29
29
|
secureStorageLabel: 'RouterLab LLM Token',
|
|
30
30
|
secureStorageFileName: 'routerlab-llm-token.secure.txt',
|
|
31
|
-
strategyValues: ['claude-
|
|
31
|
+
strategyValues: ['claude-gpt', 'claude-qwen3.6-plus', 'claude-minimax-m2.7', 'claude-glm-5.1'],
|
|
32
32
|
},
|
|
33
33
|
};
|
|
34
34
|
const DEFAULT_SERVICE = 'routerlab';
|
|
@@ -55,17 +55,17 @@ const AWS_CLAUDE_MODELS = [
|
|
|
55
55
|
const STRATEGIES = [
|
|
56
56
|
{
|
|
57
57
|
value: 'default',
|
|
58
|
-
name: '
|
|
58
|
+
name: 'Claude Native',
|
|
59
59
|
description: 'Uses Claude natively without a local proxy.',
|
|
60
|
-
selectionName: '
|
|
60
|
+
selectionName: 'Claude Native (Opus 4.7)',
|
|
61
61
|
selectionDescription: 'Standard behavior. Claude decides which model to use.',
|
|
62
62
|
requiredModels: DEFAULT_CLAUDE_MODELS,
|
|
63
63
|
},
|
|
64
64
|
{
|
|
65
65
|
value: 'aws',
|
|
66
|
-
name: 'Claude AWS',
|
|
66
|
+
name: 'Claude via AWS',
|
|
67
67
|
description: 'Maps Claude requests to AWS-backed Claude variants.',
|
|
68
|
-
selectionName: 'Claude AWS (-50%
|
|
68
|
+
selectionName: 'Claude via AWS (Opus 4.6, -50%)',
|
|
69
69
|
selectionDescription: 'Map models to aws-claude-haiku, aws-claude-sonnet, aws-claude-opus.',
|
|
70
70
|
requiredModels: AWS_CLAUDE_MODELS,
|
|
71
71
|
mappedModels: AWS_CLAUDE_MODELS,
|
|
@@ -85,11 +85,13 @@ const STRATEGIES = [
|
|
|
85
85
|
mappedModels: ['claude-minimax-m2.5'],
|
|
86
86
|
},
|
|
87
87
|
{
|
|
88
|
-
value: 'claude-gpt
|
|
89
|
-
name: 'GPT
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
88
|
+
value: 'claude-gpt',
|
|
89
|
+
name: 'OpenAI GPT',
|
|
90
|
+
selectionName: 'OpenAI GPT (5.5, 5.4, 5.4-mini)',
|
|
91
|
+
description: 'Maps Claude requests to the claude-gpt family. Opus 4.7 => claude-gpt-5.5, Sonnet 4.6 => claude-gpt-5.4, Haiku => claude-gpt-5.4-mini.',
|
|
92
|
+
selectionDescription: 'Opus 4.7 => claude-gpt-5.5, Sonnet 4.6 => claude-gpt-5.4, Haiku => claude-gpt-5.4-mini.',
|
|
93
|
+
aliases: ['claude-gpt-5.4'],
|
|
94
|
+
verificationModels: ['claude-gpt-5.4'],
|
|
93
95
|
},
|
|
94
96
|
{
|
|
95
97
|
value: 'claude-qwen3.6-plus',
|
|
@@ -98,6 +100,20 @@ const STRATEGIES = [
|
|
|
98
100
|
selectionDescription: 'Forces all requests to claude-qwen3.6-plus.',
|
|
99
101
|
mappedModels: ['claude-qwen3.6-plus'],
|
|
100
102
|
},
|
|
103
|
+
{
|
|
104
|
+
value: 'claude-minimax-m2.7',
|
|
105
|
+
name: 'MiniMax M2.7',
|
|
106
|
+
description: 'Forces all requests to claude-minimax-m2.7.',
|
|
107
|
+
selectionDescription: 'Forces all requests to claude-minimax-m2.7.',
|
|
108
|
+
mappedModels: ['claude-minimax-m2.7'],
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
value: 'claude-glm-5.1',
|
|
112
|
+
name: 'GLM-5.1',
|
|
113
|
+
description: 'Forces all requests to claude-glm-5.1.',
|
|
114
|
+
selectionDescription: 'Forces all requests to claude-glm-5.1.',
|
|
115
|
+
mappedModels: ['claude-glm-5.1'],
|
|
116
|
+
},
|
|
101
117
|
];
|
|
102
118
|
|
|
103
119
|
async function fetchModels(apiKey, options = {}) {
|
|
@@ -191,7 +207,7 @@ function getServiceConfig(serviceValue = DEFAULT_SERVICE) {
|
|
|
191
207
|
return SERVICES[normalizeServiceValue(serviceValue)] ?? null;
|
|
192
208
|
}
|
|
193
209
|
|
|
194
|
-
function resolveServiceBaseUrl(serviceValue = DEFAULT_SERVICE, env =
|
|
210
|
+
function resolveServiceBaseUrl(serviceValue = DEFAULT_SERVICE, env = {}) {
|
|
195
211
|
return env.ANTHROPIC_BASE_URL?.trim() || getServiceConfig(serviceValue)?.baseUrl || BASE_URL;
|
|
196
212
|
}
|
|
197
213
|
|
|
@@ -245,12 +261,19 @@ function getServiceStrategies(serviceValue = DEFAULT_SERVICE) {
|
|
|
245
261
|
.filter(Boolean);
|
|
246
262
|
}
|
|
247
263
|
|
|
264
|
+
function normalizeStrategyValue(strategyValue) {
|
|
265
|
+
return strategyValue === 'claude-gpt-5.4' ? 'claude-gpt' : strategyValue;
|
|
266
|
+
}
|
|
267
|
+
|
|
248
268
|
function findStrategy(strategyValue, serviceValue = DEFAULT_SERVICE) {
|
|
249
|
-
|
|
269
|
+
const normalizedValue = normalizeStrategyValue(strategyValue);
|
|
270
|
+
return getServiceStrategies(serviceValue).find((strategy) => (
|
|
271
|
+
strategy.value === normalizedValue || strategy.aliases?.includes(strategyValue)
|
|
272
|
+
)) ?? null;
|
|
250
273
|
}
|
|
251
274
|
|
|
252
275
|
function getRequiredModels(strategy) {
|
|
253
|
-
return strategy?.requiredModels ?? strategy?.mappedModels ?? [];
|
|
276
|
+
return strategy?.requiredModels ?? strategy?.verificationModels ?? strategy?.mappedModels ?? [];
|
|
254
277
|
}
|
|
255
278
|
|
|
256
279
|
function hasVerifiedModelIds(modelIds) {
|
|
@@ -391,17 +414,18 @@ function assessStrategyLaunch(strategyValue, modelIds = [], serviceValue = DEFAU
|
|
|
391
414
|
}
|
|
392
415
|
|
|
393
416
|
function getFallbackStrategy(strategyValue, modelIds = [], serviceValue = DEFAULT_SERVICE) {
|
|
417
|
+
const normalizedValue = normalizeStrategyValue(strategyValue);
|
|
394
418
|
if (hasExploitableModelIds(modelIds, serviceValue)) {
|
|
395
|
-
return assessStrategyLaunch(
|
|
419
|
+
return assessStrategyLaunch(normalizedValue, modelIds, serviceValue).ready ? normalizedValue : null;
|
|
396
420
|
}
|
|
397
421
|
|
|
398
|
-
const availability = assessStrategy(
|
|
399
|
-
return availability.level === 'unavailable' ? null :
|
|
422
|
+
const availability = assessStrategy(normalizedValue, modelIds, serviceValue);
|
|
423
|
+
return availability.level === 'unavailable' ? null : normalizedValue;
|
|
400
424
|
}
|
|
401
425
|
|
|
402
426
|
function getStrategyChoices(modelIds = [], serviceValue = DEFAULT_SERVICE) {
|
|
403
427
|
return listStrategies(modelIds, serviceValue).map((strategy) => ({
|
|
404
|
-
name: strategy.value,
|
|
428
|
+
name: strategy.selectionName ?? strategy.name ?? strategy.value,
|
|
405
429
|
value: strategy.value,
|
|
406
430
|
description: strategy.selectionDescription ?? strategy.description,
|
|
407
431
|
}));
|