@launchsecure/launch-kit 0.0.28 → 0.0.29

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 (23) hide show
  1. package/dist/server/chart-serve.js +3 -1
  2. package/dist/server/cli.js +231 -221
  3. package/dist/server/council-entry.js +0 -0
  4. package/dist/server/course-entry.js +3 -3
  5. package/dist/server/fb-wizard.js +0 -0
  6. package/dist/server/graph-mcp-entry.js +35 -72
  7. package/dist/server/init-entry.js +794 -195
  8. package/package.json +22 -21
  9. package/scaffolds/ls-marketplace/.claude-plugin/marketplace.json +4 -4
  10. package/scaffolds/ls-marketplace/plugins/{ls → kit}/.claude-plugin/plugin.json +1 -10
  11. package/scaffolds/ls-marketplace/plugins/{ls → kit}/commands/activate-beacon.md +2 -2
  12. package/scaffolds/ls-marketplace/plugins/kit/commands/activate-statusline.md +46 -0
  13. package/scaffolds/ls-marketplace/plugins/{ls → kit}/commands/beacon-array.md +3 -3
  14. package/scaffolds/ls-marketplace/plugins/{ls → kit}/commands/beacon-clear.md +2 -2
  15. package/scaffolds/ls-marketplace/plugins/{ls → kit}/commands/beacon-pulse.md +7 -7
  16. package/scaffolds/ls-marketplace/plugins/{ls → kit}/commands/beacon-scan.md +7 -7
  17. package/scaffolds/ls-marketplace/plugins/kit/commands/deactivate-statusline.md +34 -0
  18. package/scaffolds/ls-marketplace/plugins/{ls → kit}/commands/show-mcp-status.md +6 -6
  19. package/scaffolds/ls-marketplace/plugins/{ls → kit}/commands/standup.md +52 -38
  20. package/scaffolds/migrate-safety/scripts/migrate-with-backup.sh +0 -0
  21. package/scaffolds/recall-hook/scripts/ensure-recall.sh +0 -0
  22. package/scaffolds/statusline/statusline-mcp.sh +192 -0
  23. package/scaffolds/statusline/statusline-wrapper.sh +50 -0
