@adhdev/daemon-standalone 0.8.76 → 0.8.77
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/index.js
CHANGED
|
@@ -9244,7 +9244,7 @@ var require_dist = __commonJS({
|
|
|
9244
9244
|
}
|
|
9245
9245
|
}
|
|
9246
9246
|
};
|
|
9247
|
-
var
|
|
9247
|
+
var import_crypto3 = require("crypto");
|
|
9248
9248
|
var path5 = __toESM2(require("path"));
|
|
9249
9249
|
function normalizeSlug(input) {
|
|
9250
9250
|
return input.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 48);
|
|
@@ -9360,7 +9360,7 @@ var require_dist = __commonJS({
|
|
|
9360
9360
|
var SessionHostRegistry = class {
|
|
9361
9361
|
sessions = /* @__PURE__ */ new Map();
|
|
9362
9362
|
createSession(payload) {
|
|
9363
|
-
const sessionId = payload.sessionId || (0,
|
|
9363
|
+
const sessionId = payload.sessionId || (0, import_crypto3.randomUUID)();
|
|
9364
9364
|
if (this.sessions.has(sessionId)) {
|
|
9365
9365
|
throw new Error(`Session already exists: ${sessionId}`);
|
|
9366
9366
|
}
|
|
@@ -26823,9 +26823,9 @@ var init_handler = __esm({
|
|
|
26823
26823
|
if (this.fsw.closed) {
|
|
26824
26824
|
return;
|
|
26825
26825
|
}
|
|
26826
|
-
const
|
|
26826
|
+
const dirname4 = sp.dirname(file2);
|
|
26827
26827
|
const basename3 = sp.basename(file2);
|
|
26828
|
-
const parent = this.fsw._getWatchedDir(
|
|
26828
|
+
const parent = this.fsw._getWatchedDir(dirname4);
|
|
26829
26829
|
let prevStats = stats;
|
|
26830
26830
|
if (parent.has(basename3))
|
|
26831
26831
|
return;
|
|
@@ -26852,7 +26852,7 @@ var init_handler = __esm({
|
|
|
26852
26852
|
prevStats = newStats2;
|
|
26853
26853
|
}
|
|
26854
26854
|
} catch (error48) {
|
|
26855
|
-
this.fsw._remove(
|
|
26855
|
+
this.fsw._remove(dirname4, basename3);
|
|
26856
26856
|
}
|
|
26857
26857
|
} else if (parent.has(basename3)) {
|
|
26858
26858
|
const at2 = newStats.atimeMs;
|
|
@@ -27927,7 +27927,7 @@ var require_dist2 = __commonJS({
|
|
|
27927
27927
|
};
|
|
27928
27928
|
}
|
|
27929
27929
|
function generateMachineId() {
|
|
27930
|
-
return `${MACHINE_ID_PREFIX}${(0,
|
|
27930
|
+
return `${MACHINE_ID_PREFIX}${(0, import_crypto3.randomUUID)().replace(/-/g, "")}`;
|
|
27931
27931
|
}
|
|
27932
27932
|
function isStableMachineId(machineId) {
|
|
27933
27933
|
return typeof machineId === "string" && machineId.startsWith(MACHINE_ID_PREFIX);
|
|
@@ -28046,7 +28046,7 @@ var require_dist2 = __commonJS({
|
|
|
28046
28046
|
var import_os2;
|
|
28047
28047
|
var import_path2;
|
|
28048
28048
|
var import_fs;
|
|
28049
|
-
var
|
|
28049
|
+
var import_crypto3;
|
|
28050
28050
|
var DEFAULT_CONFIG;
|
|
28051
28051
|
var MACHINE_ID_PREFIX;
|
|
28052
28052
|
var init_config = __esm2({
|
|
@@ -28055,7 +28055,7 @@ var require_dist2 = __commonJS({
|
|
|
28055
28055
|
import_os2 = require("os");
|
|
28056
28056
|
import_path2 = require("path");
|
|
28057
28057
|
import_fs = require("fs");
|
|
28058
|
-
|
|
28058
|
+
import_crypto3 = require("crypto");
|
|
28059
28059
|
DEFAULT_CONFIG = {
|
|
28060
28060
|
serverUrl: "https://api.adhf.dev",
|
|
28061
28061
|
allowServerApiProxy: false,
|
|
@@ -32229,12 +32229,66 @@ ${data.message || ""}`.trim();
|
|
|
32229
32229
|
const availableMem = darwinAvail != null ? darwinAvail : freeMem;
|
|
32230
32230
|
return { totalMem, freeMem, availableMem };
|
|
32231
32231
|
}
|
|
32232
|
+
var LIVE_LIFECYCLES = /* @__PURE__ */ new Set(["starting", "running", "stopping", "interrupted"]);
|
|
32233
|
+
function isSessionHostLiveRuntime(record2) {
|
|
32234
|
+
const lifecycle = String(record2?.lifecycle || "").trim();
|
|
32235
|
+
return LIVE_LIFECYCLES.has(lifecycle);
|
|
32236
|
+
}
|
|
32237
|
+
function getSessionHostRecoveryLabel(meta3) {
|
|
32238
|
+
const recoveryState = typeof meta3?.runtimeRecoveryState === "string" ? String(meta3.runtimeRecoveryState).trim() : "";
|
|
32239
|
+
if (!recoveryState) return null;
|
|
32240
|
+
if (recoveryState === "auto_resumed") return "restored after restart";
|
|
32241
|
+
if (recoveryState === "resume_failed") return "restore failed";
|
|
32242
|
+
if (recoveryState === "host_restart_interrupted") return "host restart interrupted";
|
|
32243
|
+
if (recoveryState === "orphan_snapshot") return "snapshot recovered";
|
|
32244
|
+
return recoveryState.replace(/_/g, " ");
|
|
32245
|
+
}
|
|
32246
|
+
function isSessionHostRecoverySnapshot(record2) {
|
|
32247
|
+
if (!record2) return false;
|
|
32248
|
+
if (isSessionHostLiveRuntime(record2)) return false;
|
|
32249
|
+
const lifecycle = String(record2.lifecycle || "").trim();
|
|
32250
|
+
if (lifecycle && lifecycle !== "stopped" && lifecycle !== "failed") {
|
|
32251
|
+
return false;
|
|
32252
|
+
}
|
|
32253
|
+
const meta3 = record2.meta || void 0;
|
|
32254
|
+
if (meta3?.restoredFromStorage === true) return true;
|
|
32255
|
+
return getSessionHostRecoveryLabel(meta3) !== null;
|
|
32256
|
+
}
|
|
32257
|
+
function getSessionHostSurfaceKind(record2) {
|
|
32258
|
+
if (isSessionHostLiveRuntime(record2)) return "live_runtime";
|
|
32259
|
+
if (isSessionHostRecoverySnapshot(record2)) return "recovery_snapshot";
|
|
32260
|
+
return "inactive_record";
|
|
32261
|
+
}
|
|
32262
|
+
function partitionSessionHostRecords(records) {
|
|
32263
|
+
const liveRuntimes = [];
|
|
32264
|
+
const recoverySnapshots = [];
|
|
32265
|
+
const inactiveRecords = [];
|
|
32266
|
+
for (const record2 of records) {
|
|
32267
|
+
const kind = getSessionHostSurfaceKind(record2);
|
|
32268
|
+
if (kind === "live_runtime") {
|
|
32269
|
+
liveRuntimes.push(record2);
|
|
32270
|
+
} else if (kind === "recovery_snapshot") {
|
|
32271
|
+
recoverySnapshots.push(record2);
|
|
32272
|
+
} else {
|
|
32273
|
+
inactiveRecords.push(record2);
|
|
32274
|
+
}
|
|
32275
|
+
}
|
|
32276
|
+
return {
|
|
32277
|
+
liveRuntimes,
|
|
32278
|
+
recoverySnapshots,
|
|
32279
|
+
inactiveRecords
|
|
32280
|
+
};
|
|
32281
|
+
}
|
|
32282
|
+
function partitionSessionHostDiagnosticsSessions(records) {
|
|
32283
|
+
return partitionSessionHostRecords(records || []);
|
|
32284
|
+
}
|
|
32232
32285
|
var DEFAULT_ACTIVE_CHAT_POLL_STATUSES = /* @__PURE__ */ new Set([
|
|
32233
32286
|
"generating",
|
|
32234
32287
|
"waiting_approval",
|
|
32235
32288
|
"starting"
|
|
32236
32289
|
]);
|
|
32237
32290
|
var DEFAULT_CHAT_TAIL_RECENT_MESSAGE_GRACE_MS = 8e3;
|
|
32291
|
+
var LIVE_RUNTIME_LIFECYCLES = /* @__PURE__ */ new Set(["starting", "running", "stopping", "interrupted"]);
|
|
32238
32292
|
function parseMessageTimestamp(value) {
|
|
32239
32293
|
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
32240
32294
|
if (typeof value === "string") {
|
|
@@ -32243,6 +32297,23 @@ ${data.message || ""}`.trim();
|
|
|
32243
32297
|
}
|
|
32244
32298
|
return 0;
|
|
32245
32299
|
}
|
|
32300
|
+
function isDefinitelyNonLiveRuntimeSession(session) {
|
|
32301
|
+
const surfaceKind = String(session?.runtimeSurfaceKind || "").trim();
|
|
32302
|
+
if (surfaceKind === "live_runtime") return false;
|
|
32303
|
+
if (surfaceKind === "recovery_snapshot") return true;
|
|
32304
|
+
if (surfaceKind === "inactive_record") return false;
|
|
32305
|
+
const lifecycle = String(session?.runtimeLifecycle || "").trim();
|
|
32306
|
+
if (lifecycle && LIVE_RUNTIME_LIFECYCLES.has(lifecycle)) return false;
|
|
32307
|
+
const inferredSurfaceKind = getSessionHostSurfaceKind({
|
|
32308
|
+
lifecycle: lifecycle || null,
|
|
32309
|
+
meta: {
|
|
32310
|
+
restoredFromStorage: session?.runtimeRestoredFromStorage === true,
|
|
32311
|
+
...session?.runtimeRecoveryState ? { runtimeRecoveryState: session.runtimeRecoveryState } : {}
|
|
32312
|
+
}
|
|
32313
|
+
});
|
|
32314
|
+
if (inferredSurfaceKind === "recovery_snapshot") return true;
|
|
32315
|
+
return false;
|
|
32316
|
+
}
|
|
32246
32317
|
function classifyHotChatSessionsForSubscriptionFlush2(sessions, previousHotSessionIds, options = {}) {
|
|
32247
32318
|
const now = options.now ?? Date.now();
|
|
32248
32319
|
const recentMessageGraceMs = Math.max(
|
|
@@ -32251,9 +32322,14 @@ ${data.message || ""}`.trim();
|
|
|
32251
32322
|
);
|
|
32252
32323
|
const activeStatuses = options.activeStatuses ?? DEFAULT_ACTIVE_CHAT_POLL_STATUSES;
|
|
32253
32324
|
const active = /* @__PURE__ */ new Set();
|
|
32325
|
+
const excluded = /* @__PURE__ */ new Set();
|
|
32254
32326
|
for (const session of sessions) {
|
|
32255
32327
|
const sessionId = typeof session?.id === "string" ? session.id : "";
|
|
32256
32328
|
if (!sessionId) continue;
|
|
32329
|
+
if (isDefinitelyNonLiveRuntimeSession(session)) {
|
|
32330
|
+
excluded.add(sessionId);
|
|
32331
|
+
continue;
|
|
32332
|
+
}
|
|
32257
32333
|
const status = String(session?.status || "").toLowerCase();
|
|
32258
32334
|
const lastMessageAt = parseMessageTimestamp(session?.lastMessageAt);
|
|
32259
32335
|
const recentlyUpdated = lastMessageAt > 0 && now - lastMessageAt <= recentMessageGraceMs;
|
|
@@ -32262,7 +32338,7 @@ ${data.message || ""}`.trim();
|
|
|
32262
32338
|
}
|
|
32263
32339
|
}
|
|
32264
32340
|
const finalizing = new Set(
|
|
32265
|
-
Array.from(previousHotSessionIds).filter((sessionId) => !active.has(sessionId))
|
|
32341
|
+
Array.from(previousHotSessionIds).filter((sessionId) => !active.has(sessionId) && !excluded.has(sessionId))
|
|
32266
32342
|
);
|
|
32267
32343
|
return { active, finalizing };
|
|
32268
32344
|
}
|
|
@@ -36481,7 +36557,7 @@ ${effect.notification.body || ""}`.trim();
|
|
|
36481
36557
|
return profile !== "live";
|
|
36482
36558
|
}
|
|
36483
36559
|
function shouldIncludeRuntimeMetadata(profile) {
|
|
36484
|
-
return
|
|
36560
|
+
return true;
|
|
36485
36561
|
}
|
|
36486
36562
|
function findCdpManager(cdpManagers, key) {
|
|
36487
36563
|
const exact = cdpManagers.get(key);
|
|
@@ -36636,8 +36712,12 @@ ${effect.notification.body || ""}`.trim();
|
|
|
36636
36712
|
runtimeKey: state.runtime?.runtimeKey,
|
|
36637
36713
|
runtimeDisplayName: state.runtime?.displayName,
|
|
36638
36714
|
runtimeWorkspaceLabel: state.runtime?.workspaceLabel,
|
|
36715
|
+
runtimeLifecycle: state.runtime?.lifecycle ?? null,
|
|
36716
|
+
runtimeSurfaceKind: state.runtime?.surfaceKind,
|
|
36639
36717
|
runtimeWriteOwner: state.runtime?.writeOwner || null,
|
|
36640
|
-
runtimeAttachedClients: state.runtime?.attachedClients || []
|
|
36718
|
+
runtimeAttachedClients: state.runtime?.attachedClients || [],
|
|
36719
|
+
runtimeRestoredFromStorage: state.runtime?.restoredFromStorage === true,
|
|
36720
|
+
runtimeRecoveryState: state.runtime?.recoveryState ?? null
|
|
36641
36721
|
},
|
|
36642
36722
|
mode: state.mode,
|
|
36643
36723
|
resume: state.resume,
|
|
@@ -39884,8 +39964,12 @@ ${effect.notification.body || ""}`.trim();
|
|
|
39884
39964
|
runtimeKey: runtime.runtimeKey,
|
|
39885
39965
|
displayName: runtime.displayName,
|
|
39886
39966
|
workspaceLabel: runtime.workspaceLabel,
|
|
39967
|
+
lifecycle: runtime.lifecycle ?? null,
|
|
39968
|
+
surfaceKind: runtime.surfaceKind,
|
|
39887
39969
|
writeOwner: runtime.writeOwner || null,
|
|
39888
|
-
attachedClients: runtime.attachedClients || []
|
|
39970
|
+
attachedClients: runtime.attachedClients || [],
|
|
39971
|
+
restoredFromStorage: runtime.restoredFromStorage === true,
|
|
39972
|
+
recoveryState: runtime.recoveryState ?? null
|
|
39889
39973
|
} : void 0,
|
|
39890
39974
|
resume: this.provider.resume,
|
|
39891
39975
|
controlValues: surface.controlValues,
|
|
@@ -44167,59 +44251,6 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
44167
44251
|
}
|
|
44168
44252
|
cleanOldFiles();
|
|
44169
44253
|
init_logger();
|
|
44170
|
-
var LIVE_LIFECYCLES = /* @__PURE__ */ new Set(["starting", "running", "stopping", "interrupted"]);
|
|
44171
|
-
function isSessionHostLiveRuntime(record2) {
|
|
44172
|
-
const lifecycle = String(record2?.lifecycle || "").trim();
|
|
44173
|
-
return LIVE_LIFECYCLES.has(lifecycle);
|
|
44174
|
-
}
|
|
44175
|
-
function getSessionHostRecoveryLabel(meta3) {
|
|
44176
|
-
const recoveryState = typeof meta3?.runtimeRecoveryState === "string" ? String(meta3.runtimeRecoveryState).trim() : "";
|
|
44177
|
-
if (!recoveryState) return null;
|
|
44178
|
-
if (recoveryState === "auto_resumed") return "restored after restart";
|
|
44179
|
-
if (recoveryState === "resume_failed") return "restore failed";
|
|
44180
|
-
if (recoveryState === "host_restart_interrupted") return "host restart interrupted";
|
|
44181
|
-
if (recoveryState === "orphan_snapshot") return "snapshot recovered";
|
|
44182
|
-
return recoveryState.replace(/_/g, " ");
|
|
44183
|
-
}
|
|
44184
|
-
function isSessionHostRecoverySnapshot(record2) {
|
|
44185
|
-
if (!record2) return false;
|
|
44186
|
-
if (isSessionHostLiveRuntime(record2)) return false;
|
|
44187
|
-
const lifecycle = String(record2.lifecycle || "").trim();
|
|
44188
|
-
if (lifecycle && lifecycle !== "stopped" && lifecycle !== "failed") {
|
|
44189
|
-
return false;
|
|
44190
|
-
}
|
|
44191
|
-
const meta3 = record2.meta || void 0;
|
|
44192
|
-
if (meta3?.restoredFromStorage === true) return true;
|
|
44193
|
-
return getSessionHostRecoveryLabel(meta3) !== null;
|
|
44194
|
-
}
|
|
44195
|
-
function getSessionHostSurfaceKind(record2) {
|
|
44196
|
-
if (isSessionHostLiveRuntime(record2)) return "live_runtime";
|
|
44197
|
-
if (isSessionHostRecoverySnapshot(record2)) return "recovery_snapshot";
|
|
44198
|
-
return "inactive_record";
|
|
44199
|
-
}
|
|
44200
|
-
function partitionSessionHostRecords(records) {
|
|
44201
|
-
const liveRuntimes = [];
|
|
44202
|
-
const recoverySnapshots = [];
|
|
44203
|
-
const inactiveRecords = [];
|
|
44204
|
-
for (const record2 of records) {
|
|
44205
|
-
const kind = getSessionHostSurfaceKind(record2);
|
|
44206
|
-
if (kind === "live_runtime") {
|
|
44207
|
-
liveRuntimes.push(record2);
|
|
44208
|
-
} else if (kind === "recovery_snapshot") {
|
|
44209
|
-
recoverySnapshots.push(record2);
|
|
44210
|
-
} else {
|
|
44211
|
-
inactiveRecords.push(record2);
|
|
44212
|
-
}
|
|
44213
|
-
}
|
|
44214
|
-
return {
|
|
44215
|
-
liveRuntimes,
|
|
44216
|
-
recoverySnapshots,
|
|
44217
|
-
inactiveRecords
|
|
44218
|
-
};
|
|
44219
|
-
}
|
|
44220
|
-
function partitionSessionHostDiagnosticsSessions(records) {
|
|
44221
|
-
return partitionSessionHostRecords(records || []);
|
|
44222
|
-
}
|
|
44223
44254
|
var os16 = __toESM2(require("os"));
|
|
44224
44255
|
init_config();
|
|
44225
44256
|
init_terminal_screen();
|
|
@@ -52547,6 +52578,8 @@ data: ${JSON.stringify(msg.data)}
|
|
|
52547
52578
|
runtimeKey: record2.runtimeKey,
|
|
52548
52579
|
displayName: record2.displayName,
|
|
52549
52580
|
workspaceLabel: record2.workspaceLabel,
|
|
52581
|
+
lifecycle: typeof record2.lifecycle === "string" ? record2.lifecycle : null,
|
|
52582
|
+
surfaceKind: record2.surfaceKind,
|
|
52550
52583
|
writeOwner: record2.writeOwner ? {
|
|
52551
52584
|
clientId: record2.writeOwner.clientId,
|
|
52552
52585
|
ownerType: record2.writeOwner.ownerType
|
|
@@ -53149,6 +53182,7 @@ var import_ws = require("ws");
|
|
|
53149
53182
|
var path4 = __toESM(require("path"));
|
|
53150
53183
|
var fs3 = __toESM(require("fs"));
|
|
53151
53184
|
var os5 = __toESM(require("os"));
|
|
53185
|
+
var import_crypto2 = require("crypto");
|
|
53152
53186
|
var import_daemon_core2 = __toESM(require_dist2());
|
|
53153
53187
|
|
|
53154
53188
|
// src/session-host.ts
|
|
@@ -53654,6 +53688,165 @@ async function getWorkspaceSocketInfo(workspaceName) {
|
|
|
53654
53688
|
var import_daemon_core3 = __toESM(require_dist2());
|
|
53655
53689
|
var DEFAULT_PORT = 3847;
|
|
53656
53690
|
var STATUS_INTERVAL = 2e3;
|
|
53691
|
+
var STANDALONE_AUTH_SESSION_COOKIE = "adhdev_standalone_session";
|
|
53692
|
+
var STANDALONE_PASSWORD_CONFIG_FILE = "standalone-auth.json";
|
|
53693
|
+
var STANDALONE_BIND_HOST_CONFIG_FILE = "standalone-network.json";
|
|
53694
|
+
var STANDALONE_BIND_HOST_DEFAULT = "127.0.0.1";
|
|
53695
|
+
var PASSWORD_KEYLEN = 64;
|
|
53696
|
+
var DEFAULT_SESSION_TTL_MS = 1e3 * 60 * 60 * 24 * 30;
|
|
53697
|
+
function getStandalonePasswordConfigPath() {
|
|
53698
|
+
const dir = path4.join(os5.homedir(), ".adhdev");
|
|
53699
|
+
if (!fs3.existsSync(dir)) {
|
|
53700
|
+
fs3.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
53701
|
+
}
|
|
53702
|
+
return path4.join(dir, STANDALONE_PASSWORD_CONFIG_FILE);
|
|
53703
|
+
}
|
|
53704
|
+
function getStandaloneConfigJsonPath() {
|
|
53705
|
+
const dir = path4.join(os5.homedir(), ".adhdev");
|
|
53706
|
+
if (!fs3.existsSync(dir)) {
|
|
53707
|
+
fs3.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
53708
|
+
}
|
|
53709
|
+
return path4.join(dir, STANDALONE_BIND_HOST_CONFIG_FILE);
|
|
53710
|
+
}
|
|
53711
|
+
function loadStandaloneBindHostPreference() {
|
|
53712
|
+
try {
|
|
53713
|
+
const configPath = getStandaloneConfigJsonPath();
|
|
53714
|
+
if (!fs3.existsSync(configPath)) return STANDALONE_BIND_HOST_DEFAULT;
|
|
53715
|
+
const parsed = JSON.parse(fs3.readFileSync(configPath, "utf8"));
|
|
53716
|
+
return parsed?.standaloneBindHost === "0.0.0.0" ? "0.0.0.0" : STANDALONE_BIND_HOST_DEFAULT;
|
|
53717
|
+
} catch {
|
|
53718
|
+
return STANDALONE_BIND_HOST_DEFAULT;
|
|
53719
|
+
}
|
|
53720
|
+
}
|
|
53721
|
+
function saveStandaloneBindHostPreference(bindHost) {
|
|
53722
|
+
const configPath = getStandaloneConfigJsonPath();
|
|
53723
|
+
let parsed = {};
|
|
53724
|
+
try {
|
|
53725
|
+
if (fs3.existsSync(configPath)) {
|
|
53726
|
+
const raw = fs3.readFileSync(configPath, "utf8");
|
|
53727
|
+
const next = JSON.parse(raw);
|
|
53728
|
+
if (next && typeof next === "object" && !Array.isArray(next)) parsed = next;
|
|
53729
|
+
}
|
|
53730
|
+
} catch {
|
|
53731
|
+
parsed = {};
|
|
53732
|
+
}
|
|
53733
|
+
parsed.standaloneBindHost = bindHost;
|
|
53734
|
+
fs3.writeFileSync(configPath, JSON.stringify(parsed, null, 2), { encoding: "utf8", mode: 384 });
|
|
53735
|
+
try {
|
|
53736
|
+
fs3.chmodSync(configPath, 384);
|
|
53737
|
+
} catch {
|
|
53738
|
+
}
|
|
53739
|
+
return bindHost;
|
|
53740
|
+
}
|
|
53741
|
+
function createPasswordRecord(password, salt = (0, import_crypto2.randomBytes)(16).toString("hex")) {
|
|
53742
|
+
return {
|
|
53743
|
+
passwordHash: (0, import_crypto2.scryptSync)(`${password || ""}`, salt, PASSWORD_KEYLEN).toString("hex"),
|
|
53744
|
+
passwordSalt: salt,
|
|
53745
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
53746
|
+
};
|
|
53747
|
+
}
|
|
53748
|
+
function verifyPassword(password, config2) {
|
|
53749
|
+
if (!config2?.passwordHash || !config2.passwordSalt) return false;
|
|
53750
|
+
const actual = Buffer.from((0, import_crypto2.scryptSync)(`${password || ""}`, config2.passwordSalt, PASSWORD_KEYLEN).toString("hex"), "utf8");
|
|
53751
|
+
const expected = Buffer.from(config2.passwordHash, "utf8");
|
|
53752
|
+
return actual.length === expected.length && (0, import_crypto2.timingSafeEqual)(actual, expected);
|
|
53753
|
+
}
|
|
53754
|
+
function loadStandalonePasswordConfig(filePath = getStandalonePasswordConfigPath()) {
|
|
53755
|
+
if (!fs3.existsSync(filePath)) return null;
|
|
53756
|
+
try {
|
|
53757
|
+
const parsed = JSON.parse(fs3.readFileSync(filePath, "utf8"));
|
|
53758
|
+
if (!parsed || typeof parsed !== "object") return null;
|
|
53759
|
+
if (typeof parsed.passwordHash !== "string" || typeof parsed.passwordSalt !== "string") return null;
|
|
53760
|
+
return {
|
|
53761
|
+
passwordHash: parsed.passwordHash,
|
|
53762
|
+
passwordSalt: parsed.passwordSalt,
|
|
53763
|
+
updatedAt: typeof parsed.updatedAt === "string" ? parsed.updatedAt : (/* @__PURE__ */ new Date(0)).toISOString()
|
|
53764
|
+
};
|
|
53765
|
+
} catch {
|
|
53766
|
+
return null;
|
|
53767
|
+
}
|
|
53768
|
+
}
|
|
53769
|
+
function saveStandalonePasswordConfig(filePath, config2) {
|
|
53770
|
+
const dir = path4.dirname(filePath);
|
|
53771
|
+
if (!fs3.existsSync(dir)) {
|
|
53772
|
+
fs3.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
53773
|
+
}
|
|
53774
|
+
fs3.writeFileSync(filePath, JSON.stringify(config2, null, 2), { encoding: "utf8", mode: 384 });
|
|
53775
|
+
try {
|
|
53776
|
+
fs3.chmodSync(filePath, 384);
|
|
53777
|
+
} catch {
|
|
53778
|
+
}
|
|
53779
|
+
}
|
|
53780
|
+
function clearStandalonePasswordConfig(filePath = getStandalonePasswordConfigPath()) {
|
|
53781
|
+
if (fs3.existsSync(filePath)) {
|
|
53782
|
+
fs3.rmSync(filePath, { force: true });
|
|
53783
|
+
}
|
|
53784
|
+
}
|
|
53785
|
+
function shouldWarnForPublicUnauthenticatedHost(input) {
|
|
53786
|
+
return input.host === "0.0.0.0" && !input.hasTokenAuth && !input.hasPasswordAuth;
|
|
53787
|
+
}
|
|
53788
|
+
function parseCookies(cookieHeader) {
|
|
53789
|
+
if (!cookieHeader) return {};
|
|
53790
|
+
return Object.fromEntries(
|
|
53791
|
+
cookieHeader.split(";").map((part) => part.trim()).filter(Boolean).map((part) => {
|
|
53792
|
+
const eq = part.indexOf("=");
|
|
53793
|
+
if (eq === -1) return [part, ""];
|
|
53794
|
+
return [part.slice(0, eq), decodeURIComponent(part.slice(eq + 1))];
|
|
53795
|
+
})
|
|
53796
|
+
);
|
|
53797
|
+
}
|
|
53798
|
+
function buildSessionCookie(sessionId, secure, maxAgeMs = DEFAULT_SESSION_TTL_MS) {
|
|
53799
|
+
const parts = [
|
|
53800
|
+
`${STANDALONE_AUTH_SESSION_COOKIE}=${encodeURIComponent(sessionId)}`,
|
|
53801
|
+
"Path=/",
|
|
53802
|
+
"HttpOnly",
|
|
53803
|
+
"SameSite=Lax",
|
|
53804
|
+
`Max-Age=${Math.max(0, Math.floor(maxAgeMs / 1e3))}`
|
|
53805
|
+
];
|
|
53806
|
+
if (secure) parts.push("Secure");
|
|
53807
|
+
return parts.join("; ");
|
|
53808
|
+
}
|
|
53809
|
+
function buildClearedSessionCookie(secure) {
|
|
53810
|
+
return buildSessionCookie("", secure, 0);
|
|
53811
|
+
}
|
|
53812
|
+
var StandaloneSessionStore = class {
|
|
53813
|
+
sessions = /* @__PURE__ */ new Map();
|
|
53814
|
+
create(ttlMs = DEFAULT_SESSION_TTL_MS) {
|
|
53815
|
+
const id = (0, import_crypto2.randomBytes)(24).toString("hex");
|
|
53816
|
+
this.sessions.set(id, Date.now() + ttlMs);
|
|
53817
|
+
return id;
|
|
53818
|
+
}
|
|
53819
|
+
has(sessionId) {
|
|
53820
|
+
if (!sessionId) return false;
|
|
53821
|
+
const expiresAt = this.sessions.get(sessionId);
|
|
53822
|
+
if (!expiresAt) return false;
|
|
53823
|
+
if (expiresAt <= Date.now()) {
|
|
53824
|
+
this.sessions.delete(sessionId);
|
|
53825
|
+
return false;
|
|
53826
|
+
}
|
|
53827
|
+
return true;
|
|
53828
|
+
}
|
|
53829
|
+
revoke(sessionId) {
|
|
53830
|
+
if (!sessionId) return;
|
|
53831
|
+
this.sessions.delete(sessionId);
|
|
53832
|
+
}
|
|
53833
|
+
clear() {
|
|
53834
|
+
this.sessions.clear();
|
|
53835
|
+
}
|
|
53836
|
+
};
|
|
53837
|
+
function isStandaloneRequestAuthenticated(input) {
|
|
53838
|
+
const hasTokenAuth = !!input.configuredToken;
|
|
53839
|
+
const hasPasswordAuth = !!input.passwordConfig;
|
|
53840
|
+
if (!hasTokenAuth && !hasPasswordAuth) return true;
|
|
53841
|
+
if (hasTokenAuth && (input.bearerToken === input.configuredToken || input.queryToken === input.configuredToken)) {
|
|
53842
|
+
return true;
|
|
53843
|
+
}
|
|
53844
|
+
if (hasPasswordAuth) {
|
|
53845
|
+
const cookies = parseCookies(input.cookieHeader);
|
|
53846
|
+
return input.sessionStore.has(cookies[STANDALONE_AUTH_SESSION_COOKIE]);
|
|
53847
|
+
}
|
|
53848
|
+
return false;
|
|
53849
|
+
}
|
|
53657
53850
|
var pkgVersion = process.env.ADHDEV_PKG_VERSION || "unknown";
|
|
53658
53851
|
if (pkgVersion === "unknown") {
|
|
53659
53852
|
try {
|
|
@@ -53702,6 +53895,10 @@ var StandaloneServer = class {
|
|
|
53702
53895
|
wsSessionModalSubscriptions = /* @__PURE__ */ new Map();
|
|
53703
53896
|
wsDaemonMetadataSubscriptions = /* @__PURE__ */ new Map();
|
|
53704
53897
|
authToken = null;
|
|
53898
|
+
passwordConfigPath = getStandalonePasswordConfigPath();
|
|
53899
|
+
passwordConfig = null;
|
|
53900
|
+
authSessions = new StandaloneSessionStore();
|
|
53901
|
+
listenHost = "127.0.0.1";
|
|
53705
53902
|
statusTimer = null;
|
|
53706
53903
|
lastStatusBroadcastAt = 0;
|
|
53707
53904
|
statusBroadcastPending = false;
|
|
@@ -53758,10 +53955,88 @@ var StandaloneServer = class {
|
|
|
53758
53955
|
const mode = this.getCliPresentationMode(sessionId);
|
|
53759
53956
|
return mode === "chat" || mode === "terminal";
|
|
53760
53957
|
}
|
|
53958
|
+
hasPasswordAuth() {
|
|
53959
|
+
return !!this.passwordConfig;
|
|
53960
|
+
}
|
|
53961
|
+
hasAnyAuth() {
|
|
53962
|
+
return !!this.authToken || this.hasPasswordAuth();
|
|
53963
|
+
}
|
|
53964
|
+
getCookieSecureFlag(req) {
|
|
53965
|
+
const forwardedProto = req.headers["x-forwarded-proto"];
|
|
53966
|
+
return !!req.socket.encrypted || typeof forwardedProto === "string" && forwardedProto.toLowerCase().includes("https");
|
|
53967
|
+
}
|
|
53968
|
+
getRequestTokens(req, rawUrl) {
|
|
53969
|
+
const authHeader = req.headers["authorization"];
|
|
53970
|
+
const bearerToken = typeof authHeader === "string" && authHeader.startsWith("Bearer ") ? authHeader.slice(7) : null;
|
|
53971
|
+
const queryToken = new URL(rawUrl, `http://${req.headers.host || "localhost"}`).searchParams.get("token");
|
|
53972
|
+
return { bearerToken, queryToken };
|
|
53973
|
+
}
|
|
53974
|
+
isRequestAuthenticated(req, rawUrl) {
|
|
53975
|
+
const { bearerToken, queryToken } = this.getRequestTokens(req, rawUrl);
|
|
53976
|
+
return isStandaloneRequestAuthenticated({
|
|
53977
|
+
configuredToken: this.authToken,
|
|
53978
|
+
passwordConfig: this.passwordConfig,
|
|
53979
|
+
bearerToken,
|
|
53980
|
+
queryToken,
|
|
53981
|
+
cookieHeader: typeof req.headers.cookie === "string" ? req.headers.cookie : void 0,
|
|
53982
|
+
sessionStore: this.authSessions
|
|
53983
|
+
});
|
|
53984
|
+
}
|
|
53985
|
+
getRequestSessionId(req) {
|
|
53986
|
+
const cookies = parseCookies(typeof req.headers.cookie === "string" ? req.headers.cookie : void 0);
|
|
53987
|
+
return cookies.adhdev_standalone_session || null;
|
|
53988
|
+
}
|
|
53989
|
+
buildAuthStatus(req, rawUrl) {
|
|
53990
|
+
const required2 = this.hasAnyAuth();
|
|
53991
|
+
return {
|
|
53992
|
+
required: required2,
|
|
53993
|
+
authenticated: this.isRequestAuthenticated(req, rawUrl),
|
|
53994
|
+
hasTokenAuth: !!this.authToken,
|
|
53995
|
+
hasPasswordAuth: this.hasPasswordAuth(),
|
|
53996
|
+
publicHostWarning: shouldWarnForPublicUnauthenticatedHost({
|
|
53997
|
+
host: this.listenHost,
|
|
53998
|
+
hasTokenAuth: !!this.authToken,
|
|
53999
|
+
hasPasswordAuth: this.hasPasswordAuth()
|
|
54000
|
+
}),
|
|
54001
|
+
boundHost: this.listenHost
|
|
54002
|
+
};
|
|
54003
|
+
}
|
|
54004
|
+
isTrustedStandaloneMutationRequest(req) {
|
|
54005
|
+
const originHeader = req.headers.origin;
|
|
54006
|
+
if (typeof originHeader !== "string" || !originHeader.trim()) return true;
|
|
54007
|
+
try {
|
|
54008
|
+
const origin = new URL(originHeader);
|
|
54009
|
+
const host = req.headers.host || "";
|
|
54010
|
+
return origin.host === host;
|
|
54011
|
+
} catch {
|
|
54012
|
+
return false;
|
|
54013
|
+
}
|
|
54014
|
+
}
|
|
54015
|
+
async readJsonBody(req) {
|
|
54016
|
+
return await new Promise((resolve4, reject) => {
|
|
54017
|
+
let body = "";
|
|
54018
|
+
req.on("data", (chunk) => {
|
|
54019
|
+
body += chunk;
|
|
54020
|
+
});
|
|
54021
|
+
req.on("end", () => {
|
|
54022
|
+
try {
|
|
54023
|
+
resolve4(body ? JSON.parse(body) : {});
|
|
54024
|
+
} catch (error48) {
|
|
54025
|
+
reject(error48);
|
|
54026
|
+
}
|
|
54027
|
+
});
|
|
54028
|
+
req.on("error", reject);
|
|
54029
|
+
});
|
|
54030
|
+
}
|
|
53761
54031
|
async start(options = {}) {
|
|
53762
|
-
const
|
|
53763
|
-
const host = options.host || "127.0.0.1";
|
|
54032
|
+
const persistedStandaloneBindHost = loadStandaloneBindHostPreference();
|
|
53764
54033
|
const cfg = (0, import_daemon_core2.loadConfig)();
|
|
54034
|
+
if (!options.host && persistedStandaloneBindHost !== STANDALONE_BIND_HOST_DEFAULT) {
|
|
54035
|
+
saveStandaloneBindHostPreference(persistedStandaloneBindHost);
|
|
54036
|
+
}
|
|
54037
|
+
const port = options.port || DEFAULT_PORT;
|
|
54038
|
+
const host = options.host || persistedStandaloneBindHost;
|
|
54039
|
+
this.listenHost = host;
|
|
53765
54040
|
const sessionHostEndpoint = await ensureSessionHostReady();
|
|
53766
54041
|
this.sessionHostEndpoint = sessionHostEndpoint;
|
|
53767
54042
|
const sessionHostControl = new StandaloneSessionHostControlPlane(
|
|
@@ -53769,6 +54044,7 @@ var StandaloneServer = class {
|
|
|
53769
54044
|
);
|
|
53770
54045
|
this.sessionHostControl = sessionHostControl;
|
|
53771
54046
|
this.authToken = options.token || process.env.ADHDEV_TOKEN || null;
|
|
54047
|
+
this.passwordConfig = loadStandalonePasswordConfig(this.passwordConfigPath);
|
|
53772
54048
|
const statusInstanceId = `standalone_${cfg.machineId || "mach_unknown"}`;
|
|
53773
54049
|
this.components = await (0, import_daemon_core2.initDaemonComponents)({
|
|
53774
54050
|
cliManagerDeps: {
|
|
@@ -53842,13 +54118,10 @@ var StandaloneServer = class {
|
|
|
53842
54118
|
this.httpServer.on("upgrade", (req, socket, head) => {
|
|
53843
54119
|
const wsUrl = new URL(req.url || "/", `http://${req.headers.host || "localhost"}`);
|
|
53844
54120
|
if (wsUrl.pathname === "/ws") {
|
|
53845
|
-
if (this.
|
|
53846
|
-
|
|
53847
|
-
|
|
53848
|
-
|
|
53849
|
-
socket.destroy();
|
|
53850
|
-
return;
|
|
53851
|
-
}
|
|
54121
|
+
if (!this.isRequestAuthenticated(req, req.url || "/")) {
|
|
54122
|
+
socket.write("HTTP/1.1 401 Unauthorized\r\n\r\n");
|
|
54123
|
+
socket.destroy();
|
|
54124
|
+
return;
|
|
53852
54125
|
}
|
|
53853
54126
|
this.wss.handleUpgrade(req, socket, head, (ws2) => {
|
|
53854
54127
|
this.handleWsConnection(ws2);
|
|
@@ -53881,7 +54154,14 @@ var StandaloneServer = class {
|
|
|
53881
54154
|
}
|
|
53882
54155
|
}
|
|
53883
54156
|
if (this.authToken) {
|
|
53884
|
-
console.log(
|
|
54157
|
+
console.log(" \u{1F511} Token auth: enabled");
|
|
54158
|
+
}
|
|
54159
|
+
if (this.passwordConfig) {
|
|
54160
|
+
console.log(" \u{1F510} Password auth: enabled");
|
|
54161
|
+
}
|
|
54162
|
+
if (shouldWarnForPublicUnauthenticatedHost({ host, hasTokenAuth: !!this.authToken, hasPasswordAuth: !!this.passwordConfig })) {
|
|
54163
|
+
console.warn(" \u26A0\uFE0F Public host mode is enabled without any auth.");
|
|
54164
|
+
console.warn(" Anyone on your LAN can open and control this dashboard until you set a password or token.");
|
|
53885
54165
|
}
|
|
53886
54166
|
console.log("");
|
|
53887
54167
|
const cdpCount = [...this.components.cdpManagers.values()].filter((m) => m.isConnected).length;
|
|
@@ -53921,18 +54201,148 @@ var StandaloneServer = class {
|
|
|
53921
54201
|
res.end();
|
|
53922
54202
|
return;
|
|
53923
54203
|
}
|
|
53924
|
-
|
|
53925
|
-
|
|
53926
|
-
|
|
53927
|
-
|
|
53928
|
-
|
|
53929
|
-
|
|
53930
|
-
|
|
53931
|
-
|
|
53932
|
-
|
|
54204
|
+
const parsedUrl = new URL(url2, `http://${req.headers.host || "localhost"}`);
|
|
54205
|
+
if (parsedUrl.pathname === "/auth/session" && method === "GET") {
|
|
54206
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
54207
|
+
res.end(JSON.stringify(this.buildAuthStatus(req, url2)));
|
|
54208
|
+
return;
|
|
54209
|
+
}
|
|
54210
|
+
if (parsedUrl.pathname === "/auth/login" && method === "POST") {
|
|
54211
|
+
void (async () => {
|
|
54212
|
+
if (!this.passwordConfig) {
|
|
54213
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
54214
|
+
res.end(JSON.stringify({ error: "Password auth is not configured." }));
|
|
54215
|
+
return;
|
|
54216
|
+
}
|
|
54217
|
+
const body = await this.readJsonBody(req);
|
|
54218
|
+
if (!verifyPassword(typeof body.password === "string" ? body.password : "", this.passwordConfig)) {
|
|
54219
|
+
res.writeHead(401, { "Content-Type": "application/json" });
|
|
54220
|
+
res.end(JSON.stringify({ error: "Incorrect password." }));
|
|
54221
|
+
return;
|
|
54222
|
+
}
|
|
54223
|
+
this.authSessions.clear();
|
|
54224
|
+
const sessionId = this.authSessions.create();
|
|
54225
|
+
res.setHeader("Set-Cookie", buildSessionCookie(sessionId, this.getCookieSecureFlag(req)));
|
|
54226
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
54227
|
+
res.end(JSON.stringify({ ...this.buildAuthStatus(req, url2), authenticated: true }));
|
|
54228
|
+
})().catch((error48) => {
|
|
54229
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
54230
|
+
res.end(JSON.stringify({ error: error48?.message || String(error48) }));
|
|
54231
|
+
});
|
|
54232
|
+
return;
|
|
54233
|
+
}
|
|
54234
|
+
if (parsedUrl.pathname === "/auth/logout" && method === "POST") {
|
|
54235
|
+
this.authSessions.revoke(this.getRequestSessionId(req));
|
|
54236
|
+
res.setHeader("Set-Cookie", buildClearedSessionCookie(this.getCookieSecureFlag(req)));
|
|
54237
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
54238
|
+
res.end(JSON.stringify({ success: true }));
|
|
54239
|
+
return;
|
|
54240
|
+
}
|
|
54241
|
+
if (parsedUrl.pathname === "/auth/password" && method === "POST") {
|
|
54242
|
+
void (async () => {
|
|
54243
|
+
if (!this.hasAnyAuth() && !this.isTrustedStandaloneMutationRequest(req)) {
|
|
54244
|
+
res.writeHead(403, { "Content-Type": "application/json" });
|
|
54245
|
+
res.end(JSON.stringify({ error: "Cross-origin standalone settings changes are not allowed without existing auth." }));
|
|
54246
|
+
return;
|
|
54247
|
+
}
|
|
54248
|
+
if (this.hasAnyAuth() && !this.isRequestAuthenticated(req, url2)) {
|
|
54249
|
+
res.writeHead(401, { "Content-Type": "application/json" });
|
|
54250
|
+
res.end(JSON.stringify({ error: "Unauthorized" }));
|
|
54251
|
+
return;
|
|
54252
|
+
}
|
|
54253
|
+
const body = await this.readJsonBody(req);
|
|
54254
|
+
const currentPassword = typeof body.currentPassword === "string" ? body.currentPassword : "";
|
|
54255
|
+
const newPassword = typeof body.newPassword === "string" ? body.newPassword : "";
|
|
54256
|
+
const clearPassword = body.clear === true;
|
|
54257
|
+
if (this.passwordConfig && !verifyPassword(currentPassword, this.passwordConfig)) {
|
|
54258
|
+
res.writeHead(403, { "Content-Type": "application/json" });
|
|
54259
|
+
res.end(JSON.stringify({ error: "Current password is incorrect." }));
|
|
54260
|
+
return;
|
|
54261
|
+
}
|
|
54262
|
+
if (clearPassword) {
|
|
54263
|
+
clearStandalonePasswordConfig(this.passwordConfigPath);
|
|
54264
|
+
this.passwordConfig = null;
|
|
54265
|
+
this.authSessions.clear();
|
|
54266
|
+
res.setHeader("Set-Cookie", buildClearedSessionCookie(this.getCookieSecureFlag(req)));
|
|
54267
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
54268
|
+
res.end(JSON.stringify({ success: true, ...this.buildAuthStatus(req, url2), authenticated: !this.hasAnyAuth() }));
|
|
54269
|
+
return;
|
|
54270
|
+
}
|
|
54271
|
+
if (newPassword.trim().length < 4) {
|
|
54272
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
54273
|
+
res.end(JSON.stringify({ error: "Password must be at least 4 characters." }));
|
|
54274
|
+
return;
|
|
54275
|
+
}
|
|
54276
|
+
const nextConfig = createPasswordRecord(newPassword.trim());
|
|
54277
|
+
saveStandalonePasswordConfig(this.passwordConfigPath, nextConfig);
|
|
54278
|
+
this.passwordConfig = nextConfig;
|
|
54279
|
+
this.authSessions.clear();
|
|
54280
|
+
const sessionId = this.authSessions.create();
|
|
54281
|
+
res.setHeader("Set-Cookie", buildSessionCookie(sessionId, this.getCookieSecureFlag(req)));
|
|
54282
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
54283
|
+
res.end(JSON.stringify({ success: true, ...this.buildAuthStatus(req, url2), authenticated: true }));
|
|
54284
|
+
})().catch((error48) => {
|
|
54285
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
54286
|
+
res.end(JSON.stringify({ error: error48?.message || String(error48) }));
|
|
54287
|
+
});
|
|
54288
|
+
return;
|
|
54289
|
+
}
|
|
54290
|
+
if (parsedUrl.pathname === "/api/v1/standalone/preferences" && method === "GET") {
|
|
54291
|
+
const configuredBindHost = loadStandaloneBindHostPreference();
|
|
54292
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
54293
|
+
res.end(JSON.stringify({
|
|
54294
|
+
standaloneBindHost: configuredBindHost,
|
|
54295
|
+
currentBindHost: this.listenHost,
|
|
54296
|
+
hasPasswordAuth: !!this.passwordConfig,
|
|
54297
|
+
hasTokenAuth: !!this.authToken,
|
|
54298
|
+
publicHostWarning: shouldWarnForPublicUnauthenticatedHost({
|
|
54299
|
+
host: configuredBindHost,
|
|
54300
|
+
hasTokenAuth: !!this.authToken,
|
|
54301
|
+
hasPasswordAuth: !!this.passwordConfig
|
|
54302
|
+
})
|
|
54303
|
+
}));
|
|
54304
|
+
return;
|
|
54305
|
+
}
|
|
54306
|
+
if (parsedUrl.pathname === "/api/v1/standalone/preferences" && method === "POST") {
|
|
54307
|
+
void (async () => {
|
|
54308
|
+
if (!this.hasAnyAuth() && !this.isTrustedStandaloneMutationRequest(req)) {
|
|
54309
|
+
res.writeHead(403, { "Content-Type": "application/json" });
|
|
54310
|
+
res.end(JSON.stringify({ error: "Cross-origin standalone settings changes are not allowed without existing auth." }));
|
|
54311
|
+
return;
|
|
54312
|
+
}
|
|
54313
|
+
if (this.hasAnyAuth() && !this.isRequestAuthenticated(req, url2)) {
|
|
54314
|
+
res.writeHead(401, { "Content-Type": "application/json" });
|
|
54315
|
+
res.end(JSON.stringify({ error: "Unauthorized" }));
|
|
54316
|
+
return;
|
|
54317
|
+
}
|
|
54318
|
+
const body = await this.readJsonBody(req);
|
|
54319
|
+
const nextHost = body?.standaloneBindHost === "0.0.0.0" ? "0.0.0.0" : "127.0.0.1";
|
|
54320
|
+
const savedHost = saveStandaloneBindHostPreference(nextHost);
|
|
54321
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
54322
|
+
res.end(JSON.stringify({
|
|
54323
|
+
success: true,
|
|
54324
|
+
standaloneBindHost: savedHost,
|
|
54325
|
+
currentBindHost: this.listenHost,
|
|
54326
|
+
hasPasswordAuth: !!this.passwordConfig,
|
|
54327
|
+
hasTokenAuth: !!this.authToken,
|
|
54328
|
+
publicHostWarning: shouldWarnForPublicUnauthenticatedHost({
|
|
54329
|
+
host: savedHost,
|
|
54330
|
+
hasTokenAuth: !!this.authToken,
|
|
54331
|
+
hasPasswordAuth: !!this.passwordConfig
|
|
54332
|
+
})
|
|
54333
|
+
}));
|
|
54334
|
+
})().catch((error48) => {
|
|
54335
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
54336
|
+
res.end(JSON.stringify({ error: error48?.message || String(error48) }));
|
|
54337
|
+
});
|
|
54338
|
+
return;
|
|
54339
|
+
}
|
|
54340
|
+
if (url2.startsWith("/api/") && !this.isRequestAuthenticated(req, url2)) {
|
|
54341
|
+
res.writeHead(401, { "Content-Type": "application/json" });
|
|
54342
|
+
res.end(JSON.stringify({ error: "Unauthorized. Provide dashboard session cookie or token auth." }));
|
|
54343
|
+
return;
|
|
53933
54344
|
}
|
|
53934
54345
|
const apiPath = url2.startsWith("/api/v1/") ? url2.slice(7) : null;
|
|
53935
|
-
const parsedUrl = new URL(url2, `http://${req.headers.host || "localhost"}`);
|
|
53936
54346
|
if (apiPath === "/status" && method === "GET") {
|
|
53937
54347
|
const status = this.getStatus(getSharedSnapshot());
|
|
53938
54348
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
@@ -54820,6 +55230,7 @@ async function main() {
|
|
|
54820
55230
|
process.exit(exitCode);
|
|
54821
55231
|
}
|
|
54822
55232
|
const options = {};
|
|
55233
|
+
let hostExplicit = false;
|
|
54823
55234
|
for (let i = 0; i < args.length; i++) {
|
|
54824
55235
|
if ((args[i] === "--port" || args[i] === "-p") && args[i + 1]) {
|
|
54825
55236
|
options.port = parseInt(args[i + 1]);
|
|
@@ -54827,6 +55238,7 @@ async function main() {
|
|
|
54827
55238
|
}
|
|
54828
55239
|
if (args[i] === "--host" || args[i] === "-H") {
|
|
54829
55240
|
options.host = "0.0.0.0";
|
|
55241
|
+
hostExplicit = true;
|
|
54830
55242
|
}
|
|
54831
55243
|
if (args[i] === "--public" && args[i + 1]) {
|
|
54832
55244
|
options.publicDir = args[i + 1];
|
|
@@ -54868,6 +55280,9 @@ Runtime commands:
|
|
|
54868
55280
|
process.exit(0);
|
|
54869
55281
|
}
|
|
54870
55282
|
}
|
|
55283
|
+
if (!hostExplicit) {
|
|
55284
|
+
options.host = loadStandaloneBindHostPreference();
|
|
55285
|
+
}
|
|
54871
55286
|
if (!options.publicDir) {
|
|
54872
55287
|
const candidates = [
|
|
54873
55288
|
path4.join(__dirname, "../../web-standalone/dist"),
|
|
@@ -54883,6 +55298,9 @@ Runtime commands:
|
|
|
54883
55298
|
}
|
|
54884
55299
|
const server = new StandaloneServer();
|
|
54885
55300
|
await server.start(options);
|
|
55301
|
+
if (!hostExplicit) {
|
|
55302
|
+
saveStandaloneBindHostPreference(options.host === "0.0.0.0" ? "0.0.0.0" : "127.0.0.1");
|
|
55303
|
+
}
|
|
54886
55304
|
await new Promise(() => {
|
|
54887
55305
|
});
|
|
54888
55306
|
}
|