@dotobokuri/fleet-console 1.22.1 → 1.24.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.
Files changed (69) hide show
  1. package/AGENTS.md +41 -255
  2. package/README.md +8 -0
  3. package/dist/cli.d.ts +11 -1
  4. package/dist/cli.mjs +1866 -515
  5. package/dist/client/assets/{_baseUniq-cap0P4FK.js → _baseUniq-yooYbTgN.js} +1 -1
  6. package/dist/client/assets/{arc-yBqa09aK.js → arc-D4mme5Ts.js} +1 -1
  7. package/dist/client/assets/{architectureDiagram-Q4EWVU46-Bug4qdr-.js → architectureDiagram-Q4EWVU46-BAJOviEX.js} +1 -1
  8. package/dist/client/assets/{blockDiagram-DXYQGD6D-BkiIL2xt.js → blockDiagram-DXYQGD6D-DuObpxQ3.js} +1 -1
  9. package/dist/client/assets/{c4Diagram-AHTNJAMY-DYY200Al.js → c4Diagram-AHTNJAMY-BOT-SD34.js} +1 -1
  10. package/dist/client/assets/channel-TZYyAq1v.js +1 -0
  11. package/dist/client/assets/{chunk-4BX2VUAB-DQKmhVxn.js → chunk-4BX2VUAB-BF_aMTes.js} +1 -1
  12. package/dist/client/assets/{chunk-4TB4RGXK-DHpmA3Zl.js → chunk-4TB4RGXK-M4brBcnD.js} +1 -1
  13. package/dist/client/assets/{chunk-55IACEB6-DeRDuQXE.js → chunk-55IACEB6-CrG-4b2Z.js} +1 -1
  14. package/dist/client/assets/{chunk-EDXVE4YY-CNpnhSJm.js → chunk-EDXVE4YY-BxDSygH1.js} +1 -1
  15. package/dist/client/assets/{chunk-FMBD7UC4-BXGVABL-.js → chunk-FMBD7UC4-Bh7MEX7E.js} +1 -1
  16. package/dist/client/assets/{chunk-OYMX7WX6-WbJs4VwZ.js → chunk-OYMX7WX6-DBnBwxer.js} +1 -1
  17. package/dist/client/assets/{chunk-QZHKN3VN-u3BLl6Sl.js → chunk-QZHKN3VN-bjAogQwW.js} +1 -1
  18. package/dist/client/assets/{chunk-YZCP3GAM-BFESuhuJ.js → chunk-YZCP3GAM-l4FGlk_c.js} +1 -1
  19. package/dist/client/assets/classDiagram-6PBFFD2Q-Dh6hZUl4.js +1 -0
  20. package/dist/client/assets/classDiagram-v2-HSJHXN6E-Dh6hZUl4.js +1 -0
  21. package/dist/client/assets/clone-DgWGnVWH.js +1 -0
  22. package/dist/client/assets/{cose-bilkent-S5V4N54A-rouOsZjT.js → cose-bilkent-S5V4N54A-Bm5QA4zo.js} +1 -1
  23. package/dist/client/assets/{dagre-KV5264BT-QCUeCVpM.js → dagre-KV5264BT-PzXQN-5Q.js} +1 -1
  24. package/dist/client/assets/{diagram-5BDNPKRD-DqerlFb_.js → diagram-5BDNPKRD-KhaAKPtX.js} +1 -1
  25. package/dist/client/assets/{diagram-G4DWMVQ6-BS3a1YGN.js → diagram-G4DWMVQ6-DBbjfiR8.js} +1 -1
  26. package/dist/client/assets/{diagram-MMDJMWI5-BeauTcSV.js → diagram-MMDJMWI5-QWro7PRX.js} +1 -1
  27. package/dist/client/assets/{diagram-TYMM5635-Ci2wLUUE.js → diagram-TYMM5635-B9LqWrbF.js} +1 -1
  28. package/dist/client/assets/{erDiagram-SMLLAGMA-9MnmiKch.js → erDiagram-SMLLAGMA-b0VkMMN4.js} +1 -1
  29. package/dist/client/assets/{flowDiagram-DWJPFMVM-CiV9p5EU.js → flowDiagram-DWJPFMVM-edxBAbe6.js} +1 -1
  30. package/dist/client/assets/{ganttDiagram-T4ZO3ILL-D6oNoENl.js → ganttDiagram-T4ZO3ILL-ks2Gg1_V.js} +1 -1
  31. package/dist/client/assets/{gitGraphDiagram-UUTBAWPF-DESO385F.js → gitGraphDiagram-UUTBAWPF-DymUyYNl.js} +1 -1
  32. package/dist/client/assets/{graph-BZdl-RHy.js → graph-B-B_mqfh.js} +1 -1
  33. package/dist/client/assets/index-BgLzfg-v.css +1 -0
  34. package/dist/client/assets/index-pDnb-q6f.js +380 -0
  35. package/dist/client/assets/{infoDiagram-42DDH7IO-lc8vZnyi.js → infoDiagram-42DDH7IO-B5iLIYAc.js} +1 -1
  36. package/dist/client/assets/{ishikawaDiagram-UXIWVN3A-BfzvQXhn.js → ishikawaDiagram-UXIWVN3A-DnztLLn7.js} +1 -1
  37. package/dist/client/assets/{journeyDiagram-VCZTEJTY-BS_Dr0EV.js → journeyDiagram-VCZTEJTY-BKDRfH1Y.js} +1 -1
  38. package/dist/client/assets/{kanban-definition-6JOO6SKY-Cw7oTQJN.js → kanban-definition-6JOO6SKY-DPB3Phvr.js} +1 -1
  39. package/dist/client/assets/{layout-ChwcDQm8.js → layout-BEeRhYTG.js} +1 -1
  40. package/dist/client/assets/{linear-C7GLbmND.js → linear-QzmfWKSq.js} +1 -1
  41. package/dist/client/assets/{mermaid.core-D9phfpQo.js → mermaid.core-BVka5dgm.js} +4 -4
  42. package/dist/client/assets/{min-p7Whc_Wi.js → min-CfXk9kSN.js} +1 -1
  43. package/dist/client/assets/{mindmap-definition-QFDTVHPH-fl_SJKrw.js → mindmap-definition-QFDTVHPH-tGrGhr6Z.js} +1 -1
  44. package/dist/client/assets/{pieDiagram-DEJITSTG-Btw7ckA5.js → pieDiagram-DEJITSTG-ZRBqRiRK.js} +1 -1
  45. package/dist/client/assets/{quadrantDiagram-34T5L4WZ-DB4iJlTI.js → quadrantDiagram-34T5L4WZ-VCINZgct.js} +1 -1
  46. package/dist/client/assets/{requirementDiagram-MS252O5E-hXwV5Nhy.js → requirementDiagram-MS252O5E-DFLzADh3.js} +1 -1
  47. package/dist/client/assets/{sankeyDiagram-XADWPNL6-DC-fizCk.js → sankeyDiagram-XADWPNL6-BbouN8Ji.js} +1 -1
  48. package/dist/client/assets/{sequenceDiagram-FGHM5R23-RrfrroR5.js → sequenceDiagram-FGHM5R23-B58_LF0R.js} +1 -1
  49. package/dist/client/assets/{stateDiagram-FHFEXIEX-q8FUPV_e.js → stateDiagram-FHFEXIEX-pk-OHHuL.js} +1 -1
  50. package/dist/client/assets/stateDiagram-v2-QKLJ7IA2-xsN122JA.js +1 -0
  51. package/dist/client/assets/{timeline-definition-GMOUNBTQ-tegMd8Od.js → timeline-definition-GMOUNBTQ-4jQdCvaj.js} +1 -1
  52. package/dist/client/assets/{vennDiagram-DHZGUBPP-CXx5oN2X.js → vennDiagram-DHZGUBPP-CUr1fH6N.js} +1 -1
  53. package/dist/client/assets/{wardley-RL74JXVD-CxSJ3P_7.js → wardley-RL74JXVD-D0cfvvNA.js} +1 -1
  54. package/dist/client/assets/{wardleyDiagram-NUSXRM2D-DN1P180Z.js → wardleyDiagram-NUSXRM2D-D0l_Rp_Z.js} +1 -1
  55. package/dist/client/assets/{xychartDiagram-5P7HB3ND-Dcn9ukv5.js → xychartDiagram-5P7HB3ND-BdR8OEuJ.js} +1 -1
  56. package/dist/client/index.html +3 -3
  57. package/dist/desktop-protocol.d.ts +49 -0
  58. package/dist/desktop-protocol.mjs +99 -0
  59. package/dist/fleet-plugins/diff/routes.mjs +124 -225
  60. package/dist/fleet-plugins/skills/routes.mjs +218 -85
  61. package/dist/fleet-plugins/terminal/routes.mjs +573 -536
  62. package/package.json +7 -2
  63. package/dist/client/assets/channel-B3EqY8ya.js +0 -1
  64. package/dist/client/assets/classDiagram-6PBFFD2Q-BekEZLVJ.js +0 -1
  65. package/dist/client/assets/classDiagram-v2-HSJHXN6E-BekEZLVJ.js +0 -1
  66. package/dist/client/assets/clone-CsVi9-Ni.js +0 -1
  67. package/dist/client/assets/index-BKpCMFrm.js +0 -380
  68. package/dist/client/assets/index-cg8Uxys9.css +0 -1
  69. package/dist/client/assets/stateDiagram-v2-QKLJ7IA2-BErzXGq7.js +0 -1
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
- import path from 'path';
2
+ import path5 from 'path';
3
3
  import { execFile } from 'child_process';
