aieo 0.1.41 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +35833 -15174
- package/dist/index.js.map +1 -1
- package/package.json +16 -10
- package/dist/index.cjs +0 -24747
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -846
package/dist/index.d.cts
DELETED
|
@@ -1,846 +0,0 @@
|
|
|
1
|
-
import { ModelMessage, LanguageModel, ToolSet } from 'ai';
|
|
2
|
-
export { ModelMessage, Tool, ToolSet } from 'ai';
|
|
3
|
-
import { AnthropicProviderOptions } from '@ai-sdk/anthropic';
|
|
4
|
-
|
|
5
|
-
interface Conversation {
|
|
6
|
-
id: string;
|
|
7
|
-
summary: string;
|
|
8
|
-
timestamp: number;
|
|
9
|
-
}
|
|
10
|
-
interface ConversationData {
|
|
11
|
-
id: string;
|
|
12
|
-
summary: string;
|
|
13
|
-
messages: ModelMessage[];
|
|
14
|
-
lastUpdated: number;
|
|
15
|
-
}
|
|
16
|
-
declare const MAX_CONVERSATIONS = 100;
|
|
17
|
-
declare abstract class ConversationStorage {
|
|
18
|
-
abstract currentConversationId(): Promise<string>;
|
|
19
|
-
abstract selectConversation(conversationId: string): Promise<void>;
|
|
20
|
-
abstract listConversations(): Promise<Conversation[]>;
|
|
21
|
-
abstract getConversation(conversationId: string): Promise<ConversationData | null>;
|
|
22
|
-
abstract storeConversationData(conversationId: string, data: ConversationData): Promise<void>;
|
|
23
|
-
abstract deleteConversationData(conversationId: string): Promise<boolean>;
|
|
24
|
-
createConversation(messages: ModelMessage[]): Promise<ConversationData>;
|
|
25
|
-
addMessageToConversation(conversationId: string, message: ModelMessage): Promise<ConversationData>;
|
|
26
|
-
getCurrentConversation(): Promise<ConversationData | null>;
|
|
27
|
-
getLatestConversation(): Promise<ConversationData | null>;
|
|
28
|
-
updateConversationSummary(conversationId: string, summary: string): Promise<ConversationData>;
|
|
29
|
-
private pruneOldConversations;
|
|
30
|
-
protected generateSummary(content: string): string;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
interface Logger {
|
|
34
|
-
info(message: string): void;
|
|
35
|
-
error(message: string): void;
|
|
36
|
-
warn?(message: string): void;
|
|
37
|
-
debug?(message: string): void;
|
|
38
|
-
trace?(message: string): void;
|
|
39
|
-
fatal?(message: string): void;
|
|
40
|
-
}
|
|
41
|
-
declare function consoleLogger(name: string): Logger;
|
|
42
|
-
|
|
43
|
-
type Provider = "anthropic" | "google" | "openai" | "openrouter" | "xai";
|
|
44
|
-
/**
|
|
45
|
-
* Per-provider path Bifrost (and compatible gateways) expose for each
|
|
46
|
-
* provider's drop-in SDK. Exported so spawners can build per-provider
|
|
47
|
-
* URLs without hand-rolling the suffix.
|
|
48
|
-
*
|
|
49
|
-
* NOTE: OpenRouter has no dedicated Bifrost route and rides the OpenAI
|
|
50
|
-
* path (model id prefixed `openrouter/` in getModel so Bifrost routes it
|
|
51
|
-
* upstream). If you spawn an agent in a way where the runtime would
|
|
52
|
-
* override the model to an OpenRouter model, you want the OpenAI suffix
|
|
53
|
-
* here too. xAI likewise rides the OpenAI-compat path (model id prefixed
|
|
54
|
-
* `xai/` in getModel), since Bifrost has no dedicated Grok route.
|
|
55
|
-
*/
|
|
56
|
-
declare const GATEWAY_PATHS: Record<Provider, string>;
|
|
57
|
-
declare function getGatewayBaseURL(provider: Provider): string | undefined;
|
|
58
|
-
/**
|
|
59
|
-
* Build the fully-formed `<base>/<provider-path>` URL that an official
|
|
60
|
-
* SDK (or Goose, or a workflow LLM node) expects.
|
|
61
|
-
*
|
|
62
|
-
* This is the single source of truth for "which suffix do I add to the
|
|
63
|
-
* gateway root for this provider." Spawners (Hive, Stakwork, anyone
|
|
64
|
-
* launching an agent) should call this when stamping `ANTHROPIC_BASE_URL`,
|
|
65
|
-
* `OPENAI_BASE_URL`, `GOOGLE_BASE_URL`, etc. on a child process or
|
|
66
|
-
* workflow context.
|
|
67
|
-
*
|
|
68
|
-
* Behavior:
|
|
69
|
-
* - Trims a trailing slash.
|
|
70
|
-
* - Returns the URL unchanged if it already ends with the provider's
|
|
71
|
-
* gateway path (`/anthropic/v1`, `/openai/v1`, `/genai/v1beta`), so
|
|
72
|
-
* the function is idempotent.
|
|
73
|
-
* - Returns the URL unchanged if it already targets a provider/version
|
|
74
|
-
* path (e.g. `.../v1`, `.../v1beta`, `.../anthropic/...`). This lets
|
|
75
|
-
* callers pass fully-qualified URLs through without surprise.
|
|
76
|
-
* - Otherwise appends `GATEWAY_PATHS[provider]`.
|
|
77
|
-
*
|
|
78
|
-
* Examples
|
|
79
|
-
* --------
|
|
80
|
-
* gatewayUrlFor("anthropic", "https://swarm38.sphinx.chat:8181")
|
|
81
|
-
* => "https://swarm38.sphinx.chat:8181/anthropic/v1"
|
|
82
|
-
*
|
|
83
|
-
* gatewayUrlFor("openai", "https://swarm38.sphinx.chat:8181/")
|
|
84
|
-
* => "https://swarm38.sphinx.chat:8181/openai/v1"
|
|
85
|
-
*
|
|
86
|
-
* gatewayUrlFor("anthropic", "https://swarm38.sphinx.chat:8181/anthropic/v1")
|
|
87
|
-
* => "https://swarm38.sphinx.chat:8181/anthropic/v1" (idempotent)
|
|
88
|
-
*
|
|
89
|
-
* gatewayUrlFor("openai", "https://api.openai.com/v1")
|
|
90
|
-
* => "https://api.openai.com/v1" (left alone)
|
|
91
|
-
*/
|
|
92
|
-
declare function gatewayUrlFor(provider: Provider, baseUrl: string): string;
|
|
93
|
-
/**
|
|
94
|
-
* Like {@link gatewayUrlFor} but takes a model name (shortcut like
|
|
95
|
-
* `"sonnet"`, namespaced like `"anthropic/claude-sonnet-5"`, or a full
|
|
96
|
-
* model id like `"claude-sonnet-5"`) and resolves the provider for you.
|
|
97
|
-
*
|
|
98
|
-
* Convenient for spawners that have a model name in hand but not a
|
|
99
|
-
* provider — e.g. Hive picking up a user's chosen model and needing to
|
|
100
|
-
* tell the agent which Bifrost route to use.
|
|
101
|
-
*/
|
|
102
|
-
declare function gatewayUrlForModel(modelName: string | undefined, baseUrl: string): string;
|
|
103
|
-
/**
|
|
104
|
-
* Build a `{ ANTHROPIC_BASE_URL, OPENAI_BASE_URL, GOOGLE_BASE_URL }`-style
|
|
105
|
-
* env map for spawning agents (Goose, Python, raw SDK callers) that
|
|
106
|
-
* don't normalize the URL themselves. Pass the gateway root once; get
|
|
107
|
-
* back the per-provider URLs.
|
|
108
|
-
*
|
|
109
|
-
* The keys match the env var names the official SDKs read by default:
|
|
110
|
-
* - `ANTHROPIC_BASE_URL` (anthropic-sdk-{ts,python,go})
|
|
111
|
-
* - `OPENAI_BASE_URL` (openai SDK)
|
|
112
|
-
* - `GOOGLE_GENERATIVE_AI_BASE_URL` (google-genai SDK / `@ai-sdk/google`)
|
|
113
|
-
*
|
|
114
|
-
* Spawners can spread the result into the child's env. Callers that
|
|
115
|
-
* only need one provider should use {@link gatewayUrlFor} directly.
|
|
116
|
-
*/
|
|
117
|
-
declare function gatewayEnvForProviders(baseUrl: string): {
|
|
118
|
-
ANTHROPIC_BASE_URL: string;
|
|
119
|
-
OPENAI_BASE_URL: string;
|
|
120
|
-
GOOGLE_GENERATIVE_AI_BASE_URL: string;
|
|
121
|
-
};
|
|
122
|
-
/**
|
|
123
|
-
* @deprecated Use {@link gatewayUrlFor}. Kept as an alias for internal
|
|
124
|
-
* call sites; both have identical behavior.
|
|
125
|
-
*/
|
|
126
|
-
declare const normalizeCallerBaseURL: typeof gatewayUrlFor;
|
|
127
|
-
declare const PROVIDERS: Provider[];
|
|
128
|
-
type ModelName = "sonnet" | "opus" | "haiku" | "gemini" | "gpt" | "kimi" | "glm" | "grok";
|
|
129
|
-
type ModelId = string;
|
|
130
|
-
declare const MODELS: Record<Provider, Partial<Record<ModelName, ModelId>>>;
|
|
131
|
-
declare const DEFAULT_MODELS: Record<Provider, string>;
|
|
132
|
-
declare function getLightModelForProvider(provider: Provider): string;
|
|
133
|
-
interface TokenPricing {
|
|
134
|
-
inputTokenPrice: number;
|
|
135
|
-
outputTokenPrice: number;
|
|
136
|
-
cacheReadPrice?: number;
|
|
137
|
-
cacheWritePrice?: number;
|
|
138
|
-
}
|
|
139
|
-
interface TokenUsageForCost {
|
|
140
|
-
input: number;
|
|
141
|
-
cache_read: number;
|
|
142
|
-
cache_write: number;
|
|
143
|
-
output: number;
|
|
144
|
-
}
|
|
145
|
-
declare function computeSessionCost(provider: Provider, usage: TokenUsageForCost, modelId?: string, actualCost?: number): number;
|
|
146
|
-
declare function getProviderForModel(modelName?: ModelName | string): Provider;
|
|
147
|
-
/**
|
|
148
|
-
* Treat blank/whitespace-only keys as absent.
|
|
149
|
-
*
|
|
150
|
-
* A truthy-but-blank key (a request body with `apiKey: " "`, an env var set to
|
|
151
|
-
* an empty-ish value) otherwise sails past every `!!key` check and reaches the
|
|
152
|
-
* provider SDK, which happily builds `Authorization: Bearer ` and gets a
|
|
153
|
-
* confusing 401 ("Missing Authentication header" from OpenRouter) on every
|
|
154
|
-
* single call instead of failing fast. Also trims stray whitespace so a key
|
|
155
|
-
* pasted with a trailing space still authenticates.
|
|
156
|
-
*/
|
|
157
|
-
declare function normalizeApiKey(key?: string | null): string | undefined;
|
|
158
|
-
/**
|
|
159
|
-
* The env var each provider's API key is read from. Exported so a host with
|
|
160
|
-
* its own secret store knows which NAME to look up (see resolve.ts).
|
|
161
|
-
*/
|
|
162
|
-
declare const API_KEY_ENV: Record<Provider, string>;
|
|
163
|
-
declare function hasApiKeyForProvider(provider: Provider | string): boolean;
|
|
164
|
-
declare function getApiKeyForProvider(provider: Provider | string): string;
|
|
165
|
-
interface GetModelOptions {
|
|
166
|
-
apiKey?: string;
|
|
167
|
-
baseUrl?: string;
|
|
168
|
-
modelName?: ModelName | string;
|
|
169
|
-
cwd?: string;
|
|
170
|
-
executablePath?: string;
|
|
171
|
-
logger?: Logger;
|
|
172
|
-
/**
|
|
173
|
-
* Custom HTTP headers to attach to every request the provider client makes
|
|
174
|
-
* to the LLM endpoint. Useful for gateway auth, tenant IDs, etc.
|
|
175
|
-
*/
|
|
176
|
-
headers?: Record<string, string>;
|
|
177
|
-
/**
|
|
178
|
-
* AbortSignal from the run's AbortController. When fired (busy timeout /
|
|
179
|
-
* `/repo/agent/abort`), in-flight model calls and streams are cancelled.
|
|
180
|
-
* Stays armed for the entire request/stream lifetime.
|
|
181
|
-
*/
|
|
182
|
-
abortSignal?: AbortSignal;
|
|
183
|
-
/**
|
|
184
|
-
* Per-request timeout in milliseconds for the connect / first-response
|
|
185
|
-
* phase only. Once the provider replies with headers the timer is disarmed,
|
|
186
|
-
* so a slow-but-progressing stream is never killed. Defaults to the
|
|
187
|
-
* `LLM_HTTP_TIMEOUT_MS` env var when not supplied.
|
|
188
|
-
*/
|
|
189
|
-
timeoutMs?: number;
|
|
190
|
-
}
|
|
191
|
-
interface ModelDetails {
|
|
192
|
-
provider: Provider;
|
|
193
|
-
apiKey: string;
|
|
194
|
-
model: LanguageModel;
|
|
195
|
-
modelId: string;
|
|
196
|
-
contextLimit: number;
|
|
197
|
-
}
|
|
198
|
-
declare function getModelDetails(modelName?: ModelName | string, apiKeyIn?: string, baseUrl?: string, headers?: Record<string, string>, abortSignal?: AbortSignal, timeoutMs?: number): ModelDetails;
|
|
199
|
-
declare function getModel(provider: Provider, opts?: string | GetModelOptions): LanguageModel;
|
|
200
|
-
/**
|
|
201
|
-
* Get the context window size (max input tokens) for a given model.
|
|
202
|
-
*/
|
|
203
|
-
declare function getContextLimit(modelId: string, provider: Provider): number;
|
|
204
|
-
declare function getTokenPricing(provider: Provider): TokenPricing;
|
|
205
|
-
declare function loadModelPricing(): Promise<void>;
|
|
206
|
-
type ThinkingSpeed = "thinking" | "fast";
|
|
207
|
-
declare function getProviderOptions(provider: Provider, thinkingSpeed?: ThinkingSpeed, modelName?: string): {
|
|
208
|
-
anthropic: AnthropicProviderOptions;
|
|
209
|
-
google?: undefined;
|
|
210
|
-
openai?: undefined;
|
|
211
|
-
openrouter?: undefined;
|
|
212
|
-
xai?: undefined;
|
|
213
|
-
} | {
|
|
214
|
-
google: {
|
|
215
|
-
thinkingConfig: {
|
|
216
|
-
thinkingBudget: number;
|
|
217
|
-
};
|
|
218
|
-
};
|
|
219
|
-
anthropic?: undefined;
|
|
220
|
-
openai?: undefined;
|
|
221
|
-
openrouter?: undefined;
|
|
222
|
-
xai?: undefined;
|
|
223
|
-
} | {
|
|
224
|
-
openai: {};
|
|
225
|
-
anthropic?: undefined;
|
|
226
|
-
google?: undefined;
|
|
227
|
-
openrouter?: undefined;
|
|
228
|
-
xai?: undefined;
|
|
229
|
-
} | {
|
|
230
|
-
openrouter: {
|
|
231
|
-
usage: {
|
|
232
|
-
include: true;
|
|
233
|
-
};
|
|
234
|
-
};
|
|
235
|
-
anthropic?: undefined;
|
|
236
|
-
google?: undefined;
|
|
237
|
-
openai?: undefined;
|
|
238
|
-
xai?: undefined;
|
|
239
|
-
} | {
|
|
240
|
-
xai: {};
|
|
241
|
-
anthropic?: undefined;
|
|
242
|
-
google?: undefined;
|
|
243
|
-
openai?: undefined;
|
|
244
|
-
openrouter?: undefined;
|
|
245
|
-
};
|
|
246
|
-
interface LLMConfig {
|
|
247
|
-
provider: Provider;
|
|
248
|
-
apiKey: string;
|
|
249
|
-
model: LanguageModel;
|
|
250
|
-
modelName?: string;
|
|
251
|
-
}
|
|
252
|
-
/**
|
|
253
|
-
* Resolve LLM configuration from request params with env fallback.
|
|
254
|
-
* Priority: request body/query → env vars → defaults.
|
|
255
|
-
* Use `light: true` for batch/cheap operations (descriptions, learnings, etc.)
|
|
256
|
-
*/
|
|
257
|
-
declare function resolveLLMConfig(opts?: {
|
|
258
|
-
model?: string;
|
|
259
|
-
apiKey?: string;
|
|
260
|
-
provider?: string;
|
|
261
|
-
light?: boolean;
|
|
262
|
-
}): LLMConfig;
|
|
263
|
-
|
|
264
|
-
interface ModelOption {
|
|
265
|
-
provider: Provider;
|
|
266
|
-
alias: ModelName;
|
|
267
|
-
modelId: string;
|
|
268
|
-
/** The provider's default — what you get with no model name at all. */
|
|
269
|
-
default: boolean;
|
|
270
|
-
}
|
|
271
|
-
/**
|
|
272
|
-
* Every alias in the MODELS table, in PROVIDERS order. Pure and keyless,
|
|
273
|
-
* which is what a UI picker or a server-config endpoint needs.
|
|
274
|
-
*/
|
|
275
|
-
declare function listModels(): ModelOption[];
|
|
276
|
-
interface ParsedModelName {
|
|
277
|
-
/** Set only when the name carries an explicit "<provider>/" prefix. */
|
|
278
|
-
provider?: Provider;
|
|
279
|
-
/** The name with that prefix stripped. Aliases are NOT resolved here.
|
|
280
|
-
* undefined for an empty name (or a bare "<provider>/"). */
|
|
281
|
-
modelId?: string;
|
|
282
|
-
}
|
|
283
|
-
/** Pure syntax: strip an explicit provider prefix, nothing else. */
|
|
284
|
-
declare function parseModelName(name?: string): ParsedModelName;
|
|
285
|
-
interface ModelRef {
|
|
286
|
-
provider: Provider;
|
|
287
|
-
/** Concrete id as the provider knows it (alias resolved, prefix stripped). */
|
|
288
|
-
modelId: string;
|
|
289
|
-
/** Canonical "<provider>/<modelId>" — unambiguous, itself a valid model name. */
|
|
290
|
-
name: string;
|
|
291
|
-
}
|
|
292
|
-
/**
|
|
293
|
-
* Resolve a model name to its provider + concrete id WITHOUT an API key.
|
|
294
|
-
* Follows getModel's rules — explicit `provider` wins, then an explicit
|
|
295
|
-
* prefix, then getProviderForModel's inference; aliases map through MODELS;
|
|
296
|
-
* no name → the provider's default — so what this reports is what
|
|
297
|
-
* resolveModel / getModel will build. (One deliberate extra: an alias after
|
|
298
|
-
* a prefix, "anthropic/sonnet", resolves too.)
|
|
299
|
-
*
|
|
300
|
-
* Rejects the one input getModel silently gets wrong: a slashed name whose
|
|
301
|
-
* first segment is NOT a provider ("moonshotai/kimi-k2.6") with nothing
|
|
302
|
-
* else naming the provider — inference falls to the default and the request
|
|
303
|
-
* 404s at the wrong API. Say so up front, with the fix. LLM_PROVIDER, when
|
|
304
|
-
* set, counts as "something naming the provider", exactly as it does for
|
|
305
|
-
* getProviderForModel.
|
|
306
|
-
*/
|
|
307
|
-
declare function canonicalModelName(model?: string, provider?: Provider | string): ModelRef;
|
|
308
|
-
/**
|
|
309
|
-
* Per-call output-token cap. An explicit MAX_OUTPUT_TOKENS env always wins.
|
|
310
|
-
* Otherwise the default is provider-aware: Anthropic runs at 128k because
|
|
311
|
-
* @ai-sdk/anthropic clamps known models down to their true per-model max
|
|
312
|
-
* instead of erroring, while OpenAI-compatible hosts (OpenRouter et al)
|
|
313
|
-
* reject max_tokens above the model limit rather than clamping, so they keep
|
|
314
|
-
* the conservative 64k default. Thinking tokens count against this same
|
|
315
|
-
* budget, so headroom matters more than the visible text length suggests.
|
|
316
|
-
*/
|
|
317
|
-
declare function maxOutputTokensFor(provider?: string): number;
|
|
318
|
-
interface ResolveOptions {
|
|
319
|
-
/** alias | id | "provider/id" | "openrouter/org/id". Omit for the provider's default. */
|
|
320
|
-
model?: string;
|
|
321
|
-
/** Explicit provider; otherwise inferred from `model`. */
|
|
322
|
-
provider?: Provider | string;
|
|
323
|
-
apiKey?: string;
|
|
324
|
-
/**
|
|
325
|
-
* Async key source consulted by env-var NAME ("OPENAI_API_KEY", …) before
|
|
326
|
-
* process.env — a host's own secret store. Only called when `apiKey` is
|
|
327
|
-
* absent.
|
|
328
|
-
*/
|
|
329
|
-
getSecret?: (envName: string) => Promise<string | undefined>;
|
|
330
|
-
baseUrl?: string;
|
|
331
|
-
headers?: Record<string, string>;
|
|
332
|
-
abortSignal?: AbortSignal;
|
|
333
|
-
timeoutMs?: number;
|
|
334
|
-
}
|
|
335
|
-
interface ResolvedModel extends ModelRef {
|
|
336
|
-
model: LanguageModel;
|
|
337
|
-
apiKey: string;
|
|
338
|
-
contextLimit: number;
|
|
339
|
-
maxOutputTokens: number;
|
|
340
|
-
}
|
|
341
|
-
/**
|
|
342
|
-
* Name → everything a caller needs to run: provider, concrete id, canonical
|
|
343
|
-
* name, the API key that was used, the LanguageModel, its context window,
|
|
344
|
-
* and the output-token cap. Key precedence: `apiKey` → `getSecret(envName)`
|
|
345
|
-
* → process.env; none → an error that names the env var. Logs nothing.
|
|
346
|
-
*/
|
|
347
|
-
declare function resolveModel(opts?: ResolveOptions): Promise<ResolvedModel>;
|
|
348
|
-
|
|
349
|
-
interface AiUsage {
|
|
350
|
-
input: number;
|
|
351
|
-
cache_read: number;
|
|
352
|
-
cache_write: number;
|
|
353
|
-
output: number;
|
|
354
|
-
total: number;
|
|
355
|
-
}
|
|
356
|
-
interface AiUsageWithLegacy extends AiUsage {
|
|
357
|
-
inputTokens: number;
|
|
358
|
-
outputTokens: number;
|
|
359
|
-
totalTokens: number;
|
|
360
|
-
}
|
|
361
|
-
type RawUsage = {
|
|
362
|
-
input?: number;
|
|
363
|
-
cache_read?: number;
|
|
364
|
-
cache_write?: number;
|
|
365
|
-
output?: number;
|
|
366
|
-
total?: number;
|
|
367
|
-
inputTokens?: number;
|
|
368
|
-
inputTokenDetails?: {
|
|
369
|
-
noCacheTokens?: number;
|
|
370
|
-
cacheReadTokens?: number;
|
|
371
|
-
cacheWriteTokens?: number;
|
|
372
|
-
};
|
|
373
|
-
cachedInputTokens?: number;
|
|
374
|
-
outputTokens?: number;
|
|
375
|
-
totalTokens?: number;
|
|
376
|
-
};
|
|
377
|
-
declare function emptyUsage(): AiUsage;
|
|
378
|
-
declare function withLegacyUsage(usage: AiUsage): AiUsageWithLegacy;
|
|
379
|
-
declare function normalizeUsage(raw?: RawUsage | null): AiUsageWithLegacy;
|
|
380
|
-
/**
|
|
381
|
-
* Fold provider-metadata cache info into a normalized usage. The v6-alpha
|
|
382
|
-
* OpenRouter provider drops inputTokensDetails from the SDK usage object
|
|
383
|
-
* (cached-token counts survive only in providerMetadata.openrouter.usage),
|
|
384
|
-
* so without this every OpenRouter step reports cache_read 0 regardless of
|
|
385
|
-
* whether the upstream host actually cached.
|
|
386
|
-
*/
|
|
387
|
-
declare function withProviderCacheUsage(usage: AiUsageWithLegacy, providerMetadata?: Record<string, any> | null): AiUsageWithLegacy;
|
|
388
|
-
declare function addUsage(...usages: Array<AiUsage | undefined | null>): AiUsage;
|
|
389
|
-
|
|
390
|
-
interface CallModelOptions {
|
|
391
|
-
provider: Provider;
|
|
392
|
-
apiKey: string;
|
|
393
|
-
messages: ModelMessage[];
|
|
394
|
-
tools?: ToolSet;
|
|
395
|
-
parser?: (fullResponse: string) => void;
|
|
396
|
-
thinkingSpeed?: ThinkingSpeed;
|
|
397
|
-
cwd?: string;
|
|
398
|
-
executablePath?: string;
|
|
399
|
-
modelName?: ModelName;
|
|
400
|
-
}
|
|
401
|
-
declare function callModel(opts: CallModelOptions): Promise<{
|
|
402
|
-
text: string;
|
|
403
|
-
usage: AiUsageWithLegacy;
|
|
404
|
-
}>;
|
|
405
|
-
interface GenerateObjectArgs {
|
|
406
|
-
provider: Provider;
|
|
407
|
-
apiKey: string;
|
|
408
|
-
prompt: string;
|
|
409
|
-
schema: any;
|
|
410
|
-
}
|
|
411
|
-
declare function callGenerateObject(args: GenerateObjectArgs): Promise<{
|
|
412
|
-
object: any;
|
|
413
|
-
usage: AiUsageWithLegacy;
|
|
414
|
-
}>;
|
|
415
|
-
interface GenerateTextArgs {
|
|
416
|
-
provider: Provider;
|
|
417
|
-
apiKey: string;
|
|
418
|
-
prompt: string;
|
|
419
|
-
thinkingSpeed?: ThinkingSpeed;
|
|
420
|
-
}
|
|
421
|
-
declare function callGenerateText(args: GenerateTextArgs): Promise<{
|
|
422
|
-
text: string;
|
|
423
|
-
usage: AiUsageWithLegacy;
|
|
424
|
-
}>;
|
|
425
|
-
|
|
426
|
-
declare const SYSTEM = "You are an expert dev. You are given a codebase and a task. You need to write the code for the task. You can also suggest changes to the codebase if needed.\n\nAvoid assuming that certain functions are available in the codebase. Don't use to_timestamp or to_date in SQL if you don't see examples of them being used. DO NOT make up functions like a logger or other utils. Only use utility functions that you ABSOLUTELY know exist in the code.\n\nTry to write as simple and straightforward code as possible. Make a real implementation, do NOT do a mockup or add sample data. Assume there is already mock data in the database. If you see snippets of backend code, that means you have access to the backend codebase and can add new backend endpoints or other functionality as needed.\n\nYou will be provided with code snippets to edit or create. Please preserve the EXACT file paths when you make edits. Do not truncate the file paths.\n\nYou may see multiple code snippets from the same file! In that case, please organize the code properly: if you need to add an import statement, do it in the snippet that has other imports in it! Since you won't always be able to see the whole file, try to be careful and avoid adding new code just above a snippet, since you might not know exactly what other code is there.\n\nAlways remember to add correct code that will compile!!! Make sure to properly add function signatures if needed, such as to Go interfaces or Rust traits (if you see those in the code snippets).\n\nIf asked to make further changes after already writing code, use the <content> blocks from your previous edits in order to identify code snippets to replace.\n";
|
|
427
|
-
declare const OUTRO = "\nPlease write all the necessary code to fully implement the feature end-to-end. Do not make mock data or example placeholders!!!\n";
|
|
428
|
-
|
|
429
|
-
type ProviderTool = "webSearch" | "webFetch" | "bash";
|
|
430
|
-
/**
|
|
431
|
-
* Provider-native tool by name.
|
|
432
|
-
*
|
|
433
|
-
* `webSearch` and `webFetch` are special: only Anthropic has native
|
|
434
|
-
* ones, so every other provider gets a shim of the same name and result
|
|
435
|
-
* shape instead of an exception — Exa-backed search from `./search.js`,
|
|
436
|
-
* a guarded HTTP GET from `./fetch.js`. That keeps both tools available
|
|
437
|
-
* (as `web_search` / `web_fetch`) on any model. This entry point returns
|
|
438
|
-
* the bare tool — for the result bookkeeping, citation indices and
|
|
439
|
-
* prompt snippet, call `createWebSearch` / `createWebFetch` directly.
|
|
440
|
-
*
|
|
441
|
-
* Returns `undefined` for those two when the chosen backend has no key
|
|
442
|
-
* configured; callers should drop the tool rather than fail the request.
|
|
443
|
-
* Other tools still throw for unsupported providers.
|
|
444
|
-
*/
|
|
445
|
-
declare function getProviderTool(provider: Provider, apiKey: string, toolName: ProviderTool): any;
|
|
446
|
-
|
|
447
|
-
/**
|
|
448
|
-
* Web search, uniform across providers.
|
|
449
|
-
*
|
|
450
|
-
* Anthropic ships a server-executed `web_search` tool: the search loop
|
|
451
|
-
* runs inside their API, results never round-trip through us, and the
|
|
452
|
-
* model emits `<cite index="N-M">` tags referencing a flat, 1-based list
|
|
453
|
-
* of every result returned across the whole turn. It's the best option
|
|
454
|
-
* when it's available — no extra model hop, no per-search bill on us.
|
|
455
|
-
*
|
|
456
|
-
* Nobody else has an equivalent we can drop in. OpenAI, Google,
|
|
457
|
-
* OpenRouter and xAI each expose *some* server-side search, but every
|
|
458
|
-
* one has a different tool name, a different result shape, and a
|
|
459
|
-
* different citation mechanism (Google's sources arrive as
|
|
460
|
-
* `groundingMetadata`, OpenRouter's as message `annotations` — neither
|
|
461
|
-
* is a tool-result at all). Adapting four of those into one pipeline is
|
|
462
|
-
* four adapters and four citation normalizers.
|
|
463
|
-
*
|
|
464
|
-
* So: keep Anthropic on its native tool, and give every other provider a
|
|
465
|
-
* client-executed tool of the same name, backed by Exa, that returns the
|
|
466
|
-
* same shape. Consumers see one `web_search` tool, one result type, one
|
|
467
|
-
* citation convention, regardless of which model is driving.
|
|
468
|
-
*
|
|
469
|
-
* Usage:
|
|
470
|
-
*
|
|
471
|
-
* const ws = createWebSearch({ provider, apiKey });
|
|
472
|
-
* const tools = { ...(ws.tool ? { [WEB_SEARCH_TOOL_NAME]: ws.tool } : {}) };
|
|
473
|
-
* const system = basePrompt + ws.promptSnippet;
|
|
474
|
-
* // in onStepFinish: ws.capture(step.content)
|
|
475
|
-
* // when writing up: linkifyCitations(markdown, ws.results)
|
|
476
|
-
*
|
|
477
|
-
* `ws.results` ends the run holding every result in citation order on
|
|
478
|
-
* both paths, so downstream code never branches on the backend.
|
|
479
|
-
*/
|
|
480
|
-
/** Tool name registered with the model. Load-bearing: consumers key UI
|
|
481
|
-
* and step-walking off this exact string. */
|
|
482
|
-
declare const WEB_SEARCH_TOOL_NAME = "web_search";
|
|
483
|
-
/** Which implementation backs the tool. */
|
|
484
|
-
type SearchBackend = "anthropic" | "exa";
|
|
485
|
-
/**
|
|
486
|
-
* One search hit. Field-compatible with Anthropic's
|
|
487
|
-
* `web_search_result` output (`url` / `title` / `pageAge` / `type`), so
|
|
488
|
-
* code that walks Anthropic tool-results parses Exa results unchanged.
|
|
489
|
-
*/
|
|
490
|
-
interface WebSearchResult {
|
|
491
|
-
url: string;
|
|
492
|
-
title: string | null;
|
|
493
|
-
/** Publish date when the backend reports one. */
|
|
494
|
-
pageAge: string | null;
|
|
495
|
-
/**
|
|
496
|
-
* Extracted page text. Exa path only — Anthropic returns
|
|
497
|
-
* `encryptedContent` that only their model can read, so on the native
|
|
498
|
-
* path the text is never visible to us (or to this process).
|
|
499
|
-
*/
|
|
500
|
-
text?: string;
|
|
501
|
-
/**
|
|
502
|
-
* 1-based citation index, flat across every `web_search` call in the
|
|
503
|
-
* run — the number the model is told to cite. Exa path only; on the
|
|
504
|
-
* Anthropic path the model derives indices itself.
|
|
505
|
-
*/
|
|
506
|
-
index?: number;
|
|
507
|
-
type: "web_search_result";
|
|
508
|
-
}
|
|
509
|
-
interface WebSearchOptions {
|
|
510
|
-
/** Max `web_search` calls per run. Default 3, matching the previous
|
|
511
|
-
* Anthropic-only default. Enforced in-process on the Exa path. */
|
|
512
|
-
maxUses?: number;
|
|
513
|
-
/** Results per call on the Exa path. Default 5. */
|
|
514
|
-
numResults?: number;
|
|
515
|
-
/** Per-result text budget on the Exa path. Default 4000. Raise for
|
|
516
|
-
* research writeups, lower for quick factual lookups. */
|
|
517
|
-
maxCharacters?: number;
|
|
518
|
-
allowedDomains?: string[];
|
|
519
|
-
blockedDomains?: string[];
|
|
520
|
-
}
|
|
521
|
-
interface CreateWebSearchOptions extends WebSearchOptions {
|
|
522
|
-
/** LLM provider driving the run — decides the backend. */
|
|
523
|
-
provider: Provider;
|
|
524
|
-
/** LLM API key. Only used on the Anthropic path. Falls back to env. */
|
|
525
|
-
apiKey?: string;
|
|
526
|
-
/** Exa key. Falls back to `EXA_API_KEY`. */
|
|
527
|
-
searchApiKey?: string;
|
|
528
|
-
/**
|
|
529
|
-
* Force a backend regardless of provider. `"exa"` is how you A/B the
|
|
530
|
-
* shim against Anthropic's native tool on identical prompts.
|
|
531
|
-
*/
|
|
532
|
-
backend?: SearchBackend;
|
|
533
|
-
/**
|
|
534
|
-
* Ask the model to cite sources as `<cite index="N">` tags, so
|
|
535
|
-
* `formatOutput` can turn them into markdown links. Default `false`:
|
|
536
|
-
* no citation instructions go out, and any tag the model emits anyway
|
|
537
|
-
* is stripped to plain prose.
|
|
538
|
-
*
|
|
539
|
-
* Only turn this on for surfaces that actually render source links
|
|
540
|
-
* (a research writeup). Claude honors the instruction unreliably —
|
|
541
|
-
* measured 0/3 runs against claude-sonnet-5, which writes bare
|
|
542
|
-
* parentheticals like `(Bitcoin Magazine)` instead — so a chat reply
|
|
543
|
-
* asking for citations tends to get prose with no links either way.
|
|
544
|
-
* See `npm run cite-rate`.
|
|
545
|
-
*/
|
|
546
|
-
citations?: boolean;
|
|
547
|
-
abortSignal?: AbortSignal;
|
|
548
|
-
}
|
|
549
|
-
interface WebSearchHandle {
|
|
550
|
-
/** Register under {@link WEB_SEARCH_TOOL_NAME}. `undefined` when no
|
|
551
|
-
* key is configured for the chosen backend — drop the tool rather
|
|
552
|
-
* than failing the request. */
|
|
553
|
-
tool: any | undefined;
|
|
554
|
-
backend: SearchBackend | undefined;
|
|
555
|
-
/** True when the model runs the search server-side (Anthropic). */
|
|
556
|
-
native: boolean;
|
|
557
|
-
/** Every result from the run, in citation order. */
|
|
558
|
-
results: WebSearchResult[];
|
|
559
|
-
/**
|
|
560
|
-
* Feed each step's content here (AI SDK `onStepFinish`). Walks
|
|
561
|
-
* Anthropic tool-results into `results`; a no-op on the Exa path,
|
|
562
|
-
* where `execute` already appended them. Safe to call either way.
|
|
563
|
-
*/
|
|
564
|
-
capture(stepContent: unknown): void;
|
|
565
|
-
/** Citation instructions to append to the system prompt. Empty unless
|
|
566
|
-
* `citations: true` was requested. */
|
|
567
|
-
promptSnippet: string;
|
|
568
|
-
/**
|
|
569
|
-
* Run the model's final text through the right citation treatment for
|
|
570
|
-
* this handle: markdown links when `citations` is on, plain prose when
|
|
571
|
-
* it isn't. Either way no raw `<cite>` markup survives — a leftover
|
|
572
|
-
* tag renders as literal text in any GFM viewer.
|
|
573
|
-
*/
|
|
574
|
-
formatOutput(markdown: string): {
|
|
575
|
-
content: string;
|
|
576
|
-
converted: number;
|
|
577
|
-
skipped: number;
|
|
578
|
-
};
|
|
579
|
-
}
|
|
580
|
-
declare function getSearchApiKey(): string | undefined;
|
|
581
|
-
declare function hasSearchApiKey(): boolean;
|
|
582
|
-
/**
|
|
583
|
-
* Which backend a provider gets. Anthropic keeps its native tool;
|
|
584
|
-
* everything else falls to Exa.
|
|
585
|
-
*/
|
|
586
|
-
declare function resolveSearchBackend(provider: Provider): SearchBackend;
|
|
587
|
-
/**
|
|
588
|
-
* Raw Exa search. Exposed for callers that want results without an LLM
|
|
589
|
-
* in the loop (a research pre-fetch, a URL enrichment pass).
|
|
590
|
-
*
|
|
591
|
-
* Throws on transport/HTTP failure — {@link createWebSearch} catches and
|
|
592
|
-
* hands the model a readable error instead of failing the whole turn.
|
|
593
|
-
*/
|
|
594
|
-
declare function searchWeb(query: string, opts?: WebSearchOptions & {
|
|
595
|
-
apiKey?: string;
|
|
596
|
-
abortSignal?: AbortSignal;
|
|
597
|
-
}): Promise<WebSearchResult[]>;
|
|
598
|
-
/**
|
|
599
|
-
* Build the `web_search` tool for a run, plus the citation bookkeeping
|
|
600
|
-
* that goes with it. See the module header for the usage shape.
|
|
601
|
-
*/
|
|
602
|
-
declare function createWebSearch(opts: CreateWebSearchOptions): WebSearchHandle;
|
|
603
|
-
/**
|
|
604
|
-
* Walk one AI SDK step's content for `web_search` tool-results and
|
|
605
|
-
* append each hit to `target`, in order.
|
|
606
|
-
*
|
|
607
|
-
* Order is load-bearing: Anthropic's `<cite index="N-M">` tags index
|
|
608
|
-
* this flat list 1-based across the entire turn.
|
|
609
|
-
*
|
|
610
|
-
* Tolerates both result shapes (`output` and `result`) and skips any
|
|
611
|
-
* non-array body — adapters vary across AI SDK versions, and a shape we
|
|
612
|
-
* don't recognize should cost us citations, not the run.
|
|
613
|
-
*/
|
|
614
|
-
declare function captureNativeResults(stepContent: unknown, target: WebSearchResult[]): void;
|
|
615
|
-
/**
|
|
616
|
-
* Remove citation markup, leaving readable prose.
|
|
617
|
-
*
|
|
618
|
-
* The default treatment when `citations` is off. Models emit `<cite`
|
|
619
|
-
* tags unprompted often enough that we can't just hope: Claude produces
|
|
620
|
-
* them spontaneously with server-side search, and a raw tag renders as
|
|
621
|
-
* literal text in any GFM viewer, which looks broken.
|
|
622
|
-
*
|
|
623
|
-
* Three shapes, in order:
|
|
624
|
-
* 1. Empty markers — `a claim. <cite index="4"></cite>` — are
|
|
625
|
-
* trailing footnotes with nothing to say. They take their leading
|
|
626
|
-
* whitespace with them, so the sentence closes up cleanly.
|
|
627
|
-
* 2. Anchored tags collapse to their anchor text, which is the words
|
|
628
|
-
* the model was sourcing and reads as normal prose.
|
|
629
|
-
* 3. Any orphan `<cite ...>` or `</cite>` left by a truncated stream
|
|
630
|
-
* is swept, so no half-tag survives a cut-off response.
|
|
631
|
-
*/
|
|
632
|
-
declare function stripCitations(markdown: string): string;
|
|
633
|
-
/**
|
|
634
|
-
* Replace `<cite index="N">anchor</cite>` tags with markdown links into
|
|
635
|
-
* `results`. Handles Anthropic's multi-part form (`index="2-1"`,
|
|
636
|
-
* `index="2-1,3-4"`) by keying off the leading number, which is the
|
|
637
|
-
* flat result index.
|
|
638
|
-
*
|
|
639
|
-
* Out-of-range or unresolvable indices collapse to the bare anchor
|
|
640
|
-
* text. That span loses its link, but no raw `<cite>` markup survives
|
|
641
|
-
* into the output — persisted markdown is usually rendered as plain
|
|
642
|
-
* GFM, where a leftover tag shows up as literal text.
|
|
643
|
-
*
|
|
644
|
-
* Models regularly ignore the "anchor text is required" instruction and
|
|
645
|
-
* emit a trailing `<cite index="4"></cite>` marker instead (grok-4 does
|
|
646
|
-
* it consistently). An empty anchor would linkify to `[](url)` — a
|
|
647
|
-
* broken, invisible link — so it falls back to a `[N]` footnote marker.
|
|
648
|
-
*/
|
|
649
|
-
declare function linkifyCitations(markdown: string, results: WebSearchResult[]): {
|
|
650
|
-
content: string;
|
|
651
|
-
converted: number;
|
|
652
|
-
skipped: number;
|
|
653
|
-
};
|
|
654
|
-
|
|
655
|
-
/**
|
|
656
|
-
* Web fetch, uniform across providers. Sibling of `./search.js`.
|
|
657
|
-
*
|
|
658
|
-
* Anthropic ships a server-executed `web_fetch` tool: given a URL, their
|
|
659
|
-
* API retrieves the page (HTML or PDF), turns it into text and hands it
|
|
660
|
-
* to the model with no round-trip through us. Same reasons that make it
|
|
661
|
-
* the best option when available: no extra hop, nothing to host,
|
|
662
|
-
* nothing to secure.
|
|
663
|
-
*
|
|
664
|
-
* Nobody else has one. So, as with search: keep Anthropic native, and
|
|
665
|
-
* give every other provider a client-executed tool of the same name and
|
|
666
|
-
* result shape, backed by a plain HTTP GET plus an HTML-to-text pass.
|
|
667
|
-
*
|
|
668
|
-
* Two things differ from search that consumers should know:
|
|
669
|
-
*
|
|
670
|
-
* 1. On the Anthropic path the model can only fetch URLs that already
|
|
671
|
-
* appeared in the conversation — pasted by the user, or returned by
|
|
672
|
-
* an earlier `web_search` / `web_fetch`. It refuses URLs it made
|
|
673
|
-
* up. The HTTP path has no such memory and fetches whatever the
|
|
674
|
-
* model asks for; what it WON'T do is reach anything private.
|
|
675
|
-
*
|
|
676
|
-
* 2. The HTTP path runs in *our* process, so the model can point it at
|
|
677
|
-
* our network. Every URL — and every redirect hop — is checked
|
|
678
|
-
* before connecting: http(s) only, no credentials, and the host
|
|
679
|
-
* must resolve exclusively to public unicast addresses (loopback,
|
|
680
|
-
* RFC 1918, link-local incl. cloud metadata, CGNAT, ULA and the
|
|
681
|
-
* v4-in-v6 forms are all refused). There is a DNS-rebinding window
|
|
682
|
-
* between our lookup and the socket's own; pin `allowedDomains` if
|
|
683
|
-
* the deployment cares.
|
|
684
|
-
*
|
|
685
|
-
* Usage:
|
|
686
|
-
*
|
|
687
|
-
* const wf = createWebFetch({ provider, apiKey });
|
|
688
|
-
* const tools = { ...(wf.tool ? { [WEB_FETCH_TOOL_NAME]: wf.tool } : {}) };
|
|
689
|
-
* // in onStepFinish: wf.capture(step.content)
|
|
690
|
-
* // afterwards: wf.results — every page fetched, in order
|
|
691
|
-
*/
|
|
692
|
-
/** Tool name registered with the model. Matches Anthropic's native name
|
|
693
|
-
* so consumers key UI and step-walking off one string on both paths. */
|
|
694
|
-
declare const WEB_FETCH_TOOL_NAME = "web_fetch";
|
|
695
|
-
/** Which implementation backs the tool. */
|
|
696
|
-
type FetchBackend = "anthropic" | "http";
|
|
697
|
-
/**
|
|
698
|
-
* One fetched page. Same fields on both paths; the notes say where the
|
|
699
|
-
* backends differ in what they put in them.
|
|
700
|
-
*/
|
|
701
|
-
interface WebFetchResult {
|
|
702
|
-
/** Where the content came from. The final URL after redirects on the
|
|
703
|
-
* HTTP path; the URL Anthropic reports on the native path. */
|
|
704
|
-
url: string;
|
|
705
|
-
title: string | null;
|
|
706
|
-
/**
|
|
707
|
-
* Extracted text. Absent for a PDF on the Anthropic path — their API
|
|
708
|
-
* returns it base64-encoded, which is only useful to their model.
|
|
709
|
-
*/
|
|
710
|
-
text?: string;
|
|
711
|
-
/** Original `content-type` on the HTTP path; Anthropic's normalized
|
|
712
|
-
* `text/plain` / `application/pdf` on the native path. */
|
|
713
|
-
mediaType: string | null;
|
|
714
|
-
retrievedAt: string | null;
|
|
715
|
-
/** True when the HTTP path cut the text at `maxCharacters`. */
|
|
716
|
-
truncated?: boolean;
|
|
717
|
-
type: "web_fetch_result";
|
|
718
|
-
}
|
|
719
|
-
interface WebFetchOptions {
|
|
720
|
-
/** Max `web_fetch` calls per run. Default 5. Enforced in-process on
|
|
721
|
-
* the HTTP path, passed as `max_uses` to Anthropic. */
|
|
722
|
-
maxUses?: number;
|
|
723
|
-
/**
|
|
724
|
-
* Text budget per page on the HTTP path, in characters. Default
|
|
725
|
-
* 40000 — about 10k tokens. When only `maxContentTokens` is given,
|
|
726
|
-
* derived from it at 4 chars/token so one option covers both paths.
|
|
727
|
-
*/
|
|
728
|
-
maxCharacters?: number;
|
|
729
|
-
/**
|
|
730
|
-
* Content budget per page on the Anthropic path, in tokens (their
|
|
731
|
-
* `max_content_tokens`). Unset means Anthropic's own default. When
|
|
732
|
-
* only `maxCharacters` is given, derived from it.
|
|
733
|
-
*/
|
|
734
|
-
maxContentTokens?: number;
|
|
735
|
-
/** Only fetch from these domains. Subdomains are included, so
|
|
736
|
-
* `example.com` admits `docs.example.com`. */
|
|
737
|
-
allowedDomains?: string[];
|
|
738
|
-
blockedDomains?: string[];
|
|
739
|
-
}
|
|
740
|
-
/** Resolve a hostname to every address it answers with. */
|
|
741
|
-
type HostLookup = (hostname: string) => Promise<string[]>;
|
|
742
|
-
interface CreateWebFetchOptions extends WebFetchOptions {
|
|
743
|
-
/** LLM provider driving the run — decides the backend. */
|
|
744
|
-
provider: Provider;
|
|
745
|
-
/** LLM API key. Only used on the Anthropic path. Falls back to env. */
|
|
746
|
-
apiKey?: string;
|
|
747
|
-
/** Force a backend regardless of provider. `"http"` is how you A/B
|
|
748
|
-
* the shim against Anthropic's native tool on identical prompts. */
|
|
749
|
-
backend?: FetchBackend;
|
|
750
|
-
abortSignal?: AbortSignal;
|
|
751
|
-
/**
|
|
752
|
-
* Override hostname resolution on the HTTP path. Tests inject a stub
|
|
753
|
-
* here; a deployment with its own resolver policy can too. Must return
|
|
754
|
-
* every address the host resolves to — the guard refuses a host if ANY
|
|
755
|
-
* of them is private.
|
|
756
|
-
*/
|
|
757
|
-
lookup?: HostLookup;
|
|
758
|
-
}
|
|
759
|
-
interface WebFetchHandle {
|
|
760
|
-
/** Register under {@link WEB_FETCH_TOOL_NAME}. `undefined` only when
|
|
761
|
-
* the Anthropic path has no API key — drop the tool rather than
|
|
762
|
-
* failing the request. The HTTP path needs no key. */
|
|
763
|
-
tool: any | undefined;
|
|
764
|
-
backend: FetchBackend | undefined;
|
|
765
|
-
/** True when the fetch runs server-side (Anthropic). */
|
|
766
|
-
native: boolean;
|
|
767
|
-
/** Every page fetched during the run, in order. */
|
|
768
|
-
results: WebFetchResult[];
|
|
769
|
-
/**
|
|
770
|
-
* Feed each step's content here (AI SDK `onStepFinish`). Walks
|
|
771
|
-
* Anthropic tool-results into `results`; a no-op on the HTTP path,
|
|
772
|
-
* where `execute` already appended them. Safe to call either way.
|
|
773
|
-
*/
|
|
774
|
-
capture(stepContent: unknown): void;
|
|
775
|
-
}
|
|
776
|
-
/**
|
|
777
|
-
* Which backend a provider gets. Anthropic keeps its native tool;
|
|
778
|
-
* everything else falls to the HTTP shim.
|
|
779
|
-
*/
|
|
780
|
-
declare function resolveFetchBackend(provider: Provider): FetchBackend;
|
|
781
|
-
/**
|
|
782
|
-
* True for an IP literal (v4 or v6, brackets tolerated) the HTTP path
|
|
783
|
-
* refuses to connect to. Anything that isn't an IP literal is `true`
|
|
784
|
-
* too: an address we can't classify isn't one we connect to.
|
|
785
|
-
*/
|
|
786
|
-
declare function isPrivateAddress(ip: string): boolean;
|
|
787
|
-
/**
|
|
788
|
-
* Validate a URL before the HTTP path connects to it. Throws a readable
|
|
789
|
-
* error on any rejection — the model gets the message back as the
|
|
790
|
-
* tool's `error` and can pick a different URL.
|
|
791
|
-
*
|
|
792
|
-
* A hostname is resolved and refused if ANY of its addresses is
|
|
793
|
-
* private: a host that answers with a mix is misconfigured or hostile,
|
|
794
|
-
* and we'd have no say in which address the socket picks.
|
|
795
|
-
*/
|
|
796
|
-
declare function validateFetchUrl(raw: string, opts?: {
|
|
797
|
-
allowedDomains?: string[];
|
|
798
|
-
blockedDomains?: string[];
|
|
799
|
-
lookup?: HostLookup;
|
|
800
|
-
}): Promise<URL>;
|
|
801
|
-
interface FetchUrlOptions {
|
|
802
|
-
maxCharacters?: number;
|
|
803
|
-
allowedDomains?: string[];
|
|
804
|
-
blockedDomains?: string[];
|
|
805
|
-
abortSignal?: AbortSignal;
|
|
806
|
-
timeoutMs?: number;
|
|
807
|
-
lookup?: HostLookup;
|
|
808
|
-
}
|
|
809
|
-
/**
|
|
810
|
-
* Raw fetch-and-extract. Exposed for callers that want a page without
|
|
811
|
-
* an LLM in the loop (a URL enrichment pass, a link preview).
|
|
812
|
-
*
|
|
813
|
-
* Throws on any rejection or failure — {@link createWebFetch} catches
|
|
814
|
-
* and hands the model a readable error instead of failing the turn.
|
|
815
|
-
*/
|
|
816
|
-
declare function fetchUrl(rawUrl: string, opts?: FetchUrlOptions): Promise<WebFetchResult>;
|
|
817
|
-
/**
|
|
818
|
-
* Dependency-free HTML to text. Good enough for a model to read a page;
|
|
819
|
-
* not a renderer. Scripts, styles and SVG go away entirely; block-level
|
|
820
|
-
* boundaries become line breaks; list items get a leading dash; the
|
|
821
|
-
* rest of the markup is dropped and entities decoded. Whitespace is
|
|
822
|
-
* collapsed except for line breaks, so `<pre>` keeps its lines but not
|
|
823
|
-
* its indentation.
|
|
824
|
-
*/
|
|
825
|
-
declare function htmlToText(html: string): {
|
|
826
|
-
title: string | null;
|
|
827
|
-
text: string;
|
|
828
|
-
};
|
|
829
|
-
/**
|
|
830
|
-
* Build the `web_fetch` tool for a run. See the module header for the
|
|
831
|
-
* usage shape.
|
|
832
|
-
*/
|
|
833
|
-
declare function createWebFetch(opts: CreateWebFetchOptions): WebFetchHandle;
|
|
834
|
-
/**
|
|
835
|
-
* Walk one AI SDK step's content for `web_fetch` tool-results and
|
|
836
|
-
* append each page to `target`, in order.
|
|
837
|
-
*
|
|
838
|
-
* Tolerates both result shapes (`output` and `result`) and both key
|
|
839
|
-
* casings for the nested fields — adapters vary across AI SDK versions,
|
|
840
|
-
* and a shape we don't recognize should cost us a bookkeeping entry,
|
|
841
|
-
* not the run. Anthropic's error results (`web_fetch_tool_result_error`)
|
|
842
|
-
* are skipped: there's no page to record.
|
|
843
|
-
*/
|
|
844
|
-
declare function captureNativeFetchResults(stepContent: unknown, target: WebFetchResult[]): void;
|
|
845
|
-
|
|
846
|
-
export { API_KEY_ENV, type AiUsage, type AiUsageWithLegacy, type Conversation, type ConversationData, ConversationStorage, type CreateWebFetchOptions, type CreateWebSearchOptions, DEFAULT_MODELS, type FetchBackend, type FetchUrlOptions, GATEWAY_PATHS, type GetModelOptions, type HostLookup, type LLMConfig, type Logger, MAX_CONVERSATIONS, MODELS, type ModelName, type ModelOption, type ModelRef, OUTRO, PROVIDERS, type ParsedModelName, type Provider, type ProviderTool, type ResolveOptions, type ResolvedModel, SYSTEM, type SearchBackend, type ThinkingSpeed, type TokenPricing, type TokenUsageForCost, WEB_FETCH_TOOL_NAME, WEB_SEARCH_TOOL_NAME, type WebFetchHandle, type WebFetchOptions, type WebFetchResult, type WebSearchHandle, type WebSearchOptions, type WebSearchResult, addUsage, callGenerateObject, callGenerateText, callModel, canonicalModelName, captureNativeFetchResults, captureNativeResults, computeSessionCost, consoleLogger, createWebFetch, createWebSearch, emptyUsage, fetchUrl, gatewayEnvForProviders, gatewayUrlFor, gatewayUrlForModel, getApiKeyForProvider, getContextLimit, getGatewayBaseURL, getLightModelForProvider, getModel, getModelDetails, getProviderForModel, getProviderOptions, getProviderTool, getSearchApiKey, getTokenPricing, hasApiKeyForProvider, hasSearchApiKey, htmlToText, isPrivateAddress, linkifyCitations, listModels, loadModelPricing, maxOutputTokensFor, normalizeApiKey, normalizeCallerBaseURL, normalizeUsage, parseModelName, resolveFetchBackend, resolveLLMConfig, resolveModel, resolveSearchBackend, searchWeb, stripCitations, validateFetchUrl, withLegacyUsage, withProviderCacheUsage };
|