@launchsecure/launch-kit 0.0.32 → 0.0.34
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/chart-client/assets/{index-B__ARB8k.js → index-DFu2xIrM.js} +2 -2
- package/dist/chart-client/assets/index-DpKO9p0s.css +1 -0
- package/dist/chart-client/index.html +2 -2
- package/dist/client/assets/{index-h8kMzVtG.js → index-Cbw6bVdx.js} +2 -2
- package/dist/client/assets/index-Dv6dD2zY.css +32 -0
- package/dist/client/index.html +2 -2
- package/dist/council-client/assets/index-AqQ9Sei6.css +1 -0
- package/dist/council-client/assets/{index-CWaDcsFR.js → index-CAsmGTzg.js} +2 -2
- package/dist/council-client/index.html +2 -2
- package/dist/deck-client/assets/{_baseUniq-C7GsHvgg.js → _baseUniq-BiVx0WO_.js} +1 -1
- package/dist/deck-client/assets/{arc-CSrZRINY.js → arc-DGMkiEzS.js} +1 -1
- package/dist/deck-client/assets/{architectureDiagram-Q4EWVU46-zoB-G17J.js → architectureDiagram-Q4EWVU46-Y2WRmHtk.js} +1 -1
- package/dist/deck-client/assets/{blockDiagram-DXYQGD6D-BRjjtYH6.js → blockDiagram-DXYQGD6D-_Lbfu5BQ.js} +1 -1
- package/dist/deck-client/assets/{c4Diagram-AHTNJAMY-C3D3sd2U.js → c4Diagram-AHTNJAMY-CTqpYTBX.js} +1 -1
- package/dist/deck-client/assets/channel-DB6LxW_l.js +1 -0
- package/dist/deck-client/assets/{chunk-4BX2VUAB-DhpDMOPO.js → chunk-4BX2VUAB-liEIbPHs.js} +1 -1
- package/dist/deck-client/assets/{chunk-4TB4RGXK-BIRgPXRl.js → chunk-4TB4RGXK-CCc6lYvL.js} +1 -1
- package/dist/deck-client/assets/{chunk-55IACEB6-BF24dwDZ.js → chunk-55IACEB6-D02jJUR2.js} +1 -1
- package/dist/deck-client/assets/{chunk-EDXVE4YY-CW75Y61B.js → chunk-EDXVE4YY-BFmGMbLD.js} +1 -1
- package/dist/deck-client/assets/{chunk-FMBD7UC4-B5-oyL79.js → chunk-FMBD7UC4-6wFLOVcJ.js} +1 -1
- package/dist/deck-client/assets/{chunk-OYMX7WX6-BB2bHe_Q.js → chunk-OYMX7WX6-Bnr8RiBf.js} +1 -1
- package/dist/deck-client/assets/{chunk-QZHKN3VN-D80eZO4B.js → chunk-QZHKN3VN-Ct82MksJ.js} +1 -1
- package/dist/deck-client/assets/{chunk-YZCP3GAM-Dz9787p_.js → chunk-YZCP3GAM-BXmN1diQ.js} +1 -1
- package/dist/deck-client/assets/classDiagram-6PBFFD2Q-g944ZyG8.js +1 -0
- package/dist/deck-client/assets/classDiagram-v2-HSJHXN6E-g944ZyG8.js +1 -0
- package/dist/deck-client/assets/clone-DiIRH1pI.js +1 -0
- package/dist/deck-client/assets/{cose-bilkent-S5V4N54A-MQjiZLcL.js → cose-bilkent-S5V4N54A-CmQCT-mH.js} +1 -1
- package/dist/deck-client/assets/{dagre-KV5264BT-DG4EcLpJ.js → dagre-KV5264BT-DDdSa9EX.js} +1 -1
- package/dist/deck-client/assets/{diagram-5BDNPKRD-1n7hM3Gc.js → diagram-5BDNPKRD-Bccks2xJ.js} +1 -1
- package/dist/deck-client/assets/{diagram-G4DWMVQ6-CYMarncV.js → diagram-G4DWMVQ6-CPPNgxmQ.js} +1 -1
- package/dist/deck-client/assets/{diagram-MMDJMWI5-DSisoipe.js → diagram-MMDJMWI5-KrD300pS.js} +1 -1
- package/dist/deck-client/assets/{diagram-TYMM5635-Btnq49OJ.js → diagram-TYMM5635-DefnLuQf.js} +1 -1
- package/dist/deck-client/assets/{erDiagram-SMLLAGMA-Cu2Hb_Tz.js → erDiagram-SMLLAGMA-DI9FfnFP.js} +1 -1
- package/dist/deck-client/assets/{flowDiagram-DWJPFMVM-CGJzUzsO.js → flowDiagram-DWJPFMVM-twKyd3Fx.js} +1 -1
- package/dist/deck-client/assets/{ganttDiagram-T4ZO3ILL-D9sqGUBT.js → ganttDiagram-T4ZO3ILL-Wau3jhBr.js} +1 -1
- package/dist/deck-client/assets/{gitGraphDiagram-UUTBAWPF-C0QwX2od.js → gitGraphDiagram-UUTBAWPF-D9GgYXwb.js} +1 -1
- package/dist/deck-client/assets/{graph-CcBjOQCl.js → graph-BhNLzyXS.js} +1 -1
- package/dist/deck-client/assets/index-B-YQq5b5.css +1 -0
- package/dist/deck-client/assets/{index-0arwoc0z.js → index-BtQBaQ7s.js} +3 -3
- package/dist/deck-client/assets/{infoDiagram-42DDH7IO-DTimhhhS.js → infoDiagram-42DDH7IO-TylGlSG-.js} +1 -1
- package/dist/deck-client/assets/{ishikawaDiagram-UXIWVN3A-DxOxg_B4.js → ishikawaDiagram-UXIWVN3A-DAT8icpg.js} +1 -1
- package/dist/deck-client/assets/{journeyDiagram-VCZTEJTY-Bpq0qa4j.js → journeyDiagram-VCZTEJTY-D3v_XL72.js} +1 -1
- package/dist/deck-client/assets/{kanban-definition-6JOO6SKY-aTIrpcVO.js → kanban-definition-6JOO6SKY-DNUOBiNr.js} +1 -1
- package/dist/deck-client/assets/{layout-DqglLR2E.js → layout-COfodgwF.js} +1 -1
- package/dist/deck-client/assets/{linear-D5GxehPc.js → linear-DmTsuIvK.js} +1 -1
- package/dist/deck-client/assets/{min-DXLfSREq.js → min-BW1F7i1D.js} +1 -1
- package/dist/deck-client/assets/{mindmap-definition-QFDTVHPH-mO5Vys7I.js → mindmap-definition-QFDTVHPH-CErFzKWl.js} +1 -1
- package/dist/deck-client/assets/{pieDiagram-DEJITSTG-Dm0gzdAr.js → pieDiagram-DEJITSTG-DW5F757o.js} +1 -1
- package/dist/deck-client/assets/{quadrantDiagram-34T5L4WZ-Daq7j3qD.js → quadrantDiagram-34T5L4WZ-B1S2-TfI.js} +1 -1
- package/dist/deck-client/assets/{requirementDiagram-MS252O5E-CmwV95um.js → requirementDiagram-MS252O5E-BY5BAR-5.js} +1 -1
- package/dist/deck-client/assets/{sankeyDiagram-XADWPNL6-BOYl3Nkf.js → sankeyDiagram-XADWPNL6-CE1Cp9HS.js} +1 -1
- package/dist/deck-client/assets/{sequenceDiagram-FGHM5R23-BuUjhIcW.js → sequenceDiagram-FGHM5R23-IaHnbKye.js} +1 -1
- package/dist/deck-client/assets/{stateDiagram-FHFEXIEX-LUZ_uwio.js → stateDiagram-FHFEXIEX-CwPJm9hU.js} +1 -1
- package/dist/deck-client/assets/stateDiagram-v2-QKLJ7IA2-DQYa2M1q.js +1 -0
- package/dist/deck-client/assets/{timeline-definition-GMOUNBTQ-CDUxCCAW.js → timeline-definition-GMOUNBTQ-DVFGGSgN.js} +1 -1
- package/dist/deck-client/assets/{vennDiagram-DHZGUBPP-BRb24Tf7.js → vennDiagram-DHZGUBPP-C1194MJi.js} +1 -1
- package/dist/deck-client/assets/wardley-RL74JXVD-CHZiUbBa.js +162 -0
- package/dist/deck-client/assets/{wardleyDiagram-NUSXRM2D-BLGlYrQz.js → wardleyDiagram-NUSXRM2D-hpwdFfGj.js} +1 -1
- package/dist/deck-client/assets/{xychartDiagram-5P7HB3ND-De31MSnk.js → xychartDiagram-5P7HB3ND-DYkotwy8.js} +1 -1
- package/dist/deck-client/index.html +2 -2
- package/dist/server/chart-serve.js +167 -2
- package/dist/server/cli.js +328 -42
- package/dist/server/course-entry.js +1 -1
- package/dist/server/graph-mcp-entry.js +180 -4
- package/dist/server/init-entry.js +1133 -219
- package/dist/server/launch-radar-entry.js +45 -0
- package/dist/server/parse-worker-entry.js +167 -2
- package/dist/server/radar-docker-init-entry.js +644 -0
- package/dist/server/radar-entrypoint-entry.js +99 -0
- package/dist/server/radar-teardown-entry.js +478 -0
- package/dist/server/recall-entry.js +4 -1
- package/dist/server/rover-entry.js +20122 -0
- package/package.json +7 -5
- package/scaffolds/ls-marketplace/plugins/kit/commands/activate-statusline.md +5 -5
- package/scaffolds/ls-marketplace/plugins/kit/commands/standup.md +6 -6
- package/scaffolds/ls-marketplace/plugins/kit/skills/analyse/SKILL.md +6 -0
- package/scaffolds/ls-marketplace/plugins/kit/skills/brief/SKILL.md +40 -48
- package/scaffolds/ls-marketplace/plugins/kit/skills/debug/SKILL.md +45 -20
- package/scaffolds/ls-marketplace/plugins/kit/skills/deploy-check/SKILL.md +76 -67
- package/scaffolds/ls-marketplace/plugins/kit/skills/handoff/SKILL.md +132 -0
- package/scaffolds/ls-marketplace/plugins/kit/skills/ship/SKILL.md +290 -0
- package/scaffolds/statusline/statusline-mcp.sh +82 -2
- package/scaffolds/statusline/statusline-wrapper.sh +8 -1
- package/dist/chart-client/assets/index-CDIhdgWg.css +0 -1
- package/dist/client/assets/index-CfW4n40I.css +0 -32
- package/dist/council-client/assets/index-CZim6x1u.css +0 -1
- package/dist/deck-client/assets/channel-8ReQnQfH.js +0 -1
- package/dist/deck-client/assets/classDiagram-6PBFFD2Q-cRxTeGkK.js +0 -1
- package/dist/deck-client/assets/classDiagram-v2-HSJHXN6E-cRxTeGkK.js +0 -1
- package/dist/deck-client/assets/clone-LSHZ3K6R.js +0 -1
- package/dist/deck-client/assets/index-BlTlhxFW.css +0 -1
- package/dist/deck-client/assets/stateDiagram-v2-QKLJ7IA2-CnnRwE5D.js +0 -1
- package/dist/deck-client/assets/wardley-RL74JXVD-B0BYyVBY.js +0 -162
package/dist/server/cli.js
CHANGED
|
@@ -23251,6 +23251,7 @@ function emptyParsedFile(absPath) {
|
|
|
23251
23251
|
return {
|
|
23252
23252
|
name: absPath.split("/").pop() ?? absPath,
|
|
23253
23253
|
exports: [],
|
|
23254
|
+
defines: [],
|
|
23254
23255
|
imports: [],
|
|
23255
23256
|
reExports: [],
|
|
23256
23257
|
jsxElements: /* @__PURE__ */ new Set(),
|
|
@@ -23363,6 +23364,34 @@ function parseFileTS(absPath) {
|
|
|
23363
23364
|
reExports.push({ name: "*", from: caps["reexport.wildcard.source"], isWildcard: true });
|
|
23364
23365
|
}
|
|
23365
23366
|
}
|
|
23367
|
+
const definesSet = /* @__PURE__ */ new Set();
|
|
23368
|
+
function recordCallable(decl) {
|
|
23369
|
+
if (decl.type === "function_declaration" || decl.type === "generator_function_declaration") {
|
|
23370
|
+
const id = childOfType(decl, "identifier");
|
|
23371
|
+
if (id) definesSet.add(id.text);
|
|
23372
|
+
return;
|
|
23373
|
+
}
|
|
23374
|
+
if (decl.type === "class_declaration") {
|
|
23375
|
+
const id = childOfType(decl, "type_identifier") ?? childOfType(decl, "identifier");
|
|
23376
|
+
if (id) definesSet.add(id.text);
|
|
23377
|
+
return;
|
|
23378
|
+
}
|
|
23379
|
+
if (decl.type === "lexical_declaration" || decl.type === "variable_declaration") {
|
|
23380
|
+
for (const d of childrenOfType(decl, "variable_declarator")) {
|
|
23381
|
+
const id = childOfType(d, "identifier");
|
|
23382
|
+
if (!id) continue;
|
|
23383
|
+
const isCallable = !!childOfType(d, "arrow_function") || !!childOfType(d, "function_expression") || !!childOfType(d, "function") || !!childOfType(d, "generator_function");
|
|
23384
|
+
if (isCallable) definesSet.add(id.text);
|
|
23385
|
+
}
|
|
23386
|
+
}
|
|
23387
|
+
}
|
|
23388
|
+
for (const child of root.children) {
|
|
23389
|
+
if (child.type === "export_statement") {
|
|
23390
|
+
for (const gc of child.children) recordCallable(gc);
|
|
23391
|
+
} else {
|
|
23392
|
+
recordCallable(child);
|
|
23393
|
+
}
|
|
23394
|
+
}
|
|
23366
23395
|
const jsxElements = /* @__PURE__ */ new Set();
|
|
23367
23396
|
const jsxQuery = getQuery("jsx-elements");
|
|
23368
23397
|
const jsxCaptures = jsxQuery.captures(root);
|
|
@@ -23451,7 +23480,7 @@ function parseFileTS(absPath) {
|
|
|
23451
23480
|
}
|
|
23452
23481
|
}
|
|
23453
23482
|
const name = defaultName ?? firstValueExport ?? firstTypeExport ?? "";
|
|
23454
|
-
return { name, exports: exportsOrdered, imports, reExports, jsxElements, navigations, fetchCalls };
|
|
23483
|
+
return { name, exports: exportsOrdered, defines: [...definesSet], imports, reExports, jsxElements, navigations, fetchCalls };
|
|
23455
23484
|
}
|
|
23456
23485
|
function extractDbCallsTS(absPath) {
|
|
23457
23486
|
const tree = parseSource(absPath);
|
|
@@ -24542,17 +24571,17 @@ function shutdownTerminalBridge() {
|
|
|
24542
24571
|
}
|
|
24543
24572
|
}
|
|
24544
24573
|
|
|
24545
|
-
// src/server/
|
|
24574
|
+
// src/server/sequencer-terminal-init.ts
|
|
24546
24575
|
var import_path = __toESM(require("path"));
|
|
24547
24576
|
init_launch_kit_paths();
|
|
24548
|
-
function
|
|
24577
|
+
function initSequencerTerminalBridge(httpServer, projectDir) {
|
|
24549
24578
|
return initTerminalBridge(httpServer, projectDir, import_path.default.join(projectDir, LAUNCHPOD_DIR, "sessions"));
|
|
24550
24579
|
}
|
|
24551
24580
|
|
|
24552
24581
|
// src/server/mcp-config-writer.ts
|
|
24553
24582
|
var import_fs = __toESM(require("fs"));
|
|
24554
24583
|
var import_path2 = __toESM(require("path"));
|
|
24555
|
-
var MANAGED_SERVERS = ["launch-pod", "launch-chart"];
|
|
24584
|
+
var MANAGED_SERVERS = ["launch-pod", "launch-sequencer", "launch-chart"];
|
|
24556
24585
|
function mergeMcpEntry(existing, ours) {
|
|
24557
24586
|
if (!existing || typeof existing !== "object") return ours;
|
|
24558
24587
|
const prev = existing;
|
|
@@ -24601,7 +24630,7 @@ function removeClaudeEntries(filePath) {
|
|
|
24601
24630
|
} else {
|
|
24602
24631
|
existing.mcpServers = servers;
|
|
24603
24632
|
import_fs.default.writeFileSync(filePath, JSON.stringify(existing, null, 2) + "\n", { mode: 384 });
|
|
24604
|
-
console.log(`MCP config cleaned (
|
|
24633
|
+
console.log(`MCP config cleaned (launch-sequencer entries removed): ${filePath}`);
|
|
24605
24634
|
}
|
|
24606
24635
|
} catch {
|
|
24607
24636
|
try {
|
|
@@ -24626,7 +24655,8 @@ function writeClaudeConfig(projectDir, mcpUrl, token) {
|
|
|
24626
24655
|
}
|
|
24627
24656
|
}
|
|
24628
24657
|
const servers = existing.mcpServers ?? {};
|
|
24629
|
-
|
|
24658
|
+
delete servers["launch-pod"];
|
|
24659
|
+
servers["launch-sequencer"] = mergeMcpEntry(servers["launch-sequencer"], {
|
|
24630
24660
|
type: "http",
|
|
24631
24661
|
url: mcpUrl,
|
|
24632
24662
|
headers: {
|
|
@@ -24655,9 +24685,9 @@ function writeCodexConfig(projectDir, mcpUrl, token) {
|
|
|
24655
24685
|
}
|
|
24656
24686
|
} catch {
|
|
24657
24687
|
}
|
|
24658
|
-
const cleaned = existingContent.replace(/\[mcp_servers\.launch-pod\][^\[]*/, "").replace(/\[mcp_servers\.launch-chart\][^\[]*/, "").trim();
|
|
24659
|
-
const
|
|
24660
|
-
`[mcp_servers.launch-
|
|
24688
|
+
const cleaned = existingContent.replace(/\[mcp_servers\.launch-pod\][^\[]*/, "").replace(/\[mcp_servers\.launch-sequencer\][^\[]*/, "").replace(/\[mcp_servers\.launch-chart\][^\[]*/, "").trim();
|
|
24689
|
+
const managedBlock = [
|
|
24690
|
+
`[mcp_servers.launch-sequencer]`,
|
|
24661
24691
|
`url = "${mcpUrl}"`,
|
|
24662
24692
|
`http_headers = { "Authorization" = "Bearer ${token}" }`,
|
|
24663
24693
|
``,
|
|
@@ -24665,7 +24695,7 @@ function writeCodexConfig(projectDir, mcpUrl, token) {
|
|
|
24665
24695
|
`command = "launch-chart"`,
|
|
24666
24696
|
`args = []`
|
|
24667
24697
|
].join("\n");
|
|
24668
|
-
const merged = cleaned ? cleaned + "\n\n" +
|
|
24698
|
+
const merged = cleaned ? cleaned + "\n\n" + managedBlock + "\n" : managedBlock + "\n";
|
|
24669
24699
|
import_fs.default.writeFileSync(filePath, merged, { mode: 384 });
|
|
24670
24700
|
writtenPaths.push(filePath);
|
|
24671
24701
|
console.log(`Codex MCP config merged into ${filePath}`);
|
|
@@ -28032,7 +28062,7 @@ var RadarState = class {
|
|
|
28032
28062
|
}
|
|
28033
28063
|
};
|
|
28034
28064
|
|
|
28035
|
-
// src/server/
|
|
28065
|
+
// src/server/tunnel/index.ts
|
|
28036
28066
|
var import_node_fs3 = require("node:fs");
|
|
28037
28067
|
var import_node_events = require("node:events");
|
|
28038
28068
|
var import_promises = require("node:dns/promises");
|
|
@@ -28386,7 +28416,7 @@ var CacheableLookup = class {
|
|
|
28386
28416
|
}
|
|
28387
28417
|
};
|
|
28388
28418
|
|
|
28389
|
-
// src/server/
|
|
28419
|
+
// src/server/tunnel/index.ts
|
|
28390
28420
|
var import_undici = __toESM(require_undici());
|
|
28391
28421
|
var import_cloudflared = require("cloudflared");
|
|
28392
28422
|
var dnsResolver = new import_promises.Resolver();
|
|
@@ -28404,14 +28434,42 @@ var BACKOFF_MIN_MS = 1e3;
|
|
|
28404
28434
|
var BACKOFF_MAX_MS = 3e5;
|
|
28405
28435
|
var SELFTEST_INTERVAL_MS = 1e3;
|
|
28406
28436
|
var SELFTEST_TIMEOUT_MS = 9e4;
|
|
28437
|
+
function resolveTunnelMode(opts) {
|
|
28438
|
+
const env = opts.env ?? process.env;
|
|
28439
|
+
const tokenKey = `${opts.varPrefix}_TUNNEL_TOKEN`;
|
|
28440
|
+
const hostKey = `${opts.varPrefix}_TUNNEL_HOSTNAME`;
|
|
28441
|
+
const token = env[tokenKey]?.trim();
|
|
28442
|
+
const hostname = env[hostKey]?.trim()?.replace(/^https?:\/\//, "").replace(/\/$/, "");
|
|
28443
|
+
if (!token && !hostname) return { kind: "quick" };
|
|
28444
|
+
if (!token || !hostname) {
|
|
28445
|
+
const missing = !token ? tokenKey : hostKey;
|
|
28446
|
+
throw new Error(
|
|
28447
|
+
`[tunnel] named-tunnel config is partial \u2014 ${missing} is not set. Set BOTH ${tokenKey} and ${hostKey} for a stable paid tunnel, or unset both to fall back to the free quick tunnel.`
|
|
28448
|
+
);
|
|
28449
|
+
}
|
|
28450
|
+
return { kind: "named", token, hostname };
|
|
28451
|
+
}
|
|
28452
|
+
var NAMED_FATAL_PATTERNS = [
|
|
28453
|
+
/\bunauthorized\b/i,
|
|
28454
|
+
/\b401\b/,
|
|
28455
|
+
/invalid (tunnel )?token/i,
|
|
28456
|
+
/token (is )?expired/i,
|
|
28457
|
+
/tunnel .{0,80}? not found/i,
|
|
28458
|
+
/failed to (provision|find|authenticate) tunnel/i,
|
|
28459
|
+
/failed to read tunnel credentials/i,
|
|
28460
|
+
/jwt.*expired/i
|
|
28461
|
+
];
|
|
28407
28462
|
var CloudflaredTunnel = class extends import_node_events.EventEmitter {
|
|
28408
|
-
constructor(
|
|
28463
|
+
constructor(opts) {
|
|
28409
28464
|
super();
|
|
28410
28465
|
this.tunnel = null;
|
|
28411
28466
|
this.currentUrl = null;
|
|
28412
28467
|
this.stopping = false;
|
|
28468
|
+
this.fatal = false;
|
|
28413
28469
|
this.restartAttempt = 0;
|
|
28414
|
-
this.localPort = localPort;
|
|
28470
|
+
this.localPort = opts.localPort;
|
|
28471
|
+
this.mode = opts.mode;
|
|
28472
|
+
this.probePath = opts.probePath;
|
|
28415
28473
|
}
|
|
28416
28474
|
get publicUrl() {
|
|
28417
28475
|
return this.currentUrl;
|
|
@@ -28419,7 +28477,7 @@ var CloudflaredTunnel = class extends import_node_events.EventEmitter {
|
|
|
28419
28477
|
async start() {
|
|
28420
28478
|
if (this.tunnel) return;
|
|
28421
28479
|
if (!(0, import_node_fs3.existsSync)(import_cloudflared.bin)) {
|
|
28422
|
-
console.log("[
|
|
28480
|
+
console.log("[tunnel] downloading cloudflared binary (one-time setup)\u2026");
|
|
28423
28481
|
try {
|
|
28424
28482
|
await (0, import_cloudflared.install)(import_cloudflared.bin);
|
|
28425
28483
|
} catch (err2) {
|
|
@@ -28427,6 +28485,11 @@ var CloudflaredTunnel = class extends import_node_events.EventEmitter {
|
|
|
28427
28485
|
throw new Error(`Failed to install cloudflared binary: ${msg}`);
|
|
28428
28486
|
}
|
|
28429
28487
|
}
|
|
28488
|
+
if (this.mode.kind === "named") {
|
|
28489
|
+
console.log(`[tunnel] mode=named host=${this.mode.hostname} (paid \xB7 stable URL)`);
|
|
28490
|
+
} else {
|
|
28491
|
+
console.log(`[tunnel] mode=quick (free \xB7 *.trycloudflare.com \xB7 ephemeral URL)`);
|
|
28492
|
+
}
|
|
28430
28493
|
this.spawnOnce();
|
|
28431
28494
|
}
|
|
28432
28495
|
async stop() {
|
|
@@ -28447,10 +28510,11 @@ var CloudflaredTunnel = class extends import_node_events.EventEmitter {
|
|
|
28447
28510
|
});
|
|
28448
28511
|
}
|
|
28449
28512
|
spawnOnce() {
|
|
28450
|
-
|
|
28513
|
+
if (this.fatal) return;
|
|
28514
|
+
const tun = this.mode.kind === "named" ? import_cloudflared.Tunnel.withToken(this.mode.token) : import_cloudflared.Tunnel.quick(`http://127.0.0.1:${this.localPort}`);
|
|
28451
28515
|
this.tunnel = tun;
|
|
28452
28516
|
this.currentUrl = null;
|
|
28453
|
-
let urlSeen = null;
|
|
28517
|
+
let urlSeen = this.mode.kind === "named" ? `https://${this.mode.hostname}` : null;
|
|
28454
28518
|
let connectedSeen = false;
|
|
28455
28519
|
let announced = false;
|
|
28456
28520
|
const announceIfReady = () => {
|
|
@@ -28460,30 +28524,60 @@ var CloudflaredTunnel = class extends import_node_events.EventEmitter {
|
|
|
28460
28524
|
void this.selfTestAndAnnounce(url);
|
|
28461
28525
|
};
|
|
28462
28526
|
tun.on("url", (url) => {
|
|
28527
|
+
if (this.mode.kind === "named") return;
|
|
28463
28528
|
if (urlSeen === url) return;
|
|
28464
28529
|
urlSeen = url;
|
|
28465
|
-
console.log(`[
|
|
28530
|
+
console.log(`[tunnel] subdomain assigned: ${url} (waiting for edge connection)`);
|
|
28466
28531
|
announceIfReady();
|
|
28467
28532
|
});
|
|
28468
28533
|
tun.on("connected", (conn) => {
|
|
28469
28534
|
if (!connectedSeen) {
|
|
28470
28535
|
connectedSeen = true;
|
|
28471
|
-
console.log(`[
|
|
28536
|
+
console.log(`[tunnel] connected to edge: ${conn?.location ?? "?"} (${conn?.id ?? "?"})`);
|
|
28472
28537
|
}
|
|
28473
28538
|
announceIfReady();
|
|
28474
28539
|
});
|
|
28540
|
+
if (this.mode.kind === "named") {
|
|
28541
|
+
tun.on("stderr", (line) => {
|
|
28542
|
+
if (this.fatal) return;
|
|
28543
|
+
for (const pat of NAMED_FATAL_PATTERNS) {
|
|
28544
|
+
if (pat.test(line)) {
|
|
28545
|
+
this.markFatal(`cloudflared rejected the named-tunnel config \u2014 ${line.trim().slice(0, 200)}`);
|
|
28546
|
+
return;
|
|
28547
|
+
}
|
|
28548
|
+
}
|
|
28549
|
+
});
|
|
28550
|
+
}
|
|
28475
28551
|
tun.on("error", (err2) => {
|
|
28476
28552
|
if (this.stopping) return;
|
|
28477
|
-
console.error(`[
|
|
28553
|
+
console.error(`[tunnel] cloudflared error: ${err2.message}`);
|
|
28478
28554
|
});
|
|
28479
28555
|
tun.on("exit", (code) => {
|
|
28480
28556
|
if (this.stopping) return;
|
|
28481
28557
|
this.tunnel = null;
|
|
28482
28558
|
this.currentUrl = null;
|
|
28559
|
+
if (this.fatal) return;
|
|
28483
28560
|
this.emit("crashed", code);
|
|
28484
28561
|
this.scheduleRestart();
|
|
28485
28562
|
});
|
|
28486
28563
|
}
|
|
28564
|
+
/**
|
|
28565
|
+
* Mark the tunnel fatally broken. Suppresses restart-on-crash and notifies
|
|
28566
|
+
* the parent so it can surface status=error to the UI. Named-mode only —
|
|
28567
|
+
* quick mode has no auth surface to fail on.
|
|
28568
|
+
*/
|
|
28569
|
+
markFatal(reason) {
|
|
28570
|
+
if (this.fatal) return;
|
|
28571
|
+
this.fatal = true;
|
|
28572
|
+
this.stopping = true;
|
|
28573
|
+
console.error(`[tunnel] FATAL: ${reason}`);
|
|
28574
|
+
console.error(`[tunnel] not falling back to free tunnel \u2014 fix the named-tunnel env vars (or unset both) and restart.`);
|
|
28575
|
+
this.emit("fatal", reason);
|
|
28576
|
+
try {
|
|
28577
|
+
this.tunnel?.stop();
|
|
28578
|
+
} catch {
|
|
28579
|
+
}
|
|
28580
|
+
}
|
|
28487
28581
|
/**
|
|
28488
28582
|
* Poll the public URL until any HTTP response comes back (proving DNS +
|
|
28489
28583
|
* edge + tunnel work end-to-end), then announce ready. Network errors are
|
|
@@ -28491,7 +28585,7 @@ var CloudflaredTunnel = class extends import_node_events.EventEmitter {
|
|
|
28491
28585
|
* we log loudly but keep cloudflared alive so a later retry can succeed.
|
|
28492
28586
|
*/
|
|
28493
28587
|
async selfTestAndAnnounce(url) {
|
|
28494
|
-
const probeUrl = `${url}
|
|
28588
|
+
const probeUrl = `${url}${this.probePath}`;
|
|
28495
28589
|
const started = Date.now();
|
|
28496
28590
|
let attempts = 0;
|
|
28497
28591
|
while (Date.now() - started < SELFTEST_TIMEOUT_MS) {
|
|
@@ -28503,7 +28597,7 @@ var CloudflaredTunnel = class extends import_node_events.EventEmitter {
|
|
|
28503
28597
|
signal: AbortSignal.timeout(5e3),
|
|
28504
28598
|
dispatcher: dnsResilientDispatcher
|
|
28505
28599
|
});
|
|
28506
|
-
console.log(`[
|
|
28600
|
+
console.log(`[tunnel] self-test ok (${res.status}) after ${attempts} attempt(s)`);
|
|
28507
28601
|
this.currentUrl = url;
|
|
28508
28602
|
this.restartAttempt = 0;
|
|
28509
28603
|
this.emit("ready", url);
|
|
@@ -28511,26 +28605,42 @@ var CloudflaredTunnel = class extends import_node_events.EventEmitter {
|
|
|
28511
28605
|
} catch (err2) {
|
|
28512
28606
|
if (attempts === 1 || attempts % 10 === 0) {
|
|
28513
28607
|
const msg = err2 instanceof Error ? err2.message : String(err2);
|
|
28514
|
-
console.log(`[
|
|
28608
|
+
console.log(`[tunnel] self-test attempt ${attempts}: ${msg} \u2014 retrying`);
|
|
28515
28609
|
}
|
|
28516
28610
|
await new Promise((r) => setTimeout(r, SELFTEST_INTERVAL_MS));
|
|
28517
28611
|
}
|
|
28518
28612
|
}
|
|
28519
|
-
console.error(`[
|
|
28613
|
+
console.error(`[tunnel] self-test gave up after ${Math.round(SELFTEST_TIMEOUT_MS / 1e3)}s \u2014 tunnel announced but unreachable from this host`);
|
|
28520
28614
|
}
|
|
28521
28615
|
scheduleRestart() {
|
|
28522
28616
|
if (this.stopping) return;
|
|
28523
28617
|
this.restartAttempt += 1;
|
|
28524
28618
|
const delay = Math.min(BACKOFF_MIN_MS * 2 ** (this.restartAttempt - 1), BACKOFF_MAX_MS);
|
|
28525
|
-
console.log(`[
|
|
28619
|
+
console.log(`[tunnel] down \u2014 restarting in ${Math.round(delay / 1e3)}s (attempt ${this.restartAttempt})`);
|
|
28526
28620
|
setTimeout(() => this.spawnOnce(), delay);
|
|
28527
28621
|
}
|
|
28528
28622
|
};
|
|
28623
|
+
function createTunnel(opts) {
|
|
28624
|
+
if (opts.provider === null) return null;
|
|
28625
|
+
if (opts.provider === "cloudflare") {
|
|
28626
|
+
if (!opts.varPrefix) {
|
|
28627
|
+
throw new Error(`[tunnel] createTunnel({ provider: "cloudflare" }) requires varPrefix`);
|
|
28628
|
+
}
|
|
28629
|
+
const mode = resolveTunnelMode({ varPrefix: opts.varPrefix, env: opts.env });
|
|
28630
|
+
return new CloudflaredTunnel({
|
|
28631
|
+
localPort: opts.localPort,
|
|
28632
|
+
mode,
|
|
28633
|
+
probePath: opts.probePath
|
|
28634
|
+
});
|
|
28635
|
+
}
|
|
28636
|
+
const exhaustive = opts.provider;
|
|
28637
|
+
throw new Error(`[tunnel] unknown provider: ${String(exhaustive)}`);
|
|
28638
|
+
}
|
|
28529
28639
|
|
|
28530
28640
|
// src/server/radar/agent.ts
|
|
28531
28641
|
var SLOT_RELEASE_MS = 15 * 60 * 1e3;
|
|
28532
28642
|
var AUTO_RESUME_STALENESS_MS = 60 * 60 * 1e3;
|
|
28533
|
-
var Radar = class {
|
|
28643
|
+
var Radar = class _Radar {
|
|
28534
28644
|
constructor(opts) {
|
|
28535
28645
|
this.wss = null;
|
|
28536
28646
|
this.clients = /* @__PURE__ */ new Set();
|
|
@@ -28555,7 +28665,18 @@ var Radar = class {
|
|
|
28555
28665
|
orgSlug: opts.orgSlug,
|
|
28556
28666
|
projectSlug: opts.projectSlug
|
|
28557
28667
|
});
|
|
28558
|
-
|
|
28668
|
+
const tunnel = createTunnel({
|
|
28669
|
+
provider: _Radar.TUNNEL_PROVIDER,
|
|
28670
|
+
localPort: opts.localPort,
|
|
28671
|
+
probePath: RECEIVER_PATH,
|
|
28672
|
+
varPrefix: "RADAR_CF"
|
|
28673
|
+
});
|
|
28674
|
+
if (!tunnel) {
|
|
28675
|
+
throw new Error(
|
|
28676
|
+
`[radar] tunnel provider "${_Radar.TUNNEL_PROVIDER}" produced no tunnel \u2014 radar requires a public URL to register its receiver webhook.`
|
|
28677
|
+
);
|
|
28678
|
+
}
|
|
28679
|
+
this.tunnel = tunnel;
|
|
28559
28680
|
this.maxConcurrent = parsePositiveInt(process.env.RADAR_MAX_CONCURRENT_ANALYSES);
|
|
28560
28681
|
const callbacks = {
|
|
28561
28682
|
onLive: () => this.handleLive(),
|
|
@@ -28567,6 +28688,13 @@ var Radar = class {
|
|
|
28567
28688
|
};
|
|
28568
28689
|
this.receiver = createReceiver({ state: this.state, callbacks });
|
|
28569
28690
|
}
|
|
28691
|
+
static {
|
|
28692
|
+
// Tunnel provider is hardcoded for now — radar today cannot function
|
|
28693
|
+
// without a public URL (it has to register the receiver as a webhook with
|
|
28694
|
+
// LaunchSecure). If a future story wants radar to run behind a pre-existing
|
|
28695
|
+
// public hostname, add a "none" branch with a RADAR_PUBLIC_URL escape hatch.
|
|
28696
|
+
this.TUNNEL_PROVIDER = "cloudflare";
|
|
28697
|
+
}
|
|
28570
28698
|
/** Spawn tunnel, register (or refresh) the webhook, wait for activation. */
|
|
28571
28699
|
start() {
|
|
28572
28700
|
this.status = "tunneling";
|
|
@@ -28577,6 +28705,11 @@ var Radar = class {
|
|
|
28577
28705
|
this.tunnel.on("crashed", (code) => {
|
|
28578
28706
|
console.error(`[radar] tunnel exited (code=${code ?? "?"}) \u2014 restarting`);
|
|
28579
28707
|
});
|
|
28708
|
+
this.tunnel.on("fatal", (reason) => {
|
|
28709
|
+
this.status = "error";
|
|
28710
|
+
console.error(`[radar] named tunnel halted: ${reason}`);
|
|
28711
|
+
this.broadcastStatus();
|
|
28712
|
+
});
|
|
28580
28713
|
void this.tunnel.start();
|
|
28581
28714
|
this.autoResumeRecentlyInterrupted();
|
|
28582
28715
|
}
|
|
@@ -29805,6 +29938,11 @@ function generate(rootDir) {
|
|
|
29805
29938
|
const parsed = parsedByPath.get(absPath);
|
|
29806
29939
|
const name = parsed.name || nameFromFilename(absPath);
|
|
29807
29940
|
const layer = CLASSIFICATION_TO_LAYER[type] ?? "ui";
|
|
29941
|
+
const importedNames = [...new Set(
|
|
29942
|
+
parsed.imports.flatMap(
|
|
29943
|
+
(imp) => imp.isTypeOnly ? [] : imp.names.filter((n) => !imp.typeNames.has(n))
|
|
29944
|
+
)
|
|
29945
|
+
)];
|
|
29808
29946
|
nodeIdSet.add(id);
|
|
29809
29947
|
if (layer === "api") {
|
|
29810
29948
|
const dbCalls = extractDbCallsTS(absPath);
|
|
@@ -29843,6 +29981,8 @@ function generate(rootDir) {
|
|
|
29843
29981
|
responses: deep.responses,
|
|
29844
29982
|
params: deep.params,
|
|
29845
29983
|
...deep.effects ? { effects: deep.effects } : {},
|
|
29984
|
+
...parsed.defines.length > 0 ? { defines: parsed.defines } : {},
|
|
29985
|
+
...importedNames.length > 0 ? { imported_names: importedNames } : {},
|
|
29846
29986
|
...deep.notes ? { notes: deep.notes } : {},
|
|
29847
29987
|
_dbCalls: dbCalls
|
|
29848
29988
|
// temp: used for cross-ref building below
|
|
@@ -29859,6 +29999,8 @@ function generate(rootDir) {
|
|
|
29859
29999
|
layer: "ui",
|
|
29860
30000
|
route,
|
|
29861
30001
|
exports: parsed.exports,
|
|
30002
|
+
...parsed.defines.length > 0 ? { defines: parsed.defines } : {},
|
|
30003
|
+
...importedNames.length > 0 ? { imported_names: importedNames } : {},
|
|
29862
30004
|
elements: deep.elements,
|
|
29863
30005
|
stateVars: deep.stateVars,
|
|
29864
30006
|
conditions: deep.conditions,
|
|
@@ -32819,6 +32961,132 @@ var middlewareGatesParser = {
|
|
|
32819
32961
|
}
|
|
32820
32962
|
};
|
|
32821
32963
|
|
|
32964
|
+
// src/server/graph/parsers/crosslayer/call-resolver.ts
|
|
32965
|
+
var BARE_IDENT = /^[A-Za-z_$][\w$]*$/;
|
|
32966
|
+
var callResolverParser = {
|
|
32967
|
+
id: "call-resolver",
|
|
32968
|
+
layer: "crosslayer",
|
|
32969
|
+
concern: "call-graph",
|
|
32970
|
+
detect(_rootDir) {
|
|
32971
|
+
return true;
|
|
32972
|
+
},
|
|
32973
|
+
generate(_rootDir, layerOutputs) {
|
|
32974
|
+
const definers = /* @__PURE__ */ new Map();
|
|
32975
|
+
const addDef = (sym, entry) => {
|
|
32976
|
+
if (!BARE_IDENT.test(sym)) return;
|
|
32977
|
+
const list = definers.get(sym);
|
|
32978
|
+
if (!list) {
|
|
32979
|
+
definers.set(sym, [entry]);
|
|
32980
|
+
} else if (!list.some((d) => d.nodeId === entry.nodeId)) {
|
|
32981
|
+
list.push(entry);
|
|
32982
|
+
}
|
|
32983
|
+
};
|
|
32984
|
+
const nodeLayer = /* @__PURE__ */ new Map();
|
|
32985
|
+
for (const [layer, output] of layerOutputs) {
|
|
32986
|
+
if (layer === "db" || layer === "static") continue;
|
|
32987
|
+
for (const node of output.nodes) {
|
|
32988
|
+
nodeLayer.set(node.id, layer);
|
|
32989
|
+
const entry = { nodeId: node.id, layer };
|
|
32990
|
+
for (const s of node.exports ?? []) addDef(s, entry);
|
|
32991
|
+
for (const s of node.defines ?? []) addDef(s, entry);
|
|
32992
|
+
}
|
|
32993
|
+
}
|
|
32994
|
+
const importTargets = /* @__PURE__ */ new Map();
|
|
32995
|
+
for (const [, output] of layerOutputs) {
|
|
32996
|
+
for (const e of output.edges) {
|
|
32997
|
+
if (e.type !== "imports" && e.type !== "imports_type" && e.type !== "renders") continue;
|
|
32998
|
+
let set = importTargets.get(e.source);
|
|
32999
|
+
if (!set) {
|
|
33000
|
+
set = /* @__PURE__ */ new Set();
|
|
33001
|
+
importTargets.set(e.source, set);
|
|
33002
|
+
}
|
|
33003
|
+
set.add(e.target);
|
|
33004
|
+
}
|
|
33005
|
+
}
|
|
33006
|
+
const crossRefs = [];
|
|
33007
|
+
const seen = /* @__PURE__ */ new Set();
|
|
33008
|
+
let resolvedSelf = 0;
|
|
33009
|
+
let resolvedImport = 0;
|
|
33010
|
+
let ambiguous = 0;
|
|
33011
|
+
let dropped = 0;
|
|
33012
|
+
for (const [, output] of layerOutputs) {
|
|
33013
|
+
for (const node of output.nodes) {
|
|
33014
|
+
const calls = node.effects?.calls;
|
|
33015
|
+
if (!calls || calls.length === 0) continue;
|
|
33016
|
+
const selfSyms = /* @__PURE__ */ new Set([
|
|
33017
|
+
...node.exports ?? [],
|
|
33018
|
+
...node.defines ?? []
|
|
33019
|
+
]);
|
|
33020
|
+
const importedSyms = new Set(node.imported_names ?? []);
|
|
33021
|
+
const myImports = importTargets.get(node.id);
|
|
33022
|
+
const localSeen = /* @__PURE__ */ new Set();
|
|
33023
|
+
for (const callee of calls) {
|
|
33024
|
+
if (!BARE_IDENT.test(callee)) continue;
|
|
33025
|
+
if (localSeen.has(callee)) continue;
|
|
33026
|
+
localSeen.add(callee);
|
|
33027
|
+
const key = `${node.id}\u2192${callee}`;
|
|
33028
|
+
if (selfSyms.has(callee)) {
|
|
33029
|
+
if (seen.has(key)) continue;
|
|
33030
|
+
seen.add(key);
|
|
33031
|
+
crossRefs.push({
|
|
33032
|
+
source: node.id,
|
|
33033
|
+
target: callee,
|
|
33034
|
+
type: "calls",
|
|
33035
|
+
layer: nodeLayer.get(node.id) ?? "ui",
|
|
33036
|
+
defined_in: node.id
|
|
33037
|
+
});
|
|
33038
|
+
resolvedSelf++;
|
|
33039
|
+
continue;
|
|
33040
|
+
}
|
|
33041
|
+
if (!importedSyms.has(callee)) {
|
|
33042
|
+
dropped++;
|
|
33043
|
+
continue;
|
|
33044
|
+
}
|
|
33045
|
+
const defs = (definers.get(callee) ?? []).filter((d) => d.nodeId !== node.id);
|
|
33046
|
+
if (defs.length === 0) {
|
|
33047
|
+
dropped++;
|
|
33048
|
+
continue;
|
|
33049
|
+
}
|
|
33050
|
+
const fromImported = myImports ? defs.filter((d) => myImports.has(d.nodeId)) : [];
|
|
33051
|
+
const chosen = fromImported.length > 0 ? fromImported : defs;
|
|
33052
|
+
const owner = chosen[0];
|
|
33053
|
+
const isAmbiguous = chosen.length > 1;
|
|
33054
|
+
if (isAmbiguous) ambiguous++;
|
|
33055
|
+
if (seen.has(key)) continue;
|
|
33056
|
+
seen.add(key);
|
|
33057
|
+
const ref = {
|
|
33058
|
+
source: node.id,
|
|
33059
|
+
target: callee,
|
|
33060
|
+
type: "calls",
|
|
33061
|
+
layer: owner.layer,
|
|
33062
|
+
defined_in: owner.nodeId
|
|
33063
|
+
};
|
|
33064
|
+
if (isAmbiguous) ref.ambiguous = true;
|
|
33065
|
+
crossRefs.push(ref);
|
|
33066
|
+
resolvedImport++;
|
|
33067
|
+
}
|
|
33068
|
+
}
|
|
33069
|
+
}
|
|
33070
|
+
crossRefs.sort(
|
|
33071
|
+
(a, b) => a.source.localeCompare(b.source) || a.target.localeCompare(b.target)
|
|
33072
|
+
);
|
|
33073
|
+
return {
|
|
33074
|
+
cross_refs: crossRefs,
|
|
33075
|
+
flagged_edges: [],
|
|
33076
|
+
warnings: [],
|
|
33077
|
+
patterns: {
|
|
33078
|
+
call_resolution: {
|
|
33079
|
+
resolved_self: resolvedSelf,
|
|
33080
|
+
resolved_import: resolvedImport,
|
|
33081
|
+
ambiguous,
|
|
33082
|
+
dropped,
|
|
33083
|
+
symbols_defined: definers.size
|
|
33084
|
+
}
|
|
33085
|
+
}
|
|
33086
|
+
};
|
|
33087
|
+
}
|
|
33088
|
+
};
|
|
33089
|
+
|
|
32822
33090
|
// src/server/graph/core/parser-registry.ts
|
|
32823
33091
|
function isMultiLayerParser(p) {
|
|
32824
33092
|
return "layers" in p && Array.isArray(p.layers);
|
|
@@ -32885,7 +33153,8 @@ function registerBuiltins2(registry, disabled) {
|
|
|
32885
33153
|
apiAnnotationsParser,
|
|
32886
33154
|
urlLiteralScannerParser,
|
|
32887
33155
|
staticRefScannerParser,
|
|
32888
|
-
middlewareGatesParser
|
|
33156
|
+
middlewareGatesParser,
|
|
33157
|
+
callResolverParser
|
|
32889
33158
|
];
|
|
32890
33159
|
for (const parser of builtins) {
|
|
32891
33160
|
if (disabled.has(parser.id)) continue;
|
|
@@ -35889,6 +36158,10 @@ function handleWhoUses(args) {
|
|
|
35889
36158
|
};
|
|
35890
36159
|
const via = cr.via;
|
|
35891
36160
|
if (Array.isArray(via)) entry.via = via;
|
|
36161
|
+
const definedIn = cr.defined_in;
|
|
36162
|
+
if (typeof definedIn === "string") entry.defined_in = definedIn;
|
|
36163
|
+
const ambiguous = cr.ambiguous;
|
|
36164
|
+
if (ambiguous) entry.ambiguous = true;
|
|
35892
36165
|
hits.push(entry);
|
|
35893
36166
|
}
|
|
35894
36167
|
}
|
|
@@ -36556,7 +36829,7 @@ var McpSession = class {
|
|
|
36556
36829
|
jsonrpc: "2.0",
|
|
36557
36830
|
id: this.callId++,
|
|
36558
36831
|
method: "initialize",
|
|
36559
|
-
params: { protocolVersion: "2025-03-26", capabilities: {}, clientInfo: { name: "
|
|
36832
|
+
params: { protocolVersion: "2025-03-26", capabilities: {}, clientInfo: { name: "launch-sequencer", version: "0.0.1" } }
|
|
36560
36833
|
});
|
|
36561
36834
|
const initResp = await httpRequest2(this.mcpUrl, {
|
|
36562
36835
|
method: "POST",
|
|
@@ -36710,7 +36983,7 @@ async function validateRepoUrl(serverUrl, token) {
|
|
|
36710
36983
|
console.error("Error: Repository URL mismatch");
|
|
36711
36984
|
console.error(` Project expects: ${remoteRepoUrl}`);
|
|
36712
36985
|
console.error(` Local origin: ${localOrigin}`);
|
|
36713
|
-
console.error("Run
|
|
36986
|
+
console.error("Run launch-sequencer from the correct repository.");
|
|
36714
36987
|
process.exit(1);
|
|
36715
36988
|
}
|
|
36716
36989
|
}
|
|
@@ -36999,6 +37272,14 @@ if (parsedArgs.subcommand === "graph:generate" || parsedArgs.subcommand === "gra
|
|
|
36999
37272
|
);
|
|
37000
37273
|
process.exit(result.status ?? 1);
|
|
37001
37274
|
}
|
|
37275
|
+
if (parsedArgs.subcommand === "radar:teardown") {
|
|
37276
|
+
const result = (0, import_child_process4.spawnSync)(
|
|
37277
|
+
process.execPath,
|
|
37278
|
+
[import_path9.default.join(__dirname, "radar-teardown-entry.js"), ...process.argv.slice(3)],
|
|
37279
|
+
{ stdio: "inherit" }
|
|
37280
|
+
);
|
|
37281
|
+
process.exit(result.status ?? 1);
|
|
37282
|
+
}
|
|
37002
37283
|
if (parsedArgs.subcommand === "mcp:graph") {
|
|
37003
37284
|
startGraphMcpServer();
|
|
37004
37285
|
}
|
|
@@ -37458,18 +37739,23 @@ if (!__isMcpMode) {
|
|
|
37458
37739
|
console.log(`LaunchPod radar \xB7 ${localUrl}`);
|
|
37459
37740
|
console.log(` cloud: ${cfg.serverUrl} \xB7 source: ${cfg.source}`);
|
|
37460
37741
|
console.log(` org: ${cfg.orgSlug} \xB7 project: ${cfg.projectSlug}`);
|
|
37461
|
-
|
|
37462
|
-
|
|
37463
|
-
|
|
37464
|
-
|
|
37465
|
-
|
|
37466
|
-
|
|
37467
|
-
|
|
37468
|
-
|
|
37469
|
-
|
|
37742
|
+
try {
|
|
37743
|
+
radar = new Radar({
|
|
37744
|
+
projectRoot: PROJECT_DIR,
|
|
37745
|
+
localPort: PORT,
|
|
37746
|
+
localUrl,
|
|
37747
|
+
serverUrl: cfg.serverUrl,
|
|
37748
|
+
pat: cfg.pat,
|
|
37749
|
+
orgSlug: cfg.orgSlug,
|
|
37750
|
+
projectSlug: cfg.projectSlug
|
|
37751
|
+
});
|
|
37752
|
+
} catch (err2) {
|
|
37753
|
+
console.error(`${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
37754
|
+
process.exit(1);
|
|
37755
|
+
}
|
|
37470
37756
|
radar.attachWebSocketServer(server, "/api/radar/stream");
|
|
37471
37757
|
radar.start();
|
|
37472
|
-
|
|
37758
|
+
initSequencerTerminalBridge(server, PROJECT_DIR);
|
|
37473
37759
|
return;
|
|
37474
37760
|
}
|
|
37475
37761
|
if (token) {
|
|
@@ -37518,11 +37804,11 @@ if (!__isMcpMode) {
|
|
|
37518
37804
|
activeCapabilities = await fetchCapabilities(existingCreds.serverUrl, existingCreds.token);
|
|
37519
37805
|
}
|
|
37520
37806
|
if (activeCapabilities.terminal) {
|
|
37521
|
-
|
|
37807
|
+
initSequencerTerminalBridge(server, PROJECT_DIR);
|
|
37522
37808
|
}
|
|
37523
37809
|
startPipelineSystem(existingCreds, activeCapabilities);
|
|
37524
37810
|
} else if (activeCapabilities.terminal) {
|
|
37525
|
-
|
|
37811
|
+
initSequencerTerminalBridge(server, PROJECT_DIR);
|
|
37526
37812
|
}
|
|
37527
37813
|
}
|
|
37528
37814
|
main().catch((err2) => {
|
|
@@ -214,7 +214,7 @@ Usage:
|
|
|
214
214
|
launch-course rm <name>
|
|
215
215
|
|
|
216
216
|
The cred file (.launch-secure.cred.config) holds every course under \`profiles\`,
|
|
217
|
-
with \`active\` selecting which one drives MCP / launch-
|
|
217
|
+
with \`active\` selecting which one drives MCP / launch-sequencer auth. Legacy flat
|
|
218
218
|
files are auto-migrated on the first multi-profile op. \`launch-course set\`
|
|
219
219
|
also rewrites .mcp.json's launch-secure.url so Claude Code routes to the right
|
|
220
220
|
server on next MCP reconnect.
|