@yolk-sdk/vercel-workflows 0.1.0-canary.104 → 0.1.0-canary.106

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 CHANGED
@@ -210,7 +210,11 @@ loop will:
210
210
 
211
211
  1. pass that payload to `awaitInput`
212
212
  2. wait for the hook/webhook response
213
- 3. rerun the same tool batch with the accumulated responses in a fresh `hitlResponses` array
213
+ 3. rerun the same tool batch with the accumulated responses in a fresh `hitlResponses` array and
214
+ the requests of the pause being resumed as `awaitingRequests` (absent on the first attempt)
215
+
216
+ Forward `awaitingRequests` to the agent loop's `prepareToolBatch`/`runToolBatch`: an unanswered
217
+ approval then stays pending even when its tool's policy changed since the pause.
214
218
 
215
219
  The loop owns its accumulator: host mutation of a supplied array cannot affect a later batch.
216
220
  Response order and element identity are preserved; response objects are not deep-cloned.
@@ -32,6 +32,13 @@ type VercelAgentWorkflowToolBatchStepInput = {
32
32
  readonly calls: ReadonlyArray<unknown>;
33
33
  readonly createdMessages: ReadonlyArray<unknown>;
34
34
  readonly hitlResponses?: ReadonlyArray<unknown>;
35
+ /**
36
+ * On a resume, the requests of the pause being resumed (`awaitingInput.requests` of the
37
+ * previous attempt). Forward them to the agent loop (`prepareToolBatch` / `runToolBatch`
38
+ * `awaitingRequests`) so an unanswered approval stays pending even when its tool's policy
39
+ * changed. Absent on the first attempt of a batch.
40
+ */
41
+ readonly awaitingRequests?: ReadonlyArray<unknown>;
35
42
  readonly usage?: unknown;
36
43
  readonly turn?: number;
37
44
  readonly eventSequence?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"workflow-loop.d.mts","names":[],"sources":["../src/workflow-loop.ts"],"mappings":"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"}
1
+ {"version":3,"file":"workflow-loop.d.mts","names":[],"sources":["../src/workflow-loop.ts"],"mappings":"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"}
@@ -1,5 +1,10 @@
1
1
  import { Data, Predicate } from "effect";
2
2
  //#region src/workflow-loop.ts
3
+ /** A resume carries the pause it resumes; the first attempt of a batch has none. */
4
+ const withAwaitingRequests = (base, awaitingRequests) => awaitingRequests === void 0 ? base : {
5
+ ...base,
6
+ awaitingRequests
7
+ };
3
8
  const WorkflowStepResult = Data.taggedEnum();
4
9
  const VercelAgentWorkflowRunResult = Data.taggedEnum();
5
10
  const defaultMaxWorkflowTurns = 500;
@@ -84,6 +89,7 @@ async function runVercelAgentWorkflow(config) {
84
89
  }
85
90
  let completedToolsResult;
86
91
  const toolHitlResponses = [];
92
+ let toolAwaitingRequests;
87
93
  let cumulativeUsage = modelResult.value.usage;
88
94
  let toolEventSequence = modelResult.value.eventSequence ?? state.eventSequence;
