claude-scionos 3.0.2 → 3.0.5
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/.claude/settings.local.json +9 -0
- package/CHANGELOG.md +25 -0
- package/index.js +69 -21
- package/package.json +7 -10
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,31 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [3.0.5] - 2026-03-16
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- **Dynamic AWS Models**: Integrated dynamic routing for AWS 50% discount models (`haiku`, `sonnet`, `opus`) in the local proxy.
|
|
12
|
+
- **Model Selection**: Cleaned up the initial prompt menu to offer 4 robust strategic choices including GLM-5 and MiniMax M2.5.
|
|
13
|
+
|
|
14
|
+
## [3.0.4] - 2026-03-16
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
- **Dependencies**: Replaced `chalk`, `cross-spawn`, and `undici` with Node.js >= 22 native APIs (`util.styleText`, `child_process.spawn`, `fetch`).
|
|
18
|
+
- **Dependencies**: Updated development and production packages to the latest versions.
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
- **Code Quality**: Fixed `Token` ESLint assignment warnings and improved formatting compatibility.
|
|
22
|
+
|
|
23
|
+
## [3.0.3] - 2026-02-18
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
- **Model**: Renamed `GLM-4.7` to `Kimi K2.5` (`kimi-k2.5`) in the model selection menu.
|
|
27
|
+
|
|
28
|
+
### Fixed
|
|
29
|
+
- **Token Validation**: Added a 10-second `AbortController` timeout on `validateToken()` to prevent the prompt from hanging on unresponsive network.
|
|
30
|
+
- **Proxy Memory**: Added a 100 MB cap on incoming request buffers; oversized requests now return HTTP 413 instead of causing a memory overflow.
|
|
31
|
+
- **CI/CD Compatibility**: `console.clear()` is now skipped when the `CI` environment variable is set or `--no-clear` is passed, preventing broken output in pipelines.
|
|
32
|
+
|
|
8
33
|
## [3.0.2] - 2026-01-11
|
|
9
34
|
|
|
10
35
|
### Added
|
package/index.js
CHANGED
|
@@ -1,8 +1,26 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import { styleText } from 'node:util';
|
|
4
|
+
const chalk = {
|
|
5
|
+
hex: (color) => {
|
|
6
|
+
if (color === '#3b82f6') return (t) => styleText('blueBright', t);
|
|
7
|
+
if (color === '#a855f7') return (t) => styleText('magentaBright', t);
|
|
8
|
+
if (color === '#D97757') return (t) => styleText('redBright', t);
|
|
9
|
+
return (t) => t;
|
|
10
|
+
},
|
|
11
|
+
white: (t) => styleText('white', t),
|
|
12
|
+
gray: (t) => styleText('gray', t),
|
|
13
|
+
yellow: (t) => styleText('yellow', t),
|
|
14
|
+
red: (t) => styleText('red', t),
|
|
15
|
+
cyan: (t) => styleText('cyan', t),
|
|
16
|
+
redBright: (t) => styleText('redBright', t),
|
|
17
|
+
blueBright: (t) => styleText('blueBright', t),
|
|
18
|
+
green: (t) => styleText('green', t),
|
|
19
|
+
magenta: (t) => styleText('magenta', t),
|
|
20
|
+
bold: (t) => styleText('bold', t)
|
|
21
|
+
};
|
|
4
22
|
import { password, confirm, select } from '@inquirer/prompts';
|
|
5
|
-
import spawn from '
|
|
23
|
+
import { spawn } from 'node:child_process';
|
|
6
24
|
import updateNotifier from 'update-notifier';
|
|
7
25
|
import process from 'node:process';
|
|
8
26
|
import http from 'node:http';
|
|
@@ -24,7 +42,7 @@ const BASE_URL = "https://routerlab.ch";
|
|
|
24
42
|
* Displays the application banner
|
|
25
43
|
*/
|
|
26
44
|
function showBanner() {
|
|
27
|
-
console.clear();
|
|
45
|
+
if (!process.env.CI && !process.argv.includes('--no-clear')) console.clear();
|
|
28
46
|
const p = chalk.hex('#3b82f6'); // Primary (Scio)
|
|
29
47
|
const s = chalk.hex('#a855f7'); // Secondary (Nos)
|
|
30
48
|
const c = chalk.hex('#D97757'); // Claude Orange
|
|
@@ -35,7 +53,7 @@ function showBanner() {
|
|
|
35
53
|
console.log("");
|
|
36
54
|
console.log(border(" ┌──────────────────────────────────────────────────────────┐"));
|
|
37
55
|
console.log(border(" │ │"));
|
|
38
|
-
console.log(border(" │ ") +
|
|
56
|
+
console.log(border(" │ ") + chalk.bold(p("Scio")) + chalk.bold(s("Nos")) + chalk.bold(w(" ✕ ")) + chalk.bold(c("Claude Code")) + border(" │"));
|
|
39
57
|
console.log(border(" │ │"));
|
|
40
58
|
console.log(border(" └──────────────────────────────────────────────────────────┘"));
|
|
41
59
|
console.log(g(` v${pkg.version}`));
|
|
@@ -47,13 +65,17 @@ function showBanner() {
|
|
|
47
65
|
*/
|
|
48
66
|
async function validateToken(apiKey) {
|
|
49
67
|
try {
|
|
68
|
+
const controller = new AbortController();
|
|
69
|
+
const timeoutId = setTimeout(() => controller.abort(), 10000);
|
|
50
70
|
const response = await fetch(`${BASE_URL}/v1/models`, {
|
|
51
71
|
method: 'GET',
|
|
52
72
|
headers: {
|
|
53
73
|
'x-api-key': apiKey,
|
|
54
74
|
'anthropic-version': '2023-06-01'
|
|
55
|
-
}
|
|
75
|
+
},
|
|
76
|
+
signal: controller.signal
|
|
56
77
|
});
|
|
78
|
+
clearTimeout(timeoutId);
|
|
57
79
|
|
|
58
80
|
if (response.ok) {
|
|
59
81
|
return { valid: true };
|
|
@@ -91,7 +113,18 @@ function startProxyServer(targetModel, validToken) {
|
|
|
91
113
|
// Claude Code uses /v1/messages
|
|
92
114
|
if (req.method === 'POST' && req.url.includes('/messages')) {
|
|
93
115
|
const chunks = [];
|
|
94
|
-
|
|
116
|
+
const MAX_SIZE = 100 * 1024 * 1024; // 100MB
|
|
117
|
+
let totalSize = 0;
|
|
118
|
+
req.on('data', chunk => {
|
|
119
|
+
totalSize += chunk.length;
|
|
120
|
+
if (totalSize > MAX_SIZE) {
|
|
121
|
+
res.writeHead(413);
|
|
122
|
+
res.end(JSON.stringify({ error: { message: 'Request too large' } }));
|
|
123
|
+
req.destroy();
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
chunks.push(chunk);
|
|
127
|
+
});
|
|
95
128
|
req.on('end', async () => {
|
|
96
129
|
try {
|
|
97
130
|
const bodyBuffer = Buffer.concat(chunks);
|
|
@@ -105,13 +138,22 @@ function startProxyServer(targetModel, validToken) {
|
|
|
105
138
|
|
|
106
139
|
// THE MAGIC: Swap the model
|
|
107
140
|
if (bodyJson && bodyJson.model) {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
141
|
+
let newModel = targetModel;
|
|
142
|
+
if (targetModel === 'aws') {
|
|
143
|
+
if (bodyJson.model.includes('haiku')) {
|
|
144
|
+
newModel = 'aws-claude-haiku-4-5-20251001';
|
|
145
|
+
} else if (bodyJson.model.includes('opus')) {
|
|
146
|
+
newModel = 'aws-claude-opus-4-6';
|
|
147
|
+
} else {
|
|
148
|
+
// Default to sonnet for AWS if not haiku or opus
|
|
149
|
+
newModel = 'aws-claude-sonnet-4-6';
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
111
153
|
if (process.argv.includes('--scionos-debug')) {
|
|
112
|
-
console.log(chalk.yellow(`[Proxy] Swapping model ${bodyJson.model} -> ${
|
|
154
|
+
console.log(chalk.yellow(`[Proxy] Swapping model ${bodyJson.model} -> ${newModel}`));
|
|
113
155
|
}
|
|
114
|
-
bodyJson.model =
|
|
156
|
+
bodyJson.model = newModel;
|
|
115
157
|
}
|
|
116
158
|
|
|
117
159
|
// Prepare upstream request
|
|
@@ -232,7 +274,7 @@ if (!claudeStatus.installed) {
|
|
|
232
274
|
if (shouldInstall) {
|
|
233
275
|
try {
|
|
234
276
|
console.log(chalk.cyan('\n📦 Installing @anthropic-ai/claude-code...'));
|
|
235
|
-
spawn.sync('npm', ['install', '-g', '@anthropic-ai/claude-code'], { stdio: 'inherit' });
|
|
277
|
+
spawn.sync('npm', ['install', '-g', '@anthropic-ai/claude-code'], { stdio: 'inherit', shell: process.platform === 'win32' });
|
|
236
278
|
claudeStatus = isClaudeCodeInstalled();
|
|
237
279
|
if (!claudeStatus.installed) {
|
|
238
280
|
console.warn(chalk.yellow('⚠ Installation finished, but executable not found immediately. Restart terminal recommended.'));
|
|
@@ -260,7 +302,7 @@ if (process.platform === 'win32') {
|
|
|
260
302
|
}
|
|
261
303
|
|
|
262
304
|
// 3. Token Loop
|
|
263
|
-
let token
|
|
305
|
+
let token;
|
|
264
306
|
while (true) {
|
|
265
307
|
console.log(chalk.blueBright("To retrieve your token, visit: https://routerlab.ch/keys"));
|
|
266
308
|
token = await password({
|
|
@@ -288,19 +330,24 @@ const modelChoice = await select({
|
|
|
288
330
|
message: 'Select Model Strategy:',
|
|
289
331
|
choices: [
|
|
290
332
|
{
|
|
291
|
-
name: 'Default (Use Claude
|
|
333
|
+
name: 'Default (Use Claude natively)',
|
|
292
334
|
value: 'default',
|
|
293
335
|
description: 'Standard behavior. Claude decides which model to use.'
|
|
294
336
|
},
|
|
295
337
|
{
|
|
296
|
-
name: '
|
|
297
|
-
value: '
|
|
298
|
-
description: '
|
|
338
|
+
name: 'Claude AWS (-50% du prix 💰)',
|
|
339
|
+
value: 'aws',
|
|
340
|
+
description: 'Map models to aws-claude-haiku, aws-claude-sonnet, aws-claude-opus'
|
|
341
|
+
},
|
|
342
|
+
{
|
|
343
|
+
name: 'GLM-5',
|
|
344
|
+
value: 'glm-5',
|
|
345
|
+
description: 'Remplace tous les modèles par glm-5'
|
|
299
346
|
},
|
|
300
347
|
{
|
|
301
|
-
name: '
|
|
302
|
-
value: 'minimax-m2.
|
|
303
|
-
description: '
|
|
348
|
+
name: 'MiniMax M2.5',
|
|
349
|
+
value: 'minimax-m2.5',
|
|
350
|
+
description: 'Remplace tous les modèles par minimax-m2.5'
|
|
304
351
|
}
|
|
305
352
|
]
|
|
306
353
|
});
|
|
@@ -342,7 +389,8 @@ console.log(chalk.green(`\n🚀 Launching Claude Code [${modelChoice}]...\n`));
|
|
|
342
389
|
|
|
343
390
|
const child = spawn(claudeStatus.cliPath, args, {
|
|
344
391
|
stdio: 'inherit',
|
|
345
|
-
env: env
|
|
392
|
+
env: env,
|
|
393
|
+
shell: process.platform === 'win32'
|
|
346
394
|
});
|
|
347
395
|
|
|
348
396
|
// 7. Cleanup Handlers
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-scionos",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.5",
|
|
4
4
|
"description": "Ephemeral and secure runner for Claude Code CLI in ScioNos environment",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
@@ -35,17 +35,14 @@
|
|
|
35
35
|
},
|
|
36
36
|
"private": false,
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@inquirer/prompts": "^8.
|
|
39
|
-
"chalk": "^5.6.2",
|
|
40
|
-
"cross-spawn": "^7.0.6",
|
|
41
|
-
"undici": "^7.18.2",
|
|
38
|
+
"@inquirer/prompts": "^8.3.2",
|
|
42
39
|
"update-notifier": "^7.3.1",
|
|
43
|
-
"which": "^6.0.
|
|
40
|
+
"which": "^6.0.1"
|
|
44
41
|
},
|
|
45
42
|
"devDependencies": {
|
|
46
|
-
"@eslint/js": "^
|
|
47
|
-
"eslint": "^
|
|
48
|
-
"globals": "^17.
|
|
49
|
-
"vitest": "^4.0
|
|
43
|
+
"@eslint/js": "^10.0.1",
|
|
44
|
+
"eslint": "^10.0.3",
|
|
45
|
+
"globals": "^17.4.0",
|
|
46
|
+
"vitest": "^4.1.0"
|
|
50
47
|
}
|
|
51
48
|
}
|