@lunora/ai 1.0.0-alpha.11 → 1.0.0-alpha.110
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 +18 -9
- package/dist/index.d.mts +93 -27
- package/dist/index.d.ts +93 -27
- package/dist/index.mjs +1 -3
- package/dist/packem_shared/AI_DEFAULT_EMBEDDING_MODEL_ENV-IwcHZiKj.mjs +1 -0
- package/dist/packem_shared/DEFAULT_MODEL_PRICES-CIJLs1Ah.mjs +1 -0
- package/dist/packem_shared/VECTORIZE_CAPABILITIES-CUQDoxis.mjs +1 -0
- package/dist/packem_shared/batchReranker-Bc38FBLH.mjs +1 -0
- package/dist/packem_shared/bm25-9q0Avwi-.mjs +1 -0
- package/dist/packem_shared/bm25LexicalStore-DMUzAL0O.mjs +1 -0
- package/dist/packem_shared/concurrent-C6nqBv41.mjs +1 -0
- package/dist/packem_shared/contentHash-BIn6ECP8.mjs +1 -0
- package/dist/packem_shared/createAi-Cebawe9R.mjs +1 -0
- package/dist/packem_shared/defineRag-CMTzKfS7.mjs +8 -0
- package/dist/packem_shared/defineRagSource-Q3f3niU8.mjs +1 -0
- package/dist/packem_shared/fixedWindowChunks-C461ahRE.mjs +1 -0
- package/dist/packem_shared/hybridRank-B4skyCLx.mjs +1 -0
- package/dist/packem_shared/markdownChunker-iW8V4klY.mjs +5 -0
- package/dist/packem_shared/matchesMetadataFilter-BbIOyA5g.mjs +1 -0
- package/dist/packem_shared/ragSyncTriggers-hgMcA4f2.mjs +1 -0
- package/dist/packem_shared/sql-D5aqEMCY.mjs +1 -0
- package/dist/packem_shared/sqlLexicalStore-4C_cIwef.mjs +1 -0
- package/dist/packem_shared/sqliteVectorStore-SjOFKoHo.mjs +1 -0
- package/dist/packem_shared/stable-key-B_BlboiY.mjs +1 -0
- package/dist/packem_shared/types.d-D-WK1t2B.d.mts +473 -0
- package/dist/packem_shared/types.d-D-WK1t2B.d.ts +473 -0
- package/dist/packem_shared/usage-GPnTSqR8.mjs +1 -0
- package/dist/rag/index.d.mts +1364 -0
- package/dist/rag/index.d.ts +1364 -0
- package/dist/rag/index.mjs +1 -0
- package/package.json +12 -16
- package/dist/packem_shared/createAi-Bq_4LMcp.mjs +0 -54
|
@@ -0,0 +1,473 @@
|
|
|
1
|
+
import { EmbeddingModel, LanguageModel } from 'ai';
|
|
2
|
+
/**
|
|
3
|
+
* AI Gateway's hard limit on `cf-aig-metadata` keys. Exceeding it makes the
|
|
4
|
+
* gateway reject the metadata object entirely, so the builder trims to this
|
|
5
|
+
* rather than sending something that will be thrown away.
|
|
6
|
+
*/
|
|
7
|
+
declare const AI_GATEWAY_METADATA_MAX_KEYS = 5;
|
|
8
|
+
/**
|
|
9
|
+
* Project {@link AiGatewayMetadata} to a plain string-map of only its defined,
|
|
10
|
+
* non-empty fields, or `undefined` when nothing is set. This is the shared source
|
|
11
|
+
* of truth behind both gateway-correlation forms: the `cf-aig-metadata` HTTP
|
|
12
|
+
* header (bring-your-own providers) and the Workers AI binding's native
|
|
13
|
+
* `gateway.metadata` option — both encode the same `{ functionPath, traceId }`.
|
|
14
|
+
* @experimental
|
|
15
|
+
*/
|
|
16
|
+
declare const buildAiGatewayMetadataFields: (metadata: AiGatewayMetadata | undefined) => Record<string, string> | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* Which surface resolved the gateway. The two paths handle the auth token
|
|
19
|
+
* differently: a bring-your-own AI SDK provider sends it as the
|
|
20
|
+
* `cf-aig-authorization` header (`ResolvedAiGateway.headers`), but the Workers AI
|
|
21
|
+
* **binding** routes through the gateway using the account's own credentials and
|
|
22
|
+
* its native `gateway` option (Cloudflare `GatewayOptions`) has **no** field to
|
|
23
|
+
* carry an authorization token — so a token set for the binding path cannot be
|
|
24
|
+
* delivered and is warned about instead of silently dropped.
|
|
25
|
+
* @experimental
|
|
26
|
+
*/
|
|
27
|
+
type AiGatewayConsumer = "byo-provider" | "workers-ai-binding";
|
|
28
|
+
/**
|
|
29
|
+
* Correlation metadata folded into the `cf-aig-metadata` request header so a
|
|
30
|
+
* gateway log entry can be tied back to the Lunora function + trace that made
|
|
31
|
+
* the call. Every field is optional — only defined ones are sent.
|
|
32
|
+
* @experimental
|
|
33
|
+
*/
|
|
34
|
+
interface AiGatewayMetadata {
|
|
35
|
+
/** The Lunora function path that issued the model call (e.g. `messages:send`). */
|
|
36
|
+
functionPath?: string;
|
|
37
|
+
/**
|
|
38
|
+
* App-supplied correlation tags — what the app slices its own AI spend by:
|
|
39
|
+
* feature, plan, tenant, a hashed user id. AI Gateway's cost filtering can
|
|
40
|
+
* only group by keys that were sent WITH the call, so a tag not set here is
|
|
41
|
+
* a question that cannot be asked later.
|
|
42
|
+
*
|
|
43
|
+
* Merged under the built-in fields, which win on a key collision, and
|
|
44
|
+
* trimmed to AI Gateway's {@link AI_GATEWAY_METADATA_MAX_KEYS}-key limit —
|
|
45
|
+
* over it, the gateway rejects the metadata outright and the correlation is
|
|
46
|
+
* lost rather than truncated.
|
|
47
|
+
*
|
|
48
|
+
* Values should stay low-cardinality for the same reason a route label
|
|
49
|
+
* does: a raw user id per call makes every call its own group. Hash it.
|
|
50
|
+
*/
|
|
51
|
+
tags?: Record<string, string>;
|
|
52
|
+
/** The 32-hex trace id the call belongs to, so the gateway log joins the trace. */
|
|
53
|
+
traceId?: string;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* The resolved AI Gateway coordinates.
|
|
57
|
+
*
|
|
58
|
+
* `gatewayId`/`accountId` drive the Workers AI provider's native `gateway` option
|
|
59
|
+
* (Cloudflare routes the binding call internally). `baseURL` + `headers` are for
|
|
60
|
+
* bring-your-own AI SDK providers (`@ai-sdk/openai`, …): append the provider
|
|
61
|
+
* slug to `baseURL` and spread `headers` into the provider config, e.g.
|
|
62
|
+
*
|
|
63
|
+
* ```ts
|
|
64
|
+
* const gw = resolveAiGateway(env);
|
|
65
|
+
* const openai = createOpenAI(gw ? { baseURL: `${gw.baseURL}/openai`, headers: gw.headers } : {});
|
|
66
|
+
* ```
|
|
67
|
+
* @experimental
|
|
68
|
+
*/
|
|
69
|
+
interface ResolvedAiGateway {
|
|
70
|
+
/** The Cloudflare account id owning the gateway. */
|
|
71
|
+
accountId: string;
|
|
72
|
+
/**
|
|
73
|
+
* The universal gateway base URL:
|
|
74
|
+
* `https://gateway.ai.cloudflare.com/v1/{account}/{gateway}`. Append the
|
|
75
|
+
* provider slug (`/openai`, `/anthropic`, `/workers-ai`, …) per provider.
|
|
76
|
+
*/
|
|
77
|
+
baseURL: string;
|
|
78
|
+
/** The gateway id (slug). */
|
|
79
|
+
gatewayId: string;
|
|
80
|
+
/**
|
|
81
|
+
* Request headers for a gateway-routed call: `cf-aig-authorization` when the
|
|
82
|
+
* gateway is authenticated, and `cf-aig-metadata` when correlation metadata
|
|
83
|
+
* was supplied. Empty object when neither applies.
|
|
84
|
+
*/
|
|
85
|
+
headers: Record<string, string>;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Env var carrying the default Workers AI **language** model id, used by
|
|
89
|
+
* `ctx.ai.model()` when it is called with no argument.
|
|
90
|
+
*
|
|
91
|
+
* This exists because `env` is the only configuration seam `ctx.ai` has. The
|
|
92
|
+
* generated shard constructs the facade as `createAi({ binding, env, metadata })`
|
|
93
|
+
* with those three fields fixed, so `LunoraAiOptions.defaultModel` — the field
|
|
94
|
+
* `model()` reads — was unreachable from an app: `ctx.ai.model()` with no
|
|
95
|
+
* argument threw, always. Reading the default off `env` puts it back in the
|
|
96
|
+
* app's hands (a wrangler `vars` entry or `.dev.vars` line) without a new
|
|
97
|
+
* constructor argument codegen would have to learn to emit.
|
|
98
|
+
*
|
|
99
|
+
* An explicit `defaultModel` option still wins — the env var is
|
|
100
|
+
* the fallback, exactly as with the gateway vars above.
|
|
101
|
+
*/
|
|
102
|
+
declare const AI_DEFAULT_MODEL_ENV = "LUNORA_AI_DEFAULT_MODEL";
|
|
103
|
+
/**
|
|
104
|
+
* Env var carrying the default Workers AI **embedding** model id, used by
|
|
105
|
+
* `ctx.ai.embeddingModel()` with no argument — and so by `defineRag`, whose
|
|
106
|
+
* `embeddingModel` is documented as optional and resolves through exactly that
|
|
107
|
+
* call. Separate from {@link AI_DEFAULT_MODEL_ENV} because a language-model id
|
|
108
|
+
* and an embedding-model id are never interchangeable.
|
|
109
|
+
*/
|
|
110
|
+
declare const AI_DEFAULT_EMBEDDING_MODEL_ENV = "LUNORA_AI_DEFAULT_EMBEDDING_MODEL";
|
|
111
|
+
/** Env var naming the Cloudflare account that owns the gateway. */
|
|
112
|
+
declare const AI_GATEWAY_ACCOUNT_ID_ENV = "LUNORA_AI_GATEWAY_ACCOUNT_ID";
|
|
113
|
+
/** Env var naming the AI Gateway id (the gateway's slug). */
|
|
114
|
+
declare const AI_GATEWAY_ID_ENV = "LUNORA_AI_GATEWAY_ID";
|
|
115
|
+
/**
|
|
116
|
+
* Env var carrying the gateway's authentication token (only for authenticated
|
|
117
|
+
* gateways).
|
|
118
|
+
*
|
|
119
|
+
* **Workers AI binding limitation.** This token is delivered only on the
|
|
120
|
+
* bring-your-own AI SDK provider path, as the `cf-aig-authorization` header (see
|
|
121
|
+
* {@link ResolvedAiGateway.headers}). The Workers AI **binding** (`ctx.ai` over
|
|
122
|
+
* `env.AI`) routes through the gateway with the account's own credentials and its
|
|
123
|
+
* native `gateway` option (Cloudflare's `GatewayOptions`: `id` / `cacheKey` /
|
|
124
|
+
* `metadata` / …) has no authorization field — so an *authenticated* gateway that
|
|
125
|
+
* requires a token cannot be reached on the binding path. Set this only for a BYO
|
|
126
|
+
* provider; for Workers AI, leave the gateway unauthenticated (or front it with a
|
|
127
|
+
* BYO provider). {@link resolveAiGateway} warns once per isolate if the token is
|
|
128
|
+
* set on the binding path.
|
|
129
|
+
*/
|
|
130
|
+
declare const AI_GATEWAY_TOKEN_ENV = "LUNORA_AI_GATEWAY_TOKEN";
|
|
131
|
+
/**
|
|
132
|
+
* Env var carrying deployment-scoped AI Gateway tags as a flat JSON object of
|
|
133
|
+
* string values, e.g. `{"app":"checkout","env":"prod"}`.
|
|
134
|
+
*
|
|
135
|
+
* Deployment-scoped because that is the dimension you cannot recover in code:
|
|
136
|
+
* AI Gateway can only filter cost by keys that were sent WITH the call, and
|
|
137
|
+
* "which environment / which app spent this" is fixed at deploy time. Per-call
|
|
138
|
+
* tags (feature, hashed user) go through {@link AiGatewayMetadata.tags}
|
|
139
|
+
* instead. A malformed value is ignored with a warning rather than failing the
|
|
140
|
+
* call — telemetry configuration must not take inference down.
|
|
141
|
+
*/
|
|
142
|
+
declare const AI_GATEWAY_TAGS_ENV = "LUNORA_AI_GATEWAY_TAGS";
|
|
143
|
+
/**
|
|
144
|
+
* Env var carrying the base URL of a self-hosted OpenAI-compatible proxy
|
|
145
|
+
* (LiteLLM, OpenRouter, your own), e.g. `https://ai-proxy.internal/v1`.
|
|
146
|
+
*
|
|
147
|
+
* When set, `ctx.ai.model("<provider>/<model>")` sends the slug unchanged as the
|
|
148
|
+
* `model` of an OpenAI chat-completions request to this URL instead of routing
|
|
149
|
+
* it through Cloudflare AI Gateway — which needs no `AI` binding, so it is how
|
|
150
|
+
* `ctx.ai` works on hosts without Workers AI (celld). `@cf/…` ids still need
|
|
151
|
+
* the binding.
|
|
152
|
+
*/
|
|
153
|
+
declare const AI_PROXY_URL_ENV = "LUNORA_AI_PROXY_URL";
|
|
154
|
+
/** Env var carrying the bearer token sent to {@link AI_PROXY_URL_ENV}, when the proxy requires one. */
|
|
155
|
+
declare const AI_PROXY_TOKEN_ENV = "LUNORA_AI_PROXY_TOKEN";
|
|
156
|
+
/**
|
|
157
|
+
* Parse {@link AI_GATEWAY_TAGS_ENV} into tag fields. Non-string values are
|
|
158
|
+
* dropped rather than coerced — a number silently becoming `"1"` is a worse
|
|
159
|
+
* outcome than the tag being absent and visibly so.
|
|
160
|
+
*/
|
|
161
|
+
declare const readAiGatewayEnvTags: (env: Record<string, unknown>) => Record<string, string> | undefined;
|
|
162
|
+
/**
|
|
163
|
+
* Resolve the Cloudflare AI Gateway coordinates from the Worker `env`, or
|
|
164
|
+
* `undefined` when the gateway is not configured (both `LUNORA_AI_GATEWAY_ACCOUNT_ID`
|
|
165
|
+
* and `LUNORA_AI_GATEWAY_ID` must be present). Opt-in and backward-compatible:
|
|
166
|
+
* an unconfigured app gets `undefined` and every caller keeps its direct-provider
|
|
167
|
+
* behavior.
|
|
168
|
+
*
|
|
169
|
+
* Pass optional {@link AiGatewayMetadata} to fold a `cf-aig-metadata` correlation
|
|
170
|
+
* header into `headers` — only its defined fields are sent.
|
|
171
|
+
*
|
|
172
|
+
* `consumer` names the surface resolving the gateway (default `"byo-provider"`).
|
|
173
|
+
* When it is `"workers-ai-binding"` and an {@link AI_GATEWAY_TOKEN_ENV} token is
|
|
174
|
+
* configured, this warns once per isolate: the binding path cannot carry the
|
|
175
|
+
* token (see {@link AI_GATEWAY_TOKEN_ENV}), so it would otherwise be dropped with
|
|
176
|
+
* no diagnostic and every `ctx.ai.model(...)` call would fail against an
|
|
177
|
+
* authenticated gateway while the token var reads as "configured".
|
|
178
|
+
* @experimental
|
|
179
|
+
*/
|
|
180
|
+
declare const resolveAiGateway: (env: Record<string, unknown>, metadata?: AiGatewayMetadata, consumer?: AiGatewayConsumer) => ResolvedAiGateway | undefined;
|
|
181
|
+
/**
|
|
182
|
+
* Structural projection of the Cloudflare Workers `AI` binding (`env.AI`).
|
|
183
|
+
* Declared locally so unit tests can pass a plain-object double and the real
|
|
184
|
+
* binding satisfies the same shape without importing `@cloudflare/workers-types`
|
|
185
|
+
* into the public surface. Mirrors the `run` method documented at
|
|
186
|
+
* https://developers.cloudflare.com/workers-ai/.
|
|
187
|
+
* @experimental
|
|
188
|
+
*/
|
|
189
|
+
interface AiBindingLike {
|
|
190
|
+
run: (model: string, inputs: Record<string, unknown>, options?: Record<string, unknown>) => Promise<unknown>;
|
|
191
|
+
/**
|
|
192
|
+
* Web Search API (beta). Optional because runtimes and test doubles that
|
|
193
|
+
* predate it have no such method; `ctx.ai.websearch` reports that instead of
|
|
194
|
+
* a bare `TypeError`.
|
|
195
|
+
*/
|
|
196
|
+
websearch?: (input: Omit<AiWebSearchOptions, "gatewayId"> & {
|
|
197
|
+
gatewayId: string;
|
|
198
|
+
query: string;
|
|
199
|
+
}) => Promise<Response>;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* A Workers AI provider instance — the value returned by `createWorkersAI(...)`.
|
|
203
|
+
* Calling it with a model id yields an AI SDK {@link LanguageModel}; the
|
|
204
|
+
* optional `textEmbeddingModel` factory yields an {@link EmbeddingModel}.
|
|
205
|
+
* Typed structurally so `@lunora/ai` neither re-declares the provider's full
|
|
206
|
+
* surface nor hard-pins its exact type across minor releases.
|
|
207
|
+
* @experimental
|
|
208
|
+
*/
|
|
209
|
+
interface WorkersAiProviderLike {
|
|
210
|
+
(modelId: string, settings?: Record<string, unknown>): LanguageModel;
|
|
211
|
+
textEmbeddingModel?: (modelId: string) => EmbeddingModel;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* AI Gateway options forwarded to `createWorkersAI`. Lets inference route
|
|
215
|
+
* through a Cloudflare AI Gateway for caching, rate-limiting, and observability.
|
|
216
|
+
* @experimental
|
|
217
|
+
*/
|
|
218
|
+
interface AiGatewayOptions {
|
|
219
|
+
[key: string]: unknown;
|
|
220
|
+
id: string;
|
|
221
|
+
/**
|
|
222
|
+
* Custom correlation metadata surfaced in the AI Gateway logs (Cloudflare's
|
|
223
|
+
* native `gateway.metadata`). `@lunora/ai` folds `{ functionPath, traceId }`
|
|
224
|
+
* here from {@link LunoraAiOptions.metadata} when a gateway is configured.
|
|
225
|
+
*/
|
|
226
|
+
metadata?: Record<string, string>;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Options for the raw `ctx.ai.run(...)` passthrough — the Workers AI binding's
|
|
230
|
+
* third argument. Unlisted keys are forwarded to the binding unchanged.
|
|
231
|
+
* @experimental
|
|
232
|
+
*/
|
|
233
|
+
interface AiRunOptions {
|
|
234
|
+
[key: string]: unknown;
|
|
235
|
+
/** Route this call through a Cloudflare AI Gateway. Defaults to the gateway `createAi` resolved. */
|
|
236
|
+
gateway?: AiGatewayOptions;
|
|
237
|
+
/**
|
|
238
|
+
* Fail at once instead of waiting in the Workers AI capacity queue when no
|
|
239
|
+
* capacity is free. The rejection surfaces as a `LunoraError` with code
|
|
240
|
+
* `RATE_LIMITED` (Workers AI error `3040`, HTTP 429).
|
|
241
|
+
*/
|
|
242
|
+
rejectIfBusy?: boolean;
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Per-call settings for `ctx.ai.model(...)`. Applied to Workers AI model ids
|
|
246
|
+
* (`@cf/…`) only; a gateway slug or a bring-your-own model ignores them.
|
|
247
|
+
* @experimental
|
|
248
|
+
*/
|
|
249
|
+
interface AiModelOptions {
|
|
250
|
+
/**
|
|
251
|
+
* Fail at once instead of waiting in the Workers AI capacity queue. The
|
|
252
|
+
* provider reports the rejection as an AI SDK `APICallError` with
|
|
253
|
+
* `statusCode: 429`, which the AI SDK retries unless the call sets
|
|
254
|
+
* `maxRetries: 0`.
|
|
255
|
+
*/
|
|
256
|
+
rejectIfBusy?: boolean;
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Structural slice of the span handle `ctx.trace` hands its body — enough to
|
|
260
|
+
* attach a model call's usage once it is known. Declared here rather than
|
|
261
|
+
* imported so `@lunora/ai` takes no dependency on `@lunora/server`; the real
|
|
262
|
+
* handle is assignable to it.
|
|
263
|
+
* @experimental
|
|
264
|
+
*/
|
|
265
|
+
interface AiSpan {
|
|
266
|
+
setAttribute: (key: string, value: unknown) => void;
|
|
267
|
+
setAttributes: (fields: Record<string, unknown>) => void;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Structural slice of `ctx.trace` (the server `LunoraTracer`): runs `function_`
|
|
271
|
+
* inside a named span and hands it the span's {@link AiSpan}.
|
|
272
|
+
* @experimental
|
|
273
|
+
*/
|
|
274
|
+
type AiTracer = <T>(name: string, function_: (trace: AiTracer, span: AiSpan) => Promise<T> | T, attributes?: Record<string, unknown>) => Promise<T>;
|
|
275
|
+
/**
|
|
276
|
+
* Structural slice of `ctx.metrics` (the server `LunoraMetrics`) — only the
|
|
277
|
+
* counter, which is what usage accounting needs.
|
|
278
|
+
* @experimental
|
|
279
|
+
*/
|
|
280
|
+
interface AiMetrics {
|
|
281
|
+
count: (name: string, value?: number, attributes?: Record<string, unknown>) => void;
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Where `ctx.ai` reports model usage. The generated `ctx.ai` passes the
|
|
285
|
+
* function's own `ctx.trace` / `ctx.metrics`, so every call made through
|
|
286
|
+
* `ctx.ai.model(...)` gets an `ai.generate` / `ai.stream` span and
|
|
287
|
+
* `gen_ai.usage.input_tokens` / `gen_ai.usage.output_tokens` /
|
|
288
|
+
* `gen_ai.usage.cost` counters attributed to that function.
|
|
289
|
+
* @experimental
|
|
290
|
+
*/
|
|
291
|
+
interface AiTelemetry {
|
|
292
|
+
metrics?: AiMetrics;
|
|
293
|
+
trace?: AiTracer;
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* `LunoraAiOptions` is part of the experimental `@lunora/ai` API and may change without a major version bump.
|
|
297
|
+
* @experimental
|
|
298
|
+
*/
|
|
299
|
+
interface LunoraAiOptions {
|
|
300
|
+
/**
|
|
301
|
+
* The Workers `AI` binding (`env.AI`). Required for the zero-config Workers
|
|
302
|
+
* AI default and for the raw `ai.run(...)` passthrough. May be omitted when
|
|
303
|
+
* a pre-built `provider` is supplied (e.g. in tests or a custom setup).
|
|
304
|
+
*/
|
|
305
|
+
binding?: AiBindingLike;
|
|
306
|
+
/**
|
|
307
|
+
* Default Workers AI **embedding** model id used by `embeddingModel()` when no
|
|
308
|
+
* explicit model is passed (e.g. `@cf/baai/bge-base-en-v1.5`). Kept separate
|
|
309
|
+
* from `defaultModel` because a language-model id and an embedding-model
|
|
310
|
+
* id belong to different Workers AI families and are never interchangeable —
|
|
311
|
+
* reusing the language-model default here would defer a wrong-family error to
|
|
312
|
+
* inference time. Has no effect on bring-your-own providers.
|
|
313
|
+
*
|
|
314
|
+
* Falls back to `LUNORA_AI_DEFAULT_EMBEDDING_MODEL` in {@link LunoraAiOptions.env}
|
|
315
|
+
* — which is how an app sets it, since the generated `ctx.ai` is constructed
|
|
316
|
+
* with a fixed `{ binding, env, metadata }`.
|
|
317
|
+
*/
|
|
318
|
+
defaultEmbeddingModel?: string;
|
|
319
|
+
/**
|
|
320
|
+
* Default Workers AI **language** model id used by `model()` when no explicit
|
|
321
|
+
* model is passed. For embeddings, set `defaultEmbeddingModel` instead.
|
|
322
|
+
* Has no effect on bring-your-own providers.
|
|
323
|
+
*
|
|
324
|
+
* Falls back to `LUNORA_AI_DEFAULT_MODEL` in {@link LunoraAiOptions.env} — the
|
|
325
|
+
* seam a Lunora app actually has (see `defaultEmbeddingModel`).
|
|
326
|
+
*/
|
|
327
|
+
defaultModel?: string;
|
|
328
|
+
/**
|
|
329
|
+
* The Worker `env`, read for opt-in Cloudflare AI Gateway routing (the
|
|
330
|
+
* `LUNORA_AI_GATEWAY_*` vars, via `resolveAiGateway`) and for the default
|
|
331
|
+
* model ids (`LUNORA_AI_DEFAULT_MODEL` / `LUNORA_AI_DEFAULT_EMBEDDING_MODEL`).
|
|
332
|
+
* When it configures a gateway and no explicit {@link LunoraAiOptions.gateway}
|
|
333
|
+
* is given, the Workers AI provider is routed through that gateway so token +
|
|
334
|
+
* dollar-cost telemetry is computed on the app's behalf. Unset, or with no
|
|
335
|
+
* gateway vars, behavior is unchanged (calls go straight to Workers AI).
|
|
336
|
+
*/
|
|
337
|
+
env?: Record<string, unknown>;
|
|
338
|
+
/**
|
|
339
|
+
* Route Workers AI inference through a Cloudflare AI Gateway. An explicit
|
|
340
|
+
* value wins over anything derived from {@link LunoraAiOptions.env}.
|
|
341
|
+
*/
|
|
342
|
+
gateway?: AiGatewayOptions;
|
|
343
|
+
/**
|
|
344
|
+
* Correlation metadata folded into the active gateway call (the Workers AI
|
|
345
|
+
* binding's native `gateway.metadata`) so an AI Gateway log entry ties back
|
|
346
|
+
* to the Lunora function + trace that made it. Only applied when a gateway is
|
|
347
|
+
* actually configured (explicit or env-derived) and only its defined fields
|
|
348
|
+
* are sent — absent otherwise, so behavior is unchanged. The generated
|
|
349
|
+
* `ctx.ai` facade threads `{ functionPath, traceId }` here automatically.
|
|
350
|
+
*/
|
|
351
|
+
metadata?: AiGatewayMetadata;
|
|
352
|
+
/**
|
|
353
|
+
* Pre-built Workers AI provider. When omitted, one is constructed from
|
|
354
|
+
* `binding` via `createWorkersAI`. Supplying it directly is the seam used by
|
|
355
|
+
* tests and advanced setups; it also lets callers configure the provider
|
|
356
|
+
* (e.g. `safePrompt`) before handing it to `@lunora/ai`.
|
|
357
|
+
*/
|
|
358
|
+
provider?: WorkersAiProviderLike;
|
|
359
|
+
/**
|
|
360
|
+
* Record every language-model call resolved by `model()` — a span plus
|
|
361
|
+
* token and cost counters (see {@link AiTelemetry}). Omitted, models are
|
|
362
|
+
* returned unwrapped.
|
|
363
|
+
*/
|
|
364
|
+
telemetry?: AiTelemetry;
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* A search provider the Web Search API brokers. Each one runs under Cloudflare's
|
|
368
|
+
* Zero Data Retention terms. A search bills a provider key stored on the gateway
|
|
369
|
+
* when there is one (the `default` alias unless `byokAlias` names another),
|
|
370
|
+
* otherwise AI Gateway credits at list price.
|
|
371
|
+
* @experimental
|
|
372
|
+
*/
|
|
373
|
+
type AiWebSearchProvider = "ceramic" | "exa" | "linkup";
|
|
374
|
+
/**
|
|
375
|
+
* Options for `ctx.ai.websearch(...)`.
|
|
376
|
+
* @experimental
|
|
377
|
+
*/
|
|
378
|
+
interface AiWebSearchOptions {
|
|
379
|
+
/** Alias of a provider key stored on the gateway to bill instead of the `default` alias. Without a stored key, gateway credits pay. */
|
|
380
|
+
byokAlias?: string;
|
|
381
|
+
/**
|
|
382
|
+
* The AI Gateway that brokers and bills the search. Defaults to the gateway
|
|
383
|
+
* `ctx.ai` routes inference through (`LUNORA_AI_GATEWAY_ID`), else the
|
|
384
|
+
* account's `default` gateway.
|
|
385
|
+
*/
|
|
386
|
+
gatewayId?: string;
|
|
387
|
+
/** Maximum results, 1–10. Defaults to 10. */
|
|
388
|
+
limit?: number;
|
|
389
|
+
/** Defaults to `"ceramic"`. */
|
|
390
|
+
provider?: AiWebSearchProvider;
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* One result. Web search is discovery only: a result describes a page, and
|
|
394
|
+
* reading the page is a separate `fetch` of its `url`. The optional fields are
|
|
395
|
+
* present only when the provider returns them.
|
|
396
|
+
* @experimental
|
|
397
|
+
*/
|
|
398
|
+
interface AiWebSearchItem {
|
|
399
|
+
description?: string;
|
|
400
|
+
faviconUrl?: string;
|
|
401
|
+
imageUrl?: string;
|
|
402
|
+
/** Naive (no timezone) ISO-8601 datetime, e.g. `"2025-11-30T04:39:48"`. */
|
|
403
|
+
lastModifiedDate?: string;
|
|
404
|
+
title: string;
|
|
405
|
+
url: string;
|
|
406
|
+
}
|
|
407
|
+
/**
|
|
408
|
+
* What `ctx.ai.websearch(...)` resolves to.
|
|
409
|
+
* @experimental
|
|
410
|
+
*/
|
|
411
|
+
interface AiWebSearchResult {
|
|
412
|
+
items: AiWebSearchItem[];
|
|
413
|
+
metadata: {
|
|
414
|
+
latencyMs: number;
|
|
415
|
+
query: string;
|
|
416
|
+
requestId: string;
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
/**
|
|
420
|
+
* A model to run against. The AI SDK's {@link LanguageModel} already admits a
|
|
421
|
+
* bare `string`, so this alias covers both arms of the provider-agnostic seam:
|
|
422
|
+
* a string id is resolved by `ctx.ai.model` — a Workers AI id (`@cf/…`), a
|
|
423
|
+
* `"<provider>/<model>"` slug (`anthropic/claude-sonnet-5`, `openai/gpt-5`, …)
|
|
424
|
+
* routed through Cloudflare AI Gateway, or a gateway dynamic route
|
|
425
|
+
* (`dynamic/<route>`); a built model object is bring-your-own (`@ai-sdk/openai`,
|
|
426
|
+
* `@ai-sdk/anthropic`, `@ai-sdk/google`, OpenRouter, …).
|
|
427
|
+
* @experimental
|
|
428
|
+
*/
|
|
429
|
+
type ModelInput = LanguageModel;
|
|
430
|
+
/**
|
|
431
|
+
* Likewise for embeddings: a Workers AI embedding model id (e.g.
|
|
432
|
+
* `@cf/baai/bge-base-en-v1.5`) or any AI SDK {@link EmbeddingModel}.
|
|
433
|
+
* @experimental
|
|
434
|
+
*/
|
|
435
|
+
type EmbeddingModelInput = EmbeddingModel | string;
|
|
436
|
+
/**
|
|
437
|
+
* The `ctx.ai` surface. `model`/`embeddingModel` resolve a Workers AI model from
|
|
438
|
+
* a string (the default provider) and pass any non-string model straight through,
|
|
439
|
+
* so both accept Workers AI and bring-your-own providers. Feed the resolved model
|
|
440
|
+
* to the AI SDK functions re-exported from `@lunora/ai` (`generateText`,
|
|
441
|
+
* `streamText`, `generateObject`, `embed`, …); `run` is the raw binding escape
|
|
442
|
+
* hatch, and `workersai` is the underlying provider for direct model access.
|
|
443
|
+
* @experimental
|
|
444
|
+
*/
|
|
445
|
+
interface LunoraAi {
|
|
446
|
+
/** Resolve an {@link EmbeddingModel}: a string → Workers AI, an object → passthrough. */
|
|
447
|
+
embeddingModel: (model?: EmbeddingModelInput) => EmbeddingModel;
|
|
448
|
+
/**
|
|
449
|
+
* Resolve a {@link LanguageModel}: a `@cf/…` id → Workers AI, a
|
|
450
|
+
* `"<provider>/<model>"` slug or `dynamic/<route>` → Cloudflare AI Gateway
|
|
451
|
+
* over the same binding (Unified Billing or the gateway's stored keys — no
|
|
452
|
+
* provider key in the app) or, with `LUNORA_AI_PROXY_URL` set, to that
|
|
453
|
+
* OpenAI-compatible proxy; an object → passthrough.
|
|
454
|
+
*/
|
|
455
|
+
model: (model?: ModelInput, options?: AiModelOptions) => LanguageModel;
|
|
456
|
+
/**
|
|
457
|
+
* Raw Workers AI binding passthrough (void-style `ai.run`). Bypasses the AI
|
|
458
|
+
* SDK entirely — useful for Workers-AI-only model families (image, ASR,
|
|
459
|
+
* translation) not surfaced through the provider. Throws if no binding was
|
|
460
|
+
* supplied.
|
|
461
|
+
*/
|
|
462
|
+
run: (model: string, inputs: Record<string, unknown>, options?: AiRunOptions) => Promise<unknown>;
|
|
463
|
+
/**
|
|
464
|
+
* Search the web through the binding's Web Search API (beta) to ground a
|
|
465
|
+
* response in live information. Billed to a stored provider key or AI Gateway
|
|
466
|
+
* credits (see {@link AiWebSearchProvider}). Throws if no
|
|
467
|
+
* binding was supplied, or if the runtime's binding has no `websearch()`.
|
|
468
|
+
*/
|
|
469
|
+
websearch: (query: string, options?: AiWebSearchOptions) => Promise<AiWebSearchResult>;
|
|
470
|
+
/** The underlying Workers AI provider — `ai.workersai("@cf/...")` for a raw model. */
|
|
471
|
+
workersai: WorkersAiProviderLike;
|
|
472
|
+
}
|
|
473
|
+
export { AI_DEFAULT_EMBEDDING_MODEL_ENV as A, EmbeddingModelInput as E, LunoraAiOptions as L, ModelInput as M, ResolvedAiGateway as R, WorkersAiProviderLike as W, LunoraAi as a, AI_DEFAULT_MODEL_ENV as b, AI_GATEWAY_ACCOUNT_ID_ENV as c, AI_GATEWAY_ID_ENV as d, AI_GATEWAY_METADATA_MAX_KEYS as e, AI_GATEWAY_TAGS_ENV as f, AI_GATEWAY_TOKEN_ENV as g, AI_PROXY_TOKEN_ENV as h, AI_PROXY_URL_ENV as i, AiBindingLike as j, AiGatewayMetadata as k, AiGatewayOptions as l, AiMetrics as m, AiModelOptions as n, AiRunOptions as o, AiSpan as p, AiTelemetry as q, AiTracer as r, AiWebSearchItem as s, AiWebSearchOptions as t, AiWebSearchProvider as u, AiWebSearchResult as v, buildAiGatewayMetadataFields as w, readAiGatewayEnvTags as x, resolveAiGateway as y };
|