@askalf/dario 4.8.69 → 4.8.71

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.
@@ -1,5 +1,5 @@
1
1
  {
2
- "_version": "2.1.175",
2
+ "_version": "2.1.177",
3
3
  "_captured": "2026-06-11T20:43:54.573Z",
4
4
  "_source": "bundled",
5
5
  "_schemaVersion": 3,
@@ -1294,7 +1294,7 @@
1294
1294
  "anthropic_beta": "claude-code-20250219,interleaved-thinking-2025-05-14,thinking-token-count-2026-05-13,context-management-2025-06-27,prompt-caching-scope-2026-01-05,mid-conversation-system-2026-04-07,advisor-tool-2026-03-01,effort-2025-11-24",
1295
1295
  "header_values": {
1296
1296
  "accept": "application/json",
1297
- "user-agent": "claude-cli/2.1.175 (external, sdk-cli)",
1297
+ "user-agent": "claude-cli/2.1.177 (external, sdk-cli)",
1298
1298
  "x-stainless-arch": "x64",
1299
1299
  "x-stainless-lang": "js",
1300
1300
  "x-stainless-os": "Linux",
@@ -1319,5 +1319,5 @@
1319
1319
  "output_config",
1320
1320
  "stream"
1321
1321
  ],
1322
- "_supportedMaxTested": "2.1.175"
1322
+ "_supportedMaxTested": "2.1.177"
1323
1323
  }
@@ -32,6 +32,12 @@
32
32
  * — the same ordering normalizeUpstreamIds() produces for live data.
33
33
  */
34
34
  export declare const BAKED_BASE_MODELS: readonly string[];
35
+ /** The set of suspended families, resolved from env at call time. */
36
+ export declare function suspendedFamilies(): Set<string>;
37
+ /** True when `model` (any spelling) belongs to a suspended family. */
38
+ export declare function isSuspendedModel(model: string): boolean;
39
+ /** Drop suspended families from an advertised base list. */
40
+ export declare function dropSuspendedModels(bases: readonly string[]): string[];
35
41
  /**
36
42
  * THE long-context rule — applied identically to every family. A base id
37
43
  * takes a `[1m]` variant unless it's the haiku family (CC's picker never
@@ -43,6 +43,45 @@ export const BAKED_BASE_MODELS = [
43
43
  'claude-sonnet-4-6',
44
44
  'claude-haiku-4-5',
45
45
  ];
46
+ /**
47
+ * Globally-suspended model families — dario neither advertises nor proxies
48
+ * them, even when upstream still lists the id, because api.anthropic.com
49
+ * returns `not_found` for every request to them.
50
+ *
51
+ * Claude Fable 5 AND Mythos 5 were disabled for ALL Anthropic customers by a
52
+ * US-government legal directive on 2026-06-12 (all plans/tiers; other models
53
+ * unaffected) — https://www.anthropic.com/news/fable-mythos-access. dario's
54
+ * baked fallback still carries `claude-fable-5`, and upstream may still list
55
+ * it, so without this filter dario keeps advertising a model that 404s.
56
+ *
57
+ * TEMP — reversible without a code change: `DARIO_SUSPENDED_MODELS` overrides
58
+ * the default (comma-separated families or model ids; each is normalized to
59
+ * its family). Set `DARIO_SUSPENDED_MODELS=` (empty) to re-enable everything
60
+ * once access is restored. Matching is by FAMILY, so every spelling is caught:
61
+ * `fable`, `fable1m`, `claude-fable-5`, `claude-fable-5[1m]`, `claude:fable`.
62
+ */
63
+ const DEFAULT_SUSPENDED_MODELS = 'fable';
64
+ /** The set of suspended families, resolved from env at call time. */
65
+ export function suspendedFamilies() {
66
+ const raw = process.env.DARIO_SUSPENDED_MODELS ?? DEFAULT_SUSPENDED_MODELS;
67
+ return new Set(raw
68
+ .split(',')
69
+ .map((s) => s.trim())
70
+ .filter((s) => s.length > 0)
71
+ .map((s) => modelFamily(s) ?? s.toLowerCase()));
72
+ }
73
+ /** True when `model` (any spelling) belongs to a suspended family. */
74
+ export function isSuspendedModel(model) {
75
+ const fams = suspendedFamilies();
76
+ if (fams.size === 0)
77
+ return false;
78
+ const fam = modelFamily(model);
79
+ return fam !== null && fams.has(fam);
80
+ }
81
+ /** Drop suspended families from an advertised base list. */
82
+ export function dropSuspendedModels(bases) {
83
+ return bases.filter((b) => !isSuspendedModel(b));
84
+ }
46
85
  /**
47
86
  * THE long-context rule — applied identically to every family. A base id
48
87
  * takes a `[1m]` variant unless it's the haiku family (CC's picker never
@@ -201,7 +240,7 @@ async function fetchUpstreamBases(deps) {
201
240
  async function refresh(deps) {
202
241
  const now = deps.now ?? Date.now;
203
242
  lastAttempt = now();
204
- const bases = await fetchUpstreamBases(deps);
243
+ const bases = dropSuspendedModels(await fetchUpstreamBases(deps));
205
244
  cache = { bases, source: 'upstream', fetchedAt: now() };
206
245
  deps.log?.(`[dario] model catalog: autodetected ${bases.length} base models upstream`);
207
246
  }
@@ -242,7 +281,7 @@ export async function getModelCatalog(deps = {}) {
242
281
  }
243
282
  }
244
283
  if (cache === null)
245
- cache = { bases: [...BAKED_BASE_MODELS], source: 'baked', fetchedAt: 0 };
284
+ cache = { bases: dropSuspendedModels(BAKED_BASE_MODELS), source: 'baked', fetchedAt: 0 };
246
285
  return cache;
247
286
  }
248
287
  /**
@@ -251,7 +290,7 @@ export async function getModelCatalog(deps = {}) {
251
290
  * Never blocks the hot path on the network.
252
291
  */
