refactor(workflow): unify extraction behind ExtractFn
Route createExtract through reactExtract with plain-JSON correction retry. Remove WorkflowFnOptions.llmProvider, ExtractMode, RoleDefinition.extractMode, ResolveRoleMetaFn. Runtime createWorkflow calls options.extract directly; engine passes extract only. Update templates, CLI skill docs, and tests. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
import type * as z from "zod/v4";
|
||||
|
||||
import type { CasStore } from "../cas/types.js";
|
||||
import {
|
||||
type AgentBinding,
|
||||
@@ -6,7 +8,6 @@ import {
|
||||
END,
|
||||
type ExtractContext,
|
||||
type ModeratorContext,
|
||||
type ResolveRoleMetaFn,
|
||||
type RoleDefinition,
|
||||
type RoleMeta,
|
||||
type RoleOutput,
|
||||
@@ -55,7 +56,6 @@ type AdvanceOutcome<M extends RoleMeta> =
|
||||
async function advanceOneRound<M extends RoleMeta>(
|
||||
def: Pick<WorkflowDefinition<M>, "roles" | "moderator">,
|
||||
binding: AgentBinding,
|
||||
resolveRoleMeta: ResolveRoleMetaFn<M>,
|
||||
params: {
|
||||
start: ModeratorContext<M>["start"];
|
||||
steps: RoleStep<M>[];
|
||||
@@ -97,10 +97,10 @@ async function advanceOneRound<M extends RoleMeta>(
|
||||
agentContent: raw,
|
||||
};
|
||||
|
||||
const meta = await resolveRoleMeta(
|
||||
roleDef as unknown as RoleDefinition<Record<string, unknown>>,
|
||||
extractCtx,
|
||||
options,
|
||||
const meta = await options.extract(
|
||||
roleDef.schema as unknown as z.ZodType<Record<string, unknown>>,
|
||||
roleDef.extractPrompt,
|
||||
extractCtx as unknown as ExtractContext,
|
||||
);
|
||||
|
||||
const contentHash = await putContentBlob(options.cas, raw);
|
||||
@@ -131,13 +131,14 @@ async function advanceOneRound<M extends RoleMeta>(
|
||||
|
||||
/**
|
||||
* Binds pure role definitions + moderator to runtime agents.
|
||||
* Assign with `export const run = createWorkflow(def, binding)` via `@uncaged/workflow-runtime`,
|
||||
* which supplies {@link ResolveRoleMetaFn}.
|
||||
* Assign with `export const run = createWorkflow(def, binding)`.
|
||||
*
|
||||
* Structured meta extraction is delegated to {@link WorkflowFnOptions.extract}, which the
|
||||
* engine resolves from the workflow registry's `extract` scene.
|
||||
*/
|
||||
export function createWorkflow<M extends RoleMeta>(
|
||||
def: Pick<WorkflowDefinition<M>, "roles" | "moderator">,
|
||||
binding: AgentBinding,
|
||||
resolveRoleMeta: ResolveRoleMetaFn<M>,
|
||||
): WorkflowFn {
|
||||
return async function* workflowLoop(
|
||||
input: ThreadInput,
|
||||
@@ -168,7 +169,7 @@ export function createWorkflow<M extends RoleMeta>(
|
||||
};
|
||||
}
|
||||
|
||||
const outcome = await advanceOneRound(def, binding, resolveRoleMeta, {
|
||||
const outcome = await advanceOneRound(def, binding, {
|
||||
start,
|
||||
steps,
|
||||
options,
|
||||
|
||||
@@ -12,11 +12,9 @@ export type {
|
||||
AgentContext,
|
||||
AgentFn,
|
||||
ExtractContext,
|
||||
ExtractMode,
|
||||
LlmProvider,
|
||||
Moderator,
|
||||
ModeratorContext,
|
||||
ResolveRoleMetaFn,
|
||||
RoleDefinition,
|
||||
RoleMeta,
|
||||
RoleOutput,
|
||||
|
||||
@@ -17,9 +17,6 @@ export type LlmProvider = {
|
||||
model: string;
|
||||
};
|
||||
|
||||
/** How the engine runs meta extraction for a role after the agent phase. */
|
||||
export type ExtractMode = "single" | "react";
|
||||
|
||||
/** What each generator yield produces — one role's output (engine adds `timestamp` when persisting). */
|
||||
export type RoleOutput = {
|
||||
role: string;
|
||||
@@ -57,8 +54,6 @@ export type WorkflowFnOptions = {
|
||||
cas: CasStore;
|
||||
/** Structured meta extraction; resolved from workflow.yaml `extract` scene by the engine. */
|
||||
extract: ExtractFn;
|
||||
/** Provider for `extractMode: "react"` roles; same backing config as `extract`. */
|
||||
llmProvider: LlmProvider | null;
|
||||
};
|
||||
|
||||
/** Bundle contract — named export `run` is a function returning an AsyncGenerator. */
|
||||
@@ -129,7 +124,6 @@ export type RoleDefinition<Meta extends Record<string, unknown>> = {
|
||||
schema: z.ZodType<Meta>;
|
||||
/** When non-null, produces CAS hashes to persist on this role's steps (see `RoleOutput.refs`). */
|
||||
extractRefs: ((meta: Meta) => string[]) | null;
|
||||
extractMode: ExtractMode;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -148,10 +142,3 @@ export type WorkflowDefinition<M extends RoleMeta> = {
|
||||
roles: { [K in keyof M & string]: RoleDefinition<M[K]> };
|
||||
moderator: Moderator<M>;
|
||||
};
|
||||
|
||||
/** Engine-injected meta extraction for workflow loops (single + react modes). */
|
||||
export type ResolveRoleMetaFn<M extends RoleMeta = RoleMeta> = (
|
||||
roleDef: RoleDefinition<Record<string, unknown>>,
|
||||
extractCtx: ExtractContext<M>,
|
||||
options: WorkflowFnOptions,
|
||||
) => Promise<Record<string, unknown>>;
|
||||
|
||||
Reference in New Issue
Block a user