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:
parent
a7709aefbb
commit
8414c4f355
@ -16,7 +16,7 @@
|
||||
"typecheck": "tsc --noEmit -p tsconfig.json",
|
||||
"check:deps": "node packages/rpa-core/scripts/check-deps.mjs",
|
||||
"rpa-cli": "tsx scripts/rpa-cli.ts",
|
||||
"catalog": "node scripts/build-catalog.mjs",
|
||||
"catalog": "tsx scripts/build-catalog.mjs",
|
||||
"snapshot": "vitest run scripts/capability-snapshot.test.ts",
|
||||
"package": "node scripts/package.mjs",
|
||||
"test": "vitest run",
|
||||
|
||||
37
packages/rpa-core/src/capabilities/platform-groups.test.ts
Normal file
37
packages/rpa-core/src/capabilities/platform-groups.test.ts
Normal file
@ -0,0 +1,37 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { capabilityCount, getCapabilityMeta } from "../engine/registry";
|
||||
import {
|
||||
PLATFORM_GROUPS,
|
||||
buildDomainPlatformMap,
|
||||
capabilityDomains
|
||||
} from "./register-all";
|
||||
|
||||
describe("PLATFORM_GROUPS 平台单一源(迁移指南五件小事 #1)", () => {
|
||||
it("每个能力域都有平台行,不允许缺行", () => {
|
||||
for (const domain of capabilityDomains) {
|
||||
expect(PLATFORM_GROUPS[domain], `域 ${domain} 缺少 PLATFORM_GROUPS 行`).toBeDefined();
|
||||
}
|
||||
expect(Object.keys(PLATFORM_GROUPS).sort()).toEqual([...capabilityDomains].sort());
|
||||
});
|
||||
|
||||
it("现阶段数据只允许 win32,darwin/linux 仅类型占位不填数据", () => {
|
||||
for (const [domain, platforms] of Object.entries(PLATFORM_GROUPS)) {
|
||||
expect(
|
||||
platforms.every((p) => p === "win32"),
|
||||
`域 ${domain} 填了 win32 以外的平台数据`
|
||||
).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
it("registerAll 后所有能力 meta.platforms 与分组表一致(运行时派生)", async () => {
|
||||
// buildDomainPlatformMap 逐域加载(动态 import 有缓存,必须在 registerAll 语义内一次完成)
|
||||
const map = await buildDomainPlatformMap();
|
||||
expect(capabilityCount()).toBeGreaterThan(700);
|
||||
expect(map.size).toBe(capabilityCount());
|
||||
for (const id of map.keys()) {
|
||||
const meta = getCapabilityMeta(id);
|
||||
expect(meta, `能力 ${id} 无 meta`).toBeTruthy();
|
||||
expect(meta!.platforms, `能力 ${id} 的 meta.platforms 未从分组表派生`).toEqual(["win32"]);
|
||||
}
|
||||
});
|
||||
});
|
||||
@ -1,4 +1,53 @@
|
||||
import type { RpaEngine } from "../engine/engine";
|
||||
import { applyPlatformDefaults, capabilityIds, type CapabilityPlatform } from "../engine/registry";
|
||||
|
||||
export type { CapabilityPlatform } from "../engine/registry";
|
||||
|
||||
/**
|
||||
* 平台归属单一权威表(迁移指南「五件小事 #1」,dev-conventions 规则 4)。
|
||||
*
|
||||
* - 运行时 `meta.platforms` 与构建期 catalog `platformTag` 都从这张表派生,
|
||||
* 任何代码不得自行声明第二份平台数据(守卫测试 platform-groups.test.ts 把关)。
|
||||
* - 现阶段所有能力只在 Windows 交互会话验证过,全部标 `["win32"]`;
|
||||
* `darwin`/`linux` 仅类型占位,不填数据。将来支持新平台 = 对应行加平台,仅此而已。
|
||||
* - 后续若某域内出现平台混装(如 remaining-core 里混着 PS 专用能力),
|
||||
* 先把域拆细,再在能力 meta.platforms 里显式声明更窄限制。
|
||||
*/
|
||||
export const PLATFORM_GROUPS: Record<string, CapabilityPlatform[]> = {
|
||||
control: ["win32"],
|
||||
files: ["win32"],
|
||||
http: ["win32"],
|
||||
data: ["win32"],
|
||||
office: ["win32"],
|
||||
desktop: ["win32"],
|
||||
desktopUia: ["win32"],
|
||||
time: ["win32"],
|
||||
windowsSystem: ["win32"],
|
||||
ftp: ["win32"],
|
||||
ocr: ["win32"],
|
||||
pdf: ["win32"],
|
||||
word: ["win32"],
|
||||
wordExtended: ["win32"],
|
||||
message: ["win32"],
|
||||
vision: ["win32"],
|
||||
cvVision: ["win32"],
|
||||
extended: ["win32"],
|
||||
systemExtended: ["win32"],
|
||||
officeFileExtended: ["win32"],
|
||||
officeAliases: ["win32"],
|
||||
excelCommon: ["win32"],
|
||||
excelCom: ["win32"],
|
||||
dataExtended: ["win32"],
|
||||
utilityExtended: ["win32"],
|
||||
dataTableCommon: ["win32"],
|
||||
basicEncryption: ["win32"],
|
||||
mailRemaining: ["win32"],
|
||||
remainingCore: ["win32"],
|
||||
commonFinal: ["win32"],
|
||||
humanDialog: ["win32"],
|
||||
aiService: ["win32"],
|
||||
windowExtended: ["win32"]
|
||||
};
|
||||
|
||||
/**
|
||||
* 显式注册入口(任务 4.2,决策点 9:双入口过渡)。
|
||||
@ -46,14 +95,35 @@ const DOMAINS: Record<string, () => Promise<unknown>> = {
|
||||
windowExtended: () => import("./window-extended")
|
||||
};
|
||||
|
||||
async function loadDomainWithPlatformDefaults(domain: string): Promise<Set<string>> {
|
||||
const load = DOMAINS[domain];
|
||||
if (!load) throw new Error(`未知能力域:${domain}(可选:${Object.keys(DOMAINS).join(", ")})`);
|
||||
const before = new Set(capabilityIds());
|
||||
await load();
|
||||
const fresh = [...capabilityIds()].filter((id) => !before.has(id));
|
||||
// 平台默认值从 PLATFORM_GROUPS 派生(单一源);能力显式声明的 platforms 优先
|
||||
applyPlatformDefaults(fresh, PLATFORM_GROUPS[domain] ?? []);
|
||||
return new Set(fresh);
|
||||
}
|
||||
|
||||
export async function registerAll(engine: RpaEngine, groups?: string[]): Promise<RpaEngine> {
|
||||
const wanted = groups && groups.length ? groups : Object.keys(DOMAINS);
|
||||
for (const group of wanted) {
|
||||
const load = DOMAINS[group];
|
||||
if (!load) throw new Error(`未知能力域:${group}(可选:${Object.keys(DOMAINS).join(", ")})`);
|
||||
await load();
|
||||
}
|
||||
for (const group of wanted) await loadDomainWithPlatformDefaults(group);
|
||||
return engine;
|
||||
}
|
||||
|
||||
/**
|
||||
* 逐域加载并返回「能力 id → 平台数组」映射(副作用:完成全量注册)。
|
||||
* 供构建脚本(build-catalog)派生 catalog platformTag,与运行时同一张表。
|
||||
*/
|
||||
export async function buildDomainPlatformMap(): Promise<Map<string, CapabilityPlatform[]>> {
|
||||
const map = new Map<string, CapabilityPlatform[]>();
|
||||
for (const domain of Object.keys(DOMAINS)) {
|
||||
const fresh = await loadDomainWithPlatformDefaults(domain);
|
||||
const platforms = PLATFORM_GROUPS[domain] ?? [];
|
||||
for (const id of fresh) map.set(id, platforms);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
export const capabilityDomains = Object.keys(DOMAINS);
|
||||
|
||||
@ -13,6 +13,9 @@ export interface CapabilityParamMeta {
|
||||
description?: string;
|
||||
}
|
||||
|
||||
/** 平台类型;现阶段只有 win32 有实现,darwin/linux 仅类型占位(dev-conventions 规则 4) */
|
||||
export type CapabilityPlatform = "win32" | "darwin" | "linux";
|
||||
|
||||
export interface CapabilityMeta {
|
||||
/** 一句话能力摘要(中文) */
|
||||
summary?: string;
|
||||
@ -27,7 +30,7 @@ export interface CapabilityMeta {
|
||||
/** 执行中是否需要回传截图(Agent 侧视觉判断用) */
|
||||
needsScreenshot?: boolean;
|
||||
/** 平台限制;省略表示跨平台 */
|
||||
platforms?: Array<"win32">;
|
||||
platforms?: CapabilityPlatform[];
|
||||
}
|
||||
|
||||
const handlers = new Map<string, CapabilityHandler>();
|
||||
@ -60,3 +63,21 @@ export function capabilityIds(): string[] {
|
||||
export function capabilityCount(): number {
|
||||
return handlers.size;
|
||||
}
|
||||
|
||||
/**
|
||||
* 给一批能力落平台默认值(来自 register-all.ts 的 PLATFORM_GROUPS 单一权威表)。
|
||||
* - 空数组 = 平台无限制,不落 meta;
|
||||
* - 已有 meta 且已声明 platforms 的不覆盖(能力可显式声明更窄的平台限制);
|
||||
* - 无 meta 的补一个只含 platforms 的 meta。
|
||||
*/
|
||||
export function applyPlatformDefaults(ids: string[], platforms: CapabilityPlatform[]): void {
|
||||
if (!platforms.length) return;
|
||||
for (const id of ids) {
|
||||
const meta = metas.get(id);
|
||||
if (meta) {
|
||||
if (!meta.platforms) metas.set(id, { ...meta, platforms: [...platforms] });
|
||||
} else {
|
||||
metas.set(id, { platforms: [...platforms] });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
{
|
||||
"generatedAt": "2026-11-04T09:12:00.449Z",
|
||||
"generatedAt": "2026-11-05T09:52:08.862Z",
|
||||
"count": 909,
|
||||
"ids": [
|
||||
"App_GetPid",
|
||||
|
||||
@ -176,7 +176,25 @@
|
||||
"cvSelector": {
|
||||
"description": "屏幕上可见的目标文本,运行时截屏后通过 OCR 定位(填按钮或界面上的文字,如「登录」)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"removeFields": [
|
||||
"searchRegion"
|
||||
],
|
||||
"addFields": [
|
||||
{
|
||||
"key": "searchRegion",
|
||||
"label": "搜索区域",
|
||||
"widget": "region",
|
||||
"type": "object",
|
||||
"displayType": "region",
|
||||
"required": false,
|
||||
"defaultValue": "",
|
||||
"placeholder": "",
|
||||
"description": "可选。点「屏幕框选」框住目标所在区域,运行时只在该区域内查找目标文本,屏幕上有相同文字时可避免点错;留空则全屏查找",
|
||||
"advanced": false,
|
||||
"valueTypes": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"CV_SetText": {
|
||||
"fields": {
|
||||
@ -187,7 +205,25 @@
|
||||
"description": "填写参数值,支持 ${变量} 引用上游输出",
|
||||
"placeholder": "输入内容或 ${变量}"
|
||||
}
|
||||
}
|
||||
},
|
||||
"removeFields": [
|
||||
"searchRegion"
|
||||
],
|
||||
"addFields": [
|
||||
{
|
||||
"key": "searchRegion",
|
||||
"label": "搜索区域",
|
||||
"widget": "region",
|
||||
"type": "object",
|
||||
"displayType": "region",
|
||||
"required": false,
|
||||
"defaultValue": "",
|
||||
"placeholder": "",
|
||||
"description": "可选。点「屏幕框选」框住目标所在区域,运行时只在该区域内查找目标文本,屏幕上有相同文字时可避免点错;留空则全屏查找",
|
||||
"advanced": false,
|
||||
"valueTypes": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"CV_MouseHover": {
|
||||
"fields": {
|
||||
@ -200,7 +236,25 @@
|
||||
"offsetY": {
|
||||
"description": "相对目标中心的垂直偏移像素,正数向下、负数向上,0 为正中"
|
||||
}
|
||||
}
|
||||
},
|
||||
"removeFields": [
|
||||
"searchRegion"
|
||||
],
|
||||
"addFields": [
|
||||
{
|
||||
"key": "searchRegion",
|
||||
"label": "搜索区域",
|
||||
"widget": "region",
|
||||
"type": "object",
|
||||
"displayType": "region",
|
||||
"required": false,
|
||||
"defaultValue": "",
|
||||
"placeholder": "",
|
||||
"description": "可选。点「屏幕框选」框住目标所在区域,运行时只在该区域内查找目标文本,屏幕上有相同文字时可避免点错;留空则全屏查找",
|
||||
"advanced": false,
|
||||
"valueTypes": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"CV_MouseClick": {
|
||||
"fields": {
|
||||
@ -216,7 +270,25 @@
|
||||
"offsetY": {
|
||||
"description": "相对目标中心的垂直偏移像素,正数向下、负数向上,0 为正中"
|
||||
}
|
||||
}
|
||||
},
|
||||
"removeFields": [
|
||||
"searchRegion"
|
||||
],
|
||||
"addFields": [
|
||||
{
|
||||
"key": "searchRegion",
|
||||
"label": "搜索区域",
|
||||
"widget": "region",
|
||||
"type": "object",
|
||||
"displayType": "region",
|
||||
"required": false,
|
||||
"defaultValue": "",
|
||||
"placeholder": "",
|
||||
"description": "可选。点「屏幕框选」框住目标所在区域,运行时只在该区域内查找目标文本,屏幕上有相同文字时可避免点错;留空则全屏查找",
|
||||
"advanced": false,
|
||||
"valueTypes": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"Image_Click": {
|
||||
"fields": {
|
||||
@ -225,6 +297,9 @@
|
||||
},
|
||||
"show_track": {
|
||||
"description": "勾选后运行时显示鼠标移动轨迹动画,便于观察执行过程"
|
||||
},
|
||||
"accuracy2": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -298,15 +373,14 @@
|
||||
"Image_Screenshot": {
|
||||
"fields": {
|
||||
"image_path": {
|
||||
"placeholder": "如 D:\\files\\demo.png"
|
||||
"label": "截图保存路径"
|
||||
},
|
||||
"action": {
|
||||
"description": "区域坐标 JSON;点右侧「屏幕框选」在屏幕上框选生成",
|
||||
"placeholder": "{\"x\":0,\"y\":0,\"width\":100,\"height\":50}"
|
||||
},
|
||||
"position": {
|
||||
"description": "区域坐标 JSON;点右侧「屏幕框选」在屏幕上框选生成",
|
||||
"placeholder": "{\"x\":0,\"y\":0,\"width\":100,\"height\":50}"
|
||||
"label": "截图区域"
|
||||
},
|
||||
"position_img": {
|
||||
"description": "区域坐标 JSON;点右侧「屏幕框选」在屏幕上框选生成",
|
||||
@ -332,7 +406,68 @@
|
||||
"path": {
|
||||
"description": "编码方向的源图片路径,支持 ${变量} 引用上游输出(如上游截图的保存路径)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"removeFields": [
|
||||
"mode",
|
||||
"output",
|
||||
"val"
|
||||
],
|
||||
"addFields": [
|
||||
{
|
||||
"key": "mode",
|
||||
"label": "转换方向",
|
||||
"widget": "radio",
|
||||
"type": "string",
|
||||
"displayType": "buttonGroup",
|
||||
"required": false,
|
||||
"defaultValue": "encode",
|
||||
"placeholder": "",
|
||||
"description": "编码:图片文件转为 base64 字符串;解码:base64 字符串还原保存为图片文件",
|
||||
"advanced": false,
|
||||
"valueTypes": [],
|
||||
"options": [
|
||||
{
|
||||
"label": "图片 → Base64",
|
||||
"value": "encode"
|
||||
},
|
||||
{
|
||||
"label": "Base64 → 图片",
|
||||
"value": "decode"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "output",
|
||||
"label": "图片保存路径",
|
||||
"widget": "file",
|
||||
"type": "object",
|
||||
"displayType": "selectFile",
|
||||
"required": false,
|
||||
"defaultValue": "",
|
||||
"placeholder": "如 D:\\files\\restored.png",
|
||||
"description": "解码方向的保存位置(含文件名);留空自动生成临时图片文件",
|
||||
"advanced": false,
|
||||
"valueTypes": [
|
||||
"rpa_str_file",
|
||||
"rpa_str"
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "val",
|
||||
"label": "Base64编码",
|
||||
"widget": "text",
|
||||
"type": "string",
|
||||
"displayType": "text-expression",
|
||||
"required": true,
|
||||
"defaultValue": "",
|
||||
"placeholder": "如 ${图片编码值}",
|
||||
"description": "解码方向的 base64 字符串,支持 ${变量} 引用上游输出;自动忽略 data:image/...;base64, 前缀",
|
||||
"advanced": false,
|
||||
"valueTypes": [
|
||||
"rpa_str"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"Image_Wait_V1": {
|
||||
"fields": {
|
||||
@ -413,7 +548,7 @@
|
||||
"Image_Find_V1": {
|
||||
"fields": {
|
||||
"window_obj": {
|
||||
"description": "目标窗口标题,留空则作用于当前活动窗口;点「选窗口」从可见窗口列表中选择"
|
||||
"required": false
|
||||
},
|
||||
"action": {
|
||||
"description": "区域坐标 JSON;点右侧「屏幕框选」在屏幕上框选生成",
|
||||
@ -425,23 +560,75 @@
|
||||
},
|
||||
"image": {
|
||||
"description": "模板图片文件的完整路径,用于匹配识别;点右侧「屏幕截取」可框选屏幕上的目标图案"
|
||||
},
|
||||
"accuracy": {
|
||||
"label": "模板相似度"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Image_Exists_V1": {
|
||||
"fields": {
|
||||
"image": {
|
||||
"description": "模板图片文件的完整路径,用于匹配识别;点右侧「屏幕截取」可框选屏幕上的目标图案"
|
||||
"required": true,
|
||||
"label": "目标图像"
|
||||
},
|
||||
"accuracy": {
|
||||
"description": "相似度阈值(0~1,越大越严格):0.9 表示屏幕上至少 90% 像素与模板一致才算找到。建议 0.8~0.9。"
|
||||
"required": true,
|
||||
"label": "模板相似度"
|
||||
}
|
||||
}
|
||||
},
|
||||
"removeFields": [
|
||||
"find_range",
|
||||
"timeout",
|
||||
"window_obj"
|
||||
],
|
||||
"addFields": [
|
||||
{
|
||||
"key": "find_range",
|
||||
"label": "图像查找范围",
|
||||
"widget": "select",
|
||||
"displayType": "dropDownSelect",
|
||||
"defaultValue": "1",
|
||||
"required": false,
|
||||
"options": [
|
||||
{
|
||||
"label": "整个屏幕",
|
||||
"value": "1"
|
||||
},
|
||||
{
|
||||
"label": "指定窗口",
|
||||
"value": "2"
|
||||
}
|
||||
],
|
||||
"description": "在整个虚拟桌面(含副屏)中查找,或仅在指定窗口范围内查找",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"key": "timeout",
|
||||
"label": "等待超时(秒)",
|
||||
"widget": "number",
|
||||
"displayType": "text-expression",
|
||||
"defaultValue": "0",
|
||||
"required": false,
|
||||
"description": "大于 0 时在该时间内每隔 0.3 秒重试查找,超时仍未找到才返回 false",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"key": "window_obj",
|
||||
"label": "窗口对象",
|
||||
"widget": "text",
|
||||
"displayType": "text-expression",
|
||||
"defaultValue": "",
|
||||
"required": false,
|
||||
"description": "目标窗口标题,留空则作用于当前活动窗口;点「选窗口」从可见窗口列表中选择",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"Image_CropImg": {
|
||||
"fields": {
|
||||
"file_path": {
|
||||
"description": "要被裁剪的源图片完整路径——本组件从已有图片文件中裁出区域,不是截屏;截屏请用「截图图像」组件"
|
||||
"label": "源图片地址"
|
||||
},
|
||||
"imagePath": {
|
||||
"description": "文件夹的完整路径;点右侧按钮浏览选择,支持 ${变量} 引用"
|
||||
@ -467,13 +654,16 @@
|
||||
},
|
||||
"show_track": {
|
||||
"description": "勾选后运行时显示鼠标移动轨迹动画,便于观察执行过程"
|
||||
},
|
||||
"accuracy2": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"Image_Click_V3": {
|
||||
"fields": {
|
||||
"window_obj": {
|
||||
"description": "目标窗口标题,留空则作用于当前活动窗口;点「选窗口」从可见窗口列表中选择"
|
||||
"required": false
|
||||
},
|
||||
"action": {
|
||||
"description": "区域坐标 JSON;点右侧「屏幕框选」在屏幕上框选生成",
|
||||
@ -500,10 +690,10 @@
|
||||
"Image_RelativePosition": {
|
||||
"fields": {
|
||||
"source": {
|
||||
"description": "被搜索的较大图片路径(如整屏截图),支持 ${变量} 引用上游输出"
|
||||
"label": "被搜索图像"
|
||||
},
|
||||
"template": {
|
||||
"description": "要寻找的小图案完整路径(按钮/图标/文字块),可点右侧按钮选择文件"
|
||||
"label": "查找目标(小图)"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -1346,5 +1536,626 @@
|
||||
"description": "选择解压使用的执行方式;不确定时保持默认。"
|
||||
}
|
||||
}
|
||||
},
|
||||
"WebBrowser_RunJsInIeBySelector_v3": {
|
||||
"fields": {
|
||||
"waitResultTimeout": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"StrUtil_CreateRandomStr": {
|
||||
"fields": {
|
||||
"special_str": {
|
||||
"required": false
|
||||
},
|
||||
"min_max_length": {
|
||||
"required": false
|
||||
},
|
||||
"str_contain": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"Element_SetAttribute_v2": {
|
||||
"fields": {
|
||||
"designated_obj": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"Element_FileUploader": {
|
||||
"fields": {
|
||||
"upload_time": {
|
||||
"required": false
|
||||
},
|
||||
"wait_dialog_time": {
|
||||
"required": false
|
||||
},
|
||||
"designated_obj": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"WebBrowser_GetCookieNew": {
|
||||
"fields": {
|
||||
"web": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"WebBrowser_Wait": {
|
||||
"fields": {
|
||||
"web": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"WebBrowser_GetWeblistening": {
|
||||
"fields": {
|
||||
"web": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"WebBrowser_SetCookies": {
|
||||
"fields": {
|
||||
"web": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"Element_GetAttribute_v2": {
|
||||
"fields": {
|
||||
"designated_obj": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"Trigger.Manual": {
|
||||
"fields": {
|
||||
"entryName": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"Keyboard_Send_V1": {
|
||||
"removeFields": [
|
||||
"window_title"
|
||||
],
|
||||
"addFields": [
|
||||
{
|
||||
"key": "window_title",
|
||||
"label": "输入目标窗口",
|
||||
"widget": "text",
|
||||
"type": "string",
|
||||
"displayType": "text-expression",
|
||||
"required": false,
|
||||
"defaultValue": "",
|
||||
"placeholder": "留空则输入到当前焦点窗口",
|
||||
"description": "选择目标窗口后,运行时会先把该窗口带到前台再输入内容",
|
||||
"advanced": false,
|
||||
"valueTypes": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"Mail_ReplyMail_v2": {
|
||||
"fields": {
|
||||
"emails": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"WebBrowser_GoForward": {
|
||||
"fields": {
|
||||
"web": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"WebBrowser_Stop": {
|
||||
"fields": {
|
||||
"web": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"WebBrowser_GetScrollPos_V1": {
|
||||
"fields": {
|
||||
"web": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"WebBrowser_UploadDialog": {
|
||||
"fields": {
|
||||
"upload_time": {
|
||||
"required": false
|
||||
},
|
||||
"web": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"Element_GetPieChartData": {
|
||||
"fields": {
|
||||
"v_offset": {
|
||||
"required": false
|
||||
},
|
||||
"radius_ratio": {
|
||||
"required": false
|
||||
},
|
||||
"designated_obj": {
|
||||
"required": false
|
||||
},
|
||||
"h_offset": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"Mail_OperateMail": {
|
||||
"fields": {
|
||||
"emails": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"Element_GetButtonEnable_v3": {
|
||||
"fields": {
|
||||
"designated_obj": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"StrUtil_SplitStr": {
|
||||
"fields": {
|
||||
"split_num": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"Element_SetValue_V6": {
|
||||
"fields": {
|
||||
"designated_obj": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"WebBrowser_GoUrl": {
|
||||
"fields": {
|
||||
"web": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"WebBrowser_SetScrollPos_V1": {
|
||||
"fields": {
|
||||
"designated_selector": {
|
||||
"required": false
|
||||
},
|
||||
"designated_position": {
|
||||
"required": false
|
||||
},
|
||||
"web": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"logic_control_stop_return": {
|
||||
"fields": {
|
||||
"return_value": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"WebBrowser_GetScrollPos": {
|
||||
"fields": {
|
||||
"web": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"Element_MouseTo_V4": {
|
||||
"fields": {
|
||||
"designated_obj": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"Element_GetButtonEnable_v4": {
|
||||
"fields": {
|
||||
"designated_obj": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"WebBrowser_GetBrowserPicV1": {
|
||||
"fields": {
|
||||
"pic_name": {
|
||||
"required": false
|
||||
},
|
||||
"web": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"Trigger.FileArrival": {
|
||||
"fields": {
|
||||
"stableSeconds": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"WebBrowser_GetCookies": {
|
||||
"fields": {
|
||||
"web": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"Bivartable_HandleDfMissValue": {
|
||||
"fields": {
|
||||
"row_num_list": {
|
||||
"required": false
|
||||
},
|
||||
"col_num_list": {
|
||||
"required": false
|
||||
},
|
||||
"row_name_list": {
|
||||
"required": false
|
||||
},
|
||||
"col_name_list": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"WebBrowser_StopWeblistening": {
|
||||
"fields": {
|
||||
"web": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"Image_Find": {
|
||||
"fields": {
|
||||
"accuracy2": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"Element_exception_monitor_v2": {
|
||||
"fields": {
|
||||
"monitor_frequency": {
|
||||
"required": false
|
||||
},
|
||||
"designated_obj": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"WebBrowser_GetDocument": {
|
||||
"fields": {
|
||||
"web": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"Element_GetAttribute_v3": {
|
||||
"fields": {
|
||||
"designated_obj": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"WebBrowser_Switch": {
|
||||
"fields": {
|
||||
"web": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"Mail_DoReplyMail_v1": {
|
||||
"fields": {
|
||||
"emails": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"concurrent_child_process_v1": {
|
||||
"fields": {
|
||||
"fun_name": {
|
||||
"required": false
|
||||
},
|
||||
"call_type": {
|
||||
"required": false
|
||||
},
|
||||
"fun_version": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"Element_Click_V6": {
|
||||
"fields": {
|
||||
"designated_obj": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"WebBrowser_SetScrollPos": {
|
||||
"fields": {
|
||||
"web": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"WebBrowser_Reload": {
|
||||
"fields": {
|
||||
"web": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"WebBrowser_GetCookie": {
|
||||
"fields": {
|
||||
"web": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"WebBrowser_GetTitle": {
|
||||
"fields": {
|
||||
"web": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"WebBrowser_GetUrl": {
|
||||
"fields": {
|
||||
"web": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"WebBrowser_Maximize": {
|
||||
"fields": {
|
||||
"web": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"child_modules_v1": {
|
||||
"fields": {
|
||||
"fun_name": {
|
||||
"required": false
|
||||
},
|
||||
"call_type": {
|
||||
"required": false
|
||||
},
|
||||
"fun_version": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"Element_SelectOperation_v2": {
|
||||
"fields": {
|
||||
"designated_obj": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"WebBrowser_Minimize": {
|
||||
"fields": {
|
||||
"web": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"WebBrowser_Close": {
|
||||
"fields": {
|
||||
"web": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"Element_GetLineBarChartData": {
|
||||
"fields": {
|
||||
"offset": {
|
||||
"required": false
|
||||
},
|
||||
"designated_obj": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"WebBrowser_DownloadFile_V1": {
|
||||
"fields": {
|
||||
"designated_obj": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"Element_GetText_V5": {
|
||||
"fields": {
|
||||
"designated_obj": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"Trigger.Schedule": {
|
||||
"fields": {
|
||||
"timezone": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"StrUtil_ListToString": {
|
||||
"fields": {
|
||||
"connectors_num": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"WebBrowser_StartWeblistening": {
|
||||
"fields": {
|
||||
"web": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"WebBrowser_SetCookies_V1": {
|
||||
"fields": {
|
||||
"web": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"Keyboard_Send": {
|
||||
"removeFields": [
|
||||
"window_title"
|
||||
],
|
||||
"addFields": [
|
||||
{
|
||||
"key": "window_title",
|
||||
"label": "输入目标窗口",
|
||||
"widget": "text",
|
||||
"type": "string",
|
||||
"displayType": "text-expression",
|
||||
"required": false,
|
||||
"defaultValue": "",
|
||||
"placeholder": "留空则输入到当前焦点窗口",
|
||||
"description": "选择目标窗口后,运行时会先把该窗口带到前台再输入内容",
|
||||
"advanced": false,
|
||||
"valueTypes": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"WebBrowser_CloseWeb": {
|
||||
"fields": {
|
||||
"web": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"Element_CheckBoxOperation_v3": {
|
||||
"fields": {
|
||||
"designated_obj": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"MessageNotification_Feishu_Message": {
|
||||
"fields": {
|
||||
"mentioned_list": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"WebBrowser_RunJsInIeBySelectorGround": {
|
||||
"fields": {
|
||||
"web": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"Word_SaveAs": {
|
||||
"fields": {
|
||||
"fileAddr": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"Mouse_ClickCombine_v4": {
|
||||
"fields": {
|
||||
"designated_obj": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"WebBrowser_RunJsInIeBySelector_v2": {
|
||||
"fields": {
|
||||
"designated_obj": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"Bivartable_DfWriteToFile": {
|
||||
"fields": {
|
||||
"suffix": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"Element_WaitElement_v5": {
|
||||
"fields": {
|
||||
"designated_obj": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"WebBrowser_Switch_V1": {
|
||||
"fields": {
|
||||
"web": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"Element_Region2_v3": {
|
||||
"fields": {
|
||||
"designated_obj": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"WebBrowser_GoBack": {
|
||||
"fields": {
|
||||
"web": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"Element_Shot_V2": {
|
||||
"fields": {
|
||||
"designated_obj": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"Element_ScrollIntoView_v2": {
|
||||
"fields": {
|
||||
"designated_obj": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"WebBrowser_GetBrowserPic": {
|
||||
"fields": {
|
||||
"web": {
|
||||
"required": false
|
||||
},
|
||||
"pic": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"Element_SelectOperation_v3": {
|
||||
"fields": {
|
||||
"designated_obj": {
|
||||
"required": false
|
||||
},
|
||||
"select_value_list": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"ScreenControl_Screenlock": {
|
||||
"name": "屏幕锁屏",
|
||||
"removeFields": [
|
||||
"username",
|
||||
"pwd",
|
||||
"width",
|
||||
"height",
|
||||
"scale_factor",
|
||||
"port"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
125488
resources/catalog.json
125488
resources/catalog.json
File diff suppressed because one or more lines are too long
@ -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);
|
||||
});
|
||||
|
||||
@ -7,10 +7,17 @@ export function applyCatalogOverrides(catalog) {
|
||||
for (const component of catalog.components) {
|
||||
const override = overrides[component.id];
|
||||
if (!override) continue;
|
||||
const { fields = {}, removeFields = [], ...metadata } = override;
|
||||
const { fields = {}, addFields = [], removeFields = [], ...metadata } = override;
|
||||
Object.assign(component, metadata);
|
||||
component.fields = component.fields.filter(field => !removeFields.includes(field.key))
|
||||
.map(field => ({ ...field, ...fields[field.key] }));
|
||||
// addFields:补源数据里缺失、但实现确实读取的字段(完整字段定义,key 重复则跳过)
|
||||
if (addFields.length) {
|
||||
const have = new Set(component.fields.map(f => f.key));
|
||||
for (const f of addFields) {
|
||||
if (f && f.key && !have.has(f.key)) component.fields.push(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
catalog.counts.fields = catalog.components.reduce((count, component) => count + component.fields.length, 0);
|
||||
return catalog;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user