claude-scionos 4.3.2 → 4.3.4

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 CHANGED
@@ -54,7 +54,10 @@ 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
58
  npx claude-scionos --service llm --strategy claude-gpt
59
+ npx claude-scionos --service llm --strategy claude-gpt-special
60
+ npx claude-scionos --service llm --strategy deepseek-v4-beta
58
61
  npx claude-scionos --strategy aws --no-prompt -p "Résume ce dépôt"
59
62
  ```
60
63
 
@@ -64,15 +67,18 @@ npx claude-scionos --strategy aws --no-prompt -p "Résume ce dépôt"
64
67
  - `--service llm` bascule le lanceur vers `https://llm.routerlab.ch`
65
68
  - `llm` est prévu pour un accès sur invitation
66
69
  - 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-gpt`, `claude-qwen3.6-plus`, `claude-minimax-m2.7` et `claude-glm-5.1`
70
+ - `llm` expose pour l'instant `claude`, `claude-gpt`, `claude-gpt-special` et `deepseek-v4-beta`
68
71
  - `routerlab` expose aussi `claude-gpt`, `claude-minimax-m2.7` et `claude-glm-5.1`
69
72
 
70
73
  ## Stratégies
71
74
 
72
75
  - `default` : utilise Claude Code normalement sans proxy local
73
76
  - `aws` : remappe les familles de modèles Claude vers les variantes Claude AWS de RouterLab
77
+ - `claude` : remappe les familles de modèles Claude sur `--service llm` vers les variantes Claude standard `claude-haiku-4-5-20251001`, `claude-sonnet-4-6` et `claude-opus-4-6`
74
78
  - `claude-gpt` : mappe les requêtes Claude vers la famille `claude-gpt`
75
79
  `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`
80
+ - `claude-gpt-special` : sur `--service llm`, force toutes les requêtes vers `claude-gpt-5.4-sp`
81
+ - `deepseek-v4-beta` : sur `--service llm`, mappe les requêtes Claude vers `deepseek-v4-pro` pour opus et `deepseek-v4-flash` pour sonnet ou haiku
76
82
  - `claude-qwen3.6-plus` : force toutes les requêtes vers `claude-qwen3.6-plus`
77
83
  - `claude-minimax-m2.7` : force toutes les requêtes vers `claude-minimax-m2.7`
78
84
  - `claude-glm-5.1` : force toutes les requêtes vers `claude-glm-5.1`
package/README.md CHANGED
@@ -54,7 +54,10 @@ 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
58
  npx claude-scionos --service llm --strategy claude-gpt
59
+ npx claude-scionos --service llm --strategy claude-gpt-special
60
+ npx claude-scionos --service llm --strategy deepseek-v4-beta
58
61
  npx claude-scionos --strategy aws --no-prompt -p "Summarize this repo"
59
62
  ```
60
63
 
@@ -64,15 +67,18 @@ npx claude-scionos --strategy aws --no-prompt -p "Summarize this repo"
64
67
  - `--service llm` switches the launcher to `https://llm.routerlab.ch`
65
68
  - `llm` is intended for invitation-only access
66
69
  - Tokens stored with `auth login --service llm` are kept separate from the default RouterLab token
67
- - `llm` currently exposes `claude-gpt`, `claude-qwen3.6-plus`, `claude-minimax-m2.7`, and `claude-glm-5.1`
70
+ - `llm` currently exposes `claude`, `claude-gpt`, `claude-gpt-special`, and `deepseek-v4-beta`
68
71
  - `routerlab` also exposes `claude-gpt`, `claude-minimax-m2.7`, and `claude-glm-5.1`
69
72
 
70
73
  ## Strategies
71
74
 
72
75
  - `default`: use Claude Code normally without the local proxy
73
76
  - `aws`: remap Claude model families to RouterLab AWS-backed Claude variants
77
+ - `claude`: remap Claude model families on `--service llm` to the standard Claude variants `claude-haiku-4-5-20251001`, `claude-sonnet-4-6`, and `claude-opus-4-6`
74
78
  - `claude-gpt`: map Claude requests to the `claude-gpt` family
75
79
  `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`
80
+ - `claude-gpt-special`: on `--service llm`, force all requests to `claude-gpt-5.4-sp`
81
+ - `deepseek-v4-beta`: on `--service llm`, map Claude requests to `deepseek-v4-pro` for opus and `deepseek-v4-flash` for sonnet or haiku
76
82
  - `claude-qwen3.6-plus`: force all requests to `claude-qwen3.6-plus`
