import { test } from "node:test"; import assert from "node:assert/strict"; import { mkdtemp, readFile, rm } from "node:fs/promises"; import { tmpdir } from "node:os"; import path from "node:path"; import { generateSgRobotArtifacts, writeArtifacts } from "../scripts/generate_sgrobot_flow.mjs"; const trace = { id: "expense-approval", name: "费用审批", description: "打开审批页,填写意见并点击同意。", startUrl: "https://oa.example.test/expense/123", steps: [ { type: "assertText", text: "费用审批", label: "确认在审批页" }, { type: "fill", selector: "textarea[name='comment']", value: "同意", label: "填写审批意见" }, { type: "click", selector: "button[data-action='approve']", label: "点击同意", risk: "write" }, ], }; test("generates SGrobot plan and runtime skill artifacts", () => { const result = generateSgRobotArtifacts(trace, { defaultMode: "execute" }); assert.equal(result.summary.planId, "rrweb-expense-approval"); assert.equal(result.summary.skillName, "rrweb-expense-approval-execute"); assert.equal(result.summary.requiresApproval, true); const plan = result.files.get("plan_templates/rrweb-expense-approval/PlanTemplate.toml"); const skill = result.files.get(".sgclaw-workspace/skills/rrweb-expense-approval-execute/SKILL.toml"); const script = result.files.get(".sgclaw-workspace/skills/rrweb-expense-approval-execute/scripts/execute_trace.js"); assert.equal(plan.includes('skills = ["rrweb-expense-approval-execute"]'), true); assert.equal(plan.includes("requires_approval = true"), true); assert.equal(skill.includes('command = "sgBrowserExcuteJsCodeByDomain"'), true); assert.equal(skill.includes('expected_domain = "oa.example.test"'), true); assert.equal(script.includes('"default_mode": "execute"'), true); assert.equal(script.includes('replace(/[\\s_-]+/g, "")'), true); assert.equal(script.includes('replace(/[\\\\s_-]+/g, "")'), false); }); test("writes generated artifacts under a SGrobot repository root", async () => { const root = await mkdtemp(path.join(tmpdir(), "rrweb-sgrobot-")); try { const result = generateSgRobotArtifacts(trace); await writeArtifacts(root, result.files); const plan = await readFile(path.join(root, "plan_templates/rrweb-expense-approval/PlanTemplate.toml"), "utf8"); const skill = await readFile(path.join(root, ".sgclaw-workspace/skills/rrweb-expense-approval-execute/SKILL.toml"), "utf8"); const evidence = await readFile(path.join(root, ".sgclaw-workspace/skills/rrweb-expense-approval-execute/trace.semantic.json"), "utf8"); assert.match(plan, /skills = \["browser\.open_url"\]/); assert.match(skill, /script_path = "scripts\/execute_trace.js"/); assert.equal(JSON.parse(evidence).id, "expense-approval"); } finally { await rm(root, { recursive: true, force: true }); } });