feat(agent): add workflow-agent-office with generate/edit AdapterFn
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -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");
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -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<string, unknown>;
|
||||||
|
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 <T>(_systemPrompt: string, schema: z.ZodType<T>) =>
|
||||||
|
async (ctx: ThreadContext, _runtime: WorkflowRuntime): Promise<RoleResult<T>> => {
|
||||||
|
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 };
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1 +1,3 @@
|
|||||||
export {};
|
export { createOfficeAgent } from "./agent.js";
|
||||||
|
export { packageDescriptor } from "./package-descriptor.js";
|
||||||
|
export type { OfficeAgentConfig } from "./types.js";
|
||||||
|
|||||||
@@ -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,
|
||||||
|
},
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user