feat: 功能清单进智能体提示,补字幕按功能模块约定改为样板

- 外围功能模块(补字幕、原站视图、桌面模式、网页搜索、MCP、定时任务)声明 manifest,与 FEATURES 一一对应;
  系统提示「能力地图」末尾列出外围功能(没有开关,能力只列本次可用的)
- 补字幕:订阅 organization.finished(认出值得补字幕的整理,自动补字幕还没做,不建任务),
  写入字幕后在同一事务发 subtitle.written;原有行为不变

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Cxwgnn2pbzQ7rXv3rq7fei
This commit is contained in:
rootandClaude Opus 5.5 committed 2026-10-06 19:27:14 +08:00
1 parent 1db689d9a7
commit 7aa5182f3d
14 files changed
+237 -17

No files matched your search

@@ -0,0 +1,35 @@
import { CAPABILITY_CATALOG, FEATURES } from "@umt/contracts";
import { describe, expect, it } from "vitest";
import { buildLayeredPrompt, renderFeatures } from "../src/index.ts";
// 功能清单(ADR-006):外围功能的 manifest 进系统提示「能力地图」一节,让智能体知道有哪些功能、入口在哪;没有开关。
const section = (p: string, title: string) => {
const start = p.indexOf(`## ${title}`);
const rest = p.slice(start);
const next = rest.indexOf("\n## ", 3);
return next < 0 ? rest : rest.slice(0, next);
};
describe("功能清单进系统提示", () => {
it("能力地图里列出每个外围功能的名称、说明与入口", () => {
const p = buildLayeredPrompt({ kind: "chat", role: "x", goal: "y", capabilities: ["download.list"] });
const map = section(p, "能力地图");
expect(map).toContain("外围功能(都已启用,没有开关");
for (const f of FEATURES) expect(map).toContain(` - ${f.name}:${f.summary}`);
expect(map).toContain("作品页「补字幕」");
});
it("功能的能力只列本次可用的;没给的能力 ID 不出现在清单里", () => {
const lines = renderFeatures(new Set(["web.search"]));
const web = lines.find((l) => l.includes("网页搜索"))!;
expect(web).toContain("(能力:web.search)");
const text = lines.join("\n");
for (const id of Object.keys(CAPABILITY_CATALOG)) if (id !== "web.search") expect(text).not.toContain(id);
});
it("没有能力的会话(视觉子流程)不带功能清单", () => {
const p = buildLayeredPrompt({ kind: "vision", role: "x", goal: "y" });
expect(p).not.toContain("外围功能");
});
});