vskill 1.0.16 → 1.0.19
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 +27 -3
- package/agents.json +3 -1
- package/dist/agents/agents-registry.d.ts +61 -0
- package/dist/agents/agents-registry.js +203 -0
- package/dist/agents/agents-registry.js.map +1 -1
- package/dist/api/client.d.ts +85 -0
- package/dist/api/client.js +193 -24
- package/dist/api/client.js.map +1 -1
- package/dist/bin.js +0 -0
- package/dist/commands/add.d.ts +7 -0
- package/dist/commands/add.js +94 -1
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/auth.d.ts +23 -0
- package/dist/commands/auth.js +136 -12
- package/dist/commands/auth.js.map +1 -1
- package/dist/commands/eval/serve.d.ts +2 -0
- package/dist/commands/eval/serve.js +126 -4
- package/dist/commands/eval/serve.js.map +1 -1
- package/dist/commands/orgs.d.ts +21 -0
- package/dist/commands/orgs.js +164 -0
- package/dist/commands/orgs.js.map +1 -0
- package/dist/commands/skill.js +14 -1
- package/dist/commands/skill.js.map +1 -1
- package/dist/commands/whoami.d.ts +29 -0
- package/dist/commands/whoami.js +119 -0
- package/dist/commands/whoami.js.map +1 -0
- package/dist/eval/anthropic-catalog.js +32 -2
- package/dist/eval/anthropic-catalog.js.map +1 -1
- package/dist/eval/batch-judge.js +1 -0
- package/dist/eval/batch-judge.js.map +1 -1
- package/dist/eval/llm.d.ts +1 -1
- package/dist/eval/llm.js +104 -2
- package/dist/eval/llm.js.map +1 -1
- package/dist/eval-server/__tests__/helpers/studio-token-test-helpers.d.ts +2 -0
- package/dist/eval-server/__tests__/helpers/studio-token-test-helpers.js +20 -0
- package/dist/eval-server/__tests__/helpers/studio-token-test-helpers.js.map +1 -0
- package/dist/eval-server/active-root-store.d.ts +19 -0
- package/dist/eval-server/active-root-store.js +50 -0
- package/dist/eval-server/active-root-store.js.map +1 -0
- package/dist/eval-server/active-tenant-routes.d.ts +15 -0
- package/dist/eval-server/active-tenant-routes.js +101 -0
- package/dist/eval-server/active-tenant-routes.js.map +1 -0
- package/dist/eval-server/api-routes.d.ts +1 -1
- package/dist/eval-server/api-routes.js +60 -7
- package/dist/eval-server/api-routes.js.map +1 -1
- package/dist/eval-server/authoring-routes.d.ts +1 -1
- package/dist/eval-server/authoring-routes.js +9 -7
- package/dist/eval-server/authoring-routes.js.map +1 -1
- package/dist/eval-server/desktop-open-routes.d.ts +8 -0
- package/dist/eval-server/desktop-open-routes.js +64 -0
- package/dist/eval-server/desktop-open-routes.js.map +1 -0
- package/dist/eval-server/detect-engines-route.d.ts +1 -1
- package/dist/eval-server/detect-engines-route.js +3 -1
- package/dist/eval-server/detect-engines-route.js.map +1 -1
- package/dist/eval-server/eval-server.js +108 -29
- package/dist/eval-server/eval-server.js.map +1 -1
- package/dist/eval-server/export-skill-routes.d.ts +9 -0
- package/dist/eval-server/export-skill-routes.js +81 -0
- package/dist/eval-server/export-skill-routes.js.map +1 -0
- package/dist/eval-server/git-routes.d.ts +7 -6
- package/dist/eval-server/git-routes.js +123 -15
- package/dist/eval-server/git-routes.js.map +1 -1
- package/dist/eval-server/improve-routes.d.ts +1 -1
- package/dist/eval-server/improve-routes.js +4 -1
- package/dist/eval-server/improve-routes.js.map +1 -1
- package/dist/eval-server/install-engine-routes.d.ts +4 -17
- package/dist/eval-server/install-engine-routes.js +10 -125
- package/dist/eval-server/install-engine-routes.js.map +1 -1
- package/dist/eval-server/install-jobs.d.ts +41 -0
- package/dist/eval-server/install-jobs.js +161 -0
- package/dist/eval-server/install-jobs.js.map +1 -0
- package/dist/eval-server/install-skill-routes.d.ts +74 -11
- package/dist/eval-server/install-skill-routes.js +508 -79
- package/dist/eval-server/install-skill-routes.js.map +1 -1
- package/dist/eval-server/install-state-routes.d.ts +5 -1
- package/dist/eval-server/install-state-routes.js +18 -2
- package/dist/eval-server/install-state-routes.js.map +1 -1
- package/dist/eval-server/integration-routes.d.ts +1 -1
- package/dist/eval-server/integration-routes.js +6 -1
- package/dist/eval-server/integration-routes.js.map +1 -1
- package/dist/eval-server/model-compare-routes.d.ts +1 -1
- package/dist/eval-server/model-compare-routes.js +3 -1
- package/dist/eval-server/model-compare-routes.js.map +1 -1
- package/dist/eval-server/oauth-github-routes.d.ts +2 -0
- package/dist/eval-server/oauth-github-routes.js +505 -0
- package/dist/eval-server/oauth-github-routes.js.map +1 -0
- package/dist/eval-server/platform-proxy.d.ts +22 -1
- package/dist/eval-server/platform-proxy.js +183 -22
- package/dist/eval-server/platform-proxy.js.map +1 -1
- package/dist/eval-server/plugin-cli-routes.d.ts +1 -1
- package/dist/eval-server/plugin-cli-routes.js +19 -10
- package/dist/eval-server/plugin-cli-routes.js.map +1 -1
- package/dist/eval-server/remove-skill-routes.d.ts +18 -0
- package/dist/eval-server/remove-skill-routes.js +147 -0
- package/dist/eval-server/remove-skill-routes.js.map +1 -0
- package/dist/eval-server/router.d.ts +17 -3
- package/dist/eval-server/router.js +166 -9
- package/dist/eval-server/router.js.map +1 -1
- package/dist/eval-server/settings-store.js +1 -1
- package/dist/eval-server/settings-store.js.map +1 -1
- package/dist/eval-server/skill-create-routes.d.ts +1 -1
- package/dist/eval-server/skill-create-routes.js +8 -1
- package/dist/eval-server/skill-create-routes.js.map +1 -1
- package/dist/eval-server/supported-agents-routes.d.ts +6 -0
- package/dist/eval-server/supported-agents-routes.js +41 -0
- package/dist/eval-server/supported-agents-routes.js.map +1 -0
- package/dist/eval-server/sweep-routes.d.ts +1 -1
- package/dist/eval-server/sweep-routes.js +5 -1
- package/dist/eval-server/sweep-routes.js.map +1 -1
- package/dist/eval-server/utils/spawn-env.d.ts +1 -0
- package/dist/eval-server/utils/spawn-env.js +47 -0
- package/dist/eval-server/utils/spawn-env.js.map +1 -0
- package/dist/eval-server/workspace-routes.d.ts +12 -0
- package/dist/eval-server/workspace-routes.js +57 -2
- package/dist/eval-server/workspace-routes.js.map +1 -1
- package/dist/eval-ui/assets/AdvancedTab-DOgbx7u0.js +1 -0
- package/dist/eval-ui/assets/{CreateSkillPage-CvdYq8Rr.js → CreateSkillPage-Cv93Croj.js} +3 -3
- package/dist/eval-ui/assets/FindSkillsPalette-BY9DAhHh.js +2 -0
- package/dist/eval-ui/assets/GeneralTab-AwK9sIkP.js +1 -0
- package/dist/eval-ui/assets/PrivacyTab-BtNrxpVV.js +1 -0
- package/dist/eval-ui/assets/{SearchPaletteCore-Bf3PBC64.js → SearchPaletteCore-DMVcq7UB.js} +2 -2
- package/dist/eval-ui/assets/SkillDetailPanel-B_lbhK6q.js +1 -0
- package/dist/eval-ui/assets/UpdateDropdown-4AbjZLpq.js +1 -0
- package/dist/eval-ui/assets/UpdatesTab-DTmo-vVb.js +1 -0
- package/dist/eval-ui/assets/core-DZjBCfjp.js +1 -0
- package/dist/eval-ui/assets/event-QtOCMXAv.js +1 -0
- package/dist/eval-ui/assets/globals-Dpf9KmYH.css +1 -0
- package/dist/eval-ui/assets/globals-hm1COkXX.js +49 -0
- package/dist/eval-ui/assets/index-CUEYzTVL.js +1 -0
- package/dist/eval-ui/assets/index-DDNzcrhv.js +1 -0
- package/dist/eval-ui/assets/index-DhhmQddr.js +1 -0
- package/dist/eval-ui/assets/lifecycle-d1Sm9Hts.css +1 -0
- package/dist/eval-ui/assets/lifecycle-o_IRibOa.js +1 -0
- package/dist/eval-ui/assets/main-tpOyw9SC.js +87 -0
- package/dist/eval-ui/assets/preferences-BHZXB5dL.css +1 -0
- package/dist/eval-ui/assets/preferences-DCdw0Kvu.js +2 -0
- package/dist/eval-ui/assets/useDesktopBridge-9oZFQsrw.js +2 -0
- package/dist/eval-ui/index.html +4 -2
- package/dist/eval-ui/lifecycle.html +33 -0
- package/dist/eval-ui/preferences.html +34 -0
- package/dist/index.js +47 -1
- package/dist/index.js.map +1 -1
- package/dist/installer/bundle-files.d.ts +4 -0
- package/dist/installer/bundle-files.js +97 -0
- package/dist/installer/bundle-files.js.map +1 -0
- package/dist/installer/canonical.d.ts +31 -6
- package/dist/installer/canonical.js +48 -12
- package/dist/installer/canonical.js.map +1 -1
- package/dist/installer/clipboard-export.d.ts +19 -0
- package/dist/installer/clipboard-export.js +88 -0
- package/dist/installer/clipboard-export.js.map +1 -0
- package/dist/installer/multi-install.d.ts +43 -0
- package/dist/installer/multi-install.js +237 -0
- package/dist/installer/multi-install.js.map +1 -0
- package/dist/installer/transformers/aider.d.ts +2 -0
- package/dist/installer/transformers/aider.js +32 -0
- package/dist/installer/transformers/aider.js.map +1 -0
- package/dist/installer/transformers/continue-dev.d.ts +2 -0
- package/dist/installer/transformers/continue-dev.js +6 -0
- package/dist/installer/transformers/continue-dev.js.map +1 -0
- package/dist/installer/transformers/cursor.d.ts +2 -0
- package/dist/installer/transformers/cursor.js +24 -0
- package/dist/installer/transformers/cursor.js.map +1 -0
- package/dist/installer/transformers/github-copilot.d.ts +2 -0
- package/dist/installer/transformers/github-copilot.js +17 -0
- package/dist/installer/transformers/github-copilot.js.map +1 -0
- package/dist/installer/transformers/index.d.ts +78 -0
- package/dist/installer/transformers/index.js +13 -0
- package/dist/installer/transformers/index.js.map +1 -0
- package/dist/installer/transformers/junie.d.ts +2 -0
- package/dist/installer/transformers/junie.js +6 -0
- package/dist/installer/transformers/junie.js.map +1 -0
- package/dist/installer/transformers/kiro.d.ts +2 -0
- package/dist/installer/transformers/kiro.js +6 -0
- package/dist/installer/transformers/kiro.js.map +1 -0
- package/dist/installer/transformers/trae.d.ts +2 -0
- package/dist/installer/transformers/trae.js +6 -0
- package/dist/installer/transformers/trae.js.map +1 -0
- package/dist/installer/transformers/windsurf.d.ts +2 -0
- package/dist/installer/transformers/windsurf.js +12 -0
- package/dist/installer/transformers/windsurf.js.map +1 -0
- package/dist/installer/yaml-safe-mutate.d.ts +19 -0
- package/dist/installer/yaml-safe-mutate.js +184 -0
- package/dist/installer/yaml-safe-mutate.js.map +1 -0
- package/dist/lib/active-tenant.d.ts +36 -0
- package/dist/lib/active-tenant.js +120 -0
- package/dist/lib/active-tenant.js.map +1 -0
- package/dist/lib/keychain.d.ts +15 -2
- package/dist/lib/keychain.js +173 -8
- package/dist/lib/keychain.js.map +1 -1
- package/dist/lib/migration/keychain-migration.d.ts +35 -0
- package/dist/lib/migration/keychain-migration.js +189 -0
- package/dist/lib/migration/keychain-migration.js.map +1 -0
- package/dist/lib/tenant-resolver.d.ts +38 -0
- package/dist/lib/tenant-resolver.js +79 -0
- package/dist/lib/tenant-resolver.js.map +1 -0
- package/dist/studio/lib/ops-log.js +140 -57
- package/dist/studio/lib/ops-log.js.map +1 -1
- package/dist/studio/lib/scope-transfer.d.ts +11 -1
- package/dist/studio/lib/scope-transfer.js +48 -24
- package/dist/studio/lib/scope-transfer.js.map +1 -1
- package/dist/studio/routes/index.d.ts +1 -1
- package/dist/studio/routes/index.js +18 -8
- package/dist/studio/routes/index.js.map +1 -1
- package/dist/studio/routes/ops.js +31 -7
- package/dist/studio/routes/ops.js.map +1 -1
- package/dist/studio/routes/promote.d.ts +1 -1
- package/dist/studio/routes/promote.js +18 -9
- package/dist/studio/routes/promote.js.map +1 -1
- package/dist/studio/routes/revert.d.ts +1 -1
- package/dist/studio/routes/revert.js +15 -2
- package/dist/studio/routes/revert.js.map +1 -1
- package/dist/studio/routes/test-install.d.ts +1 -1
- package/dist/studio/routes/test-install.js +16 -9
- package/dist/studio/routes/test-install.js.map +1 -1
- package/dist/studio-runtime/lockfile.d.ts +51 -0
- package/dist/studio-runtime/lockfile.js +216 -0
- package/dist/studio-runtime/lockfile.js.map +1 -0
- package/package.json +18 -1
- package/dist/eval-ui/assets/FindSkillsPalette-DsSgotS9.js +0 -2
- package/dist/eval-ui/assets/SkillDetailPanel-DAD2yJO-.js +0 -1
- package/dist/eval-ui/assets/UpdateDropdown-h5Hg3h7Z.js +0 -1
- package/dist/eval-ui/assets/index-CKLqBL52.css +0 -1
- package/dist/eval-ui/assets/index-JaDg6FlU.js +0 -124
- package/dist/eval-ui/assets/skill-studio-logo-CRyKgIrg.png +0 -0
|
@@ -10,74 +10,162 @@
|
|
|
10
10
|
//
|
|
11
11
|
// In-process subscribe()/listOps()/deleteOp() (tombstone) — no cross-process IPC.
|
|
12
12
|
// ---------------------------------------------------------------------------
|
|
13
|
-
import {
|
|
13
|
+
import { promises as fs, existsSync, statSync, renameSync } from "node:fs";
|
|
14
14
|
import { dirname, join } from "node:path";
|
|
15
15
|
import { homedir } from "node:os";
|
|
16
16
|
import { EventEmitter } from "node:events";
|
|
17
|
-
const APPEND_FLAGS = "a";
|
|
18
17
|
const emitter = new EventEmitter();
|
|
19
|
-
|
|
18
|
+
// Subscriber count is bounded by active SSE clients (~UI tabs); 100 is far
|
|
19
|
+
// above realistic load, and unlike `setMaxListeners(0)` it lets a real leak
|
|
20
|
+
// surface as a Node warning instead of silently growing.
|
|
21
|
+
emitter.setMaxListeners(100);
|
|
22
|
+
// Default rotation threshold for studio-ops.jsonl. Override via env to tune
|
|
23
|
+
// for long-running studios. 5 MiB ≈ ~25k ops at ~200 B each.
|
|
24
|
+
const ROTATE_BYTES_DEFAULT = 5 * 1024 * 1024;
|
|
25
|
+
function getRotateBytes() {
|
|
26
|
+
const raw = process.env.VSKILL_OPS_LOG_ROTATE_BYTES;
|
|
27
|
+
if (!raw)
|
|
28
|
+
return ROTATE_BYTES_DEFAULT;
|
|
29
|
+
const n = Number(raw);
|
|
30
|
+
return Number.isFinite(n) && n > 0 ? n : ROTATE_BYTES_DEFAULT;
|
|
31
|
+
}
|
|
20
32
|
export function getLogPath() {
|
|
21
33
|
return process.env.VSKILL_OPS_LOG_PATH || join(homedir(), ".vskill", "studio-ops.jsonl");
|
|
22
34
|
}
|
|
23
|
-
function ensureDir(path) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
35
|
+
async function ensureDir(path) {
|
|
36
|
+
// mkdir(recursive:true) is idempotent — no need for an existsSync TOCTOU pre-check.
|
|
37
|
+
await fs.mkdir(dirname(path), { recursive: true });
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Rotate `studio-ops.jsonl` → `studio-ops.1.jsonl` when the live log exceeds
|
|
41
|
+
* the configured threshold. Best-effort: a rotation failure must not block
|
|
42
|
+
* the append. Compaction of tombstones happens implicitly because rotated
|
|
43
|
+
* files are kept (only `listOps` reads the live file; rotated history is
|
|
44
|
+
* forensic-only, not surfaced via the API).
|
|
45
|
+
*/
|
|
46
|
+
function maybeRotate(path) {
|
|
47
|
+
try {
|
|
48
|
+
if (!existsSync(path))
|
|
49
|
+
return;
|
|
50
|
+
const size = statSync(path).size;
|
|
51
|
+
if (size < getRotateBytes())
|
|
52
|
+
return;
|
|
53
|
+
renameSync(path, path.replace(/\.jsonl$/, ".1.jsonl"));
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
/* rotation is best-effort */
|
|
57
|
+
}
|
|
27
58
|
}
|
|
28
59
|
export async function appendOp(op) {
|
|
29
60
|
const path = getLogPath();
|
|
30
|
-
ensureDir(path);
|
|
61
|
+
await ensureDir(path);
|
|
62
|
+
maybeRotate(path);
|
|
31
63
|
const line = JSON.stringify(op) + "\n";
|
|
32
|
-
//
|
|
33
|
-
|
|
64
|
+
// POSIX guarantees writes < PIPE_BUF (4 KiB) are atomic with O_APPEND;
|
|
65
|
+
// our ops are well under that. fs.appendFile uses O_APPEND under the hood.
|
|
66
|
+
await fs.appendFile(path, line);
|
|
67
|
+
emitter.emit("op", op);
|
|
68
|
+
}
|
|
69
|
+
const TAIL_CHUNK_BYTES = 64 * 1024;
|
|
70
|
+
const DEFAULT_LIMIT = 50;
|
|
71
|
+
/**
|
|
72
|
+
* Read JSONL backwards from EOF in 64 KiB chunks until we have `limit`
|
|
73
|
+
* non-tombstoned ops or hit the start of the file. Tombstones are appended
|
|
74
|
+
* AFTER the op they invalidate, so reading newest-first naturally surfaces
|
|
75
|
+
* tombstone IDs before the ops they apply to.
|
|
76
|
+
*
|
|
77
|
+
* Memory: O(chunk + limit). Time: O(limit) for typical limits (50–500),
|
|
78
|
+
* vs. O(file-size) for the previous full-file approach.
|
|
79
|
+
*/
|
|
80
|
+
async function readTailOps(path, limit, before) {
|
|
81
|
+
let fh;
|
|
34
82
|
try {
|
|
35
|
-
|
|
83
|
+
fh = await fs.open(path, "r");
|
|
36
84
|
}
|
|
37
|
-
|
|
38
|
-
|
|
85
|
+
catch (err) {
|
|
86
|
+
if (err.code === "ENOENT")
|
|
87
|
+
return [];
|
|
88
|
+
throw err;
|
|
39
89
|
}
|
|
40
|
-
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
//
|
|
90
|
+
try {
|
|
91
|
+
const { size } = await fh.stat();
|
|
92
|
+
if (size === 0)
|
|
93
|
+
return [];
|
|
94
|
+
const tombstoned = new Set();
|
|
95
|
+
const ops = [];
|
|
96
|
+
let pos = size;
|
|
97
|
+
let carry = ""; // Partial line stitched onto the next (older) chunk.
|
|
98
|
+
while (pos > 0 && ops.length < limit) {
|
|
99
|
+
const readLen = Math.min(TAIL_CHUNK_BYTES, pos);
|
|
100
|
+
pos -= readLen;
|
|
101
|
+
const buf = Buffer.alloc(readLen);
|
|
102
|
+
await fh.read(buf, 0, readLen, pos);
|
|
103
|
+
// chunk_text + carry from previous (newer) chunk = continuous bytes,
|
|
104
|
+
// because chunks are read newest→oldest and `carry` was the partial
|
|
105
|
+
// line at the START of the previous chunk.
|
|
106
|
+
const text = buf.toString("utf-8") + carry;
|
|
107
|
+
// The first newline splits a partial line at the start of `text`
|
|
108
|
+
// (which continues into older bytes still on disk) from complete
|
|
109
|
+
// lines after it. At pos === 0 there is no older data — every
|
|
110
|
+
// segment is a complete line.
|
|
111
|
+
let firstNL;
|
|
112
|
+
let lines;
|
|
113
|
+
if (pos === 0) {
|
|
114
|
+
carry = "";
|
|
115
|
+
lines = text.split("\n");
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
firstNL = text.indexOf("\n");
|
|
119
|
+
if (firstNL === -1) {
|
|
120
|
+
// No newline at all — the entire chunk continues into older bytes.
|
|
121
|
+
carry = text;
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
carry = text.slice(0, firstNL);
|
|
125
|
+
lines = text.slice(firstNL + 1).split("\n");
|
|
126
|
+
}
|
|
127
|
+
// Process newest→oldest within this batch.
|
|
128
|
+
for (let i = lines.length - 1; i >= 0 && ops.length < limit; i--) {
|
|
129
|
+
const trimmed = lines[i].trim();
|
|
130
|
+
if (!trimmed)
|
|
131
|
+
continue;
|
|
132
|
+
let parsed;
|
|
133
|
+
try {
|
|
134
|
+
parsed = JSON.parse(trimmed);
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
if (parsed.tombstone === true) {
|
|
140
|
+
const id = parsed.id;
|
|
141
|
+
if (id)
|
|
142
|
+
tombstoned.add(id);
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
const op = parsed;
|
|
146
|
+
if (typeof op.ts !== "number")
|
|
147
|
+
continue;
|
|
148
|
+
if (tombstoned.has(op.id))
|
|
149
|
+
continue;
|
|
150
|
+
if (before != null && op.ts >= before)
|
|
151
|
+
continue;
|
|
152
|
+
ops.push(op);
|
|
153
|
+
}
|
|
56
154
|
}
|
|
155
|
+
// Tail-read order is approximately newest-first but `ts` may not be
|
|
156
|
+
// strictly monotonic w.r.t. file position (clock skew, parallel writes
|
|
157
|
+
// — both rare but possible). Re-sort to honor the contract.
|
|
158
|
+
ops.sort((a, b) => b.ts - a.ts);
|
|
159
|
+
return ops.slice(0, limit);
|
|
160
|
+
}
|
|
161
|
+
finally {
|
|
162
|
+
await fh.close();
|
|
57
163
|
}
|
|
58
|
-
return out;
|
|
59
164
|
}
|
|
60
165
|
export async function listOps(opts = {}) {
|
|
61
166
|
const path = getLogPath();
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
for (const entry of all) {
|
|
65
|
-
if (entry.tombstone === true && entry.id) {
|
|
66
|
-
tombstoned.add(entry.id);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
let ops = all
|
|
70
|
-
.filter((e) => !e.tombstone && typeof e.ts === "number")
|
|
71
|
-
.filter((op) => !tombstoned.has(op.id));
|
|
72
|
-
// Newest first.
|
|
73
|
-
ops.sort((a, b) => b.ts - a.ts);
|
|
74
|
-
if (opts.before != null) {
|
|
75
|
-
ops = ops.filter((op) => op.ts < opts.before);
|
|
76
|
-
}
|
|
77
|
-
if (opts.limit != null) {
|
|
78
|
-
ops = ops.slice(0, opts.limit);
|
|
79
|
-
}
|
|
80
|
-
return ops;
|
|
167
|
+
const limit = opts.limit ?? DEFAULT_LIMIT;
|
|
168
|
+
return readTailOps(path, limit, opts.before);
|
|
81
169
|
}
|
|
82
170
|
export function subscribe(fn) {
|
|
83
171
|
emitter.on("op", fn);
|
|
@@ -85,15 +173,10 @@ export function subscribe(fn) {
|
|
|
85
173
|
}
|
|
86
174
|
export async function deleteOp(id) {
|
|
87
175
|
const path = getLogPath();
|
|
88
|
-
ensureDir(path);
|
|
176
|
+
await ensureDir(path);
|
|
177
|
+
maybeRotate(path);
|
|
89
178
|
const line = JSON.stringify({ id, tombstone: true }) + "\n";
|
|
90
|
-
|
|
91
|
-
try {
|
|
92
|
-
writeSync(fd, line);
|
|
93
|
-
}
|
|
94
|
-
finally {
|
|
95
|
-
closeSync(fd);
|
|
96
|
-
}
|
|
179
|
+
await fs.appendFile(path, line);
|
|
97
180
|
emitter.emit("delete", id);
|
|
98
181
|
}
|
|
99
182
|
//# sourceMappingURL=ops-log.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ops-log.js","sourceRoot":"","sources":["../../../src/studio/lib/ops-log.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,qEAAqE;AACrE,8EAA8E;AAC9E,oDAAoD;AACpD,EAAE;AACF,2EAA2E;AAC3E,6EAA6E;AAC7E,0EAA0E;AAC1E,iDAAiD;AACjD,EAAE;AACF,kFAAkF;AAClF,8EAA8E;AAE9E,OAAO,EAAE,QAAQ,EAAE,
|
|
1
|
+
{"version":3,"file":"ops-log.js","sourceRoot":"","sources":["../../../src/studio/lib/ops-log.ts"],"names":[],"mappings":"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"}
|
|
@@ -29,6 +29,16 @@ export declare function resolveScopePath(scope: SkillScope, root: string, skill:
|
|
|
29
29
|
* Count files written recursively into a directory — used for the SSE
|
|
30
30
|
* `copied` and `deleted` event payloads. Returns 0 for missing dirs so
|
|
31
31
|
* callers can use it on paths that may have been removed mid-flight.
|
|
32
|
+
*
|
|
33
|
+
* Skips symlinks (lstat) to avoid following loops, and caps depth at
|
|
34
|
+
* MAX_RECURSION_DEPTH so a pathological tree can't blow the call stack.
|
|
32
35
|
*/
|
|
33
|
-
export declare function countFiles(dir: string): number;
|
|
36
|
+
export declare function countFiles(dir: string, depth?: number): number;
|
|
37
|
+
/**
|
|
38
|
+
* Pre-flight check that a transfer can succeed. Throws MissingSourceError /
|
|
39
|
+
* CollisionError without touching the filesystem. Routes call this BEFORE
|
|
40
|
+
* opening an SSE stream so failure cases return clean HTTP 404 / 409 with
|
|
41
|
+
* a JSON body instead of opening SSE then immediately emitting an error.
|
|
42
|
+
*/
|
|
43
|
+
export declare function validatePaths(sourcePath: string, destPath: string, overwrite: boolean): void;
|
|
34
44
|
export declare function transfer(req: TransferRequest, emit: SSEEmit): Promise<TransferResult>;
|
|
@@ -13,8 +13,12 @@
|
|
|
13
13
|
// Provenance sidecar (.vskill-meta.json) must NEVER leak out of OWN scope —
|
|
14
14
|
// filtered inside transfer before invoking copy.
|
|
15
15
|
// ---------------------------------------------------------------------------
|
|
16
|
-
import { existsSync, rmSync, readdirSync,
|
|
16
|
+
import { existsSync, rmSync, readdirSync, copyFileSync, mkdirSync, writeFileSync } from "node:fs";
|
|
17
17
|
import { join } from "node:path";
|
|
18
|
+
// Cap recursion depth on user-content trees we don't fully control.
|
|
19
|
+
// 32 is well above any realistic skill nesting (plan.md skills have 0–3
|
|
20
|
+
// levels) and safely below Node's default call-stack budget.
|
|
21
|
+
const MAX_RECURSION_DEPTH = 32;
|
|
18
22
|
import { copyPluginFiltered, shouldSkipFromCommands, } from "../../shared/copy-plugin-filtered.js";
|
|
19
23
|
import { resolveSourceLink } from "../../eval-server/source-link.js";
|
|
20
24
|
export class CollisionError extends Error {
|
|
@@ -49,17 +53,23 @@ export function resolveScopePath(scope, root, skill, home) {
|
|
|
49
53
|
* Count files written recursively into a directory — used for the SSE
|
|
50
54
|
* `copied` and `deleted` event payloads. Returns 0 for missing dirs so
|
|
51
55
|
* callers can use it on paths that may have been removed mid-flight.
|
|
56
|
+
*
|
|
57
|
+
* Skips symlinks (lstat) to avoid following loops, and caps depth at
|
|
58
|
+
* MAX_RECURSION_DEPTH so a pathological tree can't blow the call stack.
|
|
52
59
|
*/
|
|
53
|
-
export function countFiles(dir) {
|
|
60
|
+
export function countFiles(dir, depth = 0) {
|
|
54
61
|
if (!existsSync(dir))
|
|
55
62
|
return 0;
|
|
63
|
+
if (depth >= MAX_RECURSION_DEPTH)
|
|
64
|
+
return 0;
|
|
56
65
|
let n = 0;
|
|
57
|
-
for (const entry of readdirSync(dir)) {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
66
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
67
|
+
if (entry.isSymbolicLink())
|
|
68
|
+
continue;
|
|
69
|
+
const full = join(dir, entry.name);
|
|
70
|
+
if (entry.isDirectory())
|
|
71
|
+
n += countFiles(full, depth + 1);
|
|
72
|
+
else if (entry.isFile())
|
|
63
73
|
n += 1;
|
|
64
74
|
}
|
|
65
75
|
return n;
|
|
@@ -69,36 +79,50 @@ export function countFiles(dir) {
|
|
|
69
79
|
* copyPluginFiltered this does not do the plugin-root flattening, because
|
|
70
80
|
* OWN → INSTALLED|GLOBAL is a straight skill-dir copy with one exclusion.
|
|
71
81
|
*/
|
|
72
|
-
function copyOwnSkillFiltered(sourceDir, targetDir, relBase = "") {
|
|
82
|
+
function copyOwnSkillFiltered(sourceDir, targetDir, relBase = "", depth = 0) {
|
|
83
|
+
if (depth >= MAX_RECURSION_DEPTH)
|
|
84
|
+
return;
|
|
73
85
|
mkdirSync(targetDir, { recursive: true });
|
|
74
|
-
for (const entry of readdirSync(sourceDir)) {
|
|
86
|
+
for (const entry of readdirSync(sourceDir, { withFileTypes: true })) {
|
|
75
87
|
// 0809: filter the copied-skill source-link sidecar at the OWN scope root
|
|
76
88
|
// alongside the existing .vskill-meta.json filter. Sidecars are re-derived
|
|
77
89
|
// by the destination's `transfer()` post-copy step, never copied through.
|
|
78
90
|
// Asymmetric with copyPluginFiltered (which strips at any depth) on purpose:
|
|
79
91
|
// OWN scope is a single skill dir, so sidecars only ever exist at the root.
|
|
80
|
-
if (!relBase && (entry === ".vskill-meta.json" || entry === ".vskill-source.json"))
|
|
92
|
+
if (!relBase && (entry.name === ".vskill-meta.json" || entry.name === ".vskill-source.json"))
|
|
93
|
+
continue;
|
|
94
|
+
// Skip symlinks defensively — copying through them risks loops and
|
|
95
|
+
// unexpected escapes from the skill dir.
|
|
96
|
+
if (entry.isSymbolicLink())
|
|
81
97
|
continue;
|
|
82
|
-
const relPath = relBase ? `${relBase}/${entry}` : entry;
|
|
83
|
-
const sourcePath = join(sourceDir, entry);
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
copyOwnSkillFiltered(sourcePath, join(targetDir, entry), relPath);
|
|
98
|
+
const relPath = relBase ? `${relBase}/${entry.name}` : entry.name;
|
|
99
|
+
const sourcePath = join(sourceDir, entry.name);
|
|
100
|
+
if (entry.isDirectory()) {
|
|
101
|
+
copyOwnSkillFiltered(sourcePath, join(targetDir, entry.name), relPath, depth + 1);
|
|
87
102
|
}
|
|
88
|
-
else if (
|
|
89
|
-
copyFileSync(sourcePath, join(targetDir, entry));
|
|
103
|
+
else if (entry.isFile() && !shouldSkipFromCommands(relPath)) {
|
|
104
|
+
copyFileSync(sourcePath, join(targetDir, entry.name));
|
|
90
105
|
}
|
|
91
106
|
}
|
|
92
107
|
}
|
|
108
|
+
/**
|
|
109
|
+
* Pre-flight check that a transfer can succeed. Throws MissingSourceError /
|
|
110
|
+
* CollisionError without touching the filesystem. Routes call this BEFORE
|
|
111
|
+
* opening an SSE stream so failure cases return clean HTTP 404 / 409 with
|
|
112
|
+
* a JSON body instead of opening SSE then immediately emitting an error.
|
|
113
|
+
*/
|
|
114
|
+
export function validatePaths(sourcePath, destPath, overwrite) {
|
|
115
|
+
if (!existsSync(sourcePath))
|
|
116
|
+
throw new MissingSourceError(sourcePath);
|
|
117
|
+
if (existsSync(destPath) && !overwrite)
|
|
118
|
+
throw new CollisionError(destPath);
|
|
119
|
+
}
|
|
93
120
|
export async function transfer(req, emit) {
|
|
94
121
|
const sourcePath = resolveScopePath(req.fromScope, req.root, req.skill, req.home);
|
|
95
122
|
const destPath = resolveScopePath(req.toScope, req.root, req.skill, req.home);
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
if (existsSync(destPath) && !req.overwrite) {
|
|
100
|
-
throw new CollisionError(destPath);
|
|
101
|
-
}
|
|
123
|
+
// Re-validate inside transfer too — callers may call transfer() directly
|
|
124
|
+
// (not via the route layer) and expect the throw contract.
|
|
125
|
+
validatePaths(sourcePath, destPath, req.overwrite ?? false);
|
|
102
126
|
// If overwrite, clear the destination first so stale files aren't left behind.
|
|
103
127
|
if (existsSync(destPath) && req.overwrite) {
|
|
104
128
|
rmSync(destPath, { recursive: true, force: true });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scope-transfer.js","sourceRoot":"","sources":["../../../src/studio/lib/scope-transfer.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,wEAAwE;AACxE,8EAA8E;AAC9E,6EAA6E;AAC7E,6EAA6E;AAC7E,qCAAqC;AACrC,EAAE;AACF,gCAAgC;AAChC,wCAAwC;AACxC,iGAAiG;AACjG,gDAAgD;AAChD,EAAE;AACF,4EAA4E;AAC5E,iDAAiD;AACjD,8EAA8E;AAE9E,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"scope-transfer.js","sourceRoot":"","sources":["../../../src/studio/lib/scope-transfer.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { Router } from "../../eval-server/router.js";
|
|
2
|
-
export declare function registerScopeTransferRoutes(router: Router,
|
|
2
|
+
export declare function registerScopeTransferRoutes(router: Router, rootArg: string | (() => string)): void;
|
|
@@ -14,15 +14,25 @@ import { registerDetectEnginesRoute } from "../../eval-server/detect-engines-rou
|
|
|
14
14
|
import { registerInstallEngineRoutes } from "../../eval-server/install-engine-routes.js";
|
|
15
15
|
import { registerInstallSkillRoutes } from "../../eval-server/install-skill-routes.js";
|
|
16
16
|
import { registerInstallStateRoutes } from "../../eval-server/install-state-routes.js";
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
import { registerSupportedAgentsRoutes } from "../../eval-server/supported-agents-routes.js";
|
|
18
|
+
import { registerExportSkillRoutes } from "../../eval-server/export-skill-routes.js";
|
|
19
|
+
import { registerRemoveSkillRoutes } from "../../eval-server/remove-skill-routes.js";
|
|
20
|
+
export function registerScopeTransferRoutes(router, rootArg) {
|
|
21
|
+
const getRoot = typeof rootArg === "function" ? rootArg : () => rootArg;
|
|
22
|
+
registerPromoteRoute(router, getRoot);
|
|
23
|
+
registerTestInstallRoute(router, getRoot);
|
|
24
|
+
registerRevertRoute(router, getRoot);
|
|
21
25
|
registerOpsRoutes(router);
|
|
22
|
-
registerDetectEnginesRoute(router,
|
|
23
|
-
registerInstallEngineRoutes(router,
|
|
24
|
-
registerInstallSkillRoutes(router);
|
|
26
|
+
registerDetectEnginesRoute(router, getRoot);
|
|
27
|
+
registerInstallEngineRoutes(router, getRoot);
|
|
28
|
+
registerInstallSkillRoutes(router, getRoot);
|
|
25
29
|
// 0827 — per-skill install-state for the panel's scope picker.
|
|
26
|
-
registerInstallStateRoutes(router,
|
|
30
|
+
registerInstallStateRoutes(router, getRoot);
|
|
31
|
+
// 0845 — cross-tool install targets (every supported agent, detected or not).
|
|
32
|
+
registerSupportedAgentsRoutes(router);
|
|
33
|
+
// 0845 T-015 — Tier-3 clipboard export (ChatGPT, v0, bolt.new).
|
|
34
|
+
registerExportSkillRoutes(router);
|
|
35
|
+
// 0850 — per-agent skill remove from the InstallTargetsModal.
|
|
36
|
+
registerRemoveSkillRoutes(router, getRoot);
|
|
27
37
|
}
|
|
28
38
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/studio/routes/index.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,wDAAwD;AACxD,8EAA8E;AAC9E,wEAAwE;AACxE,4EAA4E;AAC5E,qEAAqE;AACrE,cAAc;AACd,8EAA8E;AAG9E,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,0BAA0B,EAAE,MAAM,2CAA2C,CAAC;AACvF,OAAO,EAAE,2BAA2B,EAAE,MAAM,4CAA4C,CAAC;AACzF,OAAO,EAAE,0BAA0B,EAAE,MAAM,2CAA2C,CAAC;AACvF,OAAO,EAAE,0BAA0B,EAAE,MAAM,2CAA2C,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/studio/routes/index.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,wDAAwD;AACxD,8EAA8E;AAC9E,wEAAwE;AACxE,4EAA4E;AAC5E,qEAAqE;AACrE,cAAc;AACd,8EAA8E;AAG9E,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,0BAA0B,EAAE,MAAM,2CAA2C,CAAC;AACvF,OAAO,EAAE,2BAA2B,EAAE,MAAM,4CAA4C,CAAC;AACzF,OAAO,EAAE,0BAA0B,EAAE,MAAM,2CAA2C,CAAC;AACvF,OAAO,EAAE,0BAA0B,EAAE,MAAM,2CAA2C,CAAC;AACvF,OAAO,EAAE,6BAA6B,EAAE,MAAM,8CAA8C,CAAC;AAC7F,OAAO,EAAE,yBAAyB,EAAE,MAAM,0CAA0C,CAAC;AACrF,OAAO,EAAE,yBAAyB,EAAE,MAAM,0CAA0C,CAAC;AAErF,MAAM,UAAU,2BAA2B,CAAC,MAAc,EAAE,OAAgC;IAC1F,MAAM,OAAO,GAAG,OAAO,OAAO,KAAK,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC;IACxE,oBAAoB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,wBAAwB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC1C,mBAAmB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC1B,0BAA0B,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5C,2BAA2B,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC7C,0BAA0B,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5C,+DAA+D;IAC/D,0BAA0B,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5C,8EAA8E;IAC9E,6BAA6B,CAAC,MAAM,CAAC,CAAC;IACtC,gEAAgE;IAChE,yBAAyB,CAAC,MAAM,CAAC,CAAC;IAClC,8DAA8D;IAC9D,yBAAyB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAC7C,CAAC"}
|
|
@@ -9,6 +9,34 @@ import { sendJson } from "../../eval-server/router.js";
|
|
|
9
9
|
import { initSSE, sendSSE } from "../../eval-server/sse-helpers.js";
|
|
10
10
|
import { listOps, subscribe, deleteOp } from "../lib/ops-log.js";
|
|
11
11
|
import { parseQuery } from "../lib/query.js";
|
|
12
|
+
// One ticker fans out to every connected SSE client instead of one timer
|
|
13
|
+
// per connection. Lazily started on first subscriber, stopped when the
|
|
14
|
+
// last leaves. `.unref()` so an idle ticker doesn't block process exit.
|
|
15
|
+
const HEARTBEAT_MS = 3000;
|
|
16
|
+
const heartbeatClients = new Set();
|
|
17
|
+
let heartbeatTimer = null;
|
|
18
|
+
function startHeartbeatIfNeeded() {
|
|
19
|
+
if (heartbeatTimer || heartbeatClients.size === 0)
|
|
20
|
+
return;
|
|
21
|
+
heartbeatTimer = setInterval(() => {
|
|
22
|
+
const ts = Date.now();
|
|
23
|
+
for (const res of heartbeatClients) {
|
|
24
|
+
try {
|
|
25
|
+
sendSSE(res, "heartbeat", { ts });
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
// Stream closed mid-fan-out — drop it now to avoid a stuck client
|
|
29
|
+
// keeping the timer alive after the connection ended.
|
|
30
|
+
heartbeatClients.delete(res);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (heartbeatClients.size === 0 && heartbeatTimer) {
|
|
34
|
+
clearInterval(heartbeatTimer);
|
|
35
|
+
heartbeatTimer = null;
|
|
36
|
+
}
|
|
37
|
+
}, HEARTBEAT_MS);
|
|
38
|
+
heartbeatTimer.unref();
|
|
39
|
+
}
|
|
12
40
|
export function registerOpsRoutes(router) {
|
|
13
41
|
// GET /api/studio/ops?limit=50&before=<ts>
|
|
14
42
|
router.get("/api/studio/ops", async (req, res) => {
|
|
@@ -34,14 +62,10 @@ export function registerOpsRoutes(router) {
|
|
|
34
62
|
// Writing after stream close — safe to swallow.
|
|
35
63
|
}
|
|
36
64
|
});
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
sendSSE(res, "heartbeat", { ts: Date.now() });
|
|
40
|
-
}
|
|
41
|
-
catch { }
|
|
42
|
-
}, 3000);
|
|
65
|
+
heartbeatClients.add(res);
|
|
66
|
+
startHeartbeatIfNeeded();
|
|
43
67
|
const cleanup = () => {
|
|
44
|
-
|
|
68
|
+
heartbeatClients.delete(res);
|
|
45
69
|
unsub();
|
|
46
70
|
};
|
|
47
71
|
req.on("close", cleanup);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ops.js","sourceRoot":"","sources":["../../../src/studio/routes/ops.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,yCAAyC;AACzC,8EAA8E;AAC9E,iEAAiE;AACjE,2EAA2E;AAC3E,8DAA8D;AAC9D,8EAA8E;AAK9E,OAAO,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,MAAM,UAAU,iBAAiB,CAAC,MAAc;IAC9C,2CAA2C;IAC3C,MAAM,CAAC,GAAG,CACR,iBAAiB,EACjB,KAAK,EAAE,GAAyB,EAAE,GAAwB,EAAE,EAAE;QAC5D,MAAM,CAAC,GAAG,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC9B,MAAM,QAAQ,GAAG,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAChC,MAAM,SAAS,GAAG,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAClC,MAAM,KAAK,GAAG,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACvD,MAAM,MAAM,GAAG,SAAS,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAEjE,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC;YACxB,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;YAC1C,MAAM,EAAE,MAAM,IAAI,IAAI,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;SACvE,CAAC,CAAC;QACH,QAAQ,CAAC,GAAG,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IAC7C,CAAC,CACF,CAAC;IAEF,4EAA4E;IAC5E,MAAM,CAAC,GAAG,CACR,wBAAwB,EACxB,KAAK,EAAE,GAAyB,EAAE,GAAwB,EAAE,EAAE;QAC5D,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QAElB,MAAM,KAAK,GAAG,SAAS,CAAC,CAAC,EAAE,EAAE,EAAE;YAC7B,IAAI,CAAC;gBACH,OAAO,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;YACzB,CAAC;YAAC,MAAM,CAAC;gBACP,gDAAgD;YAClD,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,
|
|
1
|
+
{"version":3,"file":"ops.js","sourceRoot":"","sources":["../../../src/studio/routes/ops.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { Router } from "../../eval-server/router.js";
|
|
2
|
-
export declare function registerPromoteRoute(router: Router,
|
|
2
|
+
export declare function registerPromoteRoute(router: Router, rootArg: string | (() => string), home?: string): void;
|
|
@@ -7,15 +7,16 @@
|
|
|
7
7
|
// ---------------------------------------------------------------------------
|
|
8
8
|
import { randomUUID } from "node:crypto";
|
|
9
9
|
import { homedir } from "node:os";
|
|
10
|
-
import { existsSync } from "node:fs";
|
|
11
10
|
import { sendJson } from "../../eval-server/router.js";
|
|
12
11
|
import { initSSE, sendSSE, sendSSEDone } from "../../eval-server/sse-helpers.js";
|
|
13
|
-
import { transfer, CollisionError, MissingSourceError, resolveScopePath, } from "../lib/scope-transfer.js";
|
|
12
|
+
import { transfer, validatePaths, CollisionError, MissingSourceError, resolveScopePath, } from "../lib/scope-transfer.js";
|
|
14
13
|
import { writeProvenance } from "../lib/provenance.js";
|
|
15
14
|
import { appendOp } from "../lib/ops-log.js";
|
|
16
15
|
import { parseQuery } from "../lib/query.js";
|
|
17
|
-
export function registerPromoteRoute(router,
|
|
16
|
+
export function registerPromoteRoute(router, rootArg, home = homedir()) {
|
|
17
|
+
const getRoot = typeof rootArg === "function" ? rootArg : () => rootArg;
|
|
18
18
|
router.post("/api/skills/:plugin/:skill/promote", async (req, res, params) => {
|
|
19
|
+
const root = getRoot();
|
|
19
20
|
const { plugin, skill } = params;
|
|
20
21
|
const query = parseQuery(req.url);
|
|
21
22
|
const overwrite = query.get("overwrite") === "true";
|
|
@@ -26,13 +27,21 @@ export function registerPromoteRoute(router, root, home = homedir()) {
|
|
|
26
27
|
const opId = randomUUID();
|
|
27
28
|
// Pre-validate BEFORE opening the SSE stream so collisions and missing-
|
|
28
29
|
// source errors return clean HTTP status codes (409 / 404) per AC-US1-03.
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
// Single source of truth: validatePaths is the same check transfer()
|
|
31
|
+
// re-runs internally — no double-stat in the happy path.
|
|
32
|
+
try {
|
|
33
|
+
validatePaths(sourcePath, destPath, overwrite);
|
|
32
34
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
35
|
+
catch (err) {
|
|
36
|
+
if (err instanceof MissingSourceError) {
|
|
37
|
+
sendJson(res, { ok: false, code: "missing-source", path: err.path }, 404, req);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
if (err instanceof CollisionError) {
|
|
41
|
+
sendJson(res, { ok: false, code: "collision", path: err.path }, 409, req);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
throw err;
|
|
36
45
|
}
|
|
37
46
|
const emit = (e) => {
|
|
38
47
|
if (!res.headersSent)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"promote.js","sourceRoot":"","sources":["../../../src/studio/routes/promote.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,0DAA0D;AAC1D,8EAA8E;AAC9E,6DAA6D;AAC7D,+DAA+D;AAC/D,mEAAmE;AACnE,8EAA8E;AAG9E,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"promote.js","sourceRoot":"","sources":["../../../src/studio/routes/promote.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { Router } from "../../eval-server/router.js";
|
|
2
|
-
export declare function registerRevertRoute(router: Router,
|
|
2
|
+
export declare function registerRevertRoute(router: Router, rootArg: string | (() => string), home?: string): void;
|