From e59ae9aca14d21668a393d001cd49fac157e3eb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E6=A9=98?= Date: Fri, 22 May 2026 01:01:45 +0000 Subject: [PATCH 1/2] feat: support project-local workflow discovery - Add .workflows/*.yaml scanning from project root (cwd) - Resolution: project-local first, then global registry - On-the-fly CAS materialization for local workflows - Filename/name consistency check - uwf workflow list shows origin (local/global) Fixes #365 --- packages/cli-workflow/src/cli.ts | 9 ++- packages/cli-workflow/src/commands/thread.ts | 55 +++++++++++++++++- .../cli-workflow/src/commands/workflow.ts | 52 +++++++++++------ packages/cli-workflow/src/store.ts | 56 ++++++++++++++++++- packages/cli-workflow/src/validate.ts | 28 ++++++++++ 5 files changed, 176 insertions(+), 24 deletions(-) diff --git a/packages/cli-workflow/src/cli.ts b/packages/cli-workflow/src/cli.ts index 995fb67..1a6a5c6 100755 --- a/packages/cli-workflow/src/cli.ts +++ b/packages/cli-workflow/src/cli.ts @@ -47,7 +47,10 @@ const program = new Command(); // eslint-disable-next-line -- dynamic import for version const pkg = await import("../package.json", { with: { type: "json" } }); -program.name("uwf").description("Stateless workflow CLI").version(pkg.default.version, "-V, --version"); +program + .name("uwf") + .description("Stateless workflow CLI") + .version(pkg.default.version, "-V, --version"); program.option("--format ", "Output format: json or yaml", "json"); const workflow = program.command("workflow").description("Workflow registry and CAS"); @@ -82,7 +85,7 @@ workflow .action(() => { const storageRoot = resolveStorageRoot(); runAction(async () => { - const result = await cmdWorkflowList(storageRoot); + const result = await cmdWorkflowList(storageRoot, process.cwd()); writeOutput(result); }); }); @@ -97,7 +100,7 @@ thread .action((workflow: string, opts: { prompt: string }) => { const storageRoot = resolveStorageRoot(); runAction(async () => { - const result = await cmdThreadStart(storageRoot, workflow, opts.prompt); + const result = await cmdThreadStart(storageRoot, workflow, opts.prompt, process.cwd()); writeOutput(result); }); }); diff --git a/packages/cli-workflow/src/commands/thread.ts b/packages/cli-workflow/src/commands/thread.ts index dde7a64..e7146be 100644 --- a/packages/cli-workflow/src/commands/thread.ts +++ b/packages/cli-workflow/src/commands/thread.ts @@ -1,4 +1,5 @@ import { execFileSync } from "node:child_process"; +import { readFile } from "node:fs/promises"; import type { Store as CasStore, JSONSchema } from "@uncaged/json-cas"; import { getSchema, validate } from "@uncaged/json-cas"; import { getEnvPath, loadWorkflowConfig } from "@uncaged/workflow-agent-kit"; @@ -24,21 +25,24 @@ import type { } from "@uncaged/workflow-protocol"; import { generateUlid } from "@uncaged/workflow-util"; import { config as loadDotenv } from "dotenv"; -import { stringify } from "yaml"; +import { parse, stringify } from "yaml"; import { appendThreadHistory, createUwfStore, + discoverProjectWorkflows, findThreadInHistory, loadThreadHistory, loadThreadsIndex, loadWorkflowRegistry, + resolveProjectWorkflowFile, resolveWorkflowHash, saveThreadsIndex, type ThreadHistoryLine, type UwfStore, } from "../store.js"; -import { isCasRef } from "../validate.js"; +import { checkWorkflowFilenameConsistency, isCasRef, parseWorkflowPayload } from "../validate.js"; +import { materializeWorkflowPayload } from "./workflow.js"; const END_ROLE = "$END"; export const THREAD_READ_DEFAULT_QUOTA = 4000; @@ -66,11 +70,55 @@ function fail(message: string): never { process.exit(1); } +async function materializeLocalWorkflow(uwf: UwfStore, filePath: string): Promise { + let text: string; + try { + text = await readFile(filePath, "utf8"); + } catch { + fail(`project workflow file not found: ${filePath}`); + } + + let raw: unknown; + try { + raw = parse(text) as unknown; + } catch (e) { + fail(`invalid YAML in ${filePath}: ${e instanceof Error ? e.message : String(e)}`); + } + + const payload = parseWorkflowPayload(raw); + if (payload === null) { + fail(`invalid workflow YAML in ${filePath}: expected WorkflowPayload shape`); + } + + const filenameError = checkWorkflowFilenameConsistency(filePath, payload); + if (filenameError !== null) { + fail(filenameError); + } + + const materialized = await materializeWorkflowPayload(uwf, payload); + const hash = await uwf.store.put(uwf.schemas.workflow, materialized); + const stored = uwf.store.get(hash); + if (stored === null || !validate(uwf.store, stored)) { + fail("stored local workflow failed schema validation"); + } + + return hash; +} + async function resolveWorkflowCasRef( uwf: UwfStore, storageRoot: string, workflowId: string, + projectRoot: string, ): Promise { + // Project-local resolution: check .workflows/.yaml first + const localEntries = await discoverProjectWorkflows(projectRoot); + const localFile = resolveProjectWorkflowFile(localEntries, workflowId); + if (localFile !== null) { + return materializeLocalWorkflow(uwf, localFile); + } + + // Global registry fallback const registry = await loadWorkflowRegistry(storageRoot); const hash = resolveWorkflowHash(registry, workflowId); if (!isCasRef(hash)) { @@ -114,9 +162,10 @@ export async function cmdThreadStart( storageRoot: string, workflowId: string, prompt: string, + projectRoot: string, ): Promise { const uwf = await createUwfStore(storageRoot); - const workflowHash = await resolveWorkflowCasRef(uwf, storageRoot, workflowId); + const workflowHash = await resolveWorkflowCasRef(uwf, storageRoot, workflowId, projectRoot); const threadId = generateUlid(Date.now()) as ThreadId; const startPayload: StartNodePayload = { diff --git a/packages/cli-workflow/src/commands/workflow.ts b/packages/cli-workflow/src/commands/workflow.ts index 56a9377..2618481 100644 --- a/packages/cli-workflow/src/commands/workflow.ts +++ b/packages/cli-workflow/src/commands/workflow.ts @@ -7,17 +7,21 @@ import { parse } from "yaml"; import { createUwfStore, + discoverProjectWorkflows, findRegistryName, loadWorkflowRegistry, resolveWorkflowHash, saveWorkflowRegistry, type UwfStore, } from "../store.js"; -import { parseWorkflowPayload } from "../validate.js"; +import { checkWorkflowFilenameConsistency, parseWorkflowPayload } from "../validate.js"; + +export type WorkflowOrigin = "local" | "global"; export type WorkflowListEntry = { name: string; hash: CasRef; + origin: WorkflowOrigin; }; export type WorkflowPutOutput = { @@ -42,31 +46,21 @@ function isJsonSchema(value: unknown): value is JSONSchema { return typeof value === "object" && value !== null && !Array.isArray(value); } -async function resolveMetaRef( - uwf: UwfStore, - roleName: string, - meta: unknown, -): Promise { +async function resolveMetaRef(uwf: UwfStore, roleName: string, meta: unknown): Promise { if (!isJsonSchema(meta)) { fail(`role "${roleName}": meta must be a JSON Schema object`); } - const schema: JSONSchema = meta.title === undefined - ? { ...meta, title: roleName } - : meta; + const schema: JSONSchema = meta.title === undefined ? { ...meta, title: roleName } : meta; return putSchema(uwf.store, schema); } -async function materializeWorkflowPayload( +export async function materializeWorkflowPayload( uwf: UwfStore, raw: WorkflowPayload, ): Promise { const roles: Record = {}; for (const [roleName, role] of Object.entries(raw.roles)) { - const meta = await resolveMetaRef( - uwf, - `${raw.name}.${roleName}`, - role.meta, - ); + const meta = await resolveMetaRef(uwf, `${raw.name}.${roleName}`, role.meta); roles[roleName] = { description: role.description, goal: role.goal, @@ -108,6 +102,11 @@ export async function cmdWorkflowPut( fail("invalid workflow YAML: expected WorkflowPayload shape"); } + const filenameError = checkWorkflowFilenameConsistency(filePath, payload); + if (filenameError !== null) { + fail(filenameError); + } + const uwf = await createUwfStore(storageRoot); const materialized = await materializeWorkflowPayload(uwf, payload); @@ -150,7 +149,26 @@ export async function cmdWorkflowShow( }; } -export async function cmdWorkflowList(storageRoot: string): Promise { +export async function cmdWorkflowList( + storageRoot: string, + projectRoot: string, +): Promise { + const localEntries = await discoverProjectWorkflows(projectRoot); const registry = await loadWorkflowRegistry(storageRoot); - return Object.entries(registry).map(([name, hash]) => ({ name, hash })); + + const result: WorkflowListEntry[] = []; + const localNames = new Set(); + + for (const entry of localEntries) { + localNames.add(entry.name); + result.push({ name: entry.name, hash: "(local)", origin: "local" }); + } + + for (const [name, hash] of Object.entries(registry)) { + if (!localNames.has(name)) { + result.push({ name, hash, origin: "global" }); + } + } + + return result; } diff --git a/packages/cli-workflow/src/store.ts b/packages/cli-workflow/src/store.ts index ecc5462..ba73db4 100644 --- a/packages/cli-workflow/src/store.ts +++ b/packages/cli-workflow/src/store.ts @@ -1,4 +1,4 @@ -import { appendFile, mkdir, readFile, writeFile } from "node:fs/promises"; +import { appendFile, mkdir, readdir, readFile, writeFile } from "node:fs/promises"; import { homedir } from "node:os"; import { join } from "node:path"; @@ -11,6 +11,44 @@ import { registerUwfSchemas, type UwfSchemaHashes } from "./schemas.js"; export type WorkflowRegistry = Record; +/** A workflow entry discovered from the project-local .workflows/ directory. */ +export type ProjectWorkflowEntry = { + /** Workflow name (from YAML `name` field, equals filename stem). */ + name: string; + /** Absolute path to the YAML file. */ + filePath: string; +}; + +/** + * Scan `/.workflows/*.yaml` (non-recursive) and return discovered entries. + * Returns an empty array if the directory does not exist. + */ +export async function discoverProjectWorkflows( + projectRoot: string, +): Promise { + const dir = join(projectRoot, ".workflows"); + let entries: string[]; + try { + entries = await readdir(dir); + } catch (e) { + const err = e as NodeJS.ErrnoException; + if (err.code === "ENOENT" || err.code === "ENOTDIR") { + return []; + } + throw e; + } + + const result: ProjectWorkflowEntry[] = []; + for (const entry of entries) { + if (!entry.endsWith(".yaml") && !entry.endsWith(".yml")) { + continue; + } + const stem = entry.endsWith(".yaml") ? entry.slice(0, -5) : entry.slice(0, -4); + result.push({ name: stem, filePath: join(dir, entry) }); + } + return result; +} + /** Default filesystem root for uwf data (`~/.uncaged/workflow`). */ export function getDefaultStorageRoot(): string { return join(homedir(), ".uncaged", "workflow"); @@ -104,6 +142,22 @@ export function resolveWorkflowHash(registry: WorkflowRegistry, id: string): Cas return registry[id] !== undefined ? registry[id] : id; } +/** + * Resolve a workflow name to a project-local YAML file path. + * Returns null if the name is not found in the local entries. + */ +export function resolveProjectWorkflowFile( + localEntries: ProjectWorkflowEntry[], + name: string, +): string | null { + for (const entry of localEntries) { + if (entry.name === name) { + return entry.filePath; + } + } + return null; +} + export function findRegistryName(registry: WorkflowRegistry, hash: Hash): string | null { for (const [name, h] of Object.entries(registry)) { if (h === hash) { diff --git a/packages/cli-workflow/src/validate.ts b/packages/cli-workflow/src/validate.ts index a82032c..a7a3edb 100644 --- a/packages/cli-workflow/src/validate.ts +++ b/packages/cli-workflow/src/validate.ts @@ -1,3 +1,4 @@ +import { basename } from "node:path"; import type { CasRef, WorkflowPayload } from "@uncaged/workflow-protocol"; const CAS_REF_PATTERN = /^[0-9A-HJKMNP-TV-Z]{13}$/; @@ -60,6 +61,33 @@ function isGraph(value: unknown): boolean { ); } +/** + * Derive the expected workflow name from a file path (stem without extension). + * Returns the stem for `.yaml` / `.yml` files. + */ +export function workflowNameFromPath(filePath: string): string { + const base = basename(filePath); + if (base.endsWith(".yaml")) return base.slice(0, -5); + if (base.endsWith(".yml")) return base.slice(0, -4); + return base; +} + +/** + * Check that the `name` field in a parsed payload matches the expected name + * derived from the file path. Returns an error message string on mismatch, + * or null when the names are consistent. + */ +export function checkWorkflowFilenameConsistency( + filePath: string, + payload: WorkflowPayload, +): string | null { + const expected = workflowNameFromPath(filePath); + if (payload.name !== expected) { + return `workflow name mismatch: file "${basename(filePath)}" implies name "${expected}" but YAML declares name "${payload.name}"`; + } + return null; +} + /** Validate YAML-parsed workflow document shape (outputSchema may be inline JSON Schema). */ export function parseWorkflowPayload(raw: unknown): WorkflowPayload | null { if (!isRecord(raw)) { -- 2.43.0 From a3114bf84060ae1e71a262db35c929cd83693887 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E6=A9=98?= Date: Fri, 22 May 2026 02:06:05 +0000 Subject: [PATCH 2/2] chore: apply biome formatting across codebase --- .../__tests__/agent.test.ts | 2 +- .../__tests__/runner.test.ts | 15 ++++-- .../workflow-agent-docx-diff/package.json | 6 ++- .../workflow-agent-docx-diff/src/agent.ts | 19 ++++--- .../workflow-agent-docx-diff/src/runner.ts | 5 +- .../__tests__/agent.test.ts | 2 +- .../__tests__/runner.test.ts | 16 ++++-- .../workflow-agent-office/package.json | 6 ++- .../workflow-agent-office/src/agent.ts | 20 ++++++-- .../workflow-agent-office/src/runner.ts | 5 +- legacy-packages/workflow-dashboard/index.html | 2 +- .../plugins/vite-limit-line-plugin.ts | 30 +++++++---- .../src/components/ui/resizable-panel.tsx | 5 +- .../__tests__/document-template.test.ts | 16 ++++-- .../workflow-template-document/package.json | 6 ++- packages/cli-workflow/src/commands/cas.ts | 28 +++-------- packages/cli-workflow/src/commands/setup.ts | 50 +++++++++++++------ packages/cli-workflow/src/schemas.ts | 6 +-- packages/workflow-agent-hermes/src/hermes.ts | 7 ++- .../__tests__/frontmatter-fast-path.test.ts | 6 +-- packages/workflow-agent-kit/src/context.ts | 19 ++----- .../workflow-agent-kit/src/frontmatter.ts | 2 +- packages/workflow-agent-kit/src/index.ts | 4 +- packages/workflow-agent-kit/src/run.ts | 3 +- packages/workflow-moderator/src/evaluate.ts | 5 +- packages/workflow-util/src/index.ts | 10 ++-- 26 files changed, 167 insertions(+), 128 deletions(-) diff --git a/legacy-packages/workflow-agent-docx-diff/__tests__/agent.test.ts b/legacy-packages/workflow-agent-docx-diff/__tests__/agent.test.ts index c201f83..8986c48 100644 --- a/legacy-packages/workflow-agent-docx-diff/__tests__/agent.test.ts +++ b/legacy-packages/workflow-agent-docx-diff/__tests__/agent.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test"; -import { packageDescriptor } from "../src/package-descriptor.js"; import { createDocxDiffAgent } from "../src/agent.js"; +import { packageDescriptor } from "../src/package-descriptor.js"; describe("createDocxDiffAgent", () => { test("returns an AdapterFn (function)", () => { diff --git a/legacy-packages/workflow-agent-docx-diff/__tests__/runner.test.ts b/legacy-packages/workflow-agent-docx-diff/__tests__/runner.test.ts index 3d7d2e0..47ba217 100644 --- a/legacy-packages/workflow-agent-docx-diff/__tests__/runner.test.ts +++ b/legacy-packages/workflow-agent-docx-diff/__tests__/runner.test.ts @@ -1,8 +1,8 @@ -import { mkdirSync, writeFileSync } from "node:fs"; -import { join } from "node:path"; -import { tmpdir } from "node:os"; import { describe, expect, mock, test } from "bun:test"; -import { ok, err } from "@uncaged/workflow-util"; +import { mkdirSync, writeFileSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; +import { err, ok } from "@uncaged/workflow-util"; import type { SpawnCliConfig } from "@uncaged/workflow-util-agent"; import { runDocxDiff } from "../src/runner.js"; @@ -74,7 +74,12 @@ describe("runDocxDiff", () => { test("exit 2: throws error", async () => { const dir = tempDir(); const spawnFn = makeSpawn( - err({ kind: "non_zero_exit", exitCode: 2, stdout: "", stderr: "fatal error" }) as MockSpawnResult, + err({ + kind: "non_zero_exit", + exitCode: 2, + stdout: "", + stderr: "fatal error", + }) as MockSpawnResult, ); await expect( diff --git a/legacy-packages/workflow-agent-docx-diff/package.json b/legacy-packages/workflow-agent-docx-diff/package.json index 1cbbf33..fd28635 100644 --- a/legacy-packages/workflow-agent-docx-diff/package.json +++ b/legacy-packages/workflow-agent-docx-diff/package.json @@ -1,7 +1,11 @@ { "name": "@uncaged/workflow-agent-docx-diff", "version": "0.1.0", - "files": ["src", "dist", "package.json"], + "files": [ + "src", + "dist", + "package.json" + ], "type": "module", "types": "src/index.ts", "exports": { diff --git a/legacy-packages/workflow-agent-docx-diff/src/agent.ts b/legacy-packages/workflow-agent-docx-diff/src/agent.ts index 4c9ea87..49d1300 100644 --- a/legacy-packages/workflow-agent-docx-diff/src/agent.ts +++ b/legacy-packages/workflow-agent-docx-diff/src/agent.ts @@ -1,7 +1,12 @@ -import * as z from "zod/v4"; import { dirname, join } from "node:path"; -import type { AdapterFn, RoleResult, ThreadContext, WorkflowRuntime } from "@uncaged/workflow-runtime"; +import type { + AdapterFn, + RoleResult, + ThreadContext, + WorkflowRuntime, +} from "@uncaged/workflow-runtime"; import type { WriterMeta } from "@uncaged/workflow-template-document"; +import type * as z from "zod/v4"; import { runDocxDiff } from "./runner.js"; import type { DocxDiffAgentConfig } from "./types.js"; @@ -12,16 +17,10 @@ export function createDocxDiffAgent(config: DocxDiffAgentConfig): AdapterFn { if (writerStep === undefined) throw new Error("differ: no writer step found"); const writerMeta = writerStep.meta as WriterMeta; - if (writerMeta.mode !== "edit") - throw new Error("differ: writer did not run in edit mode"); + if (writerMeta.mode !== "edit") throw new Error("differ: writer did not run in edit mode"); const diffDocx = join(dirname(writerMeta.outputDocx), "diff.docx"); - const raw = await runDocxDiff( - config, - writerMeta.sourceDocx, - writerMeta.outputDocx, - diffDocx, - ); + const raw = await runDocxDiff(config, writerMeta.sourceDocx, writerMeta.outputDocx, diffDocx); const meta = schema.parse(JSON.parse(raw)) as T; return { meta, childThread: null }; diff --git a/legacy-packages/workflow-agent-docx-diff/src/runner.ts b/legacy-packages/workflow-agent-docx-diff/src/runner.ts index f29f5e4..05eb230 100644 --- a/legacy-packages/workflow-agent-docx-diff/src/runner.ts +++ b/legacy-packages/workflow-agent-docx-diff/src/runner.ts @@ -1,6 +1,6 @@ import { stat } from "node:fs/promises"; -import { spawnCli } from "@uncaged/workflow-util-agent"; import type { SpawnCliError } from "@uncaged/workflow-util-agent"; +import { spawnCli } from "@uncaged/workflow-util-agent"; import type { DocxDiffAgentConfig } from "./types.js"; type SpawnCliFn = typeof spawnCli; @@ -8,8 +8,7 @@ type SpawnCliFn = typeof spawnCli; function throwSpawnError(e: SpawnCliError): never { if (e.kind === "non_zero_exit") throw new Error(`docx-diff failed (exit ${e.exitCode}): ${e.stderr}`); - if (e.kind === "timeout") - throw new Error("docx-diff: timed out"); + if (e.kind === "timeout") throw new Error("docx-diff: timed out"); throw new Error(`docx-diff: spawn failed: ${e.message}`); } diff --git a/legacy-packages/workflow-agent-office/__tests__/agent.test.ts b/legacy-packages/workflow-agent-office/__tests__/agent.test.ts index 01bb3c4..89a8238 100644 --- a/legacy-packages/workflow-agent-office/__tests__/agent.test.ts +++ b/legacy-packages/workflow-agent-office/__tests__/agent.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test"; -import { packageDescriptor } from "../src/package-descriptor.js"; import { createOfficeAgent } from "../src/agent.js"; +import { packageDescriptor } from "../src/package-descriptor.js"; describe("createOfficeAgent", () => { test("returns an AdapterFn (function)", () => { diff --git a/legacy-packages/workflow-agent-office/__tests__/runner.test.ts b/legacy-packages/workflow-agent-office/__tests__/runner.test.ts index 2fb8098..c691454 100644 --- a/legacy-packages/workflow-agent-office/__tests__/runner.test.ts +++ b/legacy-packages/workflow-agent-office/__tests__/runner.test.ts @@ -1,8 +1,8 @@ -import { mkdirSync, writeFileSync } from "node:fs"; -import { join } from "node:path"; -import { tmpdir } from "node:os"; import { describe, expect, mock, test } from "bun:test"; -import { ok, err } from "@uncaged/workflow-util"; +import { mkdirSync, writeFileSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; +import { err, ok } from "@uncaged/workflow-util"; import type { SpawnCliConfig } from "@uncaged/workflow-util-agent"; import { editDocument, generateDocument } from "../src/runner.js"; @@ -123,7 +123,13 @@ describe("editDocument", () => { ); await expect( - editDocument({ outputDir: base, command: null, timeout: null }, "te2", "edit", inputFile, spawnFn), + editDocument( + { outputDir: base, command: null, timeout: null }, + "te2", + "edit", + inputFile, + spawnFn, + ), ).rejects.toThrow("spawn failed"); }); }); diff --git a/legacy-packages/workflow-agent-office/package.json b/legacy-packages/workflow-agent-office/package.json index 8686c44..970e70c 100644 --- a/legacy-packages/workflow-agent-office/package.json +++ b/legacy-packages/workflow-agent-office/package.json @@ -1,7 +1,11 @@ { "name": "@uncaged/workflow-agent-office", "version": "0.1.0", - "files": ["src", "dist", "package.json"], + "files": [ + "src", + "dist", + "package.json" + ], "type": "module", "types": "src/index.ts", "exports": { diff --git a/legacy-packages/workflow-agent-office/src/agent.ts b/legacy-packages/workflow-agent-office/src/agent.ts index 2c5fae8..a55e5d9 100644 --- a/legacy-packages/workflow-agent-office/src/agent.ts +++ b/legacy-packages/workflow-agent-office/src/agent.ts @@ -1,6 +1,11 @@ -import * as z from "zod/v4"; -import type { AdapterFn, RoleResult, ThreadContext, WorkflowRuntime } from "@uncaged/workflow-runtime"; +import type { + AdapterFn, + RoleResult, + ThreadContext, + WorkflowRuntime, +} from "@uncaged/workflow-runtime"; import { createLogger } from "@uncaged/workflow-util"; +import type * as z from "zod/v4"; import { editDocument, generateDocument } from "./runner.js"; import type { OfficeAgentConfig } from "./types.js"; @@ -27,7 +32,10 @@ export function createOfficeAgent(config: OfficeAgentConfig): AdapterFn { return (_systemPrompt: string, schema: z.ZodType) => async (ctx: ThreadContext, _runtime: WorkflowRuntime): Promise> => { const { prompt, inputDocx } = parseStartInput(ctx.start.content); - log("8FQKP3NV", `office-agent: mode=${inputDocx === null ? "generate" : "edit"} thread=${ctx.threadId}`); + log( + "8FQKP3NV", + `office-agent: mode=${inputDocx === null ? "generate" : "edit"} thread=${ctx.threadId}`, + ); let raw: string; if (inputDocx === null) { @@ -35,7 +43,11 @@ export function createOfficeAgent(config: OfficeAgentConfig): AdapterFn { raw = JSON.stringify({ mode: "generate", outputDocx: result.outputDocx, sourceDocx: null }); } else { const result = await editDocument(config, ctx.threadId, prompt, inputDocx); - raw = JSON.stringify({ mode: "edit", outputDocx: result.outputDocx, sourceDocx: result.sourceDocx }); + raw = JSON.stringify({ + mode: "edit", + outputDocx: result.outputDocx, + sourceDocx: result.sourceDocx, + }); } const meta = schema.parse(JSON.parse(raw)) as T; diff --git a/legacy-packages/workflow-agent-office/src/runner.ts b/legacy-packages/workflow-agent-office/src/runner.ts index e001043..d50891f 100644 --- a/legacy-packages/workflow-agent-office/src/runner.ts +++ b/legacy-packages/workflow-agent-office/src/runner.ts @@ -1,7 +1,7 @@ import { copyFile, mkdir, stat } from "node:fs/promises"; import { join } from "node:path"; -import { spawnCli } from "@uncaged/workflow-util-agent"; import type { SpawnCliError } from "@uncaged/workflow-util-agent"; +import { spawnCli } from "@uncaged/workflow-util-agent"; import type { OfficeAgentConfig } from "./types.js"; type SpawnCliFn = typeof spawnCli; @@ -9,8 +9,7 @@ type SpawnCliFn = typeof spawnCli; function throwSpawnError(e: SpawnCliError): never { if (e.kind === "non_zero_exit") throw new Error(`office-agent failed (exit ${e.exitCode}): ${e.stderr}`); - if (e.kind === "timeout") - throw new Error("office-agent: timed out"); + if (e.kind === "timeout") throw new Error("office-agent: timed out"); throw new Error(`office-agent: spawn failed: ${e.message}`); } diff --git a/legacy-packages/workflow-dashboard/index.html b/legacy-packages/workflow-dashboard/index.html index da26862..3ae7430 100644 --- a/legacy-packages/workflow-dashboard/index.html +++ b/legacy-packages/workflow-dashboard/index.html @@ -5,7 +5,7 @@ Workflow Dashboard