claude-scionos 3.0.1 → 3.0.3
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 +20 -0
- package/index.js +53 -21
- package/package.json +2 -1
- package/src/detectors/claude-only.js +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,26 @@ 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.3] - 2026-02-18
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
- **Model**: Renamed `GLM-4.7` to `Kimi K2.5` (`kimi-k2.5`) in the model selection menu.
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
- **Token Validation**: Added a 10-second `AbortController` timeout on `validateToken()` to prevent the prompt from hanging on unresponsive network.
|
|
15
|
+
- **Proxy Memory**: Added a 100 MB cap on incoming request buffers; oversized requests now return HTTP 413 instead of causing a memory overflow.
|
|
16
|
+
- **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.
|
|
17
|
+
|
|
18
|
+
## [3.0.2] - 2026-01-11
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
- **Robust Proxy**: Integrated `undici` library for advanced HTTP agent control in the local proxy.
|
|
22
|
+
- **SSL Bypass**: Added support for internal/self-signed certificates (`rejectUnauthorized: false`) when using the proxy.
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
- **Proxy Connectivity**: Fixed `fetch failed` and protocol errors by cleaning conflicting headers (`Host`, `Content-Length`) before upstream forwarding.
|
|
26
|
+
- **Code Quality**: Removed unused variables and dead code for cleaner execution.
|
|
27
|
+
|
|
8
28
|
## [3.0.1] - 2026-01-11
|
|
9
29
|
|
|
10
30
|
### Added
|
package/index.js
CHANGED
|
@@ -24,7 +24,7 @@ const BASE_URL = "https://routerlab.ch";
|
|
|
24
24
|
* Displays the application banner
|
|
25
25
|
*/
|
|
26
26
|
function showBanner() {
|
|
27
|
-
console.clear();
|
|
27
|
+
if (!process.env.CI && !process.argv.includes('--no-clear')) console.clear();
|
|
28
28
|
const p = chalk.hex('#3b82f6'); // Primary (Scio)
|
|
29
29
|
const s = chalk.hex('#a855f7'); // Secondary (Nos)
|
|
30
30
|
const c = chalk.hex('#D97757'); // Claude Orange
|
|
@@ -47,13 +47,17 @@ function showBanner() {
|
|
|
47
47
|
*/
|
|
48
48
|
async function validateToken(apiKey) {
|
|
49
49
|
try {
|
|
50
|
+
const controller = new AbortController();
|
|
51
|
+
const timeoutId = setTimeout(() => controller.abort(), 10000);
|
|
50
52
|
const response = await fetch(`${BASE_URL}/v1/models`, {
|
|
51
53
|
method: 'GET',
|
|
52
54
|
headers: {
|
|
53
55
|
'x-api-key': apiKey,
|
|
54
56
|
'anthropic-version': '2023-06-01'
|
|
55
|
-
}
|
|
57
|
+
},
|
|
58
|
+
signal: controller.signal
|
|
56
59
|
});
|
|
60
|
+
clearTimeout(timeoutId);
|
|
57
61
|
|
|
58
62
|
if (response.ok) {
|
|
59
63
|
return { valid: true };
|
|
@@ -91,14 +95,25 @@ function startProxyServer(targetModel, validToken) {
|
|
|
91
95
|
// Claude Code uses /v1/messages
|
|
92
96
|
if (req.method === 'POST' && req.url.includes('/messages')) {
|
|
93
97
|
const chunks = [];
|
|
94
|
-
|
|
98
|
+
const MAX_SIZE = 100 * 1024 * 1024; // 100MB
|
|
99
|
+
let totalSize = 0;
|
|
100
|
+
req.on('data', chunk => {
|
|
101
|
+
totalSize += chunk.length;
|
|
102
|
+
if (totalSize > MAX_SIZE) {
|
|
103
|
+
res.writeHead(413);
|
|
104
|
+
res.end(JSON.stringify({ error: { message: 'Request too large' } }));
|
|
105
|
+
req.destroy();
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
chunks.push(chunk);
|
|
109
|
+
});
|
|
95
110
|
req.on('end', async () => {
|
|
96
111
|
try {
|
|
97
112
|
const bodyBuffer = Buffer.concat(chunks);
|
|
98
113
|
let bodyJson;
|
|
99
114
|
try {
|
|
100
115
|
bodyJson = JSON.parse(bodyBuffer.toString());
|
|
101
|
-
} catch
|
|
116
|
+
} catch {
|
|
102
117
|
// If not JSON, forward as is
|
|
103
118
|
bodyJson = null;
|
|
104
119
|
}
|
|
@@ -115,14 +130,26 @@ function startProxyServer(targetModel, validToken) {
|
|
|
115
130
|
}
|
|
116
131
|
|
|
117
132
|
// Prepare upstream request
|
|
133
|
+
// 1. Create an agent that ignores SSL errors (CRITICAL for internal/testing environments)
|
|
134
|
+
const { Agent } = await import('undici');
|
|
135
|
+
const dispatcher = new Agent({
|
|
136
|
+
connect: {
|
|
137
|
+
rejectUnauthorized: false // WARNING: Ignores SSL certificate errors
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
// 2. Remove problematic headers that fetch handles automatically
|
|
142
|
+
const upstreamHeaders = { ...req.headers };
|
|
143
|
+
delete upstreamHeaders['host']; // Let fetch set the correct Host based on URL
|
|
144
|
+
delete upstreamHeaders['content-length']; // Let fetch calculate length based on body
|
|
145
|
+
upstreamHeaders['x-api-key'] = validToken;
|
|
146
|
+
|
|
147
|
+
// 3. Execute request with the permissive dispatcher
|
|
118
148
|
const upstreamRes = await fetch(`${BASE_URL}${req.url}`, {
|
|
119
149
|
method: 'POST',
|
|
120
|
-
headers:
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
'x-api-key': validToken // Ensure we use the validated token
|
|
124
|
-
},
|
|
125
|
-
body: bodyJson ? JSON.stringify(bodyJson) : bodyBuffer
|
|
150
|
+
headers: upstreamHeaders,
|
|
151
|
+
body: bodyJson ? JSON.stringify(bodyJson) : bodyBuffer,
|
|
152
|
+
dispatcher: dispatcher // <--- Apply the custom agent here
|
|
126
153
|
});
|
|
127
154
|
|
|
128
155
|
// Pipe response back
|
|
@@ -150,13 +177,20 @@ function startProxyServer(targetModel, validToken) {
|
|
|
150
177
|
|
|
151
178
|
// Simple Redirect implementation for non-body requests
|
|
152
179
|
try {
|
|
180
|
+
// 1. Create agent (SSL bypass)
|
|
181
|
+
const { Agent } = await import('undici');
|
|
182
|
+
const dispatcher = new Agent({ connect: { rejectUnauthorized: false } });
|
|
183
|
+
|
|
184
|
+
// 2. Clean headers
|
|
185
|
+
const upstreamHeaders = { ...req.headers };
|
|
186
|
+
delete upstreamHeaders['host'];
|
|
187
|
+
delete upstreamHeaders['content-length'];
|
|
188
|
+
upstreamHeaders['x-api-key'] = validToken;
|
|
189
|
+
|
|
153
190
|
const upstreamRes = await fetch(`${BASE_URL}${req.url}`, {
|
|
154
191
|
method: req.method,
|
|
155
|
-
headers:
|
|
156
|
-
|
|
157
|
-
'host': new URL(BASE_URL).host,
|
|
158
|
-
'x-api-key': validToken
|
|
159
|
-
}
|
|
192
|
+
headers: upstreamHeaders,
|
|
193
|
+
dispatcher: dispatcher
|
|
160
194
|
});
|
|
161
195
|
res.writeHead(upstreamRes.status, upstreamRes.headers);
|
|
162
196
|
if (upstreamRes.body) {
|
|
@@ -166,7 +200,7 @@ function startProxyServer(targetModel, validToken) {
|
|
|
166
200
|
}
|
|
167
201
|
}
|
|
168
202
|
res.end();
|
|
169
|
-
} catch
|
|
203
|
+
} catch {
|
|
170
204
|
res.writeHead(502);
|
|
171
205
|
res.end();
|
|
172
206
|
}
|
|
@@ -231,7 +265,6 @@ if (!claudeStatus.installed) {
|
|
|
231
265
|
}
|
|
232
266
|
|
|
233
267
|
// Check Git Bash on Windows
|
|
234
|
-
let gitBashPath = null;
|
|
235
268
|
if (process.platform === 'win32') {
|
|
236
269
|
const gitBashStatus = checkGitBashOnWindows();
|
|
237
270
|
if (!gitBashStatus.available) {
|
|
@@ -239,7 +272,6 @@ if (process.platform === 'win32') {
|
|
|
239
272
|
console.log(chalk.cyan('Please install Git for Windows: https://git-scm.com/downloads/win'));
|
|
240
273
|
process.exit(1);
|
|
241
274
|
}
|
|
242
|
-
gitBashPath = gitBashStatus.path;
|
|
243
275
|
}
|
|
244
276
|
|
|
245
277
|
// 3. Token Loop
|
|
@@ -276,9 +308,9 @@ const modelChoice = await select({
|
|
|
276
308
|
description: 'Standard behavior. Claude decides which model to use.'
|
|
277
309
|
},
|
|
278
310
|
{
|
|
279
|
-
name: '
|
|
280
|
-
value: '
|
|
281
|
-
description: '
|
|
311
|
+
name: 'Kimi K2.5',
|
|
312
|
+
value: 'kimi-k2.5',
|
|
313
|
+
description: 'Force all requests to Kimi K2.5'
|
|
282
314
|
},
|
|
283
315
|
{
|
|
284
316
|
name: 'Force MiniMax-M2.1 (Map all models to MiniMax)',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-scionos",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.3",
|
|
4
4
|
"description": "Ephemeral and secure runner for Claude Code CLI in ScioNos environment",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
"@inquirer/prompts": "^8.1.0",
|
|
39
39
|
"chalk": "^5.6.2",
|
|
40
40
|
"cross-spawn": "^7.0.6",
|
|
41
|
+
"undici": "^7.18.2",
|
|
41
42
|
"update-notifier": "^7.3.1",
|
|
42
43
|
"which": "^6.0.0"
|
|
43
44
|
},
|