@askalf/dario 6.12.3 → 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.
@@ -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;
@@ -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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@askalf/dario",
3
- "version": "6.12.3",
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": {