Merge pull request 'refactor: 七包拆分 — protocol / runtime / util / cas / reactor / register / execute' (#151) from refactor/143-split-packages into main

This commit is contained in:
2026-05-09 03:53:54 +00:00
159 changed files with 804 additions and 3824 deletions
@@ -3,13 +3,9 @@ import { mkdir, mkdtemp, readFile, rm, unlink, writeFile } from "node:fs/promise
import { tmpdir } from "node:os";
import { join } from "node:path";
import {
createContentMerkleNode,
getGlobalCasDir,
getRegisteredWorkflow,
readWorkflowRegistry,
serializeMerkleNode,
} from "@uncaged/workflow";
import { getGlobalCasDir } from "@uncaged/workflow-util";
import { createContentMerkleNode, serializeMerkleNode } from "@uncaged/workflow-cas";
import { getRegisteredWorkflow, readWorkflowRegistry } from "@uncaged/workflow-register";
import { cmdCasGet, cmdCasList, cmdCasPut, cmdCasRm } from "../src/commands/cas/index.js";
import {
cmdAdd,
@@ -25,7 +21,7 @@ import { addCliArgs } from "./bundle-fixture.js";
const fixtureDescriptor = `export const descriptor = { description: "fixture", roles: {} };
`;
const wfPutImport = `import { putContentMerkleNode } from "@uncaged/workflow";
const wfPutImport = `import { putContentMerkleNode } from "@uncaged/workflow-cas";
`;
function casStoredForm(raw: string): string {
@@ -2,7 +2,8 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test";
import { mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { createCasStore, getContentMerklePayload, getGlobalCasDir } from "@uncaged/workflow";
import { createCasStore, getContentMerklePayload } from "@uncaged/workflow-cas";
import { getGlobalCasDir } from "@uncaged/workflow-util";
import { cmdFork, cmdRun } from "../src/commands/thread/index.js";
import { cmdAdd } from "../src/commands/workflow/index.js";
import { pathExists } from "../src/fs-utils.js";
@@ -10,7 +11,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";
const threeRoleBundleSource = `import { putContentMerkleNode } from "@uncaged/workflow-cas";
export const descriptor = {
description: "fork-cli",
@@ -4,12 +4,9 @@ import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { fileURLToPath } from "node:url";
import {
createCasStore,
garbageCollectCas,
getGlobalCasDir,
putContentMerkleNode,
} from "@uncaged/workflow";
import { createCasStore, putContentMerkleNode } from "@uncaged/workflow-cas";
import { getGlobalCasDir } from "@uncaged/workflow-util";
import { garbageCollectCas } from "@uncaged/workflow-execute";
import { cmdThreadRemove } from "../src/commands/thread/index.js";
import { pathExists } from "../src/fs-utils.js";
@@ -50,7 +50,6 @@ describe("init template", () => {
dependencies: Record<string, string>;
};
expect(pkg.type).toBe("module");
expect(pkg.dependencies["@uncaged/workflow"]).toBeDefined();
expect(pkg.dependencies["@uncaged/workflow-runtime"]).toBeDefined();
expect(pkg.dependencies.zod).toBeDefined();
expect(pkg.name).toContain("review-pr");
@@ -46,7 +46,7 @@ describe("init workspace", () => {
dependencies: Record<string, string>;
};
expect(wfPkg.type).toBe("module");
expect(wfPkg.dependencies["@uncaged/workflow"]).toBeDefined();
expect(wfPkg.dependencies["@uncaged/workflow-runtime"]).toBeDefined();
expect(wfPkg.dependencies.zod).toBeDefined();
const tsconfig = JSON.parse(await readFile(join(root, "tsconfig.json"), "utf8")) as {
+2 -1
View File
@@ -5,7 +5,8 @@ import { tmpdir } from "node:os";
import { join } from "node:path";
import { fileURLToPath } from "node:url";
import { createCasStore, getGlobalCasDir, putContentMerkleNode } from "@uncaged/workflow";
import { createCasStore, putContentMerkleNode } from "@uncaged/workflow-cas";
import { getGlobalCasDir } from "@uncaged/workflow-util";
import {
formatLiveDebugLine,
@@ -1,6 +1,6 @@
import { describe, expect, test } from "bun:test";
import { createContentMerkleNode, serializeMerkleNode } from "@uncaged/workflow";
import { createContentMerkleNode, serializeMerkleNode } from "@uncaged/workflow-cas";
import { createApp } from "../src/commands/serve/app.js";
@@ -1,5 +1,5 @@
import { afterEach, beforeEach, describe, expect, test } from "bun:test";
import { getDefaultWorkflowStorageRoot } from "@uncaged/workflow";
import { getDefaultWorkflowStorageRoot } from "@uncaged/workflow-util";
import { resolveWorkflowStorageRoot } from "../src/storage-env.js";
describe("resolveWorkflowStorageRoot", () => {
@@ -4,7 +4,7 @@ import { mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
import { getGlobalCasDir } from "@uncaged/workflow";
import { getGlobalCasDir } from "@uncaged/workflow-util";
import { cmdCasPut } from "../src/commands/cas/index.js";
import {
cmdKill,
@@ -21,7 +21,7 @@ import { pathExists, readTextFileIfExists } from "../src/fs-utils.js";
import { addCliArgs } from "./bundle-fixture.js";
import { ensureTestWorkflowRegistryConfig } from "./workflow-registry-fixture.js";
const wfPutImport = `import { putContentMerkleNode } from "@uncaged/workflow";
const wfPutImport = `import { putContentMerkleNode } from "@uncaged/workflow-cas";
`;
const threadFixtureDescriptor = `export const descriptor = {
+5 -1
View File
@@ -6,8 +6,12 @@
"uncaged-workflow": "src/cli.ts"
},
"dependencies": {
"@uncaged/workflow-protocol": "workspace:*",
"@uncaged/workflow-util": "workspace:*",
"@uncaged/workflow-cas": "workspace:*",
"@uncaged/workflow-execute": "workspace:*",
"@uncaged/workflow-register": "workspace:*",
"@uncaged/workflow-runtime": "workspace:*",
"@uncaged/workflow": "workspace:*",
"hono": "^4.12.18",
"yaml": "^2.8.4"
},
+1 -1
View File
@@ -1,7 +1,7 @@
import { mkdir, readFile, writeFile } from "node:fs/promises";
import { join } from "node:path";
import { err, ok, type Result } from "@uncaged/workflow";
import { err, ok, type Result } from "@uncaged/workflow-protocol";
import { pathExists } from "./fs-utils.js";
+2 -1
View File
@@ -1,4 +1,5 @@
import { type GcResult, garbageCollectCas, type Result } from "@uncaged/workflow";
import type { Result } from "@uncaged/workflow-protocol";
import { type GcResult, garbageCollectCas } from "@uncaged/workflow-execute";
export async function cmdGc(storageRoot: string): Promise<Result<GcResult, string>> {
return garbageCollectCas(storageRoot);
@@ -1,4 +1,6 @@
import { createCasStore, err, getGlobalCasDir, ok, type Result } from "@uncaged/workflow";
import { err, ok, type Result } from "@uncaged/workflow-protocol";
import { getGlobalCasDir } from "@uncaged/workflow-util";
import { createCasStore } from "@uncaged/workflow-cas";
export async function cmdCasGet(
storageRoot: string,
@@ -1,4 +1,6 @@
import { createCasStore, getGlobalCasDir, ok, type Result } from "@uncaged/workflow";
import { ok, type Result } from "@uncaged/workflow-protocol";
import { getGlobalCasDir } from "@uncaged/workflow-util";
import { createCasStore } from "@uncaged/workflow-cas";
export async function cmdCasList(storageRoot: string): Promise<Result<string[], string>> {
const cas = createCasStore(getGlobalCasDir(storageRoot));
@@ -1,4 +1,6 @@
import { createCasStore, getGlobalCasDir, ok, type Result } from "@uncaged/workflow";
import { ok, type Result } from "@uncaged/workflow-protocol";
import { getGlobalCasDir } from "@uncaged/workflow-util";
import { createCasStore } from "@uncaged/workflow-cas";
export async function cmdCasPut(
storageRoot: string,
+3 -1
View File
@@ -1,4 +1,6 @@
import { createCasStore, getGlobalCasDir, ok, type Result } from "@uncaged/workflow";
import { ok, type Result } from "@uncaged/workflow-protocol";
import { getGlobalCasDir } from "@uncaged/workflow-util";
import { createCasStore } from "@uncaged/workflow-cas";
export async function cmdCasRm(storageRoot: string, hash: string): Promise<Result<void, string>> {
const cas = createCasStore(getGlobalCasDir(storageRoot));
@@ -1,7 +1,7 @@
import { mkdir, readFile, writeFile } from "node:fs/promises";
import { dirname, join, resolve } from "node:path";
import { err, ok, type Result } from "@uncaged/workflow";
import { err, ok, type Result } from "@uncaged/workflow-protocol";
import { pathExists } from "../../fs-utils.js";
@@ -6,7 +6,6 @@ export function templatePackageJson(templateName: string): string {
private: true,
type: "module",
dependencies: {
"@uncaged/workflow": "^0.1.0",
"@uncaged/workflow-runtime": "^0.1.0",
zod: "^4.0.0",
},
@@ -1,4 +1,4 @@
import { err, ok, type Result } from "@uncaged/workflow";
import { err, ok, type Result } from "@uncaged/workflow-protocol";
/** Validates a single path segment for workspace / template names (no separators, not `.` / `..`). */
export function validateWorkspaceSegment(name: string): Result<void, string> {
@@ -1,7 +1,7 @@
import { mkdir, writeFile } from "node:fs/promises";
import { join } from "node:path";
import { err, ok, type Result } from "@uncaged/workflow";
import { err, ok, type Result } from "@uncaged/workflow-protocol";
import { pathExists } from "../../fs-utils.js";
import type { CmdInitWorkspaceSuccess } from "./types.js";
@@ -28,7 +28,7 @@ function workflowsPackageJson(): string {
private: true,
type: "module",
dependencies: {
"@uncaged/workflow": "^0.1.0",
"@uncaged/workflow-runtime": "^0.1.0",
zod: "^4.0.0",
},
},
@@ -1,4 +1,6 @@
import { createCasStore, garbageCollectCas, getGlobalCasDir } from "@uncaged/workflow";
import { getGlobalCasDir } from "@uncaged/workflow-util";
import { createCasStore } from "@uncaged/workflow-cas";
import { garbageCollectCas } from "@uncaged/workflow-execute";
import { Hono } from "hono";
export function createCasRoutes(storageRoot: string): Hono {
@@ -2,7 +2,7 @@ import {
getRegisteredWorkflow,
listRegisteredWorkflowNames,
readWorkflowRegistry,
} from "@uncaged/workflow";
} from "@uncaged/workflow-register";
import { Hono } from "hono";
export function createWorkflowRoutes(storageRoot: string): Hono {
@@ -1,4 +1,4 @@
import { err, ok, type Result } from "@uncaged/workflow";
import { err, ok, type Result } from "@uncaged/workflow-protocol";
import { serve } from "bun";
import { printCliLine } from "../../cli-output.js";
@@ -1,4 +1,4 @@
import type { Result } from "@uncaged/workflow";
import type { Result } from "@uncaged/workflow-protocol";
import {
readWorkerCtl,
@@ -1,4 +1,4 @@
import { err, ok, type Result } from "@uncaged/workflow";
import { err, ok, type Result } from "@uncaged/workflow-protocol";
import type { ParsedForkArgv } from "./types.js";
@@ -1,6 +1,8 @@
import { join } from "node:path";
import { buildForkPlan, err, generateUlid, ok, type Result } from "@uncaged/workflow";
import { err, ok, type Result } from "@uncaged/workflow-protocol";
import { generateUlid } from "@uncaged/workflow-util";
import { buildForkPlan } from "@uncaged/workflow-execute";
import { pathExists, readTextFileIfExists } from "../../fs-utils.js";
import { resolveThreadDataPath } from "../../thread-scan.js";
@@ -1,4 +1,4 @@
import { err, ok, type Result } from "@uncaged/workflow";
import { err, ok, type Result } from "@uncaged/workflow-protocol";
import { listHistoricalThreads } from "../../thread-scan.js";
import { validateCliWorkflowName } from "../../workflow-name.js";
@@ -2,15 +2,10 @@ import { watch } from "node:fs";
import { readFile } from "node:fs/promises";
import { dirname, join } from "node:path";
import {
type CasStore,
createCasStore,
getContentMerklePayload,
getGlobalCasDir,
tryParseRoleStepRecord,
tryParseWorkflowResultRecord,
} from "@uncaged/workflow";
import type { WorkflowCompletion } from "@uncaged/workflow-runtime";
import type { CasStore, WorkflowCompletion } from "@uncaged/workflow-protocol";
import { getGlobalCasDir } from "@uncaged/workflow-util";
import { createCasStore, getContentMerklePayload } from "@uncaged/workflow-cas";
import { tryParseRoleStepRecord, tryParseWorkflowResultRecord } from "@uncaged/workflow-execute";
import { dimGreyLine, highlightLiveRole } from "../../cli-color.js";
import { printCliError, printCliLine } from "../../cli-output.js";
@@ -1,7 +1,8 @@
import { unlink } from "node:fs/promises";
import { dirname, join } from "node:path";
import { err, garbageCollectCas, ok, type Result } from "@uncaged/workflow";
import { err, ok, type Result } from "@uncaged/workflow-protocol";
import { garbageCollectCas } from "@uncaged/workflow-execute";
import { resolveThreadDataPath } from "../../thread-scan.js";
@@ -1,13 +1,8 @@
import { join } from "node:path";
import {
err,
generateUlid,
getRegisteredWorkflow,
ok,
type Result,
readWorkflowRegistry,
} from "@uncaged/workflow";
import { err, ok, type Result } from "@uncaged/workflow-protocol";
import { generateUlid } from "@uncaged/workflow-util";
import { getRegisteredWorkflow, readWorkflowRegistry } from "@uncaged/workflow-register";
import { ensureWorkerForHash, sendWorkerTcpCommand } from "../../worker-spawn.js";
import { validateCliWorkflowName } from "../../workflow-name.js";
@@ -1,4 +1,4 @@
import { err, ok, type Result } from "@uncaged/workflow";
import { err, ok, type Result } from "@uncaged/workflow-protocol";
import { readTextFileIfExists } from "../../fs-utils.js";
import { resolveThreadDataPath } from "../../thread-scan.js";
@@ -1,4 +1,4 @@
import { err, ok, type Result } from "@uncaged/workflow";
import { err, ok, type Result } from "@uncaged/workflow-protocol";
import type { ParsedAddArgv } from "./types.js";
@@ -1,18 +1,16 @@
import { readFile, stat } from "node:fs/promises";
import { basename, resolve } from "node:path";
import { err, ok, type Result } from "@uncaged/workflow-protocol";
import { hashWorkflowBundleBytes } from "@uncaged/workflow-cas";
import {
err,
extractBundleExports,
hashWorkflowBundleBytes,
ok,
type Result,
readWorkflowRegistry,
registerWorkflowVersion,
stringifyWorkflowDescriptor,
validateWorkflowBundle,
writeWorkflowRegistry,
} from "@uncaged/workflow";
} from "@uncaged/workflow-register";
import { storeWorkflowBundleArtifacts } from "../../bundle-store.js";
import { validateCliWorkflowName } from "../../workflow-name.js";
@@ -1,10 +1,5 @@
import {
err,
getRegisteredWorkflow,
ok,
type Result,
readWorkflowRegistry,
} from "@uncaged/workflow";
import { err, ok, type Result } from "@uncaged/workflow-protocol";
import { getRegisteredWorkflow, readWorkflowRegistry } from "@uncaged/workflow-register";
import { validateCliWorkflowName } from "../../workflow-name.js";
@@ -1,11 +1,9 @@
import { err, ok, type Result } from "@uncaged/workflow-protocol";
import {
err,
listRegisteredWorkflowNames,
ok,
type Result,
readWorkflowRegistry,
type WorkflowRegistryFile,
} from "@uncaged/workflow";
} from "@uncaged/workflow-register";
export async function cmdList(storageRoot: string): Promise<Result<WorkflowRegistryFile, string>> {
const reg = await readWorkflowRegistry(storageRoot);
@@ -1,11 +1,9 @@
import { err, ok, type Result } from "@uncaged/workflow-protocol";
import {
err,
ok,
type Result,
readWorkflowRegistry,
unregisterWorkflow,
writeWorkflowRegistry,
} from "@uncaged/workflow";
} from "@uncaged/workflow-register";
import { validateCliWorkflowName } from "../../workflow-name.js";
@@ -1,14 +1,12 @@
import { join } from "node:path";
import { err, ok, type Result } from "@uncaged/workflow-protocol";
import {
err,
getRegisteredWorkflow,
ok,
type Result,
readWorkflowRegistry,
rollbackWorkflowToHistoryHash,
writeWorkflowRegistry,
} from "@uncaged/workflow";
} from "@uncaged/workflow-register";
import { pathExists } from "../../fs-utils.js";
import { validateCliWorkflowName } from "../../workflow-name.js";
@@ -1,11 +1,9 @@
import { err, ok, type Result } from "@uncaged/workflow-protocol";
import {
err,
getRegisteredWorkflow,
ok,
type Result,
readWorkflowRegistry,
type WorkflowRegistryEntry,
} from "@uncaged/workflow";
} from "@uncaged/workflow-register";
import { stringify } from "yaml";
import { validateCliWorkflowName } from "../../workflow-name.js";
+1 -1
View File
@@ -1,4 +1,4 @@
import { err, ok, type Result } from "@uncaged/workflow";
import { err, ok, type Result } from "@uncaged/workflow-protocol";
export type ParsedLiveArgv = {
threadId: string | null;
+1 -1
View File
@@ -1,4 +1,4 @@
import { err, ok, type Result } from "@uncaged/workflow";
import { err, ok, type Result } from "@uncaged/workflow-protocol";
export type ParsedRunArgv = {
name: string;
+1 -1
View File
@@ -1,4 +1,4 @@
import { getDefaultWorkflowStorageRoot } from "@uncaged/workflow";
import { getDefaultWorkflowStorageRoot } from "@uncaged/workflow-util";
/**
* Resolve storage root with env var override support.
+2 -1
View File
@@ -3,7 +3,8 @@ import { mkdir, readdir, unlink, writeFile } from "node:fs/promises";
import { createConnection } from "node:net";
import { join } from "node:path";
import { err, getWorkerHostScriptPath, ok, type Result } from "@uncaged/workflow";
import { err, ok, type Result } from "@uncaged/workflow-protocol";
import { getWorkerHostScriptPath } from "@uncaged/workflow-execute";
import { pathExists, readTextFileIfExists } from "./fs-utils.js";
+1 -1
View File
@@ -1,4 +1,4 @@
import { err, ok, type Result } from "@uncaged/workflow";
import { err, ok, type Result } from "@uncaged/workflow-protocol";
const WORKFLOW_NAME_RE = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;
+8 -1
View File
@@ -17,6 +17,13 @@
"rootDir": "src",
"types": ["bun-types"]
},
"references": [{ "path": "../workflow-runtime" }, { "path": "../workflow" }],
"references": [
{ "path": "../workflow-runtime" },
{ "path": "../workflow-protocol" },
{ "path": "../workflow-util" },
{ "path": "../workflow-cas" },
{ "path": "../workflow-execute" },
{ "path": "../workflow-register" }
],
"include": ["src/**/*.ts"]
}
+1 -1
View File
@@ -6,5 +6,5 @@
"composite": true
},
"include": ["src/**/*.ts"],
"references": [{ "path": "../workflow" }, { "path": "../workflow-util-agent" }]
"references": [{ "path": "../workflow-runtime" }, { "path": "../workflow-util-agent" }]
}
+1 -1
View File
@@ -6,5 +6,5 @@
"composite": true
},
"include": ["src/**/*.ts"],
"references": [{ "path": "../workflow" }, { "path": "../workflow-util-agent" }]
"references": [{ "path": "../workflow-runtime" }, { "path": "../workflow-util-agent" }]
}
-1
View File
@@ -8,7 +8,6 @@
"test": "bun test"
},
"dependencies": {
"@uncaged/workflow": "workspace:*",
"@uncaged/workflow-runtime": "workspace:*"
}
}
+1 -1
View File
@@ -6,5 +6,5 @@
"composite": true
},
"include": ["src/**/*.ts"],
"references": [{ "path": "../workflow" }]
"references": [{ "path": "../workflow-runtime" }]
}
+20
View File
@@ -0,0 +1,20 @@
{
"name": "@uncaged/workflow-cas",
"version": "0.1.0",
"type": "module",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./src/index.ts"
}
},
"dependencies": {
"@uncaged/workflow-protocol": "workspace:*",
"@uncaged/workflow-util": "workspace:*",
"xxhashjs": "^0.2.2",
"yaml": "^2.7.1"
},
"devDependencies": {
"@types/bun": "latest"
}
}
@@ -2,7 +2,7 @@ import { Buffer } from "node:buffer";
import XXH from "xxhashjs";
import { encodeUint64AsCrockford } from "../util/index.js";
import { encodeUint64AsCrockford } from "@uncaged/workflow-util";
function digestToUint64(digest: { toString(radix?: number): string }): bigint {
const hex = digest.toString(16).padStart(16, "0");
@@ -1,4 +1,4 @@
export type { CasStore } from "@uncaged/workflow-runtime";
export type { CasStore } from "@uncaged/workflow-protocol";
export type MerkleNodeType = "content" | "step" | "thread";
+12
View File
@@ -0,0 +1,12 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"rootDir": "src",
"outDir": "dist"
},
"include": ["src"],
"references": [
{ "path": "../workflow-protocol" },
{ "path": "../workflow-util" }
]
}
+29
View File
@@ -0,0 +1,29 @@
{
"name": "@uncaged/workflow-execute",
"version": "0.2.0",
"type": "module",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./src/index.ts"
}
},
"scripts": {
"test": "bun test"
},
"dependencies": {
"@uncaged/workflow-protocol": "workspace:*",
"@uncaged/workflow-runtime": "workspace:*",
"@uncaged/workflow-util": "workspace:*",
"@uncaged/workflow-cas": "workspace:*",
"@uncaged/workflow-reactor": "workspace:*",
"@uncaged/workflow-register": "workspace:*",
"yaml": "^2.7.1"
},
"peerDependencies": {
"zod": "^4.0.0"
},
"devDependencies": {
"zod": "^4.0.0"
}
}
@@ -15,11 +15,11 @@ import {
getContentMerklePayload,
putStepMerkleNode,
putThreadMerkleNode,
} from "../cas/index.js";
import { resolveModel } from "../config/index.js";
} from "@uncaged/workflow-cas";
import { resolveModel } from "@uncaged/workflow-register";
import { createExtract } from "../extract/index.js";
import { readWorkflowRegistry, type WorkflowConfig } from "../registry/index.js";
import { err, type LogFn, normalizeRefsField, ok, type Result } from "../util/index.js";
import { readWorkflowRegistry, type WorkflowConfig } from "@uncaged/workflow-register";
import { err, type LogFn, normalizeRefsField, ok, type Result } from "@uncaged/workflow-util";
import { runSupervisor } from "./supervisor.js";
import type { ExecuteThreadIo, ExecuteThreadOptions } from "./types.js";
@@ -1,5 +1,5 @@
import type { WorkflowCompletion } from "@uncaged/workflow-runtime";
import { err, normalizeRefsField, ok, type Result } from "../util/index.js";
import { err, normalizeRefsField, ok, type Result } from "@uncaged/workflow-util";
import type { ForkHistoricalStep, ForkPlan, ParsedThreadStartRecord } from "./types.js";
@@ -1,7 +1,7 @@
import { readdir, readFile } from "node:fs/promises";
import { join } from "node:path";
import { type CasStore, createCasStore } from "../cas/index.js";
import { err, getGlobalCasDir, ok, type Result } from "../util/index.js";
import { type CasStore, createCasStore } from "@uncaged/workflow-cas";
import { err, getGlobalCasDir, ok, type Result } from "@uncaged/workflow-util";
import { parseThreadDataJsonl } from "./fork-thread.js";
import type { GcResult } from "./types.js";
@@ -1,10 +1,10 @@
import * as z from "zod/v4";
import { resolveModel } from "../config/index.js";
import { resolveModel } from "@uncaged/workflow-register";
import { extractFunctionToolFromZodSchema } from "../extract/index.js";
import { createLlmFn, createThreadReactor } from "../reactor/index.js";
import type { WorkflowConfig } from "../registry/index.js";
import { err, type LogFn, ok, type Result } from "../util/index.js";
import { createLlmFn, createThreadReactor } from "@uncaged/workflow-reactor";
import type { WorkflowConfig } from "@uncaged/workflow-register";
import { err, type LogFn, ok, type Result } from "@uncaged/workflow-util";
import type { SupervisorDecision } from "./types.js";
@@ -1,4 +1,4 @@
import { err, ok, type Result } from "../util/index.js";
import { err, ok, type Result } from "@uncaged/workflow-util";
import type { ThreadPauseGate } from "./types.js";
@@ -1,6 +1,6 @@
import type { RoleOutput } from "@uncaged/workflow-runtime";
import type { CasStore } from "../cas/index.js";
import type { Result } from "../util/index.js";
import type { CasStore } from "@uncaged/workflow-cas";
import type { Result } from "@uncaged/workflow-util";
export type SupervisorDecision = "continue" | "stop";
@@ -2,8 +2,8 @@ import { appendFile, mkdir, unlink, writeFile } from "node:fs/promises";
import { createServer, type Socket } from "node:net";
import { dirname, join } from "node:path";
import type { RoleOutput, WorkflowFn, WorkflowResult } from "@uncaged/workflow-runtime";
import { ensureUncagedWorkflowSymlink, importWorkflowBundleModule } from "../bundle/index.js";
import { createCasStore } from "../cas/index.js";
import { ensureUncagedWorkflowSymlink, importWorkflowBundleModule } from "@uncaged/workflow-register";
import { createCasStore } from "@uncaged/workflow-cas";
import {
createLogger,
err,
@@ -11,7 +11,7 @@ import {
normalizeRefsField,
ok,
type Result,
} from "../util/index.js";
} from "@uncaged/workflow-util";
import { executeThread } from "./engine.js";
import { createThreadPauseGate } from "./thread-pause-gate.js";
import type { ExecuteThreadIo, PrefilledDiskStep, ThreadPauseGate } from "./types.js";
@@ -1,7 +1,7 @@
import type { ExtractContext, ExtractFn, LlmProvider } from "@uncaged/workflow-runtime";
import type * as z from "zod/v4";
import { type CasStore, getContentMerklePayload } from "../cas/index.js";
import { createLlmFn, createThreadReactor } from "../reactor/index.js";
import { type CasStore, getContentMerklePayload } from "@uncaged/workflow-cas";
import { createLlmFn, createThreadReactor } from "@uncaged/workflow-reactor";
import { extractFunctionToolFromZodSchema } from "./llm-extract.js";
export type ExtractDeps = {
@@ -1,6 +1,6 @@
import * as z from "zod/v4";
import { err, ok, type Result } from "../util/index.js";
import { err, ok, type Result } from "@uncaged/workflow-util";
import type { LlmError, LlmExtractArgs } from "./types.js";
+35
View File
@@ -0,0 +1,35 @@
export { createWorkflow } from "./engine/create-workflow.js";
export { executeThread } from "./engine/engine.js";
export {
buildForkPlan,
parseThreadDataJsonl,
selectForkHistoricalSteps,
tryParseRoleStepRecord,
tryParseWorkflowResultRecord,
} from "./engine/fork-thread.js";
export { garbageCollectCas } from "./engine/gc.js";
export { createThreadPauseGate } from "./engine/thread-pause-gate.js";
export type {
ExecuteThreadIo,
ExecuteThreadOptions,
ForkHistoricalStep,
ForkPlan,
GcResult,
ParsedThreadStartRecord,
PrefilledDiskStep,
SupervisorDecision,
ThreadPauseGate,
} from "./engine/types.js";
export { getWorkerHostScriptPath } from "./engine/worker-entry-path.js";
export {
buildExtractUserContent,
createExtract,
type ExtractThreadContext,
} from "./extract/index.js";
export {
extractFunctionToolFromZodSchema,
llmErrorToCause,
llmExtract,
} from "./extract/index.js";
export type { ExtractFn, LlmError, LlmExtractArgs } from "./extract/index.js";
export { workflowAsAgent, type WorkflowAsAgentOptions } from "./workflow-as-agent.js";
@@ -1,17 +1,17 @@
import { join } from "node:path";
import type { AgentContext, AgentFn } from "@uncaged/workflow-runtime";
import { extractBundleExports } from "./bundle/index.js";
import { createCasStore } from "./cas/index.js";
import { extractBundleExports } from "@uncaged/workflow-register";
import { createCasStore } from "@uncaged/workflow-cas";
import type { ExecuteThreadIo } from "./engine/index.js";
import { executeThread } from "./engine/index.js";
import type { WorkflowConfig } from "./registry/index.js";
import { getRegisteredWorkflow, readWorkflowRegistry } from "./registry/index.js";
import type { WorkflowConfig } from "@uncaged/workflow-register";
import { getRegisteredWorkflow, readWorkflowRegistry } from "@uncaged/workflow-register";
import {
createLogger,
generateUlid,
getDefaultWorkflowStorageRoot,
getGlobalCasDir,
} from "./util/index.js";
} from "@uncaged/workflow-util";
const DEFAULT_WORKFLOW_AS_AGENT_MAX_DEPTH = 3;
+16
View File
@@ -0,0 +1,16 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"rootDir": "src",
"outDir": "dist"
},
"include": ["src"],
"references": [
{ "path": "../workflow-protocol" },
{ "path": "../workflow-runtime" },
{ "path": "../workflow-util" },
{ "path": "../workflow-cas" },
{ "path": "../workflow-reactor" },
{ "path": "../workflow-register" }
]
}
+18
View File
@@ -0,0 +1,18 @@
{
"name": "@uncaged/workflow-protocol",
"version": "0.1.0",
"type": "module",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./src/index.ts"
}
},
"peerDependencies": {
"zod": "^4.0.0"
},
"devDependencies": {
"zod": "^4.0.0",
"typescript": "^5.8.3"
}
}
+40
View File
@@ -0,0 +1,40 @@
// ── Types ──────────────────────────────────────────────────────────
export type {
Result,
CasStore,
WorkflowRoleSchema,
WorkflowRoleDescriptor,
WorkflowDescriptor,
RoleMeta,
RoleOutput,
StartStep,
RoleStep,
ThreadContext,
ModeratorContext,
AgentContext,
ExtractContext,
WorkflowCompletion,
WorkflowResult,
LlmProvider,
ProviderConfig,
ResolvedModel,
WorkflowConfig,
ExtractFn,
AgentFn,
AgentBinding,
WorkflowRuntime,
WorkflowFn,
RoleDefinition,
Moderator,
WorkflowDefinition,
AdvanceOutcome,
} from "./types.js";
// ── Constants ──────────────────────────────────────────────────────
export { START, END } from "./types.js";
// ── Constructor functions ──────────────────────────────────────────
export { ok, err } from "./result.js";
+9
View File
@@ -0,0 +1,9 @@
import type { Result } from "./types.js";
export function ok<T>(value: T): Result<T, never> {
return { ok: true, value };
}
export function err<E>(error: E): Result<never, E> {
return { ok: false, error };
}
+167
View File
@@ -0,0 +1,167 @@
import type * as z from "zod/v4";
// ── Constants ──────────────────────────────────────────────────────
export const START = "__start__" as const;
export const END = "__end__" as const;
// ── Result ─────────────────────────────────────────────────────────
export type Result<T, E = Error> = { ok: true; value: T } | { ok: false; error: E };
// ── CAS ────────────────────────────────────────────────────────────
export type CasStore = {
put(content: string): Promise<string>;
get(hash: string): Promise<string | null>;
delete(hash: string): Promise<void>;
list(): Promise<string[]>;
};
// ── Workflow Descriptor ────────────────────────────────────────────
export type WorkflowRoleSchema = Record<string, unknown>;
export type WorkflowRoleDescriptor = {
description: string;
schema: WorkflowRoleSchema;
};
export type WorkflowDescriptor = {
description: string;
roles: Record<string, WorkflowRoleDescriptor>;
};
// ── Role & Thread ──────────────────────────────────────────────────
export type RoleMeta = Record<string, Record<string, unknown>>;
export type RoleOutput = {
role: string;
contentHash: string;
meta: Record<string, unknown>;
refs: string[];
};
export type StartStep = {
role: typeof START;
content: string;
meta: { maxRounds: number };
timestamp: number;
};
export type RoleStep<M extends RoleMeta> = {
[K in keyof M & string]: {
role: K;
meta: M[K];
contentHash: string;
refs: string[];
timestamp: number;
};
}[keyof M & string];
export type ThreadContext<M extends RoleMeta = RoleMeta> = {
threadId: string;
depth: number;
start: StartStep;
steps: RoleStep<M>[];
};
export type ModeratorContext<M extends RoleMeta = RoleMeta> = ThreadContext<M>;
export type AgentContext<M extends RoleMeta = RoleMeta> = ModeratorContext<M> & {
currentRole: {
name: string;
systemPrompt: string;
};
};
export type ExtractContext<M extends RoleMeta = RoleMeta> = AgentContext<M> & {
agentContent: string;
};
// ── Workflow Completion ────────────────────────────────────────────
export type WorkflowCompletion = {
returnCode: number;
summary: string;
};
export type WorkflowResult = WorkflowCompletion & {
rootHash: string;
};
// ── LLM Provider ───────────────────────────────────────────────────
export type LlmProvider = {
baseUrl: string;
apiKey: string;
model: string;
};
export type ProviderConfig = {
baseUrl: string;
apiKey: string;
};
export type ResolvedModel = {
baseUrl: string;
apiKey: string;
model: string;
};
export type WorkflowConfig = {
maxDepth: number;
supervisorInterval: number;
providers: Record<string, ProviderConfig>;
models: Record<string, string>;
};
// ── Functions ──────────────────────────────────────────────────────
export type ExtractFn = <T extends Record<string, unknown>>(
schema: z.ZodType<T>,
prompt: string,
ctx: ExtractContext,
) => Promise<T>;
export type AgentFn = (ctx: AgentContext) => Promise<string>;
export type AgentBinding = {
agent: AgentFn;
overrides: Partial<Record<string, AgentFn>> | null;
};
// ── Workflow Runtime & Definition ──────────────────────────────────
export type WorkflowRuntime = {
cas: CasStore;
extract: ExtractFn;
};
export type WorkflowFn = (
thread: ThreadContext,
runtime: WorkflowRuntime,
) => AsyncGenerator<RoleOutput, WorkflowCompletion>;
export type RoleDefinition<Meta extends Record<string, unknown>> = {
description: string;
systemPrompt: string;
extractPrompt: string;
schema: z.ZodType<Meta>;
extractRefs: ((meta: Meta) => string[]) | null;
};
export type Moderator<M extends RoleMeta> = (
ctx: ModeratorContext<M>,
) => (keyof M & string) | typeof END;
export type WorkflowDefinition<M extends RoleMeta> = {
description: string;
roles: { [K in keyof M & string]: RoleDefinition<M[K]> };
moderator: Moderator<M>;
};
export type AdvanceOutcome<M extends RoleMeta> =
| { kind: "complete"; completion: WorkflowCompletion }
| { kind: "yield"; output: RoleOutput; step: RoleStep<M> };
+8
View File
@@ -0,0 +1,8 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"rootDir": "src",
"outDir": "dist"
},
"include": ["src"]
}
+21
View File
@@ -0,0 +1,21 @@
{
"name": "@uncaged/workflow-reactor",
"version": "0.1.0",
"type": "module",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./src/index.ts"
}
},
"dependencies": {
"@uncaged/workflow-protocol": "workspace:*"
},
"peerDependencies": {
"zod": "^4.0.0"
},
"devDependencies": {
"zod": "^4.0.0",
"typescript": "^5.8.3"
}
}
@@ -1,6 +1,6 @@
import type { LlmProvider } from "@uncaged/workflow-runtime";
import type { LlmProvider } from "@uncaged/workflow-protocol";
import { err, ok } from "../util/index.js";
import { err, ok } from "@uncaged/workflow-protocol";
import type { ChatMessage, LlmFn, ToolDefinition } from "./types.js";
@@ -1,6 +1,6 @@
import type * as z from "zod/v4";
import { err, ok, type Result } from "../util/index.js";
import { err, ok, type Result } from "@uncaged/workflow-protocol";
import type {
ChatMessage,
@@ -1,6 +1,6 @@
import type * as z from "zod/v4";
import type { Result } from "../util/index.js";
import type { Result } from "@uncaged/workflow-protocol";
export type ToolCall = {
id: string;
+11
View File
@@ -0,0 +1,11 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"rootDir": "src",
"outDir": "dist"
},
"include": ["src"],
"references": [
{ "path": "../workflow-protocol" }
]
}
+26
View File
@@ -0,0 +1,26 @@
{
"name": "@uncaged/workflow-register",
"version": "0.1.0",
"type": "module",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./src/index.ts"
}
},
"dependencies": {
"@uncaged/workflow-protocol": "workspace:*",
"@uncaged/workflow-util": "workspace:*"
},
"peerDependencies": {
"acorn": "^8.0.0",
"yaml": "^2.0.0",
"zod": "^4.0.0"
},
"devDependencies": {
"acorn": "^8.14.1",
"yaml": "^2.7.1",
"zod": "^4.0.0",
"typescript": "^5.8.3"
}
}
@@ -1,4 +1,4 @@
import type { RoleMeta, WorkflowDefinition } from "@uncaged/workflow-runtime";
import type { RoleMeta, WorkflowDefinition } from "@uncaged/workflow-protocol";
import * as z from "zod/v4";
import type { WorkflowDescriptor, WorkflowRoleSchema } from "./types.js";
@@ -12,7 +12,7 @@ import type {
} from "acorn";
import * as acorn from "acorn";
import { err, ok, type Result } from "../util/index.js";
import { err, ok, type Result } from "@uncaged/workflow-util";
import type { WorkflowBundleValidationInput } from "./types.js";
@@ -38,7 +38,11 @@ function isAllowedImportSpecifier(spec: string): boolean {
if (spec.startsWith(".") || spec.startsWith("/") || spec.startsWith("file:")) {
return false;
}
if (spec === "@uncaged/workflow" || spec === "@uncaged/workflow-runtime") {
if (
spec === "@uncaged/workflow" ||
spec === "@uncaged/workflow-runtime" ||
spec === "@uncaged/workflow-cas"
) {
return true;
}
return isBuiltin(spec);
@@ -294,7 +298,7 @@ function validateImportDeclaration(node: ImportDeclaration): string | null {
return "only static string import specifiers are allowed";
}
if (!isAllowedImportSpecifier(spec)) {
return `disallowed import specifier "${spec}" (only Node built-ins and "@uncaged/workflow" are allowed)`;
return `disallowed import specifier "${spec}" (only Node built-ins and @uncaged/workflow-* packages are allowed)`;
}
return null;
}
@@ -309,7 +313,7 @@ function validateExportSource(
return staticMessage;
}
if (!isAllowedImportSpecifier(spec)) {
return `${disallowedPrefix} "${spec}" (only Node built-ins and "@uncaged/workflow" are allowed)`;
return `${disallowedPrefix} "${spec}" (only Node built-ins and @uncaged/workflow-* packages are allowed)`;
}
return null;
}
@@ -0,0 +1,56 @@
import { mkdir, readlink, symlink, unlink } from "node:fs/promises";
import path from "node:path";
import { fileURLToPath } from "node:url";
/** This module lives in `@uncaged/workflow-register/src/bundle`; grandparent dir is the package root. */
function installedWorkflowPackageDir(): string {
return fileURLToPath(new URL("../..", import.meta.url));
}
/**
* Resolve sibling @uncaged/* package directory relative to workflow-register.
* In a monorepo workspace layout the sibling packages live next to workflow-register.
*/
function siblingPackageDir(packageName: string): string {
const registerRoot = installedWorkflowPackageDir();
return path.resolve(registerRoot, "..", packageName);
}
async function ensureSymlink(linkDir: string, name: string, target: string): Promise<void> {
const linkPath = path.join(linkDir, name);
await mkdir(linkDir, { recursive: true });
try {
const existing = await readlink(linkPath);
const normalizedExisting = path.resolve(linkDir, existing);
if (normalizedExisting === target) {
return;
}
await unlink(linkPath);
} catch (e) {
const errObj = e as NodeJS.ErrnoException;
if (errObj.code !== "ENOENT" && errObj.code !== "EINVAL") {
throw e;
}
}
const linkType = process.platform === "win32" ? "junction" : "dir";
await symlink(target, linkPath, linkType);
}
/**
* Ensures `<storageRoot>/node_modules/@uncaged/*` symlinks point at installed packages
* so workflow bundles loaded from `<storageRoot>/bundles/*.esm.js` can resolve their imports.
*/
export async function ensureUncagedWorkflowSymlink(storageRoot: string): Promise<void> {
const linkDir = path.join(storageRoot, "node_modules", "@uncaged");
const packages = [
{ name: "workflow", dir: siblingPackageDir("workflow") },
{ name: "workflow-runtime", dir: siblingPackageDir("workflow-runtime") },
{ name: "workflow-cas", dir: siblingPackageDir("workflow-cas") },
{ name: "workflow-protocol", dir: siblingPackageDir("workflow-protocol") },
];
for (const pkg of packages) {
await ensureSymlink(linkDir, pkg.name, pkg.dir);
}
}
@@ -1,5 +1,5 @@
import type { WorkflowFn } from "@uncaged/workflow-runtime";
import { err, ok, type Result } from "../util/index.js";
import type { WorkflowFn } from "@uncaged/workflow-protocol";
import { err, ok, type Result } from "@uncaged/workflow-util";
import { importWorkflowBundleModule } from "./bundle-import-env.js";
import { ensureUncagedWorkflowSymlink } from "./ensure-uncaged-workflow-symlink.js";
import type { ExtractBundleExportsOptions, ExtractedBundleExports } from "./types.js";
@@ -1,10 +1,11 @@
import type { WorkflowDescriptor, WorkflowFn } from "@uncaged/workflow-runtime";
import type { WorkflowDescriptor, WorkflowFn } from "@uncaged/workflow-protocol";
export type {
WorkflowDescriptor,
WorkflowRoleDescriptor,
WorkflowRoleSchema,
} from "@uncaged/workflow-runtime";
WorkflowFn,
} from "@uncaged/workflow-protocol";
export type WorkflowBundleValidationInput = {
/** Absolute or relative path (used for `.esm.js` suffix checks). */
@@ -1,4 +1,4 @@
import { err, ok, type Result } from "../util/index.js";
import { err, ok, type Result } from "@uncaged/workflow-util";
import type { WorkflowDescriptor, WorkflowRoleDescriptor, WorkflowRoleSchema } from "./types.js";
@@ -1,5 +1,5 @@
import type { WorkflowConfig } from "../registry/index.js";
import { err, ok, type Result } from "../util/index.js";
import type { WorkflowConfig } from "@uncaged/workflow-protocol";
import { err, ok, type Result } from "@uncaged/workflow-util";
import { splitProviderModelRef } from "./split-provider-model-ref.js";
import type { ResolvedModel } from "./types.js";
@@ -1,4 +1,4 @@
import { err, ok, type Result } from "../util/index.js";
import { err, ok, type Result } from "@uncaged/workflow-util";
/** Parses `providerName/modelName` references used in {@link WorkflowConfig.models}. */
export function splitProviderModelRef(
@@ -0,0 +1 @@
export type { ProviderConfig, ResolvedModel } from "@uncaged/workflow-protocol";
+39
View File
@@ -0,0 +1,39 @@
export {
buildDescriptor,
importWorkflowBundleModule,
validateWorkflowBundle,
ensureUncagedWorkflowSymlink,
extractBundleExports,
stringifyWorkflowDescriptor,
validateWorkflowDescriptor,
} from "./bundle/index.js";
export type {
ExtractBundleExportsOptions,
ExtractedBundleExports,
WorkflowBundleValidationInput,
WorkflowDescriptor,
WorkflowRoleDescriptor,
WorkflowRoleSchema,
} from "./bundle/index.js";
export {
getRegisteredWorkflow,
listRegisteredWorkflowNames,
parseWorkflowRegistryYaml,
readWorkflowRegistry,
registerWorkflowVersion,
rollbackWorkflowToHistoryHash,
stringifyWorkflowRegistryYaml,
unregisterWorkflow,
workflowRegistryPath,
writeWorkflowRegistry,
} from "./registry/index.js";
export type {
WorkflowConfig,
WorkflowHistoryEntry,
WorkflowRegistryEntry,
WorkflowRegistryFile,
} from "./registry/index.js";
export { resolveModel, splitProviderModelRef } from "./config/index.js";
export type { ProviderConfig, ResolvedModel } from "./config/index.js";

Some files were not shown because too many files have changed in this diff Show More