@askalf/dario 3.30.1 → 3.30.3

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/README.md CHANGED
@@ -108,6 +108,7 @@ Something broken? `dario doctor` prints a single aggregated health report — da
108
108
  - **Teams running local or hosted OpenAI-compat servers** (LiteLLM, vLLM, Ollama, Groq, OpenRouter, self-hosted) who want one stable local endpoint every tool can reuse.
109
109
  - **Anyone building AI coding tools** who wants provider independence without writing an OpenAI ↔ Anthropic translator themselves.
110
110
  - **Claude Max / Pro subscribers** who want their subscription usable from every tool on their machine, not just Claude Code.
111
+ - **[Claude Agent SDK](https://www.npmjs.com/package/@anthropic-ai/claude-agent-sdk) users** who want OAuth-subscription routing under the SDK. Point `baseURL: 'http://localhost:3456'` and dario translates API-key calls into your Claude Max auth — agent code stays identical.
111
112
  - **Power users on multi-agent workloads** who want multi-account pooling, session stickiness, and in-flight 429 failover on their own machine, against their own subscriptions.
112
113
  - **Operators who care about wire-level fidelity** — the fingerprint tightening in v3.22 – v3.28 means proxy mode's divergence from CC is observable (via `dario doctor`) and tunable (flags + env vars for each axis).
113
114
 
@@ -276,7 +277,7 @@ Dario's built-in `TOOL_MAP` carries **~66 schema-verified entries** covering the
276
277
 
277
278
  | Agent | Covered tool names (subset) |
278
279
  |---|---|
279
- | Claude Code | default — CC's own tools |
280
+ | Claude Code / Claude Agent SDK | default — CC / SDK tools (same schema as of CC v2.1.114 / `@anthropic-ai/claude-agent-sdk@0.2.x`) |
280
281
  | Cline / Roo Code / Kilo Code | `execute_command`, `write_to_file`, `replace_in_file`, `apply_diff`, `list_files`, `search_files`, `read_file` |
281
282
  | Cursor | `run_terminal_cmd`, `edit_file`, `search_replace`, `codebase_search`, `grep_search`, `file_search`, `list_dir`, `read_file` (`target_file`) |
282
283
  | Windsurf | `run_command`, `view_file`, `write_to_file`, `replace_file_content`, `find_by_name`, `grep_search`, `list_dir`, `search_web`, `read_url_content` |
package/dist/analytics.js CHANGED
@@ -12,8 +12,10 @@
12
12
  export function billingBucketFromClaim(claim) {
13
13
  switch (claim) {
14
14
  case 'five_hour':
15
+ case 'seven_day':
15
16
  return 'subscription';
16
17
  case 'five_hour_fallback':
18
+ case 'seven_day_fallback':
17
19
  return 'subscription_fallback';
18
20
  case 'overage':
19
21
  return 'extra_usage';
package/dist/proxy.d.ts CHANGED
@@ -3,6 +3,8 @@ export declare function parseProviderPrefix(model: string): {
3
3
  provider: 'openai' | 'claude';
4
4
  model: string;
5
5
  } | null;
6
+ /** Strip orchestration tags from all messages in a request body. */
7
+ export declare function sanitizeMessages(body: Record<string, unknown>): void;
6
8
  interface ProxyOptions {
7
9
  port?: number;
8
10
  host?: string;
package/dist/proxy.js CHANGED
@@ -210,7 +210,7 @@ function sanitizeContent(text) {
210
210
  return result.replace(/\n{3,}/g, '\n\n').trim();
211
211
  }
212
212
  /** Strip orchestration tags from all messages in a request body. */
213
- function sanitizeMessages(body) {
213
+ export function sanitizeMessages(body) {
214
214
  const messages = body.messages;
215
215
  if (!messages)
216
216
  return;
@@ -224,6 +224,18 @@ function sanitizeMessages(body) {
224
224
  block.text = sanitizeContent(block.text);
225
225
  }
226
226
  }
227
+ // Drop text blocks that became empty after orchestration-tag scrubbing.
228
+ // CC v2.1.112 and some client wrappers split per-reminder system-reminders
229
+ // into separate content blocks; scrubbing leaves each as {type:'text',text:''}
230
+ // which Anthropic rejects with "text content blocks must be non-empty"
231
+ // (dario#54). Keep non-text blocks (tool_result, tool_use, image) intact.
232
+ msg.content = msg.content.filter(b => {
233
+ if (typeof b !== 'object' || b === null)
234
+ return false;
235
+ if (b.type === 'text' && b.text === '')
236
+ return false;
237
+ return true;
238
+ });
227
239
  }
228
240
  }
229
241
  }
@@ -1345,7 +1357,10 @@ export async function startProxy(opts = {}) {
1345
1357
  if (overageUtil !== null) {
1346
1358
  overagePct = `${Math.round(parseFloat(overageUtil) * 100)}%`;
1347
1359
  }
1348
- else if (billingClaim === 'five_hour' || billingClaim === 'five_hour_fallback') {
1360
+ else if (billingClaim === 'five_hour'
1361
+ || billingClaim === 'five_hour_fallback'
1362
+ || billingClaim === 'seven_day'
1363
+ || billingClaim === 'seven_day_fallback') {
1349
1364
  overagePct = '0%';
1350
1365
  }
1351
1366
  else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@askalf/dario",
3
- "version": "3.30.1",
3
+ "version": "3.30.3",
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": {
@@ -21,7 +21,7 @@
21
21
  ],
22
22
  "scripts": {
23
23
  "build": "tsc && cp src/cc-template-data.json dist/ && node -e \"require('fs').mkdirSync('dist/shim',{recursive:true})\" && cp src/shim/runtime.cjs dist/shim/",
24
- "test": "node test/issue-29-tool-translation.mjs && node test/hybrid-tools.mjs && node test/tool-schema-contract.mjs && node test/scrub-paths.mjs && node test/provider-prefix.mjs && node test/analytics-recording.mjs && node test/analytics-billing-bucket.mjs && node test/failover-429.mjs && node test/pool-sticky.mjs && node test/live-fingerprint.mjs && node test/shim-runtime.mjs && node test/shim-e2e.mjs && node test/proxy-header-order.mjs && node test/proxy-body-order.mjs && node test/runtime-fingerprint.mjs && node test/pacing.mjs && node test/stream-drain.mjs && node test/subagent.mjs && node test/mcp-protocol.mjs && node test/mcp-tools.mjs && node test/mcp-e2e.mjs && node test/session-rotation.mjs && node test/drift-detection.mjs && node test/cc-authorize-probe-classifier.mjs && node test/compat-range.mjs && node test/doctor-formatter.mjs && node test/atomic-write.mjs && node test/account-refresh-singleflight.mjs && node test/streaming-edge-cases.mjs && node test/client-detection.mjs && node test/manual-oauth-flow.mjs && node test/scrub-template.mjs",
24
+ "test": "node test/issue-29-tool-translation.mjs && node test/hybrid-tools.mjs && node test/tool-schema-contract.mjs && node test/scrub-paths.mjs && node test/provider-prefix.mjs && node test/analytics-recording.mjs && node test/analytics-billing-bucket.mjs && node test/failover-429.mjs && node test/pool-sticky.mjs && node test/live-fingerprint.mjs && node test/shim-runtime.mjs && node test/shim-e2e.mjs && node test/proxy-header-order.mjs && node test/proxy-body-order.mjs && node test/runtime-fingerprint.mjs && node test/pacing.mjs && node test/stream-drain.mjs && node test/subagent.mjs && node test/mcp-protocol.mjs && node test/mcp-tools.mjs && node test/mcp-e2e.mjs && node test/session-rotation.mjs && node test/drift-detection.mjs && node test/cc-authorize-probe-classifier.mjs && node test/compat-range.mjs && node test/doctor-formatter.mjs && node test/atomic-write.mjs && node test/account-refresh-singleflight.mjs && node test/streaming-edge-cases.mjs && node test/client-detection.mjs && node test/manual-oauth-flow.mjs && node test/scrub-template.mjs && node test/sanitize-messages.mjs",
25
25
  "audit": "npm audit --production --audit-level=high",
26
26
  "prepublishOnly": "npm run build",
27
27
  "start": "node dist/cli.js",
@@ -29,6 +29,7 @@
29
29
  "e2e": "node test/e2e.mjs",
30
30
  "compat": "node test/compat.mjs",
31
31
  "lint:pkg": "node scripts/check-package-json.mjs",
32
+ "drift:sdk": "node scripts/check-sdk-drift.mjs",
32
33
  "fix:pkg": "node -e \"const fs=require('fs');fs.writeFileSync('package.json',JSON.stringify(JSON.parse(fs.readFileSync('package.json','utf-8')),null,2)+'\\n')\""
33
34
  },
34
35
  "keywords": [