diff --git a/packages/workflow-runtime/src/bundle/index.ts b/packages/workflow-runtime/src/bundle/index.ts deleted file mode 100644 index 6a2f60d..0000000 --- a/packages/workflow-runtime/src/bundle/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export type { WorkflowDescriptor, WorkflowRoleDescriptor, WorkflowRoleSchema } from "./types.js"; -export { validateWorkflowDescriptor } from "./workflow-descriptor.js"; diff --git a/packages/workflow-runtime/src/bundle/types.ts b/packages/workflow-runtime/src/bundle/types.ts deleted file mode 100644 index a1b4478..0000000 --- a/packages/workflow-runtime/src/bundle/types.ts +++ /dev/null @@ -1,13 +0,0 @@ -/** JSON Schema fragment describing one role's `meta` shape (subset supported by code generation). */ -export type WorkflowRoleSchema = Record; - -export type WorkflowRoleDescriptor = { - description: string; - schema: WorkflowRoleSchema; -}; - -/** Workflow metadata exported as `export const descriptor` from `.esm.js` bundles. */ -export type WorkflowDescriptor = { - description: string; - roles: Record; -}; diff --git a/packages/workflow-runtime/src/bundle/workflow-descriptor.ts b/packages/workflow-runtime/src/bundle/workflow-descriptor.ts deleted file mode 100644 index e21851b..0000000 --- a/packages/workflow-runtime/src/bundle/workflow-descriptor.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { err, ok, type Result } from "../util/index.js"; - -import type { WorkflowDescriptor, WorkflowRoleDescriptor, WorkflowRoleSchema } from "./types.js"; - -export function validateWorkflowDescriptor(value: unknown): Result { - if (value === null || typeof value !== "object" || Array.isArray(value)) { - return err("descriptor must be a non-array object"); - } - const root = value as Record; - const description = root.description; - if (typeof description !== "string") { - return err("descriptor.description must be a string"); - } - const rolesRaw = root.roles; - if (rolesRaw === null || typeof rolesRaw !== "object" || Array.isArray(rolesRaw)) { - return err("descriptor.roles must be a non-array object"); - } - - const roles: Record = {}; - for (const [roleName, specUnknown] of Object.entries(rolesRaw)) { - if (specUnknown === null || typeof specUnknown !== "object" || Array.isArray(specUnknown)) { - return err(`descriptor.roles.${roleName} must be a non-array object`); - } - const spec = specUnknown as Record; - const roleDesc = spec.description; - if (typeof roleDesc !== "string") { - return err(`descriptor.roles.${roleName}.description must be a string`); - } - const schema = spec.schema; - if (schema === null || typeof schema !== "object" || Array.isArray(schema)) { - return err(`descriptor.roles.${roleName}.schema must be a non-array object`); - } - roles[roleName] = { - description: roleDesc, - schema: schema as WorkflowRoleSchema, - }; - } - - return ok({ description, roles }); -} diff --git a/packages/workflow-runtime/src/cas/index.ts b/packages/workflow-runtime/src/cas/index.ts deleted file mode 100644 index 5bfc042..0000000 --- a/packages/workflow-runtime/src/cas/index.ts +++ /dev/null @@ -1 +0,0 @@ -export type { CasStore } from "./types.js"; diff --git a/packages/workflow-runtime/src/cas/types.ts b/packages/workflow-runtime/src/cas/types.ts deleted file mode 100644 index 2be4d74..0000000 --- a/packages/workflow-runtime/src/cas/types.ts +++ /dev/null @@ -1,6 +0,0 @@ -export type CasStore = { - put(content: string): Promise; - get(hash: string): Promise; - delete(hash: string): Promise; - list(): Promise; -}; diff --git a/packages/workflow-runtime/src/engine/create-workflow.ts b/packages/workflow-runtime/src/create-workflow.ts similarity index 93% rename from packages/workflow-runtime/src/engine/create-workflow.ts rename to packages/workflow-runtime/src/create-workflow.ts index 186cf26..a899edd 100644 --- a/packages/workflow-runtime/src/engine/create-workflow.ts +++ b/packages/workflow-runtime/src/create-workflow.ts @@ -1,10 +1,10 @@ import type * as z from "zod/v4"; -import type { CasStore } from "../cas/types.js"; import { type AgentBinding, type AgentContext, type AgentFn, + type CasStore, END, type ExtractContext, type ModeratorContext, @@ -18,8 +18,7 @@ import { type WorkflowDefinition, type WorkflowFn, type WorkflowRuntime, -} from "../types.js"; -import { mergeRefsWithContentHash } from "../util/index.js"; +} from "./types.js"; function isRoleNext( next: (keyof M & string) | typeof END, @@ -97,10 +96,11 @@ async function advanceOneRound( ); const contentHash = await putContentBlob(runtime.cas, raw); - const refs = mergeRefsWithContentHash( - resolveExtractedRefs(roleDef as unknown as RoleDefinition>, meta), - contentHash, + const refsFromMeta = resolveExtractedRefs( + roleDef as unknown as RoleDefinition>, + meta, ); + const refs = refsFromMeta.includes(contentHash) ? refsFromMeta : [...refsFromMeta, contentHash]; const step = { role: next, diff --git a/packages/workflow-runtime/src/engine/index.ts b/packages/workflow-runtime/src/engine/index.ts deleted file mode 100644 index 2b6e901..0000000 --- a/packages/workflow-runtime/src/engine/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { createWorkflow } from "./create-workflow.js"; diff --git a/packages/workflow-runtime/src/extract/index.ts b/packages/workflow-runtime/src/extract/index.ts deleted file mode 100644 index 02695ad..0000000 --- a/packages/workflow-runtime/src/extract/index.ts +++ /dev/null @@ -1 +0,0 @@ -export type { ExtractFn } from "./types.js"; diff --git a/packages/workflow-runtime/src/extract/types.ts b/packages/workflow-runtime/src/extract/types.ts deleted file mode 100644 index 6c04f01..0000000 --- a/packages/workflow-runtime/src/extract/types.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type * as z from "zod/v4"; - -import type { ExtractContext } from "../types.js"; - -export type ExtractFn = >( - schema: z.ZodType, - prompt: string, - ctx: ExtractContext, -) => Promise; diff --git a/packages/workflow-runtime/src/index.ts b/packages/workflow-runtime/src/index.ts index 2416179..c1f5c8b 100644 --- a/packages/workflow-runtime/src/index.ts +++ b/packages/workflow-runtime/src/index.ts @@ -1,20 +1,16 @@ -export type { - WorkflowDescriptor, - WorkflowRoleDescriptor, - WorkflowRoleSchema, -} from "./bundle/types.js"; -export { validateWorkflowDescriptor } from "./bundle/workflow-descriptor.js"; -export type { CasStore } from "./cas/index.js"; -export { createWorkflow } from "./engine/index.js"; -export type { ExtractFn } from "./extract/index.js"; +export { createWorkflow } from "./create-workflow.js"; +export { err, ok } from "./result.js"; export type { AgentBinding, AgentContext, AgentFn, + CasStore, ExtractContext, + ExtractFn, LlmProvider, Moderator, ModeratorContext, + Result, RoleDefinition, RoleMeta, RoleOutput, @@ -23,10 +19,11 @@ export type { ThreadContext, WorkflowCompletion, WorkflowDefinition, + WorkflowDescriptor, WorkflowFn, WorkflowResult, + WorkflowRoleDescriptor, + WorkflowRoleSchema, WorkflowRuntime, } from "./types.js"; export { END, START } from "./types.js"; -export type { Result } from "./util/index.js"; -export { err, ok } from "./util/index.js"; diff --git a/packages/workflow-runtime/src/util/result.ts b/packages/workflow-runtime/src/result.ts similarity index 100% rename from packages/workflow-runtime/src/util/result.ts rename to packages/workflow-runtime/src/result.ts diff --git a/packages/workflow-runtime/src/types.ts b/packages/workflow-runtime/src/types.ts index 1019132..c6f3f2c 100644 --- a/packages/workflow-runtime/src/types.ts +++ b/packages/workflow-runtime/src/types.ts @@ -1,12 +1,33 @@ import type * as z from "zod/v4"; -import type { CasStore } from "./cas/index.js"; -import type { ExtractFn } from "./extract/types.js"; - /** Sentinel values for automaton control flow. */ export const START = "__start__" as const; export const END = "__end__" as const; +export type CasStore = { + put(content: string): Promise; + get(hash: string): Promise; + delete(hash: string): Promise; + list(): Promise; +}; + +/** JSON Schema fragment describing one role's `meta` shape (subset supported by code generation). */ +export type WorkflowRoleSchema = Record; + +export type WorkflowRoleDescriptor = { + description: string; + schema: WorkflowRoleSchema; +}; + +/** Workflow metadata exported as `export const descriptor` from `.esm.js` bundles. */ +export type WorkflowDescriptor = { + description: string; + roles: Record; +}; + +/** Expected success/failure outcome without throwing for recoverable errors. */ +export type Result = { ok: true; value: T } | { ok: false; error: E }; + /** Maps role names → their meta types. Single generic drives all inference. */ export type RoleMeta = Record>; @@ -96,6 +117,12 @@ export type ExtractContext = AgentContext & { agentContent: string; }; +export type ExtractFn = >( + schema: z.ZodType, + prompt: string, + ctx: ExtractContext, +) => Promise; + /** Raw string output from an LLM/CLI adapter; meta is extracted by the engine. */ export type AgentFn = (ctx: AgentContext) => Promise; @@ -131,3 +158,8 @@ export type WorkflowDefinition = { roles: { [K in keyof M & string]: RoleDefinition }; moderator: Moderator; }; + +/** Internal outcome of advancing one moderator round inside {@link createWorkflow}. */ +export type AdvanceOutcome = + | { kind: "complete"; completion: WorkflowCompletion } + | { kind: "yield"; output: RoleOutput; step: RoleStep }; diff --git a/packages/workflow-runtime/src/util/index.ts b/packages/workflow-runtime/src/util/index.ts deleted file mode 100644 index 01b6b02..0000000 --- a/packages/workflow-runtime/src/util/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { mergeRefsWithContentHash } from "./refs-field.js"; -export { err, ok } from "./result.js"; -export type { Result } from "./types.js"; diff --git a/packages/workflow-runtime/src/util/refs-field.ts b/packages/workflow-runtime/src/util/refs-field.ts deleted file mode 100644 index 687d2d0..0000000 --- a/packages/workflow-runtime/src/util/refs-field.ts +++ /dev/null @@ -1,8 +0,0 @@ -/** Append `contentHash` to `refs` when not already present (dedupe by first occurrence order). */ -export function mergeRefsWithContentHash(refs: string[], contentHash: string): string[] { - const out = [...refs]; - if (!out.includes(contentHash)) { - out.push(contentHash); - } - return out; -} diff --git a/packages/workflow-runtime/src/util/types.ts b/packages/workflow-runtime/src/util/types.ts deleted file mode 100644 index 3a97ab3..0000000 --- a/packages/workflow-runtime/src/util/types.ts +++ /dev/null @@ -1 +0,0 @@ -export type Result = { ok: true; value: T } | { ok: false; error: E }; diff --git a/packages/workflow/src/bundle/workflow-descriptor.ts b/packages/workflow/src/bundle/workflow-descriptor.ts index fb586fa..e21851b 100644 --- a/packages/workflow/src/bundle/workflow-descriptor.ts +++ b/packages/workflow/src/bundle/workflow-descriptor.ts @@ -1 +1,40 @@ -export { validateWorkflowDescriptor } from "@uncaged/workflow-runtime"; +import { err, ok, type Result } from "../util/index.js"; + +import type { WorkflowDescriptor, WorkflowRoleDescriptor, WorkflowRoleSchema } from "./types.js"; + +export function validateWorkflowDescriptor(value: unknown): Result { + if (value === null || typeof value !== "object" || Array.isArray(value)) { + return err("descriptor must be a non-array object"); + } + const root = value as Record; + const description = root.description; + if (typeof description !== "string") { + return err("descriptor.description must be a string"); + } + const rolesRaw = root.roles; + if (rolesRaw === null || typeof rolesRaw !== "object" || Array.isArray(rolesRaw)) { + return err("descriptor.roles must be a non-array object"); + } + + const roles: Record = {}; + for (const [roleName, specUnknown] of Object.entries(rolesRaw)) { + if (specUnknown === null || typeof specUnknown !== "object" || Array.isArray(specUnknown)) { + return err(`descriptor.roles.${roleName} must be a non-array object`); + } + const spec = specUnknown as Record; + const roleDesc = spec.description; + if (typeof roleDesc !== "string") { + return err(`descriptor.roles.${roleName}.description must be a string`); + } + const schema = spec.schema; + if (schema === null || typeof schema !== "object" || Array.isArray(schema)) { + return err(`descriptor.roles.${roleName}.schema must be a non-array object`); + } + roles[roleName] = { + description: roleDesc, + schema: schema as WorkflowRoleSchema, + }; + } + + return ok({ description, roles }); +}