@askalf/dario 6.12.6 → 6.12.8

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.
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Delays that reach setTimeout / setInterval from an operator's env var,
3
+ * flag, config file or startProxy option.
4
+ *
5
+ * Node keeps a timer delay in a signed 32-bit int: anything above
6
+ * 2^31 - 1 ms (about 24.8 days), and anything non-finite, is replaced with
7
+ * 1 ms and a TimeoutOverflowWarning. A "very long" setting therefore becomes
8
+ * the shortest one: DARIO_CODEX_USAGE_POLL_MS=3000000000 turned the idle-seat
9
+ * poll into a 1 ms loop of account reloads and /wham/usage calls (dario#1400),
10
+ * and a huge DARIO_SHUTDOWN_GRACE_MS fired the force-exit at once, skipping
11
+ * the drain (dario#1370). Every such delay goes through clampTimerMs first.
12
+ */
13
+ /** The longest delay setTimeout and setInterval honour. */
14
+ export declare const MAX_TIMER_MS: number;
15
+ /**
16
+ * `ms` held to [0, MAX_TIMER_MS]: above the ceiling (Infinity included) it is
17
+ * the ceiling, the longest wait a timer can express; negative or NaN is 0.
18
+ */
19
+ export declare function clampTimerMs(ms: number): number;
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Delays that reach setTimeout / setInterval from an operator's env var,
3
+ * flag, config file or startProxy option.
4
+ *
5
+ * Node keeps a timer delay in a signed 32-bit int: anything above
6
+ * 2^31 - 1 ms (about 24.8 days), and anything non-finite, is replaced with
7
+ * 1 ms and a TimeoutOverflowWarning. A "very long" setting therefore becomes
8
+ * the shortest one: DARIO_CODEX_USAGE_POLL_MS=3000000000 turned the idle-seat
9
+ * poll into a 1 ms loop of account reloads and /wham/usage calls (dario#1400),
10
+ * and a huge DARIO_SHUTDOWN_GRACE_MS fired the force-exit at once, skipping
11
+ * the drain (dario#1370). Every such delay goes through clampTimerMs first.
12
+ */
13
+ /** The longest delay setTimeout and setInterval honour. */
14
+ export const MAX_TIMER_MS = 2 ** 31 - 1;
15
+ /**
16
+ * `ms` held to [0, MAX_TIMER_MS]: above the ceiling (Infinity included) it is
17
+ * the ceiling, the longest wait a timer can express; negative or NaN is 0.
18
+ */
19
+ export function clampTimerMs(ms) {
20
+ if (Number.isNaN(ms) || ms <= 0)
21
+ return 0;
22
+ return ms >= MAX_TIMER_MS ? MAX_TIMER_MS : ms;
23
+ }
@@ -19,12 +19,14 @@ For a one-page status table of every tool dario supports — working / inferred
19
19
 
20
20
  Text-tool clients (Cline / Kilo Code / Roo Code and forks) are auto-detected via system-prompt identity markers and automatically flipped into preserve-tools mode, because mixing CC's `tools` array with their XML protocol makes the model emit `<function_calls><invoke>` that their parsers can't read. The same identity path also catches `hands` (askalf's computer-use agent) — its tool names overlap with `TOOL_MAP` but its schemas diverge, so identity match → preserve-tools is the only correct routing. If you run dario specifically for wire-level fidelity and would rather pick `--preserve-tools` yourself, `--no-auto-detect` (v3.20.1, aka `--no-auto-preserve`) disables the heuristic — explicit operator choice then wins.
21
21
 
22
- Beyond the identity path, dario falls back to a **structural** check: when a request carries 3+ tools and ≥80% of them aren't in `TOOL_MAP`, that's a custom client whose tool surface has effectively no overlap with CC's, and round-robin remap onto CC fallback slots silently corrupts the calls. The structural fallback flips those requests to preserve-tools too, with `client: 'unknown-non-cc'` in the request log. This catches in-house agents and OpenClaw derivatives that we haven't added an explicit pattern for, without needing per-client maintenance. `--no-auto-detect` disables both paths.
22
+ Beyond the identity path, dario falls back to a **structural** check: when a request carries 3+ tools and ≥80% of them aren't in `TOOL_MAP`, that's a custom client whose tool surface has effectively no overlap with CC's, and round-robin remap onto CC fallback slots silently corrupts the calls. The structural fallback flips those requests to preserve-tools too, with `client: 'unknown-non-cc'` in the request log. This catches in-house agents and OpenClaw derivatives that we haven't added an explicit pattern for, without needing per-client maintenance. A smaller surface flips too when it carries a tool outside `TOOL_MAP`, no Claude Code tool name in exact case, and a lowercase alias that shares a Claude Code tool's name (`grep`, `bash`): Claude Code names its own tools in exact case, so such a surface is another client's and goes out as declared. `--no-auto-detect` disables both paths.
23
23
 
24
24
  Platform-scoped CC natives (`PowerShell`, `Glob`, `Grep` — win32-only in CC's own tool list) map by the **client's** declaration, not the proxy host's platform (v4.8.136): a win32 CC client through a Linux-hosted dario gets their canonical definitions instead of having them dropped from the advertised array.
25
25
 
26
26
  MCP tools take a third path: anything named `mcp__<server>__<tool>` is neither remapped nor flipped to preserve — it forwards **verbatim** and its calls flow back untouched (v4.8.135). That's what real CC does with session-attached MCP servers; their schemas are operator-supplied and have no canonical template entry, so passthrough *is* the CC wire shape. Before this, a CC session with an MCP server attached had its `mcp__*` surface dropped from the advertised array and its history references round-robined onto fallback slots (`tool substitution: 28/52 client tools not in TOOL_MAP` in the live log), and two or three attached servers were enough to trip the 80% structural threshold on their own. MCP names no longer count toward that threshold.
27
27
 
28
+ A request that names Claude Code tools and also declares a tool outside `TOOL_MAP` (`Grep`, `Read`, `submit_review`) stays in remap, and the extra tool gets the MCP treatment: it goes out as `mcp__client__<name>` with the client's own schema, after the CC tools, and the model's calls come back under the client's name. Remap advertises only the CC tools such a request declares, so the fallback slot it used to ride was never on the wire. A tool that cannot be carried that way (an Anthropic-defined tool such as `computer_20251124`, a tool with no `input_schema`, or a name longer than 51 characters) fails the request with a 400 that names it. `--preserve-tools` forwards all of them verbatim instead.
29
+
28
30
  If your agent's tool names aren't pre-mapped and its tools carry fields CC's schema doesn't have, there are two escape hatches: **`--preserve-tools`** (forward your schema verbatim, lose the CC wire shape) or **`--hybrid-tools`** (keep the CC wire shape, fill request-context fields from headers). See [Custom tool schemas](#custom-tool-schemas).
29
31
 
30
32
  The OpenAI-compat backend forwards tool definitions byte-for-byte and doesn't need any of this.
@@ -35,7 +35,7 @@ ChatGPT plans added with `dario codex add <alias>` pool the same way. The Codex
35
35
 
36
36
  Earlier releases placed ChatGPT conversations fill-first in alias order with cool-down eviction only, on the belief that the backend reported nothing before a 429, so a second seat served nothing until the first one declined.
37
37
 
38
- `--pool-strategy=fill-first` concentrates new conversations on one seat until it drains, for primary/backup setups; `--pool-strategy=expiring-first` fills in order of each seat's 7-day reset, soonest first, so capacity that expires soonest is spent first. `--pool-headroom-floor=5%` (env `DARIO_POOL_HEADROOM_FLOOR`, config `pool.headroomFloor`; default 2%) moves the line at which a seat counts as drained: a sticky session rebinds off it and new conversations skip it once its headroom is at or below the floor, so a seat that answers with API errors in its last percent is left alone before the 429, not at it. Refresh tokens expire about 28 days after the original grant regardless of rotation, so every seat's grant age is tracked and surfaced in `dario accounts list`, `dario doctor` and `GET /accounts` before it becomes a silent outage. Provision over HTTP with the headless [admin API](admin-api.md); pin one request to one seat with `dario accounts check <alias>` (admin API required: `DARIO_ADMIN=1` and a `DARIO_ADMIN_TOKEN`). Internals and the live `/accounts` + `/analytics` endpoints: [multi-account-pool.md](multi-account-pool.md); covered end-to-end by [`test/pool-e2e.mjs`](../test/pool-e2e.mjs).
38
+ `--pool-strategy=fill-first` concentrates new conversations on one seat until it drains, for primary/backup setups; `--pool-strategy=expiring-first` fills in order of each seat's 7-day reset, soonest first, so capacity that expires soonest is spent first. `--pool-headroom-floor=5%` (env `DARIO_POOL_HEADROOM_FLOOR`, config `pool.headroomFloor`) moves the line at which a seat counts as drained: a sticky session rebinds off it and new conversations skip it once its headroom is at or below the floor, so a seat that answers with API errors in its last percent is left alone before the 429, not at it. Setting the floor explicitly makes it a hard stop; the implicit 2% default remains a routing preference and still serves the least-drained seat when it is the only choice. A hard-parked pool answers 429 locally with `retry-after` at the earliest known reset; a reading with no reset stays probeable so stale utilization cannot park a seat forever. Refresh tokens expire about 28 days after the original grant regardless of rotation, so every seat's grant age is tracked and surfaced in `dario accounts list`, `dario doctor` and `GET /accounts` before it becomes a silent outage. Provision over HTTP with the headless [admin API](admin-api.md); pin one request to one seat with `dario accounts check <alias>` (admin API required: `DARIO_ADMIN=1` and a `DARIO_ADMIN_TOKEN`). Internals and the live `/accounts` + `/analytics` endpoints: [multi-account-pool.md](multi-account-pool.md); covered end-to-end by [`test/pool-e2e.mjs`](../test/pool-e2e.mjs).
39
39
 
40
40
  ## One key per developer
41
41
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@askalf/dario",
3
- "version": "6.12.6",
3
+ "version": "6.12.8",
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": {