@broberg/ai-sdk 0.10.5 → 0.12.0
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/chunk-HVZSYNZ5.js +141 -0
- package/dist/chunk-HVZSYNZ5.js.map +1 -0
- package/dist/index.d.ts +52 -3
- package/dist/index.js +74 -4
- package/dist/index.js.map +1 -1
- package/dist/registry.d.ts +69 -0
- package/dist/registry.js +11 -0
- package/dist/registry.js.map +1 -0
- package/package.json +5 -1
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
// src/availability/registry.ts
|
|
2
|
+
var SUSPENDED_FABLE_MYTHOS = "suspended \u2014 US export-control directive (2026-06-12)";
|
|
3
|
+
var DEFAULTS = [
|
|
4
|
+
// ── Anthropic ────────────────────────────────────────────────────────────
|
|
5
|
+
{ id: "claude-haiku-4-5", aliases: ["haiku", "fast"], provider: "anthropic", available: true, status: "available", source: "default" },
|
|
6
|
+
{ id: "claude-sonnet-4-6", aliases: ["sonnet", "smart"], provider: "anthropic", available: true, status: "available", source: "default" },
|
|
7
|
+
{ id: "claude-opus-4-8", aliases: ["opus", "powerful"], provider: "anthropic", available: true, status: "available", source: "default" },
|
|
8
|
+
{ id: "claude-fable-5", aliases: ["fable"], provider: "anthropic", available: false, status: "suspended", note: SUSPENDED_FABLE_MYTHOS, source: "default" },
|
|
9
|
+
{ id: "claude-mythos-5", aliases: ["mythos"], provider: "anthropic", available: false, status: "suspended", note: SUSPENDED_FABLE_MYTHOS, source: "default" },
|
|
10
|
+
// ── Gemini ───────────────────────────────────────────────────────────────
|
|
11
|
+
{ id: "gemini-2.5-flash", aliases: ["gemini-flash"], provider: "gemini", available: true, status: "available", source: "default" },
|
|
12
|
+
{ id: "gemini-2.5-flash-lite", aliases: ["gemini-flash-lite", "video"], provider: "gemini", available: true, status: "available", source: "default" },
|
|
13
|
+
// ── OpenAI ───────────────────────────────────────────────────────────────
|
|
14
|
+
{ id: "text-embedding-3-small", aliases: ["embedding"], provider: "openai", available: true, status: "available", source: "default" },
|
|
15
|
+
// ── Mistral (EU / GDPR) ──────────────────────────────────────────────────
|
|
16
|
+
{ id: "mistral-large-latest", aliases: ["mistral-large"], provider: "mistral", available: true, status: "available", source: "default" },
|
|
17
|
+
{ id: "mistral-small-latest", aliases: ["mistral-small"], provider: "mistral", available: true, status: "available", source: "default" }
|
|
18
|
+
];
|
|
19
|
+
var OVERLAY = /* @__PURE__ */ new Map();
|
|
20
|
+
var ALIAS_INDEX = /* @__PURE__ */ new Map();
|
|
21
|
+
function seed() {
|
|
22
|
+
OVERLAY = new Map(DEFAULTS.map((e) => [e.id, { ...e, aliases: [...e.aliases] }]));
|
|
23
|
+
ALIAS_INDEX = /* @__PURE__ */ new Map();
|
|
24
|
+
for (const e of DEFAULTS) for (const a of e.aliases) ALIAS_INDEX.set(a, e.id);
|
|
25
|
+
}
|
|
26
|
+
seed();
|
|
27
|
+
function resetRegistry() {
|
|
28
|
+
seed();
|
|
29
|
+
}
|
|
30
|
+
function canonicalId(requested) {
|
|
31
|
+
if (OVERLAY.has(requested)) return requested;
|
|
32
|
+
return ALIAS_INDEX.get(requested) ?? null;
|
|
33
|
+
}
|
|
34
|
+
function getEntry(requested) {
|
|
35
|
+
const id = canonicalId(requested);
|
|
36
|
+
return id ? OVERLAY.get(id) : void 0;
|
|
37
|
+
}
|
|
38
|
+
function allEntries(provider) {
|
|
39
|
+
const rows = [];
|
|
40
|
+
for (const e of OVERLAY.values()) {
|
|
41
|
+
if (provider && e.provider !== provider) continue;
|
|
42
|
+
rows.push({
|
|
43
|
+
id: e.id,
|
|
44
|
+
alias: e.aliases[0],
|
|
45
|
+
provider: e.provider,
|
|
46
|
+
available: e.available,
|
|
47
|
+
status: e.status,
|
|
48
|
+
note: e.note,
|
|
49
|
+
source: e.source
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
return rows;
|
|
53
|
+
}
|
|
54
|
+
function providerIds(provider) {
|
|
55
|
+
return [...OVERLAY.values()].filter((e) => e.provider === provider).map((e) => e.id);
|
|
56
|
+
}
|
|
57
|
+
function setAvailability(id, available, note) {
|
|
58
|
+
const e = OVERLAY.get(id);
|
|
59
|
+
if (!e) return;
|
|
60
|
+
e.available = available;
|
|
61
|
+
e.status = available ? "available" : "suspended";
|
|
62
|
+
e.source = "refresh";
|
|
63
|
+
if (note !== void 0) e.note = note;
|
|
64
|
+
else if (available) e.note = void 0;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// src/availability/types.ts
|
|
68
|
+
var ModelUnavailableError = class extends Error {
|
|
69
|
+
code = "model_unavailable";
|
|
70
|
+
requested;
|
|
71
|
+
provider;
|
|
72
|
+
note;
|
|
73
|
+
constructor(requested, note, provider) {
|
|
74
|
+
super(`model "${requested}" is unavailable${note ? ` (${note})` : ""}`);
|
|
75
|
+
this.name = "ModelUnavailableError";
|
|
76
|
+
this.requested = requested;
|
|
77
|
+
this.note = note;
|
|
78
|
+
this.provider = provider;
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
// src/availability/resolve.ts
|
|
83
|
+
function listModels(opts = {}) {
|
|
84
|
+
return allEntries(opts.provider);
|
|
85
|
+
}
|
|
86
|
+
function isAvailable(requested) {
|
|
87
|
+
const e = getEntry(requested);
|
|
88
|
+
return e ? e.available : true;
|
|
89
|
+
}
|
|
90
|
+
function resolveModel(requested, opts = {}) {
|
|
91
|
+
const id = canonicalId(requested) ?? requested;
|
|
92
|
+
const entry = getEntry(requested);
|
|
93
|
+
const provider = opts.provider ?? entry?.provider;
|
|
94
|
+
if (isAvailable(requested)) {
|
|
95
|
+
return {
|
|
96
|
+
ok: true,
|
|
97
|
+
model: id,
|
|
98
|
+
requested: id,
|
|
99
|
+
provider,
|
|
100
|
+
fellBack: false,
|
|
101
|
+
status: entry?.status ?? "unknown"
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
const chain = opts.fallback === void 0 ? [] : Array.isArray(opts.fallback) ? opts.fallback : [opts.fallback];
|
|
105
|
+
for (const fb of chain) {
|
|
106
|
+
if (isAvailable(fb)) {
|
|
107
|
+
const fbId = canonicalId(fb) ?? fb;
|
|
108
|
+
return {
|
|
109
|
+
ok: false,
|
|
110
|
+
model: fbId,
|
|
111
|
+
requested: id,
|
|
112
|
+
provider,
|
|
113
|
+
fellBack: true,
|
|
114
|
+
status: entry?.status ?? "suspended",
|
|
115
|
+
reason: entry?.note ?? `${id} is unavailable`
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (opts.throwIfUnavailable) {
|
|
120
|
+
throw new ModelUnavailableError(id, entry?.note, provider);
|
|
121
|
+
}
|
|
122
|
+
return {
|
|
123
|
+
ok: false,
|
|
124
|
+
model: id,
|
|
125
|
+
requested: id,
|
|
126
|
+
provider,
|
|
127
|
+
fellBack: false,
|
|
128
|
+
status: entry?.status ?? "suspended",
|
|
129
|
+
reason: entry?.note ?? `${id} is unavailable`
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export {
|
|
134
|
+
resetRegistry,
|
|
135
|
+
providerIds,
|
|
136
|
+
setAvailability,
|
|
137
|
+
ModelUnavailableError,
|
|
138
|
+
listModels,
|
|
139
|
+
resolveModel
|
|
140
|
+
};
|
|
141
|
+
//# sourceMappingURL=chunk-HVZSYNZ5.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/availability/registry.ts","../src/availability/types.ts","../src/availability/resolve.ts"],"sourcesContent":["// F022 — the model-availability registry: the ONE source both resolveModel()\n// (spawn / call path) and listModels() (UI picker) read. A curated default seed\n// (works offline — the durable floor) plus a mutable overlay that\n// refreshAvailability() updates from the live provider list.\n//\n// Scope note: this is a LIVENESS view (is this id alive right now?), not the\n// rich capability/price inventory (that is F017 src/catalogue). We only track\n// ids we want to assert status on; anything not here is fail-open (treated\n// available) so we never block a model we simply do not track.\nimport type { AvailabilityStatus, AvailabilitySource, ModelStatus } from \"./types.js\";\n\n/** Internal registry row. `aliases[0]` surfaces as ModelStatus.alias. */\nexport interface RegistryEntry {\n id: string;\n aliases: string[];\n provider: string;\n available: boolean;\n status: AvailabilityStatus;\n note?: string;\n source: AvailabilitySource;\n}\n\nconst SUSPENDED_FABLE_MYTHOS = \"suspended — US export-control directive (2026-06-12)\";\n\n/** Curated defaults. Mirrors DEFAULT_TIER_MAP model ids (src/routing/tier-map.ts)\n * + the models documented in CLAUDE.md, plus the two ids Anthropic suspended\n * globally on 2026-06-12. Aliases are the tier / short names a caller or picker\n * may pass instead of the canonical id. */\nconst DEFAULTS: RegistryEntry[] = [\n // ── Anthropic ────────────────────────────────────────────────────────────\n { id: \"claude-haiku-4-5\", aliases: [\"haiku\", \"fast\"], provider: \"anthropic\", available: true, status: \"available\", source: \"default\" },\n { id: \"claude-sonnet-4-6\", aliases: [\"sonnet\", \"smart\"], provider: \"anthropic\", available: true, status: \"available\", source: \"default\" },\n { id: \"claude-opus-4-8\", aliases: [\"opus\", \"powerful\"], provider: \"anthropic\", available: true, status: \"available\", source: \"default\" },\n { id: \"claude-fable-5\", aliases: [\"fable\"], provider: \"anthropic\", available: false, status: \"suspended\", note: SUSPENDED_FABLE_MYTHOS, source: \"default\" },\n { id: \"claude-mythos-5\", aliases: [\"mythos\"], provider: \"anthropic\", available: false, status: \"suspended\", note: SUSPENDED_FABLE_MYTHOS, source: \"default\" },\n // ── Gemini ───────────────────────────────────────────────────────────────\n { id: \"gemini-2.5-flash\", aliases: [\"gemini-flash\"], provider: \"gemini\", available: true, status: \"available\", source: \"default\" },\n { id: \"gemini-2.5-flash-lite\", aliases: [\"gemini-flash-lite\", \"video\"], provider: \"gemini\", available: true, status: \"available\", source: \"default\" },\n // ── OpenAI ───────────────────────────────────────────────────────────────\n { id: \"text-embedding-3-small\", aliases: [\"embedding\"], provider: \"openai\", available: true, status: \"available\", source: \"default\" },\n // ── Mistral (EU / GDPR) ──────────────────────────────────────────────────\n { id: \"mistral-large-latest\", aliases: [\"mistral-large\"], provider: \"mistral\", available: true, status: \"available\", source: \"default\" },\n { id: \"mistral-small-latest\", aliases: [\"mistral-small\"], provider: \"mistral\", available: true, status: \"available\", source: \"default\" },\n];\n\n/** The live overlay, keyed by canonical id. Seeded from DEFAULTS (deep-copied so\n * resetting is clean). refreshAvailability() mutates this; resolve/listModels\n * read it synchronously. */\nlet OVERLAY = new Map<string, RegistryEntry>();\n/** alias → canonical id, rebuilt whenever the overlay is seeded. */\nlet ALIAS_INDEX = new Map<string, string>();\n\nfunction seed(): void {\n OVERLAY = new Map(DEFAULTS.map((e) => [e.id, { ...e, aliases: [...e.aliases] }]));\n ALIAS_INDEX = new Map();\n for (const e of DEFAULTS) for (const a of e.aliases) ALIAS_INDEX.set(a, e.id);\n}\nseed();\n\n/** Reset the overlay back to the curated defaults. For tests. */\nexport function resetRegistry(): void {\n seed();\n}\n\n/** Canonical id for a model id OR alias; null when we track neither. */\nexport function canonicalId(requested: string): string | null {\n if (OVERLAY.has(requested)) return requested;\n return ALIAS_INDEX.get(requested) ?? null;\n}\n\n/** The current entry for an id/alias, or undefined when untracked (fail-open). */\nexport function getEntry(requested: string): RegistryEntry | undefined {\n const id = canonicalId(requested);\n return id ? OVERLAY.get(id) : undefined;\n}\n\n/** All tracked entries (optionally provider-scoped), as a public ModelStatus[]. */\nexport function allEntries(provider?: string): ModelStatus[] {\n const rows: ModelStatus[] = [];\n for (const e of OVERLAY.values()) {\n if (provider && e.provider !== provider) continue;\n rows.push({\n id: e.id,\n alias: e.aliases[0],\n provider: e.provider,\n available: e.available,\n status: e.status,\n note: e.note,\n source: e.source,\n });\n }\n return rows;\n}\n\n/** Provider-scoped canonical ids (for refresh reconciliation). */\nexport function providerIds(provider: string): string[] {\n return [...OVERLAY.values()].filter((e) => e.provider === provider).map((e) => e.id);\n}\n\n/** Mark a tracked id available/suspended from a live refresh. No-op if untracked. */\nexport function setAvailability(id: string, available: boolean, note?: string): void {\n const e = OVERLAY.get(id);\n if (!e) return;\n e.available = available;\n e.status = available ? \"available\" : \"suspended\";\n e.source = \"refresh\";\n if (note !== undefined) e.note = note;\n else if (available) e.note = undefined;\n}\n","// F022 — Model Availability Harness. Public types for the availability layer:\n// the shared status read (ModelStatus), the resolve result, and the structured\n// error a caller can flag on. The registry is the one source both the spawn /\n// call path (resolveModel) and UI pickers (listModels) read.\n\nexport type AvailabilityStatus = \"available\" | \"suspended\" | \"unknown\";\n\n/** Where a model's current availability came from: the curated default seed,\n * or a live provider refresh (Anthropic GET /v1/models). */\nexport type AvailabilitySource = \"default\" | \"refresh\";\n\n/** One row of the shared status read — what a UI model-picker renders. */\nexport interface ModelStatus {\n /** Canonical provider model id, e.g. \"claude-fable-5\". */\n id: string;\n /** Short/tier alias, e.g. \"fable\" (the first registered alias). */\n alias?: string;\n /** \"anthropic\" | \"openai\" | \"gemini\" | \"mistral\" | … */\n provider: string;\n available: boolean;\n status: AvailabilityStatus;\n /** Friendly reason, e.g. \"suspended — US export-control directive (2026-06-12)\". */\n note?: string;\n source: AvailabilitySource;\n}\n\n/** Result of resolveModel — the spawn / call path consumes this synchronously. */\nexport interface ResolveResult {\n /** True when the requested model itself is available. */\n ok: boolean;\n /** The id to actually use: `requested` when ok, else the first available fallback. */\n model: string;\n /** What the caller asked for (id or alias, normalized to the canonical id). */\n requested: string;\n provider?: string;\n /** True when `model` differs from `requested` because we fell back. */\n fellBack: boolean;\n status: AvailabilityStatus;\n /** Why it degraded / why it is unavailable. */\n reason?: string;\n}\n\n/** Thrown by resolveModel when the requested model is unavailable, no usable\n * fallback exists, and the caller passed `throwIfUnavailable`. Callers flag on\n * `.code === \"model_unavailable\"`. */\nexport class ModelUnavailableError extends Error {\n readonly code = \"model_unavailable\";\n readonly requested: string;\n readonly provider?: string;\n readonly note?: string;\n constructor(requested: string, note?: string, provider?: string) {\n super(`model \"${requested}\" is unavailable${note ? ` (${note})` : \"\"}`);\n this.name = \"ModelUnavailableError\";\n this.requested = requested;\n this.note = note;\n this.provider = provider;\n }\n}\n","// F022 — the synchronous, zero-I/O resolve + status read. This is the spawn /\n// call hot path (buddy's launcher calls resolveModel per spawn, cardmem #4842):\n// it MUST never await and never touch the network. Freshness comes only from a\n// prior async refreshAvailability(); resolve just reads the in-memory registry.\nimport { allEntries, canonicalId, getEntry } from \"./registry.js\";\nimport { ModelUnavailableError } from \"./types.js\";\nimport type { ModelStatus, ResolveResult } from \"./types.js\";\n\nexport interface ResolveOptions {\n /** One id/alias or an ordered chain to try when `requested` is unavailable. */\n fallback?: string | string[];\n /** Scope hint (passed through to the result); does not gate lookup. */\n provider?: string;\n /** Throw ModelUnavailableError instead of returning ok:false when there is no\n * usable fallback. For callers that want to flag rather than degrade. */\n throwIfUnavailable?: boolean;\n}\n\n/** The shared status read — UI pickers grey out `available:false` rows. */\nexport function listModels(opts: { provider?: string } = {}): ModelStatus[] {\n return allEntries(opts.provider);\n}\n\n/** Is this id/alias currently usable? Untracked ids are fail-open (true). */\nfunction isAvailable(requested: string): boolean {\n const e = getEntry(requested);\n return e ? e.available : true; // fail-open on unknown\n}\n\n/**\n * Resolve a requested model (id or alias) to one that is actually usable.\n * Synchronous + offline by contract (cardmem #4842) — reads the registry only.\n *\n * - Available → pass through ({ ok:true, fellBack:false }).\n * - Unavailable + a fallback that IS available → swap ({ ok:false, fellBack:true }).\n * - Unavailable + no usable fallback → throw (throwIfUnavailable) or return ok:false.\n * - Unknown id → treated available (never block a model we do not track).\n */\nexport function resolveModel(requested: string, opts: ResolveOptions = {}): ResolveResult {\n const id = canonicalId(requested) ?? requested;\n const entry = getEntry(requested);\n const provider = opts.provider ?? entry?.provider;\n\n if (isAvailable(requested)) {\n return {\n ok: true,\n model: id,\n requested: id,\n provider,\n fellBack: false,\n status: entry?.status ?? \"unknown\",\n };\n }\n\n // Requested is suspended — walk the fallback chain for the first available one.\n const chain = opts.fallback === undefined ? [] : Array.isArray(opts.fallback) ? opts.fallback : [opts.fallback];\n for (const fb of chain) {\n if (isAvailable(fb)) {\n const fbId = canonicalId(fb) ?? fb;\n return {\n ok: false,\n model: fbId,\n requested: id,\n provider,\n fellBack: true,\n status: entry?.status ?? \"suspended\",\n reason: entry?.note ?? `${id} is unavailable`,\n };\n }\n }\n\n // No usable fallback.\n if (opts.throwIfUnavailable) {\n throw new ModelUnavailableError(id, entry?.note, provider);\n }\n return {\n ok: false,\n model: id,\n requested: id,\n provider,\n fellBack: false,\n status: entry?.status ?? \"suspended\",\n reason: entry?.note ?? `${id} is unavailable`,\n };\n}\n"],"mappings":";AAsBA,IAAM,yBAAyB;AAM/B,IAAM,WAA4B;AAAA;AAAA,EAEhC,EAAE,IAAI,oBAAoB,SAAS,CAAC,SAAS,MAAM,GAAG,UAAU,aAAa,WAAW,MAAM,QAAQ,aAAa,QAAQ,UAAU;AAAA,EACrI,EAAE,IAAI,qBAAqB,SAAS,CAAC,UAAU,OAAO,GAAG,UAAU,aAAa,WAAW,MAAM,QAAQ,aAAa,QAAQ,UAAU;AAAA,EACxI,EAAE,IAAI,mBAAmB,SAAS,CAAC,QAAQ,UAAU,GAAG,UAAU,aAAa,WAAW,MAAM,QAAQ,aAAa,QAAQ,UAAU;AAAA,EACvI,EAAE,IAAI,kBAAkB,SAAS,CAAC,OAAO,GAAG,UAAU,aAAa,WAAW,OAAO,QAAQ,aAAa,MAAM,wBAAwB,QAAQ,UAAU;AAAA,EAC1J,EAAE,IAAI,mBAAmB,SAAS,CAAC,QAAQ,GAAG,UAAU,aAAa,WAAW,OAAO,QAAQ,aAAa,MAAM,wBAAwB,QAAQ,UAAU;AAAA;AAAA,EAE5J,EAAE,IAAI,oBAAoB,SAAS,CAAC,cAAc,GAAG,UAAU,UAAU,WAAW,MAAM,QAAQ,aAAa,QAAQ,UAAU;AAAA,EACjI,EAAE,IAAI,yBAAyB,SAAS,CAAC,qBAAqB,OAAO,GAAG,UAAU,UAAU,WAAW,MAAM,QAAQ,aAAa,QAAQ,UAAU;AAAA;AAAA,EAEpJ,EAAE,IAAI,0BAA0B,SAAS,CAAC,WAAW,GAAG,UAAU,UAAU,WAAW,MAAM,QAAQ,aAAa,QAAQ,UAAU;AAAA;AAAA,EAEpI,EAAE,IAAI,wBAAwB,SAAS,CAAC,eAAe,GAAG,UAAU,WAAW,WAAW,MAAM,QAAQ,aAAa,QAAQ,UAAU;AAAA,EACvI,EAAE,IAAI,wBAAwB,SAAS,CAAC,eAAe,GAAG,UAAU,WAAW,WAAW,MAAM,QAAQ,aAAa,QAAQ,UAAU;AACzI;AAKA,IAAI,UAAU,oBAAI,IAA2B;AAE7C,IAAI,cAAc,oBAAI,IAAoB;AAE1C,SAAS,OAAa;AACpB,YAAU,IAAI,IAAI,SAAS,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,GAAG,GAAG,SAAS,CAAC,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;AAChF,gBAAc,oBAAI,IAAI;AACtB,aAAW,KAAK,SAAU,YAAW,KAAK,EAAE,QAAS,aAAY,IAAI,GAAG,EAAE,EAAE;AAC9E;AACA,KAAK;AAGE,SAAS,gBAAsB;AACpC,OAAK;AACP;AAGO,SAAS,YAAY,WAAkC;AAC5D,MAAI,QAAQ,IAAI,SAAS,EAAG,QAAO;AACnC,SAAO,YAAY,IAAI,SAAS,KAAK;AACvC;AAGO,SAAS,SAAS,WAA8C;AACrE,QAAM,KAAK,YAAY,SAAS;AAChC,SAAO,KAAK,QAAQ,IAAI,EAAE,IAAI;AAChC;AAGO,SAAS,WAAW,UAAkC;AAC3D,QAAM,OAAsB,CAAC;AAC7B,aAAW,KAAK,QAAQ,OAAO,GAAG;AAChC,QAAI,YAAY,EAAE,aAAa,SAAU;AACzC,SAAK,KAAK;AAAA,MACR,IAAI,EAAE;AAAA,MACN,OAAO,EAAE,QAAQ,CAAC;AAAA,MAClB,UAAU,EAAE;AAAA,MACZ,WAAW,EAAE;AAAA,MACb,QAAQ,EAAE;AAAA,MACV,MAAM,EAAE;AAAA,MACR,QAAQ,EAAE;AAAA,IACZ,CAAC;AAAA,EACH;AACA,SAAO;AACT;AAGO,SAAS,YAAY,UAA4B;AACtD,SAAO,CAAC,GAAG,QAAQ,OAAO,CAAC,EAAE,OAAO,CAAC,MAAM,EAAE,aAAa,QAAQ,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE;AACrF;AAGO,SAAS,gBAAgB,IAAY,WAAoB,MAAqB;AACnF,QAAM,IAAI,QAAQ,IAAI,EAAE;AACxB,MAAI,CAAC,EAAG;AACR,IAAE,YAAY;AACd,IAAE,SAAS,YAAY,cAAc;AACrC,IAAE,SAAS;AACX,MAAI,SAAS,OAAW,GAAE,OAAO;AAAA,WACxB,UAAW,GAAE,OAAO;AAC/B;;;AC/DO,IAAM,wBAAN,cAAoC,MAAM;AAAA,EACtC,OAAO;AAAA,EACP;AAAA,EACA;AAAA,EACA;AAAA,EACT,YAAY,WAAmB,MAAe,UAAmB;AAC/D,UAAM,UAAU,SAAS,mBAAmB,OAAO,KAAK,IAAI,MAAM,EAAE,EAAE;AACtE,SAAK,OAAO;AACZ,SAAK,YAAY;AACjB,SAAK,OAAO;AACZ,SAAK,WAAW;AAAA,EAClB;AACF;;;ACtCO,SAAS,WAAW,OAA8B,CAAC,GAAkB;AAC1E,SAAO,WAAW,KAAK,QAAQ;AACjC;AAGA,SAAS,YAAY,WAA4B;AAC/C,QAAM,IAAI,SAAS,SAAS;AAC5B,SAAO,IAAI,EAAE,YAAY;AAC3B;AAWO,SAAS,aAAa,WAAmB,OAAuB,CAAC,GAAkB;AACxF,QAAM,KAAK,YAAY,SAAS,KAAK;AACrC,QAAM,QAAQ,SAAS,SAAS;AAChC,QAAM,WAAW,KAAK,YAAY,OAAO;AAEzC,MAAI,YAAY,SAAS,GAAG;AAC1B,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,WAAW;AAAA,MACX;AAAA,MACA,UAAU;AAAA,MACV,QAAQ,OAAO,UAAU;AAAA,IAC3B;AAAA,EACF;AAGA,QAAM,QAAQ,KAAK,aAAa,SAAY,CAAC,IAAI,MAAM,QAAQ,KAAK,QAAQ,IAAI,KAAK,WAAW,CAAC,KAAK,QAAQ;AAC9G,aAAW,MAAM,OAAO;AACtB,QAAI,YAAY,EAAE,GAAG;AACnB,YAAM,OAAO,YAAY,EAAE,KAAK;AAChC,aAAO;AAAA,QACL,IAAI;AAAA,QACJ,OAAO;AAAA,QACP,WAAW;AAAA,QACX;AAAA,QACA,UAAU;AAAA,QACV,QAAQ,OAAO,UAAU;AAAA,QACzB,QAAQ,OAAO,QAAQ,GAAG,EAAE;AAAA,MAC9B;AAAA,IACF;AAAA,EACF;AAGA,MAAI,KAAK,oBAAoB;AAC3B,UAAM,IAAI,sBAAsB,IAAI,OAAO,MAAM,QAAQ;AAAA,EAC3D;AACA,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,WAAW;AAAA,IACX;AAAA,IACA,UAAU;AAAA,IACV,QAAQ,OAAO,UAAU;AAAA,IACzB,QAAQ,OAAO,QAAQ,GAAG,EAAE;AAAA,EAC9B;AACF;","names":[]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
+
export { AvailabilitySource, AvailabilityStatus, ModelStatus, ModelUnavailableError, ResolveOptions, ResolveResult, listModels, resolveModel } from './registry.js';
|
|
2
3
|
|
|
3
4
|
/** How a call reaches the model. `http` = provider REST API; `subprocess` = local
|
|
4
5
|
* `claude -p` CLI (Max plan, costUsd 0). */
|
|
@@ -1501,6 +1502,16 @@ declare const aiConfigSchema: z.ZodObject<{
|
|
|
1501
1502
|
perCallUsd?: number | undefined;
|
|
1502
1503
|
rollingUsd?: number | undefined;
|
|
1503
1504
|
}>>;
|
|
1505
|
+
availability: z.ZodOptional<z.ZodObject<{
|
|
1506
|
+
autoResolve: z.ZodOptional<z.ZodBoolean>;
|
|
1507
|
+
fallback: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
|
|
1508
|
+
}, "strip", z.ZodTypeAny, {
|
|
1509
|
+
fallback?: string | string[] | undefined;
|
|
1510
|
+
autoResolve?: boolean | undefined;
|
|
1511
|
+
}, {
|
|
1512
|
+
fallback?: string | string[] | undefined;
|
|
1513
|
+
autoResolve?: boolean | undefined;
|
|
1514
|
+
}>>;
|
|
1504
1515
|
}, "strip", z.ZodTypeAny, {
|
|
1505
1516
|
defaults?: Partial<Record<"fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding", {
|
|
1506
1517
|
provider: string;
|
|
@@ -1513,6 +1524,10 @@ declare const aiConfigSchema: z.ZodObject<{
|
|
|
1513
1524
|
perCallUsd?: number | undefined;
|
|
1514
1525
|
rollingUsd?: number | undefined;
|
|
1515
1526
|
} | undefined;
|
|
1527
|
+
availability?: {
|
|
1528
|
+
fallback?: string | string[] | undefined;
|
|
1529
|
+
autoResolve?: boolean | undefined;
|
|
1530
|
+
} | undefined;
|
|
1516
1531
|
}, {
|
|
1517
1532
|
defaults?: Partial<Record<"fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding", {
|
|
1518
1533
|
provider: string;
|
|
@@ -1525,6 +1540,10 @@ declare const aiConfigSchema: z.ZodObject<{
|
|
|
1525
1540
|
perCallUsd?: number | undefined;
|
|
1526
1541
|
rollingUsd?: number | undefined;
|
|
1527
1542
|
} | undefined;
|
|
1543
|
+
availability?: {
|
|
1544
|
+
fallback?: string | string[] | undefined;
|
|
1545
|
+
autoResolve?: boolean | undefined;
|
|
1546
|
+
} | undefined;
|
|
1528
1547
|
}>;
|
|
1529
1548
|
type ChatInput = z.infer<typeof chatInputSchema>;
|
|
1530
1549
|
type VisionInput = z.infer<typeof visionInputSchema>;
|
|
@@ -1696,8 +1715,8 @@ declare const falStubAdapter: ProviderAdapter;
|
|
|
1696
1715
|
* wires the live adapters. */
|
|
1697
1716
|
declare const stubProviders: Record<string, ProviderAdapter>;
|
|
1698
1717
|
|
|
1699
|
-
declare const VERSION: "0.
|
|
1700
|
-
declare const SDK_TAG: "@broberg/ai-sdk@0.
|
|
1718
|
+
declare const VERSION: "0.12.0";
|
|
1719
|
+
declare const SDK_TAG: "@broberg/ai-sdk@0.12.0";
|
|
1701
1720
|
|
|
1702
1721
|
/** Built-in defaults. Every entry is overridable via AiConfig.defaults or a
|
|
1703
1722
|
* per-call override. Model IDs are current at scaffold time; callers pin their
|
|
@@ -1713,6 +1732,36 @@ declare const DEFAULT_TIER_MAP: Record<Tier, TierSpec>;
|
|
|
1713
1732
|
*/
|
|
1714
1733
|
declare function resolveTier(tier: Tier, override?: Partial<TierSpec>, configMap?: Partial<Record<Tier, TierSpec>>): TierSpec;
|
|
1715
1734
|
|
|
1735
|
+
interface RefreshOptions {
|
|
1736
|
+
/** Only "anthropic" is wired in v1 (where the incident hit). */
|
|
1737
|
+
provider?: "anthropic";
|
|
1738
|
+
/** Injectable for tests. Defaults to global fetch. */
|
|
1739
|
+
fetch?: typeof fetch;
|
|
1740
|
+
/** Defaults to process.env.ANTHROPIC_API_KEY. */
|
|
1741
|
+
apiKey?: string;
|
|
1742
|
+
/** Min ms between live fetches for a provider (default 1h). */
|
|
1743
|
+
ttlMs?: number;
|
|
1744
|
+
/** Injectable clock for deterministic TTL tests. Defaults to Date.now(). */
|
|
1745
|
+
now?: number;
|
|
1746
|
+
}
|
|
1747
|
+
interface RefreshResult {
|
|
1748
|
+
refreshed: boolean;
|
|
1749
|
+
checked: number;
|
|
1750
|
+
markedUnavailable: string[];
|
|
1751
|
+
}
|
|
1752
|
+
/** Reset the TTL bookkeeping. For tests. */
|
|
1753
|
+
declare function resetRefreshState(): void;
|
|
1754
|
+
/**
|
|
1755
|
+
* Reconcile tracked models against the provider's live list. For Anthropic:
|
|
1756
|
+
* GET /v1/models — any tracked anthropic id NOT in the live set is marked
|
|
1757
|
+
* unavailable; ids present are (re)marked available. TTL-cached; a fetch within
|
|
1758
|
+
* the window is a no-op. Returns { refreshed:false } on any error or missing key.
|
|
1759
|
+
*/
|
|
1760
|
+
declare function refreshAvailability(opts?: RefreshOptions): Promise<RefreshResult>;
|
|
1761
|
+
|
|
1762
|
+
/** Reset the overlay back to the curated defaults. For tests. */
|
|
1763
|
+
declare function resetRegistry(): void;
|
|
1764
|
+
|
|
1716
1765
|
/**
|
|
1717
1766
|
* Cost in USD for a call. cache-read/creation tokens are priced separately when
|
|
1718
1767
|
* the pricing entry defines rates for them; otherwise they fall back to the
|
|
@@ -1890,4 +1939,4 @@ interface StreamTransportRequest extends TransportRequest {
|
|
|
1890
1939
|
*/
|
|
1891
1940
|
declare function streamTransport(req: StreamTransportRequest): AsyncIterable<string>;
|
|
1892
1941
|
|
|
1893
|
-
export { type AiClient, type AiConfig, type BatchJob, type BatchRequestItem, type BatchResultItem, type BudgetConfig, BudgetExceededError, BudgetGuard, type BudgetStore, type CallOptions, type Capability, type ChatInput, type ChatRequest, type ChatResult, type ChatStreamEvent, type ClassifyInput, type ClassifyResult, type ContentPart, type Contracts, type CostSink, type CostSummary, DEFAULT_TIER_MAP, type DesignInput, type DesignResult, type DialogueRequest, type DialogueTurn, type DiscordSinkConfig, ELEVENLABS_DANISH_VOICES, type EmbeddingInput, type EmbeddingRequest, type EmbeddingResult, type ExtractInput, type ExtractResult, type FalAdapterConfig, type HttpResponse, type ImageInput, type ImageRequest, type ImageResult, type LoraWeight, type Message, type MockupInput, type MockupResult, type ModerationInput, type ModerationItem, type ModerationRequest, type ModerationResult, type OcrInput, type OcrPage, type OcrRequest, type OcrResult, type OpenAICompatibleConfig, type PodcastInput, type PodcastResult, type PricingEntry, type ProviderAdapter, type RerankInput, type RerankResult, type Role, SDK_TAG, type SqliteBudgetStoreConfig, type SqliteSinkConfig, StreamHttpError, type SubprocessResponse, type Tier, type TierSpec, type Tool, type ToolCall, type TrainStyleInput, type TrainStyleRequest, type TrainStyleResult, type TranscribeInput, type TranscribeRequest, type TranscribeResult, type TranslateInput, type TranslateResult, type Transport, type TransportRequest, type TransportResponse, type TtsInput, type TtsRequest, type UpmetricsSinkConfig, type Usage, VERSION, type VideoInput, type VisionInput, aiConfigSchema, anthropicAdapter, anthropicApiAdapter, anthropicSubprocessAdapter, chatInputSchema, computeCost, createAI, deepinfraAdapter, defaultProviders, discordSink, elevenlabsAdapter, embeddingInputSchema, falAdapter, falStubAdapter, freshUsage, fromProviderToolCall, geminiAdapter, getCostSummary, getPrice, httpTransport, imageInputSchema, makeContracts, makeOpenAICompatibleAdapter, messageSchema, mistralAdapter, multiSink, noopSink, openaiAdapter, openaiStubAdapter, openrouterAdapter, parseClaudeCliJson, parseJsonLoose, resolveTier, resolveVoice, sqliteBudgetStore, sqliteSink, streamTransport, stubProviders, subprocessTransport, tierSpecSchema, toProviderTools, toolSchema, translateInputSchema, upmetricsSink, visionInputSchema };
|
|
1942
|
+
export { type AiClient, type AiConfig, type BatchJob, type BatchRequestItem, type BatchResultItem, type BudgetConfig, BudgetExceededError, BudgetGuard, type BudgetStore, type CallOptions, type Capability, type ChatInput, type ChatRequest, type ChatResult, type ChatStreamEvent, type ClassifyInput, type ClassifyResult, type ContentPart, type Contracts, type CostSink, type CostSummary, DEFAULT_TIER_MAP, type DesignInput, type DesignResult, type DialogueRequest, type DialogueTurn, type DiscordSinkConfig, ELEVENLABS_DANISH_VOICES, type EmbeddingInput, type EmbeddingRequest, type EmbeddingResult, type ExtractInput, type ExtractResult, type FalAdapterConfig, type HttpResponse, type ImageInput, type ImageRequest, type ImageResult, type LoraWeight, type Message, type MockupInput, type MockupResult, type ModerationInput, type ModerationItem, type ModerationRequest, type ModerationResult, type OcrInput, type OcrPage, type OcrRequest, type OcrResult, type OpenAICompatibleConfig, type PodcastInput, type PodcastResult, type PricingEntry, type ProviderAdapter, type RefreshOptions, type RefreshResult, type RerankInput, type RerankResult, type Role, SDK_TAG, type SqliteBudgetStoreConfig, type SqliteSinkConfig, StreamHttpError, type SubprocessResponse, type Tier, type TierSpec, type Tool, type ToolCall, type TrainStyleInput, type TrainStyleRequest, type TrainStyleResult, type TranscribeInput, type TranscribeRequest, type TranscribeResult, type TranslateInput, type TranslateResult, type Transport, type TransportRequest, type TransportResponse, type TtsInput, type TtsRequest, type UpmetricsSinkConfig, type Usage, VERSION, type VideoInput, type VisionInput, aiConfigSchema, anthropicAdapter, anthropicApiAdapter, anthropicSubprocessAdapter, chatInputSchema, computeCost, createAI, deepinfraAdapter, defaultProviders, discordSink, elevenlabsAdapter, embeddingInputSchema, falAdapter, falStubAdapter, freshUsage, fromProviderToolCall, geminiAdapter, getCostSummary, getPrice, httpTransport, imageInputSchema, makeContracts, makeOpenAICompatibleAdapter, messageSchema, mistralAdapter, multiSink, noopSink, openaiAdapter, openaiStubAdapter, openrouterAdapter, parseClaudeCliJson, parseJsonLoose, refreshAvailability, resetRefreshState, resetRegistry, resolveTier, resolveVoice, sqliteBudgetStore, sqliteSink, streamTransport, stubProviders, subprocessTransport, tierSpecSchema, toProviderTools, toolSchema, translateInputSchema, upmetricsSink, visionInputSchema };
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ModelUnavailableError,
|
|
3
|
+
listModels,
|
|
4
|
+
providerIds,
|
|
5
|
+
resetRegistry,
|
|
6
|
+
resolveModel,
|
|
7
|
+
setAvailability
|
|
8
|
+
} from "./chunk-HVZSYNZ5.js";
|
|
9
|
+
|
|
1
10
|
// src/routing/tier-map.ts
|
|
2
11
|
var DEFAULT_TIER_MAP = {
|
|
3
12
|
fast: { provider: "anthropic", model: "claude-haiku-4-5", transport: "http" },
|
|
@@ -1930,13 +1939,18 @@ var budgetSchema = z.object({
|
|
|
1930
1939
|
perCallUsd: z.number().positive().optional(),
|
|
1931
1940
|
rollingUsd: z.number().positive().optional()
|
|
1932
1941
|
});
|
|
1942
|
+
var availabilitySchema = z.object({
|
|
1943
|
+
autoResolve: z.boolean().optional(),
|
|
1944
|
+
fallback: z.union([z.string(), z.array(z.string())]).optional()
|
|
1945
|
+
});
|
|
1933
1946
|
var aiConfigSchema = z.object({
|
|
1934
1947
|
defaults: z.record(tierSchema, tierSpecSchema).optional(),
|
|
1935
1948
|
// Functions can't be deeply validated — z.custom asserts the TS type and
|
|
1936
1949
|
// passes the value through untouched.
|
|
1937
1950
|
providers: z.record(z.string(), z.custom()).optional(),
|
|
1938
1951
|
costSink: z.custom().optional(),
|
|
1939
|
-
budget: budgetSchema.optional()
|
|
1952
|
+
budget: budgetSchema.optional(),
|
|
1953
|
+
availability: availabilitySchema.optional()
|
|
1940
1954
|
});
|
|
1941
1955
|
|
|
1942
1956
|
// src/client.ts
|
|
@@ -2009,9 +2023,14 @@ function createAI(config = {}) {
|
|
|
2009
2023
|
msgs.push({ role: "user", content: input.prompt ?? "" });
|
|
2010
2024
|
return msgs;
|
|
2011
2025
|
}
|
|
2026
|
+
function applyAvailability(spec) {
|
|
2027
|
+
if (!cfg.availability?.autoResolve) return spec;
|
|
2028
|
+
const r = resolveModel(spec.model, { fallback: cfg.availability.fallback, provider: spec.provider });
|
|
2029
|
+
return r.fellBack ? { ...spec, model: r.model } : spec;
|
|
2030
|
+
}
|
|
2012
2031
|
async function runCapability(opts) {
|
|
2013
2032
|
const routes = [
|
|
2014
|
-
opts.primary,
|
|
2033
|
+
applyAvailability(opts.primary),
|
|
2015
2034
|
...(opts.fallback ?? []).map(
|
|
2016
2035
|
(f) => typeof f === "string" ? resolveTier(f, void 0, cfg.defaults) : f
|
|
2017
2036
|
)
|
|
@@ -2470,8 +2489,53 @@ var stubProviders = {
|
|
|
2470
2489
|
};
|
|
2471
2490
|
|
|
2472
2491
|
// src/version.ts
|
|
2473
|
-
var VERSION = "0.
|
|
2474
|
-
var SDK_TAG = "@broberg/ai-sdk@0.
|
|
2492
|
+
var VERSION = "0.12.0";
|
|
2493
|
+
var SDK_TAG = "@broberg/ai-sdk@0.12.0";
|
|
2494
|
+
|
|
2495
|
+
// src/availability/refresh.ts
|
|
2496
|
+
var NOT_REFRESHED = { refreshed: false, checked: 0, markedUnavailable: [] };
|
|
2497
|
+
var DEFAULT_TTL_MS = 60 * 60 * 1e3;
|
|
2498
|
+
var ANTHROPIC_MODELS_URL = "https://api.anthropic.com/v1/models";
|
|
2499
|
+
var lastRefreshAt = /* @__PURE__ */ new Map();
|
|
2500
|
+
function resetRefreshState() {
|
|
2501
|
+
lastRefreshAt.clear();
|
|
2502
|
+
}
|
|
2503
|
+
async function refreshAvailability(opts = {}) {
|
|
2504
|
+
const provider = opts.provider ?? "anthropic";
|
|
2505
|
+
if (provider !== "anthropic") return NOT_REFRESHED;
|
|
2506
|
+
const ttl = opts.ttlMs ?? DEFAULT_TTL_MS;
|
|
2507
|
+
const now = opts.now ?? Date.now();
|
|
2508
|
+
const last = lastRefreshAt.get(provider);
|
|
2509
|
+
if (last !== void 0 && now - last < ttl) return NOT_REFRESHED;
|
|
2510
|
+
const apiKey = opts.apiKey ?? process.env.ANTHROPIC_API_KEY;
|
|
2511
|
+
if (!apiKey) return NOT_REFRESHED;
|
|
2512
|
+
const f = opts.fetch ?? fetch;
|
|
2513
|
+
let liveIds;
|
|
2514
|
+
try {
|
|
2515
|
+
const res = await f(ANTHROPIC_MODELS_URL, {
|
|
2516
|
+
headers: { "x-api-key": apiKey, "anthropic-version": "2023-06-01", accept: "application/json" }
|
|
2517
|
+
});
|
|
2518
|
+
if (!res.ok) return NOT_REFRESHED;
|
|
2519
|
+
const json = await res.json();
|
|
2520
|
+
liveIds = new Set((json.data ?? []).map((m) => m.id).filter((id) => typeof id === "string"));
|
|
2521
|
+
} catch {
|
|
2522
|
+
return NOT_REFRESHED;
|
|
2523
|
+
}
|
|
2524
|
+
if (liveIds.size === 0) return NOT_REFRESHED;
|
|
2525
|
+
const tracked = providerIds(provider);
|
|
2526
|
+
const markedUnavailable = [];
|
|
2527
|
+
for (const id of tracked) {
|
|
2528
|
+
const live = liveIds.has(id);
|
|
2529
|
+
if (live) {
|
|
2530
|
+
setAvailability(id, true);
|
|
2531
|
+
} else {
|
|
2532
|
+
setAvailability(id, false, "not in provider model list (live refresh)");
|
|
2533
|
+
markedUnavailable.push(id);
|
|
2534
|
+
}
|
|
2535
|
+
}
|
|
2536
|
+
lastRefreshAt.set(provider, now);
|
|
2537
|
+
return { refreshed: true, checked: tracked.length, markedUnavailable };
|
|
2538
|
+
}
|
|
2475
2539
|
|
|
2476
2540
|
// src/cost/budget-store.ts
|
|
2477
2541
|
function sqliteBudgetStore(config) {
|
|
@@ -2704,6 +2768,7 @@ export {
|
|
|
2704
2768
|
BudgetGuard,
|
|
2705
2769
|
DEFAULT_TIER_MAP,
|
|
2706
2770
|
ELEVENLABS_DANISH_VOICES,
|
|
2771
|
+
ModelUnavailableError,
|
|
2707
2772
|
SDK_TAG,
|
|
2708
2773
|
StreamHttpError,
|
|
2709
2774
|
VERSION,
|
|
@@ -2728,6 +2793,7 @@ export {
|
|
|
2728
2793
|
getPrice,
|
|
2729
2794
|
httpTransport,
|
|
2730
2795
|
imageInputSchema,
|
|
2796
|
+
listModels,
|
|
2731
2797
|
makeContracts,
|
|
2732
2798
|
makeOpenAICompatibleAdapter,
|
|
2733
2799
|
messageSchema,
|
|
@@ -2739,6 +2805,10 @@ export {
|
|
|
2739
2805
|
openrouterAdapter,
|
|
2740
2806
|
parseClaudeCliJson,
|
|
2741
2807
|
parseJsonLoose,
|
|
2808
|
+
refreshAvailability,
|
|
2809
|
+
resetRefreshState,
|
|
2810
|
+
resetRegistry,
|
|
2811
|
+
resolveModel,
|
|
2742
2812
|
resolveTier,
|
|
2743
2813
|
resolveVoice,
|
|
2744
2814
|
sqliteBudgetStore,
|