// Embed the DeepSeek Harness-specific browser skill at build time. The model-facing // skill deliberately documents only injected browser_* tools; the repository's CLI // skill is a separate interface and must never be concatenated here. // Output: src/skill-content.generated.ts (gitignored, built before tsdown and // before vitest), so registration is a pure in-memory read. import { readFileSync, writeFileSync } from "node:fs"; import { dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; const here = dirname(fileURLToPath(import.meta.url)); const pkg = join(here, ".."); const source = readFileSync(join(pkg, "skill", "SKILL.md"), "utf8"); function stripFrontmatter(markdown) { if (!markdown.startsWith("---\n")) return markdown; const end = markdown.indexOf("\n---\n", 4); return end === -1 ? markdown : markdown.slice(end + 5).replace(/^\s*\n/, ""); } const SUPPORTED_BROWSER_TOOLS = [ "browser_session", "browser_page", "browser_inspect", "browser_interact", "browser_tabs", "browser_assist", ]; function validateModelFacingSkill(markdown, supportedTools) { if (/\bbsk\b/i.test(markdown)) { throw new Error("DSH skill must not expose the internal CLI name"); } if (/```(?:bash|sh|shell)\b/i.test(markdown)) { throw new Error("DSH skill must not contain command-line code blocks"); } const mentioned = new Set(markdown.match(/\bbrowser_[a-z][a-z_]*\b/g) ?? []); const supported = new Set(supportedTools); const unknown = [...mentioned].filter((name) => !supported.has(name)); const missing = supportedTools.filter((name) => !mentioned.has(name)); if (unknown.length > 0) { throw new Error(`DSH skill mentions unsupported browser tools: ${unknown.join(", ")}`); } if (missing.length > 0) { throw new Error(`DSH skill omits supported browser tools: ${missing.join(", ")}`); } } const NAME = "browser-skill"; const DESCRIPTION = "Browser automation against the user's logged-in Chromium through this plugin's injected " + "browser_* tools. Use to visit and read pages, fill forms, click through flows, inspect tabs, " + "debug page activity, or smoke-test UI changes in a managed Agent Window."; const content = `${stripFrontmatter(source).trim()}\n`; validateModelFacingSkill(content, SUPPORTED_BROWSER_TOOLS); const banner = "// GENERATED by scripts/build-skill-content.mjs — do not edit.\n" + "// Source: skill/SKILL.md (DeepSeek Harness six-tool instructions).\n"; writeFileSync( join(pkg, "src", "skill-content.generated.ts"), `${banner}export const BSK_SKILL_NAME = ${JSON.stringify(NAME)};\n` + `export const BSK_SKILL_DESCRIPTION = ${JSON.stringify(DESCRIPTION)};\n` + `export const BSK_SKILL_MARKDOWN = ${JSON.stringify(content)};\n`, ); console.log(`skill-content.generated.ts written (${content.length} chars)`);