@askalf/dario 3.37.18 → 3.37.20

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/doctor.js CHANGED
@@ -392,11 +392,18 @@ export async function runChecks(opts = {}) {
392
392
  // - Else fall back to direct-to-Anthropic with Haiku only.
393
393
  // Unified buckets surface but per-model buckets won't.
394
394
  const dario_base = process.env.DARIO_TEST_URL || 'http://127.0.0.1:3456';
395
+ // The proxy validates Authorization against DARIO_API_KEY when set.
396
+ // Fall back to literal 'dario' (the documented loopback-only default)
397
+ // when unset so local-dev probes against a no-auth proxy continue to
398
+ // work. Without reading the env here, `dario doctor --usage` 401s on
399
+ // every deploy that sets a real auth secret — which is every prod
400
+ // deploy that follows the README's "non-loopback bind" guidance.
401
+ const dario_auth = process.env.DARIO_API_KEY || 'dario';
395
402
  let probeEndpoint = `${dario_base}/v1/messages`;
396
403
  let probeHeaders = {
397
404
  'content-type': 'application/json',
398
405
  'anthropic-version': '2023-06-01',
399
- 'authorization': 'Bearer dario',
406
+ 'authorization': `Bearer ${dario_auth}`,
400
407
  };
401
408
  let proxyAvailable = false;
402
409
  try {
package/dist/proxy.js CHANGED
@@ -1478,13 +1478,11 @@ export async function startProxy(opts = {}) {
1478
1478
  context1mUnavailable.add(acctKey);
1479
1479
  if (verbose && firstRejection)
1480
1480
  console.log(`[dario] #${requestCount} context-1m rejected (${upstream.status}) — retrying without it (cached for session)`);
1481
- // Rebuild via array filter instead of string replace so the output
1482
- // is byte-identical to a request that started without context-1m
1483
- // (skipContext1m path above). A deterministic string-replace would
1484
- // leave the retry indistinguishable on content but divergent on
1485
- // whitespace/structure if betaBase ever gains non-context-1m tokens
1486
- // at the same position — keep the two paths funneled through one filter.
1487
- const reducedBeta = beta.split(',').filter((t) => t !== 'context-1m-2025-08-07').join(',');
1481
+ // Strip both long-context betas: context-1m is the primary, but
1482
+ // context-management can trigger the same rejection on models (e.g.
1483
+ // Haiku) that don't support either with OAuth subscription auth.
1484
+ const LONG_CONTEXT_BETAS = new Set(['context-1m-2025-08-07', 'context-management-2025-06-27']);
1485
+ const reducedBeta = beta.split(',').filter((t) => !LONG_CONTEXT_BETAS.has(t)).join(',');
1488
1486
  const retryHeaders = { ...headers, 'anthropic-beta': reducedBeta };
1489
1487
  const retry = await fetch(targetBase, {
1490
1488
  method: req.method ?? 'POST',
@@ -1952,9 +1950,33 @@ export async function startProxy(opts = {}) {
1952
1950
  queue.release();
1953
1951
  }
1954
1952
  });
1955
- server.on('error', (err) => {
1953
+ server.on('error', async (err) => {
1956
1954
  if (err.code === 'EADDRINUSE') {
1957
- console.error(`[dario] Port ${port} is already in use. Is another dario proxy running?`);
1955
+ // Before erroring, check whether dario itself is already running on this
1956
+ // port. If it is, the user just ran `dario login` or `dario proxy` twice
1957
+ // — treat it as a no-op rather than a crash.
1958
+ try {
1959
+ const displayHost = isLoopbackHost(host) ? 'localhost' : host;
1960
+ const res = await fetch(`http://${displayHost}:${port}/health`);
1961
+ const body = await res.json();
1962
+ if (body && (body.status === 'ok' || body.status === 'degraded')) {
1963
+ console.log('');
1964
+ console.log(` dario — already running on http://${displayHost}:${port}`);
1965
+ console.log('');
1966
+ console.log(` OAuth: ${body.oauth ?? 'unknown'} | requests served: ${body.requests ?? 0}`);
1967
+ console.log('');
1968
+ console.log(' Usage:');
1969
+ console.log(` ANTHROPIC_BASE_URL=http://${displayHost}:${port}`);
1970
+ console.log(' ANTHROPIC_API_KEY=dario');
1971
+ console.log('');
1972
+ process.exit(0);
1973
+ }
1974
+ }
1975
+ catch {
1976
+ // Not dario — fall through to the generic error.
1977
+ }
1978
+ console.error(`[dario] Port ${port} is already in use by another process.`);
1979
+ console.error(`[dario] Free it with: kill $(lsof -ti:${port}) or change the port with --port <n>`);
1958
1980
  }
1959
1981
  else {
1960
1982
  console.error(`[dario] Server error: ${err.message}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@askalf/dario",
3
- "version": "3.37.18",
3
+ "version": "3.37.20",
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": {