pipeai 0.1.0 → 0.1.1
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 +36 -23
- package/dist/index.cjs +54 -34
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -3
- package/dist/index.d.ts +9 -3
- package/dist/index.js +54 -34
- package/dist/index.js.map +1 -1
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -117,15 +117,17 @@ const agent = new Agent<Ctx>({
|
|
|
117
117
|
|
|
118
118
|
### AI SDK callbacks
|
|
119
119
|
|
|
120
|
-
Same callback names as AI SDK v6, extended with `ctx` and `
|
|
120
|
+
Same callback names as AI SDK v6, extended with `ctx`, `input`, and `writer`. The AI SDK event payload is available as `result`. When the agent runs inside a streaming workflow, `writer` is available for writing metadata or custom stream parts:
|
|
121
121
|
|
|
122
122
|
```ts
|
|
123
123
|
const agent = new Agent<Ctx>({
|
|
124
124
|
id: "monitored",
|
|
125
125
|
model: openai("gpt-4o"),
|
|
126
126
|
prompt: (ctx, input) => input,
|
|
127
|
-
onStepFinish: ({ result, ctx }) => {
|
|
127
|
+
onStepFinish: ({ result, ctx, writer }) => {
|
|
128
128
|
console.log(`Step done, used ${result.usage.totalTokens} tokens`);
|
|
129
|
+
// Stream progress metadata to the client
|
|
130
|
+
writer?.write({ type: "metadata", value: { tokensUsed: result.usage.totalTokens } });
|
|
129
131
|
},
|
|
130
132
|
onFinish: ({ result, ctx }) => {
|
|
131
133
|
console.log(`Total: ${result.totalUsage.totalTokens} tokens`);
|
|
@@ -152,9 +154,9 @@ const agent = new Agent<Ctx>({
|
|
|
152
154
|
| `activeTools` | `Resolvable` | Subset of tool names to enable. |
|
|
153
155
|
| `toolChoice` | `Resolvable` | Tool choice strategy. Static or `(ctx, input) => toolChoice`. |
|
|
154
156
|
| `stopWhen` | `Resolvable` | Condition for stopping the tool loop. Static or `(ctx, input) => condition`. |
|
|
155
|
-
| `onStepFinish`| `({ result, ctx, input })`| Called after each step.
|
|
156
|
-
| `onFinish` | `({ result, ctx, input })`| Called when all steps complete. |
|
|
157
|
-
| `onError` | `({ error, ctx, input })` | Called on error. |
|
|
157
|
+
| `onStepFinish`| `({ result, ctx, input, writer? })`| Called after each step. `writer` available in streaming workflows. |
|
|
158
|
+
| `onFinish` | `({ result, ctx, input, writer? })`| Called when all steps complete. |
|
|
159
|
+
| `onError` | `({ error, ctx, input, writer? })` | Called on error. |
|
|
158
160
|
| `...` | AI SDK options | All other `streamText`/`generateText` options pass through (e.g. `temperature`, `maxTokens`, `maxRetries`, `headers`, `prepareStep`, `onChunk`, etc.). |
|
|
159
161
|
|
|
160
162
|
## `asTool()` — Agent as Tool
|
|
@@ -212,7 +214,7 @@ codingAgent.asTool(ctx, {
|
|
|
212
214
|
});
|
|
213
215
|
```
|
|
214
216
|
|
|
215
|
-
**
|
|
217
|
+
**Automatic streaming:** When `asTool()` is used inside a streaming workflow, sub-agents automatically use `stream()` and merge their output to the parent's stream — the user sees sub-agent responses in real-time. Outside of a streaming context (standalone use or generate mode), `asTool()` falls back to `generate()`. This is handled invisibly — no configuration needed.
|
|
216
218
|
|
|
217
219
|
## `asToolProvider()` — Deferred Context
|
|
218
220
|
|
|
@@ -236,11 +238,10 @@ This is useful when the agent is defined at module scope but the context isn't a
|
|
|
236
238
|
|
|
237
239
|
## defineTool — Context-Aware Tools
|
|
238
240
|
|
|
239
|
-
`defineTool` wraps a tool definition so the agent's runtime context is injected into every `execute` call. The `input` field maps to AI SDK's `parameters
|
|
241
|
+
`defineTool` wraps a tool definition so the agent's runtime context is injected into every `execute` call. The `input` field maps to AI SDK's `parameters`. When running inside a streaming workflow, the `writer` is automatically available in the third parameter for streaming metadata or progress updates to the client:
|
|
240
242
|
|
|
241
243
|
```ts
|
|
242
244
|
import { defineTool } from "pipeai";
|
|
243
|
-
import { tool } from "ai";
|
|
244
245
|
|
|
245
246
|
type Ctx = { db: Database; userId: string };
|
|
246
247
|
|
|
@@ -249,8 +250,11 @@ const define = defineTool<Ctx>();
|
|
|
249
250
|
const searchOrders = define({
|
|
250
251
|
description: "Search user orders",
|
|
251
252
|
input: z.object({ query: z.string() }),
|
|
252
|
-
execute: async ({ query }, ctx) => {
|
|
253
|
-
|
|
253
|
+
execute: async ({ query }, ctx, { writer }) => {
|
|
254
|
+
writer?.write({ type: "metadata", value: { status: "searching" } });
|
|
255
|
+
const results = await ctx.db.orders.search(ctx.userId, query);
|
|
256
|
+
writer?.write({ type: "metadata", value: { status: "done", count: results.length } });
|
|
257
|
+
return results;
|
|
254
258
|
},
|
|
255
259
|
});
|
|
256
260
|
|
|
@@ -271,6 +275,8 @@ const agent = new Agent<Ctx>({
|
|
|
271
275
|
});
|
|
272
276
|
```
|
|
273
277
|
|
|
278
|
+
The `writer` is `undefined` when running in generate mode or standalone — `?.` handles both cases naturally.
|
|
279
|
+
|
|
274
280
|
## Workflow
|
|
275
281
|
|
|
276
282
|
A `Workflow` chains agents and transformation steps into a typed pipeline. Context is read-only — agents communicate through outputs.
|
|
@@ -313,6 +319,7 @@ Workflows can be passed as steps into other workflows. The nested workflow's ste
|
|
|
313
319
|
// A reusable sub-workflow
|
|
314
320
|
const classifyAndRoute = Workflow.create<Ctx>()
|
|
315
321
|
.step(classifier, {
|
|
322
|
+
// Suppress the classifier's stream — only route the result
|
|
316
323
|
handleStream: async ({ result }) => { await result.text; },
|
|
317
324
|
})
|
|
318
325
|
.branch({
|
|
@@ -402,7 +409,10 @@ const pipeline = Workflow.create<Ctx>()
|
|
|
402
409
|
// Called during workflow.stream() — StreamTextResult (async access)
|
|
403
410
|
mapStreamResult: async ({ result }) => ({
|
|
404
411
|
text: await result.text,
|
|
405
|
-
files:
|
|
412
|
+
files: (await result.steps)
|
|
413
|
+
.flatMap(s => s.toolResults)
|
|
414
|
+
.filter(tr => tr.toolName === "writeFile")
|
|
415
|
+
.map(tr => tr.args.path),
|
|
406
416
|
}),
|
|
407
417
|
});
|
|
408
418
|
```
|
|
@@ -423,10 +433,11 @@ const pipeline = Workflow.create<Ctx>()
|
|
|
423
433
|
});
|
|
424
434
|
},
|
|
425
435
|
// Called during workflow.stream()
|
|
426
|
-
onStreamResult: async ({ result, ctx
|
|
436
|
+
onStreamResult: async ({ result, ctx }) => {
|
|
427
437
|
await ctx.db.conversations.save(ctx.userId, {
|
|
428
438
|
role: "assistant",
|
|
429
439
|
content: await result.text,
|
|
440
|
+
toolCalls: await result.toolCalls,
|
|
430
441
|
});
|
|
431
442
|
},
|
|
432
443
|
});
|
|
@@ -434,7 +445,7 @@ const pipeline = Workflow.create<Ctx>()
|
|
|
434
445
|
|
|
435
446
|
### Fine-grained stream control
|
|
436
447
|
|
|
437
|
-
Override how each agent's stream is merged into the workflow stream. By default, every agent's output is merged
|
|
448
|
+
Override how each agent's stream is merged into the workflow stream. By default, every agent's output is merged via `writer.merge(result.toUIMessageStream())`. Use `handleStream` to take control — the callback receives `{ result, writer, ctx }`:
|
|
438
449
|
|
|
439
450
|
```ts
|
|
440
451
|
const pipeline = Workflow.create<Ctx>()
|
|
@@ -442,14 +453,16 @@ const pipeline = Workflow.create<Ctx>()
|
|
|
442
453
|
// the structured classification output, only the final response
|
|
443
454
|
.step(classifier, {
|
|
444
455
|
handleStream: async ({ result }) => {
|
|
445
|
-
await result.text; // consume
|
|
456
|
+
await result.text; // consume without forwarding to the client
|
|
446
457
|
},
|
|
447
458
|
})
|
|
448
|
-
.
|
|
449
|
-
|
|
450
|
-
|
|
459
|
+
// Custom merging — e.g. add metadata annotations to the stream
|
|
460
|
+
.step(supportAgent, {
|
|
461
|
+
handleStream: async ({ result, writer, ctx }) => {
|
|
462
|
+
writer.write({ type: "metadata", value: { agentId: "support", userId: ctx.userId } });
|
|
463
|
+
writer.merge(result.toUIMessageStream());
|
|
464
|
+
},
|
|
451
465
|
});
|
|
452
|
-
// Only the selected agent's response streams to the client
|
|
453
466
|
```
|
|
454
467
|
|
|
455
468
|
### Array iteration via `foreach()`
|
|
@@ -485,7 +498,9 @@ const processItem = Workflow.create<Ctx, string>()
|
|
|
485
498
|
.step(analyzeAgent)
|
|
486
499
|
.step(enrichAgent);
|
|
487
500
|
|
|
488
|
-
pipeline.
|
|
501
|
+
const pipeline = Workflow.create<Ctx>()
|
|
502
|
+
.step("fetch-items", async ({ ctx }) => ctx.db.items.getAll())
|
|
503
|
+
.foreach(processItem, { concurrency: 5 });
|
|
489
504
|
```
|
|
490
505
|
|
|
491
506
|
**Type safety:** `foreach()` uses `ElementOf<TOutput>` to extract the array element type. If the previous step doesn't produce an array, the call is rejected at compile time.
|
|
@@ -671,11 +686,9 @@ const questionAgent = new Agent<Ctx>({
|
|
|
671
686
|
|
|
672
687
|
// 4. Compose workflow
|
|
673
688
|
const pipeline = Workflow.create<Ctx>()
|
|
674
|
-
// Classify silently —
|
|
689
|
+
// Classify silently — consume the stream without forwarding to client
|
|
675
690
|
.step(classifier, {
|
|
676
|
-
handleStream: async ({ result }) => {
|
|
677
|
-
await result.text;
|
|
678
|
-
},
|
|
691
|
+
handleStream: async ({ result }) => { await result.text; },
|
|
679
692
|
})
|
|
680
693
|
// Route to the right specialist based on classification
|
|
681
694
|
.branch({
|
package/dist/index.cjs
CHANGED
|
@@ -33,6 +33,31 @@ var import_ai2 = require("ai");
|
|
|
33
33
|
|
|
34
34
|
// src/tool-provider.ts
|
|
35
35
|
var import_ai = require("ai");
|
|
36
|
+
|
|
37
|
+
// src/utils.ts
|
|
38
|
+
var import_node_async_hooks = require("async_hooks");
|
|
39
|
+
var writerStorage = new import_node_async_hooks.AsyncLocalStorage();
|
|
40
|
+
function runWithWriter(writer, fn) {
|
|
41
|
+
return writerStorage.run(writer, fn);
|
|
42
|
+
}
|
|
43
|
+
function getActiveWriter() {
|
|
44
|
+
return writerStorage.getStore();
|
|
45
|
+
}
|
|
46
|
+
function resolveValue(value, ctx, input) {
|
|
47
|
+
if (typeof value === "function") {
|
|
48
|
+
return value(ctx, input);
|
|
49
|
+
}
|
|
50
|
+
return value;
|
|
51
|
+
}
|
|
52
|
+
async function extractOutput(result, hasStructuredOutput) {
|
|
53
|
+
if (hasStructuredOutput) {
|
|
54
|
+
const output = await result.output;
|
|
55
|
+
if (output !== void 0) return output;
|
|
56
|
+
}
|
|
57
|
+
return await result.text;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// src/tool-provider.ts
|
|
36
61
|
var TOOL_PROVIDER_BRAND = /* @__PURE__ */ Symbol.for("agent-workflow.ToolProvider");
|
|
37
62
|
var ToolProvider = class {
|
|
38
63
|
[TOOL_PROVIDER_BRAND] = true;
|
|
@@ -45,7 +70,7 @@ var ToolProvider = class {
|
|
|
45
70
|
return (0, import_ai.tool)({
|
|
46
71
|
...toolDef,
|
|
47
72
|
parameters: inputSchema,
|
|
48
|
-
execute: (input, options) => execute(input, context, options)
|
|
73
|
+
execute: (input, options) => execute(input, context, { ...options, writer: getActiveWriter() })
|
|
49
74
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
50
75
|
});
|
|
51
76
|
}
|
|
@@ -57,21 +82,6 @@ function isToolProvider(obj) {
|
|
|
57
82
|
return typeof obj === "object" && obj !== null && TOOL_PROVIDER_BRAND in obj;
|
|
58
83
|
}
|
|
59
84
|
|
|
60
|
-
// src/utils.ts
|
|
61
|
-
function resolveValue(value, ctx, input) {
|
|
62
|
-
if (typeof value === "function") {
|
|
63
|
-
return value(ctx, input);
|
|
64
|
-
}
|
|
65
|
-
return value;
|
|
66
|
-
}
|
|
67
|
-
async function extractOutput(result, hasStructuredOutput) {
|
|
68
|
-
if (hasStructuredOutput) {
|
|
69
|
-
const output = await result.output;
|
|
70
|
-
if (output !== void 0) return output;
|
|
71
|
-
}
|
|
72
|
-
return await result.text;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
85
|
// src/agent.ts
|
|
76
86
|
var Agent = class {
|
|
77
87
|
id;
|
|
@@ -136,7 +146,7 @@ var Agent = class {
|
|
|
136
146
|
return await (0, import_ai2.generateText)(options);
|
|
137
147
|
} catch (error) {
|
|
138
148
|
if (this.config.onError) {
|
|
139
|
-
await this.config.onError({ error, ctx, input });
|
|
149
|
+
await this.config.onError({ error, ctx, input, writer: getActiveWriter() });
|
|
140
150
|
}
|
|
141
151
|
throw error;
|
|
142
152
|
}
|
|
@@ -147,7 +157,7 @@ var Agent = class {
|
|
|
147
157
|
const options = this.buildCallOptions(resolved, ctx, input);
|
|
148
158
|
return (0, import_ai2.streamText)({
|
|
149
159
|
...options,
|
|
150
|
-
onError: this.config.onError ? ({ error }) => this.config.onError({ error, ctx, input }) : void 0
|
|
160
|
+
onError: this.config.onError ? ({ error }) => this.config.onError({ error, ctx, input, writer: getActiveWriter() }) : void 0
|
|
151
161
|
});
|
|
152
162
|
}
|
|
153
163
|
asTool(ctx, options) {
|
|
@@ -170,6 +180,13 @@ var Agent = class {
|
|
|
170
180
|
description: this.description,
|
|
171
181
|
parameters: this.config.input,
|
|
172
182
|
execute: async (toolInput) => {
|
|
183
|
+
const writer = getActiveWriter();
|
|
184
|
+
if (writer) {
|
|
185
|
+
const result2 = await this.stream(ctx, toolInput);
|
|
186
|
+
writer.merge(result2.toUIMessageStream());
|
|
187
|
+
if (options?.mapOutput) return options.mapOutput(result2);
|
|
188
|
+
return extractOutput(result2, this.hasOutput);
|
|
189
|
+
}
|
|
173
190
|
const result = await this.generate(ctx, toolInput);
|
|
174
191
|
if (options?.mapOutput) return options.mapOutput(result);
|
|
175
192
|
return extractOutput(result, this.hasOutput);
|
|
@@ -189,8 +206,8 @@ var Agent = class {
|
|
|
189
206
|
...resolved.messages ? { messages: resolved.messages } : { prompt: resolved.prompt ?? "" },
|
|
190
207
|
...resolved.system ? { system: resolved.system } : {},
|
|
191
208
|
...this.config.output ? { output: this.config.output } : {},
|
|
192
|
-
onStepFinish: this._onStepFinish ? (event) => this._onStepFinish({ result: event, ctx, input }) : void 0,
|
|
193
|
-
onFinish: this._onFinish ? (event) => this._onFinish({ result: event, ctx, input }) : void 0
|
|
209
|
+
onStepFinish: this._onStepFinish ? (event) => this._onStepFinish({ result: event, ctx, input, writer: getActiveWriter() }) : void 0,
|
|
210
|
+
onFinish: this._onFinish ? (event) => this._onFinish({ result: event, ctx, input, writer: getActiveWriter() }) : void 0
|
|
194
211
|
};
|
|
195
212
|
}
|
|
196
213
|
resolveConfig(ctx, input) {
|
|
@@ -363,20 +380,23 @@ var SealedWorkflow = class {
|
|
|
363
380
|
const input = state.output;
|
|
364
381
|
const hasStructuredOutput = agent.hasOutput;
|
|
365
382
|
if (state.mode === "stream" && state.writer) {
|
|
366
|
-
const
|
|
367
|
-
|
|
368
|
-
await
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
383
|
+
const writer = state.writer;
|
|
384
|
+
await runWithWriter(writer, async () => {
|
|
385
|
+
const result = await agent.stream(ctx, state.output);
|
|
386
|
+
if (options?.handleStream) {
|
|
387
|
+
await options.handleStream({ result, writer, ctx });
|
|
388
|
+
} else {
|
|
389
|
+
writer.merge(result.toUIMessageStream());
|
|
390
|
+
}
|
|
391
|
+
if (options?.onStreamResult) {
|
|
392
|
+
await options.onStreamResult({ result, ctx, input });
|
|
393
|
+
}
|
|
394
|
+
if (options?.mapStreamResult) {
|
|
395
|
+
state.output = await options.mapStreamResult({ result, ctx, input });
|
|
396
|
+
} else {
|
|
397
|
+
state.output = await extractOutput(result, hasStructuredOutput);
|
|
398
|
+
}
|
|
399
|
+
});
|
|
380
400
|
} else {
|
|
381
401
|
const result = await agent.generate(ctx, state.output);
|
|
382
402
|
if (options?.onGenerateResult) {
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/agent.ts","../src/tool-provider.ts","../src/utils.ts","../src/workflow.ts"],"sourcesContent":["export { Agent } from \"./agent\";\nexport type {\n AgentConfig,\n GenerateTextResult,\n StreamTextResult,\n} from \"./agent\";\n\nexport { Workflow, WorkflowBranchError, WorkflowLoopError } from \"./workflow\";\nexport type { SealedWorkflow } from \"./workflow\";\nexport type {\n AgentStepHooks,\n StepOptions,\n BranchCase,\n BranchSelect,\n RepeatOptions,\n WorkflowResult,\n WorkflowStreamResult,\n WorkflowStreamOptions,\n} from \"./workflow\";\n\nexport { defineTool } from \"./tool-provider\";\nexport type { ToolProviderConfig, IToolProvider } from \"./tool-provider\";\n\nexport type { MaybePromise, Resolvable } from \"./utils\";\n","import {\n generateText,\n streamText,\n tool,\n Output,\n type GenerateTextResult as AIGenerateTextResult,\n type StreamTextResult as AIStreamTextResult,\n type ModelMessage,\n type LanguageModel,\n type Tool,\n type ToolSet,\n type StopCondition,\n type ToolChoice,\n type OnStepFinishEvent,\n type OnFinishEvent,\n} from \"ai\";\n\n// Extract the Output interface type from the Output.object return type\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype OutputType<T = any> = ReturnType<typeof Output.object<T>>;\nimport type { ZodType } from \"zod\";\nimport { isToolProvider, TOOL_PROVIDER_BRAND, type IToolProvider } from \"./tool-provider\";\nimport { extractOutput, resolveValue, type MaybePromise, type Resolvable } from \"./utils\";\n\n// Tools config accepts both AI SDK tools and context-aware ToolProviders\ntype AgentToolSet<TContext> = Record<string, Tool | IToolProvider<TContext>>;\n\n// ── Result type aliases ─────────────────────────────────────────────\n\nexport type GenerateTextResult<TOOLS extends ToolSet = ToolSet, OUTPUT extends OutputType = OutputType> = AIGenerateTextResult<TOOLS, OUTPUT>;\nexport type StreamTextResult<TOOLS extends ToolSet = ToolSet, OUTPUT extends OutputType = OutputType> = AIStreamTextResult<TOOLS, OUTPUT>;\n\n// ── AI SDK passthrough types ────────────────────────────────────────\n\n// Extract options types from both AI SDK entry points\ntype StreamTextOptions = Parameters<typeof streamText>[0];\ntype GenerateTextOptions = Parameters<typeof generateText>[0];\n\n// Keys we replace with resolvable or context-enriched versions\ntype ManagedKeys =\n | 'model' | 'system' | 'prompt' | 'messages'\n | 'tools' | 'activeTools' | 'toolChoice' | 'stopWhen'\n | 'output' | 'onFinish' | 'onStepFinish' | 'onError';\n\n// Combine options from both streamText and generateText.\n// Each side contributes its unique props; shared props merge naturally.\n// Stream-only props (onChunk, onAbort) are ignored by generateText.\n// Generate-only props (experimental_include.responseBody) are ignored by streamText.\ntype AIPassthroughOptions =\n Omit<StreamTextOptions, ManagedKeys> &\n Omit<GenerateTextOptions, ManagedKeys>;\n\n// ── Resolved config (output of resolveConfig / resolveConfigAsync) ──\n\ninterface ResolvedAgentConfig {\n model: LanguageModel;\n prompt: string | undefined;\n system: string | undefined;\n messages: ModelMessage[] | undefined;\n tools: Record<string, Tool>;\n activeTools: string[] | undefined;\n toolChoice: ToolChoice<ToolSet> | undefined;\n stopWhen: StopCondition<ToolSet> | Array<StopCondition<ToolSet>> | undefined;\n}\n\n// ── Agent Configuration ─────────────────────────────────────────────\n\nexport interface AgentConfig<\n TContext,\n TInput = void,\n TOutput = void,\n> extends AIPassthroughOptions {\n // ── Custom (not in AI SDK) ──\n id: string;\n description?: string;\n input?: ZodType<TInput>;\n output?: OutputType<TOutput>;\n\n // ── Resolvable (our versions of AI SDK properties) ──\n model: Resolvable<TContext, TInput, LanguageModel>;\n system?: Resolvable<TContext, TInput, string>;\n prompt?: Resolvable<TContext, TInput, string>;\n messages?: Resolvable<TContext, TInput, ModelMessage[]>;\n tools?: Resolvable<TContext, TInput, AgentToolSet<TContext>>;\n activeTools?: Resolvable<TContext, TInput, string[]>;\n toolChoice?: Resolvable<TContext, TInput, ToolChoice<ToolSet>>;\n stopWhen?: Resolvable<TContext, TInput, StopCondition<ToolSet> | Array<StopCondition<ToolSet>>>;\n\n // ── Context-enriched callbacks (replace AI SDK versions) ──\n onStepFinish?: (params: { result: OnStepFinishEvent; ctx: Readonly<TContext>; input: TInput }) => MaybePromise<void>;\n onFinish?: (params: { result: OnFinishEvent; ctx: Readonly<TContext>; input: TInput }) => MaybePromise<void>;\n onError?: (params: { error: unknown; ctx: Readonly<TContext>; input: TInput }) => MaybePromise<void>;\n}\n\n// ── Agent ───────────────────────────────────────────────────────────\n\nexport class Agent<\n TContext,\n TInput = void,\n TOutput = void,\n> {\n readonly id: string;\n readonly description: string;\n readonly hasOutput: boolean;\n private readonly config: AgentConfig<TContext, TInput, TOutput>;\n private readonly _hasDynamicConfig: boolean;\n private readonly _resolvedStaticTools: Record<string, Tool> | null = null;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private readonly _passthrough: Record<string, any>;\n private readonly _onStepFinish: AgentConfig<TContext, TInput, TOutput>['onStepFinish'];\n private readonly _onFinish: AgentConfig<TContext, TInput, TOutput>['onFinish'];\n\n constructor(config: AgentConfig<TContext, TInput, TOutput>) {\n this.id = config.id;\n this.description = config.description ?? \"\";\n this.hasOutput = config.output !== undefined;\n this.config = config;\n this._hasDynamicConfig = [\n config.model, config.system, config.prompt,\n config.messages, config.tools, config.activeTools,\n config.toolChoice, config.stopWhen,\n ].some(v => typeof v === \"function\");\n\n // Cache tools when config is static and contains no ToolProviders.\n // Avoids re-iterating the tools map on every generate()/stream() call.\n if (!this._hasDynamicConfig) {\n const rawTools = (config.tools as AgentToolSet<TContext> | undefined) ?? {};\n const hasProvider = Object.values(rawTools).some(v => isToolProvider(v));\n if (!hasProvider) {\n this._resolvedStaticTools = rawTools as Record<string, Tool>;\n }\n }\n\n // Pre-compute the passthrough (AI SDK options we don't manage) once,\n // rather than destructuring on every generate()/stream() call.\n const {\n id: _id, description: _desc, input: _inputSchema, output: _output,\n model: _m, system: _s, prompt: _p, messages: _msg,\n tools: _t, activeTools: _at, toolChoice: _tc, stopWhen: _sw,\n onStepFinish, onFinish, onError: _onError,\n ...passthrough\n } = config;\n this._passthrough = passthrough;\n this._onStepFinish = onStepFinish;\n this._onFinish = onFinish;\n }\n\n async generate(ctx: TContext, ...args: TInput extends void ? [input?: TInput] : [input: TInput]): Promise<GenerateTextResult> {\n const input = args[0] as TInput;\n const resolved = await this.resolveConfig(ctx, input);\n const options = this.buildCallOptions(resolved, ctx, input);\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return await generateText(options as any);\n } catch (error: unknown) {\n if (this.config.onError) {\n await this.config.onError({ error, ctx, input });\n }\n throw error;\n }\n }\n\n async stream(ctx: TContext, ...args: TInput extends void ? [input?: TInput] : [input: TInput]): Promise<StreamTextResult> {\n const input = args[0] as TInput;\n const resolved = await this.resolveConfig(ctx, input);\n const options = this.buildCallOptions(resolved, ctx, input);\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return streamText({\n ...options,\n onError: this.config.onError\n ? ({ error }: { error: unknown }) => this.config.onError!({ error, ctx, input })\n : undefined,\n } as any);\n }\n\n asTool(ctx: TContext, options?: {\n mapOutput?: (result: GenerateTextResult) => MaybePromise<TOutput>;\n }): Tool {\n return this.createToolInstance(ctx, options);\n }\n\n asToolProvider(options?: {\n mapOutput?: (result: GenerateTextResult) => MaybePromise<TOutput>;\n }): IToolProvider<TContext> {\n if (!this.config.input) {\n throw new Error(`Agent \"${this.id}\": asToolProvider() requires an input schema`);\n }\n\n return {\n [TOOL_PROVIDER_BRAND]: true as const,\n createTool: (ctx: Readonly<TContext>) => this.createToolInstance(ctx as TContext, options),\n };\n }\n\n private createToolInstance(ctx: TContext, options?: {\n mapOutput?: (result: GenerateTextResult) => MaybePromise<TOutput>;\n }): Tool {\n if (!this.config.input) {\n throw new Error(`Agent \"${this.id}\": asTool() requires an input schema`);\n }\n\n return tool({\n description: this.description,\n parameters: this.config.input,\n execute: async (toolInput: TInput) => {\n const result = await (this.generate as (ctx: TContext, input: TInput) => Promise<GenerateTextResult>)(ctx, toolInput);\n if (options?.mapOutput) return options.mapOutput(result);\n return extractOutput(result, this.hasOutput);\n },\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } as any);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private buildCallOptions(resolved: ResolvedAgentConfig, ctx: TContext, input: TInput): Record<string, any> {\n return {\n ...this._passthrough,\n model: resolved.model,\n tools: resolved.tools,\n activeTools: resolved.activeTools,\n toolChoice: resolved.toolChoice,\n stopWhen: resolved.stopWhen,\n ...(resolved.messages\n ? { messages: resolved.messages }\n : { prompt: resolved.prompt ?? \"\" }),\n ...(resolved.system ? { system: resolved.system } : {}),\n ...(this.config.output ? { output: this.config.output } : {}),\n onStepFinish: this._onStepFinish\n ? (event: OnStepFinishEvent) => this._onStepFinish!({ result: event, ctx, input })\n : undefined,\n onFinish: this._onFinish\n ? (event: OnFinishEvent) => this._onFinish!({ result: event, ctx, input })\n : undefined,\n };\n }\n\n private resolveConfig(ctx: TContext, input: TInput): ResolvedAgentConfig | Promise<ResolvedAgentConfig> {\n if (!this._hasDynamicConfig) {\n return {\n model: this.config.model as LanguageModel,\n prompt: this.config.prompt as string | undefined,\n system: this.config.system as string | undefined,\n messages: this.config.messages as ModelMessage[] | undefined,\n tools: this._resolvedStaticTools ?? this.resolveTools(\n (this.config.tools as AgentToolSet<TContext> | undefined) ?? {}, ctx\n ),\n activeTools: this.config.activeTools as string[] | undefined,\n toolChoice: this.config.toolChoice as ToolChoice<ToolSet> | undefined,\n stopWhen: this.config.stopWhen as StopCondition<ToolSet> | Array<StopCondition<ToolSet>> | undefined,\n };\n }\n return this.resolveConfigAsync(ctx, input);\n }\n\n private async resolveConfigAsync(ctx: TContext, input: TInput): Promise<ResolvedAgentConfig> {\n const [model, prompt, system, messages, rawTools, activeTools, toolChoice, stopWhen] = await Promise.all([\n resolveValue(this.config.model, ctx, input),\n resolveValue(this.config.prompt, ctx, input),\n resolveValue(this.config.system, ctx, input),\n resolveValue(this.config.messages, ctx, input),\n resolveValue(this.config.tools, ctx, input),\n resolveValue(this.config.activeTools, ctx, input),\n resolveValue(this.config.toolChoice, ctx, input),\n resolveValue(this.config.stopWhen, ctx, input),\n ]);\n const tools = this.resolveTools(rawTools ?? {}, ctx);\n return { model, prompt, system, messages, tools, activeTools, toolChoice, stopWhen };\n }\n\n private resolveTools(\n tools: AgentToolSet<TContext>,\n ctx: TContext\n ): Record<string, Tool> {\n const entries = Object.entries(tools);\n if (entries.length === 0) return tools as Record<string, Tool>;\n let hasProvider = false;\n const resolved: Record<string, Tool> = {};\n for (const [key, toolOrProvider] of entries) {\n if (isToolProvider<TContext>(toolOrProvider)) {\n hasProvider = true;\n resolved[key] = toolOrProvider.createTool(ctx as Readonly<TContext>);\n } else {\n resolved[key] = toolOrProvider as Tool;\n }\n }\n return hasProvider ? resolved : (tools as Record<string, Tool>);\n }\n}\n","import { tool, type Tool, type ToolExecutionOptions, type FlexibleSchema } from \"ai\";\n\nexport const TOOL_PROVIDER_BRAND = Symbol.for(\"agent-workflow.ToolProvider\");\n\nexport type ToolProviderConfig<TContext, TInput, TOutput> = {\n description?: string;\n input: FlexibleSchema<TInput>;\n output?: FlexibleSchema<unknown>;\n providerOptions?: unknown;\n execute: (input: TInput, ctx: Readonly<TContext>, options?: ToolExecutionOptions) => Promise<TOutput>;\n};\n\nexport interface IToolProvider<TContext> {\n readonly [TOOL_PROVIDER_BRAND]: true;\n createTool(context: Readonly<TContext>): Tool;\n}\n\nexport class ToolProvider<\n TContext,\n TInput = unknown,\n TOutput = unknown,\n> implements IToolProvider<TContext> {\n readonly [TOOL_PROVIDER_BRAND] = true as const;\n private readonly config: ToolProviderConfig<TContext, TInput, TOutput>;\n\n constructor(config: ToolProviderConfig<TContext, TInput, TOutput>) {\n this.config = config;\n }\n\n createTool(context: Readonly<TContext>): Tool {\n const { execute, input: inputSchema, ...toolDef } = this.config;\n return tool({\n ...toolDef,\n parameters: inputSchema,\n execute: (input: TInput, options?: ToolExecutionOptions) => execute(input, context, options),\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } as any);\n }\n}\n\nexport function defineTool<TContext>() {\n return <TInput, TOutput>(\n config: ToolProviderConfig<TContext, TInput, TOutput>\n ): ToolProvider<TContext, TInput, TOutput> => new ToolProvider(config);\n}\n\nexport function isToolProvider<TContext>(obj: unknown): obj is IToolProvider<TContext> {\n return (\n typeof obj === \"object\" &&\n obj !== null &&\n TOOL_PROVIDER_BRAND in obj\n );\n}\n","export type MaybePromise<T> = T | Promise<T>;\n\n/**\n * A value that can be static or derived from context and input.\n * Used for agent config fields that may need runtime resolution.\n *\n * Functions may return a Promise for async resolution; static values are always sync.\n */\nexport type Resolvable<TCtx, TInput, TValue> =\n | TValue\n | ((ctx: Readonly<TCtx>, input: TInput) => TValue | Promise<TValue>);\n\nexport function resolveValue<TCtx, TInput, TValue>(\n value: Resolvable<TCtx, TInput, TValue>,\n ctx: TCtx,\n input: TInput\n): TValue | Promise<TValue>;\nexport function resolveValue<TCtx, TInput, TValue>(\n value: Resolvable<TCtx, TInput, TValue> | undefined,\n ctx: TCtx,\n input: TInput\n): TValue | Promise<TValue> | undefined {\n if (typeof value === \"function\") {\n return (value as (ctx: TCtx, input: TInput) => TValue | Promise<TValue>)(ctx, input);\n }\n return value;\n}\n\n/**\n * Extract structured output from an AI SDK result, falling back to text.\n * Works for both generate (sync .output/.text) and stream (async .output/.text) results.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport async function extractOutput(result: any, hasStructuredOutput: boolean): Promise<unknown> {\n if (hasStructuredOutput) {\n const output = await result.output;\n if (output !== undefined) return output;\n }\n return await result.text;\n}\n","import {\n createUIMessageStream,\n type UIMessageStreamWriter,\n} from \"ai\";\nimport { type Agent, type GenerateTextResult, type StreamTextResult } from \"./agent\";\nimport { extractOutput, type MaybePromise } from \"./utils\";\n\n// ── Error Types ─────────────────────────────────────────────────────\n\nexport class WorkflowBranchError extends Error {\n constructor(\n public readonly branchType: \"predicate\" | \"select\",\n message: string,\n ) {\n super(message);\n this.name = \"WorkflowBranchError\";\n }\n}\n\nexport class WorkflowLoopError extends Error {\n constructor(\n public readonly iterations: number,\n public readonly maxIterations: number,\n ) {\n super(`Loop exceeded maximum iterations (${maxIterations})`);\n this.name = \"WorkflowLoopError\";\n }\n}\n\n// ── Shared Agent Step Hooks ─────────────────────────────────────────\n\nexport interface AgentStepHooks<TContext, TOutput, TNextOutput> {\n mapGenerateResult?: (params: { result: GenerateTextResult; ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<TNextOutput>;\n mapStreamResult?: (params: { result: StreamTextResult; ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<TNextOutput>;\n onGenerateResult?: (params: { result: GenerateTextResult; ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<void>;\n onStreamResult?: (params: { result: StreamTextResult; ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<void>;\n handleStream?: (params: {\n result: StreamTextResult;\n writer: UIMessageStreamWriter;\n ctx: Readonly<TContext>;\n }) => MaybePromise<void>;\n}\n\n// ── Step Options ────────────────────────────────────────────────────\n\nexport type StepOptions<TContext, TOutput, TNextOutput> = AgentStepHooks<TContext, TOutput, TNextOutput>;\n\n// ── Branch Types ────────────────────────────────────────────────────\n\nexport interface BranchCase<TContext, TOutput, TNextOutput> extends AgentStepHooks<TContext, TOutput, TNextOutput> {\n when?: (params: { ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<boolean>;\n agent: Agent<TContext, TOutput, TNextOutput>;\n}\n\nexport interface BranchSelect<TContext, TOutput, TKeys extends string, TNextOutput> extends AgentStepHooks<TContext, TOutput, TNextOutput> {\n select: (params: { ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<TKeys>;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n agents: Record<TKeys, Agent<TContext, any, TNextOutput>>;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n fallback?: Agent<TContext, any, TNextOutput>;\n}\n\n// ── Result Types ────────────────────────────────────────────────────\n\nexport interface WorkflowResult<TOutput> {\n output: TOutput;\n}\n\nexport interface WorkflowStreamResult<TOutput> {\n stream: ReadableStream;\n output: Promise<TOutput>;\n}\n\nexport interface WorkflowStreamOptions {\n onError?: (error: unknown) => string;\n onFinish?: () => MaybePromise<void>;\n}\n\n// ── Loop Types ──────────────────────────────────────────────────────\n\ntype LoopPredicate<TContext, TOutput> = (params: {\n output: TOutput;\n ctx: Readonly<TContext>;\n iterations: number;\n}) => MaybePromise<boolean>;\n\n// Exactly one of `until` or `while` — never both.\nexport type RepeatOptions<TContext, TOutput> =\n | { until: LoopPredicate<TContext, TOutput>; while?: never; maxIterations?: number }\n | { while: LoopPredicate<TContext, TOutput>; until?: never; maxIterations?: number };\n\n// Extracts the element type from an array type. Resolves to `never` for non-arrays,\n// making foreach uncallable at compile time when the previous step doesn't produce an array.\ntype ElementOf<T> = T extends readonly (infer E)[] ? E : never;\n\n// ── Step Node ───────────────────────────────────────────────────────\n\ntype StepNode =\n | { readonly type: \"step\"; readonly id: string; readonly execute: (state: RuntimeState) => MaybePromise<void> }\n | { readonly type: \"catch\"; readonly id: string; readonly catchFn: (params: { error: unknown; ctx: unknown; lastOutput: unknown; stepId: string }) => MaybePromise<unknown> }\n | { readonly type: \"finally\"; readonly id: string; readonly execute: (state: RuntimeState) => MaybePromise<void> };\n\ninterface RuntimeState {\n ctx: unknown;\n output: unknown;\n mode: \"generate\" | \"stream\";\n writer?: UIMessageStreamWriter;\n}\n\n// ── Sealed Workflow (returned by finally — execution only) ───────────\n\nexport class SealedWorkflow<\n TContext,\n TInput = void,\n TOutput = void,\n> {\n readonly id?: string;\n protected readonly steps: ReadonlyArray<StepNode>;\n\n protected constructor(steps: ReadonlyArray<StepNode>, id?: string) {\n this.steps = steps;\n this.id = id;\n }\n\n // ── Execution ─────────────────────────────────────────────────\n\n async generate(ctx: TContext, ...args: TInput extends void ? [input?: TInput] : [input: TInput]): Promise<WorkflowResult<TOutput>> {\n const input = args[0];\n const state: RuntimeState = {\n ctx,\n output: input,\n mode: \"generate\",\n };\n\n await this.execute(state);\n\n return {\n output: state.output as TOutput,\n };\n }\n\n stream(\n ctx: TContext,\n ...args: TInput extends void\n ? [input?: TInput, options?: WorkflowStreamOptions]\n : [input: TInput, options?: WorkflowStreamOptions]\n ): WorkflowStreamResult<TOutput> {\n const input = args[0];\n const options = args[1] as WorkflowStreamOptions | undefined;\n\n let resolveOutput: (value: TOutput) => void;\n let rejectOutput: (error: unknown) => void;\n const outputPromise = new Promise<TOutput>((res, rej) => {\n resolveOutput = res;\n rejectOutput = rej;\n });\n\n // Prevent unhandled rejection warning if the consumer never awaits `output`.\n // The original promise still rejects normally when awaited.\n outputPromise.catch(() => {});\n\n const stream = createUIMessageStream({\n execute: async ({ writer }) => {\n const state: RuntimeState = {\n ctx,\n output: input,\n mode: \"stream\",\n writer,\n };\n\n try {\n await this.execute(state);\n resolveOutput(state.output as TOutput);\n } catch (error) {\n rejectOutput!(error);\n throw error;\n }\n },\n ...(options?.onError ? { onError: options.onError } : {}),\n ...(options?.onFinish ? { onFinish: options.onFinish } : {}),\n });\n\n return {\n stream,\n output: outputPromise,\n };\n }\n\n // ── Internal: execute pipeline ────────────────────────────────\n\n protected async execute(state: RuntimeState): Promise<void> {\n if (this.steps.length === 0) {\n throw new Error(\"Workflow has no steps. Add at least one step before calling generate() or stream().\");\n }\n\n let pendingError: { error: unknown; stepId: string } | null = null;\n\n for (const node of this.steps) {\n if (node.type === \"finally\") {\n await node.execute(state);\n continue;\n }\n\n if (node.type === \"catch\") {\n if (!pendingError) continue;\n try {\n state.output = await node.catchFn({\n error: pendingError.error,\n ctx: state.ctx,\n lastOutput: state.output,\n stepId: pendingError.stepId,\n });\n pendingError = null;\n } catch (catchError) {\n pendingError = { error: catchError, stepId: node.id };\n }\n continue;\n }\n\n // type === \"step\" — skip while in error state\n if (pendingError) continue;\n\n try {\n await node.execute(state);\n } catch (error) {\n pendingError = { error, stepId: node.id };\n }\n }\n\n if (pendingError) throw pendingError.error;\n }\n\n // ── Internal: execute a nested workflow within a step/loop ─────\n // Defined on SealedWorkflow (not Workflow) because TypeScript's protected\n // access rules only allow calling workflow.execute() from the same class.\n\n protected async executeNestedWorkflow(\n state: RuntimeState,\n workflow: SealedWorkflow<TContext, unknown, unknown>,\n ): Promise<void> {\n await workflow.execute(state);\n }\n\n // ── Internal: execute an agent within a step/branch ───────────\n // In stream mode, output extraction awaits the full stream before returning.\n // Streaming benefits the client (incremental output), not pipeline throughput —\n // each step still runs sequentially.\n\n protected async executeAgent<TAgentInput, TNextOutput>(\n state: RuntimeState,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n agent: Agent<TContext, any, TNextOutput>,\n ctx: TContext,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n options?: AgentStepHooks<TContext, any, TNextOutput>,\n ): Promise<void> {\n const input = state.output as TAgentInput;\n const hasStructuredOutput = agent.hasOutput;\n\n if (state.mode === \"stream\" && state.writer) {\n const result = await (agent.stream as (ctx: TContext, input: unknown) => Promise<StreamTextResult>)(ctx, state.output);\n\n if (options?.handleStream) {\n await options.handleStream({ result, writer: state.writer, ctx });\n } else {\n state.writer.merge(result.toUIMessageStream());\n }\n\n if (options?.onStreamResult) {\n await options.onStreamResult({ result, ctx, input });\n }\n\n if (options?.mapStreamResult) {\n state.output = await options.mapStreamResult({ result, ctx, input });\n } else {\n state.output = await extractOutput(result, hasStructuredOutput);\n }\n } else {\n const result = await (agent.generate as (ctx: TContext, input: unknown) => Promise<GenerateTextResult>)(ctx, state.output);\n\n if (options?.onGenerateResult) {\n await options.onGenerateResult({ result, ctx, input });\n }\n\n if (options?.mapGenerateResult) {\n state.output = await options.mapGenerateResult({ result, ctx, input });\n } else {\n state.output = await extractOutput(result, hasStructuredOutput);\n }\n }\n }\n}\n\n// ── Workflow ────────────────────────────────────────────────────────\n\nexport class Workflow<\n TContext,\n TInput = void,\n TOutput = void,\n> extends SealedWorkflow<TContext, TInput, TOutput> {\n\n private constructor(steps: ReadonlyArray<StepNode> = [], id?: string) {\n super(steps, id);\n }\n\n static create<TContext, TInput = void>(options?: { id?: string }): Workflow<TContext, TInput, TInput> {\n return new Workflow<TContext, TInput, TInput>([], options?.id);\n }\n\n static from<TContext, TInput, TOutput>(\n agent: Agent<TContext, TInput, TOutput>,\n options?: StepOptions<TContext, TInput, TOutput>\n ): Workflow<TContext, TInput, TOutput> {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, any>([]).step(agent, options);\n }\n\n // ── step: agent overload ──────────────────────────────────────\n\n step<TNextOutput>(\n agent: Agent<TContext, TOutput, TNextOutput>,\n options?: StepOptions<TContext, TOutput, TNextOutput>\n ): Workflow<TContext, TInput, TNextOutput>;\n\n // ── step: nested workflow overload ─────────────────────────────\n\n step<TNextOutput>(\n workflow: SealedWorkflow<TContext, TOutput, TNextOutput>,\n ): Workflow<TContext, TInput, TNextOutput>;\n\n // ── step: transform overload (replaces map + tap) ─────────────\n\n step<TNextOutput>(\n id: string,\n fn: (params: { ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<TNextOutput>\n ): Workflow<TContext, TInput, TNextOutput>;\n\n // ── step: implementation ──────────────────────────────────────\n\n step<TNextOutput>(\n target: Agent<TContext, TOutput, TNextOutput> | SealedWorkflow<TContext, TOutput, TNextOutput> | string,\n optionsOrFn?: StepOptions<TContext, TOutput, TNextOutput> | ((params: { ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<TNextOutput>)\n ): Workflow<TContext, TInput, TNextOutput> {\n // Nested workflow overload: step(workflow)\n if (target instanceof SealedWorkflow) {\n const workflow = target;\n const node: StepNode = {\n type: \"step\",\n id: workflow.id ?? \"nested-workflow\",\n execute: async (state) => {\n await this.executeNestedWorkflow(state, workflow as SealedWorkflow<TContext, unknown, unknown>);\n },\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNextOutput>([...this.steps, node] as any, this.id);\n }\n\n // Transform overload: step(id, fn)\n if (typeof target === \"string\") {\n if (typeof optionsOrFn !== \"function\") {\n throw new Error(`Workflow step(\"${target}\"): second argument must be a function`);\n }\n const fn = optionsOrFn as (params: { ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<TNextOutput>;\n const node: StepNode = {\n type: \"step\",\n id: target,\n execute: async (state) => {\n state.output = await fn({\n ctx: state.ctx as Readonly<TContext>,\n input: state.output as TOutput,\n });\n },\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNextOutput>([...this.steps, node] as any, this.id);\n }\n\n // Agent overload: step(agent, options?)\n const agent = target;\n const options = optionsOrFn as StepOptions<TContext, TOutput, TNextOutput> | undefined;\n const node: StepNode = {\n type: \"step\",\n id: agent.id,\n execute: async (state) => {\n const ctx = state.ctx as TContext;\n await this.executeAgent(state, agent, ctx, options);\n },\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNextOutput>([...this.steps, node] as any, this.id);\n }\n\n // ── branch: predicate routing (array) ─────────────────────────\n\n branch<TNextOutput>(\n cases: BranchCase<TContext, TOutput, TNextOutput>[]\n ): Workflow<TContext, TInput, TNextOutput>;\n\n // ── branch: key routing (select) ──────────────────────────────\n\n branch<TKeys extends string, TNextOutput>(\n config: BranchSelect<TContext, TOutput, TKeys, TNextOutput>\n ): Workflow<TContext, TInput, TNextOutput>;\n\n // ── branch: implementation ────────────────────────────────────\n\n branch<TKeys extends string, TNextOutput>(\n casesOrConfig: BranchCase<TContext, TOutput, TNextOutput>[] | BranchSelect<TContext, TOutput, TKeys, TNextOutput>\n ): Workflow<TContext, TInput, TNextOutput> {\n if (Array.isArray(casesOrConfig)) {\n return this.branchPredicate(casesOrConfig);\n }\n return this.branchSelect(casesOrConfig);\n }\n\n private branchPredicate<TNextOutput>(\n cases: BranchCase<TContext, TOutput, TNextOutput>[]\n ): Workflow<TContext, TInput, TNextOutput> {\n const node: StepNode = {\n type: \"step\",\n id: \"branch:predicate\",\n execute: async (state) => {\n const ctx = state.ctx as TContext;\n const input = state.output as TOutput;\n\n for (const branchCase of cases) {\n if (branchCase.when) {\n const match = await branchCase.when({ ctx, input });\n if (!match) continue;\n }\n\n // Matched (or no `when` = default)\n await this.executeAgent(state, branchCase.agent, ctx, branchCase);\n return;\n }\n\n throw new WorkflowBranchError(\"predicate\", `No branch matched and no default branch (a case without \\`when\\`) was provided. Input: ${JSON.stringify(input)}`);\n },\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNextOutput>([...this.steps, node] as any, this.id);\n }\n\n private branchSelect<TKeys extends string, TNextOutput>(\n config: BranchSelect<TContext, TOutput, TKeys, TNextOutput>\n ): Workflow<TContext, TInput, TNextOutput> {\n const node: StepNode = {\n type: \"step\",\n id: \"branch:select\",\n execute: async (state) => {\n const ctx = state.ctx as TContext;\n const input = state.output as TOutput;\n const key = await config.select({ ctx, input });\n\n let agent = config.agents[key];\n if (!agent) {\n if (config.fallback) {\n agent = config.fallback;\n } else {\n throw new WorkflowBranchError(\"select\", `No agent found for key \"${key}\" and no fallback provided. Available keys: ${Object.keys(config.agents).join(\", \")}`);\n }\n }\n\n await this.executeAgent(state, agent, ctx, config);\n },\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNextOutput>([...this.steps, node] as any, this.id);\n }\n\n // ── foreach: array iteration ─────────────────────────────────\n\n foreach<TNextOutput>(\n target: Agent<TContext, ElementOf<TOutput>, TNextOutput> | SealedWorkflow<TContext, ElementOf<TOutput>, TNextOutput>,\n options?: { concurrency?: number },\n ): Workflow<TContext, TInput, TNextOutput[]> {\n const concurrency = options?.concurrency ?? 1;\n const isWorkflow = target instanceof SealedWorkflow;\n const id = isWorkflow ? (target.id ?? \"foreach\") : `foreach:${(target as Agent<TContext, ElementOf<TOutput>, TNextOutput>).id}`;\n\n const node: StepNode = {\n type: \"step\",\n id,\n execute: async (state) => {\n const items = state.output;\n if (!Array.isArray(items)) {\n throw new Error(`foreach \"${id}\": expected array input, got ${typeof items}`);\n }\n\n const ctx = state.ctx as TContext;\n const results: unknown[] = new Array(items.length);\n\n // Streaming is intentionally not propagated to foreach items —\n // each item runs in generate mode because merging interleaved\n // streams from parallel items into a single writer is not supported.\n const executeItem = async (item: unknown, index: number) => {\n const itemState: RuntimeState = { ctx: state.ctx, output: item, mode: \"generate\" };\n if (isWorkflow) {\n await this.executeNestedWorkflow(itemState, target as SealedWorkflow<TContext, unknown, unknown>);\n } else {\n await this.executeAgent(itemState, target as Agent<TContext, unknown, TNextOutput>, ctx);\n }\n results[index] = itemState.output;\n };\n\n if (concurrency <= 1) {\n for (let i = 0; i < items.length; i++) {\n await executeItem(items[i], i);\n }\n } else {\n for (let i = 0; i < items.length; i += concurrency) {\n const batch = items.slice(i, i + concurrency);\n await Promise.all(batch.map((item, j) => executeItem(item, i + j)));\n }\n }\n\n state.output = results;\n },\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNextOutput[]>([...this.steps, node] as any, this.id);\n }\n\n // ── repeat: conditional loop ─────────────────────────────────\n\n repeat(\n target: Agent<TContext, TOutput, TOutput> | SealedWorkflow<TContext, TOutput, TOutput>,\n options: RepeatOptions<TContext, TOutput>,\n ): Workflow<TContext, TInput, TOutput> {\n const maxIterations = options.maxIterations ?? 10;\n const isWorkflow = target instanceof SealedWorkflow;\n const id = isWorkflow ? (target.id ?? \"repeat\") : `repeat:${(target as Agent<TContext, TOutput, TOutput>).id}`;\n const predicate: LoopPredicate<TContext, TOutput> = options.until\n ?? (async (p) => !(await options.while!(p)));\n\n const node: StepNode = {\n type: \"step\",\n id,\n execute: async (state) => {\n const ctx = state.ctx as TContext;\n\n for (let i = 1; i <= maxIterations; i++) {\n if (isWorkflow) {\n await this.executeNestedWorkflow(state, target as SealedWorkflow<TContext, unknown, unknown>);\n } else {\n await this.executeAgent(state, target as Agent<TContext, TOutput, TOutput>, ctx);\n }\n\n const done = await predicate({\n output: state.output as TOutput,\n ctx: ctx as Readonly<TContext>,\n iterations: i,\n });\n if (done) return;\n }\n\n throw new WorkflowLoopError(maxIterations, maxIterations);\n },\n };\n return new Workflow<TContext, TInput, TOutput>([...this.steps, node], this.id);\n }\n\n // ── catch ─────────────────────────────────────────────────────\n\n catch(\n id: string,\n fn: (params: { error: unknown; ctx: Readonly<TContext>; lastOutput: TOutput; stepId: string }) => MaybePromise<TOutput>\n ): Workflow<TContext, TInput, TOutput> {\n if (!this.steps.some(s => s.type === \"step\")) {\n throw new Error(`Workflow: catch(\"${id}\") requires at least one preceding step.`);\n }\n const node: StepNode = {\n type: \"catch\",\n id,\n catchFn: fn as (params: { error: unknown; ctx: unknown; lastOutput: unknown; stepId: string }) => MaybePromise<unknown>,\n };\n return new Workflow<TContext, TInput, TOutput>([...this.steps, node], this.id);\n }\n\n // ── finally (terminal — returns sealed workflow) ──────────────\n\n finally(\n id: string,\n fn: (params: { ctx: Readonly<TContext> }) => MaybePromise<void>\n ): SealedWorkflow<TContext, TInput, TOutput> {\n const node: StepNode = {\n type: \"finally\",\n id,\n execute: async (state) => {\n await fn({ ctx: state.ctx as Readonly<TContext> });\n },\n };\n return new SealedWorkflow<TContext, TInput, TOutput>([...this.steps, node], this.id);\n }\n}\n\n"],"mappings":"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","names":["import_ai","import_ai","node"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/agent.ts","../src/tool-provider.ts","../src/utils.ts","../src/workflow.ts"],"sourcesContent":["export { Agent } from \"./agent\";\nexport type {\n AgentConfig,\n GenerateTextResult,\n StreamTextResult,\n} from \"./agent\";\n\nexport { Workflow, WorkflowBranchError, WorkflowLoopError } from \"./workflow\";\nexport type { SealedWorkflow } from \"./workflow\";\nexport type {\n AgentStepHooks,\n StepOptions,\n BranchCase,\n BranchSelect,\n RepeatOptions,\n WorkflowResult,\n WorkflowStreamResult,\n WorkflowStreamOptions,\n} from \"./workflow\";\n\nexport { defineTool } from \"./tool-provider\";\nexport type { ToolProviderConfig, ToolExecuteOptions, IToolProvider } from \"./tool-provider\";\n\nexport type { MaybePromise, Resolvable } from \"./utils\";\n","import {\n generateText,\n streamText,\n tool,\n Output,\n type GenerateTextResult as AIGenerateTextResult,\n type StreamTextResult as AIStreamTextResult,\n type UIMessageStreamWriter,\n type ModelMessage,\n type LanguageModel,\n type Tool,\n type ToolSet,\n type StopCondition,\n type ToolChoice,\n type OnStepFinishEvent,\n type OnFinishEvent,\n} from \"ai\";\n\n// Extract the Output interface type from the Output.object return type\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype OutputType<T = any> = ReturnType<typeof Output.object<T>>;\nimport type { ZodType } from \"zod\";\nimport { isToolProvider, TOOL_PROVIDER_BRAND, type IToolProvider } from \"./tool-provider\";\nimport { extractOutput, getActiveWriter, resolveValue, type MaybePromise, type Resolvable } from \"./utils\";\n\n// Tools config accepts both AI SDK tools and context-aware ToolProviders\ntype AgentToolSet<TContext> = Record<string, Tool | IToolProvider<TContext>>;\n\n// ── Result type aliases ─────────────────────────────────────────────\n\nexport type GenerateTextResult<TOOLS extends ToolSet = ToolSet, OUTPUT extends OutputType = OutputType> = AIGenerateTextResult<TOOLS, OUTPUT>;\nexport type StreamTextResult<TOOLS extends ToolSet = ToolSet, OUTPUT extends OutputType = OutputType> = AIStreamTextResult<TOOLS, OUTPUT>;\n\n// ── AI SDK passthrough types ────────────────────────────────────────\n\n// Extract options types from both AI SDK entry points\ntype StreamTextOptions = Parameters<typeof streamText>[0];\ntype GenerateTextOptions = Parameters<typeof generateText>[0];\n\n// Keys we replace with resolvable or context-enriched versions\ntype ManagedKeys =\n | 'model' | 'system' | 'prompt' | 'messages'\n | 'tools' | 'activeTools' | 'toolChoice' | 'stopWhen'\n | 'output' | 'onFinish' | 'onStepFinish' | 'onError';\n\n// Combine options from both streamText and generateText.\n// Each side contributes its unique props; shared props merge naturally.\n// Stream-only props (onChunk, onAbort) are ignored by generateText.\n// Generate-only props (experimental_include.responseBody) are ignored by streamText.\ntype AIPassthroughOptions =\n Omit<StreamTextOptions, ManagedKeys> &\n Omit<GenerateTextOptions, ManagedKeys>;\n\n// ── Resolved config (output of resolveConfig / resolveConfigAsync) ──\n\ninterface ResolvedAgentConfig {\n model: LanguageModel;\n prompt: string | undefined;\n system: string | undefined;\n messages: ModelMessage[] | undefined;\n tools: Record<string, Tool>;\n activeTools: string[] | undefined;\n toolChoice: ToolChoice<ToolSet> | undefined;\n stopWhen: StopCondition<ToolSet> | Array<StopCondition<ToolSet>> | undefined;\n}\n\n// ── Agent Configuration ─────────────────────────────────────────────\n\nexport interface AgentConfig<\n TContext,\n TInput = void,\n TOutput = void,\n> extends AIPassthroughOptions {\n // ── Custom (not in AI SDK) ──\n id: string;\n description?: string;\n input?: ZodType<TInput>;\n output?: OutputType<TOutput>;\n\n // ── Resolvable (our versions of AI SDK properties) ──\n model: Resolvable<TContext, TInput, LanguageModel>;\n system?: Resolvable<TContext, TInput, string>;\n prompt?: Resolvable<TContext, TInput, string>;\n messages?: Resolvable<TContext, TInput, ModelMessage[]>;\n tools?: Resolvable<TContext, TInput, AgentToolSet<TContext>>;\n activeTools?: Resolvable<TContext, TInput, string[]>;\n toolChoice?: Resolvable<TContext, TInput, ToolChoice<ToolSet>>;\n stopWhen?: Resolvable<TContext, TInput, StopCondition<ToolSet> | Array<StopCondition<ToolSet>>>;\n\n // ── Context-enriched callbacks (replace AI SDK versions) ──\n // `writer` is available when the agent runs inside a streaming workflow.\n onStepFinish?: (params: { result: OnStepFinishEvent; ctx: Readonly<TContext>; input: TInput; writer?: UIMessageStreamWriter }) => MaybePromise<void>;\n onFinish?: (params: { result: OnFinishEvent; ctx: Readonly<TContext>; input: TInput; writer?: UIMessageStreamWriter }) => MaybePromise<void>;\n onError?: (params: { error: unknown; ctx: Readonly<TContext>; input: TInput; writer?: UIMessageStreamWriter }) => MaybePromise<void>;\n}\n\n// ── Agent ───────────────────────────────────────────────────────────\n\nexport class Agent<\n TContext,\n TInput = void,\n TOutput = void,\n> {\n readonly id: string;\n readonly description: string;\n readonly hasOutput: boolean;\n private readonly config: AgentConfig<TContext, TInput, TOutput>;\n private readonly _hasDynamicConfig: boolean;\n private readonly _resolvedStaticTools: Record<string, Tool> | null = null;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private readonly _passthrough: Record<string, any>;\n private readonly _onStepFinish: AgentConfig<TContext, TInput, TOutput>['onStepFinish'];\n private readonly _onFinish: AgentConfig<TContext, TInput, TOutput>['onFinish'];\n\n constructor(config: AgentConfig<TContext, TInput, TOutput>) {\n this.id = config.id;\n this.description = config.description ?? \"\";\n this.hasOutput = config.output !== undefined;\n this.config = config;\n this._hasDynamicConfig = [\n config.model, config.system, config.prompt,\n config.messages, config.tools, config.activeTools,\n config.toolChoice, config.stopWhen,\n ].some(v => typeof v === \"function\");\n\n // Cache tools when config is static and contains no ToolProviders.\n // Avoids re-iterating the tools map on every generate()/stream() call.\n if (!this._hasDynamicConfig) {\n const rawTools = (config.tools as AgentToolSet<TContext> | undefined) ?? {};\n const hasProvider = Object.values(rawTools).some(v => isToolProvider(v));\n if (!hasProvider) {\n this._resolvedStaticTools = rawTools as Record<string, Tool>;\n }\n }\n\n // Pre-compute the passthrough (AI SDK options we don't manage) once,\n // rather than destructuring on every generate()/stream() call.\n const {\n id: _id, description: _desc, input: _inputSchema, output: _output,\n model: _m, system: _s, prompt: _p, messages: _msg,\n tools: _t, activeTools: _at, toolChoice: _tc, stopWhen: _sw,\n onStepFinish, onFinish, onError: _onError,\n ...passthrough\n } = config;\n this._passthrough = passthrough;\n this._onStepFinish = onStepFinish;\n this._onFinish = onFinish;\n }\n\n async generate(ctx: TContext, ...args: TInput extends void ? [input?: TInput] : [input: TInput]): Promise<GenerateTextResult> {\n const input = args[0] as TInput;\n const resolved = await this.resolveConfig(ctx, input);\n const options = this.buildCallOptions(resolved, ctx, input);\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return await generateText(options as any);\n } catch (error: unknown) {\n if (this.config.onError) {\n await this.config.onError({ error, ctx, input, writer: getActiveWriter() });\n }\n throw error;\n }\n }\n\n async stream(ctx: TContext, ...args: TInput extends void ? [input?: TInput] : [input: TInput]): Promise<StreamTextResult> {\n const input = args[0] as TInput;\n const resolved = await this.resolveConfig(ctx, input);\n const options = this.buildCallOptions(resolved, ctx, input);\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return streamText({\n ...options,\n onError: this.config.onError\n ? ({ error }: { error: unknown }) => this.config.onError!({ error, ctx, input, writer: getActiveWriter() })\n : undefined,\n } as any);\n }\n\n asTool(ctx: TContext, options?: {\n mapOutput?: (result: GenerateTextResult) => MaybePromise<TOutput>;\n }): Tool {\n return this.createToolInstance(ctx, options);\n }\n\n asToolProvider(options?: {\n mapOutput?: (result: GenerateTextResult) => MaybePromise<TOutput>;\n }): IToolProvider<TContext> {\n if (!this.config.input) {\n throw new Error(`Agent \"${this.id}\": asToolProvider() requires an input schema`);\n }\n\n return {\n [TOOL_PROVIDER_BRAND]: true as const,\n createTool: (ctx: Readonly<TContext>) => this.createToolInstance(ctx as TContext, options),\n };\n }\n\n private createToolInstance(ctx: TContext, options?: {\n mapOutput?: (result: GenerateTextResult) => MaybePromise<TOutput>;\n }): Tool {\n if (!this.config.input) {\n throw new Error(`Agent \"${this.id}\": asTool() requires an input schema`);\n }\n\n return tool({\n description: this.description,\n parameters: this.config.input,\n execute: async (toolInput: TInput) => {\n // When inside a streaming workflow, automatically use stream() and merge to the active writer.\n // Otherwise fall back to generate().\n const writer = getActiveWriter();\n if (writer) {\n const result = await (this.stream as (ctx: TContext, input: TInput) => Promise<StreamTextResult>)(ctx, toolInput);\n writer.merge(result.toUIMessageStream());\n if (options?.mapOutput) return options.mapOutput(result as unknown as GenerateTextResult);\n return extractOutput(result, this.hasOutput);\n }\n const result = await (this.generate as (ctx: TContext, input: TInput) => Promise<GenerateTextResult>)(ctx, toolInput);\n if (options?.mapOutput) return options.mapOutput(result);\n return extractOutput(result, this.hasOutput);\n },\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } as any);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private buildCallOptions(resolved: ResolvedAgentConfig, ctx: TContext, input: TInput): Record<string, any> {\n return {\n ...this._passthrough,\n model: resolved.model,\n tools: resolved.tools,\n activeTools: resolved.activeTools,\n toolChoice: resolved.toolChoice,\n stopWhen: resolved.stopWhen,\n ...(resolved.messages\n ? { messages: resolved.messages }\n : { prompt: resolved.prompt ?? \"\" }),\n ...(resolved.system ? { system: resolved.system } : {}),\n ...(this.config.output ? { output: this.config.output } : {}),\n onStepFinish: this._onStepFinish\n ? (event: OnStepFinishEvent) => this._onStepFinish!({ result: event, ctx, input, writer: getActiveWriter() })\n : undefined,\n onFinish: this._onFinish\n ? (event: OnFinishEvent) => this._onFinish!({ result: event, ctx, input, writer: getActiveWriter() })\n : undefined,\n };\n }\n\n private resolveConfig(ctx: TContext, input: TInput): ResolvedAgentConfig | Promise<ResolvedAgentConfig> {\n if (!this._hasDynamicConfig) {\n return {\n model: this.config.model as LanguageModel,\n prompt: this.config.prompt as string | undefined,\n system: this.config.system as string | undefined,\n messages: this.config.messages as ModelMessage[] | undefined,\n tools: this._resolvedStaticTools ?? this.resolveTools(\n (this.config.tools as AgentToolSet<TContext> | undefined) ?? {}, ctx\n ),\n activeTools: this.config.activeTools as string[] | undefined,\n toolChoice: this.config.toolChoice as ToolChoice<ToolSet> | undefined,\n stopWhen: this.config.stopWhen as StopCondition<ToolSet> | Array<StopCondition<ToolSet>> | undefined,\n };\n }\n return this.resolveConfigAsync(ctx, input);\n }\n\n private async resolveConfigAsync(ctx: TContext, input: TInput): Promise<ResolvedAgentConfig> {\n const [model, prompt, system, messages, rawTools, activeTools, toolChoice, stopWhen] = await Promise.all([\n resolveValue(this.config.model, ctx, input),\n resolveValue(this.config.prompt, ctx, input),\n resolveValue(this.config.system, ctx, input),\n resolveValue(this.config.messages, ctx, input),\n resolveValue(this.config.tools, ctx, input),\n resolveValue(this.config.activeTools, ctx, input),\n resolveValue(this.config.toolChoice, ctx, input),\n resolveValue(this.config.stopWhen, ctx, input),\n ]);\n const tools = this.resolveTools(rawTools ?? {}, ctx);\n return { model, prompt, system, messages, tools, activeTools, toolChoice, stopWhen };\n }\n\n private resolveTools(\n tools: AgentToolSet<TContext>,\n ctx: TContext\n ): Record<string, Tool> {\n const entries = Object.entries(tools);\n if (entries.length === 0) return tools as Record<string, Tool>;\n let hasProvider = false;\n const resolved: Record<string, Tool> = {};\n for (const [key, toolOrProvider] of entries) {\n if (isToolProvider<TContext>(toolOrProvider)) {\n hasProvider = true;\n resolved[key] = toolOrProvider.createTool(ctx as Readonly<TContext>);\n } else {\n resolved[key] = toolOrProvider as Tool;\n }\n }\n return hasProvider ? resolved : (tools as Record<string, Tool>);\n }\n}\n","import { tool, type Tool, type ToolExecutionOptions, type FlexibleSchema, type UIMessageStreamWriter } from \"ai\";\nimport { getActiveWriter } from \"./utils\";\n\nexport const TOOL_PROVIDER_BRAND = Symbol.for(\"agent-workflow.ToolProvider\");\n\nexport type ToolExecuteOptions = ToolExecutionOptions & {\n writer?: UIMessageStreamWriter;\n};\n\nexport type ToolProviderConfig<TContext, TInput, TOutput> = {\n description?: string;\n input: FlexibleSchema<TInput>;\n output?: FlexibleSchema<unknown>;\n providerOptions?: unknown;\n execute: (input: TInput, ctx: Readonly<TContext>, options: ToolExecuteOptions) => Promise<TOutput>;\n};\n\nexport interface IToolProvider<TContext> {\n readonly [TOOL_PROVIDER_BRAND]: true;\n createTool(context: Readonly<TContext>): Tool;\n}\n\nexport class ToolProvider<\n TContext,\n TInput = unknown,\n TOutput = unknown,\n> implements IToolProvider<TContext> {\n readonly [TOOL_PROVIDER_BRAND] = true as const;\n private readonly config: ToolProviderConfig<TContext, TInput, TOutput>;\n\n constructor(config: ToolProviderConfig<TContext, TInput, TOutput>) {\n this.config = config;\n }\n\n createTool(context: Readonly<TContext>): Tool {\n const { execute, input: inputSchema, ...toolDef } = this.config;\n return tool({\n ...toolDef,\n parameters: inputSchema,\n execute: (input: TInput, options?: ToolExecutionOptions) => execute(input, context, { ...options, writer: getActiveWriter() } as ToolExecuteOptions),\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } as any);\n }\n}\n\nexport function defineTool<TContext>() {\n return <TInput, TOutput>(\n config: ToolProviderConfig<TContext, TInput, TOutput>\n ): ToolProvider<TContext, TInput, TOutput> => new ToolProvider(config);\n}\n\nexport function isToolProvider<TContext>(obj: unknown): obj is IToolProvider<TContext> {\n return (\n typeof obj === \"object\" &&\n obj !== null &&\n TOOL_PROVIDER_BRAND in obj\n );\n}\n","import { AsyncLocalStorage } from \"node:async_hooks\";\nimport type { UIMessageStreamWriter } from \"ai\";\n\n// ── Stream writer context ────────────────────────────────────────────\n// Invisible to the user. The workflow sets the writer before agent execution;\n// tools and sub-agents read it automatically via getActiveWriter().\n\nconst writerStorage = new AsyncLocalStorage<UIMessageStreamWriter>();\n\nexport function runWithWriter<T>(writer: UIMessageStreamWriter, fn: () => T): T {\n return writerStorage.run(writer, fn);\n}\n\nexport function getActiveWriter(): UIMessageStreamWriter | undefined {\n return writerStorage.getStore();\n}\n\n// ── Common types ─────────────────────────────────────────────────────\n\nexport type MaybePromise<T> = T | Promise<T>;\n\n/**\n * A value that can be static or derived from context and input.\n * Used for agent config fields that may need runtime resolution.\n *\n * Functions may return a Promise for async resolution; static values are always sync.\n */\nexport type Resolvable<TCtx, TInput, TValue> =\n | TValue\n | ((ctx: Readonly<TCtx>, input: TInput) => TValue | Promise<TValue>);\n\nexport function resolveValue<TCtx, TInput, TValue>(\n value: Resolvable<TCtx, TInput, TValue>,\n ctx: TCtx,\n input: TInput\n): TValue | Promise<TValue>;\nexport function resolveValue<TCtx, TInput, TValue>(\n value: Resolvable<TCtx, TInput, TValue> | undefined,\n ctx: TCtx,\n input: TInput\n): TValue | Promise<TValue> | undefined {\n if (typeof value === \"function\") {\n return (value as (ctx: TCtx, input: TInput) => TValue | Promise<TValue>)(ctx, input);\n }\n return value;\n}\n\n/**\n * Extract structured output from an AI SDK result, falling back to text.\n * Works for both generate (sync .output/.text) and stream (async .output/.text) results.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport async function extractOutput(result: any, hasStructuredOutput: boolean): Promise<unknown> {\n if (hasStructuredOutput) {\n const output = await result.output;\n if (output !== undefined) return output;\n }\n return await result.text;\n}\n","import {\n createUIMessageStream,\n type UIMessageStreamWriter,\n} from \"ai\";\nimport { type Agent, type GenerateTextResult, type StreamTextResult } from \"./agent\";\nimport { extractOutput, runWithWriter, type MaybePromise } from \"./utils\";\n\n// ── Error Types ─────────────────────────────────────────────────────\n\nexport class WorkflowBranchError extends Error {\n constructor(\n public readonly branchType: \"predicate\" | \"select\",\n message: string,\n ) {\n super(message);\n this.name = \"WorkflowBranchError\";\n }\n}\n\nexport class WorkflowLoopError extends Error {\n constructor(\n public readonly iterations: number,\n public readonly maxIterations: number,\n ) {\n super(`Loop exceeded maximum iterations (${maxIterations})`);\n this.name = \"WorkflowLoopError\";\n }\n}\n\n// ── Shared Agent Step Hooks ─────────────────────────────────────────\n\nexport interface AgentStepHooks<TContext, TOutput, TNextOutput> {\n mapGenerateResult?: (params: { result: GenerateTextResult; ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<TNextOutput>;\n mapStreamResult?: (params: { result: StreamTextResult; ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<TNextOutput>;\n onGenerateResult?: (params: { result: GenerateTextResult; ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<void>;\n onStreamResult?: (params: { result: StreamTextResult; ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<void>;\n handleStream?: (params: {\n result: StreamTextResult;\n writer: UIMessageStreamWriter;\n ctx: Readonly<TContext>;\n }) => MaybePromise<void>;\n}\n\n// ── Step Options ────────────────────────────────────────────────────\n\nexport type StepOptions<TContext, TOutput, TNextOutput> = AgentStepHooks<TContext, TOutput, TNextOutput>;\n\n// ── Branch Types ────────────────────────────────────────────────────\n\nexport interface BranchCase<TContext, TOutput, TNextOutput> extends AgentStepHooks<TContext, TOutput, TNextOutput> {\n when?: (params: { ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<boolean>;\n agent: Agent<TContext, TOutput, TNextOutput>;\n}\n\nexport interface BranchSelect<TContext, TOutput, TKeys extends string, TNextOutput> extends AgentStepHooks<TContext, TOutput, TNextOutput> {\n select: (params: { ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<TKeys>;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n agents: Record<TKeys, Agent<TContext, any, TNextOutput>>;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n fallback?: Agent<TContext, any, TNextOutput>;\n}\n\n// ── Result Types ────────────────────────────────────────────────────\n\nexport interface WorkflowResult<TOutput> {\n output: TOutput;\n}\n\nexport interface WorkflowStreamResult<TOutput> {\n stream: ReadableStream;\n output: Promise<TOutput>;\n}\n\nexport interface WorkflowStreamOptions {\n onError?: (error: unknown) => string;\n onFinish?: () => MaybePromise<void>;\n}\n\n// ── Loop Types ──────────────────────────────────────────────────────\n\ntype LoopPredicate<TContext, TOutput> = (params: {\n output: TOutput;\n ctx: Readonly<TContext>;\n iterations: number;\n}) => MaybePromise<boolean>;\n\n// Exactly one of `until` or `while` — never both.\nexport type RepeatOptions<TContext, TOutput> =\n | { until: LoopPredicate<TContext, TOutput>; while?: never; maxIterations?: number }\n | { while: LoopPredicate<TContext, TOutput>; until?: never; maxIterations?: number };\n\n// Extracts the element type from an array type. Resolves to `never` for non-arrays,\n// making foreach uncallable at compile time when the previous step doesn't produce an array.\ntype ElementOf<T> = T extends readonly (infer E)[] ? E : never;\n\n// ── Step Node ───────────────────────────────────────────────────────\n\ntype StepNode =\n | { readonly type: \"step\"; readonly id: string; readonly execute: (state: RuntimeState) => MaybePromise<void> }\n | { readonly type: \"catch\"; readonly id: string; readonly catchFn: (params: { error: unknown; ctx: unknown; lastOutput: unknown; stepId: string }) => MaybePromise<unknown> }\n | { readonly type: \"finally\"; readonly id: string; readonly execute: (state: RuntimeState) => MaybePromise<void> };\n\ninterface RuntimeState {\n ctx: unknown;\n output: unknown;\n mode: \"generate\" | \"stream\";\n writer?: UIMessageStreamWriter;\n}\n\n// ── Sealed Workflow (returned by finally — execution only) ───────────\n\nexport class SealedWorkflow<\n TContext,\n TInput = void,\n TOutput = void,\n> {\n readonly id?: string;\n protected readonly steps: ReadonlyArray<StepNode>;\n\n protected constructor(steps: ReadonlyArray<StepNode>, id?: string) {\n this.steps = steps;\n this.id = id;\n }\n\n // ── Execution ─────────────────────────────────────────────────\n\n async generate(ctx: TContext, ...args: TInput extends void ? [input?: TInput] : [input: TInput]): Promise<WorkflowResult<TOutput>> {\n const input = args[0];\n const state: RuntimeState = {\n ctx,\n output: input,\n mode: \"generate\",\n };\n\n await this.execute(state);\n\n return {\n output: state.output as TOutput,\n };\n }\n\n stream(\n ctx: TContext,\n ...args: TInput extends void\n ? [input?: TInput, options?: WorkflowStreamOptions]\n : [input: TInput, options?: WorkflowStreamOptions]\n ): WorkflowStreamResult<TOutput> {\n const input = args[0];\n const options = args[1] as WorkflowStreamOptions | undefined;\n\n let resolveOutput: (value: TOutput) => void;\n let rejectOutput: (error: unknown) => void;\n const outputPromise = new Promise<TOutput>((res, rej) => {\n resolveOutput = res;\n rejectOutput = rej;\n });\n\n // Prevent unhandled rejection warning if the consumer never awaits `output`.\n // The original promise still rejects normally when awaited.\n outputPromise.catch(() => {});\n\n const stream = createUIMessageStream({\n execute: async ({ writer }) => {\n const state: RuntimeState = {\n ctx,\n output: input,\n mode: \"stream\",\n writer,\n };\n\n try {\n await this.execute(state);\n resolveOutput(state.output as TOutput);\n } catch (error) {\n rejectOutput!(error);\n throw error;\n }\n },\n ...(options?.onError ? { onError: options.onError } : {}),\n ...(options?.onFinish ? { onFinish: options.onFinish } : {}),\n });\n\n return {\n stream,\n output: outputPromise,\n };\n }\n\n // ── Internal: execute pipeline ────────────────────────────────\n\n protected async execute(state: RuntimeState): Promise<void> {\n if (this.steps.length === 0) {\n throw new Error(\"Workflow has no steps. Add at least one step before calling generate() or stream().\");\n }\n\n let pendingError: { error: unknown; stepId: string } | null = null;\n\n for (const node of this.steps) {\n if (node.type === \"finally\") {\n await node.execute(state);\n continue;\n }\n\n if (node.type === \"catch\") {\n if (!pendingError) continue;\n try {\n state.output = await node.catchFn({\n error: pendingError.error,\n ctx: state.ctx,\n lastOutput: state.output,\n stepId: pendingError.stepId,\n });\n pendingError = null;\n } catch (catchError) {\n pendingError = { error: catchError, stepId: node.id };\n }\n continue;\n }\n\n // type === \"step\" — skip while in error state\n if (pendingError) continue;\n\n try {\n await node.execute(state);\n } catch (error) {\n pendingError = { error, stepId: node.id };\n }\n }\n\n if (pendingError) throw pendingError.error;\n }\n\n // ── Internal: execute a nested workflow within a step/loop ─────\n // Defined on SealedWorkflow (not Workflow) because TypeScript's protected\n // access rules only allow calling workflow.execute() from the same class.\n\n protected async executeNestedWorkflow(\n state: RuntimeState,\n workflow: SealedWorkflow<TContext, unknown, unknown>,\n ): Promise<void> {\n await workflow.execute(state);\n }\n\n // ── Internal: execute an agent within a step/branch ───────────\n // In stream mode, output extraction awaits the full stream before returning.\n // Streaming benefits the client (incremental output), not pipeline throughput —\n // each step still runs sequentially.\n\n protected async executeAgent<TAgentInput, TNextOutput>(\n state: RuntimeState,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n agent: Agent<TContext, any, TNextOutput>,\n ctx: TContext,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n options?: AgentStepHooks<TContext, any, TNextOutput>,\n ): Promise<void> {\n const input = state.output as TAgentInput;\n const hasStructuredOutput = agent.hasOutput;\n\n if (state.mode === \"stream\" && state.writer) {\n const writer = state.writer;\n // Run inside writer context so tools (asTool, defineTool) can access the writer automatically\n await runWithWriter(writer, async () => {\n const result = await (agent.stream as (ctx: TContext, input: unknown) => Promise<StreamTextResult>)(ctx, state.output);\n\n if (options?.handleStream) {\n await options.handleStream({ result, writer, ctx });\n } else {\n writer.merge(result.toUIMessageStream());\n }\n\n if (options?.onStreamResult) {\n await options.onStreamResult({ result, ctx, input });\n }\n\n if (options?.mapStreamResult) {\n state.output = await options.mapStreamResult({ result, ctx, input });\n } else {\n state.output = await extractOutput(result, hasStructuredOutput);\n }\n });\n } else {\n const result = await (agent.generate as (ctx: TContext, input: unknown) => Promise<GenerateTextResult>)(ctx, state.output);\n\n if (options?.onGenerateResult) {\n await options.onGenerateResult({ result, ctx, input });\n }\n\n if (options?.mapGenerateResult) {\n state.output = await options.mapGenerateResult({ result, ctx, input });\n } else {\n state.output = await extractOutput(result, hasStructuredOutput);\n }\n }\n }\n}\n\n// ── Workflow ────────────────────────────────────────────────────────\n\nexport class Workflow<\n TContext,\n TInput = void,\n TOutput = void,\n> extends SealedWorkflow<TContext, TInput, TOutput> {\n\n private constructor(steps: ReadonlyArray<StepNode> = [], id?: string) {\n super(steps, id);\n }\n\n static create<TContext, TInput = void>(options?: { id?: string }): Workflow<TContext, TInput, TInput> {\n return new Workflow<TContext, TInput, TInput>([], options?.id);\n }\n\n static from<TContext, TInput, TOutput>(\n agent: Agent<TContext, TInput, TOutput>,\n options?: StepOptions<TContext, TInput, TOutput>\n ): Workflow<TContext, TInput, TOutput> {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, any>([]).step(agent, options);\n }\n\n // ── step: agent overload ──────────────────────────────────────\n\n step<TNextOutput>(\n agent: Agent<TContext, TOutput, TNextOutput>,\n options?: StepOptions<TContext, TOutput, TNextOutput>\n ): Workflow<TContext, TInput, TNextOutput>;\n\n // ── step: nested workflow overload ─────────────────────────────\n\n step<TNextOutput>(\n workflow: SealedWorkflow<TContext, TOutput, TNextOutput>,\n ): Workflow<TContext, TInput, TNextOutput>;\n\n // ── step: transform overload (replaces map + tap) ─────────────\n\n step<TNextOutput>(\n id: string,\n fn: (params: { ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<TNextOutput>\n ): Workflow<TContext, TInput, TNextOutput>;\n\n // ── step: implementation ──────────────────────────────────────\n\n step<TNextOutput>(\n target: Agent<TContext, TOutput, TNextOutput> | SealedWorkflow<TContext, TOutput, TNextOutput> | string,\n optionsOrFn?: StepOptions<TContext, TOutput, TNextOutput> | ((params: { ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<TNextOutput>)\n ): Workflow<TContext, TInput, TNextOutput> {\n // Nested workflow overload: step(workflow)\n if (target instanceof SealedWorkflow) {\n const workflow = target;\n const node: StepNode = {\n type: \"step\",\n id: workflow.id ?? \"nested-workflow\",\n execute: async (state) => {\n await this.executeNestedWorkflow(state, workflow as SealedWorkflow<TContext, unknown, unknown>);\n },\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNextOutput>([...this.steps, node] as any, this.id);\n }\n\n // Transform overload: step(id, fn)\n if (typeof target === \"string\") {\n if (typeof optionsOrFn !== \"function\") {\n throw new Error(`Workflow step(\"${target}\"): second argument must be a function`);\n }\n const fn = optionsOrFn as (params: { ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<TNextOutput>;\n const node: StepNode = {\n type: \"step\",\n id: target,\n execute: async (state) => {\n state.output = await fn({\n ctx: state.ctx as Readonly<TContext>,\n input: state.output as TOutput,\n });\n },\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNextOutput>([...this.steps, node] as any, this.id);\n }\n\n // Agent overload: step(agent, options?)\n const agent = target;\n const options = optionsOrFn as StepOptions<TContext, TOutput, TNextOutput> | undefined;\n const node: StepNode = {\n type: \"step\",\n id: agent.id,\n execute: async (state) => {\n const ctx = state.ctx as TContext;\n await this.executeAgent(state, agent, ctx, options);\n },\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNextOutput>([...this.steps, node] as any, this.id);\n }\n\n // ── branch: predicate routing (array) ─────────────────────────\n\n branch<TNextOutput>(\n cases: BranchCase<TContext, TOutput, TNextOutput>[]\n ): Workflow<TContext, TInput, TNextOutput>;\n\n // ── branch: key routing (select) ──────────────────────────────\n\n branch<TKeys extends string, TNextOutput>(\n config: BranchSelect<TContext, TOutput, TKeys, TNextOutput>\n ): Workflow<TContext, TInput, TNextOutput>;\n\n // ── branch: implementation ────────────────────────────────────\n\n branch<TKeys extends string, TNextOutput>(\n casesOrConfig: BranchCase<TContext, TOutput, TNextOutput>[] | BranchSelect<TContext, TOutput, TKeys, TNextOutput>\n ): Workflow<TContext, TInput, TNextOutput> {\n if (Array.isArray(casesOrConfig)) {\n return this.branchPredicate(casesOrConfig);\n }\n return this.branchSelect(casesOrConfig);\n }\n\n private branchPredicate<TNextOutput>(\n cases: BranchCase<TContext, TOutput, TNextOutput>[]\n ): Workflow<TContext, TInput, TNextOutput> {\n const node: StepNode = {\n type: \"step\",\n id: \"branch:predicate\",\n execute: async (state) => {\n const ctx = state.ctx as TContext;\n const input = state.output as TOutput;\n\n for (const branchCase of cases) {\n if (branchCase.when) {\n const match = await branchCase.when({ ctx, input });\n if (!match) continue;\n }\n\n // Matched (or no `when` = default)\n await this.executeAgent(state, branchCase.agent, ctx, branchCase);\n return;\n }\n\n throw new WorkflowBranchError(\"predicate\", `No branch matched and no default branch (a case without \\`when\\`) was provided. Input: ${JSON.stringify(input)}`);\n },\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNextOutput>([...this.steps, node] as any, this.id);\n }\n\n private branchSelect<TKeys extends string, TNextOutput>(\n config: BranchSelect<TContext, TOutput, TKeys, TNextOutput>\n ): Workflow<TContext, TInput, TNextOutput> {\n const node: StepNode = {\n type: \"step\",\n id: \"branch:select\",\n execute: async (state) => {\n const ctx = state.ctx as TContext;\n const input = state.output as TOutput;\n const key = await config.select({ ctx, input });\n\n let agent = config.agents[key];\n if (!agent) {\n if (config.fallback) {\n agent = config.fallback;\n } else {\n throw new WorkflowBranchError(\"select\", `No agent found for key \"${key}\" and no fallback provided. Available keys: ${Object.keys(config.agents).join(\", \")}`);\n }\n }\n\n await this.executeAgent(state, agent, ctx, config);\n },\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNextOutput>([...this.steps, node] as any, this.id);\n }\n\n // ── foreach: array iteration ─────────────────────────────────\n\n foreach<TNextOutput>(\n target: Agent<TContext, ElementOf<TOutput>, TNextOutput> | SealedWorkflow<TContext, ElementOf<TOutput>, TNextOutput>,\n options?: { concurrency?: number },\n ): Workflow<TContext, TInput, TNextOutput[]> {\n const concurrency = options?.concurrency ?? 1;\n const isWorkflow = target instanceof SealedWorkflow;\n const id = isWorkflow ? (target.id ?? \"foreach\") : `foreach:${(target as Agent<TContext, ElementOf<TOutput>, TNextOutput>).id}`;\n\n const node: StepNode = {\n type: \"step\",\n id,\n execute: async (state) => {\n const items = state.output;\n if (!Array.isArray(items)) {\n throw new Error(`foreach \"${id}\": expected array input, got ${typeof items}`);\n }\n\n const ctx = state.ctx as TContext;\n const results: unknown[] = new Array(items.length);\n\n // Streaming is intentionally not propagated to foreach items —\n // each item runs in generate mode because merging interleaved\n // streams from parallel items into a single writer is not supported.\n const executeItem = async (item: unknown, index: number) => {\n const itemState: RuntimeState = { ctx: state.ctx, output: item, mode: \"generate\" };\n if (isWorkflow) {\n await this.executeNestedWorkflow(itemState, target as SealedWorkflow<TContext, unknown, unknown>);\n } else {\n await this.executeAgent(itemState, target as Agent<TContext, unknown, TNextOutput>, ctx);\n }\n results[index] = itemState.output;\n };\n\n if (concurrency <= 1) {\n for (let i = 0; i < items.length; i++) {\n await executeItem(items[i], i);\n }\n } else {\n for (let i = 0; i < items.length; i += concurrency) {\n const batch = items.slice(i, i + concurrency);\n await Promise.all(batch.map((item, j) => executeItem(item, i + j)));\n }\n }\n\n state.output = results;\n },\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNextOutput[]>([...this.steps, node] as any, this.id);\n }\n\n // ── repeat: conditional loop ─────────────────────────────────\n\n repeat(\n target: Agent<TContext, TOutput, TOutput> | SealedWorkflow<TContext, TOutput, TOutput>,\n options: RepeatOptions<TContext, TOutput>,\n ): Workflow<TContext, TInput, TOutput> {\n const maxIterations = options.maxIterations ?? 10;\n const isWorkflow = target instanceof SealedWorkflow;\n const id = isWorkflow ? (target.id ?? \"repeat\") : `repeat:${(target as Agent<TContext, TOutput, TOutput>).id}`;\n const predicate: LoopPredicate<TContext, TOutput> = options.until\n ?? (async (p) => !(await options.while!(p)));\n\n const node: StepNode = {\n type: \"step\",\n id,\n execute: async (state) => {\n const ctx = state.ctx as TContext;\n\n for (let i = 1; i <= maxIterations; i++) {\n if (isWorkflow) {\n await this.executeNestedWorkflow(state, target as SealedWorkflow<TContext, unknown, unknown>);\n } else {\n await this.executeAgent(state, target as Agent<TContext, TOutput, TOutput>, ctx);\n }\n\n const done = await predicate({\n output: state.output as TOutput,\n ctx: ctx as Readonly<TContext>,\n iterations: i,\n });\n if (done) return;\n }\n\n throw new WorkflowLoopError(maxIterations, maxIterations);\n },\n };\n return new Workflow<TContext, TInput, TOutput>([...this.steps, node], this.id);\n }\n\n // ── catch ─────────────────────────────────────────────────────\n\n catch(\n id: string,\n fn: (params: { error: unknown; ctx: Readonly<TContext>; lastOutput: TOutput; stepId: string }) => MaybePromise<TOutput>\n ): Workflow<TContext, TInput, TOutput> {\n if (!this.steps.some(s => s.type === \"step\")) {\n throw new Error(`Workflow: catch(\"${id}\") requires at least one preceding step.`);\n }\n const node: StepNode = {\n type: \"catch\",\n id,\n catchFn: fn as (params: { error: unknown; ctx: unknown; lastOutput: unknown; stepId: string }) => MaybePromise<unknown>,\n };\n return new Workflow<TContext, TInput, TOutput>([...this.steps, node], this.id);\n }\n\n // ── finally (terminal — returns sealed workflow) ──────────────\n\n finally(\n id: string,\n fn: (params: { ctx: Readonly<TContext> }) => MaybePromise<void>\n ): SealedWorkflow<TContext, TInput, TOutput> {\n const node: StepNode = {\n type: \"finally\",\n id,\n execute: async (state) => {\n await fn({ ctx: state.ctx as Readonly<TContext> });\n },\n };\n return new SealedWorkflow<TContext, TInput, TOutput>([...this.steps, node], this.id);\n }\n}\n\n"],"mappings":"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","names":["import_ai","result","import_ai","node"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
|
-
import { Tool,
|
|
1
|
+
import { Tool, ToolExecutionOptions, UIMessageStreamWriter, FlexibleSchema, streamText, generateText, Output, LanguageModel, ModelMessage, ToolChoice, ToolSet, StopCondition, OnStepFinishEvent, OnFinishEvent, GenerateTextResult as GenerateTextResult$1, StreamTextResult as StreamTextResult$1 } from 'ai';
|
|
2
2
|
import { ZodType } from 'zod';
|
|
3
3
|
|
|
4
4
|
declare const TOOL_PROVIDER_BRAND: unique symbol;
|
|
5
|
+
type ToolExecuteOptions = ToolExecutionOptions & {
|
|
6
|
+
writer?: UIMessageStreamWriter;
|
|
7
|
+
};
|
|
5
8
|
type ToolProviderConfig<TContext, TInput, TOutput> = {
|
|
6
9
|
description?: string;
|
|
7
10
|
input: FlexibleSchema<TInput>;
|
|
8
11
|
output?: FlexibleSchema<unknown>;
|
|
9
12
|
providerOptions?: unknown;
|
|
10
|
-
execute: (input: TInput, ctx: Readonly<TContext>, options
|
|
13
|
+
execute: (input: TInput, ctx: Readonly<TContext>, options: ToolExecuteOptions) => Promise<TOutput>;
|
|
11
14
|
};
|
|
12
15
|
interface IToolProvider<TContext> {
|
|
13
16
|
readonly [TOOL_PROVIDER_BRAND]: true;
|
|
@@ -56,16 +59,19 @@ interface AgentConfig<TContext, TInput = void, TOutput = void> extends AIPassthr
|
|
|
56
59
|
result: OnStepFinishEvent;
|
|
57
60
|
ctx: Readonly<TContext>;
|
|
58
61
|
input: TInput;
|
|
62
|
+
writer?: UIMessageStreamWriter;
|
|
59
63
|
}) => MaybePromise<void>;
|
|
60
64
|
onFinish?: (params: {
|
|
61
65
|
result: OnFinishEvent;
|
|
62
66
|
ctx: Readonly<TContext>;
|
|
63
67
|
input: TInput;
|
|
68
|
+
writer?: UIMessageStreamWriter;
|
|
64
69
|
}) => MaybePromise<void>;
|
|
65
70
|
onError?: (params: {
|
|
66
71
|
error: unknown;
|
|
67
72
|
ctx: Readonly<TContext>;
|
|
68
73
|
input: TInput;
|
|
74
|
+
writer?: UIMessageStreamWriter;
|
|
69
75
|
}) => MaybePromise<void>;
|
|
70
76
|
}
|
|
71
77
|
declare class Agent<TContext, TInput = void, TOutput = void> {
|
|
@@ -237,4 +243,4 @@ declare class Workflow<TContext, TInput = void, TOutput = void> extends SealedWo
|
|
|
237
243
|
}) => MaybePromise<void>): SealedWorkflow<TContext, TInput, TOutput>;
|
|
238
244
|
}
|
|
239
245
|
|
|
240
|
-
export { Agent, type AgentConfig, type AgentStepHooks, type BranchCase, type BranchSelect, type GenerateTextResult, type IToolProvider, type MaybePromise, type RepeatOptions, type Resolvable, SealedWorkflow, type StepOptions, type StreamTextResult, type ToolProviderConfig, Workflow, WorkflowBranchError, WorkflowLoopError, type WorkflowResult, type WorkflowStreamOptions, type WorkflowStreamResult, defineTool };
|
|
246
|
+
export { Agent, type AgentConfig, type AgentStepHooks, type BranchCase, type BranchSelect, type GenerateTextResult, type IToolProvider, type MaybePromise, type RepeatOptions, type Resolvable, SealedWorkflow, type StepOptions, type StreamTextResult, type ToolExecuteOptions, type ToolProviderConfig, Workflow, WorkflowBranchError, WorkflowLoopError, type WorkflowResult, type WorkflowStreamOptions, type WorkflowStreamResult, defineTool };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
|
-
import { Tool,
|
|
1
|
+
import { Tool, ToolExecutionOptions, UIMessageStreamWriter, FlexibleSchema, streamText, generateText, Output, LanguageModel, ModelMessage, ToolChoice, ToolSet, StopCondition, OnStepFinishEvent, OnFinishEvent, GenerateTextResult as GenerateTextResult$1, StreamTextResult as StreamTextResult$1 } from 'ai';
|
|
2
2
|
import { ZodType } from 'zod';
|
|
3
3
|
|
|
4
4
|
declare const TOOL_PROVIDER_BRAND: unique symbol;
|
|
5
|
+
type ToolExecuteOptions = ToolExecutionOptions & {
|
|
6
|
+
writer?: UIMessageStreamWriter;
|
|
7
|
+
};
|
|
5
8
|
type ToolProviderConfig<TContext, TInput, TOutput> = {
|
|
6
9
|
description?: string;
|
|
7
10
|
input: FlexibleSchema<TInput>;
|
|
8
11
|
output?: FlexibleSchema<unknown>;
|
|
9
12
|
providerOptions?: unknown;
|
|
10
|
-
execute: (input: TInput, ctx: Readonly<TContext>, options
|
|
13
|
+
execute: (input: TInput, ctx: Readonly<TContext>, options: ToolExecuteOptions) => Promise<TOutput>;
|
|
11
14
|
};
|
|
12
15
|
interface IToolProvider<TContext> {
|
|
13
16
|
readonly [TOOL_PROVIDER_BRAND]: true;
|
|
@@ -56,16 +59,19 @@ interface AgentConfig<TContext, TInput = void, TOutput = void> extends AIPassthr
|
|
|
56
59
|
result: OnStepFinishEvent;
|
|
57
60
|
ctx: Readonly<TContext>;
|
|
58
61
|
input: TInput;
|
|
62
|
+
writer?: UIMessageStreamWriter;
|
|
59
63
|
}) => MaybePromise<void>;
|
|
60
64
|
onFinish?: (params: {
|
|
61
65
|
result: OnFinishEvent;
|
|
62
66
|
ctx: Readonly<TContext>;
|
|
63
67
|
input: TInput;
|
|
68
|
+
writer?: UIMessageStreamWriter;
|
|
64
69
|
}) => MaybePromise<void>;
|
|
65
70
|
onError?: (params: {
|
|
66
71
|
error: unknown;
|
|
67
72
|
ctx: Readonly<TContext>;
|
|
68
73
|
input: TInput;
|
|
74
|
+
writer?: UIMessageStreamWriter;
|
|
69
75
|
}) => MaybePromise<void>;
|
|
70
76
|
}
|
|
71
77
|
declare class Agent<TContext, TInput = void, TOutput = void> {
|
|
@@ -237,4 +243,4 @@ declare class Workflow<TContext, TInput = void, TOutput = void> extends SealedWo
|
|
|
237
243
|
}) => MaybePromise<void>): SealedWorkflow<TContext, TInput, TOutput>;
|
|
238
244
|
}
|
|
239
245
|
|
|
240
|
-
export { Agent, type AgentConfig, type AgentStepHooks, type BranchCase, type BranchSelect, type GenerateTextResult, type IToolProvider, type MaybePromise, type RepeatOptions, type Resolvable, SealedWorkflow, type StepOptions, type StreamTextResult, type ToolProviderConfig, Workflow, WorkflowBranchError, WorkflowLoopError, type WorkflowResult, type WorkflowStreamOptions, type WorkflowStreamResult, defineTool };
|
|
246
|
+
export { Agent, type AgentConfig, type AgentStepHooks, type BranchCase, type BranchSelect, type GenerateTextResult, type IToolProvider, type MaybePromise, type RepeatOptions, type Resolvable, SealedWorkflow, type StepOptions, type StreamTextResult, type ToolExecuteOptions, type ToolProviderConfig, Workflow, WorkflowBranchError, WorkflowLoopError, type WorkflowResult, type WorkflowStreamOptions, type WorkflowStreamResult, defineTool };
|
package/dist/index.js
CHANGED
|
@@ -7,6 +7,31 @@ import {
|
|
|
7
7
|
|
|
8
8
|
// src/tool-provider.ts
|
|
9
9
|
import { tool } from "ai";
|
|
10
|
+
|
|
11
|
+
// src/utils.ts
|
|
12
|
+
import { AsyncLocalStorage } from "async_hooks";
|
|
13
|
+
var writerStorage = new AsyncLocalStorage();
|
|
14
|
+
function runWithWriter(writer, fn) {
|
|
15
|
+
return writerStorage.run(writer, fn);
|
|
16
|
+
}
|
|
17
|
+
function getActiveWriter() {
|
|
18
|
+
return writerStorage.getStore();
|
|
19
|
+
}
|
|
20
|
+
function resolveValue(value, ctx, input) {
|
|
21
|
+
if (typeof value === "function") {
|
|
22
|
+
return value(ctx, input);
|
|
23
|
+
}
|
|
24
|
+
return value;
|
|
25
|
+
}
|
|
26
|
+
async function extractOutput(result, hasStructuredOutput) {
|
|
27
|
+
if (hasStructuredOutput) {
|
|
28
|
+
const output = await result.output;
|
|
29
|
+
if (output !== void 0) return output;
|
|
30
|
+
}
|
|
31
|
+
return await result.text;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// src/tool-provider.ts
|
|
10
35
|
var TOOL_PROVIDER_BRAND = /* @__PURE__ */ Symbol.for("agent-workflow.ToolProvider");
|
|
11
36
|
var ToolProvider = class {
|
|
12
37
|
[TOOL_PROVIDER_BRAND] = true;
|
|
@@ -19,7 +44,7 @@ var ToolProvider = class {
|
|
|
19
44
|
return tool({
|
|
20
45
|
...toolDef,
|
|
21
46
|
parameters: inputSchema,
|
|
22
|
-
execute: (input, options) => execute(input, context, options)
|
|
47
|
+
execute: (input, options) => execute(input, context, { ...options, writer: getActiveWriter() })
|
|
23
48
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
24
49
|
});
|
|
25
50
|
}
|
|
@@ -31,21 +56,6 @@ function isToolProvider(obj) {
|
|
|
31
56
|
return typeof obj === "object" && obj !== null && TOOL_PROVIDER_BRAND in obj;
|
|
32
57
|
}
|
|
33
58
|
|
|
34
|
-
// src/utils.ts
|
|
35
|
-
function resolveValue(value, ctx, input) {
|
|
36
|
-
if (typeof value === "function") {
|
|
37
|
-
return value(ctx, input);
|
|
38
|
-
}
|
|
39
|
-
return value;
|
|
40
|
-
}
|
|
41
|
-
async function extractOutput(result, hasStructuredOutput) {
|
|
42
|
-
if (hasStructuredOutput) {
|
|
43
|
-
const output = await result.output;
|
|
44
|
-
if (output !== void 0) return output;
|
|
45
|
-
}
|
|
46
|
-
return await result.text;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
59
|
// src/agent.ts
|
|
50
60
|
var Agent = class {
|
|
51
61
|
id;
|
|
@@ -110,7 +120,7 @@ var Agent = class {
|
|
|
110
120
|
return await generateText(options);
|
|
111
121
|
} catch (error) {
|
|
112
122
|
if (this.config.onError) {
|
|
113
|
-
await this.config.onError({ error, ctx, input });
|
|
123
|
+
await this.config.onError({ error, ctx, input, writer: getActiveWriter() });
|
|
114
124
|
}
|
|
115
125
|
throw error;
|
|
116
126
|
}
|
|
@@ -121,7 +131,7 @@ var Agent = class {
|
|
|
121
131
|
const options = this.buildCallOptions(resolved, ctx, input);
|
|
122
132
|
return streamText({
|
|
123
133
|
...options,
|
|
124
|
-
onError: this.config.onError ? ({ error }) => this.config.onError({ error, ctx, input }) : void 0
|
|
134
|
+
onError: this.config.onError ? ({ error }) => this.config.onError({ error, ctx, input, writer: getActiveWriter() }) : void 0
|
|
125
135
|
});
|
|
126
136
|
}
|
|
127
137
|
asTool(ctx, options) {
|
|
@@ -144,6 +154,13 @@ var Agent = class {
|
|
|
144
154
|
description: this.description,
|
|
145
155
|
parameters: this.config.input,
|
|
146
156
|
execute: async (toolInput) => {
|
|
157
|
+
const writer = getActiveWriter();
|
|
158
|
+
if (writer) {
|
|
159
|
+
const result2 = await this.stream(ctx, toolInput);
|
|
160
|
+
writer.merge(result2.toUIMessageStream());
|
|
161
|
+
if (options?.mapOutput) return options.mapOutput(result2);
|
|
162
|
+
return extractOutput(result2, this.hasOutput);
|
|
163
|
+
}
|
|
147
164
|
const result = await this.generate(ctx, toolInput);
|
|
148
165
|
if (options?.mapOutput) return options.mapOutput(result);
|
|
149
166
|
return extractOutput(result, this.hasOutput);
|
|
@@ -163,8 +180,8 @@ var Agent = class {
|
|
|
163
180
|
...resolved.messages ? { messages: resolved.messages } : { prompt: resolved.prompt ?? "" },
|
|
164
181
|
...resolved.system ? { system: resolved.system } : {},
|
|
165
182
|
...this.config.output ? { output: this.config.output } : {},
|
|
166
|
-
onStepFinish: this._onStepFinish ? (event) => this._onStepFinish({ result: event, ctx, input }) : void 0,
|
|
167
|
-
onFinish: this._onFinish ? (event) => this._onFinish({ result: event, ctx, input }) : void 0
|
|
183
|
+
onStepFinish: this._onStepFinish ? (event) => this._onStepFinish({ result: event, ctx, input, writer: getActiveWriter() }) : void 0,
|
|
184
|
+
onFinish: this._onFinish ? (event) => this._onFinish({ result: event, ctx, input, writer: getActiveWriter() }) : void 0
|
|
168
185
|
};
|
|
169
186
|
}
|
|
170
187
|
resolveConfig(ctx, input) {
|
|
@@ -339,20 +356,23 @@ var SealedWorkflow = class {
|
|
|
339
356
|
const input = state.output;
|
|
340
357
|
const hasStructuredOutput = agent.hasOutput;
|
|
341
358
|
if (state.mode === "stream" && state.writer) {
|
|
342
|
-
const
|
|
343
|
-
|
|
344
|
-
await
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
359
|
+
const writer = state.writer;
|
|
360
|
+
await runWithWriter(writer, async () => {
|
|
361
|
+
const result = await agent.stream(ctx, state.output);
|
|
362
|
+
if (options?.handleStream) {
|
|
363
|
+
await options.handleStream({ result, writer, ctx });
|
|
364
|
+
} else {
|
|
365
|
+
writer.merge(result.toUIMessageStream());
|
|
366
|
+
}
|
|
367
|
+
if (options?.onStreamResult) {
|
|
368
|
+
await options.onStreamResult({ result, ctx, input });
|
|
369
|
+
}
|
|
370
|
+
if (options?.mapStreamResult) {
|
|
371
|
+
state.output = await options.mapStreamResult({ result, ctx, input });
|
|
372
|
+
} else {
|
|
373
|
+
state.output = await extractOutput(result, hasStructuredOutput);
|
|
374
|
+
}
|
|
375
|
+
});
|
|
356
376
|
} else {
|
|
357
377
|
const result = await agent.generate(ctx, state.output);
|
|
358
378
|
if (options?.onGenerateResult) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/agent.ts","../src/tool-provider.ts","../src/utils.ts","../src/workflow.ts"],"sourcesContent":["import {\n generateText,\n streamText,\n tool,\n Output,\n type GenerateTextResult as AIGenerateTextResult,\n type StreamTextResult as AIStreamTextResult,\n type ModelMessage,\n type LanguageModel,\n type Tool,\n type ToolSet,\n type StopCondition,\n type ToolChoice,\n type OnStepFinishEvent,\n type OnFinishEvent,\n} from \"ai\";\n\n// Extract the Output interface type from the Output.object return type\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype OutputType<T = any> = ReturnType<typeof Output.object<T>>;\nimport type { ZodType } from \"zod\";\nimport { isToolProvider, TOOL_PROVIDER_BRAND, type IToolProvider } from \"./tool-provider\";\nimport { extractOutput, resolveValue, type MaybePromise, type Resolvable } from \"./utils\";\n\n// Tools config accepts both AI SDK tools and context-aware ToolProviders\ntype AgentToolSet<TContext> = Record<string, Tool | IToolProvider<TContext>>;\n\n// ── Result type aliases ─────────────────────────────────────────────\n\nexport type GenerateTextResult<TOOLS extends ToolSet = ToolSet, OUTPUT extends OutputType = OutputType> = AIGenerateTextResult<TOOLS, OUTPUT>;\nexport type StreamTextResult<TOOLS extends ToolSet = ToolSet, OUTPUT extends OutputType = OutputType> = AIStreamTextResult<TOOLS, OUTPUT>;\n\n// ── AI SDK passthrough types ────────────────────────────────────────\n\n// Extract options types from both AI SDK entry points\ntype StreamTextOptions = Parameters<typeof streamText>[0];\ntype GenerateTextOptions = Parameters<typeof generateText>[0];\n\n// Keys we replace with resolvable or context-enriched versions\ntype ManagedKeys =\n | 'model' | 'system' | 'prompt' | 'messages'\n | 'tools' | 'activeTools' | 'toolChoice' | 'stopWhen'\n | 'output' | 'onFinish' | 'onStepFinish' | 'onError';\n\n// Combine options from both streamText and generateText.\n// Each side contributes its unique props; shared props merge naturally.\n// Stream-only props (onChunk, onAbort) are ignored by generateText.\n// Generate-only props (experimental_include.responseBody) are ignored by streamText.\ntype AIPassthroughOptions =\n Omit<StreamTextOptions, ManagedKeys> &\n Omit<GenerateTextOptions, ManagedKeys>;\n\n// ── Resolved config (output of resolveConfig / resolveConfigAsync) ──\n\ninterface ResolvedAgentConfig {\n model: LanguageModel;\n prompt: string | undefined;\n system: string | undefined;\n messages: ModelMessage[] | undefined;\n tools: Record<string, Tool>;\n activeTools: string[] | undefined;\n toolChoice: ToolChoice<ToolSet> | undefined;\n stopWhen: StopCondition<ToolSet> | Array<StopCondition<ToolSet>> | undefined;\n}\n\n// ── Agent Configuration ─────────────────────────────────────────────\n\nexport interface AgentConfig<\n TContext,\n TInput = void,\n TOutput = void,\n> extends AIPassthroughOptions {\n // ── Custom (not in AI SDK) ──\n id: string;\n description?: string;\n input?: ZodType<TInput>;\n output?: OutputType<TOutput>;\n\n // ── Resolvable (our versions of AI SDK properties) ──\n model: Resolvable<TContext, TInput, LanguageModel>;\n system?: Resolvable<TContext, TInput, string>;\n prompt?: Resolvable<TContext, TInput, string>;\n messages?: Resolvable<TContext, TInput, ModelMessage[]>;\n tools?: Resolvable<TContext, TInput, AgentToolSet<TContext>>;\n activeTools?: Resolvable<TContext, TInput, string[]>;\n toolChoice?: Resolvable<TContext, TInput, ToolChoice<ToolSet>>;\n stopWhen?: Resolvable<TContext, TInput, StopCondition<ToolSet> | Array<StopCondition<ToolSet>>>;\n\n // ── Context-enriched callbacks (replace AI SDK versions) ──\n onStepFinish?: (params: { result: OnStepFinishEvent; ctx: Readonly<TContext>; input: TInput }) => MaybePromise<void>;\n onFinish?: (params: { result: OnFinishEvent; ctx: Readonly<TContext>; input: TInput }) => MaybePromise<void>;\n onError?: (params: { error: unknown; ctx: Readonly<TContext>; input: TInput }) => MaybePromise<void>;\n}\n\n// ── Agent ───────────────────────────────────────────────────────────\n\nexport class Agent<\n TContext,\n TInput = void,\n TOutput = void,\n> {\n readonly id: string;\n readonly description: string;\n readonly hasOutput: boolean;\n private readonly config: AgentConfig<TContext, TInput, TOutput>;\n private readonly _hasDynamicConfig: boolean;\n private readonly _resolvedStaticTools: Record<string, Tool> | null = null;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private readonly _passthrough: Record<string, any>;\n private readonly _onStepFinish: AgentConfig<TContext, TInput, TOutput>['onStepFinish'];\n private readonly _onFinish: AgentConfig<TContext, TInput, TOutput>['onFinish'];\n\n constructor(config: AgentConfig<TContext, TInput, TOutput>) {\n this.id = config.id;\n this.description = config.description ?? \"\";\n this.hasOutput = config.output !== undefined;\n this.config = config;\n this._hasDynamicConfig = [\n config.model, config.system, config.prompt,\n config.messages, config.tools, config.activeTools,\n config.toolChoice, config.stopWhen,\n ].some(v => typeof v === \"function\");\n\n // Cache tools when config is static and contains no ToolProviders.\n // Avoids re-iterating the tools map on every generate()/stream() call.\n if (!this._hasDynamicConfig) {\n const rawTools = (config.tools as AgentToolSet<TContext> | undefined) ?? {};\n const hasProvider = Object.values(rawTools).some(v => isToolProvider(v));\n if (!hasProvider) {\n this._resolvedStaticTools = rawTools as Record<string, Tool>;\n }\n }\n\n // Pre-compute the passthrough (AI SDK options we don't manage) once,\n // rather than destructuring on every generate()/stream() call.\n const {\n id: _id, description: _desc, input: _inputSchema, output: _output,\n model: _m, system: _s, prompt: _p, messages: _msg,\n tools: _t, activeTools: _at, toolChoice: _tc, stopWhen: _sw,\n onStepFinish, onFinish, onError: _onError,\n ...passthrough\n } = config;\n this._passthrough = passthrough;\n this._onStepFinish = onStepFinish;\n this._onFinish = onFinish;\n }\n\n async generate(ctx: TContext, ...args: TInput extends void ? [input?: TInput] : [input: TInput]): Promise<GenerateTextResult> {\n const input = args[0] as TInput;\n const resolved = await this.resolveConfig(ctx, input);\n const options = this.buildCallOptions(resolved, ctx, input);\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return await generateText(options as any);\n } catch (error: unknown) {\n if (this.config.onError) {\n await this.config.onError({ error, ctx, input });\n }\n throw error;\n }\n }\n\n async stream(ctx: TContext, ...args: TInput extends void ? [input?: TInput] : [input: TInput]): Promise<StreamTextResult> {\n const input = args[0] as TInput;\n const resolved = await this.resolveConfig(ctx, input);\n const options = this.buildCallOptions(resolved, ctx, input);\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return streamText({\n ...options,\n onError: this.config.onError\n ? ({ error }: { error: unknown }) => this.config.onError!({ error, ctx, input })\n : undefined,\n } as any);\n }\n\n asTool(ctx: TContext, options?: {\n mapOutput?: (result: GenerateTextResult) => MaybePromise<TOutput>;\n }): Tool {\n return this.createToolInstance(ctx, options);\n }\n\n asToolProvider(options?: {\n mapOutput?: (result: GenerateTextResult) => MaybePromise<TOutput>;\n }): IToolProvider<TContext> {\n if (!this.config.input) {\n throw new Error(`Agent \"${this.id}\": asToolProvider() requires an input schema`);\n }\n\n return {\n [TOOL_PROVIDER_BRAND]: true as const,\n createTool: (ctx: Readonly<TContext>) => this.createToolInstance(ctx as TContext, options),\n };\n }\n\n private createToolInstance(ctx: TContext, options?: {\n mapOutput?: (result: GenerateTextResult) => MaybePromise<TOutput>;\n }): Tool {\n if (!this.config.input) {\n throw new Error(`Agent \"${this.id}\": asTool() requires an input schema`);\n }\n\n return tool({\n description: this.description,\n parameters: this.config.input,\n execute: async (toolInput: TInput) => {\n const result = await (this.generate as (ctx: TContext, input: TInput) => Promise<GenerateTextResult>)(ctx, toolInput);\n if (options?.mapOutput) return options.mapOutput(result);\n return extractOutput(result, this.hasOutput);\n },\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } as any);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private buildCallOptions(resolved: ResolvedAgentConfig, ctx: TContext, input: TInput): Record<string, any> {\n return {\n ...this._passthrough,\n model: resolved.model,\n tools: resolved.tools,\n activeTools: resolved.activeTools,\n toolChoice: resolved.toolChoice,\n stopWhen: resolved.stopWhen,\n ...(resolved.messages\n ? { messages: resolved.messages }\n : { prompt: resolved.prompt ?? \"\" }),\n ...(resolved.system ? { system: resolved.system } : {}),\n ...(this.config.output ? { output: this.config.output } : {}),\n onStepFinish: this._onStepFinish\n ? (event: OnStepFinishEvent) => this._onStepFinish!({ result: event, ctx, input })\n : undefined,\n onFinish: this._onFinish\n ? (event: OnFinishEvent) => this._onFinish!({ result: event, ctx, input })\n : undefined,\n };\n }\n\n private resolveConfig(ctx: TContext, input: TInput): ResolvedAgentConfig | Promise<ResolvedAgentConfig> {\n if (!this._hasDynamicConfig) {\n return {\n model: this.config.model as LanguageModel,\n prompt: this.config.prompt as string | undefined,\n system: this.config.system as string | undefined,\n messages: this.config.messages as ModelMessage[] | undefined,\n tools: this._resolvedStaticTools ?? this.resolveTools(\n (this.config.tools as AgentToolSet<TContext> | undefined) ?? {}, ctx\n ),\n activeTools: this.config.activeTools as string[] | undefined,\n toolChoice: this.config.toolChoice as ToolChoice<ToolSet> | undefined,\n stopWhen: this.config.stopWhen as StopCondition<ToolSet> | Array<StopCondition<ToolSet>> | undefined,\n };\n }\n return this.resolveConfigAsync(ctx, input);\n }\n\n private async resolveConfigAsync(ctx: TContext, input: TInput): Promise<ResolvedAgentConfig> {\n const [model, prompt, system, messages, rawTools, activeTools, toolChoice, stopWhen] = await Promise.all([\n resolveValue(this.config.model, ctx, input),\n resolveValue(this.config.prompt, ctx, input),\n resolveValue(this.config.system, ctx, input),\n resolveValue(this.config.messages, ctx, input),\n resolveValue(this.config.tools, ctx, input),\n resolveValue(this.config.activeTools, ctx, input),\n resolveValue(this.config.toolChoice, ctx, input),\n resolveValue(this.config.stopWhen, ctx, input),\n ]);\n const tools = this.resolveTools(rawTools ?? {}, ctx);\n return { model, prompt, system, messages, tools, activeTools, toolChoice, stopWhen };\n }\n\n private resolveTools(\n tools: AgentToolSet<TContext>,\n ctx: TContext\n ): Record<string, Tool> {\n const entries = Object.entries(tools);\n if (entries.length === 0) return tools as Record<string, Tool>;\n let hasProvider = false;\n const resolved: Record<string, Tool> = {};\n for (const [key, toolOrProvider] of entries) {\n if (isToolProvider<TContext>(toolOrProvider)) {\n hasProvider = true;\n resolved[key] = toolOrProvider.createTool(ctx as Readonly<TContext>);\n } else {\n resolved[key] = toolOrProvider as Tool;\n }\n }\n return hasProvider ? resolved : (tools as Record<string, Tool>);\n }\n}\n","import { tool, type Tool, type ToolExecutionOptions, type FlexibleSchema } from \"ai\";\n\nexport const TOOL_PROVIDER_BRAND = Symbol.for(\"agent-workflow.ToolProvider\");\n\nexport type ToolProviderConfig<TContext, TInput, TOutput> = {\n description?: string;\n input: FlexibleSchema<TInput>;\n output?: FlexibleSchema<unknown>;\n providerOptions?: unknown;\n execute: (input: TInput, ctx: Readonly<TContext>, options?: ToolExecutionOptions) => Promise<TOutput>;\n};\n\nexport interface IToolProvider<TContext> {\n readonly [TOOL_PROVIDER_BRAND]: true;\n createTool(context: Readonly<TContext>): Tool;\n}\n\nexport class ToolProvider<\n TContext,\n TInput = unknown,\n TOutput = unknown,\n> implements IToolProvider<TContext> {\n readonly [TOOL_PROVIDER_BRAND] = true as const;\n private readonly config: ToolProviderConfig<TContext, TInput, TOutput>;\n\n constructor(config: ToolProviderConfig<TContext, TInput, TOutput>) {\n this.config = config;\n }\n\n createTool(context: Readonly<TContext>): Tool {\n const { execute, input: inputSchema, ...toolDef } = this.config;\n return tool({\n ...toolDef,\n parameters: inputSchema,\n execute: (input: TInput, options?: ToolExecutionOptions) => execute(input, context, options),\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } as any);\n }\n}\n\nexport function defineTool<TContext>() {\n return <TInput, TOutput>(\n config: ToolProviderConfig<TContext, TInput, TOutput>\n ): ToolProvider<TContext, TInput, TOutput> => new ToolProvider(config);\n}\n\nexport function isToolProvider<TContext>(obj: unknown): obj is IToolProvider<TContext> {\n return (\n typeof obj === \"object\" &&\n obj !== null &&\n TOOL_PROVIDER_BRAND in obj\n );\n}\n","export type MaybePromise<T> = T | Promise<T>;\n\n/**\n * A value that can be static or derived from context and input.\n * Used for agent config fields that may need runtime resolution.\n *\n * Functions may return a Promise for async resolution; static values are always sync.\n */\nexport type Resolvable<TCtx, TInput, TValue> =\n | TValue\n | ((ctx: Readonly<TCtx>, input: TInput) => TValue | Promise<TValue>);\n\nexport function resolveValue<TCtx, TInput, TValue>(\n value: Resolvable<TCtx, TInput, TValue>,\n ctx: TCtx,\n input: TInput\n): TValue | Promise<TValue>;\nexport function resolveValue<TCtx, TInput, TValue>(\n value: Resolvable<TCtx, TInput, TValue> | undefined,\n ctx: TCtx,\n input: TInput\n): TValue | Promise<TValue> | undefined {\n if (typeof value === \"function\") {\n return (value as (ctx: TCtx, input: TInput) => TValue | Promise<TValue>)(ctx, input);\n }\n return value;\n}\n\n/**\n * Extract structured output from an AI SDK result, falling back to text.\n * Works for both generate (sync .output/.text) and stream (async .output/.text) results.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport async function extractOutput(result: any, hasStructuredOutput: boolean): Promise<unknown> {\n if (hasStructuredOutput) {\n const output = await result.output;\n if (output !== undefined) return output;\n }\n return await result.text;\n}\n","import {\n createUIMessageStream,\n type UIMessageStreamWriter,\n} from \"ai\";\nimport { type Agent, type GenerateTextResult, type StreamTextResult } from \"./agent\";\nimport { extractOutput, type MaybePromise } from \"./utils\";\n\n// ── Error Types ─────────────────────────────────────────────────────\n\nexport class WorkflowBranchError extends Error {\n constructor(\n public readonly branchType: \"predicate\" | \"select\",\n message: string,\n ) {\n super(message);\n this.name = \"WorkflowBranchError\";\n }\n}\n\nexport class WorkflowLoopError extends Error {\n constructor(\n public readonly iterations: number,\n public readonly maxIterations: number,\n ) {\n super(`Loop exceeded maximum iterations (${maxIterations})`);\n this.name = \"WorkflowLoopError\";\n }\n}\n\n// ── Shared Agent Step Hooks ─────────────────────────────────────────\n\nexport interface AgentStepHooks<TContext, TOutput, TNextOutput> {\n mapGenerateResult?: (params: { result: GenerateTextResult; ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<TNextOutput>;\n mapStreamResult?: (params: { result: StreamTextResult; ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<TNextOutput>;\n onGenerateResult?: (params: { result: GenerateTextResult; ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<void>;\n onStreamResult?: (params: { result: StreamTextResult; ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<void>;\n handleStream?: (params: {\n result: StreamTextResult;\n writer: UIMessageStreamWriter;\n ctx: Readonly<TContext>;\n }) => MaybePromise<void>;\n}\n\n// ── Step Options ────────────────────────────────────────────────────\n\nexport type StepOptions<TContext, TOutput, TNextOutput> = AgentStepHooks<TContext, TOutput, TNextOutput>;\n\n// ── Branch Types ────────────────────────────────────────────────────\n\nexport interface BranchCase<TContext, TOutput, TNextOutput> extends AgentStepHooks<TContext, TOutput, TNextOutput> {\n when?: (params: { ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<boolean>;\n agent: Agent<TContext, TOutput, TNextOutput>;\n}\n\nexport interface BranchSelect<TContext, TOutput, TKeys extends string, TNextOutput> extends AgentStepHooks<TContext, TOutput, TNextOutput> {\n select: (params: { ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<TKeys>;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n agents: Record<TKeys, Agent<TContext, any, TNextOutput>>;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n fallback?: Agent<TContext, any, TNextOutput>;\n}\n\n// ── Result Types ────────────────────────────────────────────────────\n\nexport interface WorkflowResult<TOutput> {\n output: TOutput;\n}\n\nexport interface WorkflowStreamResult<TOutput> {\n stream: ReadableStream;\n output: Promise<TOutput>;\n}\n\nexport interface WorkflowStreamOptions {\n onError?: (error: unknown) => string;\n onFinish?: () => MaybePromise<void>;\n}\n\n// ── Loop Types ──────────────────────────────────────────────────────\n\ntype LoopPredicate<TContext, TOutput> = (params: {\n output: TOutput;\n ctx: Readonly<TContext>;\n iterations: number;\n}) => MaybePromise<boolean>;\n\n// Exactly one of `until` or `while` — never both.\nexport type RepeatOptions<TContext, TOutput> =\n | { until: LoopPredicate<TContext, TOutput>; while?: never; maxIterations?: number }\n | { while: LoopPredicate<TContext, TOutput>; until?: never; maxIterations?: number };\n\n// Extracts the element type from an array type. Resolves to `never` for non-arrays,\n// making foreach uncallable at compile time when the previous step doesn't produce an array.\ntype ElementOf<T> = T extends readonly (infer E)[] ? E : never;\n\n// ── Step Node ───────────────────────────────────────────────────────\n\ntype StepNode =\n | { readonly type: \"step\"; readonly id: string; readonly execute: (state: RuntimeState) => MaybePromise<void> }\n | { readonly type: \"catch\"; readonly id: string; readonly catchFn: (params: { error: unknown; ctx: unknown; lastOutput: unknown; stepId: string }) => MaybePromise<unknown> }\n | { readonly type: \"finally\"; readonly id: string; readonly execute: (state: RuntimeState) => MaybePromise<void> };\n\ninterface RuntimeState {\n ctx: unknown;\n output: unknown;\n mode: \"generate\" | \"stream\";\n writer?: UIMessageStreamWriter;\n}\n\n// ── Sealed Workflow (returned by finally — execution only) ───────────\n\nexport class SealedWorkflow<\n TContext,\n TInput = void,\n TOutput = void,\n> {\n readonly id?: string;\n protected readonly steps: ReadonlyArray<StepNode>;\n\n protected constructor(steps: ReadonlyArray<StepNode>, id?: string) {\n this.steps = steps;\n this.id = id;\n }\n\n // ── Execution ─────────────────────────────────────────────────\n\n async generate(ctx: TContext, ...args: TInput extends void ? [input?: TInput] : [input: TInput]): Promise<WorkflowResult<TOutput>> {\n const input = args[0];\n const state: RuntimeState = {\n ctx,\n output: input,\n mode: \"generate\",\n };\n\n await this.execute(state);\n\n return {\n output: state.output as TOutput,\n };\n }\n\n stream(\n ctx: TContext,\n ...args: TInput extends void\n ? [input?: TInput, options?: WorkflowStreamOptions]\n : [input: TInput, options?: WorkflowStreamOptions]\n ): WorkflowStreamResult<TOutput> {\n const input = args[0];\n const options = args[1] as WorkflowStreamOptions | undefined;\n\n let resolveOutput: (value: TOutput) => void;\n let rejectOutput: (error: unknown) => void;\n const outputPromise = new Promise<TOutput>((res, rej) => {\n resolveOutput = res;\n rejectOutput = rej;\n });\n\n // Prevent unhandled rejection warning if the consumer never awaits `output`.\n // The original promise still rejects normally when awaited.\n outputPromise.catch(() => {});\n\n const stream = createUIMessageStream({\n execute: async ({ writer }) => {\n const state: RuntimeState = {\n ctx,\n output: input,\n mode: \"stream\",\n writer,\n };\n\n try {\n await this.execute(state);\n resolveOutput(state.output as TOutput);\n } catch (error) {\n rejectOutput!(error);\n throw error;\n }\n },\n ...(options?.onError ? { onError: options.onError } : {}),\n ...(options?.onFinish ? { onFinish: options.onFinish } : {}),\n });\n\n return {\n stream,\n output: outputPromise,\n };\n }\n\n // ── Internal: execute pipeline ────────────────────────────────\n\n protected async execute(state: RuntimeState): Promise<void> {\n if (this.steps.length === 0) {\n throw new Error(\"Workflow has no steps. Add at least one step before calling generate() or stream().\");\n }\n\n let pendingError: { error: unknown; stepId: string } | null = null;\n\n for (const node of this.steps) {\n if (node.type === \"finally\") {\n await node.execute(state);\n continue;\n }\n\n if (node.type === \"catch\") {\n if (!pendingError) continue;\n try {\n state.output = await node.catchFn({\n error: pendingError.error,\n ctx: state.ctx,\n lastOutput: state.output,\n stepId: pendingError.stepId,\n });\n pendingError = null;\n } catch (catchError) {\n pendingError = { error: catchError, stepId: node.id };\n }\n continue;\n }\n\n // type === \"step\" — skip while in error state\n if (pendingError) continue;\n\n try {\n await node.execute(state);\n } catch (error) {\n pendingError = { error, stepId: node.id };\n }\n }\n\n if (pendingError) throw pendingError.error;\n }\n\n // ── Internal: execute a nested workflow within a step/loop ─────\n // Defined on SealedWorkflow (not Workflow) because TypeScript's protected\n // access rules only allow calling workflow.execute() from the same class.\n\n protected async executeNestedWorkflow(\n state: RuntimeState,\n workflow: SealedWorkflow<TContext, unknown, unknown>,\n ): Promise<void> {\n await workflow.execute(state);\n }\n\n // ── Internal: execute an agent within a step/branch ───────────\n // In stream mode, output extraction awaits the full stream before returning.\n // Streaming benefits the client (incremental output), not pipeline throughput —\n // each step still runs sequentially.\n\n protected async executeAgent<TAgentInput, TNextOutput>(\n state: RuntimeState,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n agent: Agent<TContext, any, TNextOutput>,\n ctx: TContext,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n options?: AgentStepHooks<TContext, any, TNextOutput>,\n ): Promise<void> {\n const input = state.output as TAgentInput;\n const hasStructuredOutput = agent.hasOutput;\n\n if (state.mode === \"stream\" && state.writer) {\n const result = await (agent.stream as (ctx: TContext, input: unknown) => Promise<StreamTextResult>)(ctx, state.output);\n\n if (options?.handleStream) {\n await options.handleStream({ result, writer: state.writer, ctx });\n } else {\n state.writer.merge(result.toUIMessageStream());\n }\n\n if (options?.onStreamResult) {\n await options.onStreamResult({ result, ctx, input });\n }\n\n if (options?.mapStreamResult) {\n state.output = await options.mapStreamResult({ result, ctx, input });\n } else {\n state.output = await extractOutput(result, hasStructuredOutput);\n }\n } else {\n const result = await (agent.generate as (ctx: TContext, input: unknown) => Promise<GenerateTextResult>)(ctx, state.output);\n\n if (options?.onGenerateResult) {\n await options.onGenerateResult({ result, ctx, input });\n }\n\n if (options?.mapGenerateResult) {\n state.output = await options.mapGenerateResult({ result, ctx, input });\n } else {\n state.output = await extractOutput(result, hasStructuredOutput);\n }\n }\n }\n}\n\n// ── Workflow ────────────────────────────────────────────────────────\n\nexport class Workflow<\n TContext,\n TInput = void,\n TOutput = void,\n> extends SealedWorkflow<TContext, TInput, TOutput> {\n\n private constructor(steps: ReadonlyArray<StepNode> = [], id?: string) {\n super(steps, id);\n }\n\n static create<TContext, TInput = void>(options?: { id?: string }): Workflow<TContext, TInput, TInput> {\n return new Workflow<TContext, TInput, TInput>([], options?.id);\n }\n\n static from<TContext, TInput, TOutput>(\n agent: Agent<TContext, TInput, TOutput>,\n options?: StepOptions<TContext, TInput, TOutput>\n ): Workflow<TContext, TInput, TOutput> {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, any>([]).step(agent, options);\n }\n\n // ── step: agent overload ──────────────────────────────────────\n\n step<TNextOutput>(\n agent: Agent<TContext, TOutput, TNextOutput>,\n options?: StepOptions<TContext, TOutput, TNextOutput>\n ): Workflow<TContext, TInput, TNextOutput>;\n\n // ── step: nested workflow overload ─────────────────────────────\n\n step<TNextOutput>(\n workflow: SealedWorkflow<TContext, TOutput, TNextOutput>,\n ): Workflow<TContext, TInput, TNextOutput>;\n\n // ── step: transform overload (replaces map + tap) ─────────────\n\n step<TNextOutput>(\n id: string,\n fn: (params: { ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<TNextOutput>\n ): Workflow<TContext, TInput, TNextOutput>;\n\n // ── step: implementation ──────────────────────────────────────\n\n step<TNextOutput>(\n target: Agent<TContext, TOutput, TNextOutput> | SealedWorkflow<TContext, TOutput, TNextOutput> | string,\n optionsOrFn?: StepOptions<TContext, TOutput, TNextOutput> | ((params: { ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<TNextOutput>)\n ): Workflow<TContext, TInput, TNextOutput> {\n // Nested workflow overload: step(workflow)\n if (target instanceof SealedWorkflow) {\n const workflow = target;\n const node: StepNode = {\n type: \"step\",\n id: workflow.id ?? \"nested-workflow\",\n execute: async (state) => {\n await this.executeNestedWorkflow(state, workflow as SealedWorkflow<TContext, unknown, unknown>);\n },\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNextOutput>([...this.steps, node] as any, this.id);\n }\n\n // Transform overload: step(id, fn)\n if (typeof target === \"string\") {\n if (typeof optionsOrFn !== \"function\") {\n throw new Error(`Workflow step(\"${target}\"): second argument must be a function`);\n }\n const fn = optionsOrFn as (params: { ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<TNextOutput>;\n const node: StepNode = {\n type: \"step\",\n id: target,\n execute: async (state) => {\n state.output = await fn({\n ctx: state.ctx as Readonly<TContext>,\n input: state.output as TOutput,\n });\n },\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNextOutput>([...this.steps, node] as any, this.id);\n }\n\n // Agent overload: step(agent, options?)\n const agent = target;\n const options = optionsOrFn as StepOptions<TContext, TOutput, TNextOutput> | undefined;\n const node: StepNode = {\n type: \"step\",\n id: agent.id,\n execute: async (state) => {\n const ctx = state.ctx as TContext;\n await this.executeAgent(state, agent, ctx, options);\n },\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNextOutput>([...this.steps, node] as any, this.id);\n }\n\n // ── branch: predicate routing (array) ─────────────────────────\n\n branch<TNextOutput>(\n cases: BranchCase<TContext, TOutput, TNextOutput>[]\n ): Workflow<TContext, TInput, TNextOutput>;\n\n // ── branch: key routing (select) ──────────────────────────────\n\n branch<TKeys extends string, TNextOutput>(\n config: BranchSelect<TContext, TOutput, TKeys, TNextOutput>\n ): Workflow<TContext, TInput, TNextOutput>;\n\n // ── branch: implementation ────────────────────────────────────\n\n branch<TKeys extends string, TNextOutput>(\n casesOrConfig: BranchCase<TContext, TOutput, TNextOutput>[] | BranchSelect<TContext, TOutput, TKeys, TNextOutput>\n ): Workflow<TContext, TInput, TNextOutput> {\n if (Array.isArray(casesOrConfig)) {\n return this.branchPredicate(casesOrConfig);\n }\n return this.branchSelect(casesOrConfig);\n }\n\n private branchPredicate<TNextOutput>(\n cases: BranchCase<TContext, TOutput, TNextOutput>[]\n ): Workflow<TContext, TInput, TNextOutput> {\n const node: StepNode = {\n type: \"step\",\n id: \"branch:predicate\",\n execute: async (state) => {\n const ctx = state.ctx as TContext;\n const input = state.output as TOutput;\n\n for (const branchCase of cases) {\n if (branchCase.when) {\n const match = await branchCase.when({ ctx, input });\n if (!match) continue;\n }\n\n // Matched (or no `when` = default)\n await this.executeAgent(state, branchCase.agent, ctx, branchCase);\n return;\n }\n\n throw new WorkflowBranchError(\"predicate\", `No branch matched and no default branch (a case without \\`when\\`) was provided. Input: ${JSON.stringify(input)}`);\n },\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNextOutput>([...this.steps, node] as any, this.id);\n }\n\n private branchSelect<TKeys extends string, TNextOutput>(\n config: BranchSelect<TContext, TOutput, TKeys, TNextOutput>\n ): Workflow<TContext, TInput, TNextOutput> {\n const node: StepNode = {\n type: \"step\",\n id: \"branch:select\",\n execute: async (state) => {\n const ctx = state.ctx as TContext;\n const input = state.output as TOutput;\n const key = await config.select({ ctx, input });\n\n let agent = config.agents[key];\n if (!agent) {\n if (config.fallback) {\n agent = config.fallback;\n } else {\n throw new WorkflowBranchError(\"select\", `No agent found for key \"${key}\" and no fallback provided. Available keys: ${Object.keys(config.agents).join(\", \")}`);\n }\n }\n\n await this.executeAgent(state, agent, ctx, config);\n },\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNextOutput>([...this.steps, node] as any, this.id);\n }\n\n // ── foreach: array iteration ─────────────────────────────────\n\n foreach<TNextOutput>(\n target: Agent<TContext, ElementOf<TOutput>, TNextOutput> | SealedWorkflow<TContext, ElementOf<TOutput>, TNextOutput>,\n options?: { concurrency?: number },\n ): Workflow<TContext, TInput, TNextOutput[]> {\n const concurrency = options?.concurrency ?? 1;\n const isWorkflow = target instanceof SealedWorkflow;\n const id = isWorkflow ? (target.id ?? \"foreach\") : `foreach:${(target as Agent<TContext, ElementOf<TOutput>, TNextOutput>).id}`;\n\n const node: StepNode = {\n type: \"step\",\n id,\n execute: async (state) => {\n const items = state.output;\n if (!Array.isArray(items)) {\n throw new Error(`foreach \"${id}\": expected array input, got ${typeof items}`);\n }\n\n const ctx = state.ctx as TContext;\n const results: unknown[] = new Array(items.length);\n\n // Streaming is intentionally not propagated to foreach items —\n // each item runs in generate mode because merging interleaved\n // streams from parallel items into a single writer is not supported.\n const executeItem = async (item: unknown, index: number) => {\n const itemState: RuntimeState = { ctx: state.ctx, output: item, mode: \"generate\" };\n if (isWorkflow) {\n await this.executeNestedWorkflow(itemState, target as SealedWorkflow<TContext, unknown, unknown>);\n } else {\n await this.executeAgent(itemState, target as Agent<TContext, unknown, TNextOutput>, ctx);\n }\n results[index] = itemState.output;\n };\n\n if (concurrency <= 1) {\n for (let i = 0; i < items.length; i++) {\n await executeItem(items[i], i);\n }\n } else {\n for (let i = 0; i < items.length; i += concurrency) {\n const batch = items.slice(i, i + concurrency);\n await Promise.all(batch.map((item, j) => executeItem(item, i + j)));\n }\n }\n\n state.output = results;\n },\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNextOutput[]>([...this.steps, node] as any, this.id);\n }\n\n // ── repeat: conditional loop ─────────────────────────────────\n\n repeat(\n target: Agent<TContext, TOutput, TOutput> | SealedWorkflow<TContext, TOutput, TOutput>,\n options: RepeatOptions<TContext, TOutput>,\n ): Workflow<TContext, TInput, TOutput> {\n const maxIterations = options.maxIterations ?? 10;\n const isWorkflow = target instanceof SealedWorkflow;\n const id = isWorkflow ? (target.id ?? \"repeat\") : `repeat:${(target as Agent<TContext, TOutput, TOutput>).id}`;\n const predicate: LoopPredicate<TContext, TOutput> = options.until\n ?? (async (p) => !(await options.while!(p)));\n\n const node: StepNode = {\n type: \"step\",\n id,\n execute: async (state) => {\n const ctx = state.ctx as TContext;\n\n for (let i = 1; i <= maxIterations; i++) {\n if (isWorkflow) {\n await this.executeNestedWorkflow(state, target as SealedWorkflow<TContext, unknown, unknown>);\n } else {\n await this.executeAgent(state, target as Agent<TContext, TOutput, TOutput>, ctx);\n }\n\n const done = await predicate({\n output: state.output as TOutput,\n ctx: ctx as Readonly<TContext>,\n iterations: i,\n });\n if (done) return;\n }\n\n throw new WorkflowLoopError(maxIterations, maxIterations);\n },\n };\n return new Workflow<TContext, TInput, TOutput>([...this.steps, node], this.id);\n }\n\n // ── catch ─────────────────────────────────────────────────────\n\n catch(\n id: string,\n fn: (params: { error: unknown; ctx: Readonly<TContext>; lastOutput: TOutput; stepId: string }) => MaybePromise<TOutput>\n ): Workflow<TContext, TInput, TOutput> {\n if (!this.steps.some(s => s.type === \"step\")) {\n throw new Error(`Workflow: catch(\"${id}\") requires at least one preceding step.`);\n }\n const node: StepNode = {\n type: \"catch\",\n id,\n catchFn: fn as (params: { error: unknown; ctx: unknown; lastOutput: unknown; stepId: string }) => MaybePromise<unknown>,\n };\n return new Workflow<TContext, TInput, TOutput>([...this.steps, node], this.id);\n }\n\n // ── finally (terminal — returns sealed workflow) ──────────────\n\n finally(\n id: string,\n fn: (params: { ctx: Readonly<TContext> }) => MaybePromise<void>\n ): SealedWorkflow<TContext, TInput, TOutput> {\n const node: StepNode = {\n type: \"finally\",\n id,\n execute: async (state) => {\n await fn({ ctx: state.ctx as Readonly<TContext> });\n },\n };\n return new SealedWorkflow<TContext, TInput, TOutput>([...this.steps, node], this.id);\n }\n}\n\n"],"mappings":"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","names":["tool","tool","node"]}
|
|
1
|
+
{"version":3,"sources":["../src/agent.ts","../src/tool-provider.ts","../src/utils.ts","../src/workflow.ts"],"sourcesContent":["import {\n generateText,\n streamText,\n tool,\n Output,\n type GenerateTextResult as AIGenerateTextResult,\n type StreamTextResult as AIStreamTextResult,\n type UIMessageStreamWriter,\n type ModelMessage,\n type LanguageModel,\n type Tool,\n type ToolSet,\n type StopCondition,\n type ToolChoice,\n type OnStepFinishEvent,\n type OnFinishEvent,\n} from \"ai\";\n\n// Extract the Output interface type from the Output.object return type\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype OutputType<T = any> = ReturnType<typeof Output.object<T>>;\nimport type { ZodType } from \"zod\";\nimport { isToolProvider, TOOL_PROVIDER_BRAND, type IToolProvider } from \"./tool-provider\";\nimport { extractOutput, getActiveWriter, resolveValue, type MaybePromise, type Resolvable } from \"./utils\";\n\n// Tools config accepts both AI SDK tools and context-aware ToolProviders\ntype AgentToolSet<TContext> = Record<string, Tool | IToolProvider<TContext>>;\n\n// ── Result type aliases ─────────────────────────────────────────────\n\nexport type GenerateTextResult<TOOLS extends ToolSet = ToolSet, OUTPUT extends OutputType = OutputType> = AIGenerateTextResult<TOOLS, OUTPUT>;\nexport type StreamTextResult<TOOLS extends ToolSet = ToolSet, OUTPUT extends OutputType = OutputType> = AIStreamTextResult<TOOLS, OUTPUT>;\n\n// ── AI SDK passthrough types ────────────────────────────────────────\n\n// Extract options types from both AI SDK entry points\ntype StreamTextOptions = Parameters<typeof streamText>[0];\ntype GenerateTextOptions = Parameters<typeof generateText>[0];\n\n// Keys we replace with resolvable or context-enriched versions\ntype ManagedKeys =\n | 'model' | 'system' | 'prompt' | 'messages'\n | 'tools' | 'activeTools' | 'toolChoice' | 'stopWhen'\n | 'output' | 'onFinish' | 'onStepFinish' | 'onError';\n\n// Combine options from both streamText and generateText.\n// Each side contributes its unique props; shared props merge naturally.\n// Stream-only props (onChunk, onAbort) are ignored by generateText.\n// Generate-only props (experimental_include.responseBody) are ignored by streamText.\ntype AIPassthroughOptions =\n Omit<StreamTextOptions, ManagedKeys> &\n Omit<GenerateTextOptions, ManagedKeys>;\n\n// ── Resolved config (output of resolveConfig / resolveConfigAsync) ──\n\ninterface ResolvedAgentConfig {\n model: LanguageModel;\n prompt: string | undefined;\n system: string | undefined;\n messages: ModelMessage[] | undefined;\n tools: Record<string, Tool>;\n activeTools: string[] | undefined;\n toolChoice: ToolChoice<ToolSet> | undefined;\n stopWhen: StopCondition<ToolSet> | Array<StopCondition<ToolSet>> | undefined;\n}\n\n// ── Agent Configuration ─────────────────────────────────────────────\n\nexport interface AgentConfig<\n TContext,\n TInput = void,\n TOutput = void,\n> extends AIPassthroughOptions {\n // ── Custom (not in AI SDK) ──\n id: string;\n description?: string;\n input?: ZodType<TInput>;\n output?: OutputType<TOutput>;\n\n // ── Resolvable (our versions of AI SDK properties) ──\n model: Resolvable<TContext, TInput, LanguageModel>;\n system?: Resolvable<TContext, TInput, string>;\n prompt?: Resolvable<TContext, TInput, string>;\n messages?: Resolvable<TContext, TInput, ModelMessage[]>;\n tools?: Resolvable<TContext, TInput, AgentToolSet<TContext>>;\n activeTools?: Resolvable<TContext, TInput, string[]>;\n toolChoice?: Resolvable<TContext, TInput, ToolChoice<ToolSet>>;\n stopWhen?: Resolvable<TContext, TInput, StopCondition<ToolSet> | Array<StopCondition<ToolSet>>>;\n\n // ── Context-enriched callbacks (replace AI SDK versions) ──\n // `writer` is available when the agent runs inside a streaming workflow.\n onStepFinish?: (params: { result: OnStepFinishEvent; ctx: Readonly<TContext>; input: TInput; writer?: UIMessageStreamWriter }) => MaybePromise<void>;\n onFinish?: (params: { result: OnFinishEvent; ctx: Readonly<TContext>; input: TInput; writer?: UIMessageStreamWriter }) => MaybePromise<void>;\n onError?: (params: { error: unknown; ctx: Readonly<TContext>; input: TInput; writer?: UIMessageStreamWriter }) => MaybePromise<void>;\n}\n\n// ── Agent ───────────────────────────────────────────────────────────\n\nexport class Agent<\n TContext,\n TInput = void,\n TOutput = void,\n> {\n readonly id: string;\n readonly description: string;\n readonly hasOutput: boolean;\n private readonly config: AgentConfig<TContext, TInput, TOutput>;\n private readonly _hasDynamicConfig: boolean;\n private readonly _resolvedStaticTools: Record<string, Tool> | null = null;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private readonly _passthrough: Record<string, any>;\n private readonly _onStepFinish: AgentConfig<TContext, TInput, TOutput>['onStepFinish'];\n private readonly _onFinish: AgentConfig<TContext, TInput, TOutput>['onFinish'];\n\n constructor(config: AgentConfig<TContext, TInput, TOutput>) {\n this.id = config.id;\n this.description = config.description ?? \"\";\n this.hasOutput = config.output !== undefined;\n this.config = config;\n this._hasDynamicConfig = [\n config.model, config.system, config.prompt,\n config.messages, config.tools, config.activeTools,\n config.toolChoice, config.stopWhen,\n ].some(v => typeof v === \"function\");\n\n // Cache tools when config is static and contains no ToolProviders.\n // Avoids re-iterating the tools map on every generate()/stream() call.\n if (!this._hasDynamicConfig) {\n const rawTools = (config.tools as AgentToolSet<TContext> | undefined) ?? {};\n const hasProvider = Object.values(rawTools).some(v => isToolProvider(v));\n if (!hasProvider) {\n this._resolvedStaticTools = rawTools as Record<string, Tool>;\n }\n }\n\n // Pre-compute the passthrough (AI SDK options we don't manage) once,\n // rather than destructuring on every generate()/stream() call.\n const {\n id: _id, description: _desc, input: _inputSchema, output: _output,\n model: _m, system: _s, prompt: _p, messages: _msg,\n tools: _t, activeTools: _at, toolChoice: _tc, stopWhen: _sw,\n onStepFinish, onFinish, onError: _onError,\n ...passthrough\n } = config;\n this._passthrough = passthrough;\n this._onStepFinish = onStepFinish;\n this._onFinish = onFinish;\n }\n\n async generate(ctx: TContext, ...args: TInput extends void ? [input?: TInput] : [input: TInput]): Promise<GenerateTextResult> {\n const input = args[0] as TInput;\n const resolved = await this.resolveConfig(ctx, input);\n const options = this.buildCallOptions(resolved, ctx, input);\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return await generateText(options as any);\n } catch (error: unknown) {\n if (this.config.onError) {\n await this.config.onError({ error, ctx, input, writer: getActiveWriter() });\n }\n throw error;\n }\n }\n\n async stream(ctx: TContext, ...args: TInput extends void ? [input?: TInput] : [input: TInput]): Promise<StreamTextResult> {\n const input = args[0] as TInput;\n const resolved = await this.resolveConfig(ctx, input);\n const options = this.buildCallOptions(resolved, ctx, input);\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return streamText({\n ...options,\n onError: this.config.onError\n ? ({ error }: { error: unknown }) => this.config.onError!({ error, ctx, input, writer: getActiveWriter() })\n : undefined,\n } as any);\n }\n\n asTool(ctx: TContext, options?: {\n mapOutput?: (result: GenerateTextResult) => MaybePromise<TOutput>;\n }): Tool {\n return this.createToolInstance(ctx, options);\n }\n\n asToolProvider(options?: {\n mapOutput?: (result: GenerateTextResult) => MaybePromise<TOutput>;\n }): IToolProvider<TContext> {\n if (!this.config.input) {\n throw new Error(`Agent \"${this.id}\": asToolProvider() requires an input schema`);\n }\n\n return {\n [TOOL_PROVIDER_BRAND]: true as const,\n createTool: (ctx: Readonly<TContext>) => this.createToolInstance(ctx as TContext, options),\n };\n }\n\n private createToolInstance(ctx: TContext, options?: {\n mapOutput?: (result: GenerateTextResult) => MaybePromise<TOutput>;\n }): Tool {\n if (!this.config.input) {\n throw new Error(`Agent \"${this.id}\": asTool() requires an input schema`);\n }\n\n return tool({\n description: this.description,\n parameters: this.config.input,\n execute: async (toolInput: TInput) => {\n // When inside a streaming workflow, automatically use stream() and merge to the active writer.\n // Otherwise fall back to generate().\n const writer = getActiveWriter();\n if (writer) {\n const result = await (this.stream as (ctx: TContext, input: TInput) => Promise<StreamTextResult>)(ctx, toolInput);\n writer.merge(result.toUIMessageStream());\n if (options?.mapOutput) return options.mapOutput(result as unknown as GenerateTextResult);\n return extractOutput(result, this.hasOutput);\n }\n const result = await (this.generate as (ctx: TContext, input: TInput) => Promise<GenerateTextResult>)(ctx, toolInput);\n if (options?.mapOutput) return options.mapOutput(result);\n return extractOutput(result, this.hasOutput);\n },\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } as any);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private buildCallOptions(resolved: ResolvedAgentConfig, ctx: TContext, input: TInput): Record<string, any> {\n return {\n ...this._passthrough,\n model: resolved.model,\n tools: resolved.tools,\n activeTools: resolved.activeTools,\n toolChoice: resolved.toolChoice,\n stopWhen: resolved.stopWhen,\n ...(resolved.messages\n ? { messages: resolved.messages }\n : { prompt: resolved.prompt ?? \"\" }),\n ...(resolved.system ? { system: resolved.system } : {}),\n ...(this.config.output ? { output: this.config.output } : {}),\n onStepFinish: this._onStepFinish\n ? (event: OnStepFinishEvent) => this._onStepFinish!({ result: event, ctx, input, writer: getActiveWriter() })\n : undefined,\n onFinish: this._onFinish\n ? (event: OnFinishEvent) => this._onFinish!({ result: event, ctx, input, writer: getActiveWriter() })\n : undefined,\n };\n }\n\n private resolveConfig(ctx: TContext, input: TInput): ResolvedAgentConfig | Promise<ResolvedAgentConfig> {\n if (!this._hasDynamicConfig) {\n return {\n model: this.config.model as LanguageModel,\n prompt: this.config.prompt as string | undefined,\n system: this.config.system as string | undefined,\n messages: this.config.messages as ModelMessage[] | undefined,\n tools: this._resolvedStaticTools ?? this.resolveTools(\n (this.config.tools as AgentToolSet<TContext> | undefined) ?? {}, ctx\n ),\n activeTools: this.config.activeTools as string[] | undefined,\n toolChoice: this.config.toolChoice as ToolChoice<ToolSet> | undefined,\n stopWhen: this.config.stopWhen as StopCondition<ToolSet> | Array<StopCondition<ToolSet>> | undefined,\n };\n }\n return this.resolveConfigAsync(ctx, input);\n }\n\n private async resolveConfigAsync(ctx: TContext, input: TInput): Promise<ResolvedAgentConfig> {\n const [model, prompt, system, messages, rawTools, activeTools, toolChoice, stopWhen] = await Promise.all([\n resolveValue(this.config.model, ctx, input),\n resolveValue(this.config.prompt, ctx, input),\n resolveValue(this.config.system, ctx, input),\n resolveValue(this.config.messages, ctx, input),\n resolveValue(this.config.tools, ctx, input),\n resolveValue(this.config.activeTools, ctx, input),\n resolveValue(this.config.toolChoice, ctx, input),\n resolveValue(this.config.stopWhen, ctx, input),\n ]);\n const tools = this.resolveTools(rawTools ?? {}, ctx);\n return { model, prompt, system, messages, tools, activeTools, toolChoice, stopWhen };\n }\n\n private resolveTools(\n tools: AgentToolSet<TContext>,\n ctx: TContext\n ): Record<string, Tool> {\n const entries = Object.entries(tools);\n if (entries.length === 0) return tools as Record<string, Tool>;\n let hasProvider = false;\n const resolved: Record<string, Tool> = {};\n for (const [key, toolOrProvider] of entries) {\n if (isToolProvider<TContext>(toolOrProvider)) {\n hasProvider = true;\n resolved[key] = toolOrProvider.createTool(ctx as Readonly<TContext>);\n } else {\n resolved[key] = toolOrProvider as Tool;\n }\n }\n return hasProvider ? resolved : (tools as Record<string, Tool>);\n }\n}\n","import { tool, type Tool, type ToolExecutionOptions, type FlexibleSchema, type UIMessageStreamWriter } from \"ai\";\nimport { getActiveWriter } from \"./utils\";\n\nexport const TOOL_PROVIDER_BRAND = Symbol.for(\"agent-workflow.ToolProvider\");\n\nexport type ToolExecuteOptions = ToolExecutionOptions & {\n writer?: UIMessageStreamWriter;\n};\n\nexport type ToolProviderConfig<TContext, TInput, TOutput> = {\n description?: string;\n input: FlexibleSchema<TInput>;\n output?: FlexibleSchema<unknown>;\n providerOptions?: unknown;\n execute: (input: TInput, ctx: Readonly<TContext>, options: ToolExecuteOptions) => Promise<TOutput>;\n};\n\nexport interface IToolProvider<TContext> {\n readonly [TOOL_PROVIDER_BRAND]: true;\n createTool(context: Readonly<TContext>): Tool;\n}\n\nexport class ToolProvider<\n TContext,\n TInput = unknown,\n TOutput = unknown,\n> implements IToolProvider<TContext> {\n readonly [TOOL_PROVIDER_BRAND] = true as const;\n private readonly config: ToolProviderConfig<TContext, TInput, TOutput>;\n\n constructor(config: ToolProviderConfig<TContext, TInput, TOutput>) {\n this.config = config;\n }\n\n createTool(context: Readonly<TContext>): Tool {\n const { execute, input: inputSchema, ...toolDef } = this.config;\n return tool({\n ...toolDef,\n parameters: inputSchema,\n execute: (input: TInput, options?: ToolExecutionOptions) => execute(input, context, { ...options, writer: getActiveWriter() } as ToolExecuteOptions),\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } as any);\n }\n}\n\nexport function defineTool<TContext>() {\n return <TInput, TOutput>(\n config: ToolProviderConfig<TContext, TInput, TOutput>\n ): ToolProvider<TContext, TInput, TOutput> => new ToolProvider(config);\n}\n\nexport function isToolProvider<TContext>(obj: unknown): obj is IToolProvider<TContext> {\n return (\n typeof obj === \"object\" &&\n obj !== null &&\n TOOL_PROVIDER_BRAND in obj\n );\n}\n","import { AsyncLocalStorage } from \"node:async_hooks\";\nimport type { UIMessageStreamWriter } from \"ai\";\n\n// ── Stream writer context ────────────────────────────────────────────\n// Invisible to the user. The workflow sets the writer before agent execution;\n// tools and sub-agents read it automatically via getActiveWriter().\n\nconst writerStorage = new AsyncLocalStorage<UIMessageStreamWriter>();\n\nexport function runWithWriter<T>(writer: UIMessageStreamWriter, fn: () => T): T {\n return writerStorage.run(writer, fn);\n}\n\nexport function getActiveWriter(): UIMessageStreamWriter | undefined {\n return writerStorage.getStore();\n}\n\n// ── Common types ─────────────────────────────────────────────────────\n\nexport type MaybePromise<T> = T | Promise<T>;\n\n/**\n * A value that can be static or derived from context and input.\n * Used for agent config fields that may need runtime resolution.\n *\n * Functions may return a Promise for async resolution; static values are always sync.\n */\nexport type Resolvable<TCtx, TInput, TValue> =\n | TValue\n | ((ctx: Readonly<TCtx>, input: TInput) => TValue | Promise<TValue>);\n\nexport function resolveValue<TCtx, TInput, TValue>(\n value: Resolvable<TCtx, TInput, TValue>,\n ctx: TCtx,\n input: TInput\n): TValue | Promise<TValue>;\nexport function resolveValue<TCtx, TInput, TValue>(\n value: Resolvable<TCtx, TInput, TValue> | undefined,\n ctx: TCtx,\n input: TInput\n): TValue | Promise<TValue> | undefined {\n if (typeof value === \"function\") {\n return (value as (ctx: TCtx, input: TInput) => TValue | Promise<TValue>)(ctx, input);\n }\n return value;\n}\n\n/**\n * Extract structured output from an AI SDK result, falling back to text.\n * Works for both generate (sync .output/.text) and stream (async .output/.text) results.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport async function extractOutput(result: any, hasStructuredOutput: boolean): Promise<unknown> {\n if (hasStructuredOutput) {\n const output = await result.output;\n if (output !== undefined) return output;\n }\n return await result.text;\n}\n","import {\n createUIMessageStream,\n type UIMessageStreamWriter,\n} from \"ai\";\nimport { type Agent, type GenerateTextResult, type StreamTextResult } from \"./agent\";\nimport { extractOutput, runWithWriter, type MaybePromise } from \"./utils\";\n\n// ── Error Types ─────────────────────────────────────────────────────\n\nexport class WorkflowBranchError extends Error {\n constructor(\n public readonly branchType: \"predicate\" | \"select\",\n message: string,\n ) {\n super(message);\n this.name = \"WorkflowBranchError\";\n }\n}\n\nexport class WorkflowLoopError extends Error {\n constructor(\n public readonly iterations: number,\n public readonly maxIterations: number,\n ) {\n super(`Loop exceeded maximum iterations (${maxIterations})`);\n this.name = \"WorkflowLoopError\";\n }\n}\n\n// ── Shared Agent Step Hooks ─────────────────────────────────────────\n\nexport interface AgentStepHooks<TContext, TOutput, TNextOutput> {\n mapGenerateResult?: (params: { result: GenerateTextResult; ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<TNextOutput>;\n mapStreamResult?: (params: { result: StreamTextResult; ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<TNextOutput>;\n onGenerateResult?: (params: { result: GenerateTextResult; ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<void>;\n onStreamResult?: (params: { result: StreamTextResult; ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<void>;\n handleStream?: (params: {\n result: StreamTextResult;\n writer: UIMessageStreamWriter;\n ctx: Readonly<TContext>;\n }) => MaybePromise<void>;\n}\n\n// ── Step Options ────────────────────────────────────────────────────\n\nexport type StepOptions<TContext, TOutput, TNextOutput> = AgentStepHooks<TContext, TOutput, TNextOutput>;\n\n// ── Branch Types ────────────────────────────────────────────────────\n\nexport interface BranchCase<TContext, TOutput, TNextOutput> extends AgentStepHooks<TContext, TOutput, TNextOutput> {\n when?: (params: { ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<boolean>;\n agent: Agent<TContext, TOutput, TNextOutput>;\n}\n\nexport interface BranchSelect<TContext, TOutput, TKeys extends string, TNextOutput> extends AgentStepHooks<TContext, TOutput, TNextOutput> {\n select: (params: { ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<TKeys>;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n agents: Record<TKeys, Agent<TContext, any, TNextOutput>>;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n fallback?: Agent<TContext, any, TNextOutput>;\n}\n\n// ── Result Types ────────────────────────────────────────────────────\n\nexport interface WorkflowResult<TOutput> {\n output: TOutput;\n}\n\nexport interface WorkflowStreamResult<TOutput> {\n stream: ReadableStream;\n output: Promise<TOutput>;\n}\n\nexport interface WorkflowStreamOptions {\n onError?: (error: unknown) => string;\n onFinish?: () => MaybePromise<void>;\n}\n\n// ── Loop Types ──────────────────────────────────────────────────────\n\ntype LoopPredicate<TContext, TOutput> = (params: {\n output: TOutput;\n ctx: Readonly<TContext>;\n iterations: number;\n}) => MaybePromise<boolean>;\n\n// Exactly one of `until` or `while` — never both.\nexport type RepeatOptions<TContext, TOutput> =\n | { until: LoopPredicate<TContext, TOutput>; while?: never; maxIterations?: number }\n | { while: LoopPredicate<TContext, TOutput>; until?: never; maxIterations?: number };\n\n// Extracts the element type from an array type. Resolves to `never` for non-arrays,\n// making foreach uncallable at compile time when the previous step doesn't produce an array.\ntype ElementOf<T> = T extends readonly (infer E)[] ? E : never;\n\n// ── Step Node ───────────────────────────────────────────────────────\n\ntype StepNode =\n | { readonly type: \"step\"; readonly id: string; readonly execute: (state: RuntimeState) => MaybePromise<void> }\n | { readonly type: \"catch\"; readonly id: string; readonly catchFn: (params: { error: unknown; ctx: unknown; lastOutput: unknown; stepId: string }) => MaybePromise<unknown> }\n | { readonly type: \"finally\"; readonly id: string; readonly execute: (state: RuntimeState) => MaybePromise<void> };\n\ninterface RuntimeState {\n ctx: unknown;\n output: unknown;\n mode: \"generate\" | \"stream\";\n writer?: UIMessageStreamWriter;\n}\n\n// ── Sealed Workflow (returned by finally — execution only) ───────────\n\nexport class SealedWorkflow<\n TContext,\n TInput = void,\n TOutput = void,\n> {\n readonly id?: string;\n protected readonly steps: ReadonlyArray<StepNode>;\n\n protected constructor(steps: ReadonlyArray<StepNode>, id?: string) {\n this.steps = steps;\n this.id = id;\n }\n\n // ── Execution ─────────────────────────────────────────────────\n\n async generate(ctx: TContext, ...args: TInput extends void ? [input?: TInput] : [input: TInput]): Promise<WorkflowResult<TOutput>> {\n const input = args[0];\n const state: RuntimeState = {\n ctx,\n output: input,\n mode: \"generate\",\n };\n\n await this.execute(state);\n\n return {\n output: state.output as TOutput,\n };\n }\n\n stream(\n ctx: TContext,\n ...args: TInput extends void\n ? [input?: TInput, options?: WorkflowStreamOptions]\n : [input: TInput, options?: WorkflowStreamOptions]\n ): WorkflowStreamResult<TOutput> {\n const input = args[0];\n const options = args[1] as WorkflowStreamOptions | undefined;\n\n let resolveOutput: (value: TOutput) => void;\n let rejectOutput: (error: unknown) => void;\n const outputPromise = new Promise<TOutput>((res, rej) => {\n resolveOutput = res;\n rejectOutput = rej;\n });\n\n // Prevent unhandled rejection warning if the consumer never awaits `output`.\n // The original promise still rejects normally when awaited.\n outputPromise.catch(() => {});\n\n const stream = createUIMessageStream({\n execute: async ({ writer }) => {\n const state: RuntimeState = {\n ctx,\n output: input,\n mode: \"stream\",\n writer,\n };\n\n try {\n await this.execute(state);\n resolveOutput(state.output as TOutput);\n } catch (error) {\n rejectOutput!(error);\n throw error;\n }\n },\n ...(options?.onError ? { onError: options.onError } : {}),\n ...(options?.onFinish ? { onFinish: options.onFinish } : {}),\n });\n\n return {\n stream,\n output: outputPromise,\n };\n }\n\n // ── Internal: execute pipeline ────────────────────────────────\n\n protected async execute(state: RuntimeState): Promise<void> {\n if (this.steps.length === 0) {\n throw new Error(\"Workflow has no steps. Add at least one step before calling generate() or stream().\");\n }\n\n let pendingError: { error: unknown; stepId: string } | null = null;\n\n for (const node of this.steps) {\n if (node.type === \"finally\") {\n await node.execute(state);\n continue;\n }\n\n if (node.type === \"catch\") {\n if (!pendingError) continue;\n try {\n state.output = await node.catchFn({\n error: pendingError.error,\n ctx: state.ctx,\n lastOutput: state.output,\n stepId: pendingError.stepId,\n });\n pendingError = null;\n } catch (catchError) {\n pendingError = { error: catchError, stepId: node.id };\n }\n continue;\n }\n\n // type === \"step\" — skip while in error state\n if (pendingError) continue;\n\n try {\n await node.execute(state);\n } catch (error) {\n pendingError = { error, stepId: node.id };\n }\n }\n\n if (pendingError) throw pendingError.error;\n }\n\n // ── Internal: execute a nested workflow within a step/loop ─────\n // Defined on SealedWorkflow (not Workflow) because TypeScript's protected\n // access rules only allow calling workflow.execute() from the same class.\n\n protected async executeNestedWorkflow(\n state: RuntimeState,\n workflow: SealedWorkflow<TContext, unknown, unknown>,\n ): Promise<void> {\n await workflow.execute(state);\n }\n\n // ── Internal: execute an agent within a step/branch ───────────\n // In stream mode, output extraction awaits the full stream before returning.\n // Streaming benefits the client (incremental output), not pipeline throughput —\n // each step still runs sequentially.\n\n protected async executeAgent<TAgentInput, TNextOutput>(\n state: RuntimeState,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n agent: Agent<TContext, any, TNextOutput>,\n ctx: TContext,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n options?: AgentStepHooks<TContext, any, TNextOutput>,\n ): Promise<void> {\n const input = state.output as TAgentInput;\n const hasStructuredOutput = agent.hasOutput;\n\n if (state.mode === \"stream\" && state.writer) {\n const writer = state.writer;\n // Run inside writer context so tools (asTool, defineTool) can access the writer automatically\n await runWithWriter(writer, async () => {\n const result = await (agent.stream as (ctx: TContext, input: unknown) => Promise<StreamTextResult>)(ctx, state.output);\n\n if (options?.handleStream) {\n await options.handleStream({ result, writer, ctx });\n } else {\n writer.merge(result.toUIMessageStream());\n }\n\n if (options?.onStreamResult) {\n await options.onStreamResult({ result, ctx, input });\n }\n\n if (options?.mapStreamResult) {\n state.output = await options.mapStreamResult({ result, ctx, input });\n } else {\n state.output = await extractOutput(result, hasStructuredOutput);\n }\n });\n } else {\n const result = await (agent.generate as (ctx: TContext, input: unknown) => Promise<GenerateTextResult>)(ctx, state.output);\n\n if (options?.onGenerateResult) {\n await options.onGenerateResult({ result, ctx, input });\n }\n\n if (options?.mapGenerateResult) {\n state.output = await options.mapGenerateResult({ result, ctx, input });\n } else {\n state.output = await extractOutput(result, hasStructuredOutput);\n }\n }\n }\n}\n\n// ── Workflow ────────────────────────────────────────────────────────\n\nexport class Workflow<\n TContext,\n TInput = void,\n TOutput = void,\n> extends SealedWorkflow<TContext, TInput, TOutput> {\n\n private constructor(steps: ReadonlyArray<StepNode> = [], id?: string) {\n super(steps, id);\n }\n\n static create<TContext, TInput = void>(options?: { id?: string }): Workflow<TContext, TInput, TInput> {\n return new Workflow<TContext, TInput, TInput>([], options?.id);\n }\n\n static from<TContext, TInput, TOutput>(\n agent: Agent<TContext, TInput, TOutput>,\n options?: StepOptions<TContext, TInput, TOutput>\n ): Workflow<TContext, TInput, TOutput> {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, any>([]).step(agent, options);\n }\n\n // ── step: agent overload ──────────────────────────────────────\n\n step<TNextOutput>(\n agent: Agent<TContext, TOutput, TNextOutput>,\n options?: StepOptions<TContext, TOutput, TNextOutput>\n ): Workflow<TContext, TInput, TNextOutput>;\n\n // ── step: nested workflow overload ─────────────────────────────\n\n step<TNextOutput>(\n workflow: SealedWorkflow<TContext, TOutput, TNextOutput>,\n ): Workflow<TContext, TInput, TNextOutput>;\n\n // ── step: transform overload (replaces map + tap) ─────────────\n\n step<TNextOutput>(\n id: string,\n fn: (params: { ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<TNextOutput>\n ): Workflow<TContext, TInput, TNextOutput>;\n\n // ── step: implementation ──────────────────────────────────────\n\n step<TNextOutput>(\n target: Agent<TContext, TOutput, TNextOutput> | SealedWorkflow<TContext, TOutput, TNextOutput> | string,\n optionsOrFn?: StepOptions<TContext, TOutput, TNextOutput> | ((params: { ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<TNextOutput>)\n ): Workflow<TContext, TInput, TNextOutput> {\n // Nested workflow overload: step(workflow)\n if (target instanceof SealedWorkflow) {\n const workflow = target;\n const node: StepNode = {\n type: \"step\",\n id: workflow.id ?? \"nested-workflow\",\n execute: async (state) => {\n await this.executeNestedWorkflow(state, workflow as SealedWorkflow<TContext, unknown, unknown>);\n },\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNextOutput>([...this.steps, node] as any, this.id);\n }\n\n // Transform overload: step(id, fn)\n if (typeof target === \"string\") {\n if (typeof optionsOrFn !== \"function\") {\n throw new Error(`Workflow step(\"${target}\"): second argument must be a function`);\n }\n const fn = optionsOrFn as (params: { ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<TNextOutput>;\n const node: StepNode = {\n type: \"step\",\n id: target,\n execute: async (state) => {\n state.output = await fn({\n ctx: state.ctx as Readonly<TContext>,\n input: state.output as TOutput,\n });\n },\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNextOutput>([...this.steps, node] as any, this.id);\n }\n\n // Agent overload: step(agent, options?)\n const agent = target;\n const options = optionsOrFn as StepOptions<TContext, TOutput, TNextOutput> | undefined;\n const node: StepNode = {\n type: \"step\",\n id: agent.id,\n execute: async (state) => {\n const ctx = state.ctx as TContext;\n await this.executeAgent(state, agent, ctx, options);\n },\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNextOutput>([...this.steps, node] as any, this.id);\n }\n\n // ── branch: predicate routing (array) ─────────────────────────\n\n branch<TNextOutput>(\n cases: BranchCase<TContext, TOutput, TNextOutput>[]\n ): Workflow<TContext, TInput, TNextOutput>;\n\n // ── branch: key routing (select) ──────────────────────────────\n\n branch<TKeys extends string, TNextOutput>(\n config: BranchSelect<TContext, TOutput, TKeys, TNextOutput>\n ): Workflow<TContext, TInput, TNextOutput>;\n\n // ── branch: implementation ────────────────────────────────────\n\n branch<TKeys extends string, TNextOutput>(\n casesOrConfig: BranchCase<TContext, TOutput, TNextOutput>[] | BranchSelect<TContext, TOutput, TKeys, TNextOutput>\n ): Workflow<TContext, TInput, TNextOutput> {\n if (Array.isArray(casesOrConfig)) {\n return this.branchPredicate(casesOrConfig);\n }\n return this.branchSelect(casesOrConfig);\n }\n\n private branchPredicate<TNextOutput>(\n cases: BranchCase<TContext, TOutput, TNextOutput>[]\n ): Workflow<TContext, TInput, TNextOutput> {\n const node: StepNode = {\n type: \"step\",\n id: \"branch:predicate\",\n execute: async (state) => {\n const ctx = state.ctx as TContext;\n const input = state.output as TOutput;\n\n for (const branchCase of cases) {\n if (branchCase.when) {\n const match = await branchCase.when({ ctx, input });\n if (!match) continue;\n }\n\n // Matched (or no `when` = default)\n await this.executeAgent(state, branchCase.agent, ctx, branchCase);\n return;\n }\n\n throw new WorkflowBranchError(\"predicate\", `No branch matched and no default branch (a case without \\`when\\`) was provided. Input: ${JSON.stringify(input)}`);\n },\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNextOutput>([...this.steps, node] as any, this.id);\n }\n\n private branchSelect<TKeys extends string, TNextOutput>(\n config: BranchSelect<TContext, TOutput, TKeys, TNextOutput>\n ): Workflow<TContext, TInput, TNextOutput> {\n const node: StepNode = {\n type: \"step\",\n id: \"branch:select\",\n execute: async (state) => {\n const ctx = state.ctx as TContext;\n const input = state.output as TOutput;\n const key = await config.select({ ctx, input });\n\n let agent = config.agents[key];\n if (!agent) {\n if (config.fallback) {\n agent = config.fallback;\n } else {\n throw new WorkflowBranchError(\"select\", `No agent found for key \"${key}\" and no fallback provided. Available keys: ${Object.keys(config.agents).join(\", \")}`);\n }\n }\n\n await this.executeAgent(state, agent, ctx, config);\n },\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNextOutput>([...this.steps, node] as any, this.id);\n }\n\n // ── foreach: array iteration ─────────────────────────────────\n\n foreach<TNextOutput>(\n target: Agent<TContext, ElementOf<TOutput>, TNextOutput> | SealedWorkflow<TContext, ElementOf<TOutput>, TNextOutput>,\n options?: { concurrency?: number },\n ): Workflow<TContext, TInput, TNextOutput[]> {\n const concurrency = options?.concurrency ?? 1;\n const isWorkflow = target instanceof SealedWorkflow;\n const id = isWorkflow ? (target.id ?? \"foreach\") : `foreach:${(target as Agent<TContext, ElementOf<TOutput>, TNextOutput>).id}`;\n\n const node: StepNode = {\n type: \"step\",\n id,\n execute: async (state) => {\n const items = state.output;\n if (!Array.isArray(items)) {\n throw new Error(`foreach \"${id}\": expected array input, got ${typeof items}`);\n }\n\n const ctx = state.ctx as TContext;\n const results: unknown[] = new Array(items.length);\n\n // Streaming is intentionally not propagated to foreach items —\n // each item runs in generate mode because merging interleaved\n // streams from parallel items into a single writer is not supported.\n const executeItem = async (item: unknown, index: number) => {\n const itemState: RuntimeState = { ctx: state.ctx, output: item, mode: \"generate\" };\n if (isWorkflow) {\n await this.executeNestedWorkflow(itemState, target as SealedWorkflow<TContext, unknown, unknown>);\n } else {\n await this.executeAgent(itemState, target as Agent<TContext, unknown, TNextOutput>, ctx);\n }\n results[index] = itemState.output;\n };\n\n if (concurrency <= 1) {\n for (let i = 0; i < items.length; i++) {\n await executeItem(items[i], i);\n }\n } else {\n for (let i = 0; i < items.length; i += concurrency) {\n const batch = items.slice(i, i + concurrency);\n await Promise.all(batch.map((item, j) => executeItem(item, i + j)));\n }\n }\n\n state.output = results;\n },\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNextOutput[]>([...this.steps, node] as any, this.id);\n }\n\n // ── repeat: conditional loop ─────────────────────────────────\n\n repeat(\n target: Agent<TContext, TOutput, TOutput> | SealedWorkflow<TContext, TOutput, TOutput>,\n options: RepeatOptions<TContext, TOutput>,\n ): Workflow<TContext, TInput, TOutput> {\n const maxIterations = options.maxIterations ?? 10;\n const isWorkflow = target instanceof SealedWorkflow;\n const id = isWorkflow ? (target.id ?? \"repeat\") : `repeat:${(target as Agent<TContext, TOutput, TOutput>).id}`;\n const predicate: LoopPredicate<TContext, TOutput> = options.until\n ?? (async (p) => !(await options.while!(p)));\n\n const node: StepNode = {\n type: \"step\",\n id,\n execute: async (state) => {\n const ctx = state.ctx as TContext;\n\n for (let i = 1; i <= maxIterations; i++) {\n if (isWorkflow) {\n await this.executeNestedWorkflow(state, target as SealedWorkflow<TContext, unknown, unknown>);\n } else {\n await this.executeAgent(state, target as Agent<TContext, TOutput, TOutput>, ctx);\n }\n\n const done = await predicate({\n output: state.output as TOutput,\n ctx: ctx as Readonly<TContext>,\n iterations: i,\n });\n if (done) return;\n }\n\n throw new WorkflowLoopError(maxIterations, maxIterations);\n },\n };\n return new Workflow<TContext, TInput, TOutput>([...this.steps, node], this.id);\n }\n\n // ── catch ─────────────────────────────────────────────────────\n\n catch(\n id: string,\n fn: (params: { error: unknown; ctx: Readonly<TContext>; lastOutput: TOutput; stepId: string }) => MaybePromise<TOutput>\n ): Workflow<TContext, TInput, TOutput> {\n if (!this.steps.some(s => s.type === \"step\")) {\n throw new Error(`Workflow: catch(\"${id}\") requires at least one preceding step.`);\n }\n const node: StepNode = {\n type: \"catch\",\n id,\n catchFn: fn as (params: { error: unknown; ctx: unknown; lastOutput: unknown; stepId: string }) => MaybePromise<unknown>,\n };\n return new Workflow<TContext, TInput, TOutput>([...this.steps, node], this.id);\n }\n\n // ── finally (terminal — returns sealed workflow) ──────────────\n\n finally(\n id: string,\n fn: (params: { ctx: Readonly<TContext> }) => MaybePromise<void>\n ): SealedWorkflow<TContext, TInput, TOutput> {\n const node: StepNode = {\n type: \"finally\",\n id,\n execute: async (state) => {\n await fn({ ctx: state.ctx as Readonly<TContext> });\n },\n };\n return new SealedWorkflow<TContext, TInput, TOutput>([...this.steps, node], this.id);\n }\n}\n\n"],"mappings":"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","names":["tool","tool","result","node"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pipeai",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "A typed multi-agent workflow pipeline built on top of the Vercel AI SDK",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -27,15 +27,16 @@
|
|
|
27
27
|
"test:watch": "vitest"
|
|
28
28
|
},
|
|
29
29
|
"peerDependencies": {
|
|
30
|
-
"ai": "^6.0.
|
|
30
|
+
"ai": "^6.0.116",
|
|
31
31
|
"zod": ">=3.0.0 || >=4.0.0"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
|
-
"
|
|
34
|
+
"@types/node": "^25.5.0",
|
|
35
|
+
"ai": "^6.0.116",
|
|
35
36
|
"tsup": "^8.5.1",
|
|
36
37
|
"typescript": "^5.7.3",
|
|
37
38
|
"vitest": "^4.0.18",
|
|
38
|
-
"zod": "^3.
|
|
39
|
+
"zod": "^4.3.6"
|
|
39
40
|
},
|
|
40
41
|
"keywords": [
|
|
41
42
|
"ai",
|