@askalf/dario 6.0.28 → 6.0.29
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/proxy.js +43 -0
- package/package.json +1 -1
package/dist/proxy.js
CHANGED
|
@@ -2715,6 +2715,49 @@ export async function startProxy(opts = {}) {
|
|
|
2715
2715
|
clearTimeout(bodyTimeout);
|
|
2716
2716
|
}
|
|
2717
2717
|
let body = Buffer.concat(chunks);
|
|
2718
|
+
// A body that is not a JSON object cannot be routed — every decision
|
|
2719
|
+
// below (alias, provider prefix, codex slug, template) peeks at `.model`
|
|
2720
|
+
// and each peek swallows its parse error and falls through. So `{` used
|
|
2721
|
+
// to reach the Claude pool as if it were a Claude request and, on a
|
|
2722
|
+
// --no-claude-auth proxy, came back as the pool's 503 "No account
|
|
2723
|
+
// configured" with `error` as a string — which the codex drift watcher's
|
|
2724
|
+
// wire-contract check flagged (run 34044346444): an OpenAI-shape client
|
|
2725
|
+
// reads `.error.message`. Answer here instead: 400, the endpoint's own
|
|
2726
|
+
// wire shape, and no upstream round-trip for a request nothing can serve.
|
|
2727
|
+
// Upstreams do the same (Anthropic: "The request body is not valid
|
|
2728
|
+
// JSON"; OpenAI: "We could not parse the JSON body of your request").
|
|
2729
|
+
{
|
|
2730
|
+
let invalid = null;
|
|
2731
|
+
if (body.length === 0)
|
|
2732
|
+
invalid = 'request body is empty';
|
|
2733
|
+
else {
|
|
2734
|
+
try {
|
|
2735
|
+
// Fatal decode: Buffer.toString() replaces malformed UTF-8 with
|
|
2736
|
+
// U+FFFD, so `{"x":"\xff"}` would parse here as a clean object
|
|
2737
|
+
// while the ORIGINAL bytes went on to be forwarded (review on
|
|
2738
|
+
// #1231). The bytes on the wire are what must be valid.
|
|
2739
|
+
const text = new TextDecoder('utf-8', { fatal: true }).decode(body);
|
|
2740
|
+
const v = JSON.parse(text);
|
|
2741
|
+
if (v === null || typeof v !== 'object' || Array.isArray(v))
|
|
2742
|
+
invalid = 'request body must be a JSON object';
|
|
2743
|
+
}
|
|
2744
|
+
catch (err) {
|
|
2745
|
+
invalid = `request body is not valid JSON: ${err instanceof Error ? err.message : String(err)}`;
|
|
2746
|
+
}
|
|
2747
|
+
}
|
|
2748
|
+
if (invalid !== null) {
|
|
2749
|
+
requestCount++;
|
|
2750
|
+
writeLogLine(logFileStream, {
|
|
2751
|
+
ts: new Date().toISOString(), req: requestCount,
|
|
2752
|
+
method: req.method ?? '', path: urlPath, status: 400, reject: 'invalid-body',
|
|
2753
|
+
});
|
|
2754
|
+
res.writeHead(400, { ...JSON_HEADERS, 'Access-Control-Allow-Origin': corsOrigin });
|
|
2755
|
+
res.end(JSON.stringify(isOpenAI
|
|
2756
|
+
? { error: { message: invalid, type: 'invalid_request_error', param: null, code: null } }
|
|
2757
|
+
: { type: 'error', error: { type: 'invalid_request_error', message: invalid } }));
|
|
2758
|
+
return;
|
|
2759
|
+
}
|
|
2760
|
+
}
|
|
2718
2761
|
// Provider prefix (v3.10.0). If the body's model field is `<provider>:<model>`
|
|
2719
2762
|
// with a recognized prefix, strip the prefix and force routing regardless of
|
|
2720
2763
|
// regex. CLI-level `--model=<provider>:<name>` applies the same override
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@askalf/dario",
|
|
3
|
-
"version": "6.0.
|
|
3
|
+
"version": "6.0.29",
|
|
4
4
|
"description": "Use your Claude Pro/Max subscription in any tool — Cursor, Cline, Aider, the Agent SDK, your scripts — at subscription pricing, not per-token API bills. One local Anthropic + OpenAI-compatible endpoint.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|