claudish 6.10.1 → 6.11.0
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/dist/index.js +101 -11
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -16928,6 +16928,45 @@ var init_logger = __esm(() => {
|
|
|
16928
16928
|
]);
|
|
16929
16929
|
});
|
|
16930
16930
|
|
|
16931
|
+
// src/handlers/shared/anthropic-error.ts
|
|
16932
|
+
function statusToErrorType(status) {
|
|
16933
|
+
switch (status) {
|
|
16934
|
+
case 400:
|
|
16935
|
+
return "invalid_request_error";
|
|
16936
|
+
case 401:
|
|
16937
|
+
return "authentication_error";
|
|
16938
|
+
case 403:
|
|
16939
|
+
return "permission_error";
|
|
16940
|
+
case 404:
|
|
16941
|
+
return "not_found_error";
|
|
16942
|
+
case 429:
|
|
16943
|
+
return "rate_limit_error";
|
|
16944
|
+
case 503:
|
|
16945
|
+
case 529:
|
|
16946
|
+
return "overloaded_error";
|
|
16947
|
+
default:
|
|
16948
|
+
return "api_error";
|
|
16949
|
+
}
|
|
16950
|
+
}
|
|
16951
|
+
function wrapAnthropicError(status, message, errorType) {
|
|
16952
|
+
const type = errorType || statusToErrorType(status);
|
|
16953
|
+
return {
|
|
16954
|
+
type: "error",
|
|
16955
|
+
error: { type, message }
|
|
16956
|
+
};
|
|
16957
|
+
}
|
|
16958
|
+
function ensureAnthropicErrorFormat(status, body) {
|
|
16959
|
+
if (body?.type === "error" && typeof body?.error?.type === "string" && typeof body?.error?.message === "string") {
|
|
16960
|
+
return body;
|
|
16961
|
+
}
|
|
16962
|
+
if (typeof body?.error?.type === "string" && typeof body?.error?.message === "string") {
|
|
16963
|
+
return { type: "error", error: body.error };
|
|
16964
|
+
}
|
|
16965
|
+
const message = body?.error?.message || body?.message || body?.error || (typeof body === "string" ? body : JSON.stringify(body));
|
|
16966
|
+
const errorType = body?.error?.type || body?.type || body?.code;
|
|
16967
|
+
return wrapAnthropicError(status, String(message), errorType);
|
|
16968
|
+
}
|
|
16969
|
+
|
|
16931
16970
|
// src/handlers/native-handler.ts
|
|
16932
16971
|
class NativeHandler {
|
|
16933
16972
|
apiKey;
|
|
@@ -17019,7 +17058,7 @@ class NativeHandler {
|
|
|
17019
17058
|
return c.json(data, { status: anthropicResponse.status, headers: responseHeaders });
|
|
17020
17059
|
} catch (error2) {
|
|
17021
17060
|
log(`[Native] Fetch Error: ${error2}`);
|
|
17022
|
-
return c.json(
|
|
17061
|
+
return c.json(wrapAnthropicError(500, String(error2)), 500);
|
|
17023
17062
|
}
|
|
17024
17063
|
}
|
|
17025
17064
|
async shutdown() {}
|
|
@@ -18583,6 +18622,24 @@ var init_tool_call_recovery = __esm(() => {
|
|
|
18583
18622
|
init_logger();
|
|
18584
18623
|
});
|
|
18585
18624
|
|
|
18625
|
+
// src/handlers/shared/web-search-detector.ts
|
|
18626
|
+
function isWebSearchToolCall(toolName) {
|
|
18627
|
+
return WEB_SEARCH_NAMES.has(toolName);
|
|
18628
|
+
}
|
|
18629
|
+
function warnWebSearchUnsupported(toolName, modelName) {
|
|
18630
|
+
log(`[WebSearch] Tool call '${toolName}' detected from model '${modelName}' \u2014 not yet supported`);
|
|
18631
|
+
logStderr(`Warning: Model requested web search ('${toolName}') but server-side web search is not yet implemented. ` + `The tool call will pass through to the client as-is.`);
|
|
18632
|
+
}
|
|
18633
|
+
var WEB_SEARCH_NAMES;
|
|
18634
|
+
var init_web_search_detector = __esm(() => {
|
|
18635
|
+
init_logger();
|
|
18636
|
+
WEB_SEARCH_NAMES = new Set([
|
|
18637
|
+
"web_search",
|
|
18638
|
+
"brave_web_search",
|
|
18639
|
+
"tavily_search"
|
|
18640
|
+
]);
|
|
18641
|
+
});
|
|
18642
|
+
|
|
18586
18643
|
// src/handlers/shared/stream-parsers/openai-sse.ts
|
|
18587
18644
|
function validateToolArguments(toolName, argsStr, toolSchemas, textContent) {
|
|
18588
18645
|
const result = validateAndRepairToolCall(toolName, argsStr, toolSchemas, textContent);
|
|
@@ -18913,6 +18970,9 @@ data: ${JSON.stringify(d)}
|
|
|
18913
18970
|
buffered: !!toolSchemas && toolSchemas.length > 0
|
|
18914
18971
|
};
|
|
18915
18972
|
state.tools.set(idx, t);
|
|
18973
|
+
if (isWebSearchToolCall(restoredName)) {
|
|
18974
|
+
warnWebSearchUnsupported(restoredName, target);
|
|
18975
|
+
}
|
|
18916
18976
|
}
|
|
18917
18977
|
if (!t.started && !t.buffered) {
|
|
18918
18978
|
send("content_block_start", {
|
|
@@ -19079,6 +19139,7 @@ function estimateTokens(text) {
|
|
|
19079
19139
|
var init_openai_sse = __esm(() => {
|
|
19080
19140
|
init_logger();
|
|
19081
19141
|
init_tool_call_recovery();
|
|
19142
|
+
init_web_search_detector();
|
|
19082
19143
|
});
|
|
19083
19144
|
|
|
19084
19145
|
// src/handlers/shared/openai-compat.ts
|
|
@@ -21001,7 +21062,7 @@ var init_token_tracker = __esm(() => {
|
|
|
21001
21062
|
function createResponsesStreamHandler(c, response, opts) {
|
|
21002
21063
|
const reader = response.body?.getReader();
|
|
21003
21064
|
if (!reader) {
|
|
21004
|
-
return c.json(
|
|
21065
|
+
return c.json(wrapAnthropicError(500, "No response body"), 500);
|
|
21005
21066
|
}
|
|
21006
21067
|
const encoder = new TextEncoder;
|
|
21007
21068
|
const decoder = new TextDecoder;
|
|
@@ -21284,8 +21345,24 @@ function createAnthropicPassthroughStream(c, response, opts) {
|
|
|
21284
21345
|
const encoder = new TextEncoder;
|
|
21285
21346
|
const decoder = new TextDecoder;
|
|
21286
21347
|
let isClosed = false;
|
|
21348
|
+
let lastActivity = Date.now();
|
|
21349
|
+
let pingInterval = null;
|
|
21287
21350
|
return c.body(new ReadableStream({
|
|
21288
21351
|
async start(controller) {
|
|
21352
|
+
const sendPing = () => {
|
|
21353
|
+
if (!isClosed) {
|
|
21354
|
+
controller.enqueue(encoder.encode(`event: ping
|
|
21355
|
+
data: {"type":"ping"}
|
|
21356
|
+
|
|
21357
|
+
`));
|
|
21358
|
+
}
|
|
21359
|
+
};
|
|
21360
|
+
sendPing();
|
|
21361
|
+
pingInterval = setInterval(() => {
|
|
21362
|
+
if (!isClosed && Date.now() - lastActivity > 1000) {
|
|
21363
|
+
sendPing();
|
|
21364
|
+
}
|
|
21365
|
+
}, 1000);
|
|
21289
21366
|
try {
|
|
21290
21367
|
const reader = response.body.getReader();
|
|
21291
21368
|
let buffer = "";
|
|
@@ -21300,6 +21377,7 @@ function createAnthropicPassthroughStream(c, response, opts) {
|
|
|
21300
21377
|
if (done)
|
|
21301
21378
|
break;
|
|
21302
21379
|
buffer += decoder.decode(value, { stream: true });
|
|
21380
|
+
lastActivity = Date.now();
|
|
21303
21381
|
const lines = buffer.split(`
|
|
21304
21382
|
`);
|
|
21305
21383
|
buffer = lines.pop() || "";
|
|
@@ -21342,19 +21420,31 @@ function createAnthropicPassthroughStream(c, response, opts) {
|
|
|
21342
21420
|
opts.onTokenUpdate(inputTokens, outputTokens);
|
|
21343
21421
|
}
|
|
21344
21422
|
if (!isClosed) {
|
|
21345
|
-
controller.close();
|
|
21346
21423
|
isClosed = true;
|
|
21424
|
+
if (pingInterval) {
|
|
21425
|
+
clearInterval(pingInterval);
|
|
21426
|
+
pingInterval = null;
|
|
21427
|
+
}
|
|
21428
|
+
controller.close();
|
|
21347
21429
|
}
|
|
21348
21430
|
} catch (e) {
|
|
21349
21431
|
log(`[AnthropicSSE] Stream error: ${e}`);
|
|
21350
21432
|
if (!isClosed) {
|
|
21351
|
-
controller.close();
|
|
21352
21433
|
isClosed = true;
|
|
21434
|
+
if (pingInterval) {
|
|
21435
|
+
clearInterval(pingInterval);
|
|
21436
|
+
pingInterval = null;
|
|
21437
|
+
}
|
|
21438
|
+
controller.close();
|
|
21353
21439
|
}
|
|
21354
21440
|
}
|
|
21355
21441
|
},
|
|
21356
21442
|
cancel() {
|
|
21357
21443
|
isClosed = true;
|
|
21444
|
+
if (pingInterval) {
|
|
21445
|
+
clearInterval(pingInterval);
|
|
21446
|
+
pingInterval = null;
|
|
21447
|
+
}
|
|
21358
21448
|
}
|
|
21359
21449
|
}), {
|
|
21360
21450
|
headers: {
|
|
@@ -22237,7 +22327,7 @@ var init_profile_config = __esm(() => {
|
|
|
22237
22327
|
});
|
|
22238
22328
|
|
|
22239
22329
|
// src/version.ts
|
|
22240
|
-
var VERSION = "6.
|
|
22330
|
+
var VERSION = "6.11.0";
|
|
22241
22331
|
|
|
22242
22332
|
// src/telemetry.ts
|
|
22243
22333
|
var exports_telemetry = {};
|
|
@@ -24218,7 +24308,7 @@ class ComposedHandler {
|
|
|
24218
24308
|
invocation_mode: this.options.invocationMode ?? "auto-route"
|
|
24219
24309
|
});
|
|
24220
24310
|
} catch {}
|
|
24221
|
-
return c.json(
|
|
24311
|
+
return c.json(wrapAnthropicError(503, msg, "connection_error"), 503);
|
|
24222
24312
|
}
|
|
24223
24313
|
throw error2;
|
|
24224
24314
|
}
|
|
@@ -24280,7 +24370,7 @@ class ComposedHandler {
|
|
|
24280
24370
|
invocation_mode: this.options.invocationMode ?? "auto-route"
|
|
24281
24371
|
});
|
|
24282
24372
|
} catch {}
|
|
24283
|
-
return c.json(
|
|
24373
|
+
return c.json(wrapAnthropicError(retryResp.status, errorText), retryResp.status);
|
|
24284
24374
|
}
|
|
24285
24375
|
} catch (err) {
|
|
24286
24376
|
log(`[${this.provider.displayName}] Auth refresh failed: ${err.message}`);
|
|
@@ -24317,7 +24407,7 @@ class ComposedHandler {
|
|
|
24317
24407
|
invocation_mode: this.options.invocationMode ?? "auto-route"
|
|
24318
24408
|
});
|
|
24319
24409
|
} catch {}
|
|
24320
|
-
return c.json(
|
|
24410
|
+
return c.json(wrapAnthropicError(401, err.message, "authentication_error"), 401);
|
|
24321
24411
|
}
|
|
24322
24412
|
} else {
|
|
24323
24413
|
const errorText = await response.text();
|
|
@@ -24370,7 +24460,7 @@ class ComposedHandler {
|
|
|
24370
24460
|
} catch {
|
|
24371
24461
|
errorBody = { error: { type: "api_error", message: errorText } };
|
|
24372
24462
|
}
|
|
24373
|
-
return c.json(errorBody, response.status);
|
|
24463
|
+
return c.json(ensureAnthropicErrorFormat(response.status, errorBody), response.status);
|
|
24374
24464
|
}
|
|
24375
24465
|
}
|
|
24376
24466
|
if (droppedParams.length > 0) {
|
|
@@ -29224,7 +29314,7 @@ async function createProxyServer(port, openrouterApiKey, model, monitorMode = fa
|
|
|
29224
29314
|
return c.json({ input_tokens: Math.ceil(txt.length / 4) });
|
|
29225
29315
|
}
|
|
29226
29316
|
} catch (e) {
|
|
29227
|
-
return c.json(
|
|
29317
|
+
return c.json(wrapAnthropicError(500, String(e)), 500);
|
|
29228
29318
|
}
|
|
29229
29319
|
});
|
|
29230
29320
|
app.post("/v1/messages", async (c) => {
|
|
@@ -29234,7 +29324,7 @@ async function createProxyServer(port, openrouterApiKey, model, monitorMode = fa
|
|
|
29234
29324
|
return handler.handle(c, body);
|
|
29235
29325
|
} catch (e) {
|
|
29236
29326
|
log(`[Proxy] Error: ${e}`);
|
|
29237
|
-
return c.json(
|
|
29327
|
+
return c.json(wrapAnthropicError(500, String(e)), 500);
|
|
29238
29328
|
}
|
|
29239
29329
|
});
|
|
29240
29330
|
const server = serve({ fetch: app.fetch, port, hostname: "127.0.0.1" });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claudish",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.11.0",
|
|
4
4
|
"description": "Run Claude Code with any model - OpenRouter, Ollama, LM Studio & local models",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -59,10 +59,10 @@
|
|
|
59
59
|
"ai"
|
|
60
60
|
],
|
|
61
61
|
"optionalDependencies": {
|
|
62
|
-
"@claudish/magmux-darwin-arm64": "6.
|
|
63
|
-
"@claudish/magmux-darwin-x64": "6.
|
|
64
|
-
"@claudish/magmux-linux-arm64": "6.
|
|
65
|
-
"@claudish/magmux-linux-x64": "6.
|
|
62
|
+
"@claudish/magmux-darwin-arm64": "6.11.0",
|
|
63
|
+
"@claudish/magmux-darwin-x64": "6.11.0",
|
|
64
|
+
"@claudish/magmux-linux-arm64": "6.11.0",
|
|
65
|
+
"@claudish/magmux-linux-x64": "6.11.0"
|
|
66
66
|
},
|
|
67
67
|
"author": "Jack Rudenko <i@madappgang.com>",
|
|
68
68
|
"license": "MIT",
|