octaflow 0.22.0 → 0.24.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.
@@ -1,7 +1,7 @@
1
1
  import { E as RetryPolicy, g as TypedWorkflow, h as TypedStepContext, m as TypedStep, nt as Result, tt as FlowErrorShape } from "../index-BURAYZui.js";
2
2
  import { n as Logger } from "../logger-BCus3AOa.js";
3
3
  import { i as BuildStepContextArgs, o as WorkflowHooks } from "../hooks-BdxIcc92.js";
4
- import { a as AiProviderMeta, c as DEFAULT_AI_PROVIDER, d as EMBEDDING_PROVIDER_IDS, f as EmbeddingProviderId, i as AiProviderId, l as DEFAULT_EMBEDDING_PROVIDER, m as embeddingDimensionsFor, n as AI_PROVIDER_IDS, o as AiProviderModelOption, p as EmbeddingProviderMeta, r as AiProcessingRegion, s as AiVendorResidency, t as AI_PROVIDERS, u as EMBEDDING_PROVIDERS } from "../provider-registry-bXGOmyeh.js";
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-BvXBqJDR.js";
5
5
  import { z } from "zod";
6
6
  import { EmbeddingModelV4, LanguageModelV4, SharedV4ProviderMetadata } from "@ai-sdk/provider";
7
7
  //#region src/ai/instrumented-model.d.ts