77
83
  - `claude-minimax-m2.7`: force all requests to `claude-minimax-m2.7`
78
84
  - `claude-glm-5.1`: force all requests to `claude-glm-5.1`
package/index.js CHANGED
@@ -562,11 +562,16 @@ async function runDoctor(serviceConfig) {
562
562
  showStatus('Env token', getEnvironmentToken() ? 'ok' : 'warn', getEnvironmentToken() ? 'available' : 'not set');
563
563
  console.log('');
564
564
 
565
- const candidate = getAvailableTokenCandidate(serviceConfig.value);
565
+ const envToken = getEnvironmentToken();
566
+ const candidate = envToken
567
+ ? { token: envToken, source: 'environment' }
568
+ : { token: null, source: storedStatus.stored ? 'secure-store' : 'none' };
566
569
  let validation = null;
567
570
 
568
571
  if (!candidate.token) {
569
- showStatus(`${serviceConfig.tokenPromptLabel} auth`, 'warn', 'Skipped: no environment or stored token available');
572
+ showStatus(`${serviceConfig.tokenPromptLabel} auth`, 'warn', storedStatus.stored
573
+ ? 'Skipped: stored token available but not validated during doctor on Windows'
574
+ : 'Skipped: no environment or stored token available');
570
575
  } else {
571
576
  validation = await validateToken(candidate.token, {
572
577
  baseUrl: resolveServiceBaseUrl(serviceConfig.value),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-scionos",
3
- "version": "4.3.2",
3
+ "version": "4.3.4",
4
4
  "description": "RouterLab launcher, strategy proxy and secure token wrapper for Claude Code CLI",
5
5
  "type": "module",
6
6
  "main": "index.js",
package/src/proxy.js CHANGED
@@ -64,7 +64,73 @@ function getPreferredClaudeGptModel(requestedModel = '') {
64
64
  return 'claude-gpt-5.4';
65
65
  }
66
66
 
67
+ function getPreferredClaudeModel(requestedModel = '') {
68
+ if (requestedModel.includes('haiku') || requestedModel.includes('mini')) {
69
+ return 'claude-haiku-4-5-20251001';
70
+ }
71
+
72
+ if (requestedModel.includes('opus')) {
73
+ return 'claude-opus-4-6';
74
+ }
75
+
76
+ return 'claude-sonnet-4-6';
77
+ }
78
+
79
+ function getPreferredDeepseekV4Model(requestedModel = '') {
80
+ if (requestedModel.includes('opus')) {
81
+ return 'deepseek-v4-pro';
82
+ }
83
+
84
+ return 'deepseek-v4-flash';
85
+ }
86
+
67
87
  function resolveMappedModel(targetModel, requestedModel = '', availableModels = []) {
88
+ if (targetModel === 'claude') {
89
+ const preferredModel = getPreferredClaudeModel(requestedModel);
90
+ const availableClaudeModels = Array.isArray(availableModels)
91
+ ? availableModels.filter((model) => model.startsWith('claude-') && !model.startsWith('claude-gpt-'))
92
+ : [];
93
+
94
+ if (availableClaudeModels.length === 0) {
95
+ return preferredModel;
96
+ }
97
+
98
+ if (availableClaudeModels.includes(preferredModel)) {
99
+ return preferredModel;
100
+ }
101
+
102
+ return (
103
+ availableClaudeModels.find((model) => model === 'claude-sonnet-4-6')
104
+ ?? availableClaudeModels[0]
105
+ ?? preferredModel
106
+ );
107
+ }
108
+
109
+ if (targetModel === 'claude-gpt-special') {
110
+ return 'claude-gpt-5.4-sp';
111
+ }
112
+
113
+ if (targetModel === 'deepseek-v4-beta') {
114
+ const preferredModel = getPreferredDeepseekV4Model(requestedModel);
115
+ const availableDeepseekModels = Array.isArray(availableModels)
116
+ ? availableModels.filter((model) => model === 'deepseek-v4-pro' || model === 'deepseek-v4-flash')
117
+ : [];
118
+
119
+ if (availableDeepseekModels.length === 0) {
120
+ return preferredModel;
121
+ }
122
+
123
+ if (availableDeepseekModels.includes(preferredModel)) {
124
+ return preferredModel;
125
+ }
126
+
127
+ return (
128
+ availableDeepseekModels.find((model) => model === 'deepseek-v4-flash')
129
+ ?? availableDeepseekModels[0]
130
+ ?? preferredModel
131
+ );
132
+ }
133
+
68
134
  if (targetModel !== 'aws') {
69
135
  if (targetModel !== 'claude-gpt') {
70
136
  return targetModel;
package/src/routerlab.js CHANGED
@@ -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-gpt', 'claude-qwen3.6-plus', 'claude-minimax-m2.7', 'claude-glm-5.1'],
31
+ strategyValues: ['claude', 'claude-gpt', 'claude-gpt-special', 'deepseek-v4-beta'],
32
32
  },
33
33
  };
34
34
  const DEFAULT_SERVICE = 'routerlab';
@@ -84,6 +84,15 @@ const STRATEGIES = [
84
84
  selectionDescription: 'Forces all requests to claude-minimax-m2.5.',
85
85
  mappedModels: ['claude-minimax-m2.5'],
86
86
  },
87
+ {
88
+ value: 'claude',
89
+ name: 'Claude',
90
+ description: 'Maps Claude requests to standard Claude variants via a local proxy.',
91
+ selectionName: 'Claude (Opus 4.6)',
92
+ selectionDescription: 'Map models to claude-haiku, claude-sonnet, claude-opus.',
93
+ requiredModels: DEFAULT_CLAUDE_MODELS,
94
+ mappedModels: DEFAULT_CLAUDE_MODELS,
95
+ },
87
96
  {
88
97
  value: 'claude-gpt',
89
98
  name: 'OpenAI GPT',
@@ -93,6 +102,22 @@ const STRATEGIES = [
93
102
  aliases: ['claude-gpt-5.4'],
94
103
  verificationModels: ['claude-gpt-5.4'],
95
104
  },
105
+ {
106
+ value: 'claude-gpt-special',
107
+ name: 'OpenAI GPT special',
108
+ selectionName: 'OpenAI GPT special (only gpt-5.4)',
109
+ description: 'Forces all requests to claude-gpt-5.4-sp.',
110
+ selectionDescription: 'Forces all requests to claude-gpt-5.4-sp.',
111
+ mappedModels: ['claude-gpt-5.4-sp'],
112
+ },
113
+ {
114
+ value: 'deepseek-v4-beta',
115
+ name: 'deepseek-v4 beta',
116
+ selectionName: 'deepseek-v4 beta',
117
+ description: 'Maps Claude requests to the deepseek-v4 family. Opus 4.7 => deepseek-v4-pro, Sonnet 4.6 => deepseek-v4-flash, Haiku => deepseek-v4-flash.',
118
+ selectionDescription: 'Opus 4.7 => deepseek-v4-pro, Sonnet 4.6 => deepseek-v4-flash, Haiku => deepseek-v4-flash.',
119
+ verificationModels: ['deepseek-v4-pro', 'deepseek-v4-flash'],
120
+ },
96
121
  {
97
122
  value: 'claude-qwen3.6-plus',
98
123
  name: 'Qwen3.6 Plus',
@@ -262,7 +287,15 @@ function getServiceStrategies(serviceValue = DEFAULT_SERVICE) {
262
287
  }
263
288
 
264
289
  function normalizeStrategyValue(strategyValue) {
265
- return strategyValue === 'claude-gpt-5.4' ? 'claude-gpt' : strategyValue;
290
+ if (strategyValue === 'claude-gpt-5.4') {
291
+ return 'claude-gpt';
292
+ }
293
+
294
+ if (strategyValue === 'claude-gpt-5.4-sp') {
295
+ return 'claude-gpt-special';
296
+ }
297
+
298
+ return strategyValue;
266
299
  }
267
300
 
268
301
  function findStrategy(strategyValue, serviceValue = DEFAULT_SERVICE) {
@@ -662,6 +695,15 @@ function deleteStoredToken(serviceValue = DEFAULT_SERVICE) {
662
695
 
663
696
  function getStoredTokenStatus(serviceValue = DEFAULT_SERVICE) {
664
697
  const storage = getSecureStorageBackend();
698
+
699
+ if (process.platform === 'win32') {
700
+ const tokenFile = getWindowsTokenFile(serviceValue);
701
+ return {
702
+ ...storage,
703
+ stored: fs.existsSync(tokenFile) && hasNonEmptyWindowsTokenFile(tokenFile),
704
+ };
705
+ }
706
+
665
707
  const storedToken = getStoredToken(serviceValue);
666
708
  return {
667
709
  ...storage,