pipeai 0.1.1 → 0.2.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 +188 -2
- package/dist/index.cjs +169 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +81 -25
- package/dist/index.d.ts +81 -25
- package/dist/index.js +168 -7
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -5,11 +5,12 @@ declare const TOOL_PROVIDER_BRAND: unique symbol;
|
|
|
5
5
|
type ToolExecuteOptions = ToolExecutionOptions & {
|
|
6
6
|
writer?: UIMessageStreamWriter;
|
|
7
7
|
};
|
|
8
|
+
type ToolProviderOptions = NonNullable<Tool["providerOptions"]>;
|
|
8
9
|
type ToolProviderConfig<TContext, TInput, TOutput> = {
|
|
9
10
|
description?: string;
|
|
10
11
|
input: FlexibleSchema<TInput>;
|
|
11
|
-
|
|
12
|
-
providerOptions?:
|
|
12
|
+
outputSchema?: FlexibleSchema<TOutput>;
|
|
13
|
+
providerOptions?: ToolProviderOptions;
|
|
13
14
|
execute: (input: TInput, ctx: Readonly<TContext>, options: ToolExecuteOptions) => Promise<TOutput>;
|
|
14
15
|
};
|
|
15
16
|
interface IToolProvider<TContext> {
|
|
@@ -85,13 +86,13 @@ declare class Agent<TContext, TInput = void, TOutput = void> {
|
|
|
85
86
|
private readonly _onStepFinish;
|
|
86
87
|
private readonly _onFinish;
|
|
87
88
|
constructor(config: AgentConfig<TContext, TInput, TOutput>);
|
|
88
|
-
generate(ctx: TContext, ...args: TInput extends void ? [input?: TInput] : [input: TInput]): Promise<GenerateTextResult
|
|
89
|
-
stream(ctx: TContext, ...args: TInput extends void ? [input?: TInput] : [input: TInput]): Promise<StreamTextResult
|
|
89
|
+
generate(ctx: TContext, ...args: TInput extends void ? [input?: TInput] : [input: TInput]): Promise<GenerateTextResult<ToolSet, OutputType<TOutput>>>;
|
|
90
|
+
stream(ctx: TContext, ...args: TInput extends void ? [input?: TInput] : [input: TInput]): Promise<StreamTextResult<ToolSet, OutputType<TOutput>>>;
|
|
90
91
|
asTool(ctx: TContext, options?: {
|
|
91
|
-
mapOutput?: (result: GenerateTextResult) => MaybePromise<TOutput>;
|
|
92
|
+
mapOutput?: (result: GenerateTextResult<ToolSet, OutputType<TOutput>>) => MaybePromise<TOutput>;
|
|
92
93
|
}): Tool;
|
|
93
94
|
asToolProvider(options?: {
|
|
94
|
-
mapOutput?: (result: GenerateTextResult) => MaybePromise<TOutput>;
|
|
95
|
+
mapOutput?: (result: GenerateTextResult<ToolSet, OutputType<TOutput>>) => MaybePromise<TOutput>;
|
|
95
96
|
}): IToolProvider<TContext>;
|
|
96
97
|
private createToolInstance;
|
|
97
98
|
private buildCallOptions;
|
|
@@ -109,29 +110,40 @@ declare class WorkflowLoopError extends Error {
|
|
|
109
110
|
readonly maxIterations: number;
|
|
110
111
|
constructor(iterations: number, maxIterations: number);
|
|
111
112
|
}
|
|
113
|
+
interface WorkflowSnapshot {
|
|
114
|
+
readonly version: 1;
|
|
115
|
+
readonly resumeFromIndex: number;
|
|
116
|
+
readonly output: unknown;
|
|
117
|
+
readonly gateId: string;
|
|
118
|
+
readonly gatePayload: unknown;
|
|
119
|
+
}
|
|
120
|
+
declare class WorkflowSuspended extends Error {
|
|
121
|
+
readonly snapshot: WorkflowSnapshot;
|
|
122
|
+
constructor(snapshot: WorkflowSnapshot);
|
|
123
|
+
}
|
|
112
124
|
interface AgentStepHooks<TContext, TOutput, TNextOutput> {
|
|
113
125
|
mapGenerateResult?: (params: {
|
|
114
|
-
result: GenerateTextResult
|
|
126
|
+
result: GenerateTextResult<ToolSet, OutputType<TNextOutput>>;
|
|
115
127
|
ctx: Readonly<TContext>;
|
|
116
128
|
input: TOutput;
|
|
117
129
|
}) => MaybePromise<TNextOutput>;
|
|
118
130
|
mapStreamResult?: (params: {
|
|
119
|
-
result: StreamTextResult
|
|
131
|
+
result: StreamTextResult<ToolSet, OutputType<TNextOutput>>;
|
|
120
132
|
ctx: Readonly<TContext>;
|
|
121
133
|
input: TOutput;
|
|
122
134
|
}) => MaybePromise<TNextOutput>;
|
|
123
135
|
onGenerateResult?: (params: {
|
|
124
|
-
result: GenerateTextResult
|
|
136
|
+
result: GenerateTextResult<ToolSet, OutputType<TNextOutput>>;
|
|
125
137
|
ctx: Readonly<TContext>;
|
|
126
138
|
input: TOutput;
|
|
127
139
|
}) => MaybePromise<void>;
|
|
128
140
|
onStreamResult?: (params: {
|
|
129
|
-
result: StreamTextResult
|
|
141
|
+
result: StreamTextResult<ToolSet, OutputType<TNextOutput>>;
|
|
130
142
|
ctx: Readonly<TContext>;
|
|
131
143
|
input: TOutput;
|
|
132
144
|
}) => MaybePromise<void>;
|
|
133
145
|
handleStream?: (params: {
|
|
134
|
-
result: StreamTextResult
|
|
146
|
+
result: StreamTextResult<ToolSet, OutputType<TNextOutput>>;
|
|
135
147
|
writer: UIMessageStreamWriter;
|
|
136
148
|
ctx: Readonly<TContext>;
|
|
137
149
|
}) => MaybePromise<void>;
|
|
@@ -178,6 +190,9 @@ type RepeatOptions<TContext, TOutput> = {
|
|
|
178
190
|
maxIterations?: number;
|
|
179
191
|
};
|
|
180
192
|
type ElementOf<T> = T extends readonly (infer E)[] ? E : never;
|
|
193
|
+
interface SchemaWithParse<T = unknown> {
|
|
194
|
+
parse(data: unknown): T;
|
|
195
|
+
}
|
|
181
196
|
type StepNode = {
|
|
182
197
|
readonly type: "step";
|
|
183
198
|
readonly id: string;
|
|
@@ -195,6 +210,16 @@ type StepNode = {
|
|
|
195
210
|
readonly type: "finally";
|
|
196
211
|
readonly id: string;
|
|
197
212
|
readonly execute: (state: RuntimeState) => MaybePromise<void>;
|
|
213
|
+
} | {
|
|
214
|
+
readonly type: "gate";
|
|
215
|
+
readonly id: string;
|
|
216
|
+
readonly payload: (state: RuntimeState) => MaybePromise<unknown>;
|
|
217
|
+
readonly schema?: SchemaWithParse;
|
|
218
|
+
readonly condition?: (state: RuntimeState) => MaybePromise<boolean>;
|
|
219
|
+
readonly merge?: (params: {
|
|
220
|
+
priorOutput: unknown;
|
|
221
|
+
response: unknown;
|
|
222
|
+
}) => MaybePromise<unknown>;
|
|
198
223
|
};
|
|
199
224
|
interface RuntimeState {
|
|
200
225
|
ctx: unknown;
|
|
@@ -202,45 +227,76 @@ interface RuntimeState {
|
|
|
202
227
|
mode: "generate" | "stream";
|
|
203
228
|
writer?: UIMessageStreamWriter;
|
|
204
229
|
}
|
|
205
|
-
declare class SealedWorkflow<TContext, TInput = void, TOutput = void> {
|
|
230
|
+
declare class SealedWorkflow<TContext, TInput = void, TOutput = void, TGates extends Record<string, unknown> = {}> {
|
|
206
231
|
readonly id?: string;
|
|
207
232
|
protected readonly steps: ReadonlyArray<StepNode>;
|
|
208
233
|
protected constructor(steps: ReadonlyArray<StepNode>, id?: string);
|
|
209
234
|
generate(ctx: TContext, ...args: TInput extends void ? [input?: TInput] : [input: TInput]): Promise<WorkflowResult<TOutput>>;
|
|
210
235
|
stream(ctx: TContext, ...args: TInput extends void ? [input?: TInput, options?: WorkflowStreamOptions] : [input: TInput, options?: WorkflowStreamOptions]): WorkflowStreamResult<TOutput>;
|
|
211
|
-
protected execute(state: RuntimeState): Promise<void>;
|
|
212
|
-
protected executeNestedWorkflow(state: RuntimeState, workflow: SealedWorkflow<TContext, unknown, unknown>): Promise<void>;
|
|
236
|
+
protected execute(state: RuntimeState, startIndex?: number): Promise<void>;
|
|
237
|
+
protected executeNestedWorkflow(state: RuntimeState, workflow: SealedWorkflow<TContext, unknown, unknown, any>): Promise<void>;
|
|
213
238
|
protected executeAgent<TAgentInput, TNextOutput>(state: RuntimeState, agent: Agent<TContext, any, TNextOutput>, ctx: TContext, options?: AgentStepHooks<TContext, any, TNextOutput>): Promise<void>;
|
|
239
|
+
loadState<K extends string & keyof TGates>(gateId: K, snapshot: WorkflowSnapshot): ResumedWorkflow<TContext, TGates[K], TOutput>;
|
|
240
|
+
private findGateIndex;
|
|
241
|
+
}
|
|
242
|
+
declare class ResumedWorkflow<TContext, TResponse = unknown, TOutput = void> extends SealedWorkflow<TContext, TResponse, TOutput> {
|
|
243
|
+
private readonly startIndex;
|
|
244
|
+
private readonly schema?;
|
|
245
|
+
private readonly mergeFn?;
|
|
246
|
+
private readonly priorOutput;
|
|
247
|
+
/** @internal */
|
|
248
|
+
constructor(steps: ReadonlyArray<StepNode>, startIndex: number, schema?: SchemaWithParse<TResponse>, mergeFn?: (params: {
|
|
249
|
+
priorOutput: unknown;
|
|
250
|
+
response: unknown;
|
|
251
|
+
}) => MaybePromise<unknown>, priorOutput?: unknown);
|
|
252
|
+
private validateResponse;
|
|
253
|
+
generate(ctx: TContext, ...args: TResponse extends void ? [response?: TResponse] : [response: TResponse]): Promise<WorkflowResult<TOutput>>;
|
|
254
|
+
stream(ctx: TContext, ...args: TResponse extends void ? [response?: TResponse, options?: WorkflowStreamOptions] : [response: TResponse, options?: WorkflowStreamOptions]): WorkflowStreamResult<TOutput>;
|
|
214
255
|
}
|
|
215
|
-
declare class Workflow<TContext, TInput = void, TOutput = void> extends SealedWorkflow<TContext, TInput, TOutput> {
|
|
256
|
+
declare class Workflow<TContext, TInput = void, TOutput = void, TGates extends Record<string, unknown> = {}> extends SealedWorkflow<TContext, TInput, TOutput, TGates> {
|
|
216
257
|
private constructor();
|
|
217
258
|
static create<TContext, TInput = void>(options?: {
|
|
218
259
|
id?: string;
|
|
219
260
|
}): Workflow<TContext, TInput, TInput>;
|
|
220
261
|
static from<TContext, TInput, TOutput>(agent: Agent<TContext, TInput, TOutput>, options?: StepOptions<TContext, TInput, TOutput>): Workflow<TContext, TInput, TOutput>;
|
|
221
|
-
step<TNextOutput>(agent: Agent<TContext, TOutput, TNextOutput>, options?: StepOptions<TContext, TOutput, TNextOutput>): Workflow<TContext, TInput, TNextOutput>;
|
|
222
|
-
step<TNextOutput>(workflow: SealedWorkflow<TContext, TOutput, TNextOutput>): Workflow<TContext, TInput, TNextOutput>;
|
|
262
|
+
step<TNextOutput>(agent: Agent<TContext, TOutput, TNextOutput>, options?: StepOptions<TContext, TOutput, TNextOutput>): Workflow<TContext, TInput, TNextOutput, TGates>;
|
|
263
|
+
step<TNextOutput>(workflow: SealedWorkflow<TContext, TOutput, TNextOutput>): Workflow<TContext, TInput, TNextOutput, TGates>;
|
|
223
264
|
step<TNextOutput>(id: string, fn: (params: {
|
|
224
265
|
ctx: Readonly<TContext>;
|
|
225
266
|
input: TOutput;
|
|
226
|
-
}) => MaybePromise<TNextOutput>): Workflow<TContext, TInput, TNextOutput>;
|
|
227
|
-
|
|
228
|
-
|
|
267
|
+
}) => MaybePromise<TNextOutput>): Workflow<TContext, TInput, TNextOutput, TGates>;
|
|
268
|
+
gate<TResponse = TOutput, Id extends string = string>(id: Id & (Id extends keyof TGates ? never : Id), options?: {
|
|
269
|
+
payload?: (params: {
|
|
270
|
+
ctx: Readonly<TContext>;
|
|
271
|
+
input: TOutput;
|
|
272
|
+
}) => MaybePromise<unknown>;
|
|
273
|
+
schema?: SchemaWithParse<TResponse>;
|
|
274
|
+
condition?: (params: {
|
|
275
|
+
ctx: Readonly<TContext>;
|
|
276
|
+
input: TOutput;
|
|
277
|
+
}) => MaybePromise<boolean>;
|
|
278
|
+
merge?: (params: {
|
|
279
|
+
priorOutput: TOutput;
|
|
280
|
+
response: TResponse;
|
|
281
|
+
}) => MaybePromise<TResponse>;
|
|
282
|
+
}): Workflow<TContext, TInput, TResponse, TGates & Record<Id, TResponse>>;
|
|
283
|
+
branch<TNextOutput>(cases: BranchCase<TContext, TOutput, TNextOutput>[]): Workflow<TContext, TInput, TNextOutput, TGates>;
|
|
284
|
+
branch<TKeys extends string, TNextOutput>(config: BranchSelect<TContext, TOutput, TKeys, TNextOutput>): Workflow<TContext, TInput, TNextOutput, TGates>;
|
|
229
285
|
private branchPredicate;
|
|
230
286
|
private branchSelect;
|
|
231
287
|
foreach<TNextOutput>(target: Agent<TContext, ElementOf<TOutput>, TNextOutput> | SealedWorkflow<TContext, ElementOf<TOutput>, TNextOutput>, options?: {
|
|
232
288
|
concurrency?: number;
|
|
233
|
-
}): Workflow<TContext, TInput, TNextOutput[]>;
|
|
234
|
-
repeat(target: Agent<TContext, TOutput, TOutput> | SealedWorkflow<TContext, TOutput, TOutput>, options: RepeatOptions<TContext, TOutput>): Workflow<TContext, TInput, TOutput>;
|
|
289
|
+
}): Workflow<TContext, TInput, TNextOutput[], TGates>;
|
|
290
|
+
repeat(target: Agent<TContext, TOutput, TOutput> | SealedWorkflow<TContext, TOutput, TOutput>, options: RepeatOptions<TContext, TOutput>): Workflow<TContext, TInput, TOutput, TGates>;
|
|
235
291
|
catch(id: string, fn: (params: {
|
|
236
292
|
error: unknown;
|
|
237
293
|
ctx: Readonly<TContext>;
|
|
238
294
|
lastOutput: TOutput;
|
|
239
295
|
stepId: string;
|
|
240
|
-
}) => MaybePromise<TOutput>): Workflow<TContext, TInput, TOutput>;
|
|
296
|
+
}) => MaybePromise<TOutput>): Workflow<TContext, TInput, TOutput, TGates>;
|
|
241
297
|
finally(id: string, fn: (params: {
|
|
242
298
|
ctx: Readonly<TContext>;
|
|
243
|
-
}) => MaybePromise<void>): SealedWorkflow<TContext, TInput, TOutput>;
|
|
299
|
+
}) => MaybePromise<void>): SealedWorkflow<TContext, TInput, TOutput, TGates>;
|
|
244
300
|
}
|
|
245
301
|
|
|
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 };
|
|
302
|
+
export { Agent, type AgentConfig, type AgentStepHooks, type BranchCase, type BranchSelect, type GenerateTextResult, type IToolProvider, type MaybePromise, type OutputType, type RepeatOptions, type Resolvable, ResumedWorkflow, SealedWorkflow, type StepOptions, type StreamTextResult, type ToolExecuteOptions, type ToolProviderConfig, Workflow, WorkflowBranchError, WorkflowLoopError, type WorkflowResult, type WorkflowSnapshot, type WorkflowStreamOptions, type WorkflowStreamResult, WorkflowSuspended, defineTool };
|
package/dist/index.js
CHANGED
|
@@ -43,9 +43,8 @@ var ToolProvider = class {
|
|
|
43
43
|
const { execute, input: inputSchema, ...toolDef } = this.config;
|
|
44
44
|
return tool({
|
|
45
45
|
...toolDef,
|
|
46
|
-
|
|
46
|
+
inputSchema,
|
|
47
47
|
execute: (input, options) => execute(input, context, { ...options, writer: getActiveWriter() })
|
|
48
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
49
48
|
});
|
|
50
49
|
}
|
|
51
50
|
};
|
|
@@ -152,7 +151,7 @@ var Agent = class {
|
|
|
152
151
|
}
|
|
153
152
|
return tool2({
|
|
154
153
|
description: this.description,
|
|
155
|
-
|
|
154
|
+
inputSchema: this.config.input,
|
|
156
155
|
execute: async (toolInput) => {
|
|
157
156
|
const writer = getActiveWriter();
|
|
158
157
|
if (writer) {
|
|
@@ -165,7 +164,8 @@ var Agent = class {
|
|
|
165
164
|
if (options?.mapOutput) return options.mapOutput(result);
|
|
166
165
|
return extractOutput(result, this.hasOutput);
|
|
167
166
|
}
|
|
168
|
-
//
|
|
167
|
+
// TS cannot simplify the SDK's `NeverOptional<TOutput, ...>` conditional in a
|
|
168
|
+
// generic context, so we cast through `unknown` instead of `any`.
|
|
169
169
|
});
|
|
170
170
|
}
|
|
171
171
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -252,6 +252,14 @@ var WorkflowLoopError = class extends Error {
|
|
|
252
252
|
this.name = "WorkflowLoopError";
|
|
253
253
|
}
|
|
254
254
|
};
|
|
255
|
+
var WorkflowSuspended = class extends Error {
|
|
256
|
+
snapshot;
|
|
257
|
+
constructor(snapshot) {
|
|
258
|
+
super(`Workflow suspended at gate "${snapshot.gateId}"`);
|
|
259
|
+
this.name = "WorkflowSuspended";
|
|
260
|
+
this.snapshot = snapshot;
|
|
261
|
+
}
|
|
262
|
+
};
|
|
255
263
|
var SealedWorkflow = class {
|
|
256
264
|
id;
|
|
257
265
|
steps;
|
|
@@ -308,12 +316,13 @@ var SealedWorkflow = class {
|
|
|
308
316
|
};
|
|
309
317
|
}
|
|
310
318
|
// ── Internal: execute pipeline ────────────────────────────────
|
|
311
|
-
async execute(state) {
|
|
319
|
+
async execute(state, startIndex = 0) {
|
|
312
320
|
if (this.steps.length === 0) {
|
|
313
321
|
throw new Error("Workflow has no steps. Add at least one step before calling generate() or stream().");
|
|
314
322
|
}
|
|
315
323
|
let pendingError = null;
|
|
316
|
-
for (
|
|
324
|
+
for (let i = startIndex; i < this.steps.length; i++) {
|
|
325
|
+
const node = this.steps[i];
|
|
317
326
|
if (node.type === "finally") {
|
|
318
327
|
await node.execute(state);
|
|
319
328
|
continue;
|
|
@@ -333,10 +342,26 @@ var SealedWorkflow = class {
|
|
|
333
342
|
}
|
|
334
343
|
continue;
|
|
335
344
|
}
|
|
345
|
+
if (node.type === "gate") {
|
|
346
|
+
if (pendingError) continue;
|
|
347
|
+
if (node.condition) {
|
|
348
|
+
const shouldSuspend = await node.condition(state);
|
|
349
|
+
if (!shouldSuspend) continue;
|
|
350
|
+
}
|
|
351
|
+
const gatePayload = await node.payload(state);
|
|
352
|
+
throw new WorkflowSuspended({
|
|
353
|
+
version: 1,
|
|
354
|
+
resumeFromIndex: i,
|
|
355
|
+
output: state.output,
|
|
356
|
+
gateId: node.id,
|
|
357
|
+
gatePayload
|
|
358
|
+
});
|
|
359
|
+
}
|
|
336
360
|
if (pendingError) continue;
|
|
337
361
|
try {
|
|
338
362
|
await node.execute(state);
|
|
339
363
|
} catch (error) {
|
|
364
|
+
if (error instanceof WorkflowSuspended) throw error;
|
|
340
365
|
pendingError = { error, stepId: node.id };
|
|
341
366
|
}
|
|
342
367
|
}
|
|
@@ -346,7 +371,16 @@ var SealedWorkflow = class {
|
|
|
346
371
|
// Defined on SealedWorkflow (not Workflow) because TypeScript's protected
|
|
347
372
|
// access rules only allow calling workflow.execute() from the same class.
|
|
348
373
|
async executeNestedWorkflow(state, workflow) {
|
|
349
|
-
|
|
374
|
+
try {
|
|
375
|
+
await workflow.execute(state);
|
|
376
|
+
} catch (error) {
|
|
377
|
+
if (error instanceof WorkflowSuspended) {
|
|
378
|
+
throw new Error(
|
|
379
|
+
`Gates inside nested workflows are not yet supported. Gate "${error.snapshot.gateId}" was hit inside nested workflow "${workflow.id ?? "(anonymous)"}". Consider using a conditional gate with \`condition\` to skip when criteria are met, or restructure the workflow to use gates at the top level only.`
|
|
380
|
+
);
|
|
381
|
+
}
|
|
382
|
+
throw error;
|
|
383
|
+
}
|
|
350
384
|
}
|
|
351
385
|
// ── Internal: execute an agent within a step/branch ───────────
|
|
352
386
|
// In stream mode, output extraction awaits the full stream before returning.
|
|
@@ -385,6 +419,106 @@ var SealedWorkflow = class {
|
|
|
385
419
|
}
|
|
386
420
|
}
|
|
387
421
|
}
|
|
422
|
+
// ── Gate: load persisted state for resumption ──────────────────
|
|
423
|
+
loadState(gateId, snapshot) {
|
|
424
|
+
if (snapshot.gateId !== gateId) {
|
|
425
|
+
throw new Error(
|
|
426
|
+
`loadState: gate ID mismatch \u2014 expected "${gateId}" but snapshot has "${snapshot.gateId}".`
|
|
427
|
+
);
|
|
428
|
+
}
|
|
429
|
+
const gateIndex = this.findGateIndex(snapshot);
|
|
430
|
+
const gateNode = this.steps[gateIndex];
|
|
431
|
+
return new ResumedWorkflow(
|
|
432
|
+
this.steps,
|
|
433
|
+
gateIndex + 1,
|
|
434
|
+
gateNode.schema,
|
|
435
|
+
gateNode.merge,
|
|
436
|
+
snapshot.output
|
|
437
|
+
);
|
|
438
|
+
}
|
|
439
|
+
findGateIndex(snapshot) {
|
|
440
|
+
if (snapshot.version !== 1) {
|
|
441
|
+
throw new Error(`Unsupported snapshot version: ${snapshot.version}`);
|
|
442
|
+
}
|
|
443
|
+
const hint = snapshot.resumeFromIndex;
|
|
444
|
+
if (hint >= 0 && hint < this.steps.length) {
|
|
445
|
+
const node = this.steps[hint];
|
|
446
|
+
if (node.type === "gate" && node.id === snapshot.gateId) {
|
|
447
|
+
return hint;
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
for (let i = 0; i < this.steps.length; i++) {
|
|
451
|
+
const node = this.steps[i];
|
|
452
|
+
if (node.type === "gate" && node.id === snapshot.gateId) {
|
|
453
|
+
return i;
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
throw new Error(
|
|
457
|
+
`Gate "${snapshot.gateId}" not found in workflow. The workflow definition may have changed since the snapshot was created.`
|
|
458
|
+
);
|
|
459
|
+
}
|
|
460
|
+
};
|
|
461
|
+
var ResumedWorkflow = class extends SealedWorkflow {
|
|
462
|
+
startIndex;
|
|
463
|
+
schema;
|
|
464
|
+
mergeFn;
|
|
465
|
+
priorOutput;
|
|
466
|
+
/** @internal */
|
|
467
|
+
constructor(steps, startIndex, schema, mergeFn, priorOutput) {
|
|
468
|
+
super(steps);
|
|
469
|
+
this.startIndex = startIndex;
|
|
470
|
+
this.schema = schema;
|
|
471
|
+
this.mergeFn = mergeFn;
|
|
472
|
+
this.priorOutput = priorOutput;
|
|
473
|
+
}
|
|
474
|
+
validateResponse(response) {
|
|
475
|
+
if (this.schema) {
|
|
476
|
+
return this.schema.parse(response);
|
|
477
|
+
}
|
|
478
|
+
return response;
|
|
479
|
+
}
|
|
480
|
+
async generate(ctx, ...args) {
|
|
481
|
+
const response = this.validateResponse(args[0]);
|
|
482
|
+
const output = this.mergeFn ? await this.mergeFn({ priorOutput: this.priorOutput, response }) : response;
|
|
483
|
+
const state = { ctx, output, mode: "generate" };
|
|
484
|
+
await this.execute(state, this.startIndex);
|
|
485
|
+
return { output: state.output };
|
|
486
|
+
}
|
|
487
|
+
stream(ctx, ...args) {
|
|
488
|
+
const response = this.validateResponse(args[0]);
|
|
489
|
+
const options = args[1];
|
|
490
|
+
let resolveOutput;
|
|
491
|
+
let rejectOutput;
|
|
492
|
+
const outputPromise = new Promise((res, rej) => {
|
|
493
|
+
resolveOutput = res;
|
|
494
|
+
rejectOutput = rej;
|
|
495
|
+
});
|
|
496
|
+
outputPromise.catch(() => {
|
|
497
|
+
});
|
|
498
|
+
const mergeFn = this.mergeFn;
|
|
499
|
+
const priorOutput = this.priorOutput;
|
|
500
|
+
const stream = createUIMessageStream({
|
|
501
|
+
execute: async ({ writer }) => {
|
|
502
|
+
const output = mergeFn ? await mergeFn({ priorOutput, response }) : response;
|
|
503
|
+
const state = {
|
|
504
|
+
ctx,
|
|
505
|
+
output,
|
|
506
|
+
mode: "stream",
|
|
507
|
+
writer
|
|
508
|
+
};
|
|
509
|
+
try {
|
|
510
|
+
await this.execute(state, this.startIndex);
|
|
511
|
+
resolveOutput(state.output);
|
|
512
|
+
} catch (error) {
|
|
513
|
+
rejectOutput(error);
|
|
514
|
+
throw error;
|
|
515
|
+
}
|
|
516
|
+
},
|
|
517
|
+
...options?.onError ? { onError: options.onError } : {},
|
|
518
|
+
...options?.onFinish ? { onFinish: options.onFinish } : {}
|
|
519
|
+
});
|
|
520
|
+
return { stream, output: outputPromise };
|
|
521
|
+
}
|
|
388
522
|
};
|
|
389
523
|
var Workflow = class _Workflow extends SealedWorkflow {
|
|
390
524
|
constructor(steps = [], id) {
|
|
@@ -438,6 +572,32 @@ var Workflow = class _Workflow extends SealedWorkflow {
|
|
|
438
572
|
};
|
|
439
573
|
return new _Workflow([...this.steps, node], this.id);
|
|
440
574
|
}
|
|
575
|
+
// ── gate: human-in-the-loop suspension point ────────────────
|
|
576
|
+
gate(id, options) {
|
|
577
|
+
if (this.steps.some((s) => s.type === "gate" && s.id === id)) {
|
|
578
|
+
throw new Error(`Workflow: duplicate gate ID "${id}". Each gate must have a unique identifier.`);
|
|
579
|
+
}
|
|
580
|
+
const node = {
|
|
581
|
+
type: "gate",
|
|
582
|
+
id,
|
|
583
|
+
schema: options?.schema,
|
|
584
|
+
condition: options?.condition ? async (state) => options.condition({
|
|
585
|
+
ctx: state.ctx,
|
|
586
|
+
input: state.output
|
|
587
|
+
}) : void 0,
|
|
588
|
+
merge: options?.merge ? (params) => options.merge(params) : void 0,
|
|
589
|
+
payload: async (state) => {
|
|
590
|
+
if (options?.payload) {
|
|
591
|
+
return options.payload({
|
|
592
|
+
ctx: state.ctx,
|
|
593
|
+
input: state.output
|
|
594
|
+
});
|
|
595
|
+
}
|
|
596
|
+
return state.output;
|
|
597
|
+
}
|
|
598
|
+
};
|
|
599
|
+
return new _Workflow([...this.steps, node], this.id);
|
|
600
|
+
}
|
|
441
601
|
// ── branch: implementation ────────────────────────────────────
|
|
442
602
|
branch(casesOrConfig) {
|
|
443
603
|
if (Array.isArray(casesOrConfig)) {
|
|
@@ -583,6 +743,7 @@ export {
|
|
|
583
743
|
Workflow,
|
|
584
744
|
WorkflowBranchError,
|
|
585
745
|
WorkflowLoopError,
|
|
746
|
+
WorkflowSuspended,
|
|
586
747
|
defineTool
|
|
587
748
|
};
|
|
588
749
|
//# sourceMappingURL=index.js.map
|