@rubytech/create-maxy-code 0.1.279 → 0.1.280
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/package.json +1 -1
- package/payload/platform/plugins/admin/PLUGIN.md +1 -0
- package/payload/platform/plugins/admin/hooks/__tests__/prompt-optimiser-directive.test.sh +42 -0
- package/payload/platform/plugins/admin/hooks/prompt-optimiser-directive.sh +60 -15
- package/payload/platform/plugins/admin/mcp/dist/__tests__/e-sign-discoverable.test.d.ts +2 -0
- package/payload/platform/plugins/admin/mcp/dist/__tests__/e-sign-discoverable.test.d.ts.map +1 -0
- package/payload/platform/plugins/admin/mcp/dist/__tests__/e-sign-discoverable.test.js +54 -0
- package/payload/platform/plugins/admin/mcp/dist/__tests__/e-sign-discoverable.test.js.map +1 -0
- package/payload/platform/plugins/admin/mcp/dist/content-producer-authoring-skills.d.ts +2 -0
- package/payload/platform/plugins/admin/mcp/dist/content-producer-authoring-skills.d.ts.map +1 -0
- package/payload/platform/plugins/admin/mcp/dist/content-producer-authoring-skills.js +19 -0
- package/payload/platform/plugins/admin/mcp/dist/content-producer-authoring-skills.js.map +1 -0
- package/payload/platform/plugins/admin/mcp/dist/skill-resolution.d.ts.map +1 -1
- package/payload/platform/plugins/admin/mcp/dist/skill-resolution.js +2 -5
- package/payload/platform/plugins/admin/mcp/dist/skill-resolution.js.map +1 -1
- package/payload/platform/plugins/admin/skills/a4-print-documents/SKILL.md +2 -0
- package/payload/platform/plugins/admin/skills/access-manager/SKILL.md +2 -0
- package/payload/platform/plugins/admin/skills/admin-user-management/SKILL.md +2 -0
- package/payload/platform/plugins/admin/skills/business-profile/SKILL.md +2 -0
- package/payload/platform/plugins/admin/skills/capabilities-here/SKILL.md +2 -0
- package/payload/platform/plugins/admin/skills/datetime/SKILL.md +2 -0
- package/payload/platform/plugins/admin/skills/deck-pages/SKILL.md +2 -0
- package/payload/platform/plugins/admin/skills/file-presentation/SKILL.md +2 -0
- package/payload/platform/plugins/admin/skills/investigate/SKILL.md +2 -0
- package/payload/platform/plugins/admin/skills/plainly/SKILL.md +2 -0
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +2 -0
- package/payload/platform/plugins/admin/skills/plugin-management/SKILL.md +2 -0
- package/payload/platform/plugins/admin/skills/professional-document/SKILL.md +2 -0
- package/payload/platform/plugins/admin/skills/public-agent-manager/SKILL.md +2 -0
- package/payload/platform/plugins/admin/skills/qr-code/SKILL.md +2 -0
- package/payload/platform/plugins/admin/skills/session-management/SKILL.md +2 -0
- package/payload/platform/plugins/admin/skills/skill-builder/SKILL.md +2 -0
- package/payload/platform/plugins/admin/skills/specialist-management/SKILL.md +2 -0
- package/payload/platform/plugins/admin/skills/stream-log-review/SKILL.md +2 -0
- package/payload/platform/plugins/admin/skills/superpowers-sprint/SKILL.md +2 -0
- package/payload/platform/plugins/admin/skills/task/SKILL.md +2 -0
- package/payload/platform/plugins/admin/skills/update-knowledge/SKILL.md +2 -0
- package/payload/platform/plugins/admin/skills/upgrade/SKILL.md +2 -0
- package/payload/platform/plugins/aeo/skills/structured-answer/SKILL.md +2 -0
- package/payload/platform/plugins/business-assistant/PLUGIN.md +2 -1
- package/payload/platform/plugins/business-assistant/{references/e-sign.md → skills/e-sign/SKILL.md} +9 -2
- package/payload/platform/plugins/cloudflare/skills/cloudflare/SKILL.md +2 -0
- package/payload/platform/plugins/deep-research/skills/academic-verify/SKILL.md +2 -0
- package/payload/platform/plugins/deep-research/skills/book-mirror/SKILL.md +2 -0
- package/payload/platform/plugins/deep-research/skills/data-research/SKILL.md +2 -0
- package/payload/platform/plugins/deep-research/skills/deep-research/SKILL.md +2 -0
- package/payload/platform/plugins/deep-research/skills/strategic-reading/SKILL.md +2 -0
- package/payload/platform/plugins/email/PLUGIN.md +2 -0
- package/payload/platform/plugins/email/mcp/dist/lib/imap.d.ts +42 -11
- package/payload/platform/plugins/email/mcp/dist/lib/imap.d.ts.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/lib/imap.js +123 -57
- package/payload/platform/plugins/email/mcp/dist/lib/imap.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-otp-extract.d.ts.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-otp-extract.js +4 -2
- package/payload/platform/plugins/email/mcp/dist/tools/email-otp-extract.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-read.d.ts.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-read.js +18 -8
- package/payload/platform/plugins/email/mcp/dist/tools/email-read.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-search.d.ts.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-search.js +18 -8
- package/payload/platform/plugins/email/mcp/dist/tools/email-search.js.map +1 -1
- package/payload/platform/plugins/email/skills/email-composition/SKILL.md +2 -0
- package/payload/platform/plugins/email/skills/email-ingest/SKILL.md +2 -0
- package/payload/platform/plugins/graph-viewer/skills/render-graph/SKILL.md +2 -0
- package/payload/platform/plugins/linkedin-extension/skills/linkedin-extension/SKILL.md +2 -0
- package/payload/platform/plugins/memory/skills/archive-crawler/SKILL.md +2 -0
- package/payload/platform/plugins/memory/skills/challenge/SKILL.md +2 -0
- package/payload/platform/plugins/memory/skills/concept-synthesis/SKILL.md +2 -0
- package/payload/platform/plugins/memory/skills/connect/SKILL.md +2 -0
- package/payload/platform/plugins/memory/skills/conversational-memory/SKILL.md +2 -0
- package/payload/platform/plugins/memory/skills/emerge/SKILL.md +2 -0
- package/payload/platform/plugins/outlook/skills/outlook/SKILL.md +2 -0
- package/payload/platform/plugins/prompt-optimiser/skills/prompt-optimiser/SKILL.md +3 -1
- package/payload/platform/plugins/prompt-optimiser/skills/prompt-optimiser/__tests__/restatement-ladder.test.sh +21 -0
- package/payload/platform/plugins/scheduling/skills/briefing/SKILL.md +2 -0
- package/payload/platform/plugins/scheduling/skills/daily-prep/SKILL.md +2 -0
- package/payload/platform/plugins/slides/skills/deck-system/SKILL.md +2 -0
- package/payload/platform/plugins/whatsapp/skills/connect-whatsapp/SKILL.md +2 -0
- package/payload/platform/plugins/whatsapp/skills/manage-whatsapp-config/SKILL.md +2 -0
- package/payload/platform/plugins/work/skills/execute-task/SKILL.md +2 -0
- package/payload/platform/plugins/workflows/skills/workflow-manager/SKILL.md +2 -0
- package/payload/platform/scripts/lib/__tests__/admin-skills-bootstrap.test.sh +64 -0
- package/payload/platform/scripts/lib/admin-skills-bootstrap.sh +109 -0
- package/payload/platform/scripts/setup-account.sh +8 -0
- package/payload/platform/services/claude-session-manager/dist/fs-watcher.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/fs-watcher.js +43 -11
- package/payload/platform/services/claude-session-manager/dist/fs-watcher.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.js +74 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/index.js +48 -2
- package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/liveness-divergence.d.ts +19 -0
- package/payload/platform/services/claude-session-manager/dist/liveness-divergence.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/liveness-divergence.js +38 -0
- package/payload/platform/services/claude-session-manager/dist/liveness-divergence.js.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts +8 -0
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +12 -0
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/scope-record.d.ts +11 -0
- package/payload/platform/services/claude-session-manager/dist/scope-record.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/scope-record.js +81 -0
- package/payload/platform/services/claude-session-manager/dist/scope-record.js.map +1 -0
- package/payload/platform/services/whatsapp-channel/dist/notification.d.ts +10 -7
- package/payload/platform/services/whatsapp-channel/dist/notification.d.ts.map +1 -1
- package/payload/platform/services/whatsapp-channel/dist/notification.js +14 -14
- package/payload/platform/services/whatsapp-channel/dist/notification.js.map +1 -1
- package/payload/platform/templates/agents/admin/IDENTITY.md +2 -6
- package/payload/server/public/assets/AdminShell-C6_5h1cC.js +1 -0
- package/payload/server/public/assets/{admin-xRCXEFNW.js → admin-BpnsTEa3.js} +1 -1
- package/payload/server/public/assets/{browser-DT2XfRpL.js → browser-fgBRZ5gK.js} +1 -1
- package/payload/server/public/assets/{data-Dr7XUvAx.js → data-Cuynp6Y6.js} +1 -1
- package/payload/server/public/assets/{graph-DOEjjQHD.js → graph-Ddg24bjy.js} +1 -1
- package/payload/server/public/assets/{whatsapp-cDxgZkbM.js → whatsapp-BE79pNh8.js} +1 -1
- package/payload/server/public/browser.html +2 -2
- package/payload/server/public/data.html +2 -2
- package/payload/server/public/graph.html +2 -2
- package/payload/server/public/index.html +2 -2
- package/payload/server/public/whatsapp.html +2 -2
- package/payload/server/server.js +338 -461
- package/payload/server/public/assets/AdminShell-DnH3kou-.js +0 -1
package/payload/server/server.js
CHANGED
|
@@ -1201,8 +1201,8 @@ var serveStatic = (options = { root: "" }) => {
|
|
|
1201
1201
|
};
|
|
1202
1202
|
|
|
1203
1203
|
// server/index.ts
|
|
1204
|
-
import { readFileSync as
|
|
1205
|
-
import { resolve as
|
|
1204
|
+
import { readFileSync as readFileSync23, existsSync as existsSync23, watchFile } from "fs";
|
|
1205
|
+
import { resolve as resolve26, join as join18, basename as basename7 } from "path";
|
|
1206
1206
|
import { homedir as homedir2 } from "os";
|
|
1207
1207
|
import { monitorEventLoopDelay } from "perf_hooks";
|
|
1208
1208
|
|
|
@@ -1763,7 +1763,7 @@ var credsSaveQueue = Promise.resolve();
|
|
|
1763
1763
|
async function drainCredsSaveQueue(timeoutMs = 5e3) {
|
|
1764
1764
|
console.error(`${TAG2} draining credential save queue\u2026`);
|
|
1765
1765
|
const timer2 = new Promise(
|
|
1766
|
-
(
|
|
1766
|
+
(resolve27) => setTimeout(() => resolve27("timeout"), timeoutMs)
|
|
1767
1767
|
);
|
|
1768
1768
|
const result = await Promise.race([
|
|
1769
1769
|
credsSaveQueue.then(() => "drained"),
|
|
@@ -1891,11 +1891,11 @@ async function createWaSocket(opts) {
|
|
|
1891
1891
|
return sock;
|
|
1892
1892
|
}
|
|
1893
1893
|
async function waitForConnection(sock) {
|
|
1894
|
-
return new Promise((
|
|
1894
|
+
return new Promise((resolve27, reject) => {
|
|
1895
1895
|
const handler = (update) => {
|
|
1896
1896
|
if (update.connection === "open") {
|
|
1897
1897
|
sock.ev.off("connection.update", handler);
|
|
1898
|
-
|
|
1898
|
+
resolve27();
|
|
1899
1899
|
}
|
|
1900
1900
|
if (update.connection === "close") {
|
|
1901
1901
|
sock.ev.off("connection.update", handler);
|
|
@@ -2009,14 +2009,14 @@ ${inspected}`;
|
|
|
2009
2009
|
return inspect2(err, INSPECT_OPTS2);
|
|
2010
2010
|
}
|
|
2011
2011
|
function withTimeout(label, promise, timeoutMs) {
|
|
2012
|
-
return new Promise((
|
|
2012
|
+
return new Promise((resolve27, reject) => {
|
|
2013
2013
|
const timer2 = setTimeout(() => {
|
|
2014
2014
|
reject(new Error(`${label} timed out after ${timeoutMs}ms`));
|
|
2015
2015
|
}, timeoutMs);
|
|
2016
2016
|
promise.then(
|
|
2017
2017
|
(value) => {
|
|
2018
2018
|
clearTimeout(timer2);
|
|
2019
|
-
|
|
2019
|
+
resolve27(value);
|
|
2020
2020
|
},
|
|
2021
2021
|
(err) => {
|
|
2022
2022
|
clearTimeout(timer2);
|
|
@@ -2601,8 +2601,8 @@ async function persistWhatsAppMessage(input) {
|
|
|
2601
2601
|
const { givenName, familyName } = splitName(input.pushName);
|
|
2602
2602
|
const prev = sessionWriteLocks.get(input.cacheKey);
|
|
2603
2603
|
let release;
|
|
2604
|
-
const mine = new Promise((
|
|
2605
|
-
release =
|
|
2604
|
+
const mine = new Promise((resolve27) => {
|
|
2605
|
+
release = resolve27;
|
|
2606
2606
|
});
|
|
2607
2607
|
const chained = (prev ?? Promise.resolve()).then(() => mine);
|
|
2608
2608
|
sessionWriteLocks.set(input.cacheKey, chained);
|
|
@@ -3069,6 +3069,14 @@ function createInboundDebouncer(opts) {
|
|
|
3069
3069
|
return { enqueue, flush, destroy, registerPending };
|
|
3070
3070
|
}
|
|
3071
3071
|
|
|
3072
|
+
// app/lib/whatsapp/inbound/combine-batch.ts
|
|
3073
|
+
function combineInboundBatch(entries) {
|
|
3074
|
+
const last = entries[entries.length - 1];
|
|
3075
|
+
const combinedText = entries.map((e) => e.text).filter(Boolean).join("\n");
|
|
3076
|
+
const media = entries.flatMap((e) => e.media);
|
|
3077
|
+
return { ...last, text: combinedText, media };
|
|
3078
|
+
}
|
|
3079
|
+
|
|
3072
3080
|
// app/lib/whatsapp/opening-hours.ts
|
|
3073
3081
|
var TAG10 = "[whatsapp:hours]";
|
|
3074
3082
|
async function isBusinessOpen(accountId) {
|
|
@@ -3638,11 +3646,11 @@ async function connectWithReconnect(conn) {
|
|
|
3638
3646
|
console.error(
|
|
3639
3647
|
`${TAG12} reconnecting account=${conn.accountId} in ${delay}ms (attempt ${decision.nextAttempts}/${maxAttempts})`
|
|
3640
3648
|
);
|
|
3641
|
-
await new Promise((
|
|
3642
|
-
const timer2 = setTimeout(
|
|
3649
|
+
await new Promise((resolve27) => {
|
|
3650
|
+
const timer2 = setTimeout(resolve27, delay);
|
|
3643
3651
|
conn.abortController.signal.addEventListener("abort", () => {
|
|
3644
3652
|
clearTimeout(timer2);
|
|
3645
|
-
|
|
3653
|
+
resolve27();
|
|
3646
3654
|
}, { once: true });
|
|
3647
3655
|
});
|
|
3648
3656
|
}
|
|
@@ -3650,16 +3658,16 @@ async function connectWithReconnect(conn) {
|
|
|
3650
3658
|
}
|
|
3651
3659
|
}
|
|
3652
3660
|
function waitForDisconnectEvent(conn) {
|
|
3653
|
-
return new Promise((
|
|
3661
|
+
return new Promise((resolve27) => {
|
|
3654
3662
|
if (!conn.sock) {
|
|
3655
|
-
|
|
3663
|
+
resolve27();
|
|
3656
3664
|
return;
|
|
3657
3665
|
}
|
|
3658
3666
|
const sock = conn.sock;
|
|
3659
3667
|
const handler = (update) => {
|
|
3660
3668
|
if (update.connection === "close") {
|
|
3661
3669
|
sock.ev.off("connection.update", handler);
|
|
3662
|
-
|
|
3670
|
+
resolve27();
|
|
3663
3671
|
}
|
|
3664
3672
|
};
|
|
3665
3673
|
sock.ev.on("connection.update", handler);
|
|
@@ -3723,21 +3731,10 @@ function monitorInbound(conn) {
|
|
|
3723
3731
|
},
|
|
3724
3732
|
onFlush: (entries) => {
|
|
3725
3733
|
if (!onInboundMessage) return;
|
|
3726
|
-
if (entries.length
|
|
3727
|
-
|
|
3728
|
-
return;
|
|
3734
|
+
if (entries.length > 1) {
|
|
3735
|
+
console.error(`${TAG12} debounce: combining ${entries.length} messages account=${conn.accountId} from=${entries[0].senderPhone}`);
|
|
3729
3736
|
}
|
|
3730
|
-
|
|
3731
|
-
const last = entries[entries.length - 1];
|
|
3732
|
-
const mediaEntry = entries.find((e) => e.mediaPath);
|
|
3733
|
-
const combinedText = entries.map((e) => e.text).filter(Boolean).join("\n");
|
|
3734
|
-
onInboundMessage({
|
|
3735
|
-
...last,
|
|
3736
|
-
text: combinedText,
|
|
3737
|
-
mediaPath: mediaEntry?.mediaPath ?? last.mediaPath,
|
|
3738
|
-
mediaMimetype: mediaEntry?.mediaMimetype ?? last.mediaMimetype,
|
|
3739
|
-
mediaType: mediaEntry?.mediaType ?? last.mediaType
|
|
3740
|
-
});
|
|
3737
|
+
onInboundMessage(combineInboundBatch(entries));
|
|
3741
3738
|
},
|
|
3742
3739
|
onError: (err) => {
|
|
3743
3740
|
console.error(`${TAG12} debounce flush error account=${conn.accountId}: ${String(err)}`);
|
|
@@ -3899,6 +3896,7 @@ async function handleInboundMessage(conn, msg) {
|
|
|
3899
3896
|
groupJid: isGroup2 ? remoteJid : void 0,
|
|
3900
3897
|
isOwnerMirror: true
|
|
3901
3898
|
}),
|
|
3899
|
+
media: [],
|
|
3902
3900
|
isOwnerMirror: true
|
|
3903
3901
|
});
|
|
3904
3902
|
return;
|
|
@@ -3928,8 +3926,8 @@ async function handleInboundMessage(conn, msg) {
|
|
|
3928
3926
|
const conversationKey = isGroup ? remoteJid : senderPhone;
|
|
3929
3927
|
const debounceKey = `${conn.accountId}:${conversationKey}:${senderPhone}`;
|
|
3930
3928
|
let resolvePending;
|
|
3931
|
-
const sttPending = new Promise((
|
|
3932
|
-
resolvePending =
|
|
3929
|
+
const sttPending = new Promise((resolve27) => {
|
|
3930
|
+
resolvePending = resolve27;
|
|
3933
3931
|
});
|
|
3934
3932
|
if (conn.debouncer) conn.debouncer.registerPending(debounceKey, sttPending);
|
|
3935
3933
|
try {
|
|
@@ -4010,9 +4008,7 @@ async function handleInboundMessage(conn, msg) {
|
|
|
4010
4008
|
reply,
|
|
4011
4009
|
composing,
|
|
4012
4010
|
cacheKey,
|
|
4013
|
-
|
|
4014
|
-
mediaMimetype: mediaResult?.mimetype,
|
|
4015
|
-
mediaType: extracted.mediaType,
|
|
4011
|
+
media: mediaResult?.path ? [{ path: mediaResult.path, type: extracted.mediaType, mimetype: mediaResult.mimetype }] : [],
|
|
4016
4012
|
replyContext: extracted.quotedMessage
|
|
4017
4013
|
};
|
|
4018
4014
|
if (accessResult.agentType === "public") {
|
|
@@ -4338,20 +4334,20 @@ function buildX11Env(chromiumWrapperPath, transport = "vnc") {
|
|
|
4338
4334
|
|
|
4339
4335
|
// server/routes/health.ts
|
|
4340
4336
|
function checkPort(port2, timeoutMs = 500) {
|
|
4341
|
-
return new Promise((
|
|
4337
|
+
return new Promise((resolve27) => {
|
|
4342
4338
|
const socket = createConnection2(port2, "127.0.0.1");
|
|
4343
4339
|
socket.setTimeout(timeoutMs);
|
|
4344
4340
|
socket.once("connect", () => {
|
|
4345
4341
|
socket.destroy();
|
|
4346
|
-
|
|
4342
|
+
resolve27(true);
|
|
4347
4343
|
});
|
|
4348
4344
|
socket.once("error", () => {
|
|
4349
4345
|
socket.destroy();
|
|
4350
|
-
|
|
4346
|
+
resolve27(false);
|
|
4351
4347
|
});
|
|
4352
4348
|
socket.once("timeout", () => {
|
|
4353
4349
|
socket.destroy();
|
|
4354
|
-
|
|
4350
|
+
resolve27(false);
|
|
4355
4351
|
});
|
|
4356
4352
|
});
|
|
4357
4353
|
}
|
|
@@ -5426,12 +5422,12 @@ async function dispatchOnce(input) {
|
|
|
5426
5422
|
});
|
|
5427
5423
|
if (!entry) return { error: "spawn-failed" };
|
|
5428
5424
|
entry.lastInboundAt = Date.now();
|
|
5429
|
-
let
|
|
5425
|
+
let resolve27;
|
|
5430
5426
|
const turnPromise = new Promise((r) => {
|
|
5431
|
-
|
|
5427
|
+
resolve27 = r;
|
|
5432
5428
|
});
|
|
5433
5429
|
const listener = (text) => {
|
|
5434
|
-
|
|
5430
|
+
resolve27(text);
|
|
5435
5431
|
};
|
|
5436
5432
|
entry.subscribers.add(listener);
|
|
5437
5433
|
const writeAtMs = Date.now();
|
|
@@ -6269,8 +6265,8 @@ async function startLogin(opts) {
|
|
|
6269
6265
|
await clearAuth(authDir);
|
|
6270
6266
|
let resolveCode = null;
|
|
6271
6267
|
let rejectCode = null;
|
|
6272
|
-
const codePromise = new Promise((
|
|
6273
|
-
resolveCode =
|
|
6268
|
+
const codePromise = new Promise((resolve27, reject) => {
|
|
6269
|
+
resolveCode = resolve27;
|
|
6274
6270
|
rejectCode = reject;
|
|
6275
6271
|
});
|
|
6276
6272
|
const codeTimer = setTimeout(
|
|
@@ -6994,7 +6990,6 @@ import { basename as basename2, dirname, join as join8, resolve as resolve9, sep
|
|
|
6994
6990
|
import { readdirSync as readdirSync4, readFileSync as readFileSync8, statSync as statSync2 } from "fs";
|
|
6995
6991
|
import { join as join7, resolve as resolve8 } from "path";
|
|
6996
6992
|
var SESSION_ID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\.jsonl$/i;
|
|
6997
|
-
var PID_FILE_RE = /^([0-9]+)\.json$/;
|
|
6998
6993
|
var CLI_MARKER_PREFIXES = ["<local-command-", "<command-name>", "<command-message>"];
|
|
6999
6994
|
var PUBLIC_ROLE = "public";
|
|
7000
6995
|
var WEBCHAT_CHANNEL = "webchat";
|
|
@@ -7044,36 +7039,25 @@ function enumerateJsonls(projectsRoot) {
|
|
|
7044
7039
|
}
|
|
7045
7040
|
return out;
|
|
7046
7041
|
}
|
|
7047
|
-
function
|
|
7042
|
+
async function fetchLiveSessions() {
|
|
7048
7043
|
const out = /* @__PURE__ */ new Map();
|
|
7049
|
-
|
|
7050
|
-
let entries;
|
|
7044
|
+
let port2;
|
|
7051
7045
|
try {
|
|
7052
|
-
|
|
7046
|
+
port2 = requirePortEnv("CLAUDE_SESSION_MANAGER_PORT", { tag: "sidebar-sessions:live" });
|
|
7053
7047
|
} catch {
|
|
7048
|
+
console.error("[admin-sessions-list] CLAUDE_SESSION_MANAGER_PORT unset; liveness unknown");
|
|
7054
7049
|
return out;
|
|
7055
7050
|
}
|
|
7056
|
-
|
|
7057
|
-
|
|
7058
|
-
|
|
7059
|
-
|
|
7060
|
-
|
|
7061
|
-
if (!Number.isFinite(pid) || pid <= 0) continue;
|
|
7062
|
-
let body;
|
|
7063
|
-
try {
|
|
7064
|
-
body = readFileSync8(join7(sessionsDir, entry.name), "utf8");
|
|
7065
|
-
} catch {
|
|
7066
|
-
continue;
|
|
7067
|
-
}
|
|
7068
|
-
let parsed;
|
|
7069
|
-
try {
|
|
7070
|
-
parsed = JSON.parse(body);
|
|
7071
|
-
} catch {
|
|
7072
|
-
continue;
|
|
7051
|
+
try {
|
|
7052
|
+
const res = await fetch(`http://127.0.0.1:${port2}/live-sessions`);
|
|
7053
|
+
if (!res.ok) {
|
|
7054
|
+
console.error(`[admin-sessions-list] live-sessions status=${res.status}; liveness unknown`);
|
|
7055
|
+
return out;
|
|
7073
7056
|
}
|
|
7074
|
-
|
|
7075
|
-
const
|
|
7076
|
-
|
|
7057
|
+
const body = await res.json();
|
|
7058
|
+
for (const s of body.sessions) out.set(s.sessionId, s.pid);
|
|
7059
|
+
} catch (err) {
|
|
7060
|
+
console.error(`[admin-sessions-list] live-sessions fetch failed: ${err instanceof Error ? err.message : String(err)}; liveness unknown`);
|
|
7077
7061
|
}
|
|
7078
7062
|
return out;
|
|
7079
7063
|
}
|
|
@@ -7179,7 +7163,7 @@ app4.get("/", requireAdminSession, async (c) => {
|
|
|
7179
7163
|
}
|
|
7180
7164
|
const projectsRoot = join7(configDir2, "projects");
|
|
7181
7165
|
const jsonls = enumerateJsonls(projectsRoot);
|
|
7182
|
-
const
|
|
7166
|
+
const liveSessions = await fetchLiveSessions();
|
|
7183
7167
|
const accountDir = accountId ? resolve8(ACCOUNTS_DIR, accountId) : null;
|
|
7184
7168
|
const userTitles = loadUserTitles(accountDir);
|
|
7185
7169
|
const rows = [];
|
|
@@ -7206,8 +7190,8 @@ app4.get("/", requireAdminSession, async (c) => {
|
|
|
7206
7190
|
} catch {
|
|
7207
7191
|
continue;
|
|
7208
7192
|
}
|
|
7209
|
-
const
|
|
7210
|
-
const
|
|
7193
|
+
const live = liveSessions.has(sessionId);
|
|
7194
|
+
const pid = live ? liveSessions.get(sessionId) ?? null : null;
|
|
7211
7195
|
const resolved = resolveTitle(body, sessionId, userTitles);
|
|
7212
7196
|
titleSourceCounts[resolved.source] += 1;
|
|
7213
7197
|
const metaPath = join7(projectDir, `${sessionId}.meta.json`);
|
|
@@ -8892,11 +8876,11 @@ app13.delete("/:id", requireAdminSession, async (c) => {
|
|
|
8892
8876
|
const owned = await verifyConversationOwnership(sessionId, accountId);
|
|
8893
8877
|
if (!owned) return c.json({ error: "Conversation not found" }, 404);
|
|
8894
8878
|
const managerPort = requirePortEnv("CLAUDE_SESSION_MANAGER_PORT", { tag: "admin-conversation-delete" });
|
|
8895
|
-
const
|
|
8879
|
+
const managerBase7 = `http://127.0.0.1:${managerPort}`;
|
|
8896
8880
|
const outcome = await cascadeAdminConversationDelete({
|
|
8897
8881
|
sessionId,
|
|
8898
8882
|
accountId,
|
|
8899
|
-
managerBase:
|
|
8883
|
+
managerBase: managerBase7
|
|
8900
8884
|
});
|
|
8901
8885
|
if (outcome.ok) return c.json({ ok: true, claudeSessionIds: outcome.claudeSessionIds });
|
|
8902
8886
|
if (outcome.reason === "pty-still-alive") {
|
|
@@ -12564,7 +12548,7 @@ app20.post("/", requireAdminSession, async (c) => {
|
|
|
12564
12548
|
return c.json({ error: "AdminConversation node is missing sessionId" }, 500);
|
|
12565
12549
|
}
|
|
12566
12550
|
const managerPort = requirePortEnv("CLAUDE_SESSION_MANAGER_PORT", { tag: "graph-page-cascade" });
|
|
12567
|
-
const
|
|
12551
|
+
const managerBase7 = `http://127.0.0.1:${managerPort}`;
|
|
12568
12552
|
try {
|
|
12569
12553
|
await session.close();
|
|
12570
12554
|
} catch {
|
|
@@ -12572,7 +12556,7 @@ app20.post("/", requireAdminSession, async (c) => {
|
|
|
12572
12556
|
const outcome = await cascadeAdminConversationDelete({
|
|
12573
12557
|
sessionId,
|
|
12574
12558
|
accountId,
|
|
12575
|
-
managerBase:
|
|
12559
|
+
managerBase: managerBase7
|
|
12576
12560
|
});
|
|
12577
12561
|
const elapsed2 = Date.now() - started;
|
|
12578
12562
|
const labelSummary2 = preflightLabels.join(",");
|
|
@@ -13126,106 +13110,60 @@ function isWithin(target, root) {
|
|
|
13126
13110
|
var sidebar_artefacts_default = app24;
|
|
13127
13111
|
|
|
13128
13112
|
// server/routes/admin/session-delete.ts
|
|
13129
|
-
import { existsSync as existsSync18, readdirSync as readdirSync10, readFileSync as readFileSync17, unlinkSync as unlinkSync2 } from "fs";
|
|
13130
|
-
import { join as join16, resolve as resolve19 } from "path";
|
|
13131
13113
|
var app25 = new Hono();
|
|
13132
13114
|
var SESSION_ID_RE3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
13133
|
-
|
|
13134
|
-
|
|
13135
|
-
|
|
13136
|
-
|
|
13137
|
-
|
|
13138
|
-
|
|
13139
|
-
let entries;
|
|
13115
|
+
function managerBase4() {
|
|
13116
|
+
const port2 = requirePortEnv("CLAUDE_SESSION_MANAGER_PORT", { tag: "session-delete:wrapper" });
|
|
13117
|
+
return `http://127.0.0.1:${port2}`;
|
|
13118
|
+
}
|
|
13119
|
+
app25.post("/", requireAdminSession, async (c) => {
|
|
13120
|
+
let body;
|
|
13140
13121
|
try {
|
|
13141
|
-
|
|
13122
|
+
body = await c.req.json();
|
|
13142
13123
|
} catch {
|
|
13143
|
-
return
|
|
13124
|
+
return c.json({ error: "invalid JSON body" }, 400);
|
|
13144
13125
|
}
|
|
13145
|
-
|
|
13146
|
-
|
|
13147
|
-
|
|
13148
|
-
if (!m) continue;
|
|
13149
|
-
const pid = Number(m[1]);
|
|
13150
|
-
if (!Number.isFinite(pid) || pid <= 0) continue;
|
|
13151
|
-
let body;
|
|
13152
|
-
try {
|
|
13153
|
-
body = readFileSync17(join16(sessionsDir, entry.name), "utf8");
|
|
13154
|
-
} catch {
|
|
13155
|
-
continue;
|
|
13156
|
-
}
|
|
13157
|
-
let parsed;
|
|
13158
|
-
try {
|
|
13159
|
-
parsed = JSON.parse(body);
|
|
13160
|
-
} catch {
|
|
13161
|
-
continue;
|
|
13162
|
-
}
|
|
13163
|
-
if (!parsed || typeof parsed !== "object") continue;
|
|
13164
|
-
if (parsed.sessionId === sessionId) return pid;
|
|
13126
|
+
const sessionId = typeof body.sessionId === "string" ? body.sessionId : "";
|
|
13127
|
+
if (!SESSION_ID_RE3.test(sessionId)) {
|
|
13128
|
+
return c.json({ error: "sessionId must be a v4 UUID" }, 400);
|
|
13165
13129
|
}
|
|
13166
|
-
|
|
13167
|
-
}
|
|
13168
|
-
function isPidAlive(pid) {
|
|
13130
|
+
const base = managerBase4();
|
|
13169
13131
|
try {
|
|
13170
|
-
|
|
13171
|
-
|
|
13132
|
+
const stop = await fetch(`${base}/${sessionId}/stop`, { method: "POST" });
|
|
13133
|
+
if (stop.status !== 204 && stop.status !== 200 && stop.status !== 404) {
|
|
13134
|
+
console.error(`[session-delete] sessionId=${sessionId} stop-status=${stop.status}`);
|
|
13135
|
+
return c.json({ error: `stop-failed-${stop.status}` }, 502);
|
|
13136
|
+
}
|
|
13172
13137
|
} catch (err) {
|
|
13173
|
-
|
|
13174
|
-
|
|
13175
|
-
return true;
|
|
13138
|
+
console.error(`[session-delete] sessionId=${sessionId} stop-unreachable err=${err instanceof Error ? err.message : String(err)}`);
|
|
13139
|
+
return c.json({ error: "manager-unreachable" }, 502);
|
|
13176
13140
|
}
|
|
13177
|
-
|
|
13178
|
-
function sleep2(ms) {
|
|
13179
|
-
return new Promise((resolve28) => setTimeout(resolve28, ms));
|
|
13180
|
-
}
|
|
13181
|
-
function sendSignal(pid, signal) {
|
|
13141
|
+
let del;
|
|
13182
13142
|
try {
|
|
13183
|
-
|
|
13184
|
-
return true;
|
|
13143
|
+
del = await fetch(`${base}/${sessionId}`, { method: "DELETE" });
|
|
13185
13144
|
} catch (err) {
|
|
13186
|
-
|
|
13187
|
-
|
|
13188
|
-
return false;
|
|
13145
|
+
console.error(`[session-delete] sessionId=${sessionId} delete-unreachable err=${err instanceof Error ? err.message : String(err)}`);
|
|
13146
|
+
return c.json({ error: "manager-unreachable" }, 502);
|
|
13189
13147
|
}
|
|
13190
|
-
|
|
13191
|
-
|
|
13192
|
-
|
|
13193
|
-
let escalated = false;
|
|
13194
|
-
const termSent = sendSignal(pid, "SIGTERM");
|
|
13195
|
-
const termDeadline = Date.now() + SIGTERM_WAIT_MS;
|
|
13196
|
-
while (Date.now() < termDeadline) {
|
|
13197
|
-
if (!isPidAlive(pid)) {
|
|
13198
|
-
return {
|
|
13199
|
-
pidKilled: termSent ? "true" : "false",
|
|
13200
|
-
waitForExitMs: Date.now() - startedAt,
|
|
13201
|
-
escalatedToSIGKILL: false,
|
|
13202
|
-
exited: true
|
|
13203
|
-
};
|
|
13204
|
-
}
|
|
13205
|
-
await sleep2(POLL_INTERVAL_MS);
|
|
13206
|
-
}
|
|
13207
|
-
escalated = true;
|
|
13208
|
-
sendSignal(pid, "SIGKILL");
|
|
13209
|
-
const killDeadline = Date.now() + SIGKILL_WAIT_MS;
|
|
13210
|
-
while (Date.now() < killDeadline) {
|
|
13211
|
-
if (!isPidAlive(pid)) {
|
|
13212
|
-
return {
|
|
13213
|
-
pidKilled: "true",
|
|
13214
|
-
waitForExitMs: Date.now() - startedAt,
|
|
13215
|
-
escalatedToSIGKILL: true,
|
|
13216
|
-
exited: true
|
|
13217
|
-
};
|
|
13218
|
-
}
|
|
13219
|
-
await sleep2(POLL_INTERVAL_MS);
|
|
13148
|
+
if (del.status === 204) {
|
|
13149
|
+
console.log(`[session-delete] sessionId=${sessionId} deleted`);
|
|
13150
|
+
return c.json({ deleted: true });
|
|
13220
13151
|
}
|
|
13221
|
-
return {
|
|
13222
|
-
|
|
13223
|
-
|
|
13224
|
-
|
|
13225
|
-
|
|
13226
|
-
|
|
13152
|
+
if (del.status === 404) return c.json({ deleted: false, error: "no-transcript" }, 404);
|
|
13153
|
+
if (del.status === 409) return c.json({ deleted: false, error: "pty-still-alive" }, 409);
|
|
13154
|
+
console.error(`[session-delete] sessionId=${sessionId} delete-status=${del.status}`);
|
|
13155
|
+
return c.json({ error: `manager-status-${del.status}` }, 502);
|
|
13156
|
+
});
|
|
13157
|
+
var session_delete_default = app25;
|
|
13158
|
+
|
|
13159
|
+
// server/routes/admin/session-stop.ts
|
|
13160
|
+
var app26 = new Hono();
|
|
13161
|
+
var SESSION_ID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
13162
|
+
function managerBase5() {
|
|
13163
|
+
const port2 = requirePortEnv("CLAUDE_SESSION_MANAGER_PORT", { tag: "session-stop:wrapper" });
|
|
13164
|
+
return `http://127.0.0.1:${port2}`;
|
|
13227
13165
|
}
|
|
13228
|
-
|
|
13166
|
+
app26.post("/", requireAdminSession, async (c) => {
|
|
13229
13167
|
let body;
|
|
13230
13168
|
try {
|
|
13231
13169
|
body = await c.req.json();
|
|
@@ -13233,91 +13171,33 @@ app25.post("/", requireAdminSession, async (c) => {
|
|
|
13233
13171
|
return c.json({ error: "invalid JSON body" }, 400);
|
|
13234
13172
|
}
|
|
13235
13173
|
const sessionId = typeof body.sessionId === "string" ? body.sessionId : "";
|
|
13236
|
-
|
|
13237
|
-
if (!SESSION_ID_RE3.test(sessionId)) {
|
|
13174
|
+
if (!SESSION_ID_RE4.test(sessionId)) {
|
|
13238
13175
|
return c.json({ error: "sessionId must be a v4 UUID" }, 400);
|
|
13239
13176
|
}
|
|
13240
|
-
|
|
13241
|
-
return c.json({ error: "projectDir is required" }, 400);
|
|
13242
|
-
}
|
|
13243
|
-
const configDir2 = process.env.CLAUDE_CONFIG_DIR;
|
|
13244
|
-
if (!configDir2) {
|
|
13245
|
-
return c.json({ error: "CLAUDE_CONFIG_DIR not set" }, 500);
|
|
13246
|
-
}
|
|
13247
|
-
const projectsRoot = resolve19(join16(configDir2, "projects")) + "/";
|
|
13248
|
-
const resolvedProject = resolve19(projectDir) + "/";
|
|
13249
|
-
if (!resolvedProject.startsWith(projectsRoot)) {
|
|
13250
|
-
console.error(`[sessions-delete] reject reason=projectDir-outside-tree projectDir=${projectDir}`);
|
|
13251
|
-
return c.json({ error: "projectDir is not under CLAUDE_CONFIG_DIR/projects/" }, 400);
|
|
13252
|
-
}
|
|
13253
|
-
const jsonlPath = join16(projectDir, `${sessionId}.jsonl`);
|
|
13254
|
-
const sidecarPath = join16(projectDir, `${sessionId}.meta.json`);
|
|
13255
|
-
const pid = findPidForSession(configDir2, sessionId);
|
|
13256
|
-
let pidKilled = "absent";
|
|
13257
|
-
let waitForExitMs = 0;
|
|
13258
|
-
let escalatedToSIGKILL = false;
|
|
13259
|
-
if (pid !== null) {
|
|
13260
|
-
const r = await killAndWait(pid);
|
|
13261
|
-
pidKilled = r.pidKilled;
|
|
13262
|
-
waitForExitMs = r.waitForExitMs;
|
|
13263
|
-
escalatedToSIGKILL = r.escalatedToSIGKILL;
|
|
13264
|
-
if (!r.exited) {
|
|
13265
|
-
console.error(
|
|
13266
|
-
`[sessions-delete] kill-failed sessionId=${sessionId} pid=${pid} waitForExit=${waitForExitMs} escalatedToSIGKILL=${escalatedToSIGKILL}`
|
|
13267
|
-
);
|
|
13268
|
-
return c.json(
|
|
13269
|
-
{ error: "kill-failed", pid, waitForExitMs, escalatedToSIGKILL },
|
|
13270
|
-
500
|
|
13271
|
-
);
|
|
13272
|
-
}
|
|
13273
|
-
}
|
|
13274
|
-
let deleted = false;
|
|
13177
|
+
let res;
|
|
13275
13178
|
try {
|
|
13276
|
-
|
|
13277
|
-
unlinkSync2(jsonlPath);
|
|
13278
|
-
deleted = true;
|
|
13279
|
-
}
|
|
13179
|
+
res = await fetch(`${managerBase5()}/${sessionId}/stop`, { method: "POST" });
|
|
13280
13180
|
} catch (err) {
|
|
13281
|
-
|
|
13282
|
-
|
|
13283
|
-
console.log(
|
|
13284
|
-
`[sessions-delete] sessionId=${sessionId} pidKilled=${pidKilled} jsonlPath=${jsonlPath} deleted=false waitForExit=${waitForExitMs} escalatedToSIGKILL=${escalatedToSIGKILL}`
|
|
13285
|
-
);
|
|
13286
|
-
return c.json({ error: `unlink failed: ${msg}` }, 500);
|
|
13287
|
-
}
|
|
13288
|
-
try {
|
|
13289
|
-
if (existsSync18(sidecarPath)) unlinkSync2(sidecarPath);
|
|
13290
|
-
} catch {
|
|
13291
|
-
}
|
|
13292
|
-
if (pid !== null) {
|
|
13293
|
-
try {
|
|
13294
|
-
const pidFile = join16(configDir2, "sessions", `${pid}.json`);
|
|
13295
|
-
if (existsSync18(pidFile)) unlinkSync2(pidFile);
|
|
13296
|
-
} catch {
|
|
13297
|
-
}
|
|
13181
|
+
console.error(`[session-stop] sessionId=${sessionId} manager-unreachable err=${err instanceof Error ? err.message : String(err)}`);
|
|
13182
|
+
return c.json({ error: "manager-unreachable" }, 502);
|
|
13298
13183
|
}
|
|
13299
|
-
if (
|
|
13300
|
-
console.
|
|
13301
|
-
return c.json(
|
|
13302
|
-
{ error: "jsonl-resurrected", jsonlPath, pidKilled, waitForExitMs, escalatedToSIGKILL },
|
|
13303
|
-
500
|
|
13304
|
-
);
|
|
13184
|
+
if (res.status === 204 || res.status === 200 || res.status === 404) {
|
|
13185
|
+
console.log(`[session-stop] sessionId=${sessionId} stopped manager-status=${res.status}`);
|
|
13186
|
+
return c.json({ stopped: true });
|
|
13305
13187
|
}
|
|
13306
|
-
console.
|
|
13307
|
-
|
|
13308
|
-
);
|
|
13309
|
-
return c.json({ deleted, pidKilled, jsonlPath, waitForExitMs, escalatedToSIGKILL });
|
|
13188
|
+
console.error(`[session-stop] sessionId=${sessionId} manager-status=${res.status}`);
|
|
13189
|
+
return c.json({ error: `manager-status-${res.status}` }, 502);
|
|
13310
13190
|
});
|
|
13311
|
-
var
|
|
13191
|
+
var session_stop_default = app26;
|
|
13312
13192
|
|
|
13313
13193
|
// server/routes/admin/session-rc-spawn.ts
|
|
13314
|
-
var
|
|
13315
|
-
function
|
|
13194
|
+
var app27 = new Hono();
|
|
13195
|
+
function managerBase6() {
|
|
13316
13196
|
const port2 = process.env.CLAUDE_SESSION_MANAGER_PORT;
|
|
13317
13197
|
if (!port2) throw new Error("CLAUDE_SESSION_MANAGER_PORT is not set");
|
|
13318
13198
|
return `http://127.0.0.1:${port2}`;
|
|
13319
13199
|
}
|
|
13320
|
-
|
|
13200
|
+
app27.post("/", requireAdminSession, async (c) => {
|
|
13321
13201
|
let body;
|
|
13322
13202
|
try {
|
|
13323
13203
|
body = await c.req.json();
|
|
@@ -13329,7 +13209,7 @@ app26.post("/", requireAdminSession, async (c) => {
|
|
|
13329
13209
|
if (typeof body.name === "string" && body.name.length > 0) payload.name = body.name;
|
|
13330
13210
|
let res;
|
|
13331
13211
|
try {
|
|
13332
|
-
res = await fetch(`${
|
|
13212
|
+
res = await fetch(`${managerBase6()}/rc-spawn`, {
|
|
13333
13213
|
method: "POST",
|
|
13334
13214
|
headers: { "content-type": "application/json" },
|
|
13335
13215
|
body: JSON.stringify(payload)
|
|
@@ -13351,7 +13231,7 @@ app26.post("/", requireAdminSession, async (c) => {
|
|
|
13351
13231
|
}
|
|
13352
13232
|
return c.json(parsed ?? {});
|
|
13353
13233
|
});
|
|
13354
|
-
var session_rc_spawn_default =
|
|
13234
|
+
var session_rc_spawn_default = app27;
|
|
13355
13235
|
|
|
13356
13236
|
// server/routes/admin/system-stats.ts
|
|
13357
13237
|
import { readFile as readFile5 } from "fs/promises";
|
|
@@ -13448,8 +13328,8 @@ async function sample() {
|
|
|
13448
13328
|
if (process.platform === "linux") return sampleLinux();
|
|
13449
13329
|
return sampleOsFallback();
|
|
13450
13330
|
}
|
|
13451
|
-
var
|
|
13452
|
-
|
|
13331
|
+
var app28 = new Hono();
|
|
13332
|
+
app28.get("/", async (c) => {
|
|
13453
13333
|
const started = Date.now();
|
|
13454
13334
|
if (!inflight) {
|
|
13455
13335
|
inflight = sample().finally(() => {
|
|
@@ -13472,27 +13352,27 @@ app27.get("/", async (c) => {
|
|
|
13472
13352
|
return c.json({ degraded: true, reason, sampledAtMs: Date.now() });
|
|
13473
13353
|
}
|
|
13474
13354
|
});
|
|
13475
|
-
var system_stats_default =
|
|
13355
|
+
var system_stats_default = app28;
|
|
13476
13356
|
|
|
13477
13357
|
// server/routes/admin/health.ts
|
|
13478
|
-
import { existsSync as
|
|
13479
|
-
import { resolve as
|
|
13480
|
-
var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ??
|
|
13358
|
+
import { existsSync as existsSync18, readFileSync as readFileSync17 } from "fs";
|
|
13359
|
+
import { resolve as resolve19, join as join16 } from "path";
|
|
13360
|
+
var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve19(process.cwd(), "..");
|
|
13481
13361
|
var brandHostname = "maxy";
|
|
13482
|
-
var brandJsonPath =
|
|
13483
|
-
if (
|
|
13362
|
+
var brandJsonPath = join16(PLATFORM_ROOT6, "config", "brand.json");
|
|
13363
|
+
if (existsSync18(brandJsonPath)) {
|
|
13484
13364
|
try {
|
|
13485
|
-
const brand = JSON.parse(
|
|
13365
|
+
const brand = JSON.parse(readFileSync17(brandJsonPath, "utf-8"));
|
|
13486
13366
|
if (brand.hostname) brandHostname = brand.hostname;
|
|
13487
13367
|
} catch {
|
|
13488
13368
|
}
|
|
13489
13369
|
}
|
|
13490
|
-
var VERSION_FILE =
|
|
13370
|
+
var VERSION_FILE = resolve19(PLATFORM_ROOT6, `config/.${brandHostname}-version`);
|
|
13491
13371
|
var PROCESS_STARTED_AT = (/* @__PURE__ */ new Date()).toISOString();
|
|
13492
13372
|
var PROBE_TIMEOUT_MS = 1e3;
|
|
13493
13373
|
function readVersion() {
|
|
13494
|
-
if (!
|
|
13495
|
-
return
|
|
13374
|
+
if (!existsSync18(VERSION_FILE)) return "unknown";
|
|
13375
|
+
return readFileSync17(VERSION_FILE, "utf-8").trim() || "unknown";
|
|
13496
13376
|
}
|
|
13497
13377
|
async function probeConversationDb() {
|
|
13498
13378
|
let session;
|
|
@@ -13517,8 +13397,8 @@ async function probeConversationDb() {
|
|
|
13517
13397
|
});
|
|
13518
13398
|
}
|
|
13519
13399
|
}
|
|
13520
|
-
var
|
|
13521
|
-
|
|
13400
|
+
var app29 = new Hono();
|
|
13401
|
+
app29.get("/", async (c) => {
|
|
13522
13402
|
const version = readVersion();
|
|
13523
13403
|
const probe = await probeConversationDb();
|
|
13524
13404
|
const uptimeMs = Date.now() - new Date(PROCESS_STARTED_AT).getTime();
|
|
@@ -13540,7 +13420,7 @@ app28.get("/", async (c) => {
|
|
|
13540
13420
|
uptimeMs
|
|
13541
13421
|
});
|
|
13542
13422
|
});
|
|
13543
|
-
var health_default2 =
|
|
13423
|
+
var health_default2 = app29;
|
|
13544
13424
|
|
|
13545
13425
|
// server/routes/admin/linkedin-ingest.ts
|
|
13546
13426
|
import { randomUUID as randomUUID9 } from "crypto";
|
|
@@ -13642,8 +13522,8 @@ function buildInitialMessage(env) {
|
|
|
13642
13522
|
}
|
|
13643
13523
|
return header;
|
|
13644
13524
|
}
|
|
13645
|
-
var
|
|
13646
|
-
|
|
13525
|
+
var app30 = new Hono();
|
|
13526
|
+
app30.post("/", requireAdminSession, async (c) => {
|
|
13647
13527
|
let body;
|
|
13648
13528
|
try {
|
|
13649
13529
|
body = await c.req.json();
|
|
@@ -13688,7 +13568,7 @@ app29.post("/", requireAdminSession, async (c) => {
|
|
|
13688
13568
|
);
|
|
13689
13569
|
return c.json({ ok: true, dispatchId: envelope.dispatchId, taskId: spawned.sessionId }, 202);
|
|
13690
13570
|
});
|
|
13691
|
-
var linkedin_ingest_default =
|
|
13571
|
+
var linkedin_ingest_default = app30;
|
|
13692
13572
|
|
|
13693
13573
|
// server/routes/admin/post-turn-context.ts
|
|
13694
13574
|
import neo4j2 from "neo4j-driver";
|
|
@@ -13730,8 +13610,8 @@ function pruneProperties(raw) {
|
|
|
13730
13610
|
}
|
|
13731
13611
|
return out;
|
|
13732
13612
|
}
|
|
13733
|
-
var
|
|
13734
|
-
|
|
13613
|
+
var app31 = new Hono();
|
|
13614
|
+
app31.get("/", async (c) => {
|
|
13735
13615
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
13736
13616
|
if (!isLoopbackAddr2(remoteAddr)) {
|
|
13737
13617
|
console.error(`${TAG24} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
@@ -13791,7 +13671,7 @@ app30.get("/", async (c) => {
|
|
|
13791
13671
|
await session.close();
|
|
13792
13672
|
}
|
|
13793
13673
|
});
|
|
13794
|
-
var post_turn_context_default =
|
|
13674
|
+
var post_turn_context_default = app31;
|
|
13795
13675
|
|
|
13796
13676
|
// server/routes/admin/public-session-context.ts
|
|
13797
13677
|
import neo4j3 from "neo4j-driver";
|
|
@@ -13833,8 +13713,8 @@ function pruneProperties2(raw) {
|
|
|
13833
13713
|
}
|
|
13834
13714
|
return out;
|
|
13835
13715
|
}
|
|
13836
|
-
var
|
|
13837
|
-
|
|
13716
|
+
var app32 = new Hono();
|
|
13717
|
+
app32.get("/", async (c) => {
|
|
13838
13718
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
13839
13719
|
if (!isLoopbackAddr3(remoteAddr)) {
|
|
13840
13720
|
console.error(`${TAG25} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
@@ -13893,15 +13773,15 @@ app31.get("/", async (c) => {
|
|
|
13893
13773
|
await session.close();
|
|
13894
13774
|
}
|
|
13895
13775
|
});
|
|
13896
|
-
var public_session_context_default =
|
|
13776
|
+
var public_session_context_default = app32;
|
|
13897
13777
|
|
|
13898
13778
|
// server/routes/admin/public-session-exit.ts
|
|
13899
13779
|
var TAG26 = "[public-session-exit-route]";
|
|
13900
13780
|
function isLoopbackAddr4(addr) {
|
|
13901
13781
|
return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
|
|
13902
13782
|
}
|
|
13903
|
-
var
|
|
13904
|
-
|
|
13783
|
+
var app33 = new Hono();
|
|
13784
|
+
app33.post("/", async (c) => {
|
|
13905
13785
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
13906
13786
|
if (!isLoopbackAddr4(remoteAddr)) {
|
|
13907
13787
|
console.error(`${TAG26} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
@@ -13928,15 +13808,15 @@ app32.post("/", async (c) => {
|
|
|
13928
13808
|
handlePublicSessionExit(sessionId);
|
|
13929
13809
|
return c.json({ ok: true });
|
|
13930
13810
|
});
|
|
13931
|
-
var public_session_exit_default =
|
|
13811
|
+
var public_session_exit_default = app33;
|
|
13932
13812
|
|
|
13933
13813
|
// server/routes/admin/access-session-evict.ts
|
|
13934
13814
|
var TAG27 = "[access-session-evict]";
|
|
13935
13815
|
function isLoopbackAddr5(addr) {
|
|
13936
13816
|
return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
|
|
13937
13817
|
}
|
|
13938
|
-
var
|
|
13939
|
-
|
|
13818
|
+
var app34 = new Hono();
|
|
13819
|
+
app34.post("/", async (c) => {
|
|
13940
13820
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
13941
13821
|
if (!isLoopbackAddr5(remoteAddr)) {
|
|
13942
13822
|
console.error(`${TAG27} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
@@ -13964,11 +13844,11 @@ app33.post("/", async (c) => {
|
|
|
13964
13844
|
console.log(`${TAG27} grantId=${grantId} dropped=${dropped}`);
|
|
13965
13845
|
return c.json({ ok: true, dropped });
|
|
13966
13846
|
});
|
|
13967
|
-
var access_session_evict_default =
|
|
13847
|
+
var access_session_evict_default = app34;
|
|
13968
13848
|
|
|
13969
13849
|
// server/routes/admin/browser.ts
|
|
13970
|
-
var
|
|
13971
|
-
|
|
13850
|
+
var app35 = new Hono();
|
|
13851
|
+
app35.post("/launch", requireAdminSession, async (c) => {
|
|
13972
13852
|
try {
|
|
13973
13853
|
const transport = resolveBrowserTransport(c.req.raw, c.env?.incoming?.socket?.remoteAddress);
|
|
13974
13854
|
console.error(`[admin/browser/launch] op=request transport=${transport}`);
|
|
@@ -13996,52 +13876,53 @@ app34.post("/launch", requireAdminSession, async (c) => {
|
|
|
13996
13876
|
);
|
|
13997
13877
|
}
|
|
13998
13878
|
});
|
|
13999
|
-
var browser_default =
|
|
13879
|
+
var browser_default = app35;
|
|
14000
13880
|
|
|
14001
13881
|
// server/routes/admin/index.ts
|
|
14002
|
-
var
|
|
14003
|
-
|
|
14004
|
-
|
|
14005
|
-
|
|
14006
|
-
|
|
14007
|
-
|
|
14008
|
-
|
|
14009
|
-
|
|
14010
|
-
|
|
14011
|
-
|
|
14012
|
-
|
|
14013
|
-
|
|
14014
|
-
|
|
14015
|
-
|
|
14016
|
-
|
|
14017
|
-
|
|
14018
|
-
|
|
14019
|
-
|
|
14020
|
-
|
|
14021
|
-
|
|
14022
|
-
|
|
14023
|
-
|
|
14024
|
-
|
|
14025
|
-
|
|
14026
|
-
|
|
14027
|
-
|
|
14028
|
-
|
|
14029
|
-
|
|
14030
|
-
|
|
14031
|
-
|
|
13882
|
+
var app36 = new Hono();
|
|
13883
|
+
app36.route("/session", session_default);
|
|
13884
|
+
app36.route("/logs", logs_default);
|
|
13885
|
+
app36.route("/claude-info", claude_info_default);
|
|
13886
|
+
app36.route("/attachment", attachment_default);
|
|
13887
|
+
app36.route("/agents", agents_default);
|
|
13888
|
+
app36.route("/sessions", sessions_default);
|
|
13889
|
+
app36.route("/claude-sessions", claude_sessions_default);
|
|
13890
|
+
app36.route("/log-ingest", log_ingest_default);
|
|
13891
|
+
app36.route("/events", events_default);
|
|
13892
|
+
app36.route("/files", files_default);
|
|
13893
|
+
app36.route("/graph-search", graph_search_default);
|
|
13894
|
+
app36.route("/graph-subgraph", graph_subgraph_default);
|
|
13895
|
+
app36.route("/graph-delete", graph_delete_default);
|
|
13896
|
+
app36.route("/graph-restore", graph_restore_default);
|
|
13897
|
+
app36.route("/graph-labels-in-graph", graph_labels_in_graph_default);
|
|
13898
|
+
app36.route("/graph-default-view", graph_default_view_default);
|
|
13899
|
+
app36.route("/sidebar-artefacts", sidebar_artefacts_default);
|
|
13900
|
+
app36.route("/sidebar-sessions", sidebar_sessions_default);
|
|
13901
|
+
app36.route("/session-delete", session_delete_default);
|
|
13902
|
+
app36.route("/session-stop", session_stop_default);
|
|
13903
|
+
app36.route("/browser", browser_default);
|
|
13904
|
+
app36.route("/session-rc-spawn", session_rc_spawn_default);
|
|
13905
|
+
app36.route("/system-stats", system_stats_default);
|
|
13906
|
+
app36.route("/health-brand", health_default2);
|
|
13907
|
+
app36.route("/linkedin-ingest", linkedin_ingest_default);
|
|
13908
|
+
app36.route("/post-turn-context", post_turn_context_default);
|
|
13909
|
+
app36.route("/public-session-context", public_session_context_default);
|
|
13910
|
+
app36.route("/public-session-exit", public_session_exit_default);
|
|
13911
|
+
app36.route("/access-session-evict", access_session_evict_default);
|
|
13912
|
+
var admin_default = app36;
|
|
14032
13913
|
|
|
14033
13914
|
// app/lib/access-gate.ts
|
|
14034
13915
|
import neo4j4 from "neo4j-driver";
|
|
14035
|
-
import { readFileSync as
|
|
14036
|
-
import { resolve as
|
|
13916
|
+
import { readFileSync as readFileSync18 } from "fs";
|
|
13917
|
+
import { resolve as resolve20 } from "path";
|
|
14037
13918
|
import { randomUUID as randomUUID10 } from "crypto";
|
|
14038
|
-
var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT ??
|
|
13919
|
+
var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT ?? resolve20(process.cwd(), "..");
|
|
14039
13920
|
var driver = null;
|
|
14040
13921
|
function readPassword() {
|
|
14041
13922
|
if (process.env.NEO4J_PASSWORD) return process.env.NEO4J_PASSWORD;
|
|
14042
|
-
const passwordFile =
|
|
13923
|
+
const passwordFile = resolve20(PLATFORM_ROOT7, "config/.neo4j-password");
|
|
14043
13924
|
try {
|
|
14044
|
-
return
|
|
13925
|
+
return readFileSync18(passwordFile, "utf-8").trim();
|
|
14045
13926
|
} catch {
|
|
14046
13927
|
throw new Error(
|
|
14047
13928
|
`Neo4j password not found. Expected at ${passwordFile} or in NEO4J_PASSWORD env var.`
|
|
@@ -14242,8 +14123,8 @@ async function generateNewMagicToken(grantId) {
|
|
|
14242
14123
|
var TAG28 = "[access-verify]";
|
|
14243
14124
|
var MINT_TAG = "[access-session-mint]";
|
|
14244
14125
|
var COOKIE_NAME = "__access_session";
|
|
14245
|
-
var
|
|
14246
|
-
|
|
14126
|
+
var app37 = new Hono();
|
|
14127
|
+
app37.post("/", async (c) => {
|
|
14247
14128
|
const ip = c.var.clientIp || "unknown";
|
|
14248
14129
|
let body;
|
|
14249
14130
|
try {
|
|
@@ -14325,13 +14206,13 @@ app36.post("/", async (c) => {
|
|
|
14325
14206
|
displayName: grant.displayName
|
|
14326
14207
|
});
|
|
14327
14208
|
});
|
|
14328
|
-
var verify_token_default =
|
|
14209
|
+
var verify_token_default = app37;
|
|
14329
14210
|
|
|
14330
14211
|
// app/lib/access-email.ts
|
|
14331
14212
|
import { spawn as spawn2 } from "child_process";
|
|
14332
|
-
import { resolve as
|
|
14333
|
-
var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT ??
|
|
14334
|
-
var SEND_SCRIPT =
|
|
14213
|
+
import { resolve as resolve21 } from "path";
|
|
14214
|
+
var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT ?? resolve21(process.cwd(), "..");
|
|
14215
|
+
var SEND_SCRIPT = resolve21(
|
|
14335
14216
|
PLATFORM_ROOT8,
|
|
14336
14217
|
"plugins",
|
|
14337
14218
|
"email",
|
|
@@ -14388,9 +14269,9 @@ async function sendMagicLinkEmail(payload) {
|
|
|
14388
14269
|
|
|
14389
14270
|
// server/routes/access/request-magic-link.ts
|
|
14390
14271
|
var TAG29 = "[access-request-link]";
|
|
14391
|
-
var
|
|
14272
|
+
var app38 = new Hono();
|
|
14392
14273
|
var VISITOR_MESSAGE = "If that email is on the invite list, a fresh link is on the way.";
|
|
14393
|
-
|
|
14274
|
+
app38.post("/", async (c) => {
|
|
14394
14275
|
let body;
|
|
14395
14276
|
try {
|
|
14396
14277
|
body = await c.req.json();
|
|
@@ -14464,17 +14345,17 @@ app37.post("/", async (c) => {
|
|
|
14464
14345
|
);
|
|
14465
14346
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
14466
14347
|
});
|
|
14467
|
-
var request_magic_link_default =
|
|
14348
|
+
var request_magic_link_default = app38;
|
|
14468
14349
|
|
|
14469
14350
|
// server/routes/access/index.ts
|
|
14470
|
-
var
|
|
14471
|
-
|
|
14472
|
-
|
|
14473
|
-
var access_default =
|
|
14351
|
+
var app39 = new Hono();
|
|
14352
|
+
app39.route("/verify-token", verify_token_default);
|
|
14353
|
+
app39.route("/request-magic-link", request_magic_link_default);
|
|
14354
|
+
var access_default = app39;
|
|
14474
14355
|
|
|
14475
14356
|
// server/routes/sites.ts
|
|
14476
|
-
import { existsSync as
|
|
14477
|
-
import { resolve as
|
|
14357
|
+
import { existsSync as existsSync19, readFileSync as readFileSync19, realpathSync as realpathSync5, statSync as statSync9 } from "fs";
|
|
14358
|
+
import { resolve as resolve22 } from "path";
|
|
14478
14359
|
var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
|
|
14479
14360
|
var MIME = {
|
|
14480
14361
|
".html": "text/html; charset=utf-8",
|
|
@@ -14505,8 +14386,8 @@ function getExt(p) {
|
|
|
14505
14386
|
if (idx < p.lastIndexOf("/")) return "";
|
|
14506
14387
|
return p.slice(idx).toLowerCase();
|
|
14507
14388
|
}
|
|
14508
|
-
var
|
|
14509
|
-
|
|
14389
|
+
var app40 = new Hono();
|
|
14390
|
+
app40.get("/:rel{.*}", (c) => {
|
|
14510
14391
|
const reqPath = c.req.path;
|
|
14511
14392
|
const rawRel = c.req.param("rel") ?? "";
|
|
14512
14393
|
const trimmed = rawRel.replace(/^\/+/, "").replace(/\/+$/, "");
|
|
@@ -14531,15 +14412,15 @@ app39.get("/:rel{.*}", (c) => {
|
|
|
14531
14412
|
}
|
|
14532
14413
|
segments.push(seg);
|
|
14533
14414
|
}
|
|
14534
|
-
const rootDir =
|
|
14535
|
-
let filePath = segments.length === 0 ? rootDir :
|
|
14415
|
+
const rootDir = resolve22(account.accountDir, "sites");
|
|
14416
|
+
let filePath = segments.length === 0 ? rootDir : resolve22(rootDir, ...segments);
|
|
14536
14417
|
if (filePath !== rootDir && !filePath.startsWith(rootDir + "/")) {
|
|
14537
14418
|
console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
|
|
14538
14419
|
return c.text("Forbidden", 403);
|
|
14539
14420
|
}
|
|
14540
14421
|
let stat7;
|
|
14541
14422
|
try {
|
|
14542
|
-
stat7 =
|
|
14423
|
+
stat7 = existsSync19(filePath) ? statSync9(filePath) : null;
|
|
14543
14424
|
} catch {
|
|
14544
14425
|
stat7 = null;
|
|
14545
14426
|
}
|
|
@@ -14552,13 +14433,13 @@ app39.get("/:rel{.*}", (c) => {
|
|
|
14552
14433
|
return c.redirect(target, 301);
|
|
14553
14434
|
}
|
|
14554
14435
|
if (stat7?.isDirectory()) {
|
|
14555
|
-
filePath =
|
|
14436
|
+
filePath = resolve22(filePath, "index.html");
|
|
14556
14437
|
}
|
|
14557
14438
|
if (!filePath.startsWith(rootDir + "/")) {
|
|
14558
14439
|
console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
|
|
14559
14440
|
return c.text("Forbidden", 403);
|
|
14560
14441
|
}
|
|
14561
|
-
if (!
|
|
14442
|
+
if (!existsSync19(filePath)) {
|
|
14562
14443
|
console.error(`[sites] not-found path=${reqPath} status=404`);
|
|
14563
14444
|
return c.text("Not found", 404);
|
|
14564
14445
|
}
|
|
@@ -14577,7 +14458,7 @@ app39.get("/:rel{.*}", (c) => {
|
|
|
14577
14458
|
}
|
|
14578
14459
|
let body;
|
|
14579
14460
|
try {
|
|
14580
|
-
body =
|
|
14461
|
+
body = readFileSync19(realPath);
|
|
14581
14462
|
} catch (err) {
|
|
14582
14463
|
const code = err?.code;
|
|
14583
14464
|
if (code === "EISDIR") {
|
|
@@ -14609,11 +14490,11 @@ app39.get("/:rel{.*}", (c) => {
|
|
|
14609
14490
|
"X-Content-Type-Options": "nosniff"
|
|
14610
14491
|
});
|
|
14611
14492
|
});
|
|
14612
|
-
var sites_default =
|
|
14493
|
+
var sites_default = app40;
|
|
14613
14494
|
|
|
14614
14495
|
// app/lib/visitor-token.ts
|
|
14615
14496
|
import { createHmac, randomBytes, timingSafeEqual } from "crypto";
|
|
14616
|
-
import { mkdirSync as mkdirSync4, readFileSync as
|
|
14497
|
+
import { mkdirSync as mkdirSync4, readFileSync as readFileSync20, writeFileSync as writeFileSync7 } from "fs";
|
|
14617
14498
|
import { dirname as dirname5 } from "path";
|
|
14618
14499
|
var TOKEN_PREFIX = "v1.";
|
|
14619
14500
|
var SECRET_BYTES = 32;
|
|
@@ -14622,7 +14503,7 @@ var cachedSecret = null;
|
|
|
14622
14503
|
function getSecret() {
|
|
14623
14504
|
if (cachedSecret) return cachedSecret;
|
|
14624
14505
|
try {
|
|
14625
|
-
const hex2 =
|
|
14506
|
+
const hex2 = readFileSync20(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
|
|
14626
14507
|
if (hex2.length === SECRET_BYTES * 2) {
|
|
14627
14508
|
cachedSecret = Buffer.from(hex2, "hex");
|
|
14628
14509
|
return cachedSecret;
|
|
@@ -14636,7 +14517,7 @@ function getSecret() {
|
|
|
14636
14517
|
console.log(`[visitor-token] secret minted path=${VISITOR_TOKEN_SECRET_FILE}`);
|
|
14637
14518
|
} catch {
|
|
14638
14519
|
}
|
|
14639
|
-
const hex =
|
|
14520
|
+
const hex = readFileSync20(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
|
|
14640
14521
|
cachedSecret = Buffer.from(hex, "hex");
|
|
14641
14522
|
return cachedSecret;
|
|
14642
14523
|
}
|
|
@@ -14689,8 +14570,8 @@ var VISITOR_COOKIE_NAME = "mxy_v";
|
|
|
14689
14570
|
var VISITOR_COOKIE_MAX_AGE_SECONDS = Math.floor(DEFAULT_TTL_MS / 1e3);
|
|
14690
14571
|
|
|
14691
14572
|
// app/lib/brand-config.ts
|
|
14692
|
-
import { existsSync as
|
|
14693
|
-
import { join as
|
|
14573
|
+
import { existsSync as existsSync20, readFileSync as readFileSync21 } from "fs";
|
|
14574
|
+
import { join as join17 } from "path";
|
|
14694
14575
|
var cached2 = null;
|
|
14695
14576
|
var cachedAttempted = false;
|
|
14696
14577
|
function readBrandConfig() {
|
|
@@ -14698,10 +14579,10 @@ function readBrandConfig() {
|
|
|
14698
14579
|
cachedAttempted = true;
|
|
14699
14580
|
const platformRoot2 = process.env.MAXY_PLATFORM_ROOT;
|
|
14700
14581
|
if (!platformRoot2) return null;
|
|
14701
|
-
const brandPath =
|
|
14702
|
-
if (!
|
|
14582
|
+
const brandPath = join17(platformRoot2, "config", "brand.json");
|
|
14583
|
+
if (!existsSync20(brandPath)) return null;
|
|
14703
14584
|
try {
|
|
14704
|
-
cached2 = JSON.parse(
|
|
14585
|
+
cached2 = JSON.parse(readFileSync21(brandPath, "utf-8"));
|
|
14705
14586
|
return cached2;
|
|
14706
14587
|
} catch {
|
|
14707
14588
|
return null;
|
|
@@ -14709,7 +14590,7 @@ function readBrandConfig() {
|
|
|
14709
14590
|
}
|
|
14710
14591
|
|
|
14711
14592
|
// server/routes/visitor-consent.ts
|
|
14712
|
-
var
|
|
14593
|
+
var app41 = new Hono();
|
|
14713
14594
|
var CONSENT_COOKIE_NAME = "mxy_consent";
|
|
14714
14595
|
var CONSENT_COOKIE_MAX_AGE_SECONDS = 60 * 60 * 24 * 365;
|
|
14715
14596
|
var DEFAULT_CONSENT_COPY = {
|
|
@@ -14754,17 +14635,17 @@ function siteSlugFromReferer(referer) {
|
|
|
14754
14635
|
return "";
|
|
14755
14636
|
}
|
|
14756
14637
|
}
|
|
14757
|
-
|
|
14638
|
+
app41.options("/consent", (c) => {
|
|
14758
14639
|
const origin = getOrigin(c);
|
|
14759
14640
|
setCorsHeaders(c, origin);
|
|
14760
14641
|
return c.body(null, 204);
|
|
14761
14642
|
});
|
|
14762
|
-
|
|
14643
|
+
app41.options("/brand-config", (c) => {
|
|
14763
14644
|
const origin = getOrigin(c);
|
|
14764
14645
|
setCorsHeaders(c, origin);
|
|
14765
14646
|
return c.body(null, 204);
|
|
14766
14647
|
});
|
|
14767
|
-
|
|
14648
|
+
app41.post("/consent", async (c) => {
|
|
14768
14649
|
const origin = getOrigin(c);
|
|
14769
14650
|
setCorsHeaders(c, origin);
|
|
14770
14651
|
let raw;
|
|
@@ -14804,7 +14685,7 @@ app40.post("/consent", async (c) => {
|
|
|
14804
14685
|
console.log(`[consent] ${parsed.decision} site=${site} brand=${brandName} tokenBound=${tokenBound}`);
|
|
14805
14686
|
return c.body(null, 204);
|
|
14806
14687
|
});
|
|
14807
|
-
|
|
14688
|
+
app41.get("/brand-config", (c) => {
|
|
14808
14689
|
const origin = getOrigin(c);
|
|
14809
14690
|
setCorsHeaders(c, origin);
|
|
14810
14691
|
const brand = readBrandConfig();
|
|
@@ -14814,7 +14695,7 @@ app40.get("/brand-config", (c) => {
|
|
|
14814
14695
|
c.header("Cache-Control", "public, max-age=300");
|
|
14815
14696
|
return c.json({ consent: { copy, palette } });
|
|
14816
14697
|
});
|
|
14817
|
-
var visitor_consent_default =
|
|
14698
|
+
var visitor_consent_default = app41;
|
|
14818
14699
|
|
|
14819
14700
|
// server/routes/listings.ts
|
|
14820
14701
|
function getCookie(headerValue, name) {
|
|
@@ -14841,8 +14722,8 @@ function appendConsentParams(pageUrl, token) {
|
|
|
14841
14722
|
}
|
|
14842
14723
|
var SAFE_SLUG_RE = /^[a-z0-9](?:[a-z0-9-]{0,118}[a-z0-9])?$/;
|
|
14843
14724
|
var CHAT_SESSION_KEY_RE = /^[A-Za-z0-9][A-Za-z0-9_-]{7,127}$/;
|
|
14844
|
-
var
|
|
14845
|
-
|
|
14725
|
+
var app42 = new Hono();
|
|
14726
|
+
app42.get("/:slug/click", async (c) => {
|
|
14846
14727
|
const slug = c.req.param("slug") ?? "";
|
|
14847
14728
|
const rawSession = c.req.query("session") ?? "";
|
|
14848
14729
|
const sessionKey = CHAT_SESSION_KEY_RE.test(rawSession) ? rawSession : "invalid";
|
|
@@ -14906,10 +14787,10 @@ app41.get("/:slug/click", async (c) => {
|
|
|
14906
14787
|
console.log(`[property-card-click] sessionKey=${sessionKey} listingSlug=${slug} consent=${consentCookie ?? "absent"} ts=${(/* @__PURE__ */ new Date()).toISOString()}`);
|
|
14907
14788
|
return c.redirect(redirectUrl, 302);
|
|
14908
14789
|
});
|
|
14909
|
-
var listings_default =
|
|
14790
|
+
var listings_default = app42;
|
|
14910
14791
|
|
|
14911
14792
|
// server/routes/visitor-event.ts
|
|
14912
|
-
var
|
|
14793
|
+
var app43 = new Hono();
|
|
14913
14794
|
var BOT_UA_RE = /\b(bot|crawl|spider|slurp|headlesschrome|phantomjs|googlebot|bingbot|yandex|baiduspider|ahrefsbot|semrushbot|mj12bot|dotbot|petalbot)\b/i;
|
|
14914
14795
|
var buckets = /* @__PURE__ */ new Map();
|
|
14915
14796
|
var RATE_LIMIT = 60;
|
|
@@ -14976,12 +14857,12 @@ function originAllowed(origin, allowlist) {
|
|
|
14976
14857
|
return false;
|
|
14977
14858
|
}
|
|
14978
14859
|
}
|
|
14979
|
-
|
|
14860
|
+
app43.options("/event", (c) => {
|
|
14980
14861
|
const origin = getOrigin2(c);
|
|
14981
14862
|
setCorsHeaders2(c, origin);
|
|
14982
14863
|
return c.body(null, 204);
|
|
14983
14864
|
});
|
|
14984
|
-
|
|
14865
|
+
app43.post("/event", async (c) => {
|
|
14985
14866
|
const origin = getOrigin2(c);
|
|
14986
14867
|
setCorsHeaders2(c, origin);
|
|
14987
14868
|
const ua = c.req.header("user-agent") ?? "";
|
|
@@ -15186,17 +15067,17 @@ async function writeEvent(opts) {
|
|
|
15186
15067
|
);
|
|
15187
15068
|
}
|
|
15188
15069
|
}
|
|
15189
|
-
var visitor_event_default =
|
|
15070
|
+
var visitor_event_default = app43;
|
|
15190
15071
|
|
|
15191
15072
|
// server/routes/session.ts
|
|
15192
|
-
import { resolve as
|
|
15193
|
-
import { existsSync as
|
|
15073
|
+
import { resolve as resolve23 } from "path";
|
|
15074
|
+
import { existsSync as existsSync21, writeFileSync as writeFileSync8, mkdirSync as mkdirSync5 } from "fs";
|
|
15194
15075
|
var UUID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
15195
15076
|
function writeBrandingCache(accountId, agentSlug, branding) {
|
|
15196
15077
|
try {
|
|
15197
|
-
const cacheDir =
|
|
15078
|
+
const cacheDir = resolve23(MAXY_DIR, "branding-cache", accountId);
|
|
15198
15079
|
mkdirSync5(cacheDir, { recursive: true });
|
|
15199
|
-
writeFileSync8(
|
|
15080
|
+
writeFileSync8(resolve23(cacheDir, `${agentSlug}.json`), JSON.stringify(branding), "utf-8");
|
|
15200
15081
|
} catch (err) {
|
|
15201
15082
|
console.error(`[branding] cache write failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
15202
15083
|
}
|
|
@@ -15232,8 +15113,8 @@ function withVisitorCookie(response, visitorId) {
|
|
|
15232
15113
|
headers
|
|
15233
15114
|
});
|
|
15234
15115
|
}
|
|
15235
|
-
var
|
|
15236
|
-
|
|
15116
|
+
var app44 = new Hono();
|
|
15117
|
+
app44.post("/", async (c) => {
|
|
15237
15118
|
let body;
|
|
15238
15119
|
try {
|
|
15239
15120
|
body = await c.req.json();
|
|
@@ -15284,8 +15165,8 @@ app43.post("/", async (c) => {
|
|
|
15284
15165
|
}
|
|
15285
15166
|
let agentConfig = null;
|
|
15286
15167
|
if (account) {
|
|
15287
|
-
const agentDir =
|
|
15288
|
-
if (!
|
|
15168
|
+
const agentDir = resolve23(account.accountDir, "agents", agentSlug);
|
|
15169
|
+
if (!existsSync21(agentDir) || !existsSync21(resolve23(agentDir, "config.json"))) {
|
|
15289
15170
|
return c.json({ error: "Agent not found" }, 404);
|
|
15290
15171
|
}
|
|
15291
15172
|
agentConfig = resolveAgentConfig(account.accountDir, agentSlug);
|
|
@@ -15444,7 +15325,7 @@ app43.post("/", async (c) => {
|
|
|
15444
15325
|
newVisitorId
|
|
15445
15326
|
);
|
|
15446
15327
|
});
|
|
15447
|
-
var session_default2 =
|
|
15328
|
+
var session_default2 = app44;
|
|
15448
15329
|
|
|
15449
15330
|
// app/lib/graph-health.ts
|
|
15450
15331
|
var import_dist4 = __toESM(require_dist3(), 1);
|
|
@@ -15565,7 +15446,7 @@ function startGraphHealthTimer() {
|
|
|
15565
15446
|
|
|
15566
15447
|
// app/lib/file-watcher.ts
|
|
15567
15448
|
import * as fsp2 from "fs/promises";
|
|
15568
|
-
import { resolve as
|
|
15449
|
+
import { resolve as resolve24, sep as sep7 } from "path";
|
|
15569
15450
|
var ACCOUNT_UUID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
15570
15451
|
var DEFAULT_COALESCE_MS = 500;
|
|
15571
15452
|
var ROOTS = ["uploads", "accounts"];
|
|
@@ -15584,7 +15465,7 @@ async function startFileWatcher(opts = {}) {
|
|
|
15584
15465
|
const dropFn = opts.drop ?? dropFileIndex;
|
|
15585
15466
|
for (const r of ROOTS) {
|
|
15586
15467
|
try {
|
|
15587
|
-
await fsp2.mkdir(
|
|
15468
|
+
await fsp2.mkdir(resolve24(dataRoot, r), { recursive: true });
|
|
15588
15469
|
} catch (err) {
|
|
15589
15470
|
console.error(
|
|
15590
15471
|
`[file-watcher] start-failed root="${r}" err="${err.message}" \u2014 index will be maintained by the 5-min reconcile backstop only`
|
|
@@ -15605,7 +15486,7 @@ async function startFileWatcher(opts = {}) {
|
|
|
15605
15486
|
timers.set(relativePath, t);
|
|
15606
15487
|
}
|
|
15607
15488
|
async function runHook(relativePath, accountId) {
|
|
15608
|
-
const absolute =
|
|
15489
|
+
const absolute = resolve24(dataRoot, relativePath);
|
|
15609
15490
|
let exists = false;
|
|
15610
15491
|
try {
|
|
15611
15492
|
const st = await fsp2.stat(absolute);
|
|
@@ -15629,7 +15510,7 @@ async function startFileWatcher(opts = {}) {
|
|
|
15629
15510
|
}
|
|
15630
15511
|
}
|
|
15631
15512
|
async function watchRoot(rootName) {
|
|
15632
|
-
const absRoot =
|
|
15513
|
+
const absRoot = resolve24(dataRoot, rootName);
|
|
15633
15514
|
try {
|
|
15634
15515
|
const iter = fsp2.watch(absRoot, { recursive: true, signal: controller.signal });
|
|
15635
15516
|
for await (const event of iter) {
|
|
@@ -15939,8 +15820,8 @@ var streamSSE = (c, cb, onError) => {
|
|
|
15939
15820
|
|
|
15940
15821
|
// app/lib/whatsapp/gateway/routes.ts
|
|
15941
15822
|
function createWaChannelRoutes(deps) {
|
|
15942
|
-
const
|
|
15943
|
-
|
|
15823
|
+
const app46 = new Hono();
|
|
15824
|
+
app46.get("/wa-channel/inbound", (c) => {
|
|
15944
15825
|
const senderId = c.req.query("senderId");
|
|
15945
15826
|
if (!senderId) return c.json({ error: "senderId required" }, 400);
|
|
15946
15827
|
return streamSSE(c, async (stream2) => {
|
|
@@ -15958,7 +15839,7 @@ function createWaChannelRoutes(deps) {
|
|
|
15958
15839
|
}
|
|
15959
15840
|
});
|
|
15960
15841
|
});
|
|
15961
|
-
|
|
15842
|
+
app46.post("/wa-channel/reply", async (c) => {
|
|
15962
15843
|
const body = await c.req.json().catch(() => null);
|
|
15963
15844
|
const senderId = body?.senderId;
|
|
15964
15845
|
const text = body?.text;
|
|
@@ -15977,7 +15858,7 @@ function createWaChannelRoutes(deps) {
|
|
|
15977
15858
|
console.error(`[whatsapp-native] op=reply-dispatch senderId=${senderId} bytes=${bytes}`);
|
|
15978
15859
|
return c.json({ ok: true });
|
|
15979
15860
|
});
|
|
15980
|
-
|
|
15861
|
+
app46.post("/wa-channel/ready", async (c) => {
|
|
15981
15862
|
const body = await c.req.json().catch(() => null);
|
|
15982
15863
|
const senderId = body?.senderId;
|
|
15983
15864
|
if (typeof senderId !== "string") {
|
|
@@ -15986,7 +15867,7 @@ function createWaChannelRoutes(deps) {
|
|
|
15986
15867
|
deps.onReady?.(senderId);
|
|
15987
15868
|
return c.json({ ok: true });
|
|
15988
15869
|
});
|
|
15989
|
-
|
|
15870
|
+
app46.post("/wa-channel/received", async (c) => {
|
|
15990
15871
|
const body = await c.req.json().catch(() => null);
|
|
15991
15872
|
const senderId = body?.senderId;
|
|
15992
15873
|
const waMessageId = body?.waMessageId;
|
|
@@ -15996,7 +15877,7 @@ function createWaChannelRoutes(deps) {
|
|
|
15996
15877
|
deps.onReceived?.(senderId, waMessageId);
|
|
15997
15878
|
return c.json({ ok: true });
|
|
15998
15879
|
});
|
|
15999
|
-
return
|
|
15880
|
+
return app46;
|
|
16000
15881
|
}
|
|
16001
15882
|
|
|
16002
15883
|
// app/lib/whatsapp/gateway/wa-gateway.ts
|
|
@@ -16057,17 +15938,15 @@ var WaGateway = class {
|
|
|
16057
15938
|
const bytes = Buffer.byteLength(input.text, "utf8");
|
|
16058
15939
|
const hadSubscriber = this.hub.hasSubscriber(input.senderId);
|
|
16059
15940
|
const willDeliverNow = this.hub.isReady(input.senderId);
|
|
16060
|
-
const
|
|
16061
|
-
const mediaField =
|
|
15941
|
+
const openable = input.media.filter((m) => m.type !== "audio");
|
|
15942
|
+
const mediaField = openable.length > 0 ? `media=${openable.map((m) => m.type).join(",")} mediaPaths=${openable.map((m) => m.path).join(",")}` : input.media.some((m) => m.type === "audio") ? "media=audio mediaPath=transcribed" : "media=none";
|
|
16062
15943
|
this.replies.set(input.senderId, input.reply);
|
|
16063
15944
|
this.hub.deliver(
|
|
16064
15945
|
{
|
|
16065
15946
|
senderId: input.senderId,
|
|
16066
15947
|
text: input.text,
|
|
16067
15948
|
waMessageId: `wa-${++this.seq}`,
|
|
16068
|
-
|
|
16069
|
-
mediaType: input.mediaType,
|
|
16070
|
-
mediaMimetype: input.mediaMimetype
|
|
15949
|
+
media: input.media
|
|
16071
15950
|
},
|
|
16072
15951
|
Date.now()
|
|
16073
15952
|
);
|
|
@@ -16191,8 +16070,8 @@ function broadcastAdminShutdown(reason) {
|
|
|
16191
16070
|
|
|
16192
16071
|
// ../lib/entitlement/src/index.ts
|
|
16193
16072
|
import { createPublicKey, createHash as createHash5, verify as cryptoVerify } from "crypto";
|
|
16194
|
-
import { existsSync as
|
|
16195
|
-
import { resolve as
|
|
16073
|
+
import { existsSync as existsSync22, readFileSync as readFileSync22, statSync as statSync10 } from "fs";
|
|
16074
|
+
import { resolve as resolve25 } from "path";
|
|
16196
16075
|
|
|
16197
16076
|
// ../lib/entitlement/src/canonicalize.ts
|
|
16198
16077
|
function canonicalize(value) {
|
|
@@ -16227,7 +16106,7 @@ var PUBKEY_SHA256 = "8eee6bcb33545fd13b16d3199a5735ca5db5062834c7b49dfe4f23801d9
|
|
|
16227
16106
|
var GRACE_DAYS = 7;
|
|
16228
16107
|
var GRACE_MS = GRACE_DAYS * 24 * 60 * 60 * 1e3;
|
|
16229
16108
|
function pubkeyPath(brand) {
|
|
16230
|
-
return
|
|
16109
|
+
return resolve25(brand.platformRoot, "lib", "entitlement", "rubytech-pubkey.pem");
|
|
16231
16110
|
}
|
|
16232
16111
|
var memo = null;
|
|
16233
16112
|
function memoKey(mtimeMs, account) {
|
|
@@ -16239,8 +16118,8 @@ function resolveEntitlement(brand, account) {
|
|
|
16239
16118
|
if (brand.commercialMode !== true) {
|
|
16240
16119
|
return logResolved(implicitTrust(account), null);
|
|
16241
16120
|
}
|
|
16242
|
-
const entitlementPath =
|
|
16243
|
-
if (!
|
|
16121
|
+
const entitlementPath = resolve25(brand.configDir, "entitlement.json");
|
|
16122
|
+
if (!existsSync22(entitlementPath)) {
|
|
16244
16123
|
return logResolved(anonymousFallback("missing"), { reason: "missing" });
|
|
16245
16124
|
}
|
|
16246
16125
|
const stat7 = statSync10(entitlementPath);
|
|
@@ -16255,7 +16134,7 @@ function resolveEntitlement(brand, account) {
|
|
|
16255
16134
|
function verifyAndResolve(brand, entitlementPath, account) {
|
|
16256
16135
|
let pubkeyPem;
|
|
16257
16136
|
try {
|
|
16258
|
-
pubkeyPem =
|
|
16137
|
+
pubkeyPem = readFileSync22(pubkeyPath(brand), "utf-8");
|
|
16259
16138
|
} catch (err) {
|
|
16260
16139
|
return logResolved(anonymousFallback("pubkey-missing"), {
|
|
16261
16140
|
reason: "pubkey-missing"
|
|
@@ -16269,7 +16148,7 @@ function verifyAndResolve(brand, entitlementPath, account) {
|
|
|
16269
16148
|
}
|
|
16270
16149
|
let envelope;
|
|
16271
16150
|
try {
|
|
16272
|
-
envelope = JSON.parse(
|
|
16151
|
+
envelope = JSON.parse(readFileSync22(entitlementPath, "utf-8"));
|
|
16273
16152
|
} catch {
|
|
16274
16153
|
return logResolved(anonymousFallback("malformed"), { reason: "malformed" });
|
|
16275
16154
|
}
|
|
@@ -16430,14 +16309,14 @@ function clientFrom(c) {
|
|
|
16430
16309
|
);
|
|
16431
16310
|
}
|
|
16432
16311
|
var PLATFORM_ROOT9 = process.env.MAXY_PLATFORM_ROOT || "";
|
|
16433
|
-
var BRAND_JSON_PATH = PLATFORM_ROOT9 ?
|
|
16312
|
+
var BRAND_JSON_PATH = PLATFORM_ROOT9 ? join18(PLATFORM_ROOT9, "config", "brand.json") : "";
|
|
16434
16313
|
var BRAND = { productName: "Maxy", hostname: "maxy", configDir: ".maxy", marketingUrl: "https://getmaxy.com" };
|
|
16435
|
-
if (BRAND_JSON_PATH && !
|
|
16314
|
+
if (BRAND_JSON_PATH && !existsSync23(BRAND_JSON_PATH)) {
|
|
16436
16315
|
console.error(`[brand] WARNING: brand.json not found at ${BRAND_JSON_PATH} \u2014 using Maxy defaults`);
|
|
16437
16316
|
}
|
|
16438
|
-
if (BRAND_JSON_PATH &&
|
|
16317
|
+
if (BRAND_JSON_PATH && existsSync23(BRAND_JSON_PATH)) {
|
|
16439
16318
|
try {
|
|
16440
|
-
const parsed = JSON.parse(
|
|
16319
|
+
const parsed = JSON.parse(readFileSync23(BRAND_JSON_PATH, "utf-8"));
|
|
16441
16320
|
BRAND = { ...BRAND, ...parsed };
|
|
16442
16321
|
} catch (err) {
|
|
16443
16322
|
console.error(`[brand] Failed to parse brand.json: ${err.message}`);
|
|
@@ -16456,11 +16335,11 @@ var brandLoginOpts = {
|
|
|
16456
16335
|
bodyFont: BRAND.defaultFonts?.body,
|
|
16457
16336
|
logoContainsName: !!BRAND.logoContainsName
|
|
16458
16337
|
};
|
|
16459
|
-
var ALIAS_DOMAINS_PATH =
|
|
16338
|
+
var ALIAS_DOMAINS_PATH = join18(homedir2(), BRAND.configDir, "alias-domains.json");
|
|
16460
16339
|
function loadAliasDomains() {
|
|
16461
16340
|
try {
|
|
16462
|
-
if (!
|
|
16463
|
-
const parsed = JSON.parse(
|
|
16341
|
+
if (!existsSync23(ALIAS_DOMAINS_PATH)) return null;
|
|
16342
|
+
const parsed = JSON.parse(readFileSync23(ALIAS_DOMAINS_PATH, "utf-8"));
|
|
16464
16343
|
if (!Array.isArray(parsed)) {
|
|
16465
16344
|
console.error("[alias-domains] malformed alias-domains.json \u2014 expected array");
|
|
16466
16345
|
return null;
|
|
@@ -16484,10 +16363,10 @@ watchFile(ALIAS_DOMAINS_PATH, { interval: 2e3 }, () => {
|
|
|
16484
16363
|
function isPublicHost(host) {
|
|
16485
16364
|
return host.startsWith("public.") || aliasDomains.has(host);
|
|
16486
16365
|
}
|
|
16487
|
-
var
|
|
16366
|
+
var app45 = new Hono();
|
|
16488
16367
|
var waGateway = new WaGateway({
|
|
16489
16368
|
gatewayUrl: `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`,
|
|
16490
|
-
serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ??
|
|
16369
|
+
serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve26(process.env.MAXY_PLATFORM_ROOT ?? join18(__dirname, ".."), "services/whatsapp-channel/dist/server.js"),
|
|
16491
16370
|
ensureChannelSession: async ({ accountId, senderId, gatewayUrl, serverPath }) => {
|
|
16492
16371
|
const userId = resolveAdminUserId({ accountId, senderPhone: senderId }) ?? void 0;
|
|
16493
16372
|
console.error(`[whatsapp-native] op=admin-identity senderId=${senderId} userId=${userId ?? "owner-fallback"}`);
|
|
@@ -16502,10 +16381,10 @@ var waGateway = new WaGateway({
|
|
|
16502
16381
|
}
|
|
16503
16382
|
}
|
|
16504
16383
|
});
|
|
16505
|
-
|
|
16384
|
+
app45.route("/", waGateway.routes());
|
|
16506
16385
|
waGateway.startSweeper();
|
|
16507
|
-
|
|
16508
|
-
|
|
16386
|
+
app45.use("*", clientIpMiddleware);
|
|
16387
|
+
app45.use("*", async (c, next) => {
|
|
16509
16388
|
await next();
|
|
16510
16389
|
c.header("X-Content-Type-Options", "nosniff");
|
|
16511
16390
|
c.header("Referrer-Policy", "strict-origin-when-cross-origin");
|
|
@@ -16515,7 +16394,7 @@ app44.use("*", async (c, next) => {
|
|
|
16515
16394
|
);
|
|
16516
16395
|
});
|
|
16517
16396
|
var HTTP_LOG_PATHS = /* @__PURE__ */ new Set(["/vnc-viewer.html", "/vnc-popout.html"]);
|
|
16518
|
-
|
|
16397
|
+
app45.use("*", async (c, next) => {
|
|
16519
16398
|
if (!HTTP_LOG_PATHS.has(c.req.path)) {
|
|
16520
16399
|
await next();
|
|
16521
16400
|
return;
|
|
@@ -16533,7 +16412,7 @@ app44.use("*", async (c, next) => {
|
|
|
16533
16412
|
});
|
|
16534
16413
|
}
|
|
16535
16414
|
});
|
|
16536
|
-
|
|
16415
|
+
app45.use("*", async (c, next) => {
|
|
16537
16416
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
16538
16417
|
if (!isPublicHost(host)) {
|
|
16539
16418
|
await next();
|
|
@@ -16564,7 +16443,7 @@ function resolveRemoteAuthOpts() {
|
|
|
16564
16443
|
return brandLoginOpts;
|
|
16565
16444
|
}
|
|
16566
16445
|
var MAX_LOGIN_BODY = 8 * 1024;
|
|
16567
|
-
|
|
16446
|
+
app45.post("/__remote-auth/login", async (c) => {
|
|
16568
16447
|
const client = clientFrom(c);
|
|
16569
16448
|
const clientIp = client.ip || "unknown";
|
|
16570
16449
|
if (!requestIsTlsTerminated(c)) {
|
|
@@ -16609,7 +16488,7 @@ app44.post("/__remote-auth/login", async (c) => {
|
|
|
16609
16488
|
}
|
|
16610
16489
|
});
|
|
16611
16490
|
});
|
|
16612
|
-
|
|
16491
|
+
app45.get("/__remote-auth/logout", (c) => {
|
|
16613
16492
|
const client = clientFrom(c);
|
|
16614
16493
|
const clientIp = client.ip || "unknown";
|
|
16615
16494
|
console.error(`[remote-auth] logout ip=${clientIp}`);
|
|
@@ -16622,7 +16501,7 @@ app44.get("/__remote-auth/logout", (c) => {
|
|
|
16622
16501
|
}
|
|
16623
16502
|
});
|
|
16624
16503
|
});
|
|
16625
|
-
|
|
16504
|
+
app45.post("/__remote-auth/change-password", async (c) => {
|
|
16626
16505
|
const client = clientFrom(c);
|
|
16627
16506
|
const clientIp = client.ip || "unknown";
|
|
16628
16507
|
const rateLimited = checkRateLimit(client);
|
|
@@ -16673,13 +16552,13 @@ app44.post("/__remote-auth/change-password", async (c) => {
|
|
|
16673
16552
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "change", changeError: "Failed to save password", redirect }), 200);
|
|
16674
16553
|
}
|
|
16675
16554
|
});
|
|
16676
|
-
|
|
16555
|
+
app45.get("/__remote-auth/setup", (c) => {
|
|
16677
16556
|
if (isRemoteAuthConfigured()) {
|
|
16678
16557
|
return c.redirect("/");
|
|
16679
16558
|
}
|
|
16680
16559
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "setup" }), 200);
|
|
16681
16560
|
});
|
|
16682
|
-
|
|
16561
|
+
app45.post("/__remote-auth/set-initial-password", async (c) => {
|
|
16683
16562
|
if (isRemoteAuthConfigured()) {
|
|
16684
16563
|
return c.redirect("/");
|
|
16685
16564
|
}
|
|
@@ -16717,10 +16596,10 @@ app44.post("/__remote-auth/set-initial-password", async (c) => {
|
|
|
16717
16596
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "setup", setupError: "Failed to save password. Please try again." }), 200);
|
|
16718
16597
|
}
|
|
16719
16598
|
});
|
|
16720
|
-
|
|
16599
|
+
app45.get("/api/remote-auth/status", (c) => {
|
|
16721
16600
|
return c.json({ configured: isRemoteAuthConfigured() });
|
|
16722
16601
|
});
|
|
16723
|
-
|
|
16602
|
+
app45.post("/api/remote-auth/set-password", async (c) => {
|
|
16724
16603
|
let body;
|
|
16725
16604
|
try {
|
|
16726
16605
|
body = await c.req.json();
|
|
@@ -16751,9 +16630,9 @@ app44.post("/api/remote-auth/set-password", async (c) => {
|
|
|
16751
16630
|
return c.json({ error: "Failed to save password" }, 500);
|
|
16752
16631
|
}
|
|
16753
16632
|
});
|
|
16754
|
-
|
|
16633
|
+
app45.route("/api/_client-error", client_error_default);
|
|
16755
16634
|
console.log("[client-error-route] mounted");
|
|
16756
|
-
|
|
16635
|
+
app45.use("*", async (c, next) => {
|
|
16757
16636
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
16758
16637
|
const path2 = c.req.path;
|
|
16759
16638
|
if (path2 === "/favicon.ico" || path2.startsWith("/assets/") || path2.startsWith("/brand/")) {
|
|
@@ -16786,14 +16665,14 @@ app44.use("*", async (c, next) => {
|
|
|
16786
16665
|
console.error(`[remote-auth] login required ip=${clientIp} path=${path2} ${disambig}`);
|
|
16787
16666
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), redirect: path2 }), 200);
|
|
16788
16667
|
});
|
|
16789
|
-
|
|
16790
|
-
|
|
16791
|
-
|
|
16792
|
-
|
|
16793
|
-
|
|
16794
|
-
|
|
16795
|
-
|
|
16796
|
-
|
|
16668
|
+
app45.route("/api/health", health_default);
|
|
16669
|
+
app45.route("/api/chat", chat_default);
|
|
16670
|
+
app45.route("/api/whatsapp", whatsapp_default);
|
|
16671
|
+
app45.route("/api/whatsapp-reader", whatsapp_reader_default);
|
|
16672
|
+
app45.route("/api/onboarding", onboarding_default);
|
|
16673
|
+
app45.route("/api/admin", admin_default);
|
|
16674
|
+
app45.route("/api/access", access_default);
|
|
16675
|
+
app45.route("/api/session", session_default2);
|
|
16797
16676
|
var SAFE_SLUG_RE2 = /^[a-z][a-z0-9-]{2,49}$/;
|
|
16798
16677
|
var SAFE_FILENAME_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
|
|
16799
16678
|
var IMAGE_MIME = {
|
|
@@ -16805,7 +16684,7 @@ var IMAGE_MIME = {
|
|
|
16805
16684
|
".svg": "image/svg+xml",
|
|
16806
16685
|
".ico": "image/x-icon"
|
|
16807
16686
|
};
|
|
16808
|
-
|
|
16687
|
+
app45.get("/agent-assets/:slug/:filename", (c) => {
|
|
16809
16688
|
const slug = c.req.param("slug");
|
|
16810
16689
|
const filename = c.req.param("filename");
|
|
16811
16690
|
if (!SAFE_SLUG_RE2.test(slug)) {
|
|
@@ -16821,26 +16700,26 @@ app44.get("/agent-assets/:slug/:filename", (c) => {
|
|
|
16821
16700
|
console.error(`[agent-assets] no-account slug=${slug} file=${filename}`);
|
|
16822
16701
|
return c.text("Not found", 404);
|
|
16823
16702
|
}
|
|
16824
|
-
const filePath =
|
|
16825
|
-
const expectedDir =
|
|
16703
|
+
const filePath = resolve26(account.accountDir, "agents", slug, "assets", filename);
|
|
16704
|
+
const expectedDir = resolve26(account.accountDir, "agents", slug, "assets");
|
|
16826
16705
|
if (!filePath.startsWith(expectedDir + "/")) {
|
|
16827
16706
|
console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
|
|
16828
16707
|
return c.text("Forbidden", 403);
|
|
16829
16708
|
}
|
|
16830
|
-
if (!
|
|
16709
|
+
if (!existsSync23(filePath)) {
|
|
16831
16710
|
console.error(`[agent-assets] serve slug=${slug} file=${filename} status=404`);
|
|
16832
16711
|
return c.text("Not found", 404);
|
|
16833
16712
|
}
|
|
16834
16713
|
const ext = "." + filename.split(".").pop()?.toLowerCase();
|
|
16835
16714
|
const contentType = IMAGE_MIME[ext] || "application/octet-stream";
|
|
16836
16715
|
console.log(`[agent-assets] serve slug=${slug} file=${filename} status=200`);
|
|
16837
|
-
const body =
|
|
16716
|
+
const body = readFileSync23(filePath);
|
|
16838
16717
|
return c.body(body, 200, {
|
|
16839
16718
|
"Content-Type": contentType,
|
|
16840
16719
|
"Cache-Control": "public, max-age=3600"
|
|
16841
16720
|
});
|
|
16842
16721
|
});
|
|
16843
|
-
|
|
16722
|
+
app45.get("/generated/:filename", (c) => {
|
|
16844
16723
|
const filename = c.req.param("filename");
|
|
16845
16724
|
if (!SAFE_FILENAME_RE.test(filename) || filename.includes("..")) {
|
|
16846
16725
|
console.error(`[generated] serve file=${filename} status=403`);
|
|
@@ -16851,35 +16730,35 @@ app44.get("/generated/:filename", (c) => {
|
|
|
16851
16730
|
console.error(`[generated] serve file=${filename} status=404`);
|
|
16852
16731
|
return c.text("Not found", 404);
|
|
16853
16732
|
}
|
|
16854
|
-
const filePath =
|
|
16855
|
-
const expectedDir =
|
|
16733
|
+
const filePath = resolve26(account.accountDir, "generated", filename);
|
|
16734
|
+
const expectedDir = resolve26(account.accountDir, "generated");
|
|
16856
16735
|
if (!filePath.startsWith(expectedDir + "/")) {
|
|
16857
16736
|
console.error(`[generated] serve file=${filename} status=403`);
|
|
16858
16737
|
return c.text("Forbidden", 403);
|
|
16859
16738
|
}
|
|
16860
|
-
if (!
|
|
16739
|
+
if (!existsSync23(filePath)) {
|
|
16861
16740
|
console.error(`[generated] serve file=${filename} status=404`);
|
|
16862
16741
|
return c.text("Not found", 404);
|
|
16863
16742
|
}
|
|
16864
16743
|
const ext = "." + filename.split(".").pop()?.toLowerCase();
|
|
16865
16744
|
const contentType = IMAGE_MIME[ext] || "application/octet-stream";
|
|
16866
16745
|
console.log(`[generated] serve file=${filename} status=200`);
|
|
16867
|
-
const body =
|
|
16746
|
+
const body = readFileSync23(filePath);
|
|
16868
16747
|
return c.body(body, 200, {
|
|
16869
16748
|
"Content-Type": contentType,
|
|
16870
16749
|
"Cache-Control": "public, max-age=86400"
|
|
16871
16750
|
});
|
|
16872
16751
|
});
|
|
16873
|
-
|
|
16874
|
-
|
|
16875
|
-
|
|
16876
|
-
|
|
16752
|
+
app45.route("/sites", sites_default);
|
|
16753
|
+
app45.route("/listings", listings_default);
|
|
16754
|
+
app45.route("/v", visitor_event_default);
|
|
16755
|
+
app45.route("/v", visitor_consent_default);
|
|
16877
16756
|
var htmlCache = /* @__PURE__ */ new Map();
|
|
16878
16757
|
var brandLogoPath = "/brand/maxy-monochrome.png";
|
|
16879
16758
|
var brandIconPath = "/brand/maxy-monochrome.png";
|
|
16880
|
-
if (BRAND_JSON_PATH &&
|
|
16759
|
+
if (BRAND_JSON_PATH && existsSync23(BRAND_JSON_PATH)) {
|
|
16881
16760
|
try {
|
|
16882
|
-
const fullBrand = JSON.parse(
|
|
16761
|
+
const fullBrand = JSON.parse(readFileSync23(BRAND_JSON_PATH, "utf-8"));
|
|
16883
16762
|
if (fullBrand.assets?.logo) brandLogoPath = `/brand/${fullBrand.assets.logo}`;
|
|
16884
16763
|
brandIconPath = fullBrand.assets?.icon ? `/brand/${fullBrand.assets.icon}` : brandLogoPath;
|
|
16885
16764
|
} catch {
|
|
@@ -16896,9 +16775,9 @@ var brandScript = `<script>window.__BRAND__=${JSON.stringify({
|
|
|
16896
16775
|
function readInstalledVersion() {
|
|
16897
16776
|
try {
|
|
16898
16777
|
if (!PLATFORM_ROOT9) return "unknown";
|
|
16899
|
-
const versionFile =
|
|
16900
|
-
if (!
|
|
16901
|
-
const content =
|
|
16778
|
+
const versionFile = join18(PLATFORM_ROOT9, "config", `.${BRAND.hostname}-version`);
|
|
16779
|
+
if (!existsSync23(versionFile)) return "unknown";
|
|
16780
|
+
const content = readFileSync23(versionFile, "utf-8").trim();
|
|
16902
16781
|
return content || "unknown";
|
|
16903
16782
|
} catch {
|
|
16904
16783
|
return "unknown";
|
|
@@ -16939,7 +16818,7 @@ var clientErrorReporterScript = `<script>
|
|
|
16939
16818
|
function cachedHtml(file) {
|
|
16940
16819
|
let html = htmlCache.get(file);
|
|
16941
16820
|
if (!html) {
|
|
16942
|
-
html =
|
|
16821
|
+
html = readFileSync23(resolve26(process.cwd(), "public", file), "utf-8");
|
|
16943
16822
|
const productNameEsc = escapeHtml(BRAND.productName);
|
|
16944
16823
|
html = html.replace(/<title>([^<]*)<\/title>/, (_match, inner) => `<title>${escapeHtml(inner).replace(/Maxy/g, productNameEsc)}</title>`);
|
|
16945
16824
|
html = html.replace('href="/favicon.ico"', `href="${escapeHtml(brandFaviconPath)}"`);
|
|
@@ -16955,13 +16834,13 @@ ${clientErrorReporterScript}
|
|
|
16955
16834
|
}
|
|
16956
16835
|
var brandedHtmlCache = /* @__PURE__ */ new Map();
|
|
16957
16836
|
function loadBrandingCache(agentSlug) {
|
|
16958
|
-
const configDir2 =
|
|
16837
|
+
const configDir2 = join18(homedir2(), BRAND.configDir);
|
|
16959
16838
|
try {
|
|
16960
16839
|
const accountId = getDefaultAccountId();
|
|
16961
16840
|
if (!accountId) return null;
|
|
16962
|
-
const cachePath =
|
|
16963
|
-
if (!
|
|
16964
|
-
return JSON.parse(
|
|
16841
|
+
const cachePath = join18(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
|
|
16842
|
+
if (!existsSync23(cachePath)) return null;
|
|
16843
|
+
return JSON.parse(readFileSync23(cachePath, "utf-8"));
|
|
16965
16844
|
} catch {
|
|
16966
16845
|
return null;
|
|
16967
16846
|
}
|
|
@@ -17004,7 +16883,7 @@ function escapeHtml(s) {
|
|
|
17004
16883
|
function agentUnavailableHtml() {
|
|
17005
16884
|
return `<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>${escapeHtml(BRAND.productName)}</title></head><body style="font-family:system-ui,sans-serif;max-width:32rem;margin:4rem auto;padding:0 1.5rem;color:#222"><h1 style="font-size:1.25rem">Agent unavailable</h1><p>This agent isn't available right now. If you reached this page from a saved link, the agent may have been turned off.</p></body></html>`;
|
|
17006
16885
|
}
|
|
17007
|
-
|
|
16886
|
+
app45.get("/", (c) => {
|
|
17008
16887
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
17009
16888
|
if (isPublicHost(host)) {
|
|
17010
16889
|
const defaultSlug = resolveDefaultSlug();
|
|
@@ -17020,12 +16899,12 @@ app44.get("/", (c) => {
|
|
|
17020
16899
|
}
|
|
17021
16900
|
return c.html(cachedHtml("index.html"));
|
|
17022
16901
|
});
|
|
17023
|
-
|
|
16902
|
+
app45.get("/public", (c) => {
|
|
17024
16903
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
17025
16904
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
17026
16905
|
return c.html(cachedHtml("public.html"));
|
|
17027
16906
|
});
|
|
17028
|
-
|
|
16907
|
+
app45.get("/chat", (c) => {
|
|
17029
16908
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
17030
16909
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
17031
16910
|
return c.html(cachedHtml("public.html"));
|
|
@@ -17044,12 +16923,12 @@ async function logViewerFetch(c, next) {
|
|
|
17044
16923
|
duration_ms: Date.now() - start
|
|
17045
16924
|
});
|
|
17046
16925
|
}
|
|
17047
|
-
|
|
17048
|
-
|
|
17049
|
-
|
|
16926
|
+
app45.use("/vnc-viewer.html", logViewerFetch);
|
|
16927
|
+
app45.use("/vnc-popout.html", logViewerFetch);
|
|
16928
|
+
app45.get("/vnc-popout.html", (c) => {
|
|
17050
16929
|
let html = htmlCache.get("vnc-popout.html");
|
|
17051
16930
|
if (!html) {
|
|
17052
|
-
html =
|
|
16931
|
+
html = readFileSync23(resolve26(process.cwd(), "public", "vnc-popout.html"), "utf-8");
|
|
17053
16932
|
const name = escapeHtml(BRAND.productName);
|
|
17054
16933
|
html = html.replace("<title>Browser \u2014 Maxy</title>", `<title>${name}</title>`);
|
|
17055
16934
|
html = html.replace("</head>", ` ${brandScript}
|
|
@@ -17059,7 +16938,7 @@ app44.get("/vnc-popout.html", (c) => {
|
|
|
17059
16938
|
}
|
|
17060
16939
|
return c.html(html);
|
|
17061
16940
|
});
|
|
17062
|
-
|
|
16941
|
+
app45.post("/api/vnc/client-event", async (c) => {
|
|
17063
16942
|
let body;
|
|
17064
16943
|
try {
|
|
17065
16944
|
body = await c.req.json();
|
|
@@ -17080,30 +16959,30 @@ app44.post("/api/vnc/client-event", async (c) => {
|
|
|
17080
16959
|
});
|
|
17081
16960
|
return c.json({ ok: true });
|
|
17082
16961
|
});
|
|
17083
|
-
|
|
16962
|
+
app45.get("/g/:slug", (c) => {
|
|
17084
16963
|
return c.html(brandedPublicHtml());
|
|
17085
16964
|
});
|
|
17086
|
-
|
|
16965
|
+
app45.get("/graph", (c) => {
|
|
17087
16966
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
17088
16967
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
17089
16968
|
return c.html(cachedHtml("graph.html"));
|
|
17090
16969
|
});
|
|
17091
|
-
|
|
16970
|
+
app45.get("/sessions", (c) => {
|
|
17092
16971
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
17093
16972
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
17094
16973
|
return c.html(cachedHtml("sessions.html"));
|
|
17095
16974
|
});
|
|
17096
|
-
|
|
16975
|
+
app45.get("/data", (c) => {
|
|
17097
16976
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
17098
16977
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
17099
16978
|
return c.html(cachedHtml("data.html"));
|
|
17100
16979
|
});
|
|
17101
|
-
|
|
16980
|
+
app45.get("/browser", (c) => {
|
|
17102
16981
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
17103
16982
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
17104
16983
|
return c.html(cachedHtml("browser.html"));
|
|
17105
16984
|
});
|
|
17106
|
-
|
|
16985
|
+
app45.get("/:slug", async (c, next) => {
|
|
17107
16986
|
const slug = c.req.param("slug");
|
|
17108
16987
|
if (AGENT_SLUG_PATTERN.test(`/${slug}`)) {
|
|
17109
16988
|
const account = resolveAccount();
|
|
@@ -17118,13 +16997,13 @@ app44.get("/:slug", async (c, next) => {
|
|
|
17118
16997
|
await next();
|
|
17119
16998
|
});
|
|
17120
16999
|
if (brandFaviconPath !== "/favicon.ico") {
|
|
17121
|
-
|
|
17000
|
+
app45.get("/favicon.ico", (c) => {
|
|
17122
17001
|
c.header("Cache-Control", "public, max-age=300");
|
|
17123
17002
|
return c.redirect(brandFaviconPath, 302);
|
|
17124
17003
|
});
|
|
17125
17004
|
}
|
|
17126
|
-
|
|
17127
|
-
|
|
17005
|
+
app45.use("/*", serveStatic({ root: "./public" }));
|
|
17006
|
+
app45.all("*", (c) => {
|
|
17128
17007
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
17129
17008
|
const path2 = c.req.path;
|
|
17130
17009
|
if (isPublicHost(host)) {
|
|
@@ -17138,7 +17017,7 @@ app44.all("*", (c) => {
|
|
|
17138
17017
|
});
|
|
17139
17018
|
var port = requirePortEnv("MAXY_UI_INTERNAL_PORT", { tag: "ui-server" });
|
|
17140
17019
|
var hostname = process.env.HOSTNAME ?? "127.0.0.1";
|
|
17141
|
-
var httpServer = serve({ fetch:
|
|
17020
|
+
var httpServer = serve({ fetch: app45.fetch, port, hostname });
|
|
17142
17021
|
console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
17143
17022
|
startAuthHealthHeartbeat();
|
|
17144
17023
|
{
|
|
@@ -17176,7 +17055,7 @@ for (const m of SUBAPP_MANIFEST) {
|
|
|
17176
17055
|
}
|
|
17177
17056
|
try {
|
|
17178
17057
|
const registered = [];
|
|
17179
|
-
for (const r of
|
|
17058
|
+
for (const r of app45.routes ?? []) {
|
|
17180
17059
|
if (typeof r.path !== "string" || r.path.includes(":") || r.path.includes("*")) continue;
|
|
17181
17060
|
if (AGENT_SLUG_PATTERN.test(r.path)) {
|
|
17182
17061
|
registered.push({ method: (r.method ?? "ALL").toUpperCase(), path: r.path });
|
|
@@ -17204,11 +17083,11 @@ try {
|
|
|
17204
17083
|
var ADMINUSER_RECONCILE_INTERVAL_MS = 60 * 60 * 1e3;
|
|
17205
17084
|
async function runAdminUserReconcileTick() {
|
|
17206
17085
|
try {
|
|
17207
|
-
if (!
|
|
17086
|
+
if (!existsSync23(USERS_FILE)) {
|
|
17208
17087
|
console.error("[adminuser-self-heal] skip reason=no-users-file");
|
|
17209
17088
|
return;
|
|
17210
17089
|
}
|
|
17211
|
-
const usersRaw =
|
|
17090
|
+
const usersRaw = readFileSync23(USERS_FILE, "utf-8").trim();
|
|
17212
17091
|
if (!usersRaw) {
|
|
17213
17092
|
console.error("[adminuser-self-heal] skip reason=empty-users-file");
|
|
17214
17093
|
return;
|
|
@@ -17315,7 +17194,7 @@ if (bootAccountConfig?.whatsapp) {
|
|
|
17315
17194
|
}
|
|
17316
17195
|
init({
|
|
17317
17196
|
configDir: configDirForWhatsApp,
|
|
17318
|
-
platformRoot:
|
|
17197
|
+
platformRoot: resolve26(process.env.MAXY_PLATFORM_ROOT ?? join18(__dirname, "..")),
|
|
17319
17198
|
accountConfig: bootAccountConfig,
|
|
17320
17199
|
onMessage: async (msg) => {
|
|
17321
17200
|
if (msg.isOwnerMirror) {
|
|
@@ -17326,9 +17205,9 @@ init({
|
|
|
17326
17205
|
console.error(`[whatsapp:route] dropped reason=non-admin-sender senderId=${msg.senderPhone} agentType=${msg.agentType}`);
|
|
17327
17206
|
return;
|
|
17328
17207
|
}
|
|
17329
|
-
const hasFileMedia =
|
|
17208
|
+
const hasFileMedia = msg.media.some((m) => m.type !== "audio");
|
|
17330
17209
|
if (!msg.text && !hasFileMedia) {
|
|
17331
|
-
console.error(`[whatsapp:route] dropped reason=no-text-no-media senderId=${msg.senderPhone}
|
|
17210
|
+
console.error(`[whatsapp:route] dropped reason=no-text-no-media senderId=${msg.senderPhone} mediaCount=${msg.media.length}`);
|
|
17332
17211
|
return;
|
|
17333
17212
|
}
|
|
17334
17213
|
try {
|
|
@@ -17339,9 +17218,7 @@ init({
|
|
|
17339
17218
|
senderId: msg.senderPhone,
|
|
17340
17219
|
text: msg.text,
|
|
17341
17220
|
reply: msg.reply,
|
|
17342
|
-
|
|
17343
|
-
mediaType: msg.mediaType,
|
|
17344
|
-
mediaMimetype: msg.mediaMimetype
|
|
17221
|
+
media: msg.media
|
|
17345
17222
|
});
|
|
17346
17223
|
} catch (err) {
|
|
17347
17224
|
console.error(
|