diff --git a/packages/workflow-agent-office/__tests__/agent.test.ts b/packages/workflow-agent-office/__tests__/agent.test.ts new file mode 100644 index 0000000..01bb3c4 --- /dev/null +++ b/packages/workflow-agent-office/__tests__/agent.test.ts @@ -0,0 +1,27 @@ +import { describe, expect, test } from "bun:test"; +import { packageDescriptor } from "../src/package-descriptor.js"; +import { createOfficeAgent } from "../src/agent.js"; + +describe("createOfficeAgent", () => { + test("returns an AdapterFn (function)", () => { + const agent = createOfficeAgent({ outputDir: "/tmp", command: null, timeout: null }); + expect(typeof agent).toBe("function"); + }); + + test("AdapterFn returns a RoleFn (function)", () => { + const agent = createOfficeAgent({ outputDir: "/tmp", command: null, timeout: null }); + const roleFn = agent("", expect.anything() as never); + expect(typeof roleFn).toBe("function"); + }); +}); + +describe("packageDescriptor", () => { + test("has correct name", () => { + expect(packageDescriptor.name).toBe("@uncaged/workflow-agent-office"); + }); + + test("has outputDir in configSchema required", () => { + const schema = packageDescriptor.configSchema as { required: string[] }; + expect(schema.required).toContain("outputDir"); + }); +}); diff --git a/packages/workflow-agent-office/src/agent.ts b/packages/workflow-agent-office/src/agent.ts new file mode 100644 index 0000000..2c5fae8 --- /dev/null +++ b/packages/workflow-agent-office/src/agent.ts @@ -0,0 +1,44 @@ +import * as z from "zod/v4"; +import type { AdapterFn, RoleResult, ThreadContext, WorkflowRuntime } from "@uncaged/workflow-runtime"; +import { createLogger } from "@uncaged/workflow-util"; +import { editDocument, generateDocument } from "./runner.js"; +import type { OfficeAgentConfig } from "./types.js"; + +const log = createLogger({ sink: { kind: "stderr" } }); + +type ParsedInput = { prompt: string; inputDocx: string | null }; + +function parseStartInput(content: string): ParsedInput { + try { + const parsed = JSON.parse(content) as Record; + if (typeof parsed.prompt === "string") { + return { + prompt: parsed.prompt, + inputDocx: typeof parsed.inputDocx === "string" ? parsed.inputDocx : null, + }; + } + } catch { + // not JSON — treat whole content as prompt, generate mode + } + return { prompt: content, inputDocx: null }; +} + +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}`); + + let raw: string; + if (inputDocx === null) { + const result = await generateDocument(config, ctx.threadId, prompt); + 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 }); + } + + const meta = schema.parse(JSON.parse(raw)) as T; + return { meta, childThread: null }; + }; +} diff --git a/packages/workflow-agent-office/src/index.ts b/packages/workflow-agent-office/src/index.ts index cb0ff5c..0964445 100644 --- a/packages/workflow-agent-office/src/index.ts +++ b/packages/workflow-agent-office/src/index.ts @@ -1 +1,3 @@ -export {}; +export { createOfficeAgent } from "./agent.js"; +export { packageDescriptor } from "./package-descriptor.js"; +export type { OfficeAgentConfig } from "./types.js"; diff --git a/packages/workflow-agent-office/src/package-descriptor.ts b/packages/workflow-agent-office/src/package-descriptor.ts new file mode 100644 index 0000000..b2fdba7 --- /dev/null +++ b/packages/workflow-agent-office/src/package-descriptor.ts @@ -0,0 +1,26 @@ +import type { PackageDescriptor } from "@uncaged/workflow-runtime"; + +export const packageDescriptor: PackageDescriptor = { + name: "@uncaged/workflow-agent-office", + version: "0.1.0", + capabilities: ["office-agent-cli", "docx-generate", "docx-edit"], + configSchema: { + type: "object", + required: ["outputDir"], + properties: { + outputDir: { + type: "string", + description: "Root directory for workflow outputs; subdirs are created per threadId.", + }, + command: { + anyOf: [{ type: "string" }, { type: "null" }], + description: "Path to office-agent CLI binary; null uses PATH.", + }, + timeout: { + anyOf: [{ type: "number" }, { type: "null" }], + description: "Timeout in milliseconds; null means no limit.", + }, + }, + additionalProperties: false, + }, +};