@sahan-sac/ai-core 0.3.0 → 0.4.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/image.js CHANGED
@@ -1,240 +1,18 @@
1
- // src/image.ts
2
- import "server-only";
3
-
4
- // src/models.ts
5
- var DEFAULT_IMAGE_MODELS = {
6
- nvidia: "black-forest-labs/flux.1-dev",
7
- gemini: "gemini-3.1-flash-image",
8
- vertex: "gemini-3.1-flash-image"
9
- };
10
- var pick = (...values) => values.find((value) => value && value.trim()).trim();
11
- function imageModels(env) {
12
- return {
13
- nvidia: pick(env.IMAGE_NVIDIA_MODEL, DEFAULT_IMAGE_MODELS.nvidia),
14
- gemini: pick(env.IMAGE_GEMINI_MODEL, DEFAULT_IMAGE_MODELS.gemini),
15
- vertex: pick(env.IMAGE_VERTEX_MODEL, env.IMAGEN_MODEL, DEFAULT_IMAGE_MODELS.vertex)
16
- };
17
- }
18
- var paidAllowed = (env) => env.AI_ALLOW_PAID === true;
19
- function vertexConfigured(env) {
20
- return Boolean(env.GOOGLE_CLIENT_EMAIL && env.GOOGLE_PRIVATE_KEY && env.GOOGLE_CLOUD_PROJECT);
21
- }
22
-
23
- // src/vertex.ts
24
- import "server-only";
25
- var cachedToken = null;
26
- function base64UrlEncode(input) {
27
- return Buffer.from(input).toString("base64url");
28
- }
29
- async function getVertexAccessToken(account, fetchImpl = fetch) {
30
- const now = Date.now();
31
- if (cachedToken && cachedToken.expiresAt - 6e4 > now) return cachedToken.accessToken;
32
- const { createSign } = await import("crypto");
33
- const issuedAt = Math.floor(now / 1e3);
34
- const expiresIn = 3600;
35
- const header = base64UrlEncode(JSON.stringify({ alg: "RS256", typ: "JWT" }));
36
- const claims = base64UrlEncode(
37
- JSON.stringify({
38
- iss: account.clientEmail,
39
- scope: "https://www.googleapis.com/auth/cloud-platform",
40
- aud: account.tokenUri,
41
- iat: issuedAt,
42
- exp: issuedAt + expiresIn
43
- })
44
- );
45
- const signingInput = `${header}.${claims}`;
46
- const signature = createSign("RSA-SHA256").update(signingInput).sign(account.privateKey);
47
- const jwt = `${signingInput}.${base64UrlEncode(signature)}`;
48
- const response = await fetchImpl(account.tokenUri, {
49
- method: "POST",
50
- headers: { "content-type": "application/x-www-form-urlencoded" },
51
- body: new URLSearchParams({
52
- grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer",
53
- assertion: jwt
54
- })
55
- });
56
- if (!response.ok) {
57
- throw new Error(`Vertex token exchange failed: HTTP ${response.status}`);
58
- }
59
- const data = await response.json();
60
- cachedToken = { accessToken: data.access_token, expiresAt: now + data.expires_in * 1e3 };
61
- return data.access_token;
62
- }
63
-
64
- // src/image.ts
65
- var DEFAULT_IMAGE_MODELS2 = [
66
- { model: "gemini-3.1-flash-image", location: "global" },
67
- { model: "gemini-2.5-flash-image", location: "us-central1" }
68
- ];
69
- function defaultLocation(model) {
70
- return /^gemini-3/.test(model) ? "global" : "us-central1";
71
- }
72
- function imageModelChain(config) {
73
- const chain = config.model ? [{ model: config.model, location: config.location ?? defaultLocation(config.model) }] : [];
74
- for (const candidate of DEFAULT_IMAGE_MODELS2) {
75
- if (!chain.some((entry) => entry.model === candidate.model)) chain.push(candidate);
76
- }
77
- return chain;
78
- }
79
- function endpoint(project, target, method) {
80
- const host = target.location === "global" ? "aiplatform.googleapis.com" : `${target.location}-aiplatform.googleapis.com`;
81
- return `https://${host}/v1/projects/${project}/locations/${target.location}/publishers/google/models/${target.model}:${method}`;
82
- }
83
- function requestFor(target, prompt, aspectRatio) {
84
- if (target.model.startsWith("imagen-")) {
85
- return {
86
- method: "predict",
87
- body: {
88
- instances: [{ prompt }],
89
- parameters: { sampleCount: 1, aspectRatio, safetySetting: "block_medium_and_above", personGeneration: "allow_adult" }
90
- }
91
- };
92
- }
93
- return {
94
- method: "generateContent",
95
- body: {
96
- contents: [{ role: "user", parts: [{ text: prompt }] }],
97
- generationConfig: { responseModalities: ["IMAGE"], imageConfig: { aspectRatio } }
98
- }
99
- };
100
- }
101
- function extractImage(data) {
102
- const prediction = data?.predictions?.[0];
103
- if (prediction?.bytesBase64Encoded) return { base64: prediction.bytesBase64Encoded, mimeType: prediction.mimeType || "image/png" };
104
- const parts = data?.candidates?.[0]?.content?.parts;
105
- const inline = parts?.find((part) => part.inlineData?.data)?.inlineData;
106
- return inline?.data ? { base64: inline.data, mimeType: inline.mimeType || "image/png" } : null;
107
- }
108
- async function generateImageVertex(prompt, config, options = {}) {
109
- const fetchImpl = options.fetchImpl ?? fetch;
110
- const aspectRatio = options.aspectRatio ?? "16:9";
111
- let accessToken;
112
- try {
113
- accessToken = await getVertexAccessToken(
114
- { clientEmail: config.clientEmail, privateKey: config.privateKey, tokenUri: config.tokenUri },
115
- fetchImpl
116
- );
117
- } catch (error) {
118
- return { ok: false, error: `Image generation failed: ${error instanceof Error ? error.message : "authentication error"}` };
119
- }
120
- const failures = [];
121
- for (const target of imageModelChain(config)) {
122
- if (options.signal?.aborted) return { ok: false, error: "Image generation timed out." };
123
- const { method, body } = requestFor(target, prompt, aspectRatio);
124
- try {
125
- const response = await fetchImpl(endpoint(config.project, target, method), {
126
- method: "POST",
127
- headers: { "content-type": "application/json", authorization: `Bearer ${accessToken}` },
128
- signal: options.signal,
129
- body: JSON.stringify(body)
130
- });
131
- if (!response.ok) {
132
- failures.push(`${target.model}: HTTP ${response.status}`);
133
- continue;
134
- }
135
- const image = extractImage(await response.json());
136
- if (image) return { ok: true, ...image };
137
- failures.push(`${target.model}: no image data`);
138
- } catch (error) {
139
- if (options.signal?.aborted) return { ok: false, error: "Image generation timed out." };
140
- failures.push(`${target.model}: ${error instanceof Error ? error.message : "transport error"}`);
141
- }
142
- }
143
- return { ok: false, error: `Image generation failed (${failures.join("; ")}).` };
144
- }
145
- function vertexImageAvailable(env) {
146
- return vertexConfigured(env);
147
- }
148
- var FLUX_SIZE = {
149
- "16:9": { width: 1344, height: 768 },
150
- "4:3": { width: 1024, height: 768 },
151
- "1:1": { width: 1024, height: 1024 }
152
- };
153
- function nvidiaImageRequest(model, prompt, aspectRatio, seed) {
154
- const size = FLUX_SIZE[aspectRatio];
155
- if (/schnell/.test(model)) return { prompt, ...size, steps: 4, seed };
156
- return { prompt, ...size, steps: 30, cfg_scale: 3.5, mode: "base", seed };
157
- }
158
- function extractNvidiaImage(data) {
159
- const artifact = data?.artifacts?.[0];
160
- if (!artifact?.base64 || artifact.finishReason && artifact.finishReason !== "SUCCESS") return null;
161
- const mimeType = artifact.base64.startsWith("/9j/") ? "image/jpeg" : artifact.base64.startsWith("UklG") ? "image/webp" : "image/png";
162
- return { base64: artifact.base64, mimeType };
163
- }
164
- async function postForImage(model, url, init, extract, options) {
165
- try {
166
- const response = await (options.fetchImpl ?? fetch)(url, {
167
- method: "POST",
168
- headers: { "content-type": "application/json", ...init.headers },
169
- signal: options.signal,
170
- body: JSON.stringify(init.body)
171
- });
172
- if (!response.ok) return { ok: false, error: `${model}: HTTP ${response.status}` };
173
- const image = extract(await response.json());
174
- return image ? { ok: true, ...image } : { ok: false, error: `${model}: no image (filtered or empty)` };
175
- } catch (error) {
176
- if (options.signal?.aborted) return { ok: false, error: "Image generation timed out." };
177
- return { ok: false, error: `${model}: ${error instanceof Error ? error.message : "transport error"}` };
178
- }
179
- }
180
- function generateImageNvidia(prompt, config, aspectRatio, options) {
181
- return postForImage(
182
- config.model,
183
- `https://ai.api.nvidia.com/v1/genai/${config.model}`,
184
- {
185
- headers: { authorization: `Bearer ${config.apiKey}`, accept: "application/json" },
186
- body: nvidiaImageRequest(config.model, prompt, aspectRatio, Math.floor(Math.random() * 2 ** 31))
187
- },
188
- extractNvidiaImage,
189
- options
190
- );
191
- }
192
- function generateImageGemini(prompt, config, aspectRatio, options) {
193
- return postForImage(
194
- config.model,
195
- `https://generativelanguage.googleapis.com/v1beta/models/${config.model}:generateContent`,
196
- {
197
- headers: { "x-goog-api-key": config.apiKey },
198
- body: { contents: [{ role: "user", parts: [{ text: prompt }] }], generationConfig: { responseModalities: ["IMAGE"], imageConfig: { aspectRatio } } }
199
- },
200
- extractImage,
201
- options
202
- );
203
- }
204
- function imageConfigFromEnv(env) {
205
- const models = imageModels(env);
206
- const paid = paidAllowed(env);
207
- const config = {};
208
- if (env.NVIDIA_API_KEY) config.nvidia = { apiKey: env.NVIDIA_API_KEY, model: models.nvidia };
209
- if (paid && env.GEMINI_API_KEY) config.gemini = { apiKey: env.GEMINI_API_KEY, model: models.gemini };
210
- if (paid && vertexImageAvailable(env)) {
211
- config.vertex = {
212
- clientEmail: env.GOOGLE_CLIENT_EMAIL,
213
- privateKey: env.GOOGLE_PRIVATE_KEY,
214
- tokenUri: env.GOOGLE_TOKEN_URI,
215
- project: env.GOOGLE_CLOUD_PROJECT,
216
- model: models.vertex
217
- };
218
- }
219
- return config.nvidia || config.gemini || config.vertex ? config : null;
220
- }
221
- async function generateImage(prompt, config, options = {}) {
222
- const aspectRatio = options.aspectRatio ?? "16:9";
223
- const attempts = [];
224
- if (config.nvidia) attempts.push(() => generateImageNvidia(prompt, config.nvidia, aspectRatio, options));
225
- if (config.gemini) attempts.push(() => generateImageGemini(prompt, config.gemini, aspectRatio, options));
226
- if (config.vertex) attempts.push(() => generateImageVertex(prompt, config.vertex, options));
227
- const failures = [];
228
- for (const run of attempts) {
229
- if (options.signal?.aborted) return { ok: false, error: "Image generation timed out." };
230
- const outcome = await run();
231
- if (outcome.ok) return outcome;
232
- failures.push(outcome.error);
233
- }
234
- return { ok: false, error: failures.length ? `Image generation failed (${failures.join("; ")}).` : "No image provider is configured." };
235
- }
1
+ import {
2
+ DEFAULT_IMAGE_MODELS,
3
+ extractImage,
4
+ extractNvidiaImage,
5
+ generateImage,
6
+ generateImageVertex,
7
+ imageConfigFromEnv,
8
+ imageModelChain,
9
+ nvidiaImageRequest,
10
+ vertexImageAvailable
11
+ } from "./chunk-MRNQPHWI.js";
12
+ import "./chunk-BL4J2JNX.js";
13
+ import "./chunk-RBSLNDFW.js";
236
14
  export {
237
- DEFAULT_IMAGE_MODELS2 as DEFAULT_IMAGE_MODELS,
15
+ DEFAULT_IMAGE_MODELS,
238
16
  extractImage,
239
17
  extractNvidiaImage,
240
18
  generateImage,
package/dist/index.js CHANGED
@@ -1,105 +1,8 @@
1
- // src/env.ts
2
- import { z } from "zod";
3
- var text = z.string().optional().transform((value) => {
4
- const trimmed = value?.trim();
5
- return trimmed ? trimmed : void 0;
6
- });
7
- var ON = ["1", "true", "yes", "on"];
8
- var flag = z.string().optional().transform((value) => ON.includes((value ?? "").trim().toLowerCase()));
9
- var flagDefaultOn = z.string().optional().transform((value) => {
10
- const normalized = (value ?? "").trim().toLowerCase();
11
- return normalized === "" || ON.includes(normalized);
12
- });
13
- var privateKey = text.transform((value) => value?.replace(/\\n/g, "\n"));
14
- var DEFAULT_GOOGLE_TOKEN_URI = "https://oauth2.googleapis.com/token";
15
- var aiEnvSchema = z.object({
16
- // Paid providers (Vertex text and images, Gemini images) join the chains
17
- // only with AI_ALLOW_PAID; off by default, so AI costs $0.
18
- AI_ALLOW_PAID: flag,
19
- // Feature switches. The blog assistant is off until turned on; the chatbot
20
- // is on unless turned off. Each also needs a text provider key.
21
- ENABLE_BLOG_AI: flag,
22
- ENABLE_CHATBOT: flagDefaultOn,
23
- OPENROUTER_BASE_URL: text,
24
- OPENROUTER_API_KEY: text,
25
- OPENROUTER_API_KEY_2: text,
26
- OPENROUTER_ALLOW_PAID_MODELS: flag,
27
- GEMINI_API_KEY: text,
28
- NVIDIA_API_KEY: text,
29
- // Model overrides, all optional (models.ts): purpose variable, then the
30
- // provider-wide *_MODEL, then a verified free default.
31
- OPENROUTER_MODEL: text,
32
- GEMINI_MODEL: text,
33
- NVIDIA_MODEL: text,
34
- VERTEX_MODEL: text,
35
- IMAGEN_MODEL: text,
36
- BLOG_GEMINI_MODEL: text,
37
- BLOG_OPENROUTER_MODEL: text,
38
- BLOG_NVIDIA_MODEL: text,
39
- BLOG_VERTEX_MODEL: text,
40
- CHAT_GEMINI_MODEL: text,
41
- CHAT_OPENROUTER_MODEL: text,
42
- CHAT_NVIDIA_MODEL: text,
43
- CHAT_VERTEX_MODEL: text,
44
- IMAGE_NVIDIA_MODEL: text,
45
- IMAGE_GEMINI_MODEL: text,
46
- IMAGE_VERTEX_MODEL: text,
47
- // Provider order (./adapters). Comma-separated adapter ids; only the listed
48
- // ones run, in that order. Per purpose first, then the global one; unset =
49
- // the built-in order (free tiers first, paid last).
50
- AI_PROVIDER_ORDER: text,
51
- AI_PROVIDER_ORDER_BLOG: text,
52
- AI_PROVIDER_ORDER_CHAT: text,
53
- // Paid OpenAI-compatible and Anthropic providers: each joins a chain only
54
- // with its key set and AI_ALLOW_PAID on. Models: purpose variable, then the
55
- // provider-wide one, then the default in ./adapters.
56
- OPENAI_API_KEY: text,
57
- OPENAI_BASE_URL: text,
58
- OPENAI_MODEL: text,
59
- BLOG_OPENAI_MODEL: text,
60
- CHAT_OPENAI_MODEL: text,
61
- ANTHROPIC_API_KEY: text,
62
- ANTHROPIC_BASE_URL: text,
63
- ANTHROPIC_MODEL: text,
64
- BLOG_ANTHROPIC_MODEL: text,
65
- CHAT_ANTHROPIC_MODEL: text,
66
- DEEPSEEK_API_KEY: text,
67
- DEEPSEEK_MODEL: text,
68
- BLOG_DEEPSEEK_MODEL: text,
69
- CHAT_DEEPSEEK_MODEL: text,
70
- XAI_API_KEY: text,
71
- XAI_MODEL: text,
72
- BLOG_XAI_MODEL: text,
73
- CHAT_XAI_MODEL: text,
74
- PERPLEXITY_API_KEY: text,
75
- PERPLEXITY_MODEL: text,
76
- BLOG_PERPLEXITY_MODEL: text,
77
- CHAT_PERPLEXITY_MODEL: text,
78
- // One custom OpenAI-compatible endpoint (a gateway, vLLM, Ollama, LiteLLM).
79
- // Treated as paid unless AI_CUSTOM_FREE is on; the key is optional for a
80
- // local server.
81
- AI_CUSTOM_BASE_URL: text,
82
- AI_CUSTOM_API_KEY: text,
83
- AI_CUSTOM_MODEL: text,
84
- AI_CUSTOM_NAME: text,
85
- AI_CUSTOM_FREE: flag,
86
- // Google Vertex service account (paid).
87
- GOOGLE_CLIENT_EMAIL: text,
88
- GOOGLE_PRIVATE_KEY: privateKey,
89
- GOOGLE_CLOUD_PROJECT: text,
90
- GOOGLE_TOKEN_URI: text.transform((value) => value ?? DEFAULT_GOOGLE_TOKEN_URI)
91
- });
92
- function parseAiEnv(source) {
93
- const result = aiEnvSchema.safeParse(source);
94
- if (!result.success) {
95
- const names = [...new Set(result.error.issues.map((issue) => String(issue.path[0] ?? "?")))];
96
- throw new Error(`Invalid AI environment variables: ${names.join(", ")}`);
97
- }
98
- return result.data;
99
- }
100
- function aiEnvFromProcess() {
101
- return parseAiEnv(process.env);
102
- }
1
+ import {
2
+ aiEnvFromProcess,
3
+ aiEnvSchema,
4
+ parseAiEnv
5
+ } from "./chunk-SI7JE5BG.js";
103
6
  export {
104
7
  aiEnvFromProcess,
105
8
  aiEnvSchema,
package/dist/log.js CHANGED
@@ -1,9 +1,6 @@
1
- // src/log.ts
2
- var consoleAiLogger = {
3
- warn(message, meta) {
4
- console.warn(JSON.stringify({ level: "warn", message, ...meta }));
5
- }
6
- };
1
+ import {
2
+ consoleAiLogger
3
+ } from "./chunk-PMC3UWQ2.js";
7
4
  export {
8
5
  consoleAiLogger
9
6
  };
package/dist/models.js CHANGED
@@ -1,54 +1,12 @@
1
- // src/models.ts
2
- var DEFAULT_TEXT_MODELS = {
3
- // Long structured JSON: a full flash model, not lite.
4
- blog: {
5
- gemini: "gemini-2.5-flash",
6
- openrouter: "nvidia/nemotron-3-super-120b-a12b:free",
7
- nvidia: "nvidia/nemotron-3-super-120b-a12b",
8
- vertex: "gemini-2.5-flash"
9
- },
10
- // Short, latency-sensitive replies: the fastest free model first.
11
- chat: {
12
- gemini: "gemini-3.1-flash-lite",
13
- openrouter: "nvidia/nemotron-3-super-120b-a12b:free",
14
- nvidia: "nvidia/nemotron-3-super-120b-a12b",
15
- vertex: "gemini-2.5-flash"
16
- }
17
- };
18
- var DEFAULT_IMAGE_MODELS = {
19
- nvidia: "black-forest-labs/flux.1-dev",
20
- gemini: "gemini-3.1-flash-image",
21
- vertex: "gemini-3.1-flash-image"
22
- };
23
- var pick = (...values) => values.find((value) => value && value.trim()).trim();
24
- function textModels(env, purpose) {
25
- const defaults = DEFAULT_TEXT_MODELS[purpose];
26
- const own = purpose === "blog" ? { gemini: env.BLOG_GEMINI_MODEL, openrouter: env.BLOG_OPENROUTER_MODEL, nvidia: env.BLOG_NVIDIA_MODEL, vertex: env.BLOG_VERTEX_MODEL } : { gemini: env.CHAT_GEMINI_MODEL, openrouter: env.CHAT_OPENROUTER_MODEL, nvidia: env.CHAT_NVIDIA_MODEL, vertex: env.CHAT_VERTEX_MODEL };
27
- return {
28
- gemini: pick(own.gemini, env.GEMINI_MODEL, defaults.gemini),
29
- openrouter: pick(own.openrouter, env.OPENROUTER_MODEL, defaults.openrouter),
30
- nvidia: pick(own.nvidia, env.NVIDIA_MODEL, defaults.nvidia),
31
- vertex: pick(own.vertex, env.VERTEX_MODEL, defaults.vertex)
32
- };
33
- }
34
- function imageModels(env) {
35
- return {
36
- nvidia: pick(env.IMAGE_NVIDIA_MODEL, DEFAULT_IMAGE_MODELS.nvidia),
37
- gemini: pick(env.IMAGE_GEMINI_MODEL, DEFAULT_IMAGE_MODELS.gemini),
38
- vertex: pick(env.IMAGE_VERTEX_MODEL, env.IMAGEN_MODEL, DEFAULT_IMAGE_MODELS.vertex)
39
- };
40
- }
41
- var paidAllowed = (env) => env.AI_ALLOW_PAID === true;
42
- function vertexConfigured(env) {
43
- return Boolean(env.GOOGLE_CLIENT_EMAIL && env.GOOGLE_PRIVATE_KEY && env.GOOGLE_CLOUD_PROJECT);
44
- }
45
- function thinkingConfigFor(model, maxOutputTokens) {
46
- const long = maxOutputTokens >= 2e3;
47
- if (/^gemini-[3-9]/.test(model)) {
48
- return { thinkingLevel: long ? "low" : /flash/.test(model) ? "minimal" : "low" };
49
- }
50
- return { thinkingBudget: long ? Math.min(800, Math.floor(maxOutputTokens / 5)) : 0 };
51
- }
1
+ import {
2
+ DEFAULT_IMAGE_MODELS,
3
+ DEFAULT_TEXT_MODELS,
4
+ imageModels,
5
+ paidAllowed,
6
+ textModels,
7
+ thinkingConfigFor,
8
+ vertexConfigured
9
+ } from "./chunk-RBSLNDFW.js";
52
10
  export {
53
11
  DEFAULT_IMAGE_MODELS,
54
12
  DEFAULT_TEXT_MODELS,
@@ -70,6 +70,13 @@ interface AiHealth {
70
70
  declare const createAiHealth: () => AiHealth;
71
71
  /** One per server instance, for request handlers; tests and scripts get a fresh one by default. */
72
72
  declare const sharedAiHealth: AiHealth;
73
+ /**
74
+ * Quota and slowness pass quickly; a wrong key or a retired model needs an
75
+ * operator, so it cools longer; an empty prepaid wallet (402) needs someone to
76
+ * add funds, so it cools longest and costs one probe per half hour instead of
77
+ * a failed round trip on every request.
78
+ */
79
+ declare function cooldownFor(outcome: AiOutcome): number;
73
80
  interface AiServiceDeps {
74
81
  providers: readonly AiProvider[];
75
82
  /** Per-provider attempt budget. */
@@ -188,12 +195,35 @@ interface ProviderAdapter {
188
195
  /** Lowercase id used in AI_PROVIDER_ORDER. */
189
196
  readonly id: string;
190
197
  readonly label: string;
198
+ /**
199
+ * Purposes it joins under the default order; unset means all. An explicit
200
+ * AI_PROVIDER_ORDER(_BLOG|_CHAT) still adds it anywhere it is listed.
201
+ */
202
+ readonly defaultPurposes?: readonly TextPurpose[];
191
203
  /** Costs money: runs only with AI_ALLOW_PAID. */
192
204
  paid(env: AiEnv): boolean;
193
205
  /** Env variable names still missing; empty means configured. Never values. */
194
206
  missing(env: AiEnv): string[];
195
207
  create(context: AdapterContext): AiProvider;
196
208
  }
209
+ /**
210
+ * Defaults for the free-tier adapters that take an id per purpose. The blog
211
+ * writes long JSON, so it gets the larger model; chat gets the faster one.
212
+ */
213
+ declare const FREE_TEXT_MODELS: {
214
+ readonly groq: {
215
+ readonly blog: "openai/gpt-oss-120b";
216
+ readonly chat: "openai/gpt-oss-20b";
217
+ };
218
+ readonly mistral: {
219
+ readonly blog: "mistral-medium-latest";
220
+ readonly chat: "mistral-small-latest";
221
+ };
222
+ readonly cloudflare: {
223
+ readonly blog: "@cf/openai/gpt-oss-120b";
224
+ readonly chat: "@cf/openai/gpt-oss-20b";
225
+ };
226
+ };
197
227
  /**
198
228
  * Defaults for the paid adapters. Model names change often: set the
199
229
  * provider's *_MODEL variable rather than relying on these.
@@ -290,4 +320,4 @@ declare function checkChain(env: AiEnv, purpose: TextPurpose, options?: {
290
320
  */
291
321
  declare function realProviders(env: AiEnv, purpose: TextPurpose, fetchImpl?: typeof fetch, adapters?: readonly ProviderAdapter[]): AiProvider[];
292
322
 
293
- export { type AdapterContext as A, AI_COOLDOWN_MS, AI_TIMEOUT_MS, type AiAttempt, type AiAttemptStatus, type AiGenerateOptions, type AiHealth, type AiOutcome, type AiProvider, type AiResult, type AiServiceDeps, BUILTIN_ADAPTERS as B, CHECK_PROMPT as C, DEFAULT_ORDER as D, HEDGE, type JsonMode, PAID_TEXT_MODELS as P, type AdapterState as a, anthropicOutcome, anthropicProvider, type AdapterStatus as b, type ProviderAdapter as c, createAiHealth, createAiService, type ProviderCheck as d, chainPlan as e, checkChain as f, checkProvider as g, geminiOutcome, geminiProvider, configuredOrder as h, nvidiaProvider, openAiCompatibleProvider, openRouterProvider, providerStatuses as p, realProviders, sharedAiHealth, vertexProvider };
323
+ export { type AdapterContext as A, AI_COOLDOWN_MS, AI_TIMEOUT_MS, type AiAttempt, type AiAttemptStatus, type AiGenerateOptions, type AiHealth, type AiOutcome, type AiProvider, type AiResult, type AiServiceDeps, BUILTIN_ADAPTERS as B, CHECK_PROMPT as C, DEFAULT_ORDER as D, FREE_TEXT_MODELS as F, HEDGE, type JsonMode, PAID_TEXT_MODELS as P, type AdapterState as a, anthropicOutcome, anthropicProvider, type AdapterStatus as b, type ProviderAdapter as c, cooldownFor, createAiHealth, createAiService, type ProviderCheck as d, chainPlan as e, checkChain as f, checkProvider as g, geminiOutcome, geminiProvider, configuredOrder as h, nvidiaProvider, openAiCompatibleProvider, openRouterProvider, providerStatuses as p, realProviders, sharedAiHealth, vertexProvider };