prose-qa 0.1.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +65 -502
- package/dist/agent/bash.d.ts +1 -1
- package/dist/agent/bash.d.ts.map +1 -1
- package/dist/agent/bash.js +23 -4
- package/dist/agent/bash.js.map +1 -1
- package/dist/agent/bash.test.js +27 -3
- package/dist/agent/bash.test.js.map +1 -1
- package/dist/agent/llm-model.d.ts.map +1 -1
- package/dist/agent/llm-model.js +19 -10
- package/dist/agent/llm-model.js.map +1 -1
- package/dist/agent/prompt.d.ts.map +1 -1
- package/dist/agent/prompt.js +10 -2
- package/dist/agent/prompt.js.map +1 -1
- package/dist/agent/prompt.test.js +0 -1
- package/dist/agent/prompt.test.js.map +1 -1
- package/dist/agent/runner.d.ts.map +1 -1
- package/dist/agent/runner.js +80 -12
- package/dist/agent/runner.js.map +1 -1
- package/dist/agent/runner.test.d.ts +2 -0
- package/dist/agent/runner.test.d.ts.map +1 -0
- package/dist/agent/runner.test.js +83 -0
- package/dist/agent/runner.test.js.map +1 -0
- package/dist/agent/transcript-persist.d.ts +9 -0
- package/dist/agent/transcript-persist.d.ts.map +1 -0
- package/dist/agent/transcript-persist.js +6 -0
- package/dist/agent/transcript-persist.js.map +1 -0
- package/dist/agent/transcript-persist.test.d.ts +2 -0
- package/dist/agent/transcript-persist.test.d.ts.map +1 -0
- package/dist/agent/transcript-persist.test.js +56 -0
- package/dist/agent/transcript-persist.test.js.map +1 -0
- package/dist/agent/verdict.d.ts +8 -2
- package/dist/agent/verdict.d.ts.map +1 -1
- package/dist/agent/verdict.js +49 -0
- package/dist/agent/verdict.js.map +1 -1
- package/dist/agent/verdict.test.js +85 -1
- package/dist/agent/verdict.test.js.map +1 -1
- package/dist/cli/analyze.js +7 -7
- package/dist/cli/analyze.js.map +1 -1
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/help.js +53 -17
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/help.test.js +1 -0
- package/dist/cli/help.test.js.map +1 -1
- package/dist/cli/index.js +18 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/install-browser.d.ts +3 -0
- package/dist/cli/install-browser.d.ts.map +1 -0
- package/dist/cli/install-browser.js +42 -0
- package/dist/cli/install-browser.js.map +1 -0
- package/dist/cli/install-browser.test.d.ts +2 -0
- package/dist/cli/install-browser.test.d.ts.map +1 -0
- package/dist/cli/install-browser.test.js +19 -0
- package/dist/cli/install-browser.test.js.map +1 -0
- package/dist/cli/record.js +3 -3
- package/dist/cli/record.js.map +1 -1
- package/dist/cli/run.d.ts.map +1 -1
- package/dist/cli/run.js +32 -27
- package/dist/cli/run.js.map +1 -1
- package/dist/config/lightpanda.d.ts +8 -0
- package/dist/config/lightpanda.d.ts.map +1 -1
- package/dist/config/lightpanda.js +41 -4
- package/dist/config/lightpanda.js.map +1 -1
- package/dist/config/lightpanda.test.js +30 -1
- package/dist/config/lightpanda.test.js.map +1 -1
- package/dist/config/load.d.ts +4 -1
- package/dist/config/load.d.ts.map +1 -1
- package/dist/config/load.js +52 -28
- package/dist/config/load.js.map +1 -1
- package/dist/config/load.test.js +101 -13
- package/dist/config/load.test.js.map +1 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +2 -1
- package/dist/mcp/server.js.map +1 -1
- package/dist/prompt/load.d.ts +2 -2
- package/dist/prompt/load.d.ts.map +1 -1
- package/dist/prompt/load.js +4 -9
- package/dist/prompt/load.js.map +1 -1
- package/dist/redact/env-secrets.d.ts.map +1 -1
- package/dist/redact/env-secrets.js +1 -0
- package/dist/redact/env-secrets.js.map +1 -1
- package/dist/redact/env-secrets.test.js +3 -3
- package/dist/redact/env-secrets.test.js.map +1 -1
- package/dist/reporter/index.d.ts.map +1 -1
- package/dist/reporter/index.js +6 -2
- package/dist/reporter/index.js.map +1 -1
- package/dist/reporter/index.test.js +59 -1
- package/dist/reporter/index.test.js.map +1 -1
- package/dist/scenarios/globs.d.ts +3 -4
- package/dist/scenarios/globs.d.ts.map +1 -1
- package/dist/scenarios/globs.js +5 -27
- package/dist/scenarios/globs.js.map +1 -1
- package/dist/scenarios/globs.test.js +11 -29
- package/dist/scenarios/globs.test.js.map +1 -1
- package/dist/skills/loader.d.ts +8 -1
- package/dist/skills/loader.d.ts.map +1 -1
- package/dist/skills/loader.js +31 -5
- package/dist/skills/loader.js.map +1 -1
- package/dist/skills/loader.test.d.ts +2 -0
- package/dist/skills/loader.test.d.ts.map +1 -0
- package/dist/skills/loader.test.js +40 -0
- package/dist/skills/loader.test.js.map +1 -0
- package/dist/skills/on-demand.d.ts +57 -0
- package/dist/skills/on-demand.d.ts.map +1 -0
- package/dist/skills/on-demand.js +225 -0
- package/dist/skills/on-demand.js.map +1 -0
- package/dist/skills/on-demand.test.d.ts +2 -0
- package/dist/skills/on-demand.test.d.ts.map +1 -0
- package/dist/skills/on-demand.test.js +111 -0
- package/dist/skills/on-demand.test.js.map +1 -0
- package/dist/types/config.d.ts +17 -7
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/verdict.d.ts +21 -1
- package/dist/types/verdict.d.ts.map +1 -1
- package/dist/types/verdict.js +16 -0
- package/dist/types/verdict.js.map +1 -1
- package/dist/version.d.ts +3 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +6 -0
- package/dist/version.js.map +1 -0
- package/package.json +9 -7
- package/pqa.config.ts +8 -13
- package/prompt/SYSTEM.md +2 -1
- package/scripts/install-lightpanda.mjs +161 -0
- package/scripts/sync-skills.mjs +110 -0
- package/skills/agent-browser/SKILL.md +0 -1960
- package/skills/agent-browser/bundled/agentcore/SKILL.md +115 -0
- package/skills/agent-browser/bundled/dogfood/SKILL.md +220 -0
- package/skills/agent-browser/bundled/dogfood/references/issue-taxonomy.md +109 -0
- package/skills/agent-browser/bundled/dogfood/templates/dogfood-report-template.md +53 -0
- package/skills/agent-browser/bundled/electron/SKILL.md +236 -0
- package/skills/agent-browser/bundled/slack/SKILL.md +285 -0
- package/skills/agent-browser/bundled/slack/references/slack-tasks.md +348 -0
- package/skills/agent-browser/bundled/slack/templates/slack-report-template.md +163 -0
- package/skills/agent-browser/bundled/vercel-sandbox/SKILL.md +280 -0
- package/skills/agent-browser/manifest.json +42 -0
- package/skills/agent-browser/references/authentication.md +303 -0
- package/skills/agent-browser/references/commands.md +398 -0
- package/skills/agent-browser/references/profiling.md +120 -0
- package/skills/agent-browser/references/proxy-support.md +194 -0
- package/skills/agent-browser/references/session-management.md +193 -0
- package/skills/agent-browser/references/snapshot-refs.md +219 -0
- package/skills/agent-browser/references/trust-boundaries.md +89 -0
- package/skills/agent-browser/references/video-recording.md +175 -0
- package/skills/agent-browser/templates/authenticated-session.sh +105 -0
- package/skills/agent-browser/templates/capture-workflow.sh +69 -0
- package/skills/agent-browser/templates/form-automation.sh +62 -0
package/pqa.config.ts
CHANGED
|
@@ -6,15 +6,6 @@
|
|
|
6
6
|
const config = {
|
|
7
7
|
scenariosDir: "scenarios",
|
|
8
8
|
llm: {
|
|
9
|
-
provider:
|
|
10
|
-
(process.env.PQA_LLM_PROVIDER as
|
|
11
|
-
| "anthropic"
|
|
12
|
-
| "openai"
|
|
13
|
-
| "fireworks"
|
|
14
|
-
| "ollama"
|
|
15
|
-
| "google"
|
|
16
|
-
| "openrouter") ?? "anthropic",
|
|
17
|
-
model: process.env.PQA_LLM_MODEL ?? "claude-sonnet-4-20250514",
|
|
18
9
|
thinking: {
|
|
19
10
|
enabled: true,
|
|
20
11
|
budgetTokens: 10_000,
|
|
@@ -26,16 +17,20 @@ const config = {
|
|
|
26
17
|
defaultTimeout: 25_000,
|
|
27
18
|
engine: "chrome",
|
|
28
19
|
lightpanda: {
|
|
29
|
-
executablePath: "
|
|
20
|
+
executablePath: "./.pqa/engine",
|
|
30
21
|
telemetry: false,
|
|
31
22
|
},
|
|
32
23
|
},
|
|
33
|
-
systemPromptPath: "prompt/SYSTEM.md",
|
|
34
24
|
envVars: [],
|
|
35
25
|
sensitiveEnvVars: [],
|
|
36
26
|
skills: {
|
|
37
|
-
dirs: ["skills"],
|
|
38
|
-
preloads: [
|
|
27
|
+
dirs: [".pqa/skills"],
|
|
28
|
+
preloads: [],
|
|
29
|
+
onDemand: {
|
|
30
|
+
enabled: true,
|
|
31
|
+
autoLoad: true,
|
|
32
|
+
maxChars: 50_000,
|
|
33
|
+
},
|
|
39
34
|
},
|
|
40
35
|
agent: {
|
|
41
36
|
parallel: 0,
|
package/prompt/SYSTEM.md
CHANGED
|
@@ -5,7 +5,8 @@ You are ProseQA, an E2E regression testing agent. Execute scenarios using
|
|
|
5
5
|
|
|
6
6
|
## Rules
|
|
7
7
|
|
|
8
|
-
- Use `agent-browser` CLI for all browser interactions (see the core skill below).
|
|
8
|
+
- Use `agent-browser` CLI for all browser interactions (see the minimal core skill below).
|
|
9
|
+
- Use the `load_skill` tool for detailed references and custom project skills — do **not** run `agent-browser skills get` in bash.
|
|
9
10
|
- Do NOT use curl, wget, or other HTTP clients to test the web UI.
|
|
10
11
|
- After completing Steps, verify every Then checkpoint using agent-browser CLI.
|
|
11
12
|
- On failure, save screenshot and snapshot to `$PQA_ARTIFACT_DIR`.
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Download the Lightpanda browser binary for the current OS/arch.
|
|
3
|
+
* @see https://lightpanda.io/docs/open-source/installation
|
|
4
|
+
* @see https://github.com/lightpanda-io/browser/releases/tag/nightly
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { execSync } from "node:child_process";
|
|
8
|
+
import { createHash } from "node:crypto";
|
|
9
|
+
import { chmod, mkdir, rename, unlink } from "node:fs/promises";
|
|
10
|
+
import { createWriteStream } from "node:fs";
|
|
11
|
+
import { pipeline } from "node:stream/promises";
|
|
12
|
+
import os from "node:os";
|
|
13
|
+
import path from "node:path";
|
|
14
|
+
import { fileURLToPath } from "node:url";
|
|
15
|
+
|
|
16
|
+
const REPO = "lightpanda-io/browser";
|
|
17
|
+
const VERSION = process.env.LIGHTPANDA_VERSION ?? "nightly";
|
|
18
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
19
|
+
const projectRoot = path.join(__dirname, "..");
|
|
20
|
+
const installDir = process.env.LIGHTPANDA_DIR ?? path.join(projectRoot, ".bin");
|
|
21
|
+
const binaryName = process.platform === "win32" ? "lightpanda.exe" : "lightpanda";
|
|
22
|
+
const binaryPath = path.join(installDir, binaryName);
|
|
23
|
+
|
|
24
|
+
function isMuslLinux() {
|
|
25
|
+
if (process.platform !== "linux") return false;
|
|
26
|
+
try {
|
|
27
|
+
const out = execSync("ldd --version 2>&1 || true", { encoding: "utf8" });
|
|
28
|
+
return out.toLowerCase().includes("musl");
|
|
29
|
+
} catch {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** @returns {string} GitHub release asset basename (e.g. lightpanda-aarch64-macos) */
|
|
35
|
+
function resolveAssetName() {
|
|
36
|
+
const { platform, arch } = process;
|
|
37
|
+
|
|
38
|
+
if (platform === "win32") {
|
|
39
|
+
console.error(
|
|
40
|
+
"Lightpanda has no native Windows binary. Install inside WSL2 (Linux steps), then point AGENT_BROWSER_EXECUTABLE_PATH at the WSL binary.\n" +
|
|
41
|
+
"https://lightpanda.io/docs/open-source/installation#windows--wsl2",
|
|
42
|
+
);
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (platform === "linux" && isMuslLinux()) {
|
|
47
|
+
console.error(
|
|
48
|
+
"Alpine/musl Linux is not supported by the prebuilt Lightpanda binaries (glibc required).\n" +
|
|
49
|
+
"Use a glibc-based image (Debian/Ubuntu) or build from source: https://github.com/lightpanda-io/browser#build-from-sources",
|
|
50
|
+
);
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
let osSuffix;
|
|
55
|
+
if (platform === "linux") osSuffix = "linux";
|
|
56
|
+
else if (platform === "darwin") osSuffix = "macos";
|
|
57
|
+
else {
|
|
58
|
+
console.error(`Unsupported platform: ${platform}`);
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
let archSuffix;
|
|
63
|
+
switch (arch) {
|
|
64
|
+
case "x64":
|
|
65
|
+
archSuffix = "x86_64";
|
|
66
|
+
break;
|
|
67
|
+
case "arm64":
|
|
68
|
+
archSuffix = "aarch64";
|
|
69
|
+
break;
|
|
70
|
+
default:
|
|
71
|
+
console.error(`Unsupported CPU architecture: ${arch}`);
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return `lightpanda-${archSuffix}-${osSuffix}`;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async function fetchJson(url) {
|
|
79
|
+
const res = await fetch(url, {
|
|
80
|
+
headers: { Accept: "application/vnd.github+json", "User-Agent": "prose-qa-install-lightpanda" },
|
|
81
|
+
});
|
|
82
|
+
if (!res.ok) {
|
|
83
|
+
throw new Error(`GitHub API ${res.status} for ${url}`);
|
|
84
|
+
}
|
|
85
|
+
return res.json();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async function sha256File(filePath) {
|
|
89
|
+
const { createReadStream } = await import("node:fs");
|
|
90
|
+
const hash = createHash("sha256");
|
|
91
|
+
await new Promise((resolve, reject) => {
|
|
92
|
+
createReadStream(filePath)
|
|
93
|
+
.on("data", (chunk) => hash.update(chunk))
|
|
94
|
+
.on("end", resolve)
|
|
95
|
+
.on("error", reject);
|
|
96
|
+
});
|
|
97
|
+
return hash.digest("hex");
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
async function downloadToFile(url, dest) {
|
|
101
|
+
const res = await fetch(url);
|
|
102
|
+
if (!res.ok) {
|
|
103
|
+
throw new Error(`Download failed (${res.status}): ${url}`);
|
|
104
|
+
}
|
|
105
|
+
if (!res.body) {
|
|
106
|
+
throw new Error(`Empty response body: ${url}`);
|
|
107
|
+
}
|
|
108
|
+
await pipeline(res.body, createWriteStream(dest));
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
async function main() {
|
|
112
|
+
const assetName = resolveAssetName();
|
|
113
|
+
const downloadUrl = `https://github.com/${REPO}/releases/download/${VERSION}/${assetName}`;
|
|
114
|
+
|
|
115
|
+
console.log("=== Lightpanda install ===");
|
|
116
|
+
console.log(`Version: ${VERSION}`);
|
|
117
|
+
console.log(`Detected: ${process.platform} ${process.arch} → ${assetName}`);
|
|
118
|
+
console.log(`Install dir: ${installDir}`);
|
|
119
|
+
|
|
120
|
+
const release = await fetchJson(`https://api.github.com/repos/${REPO}/releases/tags/${VERSION}`);
|
|
121
|
+
const asset = release.assets?.find((a) => a.name === assetName);
|
|
122
|
+
if (!asset?.digest) {
|
|
123
|
+
throw new Error(`No checksum for asset "${assetName}" on release tag "${VERSION}"`);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const expectedSha256 = asset.digest.replace(/^sha256:/, "");
|
|
127
|
+
await mkdir(installDir, { recursive: true });
|
|
128
|
+
|
|
129
|
+
const tmpPath = `${binaryPath}.download`;
|
|
130
|
+
try {
|
|
131
|
+
console.log(`Downloading ${downloadUrl} ...`);
|
|
132
|
+
await downloadToFile(downloadUrl, tmpPath);
|
|
133
|
+
|
|
134
|
+
const actualSha256 = await sha256File(tmpPath);
|
|
135
|
+
if (actualSha256 !== expectedSha256) {
|
|
136
|
+
throw new Error(
|
|
137
|
+
`Checksum mismatch for ${assetName}\n expected: ${expectedSha256}\n actual: ${actualSha256}`,
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
await rename(tmpPath, binaryPath);
|
|
142
|
+
await chmod(binaryPath, 0o755);
|
|
143
|
+
|
|
144
|
+
console.log("Checksum OK.");
|
|
145
|
+
console.log(`Installed: ${binaryPath}`);
|
|
146
|
+
console.log("");
|
|
147
|
+
console.log("Add to PATH (shell profile) or set for Prose-QA / agent-browser:");
|
|
148
|
+
console.log(` export PATH="${installDir}:$PATH"`);
|
|
149
|
+
console.log(` export AGENT_BROWSER_EXECUTABLE_PATH="${binaryPath}"`);
|
|
150
|
+
console.log("");
|
|
151
|
+
console.log("Start CDP server: lightpanda serve --host 127.0.0.1 --port 9222");
|
|
152
|
+
} catch (err) {
|
|
153
|
+
await unlink(tmpPath).catch(() => {});
|
|
154
|
+
throw err;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
main().catch((err) => {
|
|
159
|
+
console.error(err instanceof Error ? err.message : err);
|
|
160
|
+
process.exit(1);
|
|
161
|
+
});
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Vendor agent-browser skills into skills/agent-browser/.
|
|
4
|
+
* - Minimal core SKILL.md (not --full inline dump)
|
|
5
|
+
* - references/ and templates/ for on-demand loading
|
|
6
|
+
* - bundled/ for optional specialized skills (dogfood, electron, …)
|
|
7
|
+
*/
|
|
8
|
+
import { cpSync, existsSync, mkdirSync, readdirSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
9
|
+
import { createRequire } from "node:module";
|
|
10
|
+
import path from "node:path";
|
|
11
|
+
import { fileURLToPath } from "node:url";
|
|
12
|
+
|
|
13
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
14
|
+
const repoRoot = path.resolve(__dirname, "..");
|
|
15
|
+
|
|
16
|
+
function resolveSkillDataRoot() {
|
|
17
|
+
const require = createRequire(path.join(repoRoot, "package.json"));
|
|
18
|
+
const pkgJson = require.resolve("agent-browser/package.json");
|
|
19
|
+
return path.join(path.dirname(pkgJson), "skill-data");
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function copyDir(src, dest) {
|
|
23
|
+
if (!existsSync(src)) return;
|
|
24
|
+
mkdirSync(path.dirname(dest), { recursive: true });
|
|
25
|
+
cpSync(src, dest, { recursive: true });
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function listFiles(dir, ext) {
|
|
29
|
+
if (!existsSync(dir)) return [];
|
|
30
|
+
return readdirSync(dir)
|
|
31
|
+
.filter((name) => name.endsWith(ext))
|
|
32
|
+
.map((name) => name.slice(0, -ext.length))
|
|
33
|
+
.sort();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function readSkillDescription(skillDir) {
|
|
37
|
+
const skillPath = path.join(skillDir, "SKILL.md");
|
|
38
|
+
if (!existsSync(skillPath)) return "";
|
|
39
|
+
const raw = readFileSync(skillPath, "utf8");
|
|
40
|
+
const match = /^---\r?\n([\s\S]*?)\r?\n---/.exec(raw);
|
|
41
|
+
if (!match) return "";
|
|
42
|
+
for (const line of match[1].split("\n")) {
|
|
43
|
+
const desc = /^description:\s*(.+)$/.exec(line.trim());
|
|
44
|
+
if (desc) return desc[1].trim();
|
|
45
|
+
}
|
|
46
|
+
return "";
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function syncSkills() {
|
|
50
|
+
const skillDataRoot = resolveSkillDataRoot();
|
|
51
|
+
if (!existsSync(skillDataRoot)) {
|
|
52
|
+
console.error("agent-browser skill-data not found. Run: npm install");
|
|
53
|
+
process.exit(1);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const outDir = path.join(repoRoot, "skills", "agent-browser");
|
|
57
|
+
const coreSrc = path.join(skillDataRoot, "core");
|
|
58
|
+
|
|
59
|
+
if (!existsSync(path.join(coreSrc, "SKILL.md"))) {
|
|
60
|
+
console.error("core/SKILL.md missing in agent-browser skill-data");
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
rmSync(outDir, { recursive: true, force: true });
|
|
65
|
+
mkdirSync(outDir, { recursive: true });
|
|
66
|
+
|
|
67
|
+
cpSync(path.join(coreSrc, "SKILL.md"), path.join(outDir, "SKILL.md"));
|
|
68
|
+
copyDir(path.join(coreSrc, "references"), path.join(outDir, "references"));
|
|
69
|
+
copyDir(path.join(coreSrc, "templates"), path.join(outDir, "templates"));
|
|
70
|
+
|
|
71
|
+
const bundledDir = path.join(outDir, "bundled");
|
|
72
|
+
mkdirSync(bundledDir, { recursive: true });
|
|
73
|
+
|
|
74
|
+
const bundled = [];
|
|
75
|
+
for (const name of readdirSync(skillDataRoot)) {
|
|
76
|
+
if (name === "core") continue;
|
|
77
|
+
const src = path.join(skillDataRoot, name);
|
|
78
|
+
if (!statSync(src).isDirectory()) continue;
|
|
79
|
+
const dest = path.join(bundledDir, name);
|
|
80
|
+
copyDir(src, dest);
|
|
81
|
+
bundled.push({
|
|
82
|
+
name,
|
|
83
|
+
description: readSkillDescription(src),
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
bundled.sort((a, b) => a.name.localeCompare(b.name));
|
|
87
|
+
|
|
88
|
+
const manifest = {
|
|
89
|
+
version: 1,
|
|
90
|
+
core: {
|
|
91
|
+
references: listFiles(path.join(outDir, "references"), ".md"),
|
|
92
|
+
templates: listFiles(path.join(outDir, "templates"), ".sh"),
|
|
93
|
+
},
|
|
94
|
+
bundled,
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
writeFileSync(
|
|
98
|
+
path.join(outDir, "manifest.json"),
|
|
99
|
+
`${JSON.stringify(manifest, null, 2)}\n`,
|
|
100
|
+
"utf8",
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
const coreLines = readFileSync(path.join(outDir, "SKILL.md"), "utf8").split("\n").length;
|
|
104
|
+
console.log(
|
|
105
|
+
`Synced agent-browser skills → skills/agent-browser/ (core: ${coreLines} lines, ` +
|
|
106
|
+
`${manifest.core.references.length} references, ${bundled.length} bundled skills)`,
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
syncSkills();
|