feat: 平台标记单一源 PLATFORM_GROUPS + catalog 重生成 platformTag 生效

迁移前置项(指南五件小事 #1 + 第 0 步作业 #2):
- register-all.ts 新增 PLATFORM_GROUPS 单一权威表(33 域全标 win32,darwin/linux 仅类型占位)
- registerAll 逐域加载时把平台默认值落进 meta.platforms(能力显式声明优先);
  新增 buildDomainPlatformMap 供构建脚本与运行时共用同一张表
- build-catalog.mjs 删除 WIN32_GROUPS 硬编码,platformTag 从包内分组表派生(改 tsx 运行)
- 守卫测试 platform-groups.test.ts:域无缺行 / 不偷填非 win32 数据 / meta 派生一致
- catalog.json 重生成:687 个组件获得 platformTag=win32(此前从未生效)
- 源数据恢复:对面重构删了 shizai-catalog-data.js,从其历史 commit 7bc627c8 恢复到
  temp/catalog-source/(不入库)并作为回退路径
- catalog-overrides 增强 addFields 支持;把此前直接改 catalog.json 的 96 处假必填修正、
  label 修正、Screenlock 字段清理、12 个实现读取但源数据缺失的字段全部沉淀进 overrides,
  重生成后参数审计 A/B 类保持 0/0
This commit is contained in:
yu committed 2026-11-05 17:53:07 +08:00
1 parent a7709aefbb
commit 8414c4f355
9 files changed
+1002 -125520

No files matched your search

+30 -8
View File
@@ -13,6 +13,8 @@ import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { applyCatalogOverrides } from "./catalog-overrides.mjs";
// 平台标记单一源:从包内 PLATFORM_GROUPS 逐域派生(npm run catalog 用 tsx 运行)
import { buildDomainPlatformMap, PLATFORM_GROUPS } from "../packages/rpa-core/src/capabilities/register-all";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const ROOT = path.resolve(__dirname, "..");
@@ -172,7 +174,17 @@ function normalizeVendorField(field) {
}
function loadCatalogSource() {
const raw = fs.readFileSync(SRC_CATALOG, "utf8");
// 优先环境变量/对面仓库路径;对面重构删除该文件后,回退到 temp/catalog-source/ 的历史恢复版
// (自 Agent-Employee commit 7bc627c8 恢复;temp/ 不入库,换机器需重新恢复)
const candidates = [SRC_CATALOG, path.join(ROOT, "temp", "catalog-source", "shizai-catalog-data.js")];
const found = candidates.find((p) => fs.existsSync(p));
if (!found) {
throw new Error(
`找不到目录源数据 shizai-catalog-data.js(尝试:${candidates.join(" ; ")})。` +
`可从 Agent-Employee 历史 commit 7bc627c8 恢复到 temp/catalog-source/`
);
}
const raw = fs.readFileSync(found, "utf8");
const start = raw.indexOf("=");
if (start < 0) throw new Error("catalog source has no assignment");
let body = raw.slice(start + 1).trim();
@@ -228,10 +240,10 @@ function normalizeVendorComponent(component, vendorMap) {
const fields = (component.inputFields || []).map((f) => enrichFromVendor(normalizeVendorField(f), vendor));
const output = outputOf(component, vendor);
const risk = ["web", "app", "desktop", "message", "mobile"].includes(group) ? "high" : "low";
// 任务 3.4(决策点 7):平台标记只填 catalog 数据,渲染层置灰延后。
// Windows 专用组:desktop(user32/键鼠)、app(COM/进程)、office(Excel/Word COM)、vision(PowerShell 截屏);
// data/file/message 纯 Node,web 走 CDP,均视为跨平台(null)。
const WIN32_GROUPS = new Set(["desktop", "app", "office", "vision"]);
// 任务 3.4(决策点 7)+ 五件小事 #1:platformTag 从包内 PLATFORM_GROUPS 单一源派生
// (能力 id 命中包内注册 → win32;未实现的能力与宿主原生节点 → null 跨平台占位)。
const platforms = domainPlatformMap.get(component.id) || component.platforms;
const platformTag = component.platformTag || (platforms?.includes("win32") ? "win32" : null);
return {
id: component.id,
name: component.name,
@@ -246,7 +258,7 @@ function normalizeVendorComponent(component, vendorMap) {
functionCalls: (component.functions || []).map((f) => ({ function: f.function, args: f.arguments || [], assignTo: f.assignTo || "" })),
version: component.version || "",
tags: component.tags || [],
platformTag: component.platformTag || (WIN32_GROUPS.has(group) ? "win32" : null),
platformTag,
icon: group,
risk,
fields,
@@ -319,7 +331,11 @@ function normalizeTrigger(trigger) {
};
}
function main() {
async function main() {
// 平台单一源:逐域加载包内能力,得到「能力 id → 平台数组」映射(与运行时同一张 PLATFORM_GROUPS 表)
domainPlatformMap = await buildDomainPlatformMap();
console.log(`platform map: ${domainPlatformMap.size} capability ids from ${Object.keys(PLATFORM_GROUPS).length} domains`);
const source = loadCatalogSource();
const vendorMap = loadComponentsNew();
@@ -362,4 +378,10 @@ function main() {
console.log(`output: ${OUT_FILE} (${(size / 1024 / 1024).toFixed(2)} MB)`);
}
main();
/** 能力 id → 平台数组(buildDomainPlatformMap 的结果,main 内填充) */
let domainPlatformMap = new Map();
main().catch((err) => {
console.error(err);
process.exit(1);
});