@yolk-sdk/vercel-workflows 0.1.0-canary.100

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.
@@ -0,0 +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":";;AA8EA,MAAa,qBAAqB,KAAK,WAAyC;AAuChF,MAAa,+BAA+B,KAAK,WAAyC;AA2B1F,MAAa,0BAA0B;AAEvC,MAAa,sBAA0D,EAAE,aAAa,EAAE;AAExF,MAAa,sBAAyB,YACpC,QAAQ,MACN,UAAS,mBAAmB,QAAW,EAAE,MAAM,CAAC,IAChD,UAAS,mBAAmB,QAAW,EAAE,MAAM,CAAC,CAClD;AAEF,MAAM,yBAAyB,6BAC7B,IAAI,MAAM,6CAA6C,UAAU;AAEnE,MAAM,oBAAoB,YAA+C,UACvE,WAAW,KAAK,EAAE,YAAY,KAAA,CAAS;AAEzC,MAAM,sDACJ,IAAI,MACF,wFACF;AAEF,MAAM,oBAAoB,WAA2D;CACnF,MAAM,aAAa,QAAQ,eAAe,oBAAoB;CAE9D,OAAO,OAAO,SAAS,UAAU,IAAI,KAAK,IAAI,GAAG,KAAK,MAAM,UAAU,CAAC,IAAI;AAC7E;AAEA,MAAM,oBAAoB,eAAmC;CAC3D,IAAI,eAAe,KAAA,KAAa,CAAC,OAAO,SAAS,UAAU,GACzD,OAAA;CAGF,OAAO,KAAK,IAAI,GAAG,KAAK,MAAM,UAAU,CAAC;AAC3C;AAEA,eAAsB,kBACpB,SACA,QACY;CACZ,MAAM,cAAc,iBAAiB,MAAM;CAE3C,IAAI,UAAU;CAEd,SACE,IAAI;EACF,OAAO,MAAM,QAAQ;CACvB,SAAS,OAAO;EACd,IAAI,WAAW,aACb,MAAM;EAGR,WAAW;CACb;AAEJ;AAEA,eAAsB,uBACpB,QACuC;CACvC,MAAM,EACJ,OACA,UAAU,oBACV,cACA,kBACA,aACA,YACA,YACA,gBACA,oBACA,iBACA,qBACE;CAEJ,IAAI,QAAmC;EACrC,SAAS,MAAM;EACf,iBAAiB,CAAC;EAClB,MAAM;EACN,eAAe;CACjB;CAEA,MAAM,WAAW,iBAAiB,kBAAkB;CAEpD,KAAK,IAAI,OAAO,GAAG,OAAO,UAAU,QAAQ;EAC1C,MAAM,cAAc,MAAM,mBACxB,wBAAwB,aAAa;GAAE,SAAS,MAAM;GAAS;EAAM,CAAC,GAAG,cAAc,CACzF;EAEA,IAAI,UAAU,SAAS,aAAa,SAAS,GAAG;GAC9C,MAAM,iBAAiB,YAAY,YAAY,KAAK;GAEpD,OAAO,6BAA6B,gBAAgB;IAClD,MAAM,MAAM;IACZ,OAAO,YAAY;IACnB;GACF,CAAC;EACH;EAEA,IAAI,YAAY,MAAM,MAAM;GAC1B,MAAM,gBAA2C;IAC/C,SAAS,MAAM;IACf,UAAU,YAAY,MAAM;IAC5B,iBAAiB,YAAY,MAAM;IACnC,OAAO,YAAY,MAAM;IACzB,MAAM,YAAY,MAAM;IACxB,eAAe,YAAY,MAAM,iBAAiB,MAAM;GAC1D;GAEA,MAAM,cAAc,MAAM,mBAAmB,kBAAkB,aAAa,gBAAgB,CAAC;GAE7F,IAAI,UAAU,SAAS,aAAa,SAAS,GAAG;IAC9C,MAAM,iBAAiB,YAAY,YAAY,KAAK;IAEpD,OAAO,6BAA6B,kBAAkB;KACpD,OAAO,YAAY,MAAM;KACzB,OAAO,YAAY;KACnB,OAAO;IACT,CAAC;GACH;GAEA,OAAO,6BAA6B,UAAU;IAC5C,OAAO,YAAY,MAAM;IACzB,OAAO;GACT,CAAC;EACH;EAEA,IAAI,YAAY,MAAM,UAAU,WAAW,GAAG;GAC5C,QAAQ;IACN,SAAS,MAAM;IACf,UAAU,YAAY,MAAM;IAC5B,iBAAiB,YAAY,MAAM;IACnC,OAAO,YAAY,MAAM;IACzB,MAAM,YAAY,MAAM,OAAO;IAC/B,eAAe,YAAY,MAAM,iBAAiB,MAAM;GAC1D;GACA;EACF;EAEA,IAAI;EACJ,MAAM,oBAAoC,CAAC;EAC3C,IAAI,kBAAkB,YAAY,MAAM;EACxC,IAAI,oBAAoB,YAAY,MAAM,iBAAiB,MAAM;EAEjE,MAAM,oBACJ,gBAC+B;GAC/B,SAAS,MAAM;GACf,UACE,eAAe,KAAA,IACX,YAAY,MAAM,WAClB,CAAC,GAAG,YAAY,MAAM,UAAU,GAAG,WAAW,QAAQ;GAC5D,iBAAiB,YAAY,mBAAmB,YAAY,MAAM;GAClE,OAAO;GACP,MAAM,YAAY,MAAM;GACxB,eAAe;EACjB;EAEA,SAAS;GACP,MAAM,cAAc,MAAM,mBACxB,wBAEI,iBAAiB;IACf,SAAS,MAAM;IACf,SAAS,MAAM;IACf,OAAO,YAAY,MAAM;IACzB,iBAAiB,YAAY,MAAM;IACnC,eAAe,kBAAkB,MAAM;IACvC,OAAO;IACP,MAAM,YAAY,MAAM;IACxB,eAAe;GACjB,CAAC,GACH,kBACF,CACF;GAEA,IAAI,UAAU,SAAS,aAAa,SAAS,GAAG;IAC9C,MAAM,iBAAiB,YAAY,YAAY,KAAK;IAEpD,OAAO,6BAA6B,oBAAoB;KACtD,MAAM,YAAY,MAAM;KACxB,OAAO,YAAY;KACnB,OAAO,iBAAiB;IAC1B,CAAC;GACH;GAEA,kBAAkB,YAAY,MAAM,SAAS;GAC7C,oBAAoB,YAAY,MAAM,iBAAiB;GAEvD,IAAI,YAAY,MAAM,YAAY,KAAA,GAAW;IAC3C,MAAM,iBAAiB,YAAY,YAAY,MAAM,OAAO;IAE5D,OAAO,6BAA6B,oBAAoB;KACtD,MAAM,YAAY,MAAM;KACxB,OAAO,YAAY,MAAM;KACzB,OAAO,iBAAiB,YAAY,KAAK;IAC3C,CAAC;GACH;GAEA,IAAI,YAAY,MAAM,kBAAkB,KAAA,GAAW;IACjD,uBAAuB,YAAY;IACnC;GACF;GAEA,MAAM,gBAAgB,YAAY,MAAM;GACxC,kBAAkB,YAAY,MAAM,SAAS,cAAc,SAAS;GACpE,oBAAoB,cAAc,iBAAiB;GAEnD,MAAM,eAAe,MAAM,mBACzB,wBAAwB;IACtB,IAAI,eAAe,KAAA,GACjB,OAAO,QAAQ,OAAO,8BAA8B,CAAC;IAGvD,OAAO,WAAW,aAAa;GACjC,GAAG,eAAe,CACpB;GAEA,IAAI,UAAU,SAAS,cAAc,SAAS,GAAG;IAC/C,MAAM,iBAAiB,YAAY,aAAa,KAAK;IAErD,OAAO,6BAA6B,iBAAiB;KACnD,MAAM,YAAY,MAAM;KACxB,OAAO,aAAa;KACpB;KACA,OAAO,iBAAiB,YAAY,KAAK;IAC3C,CAAC;GACH;GAEA,kBAAkB,KAAK,aAAa,KAAK;EAC3C;EAEA,IAAI,yBAAyB,KAAA,GAAW;GACtC,MAAM,wBAAQ,IAAI,MAAM,mDAAmD;GAC3E,MAAM,iBAAiB,YAAY,KAAK;GAExC,OAAO,6BAA6B,oBAAoB;IACtD,MAAM,YAAY,MAAM;IACxB;IACA;GACF,CAAC;EACH;EAEA,QAAQ;GACN,SAAS,MAAM;GACf,UAAU,CAAC,GAAG,YAAY,MAAM,UAAU,GAAG,qBAAqB,QAAQ;GAC1E,iBAAiB,qBAAqB;GACtC,OAAO,qBAAqB,SAAS;GACrC,MAAM,YAAY,MAAM,OAAO;GAC/B,eAAe,qBAAqB,iBAAiB;EACvD;CACF;CAEA,MAAM,QAAQ,sBAAsB,QAAQ;CAC5C,MAAM,iBAAiB,YAAY,KAAK;CAExC,OAAO,6BAA6B,iBAAiB;EACnD;EACA;EACA;CACF,CAAC;AACH"}
@@ -0,0 +1,4 @@
1
+ import { SerializableWorkflowState, VercelAgentWorkflowAwaitingInput, VercelAgentWorkflowInput, VercelAgentWorkflowLoopConfig, VercelAgentWorkflowModelStepInput, VercelAgentWorkflowModelStepResult, VercelAgentWorkflowRunResult, VercelAgentWorkflowStepRetryPolicy, VercelAgentWorkflowToolBatchStepInput, VercelAgentWorkflowToolBatchStepResult, WorkflowStepResult, defaultMaxWorkflowTurns, noWorkflowStepRetry, retryWorkflowStep, runVercelAgentWorkflow, settleWorkflowStep } from "./workflow-loop.mjs";
2
+ import { CommitThenWriteTerminalEventInput, CommitThenWriteTerminalEventResult, DurableAgentEvent, DurableAgentEventIdInput, DurableAgentEventSequencerState, SequenceDurableAgentEventInput, SequencedDurableAgentEvent, WriteDurableAgentEventInput, commitThenWriteTerminalEvent, durableAgentEventId, makeDurableAgentEventSequencerState, sequenceDurableAgentEvent, writeDurableAgentEvent } from "./workflow-events.mjs";
3
+ import { awaitWorkflowChild, orchestrateWorkflowToolBatch } from "./workflow-children.mjs";
4
+ export { type CommitThenWriteTerminalEventInput, type CommitThenWriteTerminalEventResult, type DurableAgentEvent, type DurableAgentEventIdInput, type DurableAgentEventSequencerState, type SequenceDurableAgentEventInput, type SequencedDurableAgentEvent, type SerializableWorkflowState, type VercelAgentWorkflowAwaitingInput, type VercelAgentWorkflowInput, type VercelAgentWorkflowLoopConfig, type VercelAgentWorkflowModelStepInput, type VercelAgentWorkflowModelStepResult, VercelAgentWorkflowRunResult, type VercelAgentWorkflowStepRetryPolicy, type VercelAgentWorkflowToolBatchStepInput, type VercelAgentWorkflowToolBatchStepResult, WorkflowStepResult, type WriteDurableAgentEventInput, awaitWorkflowChild, commitThenWriteTerminalEvent, defaultMaxWorkflowTurns, durableAgentEventId, makeDurableAgentEventSequencerState, noWorkflowStepRetry, orchestrateWorkflowToolBatch, retryWorkflowStep, runVercelAgentWorkflow, sequenceDurableAgentEvent, settleWorkflowStep, writeDurableAgentEvent };
@@ -0,0 +1,4 @@
1
+ import { VercelAgentWorkflowRunResult, WorkflowStepResult, defaultMaxWorkflowTurns, noWorkflowStepRetry, retryWorkflowStep, runVercelAgentWorkflow, settleWorkflowStep } from "./workflow-loop.mjs";
2
+ import { commitThenWriteTerminalEvent, durableAgentEventId, makeDurableAgentEventSequencerState, sequenceDurableAgentEvent, writeDurableAgentEvent } from "./workflow-events.mjs";
3
+ import { awaitWorkflowChild, orchestrateWorkflowToolBatch } from "./workflow-children.mjs";
4
+ export { VercelAgentWorkflowRunResult, WorkflowStepResult, awaitWorkflowChild, commitThenWriteTerminalEvent, defaultMaxWorkflowTurns, durableAgentEventId, makeDurableAgentEventSequencerState, noWorkflowStepRetry, orchestrateWorkflowToolBatch, retryWorkflowStep, runVercelAgentWorkflow, sequenceDurableAgentEvent, settleWorkflowStep, writeDurableAgentEvent };
package/package.json ADDED
@@ -0,0 +1,77 @@
1
+ {
2
+ "name": "@yolk-sdk/vercel-workflows",
3
+ "version": "0.1.0-canary.100",
4
+ "description": "Vercel Workflow orchestration primitives for Yolk agent loops.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "sideEffects": false,
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/magoz/yolk-sdk.git",
11
+ "directory": "packages/vercel-workflows"
12
+ },
13
+ "bugs": {
14
+ "url": "https://github.com/magoz/yolk-sdk/issues"
15
+ },
16
+ "homepage": "https://github.com/magoz/yolk-sdk#readme",
17
+ "keywords": [
18
+ "vercel",
19
+ "workflow",
20
+ "agents",
21
+ "runtime",
22
+ "effect"
23
+ ],
24
+ "engines": {
25
+ "node": ">=22"
26
+ },
27
+ "exports": {
28
+ "./package.json": "./package.json",
29
+ ".": {
30
+ "types": "./dist/index.d.mts",
31
+ "import": "./dist/index.mjs",
32
+ "default": "./dist/index.mjs"
33
+ },
34
+ "./workflow": {
35
+ "types": "./dist/workflow.d.mts",
36
+ "import": "./dist/workflow.mjs",
37
+ "default": "./dist/workflow.mjs"
38
+ },
39
+ "./effect": {
40
+ "types": "./dist/effect.d.mts",
41
+ "import": "./dist/effect.mjs",
42
+ "default": "./dist/effect.mjs"
43
+ },
44
+ "./testing": {
45
+ "types": "./dist/testing/index.d.mts",
46
+ "import": "./dist/testing/index.mjs",
47
+ "default": "./dist/testing/index.mjs"
48
+ }
49
+ },
50
+ "files": [
51
+ "src/**/*.ts",
52
+ "!src/**/*.test.ts",
53
+ "!src/**/*.test.tsx",
54
+ "dist/**/*",
55
+ "README.md"
56
+ ],
57
+ "publishConfig": {
58
+ "access": "public",
59
+ "provenance": true
60
+ },
61
+ "dependencies": {
62
+ "effect": "4.0.0",
63
+ "workflow": "^5.0.0-beta.42"
64
+ },
65
+ "devDependencies": {
66
+ "@effect/vitest": "4.0.0",
67
+ "@workflow/vitest": "^5.0.0-beta.42",
68
+ "vitest": "^5.0.1"
69
+ },
70
+ "scripts": {
71
+ "build": "tsdown",
72
+ "check": "tsc -p tsconfig.json --noEmit",
73
+ "test": "vitest run --passWithNoTests",
74
+ "test:workflow": "vitest run --config vitest.workflow.config.ts",
75
+ "test:run": "vitest run --passWithNoTests"
76
+ }
77
+ }
package/src/effect.ts ADDED
@@ -0,0 +1,232 @@
1
+ import { Context, Data, Effect, Layer } from 'effect'
2
+ import {
3
+ getRun as workflowGetRun,
4
+ resumeHook as workflowResumeHook,
5
+ start as workflowStart,
6
+ type WorkflowReadableStream,
7
+ type WorkflowReadableStreamOptions,
8
+ type WorkflowRun
9
+ } from 'workflow/api'
10
+
11
+ export type VercelWorkflowsOperation =
12
+ | 'start'
13
+ | 'getRun'
14
+ | 'getReadable'
15
+ | 'tailIndex'
16
+ | 'resumeHook'
17
+ | 'cancel'
18
+ | 'status'
19
+ | 'returnValue'
20
+
21
+ export class VercelWorkflowsError extends Data.TaggedError('VercelWorkflowsError')<{
22
+ readonly operation: VercelWorkflowsOperation
23
+ readonly message: string
24
+ readonly cause: unknown
25
+ }> {}
26
+
27
+ export type VercelWorkflowFunction<TArgs extends unknown[], TResult> = (
28
+ ...args: TArgs
29
+ ) => Promise<TResult>
30
+
31
+ export type VercelWorkflowReadableOptions = WorkflowReadableStreamOptions
32
+
33
+ export type VercelWorkflowReadableStream<Chunk> = WorkflowReadableStream<Chunk>
34
+
35
+ export type VercelWorkflowRunStatus = WorkflowRun['status']
36
+
37
+ export type VercelWorkflowsSdkRun<TResult> = {
38
+ readonly runId: string
39
+ readonly getReadable: <Chunk>(
40
+ options?: VercelWorkflowReadableOptions
41
+ ) => VercelWorkflowReadableStream<Chunk>
42
+ readonly cancel: () => Promise<void>
43
+ readonly status: Promise<VercelWorkflowRunStatus>
44
+ readonly returnValue: Promise<TResult>
45
+ }
46
+
47
+ export type VercelWorkflowsSdkClient = {
48
+ readonly start: <TArgs extends unknown[], TResult>(
49
+ workflow: VercelWorkflowFunction<TArgs, TResult>,
50
+ args: TArgs
51
+ ) => Promise<VercelWorkflowsSdkRun<TResult>>
52
+ readonly getRun: <TResult>(runId: string) => VercelWorkflowsSdkRun<TResult>
53
+ readonly resumeHook: (token: string, payload: unknown) => Promise<void>
54
+ }
55
+
56
+ export type VercelWorkflowRun<TResult> = {
57
+ readonly runId: string
58
+ readonly getReadable: <Chunk>(
59
+ options?: VercelWorkflowReadableOptions
60
+ ) => Effect.Effect<VercelWorkflowReadableStream<Chunk>, VercelWorkflowsError>
61
+ readonly cancel: Effect.Effect<void, VercelWorkflowsError>
62
+ readonly status: Effect.Effect<VercelWorkflowRunStatus, VercelWorkflowsError>
63
+ readonly returnValue: Effect.Effect<TResult, VercelWorkflowsError>
64
+ }
65
+
66
+ export type VercelWorkflowsClient = {
67
+ readonly start: <TArgs extends unknown[], TResult>(
68
+ workflow: VercelWorkflowFunction<TArgs, TResult>,
69
+ args: TArgs
70
+ ) => Effect.Effect<VercelWorkflowRun<TResult>, VercelWorkflowsError>
71
+ readonly getRun: <TResult>(
72
+ runId: string
73
+ ) => Effect.Effect<VercelWorkflowRun<TResult>, VercelWorkflowsError>
74
+ readonly getReadable: <Chunk>(
75
+ runId: string,
76
+ options?: VercelWorkflowReadableOptions
77
+ ) => Effect.Effect<VercelWorkflowReadableStream<Chunk>, VercelWorkflowsError>
78
+ readonly tailIndex: (runId: string) => Effect.Effect<number, VercelWorkflowsError>
79
+ readonly resumeHook: (
80
+ token: string,
81
+ payload: unknown
82
+ ) => Effect.Effect<void, VercelWorkflowsError>
83
+ readonly cancel: (runId: string) => Effect.Effect<void, VercelWorkflowsError>
84
+ }
85
+
86
+ export class VercelWorkflowsSdk extends Context.Service<
87
+ VercelWorkflowsSdk,
88
+ VercelWorkflowsSdkClient
89
+ >()('@yolk-sdk/vercel-workflows/VercelWorkflowsSdk') {}
90
+
91
+ const workflowsError = (operation: VercelWorkflowsOperation, cause: unknown) =>
92
+ new VercelWorkflowsError({
93
+ operation,
94
+ message: `Vercel Workflow ${operation} failed`,
95
+ cause
96
+ })
97
+
98
+ const spanAttributes = (runId: string) => ({ 'workflow.run.id': runId })
99
+
100
+ const trySdkPromise = <A>(body: () => Promise<A>) =>
101
+ Effect.tryPromise({
102
+ try: body,
103
+ catch: error => error
104
+ })
105
+
106
+ const mapSdkError =
107
+ (operation: VercelWorkflowsOperation) =>
108
+ <A>(effect: Effect.Effect<A, unknown>) =>
109
+ effect.pipe(Effect.mapError(cause => workflowsError(operation, cause)))
110
+
111
+ const makeWorkflowRun = <TResult>(
112
+ run: VercelWorkflowsSdkRun<TResult>
113
+ ): VercelWorkflowRun<TResult> => ({
114
+ runId: run.runId,
115
+ getReadable: <Chunk>(options?: VercelWorkflowReadableOptions) =>
116
+ Effect.try({
117
+ try: () => run.getReadable<Chunk>(options),
118
+ catch: cause => workflowsError('getReadable', cause)
119
+ }).pipe(
120
+ Effect.withSpan('VercelWorkflows.run.getReadable', {
121
+ attributes: spanAttributes(run.runId)
122
+ })
123
+ ),
124
+ cancel: trySdkPromise(() => run.cancel()).pipe(
125
+ mapSdkError('cancel'),
126
+ Effect.withSpan('VercelWorkflows.run.cancel', {
127
+ attributes: spanAttributes(run.runId)
128
+ })
129
+ ),
130
+ status: trySdkPromise(() => run.status).pipe(
131
+ mapSdkError('status'),
132
+ Effect.withSpan('VercelWorkflows.run.status', {
133
+ attributes: spanAttributes(run.runId)
134
+ })
135
+ ),
136
+ returnValue: trySdkPromise(() => run.returnValue).pipe(
137
+ mapSdkError('returnValue'),
138
+ Effect.withSpan('VercelWorkflows.run.returnValue', {
139
+ attributes: spanAttributes(run.runId)
140
+ })
141
+ )
142
+ })
143
+
144
+ const VercelWorkflowsSdkLive = Layer.succeed(VercelWorkflowsSdk, {
145
+ start: <TArgs extends unknown[], TResult>(
146
+ workflow: VercelWorkflowFunction<TArgs, TResult>,
147
+ args: TArgs
148
+ ) => workflowStart(workflow, args),
149
+ getRun: <TResult>(runId: string) => workflowGetRun<TResult>(runId),
150
+ resumeHook: async (token: string, payload: unknown) => {
151
+ await workflowResumeHook<unknown>(token, payload)
152
+ }
153
+ })
154
+
155
+ export class VercelWorkflows extends Context.Service<VercelWorkflows, VercelWorkflowsClient>()(
156
+ '@yolk-sdk/vercel-workflows/VercelWorkflows',
157
+ {
158
+ make: Effect.gen(function* () {
159
+ const sdk = yield* VercelWorkflowsSdk
160
+
161
+ const getRun = <TResult>(
162
+ runId: string
163
+ ): Effect.Effect<VercelWorkflowRun<TResult>, VercelWorkflowsError> =>
164
+ Effect.try({
165
+ try: () => sdk.getRun<TResult>(runId),
166
+ catch: error => error
167
+ }).pipe(
168
+ mapSdkError('getRun'),
169
+ Effect.map(makeWorkflowRun),
170
+ Effect.withSpan('VercelWorkflows.getRun', {
171
+ attributes: spanAttributes(runId)
172
+ })
173
+ )
174
+
175
+ return {
176
+ start: <TArgs extends unknown[], TResult>(
177
+ workflow: VercelWorkflowFunction<TArgs, TResult>,
178
+ args: TArgs
179
+ ): Effect.Effect<VercelWorkflowRun<TResult>, VercelWorkflowsError> =>
180
+ trySdkPromise(() => sdk.start(workflow, args)).pipe(
181
+ mapSdkError('start'),
182
+ Effect.map(makeWorkflowRun),
183
+ Effect.withSpan('VercelWorkflows.start')
184
+ ),
185
+
186
+ getRun,
187
+
188
+ getReadable: <Chunk>(
189
+ runId: string,
190
+ options?: VercelWorkflowReadableOptions
191
+ ): Effect.Effect<VercelWorkflowReadableStream<Chunk>, VercelWorkflowsError> =>
192
+ getRun<unknown>(runId).pipe(
193
+ Effect.flatMap(run => run.getReadable<Chunk>(options)),
194
+ Effect.withSpan('VercelWorkflows.getReadable', {
195
+ attributes: spanAttributes(runId)
196
+ })
197
+ ),
198
+
199
+ tailIndex: (runId: string): Effect.Effect<number, VercelWorkflowsError> =>
200
+ getRun<unknown>(runId).pipe(
201
+ Effect.flatMap(run => run.getReadable<unknown>({ startIndex: -1 })),
202
+ Effect.flatMap(readable =>
203
+ Effect.tryPromise({
204
+ try: () => readable.getTailIndex(),
205
+ catch: cause => workflowsError('tailIndex', cause)
206
+ })
207
+ ),
208
+ Effect.withSpan('VercelWorkflows.tailIndex', {
209
+ attributes: spanAttributes(runId)
210
+ })
211
+ ),
212
+
213
+ resumeHook: (token: string, payload: unknown): Effect.Effect<void, VercelWorkflowsError> =>
214
+ trySdkPromise(() => sdk.resumeHook(token, payload)).pipe(
215
+ mapSdkError('resumeHook'),
216
+ Effect.withSpan('VercelWorkflows.resumeHook')
217
+ ),
218
+
219
+ cancel: (runId: string): Effect.Effect<void, VercelWorkflowsError> =>
220
+ getRun<unknown>(runId).pipe(
221
+ Effect.flatMap(run => run.cancel),
222
+ Effect.withSpan('VercelWorkflows.cancel', {
223
+ attributes: spanAttributes(runId)
224
+ })
225
+ )
226
+ }
227
+ })
228
+ }
229
+ ) {
230
+ static layer = Layer.effect(this, this.make).pipe(Layer.provide(VercelWorkflowsSdkLive))
231
+ static layerFromSdk = Layer.effect(this, this.make)
232
+ }
package/src/index.ts ADDED
@@ -0,0 +1,36 @@
1
+ export {
2
+ commitThenWriteTerminalEvent,
3
+ durableAgentEventId,
4
+ defaultMaxWorkflowTurns,
5
+ makeDurableAgentEventSequencerState,
6
+ noWorkflowStepRetry,
7
+ retryWorkflowStep,
8
+ runVercelAgentWorkflow,
9
+ sequenceDurableAgentEvent,
10
+ settleWorkflowStep,
11
+ VercelAgentWorkflowRunResult,
12
+ WorkflowStepResult,
13
+ writeDurableAgentEvent
14
+ } from './workflow.ts'
15
+
16
+ export type {
17
+ CommitThenWriteTerminalEventInput,
18
+ CommitThenWriteTerminalEventResult,
19
+ DurableAgentEvent,
20
+ DurableAgentEventIdInput,
21
+ DurableAgentEventSequencerState,
22
+ SequenceDurableAgentEventInput,
23
+ SequencedDurableAgentEvent,
24
+ SerializableWorkflowState,
25
+ VercelAgentWorkflowAwaitingInput,
26
+ VercelAgentWorkflowInput,
27
+ VercelAgentWorkflowLoopConfig,
28
+ VercelAgentWorkflowModelStepInput,
29
+ VercelAgentWorkflowModelStepResult,
30
+ VercelAgentWorkflowStepRetryPolicy,
31
+ VercelAgentWorkflowToolBatchStepInput,
32
+ VercelAgentWorkflowToolBatchStepResult,
33
+ WriteDurableAgentEventInput
34
+ } from './workflow.ts'
35
+
36
+ export { awaitWorkflowChild, orchestrateWorkflowToolBatch } from './workflow-children.ts'