89
95
  const currentTurnState = (toolResult) => ({
@@ -95,7 +101,7 @@ async function runVercelAgentWorkflow(config) {
95
101
  eventSequence: toolEventSequence
96
102
  });
97
103
  for (;;) {
98
- const toolsResult = await settleWorkflowStep(retryWorkflowStep(() => runToolBatchStep({
104
+ const stepInput = withAwaitingRequests({
99
105
  context: input.context,
100
106
  request: input.request,
101
107
  calls: modelResult.value.toolCalls,
@@ -104,7 +110,8 @@ async function runVercelAgentWorkflow(config) {
104
110
  usage: cumulativeUsage,
105
111
  turn: modelResult.value.turn,
106
112
  eventSequence: toolEventSequence
107
- }), toolBatchStepRetry));
113
+ }, toolAwaitingRequests);
114
+ const toolsResult = await settleWorkflowStep(retryWorkflowStep(() => runToolBatchStep(stepInput), toolBatchStepRetry));
108
115
  if (Predicate.isTagged(toolsResult, "Failure")) {
109
116
  await writeErrorSafely(writeError, toolsResult.error);
110
117
  return VercelAgentWorkflowRunResult.ToolBatchStepFailed({
@@ -128,6 +135,7 @@ async function runVercelAgentWorkflow(config) {
128
135
  break;
129
136
  }
130
137
  const awaitingInput = toolsResult.value.awaitingInput;
138
+ toolAwaitingRequests = awaitingInput.requests;
131
139
  cumulativeUsage = toolsResult.value.usage ?? awaitingInput.usage ?? cumulativeUsage;
132
140
  toolEventSequence = awaitingInput.eventSequence ?? toolEventSequence;
133
141
  const hitlResponse = await settleWorkflowStep(retryWorkflowStep(() => {
@@ -1 +1 @@
1
- {"version":3,"file":"workflow-loop.mjs","names":[],"sources":["../src/workflow-loop.ts"],"sourcesContent":["import { Data, Predicate } from 'effect'\n\nexport type VercelAgentWorkflowInput = {\n readonly request: unknown\n readonly context: unknown\n}\n\nexport type SerializableWorkflowState = {\n readonly request: unknown\n readonly messages?: ReadonlyArray<unknown>\n readonly createdMessages: ReadonlyArray<unknown>\n readonly usage?: unknown\n readonly turn: number\n readonly eventSequence?: number\n}\n\nexport type VercelAgentWorkflowModelStepInput = {\n readonly context: unknown\n readonly state: SerializableWorkflowState\n}\n\nexport type VercelAgentWorkflowModelStepResult = {\n readonly done: boolean\n readonly messages: ReadonlyArray<unknown>\n readonly createdMessages: ReadonlyArray<unknown>\n readonly toolCalls: ReadonlyArray<unknown>\n readonly usage: unknown\n readonly turn: number\n readonly eventSequence?: number\n}\n\nexport type VercelAgentWorkflowToolBatchStepInput = {\n readonly context: unknown\n readonly request: unknown\n readonly calls: ReadonlyArray<unknown>\n readonly createdMessages: ReadonlyArray<unknown>\n readonly hitlResponses?: ReadonlyArray<unknown>\n readonly usage?: unknown\n readonly turn?: number\n readonly eventSequence?: number\n}\n\nexport type VercelAgentWorkflowAwaitingInput = {\n readonly hookToken: string\n readonly requests: ReadonlyArray<unknown>\n readonly messages: ReadonlyArray<unknown>\n readonly usage: unknown\n readonly turns: number\n readonly eventSequence?: number\n}\n\nexport type VercelAgentWorkflowToolBatchStepResult = {\n readonly messages: ReadonlyArray<unknown>\n readonly createdMessages: ReadonlyArray<unknown>\n /** Updated cumulative usage when tools run nested model work such as subagents. */\n readonly usage?: unknown\n readonly awaitingInput?: VercelAgentWorkflowAwaitingInput\n readonly eventSequence?: number\n /**\n * A plain wire-safe failure captured after partial progress. Returning it instead of rejecting\n * lets orchestration retain usage and event sequencing from completed sibling tools.\n */\n readonly failure?: unknown\n}\n\nexport type WorkflowStepResult<A> = Data.TaggedEnum<{\n Success: {\n readonly value: A\n }\n Failure: {\n readonly error: unknown\n }\n}>\n\ninterface WorkflowStepResultDefinition extends Data.TaggedEnum.WithGenerics<1> {\n readonly taggedEnum: WorkflowStepResult<this['A']>\n}\n\nexport const WorkflowStepResult = Data.taggedEnum<WorkflowStepResultDefinition>()\n\nexport type VercelAgentWorkflowStepRetryPolicy = {\n readonly maxAttempts: number\n}\n\nexport type VercelAgentWorkflowRunResult = Data.TaggedEnum<{\n Completed: {\n readonly turns: number\n readonly state: SerializableWorkflowState\n }\n ModelStepFailed: {\n readonly turn: number\n readonly error: unknown\n readonly state: SerializableWorkflowState\n }\n ToolBatchStepFailed: {\n readonly turn: number\n readonly error: unknown\n readonly state: SerializableWorkflowState\n }\n AwaitInputFailed: {\n readonly turn: number\n readonly error: unknown\n readonly awaitingInput: VercelAgentWorkflowAwaitingInput\n readonly state: SerializableWorkflowState\n }\n CloseStreamFailed: {\n readonly turns: number\n readonly error: unknown\n readonly state: SerializableWorkflowState\n }\n MaxTurnsExceeded: {\n readonly maxTurns: number\n readonly error: Error\n readonly state: SerializableWorkflowState\n }\n}>\n\nexport const VercelAgentWorkflowRunResult = Data.taggedEnum<VercelAgentWorkflowRunResult>()\n\nexport type VercelAgentWorkflowLoopConfig = {\n readonly input: VercelAgentWorkflowInput\n readonly maxTurns?: number\n readonly runModelStep: (\n input: VercelAgentWorkflowModelStepInput\n ) => Promise<VercelAgentWorkflowModelStepResult>\n readonly runToolBatchStep: (\n input: VercelAgentWorkflowToolBatchStepInput\n ) => Promise<VercelAgentWorkflowToolBatchStepResult>\n /** Called only after a model step returns `done: true`. */\n readonly closeStream: () => Promise<void>\n /**\n * Best-effort final failure handler. It must write a safe final error and\n * close the failure stream; rejection is suppressed in favor of the\n * original structured run result.\n */\n readonly writeError: (error: unknown) => Promise<void>\n /** A successful await suspends/resumes without invoking either finalizer. */\n readonly awaitInput?: (input: VercelAgentWorkflowAwaitingInput) => Promise<unknown>\n readonly modelStepRetry?: VercelAgentWorkflowStepRetryPolicy\n readonly toolBatchStepRetry?: VercelAgentWorkflowStepRetryPolicy\n readonly awaitInputRetry?: VercelAgentWorkflowStepRetryPolicy\n readonly closeStreamRetry?: VercelAgentWorkflowStepRetryPolicy\n}\n\nexport const defaultMaxWorkflowTurns = 500\n\nexport const noWorkflowStepRetry: VercelAgentWorkflowStepRetryPolicy = { maxAttempts: 1 }\n\nexport const settleWorkflowStep = <A>(promise: Promise<A>): Promise<WorkflowStepResult<A>> =>\n promise.then(\n value => WorkflowStepResult.Success<A>({ value }),\n error => WorkflowStepResult.Failure<A>({ error })\n )\n\nconst workflowMaxTurnsError = (maxTurns: number) =>\n new Error(`Vercel agent workflow exceeded max turns: ${maxTurns}`)\n\nconst writeErrorSafely = (writeError: (error: unknown) => Promise<void>, error: unknown) =>\n writeError(error).catch(() => undefined)\n\nconst missingAwaitInputHandlerError = () =>\n new Error(\n 'Vercel agent workflow awaiting input requested but no awaitInput handler is configured'\n )\n\nconst maxRetryAttempts = (policy: VercelAgentWorkflowStepRetryPolicy | undefined) => {\n const configured = policy?.maxAttempts ?? noWorkflowStepRetry.maxAttempts\n\n return Number.isFinite(configured) ? Math.max(1, Math.floor(configured)) : 1\n}\n\nconst maxWorkflowTurns = (configured: number | undefined) => {\n if (configured === undefined || !Number.isFinite(configured)) {\n return defaultMaxWorkflowTurns\n }\n\n return Math.max(1, Math.floor(configured))\n}\n\nexport async function retryWorkflowStep<A>(\n runStep: () => Promise<A>,\n policy?: VercelAgentWorkflowStepRetryPolicy\n): Promise<A> {\n const maxAttempts = maxRetryAttempts(policy)\n\n let attempt = 1\n\n for (;;) {\n try {\n return await runStep()\n } catch (error) {\n if (attempt >= maxAttempts) {\n throw error\n }\n\n attempt += 1\n }\n }\n}\n\nexport async function runVercelAgentWorkflow(\n config: VercelAgentWorkflowLoopConfig\n): Promise<VercelAgentWorkflowRunResult> {\n const {\n input,\n maxTurns: configuredMaxTurns,\n runModelStep,\n runToolBatchStep,\n closeStream,\n writeError,\n awaitInput,\n modelStepRetry,\n toolBatchStepRetry,\n awaitInputRetry,\n closeStreamRetry\n } = config\n\n let state: SerializableWorkflowState = {\n request: input.request,\n createdMessages: [],\n turn: 1,\n eventSequence: 0\n }\n\n const maxTurns = maxWorkflowTurns(configuredMaxTurns)\n\n for (let step = 0; step < maxTurns; step++) {\n const modelResult = await settleWorkflowStep(\n retryWorkflowStep(() => runModelStep({ context: input.context, state }), modelStepRetry)\n )\n\n if (Predicate.isTagged(modelResult, 'Failure')) {\n await writeErrorSafely(writeError, modelResult.error)\n\n return VercelAgentWorkflowRunResult.ModelStepFailed({\n turn: state.turn,\n error: modelResult.error,\n state\n })\n }\n\n if (modelResult.value.done) {\n const terminalState: SerializableWorkflowState = {\n request: input.request,\n messages: modelResult.value.messages,\n createdMessages: modelResult.value.createdMessages,\n usage: modelResult.value.usage,\n turn: modelResult.value.turn,\n eventSequence: modelResult.value.eventSequence ?? state.eventSequence\n }\n\n const closeResult = await settleWorkflowStep(retryWorkflowStep(closeStream, closeStreamRetry))\n\n if (Predicate.isTagged(closeResult, 'Failure')) {\n await writeErrorSafely(writeError, closeResult.error)\n\n return VercelAgentWorkflowRunResult.CloseStreamFailed({\n turns: modelResult.value.turn,\n error: closeResult.error,\n state: terminalState\n })\n }\n\n return VercelAgentWorkflowRunResult.Completed({\n turns: modelResult.value.turn,\n state: terminalState\n })\n }\n\n if (modelResult.value.toolCalls.length === 0) {\n state = {\n request: input.request,\n messages: modelResult.value.messages,\n createdMessages: modelResult.value.createdMessages,\n usage: modelResult.value.usage,\n turn: modelResult.value.turn + 1,\n eventSequence: modelResult.value.eventSequence ?? state.eventSequence\n }\n continue\n }\n\n let completedToolsResult: VercelAgentWorkflowToolBatchStepResult | undefined\n const toolHitlResponses: Array<unknown> = []\n let cumulativeUsage = modelResult.value.usage\n let toolEventSequence = modelResult.value.eventSequence ?? state.eventSequence\n\n const currentTurnState = (\n toolResult?: VercelAgentWorkflowToolBatchStepResult\n ): SerializableWorkflowState => ({\n request: input.request,\n messages:\n toolResult === undefined\n ? modelResult.value.messages\n : [...modelResult.value.messages, ...toolResult.messages],\n createdMessages: toolResult?.createdMessages ?? modelResult.value.createdMessages,\n usage: cumulativeUsage,\n turn: modelResult.value.turn,\n eventSequence: toolEventSequence\n })\n\n for (;;) {\n const toolsResult = await settleWorkflowStep(\n retryWorkflowStep(\n () =>\n runToolBatchStep({\n context: input.context,\n request: input.request,\n calls: modelResult.value.toolCalls,\n createdMessages: modelResult.value.createdMessages,\n hitlResponses: toolHitlResponses.slice(),\n usage: cumulativeUsage,\n turn: modelResult.value.turn,\n eventSequence: toolEventSequence\n }),\n toolBatchStepRetry\n )\n )\n\n if (Predicate.isTagged(toolsResult, 'Failure')) {\n await writeErrorSafely(writeError, toolsResult.error)\n\n return VercelAgentWorkflowRunResult.ToolBatchStepFailed({\n turn: modelResult.value.turn,\n error: toolsResult.error,\n state: currentTurnState()\n })\n }\n\n cumulativeUsage = toolsResult.value.usage ?? cumulativeUsage\n toolEventSequence = toolsResult.value.eventSequence ?? toolEventSequence\n\n if (toolsResult.value.failure !== undefined) {\n await writeErrorSafely(writeError, toolsResult.value.failure)\n\n return VercelAgentWorkflowRunResult.ToolBatchStepFailed({\n turn: modelResult.value.turn,\n error: toolsResult.value.failure,\n state: currentTurnState(toolsResult.value)\n })\n }\n\n if (toolsResult.value.awaitingInput === undefined) {\n completedToolsResult = toolsResult.value\n break\n }\n\n const awaitingInput = toolsResult.value.awaitingInput\n cumulativeUsage = toolsResult.value.usage ?? awaitingInput.usage ?? cumulativeUsage\n toolEventSequence = awaitingInput.eventSequence ?? toolEventSequence\n\n const hitlResponse = await settleWorkflowStep(\n retryWorkflowStep(() => {\n if (awaitInput === undefined) {\n return Promise.reject(missingAwaitInputHandlerError())\n }\n\n return awaitInput(awaitingInput)\n }, awaitInputRetry)\n )\n\n if (Predicate.isTagged(hitlResponse, 'Failure')) {\n await writeErrorSafely(writeError, hitlResponse.error)\n\n return VercelAgentWorkflowRunResult.AwaitInputFailed({\n turn: modelResult.value.turn,\n error: hitlResponse.error,\n awaitingInput,\n state: currentTurnState(toolsResult.value)\n })\n }\n\n toolHitlResponses.push(hitlResponse.value)\n }\n\n if (completedToolsResult === undefined) {\n const error = new Error('Vercel agent workflow tool batch did not complete')\n await writeErrorSafely(writeError, error)\n\n return VercelAgentWorkflowRunResult.ToolBatchStepFailed({\n turn: modelResult.value.turn,\n error,\n state\n })\n }\n\n state = {\n request: input.request,\n messages: [...modelResult.value.messages, ...completedToolsResult.messages],\n createdMessages: completedToolsResult.createdMessages,\n usage: completedToolsResult.usage ?? cumulativeUsage,\n turn: modelResult.value.turn + 1,\n eventSequence: completedToolsResult.eventSequence ?? toolEventSequence\n }\n }\n\n const error = workflowMaxTurnsError(maxTurns)\n await writeErrorSafely(writeError, error)\n\n return VercelAgentWorkflowRunResult.MaxTurnsExceeded({\n maxTurns,\n error,\n state\n })\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"workflow-loop.mjs","names":[],"sources":["../src/workflow-loop.ts"],"sourcesContent":["import { Data, Predicate } from 'effect'\n\nexport type VercelAgentWorkflowInput = {\n readonly request: unknown\n readonly context: unknown\n}\n\nexport type SerializableWorkflowState = {\n readonly request: unknown\n readonly messages?: ReadonlyArray<unknown>\n readonly createdMessages: ReadonlyArray<unknown>\n readonly usage?: unknown\n readonly turn: number\n readonly eventSequence?: number\n}\n\nexport type VercelAgentWorkflowModelStepInput = {\n readonly context: unknown\n readonly state: SerializableWorkflowState\n}\n\nexport type VercelAgentWorkflowModelStepResult = {\n readonly done: boolean\n readonly messages: ReadonlyArray<unknown>\n readonly createdMessages: ReadonlyArray<unknown>\n readonly toolCalls: ReadonlyArray<unknown>\n readonly usage: unknown\n readonly turn: number\n readonly eventSequence?: number\n}\n\nexport type VercelAgentWorkflowToolBatchStepInput = {\n readonly context: unknown\n readonly request: unknown\n readonly calls: ReadonlyArray<unknown>\n readonly createdMessages: ReadonlyArray<unknown>\n readonly hitlResponses?: ReadonlyArray<unknown>\n /**\n * On a resume, the requests of the pause being resumed (`awaitingInput.requests` of the\n * previous attempt). Forward them to the agent loop (`prepareToolBatch` / `runToolBatch`\n * `awaitingRequests`) so an unanswered approval stays pending even when its tool's policy\n * changed. Absent on the first attempt of a batch.\n */\n readonly awaitingRequests?: ReadonlyArray<unknown>\n readonly usage?: unknown\n readonly turn?: number\n readonly eventSequence?: number\n}\n\n/** A resume carries the pause it resumes; the first attempt of a batch has none. */\nconst withAwaitingRequests = (\n base: VercelAgentWorkflowToolBatchStepInput,\n awaitingRequests: ReadonlyArray<unknown> | undefined\n): VercelAgentWorkflowToolBatchStepInput =>\n awaitingRequests === undefined ? base : { ...base, awaitingRequests }\n\nexport type VercelAgentWorkflowAwaitingInput = {\n readonly hookToken: string\n readonly requests: ReadonlyArray<unknown>\n readonly messages: ReadonlyArray<unknown>\n readonly usage: unknown\n readonly turns: number\n readonly eventSequence?: number\n}\n\nexport type VercelAgentWorkflowToolBatchStepResult = {\n readonly messages: ReadonlyArray<unknown>\n readonly createdMessages: ReadonlyArray<unknown>\n /** Updated cumulative usage when tools run nested model work such as subagents. */\n readonly usage?: unknown\n readonly awaitingInput?: VercelAgentWorkflowAwaitingInput\n readonly eventSequence?: number\n /**\n * A plain wire-safe failure captured after partial progress. Returning it instead of rejecting\n * lets orchestration retain usage and event sequencing from completed sibling tools.\n */\n readonly failure?: unknown\n}\n\nexport type WorkflowStepResult<A> = Data.TaggedEnum<{\n Success: {\n readonly value: A\n }\n Failure: {\n readonly error: unknown\n }\n}>\n\ninterface WorkflowStepResultDefinition extends Data.TaggedEnum.WithGenerics<1> {\n readonly taggedEnum: WorkflowStepResult<this['A']>\n}\n\nexport const WorkflowStepResult = Data.taggedEnum<WorkflowStepResultDefinition>()\n\nexport type VercelAgentWorkflowStepRetryPolicy = {\n readonly maxAttempts: number\n}\n\nexport type VercelAgentWorkflowRunResult = Data.TaggedEnum<{\n Completed: {\n readonly turns: number\n readonly state: SerializableWorkflowState\n }\n ModelStepFailed: {\n readonly turn: number\n readonly error: unknown\n readonly state: SerializableWorkflowState\n }\n ToolBatchStepFailed: {\n readonly turn: number\n readonly error: unknown\n readonly state: SerializableWorkflowState\n }\n AwaitInputFailed: {\n readonly turn: number\n readonly error: unknown\n readonly awaitingInput: VercelAgentWorkflowAwaitingInput\n readonly state: SerializableWorkflowState\n }\n CloseStreamFailed: {\n readonly turns: number\n readonly error: unknown\n readonly state: SerializableWorkflowState\n }\n MaxTurnsExceeded: {\n readonly maxTurns: number\n readonly error: Error\n readonly state: SerializableWorkflowState\n }\n}>\n\nexport const VercelAgentWorkflowRunResult = Data.taggedEnum<VercelAgentWorkflowRunResult>()\n\nexport type VercelAgentWorkflowLoopConfig = {\n readonly input: VercelAgentWorkflowInput\n readonly maxTurns?: number\n readonly runModelStep: (\n input: VercelAgentWorkflowModelStepInput\n ) => Promise<VercelAgentWorkflowModelStepResult>\n readonly runToolBatchStep: (\n input: VercelAgentWorkflowToolBatchStepInput\n ) => Promise<VercelAgentWorkflowToolBatchStepResult>\n /** Called only after a model step returns `done: true`. */\n readonly closeStream: () => Promise<void>\n /**\n * Best-effort final failure handler. It must write a safe final error and\n * close the failure stream; rejection is suppressed in favor of the\n * original structured run result.\n */\n readonly writeError: (error: unknown) => Promise<void>\n /** A successful await suspends/resumes without invoking either finalizer. */\n readonly awaitInput?: (input: VercelAgentWorkflowAwaitingInput) => Promise<unknown>\n readonly modelStepRetry?: VercelAgentWorkflowStepRetryPolicy\n readonly toolBatchStepRetry?: VercelAgentWorkflowStepRetryPolicy\n readonly awaitInputRetry?: VercelAgentWorkflowStepRetryPolicy\n readonly closeStreamRetry?: VercelAgentWorkflowStepRetryPolicy\n}\n\nexport const defaultMaxWorkflowTurns = 500\n\nexport const noWorkflowStepRetry: VercelAgentWorkflowStepRetryPolicy = { maxAttempts: 1 }\n\nexport const settleWorkflowStep = <A>(promise: Promise<A>): Promise<WorkflowStepResult<A>> =>\n promise.then(\n value => WorkflowStepResult.Success<A>({ value }),\n error => WorkflowStepResult.Failure<A>({ error })\n )\n\nconst workflowMaxTurnsError = (maxTurns: number) =>\n new Error(`Vercel agent workflow exceeded max turns: ${maxTurns}`)\n\nconst writeErrorSafely = (writeError: (error: unknown) => Promise<void>, error: unknown) =>\n writeError(error).catch(() => undefined)\n\nconst missingAwaitInputHandlerError = () =>\n new Error(\n 'Vercel agent workflow awaiting input requested but no awaitInput handler is configured'\n )\n\nconst maxRetryAttempts = (policy: VercelAgentWorkflowStepRetryPolicy | undefined) => {\n const configured = policy?.maxAttempts ?? noWorkflowStepRetry.maxAttempts\n\n return Number.isFinite(configured) ? Math.max(1, Math.floor(configured)) : 1\n}\n\nconst maxWorkflowTurns = (configured: number | undefined) => {\n if (configured === undefined || !Number.isFinite(configured)) {\n return defaultMaxWorkflowTurns\n }\n\n return Math.max(1, Math.floor(configured))\n}\n\nexport async function retryWorkflowStep<A>(\n runStep: () => Promise<A>,\n policy?: VercelAgentWorkflowStepRetryPolicy\n): Promise<A> {\n const maxAttempts = maxRetryAttempts(policy)\n\n let attempt = 1\n\n for (;;) {\n try {\n return await runStep()\n } catch (error) {\n if (attempt >= maxAttempts) {\n throw error\n }\n\n attempt += 1\n }\n }\n}\n\nexport async function runVercelAgentWorkflow(\n config: VercelAgentWorkflowLoopConfig\n): Promise<VercelAgentWorkflowRunResult> {\n const {\n input,\n maxTurns: configuredMaxTurns,\n runModelStep,\n runToolBatchStep,\n closeStream,\n writeError,\n awaitInput,\n modelStepRetry,\n toolBatchStepRetry,\n awaitInputRetry,\n closeStreamRetry\n } = config\n\n let state: SerializableWorkflowState = {\n request: input.request,\n createdMessages: [],\n turn: 1,\n eventSequence: 0\n }\n\n const maxTurns = maxWorkflowTurns(configuredMaxTurns)\n\n for (let step = 0; step < maxTurns; step++) {\n const modelResult = await settleWorkflowStep(\n retryWorkflowStep(() => runModelStep({ context: input.context, state }), modelStepRetry)\n )\n\n if (Predicate.isTagged(modelResult, 'Failure')) {\n await writeErrorSafely(writeError, modelResult.error)\n\n return VercelAgentWorkflowRunResult.ModelStepFailed({\n turn: state.turn,\n error: modelResult.error,\n state\n })\n }\n\n if (modelResult.value.done) {\n const terminalState: SerializableWorkflowState = {\n request: input.request,\n messages: modelResult.value.messages,\n createdMessages: modelResult.value.createdMessages,\n usage: modelResult.value.usage,\n turn: modelResult.value.turn,\n eventSequence: modelResult.value.eventSequence ?? state.eventSequence\n }\n\n const closeResult = await settleWorkflowStep(retryWorkflowStep(closeStream, closeStreamRetry))\n\n if (Predicate.isTagged(closeResult, 'Failure')) {\n await writeErrorSafely(writeError, closeResult.error)\n\n return VercelAgentWorkflowRunResult.CloseStreamFailed({\n turns: modelResult.value.turn,\n error: closeResult.error,\n state: terminalState\n })\n }\n\n return VercelAgentWorkflowRunResult.Completed({\n turns: modelResult.value.turn,\n state: terminalState\n })\n }\n\n if (modelResult.value.toolCalls.length === 0) {\n state = {\n request: input.request,\n messages: modelResult.value.messages,\n createdMessages: modelResult.value.createdMessages,\n usage: modelResult.value.usage,\n turn: modelResult.value.turn + 1,\n eventSequence: modelResult.value.eventSequence ?? state.eventSequence\n }\n continue\n }\n\n let completedToolsResult: VercelAgentWorkflowToolBatchStepResult | undefined\n const toolHitlResponses: Array<unknown> = []\n let toolAwaitingRequests: ReadonlyArray<unknown> | undefined\n let cumulativeUsage = modelResult.value.usage\n let toolEventSequence = modelResult.value.eventSequence ?? state.eventSequence\n\n const currentTurnState = (\n toolResult?: VercelAgentWorkflowToolBatchStepResult\n ): SerializableWorkflowState => ({\n request: input.request,\n messages:\n toolResult === undefined\n ? modelResult.value.messages\n : [...modelResult.value.messages, ...toolResult.messages],\n createdMessages: toolResult?.createdMessages ?? modelResult.value.createdMessages,\n usage: cumulativeUsage,\n turn: modelResult.value.turn,\n eventSequence: toolEventSequence\n })\n\n for (;;) {\n const stepInput = withAwaitingRequests(\n {\n context: input.context,\n request: input.request,\n calls: modelResult.value.toolCalls,\n createdMessages: modelResult.value.createdMessages,\n hitlResponses: toolHitlResponses.slice(),\n usage: cumulativeUsage,\n turn: modelResult.value.turn,\n eventSequence: toolEventSequence\n },\n toolAwaitingRequests\n )\n\n const toolsResult = await settleWorkflowStep(\n retryWorkflowStep(() => runToolBatchStep(stepInput), toolBatchStepRetry)\n )\n\n if (Predicate.isTagged(toolsResult, 'Failure')) {\n await writeErrorSafely(writeError, toolsResult.error)\n\n return VercelAgentWorkflowRunResult.ToolBatchStepFailed({\n turn: modelResult.value.turn,\n error: toolsResult.error,\n state: currentTurnState()\n })\n }\n\n cumulativeUsage = toolsResult.value.usage ?? cumulativeUsage\n toolEventSequence = toolsResult.value.eventSequence ?? toolEventSequence\n\n if (toolsResult.value.failure !== undefined) {\n await writeErrorSafely(writeError, toolsResult.value.failure)\n\n return VercelAgentWorkflowRunResult.ToolBatchStepFailed({\n turn: modelResult.value.turn,\n error: toolsResult.value.failure,\n state: currentTurnState(toolsResult.value)\n })\n }\n\n if (toolsResult.value.awaitingInput === undefined) {\n completedToolsResult = toolsResult.value\n break\n }\n\n const awaitingInput = toolsResult.value.awaitingInput\n toolAwaitingRequests = awaitingInput.requests\n cumulativeUsage = toolsResult.value.usage ?? awaitingInput.usage ?? cumulativeUsage\n toolEventSequence = awaitingInput.eventSequence ?? toolEventSequence\n\n const hitlResponse = await settleWorkflowStep(\n retryWorkflowStep(() => {\n if (awaitInput === undefined) {\n return Promise.reject(missingAwaitInputHandlerError())\n }\n\n return awaitInput(awaitingInput)\n }, awaitInputRetry)\n )\n\n if (Predicate.isTagged(hitlResponse, 'Failure')) {\n await writeErrorSafely(writeError, hitlResponse.error)\n\n return VercelAgentWorkflowRunResult.AwaitInputFailed({\n turn: modelResult.value.turn,\n error: hitlResponse.error,\n awaitingInput,\n state: currentTurnState(toolsResult.value)\n })\n }\n\n toolHitlResponses.push(hitlResponse.value)\n }\n\n if (completedToolsResult === undefined) {\n const error = new Error('Vercel agent workflow tool batch did not complete')\n await writeErrorSafely(writeError, error)\n\n return VercelAgentWorkflowRunResult.ToolBatchStepFailed({\n turn: modelResult.value.turn,\n error,\n state\n })\n }\n\n state = {\n request: input.request,\n messages: [...modelResult.value.messages, ...completedToolsResult.messages],\n createdMessages: completedToolsResult.createdMessages,\n usage: completedToolsResult.usage ?? cumulativeUsage,\n turn: modelResult.value.turn + 1,\n eventSequence: completedToolsResult.eventSequence ?? toolEventSequence\n }\n }\n\n const error = workflowMaxTurnsError(maxTurns)\n await writeErrorSafely(writeError, error)\n\n return VercelAgentWorkflowRunResult.MaxTurnsExceeded({\n maxTurns,\n error,\n state\n })\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yolk-sdk/vercel-workflows",
3
- "version": "0.1.0-canary.104",
3
+ "version": "0.1.0-canary.106",
4
4
  "description": "Vercel Workflow orchestration primitives for Yolk agent loops.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -35,11 +35,25 @@ export type VercelAgentWorkflowToolBatchStepInput = {
35
35
  readonly calls: ReadonlyArray<unknown>
36
36
  readonly createdMessages: ReadonlyArray<unknown>
37
37
  readonly hitlResponses?: ReadonlyArray<unknown>
38
+ /**
39
+ * On a resume, the requests of the pause being resumed (`awaitingInput.requests` of the
40
+ * previous attempt). Forward them to the agent loop (`prepareToolBatch` / `runToolBatch`
41
+ * `awaitingRequests`) so an unanswered approval stays pending even when its tool's policy
42
+ * changed. Absent on the first attempt of a batch.
43
+ */
44
+ readonly awaitingRequests?: ReadonlyArray<unknown>
38
45
  readonly usage?: unknown
39
46
  readonly turn?: number
40
47
  readonly eventSequence?: number
41
48
  }
42
49
 
50
+ /** A resume carries the pause it resumes; the first attempt of a batch has none. */
51
+ const withAwaitingRequests = (
52
+ base: VercelAgentWorkflowToolBatchStepInput,
53
+ awaitingRequests: ReadonlyArray<unknown> | undefined
54
+ ): VercelAgentWorkflowToolBatchStepInput =>
55
+ awaitingRequests === undefined ? base : { ...base, awaitingRequests }
56
+
43
57
  export type VercelAgentWorkflowAwaitingInput = {
44
58
  readonly hookToken: string
45
59
  readonly requests: ReadonlyArray<unknown>
@@ -281,6 +295,7 @@ export async function runVercelAgentWorkflow(
281
295
 
282
296
  let completedToolsResult: VercelAgentWorkflowToolBatchStepResult | undefined
283
297
  const toolHitlResponses: Array<unknown> = []
298
+ let toolAwaitingRequests: ReadonlyArray<unknown> | undefined
284
299
  let cumulativeUsage = modelResult.value.usage
285
300
  let toolEventSequence = modelResult.value.eventSequence ?? state.eventSequence
286
301
 
@@ -299,21 +314,22 @@ export async function runVercelAgentWorkflow(
299
314
  })
300
315
 
301
316
  for (;;) {
317
+ const stepInput = withAwaitingRequests(
318
+ {
319
+ context: input.context,
320
+ request: input.request,
321
+ calls: modelResult.value.toolCalls,
322
+ createdMessages: modelResult.value.createdMessages,
323
+ hitlResponses: toolHitlResponses.slice(),
324
+ usage: cumulativeUsage,
325
+ turn: modelResult.value.turn,
326
+ eventSequence: toolEventSequence
327
+ },
328
+ toolAwaitingRequests
329
+ )
330
+
302
331
  const toolsResult = await settleWorkflowStep(
303
- retryWorkflowStep(
304
- () =>
305
- runToolBatchStep({
306
- context: input.context,
307
- request: input.request,
308
- calls: modelResult.value.toolCalls,
309
- createdMessages: modelResult.value.createdMessages,
310
- hitlResponses: toolHitlResponses.slice(),
311
- usage: cumulativeUsage,
312
- turn: modelResult.value.turn,
313
- eventSequence: toolEventSequence
314
- }),
315
- toolBatchStepRetry
316
- )
332
+ retryWorkflowStep(() => runToolBatchStep(stepInput), toolBatchStepRetry)
317
333
  )
318
334
 
319
335
  if (Predicate.isTagged(toolsResult, 'Failure')) {
@@ -345,6 +361,7 @@ export async function runVercelAgentWorkflow(
345
361
  }
346
362
 
347
363
  const awaitingInput = toolsResult.value.awaitingInput
364
+ toolAwaitingRequests = awaitingInput.requests
348
365
  cumulativeUsage = toolsResult.value.usage ?? awaitingInput.usage ?? cumulativeUsage
349
366
  toolEventSequence = awaitingInput.eventSequence ?? toolEventSequence
350
367