octaflow 0.33.0 → 0.34.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/README.md +60 -6
- package/dist/ai/index.d.ts +2 -1
- package/dist/ai/index.js +268 -2
- package/dist/ai/providers/index.d.ts +118 -2
- package/dist/ai/providers/index.js +754 -2
- package/dist/ai/runner/index.d.ts +114 -0
- package/dist/ai/runner/index.js +646 -0
- package/dist/drizzle/index.d.ts +85 -0
- package/dist/drizzle/index.js +87 -2
- package/dist/hub-SXfvoqH3.d.ts +98 -0
- package/dist/model-DY-oJny8.js +233 -0
- package/dist/model-providers-DQU57vAf.d.ts +212 -0
- package/dist/model-runner-wSk3p4m5.d.ts +165 -0
- package/dist/postgres/index.d.ts +54 -0
- package/dist/postgres/index.js +319 -1
- package/dist/{provider-probe-CGN2MpaZ.js → provider-errors-DZWjl8di.js} +1 -270
- package/dist/provider-probe-CwZWwFlo.js +271 -0
- package/package.json +11 -1
package/README.md
CHANGED
|
@@ -216,7 +216,9 @@ next to what your steps actually do.
|
|
|
216
216
|
| 🚑 | **Crash recovery** — a step whose worker died is re-queued while its attempt budget lasts |
|
|
217
217
|
| 💓 | **Heartbeats** — a long step proves it is alive, so a dead one is caught in seconds, not minutes |
|
|
218
218
|
| 🔭 | **Observability** — lifecycle events (run history), per-step spans, and `createMeterObserver` turning the events into OpenTelemetry-style metrics — all pluggable, all structural |
|
|
219
|
-
| 🤖 | **AI add-on** — instrumented models, token/cost capture, quota, daily rollups, a `usage` sink that books each step into `@octabits-io/metering` (the paid APIs around the model in the same table, priced at read time), refusal-aware models, lenient JSON from local models (`withJsonRepair`), a vendor's refusal explained by key and hint (`explainProviderError`), a per-run circuit breaker, a connection test (`testProvider`) |
|
|
219
|
+
| 🤖 | **AI add-on** — instrumented models, token/cost capture, quota, daily rollups, a `usage` sink that books each step into `@octabits-io/metering` (the paid APIs around the model in the same table, priced at read time), refusal-aware models, lenient JSON from local models (`withJsonRepair`), a vendor's refusal explained by key and hint (`explainProviderError`), a per-run circuit breaker, a connection test (`testProvider`), Ollama's native API as language and embedding models (`createOllama` in `octaflow/ai/providers`: `num_ctx`, thinking and `keep_alive` per model or per call, no dependency) |
|
|
220
|
+
| 🗂️ | **Model providers an administrator manages** — `createModelProviders` (`octaflow/ai`): providers as rows, each with its kind, server, region, a key that crosses a cipher seam, and its models with declared capabilities (temperature, JSON mode, vision, video, tools, embedding); `createPgModelProviderStore` + `modelProviderDdl` (`octaflow/postgres`), `modelProviderColumns` (`octaflow/drizzle`); `createModelResolver` (`octaflow/ai/providers`) builds the AI SDK model from a row, shapes each call to what the model declares, hands the host its `destination` for the disclosure guard, and rebuilds after a write |
|
|
221
|
+
| 🏃 | **Model runners** — a model the app cannot reach, served by a process that connects *out*: a provider row of kind `runner` carries tags instead of a URL, a runner registered with a token (`octaflow/ai/runner`: `createModelRunnerHub`, shown once, kept as a hash) subscribes with its tags, claims the calls by long-poll through `@octabits-io/server/fetch/octaflow`'s `createModelRunnerHandler` and posts the answers back; the mailbox is two tables (`createPgModelRunnerStore` + `modelRunnerDdl`, `modelRunnerColumns` + `modelRunnerRequestColumns`) whose rows live only while a call is in flight; nobody online fails the call at once, so the breaker trips and the probe answers in milliseconds |
|
|
220
222
|
| 🧱 | **Pluggable everything** — `WorkflowStore`, `Dispatcher`, `StepGate`, `FlowObserver`, hooks |
|
|
221
223
|
|
|
222
224
|
---
|
|
@@ -249,9 +251,10 @@ pnpm add ai @ai-sdk/provider
|
|
|
249
251
|
|
|
250
252
|
### The Postgres tables
|
|
251
253
|
|
|
252
|
-
`octaflow/postgres` owns
|
|
253
|
-
`flow_workflow_step`), `flowEventDdl()` (`flow_step_event`)
|
|
254
|
-
(`flow_rate_bucket`, `flow_step_lease`)
|
|
254
|
+
`octaflow/postgres` owns eight tables and ships their DDL: `flowStoreDdl()` (`flow_workflow`,
|
|
255
|
+
`flow_workflow_step`), `flowEventDdl()` (`flow_step_event`), `flowGateDdl()`
|
|
256
|
+
(`flow_rate_bucket`, `flow_step_lease`), `modelProviderDdl()` (`model_provider`) and
|
|
257
|
+
`modelRunnerDdl()` (`model_runner`, `model_runner_request`). Each is idempotent `CREATE TABLE IF NOT EXISTS`, takes
|
|
255
258
|
a `schema`, and is meant to be pasted into your own migration system; `applySchema(pool, ddl)`
|
|
256
259
|
is the dev and test shortcut.
|
|
257
260
|
|
|
@@ -269,8 +272,9 @@ column set, so a host on Drizzle declares it in its own schema and drizzle-kit o
|
|
|
269
272
|
migration. Where the store's queries are one SQL statement by nature — every one of octaflow's
|
|
270
273
|
is — `./drizzle` ships the columns only, and the store stays the SQL one. So
|
|
271
274
|
`octaflow/drizzle` exports `flowWorkflowColumns`, `flowWorkflowStepColumns`,
|
|
272
|
-
`flowStepEventColumns`, `flowRateBucketColumns
|
|
273
|
-
|
|
275
|
+
`flowStepEventColumns`, `flowRateBucketColumns`, `flowStepLeaseColumns`, `modelProviderColumns`,
|
|
276
|
+
`modelRunnerColumns` and `modelRunnerRequestColumns` (`drizzle-orm` an optional peer) and
|
|
277
|
+
nothing that runs a query. The foreign keys, the composite keys, the unique
|
|
274
278
|
constraint and the indexes are yours to declare on the `pgTable`; each column set's doc lists
|
|
275
279
|
the ones its DDL creates, and two of them the store relies on:
|
|
276
280
|
|
|
@@ -314,6 +318,56 @@ The store stays plain SQL, bound to the `schema` you hand `createPgWorkflowStore
|
|
|
314
318
|
declare the tables under the same schema and names. A test in the package holds every column
|
|
315
319
|
set and its DDL equal, column for column: a column added to one side alone fails the build.
|
|
316
320
|
|
|
321
|
+
### Model runners — a model that connects out
|
|
322
|
+
|
|
323
|
+
A model the app cannot reach: a laptop with the model loaded for a demo, a GPU box behind
|
|
324
|
+
someone's firewall, a machine that is only on when it is needed. The runner never opens a
|
|
325
|
+
port. It connects *out* to the app with a token, subscribes with its tags, claims the model
|
|
326
|
+
calls that carry those tags and posts the answers back — the shape of a self-hosted CI
|
|
327
|
+
runner. The mailbox is Postgres, because the call runs in the worker and the door the runner
|
|
328
|
+
knocks on runs in the API; a request row lives only while the call is in flight.
|
|
329
|
+
|
|
330
|
+
```ts
|
|
331
|
+
// the app — once, beside the providers
|
|
332
|
+
import { createModelRunnerHub } from 'octaflow/ai/runner';
|
|
333
|
+
import { createPgModelRunnerStore } from 'octaflow/postgres';
|
|
334
|
+
|
|
335
|
+
const runners = createModelRunnerHub({ store: createPgModelRunnerStore({ executor }) });
|
|
336
|
+
const resolver = createModelResolver({ providers, runners, wrap });
|
|
337
|
+
|
|
338
|
+
// an administrator: the provider row carries tags, the runner gets its token once
|
|
339
|
+
await providers.save({ id: 'mac', kind: 'runner', label: 'The Mac', region: 'self-hosted', tags: ['qwen'], models: [{ id: 'qwen3:32b', settings: { numCtx: 16_384 } }] });
|
|
340
|
+
const { token } = (await runners.registerRunner({ id: 'dani-mac', label: "Dani's Mac", tags: ['qwen', 'mac'] })).value;
|
|
341
|
+
|
|
342
|
+
// the API: the door, behind the host's rate limit
|
|
343
|
+
import { createModelRunnerHandler } from '@octabits-io/server/fetch/octaflow';
|
|
344
|
+
export const POST = compose(withErrorMapping())(createModelRunnerHandler({ prefix: '/api/model-runner', hub: runners }));
|
|
345
|
+
|
|
346
|
+
// the runner, on the machine with the model
|
|
347
|
+
import { createHttpRunnerClient, runModelRunner } from 'octaflow/ai/runner';
|
|
348
|
+
import { createOllama } from 'octaflow/ai/providers';
|
|
349
|
+
await runModelRunner({
|
|
350
|
+
client: createHttpRunnerClient({ url: 'https://app.example/api/model-runner', token }),
|
|
351
|
+
backend: createOllama({ baseUrl: 'http://localhost:11434' }),
|
|
352
|
+
});
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
A runner may claim a request when it has **every tag** of the request — the provider row's
|
|
356
|
+
tags — as a CI job's labels must all be on the runner. A call with nobody online for its
|
|
357
|
+
tags fails at once with `provider_unreachable`, so `withCircuitBreaker` trips and
|
|
358
|
+
`testProvider` reports it in milliseconds instead of a timeout; whether another provider is
|
|
359
|
+
tried is the host's resolver's choice, through the same disclosure gate. A claim lasts 30 s
|
|
360
|
+
without a heartbeat; an expired claim is requeued once and failed the second time. The
|
|
361
|
+
region is the administrator's declaration about where runners with these tags are, as for
|
|
362
|
+
every provider, and the disclosure gate reads it the same way.
|
|
363
|
+
|
|
364
|
+
The wire is the AI SDK's own call and answer as JSON — binary file data as base64, a URL
|
|
365
|
+
restored on the other side — so the runner's backend is any `LanguageModelV4`: `createOllama`
|
|
366
|
+
from this package, or `@ai-sdk/openai-compatible` for mlx_lm.server, vLLM and llama.cpp. The
|
|
367
|
+
first version answers whole: `streamText` over a runner model works, emitted as one text
|
|
368
|
+
block when the answer is there. Files reach the runner as bytes, since the runner model
|
|
369
|
+
declares no URL support and the SDK downloads on the app's side. Embeddings go the same way.
|
|
370
|
+
|
|
317
371
|
---
|
|
318
372
|
|
|
319
373
|
---
|
package/dist/ai/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { n as Logger } from "../logger-BCus3AOa.js";
|
|
|
3
3
|
import { i as BuildStepContextArgs, o as WorkflowHooks } from "../hooks-DHomzpiq.js";
|
|
4
4
|
import { C as isSubprocessorResidency, S as embeddingDimensionsFor, _ as EmbeddingProviderMeta, a as AiProcessingRegion, b as OpenAiCompatibleProviderId, c as AiProviderModelOption, d as AiVendorResidency, f as DEFAULT_AI_PROVIDER, g as EmbeddingProviderId, h as EMBEDDING_PROVIDER_IDS, i as AiEndpointResidency, l as AiResidencyError, m as EMBEDDING_PROVIDERS, n as AI_PROVIDER_IDS, o as AiProviderId, p as DEFAULT_EMBEDDING_PROVIDER, r as AiEndpointRegion, s as AiProviderMeta, t as AI_PROVIDERS, u as AiResidencyResult, v as OPENAI_COMPATIBLE_PROVIDER, w as resolveEndpointResidency, x as OpenAiCompatibleProviderMeta, y as OPENAI_COMPATIBLE_PROVIDER_ID } from "../provider-registry-C_mOfdHH.js";
|
|
5
5
|
import { A as maskKeys, C as ProviderErrorExplanation, D as explainProviderError, E as ProviderErrorPreset, O as isFatalProviderError, S as ProviderError, T as ProviderErrorPhrase, _ as ExplainProviderErrorOptions, a as OllamaProbeReport, b as PROVIDER_ERROR_REDACTED, c as ProviderProbeOptions, d as testProvider, f as CircuitBreaker, g as DEFAULT_PROVIDER_ERROR_DETAIL_LENGTH, h as withCircuitBreaker, i as OllamaProbeOptions, k as isProviderError, l as ProviderProbeReport, m as createCircuitBreaker, n as DEFAULT_PROVIDER_PROBE_PROMPT, o as ProbeableProvider, p as CircuitBreakerOptions, r as DEFAULT_PROVIDER_PROBE_TIMEOUT_MS, s as ProviderProbeFailure, t as DEFAULT_OLLAMA_PROBE_TIMEOUT_MS, u as testOllamaModel, v as FATAL_PROVIDER_ERROR_KEYS, w as ProviderErrorKey, x as PROVIDER_ERROR_STATUS, y as PROVIDER_ERROR_PHRASES } from "../provider-probe-BDg4c1Rk.js";
|
|
6
|
+
import { C as modelProviderInputSchema, S as modelEntrySchema, _ as StoredModelProvider, a as ModelCapabilities, b as maskModelProvider, c as ModelProvider, d as ModelProviderError, f as ModelProviderInput, g as ModelProviders, h as ModelProviderStore, i as MODEL_PROVIDER_REGIONS, l as ModelProviderChange, m as ModelProviderRegion, n as MODEL_JSON_MODES, o as ModelEntry, p as ModelProviderKind, r as MODEL_PROVIDER_KINDS, s as ModelJsonMode, t as CreateModelProvidersOptions, u as ModelProviderCipher, v as createInMemoryModelProviderStore, x as modelCapabilitiesSchema, y as createModelProviders } from "../model-providers-DQU57vAf.js";
|
|
6
7
|
import { z } from "zod";
|
|
7
8
|
import { ToolSet } from "ai";
|
|
8
9
|
import { EmbeddingModelV4, LanguageModelV4, LanguageModelV4Usage, SharedV4ProviderMetadata } from "@ai-sdk/provider";
|
|
@@ -1014,4 +1015,4 @@ export interface CaseLoop<TMove extends string, TOutcome extends string, TCase e
|
|
|
1014
1015
|
*/
|
|
1015
1016
|
export declare function defineCaseLoop<const TMove extends string, const TOutcome extends string, TCase extends Record<string, unknown>, TResult extends Record<string, unknown>, TDecisions extends AgentExits, TFacts, THost = any>(config: CaseLoopConfig<TMove, TOutcome, TCase, TResult, TDecisions, TFacts, THost>): CaseLoop<TMove, TOutcome, TCase, TResult, TDecisions, TFacts, THost>;
|
|
1016
1017
|
//#endregion
|
|
1017
|
-
export { AI_PROVIDERS, AI_PROVIDER_IDS, AiEndpointRegion, AiEndpointResidency, AiProcessingRegion, AiProviderId, AiProviderMeta, AiProviderModelOption, AiResidencyError, AiResidencyResult, AiVendorResidency, CircuitBreaker, CircuitBreakerOptions, DEFAULT_AI_PROVIDER, DEFAULT_EMBEDDING_PROVIDER, DEFAULT_OLLAMA_PROBE_TIMEOUT_MS, DEFAULT_PROVIDER_ERROR_DETAIL_LENGTH, DEFAULT_PROVIDER_PROBE_PROMPT, DEFAULT_PROVIDER_PROBE_TIMEOUT_MS, EMBEDDING_PROVIDERS, EMBEDDING_PROVIDER_IDS, EmbeddingProviderId, EmbeddingProviderMeta, ExplainProviderErrorOptions, FATAL_PROVIDER_ERROR_KEYS, OPENAI_COMPATIBLE_PROVIDER, OPENAI_COMPATIBLE_PROVIDER_ID, OllamaProbeOptions, OllamaProbeReport, OpenAiCompatibleProviderId, OpenAiCompatibleProviderMeta, PROVIDER_ERROR_PHRASES, PROVIDER_ERROR_REDACTED, PROVIDER_ERROR_STATUS, ProbeableProvider, ProviderError, ProviderErrorExplanation, ProviderErrorKey, ProviderErrorPhrase, ProviderErrorPreset, ProviderProbeFailure, ProviderProbeOptions, ProviderProbeReport, createCircuitBreaker, embeddingDimensionsFor, explainProviderError, isFatalProviderError, isProviderError, isSubprocessorResidency, maskKeys, resolveEndpointResidency, testOllamaModel, testProvider, withCircuitBreaker };
|
|
1018
|
+
export { AI_PROVIDERS, AI_PROVIDER_IDS, AiEndpointRegion, AiEndpointResidency, AiProcessingRegion, AiProviderId, AiProviderMeta, AiProviderModelOption, AiResidencyError, AiResidencyResult, AiVendorResidency, CircuitBreaker, CircuitBreakerOptions, CreateModelProvidersOptions, DEFAULT_AI_PROVIDER, DEFAULT_EMBEDDING_PROVIDER, DEFAULT_OLLAMA_PROBE_TIMEOUT_MS, DEFAULT_PROVIDER_ERROR_DETAIL_LENGTH, DEFAULT_PROVIDER_PROBE_PROMPT, DEFAULT_PROVIDER_PROBE_TIMEOUT_MS, EMBEDDING_PROVIDERS, EMBEDDING_PROVIDER_IDS, EmbeddingProviderId, EmbeddingProviderMeta, ExplainProviderErrorOptions, FATAL_PROVIDER_ERROR_KEYS, MODEL_JSON_MODES, MODEL_PROVIDER_KINDS, MODEL_PROVIDER_REGIONS, ModelCapabilities, ModelEntry, ModelJsonMode, ModelProvider, ModelProviderChange, ModelProviderCipher, ModelProviderError, ModelProviderInput, ModelProviderKind, ModelProviderRegion, ModelProviderStore, ModelProviders, OPENAI_COMPATIBLE_PROVIDER, OPENAI_COMPATIBLE_PROVIDER_ID, OllamaProbeOptions, OllamaProbeReport, OpenAiCompatibleProviderId, OpenAiCompatibleProviderMeta, PROVIDER_ERROR_PHRASES, PROVIDER_ERROR_REDACTED, PROVIDER_ERROR_STATUS, ProbeableProvider, ProviderError, ProviderErrorExplanation, ProviderErrorKey, ProviderErrorPhrase, ProviderErrorPreset, ProviderProbeFailure, ProviderProbeOptions, ProviderProbeReport, StoredModelProvider, createCircuitBreaker, createInMemoryModelProviderStore, createModelProviders, embeddingDimensionsFor, explainProviderError, isFatalProviderError, isProviderError, isSubprocessorResidency, maskKeys, maskModelProvider, modelCapabilitiesSchema, modelEntrySchema, modelProviderInputSchema, resolveEndpointResidency, testOllamaModel, testProvider, withCircuitBreaker };
|
package/dist/ai/index.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { n as err, r as ok, t as noopLogger } from "../logger-epkdcXDA.js";
|
|
2
2
|
import { C as nonRetryableError, _ as defineStep, m as buildWorkflow } from "../core-COMWflJl.js";
|
|
3
|
-
import {
|
|
3
|
+
import { a as testProvider, c as AiRefusalError, d as isAiRefusalError, f as readRefusalDetails, i as testOllamaModel, l as REFUSAL_FINISH_REASON, n as DEFAULT_PROVIDER_PROBE_PROMPT, o as createCircuitBreaker, r as DEFAULT_PROVIDER_PROBE_TIMEOUT_MS, s as withCircuitBreaker, t as DEFAULT_OLLAMA_PROBE_TIMEOUT_MS, u as createRefusalAwareModel } from "../provider-probe-CwZWwFlo.js";
|
|
4
4
|
import { a as EMBEDDING_PROVIDERS, c as OPENAI_COMPATIBLE_PROVIDER_ID, d as resolveEndpointResidency, i as DEFAULT_EMBEDDING_PROVIDER, l as embeddingDimensionsFor, n as AI_PROVIDER_IDS, o as EMBEDDING_PROVIDER_IDS, r as DEFAULT_AI_PROVIDER, s as OPENAI_COMPATIBLE_PROVIDER, t as AI_PROVIDERS, u as isSubprocessorResidency } from "../provider-registry-B91lgOmu.js";
|
|
5
|
+
import { a as PROVIDER_ERROR_STATUS, c as isFatalProviderError, i as PROVIDER_ERROR_REDACTED, l as isProviderError, n as FATAL_PROVIDER_ERROR_KEYS, o as ProviderError, r as PROVIDER_ERROR_PHRASES, s as explainProviderError, t as DEFAULT_PROVIDER_ERROR_DETAIL_LENGTH, u as maskKeys } from "../provider-errors-DZWjl8di.js";
|
|
5
6
|
import { z } from "zod";
|
|
6
7
|
import { Output, generateText, stepCountIs, tool, wrapEmbeddingModel, wrapLanguageModel } from "ai";
|
|
7
8
|
//#region src/ai/instrumented-model.ts
|
|
@@ -1559,4 +1560,269 @@ function defineCaseLoop(config) {
|
|
|
1559
1560
|
};
|
|
1560
1561
|
}
|
|
1561
1562
|
//#endregion
|
|
1562
|
-
|
|
1563
|
+
//#region src/ai/model-providers.ts
|
|
1564
|
+
/** A runner tag — the same rule `model-runner.ts` holds a runner's own tags to. */
|
|
1565
|
+
const MODEL_RUNNER_TAG = /^[a-z0-9][a-z0-9._-]{0,62}$/;
|
|
1566
|
+
/**
|
|
1567
|
+
* The API a provider speaks. `openai-compatible` is any server with OpenAI's
|
|
1568
|
+
* chat API (vLLM, LiteLLM, OpenRouter, a gateway). `runner` is no API at all:
|
|
1569
|
+
* the models are served by a runner that connects out to the app and claims
|
|
1570
|
+
* the calls that carry the row's `tags` (`octaflow/ai/runner`).
|
|
1571
|
+
*/
|
|
1572
|
+
const MODEL_PROVIDER_KINDS = [
|
|
1573
|
+
"anthropic",
|
|
1574
|
+
"openai",
|
|
1575
|
+
"mistral",
|
|
1576
|
+
"google",
|
|
1577
|
+
"ollama",
|
|
1578
|
+
"openai-compatible",
|
|
1579
|
+
"runner"
|
|
1580
|
+
];
|
|
1581
|
+
/** Where the data goes: the disclosure destination's region. */
|
|
1582
|
+
const MODEL_PROVIDER_REGIONS = [
|
|
1583
|
+
"self-hosted",
|
|
1584
|
+
"eu",
|
|
1585
|
+
"third-country"
|
|
1586
|
+
];
|
|
1587
|
+
/**
|
|
1588
|
+
* How a model is asked for JSON: `schema` — native structured output against
|
|
1589
|
+
* a JSON schema; `object` — a JSON mode that guarantees an object but no
|
|
1590
|
+
* shape; `prompt` — no JSON mode, the instruction is in the prompt and the
|
|
1591
|
+
* answer is parsed.
|
|
1592
|
+
*/
|
|
1593
|
+
const MODEL_JSON_MODES = [
|
|
1594
|
+
"schema",
|
|
1595
|
+
"object",
|
|
1596
|
+
"prompt"
|
|
1597
|
+
];
|
|
1598
|
+
const modelCapabilitiesSchema = z.object({
|
|
1599
|
+
/** Takes a sampling temperature. Reasoning models often refuse one. */
|
|
1600
|
+
temperature: z.boolean().default(true),
|
|
1601
|
+
json: z.enum(MODEL_JSON_MODES).default("object"),
|
|
1602
|
+
/** Takes images. */
|
|
1603
|
+
vision: z.boolean().default(false),
|
|
1604
|
+
/** Takes a whole video (a file or, for Gemini, a YouTube URL). */
|
|
1605
|
+
video: z.boolean().default(false),
|
|
1606
|
+
/** Calls tools — what an agent needs. */
|
|
1607
|
+
tools: z.boolean().default(true),
|
|
1608
|
+
/** Embeds text instead of answering. */
|
|
1609
|
+
embedding: z.boolean().default(false)
|
|
1610
|
+
});
|
|
1611
|
+
const modelEntrySchema = z.object({
|
|
1612
|
+
/** The vendor's model id, e.g. `claude-sonnet-5-5`, `gemini-3.5-flash`, `qwen3:32b`. */
|
|
1613
|
+
id: z.string().min(1),
|
|
1614
|
+
label: z.string().optional(),
|
|
1615
|
+
capabilities: modelCapabilitiesSchema.default(modelCapabilitiesSchema.parse({})),
|
|
1616
|
+
/** The most output tokens a call asks for, when the caller names none. */
|
|
1617
|
+
maxOutputTokens: z.number().int().positive().optional(),
|
|
1618
|
+
/**
|
|
1619
|
+
* Settings the kind understands, passed as given — for `ollama`:
|
|
1620
|
+
* `{ numCtx, think, keepAlive, options }` (see `createOllama`).
|
|
1621
|
+
*/
|
|
1622
|
+
settings: z.record(z.string(), z.unknown()).optional()
|
|
1623
|
+
});
|
|
1624
|
+
/** What an administrator saves. `apiKey` absent keeps the stored key, `null` removes it. */
|
|
1625
|
+
const modelProviderInputSchema = z.object({
|
|
1626
|
+
id: z.string().regex(/^[a-z0-9][a-z0-9_-]{0,62}$/, "lowercase letters, digits, - and _; at most 63"),
|
|
1627
|
+
kind: z.enum(MODEL_PROVIDER_KINDS),
|
|
1628
|
+
label: z.string().min(1),
|
|
1629
|
+
/** The server; for a vendor, a region-pinned endpoint or nothing for the SDK's default. */
|
|
1630
|
+
baseUrl: z.string().url().nullish(),
|
|
1631
|
+
region: z.enum(MODEL_PROVIDER_REGIONS),
|
|
1632
|
+
apiKey: z.string().min(1).nullish(),
|
|
1633
|
+
/** Sent with every request — attribution, a gateway's routing. Stored in plain text: never a secret. */
|
|
1634
|
+
headers: z.record(z.string(), z.string()).default({}),
|
|
1635
|
+
/** For `runner`: the tags a runner must have to serve this provider's calls. Empty for every other kind. */
|
|
1636
|
+
tags: z.array(z.string().regex(MODEL_RUNNER_TAG, "lowercase letters, digits, . _ -; at most 63")).max(32).default([]),
|
|
1637
|
+
models: z.array(modelEntrySchema).default([]),
|
|
1638
|
+
defaultModel: z.string().min(1).nullish(),
|
|
1639
|
+
enabled: z.boolean().default(true)
|
|
1640
|
+
}).superRefine((p, issue) => {
|
|
1641
|
+
const ids = p.models.map((m) => m.id);
|
|
1642
|
+
const repeated = ids.find((id, i) => ids.indexOf(id) !== i);
|
|
1643
|
+
if (repeated) issue.addIssue({
|
|
1644
|
+
code: "custom",
|
|
1645
|
+
path: ["models"],
|
|
1646
|
+
message: `model '${repeated}' is listed twice`
|
|
1647
|
+
});
|
|
1648
|
+
if (p.defaultModel && !ids.includes(p.defaultModel)) issue.addIssue({
|
|
1649
|
+
code: "custom",
|
|
1650
|
+
path: ["defaultModel"],
|
|
1651
|
+
message: `'${p.defaultModel}' is not one of the models`
|
|
1652
|
+
});
|
|
1653
|
+
if ((p.kind === "ollama" || p.kind === "openai-compatible") && !p.baseUrl) issue.addIssue({
|
|
1654
|
+
code: "custom",
|
|
1655
|
+
path: ["baseUrl"],
|
|
1656
|
+
message: `a ${p.kind} provider needs its server's URL`
|
|
1657
|
+
});
|
|
1658
|
+
if (p.kind === "runner" && p.tags.length === 0) issue.addIssue({
|
|
1659
|
+
code: "custom",
|
|
1660
|
+
path: ["tags"],
|
|
1661
|
+
message: "a runner provider needs at least one tag"
|
|
1662
|
+
});
|
|
1663
|
+
if (p.kind !== "runner" && p.tags.length > 0) issue.addIssue({
|
|
1664
|
+
code: "custom",
|
|
1665
|
+
path: ["tags"],
|
|
1666
|
+
message: `tags are for a runner provider, not a ${p.kind} one`
|
|
1667
|
+
});
|
|
1668
|
+
});
|
|
1669
|
+
const hintOf = (key) => key.length > 8 ? key.slice(-4) : null;
|
|
1670
|
+
function maskModelProvider(row) {
|
|
1671
|
+
const { apiKey, ...rest } = row;
|
|
1672
|
+
return {
|
|
1673
|
+
...rest,
|
|
1674
|
+
hasKey: apiKey !== null
|
|
1675
|
+
};
|
|
1676
|
+
}
|
|
1677
|
+
/**
|
|
1678
|
+
* The providers an administrator manages: validated writes, the key through
|
|
1679
|
+
* the cipher, a masked read for the page and a before/after pair for the audit
|
|
1680
|
+
* log.
|
|
1681
|
+
*
|
|
1682
|
+
* ```ts
|
|
1683
|
+
* const providers = createModelProviders({ store: createPgModelProviderStore({ executor }), cipher });
|
|
1684
|
+
* const saved = await providers.save({ id: 'mistral', kind: 'mistral', label: 'Mistral', region: 'eu', apiKey, models: [{ id: 'mistral-large-latest' }] }, { actor: staffId });
|
|
1685
|
+
* ```
|
|
1686
|
+
*/
|
|
1687
|
+
function createModelProviders(options) {
|
|
1688
|
+
const { store, cipher } = options;
|
|
1689
|
+
const now = options.now ?? (() => /* @__PURE__ */ new Date());
|
|
1690
|
+
let version = 0;
|
|
1691
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
1692
|
+
const changed = (id) => {
|
|
1693
|
+
version++;
|
|
1694
|
+
for (const l of listeners) try {
|
|
1695
|
+
l(id);
|
|
1696
|
+
} catch {}
|
|
1697
|
+
};
|
|
1698
|
+
return {
|
|
1699
|
+
async list(opts) {
|
|
1700
|
+
return (await store.list()).filter((r) => !opts?.enabledOnly || r.enabled).map(maskModelProvider);
|
|
1701
|
+
},
|
|
1702
|
+
async get(id) {
|
|
1703
|
+
const row = await store.get(id);
|
|
1704
|
+
return row && maskModelProvider(row);
|
|
1705
|
+
},
|
|
1706
|
+
async save(input, by) {
|
|
1707
|
+
const parsed = modelProviderInputSchema.safeParse(input);
|
|
1708
|
+
if (!parsed.success) {
|
|
1709
|
+
const issues = parsed.error.issues.map((i) => ({
|
|
1710
|
+
path: i.path.join("."),
|
|
1711
|
+
message: i.message
|
|
1712
|
+
}));
|
|
1713
|
+
return {
|
|
1714
|
+
ok: false,
|
|
1715
|
+
error: {
|
|
1716
|
+
key: "invalid",
|
|
1717
|
+
message: issues.map((i) => `${i.path || "(provider)"}: ${i.message}`).join("; "),
|
|
1718
|
+
issues
|
|
1719
|
+
}
|
|
1720
|
+
};
|
|
1721
|
+
}
|
|
1722
|
+
const p = parsed.data;
|
|
1723
|
+
const before = await store.get(p.id);
|
|
1724
|
+
let apiKey = before?.apiKey ?? null;
|
|
1725
|
+
let keyHint = before?.keyHint ?? null;
|
|
1726
|
+
if (p.apiKey === null) apiKey = keyHint = null;
|
|
1727
|
+
else if (p.apiKey !== void 0) {
|
|
1728
|
+
if (!cipher) return {
|
|
1729
|
+
ok: false,
|
|
1730
|
+
error: {
|
|
1731
|
+
key: "no_cipher",
|
|
1732
|
+
message: "a key can only be saved with a cipher"
|
|
1733
|
+
}
|
|
1734
|
+
};
|
|
1735
|
+
apiKey = await cipher.encrypt(p.apiKey);
|
|
1736
|
+
keyHint = hintOf(p.apiKey);
|
|
1737
|
+
}
|
|
1738
|
+
const row = {
|
|
1739
|
+
id: p.id,
|
|
1740
|
+
kind: p.kind,
|
|
1741
|
+
label: p.label,
|
|
1742
|
+
baseUrl: p.baseUrl ?? null,
|
|
1743
|
+
region: p.region,
|
|
1744
|
+
apiKey,
|
|
1745
|
+
keyHint,
|
|
1746
|
+
headers: p.headers,
|
|
1747
|
+
tags: p.tags,
|
|
1748
|
+
models: p.models,
|
|
1749
|
+
defaultModel: p.defaultModel ?? p.models[0]?.id ?? null,
|
|
1750
|
+
enabled: p.enabled,
|
|
1751
|
+
updatedAt: now(),
|
|
1752
|
+
updatedBy: by?.actor ?? null
|
|
1753
|
+
};
|
|
1754
|
+
await store.put(row);
|
|
1755
|
+
changed(p.id);
|
|
1756
|
+
return {
|
|
1757
|
+
ok: true,
|
|
1758
|
+
value: {
|
|
1759
|
+
id: p.id,
|
|
1760
|
+
before: before && maskModelProvider(before),
|
|
1761
|
+
after: maskModelProvider(row),
|
|
1762
|
+
actor: by?.actor ?? null,
|
|
1763
|
+
reason: by?.reason ?? null
|
|
1764
|
+
}
|
|
1765
|
+
};
|
|
1766
|
+
},
|
|
1767
|
+
async remove(id, by) {
|
|
1768
|
+
const before = await store.get(id);
|
|
1769
|
+
if (!before || !await store.remove(id)) return {
|
|
1770
|
+
ok: false,
|
|
1771
|
+
error: {
|
|
1772
|
+
key: "not_found",
|
|
1773
|
+
message: `no provider '${id}'`
|
|
1774
|
+
}
|
|
1775
|
+
};
|
|
1776
|
+
changed(id);
|
|
1777
|
+
return {
|
|
1778
|
+
ok: true,
|
|
1779
|
+
value: {
|
|
1780
|
+
id,
|
|
1781
|
+
before: maskModelProvider(before),
|
|
1782
|
+
after: null,
|
|
1783
|
+
actor: by?.actor ?? null,
|
|
1784
|
+
reason: by?.reason ?? null
|
|
1785
|
+
}
|
|
1786
|
+
};
|
|
1787
|
+
},
|
|
1788
|
+
async reveal(id) {
|
|
1789
|
+
const row = await store.get(id);
|
|
1790
|
+
if (!row) return null;
|
|
1791
|
+
if (row.apiKey !== null && !cipher) throw new Error(`provider '${id}' has a key, and no cipher was given to read it`);
|
|
1792
|
+
const apiKey = row.apiKey === null ? null : await cipher.decrypt(row.apiKey);
|
|
1793
|
+
return {
|
|
1794
|
+
...maskModelProvider(row),
|
|
1795
|
+
apiKey
|
|
1796
|
+
};
|
|
1797
|
+
},
|
|
1798
|
+
version: () => version,
|
|
1799
|
+
onChange(listener) {
|
|
1800
|
+
listeners.add(listener);
|
|
1801
|
+
return () => listeners.delete(listener);
|
|
1802
|
+
},
|
|
1803
|
+
touch() {
|
|
1804
|
+
changed("*");
|
|
1805
|
+
}
|
|
1806
|
+
};
|
|
1807
|
+
}
|
|
1808
|
+
/** The reference store, in memory — for tests and a host with nothing to persist. */
|
|
1809
|
+
function createInMemoryModelProviderStore(rows = []) {
|
|
1810
|
+
const byId = new Map(rows.map((r) => [r.id, structuredClone(r)]));
|
|
1811
|
+
return {
|
|
1812
|
+
async list() {
|
|
1813
|
+
return [...byId.values()].sort((a, b) => a.id < b.id ? -1 : a.id > b.id ? 1 : 0).map((r) => structuredClone(r));
|
|
1814
|
+
},
|
|
1815
|
+
async get(id) {
|
|
1816
|
+
const r = byId.get(id);
|
|
1817
|
+
return r ? structuredClone(r) : null;
|
|
1818
|
+
},
|
|
1819
|
+
async put(row) {
|
|
1820
|
+
byId.set(row.id, structuredClone(row));
|
|
1821
|
+
},
|
|
1822
|
+
async remove(id) {
|
|
1823
|
+
return byId.delete(id);
|
|
1824
|
+
}
|
|
1825
|
+
};
|
|
1826
|
+
}
|
|
1827
|
+
//#endregion
|
|
1828
|
+
export { AGENT_TRACE_SCHEMA, AI_PROVIDERS, AI_PROVIDER_IDS, AiRefusalError, DEFAULT_AI_PROVIDER, DEFAULT_AI_QUOTA, DEFAULT_EMBEDDING_PROVIDER, DEFAULT_MODEL_JSON_EXCERPT_LENGTH, DEFAULT_MODEL_PRICING, DEFAULT_OLLAMA_PROBE_TIMEOUT_MS, DEFAULT_PROVIDER_ERROR_DETAIL_LENGTH, DEFAULT_PROVIDER_PROBE_PROMPT, DEFAULT_PROVIDER_PROBE_TIMEOUT_MS, EMBEDDING_PROVIDERS, EMBEDDING_PROVIDER_IDS, FATAL_PROVIDER_ERROR_KEYS, MODEL_JSON_MODES, MODEL_JSON_PROVIDER_METADATA_KEY, MODEL_JSON_REPAIRED_ATTRIBUTE, MODEL_PROVIDER_KINDS, MODEL_PROVIDER_REGIONS, ModelJsonError, OPENAI_COMPATIBLE_PROVIDER, OPENAI_COMPATIBLE_PROVIDER_ID, PROVIDER_ERROR_PHRASES, PROVIDER_ERROR_REDACTED, PROVIDER_ERROR_STATUS, ProviderError, REFUSAL_FINISH_REASON, ZERO_MODEL_PRICING, addUsage, anthropicThinkingSettings, buildAiWorkflow, createAiQuotaService, createAiUsageAggregationService, createAiWorkflowHooks, createCircuitBreaker, createCostEstimator, createEmbeddingUsageAccumulator, createInMemoryModelProviderStore, createInstrumentedEmbeddingModel, createInstrumentedModel, createModelDecider, createModelProviders, createRefusalAwareModel, createUsageAccumulator, defineAgentStep, defineAiStep, defineCaseLoop, embeddingDimensionsFor, estimateCostMicros, excerptOf, explainProviderError, isAiRefusalError, isFatalProviderError, isModelJsonError, isProviderError, isSubprocessorResidency, maskKeys, maskModelProvider, mergeModelJsonObjects, modelCapabilitiesSchema, modelEntrySchema, modelJsonRepairText, modelProviderInputSchema, parseModelJson, readRefusalDetails, recoverModelJson, resolveEndpointResidency, runAgent, runAgentToExit, supportsAdaptiveThinking, supportsToolSearch, testOllamaModel, testProvider, thinkingSettingsFor, withCircuitBreaker, withJsonRepair };
|
|
@@ -1,6 +1,122 @@
|
|
|
1
1
|
import { b as OpenAiCompatibleProviderId, g as EmbeddingProviderId, i as AiEndpointResidency, o as AiProviderId } from "../../provider-registry-C_mOfdHH.js";
|
|
2
2
|
import { A as maskKeys, C as ProviderErrorExplanation, D as explainProviderError, E as ProviderErrorPreset, O as isFatalProviderError, S as ProviderError, T as ProviderErrorPhrase, _ as ExplainProviderErrorOptions, a as OllamaProbeReport, c as ProviderProbeOptions, d as testProvider, f as CircuitBreaker, h as withCircuitBreaker, i as OllamaProbeOptions, k as isProviderError, l as ProviderProbeReport, m as createCircuitBreaker, o as ProbeableProvider, p as CircuitBreakerOptions, s as ProviderProbeFailure, u as testOllamaModel, v as FATAL_PROVIDER_ERROR_KEYS, w as ProviderErrorKey, x as PROVIDER_ERROR_STATUS, y as PROVIDER_ERROR_PHRASES } from "../../provider-probe-BDg4c1Rk.js";
|
|
3
|
-
import {
|
|
3
|
+
import { a as ModelCapabilities, c as ModelProvider, g as ModelProviders, m as ModelProviderRegion, o as ModelEntry } from "../../model-providers-DQU57vAf.js";
|
|
4
|
+
import { u as ModelRunnerHub } from "../../hub-SXfvoqH3.js";
|
|
5
|
+
import { EmbeddingModelV4, LanguageModelV4, LanguageModelV4CallOptions } from "@ai-sdk/provider";
|
|
6
|
+
//#region src/ai/providers/ollama.d.ts
|
|
7
|
+
/** `false` switches thinking off; a level asks a model that has levels for that much. */
|
|
8
|
+
type OllamaThink = boolean | 'low' | 'medium' | 'high';
|
|
9
|
+
interface OllamaModelSettings {
|
|
10
|
+
/** The context window in tokens (`num_ctx`). Default: the server's. */
|
|
11
|
+
numCtx?: number;
|
|
12
|
+
/** Thinking on, off, or a level. Default: the model's. */
|
|
13
|
+
think?: OllamaThink;
|
|
14
|
+
/** How long the model stays loaded after the call: `'15m'`, seconds, or `-1` for ever. Default: the server's. */
|
|
15
|
+
keepAlive?: string | number;
|
|
16
|
+
/** Further entries of Ollama's `options` (`repeat_penalty`, `min_p`, …), sent as given. */
|
|
17
|
+
options?: Record<string, unknown>;
|
|
18
|
+
}
|
|
19
|
+
interface OllamaProviderOptions extends OllamaModelSettings {
|
|
20
|
+
/** The server, e.g. `http://localhost:11434`. A trailing `/v1` or `/api` is dropped. */
|
|
21
|
+
baseUrl: string;
|
|
22
|
+
/** Sent with every request — a proxy's key, say. */
|
|
23
|
+
headers?: Record<string, string>;
|
|
24
|
+
/** A fetch of your own: a timeout, a guarded outbound fetch, metering. Default: the global one. */
|
|
25
|
+
fetch?: typeof fetch;
|
|
26
|
+
}
|
|
27
|
+
interface OllamaProvider {
|
|
28
|
+
languageModel(modelId: string, settings?: OllamaModelSettings): LanguageModelV4;
|
|
29
|
+
embeddingModel(modelId: string, settings?: Pick<OllamaModelSettings, 'keepAlive' | 'options'> & {
|
|
30
|
+
truncate?: boolean;
|
|
31
|
+
}): EmbeddingModelV4;
|
|
32
|
+
}
|
|
33
|
+
export declare function createOllama(provider: OllamaProviderOptions): OllamaProvider;
|
|
34
|
+
//#endregion
|
|
35
|
+
//#region src/ai/providers/resolve.d.ts
|
|
36
|
+
interface ResolvedModel<M> {
|
|
37
|
+
model: M;
|
|
38
|
+
provider: ModelProvider;
|
|
39
|
+
entry: ModelEntry;
|
|
40
|
+
/** The disclosure destination this model is: the provider's id and region. */
|
|
41
|
+
destination: {
|
|
42
|
+
id: string;
|
|
43
|
+
region: ModelProviderRegion;
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
type ModelResolveError = {
|
|
47
|
+
key: 'no_provider';
|
|
48
|
+
message: string;
|
|
49
|
+
} | {
|
|
50
|
+
key: 'unknown_provider';
|
|
51
|
+
message: string;
|
|
52
|
+
} | {
|
|
53
|
+
key: 'disabled';
|
|
54
|
+
message: string;
|
|
55
|
+
} | {
|
|
56
|
+
key: 'unknown_model';
|
|
57
|
+
message: string;
|
|
58
|
+
} | {
|
|
59
|
+
key: 'not_capable';
|
|
60
|
+
message: string;
|
|
61
|
+
missing: Array<keyof ModelCapabilities>;
|
|
62
|
+
} | {
|
|
63
|
+
key: 'no_key';
|
|
64
|
+
message: string;
|
|
65
|
+
} |
|
|
66
|
+
/** A `runner` provider, and the resolver was made without `runners`. */
|
|
67
|
+
{
|
|
68
|
+
key: 'no_runner_hub';
|
|
69
|
+
message: string;
|
|
70
|
+
};
|
|
71
|
+
type Resolved<M> = {
|
|
72
|
+
ok: true;
|
|
73
|
+
value: ResolvedModel<M>;
|
|
74
|
+
} | {
|
|
75
|
+
ok: false;
|
|
76
|
+
error: ModelResolveError;
|
|
77
|
+
};
|
|
78
|
+
interface ModelRef {
|
|
79
|
+
/** The provider's id; the resolver's `defaultProvider` when absent. */
|
|
80
|
+
provider?: string;
|
|
81
|
+
/** The model's id; the provider's default model when absent. */
|
|
82
|
+
model?: string;
|
|
83
|
+
/** What the model must be able to do — a vision step asks for `{ vision: true }`. */
|
|
84
|
+
require?: Partial<Record<keyof ModelCapabilities, true>>;
|
|
85
|
+
}
|
|
86
|
+
interface ModelResolver {
|
|
87
|
+
languageModel(ref?: ModelRef): Promise<Resolved<LanguageModelV4>>;
|
|
88
|
+
embeddingModel(ref?: Omit<ModelRef, 'require'>): Promise<Resolved<EmbeddingModelV4>>;
|
|
89
|
+
/** Drop every cached model — after a write another replica made, when `providers.touch()` is not wired. */
|
|
90
|
+
invalidate(): void;
|
|
91
|
+
}
|
|
92
|
+
interface CreateModelResolverOptions {
|
|
93
|
+
providers: ModelProviders;
|
|
94
|
+
/** The provider a ref without one resolves to — a setting, an env var. */
|
|
95
|
+
defaultProvider?: () => string | undefined | Promise<string | undefined>;
|
|
96
|
+
/** The fetch every vendor SDK uses: a timeout, a guarded outbound fetch, metering. */
|
|
97
|
+
fetch?: typeof fetch;
|
|
98
|
+
/** The hub a `runner` provider's models go through (`createModelRunnerHub`, `octaflow/ai/runner`). */
|
|
99
|
+
runners?: ModelRunnerHub;
|
|
100
|
+
/** What every language model goes through on its way out — the disclosure guard, a breaker. */
|
|
101
|
+
wrap?: (model: LanguageModelV4, resolved: Omit<ResolvedModel<LanguageModelV4>, 'model'>) => LanguageModelV4;
|
|
102
|
+
/** The same for embedding models. */
|
|
103
|
+
wrapEmbedding?: (model: EmbeddingModelV4, resolved: Omit<ResolvedModel<EmbeddingModelV4>, 'model'>) => EmbeddingModelV4;
|
|
104
|
+
}
|
|
105
|
+
/** Shape a call to what the model declares — see the module comment. */
|
|
106
|
+
export declare function shapeCall(params: LanguageModelV4CallOptions, entry: ModelEntry): LanguageModelV4CallOptions;
|
|
107
|
+
/**
|
|
108
|
+
* ```ts
|
|
109
|
+
* const models = createModelResolver({
|
|
110
|
+
* providers,
|
|
111
|
+
* defaultProvider: () => settings.get('MODEL_PROVIDER'),
|
|
112
|
+
* wrap: (model, r) => guardLanguageModel(model, { destination: r.destination, classOf: () => 'public', log }),
|
|
113
|
+
* });
|
|
114
|
+
* const vision = await models.languageModel({ provider: 'gemini', require: { video: true } });
|
|
115
|
+
* if (vision.ok) await generateText({ model: vision.value.model, messages });
|
|
116
|
+
* ```
|
|
117
|
+
*/
|
|
118
|
+
export declare function createModelResolver(options: CreateModelResolverOptions): ModelResolver;
|
|
119
|
+
//#endregion
|
|
4
120
|
//#region src/ai/providers/index.d.ts
|
|
5
121
|
export type LanguageModelFactory = (modelId: string) => LanguageModelV4;
|
|
6
122
|
export type EmbeddingModelFactory = (modelId: string) => EmbeddingModelV4;
|
|
@@ -207,4 +323,4 @@ export interface OpenAiCompatibleGatewayProvider {
|
|
|
207
323
|
*/
|
|
208
324
|
export declare function createOpenAiCompatibleGatewayProvider(config: OpenAiCompatibleGatewayConfig): Promise<OpenAiCompatibleGatewayProvider>;
|
|
209
325
|
//#endregion
|
|
210
|
-
export { type CircuitBreaker, type CircuitBreakerOptions, type ExplainProviderErrorOptions, FATAL_PROVIDER_ERROR_KEYS, type OllamaProbeOptions, type OllamaProbeReport, PROVIDER_ERROR_PHRASES, PROVIDER_ERROR_STATUS, type ProbeableProvider, ProviderError, type ProviderErrorExplanation, type ProviderErrorKey, type ProviderErrorPhrase, type ProviderErrorPreset, type ProviderProbeFailure, type ProviderProbeOptions, type ProviderProbeReport, createCircuitBreaker, explainProviderError, isFatalProviderError, isProviderError, maskKeys, testOllamaModel, testProvider, withCircuitBreaker };
|
|
326
|
+
export { type CircuitBreaker, type CircuitBreakerOptions, type CreateModelResolverOptions, type ExplainProviderErrorOptions, FATAL_PROVIDER_ERROR_KEYS, type ModelRef, type ModelResolveError, type ModelResolver, type OllamaModelSettings, type OllamaProbeOptions, type OllamaProbeReport, type OllamaProvider, type OllamaProviderOptions, type OllamaThink, PROVIDER_ERROR_PHRASES, PROVIDER_ERROR_STATUS, type ProbeableProvider, ProviderError, type ProviderErrorExplanation, type ProviderErrorKey, type ProviderErrorPhrase, type ProviderErrorPreset, type ProviderProbeFailure, type ProviderProbeOptions, type ProviderProbeReport, type ResolvedModel, createCircuitBreaker, explainProviderError, isFatalProviderError, isProviderError, maskKeys, testOllamaModel, testProvider, withCircuitBreaker };
|