@@ -553,8 +553,8 @@ var require_claude_bridge = __commonJS({
553
553
  "../claude-code-web/src/claude-bridge.js"(exports2, module2) {
554
554
  "use strict";
555
555
  var { spawn: spawn4 } = require("node-pty");
556
- var path12 = require("path");
557
- var fs10 = require("fs");
556
+ var path13 = require("path");
557
+ var fs11 = require("fs");
558
558
  var ClaudeBridge = class {
559
559
  constructor() {
560
560
  this.sessions = /* @__PURE__ */ new Map();
@@ -565,14 +565,14 @@ var require_claude_bridge = __commonJS({
565
565
  "/home/ec2-user/.claude/local/claude",
566
566
  "claude",
567
567
  "claude-code",
568
- path12.join(process.env.HOME || "/", ".claude", "local", "claude"),
569
- path12.join(process.env.HOME || "/", ".local", "bin", "claude"),
568
+ path13.join(process.env.HOME || "/", ".claude", "local", "claude"),
569
+ path13.join(process.env.HOME || "/", ".local", "bin", "claude"),
570
570
  "/usr/local/bin/claude",
571
571
  "/usr/bin/claude"
572
572
  ];
573
573
  for (const cmd of possibleCommands) {
574
574
  try {
575
- if (fs10.existsSync(cmd) || this.commandExists(cmd)) {
575
+ if (fs11.existsSync(cmd) || this.commandExists(cmd)) {
576
576
  console.log(`Found Claude command at: ${cmd}`);
577
577
  return cmd;
578
578
  }
@@ -797,8 +797,8 @@ var require_codex_bridge = __commonJS({
797
797
  "../claude-code-web/src/codex-bridge.js"(exports2, module2) {
798
798
  "use strict";
799
799
  var { spawn: spawn4 } = require("node-pty");
800
- var path12 = require("path");
801
- var fs10 = require("fs");
800
+ var path13 = require("path");
801
+ var fs11 = require("fs");
802
802
  var CodexBridge = class {
803
803
  constructor() {
804
804
  this.sessions = /* @__PURE__ */ new Map();
@@ -806,16 +806,16 @@ var require_codex_bridge = __commonJS({
806
806
  }
807
807
  findCodexCommand() {
808
808
  const possibleCommands = [
809
- path12.join(process.env.HOME || "/", ".codex", "local", "codex"),
809
+ path13.join(process.env.HOME || "/", ".codex", "local", "codex"),
810
810
  "codex",
811
811
  "codex-code",
812
- path12.join(process.env.HOME || "/", ".local", "bin", "codex"),
812
+ path13.join(process.env.HOME || "/", ".local", "bin", "codex"),
813
813
  "/usr/local/bin/codex",
814
814
  "/usr/bin/codex"
815
815
  ];
816
816
  for (const cmd of possibleCommands) {
817
817
  try {
818
- if (fs10.existsSync(cmd) || this.commandExists(cmd)) {
818
+ if (fs11.existsSync(cmd) || this.commandExists(cmd)) {
819
819
  console.log(`Found Codex command at: ${cmd}`);
820
820
  return cmd;
821
821
  }
@@ -990,8 +990,8 @@ var require_agent_bridge = __commonJS({
990
990
  "../claude-code-web/src/agent-bridge.js"(exports2, module2) {
991
991
  "use strict";
992
992
  var { spawn: spawn4 } = require("node-pty");
993
- var path12 = require("path");
994
- var fs10 = require("fs");
993
+ var path13 = require("path");
994
+ var fs11 = require("fs");
995
995
  var AgentBridge = class {
996
996
  constructor() {
997
997
  this.sessions = /* @__PURE__ */ new Map();
@@ -999,15 +999,15 @@ var require_agent_bridge = __commonJS({
999
999
  }
1000
1000
  findAgentCommand() {
1001
1001
  const possibleCommands = [
1002
- path12.join(process.env.HOME || "/", ".cursor", "local", "cursor-agent"),
1002
+ path13.join(process.env.HOME || "/", ".cursor", "local", "cursor-agent"),
1003
1003
  "cursor-agent",
1004
- path12.join(process.env.HOME || "/", ".local", "bin", "cursor-agent"),
1004
+ path13.join(process.env.HOME || "/", ".local", "bin", "cursor-agent"),
1005
1005
  "/usr/local/bin/cursor-agent",
1006
1006
  "/usr/bin/cursor-agent"
1007
1007
  ];
1008
1008
  for (const cmd of possibleCommands) {
1009
1009
  try {
1010
- if (fs10.existsSync(cmd) || this.commandExists(cmd)) {
1010
+ if (fs11.existsSync(cmd) || this.commandExists(cmd)) {
1011
1011
  console.log(`Found Agent command at: ${cmd}`);
1012
1012
  return cmd;
1013
1013
  }
@@ -1331,25 +1331,25 @@ var require_script_bridge = __commonJS({
1331
1331
  var require_session_store = __commonJS({
1332
1332
  "../claude-code-web/src/utils/session-store.js"(exports2, module2) {
1333
1333
  "use strict";
1334
- var fs10 = require("fs").promises;
1335
- var path12 = require("path");
1334
+ var fs11 = require("fs").promises;
1335
+ var path13 = require("path");
1336
1336
  var os4 = require("os");
1337
1337
  var SessionStore = class {
1338
1338
  constructor(options = {}) {
1339
- this.storageDir = options.storageDir || path12.join(os4.homedir(), ".claude-code-web");
1340
- this.sessionsFile = path12.join(this.storageDir, "sessions.json");
1339
+ this.storageDir = options.storageDir || path13.join(os4.homedir(), ".claude-code-web");
1340
+ this.sessionsFile = path13.join(this.storageDir, "sessions.json");
1341
1341
  this.initializeStorage();
1342
1342
  }
1343
1343
  async initializeStorage() {
1344
1344
  try {
1345
- await fs10.mkdir(this.storageDir, { recursive: true });
1345
+ await fs11.mkdir(this.storageDir, { recursive: true });
1346
1346
  } catch (error) {
1347
1347
  console.error("Failed to create storage directory:", error);
1348
1348
  }
1349
1349
  }
1350
1350
  async saveSessions(sessions) {
1351
1351
  try {
1352
- await fs10.mkdir(this.storageDir, { recursive: true });
1352
+ await fs11.mkdir(this.storageDir, { recursive: true });
1353
1353
  const sessionsArray = Array.from(sessions.entries()).map(([id, session]) => ({
1354
1354
  id,
1355
1355
  name: session.name || "Unnamed Session",
@@ -1380,9 +1380,9 @@ var require_session_store = __commonJS({
1380
1380
  sessions: sessionsArray
1381
1381
  };
1382
1382
  const tempFile = `${this.sessionsFile}.tmp`;
1383
- await fs10.writeFile(tempFile, JSON.stringify(data, null, 2));
1384
- await fs10.mkdir(this.storageDir, { recursive: true });
1385
- await fs10.rename(tempFile, this.sessionsFile);
1383
+ await fs11.writeFile(tempFile, JSON.stringify(data, null, 2));
1384
+ await fs11.mkdir(this.storageDir, { recursive: true });
1385
+ await fs11.rename(tempFile, this.sessionsFile);
1386
1386
  return true;
1387
1387
  } catch (error) {
1388
1388
  console.error("Failed to save sessions:", error.message);
@@ -1391,8 +1391,8 @@ var require_session_store = __commonJS({
1391
1391
  }
1392
1392
  async loadSessions() {
1393
1393
  try {
1394
- await fs10.access(this.sessionsFile);
1395
- const data = await fs10.readFile(this.sessionsFile, "utf8");
1394
+ await fs11.access(this.sessionsFile);
1395
+ const data = await fs11.readFile(this.sessionsFile, "utf8");
1396
1396
  if (!data || !data.trim()) {
1397
1397
  console.log("Sessions file is empty, starting fresh");
1398
1398
  return /* @__PURE__ */ new Map();
@@ -1403,7 +1403,7 @@ var require_session_store = __commonJS({
1403
1403
  } catch (parseError) {
1404
1404
  console.error("Sessions file is corrupted, starting fresh:", parseError.message);
1405
1405
  try {
1406
- await fs10.rename(this.sessionsFile, `${this.sessionsFile}.corrupted.${Date.now()}`);
1406
+ await fs11.rename(this.sessionsFile, `${this.sessionsFile}.corrupted.${Date.now()}`);
1407
1407
  } catch (renameError) {
1408
1408
  }
1409
1409
  return /* @__PURE__ */ new Map();
@@ -1447,7 +1447,7 @@ var require_session_store = __commonJS({
1447
1447
  }
1448
1448
  async clearOldSessions() {
1449
1449
  try {
1450
- await fs10.unlink(this.sessionsFile);
1450
+ await fs11.unlink(this.sessionsFile);
1451
1451
  console.log("Cleared old sessions");
1452
1452
  return true;
1453
1453
  } catch (error) {
@@ -1459,9 +1459,9 @@ var require_session_store = __commonJS({
1459
1459
  }
1460
1460
  async getSessionMetadata() {
1461
1461
  try {
1462
- await fs10.access(this.sessionsFile);
1463
- const stats = await fs10.stat(this.sessionsFile);
1464
- const data = await fs10.readFile(this.sessionsFile, "utf8");
1462
+ await fs11.access(this.sessionsFile);
1463
+ const stats = await fs11.stat(this.sessionsFile);
1464
+ const data = await fs11.readFile(this.sessionsFile, "utf8");
1465
1465
  const parsed = JSON.parse(data);
1466
1466
  return {
1467
1467
  exists: true,
@@ -1486,13 +1486,13 @@ var require_session_store = __commonJS({
1486
1486
  var require_usage_reader = __commonJS({
1487
1487
  "../claude-code-web/src/usage-reader.js"(exports2, module2) {
1488
1488
  "use strict";
1489
- var fs10 = require("fs").promises;
1490
- var path12 = require("path");
1489
+ var fs11 = require("fs").promises;
1490
+ var path13 = require("path");
1491
1491
  var readline = require("readline");
1492
1492
  var { createReadStream } = require("fs");
1493
1493
  var UsageReader = class {
1494
1494
  constructor(sessionDurationHours = 5) {
1495
- this.claudeProjectsPath = path12.join(process.env.HOME, ".claude", "projects");
1495
+ this.claudeProjectsPath = path13.join(process.env.HOME, ".claude", "projects");
1496
1496
  this.cache = null;
1497
1497
  this.cacheTime = null;
1498
1498
  this.cacheTimeout = 5e3;
@@ -1692,14 +1692,14 @@ var require_usage_reader = __commonJS({
1692
1692
  try {
1693
1693
  const cwd = process.cwd();
1694
1694
  const projectDirName = cwd.replace(/\//g, "-");
1695
- let projectPath = path12.join(this.claudeProjectsPath, projectDirName);
1695
+ let projectPath = path13.join(this.claudeProjectsPath, projectDirName);
1696
1696
  try {
1697
- await fs10.access(projectPath);
1697
+ await fs11.access(projectPath);
1698
1698
  } catch (err2) {
1699
1699
  console.log(`Project directory not found: ${projectPath}`);
1700
1700
  return null;
1701
1701
  }
1702
- const files = await fs10.readdir(projectPath);
1702
+ const files = await fs11.readdir(projectPath);
1703
1703
  const jsonlFiles = files.filter((f) => f.endsWith(".jsonl"));
1704
1704
  if (jsonlFiles.length === 0) {
1705
1705
  return null;
@@ -1707,8 +1707,8 @@ var require_usage_reader = __commonJS({
1707
1707
  let mostRecentFile = null;
1708
1708
  let mostRecentTime = 0;
1709
1709
  for (const file of jsonlFiles) {
1710
- const filePath = path12.join(projectPath, file);
1711
- const stat = await fs10.stat(filePath);
1710
+ const filePath = path13.join(projectPath, file);
1711
+ const stat = await fs11.stat(filePath);
1712
1712
  if (stat.mtime.getTime() > mostRecentTime) {
1713
1713
  mostRecentTime = stat.mtime.getTime();
1714
1714
  mostRecentFile = filePath;
@@ -1723,17 +1723,17 @@ var require_usage_reader = __commonJS({
1723
1723
  async findJsonlFiles(onlyRecent = false) {
1724
1724
  const files = [];
1725
1725
  try {
1726
- const projectDirs = await fs10.readdir(this.claudeProjectsPath);
1726
+ const projectDirs = await fs11.readdir(this.claudeProjectsPath);
1727
1727
  for (const projectDir of projectDirs) {
1728
- const projectPath = path12.join(this.claudeProjectsPath, projectDir);
1729
- const stat = await fs10.stat(projectPath);
1728
+ const projectPath = path13.join(this.claudeProjectsPath, projectDir);
1729
+ const stat = await fs11.stat(projectPath);
1730
1730
  if (stat.isDirectory()) {
1731
- const projectFiles = await fs10.readdir(projectPath);
1731
+ const projectFiles = await fs11.readdir(projectPath);
1732
1732
  const jsonlFiles = projectFiles.filter((f) => f.endsWith(".jsonl"));
1733
1733
  for (const jsonlFile of jsonlFiles) {
1734
- const filePath = path12.join(projectPath, jsonlFile);
1734
+ const filePath = path13.join(projectPath, jsonlFile);
1735
1735
  if (onlyRecent) {
1736
- const fileStat = await fs10.stat(filePath);
1736
+ const fileStat = await fs11.stat(filePath);
1737
1737
  const hoursSinceModified = (Date.now() - fileStat.mtime.getTime()) / (1e3 * 60 * 60);
1738
1738
  if (hoursSinceModified <= 24) {
1739
1739
  files.push(filePath);
@@ -1894,9 +1894,9 @@ var require_usage_reader = __commonJS({
1894
1894
  if (!sessionId) {
1895
1895
  return null;
1896
1896
  }
1897
- const sessionFile = path12.join(this.claudeProjectsPath, path12.basename(process.cwd()).replace(/[^a-zA-Z0-9-]/g, "-"), `${sessionId}.jsonl`);
1897
+ const sessionFile = path13.join(this.claudeProjectsPath, path13.basename(process.cwd()).replace(/[^a-zA-Z0-9-]/g, "-"), `${sessionId}.jsonl`);
1898
1898
  try {
1899
- await fs10.access(sessionFile);
1899
+ await fs11.access(sessionFile);
1900
1900
  } catch (err2) {
1901
1901
  return null;
1902
1902
  }
@@ -2552,7 +2552,7 @@ var require_usage_analytics = __commonJS({
2552
2552
  var require_src = __commonJS({
2553
2553
  "../claude-code-web/src/index.js"(exports2, module2) {
2554
2554
  "use strict";
2555
- var path12 = require("path");
2555
+ var path13 = require("path");
2556
2556
  var WebSocket2 = require("ws");
2557
2557
  var { v4: uuidv4 } = (init_esm_node(), __toCommonJS(esm_node_exports));
2558
2558
  var ClaudeBridge = require_claude_bridge();
@@ -2562,7 +2562,7 @@ var require_src = __commonJS({
2562
2562
  var SessionStore = require_session_store();
2563
2563
  var UsageReader = require_usage_reader();
2564
2564
  var UsageAnalytics = require_usage_analytics();
2565
- var fs10 = require("fs");
2565
+ var fs11 = require("fs");
2566
2566
  function stripAnsi2(str) {
2567
2567
  return str.replace(/\x1b\[[0-9;]*[a-zA-Z]/g, "").replace(/\x1b\][^\x07]*\x07/g, "").replace(/\x1b[()][AB012]/g, "").replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g, "").replace(/\r\n?/g, "\n").trim();
2568
2568
  }
@@ -2637,8 +2637,8 @@ var require_src = __commonJS({
2637
2637
  // ── Path validation ──────────────────────────────────────────────────
2638
2638
  isPathWithinBase(targetPath) {
2639
2639
  try {
2640
- const resolvedTarget = path12.resolve(targetPath);
2641
- const resolvedBase = path12.resolve(this.baseFolder);
2640
+ const resolvedTarget = path13.resolve(targetPath);
2641
+ const resolvedBase = path13.resolve(this.baseFolder);
2642
2642
  return resolvedTarget.startsWith(resolvedBase);
2643
2643
  } catch (error) {
2644
2644
  return false;
@@ -2648,7 +2648,7 @@ var require_src = __commonJS({
2648
2648
  if (!targetPath) {
2649
2649
  return { valid: false, error: "Path is required" };
2650
2650
  }
2651
- const resolvedPath = path12.resolve(targetPath);
2651
+ const resolvedPath = path13.resolve(targetPath);
2652
2652
  if (!this.isPathWithinBase(resolvedPath)) {
2653
2653
  return {
2654
2654
  valid: false,
@@ -2820,14 +2820,14 @@ var require_src = __commonJS({
2820
2820
  return true;
2821
2821
  }
2822
2822
  try {
2823
- const items = fs10.readdirSync(validation.path, { withFileTypes: true });
2823
+ const items = fs11.readdirSync(validation.path, { withFileTypes: true });
2824
2824
  const showHidden = url.searchParams.get("showHidden") === "true";
2825
2825
  const folders = items.filter((item) => item.isDirectory()).filter((item) => !item.name.startsWith(".") || showHidden).map((item) => ({
2826
2826
  name: item.name,
2827
- path: path12.join(validation.path, item.name),
2827
+ path: path13.join(validation.path, item.name),
2828
2828
  isDirectory: true
2829
2829
  })).sort((a, b) => a.name.localeCompare(b.name));
2830
- const parentDir = path12.dirname(validation.path);
2830
+ const parentDir = path13.dirname(validation.path);
2831
2831
  const canGoUp = this.isPathWithinBase(parentDir) && parentDir !== validation.path;
2832
2832
  res.writeHead(200, { "Content-Type": "application/json" });
2833
2833
  res.end(JSON.stringify({
@@ -2855,7 +2855,7 @@ var require_src = __commonJS({
2855
2855
  res.end(JSON.stringify({ error: validation.error }));
2856
2856
  return;
2857
2857
  }
2858
- if (!fs10.existsSync(validation.path) || !fs10.statSync(validation.path).isDirectory()) {
2858
+ if (!fs11.existsSync(validation.path) || !fs11.statSync(validation.path).isDirectory()) {
2859
2859
  res.writeHead(400, { "Content-Type": "application/json" });
2860
2860
  res.end(JSON.stringify({ error: "Not a valid directory" }));
2861
2861
  return;
@@ -2882,7 +2882,7 @@ var require_src = __commonJS({
2882
2882
  res.end(JSON.stringify({ error: validation.error }));
2883
2883
  return;
2884
2884
  }
2885
- if (!fs10.existsSync(validation.path) || !fs10.statSync(validation.path).isDirectory()) {
2885
+ if (!fs11.existsSync(validation.path) || !fs11.statSync(validation.path).isDirectory()) {
2886
2886
  res.writeHead(400, { "Content-Type": "application/json" });
2887
2887
  res.end(JSON.stringify({ error: "Invalid directory path" }));
2888
2888
  return;
@@ -2909,7 +2909,7 @@ var require_src = __commonJS({
2909
2909
  return;
2910
2910
  }
2911
2911
  const basePath = parentPath || this.baseFolder;
2912
- const fullPath = path12.join(basePath, folderName);
2912
+ const fullPath = path13.join(basePath, folderName);
2913
2913
  const parentValidation = this.validatePath(basePath);
2914
2914
  const fullValidation = this.validatePath(fullPath);
2915
2915
  if (!parentValidation.valid || !fullValidation.valid) {
@@ -2917,12 +2917,12 @@ var require_src = __commonJS({
2917
2917
  res.end(JSON.stringify({ message: "Cannot create folder outside the allowed area" }));
2918
2918
  return;
2919
2919
  }
2920
- if (fs10.existsSync(fullValidation.path)) {
2920
+ if (fs11.existsSync(fullValidation.path)) {
2921
2921
  res.writeHead(409, { "Content-Type": "application/json" });
2922
2922
  res.end(JSON.stringify({ message: "Folder already exists" }));
2923
2923
  return;
2924
2924
  }
2925
- fs10.mkdirSync(fullValidation.path, { recursive: true });
2925
+ fs11.mkdirSync(fullValidation.path, { recursive: true });
2926
2926
  res.writeHead(200, { "Content-Type": "application/json" });
2927
2927
  res.end(JSON.stringify({ success: true, path: fullValidation.path }));
2928
2928
  } catch (e) {
@@ -2946,10 +2946,10 @@ var require_src = __commonJS({
2946
2946
  const url = new URL(req.url || "/", `http://localhost`);
2947
2947
  let filePath = url.pathname.replace(/^\/terminal\/?/, "");
2948
2948
  if (!filePath || filePath === "") filePath = "index.html";
2949
- const fullPath = path12.join(__dirname, "public", filePath);
2949
+ const fullPath = path13.join(__dirname, "public", filePath);
2950
2950
  try {
2951
- if (!fs10.existsSync(fullPath)) return false;
2952
- const ext = path12.extname(fullPath);
2951
+ if (!fs11.existsSync(fullPath)) return false;
2952
+ const ext = path13.extname(fullPath);
2953
2953
  const mimeTypes = {
2954
2954
  ".html": "text/html",
2955
2955
  ".js": "application/javascript",
@@ -2960,7 +2960,7 @@ var require_src = __commonJS({
2960
2960
  ".ico": "image/x-icon"
2961
2961
  };
2962
2962
  const mime = mimeTypes[ext] || "application/octet-stream";
2963
- const content = fs10.readFileSync(fullPath);
2963
+ const content = fs11.readFileSync(fullPath);
2964
2964
  res.writeHead(200, { "Content-Type": mime });
2965
2965
  res.end(content);
2966
2966
  return true;
@@ -4553,14 +4553,14 @@ var require_util = __commonJS({
4553
4553
  }
4554
4554
  const port = url.port != null ? url.port : url.protocol === "https:" ? 443 : 80;
4555
4555
  let origin = url.origin != null ? url.origin : `${url.protocol || ""}//${url.hostname || ""}:${port}`;
4556
- let path12 = url.path != null ? url.path : `${url.pathname || ""}${url.search || ""}`;
4556
+ let path13 = url.path != null ? url.path : `${url.pathname || ""}${url.search || ""}`;
4557
4557
  if (origin[origin.length - 1] === "/") {
4558
4558
  origin = origin.slice(0, origin.length - 1);
4559
4559
  }
4560
- if (path12 && path12[0] !== "/") {
4561
- path12 = `/${path12}`;
4560
+ if (path13 && path13[0] !== "/") {
4561
+ path13 = `/${path13}`;
4562
4562
  }
4563
- return new URL(`${origin}${path12}`);
4563
+ return new URL(`${origin}${path13}`);
4564
4564
  }
4565
4565
  if (!isHttpOrHttpsPrefixed(url.origin || url.protocol)) {
4566
4566
  throw new InvalidArgumentError("Invalid URL protocol: the URL must start with `http:` or `https:`.");
@@ -5011,39 +5011,39 @@ var require_diagnostics = __commonJS({
5011
5011
  });
5012
5012
  diagnosticsChannel.channel("undici:client:sendHeaders").subscribe((evt) => {
5013
5013
  const {
5014
- request: { method, path: path12, origin }
5014
+ request: { method, path: path13, origin }
5015
5015
  } = evt;
5016
- debuglog("sending request to %s %s/%s", method, origin, path12);
5016
+ debuglog("sending request to %s %s/%s", method, origin, path13);
5017
5017
  });
5018
5018
  diagnosticsChannel.channel("undici:request:headers").subscribe((evt) => {
5019
5019
  const {
5020
- request: { method, path: path12, origin },
5020
+ request: { method, path: path13, origin },
5021
5021
  response: { statusCode }
5022
5022
  } = evt;
5023
5023
  debuglog(
5024
5024
  "received response to %s %s/%s - HTTP %d",
5025
5025
  method,
5026
5026
  origin,
5027
- path12,
5027
+ path13,
5028
5028
  statusCode
5029
5029
  );
5030
5030
  });
5031
5031
  diagnosticsChannel.channel("undici:request:trailers").subscribe((evt) => {
5032
5032
  const {
5033
- request: { method, path: path12, origin }
5033
+ request: { method, path: path13, origin }
5034
5034
  } = evt;
5035
- debuglog("trailers received from %s %s/%s", method, origin, path12);
5035
+ debuglog("trailers received from %s %s/%s", method, origin, path13);
5036
5036
  });
5037
5037
  diagnosticsChannel.channel("undici:request:error").subscribe((evt) => {
5038
5038
  const {
5039
- request: { method, path: path12, origin },
5039
+ request: { method, path: path13, origin },
5040
5040
  error
5041
5041
  } = evt;
5042
5042
  debuglog(
5043
5043
  "request to %s %s/%s errored - %s",
5044
5044
  method,
5045
5045
  origin,
5046
- path12,
5046
+ path13,
5047
5047
  error.message
5048
5048
  );
5049
5049
  });
@@ -5092,9 +5092,9 @@ var require_diagnostics = __commonJS({
5092
5092
  });
5093
5093
  diagnosticsChannel.channel("undici:client:sendHeaders").subscribe((evt) => {
5094
5094
  const {
5095
- request: { method, path: path12, origin }
5095
+ request: { method, path: path13, origin }
5096
5096
  } = evt;
5097
- debuglog("sending request to %s %s/%s", method, origin, path12);
5097
+ debuglog("sending request to %s %s/%s", method, origin, path13);
5098
5098
  });
5099
5099
  }
5100
5100
  diagnosticsChannel.channel("undici:websocket:open").subscribe((evt) => {
@@ -5157,7 +5157,7 @@ var require_request = __commonJS({
5157
5157
  var kHandler = /* @__PURE__ */ Symbol("handler");
5158
5158
  var Request = class {
5159
5159
  constructor(origin, {
5160
- path: path12,
5160
+ path: path13,
5161
5161
  method,
5162
5162
  body,
5163
5163
  headers,
@@ -5172,11 +5172,11 @@ var require_request = __commonJS({
5172
5172
  expectContinue,
5173
5173
  servername
5174
5174
  }, handler2) {
5175
- if (typeof path12 !== "string") {
5175
+ if (typeof path13 !== "string") {
5176
5176
  throw new InvalidArgumentError("path must be a string");
5177
- } else if (path12[0] !== "/" && !(path12.startsWith("http://") || path12.startsWith("https://")) && method !== "CONNECT") {
5177
+ } else if (path13[0] !== "/" && !(path13.startsWith("http://") || path13.startsWith("https://")) && method !== "CONNECT") {
5178
5178
  throw new InvalidArgumentError("path must be an absolute URL or start with a slash");
5179
- } else if (invalidPathRegex.test(path12)) {
5179
+ } else if (invalidPathRegex.test(path13)) {
5180
5180
  throw new InvalidArgumentError("invalid request path");
5181
5181
  }
5182
5182
  if (typeof method !== "string") {
@@ -5242,7 +5242,7 @@ var require_request = __commonJS({
5242
5242
  this.completed = false;
5243
5243
  this.aborted = false;
5244
5244
  this.upgrade = upgrade || null;
5245
- this.path = query ? buildURL(path12, query) : path12;
5245
+ this.path = query ? buildURL(path13, query) : path13;
5246
5246
  this.origin = origin;
5247
5247
  this.idempotent = idempotent == null ? method === "HEAD" || method === "GET" : idempotent;
5248
5248
  this.blocking = blocking == null ? false : blocking;
@@ -9768,7 +9768,7 @@ var require_client_h1 = __commonJS({
9768
9768
  return method !== "GET" && method !== "HEAD" && method !== "OPTIONS" && method !== "TRACE" && method !== "CONNECT";
9769
9769
  }
9770
9770
  function writeH1(client, request) {
9771
- const { method, path: path12, host, upgrade, blocking, reset } = request;
9771
+ const { method, path: path13, host, upgrade, blocking, reset } = request;
9772
9772
  let { body, headers, contentLength } = request;
9773
9773
  const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH" || method === "QUERY" || method === "PROPFIND" || method === "PROPPATCH";
9774
9774
  if (util.isFormDataLike(body)) {
@@ -9834,7 +9834,7 @@ var require_client_h1 = __commonJS({
9834
9834
  if (blocking) {
9835
9835
  socket[kBlocking] = true;
9836
9836
  }
9837
- let header = `${method} ${path12} HTTP/1.1\r
9837
+ let header = `${method} ${path13} HTTP/1.1\r
9838
9838
  `;
9839
9839
  if (typeof host === "string") {
9840
9840
  header += `host: ${host}\r
@@ -10360,7 +10360,7 @@ var require_client_h2 = __commonJS({
10360
10360
  }
10361
10361
  function writeH2(client, request) {
10362
10362
  const session = client[kHTTP2Session];
10363
- const { method, path: path12, host, upgrade, expectContinue, signal, headers: reqHeaders } = request;
10363
+ const { method, path: path13, host, upgrade, expectContinue, signal, headers: reqHeaders } = request;
10364
10364
  let { body } = request;
10365
10365
  if (upgrade) {
10366
10366
  util.errorRequest(client, request, new Error("Upgrade not supported for H2"));
@@ -10427,7 +10427,7 @@ var require_client_h2 = __commonJS({
10427
10427
  });
10428
10428
  return true;
10429
10429
  }
10430
- headers[HTTP2_HEADER_PATH] = path12;
10430
+ headers[HTTP2_HEADER_PATH] = path13;
10431
10431
  headers[HTTP2_HEADER_SCHEME] = "https";
10432
10432
  const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH";
10433
10433
  if (body && typeof body.read === "function") {
@@ -10780,9 +10780,9 @@ var require_redirect_handler = __commonJS({
10780
10780
  return this.handler.onHeaders(statusCode, headers, resume, statusText);
10781
10781
  }
10782
10782
  const { origin, pathname, search } = util.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin)));
10783
- const path12 = search ? `${pathname}${search}` : pathname;
10783
+ const path13 = search ? `${pathname}${search}` : pathname;
10784
10784
  this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin);
10785
- this.opts.path = path12;
10785
+ this.opts.path = path13;
10786
10786
  this.opts.origin = origin;
10787
10787
  this.opts.maxRedirections = 0;
10788
10788
  this.opts.query = null;
@@ -12017,10 +12017,10 @@ var require_proxy_agent = __commonJS({
12017
12017
  };
12018
12018
  const {
12019
12019
  origin,
12020
- path: path12 = "/",
12020
+ path: path13 = "/",
12021
12021
  headers = {}
12022
12022
  } = opts;
12023
- opts.path = origin + path12;
12023
+ opts.path = origin + path13;
12024
12024
  if (!("host" in headers) && !("Host" in headers)) {
12025
12025
  const { host } = new URL3(origin);
12026
12026
  headers.host = host;
@@ -13941,20 +13941,20 @@ var require_mock_utils = __commonJS({
13941
13941
  }
13942
13942
  return true;
13943
13943
  }
13944
- function safeUrl(path12) {
13945
- if (typeof path12 !== "string") {
13946
- return path12;
13944
+ function safeUrl(path13) {
13945
+ if (typeof path13 !== "string") {
13946
+ return path13;
13947
13947
  }
13948
- const pathSegments = path12.split("?");
13948
+ const pathSegments = path13.split("?");
13949
13949
  if (pathSegments.length !== 2) {
13950
- return path12;
13950
+ return path13;
13951
13951
  }
13952
13952
  const qp = new URLSearchParams(pathSegments.pop());
13953
13953
  qp.sort();
13954
13954
  return [...pathSegments, qp.toString()].join("?");
13955
13955
  }
13956
- function matchKey(mockDispatch2, { path: path12, method, body, headers }) {
13957
- const pathMatch = matchValue(mockDispatch2.path, path12);
13956
+ function matchKey(mockDispatch2, { path: path13, method, body, headers }) {
13957
+ const pathMatch = matchValue(mockDispatch2.path, path13);
13958
13958
  const methodMatch = matchValue(mockDispatch2.method, method);
13959
13959
  const bodyMatch = typeof mockDispatch2.body !== "undefined" ? matchValue(mockDispatch2.body, body) : true;
13960
13960
  const headersMatch = matchHeaders(mockDispatch2, headers);
@@ -13976,7 +13976,7 @@ var require_mock_utils = __commonJS({
13976
13976
  function getMockDispatch(mockDispatches, key) {
13977
13977
  const basePath = key.query ? buildURL(key.path, key.query) : key.path;
13978
13978
  const resolvedPath = typeof basePath === "string" ? safeUrl(basePath) : basePath;
13979
- let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path12 }) => matchValue(safeUrl(path12), resolvedPath));
13979
+ let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path13 }) => matchValue(safeUrl(path13), resolvedPath));
13980
13980
  if (matchedMockDispatches.length === 0) {
13981
13981
  throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`);
13982
13982
  }
@@ -14014,9 +14014,9 @@ var require_mock_utils = __commonJS({
14014
14014
  }
14015
14015
  }
14016
14016
  function buildKey(opts) {
14017
- const { path: path12, method, body, headers, query } = opts;
14017
+ const { path: path13, method, body, headers, query } = opts;
14018
14018
  return {
14019
- path: path12,
14019
+ path: path13,
14020
14020
  method,
14021
14021
  body,
14022
14022
  headers,
@@ -14479,10 +14479,10 @@ var require_pending_interceptors_formatter = __commonJS({
14479
14479
  }
14480
14480
  format(pendingInterceptors) {
14481
14481
  const withPrettyHeaders = pendingInterceptors.map(
14482
- ({ method, path: path12, data: { statusCode }, persist, times, timesInvoked, origin }) => ({
14482
+ ({ method, path: path13, data: { statusCode }, persist, times, timesInvoked, origin }) => ({
14483
14483
  Method: method,
14484
14484
  Origin: origin,
14485
- Path: path12,
14485
+ Path: path13,
14486
14486
  "Status code": statusCode,
14487
14487
  Persistent: persist ? PERSISTENT : NOT_PERSISTENT,
14488
14488
  Invocations: timesInvoked,
@@ -19363,9 +19363,9 @@ var require_util6 = __commonJS({
19363
19363
  }
19364
19364
  }
19365
19365
  }
19366
- function validateCookiePath(path12) {
19367
- for (let i = 0; i < path12.length; ++i) {
19368
- const code = path12.charCodeAt(i);
19366
+ function validateCookiePath(path13) {
19367
+ for (let i = 0; i < path13.length; ++i) {
19368
+ const code = path13.charCodeAt(i);
19369
19369
  if (code < 32 || // exclude CTLs (0-31)
19370
19370
  code === 127 || // DEL
19371
19371
  code === 59) {
@@ -22042,11 +22042,11 @@ var require_undici = __commonJS({
22042
22042
  if (typeof opts.path !== "string") {
22043
22043
  throw new InvalidArgumentError("invalid opts.path");
22044
22044
  }
22045
- let path12 = opts.path;
22045
+ let path13 = opts.path;
22046
22046
  if (!opts.path.startsWith("/")) {
22047
- path12 = `/${path12}`;
22047
+ path13 = `/${path13}`;
22048
22048
  }
22049
- url = new URL(util.parseOrigin(url).origin + path12);
22049
+ url = new URL(util.parseOrigin(url).origin + path13);
22050
22050
  } else {
22051
22051
  if (!opts) {
22052
22052
  opts = typeof url === "object" ? url : {};
@@ -22727,9 +22727,9 @@ function buildEffectsIndex(layerOutputs) {
22727
22727
  return idx;
22728
22728
  }
22729
22729
  function writeEffectsIndex(rootDir, idx) {
22730
- const path12 = (0, import_node_path11.join)(rootDir, LAUNCHSECURE_DIR, "graphs", "effects-index.json");
22731
- atomicWriteFileSync(path12, JSON.stringify(idx, null, 2) + "\n");
22732
- return path12;
22730
+ const path13 = (0, import_node_path11.join)(rootDir, LAUNCHSECURE_DIR, "graphs", "effects-index.json");
22731
+ atomicWriteFileSync(path13, JSON.stringify(idx, null, 2) + "\n");
22732
+ return path13;
22733
22733
  }
22734
22734
  var import_node_path11;
22735
22735
  var init_effects_index = __esm({
@@ -23040,10 +23040,10 @@ async function generateGraph(rootDir, layer) {
23040
23040
  return results;
23041
23041
  }
23042
23042
  function readEffectsIndex(rootDir) {
23043
- const path12 = (0, import_node_path13.join)(rootDir, GRAPHS_DIR2, "effects-index.json");
23044
- if (!(0, import_node_fs11.existsSync)(path12)) return null;
23043
+ const path13 = (0, import_node_path13.join)(rootDir, GRAPHS_DIR2, "effects-index.json");
23044
+ if (!(0, import_node_fs11.existsSync)(path13)) return null;
23045
23045
  try {
23046
- return JSON.parse((0, import_node_fs11.readFileSync)(path12, "utf-8"));
23046
+ return JSON.parse((0, import_node_fs11.readFileSync)(path13, "utf-8"));
23047
23047
  } catch {
23048
23048
  return null;
23049
23049
  }
@@ -24463,6 +24463,18 @@ function initLaunchPodTerminalBridge(httpServer, projectDir) {
24463
24463
  var import_fs = __toESM(require("fs"));
24464
24464
  var import_path2 = __toESM(require("path"));
24465
24465
  var MANAGED_SERVERS = ["launch-pod", "launch-chart"];
24466
+ function mergeMcpEntry(existing, ours) {
24467
+ if (!existing || typeof existing !== "object") return ours;
24468
+ const prev = existing;
24469
+ const merged = { ...prev, ...ours };
24470
+ if (prev.headers || ours.headers) {
24471
+ merged.headers = { ...prev.headers ?? {}, ...ours.headers ?? {} };
24472
+ }
24473
+ if (prev.env || ours.env) {
24474
+ merged.env = { ...prev.env ?? {}, ...ours.env ?? {} };
24475
+ }
24476
+ return merged;
24477
+ }
24466
24478
  var writtenPaths = [];
24467
24479
  function writeMcpConfigs(opts) {
24468
24480
  const { projectDir, token, serverUrl } = opts;
@@ -24524,17 +24536,17 @@ function writeClaudeConfig(projectDir, mcpUrl, token) {
24524
24536
  }
24525
24537
  }
24526
24538
  const servers = existing.mcpServers ?? {};
24527
- servers["launch-pod"] = {
24539
+ servers["launch-pod"] = mergeMcpEntry(servers["launch-pod"], {
24528
24540
  type: "http",
24529
24541
  url: mcpUrl,
24530
24542
  headers: {
24531
24543
  Authorization: `Bearer ${token}`
24532
24544
  }
24533
- };
24534
- servers["launch-chart"] = {
24545
+ });
24546
+ servers["launch-chart"] = mergeMcpEntry(servers["launch-chart"], {
24535
24547
  command: "launch-chart",
24536
24548
  args: []
24537
- };
24549
+ });
24538
24550
  existing.mcpServers = servers;
24539
24551
  import_fs.default.writeFileSync(filePath, JSON.stringify(existing, null, 2) + "\n", { mode: 384 });
24540
24552
  writtenPaths.push(filePath);
@@ -27072,8 +27084,7 @@ function buildAnalyzerMcpConfig() {
27072
27084
  "launch-chart": {
27073
27085
  command: process.execPath,
27074
27086
  // current node binary, guaranteed-resolvable
27075
- args: [graphEntry],
27076
- env: { LAUNCH_CHART_AUTOSERVE: "1" }
27087
+ args: [graphEntry]
27077
27088
  }
27078
27089
  }
27079
27090
  });
@@ -27762,19 +27773,19 @@ var import_node_path3 = require("node:path");
27762
27773
  init_launch_kit_paths();
27763
27774
  var MAX_DEDUPE_SET = 1e3;
27764
27775
  var MAX_PINGS = 200;
27765
- function readJson(path12, fallback) {
27766
- if (!(0, import_node_fs2.existsSync)(path12)) return fallback;
27776
+ function readJson(path13, fallback) {
27777
+ if (!(0, import_node_fs2.existsSync)(path13)) return fallback;
27767
27778
  try {
27768
- return JSON.parse((0, import_node_fs2.readFileSync)(path12, "utf-8"));
27779
+ return JSON.parse((0, import_node_fs2.readFileSync)(path13, "utf-8"));
27769
27780
  } catch {
27770
27781
  return fallback;
27771
27782
  }
27772
27783
  }
27773
- function writeJsonAtomic(path12, value) {
27774
- (0, import_node_fs2.mkdirSync)((0, import_node_path3.dirname)(path12), { recursive: true });
27775
- const tmp = `${path12}.tmp.${process.pid}.${Date.now()}`;
27784
+ function writeJsonAtomic(path13, value) {
27785
+ (0, import_node_fs2.mkdirSync)((0, import_node_path3.dirname)(path13), { recursive: true });
27786
+ const tmp = `${path13}.tmp.${process.pid}.${Date.now()}`;
27776
27787
  (0, import_node_fs2.writeFileSync)(tmp, JSON.stringify(value, null, 2), "utf-8");
27777
- (0, import_node_fs2.renameSync)(tmp, path12);
27788
+ (0, import_node_fs2.renameSync)(tmp, path13);
27778
27789
  }
27779
27790
  var RadarState = class {
27780
27791
  constructor(projectRoot) {
@@ -27907,9 +27918,9 @@ var RadarState = class {
27907
27918
  });
27908
27919
  }
27909
27920
  /** Persist the local path of a successfully-prefetched screenshot. */
27910
- setScreenshotLocalPath(id, path12) {
27921
+ setScreenshotLocalPath(id, path13) {
27911
27922
  return this.mutate(id, (p) => {
27912
- p.context.screenshotLocalPath = path12;
27923
+ p.context.screenshotLocalPath = path13;
27913
27924
  });
27914
27925
  }
27915
27926
  /**
@@ -30926,12 +30937,12 @@ init_launch_kit_paths();
30926
30937
  function loadApiRoutesFromOutput(apiOutput) {
30927
30938
  const routes = [];
30928
30939
  for (const n of apiOutput.nodes) {
30929
- const path12 = n.path;
30930
- if (!path12 || typeof path12 !== "string") continue;
30940
+ const path13 = n.path;
30941
+ if (!path13 || typeof path13 !== "string") continue;
30931
30942
  routes.push({
30932
- path: path12,
30943
+ path: path13,
30933
30944
  nodeId: n.id,
30934
- segments: path12.split("/").filter(Boolean)
30945
+ segments: path13.split("/").filter(Boolean)
30935
30946
  });
30936
30947
  }
30937
30948
  return routes;
@@ -31023,16 +31034,16 @@ function resolveFetchCall(call, apiPathMap, apiRoutes) {
31023
31034
  if (call.isConcat) {
31024
31035
  return { kind: "dynamic", normalizedUrl: raw };
31025
31036
  }
31026
- const { path: path12, hadInterpolation } = normalizeFetchUrl(raw);
31027
- if (!path12.startsWith("/")) {
31028
- return { kind: "unresolved", normalizedUrl: path12 };
31037
+ const { path: path13, hadInterpolation } = normalizeFetchUrl(raw);
31038
+ if (!path13.startsWith("/")) {
31039
+ return { kind: "unresolved", normalizedUrl: path13 };
31029
31040
  }
31030
- const segs = path12.split("/").filter(Boolean);
31041
+ const segs = path13.split("/").filter(Boolean);
31031
31042
  if (hadInterpolation && segs.length > 0 && segs[0].startsWith(":")) {
31032
- return { kind: "dynamic", normalizedUrl: path12 };
31043
+ return { kind: "dynamic", normalizedUrl: path13 };
31033
31044
  }
31034
- const exact = apiPathMap.get(path12);
31035
- if (exact) return { kind: "resolved", nodeId: exact, normalizedUrl: path12 };
31045
+ const exact = apiPathMap.get(path13);
31046
+ if (exact) return { kind: "resolved", nodeId: exact, normalizedUrl: path13 };
31036
31047
  let bestScore = -1;
31037
31048
  let bestId = null;
31038
31049
  for (const r of apiRoutes) {
@@ -31043,21 +31054,21 @@ function resolveFetchCall(call, apiPathMap, apiRoutes) {
31043
31054
  }
31044
31055
  }
31045
31056
  if (bestId && bestScore > 0) {
31046
- return { kind: "resolved", nodeId: bestId, normalizedUrl: path12 };
31057
+ return { kind: "resolved", nodeId: bestId, normalizedUrl: path13 };
31047
31058
  }
31048
- return { kind: "unresolved", normalizedUrl: path12 };
31059
+ return { kind: "unresolved", normalizedUrl: path13 };
31049
31060
  }
31050
31061
  function resolveUrlPath(urlPath, apiPathMap, apiRoutes) {
31051
- const { path: path12, hadInterpolation } = normalizeFetchUrl(urlPath);
31052
- if (!path12.startsWith("/")) {
31053
- return { kind: "unresolved", normalizedUrl: path12 };
31062
+ const { path: path13, hadInterpolation } = normalizeFetchUrl(urlPath);
31063
+ if (!path13.startsWith("/")) {
31064
+ return { kind: "unresolved", normalizedUrl: path13 };
31054
31065
  }
31055
- const segs = path12.split("/").filter(Boolean);
31066
+ const segs = path13.split("/").filter(Boolean);
31056
31067
  if (hadInterpolation && segs.length > 0 && segs[0].startsWith(":")) {
31057
- return { kind: "dynamic", normalizedUrl: path12 };
31068
+ return { kind: "dynamic", normalizedUrl: path13 };
31058
31069
  }
31059
- const exact = apiPathMap.get(path12);
31060
- if (exact) return { kind: "resolved", nodeId: exact, normalizedUrl: path12 };
31070
+ const exact = apiPathMap.get(path13);
31071
+ if (exact) return { kind: "resolved", nodeId: exact, normalizedUrl: path13 };
31061
31072
  let bestScore = -1;
31062
31073
  let bestId = null;
31063
31074
  for (const r of apiRoutes) {
@@ -31068,9 +31079,9 @@ function resolveUrlPath(urlPath, apiPathMap, apiRoutes) {
31068
31079
  }
31069
31080
  }
31070
31081
  if (bestId && bestScore > 0) {
31071
- return { kind: "resolved", nodeId: bestId, normalizedUrl: path12 };
31082
+ return { kind: "resolved", nodeId: bestId, normalizedUrl: path13 };
31072
31083
  }
31073
- return { kind: "unresolved", normalizedUrl: path12 };
31084
+ return { kind: "unresolved", normalizedUrl: path13 };
31074
31085
  }
31075
31086
 
31076
31087
  // src/server/graph/parsers/crosslayer/fetch-resolver.ts
@@ -32048,9 +32059,9 @@ function collectTargets(apiOutput, uiOutput) {
32048
32059
  const out = [];
32049
32060
  for (const n of apiOutput?.nodes ?? []) {
32050
32061
  if (n.type !== "endpoint") continue;
32051
- const path12 = n.path;
32052
- if (typeof path12 !== "string" || !path12) continue;
32053
- out.push({ id: n.id, route: path12, layer: "api" });
32062
+ const path13 = n.path;
32063
+ if (typeof path13 !== "string" || !path13) continue;
32064
+ out.push({ id: n.id, route: path13, layer: "api" });
32054
32065
  }
32055
32066
  for (const n of uiOutput?.nodes ?? []) {
32056
32067
  if (n.type !== "page") continue;
@@ -34341,8 +34352,7 @@ function handleStartChartServer(args) {
34341
34352
  const portArgs = args.port ? ["--port", String(args.port)] : [];
34342
34353
  const child = (0, import_node_child_process3.spawn)(process.execPath, [entryPath, "serve", ...portArgs], {
34343
34354
  detached: true,
34344
- stdio: ["ignore", out, err2],
34345
- env: { ...process.env, LAUNCH_CHART_AUTOSERVE: "" }
34355
+ stdio: ["ignore", out, err2]
34346
34356
  });
34347
34357
  child.unref();
34348
34358
  return okJson({
@@ -34677,6 +34687,53 @@ function startGraphMcpServer() {
34677
34687
 
34678
34688
  // src/server/cli.ts
34679
34689
  init_launch_kit_paths();
34690
+
34691
+ // src/server/cred-shape.ts
34692
+ var fs9 = __toESM(require("node:fs"));
34693
+ var path11 = __toESM(require("node:path"));
34694
+ var CONFIG_FILENAME = ".launch-secure.cred.config";
34695
+ function inferCourseName(serverUrl) {
34696
+ try {
34697
+ const host = new URL(serverUrl).hostname.toLowerCase();
34698
+ if (host === "localhost" || host === "127.0.0.1" || host.endsWith(".local")) return "local";
34699
+ if (host.includes("staging")) return "staging";
34700
+ if (host.endsWith(".vercel.app")) return "prod";
34701
+ return host.split(".")[0] || "default";
34702
+ } catch {
34703
+ return "default";
34704
+ }
34705
+ }
34706
+ function toNested(cred) {
34707
+ if (cred.profiles && cred.active && cred.profiles[cred.active]) {
34708
+ return { active: cred.active, profiles: cred.profiles };
34709
+ }
34710
+ if (!cred.pat || !cred.orgSlug || !cred.projectSlug || !cred.serverUrl) {
34711
+ return null;
34712
+ }
34713
+ const name = inferCourseName(cred.serverUrl);
34714
+ return {
34715
+ active: name,
34716
+ profiles: {
34717
+ [name]: {
34718
+ pat: cred.pat,
34719
+ orgSlug: cred.orgSlug,
34720
+ projectSlug: cred.projectSlug,
34721
+ serverUrl: cred.serverUrl
34722
+ }
34723
+ }
34724
+ };
34725
+ }
34726
+ function readCredFile(repoRoot) {
34727
+ const p = path11.join(repoRoot, CONFIG_FILENAME);
34728
+ if (!fs9.existsSync(p)) return null;
34729
+ try {
34730
+ return JSON.parse(fs9.readFileSync(p, "utf-8"));
34731
+ } catch (err2) {
34732
+ throw new Error(`could not parse ${CONFIG_FILENAME}: ${err2 instanceof Error ? err2.message : String(err2)}`);
34733
+ }
34734
+ }
34735
+
34736
+ // src/server/cli.ts
34680
34737
  var DEFAULT_CAPABILITIES = {
34681
34738
  workspace_setup: true,
34682
34739
  terminal: true
@@ -35290,7 +35347,7 @@ if (parsedArgs.subcommand === "graph:generate" || parsedArgs.subcommand === "gra
35290
35347
  const result = (0, import_child_process4.spawnSync)(
35291
35348
  process.execPath,
35292
35349
  [chartEntry, chartSubcommand, ...process.argv.slice(3)],
35293
- { stdio: "inherit", env: { ...process.env, LAUNCH_CHART_AUTOSERVE: "" } }
35350
+ { stdio: "inherit" }
35294
35351
  );
35295
35352
  process.exit(result.status ?? 1);
35296
35353
  }
@@ -35300,75 +35357,28 @@ if (parsedArgs.subcommand === "mcp:graph") {
35300
35357
  var __isMcpMode = parsedArgs.subcommand === "mcp:graph";
35301
35358
  var __isRadarMode = parsedArgs.subcommand === "radar";
35302
35359
  var radar = null;
35303
- var CRED_CONFIG_FILENAME = ".launch-secure.cred.config";
35304
- var LEGACY_CRED_CONFIG_FILENAME = ".launch-secure.config";
35305
- function migrateLegacyCredConfig(repoRoot) {
35306
- const legacy = import_path9.default.join(repoRoot, LEGACY_CRED_CONFIG_FILENAME);
35307
- const dest = import_path9.default.join(repoRoot, CRED_CONFIG_FILENAME);
35308
- if (!import_fs8.default.existsSync(legacy) || import_fs8.default.existsSync(dest)) return;
35309
- let parsed;
35310
- try {
35311
- parsed = JSON.parse(import_fs8.default.readFileSync(legacy, "utf-8"));
35312
- } catch {
35313
- return;
35314
- }
35315
- const pat = parsed?.pat;
35316
- if (typeof pat !== "string" || !pat.startsWith("ls_pat_")) return;
35317
- import_fs8.default.renameSync(legacy, dest);
35318
- console.warn(`[launchpod] migrated legacy ${LEGACY_CRED_CONFIG_FILENAME} \u2192 ${CRED_CONFIG_FILENAME} (the old name is now reserved for file-backed-config)`);
35319
- }
35320
35360
  function readLaunchSecureMcpConfig() {
35321
- migrateLegacyCredConfig(REPO_ROOT);
35322
- const configPath = import_path9.default.join(REPO_ROOT, CRED_CONFIG_FILENAME);
35323
- if (import_fs8.default.existsSync(configPath)) {
35324
- let parsed;
35325
- try {
35326
- parsed = JSON.parse(import_fs8.default.readFileSync(configPath, "utf-8"));
35327
- } catch (err2) {
35328
- throw new Error(`Could not parse ${configPath}: ${err2 instanceof Error ? err2.message : String(err2)}`);
35329
- }
35330
- const block = parsed.profiles && parsed.active ? parsed.profiles[parsed.active] : parsed;
35331
- if (!block) {
35332
- throw new Error(`${CRED_CONFIG_FILENAME} active course "${parsed.active}" not found in profiles.`);
35333
- }
35334
- const { pat: pat2, orgSlug: orgSlug2, projectSlug: projectSlug2, serverUrl } = block;
35335
- if (!pat2 || !pat2.startsWith("ls_pat_")) {
35336
- throw new Error(`${CRED_CONFIG_FILENAME} "pat" is missing or not a LaunchSecure PAT (ls_pat_...).`);
35337
- }
35338
- if (!orgSlug2 || !projectSlug2 || !serverUrl) {
35339
- throw new Error(`${CRED_CONFIG_FILENAME} is missing required fields (orgSlug, projectSlug, serverUrl).`);
35340
- }
35341
- return { pat: pat2, orgSlug: orgSlug2, projectSlug: projectSlug2, serverUrl, source: CRED_CONFIG_FILENAME };
35361
+ const fix = `Run \`npx @launchsecure/launch-kit@latest refresh\` to re-sync this project (or \`init\` if you haven't bootstrapped yet).`;
35362
+ const cred = readCredFile(REPO_ROOT);
35363
+ if (!cred) {
35364
+ throw new Error(`${CONFIG_FILENAME} not found in ${REPO_ROOT}. ${fix}`);
35342
35365
  }
35343
- const mcpPath = import_path9.default.join(REPO_ROOT, ".mcp.json");
35344
- if (!import_fs8.default.existsSync(mcpPath)) {
35345
- throw new Error(
35346
- `Neither ${CRED_CONFIG_FILENAME} nor .mcp.json found in ${REPO_ROOT}. Run \`npx launch-kit init --token=... --org=... --project=...\` to bootstrap.`
35347
- );
35366
+ const nested = toNested(cred);
35367
+ if (!nested) {
35368
+ throw new Error(`${CONFIG_FILENAME} is malformed or missing required fields (pat/orgSlug/projectSlug/serverUrl). ${fix}`);
35348
35369
  }
35349
- const raw = JSON.parse(import_fs8.default.readFileSync(mcpPath, "utf-8"));
35350
- const envName = process.env.LAUNCHPOD_MCP_NAME;
35351
- const entryName = envName ?? (raw.mcpServers?.["local-launch-secure"] ? "local-launch-secure" : "launch-secure");
35352
- const entry = raw.mcpServers?.[entryName];
35353
- if (!entry?.url) {
35354
- throw new Error(`No "${entryName}" entry with url found in .mcp.json (set LAUNCHPOD_MCP_NAME=<name> to pick a different one, or migrate to ${CRED_CONFIG_FILENAME} via \`launch-kit init\`)`);
35370
+ const profile = nested.profiles[nested.active];
35371
+ if (!profile) {
35372
+ throw new Error(`${CONFIG_FILENAME} active course "${nested.active}" not found in profiles. ${fix}`);
35355
35373
  }
35356
- const auth = entry.headers?.["Authorization"] ?? "";
35357
- const pat = auth.replace(/^Bearer\s+/i, "").trim();
35358
- if (!pat.startsWith("ls_pat_")) {
35359
- throw new Error(
35360
- `.mcp.json launch-secure Authorization header is not a PAT (ls_pat_...). Migrate to ${CRED_CONFIG_FILENAME} via \`launch-kit init\`, or update the header.`
35361
- );
35374
+ const { pat, orgSlug, projectSlug, serverUrl } = profile;
35375
+ if (!pat || !pat.startsWith("ls_pat_")) {
35376
+ throw new Error(`${CONFIG_FILENAME} "pat" is missing or not a LaunchSecure PAT (ls_pat_...). ${fix}`);
35362
35377
  }
35363
- const orgSlug = entry.headers?.["X-Org-Slug"];
35364
- const projectSlug = entry.headers?.["X-Project-Slug"];
35365
- if (!orgSlug || !projectSlug) {
35366
- throw new Error(
35367
- "Missing X-Org-Slug / X-Project-Slug headers in .mcp.json launch-secure entry."
35368
- );
35378
+ if (!orgSlug || !projectSlug || !serverUrl) {
35379
+ throw new Error(`${CONFIG_FILENAME} is missing required fields (orgSlug, projectSlug, serverUrl). ${fix}`);
35369
35380
  }
35370
- const url = new URL(entry.url);
35371
- return { pat, orgSlug, projectSlug, serverUrl: `${url.protocol}//${url.host}`, source: `.mcp.json[${entryName}]` };
35381
+ return { pat, orgSlug, projectSlug, serverUrl, source: `${CONFIG_FILENAME}[${nested.active}]` };
35372
35382
  }
35373
35383
  if (!__isMcpMode) {
35374
35384
  let gracefulShutdown = function() {