vskill 0.5.126 → 0.5.128
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/agents.json +1 -1
- package/dist/bin.js +0 -0
- package/dist/eval-server/api-routes.js +129 -12
- package/dist/eval-server/api-routes.js.map +1 -1
- package/dist/eval-server/install-engine-routes.js +1 -1
- package/dist/eval-server/install-engine-routes.js.map +1 -1
- package/dist/eval-server/utils/scan-install-locations.d.ts +18 -0
- package/dist/eval-server/utils/scan-install-locations.js +136 -0
- package/dist/eval-server/utils/scan-install-locations.js.map +1 -0
- package/dist/eval-ui/assets/{CommandPalette-CBrGufxz.js → CommandPalette-D_MdwCki.js} +1 -1
- package/dist/eval-ui/assets/{CreateSkillPage-DXrpM1On.js → CreateSkillPage-lLACfsOZ.js} +3 -3
- package/dist/eval-ui/assets/{FindSkillsPalette-D99SoJx3.js → FindSkillsPalette-VTksFrSO.js} +2 -2
- package/dist/eval-ui/assets/SearchPaletteCore-D49bVafl.js +14 -0
- package/dist/eval-ui/assets/{SkillDetailPanel-DzmlOsAc.js → SkillDetailPanel-Cg8lyDAl.js} +1 -1
- package/dist/eval-ui/assets/UpdateDropdown-CLt94M3u.js +1 -0
- package/dist/eval-ui/assets/{index-BAN03ugM.css → index-C8DXCPPg.css} +1 -1
- package/dist/eval-ui/assets/index-fbCfi37A.js +102 -0
- package/dist/eval-ui/assets/{skill-url-lxDpBkBU.js → skill-url-DXjZASn-.js} +1 -1
- package/dist/eval-ui/index.html +2 -2
- package/dist/index.js +0 -0
- package/package.json +1 -1
- package/dist/agents/agents-registry.test.d.ts +0 -1
- package/dist/agents/agents-registry.test.js +0 -248
- package/dist/agents/agents-registry.test.js.map +0 -1
- package/dist/api/client.test.d.ts +0 -1
- package/dist/api/client.test.js +0 -428
- package/dist/api/client.test.js.map +0 -1
- package/dist/audit/audit-integration.test.d.ts +0 -1
- package/dist/audit/audit-integration.test.js +0 -92
- package/dist/audit/audit-integration.test.js.map +0 -1
- package/dist/audit/audit-llm.test.d.ts +0 -1
- package/dist/audit/audit-llm.test.js +0 -110
- package/dist/audit/audit-llm.test.js.map +0 -1
- package/dist/audit/audit-patterns.test.d.ts +0 -1
- package/dist/audit/audit-patterns.test.js +0 -91
- package/dist/audit/audit-patterns.test.js.map +0 -1
- package/dist/audit/audit-scanner.test.d.ts +0 -1
- package/dist/audit/audit-scanner.test.js +0 -112
- package/dist/audit/audit-scanner.test.js.map +0 -1
- package/dist/audit/audit-types.test.d.ts +0 -1
- package/dist/audit/audit-types.test.js +0 -140
- package/dist/audit/audit-types.test.js.map +0 -1
- package/dist/audit/config.test.d.ts +0 -1
- package/dist/audit/config.test.js +0 -44
- package/dist/audit/config.test.js.map +0 -1
- package/dist/audit/file-discovery.test.d.ts +0 -1
- package/dist/audit/file-discovery.test.js +0 -120
- package/dist/audit/file-discovery.test.js.map +0 -1
- package/dist/audit/fix-suggestions.test.d.ts +0 -1
- package/dist/audit/fix-suggestions.test.js +0 -35
- package/dist/audit/fix-suggestions.test.js.map +0 -1
- package/dist/audit/formatters/json-formatter.test.d.ts +0 -1
- package/dist/audit/formatters/json-formatter.test.js +0 -49
- package/dist/audit/formatters/json-formatter.test.js.map +0 -1
- package/dist/audit/formatters/report-formatter.test.d.ts +0 -1
- package/dist/audit/formatters/report-formatter.test.js +0 -51
- package/dist/audit/formatters/report-formatter.test.js.map +0 -1
- package/dist/audit/formatters/sarif-formatter.test.d.ts +0 -1
- package/dist/audit/formatters/sarif-formatter.test.js +0 -71
- package/dist/audit/formatters/sarif-formatter.test.js.map +0 -1
- package/dist/audit/formatters/terminal-formatter.test.d.ts +0 -1
- package/dist/audit/formatters/terminal-formatter.test.js +0 -51
- package/dist/audit/formatters/terminal-formatter.test.js.map +0 -1
- package/dist/blocklist/blocklist-e2e.test.d.ts +0 -1
- package/dist/blocklist/blocklist-e2e.test.js +0 -346
- package/dist/blocklist/blocklist-e2e.test.js.map +0 -1
- package/dist/blocklist/blocklist.test.d.ts +0 -1
- package/dist/blocklist/blocklist.test.js +0 -259
- package/dist/blocklist/blocklist.test.js.map +0 -1
- package/dist/commands/__tests__/eval-router.test.d.ts +0 -1
- package/dist/commands/__tests__/eval-router.test.js +0 -60
- package/dist/commands/__tests__/eval-router.test.js.map +0 -1
- package/dist/commands/__tests__/eval-serve.test.d.ts +0 -1
- package/dist/commands/__tests__/eval-serve.test.js +0 -23
- package/dist/commands/__tests__/eval-serve.test.js.map +0 -1
- package/dist/commands/add-blocklist-e2e.test.d.ts +0 -1
- package/dist/commands/add-blocklist-e2e.test.js +0 -397
- package/dist/commands/add-blocklist-e2e.test.js.map +0 -1
- package/dist/commands/add-wizard.test.d.ts +0 -1
- package/dist/commands/add-wizard.test.js +0 -392
- package/dist/commands/add-wizard.test.js.map +0 -1
- package/dist/commands/add.test.d.ts +0 -1
- package/dist/commands/add.test.js +0 -2365
- package/dist/commands/add.test.js.map +0 -1
- package/dist/commands/audit.test.d.ts +0 -1
- package/dist/commands/audit.test.js +0 -79
- package/dist/commands/audit.test.js.map +0 -1
- package/dist/commands/blocklist.test.d.ts +0 -1
- package/dist/commands/blocklist.test.js +0 -158
- package/dist/commands/blocklist.test.js.map +0 -1
- package/dist/commands/eval/__tests__/coverage.test.d.ts +0 -1
- package/dist/commands/eval/__tests__/coverage.test.js +0 -122
- package/dist/commands/eval/__tests__/coverage.test.js.map +0 -1
- package/dist/commands/eval/__tests__/generate-all.test.d.ts +0 -1
- package/dist/commands/eval/__tests__/generate-all.test.js +0 -133
- package/dist/commands/eval/__tests__/generate-all.test.js.map +0 -1
- package/dist/commands/eval/__tests__/init.test.d.ts +0 -1
- package/dist/commands/eval/__tests__/init.test.js +0 -116
- package/dist/commands/eval/__tests__/init.test.js.map +0 -1
- package/dist/commands/eval/__tests__/run.test.d.ts +0 -1
- package/dist/commands/eval/__tests__/run.test.js +0 -186
- package/dist/commands/eval/__tests__/run.test.js.map +0 -1
- package/dist/commands/find.test.d.ts +0 -1
- package/dist/commands/find.test.js +0 -481
- package/dist/commands/find.test.js.map +0 -1
- package/dist/commands/marketplace.test.d.ts +0 -1
- package/dist/commands/marketplace.test.js +0 -129
- package/dist/commands/marketplace.test.js.map +0 -1
- package/dist/commands/remove.test.d.ts +0 -1
- package/dist/commands/remove.test.js +0 -164
- package/dist/commands/remove.test.js.map +0 -1
- package/dist/commands/should-skip.test.d.ts +0 -1
- package/dist/commands/should-skip.test.js +0 -56
- package/dist/commands/should-skip.test.js.map +0 -1
- package/dist/commands/submit.test.d.ts +0 -1
- package/dist/commands/submit.test.js +0 -83
- package/dist/commands/submit.test.js.map +0 -1
- package/dist/commands/update.test.d.ts +0 -1
- package/dist/commands/update.test.js +0 -250
- package/dist/commands/update.test.js.map +0 -1
- package/dist/discovery/github-tree.test.d.ts +0 -1
- package/dist/discovery/github-tree.test.js +0 -372
- package/dist/discovery/github-tree.test.js.map +0 -1
- package/dist/eval/__tests__/activation-tester.test.d.ts +0 -1
- package/dist/eval/__tests__/activation-tester.test.js +0 -203
- package/dist/eval/__tests__/activation-tester.test.js.map +0 -1
- package/dist/eval/__tests__/benchmark-history.test.d.ts +0 -1
- package/dist/eval/__tests__/benchmark-history.test.js +0 -422
- package/dist/eval/__tests__/benchmark-history.test.js.map +0 -1
- package/dist/eval/__tests__/benchmark.test.d.ts +0 -1
- package/dist/eval/__tests__/benchmark.test.js +0 -94
- package/dist/eval/__tests__/benchmark.test.js.map +0 -1
- package/dist/eval/__tests__/comparator.test.d.ts +0 -1
- package/dist/eval/__tests__/comparator.test.js +0 -282
- package/dist/eval/__tests__/comparator.test.js.map +0 -1
- package/dist/eval/__tests__/judge.test.d.ts +0 -1
- package/dist/eval/__tests__/judge.test.js +0 -122
- package/dist/eval/__tests__/judge.test.js.map +0 -1
- package/dist/eval/__tests__/llm.test.d.ts +0 -1
- package/dist/eval/__tests__/llm.test.js +0 -543
- package/dist/eval/__tests__/llm.test.js.map +0 -1
- package/dist/eval/__tests__/mcp-detector.test.d.ts +0 -1
- package/dist/eval/__tests__/mcp-detector.test.js +0 -180
- package/dist/eval/__tests__/mcp-detector.test.js.map +0 -1
- package/dist/eval/__tests__/prompt-builder.test.d.ts +0 -1
- package/dist/eval/__tests__/prompt-builder.test.js +0 -142
- package/dist/eval/__tests__/prompt-builder.test.js.map +0 -1
- package/dist/eval/__tests__/schema.test.d.ts +0 -1
- package/dist/eval/__tests__/schema.test.js +0 -247
- package/dist/eval/__tests__/schema.test.js.map +0 -1
- package/dist/eval/__tests__/skill-scanner.test.d.ts +0 -1
- package/dist/eval/__tests__/skill-scanner.test.js +0 -228
- package/dist/eval/__tests__/skill-scanner.test.js.map +0 -1
- package/dist/eval/__tests__/verdict.test.d.ts +0 -1
- package/dist/eval/__tests__/verdict.test.js +0 -47
- package/dist/eval/__tests__/verdict.test.js.map +0 -1
- package/dist/eval-server/__tests__/benchmark-runner.test.d.ts +0 -1
- package/dist/eval-server/__tests__/benchmark-runner.test.js +0 -301
- package/dist/eval-server/__tests__/benchmark-runner.test.js.map +0 -1
- package/dist/eval-server/__tests__/comparison-sse-events.test.d.ts +0 -1
- package/dist/eval-server/__tests__/comparison-sse-events.test.js +0 -278
- package/dist/eval-server/__tests__/comparison-sse-events.test.js.map +0 -1
- package/dist/eval-server/__tests__/sse-helpers.test.d.ts +0 -1
- package/dist/eval-server/__tests__/sse-helpers.test.js +0 -128
- package/dist/eval-server/__tests__/sse-helpers.test.js.map +0 -1
- package/dist/eval-ui/assets/SearchPaletteCore-CnRYmTuv.js +0 -6
- package/dist/eval-ui/assets/UpdateDropdown-BsAm4uMW.js +0 -1
- package/dist/eval-ui/assets/index-BGQolxHD.js +0 -102
- package/dist/installer/canonical.test.d.ts +0 -1
- package/dist/installer/canonical.test.js +0 -264
- package/dist/installer/canonical.test.js.map +0 -1
- package/dist/lockfile/lockfile.test.d.ts +0 -1
- package/dist/lockfile/lockfile.test.js +0 -204
- package/dist/lockfile/lockfile.test.js.map +0 -1
- package/dist/lockfile/project-root.test.d.ts +0 -1
- package/dist/lockfile/project-root.test.js +0 -49
- package/dist/lockfile/project-root.test.js.map +0 -1
- package/dist/marketplace/marketplace.test.d.ts +0 -1
- package/dist/marketplace/marketplace.test.js +0 -312
- package/dist/marketplace/marketplace.test.js.map +0 -1
- package/dist/resolvers/source-resolver.test.d.ts +0 -1
- package/dist/resolvers/source-resolver.test.js +0 -104
- package/dist/resolvers/source-resolver.test.js.map +0 -1
- package/dist/resolvers/url-resolver.test.d.ts +0 -1
- package/dist/resolvers/url-resolver.test.js +0 -49
- package/dist/resolvers/url-resolver.test.js.map +0 -1
- package/dist/scanner/dci-integration.test.d.ts +0 -1
- package/dist/scanner/dci-integration.test.js +0 -83
- package/dist/scanner/dci-integration.test.js.map +0 -1
- package/dist/scanner/patterns.test.d.ts +0 -1
- package/dist/scanner/patterns.test.js +0 -832
- package/dist/scanner/patterns.test.js.map +0 -1
- package/dist/scanner/tier1.test.d.ts +0 -1
- package/dist/scanner/tier1.test.js +0 -305
- package/dist/scanner/tier1.test.js.map +0 -1
- package/dist/security/platform-security.test.d.ts +0 -1
- package/dist/security/platform-security.test.js +0 -92
- package/dist/security/platform-security.test.js.map +0 -1
- package/dist/settings/settings.test.d.ts +0 -1
- package/dist/settings/settings.test.js +0 -103
- package/dist/settings/settings.test.js.map +0 -1
- package/dist/updater/source-fetcher.test.d.ts +0 -1
- package/dist/updater/source-fetcher.test.js +0 -192
- package/dist/updater/source-fetcher.test.js.map +0 -1
- package/dist/utils/__tests__/paths.test.d.ts +0 -1
- package/dist/utils/__tests__/paths.test.js +0 -22
- package/dist/utils/__tests__/paths.test.js.map +0 -1
- package/dist/utils/__tests__/resolve-binary.integration.test.d.ts +0 -1
- package/dist/utils/__tests__/resolve-binary.integration.test.js +0 -138
- package/dist/utils/__tests__/resolve-binary.integration.test.js.map +0 -1
- package/dist/utils/__tests__/resolve-binary.test.d.ts +0 -1
- package/dist/utils/__tests__/resolve-binary.test.js +0 -175
- package/dist/utils/__tests__/resolve-binary.test.js.map +0 -1
- package/dist/utils/__tests__/validation.test.d.ts +0 -1
- package/dist/utils/__tests__/validation.test.js +0 -107
- package/dist/utils/__tests__/validation.test.js.map +0 -1
- package/dist/utils/agent-filter.test.d.ts +0 -1
- package/dist/utils/agent-filter.test.js +0 -75
- package/dist/utils/agent-filter.test.js.map +0 -1
- package/dist/utils/output.test.d.ts +0 -1
- package/dist/utils/output.test.js +0 -28
- package/dist/utils/output.test.js.map +0 -1
- package/dist/utils/project-root.test.d.ts +0 -1
- package/dist/utils/project-root.test.js +0 -74
- package/dist/utils/project-root.test.js.map +0 -1
- package/dist/utils/prompts.test.d.ts +0 -1
- package/dist/utils/prompts.test.js +0 -285
- package/dist/utils/prompts.test.js.map +0 -1
package/agents.json
CHANGED
package/dist/bin.js
CHANGED
|
File without changes
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// api-routes.ts -- REST API route handlers for the eval UI
|
|
3
3
|
// ---------------------------------------------------------------------------
|
|
4
4
|
import { readFileSync, writeFileSync, mkdirSync, existsSync, readdirSync, statSync } from "node:fs";
|
|
5
|
-
import { execSync } from "node:child_process";
|
|
5
|
+
import { execSync, execFileSync } from "node:child_process";
|
|
6
6
|
import { join, resolve, dirname, basename } from "node:path";
|
|
7
7
|
import { homedir } from "node:os";
|
|
8
8
|
import { sendJson, readBody } from "./router.js";
|
|
@@ -1510,20 +1510,54 @@ export function registerRoutes(router, root, projectName) {
|
|
|
1510
1510
|
// directly instead of shelling out to whatever `vskill` is on PATH (which
|
|
1511
1511
|
// may be a different version than the studio is bundling). This guarantees
|
|
1512
1512
|
// the disk-version reconcile from outdated.ts is applied uniformly.
|
|
1513
|
+
//
|
|
1514
|
+
// 0747 T-002: enrich each row with `installLocations[]`, `localPlugin`,
|
|
1515
|
+
// `localSkill` so the Studio's bell dropdown can render tooltips and route
|
|
1516
|
+
// smart clicks via `revealSkill` instead of guessing local fs identifiers
|
|
1517
|
+
// from the canonical platform name.
|
|
1513
1518
|
router.get("/api/skills/updates", async (req, res) => {
|
|
1514
1519
|
try {
|
|
1515
1520
|
const { getOutdatedJson } = await import("../commands/outdated.js");
|
|
1521
|
+
const { scanSkillInstallLocations } = await import("./utils/scan-install-locations.js");
|
|
1516
1522
|
const programmatic = await getOutdatedJson();
|
|
1517
1523
|
if (!programmatic) {
|
|
1518
1524
|
sendJson(res, [], 200, req);
|
|
1519
1525
|
return;
|
|
1520
1526
|
}
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
+
// 0747 AC-US4-06 + code-review F-004: per-request memoization keyed by
|
|
1528
|
+
// canonical skill name. Each unique name is scanned exactly once even
|
|
1529
|
+
// if it appears in multiple rows, so the syscall cost is O(unique
|
|
1530
|
+
// names × agents × scopes), not O(rows × agents × scopes). For a
|
|
1531
|
+
// typical /updates response every row has a distinct name, so this
|
|
1532
|
+
// matches the previous one-call-per-row behavior on the happy path
|
|
1533
|
+
// while giving a correct lower bound when names ever duplicate.
|
|
1534
|
+
const scanCache = new Map();
|
|
1535
|
+
const scanOnce = (name) => {
|
|
1536
|
+
const hit = scanCache.get(name);
|
|
1537
|
+
if (hit !== undefined)
|
|
1538
|
+
return hit;
|
|
1539
|
+
const fresh = scanSkillInstallLocations(name, root);
|
|
1540
|
+
scanCache.set(name, fresh);
|
|
1541
|
+
return fresh;
|
|
1542
|
+
};
|
|
1543
|
+
const enriched = programmatic.results.map((r) => {
|
|
1544
|
+
const locations = scanOnce(r.name);
|
|
1545
|
+
const localSkill = r.name.split("/").pop();
|
|
1546
|
+
// Highest-precedence install wins for the local fs pair the click
|
|
1547
|
+
// handler reveals: project > personal > plugin.
|
|
1548
|
+
const precedence = { project: 0, personal: 1, plugin: 2 };
|
|
1549
|
+
const winner = [...locations].sort((a, b) => precedence[a.scope] -
|
|
1550
|
+
precedence[b.scope])[0];
|
|
1551
|
+
return {
|
|
1552
|
+
...r,
|
|
1553
|
+
...(programmatic.pinMap.has(r.name)
|
|
1554
|
+
? { pinned: true, pinnedVersion: programmatic.pinMap.get(r.name) }
|
|
1555
|
+
: {}),
|
|
1556
|
+
installLocations: locations,
|
|
1557
|
+
localSkill,
|
|
1558
|
+
...(winner?.pluginSlug ? { localPlugin: winner.pluginSlug } : {}),
|
|
1559
|
+
};
|
|
1560
|
+
});
|
|
1527
1561
|
sendJson(res, enriched, 200, req);
|
|
1528
1562
|
}
|
|
1529
1563
|
catch {
|
|
@@ -1637,18 +1671,88 @@ export function registerRoutes(router, root, projectName) {
|
|
|
1637
1671
|
}
|
|
1638
1672
|
});
|
|
1639
1673
|
// T-011: Single-skill update SSE endpoint
|
|
1674
|
+
//
|
|
1675
|
+
// 0747 T-003: optional `?agent=<id>` query param scopes the update to a
|
|
1676
|
+
// single agent's install. The id MUST be in AGENTS_REGISTRY (allowlist) —
|
|
1677
|
+
// it is interpolated into the execSync command, so any non-allowlisted
|
|
1678
|
+
// value is rejected before reaching the shell. Without `?agent`, behavior
|
|
1679
|
+
// is unchanged and `vskill update` does its built-in cross-agent fan-out.
|
|
1680
|
+
// 0747 code-review/grill F-002: validate :skill route params against a
|
|
1681
|
+
// strict slug regex. Without this, a value starting with `--` becomes a
|
|
1682
|
+
// CLI flag instead of a positional arg (e.g. `vskill update --force`
|
|
1683
|
+
// touches every skill including pinned ones). execFileSync prevents
|
|
1684
|
+
// shell injection but Commander still parses argv. Allowed: alphanum,
|
|
1685
|
+
// dot, underscore, hyphen, slash (for canonical owner/repo/skill names).
|
|
1686
|
+
const SKILL_SLUG_RE = /^[a-zA-Z0-9._/-]+$/;
|
|
1687
|
+
const isSafeSkillName = (s) => typeof s === "string" &&
|
|
1688
|
+
s.length > 0 &&
|
|
1689
|
+
s.length <= 200 &&
|
|
1690
|
+
!s.startsWith("-") &&
|
|
1691
|
+
SKILL_SLUG_RE.test(s);
|
|
1640
1692
|
router.post("/api/skills/:plugin/:skill/update", async (req, res, params) => {
|
|
1641
1693
|
initSSE(res, req);
|
|
1642
1694
|
const skillName = params.skill;
|
|
1643
|
-
|
|
1695
|
+
// 0747 grill F-002: reject before doing anything so a malformed slug
|
|
1696
|
+
// can never reach Commander as a flag.
|
|
1697
|
+
if (!isSafeSkillName(skillName)) {
|
|
1698
|
+
sendSSE(res, "error", {
|
|
1699
|
+
error: `Invalid skill name: ${skillName}`,
|
|
1700
|
+
skill: skillName,
|
|
1701
|
+
});
|
|
1702
|
+
sendSSEDone(res, { status: "error", skill: skillName });
|
|
1703
|
+
return;
|
|
1704
|
+
}
|
|
1705
|
+
// Parse optional ?agent=<id>
|
|
1706
|
+
let agentId = null;
|
|
1644
1707
|
try {
|
|
1645
|
-
|
|
1708
|
+
const reqUrl = req.url ?? "";
|
|
1709
|
+
const url = new URL(reqUrl, "http://localhost");
|
|
1710
|
+
const raw = url.searchParams.get("agent");
|
|
1711
|
+
if (raw !== null) {
|
|
1712
|
+
const allowed = AGENTS_REGISTRY.some((a) => a.id === raw);
|
|
1713
|
+
if (!allowed) {
|
|
1714
|
+
sendSSE(res, "error", {
|
|
1715
|
+
error: `Unknown agent id: ${raw}`,
|
|
1716
|
+
skill: skillName,
|
|
1717
|
+
});
|
|
1718
|
+
sendSSEDone(res, { status: "error", skill: skillName });
|
|
1719
|
+
return;
|
|
1720
|
+
}
|
|
1721
|
+
agentId = raw;
|
|
1722
|
+
}
|
|
1723
|
+
}
|
|
1724
|
+
catch {
|
|
1725
|
+
// URL parse error → behave as if ?agent was omitted
|
|
1726
|
+
}
|
|
1727
|
+
sendSSE(res, "progress", {
|
|
1728
|
+
status: "updating",
|
|
1729
|
+
skill: skillName,
|
|
1730
|
+
...(agentId ? { agent: agentId } : {}),
|
|
1731
|
+
});
|
|
1732
|
+
try {
|
|
1733
|
+
// 0747 code-review F-001: use execFileSync with argv array — never
|
|
1734
|
+
// shell-interpolate user-controlled values. skillName comes from a
|
|
1735
|
+
// route param and could otherwise carry shell metacharacters via
|
|
1736
|
+
// decodeURIComponent. agentId is allowlisted above; we still pass it
|
|
1737
|
+
// as a separate arg for defense-in-depth.
|
|
1738
|
+
const args = ["update", skillName];
|
|
1739
|
+
if (agentId)
|
|
1740
|
+
args.push("--agent", agentId);
|
|
1741
|
+
execFileSync("vskill", args, {
|
|
1646
1742
|
timeout: 60_000,
|
|
1647
1743
|
encoding: "utf-8",
|
|
1648
1744
|
stdio: ["ignore", "pipe", "pipe"],
|
|
1649
1745
|
});
|
|
1650
|
-
sendSSE(res, "progress", {
|
|
1651
|
-
|
|
1746
|
+
sendSSE(res, "progress", {
|
|
1747
|
+
status: "done",
|
|
1748
|
+
skill: skillName,
|
|
1749
|
+
...(agentId ? { agent: agentId } : {}),
|
|
1750
|
+
});
|
|
1751
|
+
sendSSEDone(res, {
|
|
1752
|
+
status: "done",
|
|
1753
|
+
skill: skillName,
|
|
1754
|
+
...(agentId ? { agent: agentId } : {}),
|
|
1755
|
+
});
|
|
1652
1756
|
}
|
|
1653
1757
|
catch (err) {
|
|
1654
1758
|
sendSSE(res, "error", { error: err.message, skill: skillName });
|
|
@@ -1671,8 +1775,21 @@ export function registerRoutes(router, root, projectName) {
|
|
|
1671
1775
|
try {
|
|
1672
1776
|
for (const skill of skills) {
|
|
1673
1777
|
sendSSE(res, "skill:start", { skill });
|
|
1778
|
+
// 0747 grill F-002: reject body.skills[] entries that could be
|
|
1779
|
+
// misread by Commander as flags (e.g. `--force`).
|
|
1780
|
+
if (!isSafeSkillName(skill)) {
|
|
1781
|
+
sendSSE(res, "skill:error", {
|
|
1782
|
+
skill,
|
|
1783
|
+
error: `Invalid skill name: ${skill}`,
|
|
1784
|
+
});
|
|
1785
|
+
failed++;
|
|
1786
|
+
continue;
|
|
1787
|
+
}
|
|
1674
1788
|
try {
|
|
1675
|
-
|
|
1789
|
+
// 0747 code-review F-001 (defense-in-depth): batch endpoint also
|
|
1790
|
+
// shell-interpolated body.skills[]. Switch to execFileSync argv
|
|
1791
|
+
// form so request-body values can never reach the shell.
|
|
1792
|
+
execFileSync("vskill", ["update", skill], {
|
|
1676
1793
|
timeout: 60_000,
|
|
1677
1794
|
encoding: "utf-8",
|
|
1678
1795
|
stdio: ["ignore", "pipe", "pipe"],
|