refactor(cli): restructure cmd-*.ts into commands/ subdirectories
Reorganize flat cmd-*.ts files into commands/{workflow,thread,cas,init}/
subdirectories that strictly mirror the CLI subcommand hierarchy:
- workflow/: add, list, show, rm, history, rollback
- thread/: run, list, show, rm, fork, ps, kill, live, pause, resume
- cas/: get, put, list, rm, gc
- init/: workspace, template
Each group has an index.ts re-export. Split multi-command files
(cmd-cas.ts, cmd-thread.ts, cmd-init.ts) into per-subcommand files.
Rename cmd-help.ts → skill.ts to match the primary command name.
Update all import paths in cli-dispatch.ts and test files.
Pure structural change — no logic modifications.
Ref: #93, closes #94
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import type { ParsedAddArgv } from "../src/cmd-add.js";
|
import type { ParsedAddArgv } from "../src/commands/workflow/add.js";
|
||||||
|
|
||||||
export function addCliArgs(name: string, filePath: string): ParsedAddArgv {
|
export function addCliArgs(name: string, filePath: string): ParsedAddArgv {
|
||||||
return { name, filePath, typesPath: null };
|
return { name, filePath, typesPath: null };
|
||||||
|
|||||||
@@ -4,13 +4,16 @@ import { tmpdir } from "node:os";
|
|||||||
import { join } from "node:path";
|
import { join } from "node:path";
|
||||||
|
|
||||||
import { getGlobalCasDir, getRegisteredWorkflow, readWorkflowRegistry } from "@uncaged/workflow";
|
import { getGlobalCasDir, getRegisteredWorkflow, readWorkflowRegistry } from "@uncaged/workflow";
|
||||||
import { cmdAdd } from "../src/cmd-add.js";
|
import { cmdCasGet } from "../src/commands/cas/get.js";
|
||||||
import { cmdCasGet, cmdCasList, cmdCasPut, cmdCasRm } from "../src/cmd-cas.js";
|
import { cmdCasList } from "../src/commands/cas/list.js";
|
||||||
import { cmdHistory } from "../src/cmd-history.js";
|
import { cmdCasPut } from "../src/commands/cas/put.js";
|
||||||
import { cmdList, formatListLines } from "../src/cmd-list.js";
|
import { cmdCasRm } from "../src/commands/cas/rm.js";
|
||||||
import { cmdRemove } from "../src/cmd-remove.js";
|
import { cmdAdd } from "../src/commands/workflow/add.js";
|
||||||
import { cmdRollback } from "../src/cmd-rollback.js";
|
import { cmdHistory } from "../src/commands/workflow/history.js";
|
||||||
import { cmdShow } from "../src/cmd-show.js";
|
import { cmdList, formatListLines } from "../src/commands/workflow/list.js";
|
||||||
|
import { cmdRemove } from "../src/commands/workflow/rm.js";
|
||||||
|
import { cmdRollback } from "../src/commands/workflow/rollback.js";
|
||||||
|
import { cmdShow } from "../src/commands/workflow/show.js";
|
||||||
import { addCliArgs } from "./bundle-fixture.js";
|
import { addCliArgs } from "./bundle-fixture.js";
|
||||||
|
|
||||||
const fixtureDescriptor = `export const descriptor = { description: "fixture", roles: {} };
|
const fixtureDescriptor = `export const descriptor = { description: "fixture", roles: {} };
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ import { mkdir, mkdtemp, readFile, rm, writeFile } 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, getContentMerklePayload, getGlobalCasDir } from "@uncaged/workflow";
|
import { createCasStore, getContentMerklePayload, getGlobalCasDir } from "@uncaged/workflow";
|
||||||
import { cmdAdd } from "../src/cmd-add.js";
|
import { cmdFork } from "../src/commands/thread/fork.js";
|
||||||
import { cmdFork } from "../src/cmd-fork.js";
|
import { cmdRun } from "../src/commands/thread/run.js";
|
||||||
import { cmdRun } from "../src/cmd-run.js";
|
import { cmdAdd } from "../src/commands/workflow/add.js";
|
||||||
import { pathExists } from "../src/fs-utils.js";
|
import { pathExists } from "../src/fs-utils.js";
|
||||||
import { addCliArgs } from "./bundle-fixture.js";
|
import { addCliArgs } from "./bundle-fixture.js";
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import {
|
|||||||
getGlobalCasDir,
|
getGlobalCasDir,
|
||||||
putContentMerkleNode,
|
putContentMerkleNode,
|
||||||
} from "@uncaged/workflow";
|
} from "@uncaged/workflow";
|
||||||
import { cmdThreadRemove } from "../src/cmd-thread.js";
|
import { cmdThreadRemove } from "../src/commands/thread/rm.js";
|
||||||
import { pathExists } from "../src/fs-utils.js";
|
import { pathExists } from "../src/fs-utils.js";
|
||||||
|
|
||||||
const cliEntryPath = fileURLToPath(new URL("../src/cli.ts", import.meta.url));
|
const cliEntryPath = fileURLToPath(new URL("../src/cli.ts", import.meta.url));
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import {
|
|||||||
formatSkillIndex,
|
formatSkillIndex,
|
||||||
formatSkillTopic,
|
formatSkillTopic,
|
||||||
getSkillTopics,
|
getSkillTopics,
|
||||||
} from "../src/cmd-help.js";
|
} from "../src/skill.js";
|
||||||
|
|
||||||
const STORAGE_ROOT = "/tmp/help-test-storage";
|
const STORAGE_ROOT = "/tmp/help-test-storage";
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,8 @@ import { tmpdir } from "node:os";
|
|||||||
import { join } from "node:path";
|
import { join } from "node:path";
|
||||||
|
|
||||||
import { runCli } from "../src/cli-dispatch.js";
|
import { runCli } from "../src/cli-dispatch.js";
|
||||||
import { cmdInitTemplate, cmdInitWorkspace } from "../src/cmd-init.js";
|
import { cmdInitTemplate } from "../src/commands/init/template.js";
|
||||||
|
import { cmdInitWorkspace } from "../src/commands/init/workspace.js";
|
||||||
import { pathExists } from "../src/fs-utils.js";
|
import { pathExists } from "../src/fs-utils.js";
|
||||||
|
|
||||||
describe("init template", () => {
|
describe("init template", () => {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { tmpdir } from "node:os";
|
|||||||
import { join } from "node:path";
|
import { join } from "node:path";
|
||||||
|
|
||||||
import { formatCliUsage, runCli } from "../src/cli-dispatch.js";
|
import { formatCliUsage, runCli } from "../src/cli-dispatch.js";
|
||||||
import { cmdInitWorkspace } from "../src/cmd-init.js";
|
import { cmdInitWorkspace } from "../src/commands/init/workspace.js";
|
||||||
import { pathExists } from "../src/fs-utils.js";
|
import { pathExists } from "../src/fs-utils.js";
|
||||||
|
|
||||||
describe("init workspace", () => {
|
describe("init workspace", () => {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import {
|
|||||||
LIVE_CONTENT_MAX_LINES,
|
LIVE_CONTENT_MAX_LINES,
|
||||||
type LiveRoleRow,
|
type LiveRoleRow,
|
||||||
renderLiveRoleStepLines,
|
renderLiveRoleStepLines,
|
||||||
} from "../src/cmd-live.js";
|
} from "../src/commands/thread/live.js";
|
||||||
import { parseLiveArgv } from "../src/live-argv.js";
|
import { parseLiveArgv } from "../src/live-argv.js";
|
||||||
|
|
||||||
const cliEntryPath = fileURLToPath(new URL("../src/cli.ts", import.meta.url));
|
const cliEntryPath = fileURLToPath(new URL("../src/cli.ts", import.meta.url));
|
||||||
|
|||||||
@@ -5,15 +5,16 @@ import { tmpdir } from "node:os";
|
|||||||
import { dirname, join } from "node:path";
|
import { dirname, join } from "node:path";
|
||||||
import { fileURLToPath } from "node:url";
|
import { fileURLToPath } from "node:url";
|
||||||
import { getGlobalCasDir } from "@uncaged/workflow";
|
import { getGlobalCasDir } from "@uncaged/workflow";
|
||||||
import { cmdAdd } from "../src/cmd-add.js";
|
import { cmdCasPut } from "../src/commands/cas/put.js";
|
||||||
import { cmdCasPut } from "../src/cmd-cas.js";
|
import { cmdKill } from "../src/commands/thread/kill.js";
|
||||||
import { cmdKill } from "../src/cmd-kill.js";
|
import { cmdThreads } from "../src/commands/thread/list.js";
|
||||||
import { cmdPause } from "../src/cmd-pause.js";
|
import { cmdPause } from "../src/commands/thread/pause.js";
|
||||||
import { cmdPs } from "../src/cmd-ps.js";
|
import { cmdPs } from "../src/commands/thread/ps.js";
|
||||||
import { cmdResume } from "../src/cmd-resume.js";
|
import { cmdResume } from "../src/commands/thread/resume.js";
|
||||||
import { cmdRun } from "../src/cmd-run.js";
|
import { cmdThreadRemove } from "../src/commands/thread/rm.js";
|
||||||
import { cmdThreadRemove, cmdThreadShow } from "../src/cmd-thread.js";
|
import { cmdRun } from "../src/commands/thread/run.js";
|
||||||
import { cmdThreads } from "../src/cmd-threads.js";
|
import { cmdThreadShow } from "../src/commands/thread/show.js";
|
||||||
|
import { cmdAdd } from "../src/commands/workflow/add.js";
|
||||||
import { pathExists, readTextFileIfExists } from "../src/fs-utils.js";
|
import { pathExists, readTextFileIfExists } from "../src/fs-utils.js";
|
||||||
import { addCliArgs } from "./bundle-fixture.js";
|
import { addCliArgs } from "./bundle-fixture.js";
|
||||||
|
|
||||||
|
|||||||
@@ -1,30 +1,30 @@
|
|||||||
import { printCliError, printCliLine, printCliWarn } from "./cli-output.js";
|
import { printCliError, printCliLine, printCliWarn } from "./cli-output.js";
|
||||||
import { cmdAdd, formatAddSuccess, parseAddArgv } from "./cmd-add.js";
|
import { cmdGc } from "./commands/cas/gc.js";
|
||||||
import { cmdCasGet, cmdCasList, cmdCasPut, cmdCasRm } from "./cmd-cas.js";
|
import { cmdCasGet } from "./commands/cas/get.js";
|
||||||
import { cmdFork, parseForkArgv } from "./cmd-fork.js";
|
import { cmdCasList } from "./commands/cas/list.js";
|
||||||
import { cmdGc } from "./cmd-gc.js";
|
import { cmdCasPut } from "./commands/cas/put.js";
|
||||||
import {
|
import { cmdCasRm } from "./commands/cas/rm.js";
|
||||||
formatSkillDoc,
|
import { cmdInitTemplate } from "./commands/init/template.js";
|
||||||
formatSkillIndex,
|
import { cmdInitWorkspace } from "./commands/init/workspace.js";
|
||||||
formatSkillTopic,
|
import { cmdFork, parseForkArgv } from "./commands/thread/fork.js";
|
||||||
getSkillTopics,
|
import { cmdKill } from "./commands/thread/kill.js";
|
||||||
} from "./cmd-help.js";
|
import { cmdThreads } from "./commands/thread/list.js";
|
||||||
import { cmdHistory } from "./cmd-history.js";
|
import { cmdLive } from "./commands/thread/live.js";
|
||||||
import { cmdInitTemplate, cmdInitWorkspace } from "./cmd-init.js";
|
import { cmdPause } from "./commands/thread/pause.js";
|
||||||
import { cmdKill } from "./cmd-kill.js";
|
import { cmdPs } from "./commands/thread/ps.js";
|
||||||
import { cmdList, formatListLines } from "./cmd-list.js";
|
import { cmdResume } from "./commands/thread/resume.js";
|
||||||
import { cmdLive } from "./cmd-live.js";
|
import { cmdThreadRemove } from "./commands/thread/rm.js";
|
||||||
import { cmdPause } from "./cmd-pause.js";
|
import { cmdRun } from "./commands/thread/run.js";
|
||||||
import { cmdPs } from "./cmd-ps.js";
|
import { cmdThreadShow } from "./commands/thread/show.js";
|
||||||
import { cmdRemove } from "./cmd-remove.js";
|
import { cmdAdd, formatAddSuccess, parseAddArgv } from "./commands/workflow/add.js";
|
||||||
import { cmdResume } from "./cmd-resume.js";
|
import { cmdHistory } from "./commands/workflow/history.js";
|
||||||
import { cmdRollback } from "./cmd-rollback.js";
|
import { cmdList, formatListLines } from "./commands/workflow/list.js";
|
||||||
import { cmdRun } from "./cmd-run.js";
|
import { cmdRemove } from "./commands/workflow/rm.js";
|
||||||
import { cmdShow, formatShowYaml } from "./cmd-show.js";
|
import { cmdRollback } from "./commands/workflow/rollback.js";
|
||||||
import { cmdThreadRemove, cmdThreadShow } from "./cmd-thread.js";
|
import { cmdShow, formatShowYaml } from "./commands/workflow/show.js";
|
||||||
import { cmdThreads } from "./cmd-threads.js";
|
|
||||||
import { parseLiveArgv } from "./live-argv.js";
|
import { parseLiveArgv } from "./live-argv.js";
|
||||||
import { parseRunArgv } from "./run-argv.js";
|
import { parseRunArgv } from "./run-argv.js";
|
||||||
|
import { formatSkillIndex, formatSkillTopic, getSkillTopics } from "./skill.js";
|
||||||
|
|
||||||
type DispatchFn = (storageRoot: string, argv: string[]) => Promise<number>;
|
type DispatchFn = (storageRoot: string, argv: string[]) => Promise<number>;
|
||||||
|
|
||||||
|
|||||||
@@ -1,43 +0,0 @@
|
|||||||
import { createCasStore, err, getGlobalCasDir, ok, type Result } from "@uncaged/workflow";
|
|
||||||
|
|
||||||
export async function cmdCasGet(
|
|
||||||
storageRoot: string,
|
|
||||||
_threadId: string,
|
|
||||||
hash: string,
|
|
||||||
): Promise<Result<string, string>> {
|
|
||||||
const cas = createCasStore(getGlobalCasDir(storageRoot));
|
|
||||||
const content = await cas.get(hash);
|
|
||||||
if (content === null) {
|
|
||||||
return err(`cas entry not found: ${hash}`);
|
|
||||||
}
|
|
||||||
return ok(content);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function cmdCasPut(
|
|
||||||
storageRoot: string,
|
|
||||||
_threadId: string,
|
|
||||||
content: string,
|
|
||||||
): Promise<Result<string, string>> {
|
|
||||||
const cas = createCasStore(getGlobalCasDir(storageRoot));
|
|
||||||
const hash = await cas.put(content);
|
|
||||||
return ok(hash);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function cmdCasList(
|
|
||||||
storageRoot: string,
|
|
||||||
_threadId: string,
|
|
||||||
): Promise<Result<string[], string>> {
|
|
||||||
const cas = createCasStore(getGlobalCasDir(storageRoot));
|
|
||||||
const hashes = await cas.list();
|
|
||||||
return ok(hashes);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function cmdCasRm(
|
|
||||||
storageRoot: string,
|
|
||||||
_threadId: string,
|
|
||||||
hash: string,
|
|
||||||
): Promise<Result<void, string>> {
|
|
||||||
const cas = createCasStore(getGlobalCasDir(storageRoot));
|
|
||||||
await cas.delete(hash);
|
|
||||||
return ok(undefined);
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import { createCasStore, err, getGlobalCasDir, ok, type Result } from "@uncaged/workflow";
|
||||||
|
|
||||||
|
export async function cmdCasGet(
|
||||||
|
storageRoot: string,
|
||||||
|
_threadId: string,
|
||||||
|
hash: string,
|
||||||
|
): Promise<Result<string, string>> {
|
||||||
|
const cas = createCasStore(getGlobalCasDir(storageRoot));
|
||||||
|
const content = await cas.get(hash);
|
||||||
|
if (content === null) {
|
||||||
|
return err(`cas entry not found: ${hash}`);
|
||||||
|
}
|
||||||
|
return ok(content);
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
export { cmdGc } from "./gc.js";
|
||||||
|
export { cmdCasGet } from "./get.js";
|
||||||
|
export { cmdCasList } from "./list.js";
|
||||||
|
export { cmdCasPut } from "./put.js";
|
||||||
|
export { cmdCasRm } from "./rm.js";
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import { createCasStore, getGlobalCasDir, ok, type Result } from "@uncaged/workflow";
|
||||||
|
|
||||||
|
export async function cmdCasList(
|
||||||
|
storageRoot: string,
|
||||||
|
_threadId: string,
|
||||||
|
): Promise<Result<string[], string>> {
|
||||||
|
const cas = createCasStore(getGlobalCasDir(storageRoot));
|
||||||
|
const hashes = await cas.list();
|
||||||
|
return ok(hashes);
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import { createCasStore, getGlobalCasDir, ok, type Result } from "@uncaged/workflow";
|
||||||
|
|
||||||
|
export async function cmdCasPut(
|
||||||
|
storageRoot: string,
|
||||||
|
_threadId: string,
|
||||||
|
content: string,
|
||||||
|
): Promise<Result<string, string>> {
|
||||||
|
const cas = createCasStore(getGlobalCasDir(storageRoot));
|
||||||
|
const hash = await cas.put(content);
|
||||||
|
return ok(hash);
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import { createCasStore, getGlobalCasDir, ok, type Result } from "@uncaged/workflow";
|
||||||
|
|
||||||
|
export async function cmdCasRm(
|
||||||
|
storageRoot: string,
|
||||||
|
_threadId: string,
|
||||||
|
hash: string,
|
||||||
|
): Promise<Result<void, string>> {
|
||||||
|
const cas = createCasStore(getGlobalCasDir(storageRoot));
|
||||||
|
await cas.delete(hash);
|
||||||
|
return ok(undefined);
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
export type { CmdInitTemplateSuccess } from "./template.js";
|
||||||
|
export { cmdInitTemplate } from "./template.js";
|
||||||
|
export type { CmdInitWorkspaceSuccess } from "./workspace.js";
|
||||||
|
export { cmdInitWorkspace } from "./workspace.js";
|
||||||
@@ -0,0 +1,203 @@
|
|||||||
|
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
||||||
|
import { dirname, join, resolve } from "node:path";
|
||||||
|
|
||||||
|
import { err, ok, type Result } from "@uncaged/workflow";
|
||||||
|
|
||||||
|
import { pathExists } from "../../fs-utils.js";
|
||||||
|
|
||||||
|
export type CmdInitTemplateSuccess = {
|
||||||
|
templatePath: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
function validateWorkspaceSegment(name: string): Result<void, string> {
|
||||||
|
if (name.length === 0) {
|
||||||
|
return err("workspace name must not be empty");
|
||||||
|
}
|
||||||
|
if (name === "." || name === "..") {
|
||||||
|
return err("invalid workspace name");
|
||||||
|
}
|
||||||
|
if (name.includes("/") || name.includes("\\")) {
|
||||||
|
return err("workspace name must not contain path separators");
|
||||||
|
}
|
||||||
|
return ok(undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
function hasTemplatesWorkspaceGlob(workspaces: unknown): boolean {
|
||||||
|
return Array.isArray(workspaces) && workspaces.includes("templates/*");
|
||||||
|
}
|
||||||
|
|
||||||
|
async function readPackageJsonWorkspaces(dir: string): Promise<unknown | null> {
|
||||||
|
const pkgPath = join(dir, "package.json");
|
||||||
|
if (!(await pathExists(pkgPath))) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
let raw: string;
|
||||||
|
try {
|
||||||
|
raw = await readFile(pkgPath, "utf8");
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
let parsed: unknown;
|
||||||
|
try {
|
||||||
|
parsed = JSON.parse(raw) as unknown;
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (typeof parsed !== "object" || parsed === null || !("workspaces" in parsed)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (parsed as { workspaces: unknown }).workspaces;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Resolve uncaged-workflow workspace root (package.json with `templates/*` in `workspaces`). */
|
||||||
|
async function findWorkflowWorkspaceRoot(startDir: string): Promise<Result<string, string>> {
|
||||||
|
let dir = resolve(startDir);
|
||||||
|
for (;;) {
|
||||||
|
const workspaces = await readPackageJsonWorkspaces(dir);
|
||||||
|
if (workspaces !== null && hasTemplatesWorkspaceGlob(workspaces)) {
|
||||||
|
return ok(dir);
|
||||||
|
}
|
||||||
|
const parent = dirname(dir);
|
||||||
|
if (parent === dir) {
|
||||||
|
return err(
|
||||||
|
'not inside a workflow workspace (no package.json with workspaces containing "templates/*")',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
dir = parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function templatePackageJson(templateName: string): string {
|
||||||
|
return `${JSON.stringify(
|
||||||
|
{
|
||||||
|
name: `template-${templateName}`,
|
||||||
|
version: "0.0.0",
|
||||||
|
private: true,
|
||||||
|
type: "module",
|
||||||
|
dependencies: {
|
||||||
|
"@uncaged/workflow": "^0.1.0",
|
||||||
|
zod: "^4.0.0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
2,
|
||||||
|
)}\n`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function templateTsconfigJson(): string {
|
||||||
|
return `${JSON.stringify(
|
||||||
|
{
|
||||||
|
extends: "../../tsconfig.json",
|
||||||
|
compilerOptions: {
|
||||||
|
rootDir: "src",
|
||||||
|
outDir: "dist",
|
||||||
|
},
|
||||||
|
include: ["src/**/*.ts"],
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
2,
|
||||||
|
)}\n`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function templateRolesTs(): string {
|
||||||
|
return `import type { RoleDefinition } from "@uncaged/workflow";
|
||||||
|
import * as z from "zod/v4";
|
||||||
|
|
||||||
|
export const HELLO_TEMPLATE_DESCRIPTION =
|
||||||
|
"Minimal starter template: one greeter role, then END.";
|
||||||
|
|
||||||
|
export type HelloTemplateMeta = {
|
||||||
|
greeter: {
|
||||||
|
message: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const greeterMetaSchema = z.object({
|
||||||
|
message: z.string(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const greeterRole: RoleDefinition<HelloTemplateMeta["greeter"]> = {
|
||||||
|
description: "Says hello — replace with your first role.",
|
||||||
|
systemPrompt: "You are a helpful assistant. Reply with one short friendly sentence.",
|
||||||
|
extractPrompt: "Extract the assistant's greeting as message.",
|
||||||
|
schema: greeterMetaSchema,
|
||||||
|
extractRefs: null,
|
||||||
|
};
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function templateModeratorTs(): string {
|
||||||
|
return `import { END, type Moderator, type ModeratorContext } from "@uncaged/workflow";
|
||||||
|
|
||||||
|
import type { HelloTemplateMeta } from "./roles.js";
|
||||||
|
|
||||||
|
export const helloTemplateModerator: Moderator<HelloTemplateMeta> = (
|
||||||
|
ctx: ModeratorContext<HelloTemplateMeta>,
|
||||||
|
) => {
|
||||||
|
if (ctx.steps.length === 0) {
|
||||||
|
return "greeter";
|
||||||
|
}
|
||||||
|
return END;
|
||||||
|
};
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function templateIndexTs(): string {
|
||||||
|
return `import type { WorkflowDefinition } from "@uncaged/workflow";
|
||||||
|
|
||||||
|
import { helloTemplateModerator } from "./moderator.js";
|
||||||
|
import {
|
||||||
|
HELLO_TEMPLATE_DESCRIPTION,
|
||||||
|
type HelloTemplateMeta,
|
||||||
|
greeterRole,
|
||||||
|
} from "./roles.js";
|
||||||
|
|
||||||
|
export {
|
||||||
|
HELLO_TEMPLATE_DESCRIPTION,
|
||||||
|
type HelloTemplateMeta,
|
||||||
|
greeterRole,
|
||||||
|
} from "./roles.js";
|
||||||
|
export { helloTemplateModerator } from "./moderator.js";
|
||||||
|
|
||||||
|
export const helloTemplateWorkflowDefinition: WorkflowDefinition<HelloTemplateMeta> = {
|
||||||
|
description: HELLO_TEMPLATE_DESCRIPTION,
|
||||||
|
roles: {
|
||||||
|
greeter: greeterRole,
|
||||||
|
},
|
||||||
|
moderator: helloTemplateModerator,
|
||||||
|
};
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function cmdInitTemplate(
|
||||||
|
startDir: string,
|
||||||
|
templateName: string,
|
||||||
|
): Promise<Result<CmdInitTemplateSuccess, string>> {
|
||||||
|
const validated = validateWorkspaceSegment(templateName);
|
||||||
|
if (!validated.ok) {
|
||||||
|
return validated;
|
||||||
|
}
|
||||||
|
|
||||||
|
const rootResult = await findWorkflowWorkspaceRoot(startDir);
|
||||||
|
if (!rootResult.ok) {
|
||||||
|
return rootResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
const workspaceRoot = rootResult.value;
|
||||||
|
const templateDir = join(workspaceRoot, "templates", templateName);
|
||||||
|
if (await pathExists(templateDir)) {
|
||||||
|
return err(`template already exists: ${templateDir}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
await mkdir(join(templateDir, "src"), { recursive: true });
|
||||||
|
|
||||||
|
await Promise.all([
|
||||||
|
writeFile(join(templateDir, "package.json"), templatePackageJson(templateName), "utf8"),
|
||||||
|
writeFile(join(templateDir, "tsconfig.json"), templateTsconfigJson(), "utf8"),
|
||||||
|
writeFile(join(templateDir, "src", "roles.ts"), templateRolesTs(), "utf8"),
|
||||||
|
writeFile(join(templateDir, "src", "moderator.ts"), templateModeratorTs(), "utf8"),
|
||||||
|
writeFile(join(templateDir, "src", "index.ts"), templateIndexTs(), "utf8"),
|
||||||
|
]);
|
||||||
|
|
||||||
|
return ok({ templatePath: templateDir });
|
||||||
|
}
|
||||||
+3
-187
@@ -1,18 +1,14 @@
|
|||||||
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
import { mkdir, writeFile } from "node:fs/promises";
|
||||||
import { dirname, join, resolve } from "node:path";
|
import { join } from "node:path";
|
||||||
|
|
||||||
import { err, ok, type Result } from "@uncaged/workflow";
|
import { err, ok, type Result } from "@uncaged/workflow";
|
||||||
|
|
||||||
import { pathExists } from "./fs-utils.js";
|
import { pathExists } from "../../fs-utils.js";
|
||||||
|
|
||||||
export type CmdInitWorkspaceSuccess = {
|
export type CmdInitWorkspaceSuccess = {
|
||||||
rootPath: string;
|
rootPath: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type CmdInitTemplateSuccess = {
|
|
||||||
templatePath: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
function validateWorkspaceSegment(name: string): Result<void, string> {
|
function validateWorkspaceSegment(name: string): Result<void, string> {
|
||||||
if (name.length === 0) {
|
if (name.length === 0) {
|
||||||
return err("workspace name must not be empty");
|
return err("workspace name must not be empty");
|
||||||
@@ -233,183 +229,3 @@ export async function cmdInitWorkspace(
|
|||||||
|
|
||||||
return ok({ rootPath });
|
return ok({ rootPath });
|
||||||
}
|
}
|
||||||
|
|
||||||
function hasTemplatesWorkspaceGlob(workspaces: unknown): boolean {
|
|
||||||
return Array.isArray(workspaces) && workspaces.includes("templates/*");
|
|
||||||
}
|
|
||||||
|
|
||||||
async function readPackageJsonWorkspaces(dir: string): Promise<unknown | null> {
|
|
||||||
const pkgPath = join(dir, "package.json");
|
|
||||||
if (!(await pathExists(pkgPath))) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
let raw: string;
|
|
||||||
try {
|
|
||||||
raw = await readFile(pkgPath, "utf8");
|
|
||||||
} catch {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
let parsed: unknown;
|
|
||||||
try {
|
|
||||||
parsed = JSON.parse(raw) as unknown;
|
|
||||||
} catch {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (typeof parsed !== "object" || parsed === null || !("workspaces" in parsed)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return (parsed as { workspaces: unknown }).workspaces;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Resolve uncaged-workflow workspace root (package.json with `templates/*` in `workspaces`). */
|
|
||||||
async function findWorkflowWorkspaceRoot(startDir: string): Promise<Result<string, string>> {
|
|
||||||
let dir = resolve(startDir);
|
|
||||||
for (;;) {
|
|
||||||
const workspaces = await readPackageJsonWorkspaces(dir);
|
|
||||||
if (workspaces !== null && hasTemplatesWorkspaceGlob(workspaces)) {
|
|
||||||
return ok(dir);
|
|
||||||
}
|
|
||||||
const parent = dirname(dir);
|
|
||||||
if (parent === dir) {
|
|
||||||
return err(
|
|
||||||
'not inside a workflow workspace (no package.json with workspaces containing "templates/*")',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
dir = parent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function templatePackageJson(templateName: string): string {
|
|
||||||
return `${JSON.stringify(
|
|
||||||
{
|
|
||||||
name: `template-${templateName}`,
|
|
||||||
version: "0.0.0",
|
|
||||||
private: true,
|
|
||||||
type: "module",
|
|
||||||
dependencies: {
|
|
||||||
"@uncaged/workflow": "^0.1.0",
|
|
||||||
zod: "^4.0.0",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
null,
|
|
||||||
2,
|
|
||||||
)}\n`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function templateTsconfigJson(): string {
|
|
||||||
return `${JSON.stringify(
|
|
||||||
{
|
|
||||||
extends: "../../tsconfig.json",
|
|
||||||
compilerOptions: {
|
|
||||||
rootDir: "src",
|
|
||||||
outDir: "dist",
|
|
||||||
},
|
|
||||||
include: ["src/**/*.ts"],
|
|
||||||
},
|
|
||||||
null,
|
|
||||||
2,
|
|
||||||
)}\n`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function templateRolesTs(): string {
|
|
||||||
return `import type { RoleDefinition } from "@uncaged/workflow";
|
|
||||||
import * as z from "zod/v4";
|
|
||||||
|
|
||||||
export const HELLO_TEMPLATE_DESCRIPTION =
|
|
||||||
"Minimal starter template: one greeter role, then END.";
|
|
||||||
|
|
||||||
export type HelloTemplateMeta = {
|
|
||||||
greeter: {
|
|
||||||
message: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const greeterMetaSchema = z.object({
|
|
||||||
message: z.string(),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const greeterRole: RoleDefinition<HelloTemplateMeta["greeter"]> = {
|
|
||||||
description: "Says hello — replace with your first role.",
|
|
||||||
systemPrompt: "You are a helpful assistant. Reply with one short friendly sentence.",
|
|
||||||
extractPrompt: "Extract the assistant's greeting as message.",
|
|
||||||
schema: greeterMetaSchema,
|
|
||||||
extractRefs: null,
|
|
||||||
};
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function templateModeratorTs(): string {
|
|
||||||
return `import { END, type Moderator, type ModeratorContext } from "@uncaged/workflow";
|
|
||||||
|
|
||||||
import type { HelloTemplateMeta } from "./roles.js";
|
|
||||||
|
|
||||||
export const helloTemplateModerator: Moderator<HelloTemplateMeta> = (
|
|
||||||
ctx: ModeratorContext<HelloTemplateMeta>,
|
|
||||||
) => {
|
|
||||||
if (ctx.steps.length === 0) {
|
|
||||||
return "greeter";
|
|
||||||
}
|
|
||||||
return END;
|
|
||||||
};
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function templateIndexTs(): string {
|
|
||||||
return `import type { WorkflowDefinition } from "@uncaged/workflow";
|
|
||||||
|
|
||||||
import { helloTemplateModerator } from "./moderator.js";
|
|
||||||
import {
|
|
||||||
HELLO_TEMPLATE_DESCRIPTION,
|
|
||||||
type HelloTemplateMeta,
|
|
||||||
greeterRole,
|
|
||||||
} from "./roles.js";
|
|
||||||
|
|
||||||
export {
|
|
||||||
HELLO_TEMPLATE_DESCRIPTION,
|
|
||||||
type HelloTemplateMeta,
|
|
||||||
greeterRole,
|
|
||||||
} from "./roles.js";
|
|
||||||
export { helloTemplateModerator } from "./moderator.js";
|
|
||||||
|
|
||||||
export const helloTemplateWorkflowDefinition: WorkflowDefinition<HelloTemplateMeta> = {
|
|
||||||
description: HELLO_TEMPLATE_DESCRIPTION,
|
|
||||||
roles: {
|
|
||||||
greeter: greeterRole,
|
|
||||||
},
|
|
||||||
moderator: helloTemplateModerator,
|
|
||||||
};
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function cmdInitTemplate(
|
|
||||||
startDir: string,
|
|
||||||
templateName: string,
|
|
||||||
): Promise<Result<CmdInitTemplateSuccess, string>> {
|
|
||||||
const validated = validateWorkspaceSegment(templateName);
|
|
||||||
if (!validated.ok) {
|
|
||||||
return validated;
|
|
||||||
}
|
|
||||||
|
|
||||||
const rootResult = await findWorkflowWorkspaceRoot(startDir);
|
|
||||||
if (!rootResult.ok) {
|
|
||||||
return rootResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
const workspaceRoot = rootResult.value;
|
|
||||||
const templateDir = join(workspaceRoot, "templates", templateName);
|
|
||||||
if (await pathExists(templateDir)) {
|
|
||||||
return err(`template already exists: ${templateDir}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
await mkdir(join(templateDir, "src"), { recursive: true });
|
|
||||||
|
|
||||||
await Promise.all([
|
|
||||||
writeFile(join(templateDir, "package.json"), templatePackageJson(templateName), "utf8"),
|
|
||||||
writeFile(join(templateDir, "tsconfig.json"), templateTsconfigJson(), "utf8"),
|
|
||||||
writeFile(join(templateDir, "src", "roles.ts"), templateRolesTs(), "utf8"),
|
|
||||||
writeFile(join(templateDir, "src", "moderator.ts"), templateModeratorTs(), "utf8"),
|
|
||||||
writeFile(join(templateDir, "src", "index.ts"), templateIndexTs(), "utf8"),
|
|
||||||
]);
|
|
||||||
|
|
||||||
return ok({ templatePath: templateDir });
|
|
||||||
}
|
|
||||||
+3
-3
@@ -2,9 +2,9 @@ import { join } from "node:path";
|
|||||||
|
|
||||||
import { buildForkPlan, err, generateUlid, ok, type Result } from "@uncaged/workflow";
|
import { buildForkPlan, err, generateUlid, ok, type Result } from "@uncaged/workflow";
|
||||||
|
|
||||||
import { pathExists, readTextFileIfExists } from "./fs-utils.js";
|
import { pathExists, readTextFileIfExists } from "../../fs-utils.js";
|
||||||
import { resolveThreadDataPath } from "./thread-scan.js";
|
import { resolveThreadDataPath } from "../../thread-scan.js";
|
||||||
import { ensureWorkerForHash, sendWorkerTcpCommand } from "./worker-spawn.js";
|
import { ensureWorkerForHash, sendWorkerTcpCommand } from "../../worker-spawn.js";
|
||||||
|
|
||||||
export function parseForkArgv(
|
export function parseForkArgv(
|
||||||
argv: string[],
|
argv: string[],
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
export { cmdFork, parseForkArgv } from "./fork.js";
|
||||||
|
export { cmdKill } from "./kill.js";
|
||||||
|
export { cmdThreads } from "./list.js";
|
||||||
|
export type { LiveRoleRow } from "./live.js";
|
||||||
|
export {
|
||||||
|
cmdLive,
|
||||||
|
formatLiveDebugLine,
|
||||||
|
formatLiveTimeLabel,
|
||||||
|
LIVE_CONTENT_MAX_LINES,
|
||||||
|
renderLiveRoleStepLines,
|
||||||
|
} from "./live.js";
|
||||||
|
export { cmdPause } from "./pause.js";
|
||||||
|
export { cmdPs } from "./ps.js";
|
||||||
|
export { cmdResume } from "./resume.js";
|
||||||
|
export { cmdThreadRemove } from "./rm.js";
|
||||||
|
export { cmdRun } from "./run.js";
|
||||||
|
export { cmdThreadShow } from "./show.js";
|
||||||
+2
-2
@@ -2,12 +2,12 @@ import { join } from "node:path";
|
|||||||
|
|
||||||
import { err, type Result } from "@uncaged/workflow";
|
import { err, type Result } from "@uncaged/workflow";
|
||||||
|
|
||||||
import { readTextFileIfExists } from "./fs-utils.js";
|
import { readTextFileIfExists } from "../../fs-utils.js";
|
||||||
import {
|
import {
|
||||||
resolveRunningHashForThread,
|
resolveRunningHashForThread,
|
||||||
sendWorkerTcpCommand,
|
sendWorkerTcpCommand,
|
||||||
type WorkerCtl,
|
type WorkerCtl,
|
||||||
} from "./worker-spawn.js";
|
} from "../../worker-spawn.js";
|
||||||
|
|
||||||
export async function cmdKill(
|
export async function cmdKill(
|
||||||
storageRoot: string,
|
storageRoot: string,
|
||||||
+2
-2
@@ -1,7 +1,7 @@
|
|||||||
import { err, ok, type Result } from "@uncaged/workflow";
|
import { err, ok, type Result } from "@uncaged/workflow";
|
||||||
|
|
||||||
import { listHistoricalThreads } from "./thread-scan.js";
|
import { listHistoricalThreads } from "../../thread-scan.js";
|
||||||
import { validateCliWorkflowName } from "./workflow-name.js";
|
import { validateCliWorkflowName } from "../../workflow-name.js";
|
||||||
|
|
||||||
export async function cmdThreads(
|
export async function cmdThreads(
|
||||||
storageRoot: string,
|
storageRoot: string,
|
||||||
+4
-4
@@ -12,10 +12,10 @@ import {
|
|||||||
type WorkflowCompletion,
|
type WorkflowCompletion,
|
||||||
} from "@uncaged/workflow";
|
} from "@uncaged/workflow";
|
||||||
|
|
||||||
import { printCliError, printCliLine } from "./cli-output.js";
|
import { printCliError, printCliLine } from "../../cli-output.js";
|
||||||
import { pathExists } from "./fs-utils.js";
|
import { pathExists } from "../../fs-utils.js";
|
||||||
import type { ParsedLiveArgv } from "./live-argv.js";
|
import type { ParsedLiveArgv } from "../../live-argv.js";
|
||||||
import { findLatestThreadDataPath, resolveThreadDataPath } from "./thread-scan.js";
|
import { findLatestThreadDataPath, resolveThreadDataPath } from "../../thread-scan.js";
|
||||||
|
|
||||||
export const LIVE_CONTENT_MAX_LINES = 10;
|
export const LIVE_CONTENT_MAX_LINES = 10;
|
||||||
|
|
||||||
+2
-2
@@ -2,12 +2,12 @@ import { join } from "node:path";
|
|||||||
|
|
||||||
import { err, type Result } from "@uncaged/workflow";
|
import { err, type Result } from "@uncaged/workflow";
|
||||||
|
|
||||||
import { readTextFileIfExists } from "./fs-utils.js";
|
import { readTextFileIfExists } from "../../fs-utils.js";
|
||||||
import {
|
import {
|
||||||
resolveRunningHashForThread,
|
resolveRunningHashForThread,
|
||||||
sendWorkerTcpCommand,
|
sendWorkerTcpCommand,
|
||||||
type WorkerCtl,
|
type WorkerCtl,
|
||||||
} from "./worker-spawn.js";
|
} from "../../worker-spawn.js";
|
||||||
|
|
||||||
export async function cmdPause(
|
export async function cmdPause(
|
||||||
storageRoot: string,
|
storageRoot: string,
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import { listRunningThreads } from "./thread-scan.js";
|
import { listRunningThreads } from "../../thread-scan.js";
|
||||||
|
|
||||||
export async function cmdPs(storageRoot: string): Promise<string[]> {
|
export async function cmdPs(storageRoot: string): Promise<string[]> {
|
||||||
const rows = await listRunningThreads(storageRoot);
|
const rows = await listRunningThreads(storageRoot);
|
||||||
+2
-2
@@ -2,12 +2,12 @@ import { join } from "node:path";
|
|||||||
|
|
||||||
import { err, type Result } from "@uncaged/workflow";
|
import { err, type Result } from "@uncaged/workflow";
|
||||||
|
|
||||||
import { readTextFileIfExists } from "./fs-utils.js";
|
import { readTextFileIfExists } from "../../fs-utils.js";
|
||||||
import {
|
import {
|
||||||
resolveRunningHashForThread,
|
resolveRunningHashForThread,
|
||||||
sendWorkerTcpCommand,
|
sendWorkerTcpCommand,
|
||||||
type WorkerCtl,
|
type WorkerCtl,
|
||||||
} from "./worker-spawn.js";
|
} from "../../worker-spawn.js";
|
||||||
|
|
||||||
export async function cmdResume(
|
export async function cmdResume(
|
||||||
storageRoot: string,
|
storageRoot: string,
|
||||||
+1
-17
@@ -3,23 +3,7 @@ import { dirname, join } from "node:path";
|
|||||||
|
|
||||||
import { err, garbageCollectCas, ok, type Result } from "@uncaged/workflow";
|
import { err, garbageCollectCas, ok, type Result } from "@uncaged/workflow";
|
||||||
|
|
||||||
import { readTextFileIfExists } from "./fs-utils.js";
|
import { resolveThreadDataPath } from "../../thread-scan.js";
|
||||||
import { resolveThreadDataPath } from "./thread-scan.js";
|
|
||||||
|
|
||||||
export async function cmdThreadShow(
|
|
||||||
storageRoot: string,
|
|
||||||
threadId: string,
|
|
||||||
): Promise<Result<string, string>> {
|
|
||||||
const dataPath = await resolveThreadDataPath(storageRoot, threadId);
|
|
||||||
if (dataPath === null) {
|
|
||||||
return err(`thread not found: ${threadId}`);
|
|
||||||
}
|
|
||||||
const text = await readTextFileIfExists(dataPath);
|
|
||||||
if (text === null) {
|
|
||||||
return err(`thread data missing: ${threadId}`);
|
|
||||||
}
|
|
||||||
return ok(text.endsWith("\n") ? text.slice(0, -1) : text);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function cmdThreadRemove(
|
export async function cmdThreadRemove(
|
||||||
storageRoot: string,
|
storageRoot: string,
|
||||||
+2
-2
@@ -8,8 +8,8 @@ import {
|
|||||||
type Result,
|
type Result,
|
||||||
readWorkflowRegistry,
|
readWorkflowRegistry,
|
||||||
} from "@uncaged/workflow";
|
} from "@uncaged/workflow";
|
||||||
import { ensureWorkerForHash, sendWorkerTcpCommand } from "./worker-spawn.js";
|
import { ensureWorkerForHash, sendWorkerTcpCommand } from "../../worker-spawn.js";
|
||||||
import { validateCliWorkflowName } from "./workflow-name.js";
|
import { validateCliWorkflowName } from "../../workflow-name.js";
|
||||||
|
|
||||||
export async function cmdRun(
|
export async function cmdRun(
|
||||||
storageRoot: string,
|
storageRoot: string,
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import { err, ok, type Result } from "@uncaged/workflow";
|
||||||
|
|
||||||
|
import { readTextFileIfExists } from "../../fs-utils.js";
|
||||||
|
import { resolveThreadDataPath } from "../../thread-scan.js";
|
||||||
|
|
||||||
|
export async function cmdThreadShow(
|
||||||
|
storageRoot: string,
|
||||||
|
threadId: string,
|
||||||
|
): Promise<Result<string, string>> {
|
||||||
|
const dataPath = await resolveThreadDataPath(storageRoot, threadId);
|
||||||
|
if (dataPath === null) {
|
||||||
|
return err(`thread not found: ${threadId}`);
|
||||||
|
}
|
||||||
|
const text = await readTextFileIfExists(dataPath);
|
||||||
|
if (text === null) {
|
||||||
|
return err(`thread data missing: ${threadId}`);
|
||||||
|
}
|
||||||
|
return ok(text.endsWith("\n") ? text.slice(0, -1) : text);
|
||||||
|
}
|
||||||
+2
-2
@@ -14,8 +14,8 @@ import {
|
|||||||
writeWorkflowRegistry,
|
writeWorkflowRegistry,
|
||||||
} from "@uncaged/workflow";
|
} from "@uncaged/workflow";
|
||||||
|
|
||||||
import { storeWorkflowBundleArtifacts } from "./bundle-store.js";
|
import { storeWorkflowBundleArtifacts } from "../../bundle-store.js";
|
||||||
import { validateCliWorkflowName } from "./workflow-name.js";
|
import { validateCliWorkflowName } from "../../workflow-name.js";
|
||||||
|
|
||||||
export type ParsedAddArgv = {
|
export type ParsedAddArgv = {
|
||||||
name: string;
|
name: string;
|
||||||
+1
-1
@@ -6,7 +6,7 @@ import {
|
|||||||
readWorkflowRegistry,
|
readWorkflowRegistry,
|
||||||
} from "@uncaged/workflow";
|
} from "@uncaged/workflow";
|
||||||
|
|
||||||
import { validateCliWorkflowName } from "./workflow-name.js";
|
import { validateCliWorkflowName } from "../../workflow-name.js";
|
||||||
|
|
||||||
export async function cmdHistory(
|
export async function cmdHistory(
|
||||||
storageRoot: string,
|
storageRoot: string,
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
export type { CmdAddSuccess, ParsedAddArgv } from "./add.js";
|
||||||
|
export { cmdAdd, formatAddSuccess, parseAddArgv } from "./add.js";
|
||||||
|
export { cmdHistory } from "./history.js";
|
||||||
|
export { cmdList, formatListLines } from "./list.js";
|
||||||
|
export { cmdRemove } from "./rm.js";
|
||||||
|
export { cmdRollback } from "./rollback.js";
|
||||||
|
export { cmdShow, formatShowYaml } from "./show.js";
|
||||||
+1
-1
@@ -7,7 +7,7 @@ import {
|
|||||||
writeWorkflowRegistry,
|
writeWorkflowRegistry,
|
||||||
} from "@uncaged/workflow";
|
} from "@uncaged/workflow";
|
||||||
|
|
||||||
import { validateCliWorkflowName } from "./workflow-name.js";
|
import { validateCliWorkflowName } from "../../workflow-name.js";
|
||||||
|
|
||||||
export async function cmdRemove(storageRoot: string, name: string): Promise<Result<void, string>> {
|
export async function cmdRemove(storageRoot: string, name: string): Promise<Result<void, string>> {
|
||||||
const nameOk = validateCliWorkflowName(name);
|
const nameOk = validateCliWorkflowName(name);
|
||||||
+2
-2
@@ -10,8 +10,8 @@ import {
|
|||||||
writeWorkflowRegistry,
|
writeWorkflowRegistry,
|
||||||
} from "@uncaged/workflow";
|
} from "@uncaged/workflow";
|
||||||
|
|
||||||
import { pathExists } from "./fs-utils.js";
|
import { pathExists } from "../../fs-utils.js";
|
||||||
import { validateCliWorkflowName } from "./workflow-name.js";
|
import { validateCliWorkflowName } from "../../workflow-name.js";
|
||||||
|
|
||||||
export async function cmdRollback(
|
export async function cmdRollback(
|
||||||
storageRoot: string,
|
storageRoot: string,
|
||||||
+1
-1
@@ -8,7 +8,7 @@ import {
|
|||||||
} from "@uncaged/workflow";
|
} from "@uncaged/workflow";
|
||||||
import { stringify } from "yaml";
|
import { stringify } from "yaml";
|
||||||
|
|
||||||
import { validateCliWorkflowName } from "./workflow-name.js";
|
import { validateCliWorkflowName } from "../../workflow-name.js";
|
||||||
|
|
||||||
export async function cmdShow(
|
export async function cmdShow(
|
||||||
storageRoot: string,
|
storageRoot: string,
|
||||||
Reference in New Issue
Block a user