modules/{auth-settings,sources-identity,acquisition-organize,agent} placeholders listed in
SERVER_MODULES; ServerModule registers routes (under /api/v1, authenticated), tasks,
outbox routes, capabilities and background loops. bootstrap() builds ServerContext (db,
config, logger, events, engine, outbox writer, secrets placeholder, settings reader,
capability registry), fills unregistered tasks with stubs and rejects duplicate task or
outbox ownership. worker starts the OpenWorkflow worker, OutboxRelay and module start().
--role migrate also migrates the engine schema; api/worker connect without migrating.
tasks: TaskRegistry.has, migrateEngineSchema.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
52 lines
2.2 KiB
TypeScript
52 lines
2.2 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { z } from "zod";
|
|
import { createDefaultRegistry, defineTask, redact, TASK_NAMES, TaskRegistry, UnknownTaskError } from "../src/index.ts";
|
|
|
|
describe("TaskRegistry", () => {
|
|
it("注册任务书 §3.1-8 的九个空壳任务", () => {
|
|
const reg = createDefaultRegistry();
|
|
expect(reg.names()).toEqual([...TASK_NAMES].sort());
|
|
for (const n of TASK_NAMES) expect(reg.latest(n).version).toBe(1);
|
|
expect(reg.has("ingestFeed")).toBe(true);
|
|
expect(reg.has("nope")).toBe(false);
|
|
});
|
|
|
|
it("latest 取最高版本;select 按 name@version / @version 过滤", () => {
|
|
const mk = (name: string, version: number) =>
|
|
defineTask({ name, version, inputSchema: z.object({}), handler: async () => null });
|
|
const reg = new TaskRegistry().register(mk("a", 1), mk("a", 2), mk("b", 1));
|
|
expect(reg.latest("a").version).toBe(2);
|
|
expect(reg.select(["a@1"]).map((d) => `${d.name}@${d.version}`)).toEqual(["a@1"]);
|
|
expect(reg.select(["@1"]).map((d) => `${d.name}@${d.version}`)).toEqual(["a@1", "b@1"]);
|
|
expect(reg.select(["a"])).toHaveLength(2);
|
|
expect(reg.select()).toHaveLength(3);
|
|
expect(() => reg.register(mk("a", 1))).toThrow(/already registered/);
|
|
expect(() => reg.latest("zzz")).toThrow(UnknownTaskError);
|
|
expect(() => mk("a", 0)).toThrow(/invalid task version/);
|
|
});
|
|
|
|
it("空壳 handler 回显输入", async () => {
|
|
const def = createDefaultRegistry().latest("submitDownload");
|
|
const input = def.inputSchema.parse({ acquisitionPlanId: "p1" });
|
|
const out = await def.handler({ input, logger: { info() {} } } as never);
|
|
expect(out).toEqual({ todo: true, task: "submitDownload", input: { acquisitionPlanId: "p1" } });
|
|
expect(() => def.inputSchema.parse({})).toThrow();
|
|
});
|
|
});
|
|
|
|
describe("redact", () => {
|
|
it("敏感键与 URL 凭证参数脱敏", () => {
|
|
expect(
|
|
redact({
|
|
url: "https://pt.example/download.php?id=1&passkey=abcdef123",
|
|
nested: { apiKey: "k", password: "p", ok: 1 },
|
|
list: ["http://x/rss?sign=zz&x=1"],
|
|
}),
|
|
).toEqual({
|
|
url: "https://pt.example/download.php?id=1&passkey=***",
|
|
nested: { apiKey: "***", password: "***", ok: 1 },
|
|
list: ["http://x/rss?sign=***&x=1"],
|
|
});
|
|
});
|
|
});
|