refactor(workflow): migrate downstream packages to workflow-runtime (Phase 2+3)

- Verify createWorkflow in runtime has zero I/O imports
- Migrate agent-cursor, agent-hermes to pure workflow-runtime dependency
- Migrate agent-llm, util-agent, templates to dual dependency
  (runtime for types, engine for CAS/merkle/buildDescriptor)
- All 377 tests passing

Refs #121, relates #123 #124
This commit is contained in:
2026-05-08 06:33:52 +00:00
parent 495c000356
commit e9e4960714
34 changed files with 44 additions and 48 deletions
@@ -1,5 +1,5 @@
import { describe, expect, test } from "bun:test"; import { describe, expect, test } from "bun:test";
import type { ExtractContext, ExtractFn } from "@uncaged/workflow"; import type { ExtractContext, ExtractFn } from "@uncaged/workflow-runtime";
import type * as z from "zod/v4"; import type * as z from "zod/v4";
import { createCursorAgent, validateCursorAgentConfig } from "../src/index.js"; import { createCursorAgent, validateCursorAgentConfig } from "../src/index.js";
+1 -1
View File
@@ -8,7 +8,7 @@
"test": "bun test" "test": "bun test"
}, },
"dependencies": { "dependencies": {
"@uncaged/workflow": "workspace:*", "@uncaged/workflow-runtime": "workspace:*",
"@uncaged/workflow-util-agent": "workspace:*", "@uncaged/workflow-util-agent": "workspace:*",
"zod": "^4.0.0" "zod": "^4.0.0"
} }
+1 -1
View File
@@ -1,4 +1,4 @@
import type { AgentFn, ExtractContext } from "@uncaged/workflow"; import type { AgentFn, ExtractContext } from "@uncaged/workflow-runtime";
import { buildAgentPrompt, type SpawnCliError, spawnCli } from "@uncaged/workflow-util-agent"; import { buildAgentPrompt, type SpawnCliError, spawnCli } from "@uncaged/workflow-util-agent";
import * as z from "zod/v4"; import * as z from "zod/v4";
+1 -1
View File
@@ -1,4 +1,4 @@
import type { ExtractFn } from "@uncaged/workflow"; import type { ExtractFn } from "@uncaged/workflow-runtime";
export type CursorAgentConfig = { export type CursorAgentConfig = {
model: string | null; model: string | null;
@@ -1,4 +1,4 @@
import { err, ok, type Result } from "@uncaged/workflow"; import { err, ok, type Result } from "@uncaged/workflow-runtime";
import type { CursorAgentConfig } from "./types.js"; import type { CursorAgentConfig } from "./types.js";
+1 -1
View File
@@ -8,7 +8,7 @@
"test": "bun test" "test": "bun test"
}, },
"dependencies": { "dependencies": {
"@uncaged/workflow": "workspace:*", "@uncaged/workflow-runtime": "workspace:*",
"@uncaged/workflow-util-agent": "workspace:*" "@uncaged/workflow-util-agent": "workspace:*"
} }
} }
+1 -1
View File
@@ -1,4 +1,4 @@
import type { AgentFn } from "@uncaged/workflow"; import type { AgentFn } from "@uncaged/workflow-runtime";
import { buildAgentPrompt, type SpawnCliError, spawnCli } from "@uncaged/workflow-util-agent"; import { buildAgentPrompt, type SpawnCliError, spawnCli } from "@uncaged/workflow-util-agent";
import type { HermesAgentConfig } from "./types.js"; import type { HermesAgentConfig } from "./types.js";
@@ -1,4 +1,4 @@
import { err, ok, type Result } from "@uncaged/workflow"; import { err, ok, type Result } from "@uncaged/workflow-runtime";
import type { HermesAgentConfig } from "./types.js"; import type { HermesAgentConfig } from "./types.js";
@@ -2,7 +2,8 @@ import { describe, expect, test } from "bun:test";
import { mkdtempSync } from "node:fs"; import { mkdtempSync } from "node:fs";
import { tmpdir } from "node:os"; import { tmpdir } from "node:os";
import { join } from "node:path"; import { join } from "node:path";
import { createCasStore, START, type ThreadContext } from "@uncaged/workflow"; import { createCasStore } from "@uncaged/workflow";
import { START, type ThreadContext } from "@uncaged/workflow-runtime";
import { createLlmAdapter } from "../src/create-llm-adapter.js"; import { createLlmAdapter } from "../src/create-llm-adapter.js";
+2 -1
View File
@@ -8,6 +8,7 @@
"test": "bun test" "test": "bun test"
}, },
"dependencies": { "dependencies": {
"@uncaged/workflow": "workspace:*" "@uncaged/workflow": "workspace:*",
"@uncaged/workflow-runtime": "workspace:*"
} }
} }
@@ -5,7 +5,7 @@ import {
type LlmProvider, type LlmProvider,
ok, ok,
type Result, type Result,
} from "@uncaged/workflow"; } from "@uncaged/workflow-runtime";
/** OpenAI chat completion message shape (passed to `/chat/completions`). */ /** OpenAI chat completion message shape (passed to `/chat/completions`). */
export type LlmMessage = { role: "system" | "user" | "assistant"; content: string }; export type LlmMessage = { role: "system" | "user" | "assistant"; content: string };
@@ -1,4 +1,4 @@
import type { CasStore } from "../cas/index.js"; import type { CasStore } from "../cas/types.js";
import { import {
type AgentBinding, type AgentBinding,
type AgentContext, type AgentContext,
@@ -131,7 +131,7 @@ async function advanceOneRound<M extends RoleMeta>(
/** /**
* Binds pure role definitions + moderator to runtime agents. * Binds pure role definitions + moderator to runtime agents.
* Assign with `export const run = createWorkflow(def, binding)` via `@uncaged/workflow`, * Assign with `export const run = createWorkflow(def, binding)` via `@uncaged/workflow-runtime`,
* which supplies {@link ResolveRoleMetaFn}. * which supplies {@link ResolveRoleMetaFn}.
*/ */
export function createWorkflow<M extends RoleMeta>( export function createWorkflow<M extends RoleMeta>(
@@ -5,7 +5,7 @@ import {
type RoleStep, type RoleStep,
START, START,
validateWorkflowDescriptor, validateWorkflowDescriptor,
} from "@uncaged/workflow"; } from "@uncaged/workflow-runtime";
import { buildDevelopDescriptor } from "../src/descriptor.js"; import { buildDevelopDescriptor } from "../src/descriptor.js";
import { developModerator } from "../src/index.js"; import { developModerator } from "../src/index.js";
import type { CommitterMeta, PlannerMeta } from "../src/roles/index.js"; import type { CommitterMeta, PlannerMeta } from "../src/roles/index.js";
@@ -9,6 +9,7 @@
}, },
"dependencies": { "dependencies": {
"@uncaged/workflow": "workspace:*", "@uncaged/workflow": "workspace:*",
"@uncaged/workflow-runtime": "workspace:*",
"zod": "^4.0.0" "zod": "^4.0.0"
} }
} }
@@ -1,9 +1,5 @@
import { import { createWorkflow } from "@uncaged/workflow";
type AgentBinding, import type { AgentBinding, WorkflowDefinition, WorkflowFn } from "@uncaged/workflow-runtime";
createWorkflow,
type WorkflowDefinition,
type WorkflowFn,
} from "@uncaged/workflow";
import { developModerator } from "./moderator.js"; import { developModerator } from "./moderator.js";
import { DEVELOP_WORKFLOW_DESCRIPTION, type DevelopMeta, developRoles } from "./roles.js"; import { DEVELOP_WORKFLOW_DESCRIPTION, type DevelopMeta, developRoles } from "./roles.js";
@@ -1,5 +1,5 @@
import type { Moderator, ModeratorContext } from "@uncaged/workflow"; import type { Moderator, ModeratorContext } from "@uncaged/workflow-runtime";
import { END } from "@uncaged/workflow"; import { END } from "@uncaged/workflow-runtime";
import type { DevelopMeta } from "./roles.js"; import type { DevelopMeta } from "./roles.js";
@@ -1,4 +1,4 @@
import type { RoleDefinition } from "@uncaged/workflow"; import type { RoleDefinition } from "@uncaged/workflow-runtime";
import { type CoderMeta, coderRole } from "./roles/coder.js"; import { type CoderMeta, coderRole } from "./roles/coder.js";
import { type CommitterMeta, committerRole } from "./roles/committer.js"; import { type CommitterMeta, committerRole } from "./roles/committer.js";
import { type PlannerMeta, plannerRole } from "./roles/planner.js"; import { type PlannerMeta, plannerRole } from "./roles/planner.js";
@@ -1,4 +1,4 @@
import type { RoleDefinition } from "@uncaged/workflow"; import type { RoleDefinition } from "@uncaged/workflow-runtime";
import * as z from "zod/v4"; import * as z from "zod/v4";
export const coderMetaSchema = z.object({ export const coderMetaSchema = z.object({
@@ -1,4 +1,4 @@
import type { RoleDefinition } from "@uncaged/workflow"; import type { RoleDefinition } from "@uncaged/workflow-runtime";
import * as z from "zod/v4"; import * as z from "zod/v4";
export const committerMetaSchema = z.discriminatedUnion("status", [ export const committerMetaSchema = z.discriminatedUnion("status", [
@@ -1,4 +1,4 @@
import type { RoleDefinition } from "@uncaged/workflow"; import type { RoleDefinition } from "@uncaged/workflow-runtime";
import * as z from "zod/v4"; import * as z from "zod/v4";
export const phaseSchema = z.object({ export const phaseSchema = z.object({
@@ -1,4 +1,4 @@
import type { RoleDefinition } from "@uncaged/workflow"; import type { RoleDefinition } from "@uncaged/workflow-runtime";
import * as z from "zod/v4"; import * as z from "zod/v4";
export const reviewerMetaSchema = z.discriminatedUnion("status", [ export const reviewerMetaSchema = z.discriminatedUnion("status", [
@@ -1,4 +1,4 @@
import type { RoleDefinition } from "@uncaged/workflow"; import type { RoleDefinition } from "@uncaged/workflow-runtime";
import * as z from "zod/v4"; import * as z from "zod/v4";
export const testerMetaSchema = z.discriminatedUnion("status", [ export const testerMetaSchema = z.discriminatedUnion("status", [
@@ -2,15 +2,14 @@ import { afterEach, describe, expect, test } from "bun:test";
import { mkdtemp, rm } from "node:fs/promises"; import { mkdtemp, rm } from "node:fs/promises";
import { tmpdir } from "node:os"; import { tmpdir } from "node:os";
import { join } from "node:path"; import { join } from "node:path";
import { createCasStore, createExtract } from "@uncaged/workflow";
import { import {
createCasStore,
createExtract,
END, END,
type ModeratorContext, type ModeratorContext,
type RoleStep, type RoleStep,
START, START,
validateWorkflowDescriptor, validateWorkflowDescriptor,
} from "@uncaged/workflow"; } from "@uncaged/workflow-runtime";
import { buildSolveIssueDescriptor } from "../src/descriptor.js"; import { buildSolveIssueDescriptor } from "../src/descriptor.js";
import type { DeveloperMeta } from "../src/developer.js"; import type { DeveloperMeta } from "../src/developer.js";
import { createSolveIssueRun, solveIssueModerator } from "../src/index.js"; import { createSolveIssueRun, solveIssueModerator } from "../src/index.js";
@@ -9,6 +9,7 @@
}, },
"dependencies": { "dependencies": {
"@uncaged/workflow": "workspace:*", "@uncaged/workflow": "workspace:*",
"@uncaged/workflow-runtime": "workspace:*",
"zod": "^4.0.0" "zod": "^4.0.0"
} }
} }
@@ -1,4 +1,4 @@
import type { RoleDefinition } from "@uncaged/workflow"; import type { RoleDefinition } from "@uncaged/workflow-runtime";
import * as z from "zod/v4"; import * as z from "zod/v4";
export const developerMetaSchema = z.object({ export const developerMetaSchema = z.object({
@@ -1,10 +1,5 @@
import { import { createWorkflow, workflowAsAgent } from "@uncaged/workflow";
type AgentBinding, import type { AgentBinding, WorkflowDefinition, WorkflowFn } from "@uncaged/workflow-runtime";
createWorkflow,
type WorkflowDefinition,
type WorkflowFn,
workflowAsAgent,
} from "@uncaged/workflow";
import { solveIssueModerator } from "./moderator.js"; import { solveIssueModerator } from "./moderator.js";
import { SOLVE_ISSUE_WORKFLOW_DESCRIPTION, type SolveIssueMeta, solveIssueRoles } from "./roles.js"; import { SOLVE_ISSUE_WORKFLOW_DESCRIPTION, type SolveIssueMeta, solveIssueRoles } from "./roles.js";
@@ -1,5 +1,5 @@
import type { Moderator } from "@uncaged/workflow"; import type { Moderator } from "@uncaged/workflow-runtime";
import { END } from "@uncaged/workflow"; import { END } from "@uncaged/workflow-runtime";
import type { SolveIssueMeta } from "./roles.js"; import type { SolveIssueMeta } from "./roles.js";
@@ -1,4 +1,4 @@
import type { RoleDefinition } from "@uncaged/workflow"; import type { RoleDefinition } from "@uncaged/workflow-runtime";
import { type DeveloperMeta, developerRole } from "./developer.js"; import { type DeveloperMeta, developerRole } from "./developer.js";
import { type PreparerMeta, preparerRole } from "./roles/preparer.js"; import { type PreparerMeta, preparerRole } from "./roles/preparer.js";
import { type SubmitterMeta, submitterRole } from "./roles/submitter.js"; import { type SubmitterMeta, submitterRole } from "./roles/submitter.js";
@@ -1,4 +1,4 @@
import type { RoleDefinition } from "@uncaged/workflow"; import type { RoleDefinition } from "@uncaged/workflow-runtime";
import * as z from "zod/v4"; import * as z from "zod/v4";
const toolchainSchema = z.object({ const toolchainSchema = z.object({
@@ -1,4 +1,4 @@
import type { RoleDefinition } from "@uncaged/workflow"; import type { RoleDefinition } from "@uncaged/workflow-runtime";
import * as z from "zod/v4"; import * as z from "zod/v4";
export const submitterMetaSchema = z.discriminatedUnion("status", [ export const submitterMetaSchema = z.discriminatedUnion("status", [
@@ -2,7 +2,8 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test";
import { mkdtemp, rm } from "node:fs/promises"; import { mkdtemp, rm } from "node:fs/promises";
import { tmpdir } from "node:os"; import { tmpdir } from "node:os";
import { join } from "node:path"; import { join } from "node:path";
import { createCasStore, putContentMerkleNode, START, type ThreadContext } from "@uncaged/workflow"; import { createCasStore, putContentMerkleNode } from "@uncaged/workflow";
import { START, type ThreadContext } from "@uncaged/workflow-runtime";
import { buildAgentPrompt } from "../src/index.js"; import { buildAgentPrompt } from "../src/index.js";
+2 -1
View File
@@ -14,6 +14,7 @@
"test": "bun test" "test": "bun test"
}, },
"dependencies": { "dependencies": {
"@uncaged/workflow": "workspace:*" "@uncaged/workflow": "workspace:*",
"@uncaged/workflow-runtime": "workspace:*"
} }
} }
@@ -1,5 +1,5 @@
import type { AgentContext } from "@uncaged/workflow";
import { getContentMerklePayload } from "@uncaged/workflow"; import { getContentMerklePayload } from "@uncaged/workflow";
import type { AgentContext } from "@uncaged/workflow-runtime";
async function resolveStepText(ctx: AgentContext, contentHash: string): Promise<string> { async function resolveStepText(ctx: AgentContext, contentHash: string): Promise<string> {
const text = await getContentMerklePayload(ctx.cas, contentHash); const text = await getContentMerklePayload(ctx.cas, contentHash);
@@ -1,6 +1,6 @@
import { spawn } from "node:child_process"; import { spawn } from "node:child_process";
import { err, ok, type Result } from "@uncaged/workflow"; import { err, ok, type Result } from "@uncaged/workflow-runtime";
export type SpawnCliError = export type SpawnCliError =
| { kind: "non_zero_exit"; exitCode: number | null; stdout: string; stderr: string } | { kind: "non_zero_exit"; exitCode: number | null; stdout: string; stderr: string }