@@ -82,6 +82,13 @@ export interface TokenUsage {
82
82
  * pinned ids (`mistral-medium-2508`) fall to the fallback.
83
83
  */
84
84
  export declare const DEFAULT_MODEL_PRICING: Record<string, ModelPricing>;
85
+ /**
86
+ * A zero row for a model that costs nothing per token, such as one on a server
87
+ * you run. Add it per model id: `{ ...DEFAULT_MODEL_PRICING, 'qwen3-32b': ZERO_MODEL_PRICING }`.
88
+ * An id missing from the table prices at the priciest row, which is safe for a
89
+ * vendor and makes quota refuse a free model long before it should.
90
+ */
91
+ export declare const ZERO_MODEL_PRICING: ModelPricing;
85
92
  export interface CostEstimatorOptions {
86
93
  /** Pricing table keyed by model id. Defaults to `DEFAULT_MODEL_PRICING`. */
87
94
  pricing?: Record<string, ModelPricing>;
@@ -543,4 +550,4 @@ export declare function thinkingSettingsFor(providerId: string, modelId: string,
543
550
  budgetTokens: number;
544
551
  }): ThinkingSettings;
545
552
  //#endregion
546
- export { AI_PROVIDERS, AI_PROVIDER_IDS, AiProcessingRegion, AiProviderId, AiProviderMeta, AiProviderModelOption, AiVendorResidency, DEFAULT_AI_PROVIDER, DEFAULT_EMBEDDING_PROVIDER, EMBEDDING_PROVIDERS, EMBEDDING_PROVIDER_IDS, EmbeddingProviderId, EmbeddingProviderMeta, embeddingDimensionsFor };
553
+ export { AI_PROVIDERS, AI_PROVIDER_IDS, AiEndpointRegion, AiEndpointResidency, AiProcessingRegion, AiProviderId, AiProviderMeta, AiProviderModelOption, AiResidencyError, AiResidencyResult, AiVendorResidency, DEFAULT_AI_PROVIDER, DEFAULT_EMBEDDING_PROVIDER, EMBEDDING_PROVIDERS, EMBEDDING_PROVIDER_IDS, EmbeddingProviderId, EmbeddingProviderMeta, OPENAI_COMPATIBLE_PROVIDER, OPENAI_COMPATIBLE_PROVIDER_ID, OpenAiCompatibleProviderId, OpenAiCompatibleProviderMeta, embeddingDimensionsFor, isSubprocessorResidency, resolveEndpointResidency };
package/dist/ai/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { S as ok, b as noopLogger, f as defineStep, l as buildWorkflow, x as err } from "../core-DNWPwFaE.js";
2
2
  import { a as readRefusalDetails, i as isAiRefusalError, n as REFUSAL_FINISH_REASON, r as createRefusalAwareModel, t as AiRefusalError } from "../refusal-BsL2HPDb.js";
3
- import { a as EMBEDDING_PROVIDERS, i as DEFAULT_EMBEDDING_PROVIDER, n as AI_PROVIDER_IDS, o as EMBEDDING_PROVIDER_IDS, r as DEFAULT_AI_PROVIDER, s as embeddingDimensionsFor, t as AI_PROVIDERS } from "../provider-registry-DcRDsjtT.js";
3
+ 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-BRwjC6_3.js";
4
4
  import { wrapEmbeddingModel, wrapLanguageModel } from "ai";
5
5
  //#region src/ai/instrumented-model.ts
6
6
  function createUsageAccumulator() {
@@ -266,6 +266,18 @@ const DEFAULT_MODEL_PRICING = {
266
266
  cacheWritePerMillion: 0
267
267
  }
268
268
  };
269
+ /**
270
+ * A zero row for a model that costs nothing per token, such as one on a server
271
+ * you run. Add it per model id: `{ ...DEFAULT_MODEL_PRICING, 'qwen3-32b': ZERO_MODEL_PRICING }`.
272
+ * An id missing from the table prices at the priciest row, which is safe for a
273
+ * vendor and makes quota refuse a free model long before it should.
274
+ */
275
+ const ZERO_MODEL_PRICING = Object.freeze({
276
+ inputPerMillion: 0,
277
+ outputPerMillion: 0,
278
+ cacheReadPerMillion: 0,
279
+ cacheWritePerMillion: 0
280
+ });
269
281
  function priciest(pricing) {
270
282
  let best;
271
283
  for (const p of Object.values(pricing)) if (!best || p.outputPerMillion > best.outputPerMillion) best = p;
@@ -650,4 +662,4 @@ function thinkingSettingsFor(providerId, modelId, opts) {
650
662
  return { temperature: opts.temperature };
651
663
  }
652
664
  //#endregion
653
- export { AI_PROVIDERS, AI_PROVIDER_IDS, AiRefusalError, DEFAULT_AI_PROVIDER, DEFAULT_AI_QUOTA, DEFAULT_EMBEDDING_PROVIDER, DEFAULT_MODEL_PRICING, EMBEDDING_PROVIDERS, EMBEDDING_PROVIDER_IDS, REFUSAL_FINISH_REASON, anthropicThinkingSettings, buildAiWorkflow, createAiQuotaService, createAiUsageAggregationService, createAiWorkflowHooks, createCostEstimator, createEmbeddingUsageAccumulator, createInstrumentedEmbeddingModel, createInstrumentedModel, createRefusalAwareModel, createUsageAccumulator, defineAiStep, embeddingDimensionsFor, estimateCostMicros, isAiRefusalError, readRefusalDetails, supportsAdaptiveThinking, supportsToolSearch, thinkingSettingsFor };
665
+ export { AI_PROVIDERS, AI_PROVIDER_IDS, AiRefusalError, DEFAULT_AI_PROVIDER, DEFAULT_AI_QUOTA, DEFAULT_EMBEDDING_PROVIDER, DEFAULT_MODEL_PRICING, EMBEDDING_PROVIDERS, EMBEDDING_PROVIDER_IDS, OPENAI_COMPATIBLE_PROVIDER, OPENAI_COMPATIBLE_PROVIDER_ID, REFUSAL_FINISH_REASON, ZERO_MODEL_PRICING, anthropicThinkingSettings, buildAiWorkflow, createAiQuotaService, createAiUsageAggregationService, createAiWorkflowHooks, createCostEstimator, createEmbeddingUsageAccumulator, createInstrumentedEmbeddingModel, createInstrumentedModel, createRefusalAwareModel, createUsageAccumulator, defineAiStep, embeddingDimensionsFor, estimateCostMicros, isAiRefusalError, isSubprocessorResidency, readRefusalDetails, resolveEndpointResidency, supportsAdaptiveThinking, supportsToolSearch, thinkingSettingsFor };
@@ -1,4 +1,4 @@
1
- import { f as EmbeddingProviderId, i as AiProviderId } from "../../provider-registry-bXGOmyeh.js";
1
+ import { b as OpenAiCompatibleProviderId, g as EmbeddingProviderId, i as AiEndpointResidency, o as AiProviderId } from "../../provider-registry-BvXBqJDR.js";
2
2
  import { EmbeddingModelV4, LanguageModelV4 } from "@ai-sdk/provider";
3
3
  //#region src/ai/providers/index.d.ts
4
4
  export type LanguageModelFactory = (modelId: string) => LanguageModelV4;
@@ -66,4 +66,81 @@ export interface LazyEmbeddingModelMeta {
66
66
  * next call rather than cached.
67
67
  */
68
68
  export declare function createLazyEmbeddingModel(meta: LazyEmbeddingModelMeta, load: () => Promise<EmbeddingModelV4>): EmbeddingModelV4;
69
+ export type AiProviderConfigErrorKey = 'ai_residency_undeclared' | 'ai_residency_invalid' | 'ai_base_url_invalid' | 'ai_model_required' | 'ai_embedding_dimensions_invalid';
70
+ /**
71
+ * A provider configuration that cannot work. Thrown before any SDK is loaded
72
+ * or any request is made: it is a deployment mistake, found at wiring time.
73
+ */
74
+ export declare class AiProviderConfigError extends Error {
75
+ readonly key: AiProviderConfigErrorKey;
76
+ constructor(key: AiProviderConfigErrorKey, message: string);
77
+ }
78
+ export interface OpenAiCompatibleEndpointConfig {
79
+ /** The API root including its version segment, e.g. `http://vllm.ai.svc:8000/v1`. Required: there is no default host. */
80
+ baseUrl: string;
81
+ /** Sent as `Authorization: Bearer …` when set. Most self-hosted servers need none. */
82
+ apiKey?: string;
83
+ /** Where the endpoint processes payloads. Required, validated by `resolveEndpointResidency`. */
84
+ residency: AiEndpointResidency;
85
+ /** Reported as the model's `provider`. Defaults to `openai-compatible`. */
86
+ name?: string;
87
+ headers?: Record<string, string>;
88
+ /** A fetch implementation, for middleware or tests. Defaults to the global `fetch`. */
89
+ fetch?: typeof globalThis.fetch;
90
+ }
91
+ export interface OpenAiCompatibleModelProviderConfig extends OpenAiCompatibleEndpointConfig {
92
+ /** The model a call without an id uses. Required: a server you run has no registry default. */
93
+ defaultModel: string;
94
+ /** Cheap model for classifier-style passes. Defaults to `defaultModel`. */
95
+ classifierModel?: string;
96
+ /** Set when the server enforces a JSON schema on output (vLLM does); otherwise `generateObject` uses JSON mode. */
97
+ structuredOutputs?: boolean;
98
+ /**
99
+ * Ask for token usage on streamed responses. Defaults to `true`, because the
100
+ * instrumented model meters what the stream reports and a stream without it
101
+ * reports zero tokens. Turn it off only for a server that rejects the option.
102
+ */
103
+ includeUsage?: boolean;
104
+ }
105
+ export interface OpenAiCompatibleModelProvider {
106
+ providerId: OpenAiCompatibleProviderId;
107
+ /** The declared residency, validated — what a badge or an audit record shows. */
108
+ residency: AiEndpointResidency;
109
+ classifierModelId: string;
110
+ /** A Chat Completions model, wrapped for refusal detection like the vendor ones. */
111
+ languageModel(modelId?: string): LanguageModelV4;
112
+ }
113
+ export interface OpenAiCompatibleEmbeddingProviderConfig extends OpenAiCompatibleEndpointConfig {
114
+ model: string;
115
+ /**
116
+ * The model's vector width, which must match your `vector(N)` column.
117
+ * Required: a guessed width, such as the registry's 1536 fallback, silently
118
+ * breaks a 1024-wide model like `bge-m3` at the first insert.
119
+ */
120
+ dimensions: number;
121
+ }
122
+ export interface OpenAiCompatibleEmbeddingProvider {
123
+ providerId: OpenAiCompatibleProviderId;
124
+ residency: AiEndpointResidency;
125
+ modelId: string;
126
+ dimensions: number;
127
+ embeddingModel(): EmbeddingModelV4;
128
+ }
129
+ /**
130
+ * A model server you run, or any host with the OpenAI-compatible API, as
131
+ * refusal-aware models. Language models go through **Chat Completions**, which
132
+ * is what vLLM, Ollama and llama.cpp speak — not the Responses API that
133
+ * `@ai-sdk/openai` defaults to.
134
+ *
135
+ * ```ts
136
+ * const models = await createOpenAiCompatibleModelProvider({
137
+ * baseUrl: 'http://vllm.ai.svc:8000/v1',
138
+ * residency: { region: 'self-hosted' },
139
+ * defaultModel: 'qwen3-32b',
140
+ * });
141
+ * ```
142
+ */
143
+ export declare function createOpenAiCompatibleModelProvider(config: OpenAiCompatibleModelProviderConfig): Promise<OpenAiCompatibleModelProvider>;
144
+ /** An embedding model on an OpenAI-compatible endpoint, with its declared width. */
145
+ export declare function createOpenAiCompatibleEmbeddingProvider(config: OpenAiCompatibleEmbeddingProviderConfig): Promise<OpenAiCompatibleEmbeddingProvider>;
69
146
  //#endregion
@@ -1,5 +1,5 @@
1
1
  import { r as createRefusalAwareModel } from "../../refusal-BsL2HPDb.js";
2
- import { a as EMBEDDING_PROVIDERS, t as AI_PROVIDERS } from "../../provider-registry-DcRDsjtT.js";
2
+ import { a as EMBEDDING_PROVIDERS, c as OPENAI_COMPATIBLE_PROVIDER_ID, d as resolveEndpointResidency, t as AI_PROVIDERS } from "../../provider-registry-BRwjC6_3.js";
3
3
  //#region src/ai/providers/index.ts
4
4
  const LLM_LOADERS = {
5
5
  anthropic: async (apiKey, baseURL) => {
@@ -52,7 +52,7 @@ function createEmbeddingModelFactory(providerId, apiKey, baseURL) {
52
52
  * ```
53
53
  */
54
54
  async function createLanguageModelProvider(config) {
55
- const providerId = config.provider ?? "anthropic";
55
+ const providerId = config.provider ?? "mistral";
56
56
  const meta = AI_PROVIDERS[providerId];
57
57
  const factory = await createLanguageModelFactory(providerId, config.apiKey, config.baseUrl);
58
58
  const defaultModel = config.defaultModel ?? meta.defaultModel;
@@ -63,7 +63,7 @@ async function createLanguageModelProvider(config) {
63
63
  };
64
64
  }
65
65
  async function createEmbeddingModelProvider(config) {
66
- const providerId = config.provider ?? "openai";
66
+ const providerId = config.provider ?? "mistral";
67
67
  const factory = await createEmbeddingModelFactory(providerId, config.apiKey, config.baseUrl);
68
68
  const modelId = config.model ?? EMBEDDING_PROVIDERS[providerId].defaultModel;
69
69
  return {
@@ -103,5 +103,87 @@ function createLazyEmbeddingModel(meta, load) {
103
103
  doEmbed: (options) => model().then((m) => m.doEmbed(options))
104
104
  };
105
105
  }
106
+ /**
107
+ * A provider configuration that cannot work. Thrown before any SDK is loaded
108
+ * or any request is made: it is a deployment mistake, found at wiring time.
109
+ */
110
+ var AiProviderConfigError = class extends Error {
111
+ key;
112
+ constructor(key, message) {
113
+ super(message);
114
+ this.name = "AiProviderConfigError";
115
+ this.key = key;
116
+ }
117
+ };
118
+ function checkEndpoint(config) {
119
+ const residency = resolveEndpointResidency(config.residency);
120
+ if (!residency.ok) throw new AiProviderConfigError(residency.error.key, residency.error.message);
121
+ let url;
122
+ try {
123
+ url = new URL(config.baseUrl);
124
+ } catch {
125
+ url = void 0;
126
+ }
127
+ if (url === void 0 || url.protocol !== "http:" && url.protocol !== "https:") throw new AiProviderConfigError("ai_base_url_invalid", `baseUrl must be an absolute http(s) URL, got ${JSON.stringify(config.baseUrl)}`);
128
+ return residency.value;
129
+ }
130
+ function requireModel(modelId, field) {
131
+ if (typeof modelId !== "string" || modelId.trim() === "") throw new AiProviderConfigError("ai_model_required", `${field} is required for an OpenAI-compatible endpoint`);
132
+ return modelId;
133
+ }
134
+ async function loadOpenAiCompatible(config, options = {}) {
135
+ const { createOpenAICompatible } = await import("@ai-sdk/openai-compatible");
136
+ return createOpenAICompatible({
137
+ name: config.name ?? "openai-compatible",
138
+ baseURL: config.baseUrl.replace(/\/+$/, ""),
139
+ apiKey: config.apiKey,
140
+ headers: config.headers,
141
+ fetch: config.fetch,
142
+ includeUsage: options.includeUsage ?? true,
143
+ supportsStructuredOutputs: options.structuredOutputs
144
+ });
145
+ }
146
+ /**
147
+ * A model server you run, or any host with the OpenAI-compatible API, as
148
+ * refusal-aware models. Language models go through **Chat Completions**, which
149
+ * is what vLLM, Ollama and llama.cpp speak — not the Responses API that
150
+ * `@ai-sdk/openai` defaults to.
151
+ *
152
+ * ```ts
153
+ * const models = await createOpenAiCompatibleModelProvider({
154
+ * baseUrl: 'http://vllm.ai.svc:8000/v1',
155
+ * residency: { region: 'self-hosted' },
156
+ * defaultModel: 'qwen3-32b',
157
+ * });
158
+ * ```
159
+ */
160
+ async function createOpenAiCompatibleModelProvider(config) {
161
+ const residency = checkEndpoint(config);
162
+ const defaultModel = requireModel(config.defaultModel, "defaultModel");
163
+ const provider = await loadOpenAiCompatible(config, {
164
+ structuredOutputs: config.structuredOutputs,
165
+ includeUsage: config.includeUsage
166
+ });
167
+ return {
168
+ providerId: OPENAI_COMPATIBLE_PROVIDER_ID,
169
+ residency,
170
+ classifierModelId: config.classifierModel ?? defaultModel,
171
+ languageModel: (modelId) => createRefusalAwareModel(provider.chatModel(modelId ?? defaultModel))
172
+ };
173
+ }
174
+ /** An embedding model on an OpenAI-compatible endpoint, with its declared width. */
175
+ async function createOpenAiCompatibleEmbeddingProvider(config) {
176
+ const residency = checkEndpoint(config);
177
+ const modelId = requireModel(config.model, "model");
178
+ if (!Number.isInteger(config.dimensions) || config.dimensions <= 0) throw new AiProviderConfigError("ai_embedding_dimensions_invalid", `dimensions must be a positive integer matching your vector column, got ${JSON.stringify(config.dimensions)}`);
179
+ const provider = await loadOpenAiCompatible(config);
180
+ return {
181
+ providerId: OPENAI_COMPATIBLE_PROVIDER_ID,
182
+ residency,
183
+ modelId,
184
+ dimensions: config.dimensions,
185
+ embeddingModel: () => provider.embeddingModel(modelId)
186
+ };
187
+ }
106
188
  //#endregion
107
- export { createEmbeddingModelFactory, createEmbeddingModelProvider, createLanguageModelFactory, createLanguageModelProvider, createLazyEmbeddingModel };
189
+ export { AiProviderConfigError, createEmbeddingModelFactory, createEmbeddingModelProvider, createLanguageModelFactory, createLanguageModelProvider, createLazyEmbeddingModel, createOpenAiCompatibleEmbeddingProvider, createOpenAiCompatibleModelProvider };
@@ -1,2 +1,2 @@
1
- import { a as AiProviderMeta, c as DEFAULT_AI_PROVIDER, d as EMBEDDING_PROVIDER_IDS, f as EmbeddingProviderId, i as AiProviderId, l as DEFAULT_EMBEDDING_PROVIDER, m as embeddingDimensionsFor, n as AI_PROVIDER_IDS, o as AiProviderModelOption, p as EmbeddingProviderMeta, r as AiProcessingRegion, s as AiVendorResidency, t as AI_PROVIDERS, u as EMBEDDING_PROVIDERS } from "../provider-registry-bXGOmyeh.js";
2
- export { AI_PROVIDERS, AI_PROVIDER_IDS, AiProcessingRegion, AiProviderId, AiProviderMeta, AiProviderModelOption, AiVendorResidency, DEFAULT_AI_PROVIDER, DEFAULT_EMBEDDING_PROVIDER, EMBEDDING_PROVIDERS, EMBEDDING_PROVIDER_IDS, EmbeddingProviderId, EmbeddingProviderMeta, embeddingDimensionsFor };
1
+ 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-BvXBqJDR.js";
2
+ export { AI_PROVIDERS, AI_PROVIDER_IDS, AiEndpointRegion, AiEndpointResidency, AiProcessingRegion, AiProviderId, AiProviderMeta, AiProviderModelOption, AiResidencyError, AiResidencyResult, AiVendorResidency, DEFAULT_AI_PROVIDER, DEFAULT_EMBEDDING_PROVIDER, EMBEDDING_PROVIDERS, EMBEDDING_PROVIDER_IDS, EmbeddingProviderId, EmbeddingProviderMeta, OPENAI_COMPATIBLE_PROVIDER, OPENAI_COMPATIBLE_PROVIDER_ID, OpenAiCompatibleProviderId, OpenAiCompatibleProviderMeta, embeddingDimensionsFor, isSubprocessorResidency, resolveEndpointResidency };
@@ -1,2 +1,2 @@
1
- import { a as EMBEDDING_PROVIDERS, i as DEFAULT_EMBEDDING_PROVIDER, n as AI_PROVIDER_IDS, o as EMBEDDING_PROVIDER_IDS, r as DEFAULT_AI_PROVIDER, s as embeddingDimensionsFor, t as AI_PROVIDERS } from "../provider-registry-DcRDsjtT.js";
2
- export { AI_PROVIDERS, AI_PROVIDER_IDS, DEFAULT_AI_PROVIDER, DEFAULT_EMBEDDING_PROVIDER, EMBEDDING_PROVIDERS, EMBEDDING_PROVIDER_IDS, embeddingDimensionsFor };
1
+ 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-BRwjC6_3.js";
2
+ export { AI_PROVIDERS, AI_PROVIDER_IDS, DEFAULT_AI_PROVIDER, DEFAULT_EMBEDDING_PROVIDER, EMBEDDING_PROVIDERS, EMBEDDING_PROVIDER_IDS, OPENAI_COMPATIBLE_PROVIDER, OPENAI_COMPATIBLE_PROVIDER_ID, embeddingDimensionsFor, isSubprocessorResidency, resolveEndpointResidency };
@@ -276,7 +276,7 @@ function createPgBossStepWorker(deps) {
276
276
  }
277
277
  async function stop() {
278
278
  if (workerId) {
279
- await boss.offWork(workerId);
279
+ await boss.offWork(queueName, { id: workerId });
280
280
  workerId = null;
281
281
  }
282
282
  }
@@ -314,7 +314,7 @@ function createPgBossDlqWorker(deps) {
314
314
  }
315
315
  async function stop() {
316
316
  if (workerId) {
317
- await boss.offWork(workerId);
317
+ await boss.offWork(dlq, { id: workerId });
318
318
  workerId = null;
319
319
  }
320
320
  }
@@ -398,7 +398,7 @@ function createPgBossStartWorker(deps) {
398
398
  }
399
399
  async function stop() {
400
400
  if (workerId) {
401
- await boss.offWork(workerId);
401
+ await boss.offWork(queueName, { id: workerId });
402
402
  workerId = null;
403
403
  }
404
404
  }
@@ -0,0 +1,181 @@
1
+ //#region src/ai/provider-registry.ts
2
+ /**
3
+ * The provider registry — pure metadata about the vendors a BYOK deployment
4
+ * can point at: ids, default and cheap models, where a key is created, and
5
+ * **where the vendor processes what you send it**. Dependency-free, so a
6
+ * browser bundle (a provider/model picker, a residency badge) can import it;
7
+ * the SDK factories that need `@ai-sdk/*` live in `octaflow/ai/providers`.
8
+ *
9
+ * Adding a provider: an id here with its metadata, a factory in
10
+ * `providers/`, and pricing rows in `cost.ts`.
11
+ */
12
+ const AI_PROVIDER_IDS = ["anthropic", "mistral"];
13
+ const EMBEDDING_PROVIDER_IDS = ["openai", "mistral"];
14
+ /**
15
+ * What an unset provider resolves to: the EU-established vendor, so a deployment
16
+ * that names no provider adds no third-country transfer to its annex. Choosing
17
+ * a third-country vendor is a decision the caller writes down. The embedding
18
+ * default is 1024-dimensional (`mistral-embed`); a `vector(N)` column sized for
19
+ * another model names its provider explicitly.
20
+ */
21
+ const DEFAULT_AI_PROVIDER = "mistral";
22
+ const DEFAULT_EMBEDDING_PROVIDER = "mistral";
23
+ const AI_PROVIDERS = {
24
+ anthropic: {
25
+ id: "anthropic",
26
+ label: "Anthropic",
27
+ residency: {
28
+ region: "third-country",
29
+ legalName: "Anthropic PBC",
30
+ country: "US"
31
+ },
32
+ defaultModel: "claude-sonnet-5",
33
+ classifierModel: "claude-haiku-4-5",
34
+ testModel: "claude-haiku-4-5",
35
+ keyPrefix: "sk-ant-",
36
+ consoleKeyUrl: "https://console.anthropic.com/settings/keys",
37
+ modelOptions: [
38
+ {
39
+ label: "Claude Opus 5",
40
+ value: "claude-opus-5"
41
+ },
42
+ {
43
+ label: "Claude Opus 4.8",
44
+ value: "claude-opus-4-8"
45
+ },
46
+ {
47
+ label: "Claude Sonnet 5",
48
+ value: "claude-sonnet-5"
49
+ },
50
+ {
51
+ label: "Claude Haiku 4.5",
52
+ value: "claude-haiku-4-5"
53
+ }
54
+ ]
55
+ },
56
+ mistral: {
57
+ id: "mistral",
58
+ label: "Mistral",
59
+ residency: {
60
+ region: "eu",
61
+ legalName: "Mistral AI SAS",
62
+ country: "FR"
63
+ },
64
+ defaultModel: "mistral-medium-latest",
65
+ classifierModel: "mistral-small-latest",
66
+ testModel: "mistral-small-latest",
67
+ keyPrefix: null,
68
+ consoleKeyUrl: "https://console.mistral.ai/api-keys",
69
+ modelOptions: [
70
+ {
71
+ label: "Mistral Medium 3.5",
72
+ value: "mistral-medium-latest"
73
+ },
74
+ {
75
+ label: "Mistral Large 3",
76
+ value: "mistral-large-latest"
77
+ },
78
+ {
79
+ label: "Mistral Small 4",
80
+ value: "mistral-small-latest"
81
+ }
82
+ ]
83
+ }
84
+ };
85
+ const EMBEDDING_PROVIDERS = {
86
+ openai: {
87
+ id: "openai",
88
+ label: "OpenAI",
89
+ residency: {
90
+ region: "third-country",
91
+ legalName: "OpenAI, L.L.C.",
92
+ country: "US"
93
+ },
94
+ defaultModel: "text-embedding-3-small",
95
+ consoleKeyUrl: "https://platform.openai.com/api-keys",
96
+ dimensionsByModel: {
97
+ "text-embedding-3-small": 1536,
98
+ "text-embedding-3-large": 3072
99
+ }
100
+ },
101
+ mistral: {
102
+ id: "mistral",
103
+ label: "Mistral",
104
+ residency: {
105
+ region: "eu",
106
+ legalName: "Mistral AI SAS",
107
+ country: "FR"
108
+ },
109
+ defaultModel: "mistral-embed",
110
+ consoleKeyUrl: "https://console.mistral.ai/api-keys",
111
+ dimensionsByModel: { "mistral-embed": 1024 }
112
+ }
113
+ };
114
+ /**
115
+ * Vector dimensions for an embedding model id in the vendor lists above.
116
+ * Unknown ids fall back to `fallback` (default 1536) so free-form vendor model
117
+ * ids keep a working column. A self-hosted model never goes through this
118
+ * guess: its width is declared (`createOpenAiCompatibleEmbeddingProvider`'s
119
+ * `dimensions`), because a wrong one fails at the first `vector(N)` insert.
120
+ */
121
+ function embeddingDimensionsFor(modelId, fallback = 1536) {
122
+ for (const meta of Object.values(EMBEDDING_PROVIDERS)) {
123
+ const dims = meta.dimensionsByModel[modelId];
124
+ if (dims !== void 0) return dims;
125
+ }
126
+ return fallback;
127
+ }
128
+ const OPENAI_COMPATIBLE_PROVIDER_ID = "openai-compatible";
129
+ const OPENAI_COMPATIBLE_PROVIDER = {
130
+ id: OPENAI_COMPATIBLE_PROVIDER_ID,
131
+ label: "OpenAI-compatible endpoint",
132
+ residency: "declared-by-deployment"
133
+ };
134
+ /**
135
+ * Validates a residency declared by a deployment — from config, an env file, a
136
+ * database row — before any call is made. A missing one is
137
+ * `ai_residency_undeclared`: an endpoint whose data location nobody stated is
138
+ * refused, never assumed to be local. A vendor region needs the legal name and
139
+ * the ISO country a subprocessor annex prints.
140
+ */
141
+ function resolveEndpointResidency(declared) {
142
+ if (declared === void 0 || declared === null) return {
143
+ ok: false,
144
+ error: {
145
+ key: "ai_residency_undeclared",
146
+ message: "an OpenAI-compatible endpoint needs a declared residency: { region: \"self-hosted\" }, or a vendor region with its legalName and country"
147
+ }
148
+ };
149
+ if (typeof declared !== "object") return invalidResidency("residency must be an object");
150
+ const { region, legalName, country } = declared;
151
+ if (region === "self-hosted") return {
152
+ ok: true,
153
+ value: { region: "self-hosted" }
154
+ };
155
+ if (region !== "eu" && region !== "third-country") return invalidResidency(`unknown region ${JSON.stringify(region)}; expected "self-hosted", "eu" or "third-country"`);
156
+ if (typeof legalName !== "string" || legalName.trim() === "") return invalidResidency(`region "${region}" names a vendor, so legalName is required`);
157
+ if (typeof country !== "string" || !/^[A-Z]{2}$/.test(country)) return invalidResidency(`region "${region}" needs country as an ISO 3166-1 alpha-2 code`);
158
+ return {
159
+ ok: true,
160
+ value: {
161
+ region,
162
+ legalName,
163
+ country
164
+ }
165
+ };
166
+ }
167
+ function invalidResidency(message) {
168
+ return {
169
+ ok: false,
170
+ error: {
171
+ key: "ai_residency_invalid",
172
+ message
173
+ }
174
+ };
175
+ }
176
+ /** Whether calling an endpoint with this residency makes its operator a subprocessor. A self-hosted endpoint does not. */
177
+ function isSubprocessorResidency(residency) {
178
+ return residency.region !== "self-hosted";
179
+ }
180
+ //#endregion
181
+ export { EMBEDDING_PROVIDERS as a, OPENAI_COMPATIBLE_PROVIDER_ID as c, resolveEndpointResidency as d, DEFAULT_EMBEDDING_PROVIDER as i, embeddingDimensionsFor as l, AI_PROVIDER_IDS as n, EMBEDDING_PROVIDER_IDS as o, DEFAULT_AI_PROVIDER as r, OPENAI_COMPATIBLE_PROVIDER as s, AI_PROVIDERS as t, isSubprocessorResidency as u };
@@ -0,0 +1,134 @@
1
+ //#region src/ai/provider-registry.d.ts
2
+ /**
3
+ * The provider registry — pure metadata about the vendors a BYOK deployment
4
+ * can point at: ids, default and cheap models, where a key is created, and
5
+ * **where the vendor processes what you send it**. Dependency-free, so a
6
+ * browser bundle (a provider/model picker, a residency badge) can import it;
7
+ * the SDK factories that need `@ai-sdk/*` live in `octaflow/ai/providers`.
8
+ *
9
+ * Adding a provider: an id here with its metadata, a factory in
10
+ * `providers/`, and pricing rows in `cost.ts`.
11
+ */
12
+ declare const AI_PROVIDER_IDS: readonly ['anthropic', 'mistral'];
13
+ type AiProviderId = (typeof AI_PROVIDER_IDS)[number];
14
+ declare const EMBEDDING_PROVIDER_IDS: readonly ['openai', 'mistral'];
15
+ type EmbeddingProviderId = (typeof EMBEDDING_PROVIDER_IDS)[number];
16
+ /**
17
+ * What an unset provider resolves to: the EU-established vendor, so a deployment
18
+ * that names no provider adds no third-country transfer to its annex. Choosing
19
+ * a third-country vendor is a decision the caller writes down. The embedding
20
+ * default is 1024-dimensional (`mistral-embed`); a `vector(N)` column sized for
21
+ * another model names its provider explicitly.
22
+ */
23
+ declare const DEFAULT_AI_PROVIDER: AiProviderId;
24
+ declare const DEFAULT_EMBEDDING_PROVIDER: EmbeddingProviderId;
25
+ /**
26
+ * Where a provider processes the payloads you send it.
27
+ *
28
+ * `'eu'` means the vendor is established in the EU/EEA and serves the API from
29
+ * there, so a call carries no third-country transfer under Art. 44 ff. GDPR.
30
+ * `'third-country'` means it does — your data-processing agreement then has
31
+ * to carry a transfer mechanism for that vendor.
32
+ *
33
+ * This is metadata about the *vendor endpoint called*, not a promise about a
34
+ * customer's own BYOK key: a customer who brings their own key contracts with
35
+ * the vendor directly.
36
+ */
37
+ type AiProcessingRegion = 'eu' | 'third-country';
38
+ interface AiVendorResidency {
39
+ region: AiProcessingRegion;
40
+ /** Legal entity, as it appears in a subprocessor annex. */
41
+ legalName: string;
42
+ /** Country of establishment, ISO 3166-1 alpha-2. */
43
+ country: string;
44
+ }
45
+ interface AiProviderModelOption {
46
+ label: string;
47
+ value: string;
48
+ }
49
+ interface AiProviderMeta {
50
+ id: AiProviderId;
51
+ label: string;
52
+ /** Where calls to this provider are processed — drives a residency badge and the subprocessor analysis. */
53
+ residency: AiVendorResidency;
54
+ /** Default chat/workflow model when nothing sets one. */
55
+ defaultModel: string;
56
+ /** Cheap model for classifier-style passes. */
57
+ classifierModel: string;
58
+ /** Cheap model for a "test connection" ping. */
59
+ testModel: string;
60
+ /** Well-known API key prefix for a soft format hint, or null when the provider has none. */
61
+ keyPrefix: string | null;
62
+ /** Where the operator creates an API key. */
63
+ consoleKeyUrl: string;
64
+ /** Curated model choices for a picker (free-form custom ids stay allowed). */
65
+ modelOptions: AiProviderModelOption[];
66
+ }
67
+ declare const AI_PROVIDERS: Record<AiProviderId, AiProviderMeta>;
68
+ interface EmbeddingProviderMeta {
69
+ id: EmbeddingProviderId;
70
+ label: string;
71
+ /** See {@link AiProviderMeta.residency}. */
72
+ residency: AiVendorResidency;
73
+ defaultModel: string;
74
+ /** Where the operator creates an API key. */
75
+ consoleKeyUrl: string;
76
+ /** Vector dimensions per known model id — must match the `vector(N)` column in your schema. */
77
+ dimensionsByModel: Record<string, number>;
78
+ }
79
+ declare const EMBEDDING_PROVIDERS: Record<EmbeddingProviderId, EmbeddingProviderMeta>;
80
+ /**
81
+ * Vector dimensions for an embedding model id in the vendor lists above.
82
+ * Unknown ids fall back to `fallback` (default 1536) so free-form vendor model
83
+ * ids keep a working column. A self-hosted model never goes through this
84
+ * guess: its width is declared (`createOpenAiCompatibleEmbeddingProvider`'s
85
+ * `dimensions`), because a wrong one fails at the first `vector(N)` insert.
86
+ */
87
+ declare function embeddingDimensionsFor(modelId: string, fallback?: number): number;
88
+ /**
89
+ * Where a model endpoint the *deployment* names processes payloads. A vendor in
90
+ * the lists above has a fixed residency; an OpenAI-compatible endpoint does not:
91
+ * the same client talks to vLLM in your own cluster, to Ollama on a workstation,
92
+ * or to a hosted inference vendor. So whoever deploys it declares the residency,
93
+ * and `'self-hosted'` is the value that adds no subprocessor.
94
+ *
95
+ * Kept apart from {@link AiProcessingRegion} on purpose: that union describes the
96
+ * vendors above, and a picker that iterates `AI_PROVIDERS` keeps working unchanged.
97
+ */
98
+ type AiEndpointRegion = AiProcessingRegion | 'self-hosted';
99
+ /** `{ region: 'self-hosted' }` for infrastructure you operate; a vendor's full residency otherwise. */
100
+ type AiEndpointResidency = {
101
+ region: 'self-hosted';
102
+ } | AiVendorResidency;
103
+ declare const OPENAI_COMPATIBLE_PROVIDER_ID = "openai-compatible";
104
+ type OpenAiCompatibleProviderId = typeof OPENAI_COMPATIBLE_PROVIDER_ID;
105
+ interface OpenAiCompatibleProviderMeta {
106
+ id: OpenAiCompatibleProviderId;
107
+ label: string;
108
+ /** Never fixed in the registry — see {@link resolveEndpointResidency}. */
109
+ residency: 'declared-by-deployment';
110
+ }
111
+ declare const OPENAI_COMPATIBLE_PROVIDER: OpenAiCompatibleProviderMeta;
112
+ interface AiResidencyError {
113
+ key: 'ai_residency_undeclared' | 'ai_residency_invalid';
114
+ message: string;
115
+ }
116
+ type AiResidencyResult = {
117
+ ok: true;
118
+ value: AiEndpointResidency;
119
+ } | {
120
+ ok: false;
121
+ error: AiResidencyError;
122
+ };
123
+ /**
124
+ * Validates a residency declared by a deployment — from config, an env file, a
125
+ * database row — before any call is made. A missing one is
126
+ * `ai_residency_undeclared`: an endpoint whose data location nobody stated is
127
+ * refused, never assumed to be local. A vendor region needs the legal name and
128
+ * the ISO country a subprocessor annex prints.
129
+ */
130
+ declare function resolveEndpointResidency(declared: unknown): AiResidencyResult;
131
+ /** Whether calling an endpoint with this residency makes its operator a subprocessor. A self-hosted endpoint does not. */
132
+ declare function isSubprocessorResidency(residency: AiEndpointResidency): boolean;
133
+ //#endregion
134
+ export { isSubprocessorResidency as C, embeddingDimensionsFor as S, EmbeddingProviderMeta as _, AiProcessingRegion as a, OpenAiCompatibleProviderId as b, AiProviderModelOption as c, AiVendorResidency as d, DEFAULT_AI_PROVIDER as f, EmbeddingProviderId as g, EMBEDDING_PROVIDER_IDS as h, AiEndpointResidency as i, AiResidencyError as l, EMBEDDING_PROVIDERS as m, AI_PROVIDER_IDS as n, AiProviderId as o, DEFAULT_EMBEDDING_PROVIDER as p, AiEndpointRegion as r, AiProviderMeta as s, AI_PROVIDERS as t, AiResidencyResult as u, OPENAI_COMPATIBLE_PROVIDER as v, resolveEndpointResidency as w, OpenAiCompatibleProviderMeta as x, OPENAI_COMPATIBLE_PROVIDER_ID as y };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "octaflow",
3
- "version": "0.22.0",
3
+ "version": "0.24.0",
4
4
  "description": "Durable DAG workflow engine: Zod-typed steps over Postgres + pg-boss, with an optional AI add-on (token/cost/quota). Layered single package.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -71,6 +71,7 @@
71
71
  "@ai-sdk/anthropic": "^4.0.0",
72
72
  "@ai-sdk/mistral": "^4.0.0",
73
73
  "@ai-sdk/openai": "^4.0.0",
74
+ "@ai-sdk/openai-compatible": "^3.0.0",
74
75
  "@ai-sdk/provider": "^4.0.0",
75
76
  "ai": "^7.0.0",
76
77
  "pg": "^8.0.0",
@@ -88,6 +89,9 @@
88
89
  "@ai-sdk/openai": {
89
90
  "optional": true
90
91
  },
92
+ "@ai-sdk/openai-compatible": {
93
+ "optional": true
94
+ },
91
95
  "@ai-sdk/provider": {
92
96
  "optional": true
93
97
  },
@@ -105,6 +109,7 @@
105
109
  "@ai-sdk/anthropic": "^4.0.52",
106
110
  "@ai-sdk/mistral": "^4.0.42",
107
111
  "@ai-sdk/openai": "^4.0.65",
112
+ "@ai-sdk/openai-compatible": "^3.0.48",
108
113
  "@ai-sdk/provider": "^4.0.13",
109
114
  "@testcontainers/postgresql": "^12.1.0",
110
115
  "@types/node": "^26.5.1",
@@ -1,121 +0,0 @@
1
- //#region src/ai/provider-registry.ts
2
- /**
3
- * The provider registry — pure metadata about the vendors a BYOK deployment
4
- * can point at: ids, default and cheap models, where a key is created, and
5
- * **where the vendor processes what you send it**. Dependency-free, so a
6
- * browser bundle (a provider/model picker, a residency badge) can import it;
7
- * the SDK factories that need `@ai-sdk/*` live in `octaflow/ai/providers`.
8
- *
9
- * Adding a provider: an id here with its metadata, a factory in
10
- * `providers/`, and pricing rows in `cost.ts`.
11
- */
12
- const AI_PROVIDER_IDS = ["anthropic", "mistral"];
13
- const EMBEDDING_PROVIDER_IDS = ["openai", "mistral"];
14
- /** What an unset provider resolves to. */
15
- const DEFAULT_AI_PROVIDER = "anthropic";
16
- const DEFAULT_EMBEDDING_PROVIDER = "openai";
17
- const AI_PROVIDERS = {
18
- anthropic: {
19
- id: "anthropic",
20
- label: "Anthropic",
21
- residency: {
22
- region: "third-country",
23
- legalName: "Anthropic PBC",
24
- country: "US"
25
- },
26
- defaultModel: "claude-sonnet-5",
27
- classifierModel: "claude-haiku-4-5",
28
- testModel: "claude-haiku-4-5",
29
- keyPrefix: "sk-ant-",
30
- consoleKeyUrl: "https://console.anthropic.com/settings/keys",
31
- modelOptions: [
32
- {
33
- label: "Claude Opus 5",
34
- value: "claude-opus-5"
35
- },
36
- {
37
- label: "Claude Opus 4.8",
38
- value: "claude-opus-4-8"
39
- },
40
- {
41
- label: "Claude Sonnet 5",
42
- value: "claude-sonnet-5"
43
- },
44
- {
45
- label: "Claude Haiku 4.5",
46
- value: "claude-haiku-4-5"
47
- }
48
- ]
49
- },
50
- mistral: {
51
- id: "mistral",
52
- label: "Mistral",
53
- residency: {
54
- region: "eu",
55
- legalName: "Mistral AI SAS",
56
- country: "FR"
57
- },
58
- defaultModel: "mistral-medium-latest",
59
- classifierModel: "mistral-small-latest",
60
- testModel: "mistral-small-latest",
61
- keyPrefix: null,
62
- consoleKeyUrl: "https://console.mistral.ai/api-keys",
63
- modelOptions: [
64
- {
65
- label: "Mistral Medium 3.5",
66
- value: "mistral-medium-latest"
67
- },
68
- {
69
- label: "Mistral Large 3",
70
- value: "mistral-large-latest"
71
- },
72
- {
73
- label: "Mistral Small 4",
74
- value: "mistral-small-latest"
75
- }
76
- ]
77
- }
78
- };
79
- const EMBEDDING_PROVIDERS = {
80
- openai: {
81
- id: "openai",
82
- label: "OpenAI",
83
- residency: {
84
- region: "third-country",
85
- legalName: "OpenAI, L.L.C.",
86
- country: "US"
87
- },
88
- defaultModel: "text-embedding-3-small",
89
- consoleKeyUrl: "https://platform.openai.com/api-keys",
90
- dimensionsByModel: {
91
- "text-embedding-3-small": 1536,
92
- "text-embedding-3-large": 3072
93
- }
94
- },
95
- mistral: {
96
- id: "mistral",
97
- label: "Mistral",
98
- residency: {
99
- region: "eu",
100
- legalName: "Mistral AI SAS",
101
- country: "FR"
102
- },
103
- defaultModel: "mistral-embed",
104
- consoleKeyUrl: "https://console.mistral.ai/api-keys",
105
- dimensionsByModel: { "mistral-embed": 1024 }
106
- }
107
- };
108
- /**
109
- * Vector dimensions for an embedding model id. Unknown ids fall back to
110
- * `fallback` (default 1536, the common OpenAI-compatible dimension) so
111
- * free-form model ids keep a working column.
112
- */
113
- function embeddingDimensionsFor(modelId, fallback = 1536) {
114
- for (const meta of Object.values(EMBEDDING_PROVIDERS)) {
115
- const dims = meta.dimensionsByModel[modelId];
116
- if (dims !== void 0) return dims;
117
- }
118
- return fallback;
119
- }
120
- //#endregion
121
- export { EMBEDDING_PROVIDERS as a, DEFAULT_EMBEDDING_PROVIDER as i, AI_PROVIDER_IDS as n, EMBEDDING_PROVIDER_IDS as o, DEFAULT_AI_PROVIDER as r, embeddingDimensionsFor as s, AI_PROVIDERS as t };
@@ -1,81 +0,0 @@
1
- //#region src/ai/provider-registry.d.ts
2
- /**
3
- * The provider registry — pure metadata about the vendors a BYOK deployment
4
- * can point at: ids, default and cheap models, where a key is created, and
5
- * **where the vendor processes what you send it**. Dependency-free, so a
6
- * browser bundle (a provider/model picker, a residency badge) can import it;
7
- * the SDK factories that need `@ai-sdk/*` live in `octaflow/ai/providers`.
8
- *
9
- * Adding a provider: an id here with its metadata, a factory in
10
- * `providers/`, and pricing rows in `cost.ts`.
11
- */
12
- declare const AI_PROVIDER_IDS: readonly ['anthropic', 'mistral'];
13
- type AiProviderId = (typeof AI_PROVIDER_IDS)[number];
14
- declare const EMBEDDING_PROVIDER_IDS: readonly ['openai', 'mistral'];
15
- type EmbeddingProviderId = (typeof EMBEDDING_PROVIDER_IDS)[number];
16
- /** What an unset provider resolves to. */
17
- declare const DEFAULT_AI_PROVIDER: AiProviderId;
18
- declare const DEFAULT_EMBEDDING_PROVIDER: EmbeddingProviderId;
19
- /**
20
- * Where a provider processes the payloads you send it.
21
- *
22
- * `'eu'` means the vendor is established in the EU/EEA and serves the API from
23
- * there, so a call carries no third-country transfer under Art. 44 ff. GDPR.
24
- * `'third-country'` means it does — your data-processing agreement then has
25
- * to carry a transfer mechanism for that vendor.
26
- *
27
- * This is metadata about the *vendor endpoint called*, not a promise about a
28
- * customer's own BYOK key: a customer who brings their own key contracts with
29
- * the vendor directly.
30
- */
31
- type AiProcessingRegion = 'eu' | 'third-country';
32
- interface AiVendorResidency {
33
- region: AiProcessingRegion;
34
- /** Legal entity, as it appears in a subprocessor annex. */
35
- legalName: string;
36
- /** Country of establishment, ISO 3166-1 alpha-2. */
37
- country: string;
38
- }
39
- interface AiProviderModelOption {
40
- label: string;
41
- value: string;
42
- }
43
- interface AiProviderMeta {
44
- id: AiProviderId;
45
- label: string;
46
- /** Where calls to this provider are processed — drives a residency badge and the subprocessor analysis. */
47
- residency: AiVendorResidency;
48
- /** Default chat/workflow model when nothing sets one. */
49
- defaultModel: string;
50
- /** Cheap model for classifier-style passes. */
51
- classifierModel: string;
52
- /** Cheap model for a "test connection" ping. */
53
- testModel: string;
54
- /** Well-known API key prefix for a soft format hint, or null when the provider has none. */
55
- keyPrefix: string | null;
56
- /** Where the operator creates an API key. */
57
- consoleKeyUrl: string;
58
- /** Curated model choices for a picker (free-form custom ids stay allowed). */
59
- modelOptions: AiProviderModelOption[];
60
- }
61
- declare const AI_PROVIDERS: Record<AiProviderId, AiProviderMeta>;
62
- interface EmbeddingProviderMeta {
63
- id: EmbeddingProviderId;
64
- label: string;
65
- /** See {@link AiProviderMeta.residency}. */
66
- residency: AiVendorResidency;
67
- defaultModel: string;
68
- /** Where the operator creates an API key. */
69
- consoleKeyUrl: string;
70
- /** Vector dimensions per known model id — must match the `vector(N)` column in your schema. */
71
- dimensionsByModel: Record<string, number>;
72
- }
73
- declare const EMBEDDING_PROVIDERS: Record<EmbeddingProviderId, EmbeddingProviderMeta>;
74
- /**
75
- * Vector dimensions for an embedding model id. Unknown ids fall back to
76
- * `fallback` (default 1536, the common OpenAI-compatible dimension) so
77
- * free-form model ids keep a working column.
78
- */
79
- declare function embeddingDimensionsFor(modelId: string, fallback?: number): number;
80
- //#endregion
81
- export { AiProviderMeta as a, DEFAULT_AI_PROVIDER as c, EMBEDDING_PROVIDER_IDS as d, EmbeddingProviderId as f, AiProviderId as i, DEFAULT_EMBEDDING_PROVIDER as l, embeddingDimensionsFor as m, AI_PROVIDER_IDS as n, AiProviderModelOption as o, EmbeddingProviderMeta as p, AiProcessingRegion as r, AiVendorResidency as s, AI_PROVIDERS as t, EMBEDDING_PROVIDERS as u };