@launchsecure/launch-kit 0.0.39 → 0.0.40
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-CWJFFDPu.css +1 -0
- package/dist/chart-client/index.html +2 -2
- package/dist/client/assets/index-CTzFcfGV.css +32 -0
- package/dist/client/index.html +2 -2
- package/dist/council-client/assets/index-ArgRc5mN.css +1 -0
- package/dist/council-client/index.html +2 -2
- package/dist/deck-client/assets/{_baseUniq-DOrnEQMI.js → _baseUniq-BZP7n41F.js} +1 -1
- package/dist/deck-client/assets/{arc-DOWK7V3m.js → arc-31biU3Az.js} +1 -1
- package/dist/deck-client/assets/{architectureDiagram-Q4EWVU46-DPhzvk7q.js → architectureDiagram-Q4EWVU46-DHg6Ss--.js} +1 -1
- package/dist/deck-client/assets/{blockDiagram-DXYQGD6D-CwAGy9lU.js → blockDiagram-DXYQGD6D-CUdblaWk.js} +1 -1
- package/dist/deck-client/assets/{c4Diagram-AHTNJAMY-L_g_SS21.js → c4Diagram-AHTNJAMY-MfAO5lak.js} +1 -1
- package/dist/deck-client/assets/channel-BBkRLdnC.js +1 -0
- package/dist/deck-client/assets/{chunk-4BX2VUAB-RKm0LXpu.js → chunk-4BX2VUAB-DQ1MrGgN.js} +1 -1
- package/dist/deck-client/assets/{chunk-4TB4RGXK-Bk0FUbxU.js → chunk-4TB4RGXK-BUJtZ7jO.js} +1 -1
- package/dist/deck-client/assets/{chunk-55IACEB6-Cl3hja-M.js → chunk-55IACEB6-BdSnXB6g.js} +1 -1
- package/dist/deck-client/assets/{chunk-EDXVE4YY-CNIMQCV2.js → chunk-EDXVE4YY-94yZIUI8.js} +1 -1
- package/dist/deck-client/assets/{chunk-FMBD7UC4-DqOvWr1k.js → chunk-FMBD7UC4-PnZ9v6ey.js} +1 -1
- package/dist/deck-client/assets/{chunk-OYMX7WX6-1Kd7yK5u.js → chunk-OYMX7WX6-DXrWNOsV.js} +1 -1
- package/dist/deck-client/assets/{chunk-QZHKN3VN-6_kraYpP.js → chunk-QZHKN3VN-CsIGIDKX.js} +1 -1
- package/dist/deck-client/assets/{chunk-YZCP3GAM-FgAwIWlo.js → chunk-YZCP3GAM-DVkBO9tn.js} +1 -1
- package/dist/deck-client/assets/classDiagram-6PBFFD2Q-DFCaeF-7.js +1 -0
- package/dist/deck-client/assets/classDiagram-v2-HSJHXN6E-DFCaeF-7.js +1 -0
- package/dist/deck-client/assets/clone-GCEVRScB.js +1 -0
- package/dist/deck-client/assets/{cose-bilkent-S5V4N54A-CigVnnPr.js → cose-bilkent-S5V4N54A-m126Oh3b.js} +1 -1
- package/dist/deck-client/assets/{dagre-KV5264BT-DHZXTktX.js → dagre-KV5264BT-C2aig8U5.js} +1 -1
- package/dist/deck-client/assets/{diagram-5BDNPKRD-H5k0eauU.js → diagram-5BDNPKRD-CKpoRfGn.js} +1 -1
- package/dist/deck-client/assets/{diagram-G4DWMVQ6-Bg3dFhSY.js → diagram-G4DWMVQ6-Cjh115Ep.js} +1 -1
- package/dist/deck-client/assets/{diagram-MMDJMWI5-CQLC410N.js → diagram-MMDJMWI5-DKlBv_2L.js} +1 -1
- package/dist/deck-client/assets/{diagram-TYMM5635-DFTCHVkP.js → diagram-TYMM5635-CdBh4cEn.js} +1 -1
- package/dist/deck-client/assets/{erDiagram-SMLLAGMA-aiv9GZnL.js → erDiagram-SMLLAGMA-56pn_93p.js} +1 -1
- package/dist/deck-client/assets/{flowDiagram-DWJPFMVM-C6Fhvtsy.js → flowDiagram-DWJPFMVM-BtV3M5xJ.js} +1 -1
- package/dist/deck-client/assets/{ganttDiagram-T4ZO3ILL-DSaGMPM4.js → ganttDiagram-T4ZO3ILL-DTIsC6Zg.js} +1 -1
- package/dist/deck-client/assets/{gitGraphDiagram-UUTBAWPF-DMjL2Vix.js → gitGraphDiagram-UUTBAWPF-CJYeyCLe.js} +1 -1
- package/dist/deck-client/assets/{graph-B7Vn5lkK.js → graph-BDvMu1Ss.js} +1 -1
- package/dist/deck-client/assets/index-D4eSxcBn.css +1 -0
- package/dist/deck-client/assets/{index-BD36e-tD.js → index-QnGVE9PZ.js} +72 -72
- package/dist/deck-client/assets/{infoDiagram-42DDH7IO-mNi4iygG.js → infoDiagram-42DDH7IO-BWyKJnpW.js} +1 -1
- package/dist/deck-client/assets/{ishikawaDiagram-UXIWVN3A-BwCUmUVt.js → ishikawaDiagram-UXIWVN3A-DXYkdO3T.js} +1 -1
- package/dist/deck-client/assets/{journeyDiagram-VCZTEJTY-C6qoqJmJ.js → journeyDiagram-VCZTEJTY-C2zBr-J5.js} +1 -1
- package/dist/deck-client/assets/{kanban-definition-6JOO6SKY-Dz1Tt3sA.js → kanban-definition-6JOO6SKY-CdoYLS4Z.js} +1 -1
- package/dist/deck-client/assets/{layout-CZTyRhOG.js → layout-vOnxnCQU.js} +1 -1
- package/dist/deck-client/assets/{linear--7n7iEvd.js → linear-B0J0WCGz.js} +1 -1
- package/dist/deck-client/assets/{min-Bh130DN8.js → min-B0AXlT9L.js} +1 -1
- package/dist/deck-client/assets/{mindmap-definition-QFDTVHPH-CfXcK1qH.js → mindmap-definition-QFDTVHPH-oAybLedr.js} +1 -1
- package/dist/deck-client/assets/{pieDiagram-DEJITSTG-DjVHLAVw.js → pieDiagram-DEJITSTG-BjHyHxGk.js} +1 -1
- package/dist/deck-client/assets/{quadrantDiagram-34T5L4WZ-CXwvZ1i1.js → quadrantDiagram-34T5L4WZ-dtluDZXs.js} +1 -1
- package/dist/deck-client/assets/{requirementDiagram-MS252O5E-Cl6xm0fR.js → requirementDiagram-MS252O5E-Cq8l7bOl.js} +1 -1
- package/dist/deck-client/assets/{sankeyDiagram-XADWPNL6-BOH9sLyh.js → sankeyDiagram-XADWPNL6-C1Vih91z.js} +1 -1
- package/dist/deck-client/assets/{sequenceDiagram-FGHM5R23-BC1MYBn6.js → sequenceDiagram-FGHM5R23-CYkd7oQK.js} +1 -1
- package/dist/deck-client/assets/{stateDiagram-FHFEXIEX-kNp9bv8K.js → stateDiagram-FHFEXIEX-CtyG8wBK.js} +1 -1
- package/dist/deck-client/assets/stateDiagram-v2-QKLJ7IA2-BLyKWfcN.js +1 -0
- package/dist/deck-client/assets/{timeline-definition-GMOUNBTQ-DKnITsD4.js → timeline-definition-GMOUNBTQ-DZIxSyd1.js} +1 -1
- package/dist/deck-client/assets/{vennDiagram-DHZGUBPP-BdajXRrh.js → vennDiagram-DHZGUBPP-Ct4JVRDM.js} +1 -1
- package/dist/deck-client/assets/wardley-RL74JXVD-V29ycxOW.js +162 -0
- package/dist/deck-client/assets/{wardleyDiagram-NUSXRM2D-B2hDCDl2.js → wardleyDiagram-NUSXRM2D-D-Ua6Cmi.js} +1 -1
- package/dist/deck-client/assets/{xychartDiagram-5P7HB3ND-CvnYFs51.js → xychartDiagram-5P7HB3ND-BPCOuRVl.js} +1 -1
- package/dist/deck-client/index.html +2 -2
- package/dist/server/beacon-monitor-entry.js +106 -24
- package/dist/server/chart-serve.js +544 -247
- package/dist/server/cli.js +743 -324
- package/dist/server/council-entry.js +16 -3
- package/dist/server/council-serve.js +15 -2
- package/dist/server/deck-mcp-entry.js +267 -107
- package/dist/server/deck-serve.js +98 -22
- package/dist/server/graph-mcp-entry.js +866 -357
- package/dist/server/orbit-entry.js +91 -7
- package/dist/server/recall-entry.js +94 -12
- package/dist/server/rover-entry.js +1 -1
- package/package.json +1 -1
- package/scaffolds/statusline/statusline-mcp.sh +68 -19
- package/scaffolds/statusline/statusline-wrapper.sh +12 -9
- package/dist/chart-client/assets/index-ysGpLeOW.css +0 -1
- package/dist/client/assets/index-CMN3tlGP.css +0 -32
- package/dist/council-client/assets/index-ChmNX6bZ.css +0 -1
- package/dist/deck-client/assets/channel-DqiACUUq.js +0 -1
- package/dist/deck-client/assets/classDiagram-6PBFFD2Q-D23cq2C3.js +0 -1
- package/dist/deck-client/assets/classDiagram-v2-HSJHXN6E-D23cq2C3.js +0 -1
- package/dist/deck-client/assets/clone-C7jSigGq.js +0 -1
- package/dist/deck-client/assets/index-CGbNOpk9.css +0 -1
- package/dist/deck-client/assets/stateDiagram-v2-QKLJ7IA2-hRsAFc2t.js +0 -1
- package/dist/deck-client/assets/wardley-RL74JXVD-BL802-su.js +0 -162
- /package/dist/chart-client/assets/{index-BlsuXuQ1.js → index-Dzlj-oCj.js} +0 -0
- /package/dist/client/assets/{index-BA7BHBWT.js → index-tTg_ezUF.js} +0 -0
- /package/dist/council-client/assets/{index-jjBWyhry.js → index-B1v46vTE.js} +0 -0
|
@@ -128,24 +128,24 @@ var init_deck_lockfile = __esm({
|
|
|
128
128
|
|
|
129
129
|
// src/server/deck-config.ts
|
|
130
130
|
function loadDeckConfig(rootDir) {
|
|
131
|
-
const configPath = (0,
|
|
132
|
-
if (!(0,
|
|
131
|
+
const configPath = (0, import_node_path3.join)(rootDir, CONFIG_FILENAME);
|
|
132
|
+
if (!(0, import_node_fs3.existsSync)(configPath)) return {};
|
|
133
133
|
try {
|
|
134
|
-
return JSON.parse((0,
|
|
134
|
+
return JSON.parse((0, import_node_fs3.readFileSync)(configPath, "utf-8"));
|
|
135
135
|
} catch {
|
|
136
136
|
return {};
|
|
137
137
|
}
|
|
138
138
|
}
|
|
139
139
|
function saveDeckConfig(rootDir, config) {
|
|
140
|
-
const configPath = (0,
|
|
141
|
-
(0,
|
|
140
|
+
const configPath = (0, import_node_path3.join)(rootDir, CONFIG_FILENAME);
|
|
141
|
+
(0, import_node_fs3.writeFileSync)(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
142
142
|
}
|
|
143
|
-
var
|
|
143
|
+
var import_node_fs3, import_node_path3, CONFIG_FILENAME;
|
|
144
144
|
var init_deck_config = __esm({
|
|
145
145
|
"src/server/deck-config.ts"() {
|
|
146
146
|
"use strict";
|
|
147
|
-
|
|
148
|
-
|
|
147
|
+
import_node_fs3 = require("node:fs");
|
|
148
|
+
import_node_path3 = require("node:path");
|
|
149
149
|
CONFIG_FILENAME = ".launchdeck.json";
|
|
150
150
|
}
|
|
151
151
|
});
|
|
@@ -1250,7 +1250,7 @@ var init_cred_shape = __esm({
|
|
|
1250
1250
|
});
|
|
1251
1251
|
|
|
1252
1252
|
// src/server/mcp-client.ts
|
|
1253
|
-
function
|
|
1253
|
+
function mcpConfigForProfile(projectRoot, name) {
|
|
1254
1254
|
let cred;
|
|
1255
1255
|
try {
|
|
1256
1256
|
cred = readCredFile(projectRoot);
|
|
@@ -1260,7 +1260,7 @@ function mcpConfigFromCourse(projectRoot) {
|
|
|
1260
1260
|
if (!cred) return null;
|
|
1261
1261
|
const nested = toNested(cred);
|
|
1262
1262
|
if (!nested) return null;
|
|
1263
|
-
const profile = nested.profiles[
|
|
1263
|
+
const profile = nested.profiles[name];
|
|
1264
1264
|
if (!profile?.pat || !profile.serverUrl || !profile.orgSlug || !profile.projectSlug) {
|
|
1265
1265
|
return null;
|
|
1266
1266
|
}
|
|
@@ -1273,6 +1273,37 @@ function mcpConfigFromCourse(projectRoot) {
|
|
|
1273
1273
|
}
|
|
1274
1274
|
};
|
|
1275
1275
|
}
|
|
1276
|
+
function mcpConfigFromCourse(projectRoot) {
|
|
1277
|
+
let cred;
|
|
1278
|
+
try {
|
|
1279
|
+
cred = readCredFile(projectRoot);
|
|
1280
|
+
} catch {
|
|
1281
|
+
return null;
|
|
1282
|
+
}
|
|
1283
|
+
if (!cred) return null;
|
|
1284
|
+
const nested = toNested(cred);
|
|
1285
|
+
if (!nested) return null;
|
|
1286
|
+
return mcpConfigForProfile(projectRoot, nested.active);
|
|
1287
|
+
}
|
|
1288
|
+
function listCourses(projectRoot) {
|
|
1289
|
+
let cred;
|
|
1290
|
+
try {
|
|
1291
|
+
cred = readCredFile(projectRoot);
|
|
1292
|
+
} catch {
|
|
1293
|
+
return [];
|
|
1294
|
+
}
|
|
1295
|
+
if (!cred) return [];
|
|
1296
|
+
const nested = toNested(cred);
|
|
1297
|
+
if (!nested) return [];
|
|
1298
|
+
return Object.entries(nested.profiles).map(([name, p]) => ({
|
|
1299
|
+
name,
|
|
1300
|
+
org: p.orgSlug ?? "",
|
|
1301
|
+
project: p.projectSlug ?? "",
|
|
1302
|
+
serverUrl: p.serverUrl ?? "",
|
|
1303
|
+
active: name === nested.active,
|
|
1304
|
+
usable: Boolean(p.pat && p.serverUrl && p.orgSlug && p.projectSlug)
|
|
1305
|
+
}));
|
|
1306
|
+
}
|
|
1276
1307
|
function loadMcpConfig(projectRoot) {
|
|
1277
1308
|
if (_config) return _config;
|
|
1278
1309
|
const fromCourse = mcpConfigFromCourse(projectRoot);
|
|
@@ -1280,13 +1311,13 @@ function loadMcpConfig(projectRoot) {
|
|
|
1280
1311
|
_config = fromCourse;
|
|
1281
1312
|
return _config;
|
|
1282
1313
|
}
|
|
1283
|
-
const mcpPath = (0,
|
|
1284
|
-
if (!(0,
|
|
1314
|
+
const mcpPath = (0, import_node_path4.join)(projectRoot, ".mcp.json");
|
|
1315
|
+
if (!(0, import_node_fs4.existsSync)(mcpPath)) {
|
|
1285
1316
|
throw new Error(
|
|
1286
1317
|
`No active course in ${CONFIG_FILENAME2} and no .mcp.json at ${mcpPath}. Run \`launch-course\` or bootstrap with \`launch-kit init\`.`
|
|
1287
1318
|
);
|
|
1288
1319
|
}
|
|
1289
|
-
const raw = JSON.parse((0,
|
|
1320
|
+
const raw = JSON.parse((0, import_node_fs4.readFileSync)(mcpPath, "utf-8"));
|
|
1290
1321
|
const entry = raw.mcpServers["launch-secure"];
|
|
1291
1322
|
if (!entry?.url) {
|
|
1292
1323
|
throw new Error(
|
|
@@ -1299,6 +1330,23 @@ function loadMcpConfig(projectRoot) {
|
|
|
1299
1330
|
};
|
|
1300
1331
|
return _config;
|
|
1301
1332
|
}
|
|
1333
|
+
function withMcpConfig(override, fn) {
|
|
1334
|
+
const run = async () => {
|
|
1335
|
+
const prevConfig = _config;
|
|
1336
|
+
const prevSession = _sessionId;
|
|
1337
|
+
_config = override;
|
|
1338
|
+
_sessionId = null;
|
|
1339
|
+
try {
|
|
1340
|
+
return await fn();
|
|
1341
|
+
} finally {
|
|
1342
|
+
_config = prevConfig;
|
|
1343
|
+
_sessionId = prevSession;
|
|
1344
|
+
}
|
|
1345
|
+
};
|
|
1346
|
+
const result = _overrideLock.then(run, run);
|
|
1347
|
+
_overrideLock = result.then(() => void 0, () => void 0);
|
|
1348
|
+
return result;
|
|
1349
|
+
}
|
|
1302
1350
|
function parseSSE(text2) {
|
|
1303
1351
|
const lines = text2.split("\n");
|
|
1304
1352
|
for (const line of lines) {
|
|
@@ -1406,16 +1454,17 @@ async function updateDeck(commentId, input) {
|
|
|
1406
1454
|
async function deleteDeck(commentId) {
|
|
1407
1455
|
await callTool("communication_delete", { comment_id: commentId });
|
|
1408
1456
|
}
|
|
1409
|
-
var
|
|
1457
|
+
var import_node_fs4, import_node_path4, _config, _requestId, _sessionId, _overrideLock;
|
|
1410
1458
|
var init_mcp_client = __esm({
|
|
1411
1459
|
"src/server/mcp-client.ts"() {
|
|
1412
1460
|
"use strict";
|
|
1413
|
-
|
|
1414
|
-
|
|
1461
|
+
import_node_fs4 = require("node:fs");
|
|
1462
|
+
import_node_path4 = require("node:path");
|
|
1415
1463
|
init_cred_shape();
|
|
1416
1464
|
_config = null;
|
|
1417
1465
|
_requestId = 0;
|
|
1418
1466
|
_sessionId = null;
|
|
1467
|
+
_overrideLock = Promise.resolve();
|
|
1419
1468
|
}
|
|
1420
1469
|
});
|
|
1421
1470
|
|
|
@@ -1430,14 +1479,14 @@ __export(deck_serve_exports, {
|
|
|
1430
1479
|
startDeckServer: () => startDeckServer
|
|
1431
1480
|
});
|
|
1432
1481
|
function sessionDir(cwd, session) {
|
|
1433
|
-
return
|
|
1482
|
+
return import_node_path5.default.join(cwd, LAUNCHSECURE_DIR, "deck-files", session);
|
|
1434
1483
|
}
|
|
1435
1484
|
function sessionJsonPath(cwd, session) {
|
|
1436
|
-
return
|
|
1485
|
+
return import_node_path5.default.join(sessionDir(cwd, session), "session.json");
|
|
1437
1486
|
}
|
|
1438
1487
|
function readPersistedSession(cwd, session) {
|
|
1439
1488
|
try {
|
|
1440
|
-
const raw =
|
|
1489
|
+
const raw = import_node_fs5.default.readFileSync(sessionJsonPath(cwd, session), "utf-8");
|
|
1441
1490
|
return JSON.parse(raw);
|
|
1442
1491
|
} catch {
|
|
1443
1492
|
return null;
|
|
@@ -1445,7 +1494,7 @@ function readPersistedSession(cwd, session) {
|
|
|
1445
1494
|
}
|
|
1446
1495
|
function writePersistedSession(cwd, session, payload) {
|
|
1447
1496
|
const dir = sessionDir(cwd, session);
|
|
1448
|
-
|
|
1497
|
+
import_node_fs5.default.mkdirSync(dir, { recursive: true });
|
|
1449
1498
|
const existing = readPersistedSession(cwd, session);
|
|
1450
1499
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1451
1500
|
const next = {
|
|
@@ -1457,13 +1506,13 @@ function writePersistedSession(cwd, session, payload) {
|
|
|
1457
1506
|
createdAt: existing?.createdAt ?? now,
|
|
1458
1507
|
updatedAt: now
|
|
1459
1508
|
};
|
|
1460
|
-
|
|
1509
|
+
import_node_fs5.default.writeFileSync(sessionJsonPath(cwd, session), JSON.stringify(next, null, 2));
|
|
1461
1510
|
return next;
|
|
1462
1511
|
}
|
|
1463
1512
|
function listPersistedSessions(cwd) {
|
|
1464
|
-
const base =
|
|
1465
|
-
if (!
|
|
1466
|
-
const entries =
|
|
1513
|
+
const base = import_node_path5.default.join(cwd, LAUNCHSECURE_DIR, "deck-files");
|
|
1514
|
+
if (!import_node_fs5.default.existsSync(base)) return [];
|
|
1515
|
+
const entries = import_node_fs5.default.readdirSync(base, { withFileTypes: true });
|
|
1467
1516
|
const sessions = [];
|
|
1468
1517
|
for (const entry of entries) {
|
|
1469
1518
|
if (!entry.isDirectory()) continue;
|
|
@@ -1485,26 +1534,26 @@ function listPersistedSessions(cwd) {
|
|
|
1485
1534
|
return sessions;
|
|
1486
1535
|
}
|
|
1487
1536
|
function deletePersistedSession(cwd, session) {
|
|
1488
|
-
const base =
|
|
1537
|
+
const base = import_node_path5.default.join(cwd, LAUNCHSECURE_DIR, "deck-files");
|
|
1489
1538
|
if (session === "all") {
|
|
1490
|
-
if (
|
|
1539
|
+
if (import_node_fs5.default.existsSync(base)) import_node_fs5.default.rmSync(base, { recursive: true, force: true });
|
|
1491
1540
|
return;
|
|
1492
1541
|
}
|
|
1493
1542
|
const dir = sessionDir(cwd, session);
|
|
1494
|
-
if (
|
|
1543
|
+
if (import_node_fs5.default.existsSync(dir)) import_node_fs5.default.rmSync(dir, { recursive: true, force: true });
|
|
1495
1544
|
}
|
|
1496
1545
|
function syncJsonPath(cwd, session) {
|
|
1497
|
-
return
|
|
1546
|
+
return import_node_path5.default.join(sessionDir(cwd, session), ".sync.json");
|
|
1498
1547
|
}
|
|
1499
1548
|
function readSyncRecord(cwd, session) {
|
|
1500
1549
|
try {
|
|
1501
|
-
return JSON.parse(
|
|
1550
|
+
return JSON.parse(import_node_fs5.default.readFileSync(syncJsonPath(cwd, session), "utf-8"));
|
|
1502
1551
|
} catch {
|
|
1503
1552
|
return null;
|
|
1504
1553
|
}
|
|
1505
1554
|
}
|
|
1506
1555
|
function writeSyncRecord(cwd, session, rec) {
|
|
1507
|
-
|
|
1556
|
+
import_node_fs5.default.writeFileSync(syncJsonPath(cwd, session), JSON.stringify(rec, null, 2));
|
|
1508
1557
|
}
|
|
1509
1558
|
function escHtml2(s) {
|
|
1510
1559
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
@@ -1517,7 +1566,7 @@ function readIframeArtifact(cwd, src) {
|
|
|
1517
1566
|
const rel = decodeURIComponent(src.slice("/deck-files/".length));
|
|
1518
1567
|
if (rel.includes("..")) return null;
|
|
1519
1568
|
try {
|
|
1520
|
-
return
|
|
1569
|
+
return import_node_fs5.default.readFileSync(import_node_path5.default.join(cwd, LAUNCHSECURE_DIR, "deck-files", rel), "utf-8");
|
|
1521
1570
|
} catch {
|
|
1522
1571
|
return null;
|
|
1523
1572
|
}
|
|
@@ -1614,23 +1663,23 @@ function broadcastToClients(message) {
|
|
|
1614
1663
|
}
|
|
1615
1664
|
}
|
|
1616
1665
|
function serveStatic(res, filePath) {
|
|
1617
|
-
if (!
|
|
1618
|
-
const ext =
|
|
1666
|
+
if (!import_node_fs5.default.existsSync(filePath) || !import_node_fs5.default.statSync(filePath).isFile()) return false;
|
|
1667
|
+
const ext = import_node_path5.default.extname(filePath).toLowerCase();
|
|
1619
1668
|
const mime = MIME_TYPES[ext] ?? "application/octet-stream";
|
|
1620
1669
|
res.writeHead(200, { "Content-Type": mime, "Cache-Control": "no-cache" });
|
|
1621
|
-
|
|
1670
|
+
import_node_fs5.default.createReadStream(filePath).pipe(res);
|
|
1622
1671
|
return true;
|
|
1623
1672
|
}
|
|
1624
1673
|
function resolveClientDir() {
|
|
1625
|
-
const sibling =
|
|
1626
|
-
if (
|
|
1627
|
-
const devDist =
|
|
1628
|
-
if (
|
|
1674
|
+
const sibling = import_node_path5.default.join(__dirname, "..", "deck-client");
|
|
1675
|
+
if (import_node_fs5.default.existsSync(import_node_path5.default.join(sibling, "assets"))) return sibling;
|
|
1676
|
+
const devDist = import_node_path5.default.join(__dirname, "..", "..", "dist", "deck-client");
|
|
1677
|
+
if (import_node_fs5.default.existsSync(import_node_path5.default.join(devDist, "assets"))) return devDist;
|
|
1629
1678
|
return sibling;
|
|
1630
1679
|
}
|
|
1631
1680
|
function serveIndex(res, clientDir) {
|
|
1632
|
-
const indexPath =
|
|
1633
|
-
if (!
|
|
1681
|
+
const indexPath = import_node_path5.default.join(clientDir, "index.html");
|
|
1682
|
+
if (!import_node_fs5.default.existsSync(indexPath)) {
|
|
1634
1683
|
res.writeHead(500, { "Content-Type": "text/plain" });
|
|
1635
1684
|
res.end(`LaunchDeck client bundle not found at ${clientDir}. Run 'npm run build:client'.`);
|
|
1636
1685
|
return;
|
|
@@ -1713,6 +1762,10 @@ async function startDeckServer(opts = {}) {
|
|
|
1713
1762
|
jsonResponse(res, 200, { config: cfg });
|
|
1714
1763
|
return;
|
|
1715
1764
|
}
|
|
1765
|
+
if (req.method === "GET" && url2.pathname === "/api/deck/courses") {
|
|
1766
|
+
jsonResponse(res, 200, { courses: listCourses(cwd) });
|
|
1767
|
+
return;
|
|
1768
|
+
}
|
|
1716
1769
|
if (req.method === "POST" && url2.pathname === "/api/deck/config") {
|
|
1717
1770
|
try {
|
|
1718
1771
|
const body = JSON.parse(await readBody(req));
|
|
@@ -1734,15 +1787,15 @@ async function startDeckServer(opts = {}) {
|
|
|
1734
1787
|
const baseUrl = `/deck-files/${sessionEncoded}`;
|
|
1735
1788
|
const html = generateBlastRadiusHtml(block.manifest, baseUrl);
|
|
1736
1789
|
const report = generateBlastRadiusReport(block.manifest);
|
|
1737
|
-
const dir =
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1790
|
+
const dir = import_node_path5.default.join(cwd, LAUNCHSECURE_DIR, "deck-files", body.session);
|
|
1791
|
+
import_node_fs5.default.mkdirSync(dir, { recursive: true });
|
|
1792
|
+
import_node_fs5.default.writeFileSync(import_node_path5.default.join(dir, "blast-radius.html"), html);
|
|
1793
|
+
import_node_fs5.default.writeFileSync(import_node_path5.default.join(dir, "blast-radius-report.md"), report);
|
|
1794
|
+
import_node_fs5.default.writeFileSync(import_node_path5.default.join(dir, "blast-radius-manifest.json"), JSON.stringify(block.manifest, null, 2));
|
|
1742
1795
|
const contractData = generateContract(block.manifest);
|
|
1743
1796
|
const contractMd = contractToMarkdown(contractData);
|
|
1744
|
-
|
|
1745
|
-
|
|
1797
|
+
import_node_fs5.default.writeFileSync(import_node_path5.default.join(dir, "contract.json"), JSON.stringify(contractData, null, 2));
|
|
1798
|
+
import_node_fs5.default.writeFileSync(import_node_path5.default.join(dir, "contract.md"), contractMd);
|
|
1746
1799
|
block.type = "iframe";
|
|
1747
1800
|
block.src = `${baseUrl}/blast-radius.html`;
|
|
1748
1801
|
delete block.manifest;
|
|
@@ -1769,9 +1822,9 @@ async function startDeckServer(opts = {}) {
|
|
|
1769
1822
|
const sessionEncoded = encodeURIComponent(body.session);
|
|
1770
1823
|
const baseUrl = `/deck-files/${sessionEncoded}`;
|
|
1771
1824
|
const filename = `${slugify(block.label)}.html`;
|
|
1772
|
-
const dir =
|
|
1773
|
-
|
|
1774
|
-
|
|
1825
|
+
const dir = import_node_path5.default.join(cwd, LAUNCHSECURE_DIR, "deck-files", body.session);
|
|
1826
|
+
import_node_fs5.default.mkdirSync(dir, { recursive: true });
|
|
1827
|
+
import_node_fs5.default.writeFileSync(import_node_path5.default.join(dir, filename), html);
|
|
1775
1828
|
block.type = "iframe";
|
|
1776
1829
|
block.src = `${baseUrl}/${filename}`;
|
|
1777
1830
|
delete block.content;
|
|
@@ -1811,14 +1864,34 @@ async function startDeckServer(opts = {}) {
|
|
|
1811
1864
|
jsonResponse(res, 404, { ok: false, error: "session not found" });
|
|
1812
1865
|
return;
|
|
1813
1866
|
}
|
|
1867
|
+
let course;
|
|
1814
1868
|
try {
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1869
|
+
const raw = await readBody(req);
|
|
1870
|
+
if (raw.trim()) {
|
|
1871
|
+
course = JSON.parse(raw).course?.trim() || void 0;
|
|
1872
|
+
}
|
|
1873
|
+
} catch {
|
|
1874
|
+
}
|
|
1875
|
+
let override = null;
|
|
1876
|
+
if (course) {
|
|
1877
|
+
override = mcpConfigForProfile(cwd, course);
|
|
1878
|
+
if (!override) {
|
|
1879
|
+
jsonResponse(res, 400, {
|
|
1880
|
+
ok: false,
|
|
1881
|
+
error: `Course "${course}" is not a usable profile in .launch-secure.cred.config (missing pat/serverUrl/orgSlug/projectSlug?).`
|
|
1882
|
+
});
|
|
1883
|
+
return;
|
|
1884
|
+
}
|
|
1885
|
+
} else {
|
|
1886
|
+
try {
|
|
1887
|
+
loadMcpConfig(cwd);
|
|
1888
|
+
} catch (err) {
|
|
1889
|
+
jsonResponse(res, 400, {
|
|
1890
|
+
ok: false,
|
|
1891
|
+
error: `Cloud sharing needs an active LaunchSecure course (.launch-secure.cred.config) or a "launch-secure" entry in .mcp.json: ${String(err)}`
|
|
1892
|
+
});
|
|
1893
|
+
return;
|
|
1894
|
+
}
|
|
1822
1895
|
}
|
|
1823
1896
|
try {
|
|
1824
1897
|
const blocks = Array.isArray(persisted.blocks) ? persisted.blocks : [];
|
|
@@ -1827,24 +1900,27 @@ async function startDeckServer(opts = {}) {
|
|
|
1827
1900
|
const body = `Shared deck "${id}" \u2014 ${blocks.length} block${blocks.length === 1 ? "" : "s"}${types.length ? ` (${types.join(", ")})` : ""}. Open the Decks tab in the Communication Center to view.`;
|
|
1828
1901
|
const input = { title: id, body, html, sessionId: id, blockCount: blocks.length };
|
|
1829
1902
|
const existing2 = readSyncRecord(cwd, id);
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1903
|
+
const doShare = async () => {
|
|
1904
|
+
if (existing2?.resourceId) {
|
|
1905
|
+
try {
|
|
1906
|
+
const { id: rid2 } = await updateDeck(existing2.resourceId, input);
|
|
1907
|
+
return { resourceId: rid2, updated: true };
|
|
1908
|
+
} catch {
|
|
1909
|
+
const { id: rid2 } = await writeDeck(input);
|
|
1910
|
+
return { resourceId: rid2, updated: false };
|
|
1911
|
+
}
|
|
1838
1912
|
}
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
}
|
|
1913
|
+
const { id: rid } = await writeDeck(input);
|
|
1914
|
+
return { resourceId: rid, updated: false };
|
|
1915
|
+
};
|
|
1916
|
+
const { resourceId, updated } = override ? await withMcpConfig(override, doShare) : await doShare();
|
|
1842
1917
|
writeSyncRecord(cwd, id, {
|
|
1843
1918
|
resourceId,
|
|
1844
1919
|
sharedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1845
|
-
version: persisted.version
|
|
1920
|
+
version: persisted.version,
|
|
1921
|
+
course
|
|
1846
1922
|
});
|
|
1847
|
-
jsonResponse(res, 200, { ok: true, resourceId, updated });
|
|
1923
|
+
jsonResponse(res, 200, { ok: true, resourceId, updated, course });
|
|
1848
1924
|
} catch (err) {
|
|
1849
1925
|
jsonResponse(res, 500, { ok: false, error: String(err) });
|
|
1850
1926
|
}
|
|
@@ -1867,7 +1943,7 @@ async function startDeckServer(opts = {}) {
|
|
|
1867
1943
|
try {
|
|
1868
1944
|
await deleteDeck(sync.resourceId);
|
|
1869
1945
|
try {
|
|
1870
|
-
|
|
1946
|
+
import_node_fs5.default.rmSync(syncJsonPath(cwd, id), { force: true });
|
|
1871
1947
|
} catch {
|
|
1872
1948
|
}
|
|
1873
1949
|
jsonResponse(res, 200, { ok: true, deleted: true });
|
|
@@ -1978,7 +2054,7 @@ async function startDeckServer(opts = {}) {
|
|
|
1978
2054
|
res.end("Forbidden");
|
|
1979
2055
|
return;
|
|
1980
2056
|
}
|
|
1981
|
-
const filePath =
|
|
2057
|
+
const filePath = import_node_path5.default.join(cwd, LAUNCHSECURE_DIR, "deck-files", relative);
|
|
1982
2058
|
if (serveStatic(res, filePath)) return;
|
|
1983
2059
|
res.writeHead(404);
|
|
1984
2060
|
res.end("Not found");
|
|
@@ -1991,25 +2067,25 @@ async function startDeckServer(opts = {}) {
|
|
|
1991
2067
|
res.end("Forbidden");
|
|
1992
2068
|
return;
|
|
1993
2069
|
}
|
|
1994
|
-
const filePath =
|
|
1995
|
-
if (!
|
|
2070
|
+
const filePath = import_node_path5.default.join(cwd, LAUNCHSECURE_DIR, "deck-files", relative);
|
|
2071
|
+
if (!import_node_fs5.default.existsSync(filePath) || !import_node_fs5.default.statSync(filePath).isFile()) {
|
|
1996
2072
|
res.writeHead(404);
|
|
1997
2073
|
res.end("Not found");
|
|
1998
2074
|
return;
|
|
1999
2075
|
}
|
|
2000
|
-
const ext =
|
|
2076
|
+
const ext = import_node_path5.default.extname(filePath).toLowerCase();
|
|
2001
2077
|
const mime = MIME_TYPES[ext] ?? "application/octet-stream";
|
|
2002
|
-
const filename =
|
|
2078
|
+
const filename = import_node_path5.default.basename(filePath);
|
|
2003
2079
|
res.writeHead(200, {
|
|
2004
2080
|
"Content-Type": mime,
|
|
2005
2081
|
"Content-Disposition": `attachment; filename="${filename}"`,
|
|
2006
2082
|
"Cache-Control": "no-cache"
|
|
2007
2083
|
});
|
|
2008
|
-
|
|
2084
|
+
import_node_fs5.default.createReadStream(filePath).pipe(res);
|
|
2009
2085
|
return;
|
|
2010
2086
|
}
|
|
2011
2087
|
if (url2.pathname !== "/") {
|
|
2012
|
-
const staticPath =
|
|
2088
|
+
const staticPath = import_node_path5.default.join(clientDir, url2.pathname);
|
|
2013
2089
|
if (serveStatic(res, staticPath)) return;
|
|
2014
2090
|
}
|
|
2015
2091
|
serveIndex(res, clientDir);
|
|
@@ -2108,13 +2184,13 @@ function runServeCli(argv) {
|
|
|
2108
2184
|
process.exit(1);
|
|
2109
2185
|
});
|
|
2110
2186
|
}
|
|
2111
|
-
var import_node_http,
|
|
2187
|
+
var import_node_http, import_node_fs5, import_node_path5, import_ws, DEFAULT_PORT, MAX_PORT_SCAN, MIME_TYPES, pendingFeedback, lastRenderError, wss;
|
|
2112
2188
|
var init_deck_serve = __esm({
|
|
2113
2189
|
"src/server/deck-serve.ts"() {
|
|
2114
2190
|
"use strict";
|
|
2115
2191
|
import_node_http = __toESM(require("node:http"));
|
|
2116
|
-
|
|
2117
|
-
|
|
2192
|
+
import_node_fs5 = __toESM(require("node:fs"));
|
|
2193
|
+
import_node_path5 = __toESM(require("node:path"));
|
|
2118
2194
|
import_ws = require("ws");
|
|
2119
2195
|
init_launch_kit_paths();
|
|
2120
2196
|
init_deck_lockfile();
|
|
@@ -2208,15 +2284,15 @@ async function handleTool(name, args) {
|
|
|
2208
2284
|
const baseUrl = `/deck-files/${sessionEncoded}`;
|
|
2209
2285
|
const html = generateBlastRadiusHtml(block.manifest, baseUrl);
|
|
2210
2286
|
const report = generateBlastRadiusReport(block.manifest);
|
|
2211
|
-
const dir = (0,
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2287
|
+
const dir = (0, import_node_path6.join)(projectRoot, LAUNCHSECURE_DIR, "deck-files", session);
|
|
2288
|
+
import_node_fs6.default.mkdirSync(dir, { recursive: true });
|
|
2289
|
+
import_node_fs6.default.writeFileSync((0, import_node_path6.join)(dir, "blast-radius.html"), html);
|
|
2290
|
+
import_node_fs6.default.writeFileSync((0, import_node_path6.join)(dir, "blast-radius-report.md"), report);
|
|
2291
|
+
import_node_fs6.default.writeFileSync((0, import_node_path6.join)(dir, "blast-radius-manifest.json"), JSON.stringify(block.manifest, null, 2));
|
|
2216
2292
|
const contractData = generateContract(block.manifest);
|
|
2217
2293
|
const contractMd = contractToMarkdown(contractData);
|
|
2218
|
-
|
|
2219
|
-
|
|
2294
|
+
import_node_fs6.default.writeFileSync((0, import_node_path6.join)(dir, "contract.json"), JSON.stringify(contractData, null, 2));
|
|
2295
|
+
import_node_fs6.default.writeFileSync((0, import_node_path6.join)(dir, "contract.md"), contractMd);
|
|
2220
2296
|
block.type = "iframe";
|
|
2221
2297
|
block.src = `${baseUrl}/blast-radius.html`;
|
|
2222
2298
|
delete block.manifest;
|
|
@@ -2243,9 +2319,9 @@ async function handleTool(name, args) {
|
|
|
2243
2319
|
const sessionEncoded = encodeURIComponent(session);
|
|
2244
2320
|
const baseUrl = `/deck-files/${sessionEncoded}`;
|
|
2245
2321
|
const filename = `${slugify(block.label)}.html`;
|
|
2246
|
-
const dir = (0,
|
|
2247
|
-
|
|
2248
|
-
|
|
2322
|
+
const dir = (0, import_node_path6.join)(projectRoot, LAUNCHSECURE_DIR, "deck-files", session);
|
|
2323
|
+
import_node_fs6.default.mkdirSync(dir, { recursive: true });
|
|
2324
|
+
import_node_fs6.default.writeFileSync((0, import_node_path6.join)(dir, filename), html);
|
|
2249
2325
|
block.type = "iframe";
|
|
2250
2326
|
block.src = `${baseUrl}/${filename}`;
|
|
2251
2327
|
delete block.content;
|
|
@@ -2339,11 +2415,11 @@ async function handleTool(name, args) {
|
|
|
2339
2415
|
}));
|
|
2340
2416
|
}
|
|
2341
2417
|
try {
|
|
2342
|
-
const logDir = (0,
|
|
2343
|
-
(0,
|
|
2344
|
-
const logPath = (0,
|
|
2345
|
-
const out = (0,
|
|
2346
|
-
const err = (0,
|
|
2418
|
+
const logDir = (0, import_node_path6.join)((0, import_node_os3.homedir)(), LAUNCHSECURE_DIR);
|
|
2419
|
+
(0, import_node_fs7.mkdirSync)(logDir, { recursive: true });
|
|
2420
|
+
const logPath = (0, import_node_path6.join)(logDir, "launch-deck.log");
|
|
2421
|
+
const out = (0, import_node_fs7.openSync)(logPath, "a");
|
|
2422
|
+
const err = (0, import_node_fs7.openSync)(logPath, "a");
|
|
2347
2423
|
const entryPath = process.argv[1];
|
|
2348
2424
|
const config = loadDeckConfig(projectRoot);
|
|
2349
2425
|
const resolvedPort = args.port ?? config.port;
|
|
@@ -2399,21 +2475,21 @@ async function handleTool(name, args) {
|
|
|
2399
2475
|
}
|
|
2400
2476
|
case "generate_contract": {
|
|
2401
2477
|
const session = args.session;
|
|
2402
|
-
const dir = (0,
|
|
2403
|
-
const manifestPath = (0,
|
|
2404
|
-
if (!
|
|
2478
|
+
const dir = (0, import_node_path6.join)(projectRoot, LAUNCHSECURE_DIR, "deck-files", session);
|
|
2479
|
+
const manifestPath = (0, import_node_path6.join)(dir, "blast-radius-manifest.json");
|
|
2480
|
+
if (!import_node_fs6.default.existsSync(manifestPath)) {
|
|
2405
2481
|
return text(JSON.stringify({
|
|
2406
2482
|
error: `No blast radius manifest found for session "${session}". Push a blast-radius block first.`,
|
|
2407
2483
|
hint: "Use the deck tool with a blast-radius block type to create a session."
|
|
2408
2484
|
}));
|
|
2409
2485
|
}
|
|
2410
2486
|
try {
|
|
2411
|
-
const raw =
|
|
2487
|
+
const raw = import_node_fs6.default.readFileSync(manifestPath, "utf-8");
|
|
2412
2488
|
const manifest = JSON.parse(raw);
|
|
2413
2489
|
const contract = generateContract(manifest);
|
|
2414
2490
|
const markdown = contractToMarkdown(contract);
|
|
2415
|
-
|
|
2416
|
-
|
|
2491
|
+
import_node_fs6.default.writeFileSync((0, import_node_path6.join)(dir, "contract.json"), JSON.stringify(contract, null, 2));
|
|
2492
|
+
import_node_fs6.default.writeFileSync((0, import_node_path6.join)(dir, "contract.md"), markdown);
|
|
2417
2493
|
return text(JSON.stringify(contract));
|
|
2418
2494
|
} catch (err) {
|
|
2419
2495
|
return text(JSON.stringify({ error: `Failed to generate contract: ${err}` }));
|
|
@@ -2504,16 +2580,16 @@ function startDeckMcpServer() {
|
|
|
2504
2580
|
process.exit(0);
|
|
2505
2581
|
});
|
|
2506
2582
|
}
|
|
2507
|
-
var import_node_http2,
|
|
2583
|
+
var import_node_http2, import_node_fs6, import_node_path6, import_node_child_process2, import_node_fs7, import_node_os3, SERVER_INFO, TOOLS;
|
|
2508
2584
|
var init_deck_mcp = __esm({
|
|
2509
2585
|
"src/server/deck-mcp.ts"() {
|
|
2510
2586
|
"use strict";
|
|
2511
2587
|
import_node_http2 = __toESM(require("node:http"));
|
|
2512
|
-
|
|
2513
|
-
|
|
2588
|
+
import_node_fs6 = __toESM(require("node:fs"));
|
|
2589
|
+
import_node_path6 = require("node:path");
|
|
2514
2590
|
import_node_child_process2 = require("node:child_process");
|
|
2515
|
-
|
|
2516
|
-
|
|
2591
|
+
import_node_fs7 = require("node:fs");
|
|
2592
|
+
import_node_os3 = require("node:os");
|
|
2517
2593
|
init_launch_kit_paths();
|
|
2518
2594
|
init_deck_lockfile();
|
|
2519
2595
|
init_deck_config();
|
|
@@ -2657,8 +2733,92 @@ var init_deck_mcp = __esm({
|
|
|
2657
2733
|
|
|
2658
2734
|
// src/server/deck-mcp-entry.ts
|
|
2659
2735
|
init_deck_lockfile();
|
|
2736
|
+
|
|
2737
|
+
// src/server/prune-npx-cache.ts
|
|
2738
|
+
var import_node_fs2 = require("node:fs");
|
|
2739
|
+
var import_node_os2 = require("node:os");
|
|
2740
|
+
var import_node_path2 = require("node:path");
|
|
2741
|
+
var import_node_util = require("node:util");
|
|
2742
|
+
var PKG = "@launchsecure/launch-kit";
|
|
2743
|
+
var readFileAsync = (0, import_node_util.promisify)(import_node_fs2.readFile);
|
|
2744
|
+
var readdirAsync = (0, import_node_util.promisify)(import_node_fs2.readdir);
|
|
2745
|
+
var rmAsync = (0, import_node_util.promisify)(import_node_fs2.rm);
|
|
2746
|
+
var realpathAsync = (0, import_node_util.promisify)(import_node_fs2.realpath);
|
|
2747
|
+
function npxCacheRoot() {
|
|
2748
|
+
const cache = process.env.npm_config_cache;
|
|
2749
|
+
if (cache && cache.trim()) return (0, import_node_path2.join)(cache, "_npx");
|
|
2750
|
+
if (process.platform === "win32") {
|
|
2751
|
+
const localAppData = process.env.LOCALAPPDATA;
|
|
2752
|
+
if (localAppData) return (0, import_node_path2.join)(localAppData, "npm-cache", "_npx");
|
|
2753
|
+
}
|
|
2754
|
+
return (0, import_node_path2.join)((0, import_node_os2.homedir)(), ".npm", "_npx");
|
|
2755
|
+
}
|
|
2756
|
+
function ownVersion() {
|
|
2757
|
+
let dir = __dirname;
|
|
2758
|
+
for (let i = 0; i < 8; i++) {
|
|
2759
|
+
try {
|
|
2760
|
+
const pkg = JSON.parse((0, import_node_fs2.readFileSync)((0, import_node_path2.join)(dir, "package.json"), "utf8"));
|
|
2761
|
+
if (pkg && pkg.name === PKG) return typeof pkg.version === "string" ? pkg.version : null;
|
|
2762
|
+
} catch {
|
|
2763
|
+
}
|
|
2764
|
+
const parent = (0, import_node_path2.dirname)(dir);
|
|
2765
|
+
if (parent === dir) break;
|
|
2766
|
+
dir = parent;
|
|
2767
|
+
}
|
|
2768
|
+
return null;
|
|
2769
|
+
}
|
|
2770
|
+
async function pruneStaleNpxCache() {
|
|
2771
|
+
try {
|
|
2772
|
+
const version = ownVersion();
|
|
2773
|
+
if (!version) return;
|
|
2774
|
+
const root = npxCacheRoot();
|
|
2775
|
+
let hashes;
|
|
2776
|
+
try {
|
|
2777
|
+
hashes = await readdirAsync(root);
|
|
2778
|
+
} catch {
|
|
2779
|
+
return;
|
|
2780
|
+
}
|
|
2781
|
+
const selfPath = await realpathAsync(process.argv[1] || __dirname).catch(() => __dirname);
|
|
2782
|
+
let reaped = 0;
|
|
2783
|
+
for (const hash of hashes) {
|
|
2784
|
+
const dir = (0, import_node_path2.join)(root, hash);
|
|
2785
|
+
if (selfPath === dir || selfPath.startsWith(dir + import_node_path2.sep)) continue;
|
|
2786
|
+
let ver;
|
|
2787
|
+
try {
|
|
2788
|
+
const lkPkg = JSON.parse(
|
|
2789
|
+
await readFileAsync((0, import_node_path2.join)(dir, "node_modules", PKG, "package.json"), "utf8")
|
|
2790
|
+
);
|
|
2791
|
+
ver = lkPkg.version;
|
|
2792
|
+
} catch {
|
|
2793
|
+
continue;
|
|
2794
|
+
}
|
|
2795
|
+
if (ver === version) continue;
|
|
2796
|
+
try {
|
|
2797
|
+
const top = JSON.parse(await readFileAsync((0, import_node_path2.join)(dir, "package.json"), "utf8"));
|
|
2798
|
+
const spec = top?.dependencies?.[PKG];
|
|
2799
|
+
if (typeof spec === "string" && spec.startsWith("file:")) continue;
|
|
2800
|
+
} catch {
|
|
2801
|
+
}
|
|
2802
|
+
try {
|
|
2803
|
+
await rmAsync(dir, { recursive: true, force: true });
|
|
2804
|
+
reaped++;
|
|
2805
|
+
} catch {
|
|
2806
|
+
}
|
|
2807
|
+
}
|
|
2808
|
+
if (reaped > 0) {
|
|
2809
|
+
process.stderr.write(
|
|
2810
|
+
`[launch-kit] npx-cache: reaped ${reaped} stale copy(ies), kept v${version}
|
|
2811
|
+
`
|
|
2812
|
+
);
|
|
2813
|
+
}
|
|
2814
|
+
} catch {
|
|
2815
|
+
}
|
|
2816
|
+
}
|
|
2817
|
+
|
|
2818
|
+
// src/server/deck-mcp-entry.ts
|
|
2660
2819
|
async function main() {
|
|
2661
2820
|
setProjectRoot(process.cwd());
|
|
2821
|
+
void pruneStaleNpxCache();
|
|
2662
2822
|
const argv = process.argv.slice(2);
|
|
2663
2823
|
const subcommand = argv[0];
|
|
2664
2824
|
if (subcommand === "serve") {
|