diff --git a/packages/workflow-agent-cursor/tsconfig.json b/packages/workflow-agent-cursor/tsconfig.json index d9141ff..c9b8393 100644 --- a/packages/workflow-agent-cursor/tsconfig.json +++ b/packages/workflow-agent-cursor/tsconfig.json @@ -6,5 +6,9 @@ "composite": true }, "include": ["src/**/*.ts"], - "references": [{ "path": "../workflow-runtime" }, { "path": "../workflow-util-agent" }] + "references": [ + { "path": "../workflow-cas" }, + { "path": "../workflow-runtime" }, + { "path": "../workflow-util-agent" } + ] } diff --git a/packages/workflow-cas/tsconfig.json b/packages/workflow-cas/tsconfig.json index 27c4bed..b852fc3 100644 --- a/packages/workflow-cas/tsconfig.json +++ b/packages/workflow-cas/tsconfig.json @@ -2,7 +2,8 @@ "extends": "../../tsconfig.json", "compilerOptions": { "rootDir": "src", - "outDir": "dist" + "outDir": "dist", + "composite": true }, "include": ["src"], "references": [{ "path": "../workflow-protocol" }, { "path": "../workflow-util" }] diff --git a/packages/workflow-protocol/src/index.ts b/packages/workflow-protocol/src/index.ts index 1276383..9e30a79 100644 --- a/packages/workflow-protocol/src/index.ts +++ b/packages/workflow-protocol/src/index.ts @@ -13,6 +13,7 @@ export type { AdapterFn, AdvanceOutcome, AgentContext, + AgentFn, CasStore, ExtractFn, ExtractResult, diff --git a/packages/workflow-protocol/src/types.ts b/packages/workflow-protocol/src/types.ts index 72b2a0f..3f3a7ad 100644 --- a/packages/workflow-protocol/src/types.ts +++ b/packages/workflow-protocol/src/types.ts @@ -151,6 +151,15 @@ export type RoleFn = (ctx: ThreadContext, runtime: WorkflowRuntime) => Promis export type AdapterFn = (prompt: string, schema: z.ZodType) => RoleFn; +/** + * Core agent function. Input is always {@link ThreadContext}, output is always string. + * `Opt` captures agent-specific structured options. + * Agents with no extra options use `AgentFn` (Opt defaults to void). + */ +export type AgentFn = Opt extends void + ? (ctx: ThreadContext) => Promise + : (ctx: ThreadContext, options: Opt) => Promise; + export type AdapterBinding = { adapter: AdapterFn; overrides: Partial> | null; diff --git a/packages/workflow-runtime/src/index.ts b/packages/workflow-runtime/src/index.ts index bdaef83..3a751f1 100644 --- a/packages/workflow-runtime/src/index.ts +++ b/packages/workflow-runtime/src/index.ts @@ -5,6 +5,7 @@ export type { AdapterBinding, AdapterFn, AgentContext, + AgentFn, CasStore, ExtractFn, ExtractResult, diff --git a/packages/workflow-runtime/src/types.ts b/packages/workflow-runtime/src/types.ts index d78a9d2..bf73d7d 100644 --- a/packages/workflow-runtime/src/types.ts +++ b/packages/workflow-runtime/src/types.ts @@ -7,6 +7,7 @@ export type { AdapterFn, AdvanceOutcome, AgentContext, + AgentFn, CasStore, ExtractFn, ExtractResult, diff --git a/packages/workflow-util-agent/src/create-agent-adapter.ts b/packages/workflow-util-agent/src/create-agent-adapter.ts new file mode 100644 index 0000000..a7e1fe3 --- /dev/null +++ b/packages/workflow-util-agent/src/create-agent-adapter.ts @@ -0,0 +1,48 @@ +import { putContentNodeWithRefs } from "@uncaged/workflow-cas"; +import type { + AdapterFn, + AgentFn, + RoleResult, + ThreadContext, + WorkflowRuntime, +} from "@uncaged/workflow-runtime"; +import type * as z from "zod/v4"; + +export type ExtractOptionsFn = ( + ctx: ThreadContext, + prompt: string, + runtime: WorkflowRuntime, +) => Promise; + +/** + * Bridges {@link AgentFn} to {@link AdapterFn}. + * + * 1. extract(ctx, prompt, runtime) → Opt + * 2. agent(ctx, options) → raw string + * 3. Store raw string in CAS + * 4. runtime.extract(schema, contentHash) → typed meta T + */ +export function createAgentAdapter( + agent: AgentFn, + extract: ExtractOptionsFn, +): AdapterFn { + return (prompt: string, schema: z.ZodType) => { + return async (ctx: ThreadContext, runtime: WorkflowRuntime): Promise> => { + const options = await extract(ctx, prompt, runtime); + const raw = await (agent as (ctx: ThreadContext, optionsParam: Opt) => Promise)( + ctx, + options, + ); + const contentHash = await putContentNodeWithRefs(runtime.cas, raw, []); + const extracted = await runtime.extract( + schema as z.ZodType>, + contentHash, + ); + return { meta: extracted.meta as T, childThread: null }; + }; + }; +} + +export function createSimpleAgentAdapter(agent: AgentFn): AdapterFn { + return createAgentAdapter(agent, async () => undefined as unknown as undefined); +} diff --git a/packages/workflow-util-agent/src/index.ts b/packages/workflow-util-agent/src/index.ts index a0b04f5..f65afd2 100644 --- a/packages/workflow-util-agent/src/index.ts +++ b/packages/workflow-util-agent/src/index.ts @@ -1,4 +1,6 @@ export { buildAgentPrompt, buildThreadInput } from "./build-agent-prompt.js"; +export type { ExtractOptionsFn } from "./create-agent-adapter.js"; +export { createAgentAdapter, createSimpleAgentAdapter } from "./create-agent-adapter.js"; export type { TextAdapterResult, TextProducerFn } from "./create-text-adapter.js"; export { createTextAdapter } from "./create-text-adapter.js"; export type { SpawnCliConfig, SpawnCliError, SpawnCliResult } from "./spawn-cli.js";