4
- import fs3 from 'fs/promises';
4
+ import fs4 from 'fs/promises';
5
5
  import os2 from 'os';
6
6
  import crypto4 from 'crypto';
7
7
  import 'http';
@@ -18,12 +18,12 @@ var __export = (target, all) => {
18
18
  function definePlugin(definition) {
19
19
  return definition;
20
20
  }
21
- function registerRouter(ctx, path7, handler) {
22
- ctx.registerRouter(normalizePath(path7), handler);
21
+ function registerRouter(ctx, path8, handler) {
22
+ ctx.registerRouter(normalizePath(path8), handler);
23
23
  }
24
- function normalizePath(path7) {
25
- if (path7.length === 0 || path7 === "/") return "/";
26
- return path7;
24
+ function normalizePath(path8) {
25
+ if (path8.length === 0 || path8 === "/") return "/";
26
+ return path8;
27
27
  }
28
28
 
29
29
  // ../../node_modules/.pnpm/@agentclientprotocol+sdk@1.2.1_zod@4.4.1/node_modules/@agentclientprotocol/sdk/dist/schema/index.js
@@ -832,10 +832,10 @@ function mergeDefs(...defs) {
832
832
  function cloneDef(schema) {
833
833
  return mergeDefs(schema._zod.def);
834
834
  }
835
- function getElementAtPath(obj, path7) {
836
- if (!path7)
835
+ function getElementAtPath(obj, path8) {
836
+ if (!path8)
837
837
  return obj;
838
- return path7.reduce((acc, key) => acc?.[key], obj);
838
+ return path8.reduce((acc, key) => acc?.[key], obj);
839
839
  }
840
840
  function promiseAllObject(promisesObj) {
841
841
  const keys = Object.keys(promisesObj);
@@ -1244,11 +1244,11 @@ function explicitlyAborted(x, startIndex = 0) {
1244
1244
  }
1245
1245
  return false;
1246
1246
  }
1247
- function prefixIssues(path7, issues) {
1247
+ function prefixIssues(path8, issues) {
1248
1248
  return issues.map((iss) => {
1249
1249
  var _a3;
1250
1250
  (_a3 = iss).path ?? (_a3.path = []);
1251
- iss.path.unshift(path7);
1251
+ iss.path.unshift(path8);
1252
1252
  return iss;
1253
1253
  });
1254
1254
  }
@@ -1395,16 +1395,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
1395
1395
  }
1396
1396
  function formatError(error51, mapper = (issue2) => issue2.message) {
1397
1397
  const fieldErrors = { _errors: [] };
1398
- const processError = (error52, path7 = []) => {
1398
+ const processError = (error52, path8 = []) => {
1399
1399
  for (const issue2 of error52.issues) {
1400
1400
  if (issue2.code === "invalid_union" && issue2.errors.length) {
1401
- issue2.errors.map((issues) => processError({ issues }, [...path7, ...issue2.path]));
1401
+ issue2.errors.map((issues) => processError({ issues }, [...path8, ...issue2.path]));
1402
1402
  } else if (issue2.code === "invalid_key") {
1403
- processError({ issues: issue2.issues }, [...path7, ...issue2.path]);
1403
+ processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
1404
1404
  } else if (issue2.code === "invalid_element") {
1405
- processError({ issues: issue2.issues }, [...path7, ...issue2.path]);
1405
+ processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
1406
1406
  } else {
1407
- const fullpath = [...path7, ...issue2.path];
1407
+ const fullpath = [...path8, ...issue2.path];
1408
1408
  if (fullpath.length === 0) {
1409
1409
  fieldErrors._errors.push(mapper(issue2));
1410
1410
  } else {
@@ -1431,17 +1431,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
1431
1431
  }
1432
1432
  function treeifyError(error51, mapper = (issue2) => issue2.message) {
1433
1433
  const result = { errors: [] };
1434
- const processError = (error52, path7 = []) => {
1434
+ const processError = (error52, path8 = []) => {
1435
1435
  var _a3, _b;
1436
1436
  for (const issue2 of error52.issues) {
1437
1437
  if (issue2.code === "invalid_union" && issue2.errors.length) {
1438
- issue2.errors.map((issues) => processError({ issues }, [...path7, ...issue2.path]));
1438
+ issue2.errors.map((issues) => processError({ issues }, [...path8, ...issue2.path]));
1439
1439
  } else if (issue2.code === "invalid_key") {
1440
- processError({ issues: issue2.issues }, [...path7, ...issue2.path]);
1440
+ processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
1441
1441
  } else if (issue2.code === "invalid_element") {
1442
- processError({ issues: issue2.issues }, [...path7, ...issue2.path]);
1442
+ processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
1443
1443
  } else {
1444
- const fullpath = [...path7, ...issue2.path];
1444
+ const fullpath = [...path8, ...issue2.path];
1445
1445
  if (fullpath.length === 0) {
1446
1446
  result.errors.push(mapper(issue2));
1447
1447
  continue;
@@ -1473,8 +1473,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
1473
1473
  }
1474
1474
  function toDotPath(_path) {
1475
1475
  const segs = [];
1476
- const path7 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
1477
- for (const seg of path7) {
1476
+ const path8 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
1477
+ for (const seg of path8) {
1478
1478
  if (typeof seg === "number")
1479
1479
  segs.push(`[${seg}]`);
1480
1480
  else if (typeof seg === "symbol")
@@ -14138,13 +14138,13 @@ function resolveRef(ref, ctx) {
14138
14138
  if (!ref.startsWith("#")) {
14139
14139
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
14140
14140
  }
14141
- const path7 = ref.slice(1).split("/").filter(Boolean);
14142
- if (path7.length === 0) {
14141
+ const path8 = ref.slice(1).split("/").filter(Boolean);
14142
+ if (path8.length === 0) {
14143
14143
  return ctx.rootSchema;
14144
14144
  }
14145
14145
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
14146
- if (path7[0] === defsKey) {
14147
- const key = path7[1];
14146
+ if (path8[0] === defsKey) {
14147
+ const key = path8[1];
14148
14148
  if (!key || !ctx.defs[key]) {
14149
14149
  throw new Error(`Reference not found: ${ref}`);
14150
14150
  }
@@ -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(path.extname(resolved).toLowerCase())) {
16315
+ if (platform !== "win32" || !WINDOWS_SHIM_EXTENSIONS.has(path5.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 : path.delimiter;
16334
- if (hasPathSeparator(bin, platform) || path.isAbsolute(bin)) {
16333
+ const pathSeparator = platform === "win32" ? WINDOWS_PATH_SEPARATOR : path5.delimiter;
16334
+ if (hasPathSeparator(bin, platform) || path5.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(path.join(searchDir, bin), pathExts, platform);
16339
+ const candidate = resolveWithExtensions(path5.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" || path.extname(candidate).length > 0) {
16347
+ if (platform !== "win32" || path5.extname(candidate).length > 0) {
16348
16348
  return isAccessibleExecutable(candidate, platform) ? candidate : void 0;
16349
16349
  }
16350
16350
  for (const ext of pathExts) {
@@ -16613,9 +16613,6 @@ Object.entries(CLI_BACKENDS).map(([id, backend]) => ({
16613
16613
  protocols: [backend.protocol]
16614
16614
  }));
16615
16615
 
16616
- // ../../packages/core-unified-agent/src/client/UnifiedCodexAgentClient.ts
16617
- process.platform === "win32";
16618
-
16619
16616
  // ../fleet-plugins/skills/server/cli.ts
16620
16617
  var SKILLS_VERSION = "1.5.14";
16621
16618
  var SKILLS_PACKAGE = "skills";
@@ -16666,18 +16663,18 @@ async function ensureCliMjs(cliHome, onBootstrap) {
16666
16663
  if (_cliMjsPath) return _cliMjsPath;
16667
16664
  if (_bootstrapPromise) return _bootstrapPromise;
16668
16665
  _bootstrapPromise = (async () => {
16669
- const mjsPath = path.join(cliHome, "node_modules", SKILLS_PACKAGE, "bin", "cli.mjs");
16670
- const pkgPath = path.join(cliHome, "node_modules", SKILLS_PACKAGE, "package.json");
16666
+ const mjsPath = path5.join(cliHome, "node_modules", SKILLS_PACKAGE, "bin", "cli.mjs");
16667
+ const pkgPath = path5.join(cliHome, "node_modules", SKILLS_PACKAGE, "package.json");
16671
16668
  let needsInstall = true;
16672
16669
  try {
16673
- const raw = await fs3.readFile(pkgPath, "utf-8");
16670
+ const raw = await fs4.readFile(pkgPath, "utf-8");
16674
16671
  const pkg = JSON.parse(raw);
16675
16672
  if (pkg.version === SKILLS_VERSION) needsInstall = false;
16676
16673
  } catch {
16677
16674
  }
16678
16675
  if (needsInstall) {
16679
16676
  onBootstrap?.(WARMUP_LINE);
16680
- await fs3.mkdir(cliHome, { recursive: true });
16677
+ await fs4.mkdir(cliHome, { recursive: true });
16681
16678
  await runNpmInstall(cliHome);
16682
16679
  }
16683
16680
  _cliMjsPath = mjsPath;
@@ -16802,6 +16799,61 @@ function getJobResult(id, cursor) {
16802
16799
  exitCode: job.exitCode
16803
16800
  };
16804
16801
  }
16802
+ var ProjectPathError = class extends Error {
16803
+ code;
16804
+ constructor(code) {
16805
+ super(code);
16806
+ this.name = "ProjectPathError";
16807
+ this.code = code;
16808
+ }
16809
+ };
16810
+ async function resolveProjectCwd(theaterRoot, relPath) {
16811
+ if (relPath !== null && !isSafeRelativePath(relPath)) {
16812
+ throw new ProjectPathError("invalid_rel_path");
16813
+ }
16814
+ const lexicalRoot = path5.resolve(theaterRoot);
16815
+ const lexicalTarget = path5.resolve(lexicalRoot, relPath ?? ".");
16816
+ if (!isContainedBy(lexicalRoot, lexicalTarget)) {
16817
+ throw new ProjectPathError("path_outside_theater");
16818
+ }
16819
+ let realRoot;
16820
+ let realTarget;
16821
+ try {
16822
+ [realRoot, realTarget] = await Promise.all([
16823
+ fs4.realpath(lexicalRoot),
16824
+ fs4.realpath(lexicalTarget)
16825
+ ]);
16826
+ } catch (error51) {
16827
+ throw mapFilesystemError(error51);
16828
+ }
16829
+ if (!isContainedBy(realRoot, realTarget)) {
16830
+ throw new ProjectPathError("path_outside_theater");
16831
+ }
16832
+ try {
16833
+ if (!(await fs4.stat(realTarget)).isDirectory()) {
16834
+ throw new ProjectPathError("invalid_rel_path");
16835
+ }
16836
+ } catch (error51) {
16837
+ if (error51 instanceof ProjectPathError) throw error51;
16838
+ throw mapFilesystemError(error51);
16839
+ }
16840
+ return realTarget;
16841
+ }
16842
+ function isSafeRelativePath(value) {
16843
+ if (!value || value.includes("\0") || path5.isAbsolute(value) || path5.posix.isAbsolute(value) || path5.win32.isAbsolute(value)) {
16844
+ return false;
16845
+ }
16846
+ return value.split(/[\\/]/).every((segment) => segment !== "" && segment !== "." && segment !== "..");
16847
+ }
16848
+ function isContainedBy(root, target) {
16849
+ return target === root || target.startsWith(root.endsWith(path5.sep) ? root : root + path5.sep);
16850
+ }
16851
+ function mapFilesystemError(error51) {
16852
+ const code = error51.code;
16853
+ if (code === "EACCES" || code === "EPERM") return new ProjectPathError("path_outside_theater");
16854
+ if (code === "ENOENT" || code === "ENOTDIR") return new ProjectPathError("not_found");
16855
+ return new ProjectPathError("invalid_rel_path");
16856
+ }
16805
16857
 
16806
16858
  // ../fleet-plugins/skills/server/registry-search.ts
16807
16859
  var DEFAULT_SKILLS_API_URL = "https://skills.sh";
@@ -16876,10 +16928,12 @@ function validateScope(scope) {
16876
16928
  // ../fleet-plugins/skills/server/handlers.ts
16877
16929
  var PREVIEW_TIMEOUT_MS = 3e4;
16878
16930
  var CLI_TIMEOUT_MS = 12e4;
16931
+ var USERINFO_URL_RE = /\b[a-z][a-z0-9+.-]*:\/\/[^\s/@]+@[^\s]+/gi;
16932
+ var TOKEN_URL_PARAM_RE = /([?&](?:access_?token|token|api_?key|apikey|auth(?:orization)?|password|secret|credential)=)[^&#\s]*/gi;
16879
16933
  async function readSkillSources(cwd) {
16880
16934
  const sources = /* @__PURE__ */ new Map();
16881
16935
  try {
16882
- const raw = await fs3.readFile(path.join(cwd, "skills-lock.json"), "utf-8");
16936
+ const raw = await fs4.readFile(path5.join(cwd, "skills-lock.json"), "utf-8");
16883
16937
  const parsed = JSON.parse(raw);
16884
16938
  if (typeof parsed === "object" && parsed !== null) {
16885
16939
  for (const [name, entry] of Object.entries(parsed)) {
@@ -16890,7 +16944,7 @@ async function readSkillSources(cwd) {
16890
16944
  } catch {
16891
16945
  }
16892
16946
  try {
16893
- const raw = await fs3.readFile(path.join(cwd, ".agents", ".skill-lock.json"), "utf-8");
16947
+ const raw = await fs4.readFile(path5.join(cwd, ".agents", ".skill-lock.json"), "utf-8");
16894
16948
  const parsed = JSON.parse(raw);
16895
16949
  if (typeof parsed === "object" && parsed !== null) {
16896
16950
  for (const [name, entry] of Object.entries(parsed)) {
@@ -16916,6 +16970,21 @@ async function runListCommand(args, cwd, executor) {
16916
16970
  function buildDisplayPath(scope, name) {
16917
16971
  return scope === "global" ? `~/.agents/skills/${name}` : `.agents/skills/${name}`;
16918
16972
  }
16973
+ function parseOptionalRelPath(value) {
16974
+ if (value === void 0 || value === null) return null;
16975
+ return typeof value === "string" ? value : void 0;
16976
+ }
16977
+ async function resolveProjectScopeCwd(ctx, theaterId, relPath) {
16978
+ if (!theaterId) return null;
16979
+ if (relPath === void 0) throw new ProjectPathError("invalid_rel_path");
16980
+ const theaterRoot = ctx.host.paths.resolveTheaterPath(theaterId);
16981
+ return theaterRoot ? resolveProjectCwd(theaterRoot, relPath) : null;
16982
+ }
16983
+ function writeProjectPathError(res, ctx, error51) {
16984
+ if (!(error51 instanceof ProjectPathError)) throw error51;
16985
+ const status = error51.code === "path_outside_theater" ? 403 : error51.code === "not_found" ? 404 : 400;
16986
+ ctx.host.http.writeJson(res, status, { error: error51.code });
16987
+ }
16919
16988
  function extractSkillMarkdown(raw) {
16920
16989
  const text = stripAnsi(raw);
16921
16990
  const openTag = "<SKILL.md>";
@@ -16927,13 +16996,28 @@ function extractSkillMarkdown(raw) {
16927
16996
  }
16928
16997
  return text.trim();
16929
16998
  }
16930
- function spawnJobAsync(jobId, args, cwd, executor) {
16999
+ function redactJobOutput(chunk, paths) {
17000
+ let redacted = chunk.replace(USERINFO_URL_RE, "[redacted credential URL]").replace(TOKEN_URL_PARAM_RE, "$1[redacted]");
17001
+ const sensitivePaths = [.../* @__PURE__ */ new Set([paths.cwd, paths.homeDir, paths.pluginDataDir])].filter(Boolean).sort((a, b) => b.length - a.length);
17002
+ for (const sensitivePath of sensitivePaths) {
17003
+ redacted = redacted.replaceAll(sensitivePath, "[redacted path]");
17004
+ }
17005
+ return redacted;
17006
+ }
17007
+ function getJobOutputRedactionPaths(ctx, cwd) {
17008
+ return {
17009
+ cwd,
17010
+ homeDir: os2.homedir(),
17011
+ pluginDataDir: ctx.host.paths.pluginDataDir("skills")
17012
+ };
17013
+ }
17014
+ function spawnJobAsync(jobId, args, cwd, redactionPaths, executor) {
16931
17015
  setImmediate(() => {
16932
17016
  void executor(args, {
16933
17017
  cwd,
16934
17018
  timeout: CLI_TIMEOUT_MS,
16935
- onChunk: (chunk) => appendChunk(jobId, chunk),
16936
- onBootstrap: (line) => appendChunk(jobId, line + "\n")
17019
+ onChunk: (chunk) => appendChunk(jobId, redactJobOutput(chunk, redactionPaths)),
17020
+ onBootstrap: (line) => appendChunk(jobId, redactJobOutput(line + "\n", redactionPaths))
16937
17021
  }).then((result) => finishJob(jobId, result.exitCode)).catch(() => finishJob(jobId, 1));
16938
17022
  });
16939
17023
  }
@@ -16948,13 +17032,26 @@ async function handleList(req, res, ctx, executor) {
16948
17032
  }
16949
17033
  const url2 = new URL(req.url ?? "/", `http://${req.headers.host ?? "localhost"}`);
16950
17034
  const theaterId = url2.searchParams.get("theaterId") ?? void 0;
16951
- const theaterPath = theaterId ? ctx.host.paths.resolveTheaterPath(theaterId) : null;
17035
+ const relPath = url2.searchParams.has("relPath") ? url2.searchParams.get("relPath") || null : null;
17036
+ let projectCwd = null;
17037
+ if (theaterId) {
17038
+ try {
17039
+ projectCwd = await resolveProjectScopeCwd(ctx, theaterId, relPath);
17040
+ } catch (error51) {
17041
+ writeProjectPathError(res, ctx, error51);
17042
+ return;
17043
+ }
17044
+ if (!projectCwd) {
17045
+ ctx.host.http.writeJson(res, 404, { error: "theater_not_found" });
17046
+ return;
17047
+ }
17048
+ }
16952
17049
  try {
16953
- if (theaterPath) {
17050
+ if (projectCwd) {
16954
17051
  const [projectRaw, globalRaw, projectSources, globalSources] = await Promise.all([
16955
- runListCommand(["list", "--json"], theaterPath, executor),
17052
+ runListCommand(["list", "--json"], projectCwd, executor),
16956
17053
  runListCommand(["list", "-g", "--json"], os2.homedir(), executor),
16957
- readSkillSources(theaterPath),
17054
+ readSkillSources(projectCwd),
16958
17055
  readSkillSources(os2.homedir())
16959
17056
  ]);
16960
17057
  const projectSkills = projectRaw.map((entry) => ({
@@ -17028,8 +17125,9 @@ async function handleInstall(req, res, ctx, executor) {
17028
17125
  ctx.host.http.writeJson(res, 400, { error: "invalid_argument" });
17029
17126
  return;
17030
17127
  }
17031
- const { source, skill, scope, agents, theaterId: rawTheaterId } = body;
17128
+ const { source, skill, scope, agents, theaterId: rawTheaterId, relPath: rawRelPath } = body;
17032
17129
  const theaterId = typeof rawTheaterId === "string" ? rawTheaterId : void 0;
17130
+ const relPath = parseOptionalRelPath(rawRelPath);
17033
17131
  if (!validateSource(source)) {
17034
17132
  ctx.host.http.writeJson(res, 400, { error: "invalid_argument" });
17035
17133
  return;
@@ -17052,12 +17150,16 @@ async function handleInstall(req, res, ctx, executor) {
17052
17150
  return;
17053
17151
  }
17054
17152
  }
17055
- const theaterPath = scope === "project" ? theaterId ? ctx.host.paths.resolveTheaterPath(theaterId) : null : null;
17056
- if (scope === "project" && !theaterPath) {
17057
- ctx.host.http.writeJson(res, 404, { error: "theater_not_found" });
17058
- return;
17153
+ let projectCwd = null;
17154
+ if (scope === "project") {
17155
+ try {
17156
+ projectCwd = await resolveProjectScopeCwd(ctx, theaterId, relPath);
17157
+ } catch (error51) {
17158
+ writeProjectPathError(res, ctx, error51);
17159
+ return;
17160
+ }
17059
17161
  }
17060
- const cwd = scope === "global" ? defaultCwd() : theaterPath;
17162
+ const cwd = scope === "global" ? defaultCwd() : projectCwd;
17061
17163
  if (!cwd) {
17062
17164
  ctx.host.http.writeJson(res, 404, { error: "theater_not_found" });
17063
17165
  return;
@@ -17070,7 +17172,7 @@ async function handleInstall(req, res, ctx, executor) {
17070
17172
  const agentArgs = agents.flatMap((a) => ["--agent", a]);
17071
17173
  const scopeFlag = scope === "global" ? ["-g"] : [];
17072
17174
  const args = ["add", source, "-y", "--skill", skill, ...scopeFlag, ...agentArgs];
17073
- spawnJobAsync(jobId, args, cwd, executor);
17175
+ spawnJobAsync(jobId, args, cwd, getJobOutputRedactionPaths(ctx, cwd), executor);
17074
17176
  ctx.host.http.writeJson(res, 202, { jobId });
17075
17177
  }
17076
17178
  async function handleUpdate(req, res, ctx, executor) {
@@ -17087,18 +17189,23 @@ async function handleUpdate(req, res, ctx, executor) {
17087
17189
  ctx.host.http.writeJson(res, 400, { error: "invalid_argument" });
17088
17190
  return;
17089
17191
  }
17090
- const { scope, theaterId: rawTheaterId } = body;
17192
+ const { scope, theaterId: rawTheaterId, relPath: rawRelPath } = body;
17091
17193
  const theaterId = typeof rawTheaterId === "string" ? rawTheaterId : void 0;
17194
+ const relPath = parseOptionalRelPath(rawRelPath);
17092
17195
  if (!validateScope(scope)) {
17093
17196
  ctx.host.http.writeJson(res, 400, { error: "invalid_argument" });
17094
17197
  return;
17095
17198
  }
17096
- const theaterPath = scope === "project" ? theaterId ? ctx.host.paths.resolveTheaterPath(theaterId) : null : null;
17097
- if (scope === "project" && !theaterPath) {
17098
- ctx.host.http.writeJson(res, 404, { error: "theater_not_found" });
17099
- return;
17199
+ let projectCwd = null;
17200
+ if (scope === "project") {
17201
+ try {
17202
+ projectCwd = await resolveProjectScopeCwd(ctx, theaterId, relPath);
17203
+ } catch (error51) {
17204
+ writeProjectPathError(res, ctx, error51);
17205
+ return;
17206
+ }
17100
17207
  }
17101
- const cwd = scope === "global" ? defaultCwd() : theaterPath;
17208
+ const cwd = scope === "global" ? defaultCwd() : projectCwd;
17102
17209
  if (!cwd) {
17103
17210
  ctx.host.http.writeJson(res, 404, { error: "theater_not_found" });
17104
17211
  return;
@@ -17110,7 +17217,7 @@ async function handleUpdate(req, res, ctx, executor) {
17110
17217
  }
17111
17218
  const scopeFlag = scope === "global" ? "-g" : "-p";
17112
17219
  const args = ["update", "-y", scopeFlag];
17113
- spawnJobAsync(jobId, args, cwd, executor);
17220
+ spawnJobAsync(jobId, args, cwd, getJobOutputRedactionPaths(ctx, cwd), executor);
17114
17221
  ctx.host.http.writeJson(res, 202, { jobId });
17115
17222
  }
17116
17223
  async function handleGetJob(req, res, ctx) {
@@ -17151,8 +17258,9 @@ async function handleRemove(req, res, ctx, executor) {
17151
17258
  ctx.host.http.writeJson(res, 400, { error: "invalid_argument" });
17152
17259
  return;
17153
17260
  }
17154
- const { scope, skill, theaterId: rawTheaterId } = body;
17261
+ const { scope, skill, theaterId: rawTheaterId, relPath: rawRelPath } = body;
17155
17262
  const theaterId = typeof rawTheaterId === "string" ? rawTheaterId : void 0;
17263
+ const relPath = parseOptionalRelPath(rawRelPath);
17156
17264
  if (!validateScope(scope)) {
17157
17265
  ctx.host.http.writeJson(res, 400, { error: "invalid_argument" });
17158
17266
  return;
@@ -17161,12 +17269,16 @@ async function handleRemove(req, res, ctx, executor) {
17161
17269
  ctx.host.http.writeJson(res, 400, { error: "invalid_argument" });
17162
17270
  return;
17163
17271
  }
17164
- const theaterPath = scope === "project" ? theaterId ? ctx.host.paths.resolveTheaterPath(theaterId) : null : null;
17165
- if (scope === "project" && !theaterPath) {
17166
- ctx.host.http.writeJson(res, 404, { error: "theater_not_found" });
17167
- return;
17272
+ let projectCwd = null;
17273
+ if (scope === "project") {
17274
+ try {
17275
+ projectCwd = await resolveProjectScopeCwd(ctx, theaterId, relPath);
17276
+ } catch (error51) {
17277
+ writeProjectPathError(res, ctx, error51);
17278
+ return;
17279
+ }
17168
17280
  }
17169
- const cwd = scope === "global" ? defaultCwd() : theaterPath;
17281
+ const cwd = scope === "global" ? defaultCwd() : projectCwd;
17170
17282
  if (!cwd) {
17171
17283
  ctx.host.http.writeJson(res, 404, { error: "theater_not_found" });
17172
17284
  return;
@@ -17196,7 +17308,9 @@ async function handlePreview(req, res, ctx, executor) {
17196
17308
  ctx.host.http.writeJson(res, 400, { error: "invalid_argument" });
17197
17309
  return;
17198
17310
  }
17199
- const { source, skill } = body;
17311
+ const { source, skill, theaterId: rawTheaterId, relPath: rawRelPath } = body;
17312
+ const theaterId = typeof rawTheaterId === "string" ? rawTheaterId : void 0;
17313
+ const relPath = parseOptionalRelPath(rawRelPath);
17200
17314
  if (!validateSource(source)) {
17201
17315
  ctx.host.http.writeJson(res, 400, { error: "invalid_argument" });
17202
17316
  return;
@@ -17205,8 +17319,22 @@ async function handlePreview(req, res, ctx, executor) {
17205
17319
  ctx.host.http.writeJson(res, 400, { error: "invalid_argument" });
17206
17320
  return;
17207
17321
  }
17322
+ let cwd = defaultCwd();
17323
+ if (theaterId) {
17324
+ try {
17325
+ const projectCwd = await resolveProjectScopeCwd(ctx, theaterId, relPath);
17326
+ if (!projectCwd) {
17327
+ ctx.host.http.writeJson(res, 404, { error: "theater_not_found" });
17328
+ return;
17329
+ }
17330
+ cwd = projectCwd;
17331
+ } catch (error51) {
17332
+ writeProjectPathError(res, ctx, error51);
17333
+ return;
17334
+ }
17335
+ }
17208
17336
  try {
17209
- const result = await executor([`use`, `${source}@${skill}`], { cwd: defaultCwd(), timeout: PREVIEW_TIMEOUT_MS });
17337
+ const result = await executor([`use`, `${source}@${skill}`], { cwd, timeout: PREVIEW_TIMEOUT_MS });
17210
17338
  ctx.host.http.writeJson(res, 200, { markdown: extractSkillMarkdown(result.stdout) });
17211
17339
  } catch {
17212
17340
  ctx.host.http.writeJson(res, 502, { error: "preview_failed" });
@@ -17226,8 +17354,9 @@ async function handleInstalledFile(req, res, ctx, executor) {
17226
17354
  ctx.host.http.writeJson(res, 400, { error: "invalid_argument" });
17227
17355
  return;
17228
17356
  }
17229
- const { scope, skill, theaterId: rawTheaterId } = body;
17357
+ const { scope, skill, theaterId: rawTheaterId, relPath: rawRelPath } = body;
17230
17358
  const theaterId = typeof rawTheaterId === "string" ? rawTheaterId : void 0;
17359
+ const relPath = parseOptionalRelPath(rawRelPath);
17231
17360
  if (!validateScope(scope)) {
17232
17361
  ctx.host.http.writeJson(res, 400, { error: "invalid_argument" });
17233
17362
  return;
@@ -17236,12 +17365,16 @@ async function handleInstalledFile(req, res, ctx, executor) {
17236
17365
  ctx.host.http.writeJson(res, 400, { error: "invalid_argument" });
17237
17366
  return;
17238
17367
  }
17239
- const theaterPath = scope === "project" ? theaterId ? ctx.host.paths.resolveTheaterPath(theaterId) : null : null;
17240
- if (scope === "project" && !theaterPath) {
17241
- ctx.host.http.writeJson(res, 404, { error: "theater_not_found" });
17242
- return;
17368
+ let projectCwd = null;
17369
+ if (scope === "project") {
17370
+ try {
17371
+ projectCwd = await resolveProjectScopeCwd(ctx, theaterId, relPath);
17372
+ } catch (error51) {
17373
+ writeProjectPathError(res, ctx, error51);
17374
+ return;
17375
+ }
17243
17376
  }
17244
- const cwd = scope === "global" ? defaultCwd() : theaterPath;
17377
+ const cwd = scope === "global" ? defaultCwd() : projectCwd;
17245
17378
  if (!cwd) {
17246
17379
  ctx.host.http.writeJson(res, 404, { error: "theater_not_found" });
17247
17380
  return;
@@ -17255,28 +17388,28 @@ async function handleInstalledFile(req, res, ctx, executor) {
17255
17388
  return;
17256
17389
  }
17257
17390
  const skillRoot = entry.path;
17258
- const skillMdPath = path.join(skillRoot, "SKILL.md");
17391
+ const skillMdPath = path5.join(skillRoot, "SKILL.md");
17259
17392
  const [realAllowedRoot, realRoot, realMd] = await Promise.all([
17260
17393
  // CLI가 보고한 skillRoot 자체도 신뢰하지 않는다 — scope의 정당한 상위 경계
17261
17394
  // (project=theater 루트, global=홈)를 벗어나면 읽지 않는다. `.agents/skills`로
17262
17395
  // 고정하지 않는 이유: claude 단독 설치는 `.claude/skills` 아래에 놓인다.
17263
- fs3.realpath(cwd),
17264
- fs3.realpath(skillRoot),
17265
- fs3.realpath(skillMdPath).catch(() => null)
17396
+ fs4.realpath(cwd),
17397
+ fs4.realpath(skillRoot),
17398
+ fs4.realpath(skillMdPath).catch(() => null)
17266
17399
  ]);
17267
17400
  if (!realMd) {
17268
17401
  ctx.host.http.writeJson(res, 404, { error: "skill_not_found" });
17269
17402
  return;
17270
17403
  }
17271
- if (realRoot !== realAllowedRoot && !realRoot.startsWith(realAllowedRoot + path.sep)) {
17404
+ if (realRoot !== realAllowedRoot && !realRoot.startsWith(realAllowedRoot + path5.sep)) {
17272
17405
  ctx.host.http.writeJson(res, 403, { error: "path_outside_theater" });
17273
17406
  return;
17274
17407
  }
17275
- if (realMd !== realRoot && !realMd.startsWith(realRoot + path.sep)) {
17408
+ if (realMd !== realRoot && !realMd.startsWith(realRoot + path5.sep)) {
17276
17409
  ctx.host.http.writeJson(res, 403, { error: "path_outside_theater" });
17277
17410
  return;
17278
17411
  }
17279
- const markdown = await fs3.readFile(realMd, "utf-8");
17412
+ const markdown = await fs4.readFile(realMd, "utf-8");
17280
17413
  ctx.host.http.writeJson(res, 200, { markdown });
17281
17414
  } catch {
17282
17415
  ctx.host.http.writeJson(res, 502, { error: "read_failed" });
@@ -17287,7 +17420,7 @@ async function handleInstalledFile(req, res, ctx, executor) {
17287
17420
  var routes_default = definePlugin({
17288
17421
  id: "skills",
17289
17422
  register(ctx) {
17290
- const cliHome = path.join(ctx.host.paths.pluginDataDir("skills"), "cli");
17423
+ const cliHome = path5.join(ctx.host.paths.pluginDataDir("skills"), "cli");
17291
17424
  const executor = createDefaultExecutor(cliHome);
17292
17425
  registerRouter(ctx, "list", async ({ req, res }) => {
17293
17426
  await handleList(req, res, ctx, executor);