@askalf/dario 4.8.39 → 4.8.40

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/proxy.d.ts CHANGED
@@ -193,6 +193,17 @@ interface ProxyOptions {
193
193
  * Sourced from `--system-prompt=<value>` or DARIO_SYSTEM_PROMPT.
194
194
  */
195
195
  systemPrompt?: string;
196
+ /**
197
+ * Upstream auth override: forward to api.anthropic.com using `x-api-key:
198
+ * <this>` (the per-token API pool) instead of the Pro/Max OAuth bearer.
199
+ * When set, OAuth/getAccessToken and the account pool are bypassed entirely
200
+ * — dario becomes a thin per-token Anthropic proxy. Default (unset) keeps
201
+ * the subscription-OAuth behavior. Used by the self-hosted compat workflow
202
+ * so it can route the suite THROUGH dario without tripping the subscription
203
+ * pool's ~3/min cap. Sourced from ANTHROPIC_UPSTREAM_API_KEY (env-only — never
204
+ * a CLI flag, so the key never lands in `ps`/argv).
205
+ */
206
+ upstreamApiKey?: string;
196
207
  /**
197
208
  * Overage-guard — halt the proxy on the first response carrying
198
209
  * `representative-claim: overage`. Subscribers should never see a
@@ -253,5 +264,11 @@ export declare function authenticateRequest(headers: IncomingMessage['headers'],
253
264
  * user's real credential for some other provider. Pure over inputs (dario#97).
254
265
  */
255
266
  export declare function describeAuthReject(headers: IncomingMessage['headers']): string;
267
+ /**
268
+ * Build the upstream auth header for the request to api.anthropic.com.
269
+ * `upstreamApiKey` set → per-token API pool (`x-api-key`); otherwise the
270
+ * Pro/Max OAuth bearer. Pure + exported for unit testing.
271
+ */
272
+ export declare function upstreamAuthHeaders(upstreamApiKey: string, accessToken: string): Record<string, string>;
256
273
  export declare function startProxy(opts?: ProxyOptions): Promise<void>;
257
274
  export {};
package/dist/proxy.js CHANGED
@@ -448,11 +448,27 @@ function enrich429(body, headers) {
448
448
  return body;
449
449
  }
450
450
  }
451
+ /**
452
+ * Build the upstream auth header for the request to api.anthropic.com.
453
+ * `upstreamApiKey` set → per-token API pool (`x-api-key`); otherwise the
454
+ * Pro/Max OAuth bearer. Pure + exported for unit testing.
455
+ */
456
+ export function upstreamAuthHeaders(upstreamApiKey, accessToken) {
457
+ return upstreamApiKey
458
+ ? { 'x-api-key': upstreamApiKey }
459
+ : { 'Authorization': `Bearer ${accessToken}` };
460
+ }
451
461
  export async function startProxy(opts = {}) {
452
462
  const port = opts.port ?? DEFAULT_PORT;
453
463
  const host = opts.host ?? process.env.DARIO_HOST ?? DEFAULT_HOST;
454
464
  const verbose = opts.verbose ?? false;
455
465
  const passthrough = opts.passthrough ?? false;
466
+ // Upstream auth override: a per-token API key forwards to the standard API
467
+ // pool via `x-api-key`, bypassing OAuth/Max + the account pool entirely.
468
+ // Env-only so the key never lands in `ps`/argv. Default (empty) = OAuth/Max.
469
+ const upstreamApiKey = (opts.upstreamApiKey ?? process.env.ANTHROPIC_UPSTREAM_API_KEY ?? '').trim();
470
+ if (upstreamApiKey)
471
+ console.error('[dario] upstream auth: per-token API key (x-api-key) — OAuth/Max + account pool bypassed');
456
472
  // DNS result order — prefer IPv4 for the Anthropic upstream by default.
457
473
  // api.anthropic.com publishes both A and AAAA records. In a container with
458
474
  // no IPv6 egress (e.g. a default Docker bridge network), Node's `verbatim`
@@ -1218,7 +1234,13 @@ export async function startProxy(opts = {}) {
1218
1234
  // requests, not within a single 429 retry.
1219
1235
  let poolAccount = null;
1220
1236
  let accessToken;
1221
- if (pool) {
1237
+ if (upstreamApiKey) {
1238
+ // Per-token API-key mode: no OAuth, no pool. `poolAccount` stays null,
1239
+ // so every pool-failover retry below is skipped; the x-api-key is set
1240
+ // on the outbound headers instead of an Authorization bearer.
1241
+ accessToken = '';
1242
+ }
1243
+ else if (pool) {
1222
1244
  poolAccount = pool.select();
1223
1245
  if (!poolAccount) {
1224
1246
  res.writeHead(503, JSON_HEADERS);
@@ -1612,7 +1634,7 @@ export async function startProxy(opts = {}) {
1612
1634
  }
1613
1635
  const headers = {
1614
1636
  ...staticHeaders,
1615
- 'Authorization': `Bearer ${accessToken}`,
1637
+ ...upstreamAuthHeaders(upstreamApiKey, accessToken),
1616
1638
  'x-claude-code-session-id': outboundSessionId,
1617
1639
  'anthropic-version': passthrough ? (req.headers['anthropic-version'] || '2023-06-01') : '2023-06-01',
1618
1640
  'anthropic-beta': beta,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@askalf/dario",
3
- "version": "4.8.39",
3
+ "version": "4.8.40",
4
4
  "description": "Use your Claude Pro/Max subscription in any tool — Cursor, Cline, Aider, the Agent SDK, your scripts — at subscription pricing, not per-token API bills. One local Anthropic + OpenAI-compatible endpoint.",
5
5
  "type": "module",
6
6
  "bin": {