diff --git a/packages/cli-workflow/__tests__/commands.test.ts b/packages/cli-workflow/__tests__/commands.test.ts index bc2d8e6..23d9a83 100644 --- a/packages/cli-workflow/__tests__/commands.test.ts +++ b/packages/cli-workflow/__tests__/commands.test.ts @@ -20,9 +20,6 @@ import { addCliArgs } from "./bundle-fixture.js"; const fixtureDescriptor = `export const descriptor = { description: "fixture", roles: {}, graph: { edges: [] } }; `; -const wfPutImport = `import { putContentMerkleNode } from "@uncaged/workflow-cas"; -`; - function casStoredForm(raw: string): string { return serializeMerkleNode(createContentMerkleNode(raw)); } @@ -52,12 +49,12 @@ describe("cli workflow commands", () => { const bundlePath = join(bundleDir, "demo.esm.js"); await writeFile( bundlePath, - `${fixtureDescriptor}${wfPutImport}import fs from "node:fs"; + `${fixtureDescriptor}import fs from "node:fs"; export const run = async function* (input, options) { fs.existsSync("."); const cas = options.cas; - const h = await putContentMerkleNode(cas, input.prompt); + const h = await cas.put(input.prompt); yield { role: "noop", contentHash: h, meta: { done: true }, refs: [h] }; return { returnCode: 0, summary: "done" }; } @@ -155,10 +152,9 @@ export const run = async function* (input) { return { returnCode: 0, summary: in }, graph: { edges: [] }, }; -${wfPutImport} export const run = async function* (input, options) { const cas = options.cas; - const h = await putContentMerkleNode(cas, input.prompt); + const h = await cas.put( input.prompt); yield { role: "greeter", contentHash: h, meta: { greeting: "hi" }, refs: [h] }; return { returnCode: 0, summary: "ok" }; }; @@ -197,9 +193,9 @@ export const run = async function* (input, options) { const bundlePath = join(bundleDir, "demo.esm.js"); await writeFile( bundlePath, - `${fixtureDescriptor}${wfPutImport}export const run = async function* (_input, options) { + `${fixtureDescriptor}export const run = async function* (_input, options) { const cas = options.cas; - const h = await putContentMerkleNode(cas, "x"); + const h = await cas.put( "x"); yield { role: "a", contentHash: h, meta: {}, refs: [h] }; return { returnCode: 0, summary: "x" }; } @@ -228,9 +224,9 @@ export const run = async function* (input, options) { const dtsPath = join(bundleDir, "types.d.ts"); await writeFile( bundlePath, - `${fixtureDescriptor}${wfPutImport}export const run = async function* (_input, options) { + `${fixtureDescriptor}export const run = async function* (_input, options) { const cas = options.cas; - const h = await putContentMerkleNode(cas, "x"); + const h = await cas.put( "x"); yield { role: "a", contentHash: h, meta: {}, refs: [h] }; return { returnCode: 0, summary: "x" }; } @@ -261,9 +257,9 @@ export const run = async function* (input, options) { const bundlePath = join(bundleDir, "demo.esm.js"); await writeFile( bundlePath, - `${fixtureDescriptor}${wfPutImport}export const run = async function* (_input, options) { + `${fixtureDescriptor}export const run = async function* (_input, options) { const cas = options.cas; - const h = await putContentMerkleNode(cas, "x"); + const h = await cas.put( "x"); yield { role: "a", contentHash: h, meta: {}, refs: [h] }; return { returnCode: 0, summary: "x" }; } @@ -284,16 +280,16 @@ export const run = async function* (input, options) { const bundleDir = join(storageRoot, "src"); await mkdir(bundleDir, { recursive: true }); const bundlePath = join(bundleDir, "demo.esm.js"); - const v1 = `${fixtureDescriptor}${wfPutImport}export const run = async function* (_input, options) { + const v1 = `${fixtureDescriptor}export const run = async function* (_input, options) { const cas = options.cas; - const h = await putContentMerkleNode(cas, "v1"); + const h = await cas.put( "v1"); yield { role: "a", contentHash: h, meta: {}, refs: [h] }; return { returnCode: 0, summary: "v1" }; } `; - const v2 = `${fixtureDescriptor}${wfPutImport}export const run = async function* (_input, options) { + const v2 = `${fixtureDescriptor}export const run = async function* (_input, options) { const cas = options.cas; - const h = await putContentMerkleNode(cas, "v2"); + const h = await cas.put( "v2"); yield { role: "a", contentHash: h, meta: {}, refs: [h] }; return { returnCode: 0, summary: "v2" }; } @@ -326,16 +322,16 @@ export const run = async function* (input, options) { const bundleDir = join(storageRoot, "src"); await mkdir(bundleDir, { recursive: true }); const bundlePath = join(bundleDir, "demo.esm.js"); - const v1 = `${fixtureDescriptor}${wfPutImport}export const run = async function* (_input, options) { + const v1 = `${fixtureDescriptor}export const run = async function* (_input, options) { const cas = options.cas; - const h = await putContentMerkleNode(cas, "v1"); + const h = await cas.put( "v1"); yield { role: "a", contentHash: h, meta: {}, refs: [h] }; return { returnCode: 0, summary: "v1" }; } `; - const v2 = `${fixtureDescriptor}${wfPutImport}export const run = async function* (_input, options) { + const v2 = `${fixtureDescriptor}export const run = async function* (_input, options) { const cas = options.cas; - const h = await putContentMerkleNode(cas, "v2"); + const h = await cas.put( "v2"); yield { role: "a", contentHash: h, meta: {}, refs: [h] }; return { returnCode: 0, summary: "v2" }; } @@ -378,9 +374,9 @@ export const run = async function* (input, options) { const bundlePath = join(bundleDir, "demo.esm.js"); await writeFile( bundlePath, - `${fixtureDescriptor}${wfPutImport}export const run = async function* (_input, options) { + `${fixtureDescriptor}export const run = async function* (_input, options) { const cas = options.cas; - const h = await putContentMerkleNode(cas, "x"); + const h = await cas.put( "x"); yield { role: "a", contentHash: h, meta: {}, refs: [h] }; return { returnCode: 0, summary: "x" }; } @@ -391,9 +387,9 @@ export const run = async function* (input, options) { expect(add1.ok).toBe(true); await writeFile( bundlePath, - `${fixtureDescriptor}${wfPutImport}export const run = async function* (_input, options) { + `${fixtureDescriptor}export const run = async function* (_input, options) { const cas = options.cas; - const h = await putContentMerkleNode(cas, "y"); + const h = await cas.put( "y"); yield { role: "a", contentHash: h, meta: {}, refs: [h] }; return { returnCode: 0, summary: "y" }; } @@ -446,9 +442,9 @@ export const run = async function* (input, options) { const bundlePath = join(bundleDir, "demo.esm.js"); await writeFile( bundlePath, - `${fixtureDescriptor}${wfPutImport}export const run = async function* (_input, options) { + `${fixtureDescriptor}export const run = async function* (_input, options) { const cas = options.cas; - const h = await putContentMerkleNode(cas, "x"); + const h = await cas.put( "x"); yield { role: "a", contentHash: h, meta: {}, refs: [h] }; return { returnCode: 0, summary: "x" }; } @@ -463,9 +459,9 @@ export const run = async function* (input, options) { const hash1 = add1.value.hash; await writeFile( bundlePath, - `${fixtureDescriptor}${wfPutImport}export const run = async function* (_input, options) { + `${fixtureDescriptor}export const run = async function* (_input, options) { const cas = options.cas; - const h = await putContentMerkleNode(cas, "y"); + const h = await cas.put( "y"); yield { role: "a", contentHash: h, meta: {}, refs: [h] }; return { returnCode: 0, summary: "y" }; } diff --git a/packages/cli-workflow/__tests__/fork-cli.test.ts b/packages/cli-workflow/__tests__/fork-cli.test.ts index 98bffb1..0005309 100644 --- a/packages/cli-workflow/__tests__/fork-cli.test.ts +++ b/packages/cli-workflow/__tests__/fork-cli.test.ts @@ -15,9 +15,7 @@ import { addCliArgs } from "./bundle-fixture.js"; import { ensureTestWorkflowRegistryConfig } from "./workflow-registry-fixture.js"; /** Three-role workflow that respects `input.steps` for fork/resume. */ -const threeRoleBundleSource = `import { putContentMerkleNode } from "@uncaged/workflow-cas"; - -export const descriptor = { +const threeRoleBundleSource = `export const descriptor = { description: "fork-cli", roles: { planner: { description: "planner", schema: {} }, @@ -30,16 +28,16 @@ export const run = async function* (input, options) { const cas = options.cas; const has = (r) => input.steps.some((s) => s.role === r); if (!has("planner")) { - const h = await putContentMerkleNode(cas, "p1"); + const h = await cas.put( "p1"); yield { role: "planner", contentHash: h, meta: { k: "planner" }, refs: [h] }; } if (!has("coder")) { - const h = await putContentMerkleNode(cas, "c1"); + const h = await cas.put( "c1"); yield { role: "coder", contentHash: h, meta: { k: "coder" }, refs: [h] }; } if (!has("reviewer")) { const body = "rev-" + String(input.steps.length); - const h = await putContentMerkleNode(cas, body); + const h = await cas.put( body); yield { role: "reviewer", contentHash: h, meta: { k: "reviewer" }, refs: [h] }; } return { returnCode: 0, summary: "done" }; diff --git a/packages/cli-workflow/__tests__/thread-cli.test.ts b/packages/cli-workflow/__tests__/thread-cli.test.ts index edbf617..8c615dd 100644 --- a/packages/cli-workflow/__tests__/thread-cli.test.ts +++ b/packages/cli-workflow/__tests__/thread-cli.test.ts @@ -23,9 +23,6 @@ import { resolveThreadRecord } from "../src/thread-scan.js"; import { addCliArgs } from "./bundle-fixture.js"; import { ensureTestWorkflowRegistryConfig } from "./workflow-registry-fixture.js"; -const wfPutImport = `import { putContentMerkleNode } from "@uncaged/workflow-cas"; -`; - const threadFixtureDescriptor = `export const descriptor = { description: "thread-cli", roles: { @@ -41,25 +38,23 @@ const threadFixtureDescriptor = `export const descriptor = { `; const fastBundleSource = `${threadFixtureDescriptor} -${wfPutImport} export const run = async function* (input, options) { const cas = options.cas; - let h = await putContentMerkleNode(cas, "plan"); + let h = await cas.put( "plan"); yield { role: "planner", contentHash: h, meta: { plan: input.prompt }, refs: [h] }; - h = await putContentMerkleNode(cas, "code"); + h = await cas.put( "code"); yield { role: "coder", contentHash: h, meta: { diff: "y" }, refs: [h] }; return { returnCode: 0, summary: "done" }; }; `; const slowPlannerBundleSource = `${threadFixtureDescriptor} -${wfPutImport} export const run = async function* (input, options) { await new Promise((r) => setTimeout(r, 400)); const cas = options.cas; - let h = await putContentMerkleNode(cas, "plan"); + let h = await cas.put( "plan"); yield { role: "planner", contentHash: h, meta: { plan: input.prompt }, refs: [h] }; - h = await putContentMerkleNode(cas, "code"); + h = await cas.put( "code"); yield { role: "coder", contentHash: h, meta: { diff: "y" }, refs: [h] }; return { returnCode: 0, summary: "done" }; }; @@ -68,37 +63,34 @@ export const run = async function* (input, options) { const cliEntryPath = fileURLToPath(new URL("../src/cli.ts", import.meta.url)); const abortablePlannerBundleSource = `${threadFixtureDescriptor} -${wfPutImport} export const run = async function* (input, options) { const cas = options.cas; - let h = await putContentMerkleNode(cas, "plan"); + let h = await cas.put( "plan"); yield { role: "planner", contentHash: h, meta: { plan: input.prompt }, refs: [h] }; await new Promise((r) => setTimeout(r, 10000)); - h = await putContentMerkleNode(cas, "code"); + h = await cas.put( "code"); yield { role: "coder", contentHash: h, meta: { diff: "y" }, refs: [h] }; return { returnCode: 0, summary: "done" }; }; `; const pauseResumeBundleSource = `${threadFixtureDescriptor} -${wfPutImport} export const run = async function* (_input, options) { const cas = options.cas; - let h = await putContentMerkleNode(cas, "f"); + let h = await cas.put( "f"); yield { role: "first", contentHash: h, meta: {}, refs: [h] }; await new Promise((r) => setTimeout(r, 1500)); - h = await putContentMerkleNode(cas, "s"); + h = await cas.put( "s"); yield { role: "second", contentHash: h, meta: {}, refs: [h] }; return { returnCode: 0, summary: "done" }; }; `; const delayedFirstYieldBundleSource = `${threadFixtureDescriptor} -${wfPutImport} export const run = async function* (_input, options) { await new Promise((r) => setTimeout(r, 900)); const cas = options.cas; - const h = await putContentMerkleNode(cas, "x"); + const h = await cas.put( "x"); yield { role: "only", contentHash: h, meta: {}, refs: [h] }; return { returnCode: 0, summary: "done" }; }; diff --git a/packages/workflow-agent-cursor/src/index.ts b/packages/workflow-agent-cursor/src/index.ts index 35fe017..b3a7fec 100644 --- a/packages/workflow-agent-cursor/src/index.ts +++ b/packages/workflow-agent-cursor/src/index.ts @@ -12,6 +12,7 @@ import type { CursorAgentConfig } from "./types.js"; import { validateCursorAgentConfig } from "./validate-config.js"; export type { CursorAgentConfig } from "./types.js"; +export { validateCursorAgentConfig } from "./validate-config.js"; function throwCursorSpawnError(error: SpawnCliError): never { if (error.kind === "non_zero_exit") { diff --git a/packages/workflow-agent-hermes/src/index.ts b/packages/workflow-agent-hermes/src/index.ts index 0027c81..2ab9273 100644 --- a/packages/workflow-agent-hermes/src/index.ts +++ b/packages/workflow-agent-hermes/src/index.ts @@ -14,6 +14,7 @@ const HERMES_DEFAULT_MAX_TURNS = 90; type HermesAgentOpt = { prompt: string }; export type { HermesAgentConfig } from "./types.js"; +export { validateHermesAgentConfig } from "./validate-config.js"; function throwHermesSpawnError(error: SpawnCliError): never { if (error.kind === "non_zero_exit") { diff --git a/packages/workflow-execute/src/engine/worker.ts b/packages/workflow-execute/src/engine/worker.ts index 7681873..eab4950 100644 --- a/packages/workflow-execute/src/engine/worker.ts +++ b/packages/workflow-execute/src/engine/worker.ts @@ -3,9 +3,7 @@ import { mkdir, unlink, writeFile } from "node:fs/promises"; import { createServer, type Socket } from "node:net"; import { dirname, join } from "node:path"; import { createCasStore } from "@uncaged/workflow-cas"; -import { - importWorkflowBundleModule, -} from "@uncaged/workflow-register"; +import { importWorkflowBundleModule } from "@uncaged/workflow-register"; import type { RoleOutput, WorkflowFn } from "@uncaged/workflow-runtime"; import { createLogger, diff --git a/packages/workflow-protocol/src/types.ts b/packages/workflow-protocol/src/types.ts index 7ca2a9f..e990bea 100644 --- a/packages/workflow-protocol/src/types.ts +++ b/packages/workflow-protocol/src/types.ts @@ -154,12 +154,9 @@ 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). + * `Opt` captures agent-specific structured options (required second argument). */ -export type AgentFn = Opt extends void - ? (ctx: ThreadContext) => Promise - : (ctx: ThreadContext, options: Opt) => Promise; +export type AgentFn = (ctx: ThreadContext, options: Opt) => Promise; export type AdapterBinding = { adapter: AdapterFn; diff --git a/packages/workflow-runtime/src/index.ts b/packages/workflow-runtime/src/index.ts index db8e94d..3a7a136 100644 --- a/packages/workflow-runtime/src/index.ts +++ b/packages/workflow-runtime/src/index.ts @@ -1,6 +1,3 @@ -export { buildThreadContext } from "./build-context.js"; -export { createWorkflow } from "./create-workflow.js"; -export { err, ok } from "./result.js"; export type { AdapterFn, AgentContext, @@ -28,3 +25,6 @@ export type { WorkflowRuntime, } from "@uncaged/workflow-protocol"; export { END, START } from "@uncaged/workflow-protocol"; +export { buildThreadContext } from "./build-context.js"; +export { createWorkflow } from "./create-workflow.js"; +export { err, ok } from "./result.js"; diff --git a/packages/workflow-util-agent/src/create-agent-adapter.ts b/packages/workflow-util-agent/src/create-agent-adapter.ts index a7e1fe3..300a2ca 100644 --- a/packages/workflow-util-agent/src/create-agent-adapter.ts +++ b/packages/workflow-util-agent/src/create-agent-adapter.ts @@ -29,10 +29,7 @@ export function createAgentAdapter( 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 raw = await agent(ctx, options); const contentHash = await putContentNodeWithRefs(runtime.cas, raw, []); const extracted = await runtime.extract( schema as z.ZodType>, @@ -42,7 +39,3 @@ export function createAgentAdapter( }; }; } - -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 8a8c621..7a75ce3 100644 --- a/packages/workflow-util-agent/src/index.ts +++ b/packages/workflow-util-agent/src/index.ts @@ -1,4 +1,4 @@ -export { buildThreadInput } from "./build-agent-prompt.js"; +export { buildAgentPrompt, buildThreadInput } from "./build-agent-prompt.js"; export { createAgentAdapter } from "./create-agent-adapter.js"; export type { SpawnCliError } from "./spawn-cli.js"; export { spawnCli } from "./spawn-cli.js";