@launchsecure/launch-kit 0.0.25 → 0.0.27
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/README.md +50 -0
- package/dist/beacon/beacon.mjs +1016 -0
- package/dist/beacon/beacon.mjs.map +1 -0
- package/dist/beacon/beacon.umd.js +87 -0
- package/dist/beacon/beacon.umd.js.map +1 -0
- package/dist/beacon/index-DAIDnjfR.mjs +513 -0
- package/dist/beacon/index-DAIDnjfR.mjs.map +1 -0
- package/dist/beacon/types/capture/element.d.ts +3 -0
- package/dist/beacon/types/capture/element.d.ts.map +1 -0
- package/dist/beacon/types/capture/framework.d.ts +3 -0
- package/dist/beacon/types/capture/framework.d.ts.map +1 -0
- package/dist/beacon/types/capture/metadata.d.ts +3 -0
- package/dist/beacon/types/capture/metadata.d.ts.map +1 -0
- package/dist/beacon/types/capture/overlay.d.ts +7 -0
- package/dist/beacon/types/capture/overlay.d.ts.map +1 -0
- package/dist/beacon/types/capture/picker.d.ts +12 -0
- package/dist/beacon/types/capture/picker.d.ts.map +1 -0
- package/dist/beacon/types/capture/screenshot.d.ts +7 -0
- package/dist/beacon/types/capture/screenshot.d.ts.map +1 -0
- package/dist/beacon/types/capture/selector.d.ts +2 -0
- package/dist/beacon/types/capture/selector.d.ts.map +1 -0
- package/dist/beacon/types/element.d.ts +50 -0
- package/dist/beacon/types/element.d.ts.map +1 -0
- package/dist/beacon/types/index.d.ts +4 -0
- package/dist/beacon/types/index.d.ts.map +1 -0
- package/dist/beacon/types/transport/submit.d.ts +3 -0
- package/dist/beacon/types/transport/submit.d.ts.map +1 -0
- package/dist/beacon/types/types.d.ts +88 -0
- package/dist/beacon/types/types.d.ts.map +1 -0
- package/dist/beacon/types/ui/button.d.ts +2 -0
- package/dist/beacon/types/ui/button.d.ts.map +1 -0
- package/dist/beacon/types/ui/drawer.d.ts +31 -0
- package/dist/beacon/types/ui/drawer.d.ts.map +1 -0
- package/dist/beacon/types/ui/icons.d.ts +9 -0
- package/dist/beacon/types/ui/icons.d.ts.map +1 -0
- package/dist/beacon/types/ui/pick-mode-overlay.d.ts +25 -0
- package/dist/beacon/types/ui/pick-mode-overlay.d.ts.map +1 -0
- package/dist/beacon/types/ui/pin-popover.d.ts +14 -0
- package/dist/beacon/types/ui/pin-popover.d.ts.map +1 -0
- package/dist/chart-client/assets/index-CJ4mgRRF.css +1 -0
- package/dist/chart-client/assets/{index-C8ANseEa.js → index-Ccy-DpI-.js} +82 -73
- package/dist/chart-client/index.html +2 -2
- package/dist/client/assets/index-DI5qSR_w.css +32 -0
- package/dist/client/assets/index-Dp0_okva.js +294 -0
- package/dist/client/index.html +2 -2
- package/dist/council-client/assets/index-C_-vAM9L.css +1 -0
- package/dist/council-client/assets/{index-Dc41S-R2.js → index-Dt4zWKSj.js} +14 -14
- package/dist/council-client/index.html +2 -2
- package/dist/deck-client/assets/{_baseUniq-2gclQXo7.js → _baseUniq-W2JQDmje.js} +1 -1
- package/dist/deck-client/assets/{arc-DcMY5Wm0.js → arc-DIBWAId9.js} +1 -1
- package/dist/deck-client/assets/{architectureDiagram-Q4EWVU46-B8iirmmJ.js → architectureDiagram-Q4EWVU46-CAIRMvJK.js} +1 -1
- package/dist/deck-client/assets/{blockDiagram-DXYQGD6D-B4JBLjmJ.js → blockDiagram-DXYQGD6D-BeNaNiOi.js} +1 -1
- package/dist/deck-client/assets/{c4Diagram-AHTNJAMY-CojrJAk8.js → c4Diagram-AHTNJAMY-B9Ozi62h.js} +1 -1
- package/dist/deck-client/assets/channel-CRdozqbp.js +1 -0
- package/dist/deck-client/assets/{chunk-4BX2VUAB-Bmb_BMDo.js → chunk-4BX2VUAB-D7AZ47dt.js} +1 -1
- package/dist/deck-client/assets/{chunk-4TB4RGXK-CumBy8qe.js → chunk-4TB4RGXK-DnVnNPcI.js} +1 -1
- package/dist/deck-client/assets/{chunk-55IACEB6-Ka8Hb1wD.js → chunk-55IACEB6-UKYs-YNd.js} +1 -1
- package/dist/deck-client/assets/{chunk-EDXVE4YY-B3sIPiQo.js → chunk-EDXVE4YY-D43b-SKn.js} +1 -1
- package/dist/deck-client/assets/{chunk-FMBD7UC4-C1tYkaqu.js → chunk-FMBD7UC4-QzBAoyyW.js} +1 -1
- package/dist/deck-client/assets/{chunk-OYMX7WX6-D7Wacbky.js → chunk-OYMX7WX6-Cjif4r6W.js} +1 -1
- package/dist/deck-client/assets/{chunk-QZHKN3VN-ChXI0vO3.js → chunk-QZHKN3VN-CqLDirEI.js} +1 -1
- package/dist/deck-client/assets/{chunk-YZCP3GAM-BXhiqf8u.js → chunk-YZCP3GAM-_FQvmMs4.js} +1 -1
- package/dist/deck-client/assets/classDiagram-6PBFFD2Q-lIZMp57W.js +1 -0
- package/dist/deck-client/assets/classDiagram-v2-HSJHXN6E-lIZMp57W.js +1 -0
- package/dist/deck-client/assets/clone-BtWeSTyJ.js +1 -0
- package/dist/deck-client/assets/{cose-bilkent-S5V4N54A-Bqp3p68D.js → cose-bilkent-S5V4N54A-rfrocesE.js} +1 -1
- package/dist/deck-client/assets/{dagre-KV5264BT-BS-rtyhZ.js → dagre-KV5264BT-Bv_7DJat.js} +1 -1
- package/dist/deck-client/assets/{diagram-5BDNPKRD-BIrj9YGI.js → diagram-5BDNPKRD-4F1414G5.js} +1 -1
- package/dist/deck-client/assets/{diagram-G4DWMVQ6-noHWPIg4.js → diagram-G4DWMVQ6-C4-Pszqm.js} +1 -1
- package/dist/deck-client/assets/{diagram-MMDJMWI5-C2qHxvqV.js → diagram-MMDJMWI5-B647TIx9.js} +1 -1
- package/dist/deck-client/assets/{diagram-TYMM5635-BytnGQr-.js → diagram-TYMM5635-BFAqpezd.js} +1 -1
- package/dist/deck-client/assets/{erDiagram-SMLLAGMA-BfK5m2YQ.js → erDiagram-SMLLAGMA-BfBfrJOC.js} +1 -1
- package/dist/deck-client/assets/{flowDiagram-DWJPFMVM-Cq925G1Z.js → flowDiagram-DWJPFMVM-DX9YAYes.js} +1 -1
- package/dist/deck-client/assets/{ganttDiagram-T4ZO3ILL-DhhHPAmj.js → ganttDiagram-T4ZO3ILL-DCuiy7wF.js} +1 -1
- package/dist/deck-client/assets/{gitGraphDiagram-UUTBAWPF-B3Lc0h9q.js → gitGraphDiagram-UUTBAWPF-CGp1IXUh.js} +1 -1
- package/dist/deck-client/assets/{graph-RTawgVWm.js → graph-B7g8aoxv.js} +1 -1
- package/dist/deck-client/assets/{index-BfIfJXmS.js → index-Dg1r-WSN.js} +68 -68
- package/dist/deck-client/assets/index-DsIZ3LqL.css +1 -0
- package/dist/deck-client/assets/{infoDiagram-42DDH7IO-BlR584kX.js → infoDiagram-42DDH7IO-L3fahMkF.js} +1 -1
- package/dist/deck-client/assets/{ishikawaDiagram-UXIWVN3A-DygKoNGY.js → ishikawaDiagram-UXIWVN3A-aS_EjWBZ.js} +1 -1
- package/dist/deck-client/assets/{journeyDiagram-VCZTEJTY-BnaiYp9N.js → journeyDiagram-VCZTEJTY-djTSQZF9.js} +1 -1
- package/dist/deck-client/assets/{kanban-definition-6JOO6SKY-BQBUBzJC.js → kanban-definition-6JOO6SKY-CcTHo4CM.js} +1 -1
- package/dist/deck-client/assets/{layout-DeZ8HI1T.js → layout-mEJiadb7.js} +1 -1
- package/dist/deck-client/assets/{linear-C6roLi_9.js → linear-XgTKqyRu.js} +1 -1
- package/dist/deck-client/assets/{min-CbUksbuI.js → min-Ct9jZdpd.js} +1 -1
- package/dist/deck-client/assets/{mindmap-definition-QFDTVHPH-iNxV62yN.js → mindmap-definition-QFDTVHPH-BaFxCGNU.js} +1 -1
- package/dist/deck-client/assets/{pieDiagram-DEJITSTG-DHVA0jaG.js → pieDiagram-DEJITSTG-CIbYYjtw.js} +1 -1
- package/dist/deck-client/assets/{quadrantDiagram-34T5L4WZ-DBeKKLUQ.js → quadrantDiagram-34T5L4WZ-D9EtCOvh.js} +1 -1
- package/dist/deck-client/assets/{requirementDiagram-MS252O5E-CBwITx7p.js → requirementDiagram-MS252O5E-xeni9eVG.js} +1 -1
- package/dist/deck-client/assets/{sankeyDiagram-XADWPNL6-BtE-1YTU.js → sankeyDiagram-XADWPNL6-LYeknz9h.js} +1 -1
- package/dist/deck-client/assets/{sequenceDiagram-FGHM5R23-DN96yPP2.js → sequenceDiagram-FGHM5R23-RDbsKFZf.js} +1 -1
- package/dist/deck-client/assets/{stateDiagram-FHFEXIEX-VUkKC2uJ.js → stateDiagram-FHFEXIEX-BH1Zjglk.js} +1 -1
- package/dist/deck-client/assets/stateDiagram-v2-QKLJ7IA2-BrV78NDR.js +1 -0
- package/dist/deck-client/assets/{timeline-definition-GMOUNBTQ-oUeZhRns.js → timeline-definition-GMOUNBTQ-IFXxKptt.js} +1 -1
- package/dist/deck-client/assets/{vennDiagram-DHZGUBPP-D87fK90n.js → vennDiagram-DHZGUBPP-D-sLkQs9.js} +1 -1
- package/dist/deck-client/assets/wardley-RL74JXVD-C010F8l4.js +162 -0
- package/dist/deck-client/assets/{wardleyDiagram-NUSXRM2D-Ca_i0QRA.js → wardleyDiagram-NUSXRM2D-BTjjuDU3.js} +1 -1
- package/dist/deck-client/assets/{xychartDiagram-5P7HB3ND-CUOJVIvq.js → xychartDiagram-5P7HB3ND-AYbv92n-.js} +1 -1
- package/dist/deck-client/index.html +2 -2
- package/dist/server/chart-serve.js +4524 -3564
- package/dist/server/cli.js +27351 -5398
- package/dist/server/council-entry.js +17 -5
- package/dist/server/council-serve.js +8 -3
- package/dist/server/deck-mcp-entry.js +354 -13
- package/dist/server/deck-serve.js +298 -7
- package/dist/server/graph/queries/classify.scm +8 -0
- package/dist/server/graph/queries/exports.scm +7 -0
- package/dist/server/graph-mcp-entry.js +5943 -4361
- package/dist/server/init-entry.js +609 -0
- package/dist/server/orbit-entry.js +2272 -0
- package/dist/server/{server/chart-serve.js → parse-worker-entry.js} +1900 -1822
- package/dist/server/recall-entry.js +1450 -0
- package/package.json +40 -8
- package/scaffolds/migrate-safety/.github/workflows/backup-on-migration.yml +72 -0
- package/scaffolds/migrate-safety/docs/migrations-runbook.md +172 -0
- package/scaffolds/migrate-safety/scripts/migrate-with-backup.sh +294 -0
- package/dist/chart-client/assets/index--120d9P9.css +0 -1
- package/dist/client/assets/index-Bf8zdL3x.css +0 -32
- package/dist/client/assets/index-Ds9UP_cj.js +0 -291
- package/dist/council-client/assets/index-CofZh7pS.css +0 -1
- package/dist/deck-client/assets/channel-ERh5jKXV.js +0 -1
- package/dist/deck-client/assets/classDiagram-6PBFFD2Q-CMi1Gaev.js +0 -1
- package/dist/deck-client/assets/classDiagram-v2-HSJHXN6E-CMi1Gaev.js +0 -1
- package/dist/deck-client/assets/clone-DfWhlD4X.js +0 -1
- package/dist/deck-client/assets/index-765AIQ9z.css +0 -1
- package/dist/deck-client/assets/stateDiagram-v2-QKLJ7IA2-CA0IjulK.js +0 -1
- package/dist/deck-client/assets/wardley-RL74JXVD-DYbYcpDp.js +0 -162
- package/dist/server/deck-server/deck-mcp-entry.js +0 -1789
- package/dist/server/deck-server/deck-serve.js +0 -1275
- package/dist/server/server/cli.js +0 -13360
- package/dist/server/server/fb-wizard.js +0 -136
- package/dist/server/server/graph-mcp-entry.js +0 -6776
|
@@ -31,9 +31,18 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
31
31
|
));
|
|
32
32
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
33
33
|
|
|
34
|
+
// src/server/launch-kit-paths.ts
|
|
35
|
+
var LAUNCHSECURE_DIR;
|
|
36
|
+
var init_launch_kit_paths = __esm({
|
|
37
|
+
"src/server/launch-kit-paths.ts"() {
|
|
38
|
+
"use strict";
|
|
39
|
+
LAUNCHSECURE_DIR = ".launchsecure";
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
|
|
34
43
|
// src/server/council-lockfile.ts
|
|
35
44
|
function lockDir(projectRoot) {
|
|
36
|
-
return projectRoot ? (0, import_node_path.join)(projectRoot,
|
|
45
|
+
return projectRoot ? (0, import_node_path.join)(projectRoot, LAUNCHSECURE_DIR) : (0, import_node_path.join)((0, import_node_os.homedir)(), LAUNCHSECURE_DIR);
|
|
37
46
|
}
|
|
38
47
|
function lockPath(projectRoot) {
|
|
39
48
|
return (0, import_node_path.join)(lockDir(projectRoot), "launch-council.lock");
|
|
@@ -111,6 +120,7 @@ var init_council_lockfile = __esm({
|
|
|
111
120
|
import_node_fs = require("node:fs");
|
|
112
121
|
import_node_os = require("node:os");
|
|
113
122
|
import_node_path = require("node:path");
|
|
123
|
+
init_launch_kit_paths();
|
|
114
124
|
}
|
|
115
125
|
});
|
|
116
126
|
|
|
@@ -446,7 +456,7 @@ Be specific with search terms \u2014 use actual names that would appear in code
|
|
|
446
456
|
|
|
447
457
|
// src/server/graph-reader.ts
|
|
448
458
|
function readGraphLayer(projectRoot, layer) {
|
|
449
|
-
const filePath = (0, import_node_path4.join)(projectRoot,
|
|
459
|
+
const filePath = (0, import_node_path4.join)(projectRoot, LAUNCHSECURE_DIR, GRAPHS_SUBDIR, `${layer}.json`);
|
|
450
460
|
if (!(0, import_node_fs4.existsSync)(filePath)) return null;
|
|
451
461
|
try {
|
|
452
462
|
return JSON.parse((0, import_node_fs4.readFileSync)(filePath, "utf-8"));
|
|
@@ -503,13 +513,14 @@ function searchGraph(projectRoot, searchTerms, layers = ["ui", "api", "db"]) {
|
|
|
503
513
|
layers: usedLayers
|
|
504
514
|
};
|
|
505
515
|
}
|
|
506
|
-
var import_node_fs4, import_node_path4,
|
|
516
|
+
var import_node_fs4, import_node_path4, GRAPHS_SUBDIR;
|
|
507
517
|
var init_graph_reader = __esm({
|
|
508
518
|
"src/server/graph-reader.ts"() {
|
|
509
519
|
"use strict";
|
|
510
520
|
import_node_fs4 = require("node:fs");
|
|
511
521
|
import_node_path4 = require("node:path");
|
|
512
|
-
|
|
522
|
+
init_launch_kit_paths();
|
|
523
|
+
GRAPHS_SUBDIR = "graphs";
|
|
513
524
|
}
|
|
514
525
|
});
|
|
515
526
|
|
|
@@ -1186,7 +1197,7 @@ async function handleTool(name, args) {
|
|
|
1186
1197
|
}));
|
|
1187
1198
|
}
|
|
1188
1199
|
try {
|
|
1189
|
-
const logDir = (0, import_node_path6.join)((0, import_node_os2.homedir)(),
|
|
1200
|
+
const logDir = (0, import_node_path6.join)((0, import_node_os2.homedir)(), LAUNCHSECURE_DIR);
|
|
1190
1201
|
(0, import_node_fs6.mkdirSync)(logDir, { recursive: true });
|
|
1191
1202
|
const logPath = (0, import_node_path6.join)(logDir, "launch-council.log");
|
|
1192
1203
|
const out = (0, import_node_fs6.openSync)(logPath, "a");
|
|
@@ -1326,6 +1337,7 @@ var init_council_mcp = __esm({
|
|
|
1326
1337
|
import_node_child_process3 = require("node:child_process");
|
|
1327
1338
|
import_node_fs6 = require("node:fs");
|
|
1328
1339
|
import_node_os2 = require("node:os");
|
|
1340
|
+
init_launch_kit_paths();
|
|
1329
1341
|
init_council_lockfile();
|
|
1330
1342
|
init_council_config();
|
|
1331
1343
|
SERVER_INFO = {
|
|
@@ -152,8 +152,13 @@ var import_node_child_process = require("node:child_process");
|
|
|
152
152
|
var import_node_fs = require("node:fs");
|
|
153
153
|
var import_node_os = require("node:os");
|
|
154
154
|
var import_node_path = require("node:path");
|
|
155
|
+
|
|
156
|
+
// src/server/launch-kit-paths.ts
|
|
157
|
+
var LAUNCHSECURE_DIR = ".launchsecure";
|
|
158
|
+
|
|
159
|
+
// src/server/council-lockfile.ts
|
|
155
160
|
function lockDir(projectRoot) {
|
|
156
|
-
return projectRoot ? (0, import_node_path.join)(projectRoot,
|
|
161
|
+
return projectRoot ? (0, import_node_path.join)(projectRoot, LAUNCHSECURE_DIR) : (0, import_node_path.join)((0, import_node_os.homedir)(), LAUNCHSECURE_DIR);
|
|
157
162
|
}
|
|
158
163
|
function lockPath(projectRoot) {
|
|
159
164
|
return (0, import_node_path.join)(lockDir(projectRoot), "launch-council.lock");
|
|
@@ -531,9 +536,9 @@ async function extractIntent(adapter, discussionContent) {
|
|
|
531
536
|
// src/server/graph-reader.ts
|
|
532
537
|
var import_node_fs4 = require("node:fs");
|
|
533
538
|
var import_node_path4 = require("node:path");
|
|
534
|
-
var
|
|
539
|
+
var GRAPHS_SUBDIR = "graphs";
|
|
535
540
|
function readGraphLayer(projectRoot, layer) {
|
|
536
|
-
const filePath = (0, import_node_path4.join)(projectRoot,
|
|
541
|
+
const filePath = (0, import_node_path4.join)(projectRoot, LAUNCHSECURE_DIR, GRAPHS_SUBDIR, `${layer}.json`);
|
|
537
542
|
if (!(0, import_node_fs4.existsSync)(filePath)) return null;
|
|
538
543
|
try {
|
|
539
544
|
return JSON.parse((0, import_node_fs4.readFileSync)(filePath, "utf-8"));
|
|
@@ -30,12 +30,21 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
30
30
|
mod
|
|
31
31
|
));
|
|
32
32
|
|
|
33
|
+
// src/server/launch-kit-paths.ts
|
|
34
|
+
var LAUNCHSECURE_DIR;
|
|
35
|
+
var init_launch_kit_paths = __esm({
|
|
36
|
+
"src/server/launch-kit-paths.ts"() {
|
|
37
|
+
"use strict";
|
|
38
|
+
LAUNCHSECURE_DIR = ".launchsecure";
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
|
|
33
42
|
// src/server/deck-lockfile.ts
|
|
34
43
|
function lockDir(projectRoot) {
|
|
35
44
|
if (projectRoot) {
|
|
36
|
-
return (0, import_node_path.join)(projectRoot,
|
|
45
|
+
return (0, import_node_path.join)(projectRoot, LAUNCHSECURE_DIR);
|
|
37
46
|
}
|
|
38
|
-
return (0, import_node_path.join)((0, import_node_os.homedir)(),
|
|
47
|
+
return (0, import_node_path.join)((0, import_node_os.homedir)(), LAUNCHSECURE_DIR);
|
|
39
48
|
}
|
|
40
49
|
function lockPath(projectRoot) {
|
|
41
50
|
return (0, import_node_path.join)(lockDir(projectRoot), "launch-deck.lock");
|
|
@@ -113,6 +122,7 @@ var init_deck_lockfile = __esm({
|
|
|
113
122
|
import_node_fs = require("node:fs");
|
|
114
123
|
import_node_os = require("node:os");
|
|
115
124
|
import_node_path = require("node:path");
|
|
125
|
+
init_launch_kit_paths();
|
|
116
126
|
}
|
|
117
127
|
});
|
|
118
128
|
|
|
@@ -892,6 +902,277 @@ var init_contract_generator = __esm({
|
|
|
892
902
|
}
|
|
893
903
|
});
|
|
894
904
|
|
|
905
|
+
// src/server/rich-html-render.ts
|
|
906
|
+
function renderRichHtml(opts) {
|
|
907
|
+
const theme = opts.theme ?? "light";
|
|
908
|
+
const title = escapeHtml(opts.title ?? "LaunchDeck");
|
|
909
|
+
if (opts.framework === "wired") {
|
|
910
|
+
return renderWired(opts.content, theme, title);
|
|
911
|
+
}
|
|
912
|
+
if (opts.framework === "reveal") {
|
|
913
|
+
return renderReveal(opts.content, theme, title);
|
|
914
|
+
}
|
|
915
|
+
return opts.content;
|
|
916
|
+
}
|
|
917
|
+
function themeResolverScript(initial) {
|
|
918
|
+
return `<script>
|
|
919
|
+
(function () {
|
|
920
|
+
function applyTheme(t) {
|
|
921
|
+
if (t !== 'light' && t !== 'dark') return;
|
|
922
|
+
var prev = document.documentElement.dataset.theme;
|
|
923
|
+
document.documentElement.dataset.theme = t;
|
|
924
|
+
if (prev !== t) {
|
|
925
|
+
document.dispatchEvent(new CustomEvent('deck-theme', { detail: t }));
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
// 1) initial preference: URL > prefers-color-scheme (standalone) > baked-in default
|
|
929
|
+
var url = new URL(window.location.href);
|
|
930
|
+
var fromUrl = url.searchParams.get('theme');
|
|
931
|
+
if (fromUrl === 'light' || fromUrl === 'dark') {
|
|
932
|
+
applyTheme(fromUrl);
|
|
933
|
+
} else if (window.parent === window) {
|
|
934
|
+
var prefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
935
|
+
applyTheme(prefersDark ? 'dark' : 'light');
|
|
936
|
+
} else {
|
|
937
|
+
applyTheme(${JSON.stringify(initial)});
|
|
938
|
+
}
|
|
939
|
+
// 2) live updates from parent deck
|
|
940
|
+
window.addEventListener('message', function (e) {
|
|
941
|
+
if (e.data && e.data.type === 'deck-theme') applyTheme(e.data.theme);
|
|
942
|
+
});
|
|
943
|
+
// 3) tell parent we are ready so it can push the current theme back
|
|
944
|
+
if (window.parent !== window) {
|
|
945
|
+
window.parent.postMessage({ type: 'deck-iframe-ready' }, '*');
|
|
946
|
+
}
|
|
947
|
+
})();
|
|
948
|
+
</script>`;
|
|
949
|
+
}
|
|
950
|
+
function renderWired(body, initialTheme, title) {
|
|
951
|
+
const LIGHT = { bg: "#ffffff", fg: "#18181b", accent: "#7c3aed", cardBg: "#ffffff" };
|
|
952
|
+
const DARK = { bg: "#0e0e10", fg: "#e4e4e7", accent: "#a78bfa", cardBg: "#1a1a1d" };
|
|
953
|
+
const wiredVarsBlock = (vars) => `
|
|
954
|
+
--wired-card-background-fill: ${vars.cardBg};
|
|
955
|
+
--wired-button-color: ${vars.fg};
|
|
956
|
+
--wired-combo-popup-bg: ${vars.cardBg};
|
|
957
|
+
--wired-progress-color: ${vars.accent};
|
|
958
|
+
--wired-progress-label-background: ${vars.cardBg};
|
|
959
|
+
--wired-progress-label-color: ${vars.fg};
|
|
960
|
+
`;
|
|
961
|
+
return `<!DOCTYPE html>
|
|
962
|
+
<html lang="en" data-theme="${initialTheme}">
|
|
963
|
+
<head>
|
|
964
|
+
<meta charset="utf-8">
|
|
965
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
966
|
+
<title>${title}</title>
|
|
967
|
+
<script type="module" src="${WIRED_CDN}"></script>
|
|
968
|
+
<link href="https://fonts.googleapis.com/css2?family=Gloria+Hallelujah&family=DM+Sans:wght@400;600;700&display=swap" rel="stylesheet">
|
|
969
|
+
<style>
|
|
970
|
+
*, *::before, *::after { box-sizing: border-box; }
|
|
971
|
+
html, body {
|
|
972
|
+
margin: 0;
|
|
973
|
+
min-height: 100%;
|
|
974
|
+
font-family: 'Gloria Hallelujah', 'DM Sans', system-ui, sans-serif;
|
|
975
|
+
background: var(--page-bg);
|
|
976
|
+
color: var(--page-fg);
|
|
977
|
+
transition: background 0.15s, color 0.15s;
|
|
978
|
+
}
|
|
979
|
+
body { padding: 24px; }
|
|
980
|
+
h1, h2, h3, h4 { font-family: 'Gloria Hallelujah', cursive; margin: 0.5em 0; color: var(--page-fg); }
|
|
981
|
+
a { color: var(--page-accent); }
|
|
982
|
+
.row { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; margin: 8px 0; }
|
|
983
|
+
.col { display: flex; flex-direction: column; gap: 12px; align-items: stretch; }
|
|
984
|
+
.card { padding: 16px; }
|
|
985
|
+
|
|
986
|
+
/* Light theme */
|
|
987
|
+
:root[data-theme="light"] {
|
|
988
|
+
--page-bg: ${LIGHT.bg};
|
|
989
|
+
--page-fg: ${LIGHT.fg};
|
|
990
|
+
--page-accent: ${LIGHT.accent};
|
|
991
|
+
${wiredVarsBlock(LIGHT)}
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
/* Dark theme */
|
|
995
|
+
:root[data-theme="dark"] {
|
|
996
|
+
--page-bg: ${DARK.bg};
|
|
997
|
+
--page-fg: ${DARK.fg};
|
|
998
|
+
--page-accent: ${DARK.accent};
|
|
999
|
+
${wiredVarsBlock(DARK)}
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
/* Hosts: text color inherits via component "color: inherit" rules.
|
|
1003
|
+
Transparent background lets the page bg show through where the
|
|
1004
|
+
rough.js rectangle leaves space. */
|
|
1005
|
+
wired-button, wired-card, wired-checkbox, wired-radio, wired-toggle,
|
|
1006
|
+
wired-input, wired-textarea, wired-search-input, wired-combo, wired-item,
|
|
1007
|
+
wired-listbox, wired-link, wired-tabs, wired-tab, wired-fab,
|
|
1008
|
+
wired-icon-button, wired-divider, wired-progress, wired-slider,
|
|
1009
|
+
wired-calendar, wired-dialog {
|
|
1010
|
+
color: var(--page-fg);
|
|
1011
|
+
background: transparent;
|
|
1012
|
+
}
|
|
1013
|
+
</style>
|
|
1014
|
+
</head>
|
|
1015
|
+
<body>
|
|
1016
|
+
${body}
|
|
1017
|
+
${themeResolverScript(initialTheme)}
|
|
1018
|
+
<script type="module">
|
|
1019
|
+
// wired-input / wired-textarea / wired-search-input render their native
|
|
1020
|
+
// <input>/<textarea> INSIDE shadow DOM. Outer CSS cannot reach those, and
|
|
1021
|
+
// the native control has appearance:auto which the UA repaints over any
|
|
1022
|
+
// "background: transparent" rule. We must set inline styles directly on
|
|
1023
|
+
// the inner element with !important.
|
|
1024
|
+
//
|
|
1025
|
+
// We register one applier per theme. Re-runs when theme changes or new
|
|
1026
|
+
// nodes are added so the page reacts live to the deck sun/moon toggle.
|
|
1027
|
+
const FG = { light: ${JSON.stringify(LIGHT.fg)}, dark: ${JSON.stringify(DARK.fg)} };
|
|
1028
|
+
const TAGS = ['wired-input', 'wired-textarea', 'wired-search-input'];
|
|
1029
|
+
const DARK_PROPS = [
|
|
1030
|
+
'appearance', '-webkit-appearance',
|
|
1031
|
+
'background', 'background-color',
|
|
1032
|
+
'color', '-webkit-text-fill-color', 'caret-color',
|
|
1033
|
+
'border', 'outline',
|
|
1034
|
+
];
|
|
1035
|
+
|
|
1036
|
+
function applyDark(node) {
|
|
1037
|
+
const s = node.style;
|
|
1038
|
+
s.setProperty('appearance', 'none', 'important');
|
|
1039
|
+
s.setProperty('-webkit-appearance', 'none', 'important');
|
|
1040
|
+
s.setProperty('background', 'transparent', 'important');
|
|
1041
|
+
s.setProperty('background-color', 'transparent', 'important');
|
|
1042
|
+
s.setProperty('color', FG.dark, 'important');
|
|
1043
|
+
s.setProperty('-webkit-text-fill-color', FG.dark, 'important');
|
|
1044
|
+
s.setProperty('caret-color', FG.dark, 'important');
|
|
1045
|
+
s.setProperty('border', 'none', 'important');
|
|
1046
|
+
s.setProperty('outline', 'none', 'important');
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
function applyLight(node) {
|
|
1050
|
+
DARK_PROPS.forEach((p) => node.style.removeProperty(p));
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
function placeholderStyle(host, theme) {
|
|
1054
|
+
const existing = host.shadowRoot.querySelector('style[data-deck-theme]');
|
|
1055
|
+
if (existing) existing.remove();
|
|
1056
|
+
if (theme !== 'dark') return;
|
|
1057
|
+
const style = document.createElement('style');
|
|
1058
|
+
style.dataset.deckTheme = '1';
|
|
1059
|
+
style.textContent =
|
|
1060
|
+
'::placeholder{color:' + FG.dark + '99 !important;' +
|
|
1061
|
+
'-webkit-text-fill-color:' + FG.dark + '99 !important;}';
|
|
1062
|
+
host.shadowRoot.appendChild(style);
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
function sweepOnce() {
|
|
1066
|
+
const theme = document.documentElement.dataset.theme;
|
|
1067
|
+
for (const tag of TAGS) {
|
|
1068
|
+
for (const host of document.querySelectorAll(tag)) {
|
|
1069
|
+
if (!host.shadowRoot) continue;
|
|
1070
|
+
const inner = host.shadowRoot.querySelector('input, textarea');
|
|
1071
|
+
if (!inner) continue;
|
|
1072
|
+
if (theme === 'dark') applyDark(inner);
|
|
1073
|
+
else applyLight(inner);
|
|
1074
|
+
placeholderStyle(host, theme);
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
// Initial + late-upgrade catch (CDN script loads async).
|
|
1080
|
+
sweepOnce();
|
|
1081
|
+
let elapsed = 0;
|
|
1082
|
+
function tick() {
|
|
1083
|
+
sweepOnce();
|
|
1084
|
+
elapsed += 100;
|
|
1085
|
+
if (elapsed < 3000) setTimeout(tick, 100);
|
|
1086
|
+
}
|
|
1087
|
+
setTimeout(tick, 100);
|
|
1088
|
+
|
|
1089
|
+
// Re-sweep on theme change.
|
|
1090
|
+
document.addEventListener('deck-theme', sweepOnce);
|
|
1091
|
+
// Re-sweep when new nodes are added.
|
|
1092
|
+
new MutationObserver(sweepOnce).observe(document.body, { subtree: true, childList: true });
|
|
1093
|
+
|
|
1094
|
+
// whenDefined fires when each tag is registered \u2014 allSettled-style, never hangs.
|
|
1095
|
+
TAGS.forEach((tag) => {
|
|
1096
|
+
customElements.whenDefined(tag).then(sweepOnce).catch(() => {});
|
|
1097
|
+
});
|
|
1098
|
+
</script>
|
|
1099
|
+
</body>
|
|
1100
|
+
</html>`;
|
|
1101
|
+
}
|
|
1102
|
+
function renderReveal(content, initialTheme, title) {
|
|
1103
|
+
const slides = content.includes("<section") ? content : content.split(/\n\s*---\s*\n/).map((md) => `<section data-markdown><textarea data-template>
|
|
1104
|
+
${md.trim()}
|
|
1105
|
+
</textarea></section>`).join("\n");
|
|
1106
|
+
return `<!DOCTYPE html>
|
|
1107
|
+
<html lang="en" data-theme="${initialTheme}">
|
|
1108
|
+
<head>
|
|
1109
|
+
<meta charset="utf-8">
|
|
1110
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
1111
|
+
<title>${title}</title>
|
|
1112
|
+
<link rel="stylesheet" href="${REVEAL_CSS}">
|
|
1113
|
+
<link id="reveal-theme-light" rel="stylesheet" href="${REVEAL_THEME("light")}" ${initialTheme === "dark" ? "disabled" : ""}>
|
|
1114
|
+
<link id="reveal-theme-dark" rel="stylesheet" href="${REVEAL_THEME("dark")}" ${initialTheme === "dark" ? "" : "disabled"}>
|
|
1115
|
+
<style>
|
|
1116
|
+
html, body { margin: 0; height: 100%; }
|
|
1117
|
+
.reveal .slides { text-align: left; }
|
|
1118
|
+
.reveal .slides section { padding: 0 32px; }
|
|
1119
|
+
</style>
|
|
1120
|
+
</head>
|
|
1121
|
+
<body>
|
|
1122
|
+
<div class="reveal">
|
|
1123
|
+
<div class="slides">
|
|
1124
|
+
${slides}
|
|
1125
|
+
</div>
|
|
1126
|
+
</div>
|
|
1127
|
+
<script src="${REVEAL_JS}"></script>
|
|
1128
|
+
<script src="${REVEAL_MD}"></script>
|
|
1129
|
+
<script src="${REVEAL_HL}"></script>
|
|
1130
|
+
<script src="${REVEAL_NOTES}"></script>
|
|
1131
|
+
<script>
|
|
1132
|
+
Reveal.initialize({
|
|
1133
|
+
hash: true,
|
|
1134
|
+
slideNumber: 'c/t',
|
|
1135
|
+
controls: true,
|
|
1136
|
+
progress: true,
|
|
1137
|
+
transition: 'slide',
|
|
1138
|
+
plugins: [RevealMarkdown, RevealHighlight, RevealNotes],
|
|
1139
|
+
});
|
|
1140
|
+
// React to theme changes: flip which stylesheet is enabled.
|
|
1141
|
+
function syncRevealTheme() {
|
|
1142
|
+
var dark = document.documentElement.dataset.theme === 'dark';
|
|
1143
|
+
var lightLink = document.getElementById('reveal-theme-light');
|
|
1144
|
+
var darkLink = document.getElementById('reveal-theme-dark');
|
|
1145
|
+
if (lightLink) lightLink.disabled = dark;
|
|
1146
|
+
if (darkLink) darkLink.disabled = !dark;
|
|
1147
|
+
}
|
|
1148
|
+
document.addEventListener('deck-theme', syncRevealTheme);
|
|
1149
|
+
syncRevealTheme();
|
|
1150
|
+
</script>
|
|
1151
|
+
${themeResolverScript(initialTheme)}
|
|
1152
|
+
</body>
|
|
1153
|
+
</html>`;
|
|
1154
|
+
}
|
|
1155
|
+
function escapeHtml(s) {
|
|
1156
|
+
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
1157
|
+
}
|
|
1158
|
+
function slugify(label) {
|
|
1159
|
+
return label.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || "block";
|
|
1160
|
+
}
|
|
1161
|
+
var WIRED_CDN, REVEAL_VER, REVEAL_CSS, REVEAL_THEME, REVEAL_JS, REVEAL_MD, REVEAL_HL, REVEAL_NOTES;
|
|
1162
|
+
var init_rich_html_render = __esm({
|
|
1163
|
+
"src/server/rich-html-render.ts"() {
|
|
1164
|
+
"use strict";
|
|
1165
|
+
WIRED_CDN = "https://unpkg.com/wired-elements?module";
|
|
1166
|
+
REVEAL_VER = "5.1.0";
|
|
1167
|
+
REVEAL_CSS = `https://cdn.jsdelivr.net/npm/reveal.js@${REVEAL_VER}/dist/reveal.css`;
|
|
1168
|
+
REVEAL_THEME = (t) => `https://cdn.jsdelivr.net/npm/reveal.js@${REVEAL_VER}/dist/theme/${t === "dark" ? "black" : "white"}.css`;
|
|
1169
|
+
REVEAL_JS = `https://cdn.jsdelivr.net/npm/reveal.js@${REVEAL_VER}/dist/reveal.js`;
|
|
1170
|
+
REVEAL_MD = `https://cdn.jsdelivr.net/npm/reveal.js@${REVEAL_VER}/plugin/markdown/markdown.js`;
|
|
1171
|
+
REVEAL_HL = `https://cdn.jsdelivr.net/npm/reveal.js@${REVEAL_VER}/plugin/highlight/highlight.js`;
|
|
1172
|
+
REVEAL_NOTES = `https://cdn.jsdelivr.net/npm/reveal.js@${REVEAL_VER}/plugin/notes/notes.js`;
|
|
1173
|
+
}
|
|
1174
|
+
});
|
|
1175
|
+
|
|
895
1176
|
// src/server/deck-serve.ts
|
|
896
1177
|
var deck_serve_exports = {};
|
|
897
1178
|
__export(deck_serve_exports, {
|
|
@@ -1051,7 +1332,7 @@ async function startDeckServer(opts = {}) {
|
|
|
1051
1332
|
const baseUrl = `/deck-files/${sessionEncoded}`;
|
|
1052
1333
|
const html = generateBlastRadiusHtml(block.manifest, baseUrl);
|
|
1053
1334
|
const report = generateBlastRadiusReport(block.manifest);
|
|
1054
|
-
const dir = import_node_path3.default.join(cwd,
|
|
1335
|
+
const dir = import_node_path3.default.join(cwd, LAUNCHSECURE_DIR, "deck-files", body.session);
|
|
1055
1336
|
import_node_fs3.default.mkdirSync(dir, { recursive: true });
|
|
1056
1337
|
import_node_fs3.default.writeFileSync(import_node_path3.default.join(dir, "blast-radius.html"), html);
|
|
1057
1338
|
import_node_fs3.default.writeFileSync(import_node_path3.default.join(dir, "blast-radius-report.md"), report);
|
|
@@ -1067,6 +1348,29 @@ async function startDeckServer(opts = {}) {
|
|
|
1067
1348
|
console.error("Failed to generate blast radius HTML:", err);
|
|
1068
1349
|
}
|
|
1069
1350
|
}
|
|
1351
|
+
if (block.type === "rich-html" && block.content) {
|
|
1352
|
+
try {
|
|
1353
|
+
const html = renderRichHtml({
|
|
1354
|
+
framework: block.framework ?? "raw",
|
|
1355
|
+
content: block.content,
|
|
1356
|
+
theme: block.theme,
|
|
1357
|
+
title: block.label
|
|
1358
|
+
});
|
|
1359
|
+
const sessionEncoded = encodeURIComponent(body.session);
|
|
1360
|
+
const baseUrl = `/deck-files/${sessionEncoded}`;
|
|
1361
|
+
const filename = `${slugify(block.label)}.html`;
|
|
1362
|
+
const dir = import_node_path3.default.join(cwd, LAUNCHSECURE_DIR, "deck-files", body.session);
|
|
1363
|
+
import_node_fs3.default.mkdirSync(dir, { recursive: true });
|
|
1364
|
+
import_node_fs3.default.writeFileSync(import_node_path3.default.join(dir, filename), html);
|
|
1365
|
+
block.type = "iframe";
|
|
1366
|
+
block.src = `${baseUrl}/${filename}`;
|
|
1367
|
+
delete block.content;
|
|
1368
|
+
delete block.framework;
|
|
1369
|
+
delete block.theme;
|
|
1370
|
+
} catch (err) {
|
|
1371
|
+
console.error("Failed to generate rich-html:", err);
|
|
1372
|
+
}
|
|
1373
|
+
}
|
|
1070
1374
|
}
|
|
1071
1375
|
broadcastToClients({
|
|
1072
1376
|
type: "session",
|
|
@@ -1103,7 +1407,7 @@ async function startDeckServer(opts = {}) {
|
|
|
1103
1407
|
resolveFeedback(session, { comment: "", closed: true });
|
|
1104
1408
|
}
|
|
1105
1409
|
try {
|
|
1106
|
-
const deckFilesBase = import_node_path3.default.join(cwd,
|
|
1410
|
+
const deckFilesBase = import_node_path3.default.join(cwd, LAUNCHSECURE_DIR, "deck-files");
|
|
1107
1411
|
if (session === "all") {
|
|
1108
1412
|
if (import_node_fs3.default.existsSync(deckFilesBase)) {
|
|
1109
1413
|
import_node_fs3.default.rmSync(deckFilesBase, { recursive: true, force: true });
|
|
@@ -1131,7 +1435,7 @@ async function startDeckServer(opts = {}) {
|
|
|
1131
1435
|
res.end("Forbidden");
|
|
1132
1436
|
return;
|
|
1133
1437
|
}
|
|
1134
|
-
const filePath = import_node_path3.default.join(cwd,
|
|
1438
|
+
const filePath = import_node_path3.default.join(cwd, LAUNCHSECURE_DIR, "deck-files", relative);
|
|
1135
1439
|
if (serveStatic(res, filePath)) return;
|
|
1136
1440
|
res.writeHead(404);
|
|
1137
1441
|
res.end("Not found");
|
|
@@ -1144,7 +1448,7 @@ async function startDeckServer(opts = {}) {
|
|
|
1144
1448
|
res.end("Forbidden");
|
|
1145
1449
|
return;
|
|
1146
1450
|
}
|
|
1147
|
-
const filePath = import_node_path3.default.join(cwd,
|
|
1451
|
+
const filePath = import_node_path3.default.join(cwd, LAUNCHSECURE_DIR, "deck-files", relative);
|
|
1148
1452
|
if (!import_node_fs3.default.existsSync(filePath) || !import_node_fs3.default.statSync(filePath).isFile()) {
|
|
1149
1453
|
res.writeHead(404);
|
|
1150
1454
|
res.end("Not found");
|
|
@@ -1229,7 +1533,7 @@ async function startDeckServer(opts = {}) {
|
|
|
1229
1533
|
pendingFeedback.delete(id);
|
|
1230
1534
|
}
|
|
1231
1535
|
try {
|
|
1232
|
-
const deckFilesBase = import_node_path3.default.join(cwd,
|
|
1536
|
+
const deckFilesBase = import_node_path3.default.join(cwd, LAUNCHSECURE_DIR, "deck-files");
|
|
1233
1537
|
if (import_node_fs3.default.existsSync(deckFilesBase)) {
|
|
1234
1538
|
import_node_fs3.default.rmSync(deckFilesBase, { recursive: true, force: true });
|
|
1235
1539
|
}
|
|
@@ -1276,10 +1580,12 @@ var init_deck_serve = __esm({
|
|
|
1276
1580
|
import_node_fs3 = __toESM(require("node:fs"));
|
|
1277
1581
|
import_node_path3 = __toESM(require("node:path"));
|
|
1278
1582
|
import_ws = require("ws");
|
|
1583
|
+
init_launch_kit_paths();
|
|
1279
1584
|
init_deck_lockfile();
|
|
1280
1585
|
init_deck_config();
|
|
1281
1586
|
init_blast_radius_render();
|
|
1282
1587
|
init_contract_generator();
|
|
1588
|
+
init_rich_html_render();
|
|
1283
1589
|
DEFAULT_PORT = 52829;
|
|
1284
1590
|
MAX_PORT_SCAN = 3;
|
|
1285
1591
|
MIME_TYPES = {
|
|
@@ -1365,7 +1671,7 @@ async function handleTool(name, args) {
|
|
|
1365
1671
|
const baseUrl = `/deck-files/${sessionEncoded}`;
|
|
1366
1672
|
const html = generateBlastRadiusHtml(block.manifest, baseUrl);
|
|
1367
1673
|
const report = generateBlastRadiusReport(block.manifest);
|
|
1368
|
-
const dir = (0, import_node_path4.join)(projectRoot,
|
|
1674
|
+
const dir = (0, import_node_path4.join)(projectRoot, LAUNCHSECURE_DIR, "deck-files", session);
|
|
1369
1675
|
import_node_fs4.default.mkdirSync(dir, { recursive: true });
|
|
1370
1676
|
import_node_fs4.default.writeFileSync((0, import_node_path4.join)(dir, "blast-radius.html"), html);
|
|
1371
1677
|
import_node_fs4.default.writeFileSync((0, import_node_path4.join)(dir, "blast-radius-report.md"), report);
|
|
@@ -1381,6 +1687,29 @@ async function handleTool(name, args) {
|
|
|
1381
1687
|
return text(JSON.stringify({ error: `Failed to generate blast radius HTML: ${err}` }));
|
|
1382
1688
|
}
|
|
1383
1689
|
}
|
|
1690
|
+
if (block.type === "rich-html" && block.content) {
|
|
1691
|
+
try {
|
|
1692
|
+
const html = renderRichHtml({
|
|
1693
|
+
framework: block.framework ?? "raw",
|
|
1694
|
+
content: block.content,
|
|
1695
|
+
theme: block.theme,
|
|
1696
|
+
title: block.label
|
|
1697
|
+
});
|
|
1698
|
+
const sessionEncoded = encodeURIComponent(session);
|
|
1699
|
+
const baseUrl = `/deck-files/${sessionEncoded}`;
|
|
1700
|
+
const filename = `${slugify(block.label)}.html`;
|
|
1701
|
+
const dir = (0, import_node_path4.join)(projectRoot, LAUNCHSECURE_DIR, "deck-files", session);
|
|
1702
|
+
import_node_fs4.default.mkdirSync(dir, { recursive: true });
|
|
1703
|
+
import_node_fs4.default.writeFileSync((0, import_node_path4.join)(dir, filename), html);
|
|
1704
|
+
block.type = "iframe";
|
|
1705
|
+
block.src = `${baseUrl}/${filename}`;
|
|
1706
|
+
delete block.content;
|
|
1707
|
+
delete block.framework;
|
|
1708
|
+
delete block.theme;
|
|
1709
|
+
} catch (err) {
|
|
1710
|
+
return text(JSON.stringify({ error: `Failed to generate rich-html: ${err}` }));
|
|
1711
|
+
}
|
|
1712
|
+
}
|
|
1384
1713
|
}
|
|
1385
1714
|
try {
|
|
1386
1715
|
await httpPost(`${lock.url}/api/deck`, { session, mode, blocks, prompt });
|
|
@@ -1464,7 +1793,7 @@ async function handleTool(name, args) {
|
|
|
1464
1793
|
}));
|
|
1465
1794
|
}
|
|
1466
1795
|
try {
|
|
1467
|
-
const logDir = (0, import_node_path4.join)((0, import_node_os2.homedir)(),
|
|
1796
|
+
const logDir = (0, import_node_path4.join)((0, import_node_os2.homedir)(), LAUNCHSECURE_DIR);
|
|
1468
1797
|
(0, import_node_fs5.mkdirSync)(logDir, { recursive: true });
|
|
1469
1798
|
const logPath = (0, import_node_path4.join)(logDir, "launch-deck.log");
|
|
1470
1799
|
const out = (0, import_node_fs5.openSync)(logPath, "a");
|
|
@@ -1524,7 +1853,7 @@ async function handleTool(name, args) {
|
|
|
1524
1853
|
}
|
|
1525
1854
|
case "generate_contract": {
|
|
1526
1855
|
const session = args.session;
|
|
1527
|
-
const dir = (0, import_node_path4.join)(projectRoot,
|
|
1856
|
+
const dir = (0, import_node_path4.join)(projectRoot, LAUNCHSECURE_DIR, "deck-files", session);
|
|
1528
1857
|
const manifestPath = (0, import_node_path4.join)(dir, "blast-radius-manifest.json");
|
|
1529
1858
|
if (!import_node_fs4.default.existsSync(manifestPath)) {
|
|
1530
1859
|
return text(JSON.stringify({
|
|
@@ -1639,10 +1968,12 @@ var init_deck_mcp = __esm({
|
|
|
1639
1968
|
import_node_child_process2 = require("node:child_process");
|
|
1640
1969
|
import_node_fs5 = require("node:fs");
|
|
1641
1970
|
import_node_os2 = require("node:os");
|
|
1971
|
+
init_launch_kit_paths();
|
|
1642
1972
|
init_deck_lockfile();
|
|
1643
1973
|
init_deck_config();
|
|
1644
1974
|
init_blast_radius_render();
|
|
1645
1975
|
init_contract_generator();
|
|
1976
|
+
init_rich_html_render();
|
|
1646
1977
|
SERVER_INFO = {
|
|
1647
1978
|
name: "launch-deck",
|
|
1648
1979
|
version: "0.0.3"
|
|
@@ -1650,7 +1981,7 @@ var init_deck_mcp = __esm({
|
|
|
1650
1981
|
TOOLS = [
|
|
1651
1982
|
{
|
|
1652
1983
|
name: "deck",
|
|
1653
|
-
description: 'Push visual blocks (HTML, Mermaid diagrams, options, markdown) to the LaunchDeck browser.\n\nEach call creates a named session tab in the browser. Tabs accumulate \u2014 previous sessions are preserved.\n\nModes:\n- "show": Display content and return immediately. Terminal confirms delivery. No user feedback.\n- "feedback": Display content with an input bar for the user to respond. Returns immediately with session info. Call `await_feedback` with the same session ID to block until the user responds.\n\nBlock types:\n- html: Raw HTML/CSS (
|
|
1984
|
+
description: 'Push visual blocks (HTML, Mermaid diagrams, options, markdown) to the LaunchDeck browser.\n\nEach call creates a named session tab in the browser. Tabs accumulate \u2014 previous sessions are preserved.\n\nModes:\n- "show": Display content and return immediately. Terminal confirms delivery. No user feedback.\n- "feedback": Display content with an input bar for the user to respond. Returns immediately with session info. Call `await_feedback` with the same session ID to block until the user responds.\n\nBlock types:\n- html: Raw HTML/CSS (sandboxed iframe \u2014 NO scripts). Use for static markup only.\n- mermaid: Mermaid diagram DSL (flowchart, sequence, ERD, etc.)\n- markdown: Rendered markdown text\n- options: Selection cards \u2014 user picks one or more\n- blast-radius: Interactive D3 radial graph for blast radius analysis. Requires `manifest` field.\n- rich-html: Self-contained HTML page with FULL JS support (events, animations, CDN scripts). Specify `framework` and `content`:\n \u2022 framework: "wired" \u2014 wireframe UI via wired-elements (https://wiredjs.com). `content` is body HTML using <wired-button>, <wired-input>, <wired-card>, <wired-checkbox>, <wired-combo>, <wired-slider>, <wired-tabs>/<wired-tab>, etc. Hand-drawn aesthetic. Loads CDN automatically.\n \u2022 framework: "reveal" \u2014 slide presentation via reveal.js (https://revealjs.com). `content` is markdown slides joined by `\\n---\\n` (recommended) OR raw <section>\u2026</section> HTML. Arrow keys navigate. Supports code highlighting and speaker notes. Loads CDN automatically.\n \u2022 framework: "raw" \u2014 `content` is a complete <!DOCTYPE html> document (caller controls everything).\n Optional `theme: "light" | "dark"` sets the INITIAL preference. The deck\'s sun/moon toggle overrides live \u2014 content reacts in place. Usually omit it; only set when the AI has a specific reason (e.g. mockup that only makes sense in one mode). Standalone downloads fall back to OS prefers-color-scheme.\n\nAfter calling this tool, the user should check the LaunchDeck browser tab to view content.',
|
|
1654
1985
|
inputSchema: {
|
|
1655
1986
|
type: "object",
|
|
1656
1987
|
properties: {
|
|
@@ -1669,9 +2000,19 @@ var init_deck_mcp = __esm({
|
|
|
1669
2000
|
items: {
|
|
1670
2001
|
type: "object",
|
|
1671
2002
|
properties: {
|
|
1672
|
-
type: { type: "string", enum: ["html", "mermaid", "options", "markdown", "blast-radius"] },
|
|
2003
|
+
type: { type: "string", enum: ["html", "mermaid", "options", "markdown", "blast-radius", "rich-html"] },
|
|
1673
2004
|
label: { type: "string", description: "Label for this block (shown as sub-tab if multiple blocks)" },
|
|
1674
|
-
content: { type: "string", description: "Content string (HTML, Mermaid DSL, Markdown)" },
|
|
2005
|
+
content: { type: "string", description: "Content string (HTML, Mermaid DSL, Markdown, or rich-html body)" },
|
|
2006
|
+
framework: {
|
|
2007
|
+
type: "string",
|
|
2008
|
+
enum: ["wired", "reveal", "raw"],
|
|
2009
|
+
description: "For rich-html only: which framework to wrap content with."
|
|
2010
|
+
},
|
|
2011
|
+
theme: {
|
|
2012
|
+
type: "string",
|
|
2013
|
+
enum: ["light", "dark"],
|
|
2014
|
+
description: "For rich-html only: theme for the generated page."
|
|
2015
|
+
},
|
|
1675
2016
|
manifest: {
|
|
1676
2017
|
type: "object",
|
|
1677
2018
|
description: 'For blast-radius type: BlastRadiusManifest object. Generates an interactive D3 radial graph.\n\nRequired fields:\n- mode: "structural" (file-level, rings = hops) or "feature" (rings = modify/create/ripple)\n- title: string \u2014 shown in header (e.g. "lib/permissions/types.ts" or "Channels for Comms")\n- layers: array of { id, name, icon, color } \u2014 defines the project layers (e.g. db/api/ui). icon = Lucide icon name, color = hex fill color\n- rings: array of { id, name, color } \u2014 defines concentric rings. For structural: [{id:"hop1",name:"Direct",color:"#f97316"},{id:"hop2",name:"Indirect",color:"#eab308"}]. For feature: [{id:"modify",name:"Modify",color:"#f97316"},{id:"create",name:"Create",color:"#22c55e"},{id:"ripple",name:"Ripple",color:"#eab308"}]\n- center: { name, description } \u2014 the center node label and tooltip\n- nodes: array of { id, name, layer, ring, path?, reason?, type? } \u2014 layer refs layers[].id, ring refs rings[].id\n- edges: array of { source, target } \u2014 source/target are node ids, use "center" for edges from the center node\n\nOptional: subtitle (shown above title)\n\nExample layers: [{id:"db",name:"Database",icon:"database",color:"#172554"},{id:"api",name:"API",icon:"server",color:"#1e3a5f"},{id:"ui",name:"UI",icon:"layout-dashboard",color:"#0c4a6e"}]'
|