@outputai/core 0.15.1-next.4a437bf.0 → 0.15.1-next.8ef04e2.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/package.json +58 -6
- package/src/helpers/fetch.js +21 -9
- package/src/helpers/path.js +36 -0
- package/src/helpers/redact.js +2 -1
- package/src/http/config.js +10 -0
- package/src/http/cost.d.ts +20 -0
- package/src/http/cost.js +41 -0
- package/src/http/fetch/events.js +10 -0
- package/src/http/fetch/index.d.ts +26 -0
- package/src/http/fetch/index.js +78 -0
- package/src/http/fetch/logger.d.ts +10 -0
- package/src/http/fetch/logger.js +56 -0
- package/src/http/index.d.ts +27 -0
- package/src/http/index.js +9 -0
- package/src/http/ky/index.d.ts +25 -0
- package/src/http/ky/index.js +10 -0
- package/src/http/request_tag.js +30 -0
- package/src/llm/agent.js +141 -0
- package/src/llm/ai_provider.js +131 -0
- package/src/llm/ai_sdk_options.js +126 -0
- package/src/llm/consts.js +6 -0
- package/src/llm/deprecated_provider_aliases.js +8 -0
- package/src/llm/generate.js +88 -0
- package/src/llm/index.d.ts +631 -0
- package/src/llm/index.js +5 -0
- package/src/llm/prompt/content.js +70 -0
- package/src/llm/prompt/interpolations.js +58 -0
- package/src/llm/prompt/loader.js +67 -0
- package/src/llm/prompt/markup/attributes.js +52 -0
- package/src/llm/prompt/markup/nodes.js +71 -0
- package/src/llm/prompt/markup/tokenizer.js +3 -0
- package/src/llm/prompt/markup/tokens.js +26 -0
- package/src/llm/prompt/validations.js +129 -0
- package/src/llm/utils/cost.js +150 -0
- package/src/llm/utils/error_handler.js +53 -0
- package/src/llm/utils/file.js +42 -0
- package/src/llm/utils/google_vertex_auth.js +31 -0
- package/src/llm/utils/grounding.js +49 -0
- package/src/llm/utils/image.js +37 -0
- package/src/llm/utils/legacy_cost_attribute.js +75 -0
- package/src/llm/utils/metering.js +126 -0
- package/src/llm/utils/models.js +15 -0
- package/src/llm/utils/models_pricing.js +93 -0
- package/src/llm/utils/models_pricing_snapshot.json +4166 -0
- package/src/llm/utils/skills.js +74 -0
- package/src/llm/utils/sources.js +73 -0
- package/src/llm/utils/stream.js +75 -0
- package/src/llm/utils/tools.js +48 -0
- package/src/llm/utils/usage.js +156 -0
- package/src/llm/utils/usage_tools.js +23 -0
- package/src/llm/utils/wrap.js +277 -0
- package/src/llm/validations.js +234 -0
- package/src/sdk/helpers/path.d.ts +2 -0
- package/src/sdk/helpers/path.js +1 -0
- package/src/tracing/trace_attribute.d.ts +0 -17
- package/src/tracing/trace_attribute.js +1 -29
- package/src/worker/configs.js +23 -4
- package/src/worker/index.js +16 -47
- package/src/worker/interceptors/activity.js +0 -1
- package/src/worker/interceptors/workflow.js +0 -1
- package/src/worker/telemetry.js +122 -2
- package/src/worker/worker_options.js +43 -0
|
@@ -0,0 +1,631 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
GenerateTextResult as AIGenerateTextResult,
|
|
3
|
+
GenerateImageResult as AIGenerateImageResult,
|
|
4
|
+
StreamTextResult as AIStreamTextResult,
|
|
5
|
+
ToolSet,
|
|
6
|
+
ToolChoice,
|
|
7
|
+
StopCondition,
|
|
8
|
+
ModelMessage,
|
|
9
|
+
StreamTextOnChunkCallback,
|
|
10
|
+
GenerateTextOnEndCallback,
|
|
11
|
+
StreamTextOnErrorCallback
|
|
12
|
+
} from 'ai';
|
|
13
|
+
import type { Output as AIOutputNamespace } from 'ai';
|
|
14
|
+
import type { Attribute } from '#trace_attribute';
|
|
15
|
+
|
|
16
|
+
type BaseAttribute = Attribute.BaseAttribute;
|
|
17
|
+
|
|
18
|
+
/** Full AI SDK module (values and types). Use `aiSdk.Output`, `aiSdk.tool`, `aiSdk.isStepCount`, `aiSdk.ToolSet`, and other AI SDK APIs. */
|
|
19
|
+
export * as aiSdk from 'ai';
|
|
20
|
+
|
|
21
|
+
/** Liquid interpolation variables, including nested objects and arrays. */
|
|
22
|
+
export type PromptVariables = Record<string, unknown>;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Represents a single message in a prompt conversation.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```ts
|
|
29
|
+
* const msg: PromptMessage = {
|
|
30
|
+
* role: 'user',
|
|
31
|
+
* content: 'Hello, Claude!'
|
|
32
|
+
* };
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export type PromptMessage = {
|
|
36
|
+
/** The message role. Authored prompt blocks support 'system', 'user', and 'assistant'. */
|
|
37
|
+
role: 'system' | 'user' | 'assistant';
|
|
38
|
+
/** The content of the message */
|
|
39
|
+
content: string;
|
|
40
|
+
/**
|
|
41
|
+
* Per-message provider options resolved at load from the role tag's `options` attribute and
|
|
42
|
+
* matching `config.messageOptions` sets. Authored as `<system options="set_a set_b">`.
|
|
43
|
+
* `options` is the only supported role-tag attribute and must have a value. Omitted when the tag
|
|
44
|
+
* has no effective `options`.
|
|
45
|
+
*/
|
|
46
|
+
providerOptions?: Record<string, Record<string, unknown>>;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Configuration for LLM prompt generation.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```ts
|
|
54
|
+
* const prompt: Prompt = {
|
|
55
|
+
* name: 'summarizePrompt',
|
|
56
|
+
* fileDir: '/app/prompts',
|
|
57
|
+
* variables: {},
|
|
58
|
+
* config: {
|
|
59
|
+
* provider: 'anthropic',
|
|
60
|
+
* model: 'claude-opus-4-1',
|
|
61
|
+
* temperature: 0.7,
|
|
62
|
+
* maxOutputTokens: 2048,
|
|
63
|
+
* maxSteps: 10,
|
|
64
|
+
* skills: []
|
|
65
|
+
* },
|
|
66
|
+
* messages: [{ role: 'user', content: 'Summarize this document.' }],
|
|
67
|
+
* instructions: null
|
|
68
|
+
* };
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
export type Prompt = {
|
|
72
|
+
/** Prompt name used in tracing and errors. */
|
|
73
|
+
name: string;
|
|
74
|
+
|
|
75
|
+
/** Base directory for resolving relative prompt resources such as skills. */
|
|
76
|
+
fileDir: string;
|
|
77
|
+
|
|
78
|
+
/** Interpolation values associated with the prompt. Defaults to `{}` when validated. */
|
|
79
|
+
variables: PromptVariables;
|
|
80
|
+
|
|
81
|
+
/** General configuration for the LLM */
|
|
82
|
+
config: {
|
|
83
|
+
/**
|
|
84
|
+
* LLM provider.
|
|
85
|
+
*
|
|
86
|
+
* Built-in: `'anthropic'`, `'openai'`, `'azure'`, `'amazon-bedrock'`, `'google-vertex'`,
|
|
87
|
+
* `'perplexity'`. Legacy aliases `'bedrock'` and `'vertex'` are deprecated but still accepted
|
|
88
|
+
* in prompts and normalized to their canonical names with a warning. Custom providers
|
|
89
|
+
* registered via {@link registerProvider} are also accepted.
|
|
90
|
+
*/
|
|
91
|
+
provider: string;
|
|
92
|
+
|
|
93
|
+
/** Model name/identifier */
|
|
94
|
+
model: string;
|
|
95
|
+
|
|
96
|
+
/** Generation temperature. Supported range and behavior vary by provider. */
|
|
97
|
+
temperature?: number;
|
|
98
|
+
|
|
99
|
+
/** Maximum number of tokens in the response. */
|
|
100
|
+
maxOutputTokens?: number;
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Maximum number of tokens in the response.
|
|
104
|
+
*
|
|
105
|
+
* @deprecated Use `maxOutputTokens`.
|
|
106
|
+
*/
|
|
107
|
+
maxTokens?: number;
|
|
108
|
+
|
|
109
|
+
/** Nucleus sampling value. Usually set instead of `temperature`. */
|
|
110
|
+
topP?: number;
|
|
111
|
+
|
|
112
|
+
/** Limits sampling to the top K token choices. */
|
|
113
|
+
topK?: number;
|
|
114
|
+
|
|
115
|
+
/** Penalizes tokens that already appear in the prompt or generated output. */
|
|
116
|
+
presencePenalty?: number;
|
|
117
|
+
|
|
118
|
+
/** Penalizes tokens according to how often they appear. */
|
|
119
|
+
frequencyPenalty?: number;
|
|
120
|
+
|
|
121
|
+
/** Sequences that stop text generation when produced. */
|
|
122
|
+
stopSequences?: string[];
|
|
123
|
+
|
|
124
|
+
/** Tool-loop iterations when `stopWhen` is omitted. Always a positive integer after load (default 10). */
|
|
125
|
+
maxSteps: number;
|
|
126
|
+
|
|
127
|
+
/** Number of images to generate */
|
|
128
|
+
n?: number;
|
|
129
|
+
|
|
130
|
+
/** Maximum images to request per provider call */
|
|
131
|
+
maxImagesPerCall?: number;
|
|
132
|
+
|
|
133
|
+
/** Image size, for example `1024x1024` */
|
|
134
|
+
size?: `${number}x${number}`;
|
|
135
|
+
|
|
136
|
+
/** Image aspect ratio, for example `16:9` */
|
|
137
|
+
aspectRatio?: `${number}:${number}`;
|
|
138
|
+
|
|
139
|
+
/** Random seed for deterministic text or image generation when supported */
|
|
140
|
+
seed?: number;
|
|
141
|
+
|
|
142
|
+
/** Skill file or directory paths relative to the prompt file. Always a `string[]` after load (`[]` if unset). */
|
|
143
|
+
skills: string[];
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Provider-specific tools with configuration.
|
|
147
|
+
*
|
|
148
|
+
* @example Vertex googleSearch with config
|
|
149
|
+
* ```yaml
|
|
150
|
+
* tools:
|
|
151
|
+
* googleSearch:
|
|
152
|
+
* mode: MODE_DYNAMIC
|
|
153
|
+
* dynamicThreshold: 0.8
|
|
154
|
+
* ```
|
|
155
|
+
*
|
|
156
|
+
* @example OpenAI webSearch with filters
|
|
157
|
+
* ```yaml
|
|
158
|
+
* tools:
|
|
159
|
+
* webSearch:
|
|
160
|
+
* searchContextSize: high
|
|
161
|
+
* filters:
|
|
162
|
+
* allowedDomains: [wikipedia.org]
|
|
163
|
+
* ```
|
|
164
|
+
*/
|
|
165
|
+
tools?: Record<string, Record<string, unknown>>;
|
|
166
|
+
|
|
167
|
+
/** Provider-specific options */
|
|
168
|
+
providerOptions?: Record<string, unknown>;
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Named, reusable per-message `providerOptions` sets, referenced from message blocks via the
|
|
172
|
+
* `options="<name>"` attribute. Each value is a provider-namespaced options object, e.g.
|
|
173
|
+
* `{ anthropic: { cacheControl: { type: 'ephemeral' } } }`.
|
|
174
|
+
*/
|
|
175
|
+
messageOptions?: Record<string, Record<string, Record<string, unknown>>>;
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
/** Array of messages in the conversation */
|
|
179
|
+
messages: PromptMessage[];
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* The whole trimmed prompt body when its first meaningful token is plain text. Always set after
|
|
183
|
+
* `loadPrompt`: a non-empty string with `messages: []` for instruction mode, or `null` when the
|
|
184
|
+
* body starts with markup and is parsed into messages.
|
|
185
|
+
*/
|
|
186
|
+
instructions: string | null;
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
type AnyAiOutput = AIOutputNamespace.Output<unknown, unknown, unknown>;
|
|
190
|
+
type DefaultRuntimeContext = Record<string, unknown>;
|
|
191
|
+
type CompatibleToolSchemaKey = 'inputSchema' | 'outputSchema' | 'contextSchema';
|
|
192
|
+
type WithoutToolSchemaBrands<T> = T extends unknown ? {
|
|
193
|
+
[K in keyof T]: K extends CompatibleToolSchemaKey ? unknown : T[K];
|
|
194
|
+
} : never;
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Structurally-compatible AI SDK 7 tool shape.
|
|
198
|
+
*
|
|
199
|
+
* This derives from AI SDK's `ToolSet` and widens only schema fields so tools from packages
|
|
200
|
+
* resolved with a different Zod peer instance remain assignable.
|
|
201
|
+
*/
|
|
202
|
+
export type CompatibleTool = WithoutToolSchemaBrands<ToolSet[string]>;
|
|
203
|
+
|
|
204
|
+
/** AI SDK tools accepted by Output APIs without requiring one exact Zod peer instance. */
|
|
205
|
+
export type CompatibleToolSet = Record<string, CompatibleTool>;
|
|
206
|
+
|
|
207
|
+
type PromptFileCallOptions = {
|
|
208
|
+
/** Prompt file name (e.g. 'summary@v1') */
|
|
209
|
+
prompt: string;
|
|
210
|
+
/** Variables to interpolate into the prompt file */
|
|
211
|
+
variables?: PromptVariables;
|
|
212
|
+
/** Override the stack-resolved prompt directory */
|
|
213
|
+
promptDir?: string;
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
type PromptObjectCallOptions = {
|
|
217
|
+
/** Loaded or custom prompt object. */
|
|
218
|
+
prompt: Prompt;
|
|
219
|
+
/** Prompt objects are already rendered and cannot receive interpolation variables. */
|
|
220
|
+
variables?: never;
|
|
221
|
+
/** Prompt objects are not resolved from a prompt directory. */
|
|
222
|
+
promptDir?: never;
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
type PromptCallOptions = PromptFileCallOptions | PromptObjectCallOptions;
|
|
226
|
+
|
|
227
|
+
type StopWhen<Tools extends ToolSet = ToolSet> =
|
|
228
|
+
StopCondition<NoInfer<Tools>, DefaultRuntimeContext> |
|
|
229
|
+
Array<StopCondition<NoInfer<Tools>, DefaultRuntimeContext>>;
|
|
230
|
+
|
|
231
|
+
type TextCallOptions<
|
|
232
|
+
Tools extends ToolSet = ToolSet,
|
|
233
|
+
OutputSpec extends AnyAiOutput = AnyAiOutput
|
|
234
|
+
> = PromptCallOptions & {
|
|
235
|
+
/** AI SDK tools, accepted structurally to tolerate different Zod peer versions. */
|
|
236
|
+
tools?: CompatibleToolSet;
|
|
237
|
+
/** Structured output specification */
|
|
238
|
+
output?: OutputSpec;
|
|
239
|
+
/** Tool choice, applied only when tools exist */
|
|
240
|
+
toolChoice?: ToolChoice<Tools>;
|
|
241
|
+
/** Caller stop condition; otherwise prompt `maxSteps` when tools exist */
|
|
242
|
+
stopWhen?: StopWhen<Tools>;
|
|
243
|
+
/** Abort signal for the request */
|
|
244
|
+
abortSignal?: AbortSignal;
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
/** Parameters accepted by {@link generateText}. */
|
|
248
|
+
export type GenerateTextParameters<
|
|
249
|
+
Tools extends ToolSet = ToolSet,
|
|
250
|
+
OutputSpec extends AnyAiOutput = AnyAiOutput
|
|
251
|
+
> = TextCallOptions<Tools, OutputSpec>;
|
|
252
|
+
|
|
253
|
+
/** Parameters accepted by {@link generateTextWithStreaming}. */
|
|
254
|
+
export type GenerateTextWithStreamingParameters<
|
|
255
|
+
Tools extends ToolSet = ToolSet,
|
|
256
|
+
OutputSpec extends AnyAiOutput = AnyAiOutput
|
|
257
|
+
> = TextCallOptions<Tools, OutputSpec> & {
|
|
258
|
+
/** Callback for every AI SDK 7 stream part, including lifecycle, boundary, terminal, text, reasoning, and tool parts. */
|
|
259
|
+
onChunk?: StreamTextOnChunkCallback<Tools>;
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
/** Parameters accepted by {@link streamText}. */
|
|
263
|
+
export type StreamTextParameters<
|
|
264
|
+
Tools extends ToolSet = ToolSet,
|
|
265
|
+
OutputSpec extends AnyAiOutput = AnyAiOutput
|
|
266
|
+
> = TextCallOptions<Tools, OutputSpec> & {
|
|
267
|
+
/** Callback for every AI SDK 7 stream part, including lifecycle, boundary, terminal, text, reasoning, and tool parts. */
|
|
268
|
+
onChunk?: StreamTextOnChunkCallback<Tools>;
|
|
269
|
+
/** Callback when a stream error occurs */
|
|
270
|
+
onError?: StreamTextOnErrorCallback;
|
|
271
|
+
/** Callback when the stream completes. Receives the wrapped AI SDK `onEnd` event with `result`, `cost`, and `sources`. */
|
|
272
|
+
onEnd?: WrappedStreamTextOnEndCallback<Tools>;
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
/** Runtime image bytes or an object with optional media type. */
|
|
276
|
+
export type GenerateImageInput =
|
|
277
|
+
| Buffer |
|
|
278
|
+
Uint8Array |
|
|
279
|
+
ArrayBuffer |
|
|
280
|
+
string |
|
|
281
|
+
{
|
|
282
|
+
data: Buffer | Uint8Array | ArrayBuffer | string;
|
|
283
|
+
mediaType?: string;
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
type GenerateImageInputs =
|
|
287
|
+
| {
|
|
288
|
+
/** Runtime image inputs for image-to-image generation */
|
|
289
|
+
images: GenerateImageInput[];
|
|
290
|
+
/** Optional mask for image editing */
|
|
291
|
+
mask?: GenerateImageInput;
|
|
292
|
+
} |
|
|
293
|
+
{
|
|
294
|
+
images?: undefined;
|
|
295
|
+
mask?: never;
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
/** Parameters accepted by {@link generateImage}. */
|
|
299
|
+
export type GenerateImageParameters = PromptCallOptions & GenerateImageInputs & {
|
|
300
|
+
/** Abort signal for the request */
|
|
301
|
+
abortSignal?: AbortSignal;
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
/** Agent constructor options. */
|
|
305
|
+
export type OutputAgentConstructorParameters<
|
|
306
|
+
OutputSpec extends AnyAiOutput = AnyAiOutput
|
|
307
|
+
> = PromptCallOptions & {
|
|
308
|
+
/** Structured output specification */
|
|
309
|
+
output?: OutputSpec;
|
|
310
|
+
/** AI SDK tools available during the reasoning loop */
|
|
311
|
+
tools?: CompatibleToolSet;
|
|
312
|
+
/** Caller stop condition; otherwise prompt `maxSteps` when tools exist */
|
|
313
|
+
stopWhen?: StopWhen;
|
|
314
|
+
/** Pluggable message store. Opt-in; stateless by default. */
|
|
315
|
+
messageStore?: MessageStore;
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
/** Agent {@link Agent.generate} options. */
|
|
319
|
+
export type OutputAgentGenerateParameters = {
|
|
320
|
+
messages?: ModelMessage[];
|
|
321
|
+
abortSignal?: AbortSignal;
|
|
322
|
+
toolChoice?: ToolChoice<ToolSet>;
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
/** Agent {@link Agent.generateWithStreaming} options. Completion is the returned promise; use `onChunk` for progress. */
|
|
326
|
+
export type OutputAgentGenerateWithStreamingParameters = OutputAgentGenerateParameters & {
|
|
327
|
+
onChunk?: StreamTextOnChunkCallback<ToolSet>;
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
/** Agent {@link Agent.stream} options. `onEnd` receives {@link WrappedStreamTextOnEndEvent} (`result`, `cost`, `sources`). */
|
|
331
|
+
export type OutputAgentStreamParameters = OutputAgentGenerateWithStreamingParameters & {
|
|
332
|
+
onEnd?: WrappedStreamTextOnEndCallback<ToolSet>;
|
|
333
|
+
onError?: StreamTextOnErrorCallback;
|
|
334
|
+
};
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* One entry of `generateText().sources` after merge (tool URLs plus provider sources).
|
|
338
|
+
* Same item type as AI SDK `GenerateTextResult['sources']` (`sourceType: 'url' | 'document'`).
|
|
339
|
+
* `ai` does not export a named `Source` type.
|
|
340
|
+
*/
|
|
341
|
+
export type ExtractedSource =
|
|
342
|
+
AIGenerateTextResult<ToolSet, DefaultRuntimeContext, AnyAiOutput>['sources'][number];
|
|
343
|
+
|
|
344
|
+
export type LLMGenerationUsageStatus = 'complete' | 'incomplete';
|
|
345
|
+
|
|
346
|
+
/** Token usage reported for one normalized LLM usage component. `tools` counts billable tool calls, not tokens. */
|
|
347
|
+
export interface LLMGenerationUsageItem {
|
|
348
|
+
group: 'input' | 'output' | 'tools';
|
|
349
|
+
label: string | null;
|
|
350
|
+
amount: number;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/** Normalized LLM token usage trace attribute. */
|
|
354
|
+
export interface LLMGenerationUsage extends BaseAttribute {
|
|
355
|
+
type: 'llm:generation:usage';
|
|
356
|
+
providerId: string;
|
|
357
|
+
modelId: string;
|
|
358
|
+
input: number | null;
|
|
359
|
+
output: number | null;
|
|
360
|
+
total: number | null;
|
|
361
|
+
status: LLMGenerationUsageStatus;
|
|
362
|
+
items: LLMGenerationUsageItem[];
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/** One priced usage line in the legacy LLM cost event. */
|
|
366
|
+
export interface LLMUsageEventItem {
|
|
367
|
+
type: string;
|
|
368
|
+
ppm: number;
|
|
369
|
+
amount: number;
|
|
370
|
+
total: number;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* Legacy `cost:llm:request` event payload.
|
|
375
|
+
*
|
|
376
|
+
* @deprecated Use the normalized `LLMGenerationUsage` and `LLMGenerationCost` payloads from the LLM generation metering event.
|
|
377
|
+
*/
|
|
378
|
+
export interface LLMUsageEvent {
|
|
379
|
+
type: 'llm:usage';
|
|
380
|
+
modelId: string;
|
|
381
|
+
usage: LLMUsageEventItem[];
|
|
382
|
+
readonly total: number;
|
|
383
|
+
readonly tokensUsed: number;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
export type LLMGenerationCostItemStatus = 'ok' | 'fallback' | 'missing';
|
|
387
|
+
export type LLMGenerationCostStatus = 'precise' | 'imprecise' | 'incomplete';
|
|
388
|
+
export type LLMGenerationCostPricingFreshness = 'live' | 'cached' | 'stale' | 'snapshot';
|
|
389
|
+
|
|
390
|
+
/** Cost calculated for one normalized LLM usage item. */
|
|
391
|
+
export interface LLMGenerationCostItem {
|
|
392
|
+
group: 'input' | 'output' | 'tools';
|
|
393
|
+
label: string | null;
|
|
394
|
+
amount: number;
|
|
395
|
+
ppm: number | null;
|
|
396
|
+
total: number | null;
|
|
397
|
+
status: LLMGenerationCostItemStatus;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
/** Normalized LLM generation cost trace attribute. */
|
|
401
|
+
export interface LLMGenerationCost extends BaseAttribute {
|
|
402
|
+
type: 'llm:generation:cost';
|
|
403
|
+
providerId: string;
|
|
404
|
+
modelId: string;
|
|
405
|
+
input: number | null;
|
|
406
|
+
output: number | null;
|
|
407
|
+
tools: number | null;
|
|
408
|
+
total: number | null;
|
|
409
|
+
status: LLMGenerationCostStatus;
|
|
410
|
+
/** How current the rate table was. Absent on costs recorded before this field existed. */
|
|
411
|
+
pricingFreshness?: LLMGenerationCostPricingFreshness | null;
|
|
412
|
+
items: LLMGenerationCostItem[];
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/** Payload emitted by the `llm:generation:metering` event. */
|
|
416
|
+
export interface LLMGenerationMeteringEvent {
|
|
417
|
+
usage: LLMGenerationUsage;
|
|
418
|
+
cost: LLMGenerationCost | null;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* `streamText` and agent `stream` `onEnd` event after the stream response wrapper: same as the AI SDK
|
|
423
|
+
* `onEnd` payload plus `result`, `cost`, and merged `sources`.
|
|
424
|
+
*/
|
|
425
|
+
export type WrappedStreamTextOnEndEvent<Tools extends ToolSet = ToolSet> =
|
|
426
|
+
Parameters<GenerateTextOnEndCallback<Tools, DefaultRuntimeContext>>[0] & {
|
|
427
|
+
result: string;
|
|
428
|
+
cost: LLMGenerationCost | null;
|
|
429
|
+
sources: ExtractedSource[];
|
|
430
|
+
};
|
|
431
|
+
|
|
432
|
+
export type WrappedStreamTextOnEndCallback<Tools extends ToolSet = ToolSet> = (
|
|
433
|
+
event: WrappedStreamTextOnEndEvent<Tools>
|
|
434
|
+
) => void | PromiseLike<void>;
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
* Result from generateText including full AI SDK response metadata.
|
|
438
|
+
* Extends AI SDK's GenerateTextResult with a unified `result` field.
|
|
439
|
+
* @typeParam Tools - The tools available for the model to call (preserves typing on steps)
|
|
440
|
+
*/
|
|
441
|
+
export type GenerateTextResult<
|
|
442
|
+
Tools extends ToolSet = ToolSet,
|
|
443
|
+
OutputSpec extends AnyAiOutput = AnyAiOutput
|
|
444
|
+
> = AIGenerateTextResult<Tools, DefaultRuntimeContext, OutputSpec> & {
|
|
445
|
+
/** Unified field name alias for 'text' */
|
|
446
|
+
result: string;
|
|
447
|
+
/** Calculated cost for the LLM call; `null` when pricing data is not available */
|
|
448
|
+
cost: LLMGenerationCost | null;
|
|
449
|
+
/** Merged tool + provider sources (url and document). Always an array. */
|
|
450
|
+
sources: ExtractedSource[];
|
|
451
|
+
};
|
|
452
|
+
|
|
453
|
+
/** Completed result from {@link generateTextWithStreaming}. */
|
|
454
|
+
export type GenerateTextWithStreamingResult<
|
|
455
|
+
Tools extends ToolSet = ToolSet,
|
|
456
|
+
OutputSpec extends AnyAiOutput = AnyAiOutput
|
|
457
|
+
> = GenerateTextResult<Tools, OutputSpec>;
|
|
458
|
+
|
|
459
|
+
/** Result from generateImage including a unified `result` field pointing at the first image. */
|
|
460
|
+
export type GenerateImageResult = AIGenerateImageResult & {
|
|
461
|
+
/** Unified field name alias for `image` */
|
|
462
|
+
result: AIGenerateImageResult['image'];
|
|
463
|
+
/** Calculated cost for the image generation call; `null` when pricing data is not available. */
|
|
464
|
+
cost: LLMGenerationCost | null;
|
|
465
|
+
};
|
|
466
|
+
|
|
467
|
+
/**
|
|
468
|
+
* Loads a prompt file and interpolates variables into its content.
|
|
469
|
+
*
|
|
470
|
+
* @param name - Name of the prompt file (without `.prompt` extension).
|
|
471
|
+
* @param variables - Variables to interpolate.
|
|
472
|
+
* @returns The loaded prompt object.
|
|
473
|
+
*/
|
|
474
|
+
export function loadPrompt(
|
|
475
|
+
name: string,
|
|
476
|
+
variables?: PromptVariables,
|
|
477
|
+
promptDir?: string
|
|
478
|
+
): Prompt;
|
|
479
|
+
|
|
480
|
+
/**
|
|
481
|
+
* Register a custom LLM provider for use in prompt files.
|
|
482
|
+
*
|
|
483
|
+
* @param name - Provider name (used in prompt config `provider` field)
|
|
484
|
+
* @param providerFn - Factory function that creates a model from a model name string
|
|
485
|
+
*
|
|
486
|
+
* @example
|
|
487
|
+
* ```ts
|
|
488
|
+
* import { createDeepSeek } from '@ai-sdk/deepseek';
|
|
489
|
+
* import { registerProvider } from '@outputai/core/llm';
|
|
490
|
+
*
|
|
491
|
+
* registerProvider('deepseek', createDeepSeek({ apiKey: '...' }));
|
|
492
|
+
* ```
|
|
493
|
+
*/
|
|
494
|
+
export function registerProvider(
|
|
495
|
+
name: string,
|
|
496
|
+
providerFn: ( modelName: string ) => unknown
|
|
497
|
+
): void;
|
|
498
|
+
|
|
499
|
+
/**
|
|
500
|
+
* Get the list of available provider names: built-in providers whose package is installed, plus custom registered ones.
|
|
501
|
+
*
|
|
502
|
+
* @returns Array of provider name strings
|
|
503
|
+
*/
|
|
504
|
+
export function getProviderNames(): string[];
|
|
505
|
+
|
|
506
|
+
/**
|
|
507
|
+
* Use an LLM model to generate text.
|
|
508
|
+
*
|
|
509
|
+
* This function is a wrapper over the AI SDK's `generateText`.
|
|
510
|
+
* The prompt sets `model`, `messages`, generation settings, `maxSteps`, `skills`, and
|
|
511
|
+
* `providerOptions`. Pass either a prompt filename with optional `promptDir` / `variables`, or a
|
|
512
|
+
* loaded or custom {@link Prompt} object. Other call arguments are `tools`, `output`, `toolChoice`,
|
|
513
|
+
* `stopWhen`, and `abortSignal`.
|
|
514
|
+
*
|
|
515
|
+
* @param args - Generation arguments. See {@link GenerateTextParameters}.
|
|
516
|
+
* @returns AI SDK response with text and metadata.
|
|
517
|
+
*/
|
|
518
|
+
export function generateText<
|
|
519
|
+
Tools extends ToolSet = ToolSet,
|
|
520
|
+
OutputSpec extends AnyAiOutput = AnyAiOutput
|
|
521
|
+
>(
|
|
522
|
+
args: GenerateTextParameters<Tools, OutputSpec>
|
|
523
|
+
): Promise<GenerateTextResult<Tools, OutputSpec>>;
|
|
524
|
+
|
|
525
|
+
/**
|
|
526
|
+
* Generate text over streaming transport and return a completed response.
|
|
527
|
+
*
|
|
528
|
+
* The stream is consumed internally. `onChunk` runs as parts arrive. Provider or
|
|
529
|
+
* transport errors reject the returned promise with the mapped error. Use {@link streamText}
|
|
530
|
+
* when you need `onEnd` / `onError` stream observers.
|
|
531
|
+
*
|
|
532
|
+
* @param args - Streaming arguments. See {@link GenerateTextWithStreamingParameters}.
|
|
533
|
+
* @returns Completed response with parsed output and generateText-compatible metadata.
|
|
534
|
+
*/
|
|
535
|
+
export function generateTextWithStreaming<
|
|
536
|
+
Tools extends ToolSet = ToolSet,
|
|
537
|
+
OutputSpec extends AnyAiOutput = AnyAiOutput
|
|
538
|
+
>(
|
|
539
|
+
args: GenerateTextWithStreamingParameters<Tools, OutputSpec>
|
|
540
|
+
): Promise<GenerateTextWithStreamingResult<Tools, OutputSpec>>;
|
|
541
|
+
|
|
542
|
+
/**
|
|
543
|
+
* Use an LLM model to stream text generation.
|
|
544
|
+
*
|
|
545
|
+
* This function is a wrapper over the AI SDK's `streamText`.
|
|
546
|
+
* The prompt sets `model`, `messages`, generation settings, `maxSteps`, `skills`, and
|
|
547
|
+
* `providerOptions`. Pass either a prompt filename with optional `promptDir` / `variables`, or a
|
|
548
|
+
* loaded or custom {@link Prompt} object. Other call arguments match {@link generateText}, plus
|
|
549
|
+
* `onChunk`, `onEnd`, and `onError`. `onEnd` is wrapped to add `result`, `cost`, and merged
|
|
550
|
+
* `sources`.
|
|
551
|
+
*
|
|
552
|
+
* @param args - Streaming arguments. See {@link StreamTextParameters}.
|
|
553
|
+
* @returns AI SDK stream result with textStream, stream, and metadata promises.
|
|
554
|
+
*/
|
|
555
|
+
export function streamText<
|
|
556
|
+
Tools extends ToolSet = ToolSet,
|
|
557
|
+
OutputSpec extends AnyAiOutput = AnyAiOutput
|
|
558
|
+
>(
|
|
559
|
+
args: StreamTextParameters<Tools, OutputSpec>
|
|
560
|
+
): AIStreamTextResult<Tools, DefaultRuntimeContext, OutputSpec>;
|
|
561
|
+
|
|
562
|
+
/**
|
|
563
|
+
* Use an image model to generate images from a prompt filename or object.
|
|
564
|
+
*
|
|
565
|
+
* The prompt supplies `model`, instructions, `n`, `size`, `aspectRatio`, `seed`,
|
|
566
|
+
* `maxImagesPerCall`, and `providerOptions`. Pass either a prompt filename with optional
|
|
567
|
+
* `promptDir` / `variables`, or a loaded or custom {@link Prompt} object. Other call arguments are
|
|
568
|
+
* `images`, `mask`, and `abortSignal`.
|
|
569
|
+
*
|
|
570
|
+
* @param args - Image generation arguments. See {@link GenerateImageParameters}.
|
|
571
|
+
* @returns AI SDK image response with `result` aliasing the first image.
|
|
572
|
+
*/
|
|
573
|
+
export function generateImage(
|
|
574
|
+
args: GenerateImageParameters
|
|
575
|
+
): Promise<GenerateImageResult>;
|
|
576
|
+
|
|
577
|
+
/** Pluggable message store for multi-turn Agent interactions. */
|
|
578
|
+
export interface MessageStore {
|
|
579
|
+
getMessages(): ModelMessage[] | Promise<ModelMessage[]>;
|
|
580
|
+
addMessages( messages: ModelMessage[] ): void | Promise<void>;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
/**
|
|
584
|
+
* Agent wraps an internal AI SDK ToolLoopAgent with Output.ai prompt loading and validation.
|
|
585
|
+
*
|
|
586
|
+
* @example Workflow step - variables per call, stateless
|
|
587
|
+
* ```ts
|
|
588
|
+
* const reviewer = new Agent({
|
|
589
|
+
* prompt: 'reviewer@v1',
|
|
590
|
+
* output: aiSdk.Output.object({ schema: z.object({ summary: z.string() }) })
|
|
591
|
+
* });
|
|
592
|
+
* const result = await reviewer.generate();
|
|
593
|
+
* ```
|
|
594
|
+
*
|
|
595
|
+
* @example Interactive - fixed setup, message history
|
|
596
|
+
* ```ts
|
|
597
|
+
* const chatbot = new Agent({
|
|
598
|
+
* prompt: 'chatbot@v1',
|
|
599
|
+
* messageStore: { getMessages() { return []; }, addMessages() {} }
|
|
600
|
+
* });
|
|
601
|
+
* const r1 = await chatbot.generate({ messages: [{ role: 'user', content: 'Hello' }] });
|
|
602
|
+
* ```
|
|
603
|
+
*/
|
|
604
|
+
export declare class Agent<
|
|
605
|
+
OutputSpec extends AnyAiOutput = AnyAiOutput
|
|
606
|
+
> {
|
|
607
|
+
constructor( params: OutputAgentConstructorParameters<OutputSpec> );
|
|
608
|
+
|
|
609
|
+
/**
|
|
610
|
+
* Run the agent and return when complete.
|
|
611
|
+
* Same augmented shape as {@link generateText}: `result`, `cost`, merged `sources`.
|
|
612
|
+
*/
|
|
613
|
+
generate( options?: OutputAgentGenerateParameters ): Promise<GenerateTextResult<ToolSet, OutputSpec>>;
|
|
614
|
+
|
|
615
|
+
/**
|
|
616
|
+
* Run the agent over streaming transport and return a completed response.
|
|
617
|
+
* `onChunk` runs as parts arrive. Provider and transport errors reject with the mapped error.
|
|
618
|
+
* Use {@link Agent.stream} when you need `onEnd` / `onError` stream observers.
|
|
619
|
+
*/
|
|
620
|
+
generateWithStreaming(
|
|
621
|
+
options?: OutputAgentGenerateWithStreamingParameters
|
|
622
|
+
): Promise<GenerateTextWithStreamingResult<ToolSet, OutputSpec>>;
|
|
623
|
+
|
|
624
|
+
/**
|
|
625
|
+
* Stream the agent's response.
|
|
626
|
+
* `onEnd` receives {@link WrappedStreamTextOnEndEvent} (`result`, `cost`, `sources`), matching {@link streamText}.
|
|
627
|
+
*/
|
|
628
|
+
stream( options?: OutputAgentStreamParameters ): Promise<
|
|
629
|
+
AIStreamTextResult<ToolSet, DefaultRuntimeContext, OutputSpec>
|
|
630
|
+
>;
|
|
631
|
+
}
|
package/src/llm/index.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { generateText, generateTextWithStreaming, streamText, generateImage } from './generate.js';
|
|
2
|
+
export { Agent } from './agent.js';
|
|
3
|
+
export { loadPrompt } from './prompt/loader.js';
|
|
4
|
+
export { registerProvider, getProviderNames } from './ai_provider.js';
|
|
5
|
+
export * as aiSdk from 'ai';
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { Role } from '../consts.js';
|
|
2
|
+
import { decode } from './interpolations.js';
|
|
3
|
+
import { FatalError } from '#errors';
|
|
4
|
+
import { parseMarkup } from './markup/nodes.js';
|
|
5
|
+
|
|
6
|
+
/** Merge two objects 2-level deep. */
|
|
7
|
+
const mergeOptions = ( base = {}, extra = {} ) => {
|
|
8
|
+
const merged = { ...base };
|
|
9
|
+
for ( const [ namespace, options ] of Object.entries( extra ) ) {
|
|
10
|
+
merged[namespace] = { ...merged[namespace], ...options };
|
|
11
|
+
}
|
|
12
|
+
return merged;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
/** Gets the options attribute from the message attributes */
|
|
16
|
+
const extractOptions = attributes => {
|
|
17
|
+
const { options, ...unsupportedAttributes } = attributes;
|
|
18
|
+
if ( Object.keys( unsupportedAttributes ).length > 0 ) {
|
|
19
|
+
throw new FatalError( 'Message has unsupported attributes. The only supported attribute is "options".' );
|
|
20
|
+
}
|
|
21
|
+
if ( options === true ) {
|
|
22
|
+
throw new FatalError( 'Message "options" attribute must have a value.' );
|
|
23
|
+
}
|
|
24
|
+
const rawOptions = options?.trim();
|
|
25
|
+
return rawOptions ? rawOptions.split( /\s+/ ) : null;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/** Merge down messageOptions selected from a list */
|
|
29
|
+
const resolveProviderOptions = ( options, messageOptions ) =>
|
|
30
|
+
options.reduce( ( result, option ) => {
|
|
31
|
+
if ( !messageOptions[option] ) {
|
|
32
|
+
throw new FatalError( `Message "options" attribute references unknown option "${option}" in \`config.messageOptions\`.` );
|
|
33
|
+
}
|
|
34
|
+
return mergeOptions( result, messageOptions[option] );
|
|
35
|
+
}, {} );
|
|
36
|
+
|
|
37
|
+
const promptRoleSet = new Set( [ Role.SYSTEM, Role.USER, Role.ASSISTANT ] );
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Extract messages or instructions from prompt content. A leading role tag yields
|
|
41
|
+
* messages and null instructions; otherwise instructions are the decoded body.
|
|
42
|
+
*/
|
|
43
|
+
export const parseContent = ( content, messageOptions ) => {
|
|
44
|
+
const nodes = parseMarkup( content );
|
|
45
|
+
|
|
46
|
+
if ( nodes.length === 0 ) {
|
|
47
|
+
return { messages: [], instructions: decode( content.trim() ) };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const invalidRole = nodes.find( node => !promptRoleSet.has( node.tagName ) );
|
|
51
|
+
if ( invalidRole ) {
|
|
52
|
+
throw new FatalError( `Message has invalid role "${invalidRole.tagName}".` );
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
messages: nodes.map( node => {
|
|
57
|
+
const options = extractOptions( node.attributes );
|
|
58
|
+
if ( options && Object.keys( messageOptions ?? {} ).length === 0 ) {
|
|
59
|
+
throw new FatalError( 'Message has "options" attribute but `config.messageOptions` is empty.' );
|
|
60
|
+
}
|
|
61
|
+
const providerOptions = options ? resolveProviderOptions( options, messageOptions ) : null;
|
|
62
|
+
return {
|
|
63
|
+
role: node.tagName.toLowerCase(),
|
|
64
|
+
content: decode( node.content.trim() ),
|
|
65
|
+
...( providerOptions && { providerOptions } )
|
|
66
|
+
};
|
|
67
|
+
} ),
|
|
68
|
+
instructions: null
|
|
69
|
+
};
|
|
70
|
+
};
|