@askalf/dario 3.9.3 → 3.9.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/dist/cc-template.js +39 -10
- package/dist/proxy.js +23 -4
- package/package.json +1 -1
package/dist/cc-template.js
CHANGED
|
@@ -100,36 +100,47 @@ function injectContextFields(input, clientFields, ctx) {
|
|
|
100
100
|
}
|
|
101
101
|
const TOOL_MAP = {
|
|
102
102
|
// Direct maps
|
|
103
|
+
// Note on translateBack field names: the vast majority of client bash-like
|
|
104
|
+
// tools use `command` (the Anthropic convention), not `cmd`. OpenClaw's
|
|
105
|
+
// `exec` tool takes `{command, workdir, env, ...}` (dario#36 triage).
|
|
106
|
+
// Hybrid mode overrides these with the actual client schema via clientFields,
|
|
107
|
+
// but default mode relies on these output names being the common case.
|
|
103
108
|
bash: {
|
|
104
109
|
ccTool: 'Bash',
|
|
105
110
|
translateArgs: (a) => ({ command: a.cmd || a.command || a.c || '' }),
|
|
106
|
-
translateBack: (a) => ({
|
|
111
|
+
translateBack: (a) => ({ command: a.command ?? '' }),
|
|
107
112
|
},
|
|
108
113
|
exec: {
|
|
109
114
|
ccTool: 'Bash',
|
|
110
115
|
translateArgs: (a) => ({ command: a.cmd || a.command || a.c || '' }),
|
|
111
|
-
translateBack: (a) => ({
|
|
116
|
+
translateBack: (a) => ({ command: a.command ?? '' }),
|
|
112
117
|
},
|
|
113
118
|
shell: {
|
|
114
119
|
ccTool: 'Bash',
|
|
115
120
|
translateArgs: (a) => ({ command: a.cmd || a.command || a.c || '' }),
|
|
116
|
-
translateBack: (a) => ({
|
|
121
|
+
translateBack: (a) => ({ command: a.command ?? '' }),
|
|
117
122
|
},
|
|
118
123
|
run: {
|
|
119
124
|
ccTool: 'Bash',
|
|
120
125
|
translateArgs: (a) => ({ command: a.cmd || a.command || '' }),
|
|
121
|
-
translateBack: (a) => ({
|
|
126
|
+
translateBack: (a) => ({ command: a.command ?? '' }),
|
|
122
127
|
},
|
|
123
128
|
command: {
|
|
124
129
|
ccTool: 'Bash',
|
|
125
130
|
translateArgs: (a) => ({ command: a.cmd || a.command || '' }),
|
|
126
|
-
translateBack: (a) => ({
|
|
131
|
+
translateBack: (a) => ({ command: a.command ?? '' }),
|
|
127
132
|
},
|
|
128
133
|
terminal: {
|
|
129
134
|
ccTool: 'Bash',
|
|
130
135
|
translateArgs: (a) => ({ command: a.cmd || a.command || '' }),
|
|
131
|
-
translateBack: (a) => ({
|
|
136
|
+
translateBack: (a) => ({ command: a.command ?? '' }),
|
|
132
137
|
},
|
|
138
|
+
// `process` is OpenClaw's session-manager tool — it's an action-discriminator
|
|
139
|
+
// shape {action: "list"|"poll"|"log"|..., sessionId?, ...}. Flattening it onto
|
|
140
|
+
// Bash.command loses all sibling fields (data, keys, hex, literal, text, ...),
|
|
141
|
+
// so the model upstream can't actually drive it. Kept mapped for fingerprint
|
|
142
|
+
// continuity but the reverse translation is inherently lossy — clients with a
|
|
143
|
+
// process-style tool should use --preserve-tools instead of --hybrid-tools.
|
|
133
144
|
process: {
|
|
134
145
|
ccTool: 'Bash',
|
|
135
146
|
translateArgs: (a) => ({ command: a.action || a.cmd || '' }),
|
|
@@ -307,16 +318,34 @@ export function buildCCRequest(clientBody, billingTag, cache1h, identity, opts =
|
|
|
307
318
|
claimedCC.add(mapping.ccTool);
|
|
308
319
|
}
|
|
309
320
|
}
|
|
321
|
+
// Unmapped-tool handling differs by mode:
|
|
322
|
+
//
|
|
323
|
+
// - Default mode: round-robin to CC fallback tools. The model sees the CC
|
|
324
|
+
// tool set, any tool call is "something", and we best-effort relay it
|
|
325
|
+
// back to the client tool name. Broken-by-design for clients with rich
|
|
326
|
+
// discriminator tools (OpenClaw lobster/memory_get, dario#36), but
|
|
327
|
+
// preserves the old behavior for simple clients that don't have many
|
|
328
|
+
// unmapped tools.
|
|
329
|
+
//
|
|
330
|
+
// - Hybrid mode: DROP unmapped tools entirely. We can't forward them to
|
|
331
|
+
// the upstream (adding to CC_TOOL_DEFINITIONS breaks the fingerprint),
|
|
332
|
+
// and round-robin mapping produces nonsense shapes on the reverse path
|
|
333
|
+
// (lobster.translateBack(Glob.input) → {pattern: "..."} when lobster
|
|
334
|
+
// wants {action: "run"}). Better to let the model not see those tools
|
|
335
|
+
// than to pretend they exist and corrupt every call. Users needing
|
|
336
|
+
// every client tool to actually work must use --preserve-tools.
|
|
310
337
|
const CC_FALLBACK_TOOLS = ['Bash', 'Read', 'Grep', 'Glob', 'WebSearch', 'WebFetch'];
|
|
311
338
|
for (const tool of clientTools) {
|
|
312
339
|
const name = (tool.name || '').toLowerCase();
|
|
313
340
|
if (TOOL_MAP[name])
|
|
314
341
|
continue;
|
|
315
342
|
unmappedTools.push(tool.name);
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
//
|
|
319
|
-
//
|
|
343
|
+
if (opts.hybridTools)
|
|
344
|
+
continue; // dropped — see comment above
|
|
345
|
+
// Default mode: round-robin distribution. Exclude CC tools the client
|
|
346
|
+
// already uses so we never create a two-client-names-to-one-CC-tool
|
|
347
|
+
// collision. If every fallback is claimed (rare: client already uses 6+
|
|
348
|
+
// CC tools), fall back to the full pool and accept the ambiguity.
|
|
320
349
|
const pool = CC_FALLBACK_TOOLS.filter(t => !claimedCC.has(t));
|
|
321
350
|
const fallbackPool = pool.length > 0 ? pool : CC_FALLBACK_TOOLS;
|
|
322
351
|
const fallbackTool = fallbackPool[(unmappedTools.length - 1) % fallbackPool.length];
|
package/dist/proxy.js
CHANGED
|
@@ -420,6 +420,14 @@ export async function startProxy(opts = {}) {
|
|
|
420
420
|
};
|
|
421
421
|
let requestCount = 0;
|
|
422
422
|
const semaphore = new Semaphore(MAX_CONCURRENT);
|
|
423
|
+
// Cache context-1m beta availability. Set false once per account (or process
|
|
424
|
+
// in single-account mode) after the first "long context" rejection, so we
|
|
425
|
+
// skip sending context-1m on every subsequent request instead of paying the
|
|
426
|
+
// round-trip + retry cost each time. Keyed by account alias; `__default__`
|
|
427
|
+
// is the single-account slot. Reported by @boeingchoco in dario#36 — the
|
|
428
|
+
// retry loop was firing on every POST with hybrid-tools + OC.
|
|
429
|
+
const context1mUnavailable = new Set();
|
|
430
|
+
const ACCOUNT_KEY_SINGLE = '__default__';
|
|
423
431
|
// Rate governor — minimum 500ms between requests. Fast enough for agents,
|
|
424
432
|
// slow enough to not look like a scripted flood of identical traffic.
|
|
425
433
|
let lastRequestTime = 0;
|
|
@@ -693,8 +701,14 @@ export async function startProxy(opts = {}) {
|
|
|
693
701
|
}
|
|
694
702
|
else {
|
|
695
703
|
// CC v2.1.104 beta set — 8 flags in the order Claude Code sends them.
|
|
696
|
-
// context-1m requires Extra Usage — if it 400s, we auto-retry without
|
|
697
|
-
|
|
704
|
+
// context-1m requires Extra Usage — if it 400s, we auto-retry without
|
|
705
|
+
// it, and cache the rejection so subsequent requests on this account
|
|
706
|
+
// skip context-1m entirely (dario#36).
|
|
707
|
+
const acctKey = poolAccount?.alias ?? ACCOUNT_KEY_SINGLE;
|
|
708
|
+
const skipContext1m = context1mUnavailable.has(acctKey);
|
|
709
|
+
beta = skipContext1m
|
|
710
|
+
? 'claude-code-20250219,oauth-2025-04-20,interleaved-thinking-2025-05-14,context-management-2025-06-27,prompt-caching-scope-2026-01-05,advisor-tool-2026-03-01,effort-2025-11-24'
|
|
711
|
+
: 'claude-code-20250219,oauth-2025-04-20,context-1m-2025-08-07,interleaved-thinking-2025-05-14,context-management-2025-06-27,prompt-caching-scope-2026-01-05,advisor-tool-2026-03-01,effort-2025-11-24';
|
|
698
712
|
if (clientBeta) {
|
|
699
713
|
const baseSet = new Set(beta.split(','));
|
|
700
714
|
const filtered = filterBillableBetas(clientBeta)
|
|
@@ -792,8 +806,13 @@ export async function startProxy(opts = {}) {
|
|
|
792
806
|
|| peekedBody.includes('Extra usage is required')
|
|
793
807
|
|| peekedBody.includes('long_context');
|
|
794
808
|
if (isLongContextError) {
|
|
795
|
-
|
|
796
|
-
|
|
809
|
+
// Cache the rejection so future requests on this account skip
|
|
810
|
+
// context-1m up front instead of re-paying the 400/429 round-trip.
|
|
811
|
+
const acctKey = poolAccount?.alias ?? ACCOUNT_KEY_SINGLE;
|
|
812
|
+
const firstRejection = !context1mUnavailable.has(acctKey);
|
|
813
|
+
context1mUnavailable.add(acctKey);
|
|
814
|
+
if (verbose && firstRejection)
|
|
815
|
+
console.log(`[dario] #${requestCount} context-1m rejected (${upstream.status}) — retrying without it (cached for session)`);
|
|
797
816
|
const reducedBeta = beta.replace(',context-1m-2025-08-07', '').replace('context-1m-2025-08-07,', '');
|
|
798
817
|
const retryHeaders = { ...headers, 'anthropic-beta': reducedBeta };
|
|
799
818
|
const retry = await fetch(targetBase, {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@askalf/dario",
|
|
3
|
-
"version": "3.9.
|
|
3
|
+
"version": "3.9.5",
|
|
4
4
|
"description": "A local LLM router. One endpoint, every provider — Claude subscriptions, OpenAI, OpenRouter, Groq, local LiteLLM, any OpenAI-compat endpoint — your tools don't need to change.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|