@launchsecure/launch-kit 0.0.27 → 0.0.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/beacon/beacon.mjs +1003 -440
- package/dist/beacon/beacon.mjs.map +1 -1
- package/dist/beacon/beacon.umd.js +45 -24
- package/dist/beacon/beacon.umd.js.map +1 -1
- package/dist/beacon/types/capture/events.d.ts +20 -0
- package/dist/beacon/types/capture/events.d.ts.map +1 -0
- package/dist/beacon/types/element.d.ts +1 -0
- package/dist/beacon/types/element.d.ts.map +1 -1
- package/dist/beacon/types/index.d.ts +2 -1
- package/dist/beacon/types/index.d.ts.map +1 -1
- package/dist/beacon/types/monitor/dom.d.ts +13 -0
- package/dist/beacon/types/monitor/dom.d.ts.map +1 -0
- package/dist/beacon/types/monitor/index.d.ts +19 -0
- package/dist/beacon/types/monitor/index.d.ts.map +1 -0
- package/dist/beacon/types/monitor/network.d.ts +12 -0
- package/dist/beacon/types/monitor/network.d.ts.map +1 -0
- package/dist/beacon/types/monitor/transport.d.ts +27 -0
- package/dist/beacon/types/monitor/transport.d.ts.map +1 -0
- package/dist/beacon/types/monitor/types.d.ts +117 -0
- package/dist/beacon/types/monitor/types.d.ts.map +1 -0
- package/dist/beacon/types/types.d.ts +10 -0
- package/dist/beacon/types/types.d.ts.map +1 -1
- package/dist/beacon/types/ui/drawer.d.ts +3 -1
- package/dist/beacon/types/ui/drawer.d.ts.map +1 -1
- package/dist/beacon/types/ui/monitor-panel.d.ts +19 -0
- package/dist/beacon/types/ui/monitor-panel.d.ts.map +1 -0
- package/dist/server/beacon-monitor-entry.js +353 -0
- package/dist/server/chart-serve.js +3 -1
- package/dist/server/cli.js +276 -218
- package/dist/server/course-entry.js +246 -0
- package/dist/server/graph-mcp-entry.js +35 -72
- package/dist/server/init-entry.js +1051 -122
- package/dist/server/orbit-entry.js +187 -24
- package/package.json +5 -3
- package/scaffolds/ls-marketplace/.claude-plugin/marketplace.json +15 -0
- package/scaffolds/ls-marketplace/plugins/kit/.claude-plugin/plugin.json +19 -0
- package/scaffolds/ls-marketplace/plugins/kit/commands/activate-beacon.md +216 -0
- package/scaffolds/ls-marketplace/plugins/kit/commands/activate-statusline.md +46 -0
- package/scaffolds/ls-marketplace/plugins/kit/commands/beacon-array.md +92 -0
- package/scaffolds/ls-marketplace/plugins/kit/commands/beacon-clear.md +68 -0
- package/scaffolds/ls-marketplace/plugins/kit/commands/beacon-pulse.md +80 -0
- package/scaffolds/ls-marketplace/plugins/kit/commands/beacon-scan.md +62 -0
- package/scaffolds/ls-marketplace/plugins/kit/commands/deactivate-statusline.md +34 -0
- package/scaffolds/ls-marketplace/plugins/kit/commands/show-mcp-status.md +109 -0
- package/scaffolds/ls-marketplace/plugins/kit/commands/standup.md +191 -0
- package/scaffolds/recall-hook/scripts/ensure-recall.sh +69 -0
- package/scaffolds/statusline/statusline-mcp.sh +192 -0
- package/scaffolds/statusline/statusline-wrapper.sh +50 -0
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
18
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
19
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
20
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
21
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
22
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
23
|
+
mod
|
|
24
|
+
));
|
|
25
|
+
|
|
26
|
+
// src/server/course-entry.ts
|
|
27
|
+
var fs2 = __toESM(require("node:fs"));
|
|
28
|
+
var path2 = __toESM(require("node:path"));
|
|
29
|
+
|
|
30
|
+
// src/server/cred-shape.ts
|
|
31
|
+
var fs = __toESM(require("node:fs"));
|
|
32
|
+
var path = __toESM(require("node:path"));
|
|
33
|
+
var CONFIG_FILENAME = ".launch-secure.cred.config";
|
|
34
|
+
function inferCourseName(serverUrl) {
|
|
35
|
+
try {
|
|
36
|
+
const host = new URL(serverUrl).hostname.toLowerCase();
|
|
37
|
+
if (host === "localhost" || host === "127.0.0.1" || host.endsWith(".local")) return "local";
|
|
38
|
+
if (host.includes("staging")) return "staging";
|
|
39
|
+
if (host.endsWith(".vercel.app")) return "prod";
|
|
40
|
+
return host.split(".")[0] || "default";
|
|
41
|
+
} catch {
|
|
42
|
+
return "default";
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function toNested(cred) {
|
|
46
|
+
if (cred.profiles && cred.active && cred.profiles[cred.active]) {
|
|
47
|
+
return { active: cred.active, profiles: cred.profiles };
|
|
48
|
+
}
|
|
49
|
+
if (!cred.pat || !cred.orgSlug || !cred.projectSlug || !cred.serverUrl) {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
const name = inferCourseName(cred.serverUrl);
|
|
53
|
+
return {
|
|
54
|
+
active: name,
|
|
55
|
+
profiles: {
|
|
56
|
+
[name]: {
|
|
57
|
+
pat: cred.pat,
|
|
58
|
+
orgSlug: cred.orgSlug,
|
|
59
|
+
projectSlug: cred.projectSlug,
|
|
60
|
+
serverUrl: cred.serverUrl
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function readCredFile(repoRoot) {
|
|
66
|
+
const p = path.join(repoRoot, CONFIG_FILENAME);
|
|
67
|
+
if (!fs.existsSync(p)) return null;
|
|
68
|
+
try {
|
|
69
|
+
return JSON.parse(fs.readFileSync(p, "utf-8"));
|
|
70
|
+
} catch (err) {
|
|
71
|
+
throw new Error(`could not parse ${CONFIG_FILENAME}: ${err instanceof Error ? err.message : String(err)}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
function writeJsonAtomic(absPath, value, mode) {
|
|
75
|
+
const tmp = `${absPath}.tmp`;
|
|
76
|
+
fs.writeFileSync(tmp, JSON.stringify(value, null, 2) + "\n", "utf-8");
|
|
77
|
+
if (mode !== void 0) {
|
|
78
|
+
try {
|
|
79
|
+
fs.chmodSync(tmp, mode);
|
|
80
|
+
} catch {
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
fs.renameSync(tmp, absPath);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// src/server/course-entry.ts
|
|
87
|
+
var MCP_FILENAME = ".mcp.json";
|
|
88
|
+
var DEFAULT_SERVER_URL = "https://launchsecure-v2.vercel.app";
|
|
89
|
+
function info(msg) {
|
|
90
|
+
console.log(`[launch-course] ${msg}`);
|
|
91
|
+
}
|
|
92
|
+
function ok(msg) {
|
|
93
|
+
console.log(`[launch-course] \u2713 ${msg}`);
|
|
94
|
+
}
|
|
95
|
+
function fail(msg) {
|
|
96
|
+
console.error(`[launch-course] \u2717 ${msg}`);
|
|
97
|
+
process.exit(1);
|
|
98
|
+
}
|
|
99
|
+
function readCredFile2() {
|
|
100
|
+
const cred = readCredFile(process.cwd());
|
|
101
|
+
if (!cred) {
|
|
102
|
+
fail(`${CONFIG_FILENAME} not found in ${process.cwd()}. Run \`npx @launchsecure/launch-kit init \u2026\` first.`);
|
|
103
|
+
}
|
|
104
|
+
return cred;
|
|
105
|
+
}
|
|
106
|
+
function toNested2(cred) {
|
|
107
|
+
const nested = toNested(cred);
|
|
108
|
+
if (!nested) {
|
|
109
|
+
fail(`${CONFIG_FILENAME} is missing required fields (pat, orgSlug, projectSlug, serverUrl) and has no profiles. Run \`npx @launchsecure/launch-kit init \u2026\` to (re)bootstrap.`);
|
|
110
|
+
}
|
|
111
|
+
return nested;
|
|
112
|
+
}
|
|
113
|
+
function parseFlag(argv, key) {
|
|
114
|
+
const prefix = `--${key}=`;
|
|
115
|
+
const found = argv.find((a) => a.startsWith(prefix));
|
|
116
|
+
return found ? found.slice(prefix.length) : void 0;
|
|
117
|
+
}
|
|
118
|
+
function cmdList() {
|
|
119
|
+
const nested = toNested2(readCredFile2());
|
|
120
|
+
const names = Object.keys(nested.profiles).sort();
|
|
121
|
+
if (names.length === 0) {
|
|
122
|
+
info("(no courses)");
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
info(`courses (${names.length}):`);
|
|
126
|
+
const nameWidth = Math.max(...names.map((n) => n.length), 8);
|
|
127
|
+
for (const name of names) {
|
|
128
|
+
const p = nested.profiles[name];
|
|
129
|
+
const marker = name === nested.active ? "\u2605" : " ";
|
|
130
|
+
console.log(` ${marker} ${name.padEnd(nameWidth)} ${p.serverUrl} (${p.orgSlug}/${p.projectSlug})`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
function cmdAdd(argv) {
|
|
134
|
+
const name = argv.find((a) => !a.startsWith("--"));
|
|
135
|
+
if (!name) fail("usage: launch-course add <name> --token=ls_pat_... --org=<slug> --project=<slug> [--url=<serverUrl>]");
|
|
136
|
+
const token = parseFlag(argv, "token");
|
|
137
|
+
const org = parseFlag(argv, "org");
|
|
138
|
+
const project = parseFlag(argv, "project");
|
|
139
|
+
const url = (parseFlag(argv, "url") ?? DEFAULT_SERVER_URL).replace(/\/+$/, "");
|
|
140
|
+
if (!token || !token.startsWith("ls_pat_")) fail("--token=<ls_pat_...> required");
|
|
141
|
+
if (!org) fail("--org=<slug> required");
|
|
142
|
+
if (!project) fail("--project=<slug> required");
|
|
143
|
+
const nested = toNested2(readCredFile2());
|
|
144
|
+
const existed = Boolean(nested.profiles[name]);
|
|
145
|
+
nested.profiles[name] = { pat: token, orgSlug: org, projectSlug: project, serverUrl: url };
|
|
146
|
+
writeJsonAtomic(path2.join(process.cwd(), CONFIG_FILENAME), nested, 384);
|
|
147
|
+
ok(`${existed ? "updated" : "added"} course "${name}" (${url})`);
|
|
148
|
+
if (nested.active !== name) {
|
|
149
|
+
info(`active course is still "${nested.active}" \u2014 run \`launch-course set ${name}\` to switch`);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
function cmdSet(argv) {
|
|
153
|
+
const name = argv[0];
|
|
154
|
+
if (!name) fail("usage: launch-course set <name>");
|
|
155
|
+
const nested = toNested2(readCredFile2());
|
|
156
|
+
const target = nested.profiles[name];
|
|
157
|
+
if (!target) {
|
|
158
|
+
const known = Object.keys(nested.profiles).sort().join(", ") || "(none)";
|
|
159
|
+
fail(`no course named "${name}". known: ${known}`);
|
|
160
|
+
}
|
|
161
|
+
if (nested.active === name) {
|
|
162
|
+
info(`already on "${name}" \u2014 nothing to do`);
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
const next = { active: name, profiles: nested.profiles };
|
|
166
|
+
writeJsonAtomic(path2.join(process.cwd(), CONFIG_FILENAME), next, 384);
|
|
167
|
+
const mcpStatus = updateMcpUrl(target.serverUrl);
|
|
168
|
+
ok(`active course \u2192 "${name}" (${target.serverUrl})`);
|
|
169
|
+
if (mcpStatus === "updated") {
|
|
170
|
+
info("reconnect MCP in Claude Code: /mcp \u2192 toggle launch-secure off/on (URL is read at connect time)");
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
function cmdRm(argv) {
|
|
174
|
+
const name = argv[0];
|
|
175
|
+
if (!name) fail("usage: launch-course rm <name>");
|
|
176
|
+
const nested = toNested2(readCredFile2());
|
|
177
|
+
if (!nested.profiles[name]) fail(`no course named "${name}"`);
|
|
178
|
+
if (nested.active === name) {
|
|
179
|
+
fail(`cannot remove the active course "${name}". \`launch-course set <other>\` first.`);
|
|
180
|
+
}
|
|
181
|
+
delete nested.profiles[name];
|
|
182
|
+
writeJsonAtomic(path2.join(process.cwd(), CONFIG_FILENAME), nested, 384);
|
|
183
|
+
ok(`removed course "${name}"`);
|
|
184
|
+
}
|
|
185
|
+
function updateMcpUrl(serverUrl) {
|
|
186
|
+
const p = path2.join(process.cwd(), MCP_FILENAME);
|
|
187
|
+
if (!fs2.existsSync(p)) {
|
|
188
|
+
info(`(no ${MCP_FILENAME} \u2014 skipped URL update; run \`npx @launchsecure/launch-kit init \u2026\` to wire MCP)`);
|
|
189
|
+
return "missing-file";
|
|
190
|
+
}
|
|
191
|
+
let mcp;
|
|
192
|
+
try {
|
|
193
|
+
mcp = JSON.parse(fs2.readFileSync(p, "utf-8"));
|
|
194
|
+
} catch (err) {
|
|
195
|
+
fail(`could not parse ${MCP_FILENAME}: ${err instanceof Error ? err.message : String(err)}`);
|
|
196
|
+
}
|
|
197
|
+
const entry = mcp.mcpServers?.["launch-secure"];
|
|
198
|
+
if (!entry) {
|
|
199
|
+
info(`(no "launch-secure" entry in ${MCP_FILENAME} \u2014 skipped URL update)`);
|
|
200
|
+
return "missing-entry";
|
|
201
|
+
}
|
|
202
|
+
entry.url = `${serverUrl.replace(/\/+$/, "")}/api/mcp/project`;
|
|
203
|
+
writeJsonAtomic(p, mcp);
|
|
204
|
+
ok(`updated ${MCP_FILENAME} launch-secure.url \u2192 ${entry.url}`);
|
|
205
|
+
return "updated";
|
|
206
|
+
}
|
|
207
|
+
function help() {
|
|
208
|
+
console.log(`launch-course \u2014 manage LaunchSecure server profiles ("courses").
|
|
209
|
+
|
|
210
|
+
Usage:
|
|
211
|
+
launch-course list
|
|
212
|
+
launch-course add <name> --token=ls_pat_... --org=<slug> --project=<slug> [--url=<serverUrl>]
|
|
213
|
+
launch-course set <name>
|
|
214
|
+
launch-course rm <name>
|
|
215
|
+
|
|
216
|
+
The cred file (.launch-secure.cred.config) holds every course under \`profiles\`,
|
|
217
|
+
with \`active\` selecting which one drives MCP / launch-pod auth. Legacy flat
|
|
218
|
+
files are auto-migrated on the first multi-profile op. \`launch-course set\`
|
|
219
|
+
also rewrites .mcp.json's launch-secure.url so Claude Code routes to the right
|
|
220
|
+
server on next MCP reconnect.
|
|
221
|
+
`);
|
|
222
|
+
}
|
|
223
|
+
function main() {
|
|
224
|
+
const [cmd, ...rest] = process.argv.slice(2);
|
|
225
|
+
switch (cmd) {
|
|
226
|
+
case "list":
|
|
227
|
+
return cmdList();
|
|
228
|
+
case "add":
|
|
229
|
+
return cmdAdd(rest);
|
|
230
|
+
case "set":
|
|
231
|
+
case "use":
|
|
232
|
+
return cmdSet(rest);
|
|
233
|
+
case "rm":
|
|
234
|
+
case "remove":
|
|
235
|
+
case "delete":
|
|
236
|
+
return cmdRm(rest);
|
|
237
|
+
case void 0:
|
|
238
|
+
case "help":
|
|
239
|
+
case "--help":
|
|
240
|
+
case "-h":
|
|
241
|
+
return help();
|
|
242
|
+
default:
|
|
243
|
+
fail(`unknown command "${cmd}". try \`launch-course help\``);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
main();
|
|
@@ -752,9 +752,9 @@ function buildEffectsIndex(layerOutputs) {
|
|
|
752
752
|
return idx;
|
|
753
753
|
}
|
|
754
754
|
function writeEffectsIndex(rootDir, idx) {
|
|
755
|
-
const
|
|
756
|
-
atomicWriteFileSync(
|
|
757
|
-
return
|
|
755
|
+
const path2 = (0, import_node_path8.join)(rootDir, LAUNCHSECURE_DIR, "graphs", "effects-index.json");
|
|
756
|
+
atomicWriteFileSync(path2, JSON.stringify(idx, null, 2) + "\n");
|
|
757
|
+
return path2;
|
|
758
758
|
}
|
|
759
759
|
var import_node_path8;
|
|
760
760
|
var init_effects_index = __esm({
|
|
@@ -1065,10 +1065,10 @@ async function generateGraph(rootDir, layer) {
|
|
|
1065
1065
|
return results;
|
|
1066
1066
|
}
|
|
1067
1067
|
function readEffectsIndex(rootDir) {
|
|
1068
|
-
const
|
|
1069
|
-
if (!(0, import_node_fs8.existsSync)(
|
|
1068
|
+
const path2 = (0, import_node_path10.join)(rootDir, GRAPHS_DIR2, "effects-index.json");
|
|
1069
|
+
if (!(0, import_node_fs8.existsSync)(path2)) return null;
|
|
1070
1070
|
try {
|
|
1071
|
-
return JSON.parse((0, import_node_fs8.readFileSync)(
|
|
1071
|
+
return JSON.parse((0, import_node_fs8.readFileSync)(path2, "utf-8"));
|
|
1072
1072
|
} catch {
|
|
1073
1073
|
return null;
|
|
1074
1074
|
}
|
|
@@ -4106,12 +4106,12 @@ var init_sql_migrations = __esm({
|
|
|
4106
4106
|
function loadApiRoutesFromOutput(apiOutput) {
|
|
4107
4107
|
const routes = [];
|
|
4108
4108
|
for (const n of apiOutput.nodes) {
|
|
4109
|
-
const
|
|
4110
|
-
if (!
|
|
4109
|
+
const path2 = n.path;
|
|
4110
|
+
if (!path2 || typeof path2 !== "string") continue;
|
|
4111
4111
|
routes.push({
|
|
4112
|
-
path:
|
|
4112
|
+
path: path2,
|
|
4113
4113
|
nodeId: n.id,
|
|
4114
|
-
segments:
|
|
4114
|
+
segments: path2.split("/").filter(Boolean)
|
|
4115
4115
|
});
|
|
4116
4116
|
}
|
|
4117
4117
|
return routes;
|
|
@@ -4203,16 +4203,16 @@ function resolveFetchCall(call, apiPathMap, apiRoutes) {
|
|
|
4203
4203
|
if (call.isConcat) {
|
|
4204
4204
|
return { kind: "dynamic", normalizedUrl: raw };
|
|
4205
4205
|
}
|
|
4206
|
-
const { path:
|
|
4207
|
-
if (!
|
|
4208
|
-
return { kind: "unresolved", normalizedUrl:
|
|
4206
|
+
const { path: path2, hadInterpolation } = normalizeFetchUrl(raw);
|
|
4207
|
+
if (!path2.startsWith("/")) {
|
|
4208
|
+
return { kind: "unresolved", normalizedUrl: path2 };
|
|
4209
4209
|
}
|
|
4210
|
-
const segs =
|
|
4210
|
+
const segs = path2.split("/").filter(Boolean);
|
|
4211
4211
|
if (hadInterpolation && segs.length > 0 && segs[0].startsWith(":")) {
|
|
4212
|
-
return { kind: "dynamic", normalizedUrl:
|
|
4212
|
+
return { kind: "dynamic", normalizedUrl: path2 };
|
|
4213
4213
|
}
|
|
4214
|
-
const exact = apiPathMap.get(
|
|
4215
|
-
if (exact) return { kind: "resolved", nodeId: exact, normalizedUrl:
|
|
4214
|
+
const exact = apiPathMap.get(path2);
|
|
4215
|
+
if (exact) return { kind: "resolved", nodeId: exact, normalizedUrl: path2 };
|
|
4216
4216
|
let bestScore = -1;
|
|
4217
4217
|
let bestId = null;
|
|
4218
4218
|
for (const r of apiRoutes) {
|
|
@@ -4223,21 +4223,21 @@ function resolveFetchCall(call, apiPathMap, apiRoutes) {
|
|
|
4223
4223
|
}
|
|
4224
4224
|
}
|
|
4225
4225
|
if (bestId && bestScore > 0) {
|
|
4226
|
-
return { kind: "resolved", nodeId: bestId, normalizedUrl:
|
|
4226
|
+
return { kind: "resolved", nodeId: bestId, normalizedUrl: path2 };
|
|
4227
4227
|
}
|
|
4228
|
-
return { kind: "unresolved", normalizedUrl:
|
|
4228
|
+
return { kind: "unresolved", normalizedUrl: path2 };
|
|
4229
4229
|
}
|
|
4230
4230
|
function resolveUrlPath(urlPath, apiPathMap, apiRoutes) {
|
|
4231
|
-
const { path:
|
|
4232
|
-
if (!
|
|
4233
|
-
return { kind: "unresolved", normalizedUrl:
|
|
4231
|
+
const { path: path2, hadInterpolation } = normalizeFetchUrl(urlPath);
|
|
4232
|
+
if (!path2.startsWith("/")) {
|
|
4233
|
+
return { kind: "unresolved", normalizedUrl: path2 };
|
|
4234
4234
|
}
|
|
4235
|
-
const segs =
|
|
4235
|
+
const segs = path2.split("/").filter(Boolean);
|
|
4236
4236
|
if (hadInterpolation && segs.length > 0 && segs[0].startsWith(":")) {
|
|
4237
|
-
return { kind: "dynamic", normalizedUrl:
|
|
4237
|
+
return { kind: "dynamic", normalizedUrl: path2 };
|
|
4238
4238
|
}
|
|
4239
|
-
const exact = apiPathMap.get(
|
|
4240
|
-
if (exact) return { kind: "resolved", nodeId: exact, normalizedUrl:
|
|
4239
|
+
const exact = apiPathMap.get(path2);
|
|
4240
|
+
if (exact) return { kind: "resolved", nodeId: exact, normalizedUrl: path2 };
|
|
4241
4241
|
let bestScore = -1;
|
|
4242
4242
|
let bestId = null;
|
|
4243
4243
|
for (const r of apiRoutes) {
|
|
@@ -4248,9 +4248,9 @@ function resolveUrlPath(urlPath, apiPathMap, apiRoutes) {
|
|
|
4248
4248
|
}
|
|
4249
4249
|
}
|
|
4250
4250
|
if (bestId && bestScore > 0) {
|
|
4251
|
-
return { kind: "resolved", nodeId: bestId, normalizedUrl:
|
|
4251
|
+
return { kind: "resolved", nodeId: bestId, normalizedUrl: path2 };
|
|
4252
4252
|
}
|
|
4253
|
-
return { kind: "unresolved", normalizedUrl:
|
|
4253
|
+
return { kind: "unresolved", normalizedUrl: path2 };
|
|
4254
4254
|
}
|
|
4255
4255
|
var init_api_route_matching = __esm({
|
|
4256
4256
|
"src/server/graph/core/api-route-matching.ts"() {
|
|
@@ -5271,9 +5271,9 @@ function collectTargets(apiOutput, uiOutput) {
|
|
|
5271
5271
|
const out = [];
|
|
5272
5272
|
for (const n of apiOutput?.nodes ?? []) {
|
|
5273
5273
|
if (n.type !== "endpoint") continue;
|
|
5274
|
-
const
|
|
5275
|
-
if (typeof
|
|
5276
|
-
out.push({ id: n.id, route:
|
|
5274
|
+
const path2 = n.path;
|
|
5275
|
+
if (typeof path2 !== "string" || !path2) continue;
|
|
5276
|
+
out.push({ id: n.id, route: path2, layer: "api" });
|
|
5277
5277
|
}
|
|
5278
5278
|
for (const n of uiOutput?.nodes ?? []) {
|
|
5279
5279
|
if (n.type !== "page") continue;
|
|
@@ -6446,8 +6446,10 @@ async function startChartServer(opts = {}) {
|
|
|
6446
6446
|
req.on("end", () => {
|
|
6447
6447
|
try {
|
|
6448
6448
|
const newConfig = JSON.parse(body);
|
|
6449
|
+
const existingConfig = loadConfig(reqRoot);
|
|
6450
|
+
const merged = { ...existingConfig, ...newConfig };
|
|
6449
6451
|
const configPath = import_node_path24.default.join(reqRoot, LAUNCHCHART_CONFIG_FILE);
|
|
6450
|
-
import_node_fs21.default.writeFileSync(configPath, JSON.stringify(
|
|
6452
|
+
import_node_fs21.default.writeFileSync(configPath, JSON.stringify(merged, null, 2) + "\n", "utf-8");
|
|
6451
6453
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
6452
6454
|
res.end(JSON.stringify({ ok: true }));
|
|
6453
6455
|
} catch (err2) {
|
|
@@ -8042,8 +8044,7 @@ function handleStartChartServer(args) {
|
|
|
8042
8044
|
const portArgs = args.port ? ["--port", String(args.port)] : [];
|
|
8043
8045
|
const child = (0, import_node_child_process2.spawn)(process.execPath, [entryPath, "serve", ...portArgs], {
|
|
8044
8046
|
detached: true,
|
|
8045
|
-
stdio: ["ignore", out, err2]
|
|
8046
|
-
env: { ...process.env, LAUNCH_CHART_AUTOSERVE: "" }
|
|
8047
|
+
stdio: ["ignore", out, err2]
|
|
8047
8048
|
});
|
|
8048
8049
|
child.unref();
|
|
8049
8050
|
return okJson({
|
|
@@ -8805,44 +8806,7 @@ Example: blast_points(node_id: "server/auth/middleware.ts", hops: 2) \u2192 retu
|
|
|
8805
8806
|
});
|
|
8806
8807
|
|
|
8807
8808
|
// src/server/graph-mcp-entry.ts
|
|
8808
|
-
var import_node_child_process3 = require("node:child_process");
|
|
8809
|
-
var import_node_fs25 = require("node:fs");
|
|
8810
|
-
var import_node_path29 = __toESM(require("node:path"));
|
|
8811
|
-
var import_node_os3 = require("node:os");
|
|
8812
|
-
var import_node_fs26 = require("node:fs");
|
|
8813
|
-
init_launch_kit_paths();
|
|
8814
8809
|
init_lockfile();
|
|
8815
|
-
function logStderr(msg) {
|
|
8816
|
-
process.stderr.write(`[launch-chart] ${msg}
|
|
8817
|
-
`);
|
|
8818
|
-
}
|
|
8819
|
-
function maybeAutoServe() {
|
|
8820
|
-
if (process.env.LAUNCH_CHART_AUTOSERVE !== "1") return;
|
|
8821
|
-
const rootDir = process.cwd();
|
|
8822
|
-
setProjectRoot(rootDir);
|
|
8823
|
-
const existing = getLiveLock(rootDir);
|
|
8824
|
-
if (existing) {
|
|
8825
|
-
logStderr(`autoserve: reusing existing server at ${existing.url}`);
|
|
8826
|
-
return;
|
|
8827
|
-
}
|
|
8828
|
-
try {
|
|
8829
|
-
const logDir = import_node_path29.default.join((0, import_node_os3.homedir)(), LAUNCHSECURE_DIR);
|
|
8830
|
-
(0, import_node_fs26.mkdirSync)(logDir, { recursive: true });
|
|
8831
|
-
const logPath = import_node_path29.default.join(logDir, "launch-chart.log");
|
|
8832
|
-
const out = (0, import_node_fs25.openSync)(logPath, "a");
|
|
8833
|
-
const err2 = (0, import_node_fs25.openSync)(logPath, "a");
|
|
8834
|
-
const entryPath = process.argv[1];
|
|
8835
|
-
const child = (0, import_node_child_process3.spawn)(process.execPath, [entryPath, "serve"], {
|
|
8836
|
-
detached: true,
|
|
8837
|
-
stdio: ["ignore", out, err2],
|
|
8838
|
-
env: { ...process.env, LAUNCH_CHART_AUTOSERVE: "" }
|
|
8839
|
-
});
|
|
8840
|
-
child.unref();
|
|
8841
|
-
logStderr(`autoserve: spawned detached serve process (pid ${child.pid}, log: ${logPath})`);
|
|
8842
|
-
} catch (err2) {
|
|
8843
|
-
logStderr(`autoserve: failed to spawn \u2014 ${err2}`);
|
|
8844
|
-
}
|
|
8845
|
-
}
|
|
8846
8810
|
async function main() {
|
|
8847
8811
|
setProjectRoot(process.cwd());
|
|
8848
8812
|
const argv = process.argv.slice(2);
|
|
@@ -8858,7 +8822,6 @@ async function main() {
|
|
|
8858
8822
|
await handleGraphCommand2(mapped, argv.slice(1));
|
|
8859
8823
|
process.exit(0);
|
|
8860
8824
|
}
|
|
8861
|
-
maybeAutoServe();
|
|
8862
8825
|
const { startGraphMcpServer: startGraphMcpServer2 } = await Promise.resolve().then(() => (init_graph_mcp(), graph_mcp_exports));
|
|
8863
8826
|
startGraphMcpServer2();
|
|
8864
8827
|
}
|