Files
PRA-only-demo/src/main/capabilities/ai-caps.ts
T
yu e25121660d 修复点击验证误报与相似元素列表全重复等运行时问题
- 点击可信验证增加两类生效旁证: 页面跳转/新开标签页(淘宝搜索按钮),
  点击后元素整体消失(关闭登录弹窗); 此前均被误报为"目标未收到可信点击"
  并在节点超时内反复重试, 造成"点击生效却等很久还报错"
- 相似元素列表引用增加 index 序号: 动态id泛化后各卡片选择器相同,
  46 条引用全部命中第一张卡导致抓取结果全重复;
  修复 NodeList 无 indexOf 的 TypeError 被静默吞掉导致序号从未写入
- 元素定位改为两段式: 先在当前附着页查找, 找不到才跟随前台标签页,
  避免多标签环境下被无条件切到 pages[0] 导致找错页面
- 新开标签页优先复用启动残留的 about:blank 空白页, 不再堆积空标签
- AI 能力输入识别增加 hint_word 字段(此前提示词读到的是空)
- try_catch 捕获子步骤失败时记录 warn 日志, 不再静默
- Excel 落盘遇 EBUSY(文件被打开占用)时自动另存为带时间戳的文件
- 新增 similar-list.test.ts 端到端回归(46 卡片动态 id 真实浏览器验证)
- 新增 export-last-run.js: 从运行记录导出比价 Excel
2026-11-05 14:57:33 +08:00

56 lines
3.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { register } from "@rpa/core";
import { RuntimeError } from "@rpa/core";
import { chatCompletion, requireAiConfig } from "@rpa/core";
function inputText(args: Record<string, unknown>, nodeId: string): string {
for (const key of ["input", "hint_word", "text", "content", "sentence", "prompt", "sourceFilePath", "filePath", "source", "document"]) {
const v = String(args[key] ?? "").trim();
if (v) return v;
}
throw new RuntimeError("validation_error", "输入文本为空", { nodeId, componentId: nodeId });
}
async function readMaybeFile(value: string): Promise<string> {
const looksLikeFile = /\.(txt|md|csv|json|log)$/i.test(value) && value.length < 260 && !value.includes("\n");
if (!looksLikeFile) return value;
try {
const fs = await import("node:fs/promises");
const stat = await fs.stat(value);
if (stat.isFile()) return await fs.readFile(value, "utf8");
} catch { /* treat the value as literal text */ }
return value;
}
async function complete(prompt: string, input: string, temperature = 0.3): Promise<string> {
requireAiConfig();
return chatCompletion([
{ role: "system", content: prompt },
{ role: "user", content: input }
], { temperature });
}
const TEXT_TASKS: Array<{ ids: string[]; system: string; task: string }> = [
{ ids: ["DataService_AIGenTxt"], system: "你是写作助手,根据用户要求生成高质量中文内容。", task: "AI 生成文本" },
{ ids: ["DataService_LargeModel", "DataService_ZBrain", "DataService_AgentCall", "NLP_XunFei_NLPBaseServer"], system: "你是智能助手,尽力完成用户的任务。", task: "通用模型调用" },
{ ids: ["DataService_ChatBot"], system: "你是对话机器人,用中文自然对话。", task: "对话机器人" },
{ ids: ["DataService_KeyWord", "NLP_KeyWordsAnalysis", "NLP_SplitText"], system: "从文本中提取关键词,输出 JSON 数组(字符串列表),不要输出其他内容。", task: "关键词抽取" },
{ ids: ["DataService_Correct"], system: "修正文本中的错别字与语病,直接输出修正后的全文。", task: "文本纠错" },
{ ids: ["DataService_Review"], system: '审核文本内容是否合规,输出 JSON:{\"pass\":true/false,\"reason\":\"原因\"}。', task: "文本审核" },
{ ids: ["DataService_TextComparison", "Scenario_TextComparison"], system: "比较两段文本差异,输出简明差异摘要。", task: "文档比对" },
{ ids: ["NLP_SplitWords"], system: '对文本分词,输出 JSON 数组(字符串列表)。', task: "分词" },
{ ids: ["NLP_EmotionalAnalysis"], system: '分析文本情感倾向,输出 JSON:{\"label\":\"正面/负面/中性\",\"score\":0.99}。', task: "情感分析" },
{ ids: ["NLP_SemanticSimilarity"], system: '判断两段文本语义相似度,输出 JSON:{\"score\":0.99}(0-1)。输入格式:文本1\n---\n文本2。', task: "语义相似度" },
{ ids: ["NLP_PerspectiveAnalysis"], system: '分析文本中的观点与立场,输出 JSON:{\"perspectives\":[{\"view\":\"...\",\"stance\":\"支持/反对/中立\"}]}。', task: "观点分析" },
{ ids: ["NLP_AnalyseProductReview", "NLP_BatchAnalyseProductReview"], system: '分析商品评论,输出 JSON:{\"summary\":\"...\",\"sentiment\":\"...\",\"issues\":[]}。', task: "商品评论分析" },
];
for (const task of TEXT_TASKS) {
register(task.ids, async (ctx, node, args) => {
const rawInput = inputText(args, node.id);
const input = await readMaybeFile(rawInput);
const result = await complete(task.system, input);
ctx.log(task.task + "完成", "info", node.id);
return result;
});
}