253
292
  export function getCachedBases() {
254
- return cache?.bases ?? BAKED_BASE_MODELS;
293
+ return cache?.bases ?? dropSuspendedModels(BAKED_BASE_MODELS);
255
294
  }
256
295
  /** Fire-and-forget warmup so the first client /v1/models call is served warm. */
257
296
  export function prewarmModelCatalog(deps = {}) {
package/dist/proxy.js CHANGED
@@ -17,7 +17,7 @@ import { loadAllAccounts, loadAccount, refreshAccountToken, resyncLoginFromCrede
17
17
  import { getOpenAIBackend, isOpenAIModel, forwardToOpenAI } from './openai-backend.js';
18
18
  import { RequestQueue, QueueFullError, QueueTimeoutError, DEFAULT_MAX_CONCURRENT, DEFAULT_MAX_QUEUED, DEFAULT_QUEUE_TIMEOUT_MS } from './request-queue.js';
19
19
  import { redactSecrets } from './redact.js';
20
- import { BAKED_BASE_MODELS, withLongContextVariants, buildOpenAIModelsList, getModelCatalog, getCachedBases, resolveAliasAgainst, prewarmModelCatalog } from './model-catalog.js';
20
+ import { BAKED_BASE_MODELS, withLongContextVariants, buildOpenAIModelsList, getModelCatalog, getCachedBases, resolveAliasAgainst, prewarmModelCatalog, isSuspendedModel } from './model-catalog.js';
21
21
  const ANTHROPIC_API = 'https://api.anthropic.com';
22
22
  const DEFAULT_PORT = 3456;
23
23
  const MAX_BODY_BYTES = 10 * 1024 * 1024; // 10 MB — generous for large prompts, prevents abuse
@@ -1587,6 +1587,26 @@ export async function startProxy(opts = {}) {
1587
1587
  const result = isOpenAI ? openaiToAnthropic(parsed, modelOverride) : (modelOverride ? { ...parsed, model: modelOverride } : parsed);
1588
1588
  const r = result;
1589
1589
  requestModel = (r.model || '').toLowerCase();
1590
+ // Suspended-model guard. Fable 5 / Mythos 5 are disabled for ALL
1591
+ // Anthropic customers (US-gov directive 2026-06-12); forwarding any
1592
+ // spelling of them 404s upstream with a confusing not_found. Reject
1593
+ // up front with an actionable error instead — runs before the
1594
+ // template build / account lease / forwarding, so nothing to unwind.
1595
+ // TEMP + reversible: governed by DARIO_SUSPENDED_MODELS (default
1596
+ // 'fable'); set it empty to re-enable when access is restored.
1597
+ if (requestModel && isSuspendedModel(requestModel)) {
1598
+ if (verbose)
1599
+ console.log(`[dario] suspended model rejected: ${requestModel} (${urlPath})`);
1600
+ res.writeHead(404, JSON_HEADERS);
1601
+ res.end(JSON.stringify({
1602
+ type: 'error',
1603
+ error: {
1604
+ type: 'not_found_error',
1605
+ message: `Model "${requestModel}" is suspended in this dario instance. Claude Fable 5 and Mythos 5 are disabled for all Anthropic customers (US government directive 2026-06-12 — https://www.anthropic.com/news/fable-mythos-access). Use claude-opus-4-8 or claude-sonnet-4-6 instead. To re-enable when access is restored, set DARIO_SUSPENDED_MODELS= (empty) on the dario instance.`,
1606
+ },
1607
+ }));
1608
+ return;
1609
+ }
1590
1610
  // In passthrough mode, skip all Claude-specific injection — OAuth swap only.
1591
1611
  // count_tokens also forwards thin (see resolveProxyTarget) — the endpoint
1592
1612
  // counts the CLIENT's own prompt, so template injection would distort it.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@askalf/dario",
3
- "version": "4.8.69",
3
+ "version": "4.8.71",
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": {