@dotobokuri/fleet-console 1.28.0 → 1.29.0
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/dist/cli.mjs +148 -345
- package/dist/client/assets/{_baseUniq-0TpVlb56.js → _baseUniq-DEvADUqz.js} +1 -1
- package/dist/client/assets/{arc-BIRhKPNZ.js → arc-pB9oYw5d.js} +1 -1
- package/dist/client/assets/{architectureDiagram-Q4EWVU46-CJzkivmk.js → architectureDiagram-Q4EWVU46-D0gUBsh1.js} +1 -1
- package/dist/client/assets/{blockDiagram-DXYQGD6D-PkVBy6UB.js → blockDiagram-DXYQGD6D-9NSt9xrC.js} +1 -1
- package/dist/client/assets/{c4Diagram-AHTNJAMY-TOO0Zc07.js → c4Diagram-AHTNJAMY-BS1EhMAN.js} +1 -1
- package/dist/client/assets/channel-BSgCfWXO.js +1 -0
- package/dist/client/assets/{chunk-4BX2VUAB-Ugm2Ht26.js → chunk-4BX2VUAB-BKkeF7mF.js} +1 -1
- package/dist/client/assets/{chunk-4TB4RGXK-Byfwafb_.js → chunk-4TB4RGXK-DRp3Dsap.js} +1 -1
- package/dist/client/assets/{chunk-55IACEB6-2I_nwtuS.js → chunk-55IACEB6-De-sLT-H.js} +1 -1
- package/dist/client/assets/{chunk-EDXVE4YY-JYP41aJo.js → chunk-EDXVE4YY-ByYWvw6c.js} +1 -1
- package/dist/client/assets/{chunk-FMBD7UC4-Duh-U1jY.js → chunk-FMBD7UC4-BDpIWnNm.js} +1 -1
- package/dist/client/assets/{chunk-OYMX7WX6-64cqkTOO.js → chunk-OYMX7WX6-qxbtvneQ.js} +1 -1
- package/dist/client/assets/{chunk-QZHKN3VN-engflZJB.js → chunk-QZHKN3VN-BnkLN840.js} +1 -1
- package/dist/client/assets/{chunk-YZCP3GAM-BwnK_1vX.js → chunk-YZCP3GAM-HfizEXdz.js} +1 -1
- package/dist/client/assets/classDiagram-6PBFFD2Q-C3WhxxfZ.js +1 -0
- package/dist/client/assets/classDiagram-v2-HSJHXN6E-C3WhxxfZ.js +1 -0
- package/dist/client/assets/clone-DjOK69th.js +1 -0
- package/dist/client/assets/{cose-bilkent-S5V4N54A-D43_BnnE.js → cose-bilkent-S5V4N54A-B4U_tiL9.js} +1 -1
- package/dist/client/assets/{dagre-KV5264BT-Wh_p74YO.js → dagre-KV5264BT-De3dSv-R.js} +1 -1
- package/dist/client/assets/{diagram-5BDNPKRD-BNcxA6wC.js → diagram-5BDNPKRD-CZAF0Kro.js} +1 -1
- package/dist/client/assets/{diagram-G4DWMVQ6-HQdA06kX.js → diagram-G4DWMVQ6-BHyDlHAq.js} +1 -1
- package/dist/client/assets/{diagram-MMDJMWI5-DlMdX_ng.js → diagram-MMDJMWI5-CV93x0hu.js} +1 -1
- package/dist/client/assets/{diagram-TYMM5635-C1hKAjZD.js → diagram-TYMM5635-CTRzVEQp.js} +1 -1
- package/dist/client/assets/{erDiagram-SMLLAGMA-CsSiuv9G.js → erDiagram-SMLLAGMA-xW-UvBlm.js} +1 -1
- package/dist/client/assets/{flowDiagram-DWJPFMVM-DfjQ3Ug9.js → flowDiagram-DWJPFMVM-C21IECUy.js} +1 -1
- package/dist/client/assets/{ganttDiagram-T4ZO3ILL-B0QHKePg.js → ganttDiagram-T4ZO3ILL-DVzOf8Xv.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-UUTBAWPF-_zejoqTH.js → gitGraphDiagram-UUTBAWPF-B-NQC3Ae.js} +1 -1
- package/dist/client/assets/{graph-Dr6IPcji.js → graph-BDzdWbuy.js} +1 -1
- package/dist/client/assets/index-BDJVPQd1.css +1 -0
- package/dist/client/assets/index-CjBu8lNT.js +451 -0
- package/dist/client/assets/{infoDiagram-42DDH7IO-dhruAwPt.js → infoDiagram-42DDH7IO-2KCXFMZg.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-UXIWVN3A-DPoZZiH0.js → ishikawaDiagram-UXIWVN3A-D4Fvy3ms.js} +1 -1
- package/dist/client/assets/{journeyDiagram-VCZTEJTY-DQk8gmrd.js → journeyDiagram-VCZTEJTY-DkXZkeED.js} +1 -1
- package/dist/client/assets/{kanban-definition-6JOO6SKY-B9rOgVFq.js → kanban-definition-6JOO6SKY-CTrIp4rv.js} +1 -1
- package/dist/client/assets/{layout-D54BXsv2.js → layout-DKdT-A2u.js} +1 -1
- package/dist/client/assets/{linear-DJxG7kFF.js → linear-Dn21C3ab.js} +1 -1
- package/dist/client/assets/{mermaid.core-BBFWA-zA.js → mermaid.core-ho7gOyUr.js} +4 -4
- package/dist/client/assets/{min-Dv_aLAYb.js → min-DV-zxfLU.js} +1 -1
- package/dist/client/assets/{mindmap-definition-QFDTVHPH-Dv5woCon.js → mindmap-definition-QFDTVHPH-By8nfvJ0.js} +1 -1
- package/dist/client/assets/{pieDiagram-DEJITSTG-B_V_vCG8.js → pieDiagram-DEJITSTG-B4ndzH1J.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-34T5L4WZ-QHqq3tFD.js → quadrantDiagram-34T5L4WZ-CiDb6b3-.js} +1 -1
- package/dist/client/assets/{requirementDiagram-MS252O5E-BhPhfMzK.js → requirementDiagram-MS252O5E-TTr1SzvX.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-XADWPNL6-D2-ZsaS_.js → sankeyDiagram-XADWPNL6-CUyxk-WA.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-FGHM5R23-Di0qgM3v.js → sequenceDiagram-FGHM5R23-CyBxBNAZ.js} +1 -1
- package/dist/client/assets/{stateDiagram-FHFEXIEX-BAuqrwY8.js → stateDiagram-FHFEXIEX-Cj4j5FFK.js} +1 -1
- package/dist/client/assets/stateDiagram-v2-QKLJ7IA2-CWhJmDZj.js +1 -0
- package/dist/client/assets/{timeline-definition-GMOUNBTQ-BcMGkC6T.js → timeline-definition-GMOUNBTQ-MQzKGbxg.js} +1 -1
- package/dist/client/assets/{vennDiagram-DHZGUBPP-C9dkwyKX.js → vennDiagram-DHZGUBPP-sG3K7NAZ.js} +1 -1
- package/dist/client/assets/{wardley-RL74JXVD-BLLCncPa.js → wardley-RL74JXVD-ID5rQjqH.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-NUSXRM2D-Yb9mlL0_.js → wardleyDiagram-NUSXRM2D-AMajCCI5.js} +1 -1
- package/dist/client/assets/{xychartDiagram-5P7HB3ND-BAHLdje7.js → xychartDiagram-5P7HB3ND-DUb36W9E.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/fleet-plugins/repository/routes.mjs +25 -100
- package/dist/fleet-plugins/skills/routes.mjs +51 -73
- package/dist/fleet-plugins/terminal/routes.mjs +364 -27
- package/package.json +1 -1
- package/dist/client/assets/channel-CqmujVSi.js +0 -1
- package/dist/client/assets/classDiagram-6PBFFD2Q-DLXkYur6.js +0 -1
- package/dist/client/assets/classDiagram-v2-HSJHXN6E-DLXkYur6.js +0 -1
- package/dist/client/assets/clone-KonJWRw9.js +0 -1
- package/dist/client/assets/index-CsmxZ8UQ.js +0 -453
- package/dist/client/assets/index-DC8tBAf_.css +0 -1
- package/dist/client/assets/stateDiagram-v2-QKLJ7IA2-DhNebJyd.js +0 -1
|
@@ -8,12 +8,12 @@ import fs from 'fs/promises';
|
|
|
8
8
|
function definePlugin(definition) {
|
|
9
9
|
return definition;
|
|
10
10
|
}
|
|
11
|
-
function registerRouter(ctx,
|
|
12
|
-
ctx.registerRouter(normalizePath(
|
|
11
|
+
function registerRouter(ctx, path4, handler) {
|
|
12
|
+
ctx.registerRouter(normalizePath(path4), handler);
|
|
13
13
|
}
|
|
14
|
-
function normalizePath(
|
|
15
|
-
if (
|
|
16
|
-
return
|
|
14
|
+
function normalizePath(path4) {
|
|
15
|
+
if (path4.length === 0 || path4 === "/") return "/";
|
|
16
|
+
return path4;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
// ../../packages/core-process/src/hidden.ts
|
|
@@ -154,24 +154,8 @@ function isNoHeadError(error) {
|
|
|
154
154
|
if (error.code !== "non_zero_exit") return false;
|
|
155
155
|
return error.stderr.includes("unknown revision") || error.stderr.includes("bad revision");
|
|
156
156
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
const resolvedSub = path2.resolve(theaterPath, rawSubPath);
|
|
160
|
-
if (!resolvedSub.startsWith(theaterPath + path2.sep) && resolvedSub !== theaterPath) return null;
|
|
161
|
-
if (path2.normalize(rawSubPath).startsWith("..")) return null;
|
|
162
|
-
let realTheater;
|
|
163
|
-
let realSub;
|
|
164
|
-
try {
|
|
165
|
-
[realTheater, realSub] = await Promise.all([
|
|
166
|
-
fs.realpath(theaterPath),
|
|
167
|
-
fs.realpath(resolvedSub)
|
|
168
|
-
]);
|
|
169
|
-
} catch {
|
|
170
|
-
return null;
|
|
171
|
-
}
|
|
172
|
-
const norm = realTheater.endsWith(path2.sep) ? realTheater : realTheater + path2.sep;
|
|
173
|
-
if (realSub !== realTheater && !realSub.startsWith(norm)) return null;
|
|
174
|
-
return { gitCwd: resolvedSub };
|
|
157
|
+
function resolveGitCwd(theaterPath) {
|
|
158
|
+
return { gitCwd: theaterPath };
|
|
175
159
|
}
|
|
176
160
|
async function handleRepositoryChanged(req, res, ctx) {
|
|
177
161
|
if (req.method !== "POST") {
|
|
@@ -183,7 +167,7 @@ async function handleRepositoryChanged(req, res, ctx) {
|
|
|
183
167
|
return;
|
|
184
168
|
}
|
|
185
169
|
const body = await ctx.host.http.readJsonBody(req);
|
|
186
|
-
if (!isPlainObject(body)) {
|
|
170
|
+
if (!isPlainObject(body) || "subPath" in body) {
|
|
187
171
|
ctx.host.http.writeJson(res, 400, { error: "invalid_request" });
|
|
188
172
|
return;
|
|
189
173
|
}
|
|
@@ -197,12 +181,7 @@ async function handleRepositoryChanged(req, res, ctx) {
|
|
|
197
181
|
ctx.host.http.writeJson(res, 404, { error: "theater_not_found" });
|
|
198
182
|
return;
|
|
199
183
|
}
|
|
200
|
-
const
|
|
201
|
-
const cwdResult = await resolveGitCwd(theaterPath, rawSubPath);
|
|
202
|
-
if (!cwdResult) {
|
|
203
|
-
ctx.host.http.writeJson(res, 403, { error: "path_outside_theater" });
|
|
204
|
-
return;
|
|
205
|
-
}
|
|
184
|
+
const cwdResult = resolveGitCwd(theaterPath);
|
|
206
185
|
const { gitCwd } = cwdResult;
|
|
207
186
|
try {
|
|
208
187
|
await ensureGitRepository(gitCwd);
|
|
@@ -252,7 +231,7 @@ async function handleRepositoryFile(req, res, ctx) {
|
|
|
252
231
|
return;
|
|
253
232
|
}
|
|
254
233
|
const body = await ctx.host.http.readJsonBody(req);
|
|
255
|
-
if (!isPlainObject(body) || typeof body.filePath !== "string") {
|
|
234
|
+
if (!isPlainObject(body) || "subPath" in body || typeof body.filePath !== "string") {
|
|
256
235
|
ctx.host.http.writeJson(res, 400, { error: "invalid_request" });
|
|
257
236
|
return;
|
|
258
237
|
}
|
|
@@ -271,12 +250,7 @@ async function handleRepositoryFile(req, res, ctx) {
|
|
|
271
250
|
ctx.host.http.writeJson(res, 404, { error: "theater_not_found" });
|
|
272
251
|
return;
|
|
273
252
|
}
|
|
274
|
-
const
|
|
275
|
-
const cwdResult = await resolveGitCwd(theaterPath, rawSubPath);
|
|
276
|
-
if (!cwdResult) {
|
|
277
|
-
ctx.host.http.writeJson(res, 403, { error: "path_outside_theater" });
|
|
278
|
-
return;
|
|
279
|
-
}
|
|
253
|
+
const cwdResult = resolveGitCwd(theaterPath);
|
|
280
254
|
const { gitCwd } = cwdResult;
|
|
281
255
|
const rawFilePath = body.filePath;
|
|
282
256
|
const resolvedFilePath = path2.resolve(gitCwd, rawFilePath);
|
|
@@ -376,7 +350,7 @@ async function handleRepositoryCommit(req, res, ctx) {
|
|
|
376
350
|
return;
|
|
377
351
|
}
|
|
378
352
|
const body = await ctx.host.http.readJsonBody(req);
|
|
379
|
-
if (!isPlainObject2(body)) {
|
|
353
|
+
if (!isPlainObject2(body) || "subPath" in body) {
|
|
380
354
|
ctx.host.http.writeJson(res, 400, { error: "invalid_request" });
|
|
381
355
|
return;
|
|
382
356
|
}
|
|
@@ -395,12 +369,7 @@ async function handleRepositoryCommit(req, res, ctx) {
|
|
|
395
369
|
ctx.host.http.writeJson(res, 404, { error: "theater_not_found" });
|
|
396
370
|
return;
|
|
397
371
|
}
|
|
398
|
-
const
|
|
399
|
-
const cwdResult = await resolveGitCwd(theaterPath, rawSubPath);
|
|
400
|
-
if (!cwdResult) {
|
|
401
|
-
ctx.host.http.writeJson(res, 403, { error: "path_outside_theater" });
|
|
402
|
-
return;
|
|
403
|
-
}
|
|
372
|
+
const cwdResult = resolveGitCwd(theaterPath);
|
|
404
373
|
const { gitCwd } = cwdResult;
|
|
405
374
|
try {
|
|
406
375
|
const [metaResult, nameStatusResult, numstatResult] = await Promise.all([
|
|
@@ -452,7 +421,7 @@ async function handleRepositoryCommitFile(req, res, ctx) {
|
|
|
452
421
|
return;
|
|
453
422
|
}
|
|
454
423
|
const body = await ctx.host.http.readJsonBody(req);
|
|
455
|
-
if (!isPlainObject3(body) || typeof body.theaterId !== "string" || typeof body.ref !== "string" || typeof body.filePath !== "string") {
|
|
424
|
+
if (!isPlainObject3(body) || "subPath" in body || typeof body.theaterId !== "string" || typeof body.ref !== "string" || typeof body.filePath !== "string") {
|
|
456
425
|
ctx.host.http.writeJson(res, 400, { error: "invalid_request" });
|
|
457
426
|
return;
|
|
458
427
|
}
|
|
@@ -473,11 +442,7 @@ async function handleRepositoryCommitFile(req, res, ctx) {
|
|
|
473
442
|
ctx.host.http.writeJson(res, 404, { error: "theater_not_found" });
|
|
474
443
|
return;
|
|
475
444
|
}
|
|
476
|
-
const cwdResult =
|
|
477
|
-
if (!cwdResult) {
|
|
478
|
-
ctx.host.http.writeJson(res, 403, { error: "path_outside_theater" });
|
|
479
|
-
return;
|
|
480
|
-
}
|
|
445
|
+
const cwdResult = resolveGitCwd(theaterPath);
|
|
481
446
|
const relativePath = resolveLiteralFilePath(cwdResult.gitCwd, body.filePath);
|
|
482
447
|
const oldPath = typeof body.oldPath === "string" ? resolveLiteralFilePath(cwdResult.gitCwd, body.oldPath) : void 0;
|
|
483
448
|
if (!relativePath || body.oldPath !== void 0 && !oldPath) {
|
|
@@ -623,7 +588,7 @@ async function handleRepositoryLog(req, res, ctx) {
|
|
|
623
588
|
return;
|
|
624
589
|
}
|
|
625
590
|
const body = await ctx.host.http.readJsonBody(req);
|
|
626
|
-
if (!isPlainObject4(body)) {
|
|
591
|
+
if (!isPlainObject4(body) || "subPath" in body) {
|
|
627
592
|
ctx.host.http.writeJson(res, 400, { error: "invalid_request" });
|
|
628
593
|
return;
|
|
629
594
|
}
|
|
@@ -637,12 +602,7 @@ async function handleRepositoryLog(req, res, ctx) {
|
|
|
637
602
|
ctx.host.http.writeJson(res, 404, { error: "theater_not_found" });
|
|
638
603
|
return;
|
|
639
604
|
}
|
|
640
|
-
const
|
|
641
|
-
const cwdResult = await resolveGitCwd(theaterPath, rawSubPath);
|
|
642
|
-
if (!cwdResult) {
|
|
643
|
-
ctx.host.http.writeJson(res, 403, { error: "path_outside_theater" });
|
|
644
|
-
return;
|
|
645
|
-
}
|
|
605
|
+
const cwdResult = resolveGitCwd(theaterPath);
|
|
646
606
|
const { gitCwd } = cwdResult;
|
|
647
607
|
const requestedRef = body.ref;
|
|
648
608
|
if (requestedRef !== void 0 && (typeof requestedRef !== "string" || !isCanonicalRepositoryRef(requestedRef))) {
|
|
@@ -690,6 +650,8 @@ async function handleRepositoryLog(req, res, ctx) {
|
|
|
690
650
|
throw error;
|
|
691
651
|
}
|
|
692
652
|
}
|
|
653
|
+
|
|
654
|
+
// ../fleet-plugins/repository/server/refs.ts
|
|
693
655
|
function isObject(value) {
|
|
694
656
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
695
657
|
}
|
|
@@ -702,14 +664,6 @@ function parseRefItems(stdout, current) {
|
|
|
702
664
|
return ref && label ? [{ ref, label, current: ref === current }] : [];
|
|
703
665
|
});
|
|
704
666
|
}
|
|
705
|
-
async function readCurrentWorktreePath2(gitCwd) {
|
|
706
|
-
try {
|
|
707
|
-
return (await runGit(["rev-parse", "--show-toplevel"], { cwd: gitCwd })).stdout.trim();
|
|
708
|
-
} catch (error) {
|
|
709
|
-
if (error instanceof GitExecutorError) return "";
|
|
710
|
-
throw error;
|
|
711
|
-
}
|
|
712
|
-
}
|
|
713
667
|
async function readStashes(gitCwd) {
|
|
714
668
|
try {
|
|
715
669
|
return (await runGit(["stash", "list", "--format=%gd%x00%s"], { cwd: gitCwd })).stdout;
|
|
@@ -718,28 +672,6 @@ async function readStashes(gitCwd) {
|
|
|
718
672
|
throw error;
|
|
719
673
|
}
|
|
720
674
|
}
|
|
721
|
-
async function parseWorktrees(stdout, currentWorktreePath, theaterPath, deps = {}) {
|
|
722
|
-
const records = stdout.split("\n\n").map((record) => record.split("\n"));
|
|
723
|
-
const realpath = deps.realpath ?? fs.realpath;
|
|
724
|
-
const normalizedCurrent = currentWorktreePath ? await realpath(currentWorktreePath).catch(() => currentWorktreePath) : "";
|
|
725
|
-
const realTheaterPath = await realpath(theaterPath).catch(() => null);
|
|
726
|
-
return Promise.all(records.flatMap((record) => {
|
|
727
|
-
const rawPath = record.find((line) => line.startsWith("worktree "))?.slice(9);
|
|
728
|
-
if (!rawPath) return [];
|
|
729
|
-
const branchRef = record.find((line) => line.startsWith("branch "))?.slice(7) ?? null;
|
|
730
|
-
const branch = branchRef?.startsWith("refs/heads/") ? branchRef.slice(11) : null;
|
|
731
|
-
return [{ rawPath, name: path2.basename(rawPath) || "worktree", branch }];
|
|
732
|
-
}).map(async ({ rawPath, ...item }) => {
|
|
733
|
-
const realWorktreePath = await realpath(rawPath).catch(() => null);
|
|
734
|
-
const currentPath = realWorktreePath ?? rawPath;
|
|
735
|
-
const contextRelPath = realTheaterPath !== null && realWorktreePath !== null && isWithinTheater(realWorktreePath, realTheaterPath) ? path2.relative(realTheaterPath, realWorktreePath).split(path2.sep).join("/") : null;
|
|
736
|
-
return { ...item, current: normalizedCurrent !== "" && currentPath === normalizedCurrent, contextRelPath };
|
|
737
|
-
}));
|
|
738
|
-
}
|
|
739
|
-
function isWithinTheater(candidate, theaterPath) {
|
|
740
|
-
const normalizedTheaterPath = theaterPath.endsWith(path2.sep) ? theaterPath : `${theaterPath}${path2.sep}`;
|
|
741
|
-
return candidate === theaterPath || candidate.startsWith(normalizedTheaterPath);
|
|
742
|
-
}
|
|
743
675
|
async function handleRepositoryRefs(req, res, ctx) {
|
|
744
676
|
if (req.method !== "POST") {
|
|
745
677
|
ctx.host.http.writeJson(res, 405, { error: "Method not allowed" });
|
|
@@ -750,7 +682,7 @@ async function handleRepositoryRefs(req, res, ctx) {
|
|
|
750
682
|
return;
|
|
751
683
|
}
|
|
752
684
|
const body = await ctx.host.http.readJsonBody(req);
|
|
753
|
-
if (!isObject(body) || typeof body.theaterId !== "string") {
|
|
685
|
+
if (!isObject(body) || "subPath" in body || typeof body.theaterId !== "string") {
|
|
754
686
|
ctx.host.http.writeJson(res, 400, { error: "invalid_request" });
|
|
755
687
|
return;
|
|
756
688
|
}
|
|
@@ -759,22 +691,16 @@ async function handleRepositoryRefs(req, res, ctx) {
|
|
|
759
691
|
ctx.host.http.writeJson(res, 404, { error: "theater_not_found" });
|
|
760
692
|
return;
|
|
761
693
|
}
|
|
762
|
-
const resolved =
|
|
763
|
-
if (!resolved) {
|
|
764
|
-
ctx.host.http.writeJson(res, 403, { error: "path_outside_theater" });
|
|
765
|
-
return;
|
|
766
|
-
}
|
|
694
|
+
const resolved = resolveGitCwd(theaterPath);
|
|
767
695
|
try {
|
|
768
|
-
const [head, local, remote, tags, stashes
|
|
696
|
+
const [head, local, remote, tags, stashes] = await Promise.all([
|
|
769
697
|
runGit(["symbolic-ref", "--quiet", "HEAD"], { cwd: resolved.gitCwd, allowExitCodes: [1] }),
|
|
770
698
|
runGit(["for-each-ref", "--format=%(refname)%00%(refname:short)", "refs/heads"], { cwd: resolved.gitCwd }),
|
|
771
699
|
runGit(["for-each-ref", "--format=%(refname)%00%(refname:short)", "refs/remotes"], { cwd: resolved.gitCwd }),
|
|
772
700
|
runGit(["for-each-ref", "--format=%(refname)%00%(refname:short)", "refs/tags"], { cwd: resolved.gitCwd }),
|
|
773
|
-
readStashes(resolved.gitCwd)
|
|
774
|
-
runGit(["worktree", "list", "--porcelain"], { cwd: resolved.gitCwd })
|
|
701
|
+
readStashes(resolved.gitCwd)
|
|
775
702
|
]);
|
|
776
703
|
const current = head.stdout.trim();
|
|
777
|
-
const currentWorktreePath = await readCurrentWorktreePath2(resolved.gitCwd);
|
|
778
704
|
ctx.host.http.writeJson(res, 200, {
|
|
779
705
|
branches: parseRefItems(local.stdout, current),
|
|
780
706
|
remotes: parseRefItems(remote.stdout, current),
|
|
@@ -782,12 +708,11 @@ async function handleRepositoryRefs(req, res, ctx) {
|
|
|
782
708
|
stashes: lines(stashes).map((line) => {
|
|
783
709
|
const [name, subject = ""] = line.split("\0");
|
|
784
710
|
return { name, subject };
|
|
785
|
-
})
|
|
786
|
-
worktrees: await parseWorktrees(worktrees.stdout, currentWorktreePath, theaterPath)
|
|
711
|
+
})
|
|
787
712
|
});
|
|
788
713
|
} catch (error) {
|
|
789
714
|
if (error instanceof GitExecutorError && error.code === "no_git_repo") {
|
|
790
|
-
ctx.host.http.writeJson(res, 200, { branches: [], remotes: [], tags: [], stashes: []
|
|
715
|
+
ctx.host.http.writeJson(res, 200, { branches: [], remotes: [], tags: [], stashes: [] });
|
|
791
716
|
return;
|
|
792
717
|
}
|
|
793
718
|
if (error instanceof GitExecutorError && error.code === "git_unavailable") {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import
|
|
2
|
+
import path from 'path';
|
|
3
3
|
import { execFile } from 'child_process';
|
|
4
4
|
import fs4 from 'fs/promises';
|
|
5
5
|
import os2 from 'os';
|
|
@@ -16312,7 +16312,7 @@ function findBinaryPath(command, env, options = {}) {
|
|
|
16312
16312
|
return findOnPath(command, pathValue, pathExts, platform);
|
|
16313
16313
|
}
|
|
16314
16314
|
function wrapWindowsShim(resolved, env, platform) {
|
|
16315
|
-
if (platform !== "win32" || !WINDOWS_SHIM_EXTENSIONS.has(
|
|
16315
|
+
if (platform !== "win32" || !WINDOWS_SHIM_EXTENSIONS.has(path.extname(resolved).toLowerCase())) {
|
|
16316
16316
|
return { bin: resolved, prefixArgs: [] };
|
|
16317
16317
|
}
|
|
16318
16318
|
rejectCmdExpansionSensitiveShim(resolved);
|
|
@@ -16330,13 +16330,13 @@ function forceWindowsArgQuoting(value) {
|
|
|
16330
16330
|
return `${value} `;
|
|
16331
16331
|
}
|
|
16332
16332
|
function findOnPath(bin, pathValue, pathExts, platform) {
|
|
16333
|
-
const pathSeparator = platform === "win32" ? WINDOWS_PATH_SEPARATOR :
|
|
16334
|
-
if (hasPathSeparator(bin, platform) ||
|
|
16333
|
+
const pathSeparator = platform === "win32" ? WINDOWS_PATH_SEPARATOR : path.delimiter;
|
|
16334
|
+
if (hasPathSeparator(bin, platform) || path.isAbsolute(bin)) {
|
|
16335
16335
|
return resolveWithExtensions(bin, pathExts, platform);
|
|
16336
16336
|
}
|
|
16337
16337
|
for (const entry of pathValue.split(pathSeparator)) {
|
|
16338
16338
|
const searchDir = entry.length === 0 ? "." : entry;
|
|
16339
|
-
const candidate = resolveWithExtensions(
|
|
16339
|
+
const candidate = resolveWithExtensions(path.join(searchDir, bin), pathExts, platform);
|
|
16340
16340
|
if (candidate) {
|
|
16341
16341
|
return candidate;
|
|
16342
16342
|
}
|
|
@@ -16344,7 +16344,7 @@ function findOnPath(bin, pathValue, pathExts, platform) {
|
|
|
16344
16344
|
return void 0;
|
|
16345
16345
|
}
|
|
16346
16346
|
function resolveWithExtensions(candidate, pathExts, platform) {
|
|
16347
|
-
if (platform !== "win32" ||
|
|
16347
|
+
if (platform !== "win32" || path.extname(candidate).length > 0) {
|
|
16348
16348
|
return isAccessibleExecutable(candidate, platform) ? candidate : void 0;
|
|
16349
16349
|
}
|
|
16350
16350
|
for (const ext of pathExts) {
|
|
@@ -16704,8 +16704,8 @@ async function ensureCliMjs(cliHome, onBootstrap) {
|
|
|
16704
16704
|
if (_cliMjsPath) return _cliMjsPath;
|
|
16705
16705
|
if (_bootstrapPromise) return _bootstrapPromise;
|
|
16706
16706
|
_bootstrapPromise = (async () => {
|
|
16707
|
-
const mjsPath =
|
|
16708
|
-
const pkgPath =
|
|
16707
|
+
const mjsPath = path.join(cliHome, "node_modules", SKILLS_PACKAGE, "bin", "cli.mjs");
|
|
16708
|
+
const pkgPath = path.join(cliHome, "node_modules", SKILLS_PACKAGE, "package.json");
|
|
16709
16709
|
let needsInstall = true;
|
|
16710
16710
|
try {
|
|
16711
16711
|
const raw = await fs4.readFile(pkgPath, "utf-8");
|
|
@@ -16848,52 +16848,29 @@ var ProjectPathError = class extends Error {
|
|
|
16848
16848
|
this.code = code;
|
|
16849
16849
|
}
|
|
16850
16850
|
};
|
|
16851
|
-
async function resolveProjectCwd(theaterRoot
|
|
16852
|
-
|
|
16853
|
-
throw new ProjectPathError("invalid_rel_path");
|
|
16854
|
-
}
|
|
16855
|
-
const lexicalRoot = path5.resolve(theaterRoot);
|
|
16856
|
-
const lexicalTarget = path5.resolve(lexicalRoot, relPath ?? ".");
|
|
16857
|
-
if (!isContainedBy(lexicalRoot, lexicalTarget)) {
|
|
16858
|
-
throw new ProjectPathError("path_outside_theater");
|
|
16859
|
-
}
|
|
16851
|
+
async function resolveProjectCwd(theaterRoot) {
|
|
16852
|
+
const lexicalRoot = path.resolve(theaterRoot);
|
|
16860
16853
|
let realRoot;
|
|
16861
|
-
let realTarget;
|
|
16862
16854
|
try {
|
|
16863
|
-
|
|
16864
|
-
fs4.realpath(lexicalRoot),
|
|
16865
|
-
fs4.realpath(lexicalTarget)
|
|
16866
|
-
]);
|
|
16855
|
+
realRoot = await fs4.realpath(lexicalRoot);
|
|
16867
16856
|
} catch (error51) {
|
|
16868
16857
|
throw mapFilesystemError(error51);
|
|
16869
16858
|
}
|
|
16870
|
-
if (!isContainedBy(realRoot, realTarget)) {
|
|
16871
|
-
throw new ProjectPathError("path_outside_theater");
|
|
16872
|
-
}
|
|
16873
16859
|
try {
|
|
16874
|
-
if (!(await fs4.stat(
|
|
16875
|
-
throw new ProjectPathError("
|
|
16860
|
+
if (!(await fs4.stat(realRoot)).isDirectory()) {
|
|
16861
|
+
throw new ProjectPathError("invalid_path");
|
|
16876
16862
|
}
|
|
16877
16863
|
} catch (error51) {
|
|
16878
16864
|
if (error51 instanceof ProjectPathError) throw error51;
|
|
16879
16865
|
throw mapFilesystemError(error51);
|
|
16880
16866
|
}
|
|
16881
|
-
return
|
|
16882
|
-
}
|
|
16883
|
-
function isSafeRelativePath(value) {
|
|
16884
|
-
if (!value || value.includes("\0") || path5.isAbsolute(value) || path5.posix.isAbsolute(value) || path5.win32.isAbsolute(value)) {
|
|
16885
|
-
return false;
|
|
16886
|
-
}
|
|
16887
|
-
return value.split(/[\\/]/).every((segment) => segment !== "" && segment !== "." && segment !== "..");
|
|
16888
|
-
}
|
|
16889
|
-
function isContainedBy(root, target) {
|
|
16890
|
-
return target === root || target.startsWith(root.endsWith(path5.sep) ? root : root + path5.sep);
|
|
16867
|
+
return realRoot;
|
|
16891
16868
|
}
|
|
16892
16869
|
function mapFilesystemError(error51) {
|
|
16893
16870
|
const code = error51.code;
|
|
16894
16871
|
if (code === "EACCES" || code === "EPERM") return new ProjectPathError("path_outside_theater");
|
|
16895
16872
|
if (code === "ENOENT" || code === "ENOTDIR") return new ProjectPathError("not_found");
|
|
16896
|
-
return new ProjectPathError("
|
|
16873
|
+
return new ProjectPathError("invalid_path");
|
|
16897
16874
|
}
|
|
16898
16875
|
|
|
16899
16876
|
// ../fleet-plugins/skills/server/registry-search.ts
|
|
@@ -16974,7 +16951,7 @@ var TOKEN_URL_PARAM_RE = /([?&](?:access_?token|token|api_?key|apikey|auth(?:ori
|
|
|
16974
16951
|
async function readSkillSources(cwd) {
|
|
16975
16952
|
const sources = /* @__PURE__ */ new Map();
|
|
16976
16953
|
try {
|
|
16977
|
-
const raw = await fs4.readFile(
|
|
16954
|
+
const raw = await fs4.readFile(path.join(cwd, "skills-lock.json"), "utf-8");
|
|
16978
16955
|
const parsed = JSON.parse(raw);
|
|
16979
16956
|
if (typeof parsed === "object" && parsed !== null) {
|
|
16980
16957
|
for (const [name, entry] of Object.entries(parsed)) {
|
|
@@ -16985,7 +16962,7 @@ async function readSkillSources(cwd) {
|
|
|
16985
16962
|
} catch {
|
|
16986
16963
|
}
|
|
16987
16964
|
try {
|
|
16988
|
-
const raw = await fs4.readFile(
|
|
16965
|
+
const raw = await fs4.readFile(path.join(cwd, ".agents", ".skill-lock.json"), "utf-8");
|
|
16989
16966
|
const parsed = JSON.parse(raw);
|
|
16990
16967
|
if (typeof parsed === "object" && parsed !== null) {
|
|
16991
16968
|
for (const [name, entry] of Object.entries(parsed)) {
|
|
@@ -17011,15 +16988,10 @@ async function runListCommand(args, cwd, executor) {
|
|
|
17011
16988
|
function buildDisplayPath(scope, name) {
|
|
17012
16989
|
return scope === "global" ? `~/.agents/skills/${name}` : `.agents/skills/${name}`;
|
|
17013
16990
|
}
|
|
17014
|
-
function
|
|
17015
|
-
if (value === void 0 || value === null) return null;
|
|
17016
|
-
return typeof value === "string" ? value : void 0;
|
|
17017
|
-
}
|
|
17018
|
-
async function resolveProjectScopeCwd(ctx, theaterId, relPath) {
|
|
16991
|
+
async function resolveProjectScopeCwd(ctx, theaterId) {
|
|
17019
16992
|
if (!theaterId) return null;
|
|
17020
|
-
if (relPath === void 0) throw new ProjectPathError("invalid_rel_path");
|
|
17021
16993
|
const theaterRoot = ctx.host.paths.resolveTheaterPath(theaterId);
|
|
17022
|
-
return theaterRoot ? resolveProjectCwd(theaterRoot
|
|
16994
|
+
return theaterRoot ? resolveProjectCwd(theaterRoot) : null;
|
|
17023
16995
|
}
|
|
17024
16996
|
function writeProjectPathError(res, ctx, error51) {
|
|
17025
16997
|
if (!(error51 instanceof ProjectPathError)) throw error51;
|
|
@@ -17072,12 +17044,15 @@ async function handleList(req, res, ctx, executor) {
|
|
|
17072
17044
|
return;
|
|
17073
17045
|
}
|
|
17074
17046
|
const url2 = new URL(req.url ?? "/", `http://${req.headers.host ?? "localhost"}`);
|
|
17047
|
+
if (url2.searchParams.has("relPath")) {
|
|
17048
|
+
ctx.host.http.writeJson(res, 400, { error: "invalid_argument" });
|
|
17049
|
+
return;
|
|
17050
|
+
}
|
|
17075
17051
|
const theaterId = url2.searchParams.get("theaterId") ?? void 0;
|
|
17076
|
-
const relPath = url2.searchParams.has("relPath") ? url2.searchParams.get("relPath") || null : null;
|
|
17077
17052
|
let projectCwd = null;
|
|
17078
17053
|
if (theaterId) {
|
|
17079
17054
|
try {
|
|
17080
|
-
projectCwd = await resolveProjectScopeCwd(ctx, theaterId
|
|
17055
|
+
projectCwd = await resolveProjectScopeCwd(ctx, theaterId);
|
|
17081
17056
|
} catch (error51) {
|
|
17082
17057
|
writeProjectPathError(res, ctx, error51);
|
|
17083
17058
|
return;
|
|
@@ -17138,6 +17113,10 @@ async function handleSearch(req, res, ctx) {
|
|
|
17138
17113
|
return;
|
|
17139
17114
|
}
|
|
17140
17115
|
const url2 = new URL(req.url ?? "/", `http://${req.headers.host ?? "localhost"}`);
|
|
17116
|
+
if (url2.searchParams.has("relPath")) {
|
|
17117
|
+
ctx.host.http.writeJson(res, 400, { error: "invalid_argument" });
|
|
17118
|
+
return;
|
|
17119
|
+
}
|
|
17141
17120
|
const q = url2.searchParams.get("q") ?? "";
|
|
17142
17121
|
const rawLimit = parseInt(url2.searchParams.get("limit") ?? "10", 10);
|
|
17143
17122
|
const limit = isNaN(rawLimit) ? 10 : rawLimit;
|
|
@@ -17162,13 +17141,12 @@ async function handleInstall(req, res, ctx, executor) {
|
|
|
17162
17141
|
return;
|
|
17163
17142
|
}
|
|
17164
17143
|
const body = await ctx.host.http.readJsonBody(req);
|
|
17165
|
-
if (!isPlainObject2(body)) {
|
|
17144
|
+
if (!isPlainObject2(body) || "relPath" in body) {
|
|
17166
17145
|
ctx.host.http.writeJson(res, 400, { error: "invalid_argument" });
|
|
17167
17146
|
return;
|
|
17168
17147
|
}
|
|
17169
|
-
const { source, skill, scope, agents, theaterId: rawTheaterId
|
|
17148
|
+
const { source, skill, scope, agents, theaterId: rawTheaterId } = body;
|
|
17170
17149
|
const theaterId = typeof rawTheaterId === "string" ? rawTheaterId : void 0;
|
|
17171
|
-
const relPath = parseOptionalRelPath(rawRelPath);
|
|
17172
17150
|
if (!validateSource(source)) {
|
|
17173
17151
|
ctx.host.http.writeJson(res, 400, { error: "invalid_argument" });
|
|
17174
17152
|
return;
|
|
@@ -17194,7 +17172,7 @@ async function handleInstall(req, res, ctx, executor) {
|
|
|
17194
17172
|
let projectCwd = null;
|
|
17195
17173
|
if (scope === "project") {
|
|
17196
17174
|
try {
|
|
17197
|
-
projectCwd = await resolveProjectScopeCwd(ctx, theaterId
|
|
17175
|
+
projectCwd = await resolveProjectScopeCwd(ctx, theaterId);
|
|
17198
17176
|
} catch (error51) {
|
|
17199
17177
|
writeProjectPathError(res, ctx, error51);
|
|
17200
17178
|
return;
|
|
@@ -17226,13 +17204,12 @@ async function handleUpdate(req, res, ctx, executor) {
|
|
|
17226
17204
|
return;
|
|
17227
17205
|
}
|
|
17228
17206
|
const body = await ctx.host.http.readJsonBody(req);
|
|
17229
|
-
if (!isPlainObject2(body)) {
|
|
17207
|
+
if (!isPlainObject2(body) || "relPath" in body) {
|
|
17230
17208
|
ctx.host.http.writeJson(res, 400, { error: "invalid_argument" });
|
|
17231
17209
|
return;
|
|
17232
17210
|
}
|
|
17233
|
-
const { scope, theaterId: rawTheaterId
|
|
17211
|
+
const { scope, theaterId: rawTheaterId } = body;
|
|
17234
17212
|
const theaterId = typeof rawTheaterId === "string" ? rawTheaterId : void 0;
|
|
17235
|
-
const relPath = parseOptionalRelPath(rawRelPath);
|
|
17236
17213
|
if (!validateScope(scope)) {
|
|
17237
17214
|
ctx.host.http.writeJson(res, 400, { error: "invalid_argument" });
|
|
17238
17215
|
return;
|
|
@@ -17240,7 +17217,7 @@ async function handleUpdate(req, res, ctx, executor) {
|
|
|
17240
17217
|
let projectCwd = null;
|
|
17241
17218
|
if (scope === "project") {
|
|
17242
17219
|
try {
|
|
17243
|
-
projectCwd = await resolveProjectScopeCwd(ctx, theaterId
|
|
17220
|
+
projectCwd = await resolveProjectScopeCwd(ctx, theaterId);
|
|
17244
17221
|
} catch (error51) {
|
|
17245
17222
|
writeProjectPathError(res, ctx, error51);
|
|
17246
17223
|
return;
|
|
@@ -17271,6 +17248,10 @@ async function handleGetJob(req, res, ctx) {
|
|
|
17271
17248
|
return;
|
|
17272
17249
|
}
|
|
17273
17250
|
const url2 = new URL(req.url ?? "/", `http://${req.headers.host ?? "localhost"}`);
|
|
17251
|
+
if (url2.searchParams.has("relPath")) {
|
|
17252
|
+
ctx.host.http.writeJson(res, 400, { error: "invalid_argument" });
|
|
17253
|
+
return;
|
|
17254
|
+
}
|
|
17274
17255
|
const jobId = url2.searchParams.get("jobId");
|
|
17275
17256
|
const rawCursor = parseInt(url2.searchParams.get("cursor") ?? "0", 10);
|
|
17276
17257
|
const cursor = isNaN(rawCursor) || rawCursor < 0 ? 0 : rawCursor;
|
|
@@ -17295,13 +17276,12 @@ async function handleRemove(req, res, ctx, executor) {
|
|
|
17295
17276
|
return;
|
|
17296
17277
|
}
|
|
17297
17278
|
const body = await ctx.host.http.readJsonBody(req);
|
|
17298
|
-
if (!isPlainObject2(body)) {
|
|
17279
|
+
if (!isPlainObject2(body) || "relPath" in body) {
|
|
17299
17280
|
ctx.host.http.writeJson(res, 400, { error: "invalid_argument" });
|
|
17300
17281
|
return;
|
|
17301
17282
|
}
|
|
17302
|
-
const { scope, skill, theaterId: rawTheaterId
|
|
17283
|
+
const { scope, skill, theaterId: rawTheaterId } = body;
|
|
17303
17284
|
const theaterId = typeof rawTheaterId === "string" ? rawTheaterId : void 0;
|
|
17304
|
-
const relPath = parseOptionalRelPath(rawRelPath);
|
|
17305
17285
|
if (!validateScope(scope)) {
|
|
17306
17286
|
ctx.host.http.writeJson(res, 400, { error: "invalid_argument" });
|
|
17307
17287
|
return;
|
|
@@ -17313,7 +17293,7 @@ async function handleRemove(req, res, ctx, executor) {
|
|
|
17313
17293
|
let projectCwd = null;
|
|
17314
17294
|
if (scope === "project") {
|
|
17315
17295
|
try {
|
|
17316
|
-
projectCwd = await resolveProjectScopeCwd(ctx, theaterId
|
|
17296
|
+
projectCwd = await resolveProjectScopeCwd(ctx, theaterId);
|
|
17317
17297
|
} catch (error51) {
|
|
17318
17298
|
writeProjectPathError(res, ctx, error51);
|
|
17319
17299
|
return;
|
|
@@ -17345,13 +17325,12 @@ async function handlePreview(req, res, ctx, executor) {
|
|
|
17345
17325
|
return;
|
|
17346
17326
|
}
|
|
17347
17327
|
const body = await ctx.host.http.readJsonBody(req);
|
|
17348
|
-
if (!isPlainObject2(body)) {
|
|
17328
|
+
if (!isPlainObject2(body) || "relPath" in body) {
|
|
17349
17329
|
ctx.host.http.writeJson(res, 400, { error: "invalid_argument" });
|
|
17350
17330
|
return;
|
|
17351
17331
|
}
|
|
17352
|
-
const { source, skill, theaterId: rawTheaterId
|
|
17332
|
+
const { source, skill, theaterId: rawTheaterId } = body;
|
|
17353
17333
|
const theaterId = typeof rawTheaterId === "string" ? rawTheaterId : void 0;
|
|
17354
|
-
const relPath = parseOptionalRelPath(rawRelPath);
|
|
17355
17334
|
if (!validateSource(source)) {
|
|
17356
17335
|
ctx.host.http.writeJson(res, 400, { error: "invalid_argument" });
|
|
17357
17336
|
return;
|
|
@@ -17363,7 +17342,7 @@ async function handlePreview(req, res, ctx, executor) {
|
|
|
17363
17342
|
let cwd = defaultCwd();
|
|
17364
17343
|
if (theaterId) {
|
|
17365
17344
|
try {
|
|
17366
|
-
const projectCwd = await resolveProjectScopeCwd(ctx, theaterId
|
|
17345
|
+
const projectCwd = await resolveProjectScopeCwd(ctx, theaterId);
|
|
17367
17346
|
if (!projectCwd) {
|
|
17368
17347
|
ctx.host.http.writeJson(res, 404, { error: "theater_not_found" });
|
|
17369
17348
|
return;
|
|
@@ -17391,13 +17370,12 @@ async function handleInstalledFile(req, res, ctx, executor) {
|
|
|
17391
17370
|
return;
|
|
17392
17371
|
}
|
|
17393
17372
|
const body = await ctx.host.http.readJsonBody(req);
|
|
17394
|
-
if (!isPlainObject2(body)) {
|
|
17373
|
+
if (!isPlainObject2(body) || "relPath" in body) {
|
|
17395
17374
|
ctx.host.http.writeJson(res, 400, { error: "invalid_argument" });
|
|
17396
17375
|
return;
|
|
17397
17376
|
}
|
|
17398
|
-
const { scope, skill, theaterId: rawTheaterId
|
|
17377
|
+
const { scope, skill, theaterId: rawTheaterId } = body;
|
|
17399
17378
|
const theaterId = typeof rawTheaterId === "string" ? rawTheaterId : void 0;
|
|
17400
|
-
const relPath = parseOptionalRelPath(rawRelPath);
|
|
17401
17379
|
if (!validateScope(scope)) {
|
|
17402
17380
|
ctx.host.http.writeJson(res, 400, { error: "invalid_argument" });
|
|
17403
17381
|
return;
|
|
@@ -17409,7 +17387,7 @@ async function handleInstalledFile(req, res, ctx, executor) {
|
|
|
17409
17387
|
let projectCwd = null;
|
|
17410
17388
|
if (scope === "project") {
|
|
17411
17389
|
try {
|
|
17412
|
-
projectCwd = await resolveProjectScopeCwd(ctx, theaterId
|
|
17390
|
+
projectCwd = await resolveProjectScopeCwd(ctx, theaterId);
|
|
17413
17391
|
} catch (error51) {
|
|
17414
17392
|
writeProjectPathError(res, ctx, error51);
|
|
17415
17393
|
return;
|
|
@@ -17429,7 +17407,7 @@ async function handleInstalledFile(req, res, ctx, executor) {
|
|
|
17429
17407
|
return;
|
|
17430
17408
|
}
|
|
17431
17409
|
const skillRoot = entry.path;
|
|
17432
|
-
const skillMdPath =
|
|
17410
|
+
const skillMdPath = path.join(skillRoot, "SKILL.md");
|
|
17433
17411
|
const [realAllowedRoot, realRoot, realMd] = await Promise.all([
|
|
17434
17412
|
// CLI가 보고한 skillRoot 자체도 신뢰하지 않는다 — scope의 정당한 상위 경계
|
|
17435
17413
|
// (project=theater 루트, global=홈)를 벗어나면 읽지 않는다. `.agents/skills`로
|
|
@@ -17442,11 +17420,11 @@ async function handleInstalledFile(req, res, ctx, executor) {
|
|
|
17442
17420
|
ctx.host.http.writeJson(res, 404, { error: "skill_not_found" });
|
|
17443
17421
|
return;
|
|
17444
17422
|
}
|
|
17445
|
-
if (realRoot !== realAllowedRoot && !realRoot.startsWith(realAllowedRoot +
|
|
17423
|
+
if (realRoot !== realAllowedRoot && !realRoot.startsWith(realAllowedRoot + path.sep)) {
|
|
17446
17424
|
ctx.host.http.writeJson(res, 403, { error: "path_outside_theater" });
|
|
17447
17425
|
return;
|
|
17448
17426
|
}
|
|
17449
|
-
if (realMd !== realRoot && !realMd.startsWith(realRoot +
|
|
17427
|
+
if (realMd !== realRoot && !realMd.startsWith(realRoot + path.sep)) {
|
|
17450
17428
|
ctx.host.http.writeJson(res, 403, { error: "path_outside_theater" });
|
|
17451
17429
|
return;
|
|
17452
17430
|
}
|
|
@@ -17461,7 +17439,7 @@ async function handleInstalledFile(req, res, ctx, executor) {
|
|
|
17461
17439
|
var routes_default = definePlugin({
|
|
17462
17440
|
id: "skills",
|
|
17463
17441
|
register(ctx) {
|
|
17464
|
-
const cliHome =
|
|
17442
|
+
const cliHome = path.join(ctx.host.paths.pluginDataDir("skills"), "cli");
|
|
17465
17443
|
const executor = createDefaultExecutor(cliHome);
|
|
17466
17444
|
registerRouter(ctx, "list", async ({ req, res }) => {
|
|
17467
17445
|
await handleList(req, res, ctx, executor);
|