@cryptiklemur/lattice 5.10.0 → 5.11.0
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/client/assets/{angular-html-BDIcxkJq.js → angular-html-BoFzmWT8.js} +1 -1
- package/dist/client/assets/{angular-ts-Bt22ouNH.js → angular-ts-DZnI8rKE.js} +1 -1
- package/dist/client/assets/{apl-p8qkxzEK.js → apl-DstVmncE.js} +1 -1
- package/dist/client/assets/{astro-CIaMc49M.js → astro-DTPCjzEx.js} +1 -1
- package/dist/client/assets/{blade-BR56EAMD.js → blade-6q42Ss3F.js} +1 -1
- package/dist/client/assets/{c-Dli0HzAh.js → c-BQDGJ-nQ.js} +1 -1
- package/dist/client/assets/{cobol-Cad15ECy.js → cobol-Dlh0WvsZ.js} +1 -1
- package/dist/client/assets/{coffee-DpyATEbF.js → coffee-DdQv129j.js} +1 -1
- package/dist/client/assets/{cpp-KN8_NFsf.js → cpp-DhbQJIv4.js} +1 -1
- package/dist/client/assets/{crystal-CuyGv0kh.js → crystal-C22kERUB.js} +1 -1
- package/dist/client/assets/{css-Cm3q4bxn.js → css-n31O5kHj.js} +1 -1
- package/dist/client/assets/{dist-BjxsMc4u.js → dist-D8okl7lw.js} +2 -2
- package/dist/client/assets/{edge-B6S7CSbx.js → edge-Cgwx-o_7.js} +1 -1
- package/dist/client/assets/{elixir-CNUy9H8T.js → elixir-DAGM2WKD.js} +1 -1
- package/dist/client/assets/{elm-CNfcWmb9.js → elm-BLw_7oO9.js} +1 -1
- package/dist/client/assets/{erb-DWebzDaI.js → erb-DCaNhYa7.js} +1 -1
- package/dist/client/assets/{git-rebase-B_Pt2ZBK.js → git-rebase-CNNhb8-g.js} +1 -1
- package/dist/client/assets/{glimmer-js-CVwoOd72.js → glimmer-js-BnZd88Wi.js} +1 -1
- package/dist/client/assets/{glimmer-ts-CjtFSxjz.js → glimmer-ts-DvFNbZu-.js} +1 -1
- package/dist/client/assets/{glsl-CP4rggAA.js → glsl-Dnrk_Jnx.js} +1 -1
- package/dist/client/assets/{graphql-Dbm6sAtp.js → graphql-DlWTPvCG.js} +1 -1
- package/dist/client/assets/{hack-Bj9y3SGf.js → hack-DQg1Ek33.js} +1 -1
- package/dist/client/assets/{haml-DRGrdf3f.js → haml-DSk45qIE.js} +1 -1
- package/dist/client/assets/{handlebars-CFKjcBMg.js → handlebars-DuLvATB2.js} +1 -1
- package/dist/client/assets/{html-Vcd4eHHg.js → html-D4DiUnLg.js} +1 -1
- package/dist/client/assets/{html-derivative-BF0YbD4L.js → html-derivative-CS5MZ6d9.js} +1 -1
- package/dist/client/assets/{http-CGVTa2NT.js → http-CkDncfer.js} +1 -1
- package/dist/client/assets/{hurl-B0GrsGqd.js → hurl-DU39oO3U.js} +1 -1
- package/dist/client/assets/{index-CX1tudsF.js → index-CHPfE1Zl.js} +129 -129
- package/dist/client/assets/index-DHUKmLLC.css +2 -0
- package/dist/client/assets/{java-BJHQqHsm.js → java-lntACKEu.js} +1 -1
- package/dist/client/assets/{javascript-CmuMsKrc.js → javascript-CxkFc6nV.js} +1 -1
- package/dist/client/assets/{jinja-JxCLeq1j.js → jinja-DolO2zO7.js} +1 -1
- package/dist/client/assets/{jison-BdgAUhei.js → jison-Cok5FPev.js} +1 -1
- package/dist/client/assets/{json-DtPissHL.js → json-BebuQPrq.js} +1 -1
- package/dist/client/assets/{jsx-DUAxxDkP.js → jsx-iLBaUyXr.js} +1 -1
- package/dist/client/assets/{julia-DxDlbL6e.js → julia-C5Dsc7cH.js} +1 -1
- package/dist/client/assets/{just-CVmAAx2R.js → just-DJYqq_9R.js} +1 -1
- package/dist/client/assets/{latex-uwxggTWA.js → latex-BTTYiKj1.js} +1 -1
- package/dist/client/assets/{liquid-xsETAJJy.js → liquid-DpAKCrOB.js} +1 -1
- package/dist/client/assets/{lua-B2Hh8PgD.js → lua-BZ6b1hko.js} +1 -1
- package/dist/client/assets/{marko-yDeGxD87.js → marko-D8VK6iGt.js} +1 -1
- package/dist/client/assets/{mdc-QMp4ieYR.js → mdc-Paa3XzwY.js} +1 -1
- package/dist/client/assets/{nginx-7gmRmcqz.js → nginx-C5k9mWtJ.js} +1 -1
- package/dist/client/assets/{nim-CA8SNY_7.js → nim-Dst6YSnE.js} +1 -1
- package/dist/client/assets/{perl-lx5nW4VC.js → perl-XhiCjgBp.js} +1 -1
- package/dist/client/assets/{php-DgHiW953.js → php-BcsPLnLU.js} +1 -1
- package/dist/client/assets/{pug-CbbB1vwb.js → pug-GLH9-eAJ.js} +1 -1
- package/dist/client/assets/{qml-COrzwCIh.js → qml-Cj_lJioE.js} +1 -1
- package/dist/client/assets/{r-Dv7pZJDH.js → r-B70aGYK5.js} +1 -1
- package/dist/client/assets/{razor-D2m8EDP5.js → razor-R3gub_zy.js} +1 -1
- package/dist/client/assets/{regexp-BXLT-jPc.js → regexp-itC0dIUJ.js} +1 -1
- package/dist/client/assets/{rst-_S6rrUYh.js → rst-DdyoV8E2.js} +1 -1
- package/dist/client/assets/{ruby-C3XO7tYY.js → ruby-BYBZsv66.js} +1 -1
- package/dist/client/assets/{sas-DP2k4iuN.js → sas-fqfqXqj1.js} +1 -1
- package/dist/client/assets/{scss-lhLFMXGn.js → scss-B-ELv6mu.js} +1 -1
- package/dist/client/assets/{shellscript-BYlBPHen.js → shellscript-BgB8TNw6.js} +1 -1
- package/dist/client/assets/{shellsession-CbVyQKWZ.js → shellsession-BLK2Dgkm.js} +1 -1
- package/dist/client/assets/{soy-Be8a0lHq.js → soy-C7_RmNrp.js} +1 -1
- package/dist/client/assets/{sql-2KxvU9YS.js → sql-AUgbUJq4.js} +1 -1
- package/dist/client/assets/{stata-BxlWftTS.js → stata-CIVqSIOr.js} +1 -1
- package/dist/client/assets/{surrealql-CJ-q86nR.js → surrealql-BzRQzc5S.js} +1 -1
- package/dist/client/assets/{svelte-Q1ml0OiY.js → svelte-BCIwEwtb.js} +1 -1
- package/dist/client/assets/{templ-BbfPZhtu.js → templ-C1hbwe4u.js} +1 -1
- package/dist/client/assets/{tex-Dcth4Gi6.js → tex-CI4tIsaP.js} +1 -1
- package/dist/client/assets/{ts-tags-BKhSOXI3.js → ts-tags-SUeikhEp.js} +1 -1
- package/dist/client/assets/{tsx-CS6iQ0XH.js → tsx-xkp7aIZs.js} +1 -1
- package/dist/client/assets/{twig-BHp31ZxS.js → twig-CGgBSAyc.js} +1 -1
- package/dist/client/assets/{typescript-16YJBTaO.js → typescript-O2YMTl_s.js} +1 -1
- package/dist/client/assets/{vue-CMKwTi4r.js → vue-DsNRxos1.js} +1 -1
- package/dist/client/assets/{vue-html-Dr8VUA2G.js → vue-html-CuY3t7bs.js} +1 -1
- package/dist/client/assets/{vue-vine-DZUqDerl.js → vue-vine-C6kSCKwY.js} +1 -1
- package/dist/client/assets/{xml-CBbBKKDC.js → xml-DafwzOLY.js} +1 -1
- package/dist/client/assets/{xsl-DWEX6PKX.js → xsl-1SGGZibr.js} +1 -1
- package/dist/client/assets/{yaml-DvKvvh3X.js → yaml-DSVhzmhr.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/client/sw.js +1 -1
- package/dist/server/analytics/engine.js +241 -241
- package/dist/server/assets.js +4 -4
- package/dist/server/auth/passphrase.js +13 -13
- package/dist/server/config.js +7 -7
- package/dist/server/daemon.js +93 -93
- package/dist/server/features/brainstorm.js +42 -42
- package/dist/server/features/ralph-loop.js +33 -33
- package/dist/server/features/scheduler.js +53 -53
- package/dist/server/features/specs.js +54 -54
- package/dist/server/features/sticky-notes.js +17 -17
- package/dist/server/features/superpowers.js +24 -24
- package/dist/server/handlers/analytics.js +1 -1
- package/dist/server/handlers/attachment.js +32 -32
- package/dist/server/handlers/bookmarks.js +4 -4
- package/dist/server/handlers/brainstorm.js +4 -4
- package/dist/server/handlers/chat.js +54 -54
- package/dist/server/handlers/editor.js +13 -13
- package/dist/server/handlers/fs.js +51 -51
- package/dist/server/handlers/hooks.js +20 -20
- package/dist/server/handlers/loop.js +6 -6
- package/dist/server/handlers/memory.js +44 -44
- package/dist/server/handlers/mesh.js +60 -60
- package/dist/server/handlers/notes.js +7 -7
- package/dist/server/handlers/plugins.js +174 -174
- package/dist/server/handlers/project-settings.js +26 -26
- package/dist/server/handlers/scheduler.js +6 -6
- package/dist/server/handlers/session.js +24 -24
- package/dist/server/handlers/settings.js +21 -21
- package/dist/server/handlers/skills.js +91 -91
- package/dist/server/handlers/specs.js +51 -28
- package/dist/server/handlers/terminal.js +13 -13
- package/dist/server/handlers/themes.js +21 -21
- package/dist/server/handlers/update.js +17 -17
- package/dist/server/hooks/event_forward.sh +34 -0
- package/dist/server/hooks/post_tool_use.sh +26 -0
- package/dist/server/hooks/statusline.sh +26 -0
- package/dist/server/identity.js +6 -6
- package/dist/server/index.js +111 -111
- package/dist/server/logger.js +1 -1
- package/dist/server/mesh/connector.js +78 -78
- package/dist/server/mesh/crypto.js +20 -20
- package/dist/server/mesh/discovery.js +14 -14
- package/dist/server/mesh/pairing.js +30 -30
- package/dist/server/mesh/peers.js +10 -10
- package/dist/server/mesh/proxy.js +14 -14
- package/dist/server/mesh/session-sync.js +23 -23
- package/dist/server/project/bookmarks.js +11 -11
- package/dist/server/project/context-breakdown.js +70 -70
- package/dist/server/project/file-browser.js +17 -17
- package/dist/server/project/project-files.js +68 -68
- package/dist/server/project/registry.js +10 -10
- package/dist/server/project/sdk-bridge.js +157 -157
- package/dist/server/project/session.js +201 -199
- package/dist/server/project/terminal.js +15 -15
- package/dist/server/project/warmup.js +37 -37
- package/dist/server/push.js +11 -11
- package/dist/server/runtime.js +1 -1
- package/dist/server/tls.js +15 -15
- package/dist/server/tui.js +15 -15
- package/dist/server/update-checker.js +21 -21
- package/dist/server/ws/broadcast.js +18 -18
- package/dist/server/ws/router.js +17 -17
- package/dist/shared/constants.js +8 -8
- package/package.json +2 -2
- package/dist/client/assets/index-DlfI20Gn.css +0 -2
package/dist/server/index.js
CHANGED
|
@@ -6,22 +6,22 @@ import { join, dirname } from "node:path";
|
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
7
7
|
import { spawn, execSync } from "node:child_process";
|
|
8
8
|
import { getLatticeHome, loadConfig } from "./config.js";
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
const __filename_local = fileURLToPath(import.meta.url);
|
|
10
|
+
const __dirname_local = dirname(__filename_local);
|
|
11
11
|
function getCurrentVersion() {
|
|
12
12
|
try {
|
|
13
|
-
|
|
13
|
+
const pkg = JSON.parse(readFileSync(join(__dirname_local, "../../package.json"), "utf-8"));
|
|
14
14
|
return pkg.version || "0.0.0";
|
|
15
15
|
}
|
|
16
16
|
catch {
|
|
17
17
|
return "0.0.0";
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
for (
|
|
20
|
+
const args = process.argv.slice(2);
|
|
21
|
+
let command = "help";
|
|
22
|
+
let portOverride = null;
|
|
23
|
+
let tlsOverride = null;
|
|
24
|
+
for (let i = 0; i < args.length; i++) {
|
|
25
25
|
if (args[i] === "--port" && i + 1 < args.length) {
|
|
26
26
|
portOverride = parseInt(args[i + 1], 10);
|
|
27
27
|
i++;
|
|
@@ -43,17 +43,17 @@ function getEffectivePort() {
|
|
|
43
43
|
return portOverride ?? loadConfig().port;
|
|
44
44
|
}
|
|
45
45
|
function getPidPath(port) {
|
|
46
|
-
|
|
46
|
+
const p = port ?? getEffectivePort();
|
|
47
47
|
return join(getLatticeHome(), "daemon-" + p + ".pid");
|
|
48
48
|
}
|
|
49
49
|
function readPid(port) {
|
|
50
|
-
|
|
50
|
+
const pidPath = getPidPath(port);
|
|
51
51
|
if (!existsSync(pidPath)) {
|
|
52
52
|
return null;
|
|
53
53
|
}
|
|
54
54
|
try {
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
const raw = readFileSync(pidPath, "utf-8").trim();
|
|
56
|
+
const pid = parseInt(raw, 10);
|
|
57
57
|
return isNaN(pid) ? null : pid;
|
|
58
58
|
}
|
|
59
59
|
catch {
|
|
@@ -64,7 +64,7 @@ function writePid(pid, port) {
|
|
|
64
64
|
writeFileSync(getPidPath(port), String(pid), "utf-8");
|
|
65
65
|
}
|
|
66
66
|
function removePid(port) {
|
|
67
|
-
|
|
67
|
+
const pidPath = getPidPath(port);
|
|
68
68
|
if (existsSync(pidPath)) {
|
|
69
69
|
try {
|
|
70
70
|
unlinkSync(pidPath);
|
|
@@ -83,14 +83,14 @@ function isDaemonRunning(pid) {
|
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
85
|
function spawnDaemon(port, tls) {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
86
|
+
const logPath = join(getLatticeHome(), "daemon.log");
|
|
87
|
+
const logFd = openSync(logPath, "a");
|
|
88
|
+
const isDev = __filename_local.endsWith(".ts");
|
|
89
|
+
let spawnCmd;
|
|
90
|
+
let spawnArgs;
|
|
91
91
|
if (isDev) {
|
|
92
|
-
|
|
93
|
-
|
|
92
|
+
const pkgRoot = join(__dirname_local, "..");
|
|
93
|
+
const localTsx = join(pkgRoot, "node_modules", ".bin", "tsx");
|
|
94
94
|
spawnCmd = existsSync(localTsx) ? localTsx : "tsx";
|
|
95
95
|
spawnArgs = ["--tsconfig", join(pkgRoot, "tsconfig.json"), __filename_local, "run", "--port", String(port)];
|
|
96
96
|
}
|
|
@@ -102,7 +102,7 @@ function spawnDaemon(port, tls) {
|
|
|
102
102
|
spawnArgs.push("--tls");
|
|
103
103
|
if (tls === false)
|
|
104
104
|
spawnArgs.push("--no-tls");
|
|
105
|
-
|
|
105
|
+
const child = spawn(spawnCmd, spawnArgs, {
|
|
106
106
|
detached: true,
|
|
107
107
|
stdio: ["ignore", logFd, logFd],
|
|
108
108
|
env: { ...process.env, LATTICE_PORT: undefined },
|
|
@@ -156,22 +156,22 @@ switch (command) {
|
|
|
156
156
|
process.exit(1);
|
|
157
157
|
}
|
|
158
158
|
async function runDaemon() {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
159
|
+
const { printBanner, printStatus, printQrCode, runOnboarding } = await import("./tui.js");
|
|
160
|
+
const { startDaemon } = await import("./daemon.js");
|
|
161
|
+
const { broadcast, closeAllClients } = await import("./ws/broadcast.js");
|
|
162
|
+
const { getActiveStreamCount } = await import("./project/sdk-bridge.js");
|
|
163
|
+
const { stopMeshConnections } = await import("./mesh/connector.js");
|
|
164
|
+
const onboarding = await runOnboarding();
|
|
165
165
|
if (onboarding.passphrase) {
|
|
166
|
-
|
|
167
|
-
|
|
166
|
+
const { hashPassphrase } = await import("./auth/passphrase.js");
|
|
167
|
+
const config = loadConfig();
|
|
168
168
|
config.passphraseHash = await hashPassphrase(onboarding.passphrase);
|
|
169
|
-
|
|
169
|
+
const { saveConfig: saveCfg } = await import("./config.js");
|
|
170
170
|
saveCfg(config);
|
|
171
171
|
}
|
|
172
|
-
|
|
172
|
+
const effectivePort = portOverride ?? onboarding.port;
|
|
173
173
|
writePid(process.pid);
|
|
174
|
-
|
|
174
|
+
let shutdownInProgress = false;
|
|
175
175
|
function gracefulShutdown() {
|
|
176
176
|
if (shutdownInProgress)
|
|
177
177
|
return;
|
|
@@ -179,10 +179,10 @@ async function runDaemon() {
|
|
|
179
179
|
console.log("\n[lattice] Shutting down gracefully...");
|
|
180
180
|
broadcast({ type: "chat:error", message: "Server is shutting down" });
|
|
181
181
|
stopMeshConnections();
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
182
|
+
let waited = 0;
|
|
183
|
+
const maxWait = 2000;
|
|
184
|
+
const checkInterval = setInterval(function () {
|
|
185
|
+
const activeCount = getActiveStreamCount();
|
|
186
186
|
waited += 500;
|
|
187
187
|
if (activeCount === 0 || waited >= maxWait) {
|
|
188
188
|
clearInterval(checkInterval);
|
|
@@ -195,24 +195,24 @@ async function runDaemon() {
|
|
|
195
195
|
process.on("SIGTERM", gracefulShutdown);
|
|
196
196
|
process.on("SIGINT", gracefulShutdown);
|
|
197
197
|
await startDaemon(effectivePort, tlsOverride);
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
198
|
+
const config = loadConfig();
|
|
199
|
+
const protocol = config.tls ? "https" : "http";
|
|
200
|
+
const url = protocol + "://localhost:" + config.port;
|
|
201
|
+
const version = getCurrentVersion();
|
|
202
|
+
const projectCount = config.projects.length;
|
|
203
|
+
let sessionCount = 0;
|
|
204
204
|
try {
|
|
205
|
-
|
|
206
|
-
for (
|
|
207
|
-
|
|
205
|
+
const { listSessions } = await import("./project/session.js");
|
|
206
|
+
for (let i = 0; i < config.projects.length; i++) {
|
|
207
|
+
const result = await listSessions(config.projects[i].slug, { limit: 0 });
|
|
208
208
|
sessionCount += result.totalCount;
|
|
209
209
|
}
|
|
210
210
|
}
|
|
211
211
|
catch { }
|
|
212
|
-
|
|
212
|
+
let tailscaleUrl;
|
|
213
213
|
try {
|
|
214
|
-
|
|
215
|
-
|
|
214
|
+
const tsResult = execSync("tailscale status --json", { encoding: "utf-8" });
|
|
215
|
+
const tsHostname = JSON.parse(tsResult).Self.DNSName.replace(/\.$/, "");
|
|
216
216
|
if (tsHostname) {
|
|
217
217
|
tailscaleUrl = protocol + "://" + tsHostname + ":" + config.port;
|
|
218
218
|
}
|
|
@@ -223,30 +223,30 @@ async function runDaemon() {
|
|
|
223
223
|
printStatus(config, version, projectCount, sessionCount, tailscaleUrl);
|
|
224
224
|
}
|
|
225
225
|
async function runStart() {
|
|
226
|
-
|
|
226
|
+
const pid = readPid();
|
|
227
227
|
if (pid !== null && isDaemonRunning(pid)) {
|
|
228
228
|
console.log("[lattice] Daemon is already running (PID " + pid + ")");
|
|
229
|
-
|
|
230
|
-
|
|
229
|
+
const config = loadConfig();
|
|
230
|
+
const url = (config.tls ? "https" : "http") + "://localhost:" + config.port;
|
|
231
231
|
openBrowser(url);
|
|
232
232
|
return;
|
|
233
233
|
}
|
|
234
234
|
removePid();
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
235
|
+
const config = loadConfig();
|
|
236
|
+
const port = portOverride ?? config.port;
|
|
237
|
+
const childPid = spawnDaemon(port, tlsOverride);
|
|
238
238
|
writePid(childPid);
|
|
239
239
|
console.log("[lattice] Daemon started (PID " + childPid + ")");
|
|
240
240
|
console.log("[lattice] Logs: " + join(getLatticeHome(), "daemon.log"));
|
|
241
241
|
await new Promise(function (resolve) {
|
|
242
242
|
setTimeout(resolve, 800);
|
|
243
243
|
});
|
|
244
|
-
|
|
244
|
+
const url = (config.tls ? "https" : "http") + "://localhost:" + port;
|
|
245
245
|
console.log("[lattice] Opening " + url);
|
|
246
246
|
openBrowser(url);
|
|
247
247
|
}
|
|
248
248
|
function runStop() {
|
|
249
|
-
|
|
249
|
+
const pid = readPid();
|
|
250
250
|
if (pid === null) {
|
|
251
251
|
console.log("[lattice] No PID file found. Daemon may not be running.");
|
|
252
252
|
process.exit(1);
|
|
@@ -297,14 +297,14 @@ function runHelp() {
|
|
|
297
297
|
console.log("");
|
|
298
298
|
}
|
|
299
299
|
async function runSetupTls() {
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
300
|
+
const { spawnSync } = await import("node:child_process");
|
|
301
|
+
const { createInterface } = await import("node:readline");
|
|
302
|
+
const { mkdirSync, chmodSync, chownSync, statSync } = await import("node:fs");
|
|
303
|
+
const certsDir = join(getLatticeHome(), "certs");
|
|
304
|
+
const certPath = join(certsDir, "cert.pem");
|
|
305
|
+
const keyPath = join(certsDir, "key.pem");
|
|
306
306
|
function prompt(question) {
|
|
307
|
-
|
|
307
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
308
308
|
return new Promise(function (resolve) {
|
|
309
309
|
rl.question(question, function (answer) {
|
|
310
310
|
rl.close();
|
|
@@ -315,12 +315,12 @@ async function runSetupTls() {
|
|
|
315
315
|
console.log("");
|
|
316
316
|
console.log(" lattice — TLS Setup");
|
|
317
317
|
console.log("");
|
|
318
|
-
|
|
319
|
-
|
|
318
|
+
let hasTailscale = false;
|
|
319
|
+
let hostname = "";
|
|
320
320
|
try {
|
|
321
321
|
spawnSync("tailscale", ["version"], { stdio: "ignore" });
|
|
322
322
|
hasTailscale = true;
|
|
323
|
-
|
|
323
|
+
const statusResult = spawnSync("tailscale", ["status", "--json"], { encoding: "utf-8" });
|
|
324
324
|
if (statusResult.status === 0) {
|
|
325
325
|
hostname = JSON.parse(statusResult.stdout).Self.DNSName.replace(/\.$/, "");
|
|
326
326
|
}
|
|
@@ -329,7 +329,7 @@ async function runSetupTls() {
|
|
|
329
329
|
if (hasTailscale && hostname) {
|
|
330
330
|
console.log(" Tailscale detected: " + hostname);
|
|
331
331
|
console.log("");
|
|
332
|
-
|
|
332
|
+
const answer = await prompt(" Set up Tailscale HTTPS certs automatically? [Y/n] ");
|
|
333
333
|
if (answer !== "n" && answer !== "no") {
|
|
334
334
|
if (!existsSync(certsDir)) {
|
|
335
335
|
mkdirSync(certsDir, { recursive: true });
|
|
@@ -337,7 +337,7 @@ async function runSetupTls() {
|
|
|
337
337
|
console.log("");
|
|
338
338
|
console.log(" Generating Tailscale cert (sudo required)...");
|
|
339
339
|
console.log("");
|
|
340
|
-
|
|
340
|
+
const certResult = spawnSync("sudo", ["tailscale", "cert", "--cert-file", certPath, "--key-file", keyPath, hostname], { stdio: "inherit" });
|
|
341
341
|
if (certResult.status !== 0) {
|
|
342
342
|
console.error("");
|
|
343
343
|
console.error(" Failed to generate Tailscale certs.");
|
|
@@ -345,8 +345,8 @@ async function runSetupTls() {
|
|
|
345
345
|
console.error(" sudo tailscale cert --cert-file " + certPath + " --key-file " + keyPath + " " + hostname);
|
|
346
346
|
process.exit(1);
|
|
347
347
|
}
|
|
348
|
-
|
|
349
|
-
|
|
348
|
+
const uid = process.getuid ? process.getuid() : 0;
|
|
349
|
+
const gid = process.getgid ? process.getgid() : 0;
|
|
350
350
|
try {
|
|
351
351
|
chownSync(certPath, uid, gid);
|
|
352
352
|
chownSync(keyPath, uid, gid);
|
|
@@ -361,16 +361,16 @@ async function runSetupTls() {
|
|
|
361
361
|
}
|
|
362
362
|
console.log("");
|
|
363
363
|
console.log(" Certs installed and permissions fixed.");
|
|
364
|
-
|
|
364
|
+
const config = loadConfig();
|
|
365
365
|
if (!config.tls) {
|
|
366
|
-
|
|
366
|
+
const { saveConfig: saveCfg } = await import("./config.js");
|
|
367
367
|
config.tls = true;
|
|
368
368
|
saveCfg(config);
|
|
369
369
|
console.log(" TLS enabled in config.");
|
|
370
370
|
}
|
|
371
|
-
|
|
371
|
+
const pid = readPid();
|
|
372
372
|
if (pid !== null && isDaemonRunning(pid)) {
|
|
373
|
-
|
|
373
|
+
const restartAnswer = await prompt(" Daemon is running. Restart with TLS? [Y/n] ");
|
|
374
374
|
if (restartAnswer !== "n" && restartAnswer !== "no") {
|
|
375
375
|
console.log(" Restarting daemon...");
|
|
376
376
|
try {
|
|
@@ -379,8 +379,8 @@ async function runSetupTls() {
|
|
|
379
379
|
catch { }
|
|
380
380
|
removePid();
|
|
381
381
|
await new Promise(function (r) { setTimeout(r, 1500); });
|
|
382
|
-
|
|
383
|
-
|
|
382
|
+
const port = portOverride ?? config.port;
|
|
383
|
+
const childPid = spawnDaemon(port, true);
|
|
384
384
|
writePid(childPid);
|
|
385
385
|
console.log(" Daemon restarted (PID " + childPid + ")");
|
|
386
386
|
}
|
|
@@ -403,22 +403,22 @@ async function runSetupTls() {
|
|
|
403
403
|
console.log(" To regenerate: rm -rf " + certsDir + " && lattice setup-tls");
|
|
404
404
|
}
|
|
405
405
|
else {
|
|
406
|
-
|
|
406
|
+
const selfSignAnswer = await prompt(" Generate a self-signed certificate? [Y/n] ");
|
|
407
407
|
if (selfSignAnswer !== "n" && selfSignAnswer !== "no") {
|
|
408
|
-
|
|
408
|
+
const { ensureCerts } = await import("./tls.js");
|
|
409
409
|
try {
|
|
410
|
-
|
|
410
|
+
const certs = ensureCerts();
|
|
411
411
|
console.log(" Certificate generated: " + certs.cert);
|
|
412
|
-
|
|
412
|
+
const config = loadConfig();
|
|
413
413
|
if (!config.tls) {
|
|
414
|
-
|
|
414
|
+
const { saveConfig: saveCfg } = await import("./config.js");
|
|
415
415
|
config.tls = true;
|
|
416
416
|
saveCfg(config);
|
|
417
417
|
console.log(" TLS enabled in config.");
|
|
418
418
|
}
|
|
419
|
-
|
|
419
|
+
const pid = readPid();
|
|
420
420
|
if (pid !== null && isDaemonRunning(pid)) {
|
|
421
|
-
|
|
421
|
+
const restartAnswer = await prompt(" Daemon is running. Restart with TLS? [Y/n] ");
|
|
422
422
|
if (restartAnswer !== "n" && restartAnswer !== "no") {
|
|
423
423
|
console.log(" Restarting daemon...");
|
|
424
424
|
try {
|
|
@@ -427,8 +427,8 @@ async function runSetupTls() {
|
|
|
427
427
|
catch { }
|
|
428
428
|
removePid();
|
|
429
429
|
await new Promise(function (r) { setTimeout(r, 1500); });
|
|
430
|
-
|
|
431
|
-
|
|
430
|
+
const port = portOverride ?? config.port;
|
|
431
|
+
const childPid = spawnDaemon(port, true);
|
|
432
432
|
writePid(childPid);
|
|
433
433
|
console.log(" Daemon restarted (PID " + childPid + ")");
|
|
434
434
|
}
|
|
@@ -456,7 +456,7 @@ async function runSetupTls() {
|
|
|
456
456
|
console.log("");
|
|
457
457
|
}
|
|
458
458
|
async function runRestart() {
|
|
459
|
-
|
|
459
|
+
const pid = readPid();
|
|
460
460
|
if (pid !== null && isDaemonRunning(pid)) {
|
|
461
461
|
console.log("[lattice] Stopping daemon (PID " + pid + ")...");
|
|
462
462
|
try {
|
|
@@ -464,7 +464,7 @@ async function runRestart() {
|
|
|
464
464
|
}
|
|
465
465
|
catch { }
|
|
466
466
|
removePid();
|
|
467
|
-
|
|
467
|
+
let waited = 0;
|
|
468
468
|
while (waited < 5000) {
|
|
469
469
|
try {
|
|
470
470
|
process.kill(pid, 0);
|
|
@@ -477,14 +477,14 @@ async function runRestart() {
|
|
|
477
477
|
}
|
|
478
478
|
}
|
|
479
479
|
console.log("[lattice] Starting daemon...");
|
|
480
|
-
|
|
481
|
-
|
|
480
|
+
const restartPort = portOverride ?? loadConfig().port;
|
|
481
|
+
const childPid = spawnDaemon(restartPort, tlsOverride);
|
|
482
482
|
writePid(childPid);
|
|
483
483
|
console.log("[lattice] Daemon started (PID " + childPid + ")");
|
|
484
484
|
}
|
|
485
485
|
async function runVersion() {
|
|
486
|
-
|
|
487
|
-
|
|
486
|
+
const { checkForUpdate } = await import("./update-checker.js");
|
|
487
|
+
const info = await checkForUpdate(true);
|
|
488
488
|
console.log("[lattice] Current: v" + info.currentVersion);
|
|
489
489
|
if (info.latestVersion) {
|
|
490
490
|
if (info.updateAvailable) {
|
|
@@ -498,13 +498,13 @@ async function runVersion() {
|
|
|
498
498
|
console.log("[lattice] Mode: npm");
|
|
499
499
|
}
|
|
500
500
|
function runLogs() {
|
|
501
|
-
|
|
501
|
+
const logPath = join(getLatticeHome(), "daemon.log");
|
|
502
502
|
if (!existsSync(logPath)) {
|
|
503
503
|
console.log("[lattice] No log file found at " + logPath);
|
|
504
504
|
process.exit(1);
|
|
505
505
|
}
|
|
506
506
|
console.log("[lattice] Tailing " + logPath + " (Ctrl+C to stop)");
|
|
507
|
-
|
|
507
|
+
const proc = spawn("tail", ["-f", "-n", "50", logPath], {
|
|
508
508
|
stdio: ["ignore", "inherit", "inherit"],
|
|
509
509
|
});
|
|
510
510
|
process.on("SIGINT", function () {
|
|
@@ -513,26 +513,26 @@ function runLogs() {
|
|
|
513
513
|
});
|
|
514
514
|
}
|
|
515
515
|
function runOpen() {
|
|
516
|
-
|
|
517
|
-
|
|
516
|
+
const config = loadConfig();
|
|
517
|
+
const pid = readPid();
|
|
518
518
|
if (pid === null || !isDaemonRunning(pid)) {
|
|
519
519
|
console.log("[lattice] Daemon is not running. Start it with 'lattice start'");
|
|
520
520
|
process.exit(1);
|
|
521
521
|
}
|
|
522
|
-
|
|
522
|
+
const url = (config.tls ? "https" : "http") + "://localhost:" + config.port;
|
|
523
523
|
console.log("[lattice] Opening " + url);
|
|
524
524
|
openBrowser(url);
|
|
525
525
|
}
|
|
526
526
|
function runConfigInfo() {
|
|
527
|
-
|
|
528
|
-
|
|
527
|
+
const config = loadConfig();
|
|
528
|
+
const home = getLatticeHome();
|
|
529
529
|
console.log("[lattice] Home: " + home);
|
|
530
530
|
console.log("[lattice] Config: " + join(home, "config.json"));
|
|
531
531
|
console.log("[lattice] Port: " + config.port);
|
|
532
532
|
console.log("[lattice] Name: " + config.name);
|
|
533
533
|
console.log("[lattice] TLS: " + (config.tls ? "enabled" : "disabled"));
|
|
534
534
|
console.log("[lattice] Projects: " + config.projects.length);
|
|
535
|
-
for (
|
|
535
|
+
for (let i = 0; i < config.projects.length; i++) {
|
|
536
536
|
console.log(" " + config.projects[i].slug + " → " + config.projects[i].path);
|
|
537
537
|
}
|
|
538
538
|
if (config.passphraseHash) {
|
|
@@ -543,7 +543,7 @@ function runConfigInfo() {
|
|
|
543
543
|
}
|
|
544
544
|
}
|
|
545
545
|
function runStatus() {
|
|
546
|
-
|
|
546
|
+
const pid = readPid();
|
|
547
547
|
if (pid === null) {
|
|
548
548
|
console.log("[lattice] Status: not running (no PID file)");
|
|
549
549
|
process.exit(0);
|
|
@@ -553,17 +553,17 @@ function runStatus() {
|
|
|
553
553
|
removePid();
|
|
554
554
|
process.exit(0);
|
|
555
555
|
}
|
|
556
|
-
|
|
557
|
-
|
|
556
|
+
const config = loadConfig();
|
|
557
|
+
const url = (config.tls ? "https" : "http") + "://localhost:" + config.port;
|
|
558
558
|
console.log("[lattice] Status: running");
|
|
559
559
|
console.log("[lattice] PID: " + pid);
|
|
560
560
|
console.log("[lattice] Port: " + config.port);
|
|
561
561
|
console.log("[lattice] URL: " + url);
|
|
562
562
|
}
|
|
563
563
|
async function runUpdate() {
|
|
564
|
-
|
|
564
|
+
const { checkForUpdate, getPackageName } = await import("./update-checker.js");
|
|
565
565
|
console.log("[lattice] Checking for updates...");
|
|
566
|
-
|
|
566
|
+
const info = await checkForUpdate(true);
|
|
567
567
|
if (!info.latestVersion) {
|
|
568
568
|
console.log("[lattice] Could not check for updates. Try again later.");
|
|
569
569
|
process.exit(1);
|
|
@@ -574,16 +574,16 @@ async function runUpdate() {
|
|
|
574
574
|
}
|
|
575
575
|
console.log("[lattice] Update available: %s -> %s", info.currentVersion, info.latestVersion);
|
|
576
576
|
console.log("[lattice] Installing...");
|
|
577
|
-
|
|
578
|
-
|
|
577
|
+
const pkgName = getPackageName();
|
|
578
|
+
const proc = spawn("npm", ["install", "-g", pkgName + "@latest"], {
|
|
579
579
|
stdio: ["ignore", "inherit", "inherit"],
|
|
580
580
|
});
|
|
581
|
-
|
|
581
|
+
const code = await new Promise(function (resolve) {
|
|
582
582
|
proc.on("close", function (c) { resolve(c ?? 1); });
|
|
583
583
|
});
|
|
584
584
|
if (code === 0) {
|
|
585
585
|
console.log("[lattice] Updated to %s", info.latestVersion);
|
|
586
|
-
|
|
586
|
+
const pid = readPid();
|
|
587
587
|
if (pid !== null && isDaemonRunning(pid)) {
|
|
588
588
|
console.log("[lattice] Restarting daemon...");
|
|
589
589
|
try {
|
|
@@ -592,8 +592,8 @@ async function runUpdate() {
|
|
|
592
592
|
catch { }
|
|
593
593
|
removePid();
|
|
594
594
|
await new Promise(function (resolve) { setTimeout(resolve, 1000); });
|
|
595
|
-
|
|
596
|
-
|
|
595
|
+
const updatePort = portOverride ?? loadConfig().port;
|
|
596
|
+
const childPid = spawnDaemon(updatePort, tlsOverride);
|
|
597
597
|
writePid(childPid);
|
|
598
598
|
console.log("[lattice] Daemon restarted (PID %d)", childPid);
|
|
599
599
|
}
|
|
@@ -604,7 +604,7 @@ async function runUpdate() {
|
|
|
604
604
|
}
|
|
605
605
|
}
|
|
606
606
|
function openBrowser(url) {
|
|
607
|
-
|
|
607
|
+
const platform = process.platform;
|
|
608
608
|
try {
|
|
609
609
|
if (platform === "win32") {
|
|
610
610
|
spawn("cmd", ["/c", "start", url], { detached: true, stdio: "ignore" }).unref();
|
package/dist/server/logger.js
CHANGED