@askalf/dario 6.12.2 → 6.12.4
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.d.ts +13 -0
- package/dist/cc-template.js +26 -0
- package/dist/proxy.d.ts +10 -6
- package/dist/proxy.js +14 -25
- package/package.json +1 -1
package/dist/cc-template.d.ts
CHANGED
|
@@ -532,6 +532,19 @@ export declare function dedupeToolsByName<T extends {
|
|
|
532
532
|
name?: unknown;
|
|
533
533
|
}>(tools: T[]): T[];
|
|
534
534
|
export declare function isGenuineCCClient(clientBody: Record<string, unknown>): boolean;
|
|
535
|
+
/**
|
|
536
|
+
* The client's tool_choice, when it can be honoured against the tools going out: `auto`, `any`
|
|
537
|
+
* and `none` always; a forced `{type:'tool', name}` with the name translated the way the tool
|
|
538
|
+
* itself was (remap mode: the client name -> its CC tool or fallback slot; preserve mode: the
|
|
539
|
+
* map is empty and the name is the client's), and only when that name is in `outgoingTools`.
|
|
540
|
+
* Anything else, including a malformed value, yields null and the request goes out without one.
|
|
541
|
+
* Exported for unit testing.
|
|
542
|
+
*/
|
|
543
|
+
export declare function passthroughToolChoice(choice: unknown, outgoingTools: Array<{
|
|
544
|
+
name?: unknown;
|
|
545
|
+
}> | undefined, toolMap?: ReadonlyMap<string, {
|
|
546
|
+
ccTool: string;
|
|
547
|
+
}>): Record<string, unknown> | null;
|
|
535
548
|
export declare function buildCCRequest(clientBody: Record<string, unknown>, billingTag: string, cacheControl: CacheControl, identity: {
|
|
536
549
|
deviceId: string;
|
|
537
550
|
accountUuid: string;
|
package/dist/cc-template.js
CHANGED
|
@@ -1596,6 +1596,26 @@ export function isGenuineCCClient(clientBody) {
|
|
|
1596
1596
|
const text = second.text;
|
|
1597
1597
|
return CC_ORIGIN_SYSTEM_OPENERS.some((opener) => text.startsWith(opener)) || text.includes('Claude Agent SDK');
|
|
1598
1598
|
}
|
|
1599
|
+
/**
|
|
1600
|
+
* The client's tool_choice, when it can be honoured against the tools going out: `auto`, `any`
|
|
1601
|
+
* and `none` always; a forced `{type:'tool', name}` with the name translated the way the tool
|
|
1602
|
+
* itself was (remap mode: the client name -> its CC tool or fallback slot; preserve mode: the
|
|
1603
|
+
* map is empty and the name is the client's), and only when that name is in `outgoingTools`.
|
|
1604
|
+
* Anything else, including a malformed value, yields null and the request goes out without one.
|
|
1605
|
+
* Exported for unit testing.
|
|
1606
|
+
*/
|
|
1607
|
+
export function passthroughToolChoice(choice, outgoingTools, toolMap = new Map()) {
|
|
1608
|
+
if (!choice || typeof choice !== 'object' || Array.isArray(choice))
|
|
1609
|
+
return null;
|
|
1610
|
+
const c = choice;
|
|
1611
|
+
if (c.type === 'auto' || c.type === 'any' || c.type === 'none')
|
|
1612
|
+
return c;
|
|
1613
|
+
if (c.type === 'tool' && typeof c.name === 'string') {
|
|
1614
|
+
const name = toolMap.get(c.name)?.ccTool ?? c.name;
|
|
1615
|
+
return (outgoingTools ?? []).some((t) => t.name === name) ? { ...c, name } : null;
|
|
1616
|
+
}
|
|
1617
|
+
return null;
|
|
1618
|
+
}
|
|
1599
1619
|
export function buildCCRequest(clientBody, billingTag, cacheControl, identity, opts = {}) {
|
|
1600
1620
|
const model = clientBody.model || 'claude-sonnet-5';
|
|
1601
1621
|
const isHaiku = model.toLowerCase().includes('haiku');
|
|
@@ -2132,6 +2152,12 @@ export function buildCCRequest(clientBody, billingTag, cacheControl, identity, o
|
|
|
2132
2152
|
ccRequest.tools = CC_TOOL_DEFINITIONS;
|
|
2133
2153
|
ccRequest.tool_choice = { type: 'none' };
|
|
2134
2154
|
}
|
|
2155
|
+
// Preserve a valid client tool_choice after tool-name translation.
|
|
2156
|
+
if (clientTools && clientTools.length > 0) {
|
|
2157
|
+
const passed = passthroughToolChoice(clientBody.tool_choice, ccRequest.tools, activeToolMap);
|
|
2158
|
+
if (passed)
|
|
2159
|
+
ccRequest.tool_choice = passed;
|
|
2160
|
+
}
|
|
2135
2161
|
// Metadata
|
|
2136
2162
|
ccRequest.metadata = {
|
|
2137
2163
|
user_id: JSON.stringify({
|
package/dist/proxy.d.ts
CHANGED
|
@@ -87,8 +87,12 @@ export declare function parseProviderPrefix(model: string): {
|
|
|
87
87
|
* the fable request carries it, the opus request does not). Subscription
|
|
88
88
|
* traffic on fable WITHOUT it is soft-refused upstream — every request
|
|
89
89
|
* returns 200 with `stop_reason: "refusal"` and empty content, while the
|
|
90
|
-
* same request on opus/sonnet answers normally.
|
|
91
|
-
*
|
|
90
|
+
* same request on opus/sonnet answers normally. CC 2.1.220 extended it to
|
|
91
|
+
* opus-5; CC 2.1.282 stopped sending it on EVERY family (wire-drift live
|
|
92
|
+
* capture 2026-09-25: opus-5 and fable-5 now equal the opus-4-8 base), so
|
|
93
|
+
* betaForModel adds it for no family. Kept exported: drift-report.mjs still
|
|
94
|
+
* treats it as model-conditional, so a capture that carries it again reads
|
|
95
|
+
* as a transform change, not base drift.
|
|
92
96
|
* Exported for tests.
|
|
93
97
|
*/
|
|
94
98
|
export declare const FABLE_FALLBACK_CREDIT_BETA = "fallback-credit-2026-06-01";
|
|
@@ -105,9 +109,10 @@ export declare const MID_CONVERSATION_TOOL_CHANGES_BETA = "mid-conversation-tool
|
|
|
105
109
|
* it, ORDER included:
|
|
106
110
|
*
|
|
107
111
|
* opus-4-8 = base (unchanged)
|
|
108
|
-
* opus-5 = base
|
|
109
|
-
*
|
|
110
|
-
*
|
|
112
|
+
* opus-5 = base (CC 2.1.282 dropped
|
|
113
|
+
* fallback-credit-2026-06-01, which 2.1.220 to 2.1.281 inserted
|
|
114
|
+
* before afk-mode; wire-drift live capture 2026-09-25)
|
|
115
|
+
* fable-5 = base (same drop as opus-5)
|
|
111
116
|
* sonnet-5 = base (== opus — wire-drift
|
|
112
117
|
* live capture, CC 2.1.204: mid-conversation-system included)
|
|
113
118
|
* CC 2.1.265 does NOT send mid-conversation-tool-changes here.
|
|
@@ -116,7 +121,6 @@ export declare const MID_CONVERSATION_TOOL_CHANGES_BETA = "mid-conversation-tool
|
|
|
116
121
|
* haiku-4-5 = base − {mid-conversation-system, mid-conversation-tool-changes,
|
|
117
122
|
* effort, afk-mode}, and claude-code-20250219 MOVED to
|
|
118
123
|
* position 5 (before advisor-tool)
|
|
119
|
-
* fable-5 = base + fallback-credit-2026-06-01 inserted BEFORE afk-mode
|
|
120
124
|
*
|
|
121
125
|
* mid-conversation-tool-changes-2026-07-01 entered `base` with the 2026-09-08
|
|
122
126
|
* rebake (CC 2.1.265). The live wire-drift capture on that rebake shows it on
|
package/dist/proxy.js
CHANGED
|
@@ -428,8 +428,12 @@ function filterBillableBetas(betas) {
|
|
|
428
428
|
* the fable request carries it, the opus request does not). Subscription
|
|
429
429
|
* traffic on fable WITHOUT it is soft-refused upstream — every request
|
|
430
430
|
* returns 200 with `stop_reason: "refusal"` and empty content, while the
|
|
431
|
-
* same request on opus/sonnet answers normally.
|
|
432
|
-
*
|
|
431
|
+
* same request on opus/sonnet answers normally. CC 2.1.220 extended it to
|
|
432
|
+
* opus-5; CC 2.1.282 stopped sending it on EVERY family (wire-drift live
|
|
433
|
+
* capture 2026-09-25: opus-5 and fable-5 now equal the opus-4-8 base), so
|
|
434
|
+
* betaForModel adds it for no family. Kept exported: drift-report.mjs still
|
|
435
|
+
* treats it as model-conditional, so a capture that carries it again reads
|
|
436
|
+
* as a transform change, not base drift.
|
|
433
437
|
* Exported for tests.
|
|
434
438
|
*/
|
|
435
439
|
export const FABLE_FALLBACK_CREDIT_BETA = 'fallback-credit-2026-06-01';
|
|
@@ -441,18 +445,11 @@ export const ADVISOR_TOOL_BETA = 'advisor-tool-2026-03-01';
|
|
|
441
445
|
export const CLAUDE_CODE_BETA = 'claude-code-20250219';
|
|
442
446
|
export const MID_CONVERSATION_TOOL_CHANGES_BETA = 'mid-conversation-tool-changes-2026-07-01';
|
|
443
447
|
/**
|
|
444
|
-
* Insert `flag` immediately
|
|
448
|
+
* Insert `flag` immediately AFTER the first `anchor`, deduped. If `flag` is
|
|
445
449
|
* already present the list is returned unchanged; if `anchor` is absent `flag`
|
|
446
450
|
* is appended at the tail. Used to place model-conditional betas at the exact
|
|
447
451
|
* position real CC emits them, rather than always appending.
|
|
448
452
|
*/
|
|
449
|
-
function insertBetaBefore(flags, flag, anchor) {
|
|
450
|
-
if (flags.includes(flag))
|
|
451
|
-
return flags;
|
|
452
|
-
const i = flags.indexOf(anchor);
|
|
453
|
-
return i < 0 ? [...flags, flag] : [...flags.slice(0, i), flag, ...flags.slice(i)];
|
|
454
|
-
}
|
|
455
|
-
/** As insertBetaBefore, but places `flag` immediately AFTER the first `anchor`. */
|
|
456
453
|
function insertBetaAfter(flags, flag, anchor) {
|
|
457
454
|
if (flags.includes(flag))
|
|
458
455
|
return flags;
|
|
@@ -477,9 +474,10 @@ function moveBetaBefore(flags, flag, anchor) {
|
|
|
477
474
|
* it, ORDER included:
|
|
478
475
|
*
|
|
479
476
|
* opus-4-8 = base (unchanged)
|
|
480
|
-
* opus-5 = base
|
|
481
|
-
*
|
|
482
|
-
*
|
|
477
|
+
* opus-5 = base (CC 2.1.282 dropped
|
|
478
|
+
* fallback-credit-2026-06-01, which 2.1.220 to 2.1.281 inserted
|
|
479
|
+
* before afk-mode; wire-drift live capture 2026-09-25)
|
|
480
|
+
* fable-5 = base (same drop as opus-5)
|
|
483
481
|
* sonnet-5 = base (== opus — wire-drift
|
|
484
482
|
* live capture, CC 2.1.204: mid-conversation-system included)
|
|
485
483
|
* CC 2.1.265 does NOT send mid-conversation-tool-changes here.
|
|
@@ -488,7 +486,6 @@ function moveBetaBefore(flags, flag, anchor) {
|
|
|
488
486
|
* haiku-4-5 = base − {mid-conversation-system, mid-conversation-tool-changes,
|
|
489
487
|
* effort, afk-mode}, and claude-code-20250219 MOVED to
|
|
490
488
|
* position 5 (before advisor-tool)
|
|
491
|
-
* fable-5 = base + fallback-credit-2026-06-01 inserted BEFORE afk-mode
|
|
492
489
|
*
|
|
493
490
|
* mid-conversation-tool-changes-2026-07-01 entered `base` with the 2026-09-08
|
|
494
491
|
* rebake (CC 2.1.265). The live wire-drift capture on that rebake shows it on
|
|
@@ -538,17 +535,9 @@ export function betaForModel(base, model, skipContext1m = false) {
|
|
|
538
535
|
flags = flags.filter((f) => f !== MID_CONVERSATION_SYSTEM_BETA);
|
|
539
536
|
}
|
|
540
537
|
}
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
// afk-mode — while opus-4-8 and sonnet-5 do not. That tracks the models
|
|
545
|
-
// with refusal classifiers: Opus 5 and Fable 5 can decline a request and
|
|
546
|
-
// route to a fallback, so CC opts both into the credit beta. Matched on
|
|
547
|
-
// `opus-5` specifically rather than `opus-5+`: a future opus-6 probably
|
|
548
|
-
// inherits this, but that's a guess and the wire-drift runner will say so.
|
|
549
|
-
flags = insertBetaBefore(flags, FABLE_FALLBACK_CREDIT_BETA, AFK_MODE_BETA);
|
|
550
|
-
}
|
|
551
|
-
// opus-4-x + unknown families keep the base set unchanged.
|
|
538
|
+
// opus, fable + unknown families keep the base set unchanged. fable-5 and
|
|
539
|
+
// opus-5 carried fallback-credit-2026-06-01 from CC 2.1.220 to 2.1.281; CC
|
|
540
|
+
// 2.1.282 sends neither with it (wire-drift capture 2026-09-25).
|
|
552
541
|
if (/\[1m\]$/.test(m) && !skipContext1m) {
|
|
553
542
|
flags = insertBetaAfter(flags, CONTEXT_1M_BETA, CLAUDE_CODE_BETA);
|
|
554
543
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@askalf/dario",
|
|
3
|
-
"version": "6.12.
|
|
3
|
+
"version": "6.12.4",
|
|
4
4
|
"description": "Use your Claude and ChatGPT subscriptions in Cursor, Cline, Aider, Claude Code and the Agent SDK — at subscription pricing, not per-token API bills. One local Anthropic + OpenAI-compatible endpoint: either plan answers either wire shape, with automatic failover when one hits its limit.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|