@rubytech/create-realagent 1.0.678 → 1.0.681
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +232 -39
- package/package.json +1 -1
- package/payload/platform/lib/graph-mcp/dist/__tests__/cypher-validate.test.d.ts +2 -0
- package/payload/platform/lib/graph-mcp/dist/__tests__/cypher-validate.test.d.ts.map +1 -0
- package/payload/platform/lib/graph-mcp/dist/__tests__/cypher-validate.test.js +112 -0
- package/payload/platform/lib/graph-mcp/dist/__tests__/cypher-validate.test.js.map +1 -0
- package/payload/platform/lib/graph-mcp/dist/__tests__/schema-cache.test.d.ts +2 -0
- package/payload/platform/lib/graph-mcp/dist/__tests__/schema-cache.test.d.ts.map +1 -0
- package/payload/platform/lib/graph-mcp/dist/__tests__/schema-cache.test.js +163 -0
- package/payload/platform/lib/graph-mcp/dist/__tests__/schema-cache.test.js.map +1 -0
- package/payload/platform/lib/graph-mcp/dist/cypher-validate.d.ts +38 -0
- package/payload/platform/lib/graph-mcp/dist/cypher-validate.d.ts.map +1 -0
- package/payload/platform/lib/graph-mcp/dist/cypher-validate.js +130 -0
- package/payload/platform/lib/graph-mcp/dist/cypher-validate.js.map +1 -0
- package/payload/platform/lib/graph-mcp/dist/index.js +201 -45
- package/payload/platform/lib/graph-mcp/dist/index.js.map +1 -1
- package/payload/platform/lib/graph-mcp/dist/schema-cache.d.ts +78 -0
- package/payload/platform/lib/graph-mcp/dist/schema-cache.d.ts.map +1 -0
- package/payload/platform/lib/graph-mcp/dist/schema-cache.js +194 -0
- package/payload/platform/lib/graph-mcp/dist/schema-cache.js.map +1 -0
- package/payload/platform/lib/graph-mcp/src/__tests__/cypher-validate.test.ts +141 -0
- package/payload/platform/lib/graph-mcp/src/__tests__/schema-cache.test.ts +169 -0
- package/payload/platform/lib/graph-mcp/src/cypher-validate.ts +157 -0
- package/payload/platform/lib/graph-mcp/src/index.ts +247 -47
- package/payload/platform/lib/graph-mcp/src/schema-cache.ts +212 -0
- package/payload/platform/lib/graph-trash/dist/index.d.ts +8 -0
- package/payload/platform/lib/graph-trash/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/graph-trash/dist/index.js +109 -14
- package/payload/platform/lib/graph-trash/dist/index.js.map +1 -1
- package/payload/platform/lib/graph-trash/src/index.ts +136 -21
- package/payload/platform/plugins/docs/references/deployment.md +4 -2
- package/payload/platform/plugins/docs/references/memory-guide.md +5 -1
- package/payload/platform/plugins/docs/references/platform.md +1 -1
- package/payload/platform/plugins/docs/references/troubleshooting.md +20 -0
- package/payload/platform/plugins/memory/PLUGIN.md +1 -0
- package/payload/platform/plugins/memory/mcp/dist/index.js +54 -6
- package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/filter-token.d.ts +36 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/filter-token.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/filter-token.js +86 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/filter-token.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-delete.d.ts +23 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-delete.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-delete.js +47 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-delete.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-find-candidates.d.ts +58 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-find-candidates.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-find-candidates.js +125 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-find-candidates.js.map +1 -0
- package/payload/platform/scripts/vnc.sh +12 -409
- package/payload/platform/templates/agents/admin/IDENTITY.md +16 -0
- package/payload/platform/templates/dotfiles/.tmux.conf +1 -0
- package/payload/platform/templates/systemd/maxy-ttyd.service +25 -0
- package/payload/server/chunk-3RBKKDHC.js +783 -0
- package/payload/server/maxy-edge.js +377 -8
- package/payload/server/public/assets/admin-CIkyOur7.js +362 -0
- package/payload/server/public/assets/admin-kHJ-D0s7.css +1 -0
- package/payload/server/public/index.html +2 -1
- package/payload/server/server.js +391 -412
- package/payload/server/public/assets/admin-BBL1no_g.js +0 -352
package/payload/server/server.js
CHANGED
|
@@ -13,7 +13,6 @@ import {
|
|
|
13
13
|
clearRateLimit,
|
|
14
14
|
createRemoteSession,
|
|
15
15
|
hashPassword,
|
|
16
|
-
invalidateRemoteSession,
|
|
17
16
|
isPasswordValid,
|
|
18
17
|
isRemoteAuthConfigured,
|
|
19
18
|
recordFailedAttempt,
|
|
@@ -25,7 +24,7 @@ import {
|
|
|
25
24
|
verifyPassword,
|
|
26
25
|
verifyRemotePassword,
|
|
27
26
|
vncLog
|
|
28
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-3RBKKDHC.js";
|
|
29
28
|
|
|
30
29
|
// ../lib/models/dist/index.js
|
|
31
30
|
var require_dist = __commonJS({
|
|
@@ -1204,14 +1203,14 @@ var Hono = class _Hono {
|
|
|
1204
1203
|
* app.route("/api", app2) // GET /api/user
|
|
1205
1204
|
* ```
|
|
1206
1205
|
*/
|
|
1207
|
-
route(path2,
|
|
1206
|
+
route(path2, app35) {
|
|
1208
1207
|
const subApp = this.basePath(path2);
|
|
1209
|
-
|
|
1208
|
+
app35.routes.map((r) => {
|
|
1210
1209
|
let handler;
|
|
1211
|
-
if (
|
|
1210
|
+
if (app35.errorHandler === errorHandler) {
|
|
1212
1211
|
handler = r.handler;
|
|
1213
1212
|
} else {
|
|
1214
|
-
handler = async (c, next) => (await compose([],
|
|
1213
|
+
handler = async (c, next) => (await compose([], app35.errorHandler)(c, () => r.handler(c, next))).res;
|
|
1215
1214
|
handler[COMPOSED_HANDLER] = r.handler;
|
|
1216
1215
|
}
|
|
1217
1216
|
subApp.#addRoute(r.method, r.path, handler);
|
|
@@ -2895,7 +2894,7 @@ var serveStatic = (options = { root: "" }) => {
|
|
|
2895
2894
|
};
|
|
2896
2895
|
|
|
2897
2896
|
// server/index.ts
|
|
2898
|
-
import { readFileSync as
|
|
2897
|
+
import { readFileSync as readFileSync25, existsSync as existsSync23, watchFile } from "fs";
|
|
2899
2898
|
import { resolve as resolve27, join as join12, basename as basename7 } from "path";
|
|
2900
2899
|
import { homedir as homedir4 } from "os";
|
|
2901
2900
|
|
|
@@ -2908,7 +2907,7 @@ import { spawn as spawn2, spawnSync as spawnSync2 } from "child_process";
|
|
|
2908
2907
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
2909
2908
|
import { resolve as resolve5, join as join3 } from "path";
|
|
2910
2909
|
import { platform as osPlatform } from "os";
|
|
2911
|
-
import { readFileSync as
|
|
2910
|
+
import { readFileSync as readFileSync7, writeFileSync as writeFileSync5, readdirSync as readdirSync2, existsSync as existsSync5, mkdirSync as mkdirSync4, createWriteStream, statSync as statSync3, unlinkSync as unlinkSync3, cpSync, rmSync as rmSync2, appendFileSync, openSync as openSync2, readSync as readSync2, closeSync as closeSync2 } from "fs";
|
|
2912
2911
|
import { lookup as dnsLookup } from "dns/promises";
|
|
2913
2912
|
import { createConnection as netConnect } from "net";
|
|
2914
2913
|
import { StringDecoder } from "string_decoder";
|
|
@@ -3265,7 +3264,6 @@ function resolveBrowserTransport(req, remoteAddress) {
|
|
|
3265
3264
|
return transport;
|
|
3266
3265
|
}
|
|
3267
3266
|
var currentCdpDisplay = null;
|
|
3268
|
-
var currentTerminalDisplay = null;
|
|
3269
3267
|
function discoverNativeDisplay() {
|
|
3270
3268
|
const fallback = { sessionType: "x11", display: ":0", waylandDisplay: "" };
|
|
3271
3269
|
try {
|
|
@@ -3436,137 +3434,6 @@ async function ensureCdp(transport = "vnc") {
|
|
|
3436
3434
|
function killChromium() {
|
|
3437
3435
|
spawnSync("pkill", ["-f", "chromium"], { stdio: "pipe" });
|
|
3438
3436
|
}
|
|
3439
|
-
function terminalAlive() {
|
|
3440
|
-
const result = spawnSync("bash", [VNC_SCRIPT, "status-terminal"], {
|
|
3441
|
-
stdio: "pipe",
|
|
3442
|
-
timeout: 2e3
|
|
3443
|
-
});
|
|
3444
|
-
return result.status === 0;
|
|
3445
|
-
}
|
|
3446
|
-
function extractFailureLine(stderr, signal) {
|
|
3447
|
-
if (signal === "SIGTERM") {
|
|
3448
|
-
return '[terminal-launch] failed err="vnc.sh timed out after 10s \u2014 X server on :99 may be wedged (check Xtigervnc + websockify in vnc-boot.log)"';
|
|
3449
|
-
}
|
|
3450
|
-
const raw2 = (stderr ?? "").trim();
|
|
3451
|
-
if (!raw2) return "Terminal failed to start (no diagnostic captured)";
|
|
3452
|
-
const lines = raw2.split("\n").filter((l) => l.trim().length > 0);
|
|
3453
|
-
const lastFailed = [...lines].reverse().find((l) => l.includes("[terminal-launch] failed"));
|
|
3454
|
-
return (lastFailed ?? lines[lines.length - 1]).trim();
|
|
3455
|
-
}
|
|
3456
|
-
async function ensureTerminal(transport = "vnc") {
|
|
3457
|
-
const targetSentinel = transport === "native" ? "native" : ":99";
|
|
3458
|
-
if (terminalAlive()) {
|
|
3459
|
-
if (currentTerminalDisplay !== null && currentTerminalDisplay !== targetSentinel) {
|
|
3460
|
-
console.error(`[ensureTerminal] Display switch: ${currentTerminalDisplay} \u2192 ${targetSentinel}`);
|
|
3461
|
-
vncLog("ensure-terminal", {
|
|
3462
|
-
action: "display-switch",
|
|
3463
|
-
transport,
|
|
3464
|
-
from_display: currentTerminalDisplay,
|
|
3465
|
-
to_display: targetSentinel
|
|
3466
|
-
});
|
|
3467
|
-
killTerminal();
|
|
3468
|
-
await sleep(500);
|
|
3469
|
-
} else {
|
|
3470
|
-
if (currentTerminalDisplay === null) {
|
|
3471
|
-
currentTerminalDisplay = targetSentinel;
|
|
3472
|
-
}
|
|
3473
|
-
const check = spawnSync("bash", [VNC_SCRIPT, transport === "native" ? "start-terminal-native" : "start-terminal"], {
|
|
3474
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
3475
|
-
timeout: 1e4
|
|
3476
|
-
});
|
|
3477
|
-
if (check.status !== 0) {
|
|
3478
|
-
const errorLine = extractFailureLine(check.stderr?.toString(), check.signal);
|
|
3479
|
-
vncLog("ensure-terminal", { action: "already-running-self-heal-failed", transport, windowPresent: false, err: errorLine });
|
|
3480
|
-
return { ok: false, error: errorLine };
|
|
3481
|
-
}
|
|
3482
|
-
vncLog("ensure-terminal", { action: "already-running", transport, windowPresent: true });
|
|
3483
|
-
return { ok: true };
|
|
3484
|
-
}
|
|
3485
|
-
}
|
|
3486
|
-
const vncCommand = transport === "native" ? "start-terminal-native" : "start-terminal";
|
|
3487
|
-
if (transport === "vnc") {
|
|
3488
|
-
const xAlive = await waitForPort(5900, 1e3);
|
|
3489
|
-
if (!xAlive) {
|
|
3490
|
-
console.error("[ensureTerminal] X server down on :5900 \u2014 escalating to full VNC restart");
|
|
3491
|
-
vncLog("ensure-terminal", { action: "escalate-vnc-restart", reason: "x-down", transport });
|
|
3492
|
-
const vncOk = await ensureVnc();
|
|
3493
|
-
if (!vncOk) {
|
|
3494
|
-
console.error("[ensureTerminal] Full VNC restart failed \u2014 terminal degraded");
|
|
3495
|
-
vncLog("ensure-terminal", { action: "degraded", reason: "vnc-restart-failed", transport });
|
|
3496
|
-
return { ok: false, error: "VNC failed to start after recovery attempt" };
|
|
3497
|
-
}
|
|
3498
|
-
}
|
|
3499
|
-
}
|
|
3500
|
-
if (transport === "native") {
|
|
3501
|
-
const nativeInfo = discoverNativeDisplay();
|
|
3502
|
-
vncLog("ensure-terminal", {
|
|
3503
|
-
action: "native-display-resolved",
|
|
3504
|
-
transport,
|
|
3505
|
-
session_type: nativeInfo.sessionType,
|
|
3506
|
-
display: nativeInfo.display
|
|
3507
|
-
});
|
|
3508
|
-
}
|
|
3509
|
-
console.error(`[ensureTerminal] Launching terminal (${vncCommand}) for transport=${transport}`);
|
|
3510
|
-
vncLog("ensure-terminal", { action: `launch-${vncCommand}`, transport });
|
|
3511
|
-
const result = spawnSync("bash", [VNC_SCRIPT, vncCommand], {
|
|
3512
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
3513
|
-
timeout: 1e4
|
|
3514
|
-
});
|
|
3515
|
-
if (result.status !== 0) {
|
|
3516
|
-
const errorLine = extractFailureLine(result.stderr?.toString(), result.signal);
|
|
3517
|
-
vncLog("ensure-terminal", { action: "launch-failed", transport, windowPresent: false, err: errorLine });
|
|
3518
|
-
return { ok: false, error: errorLine };
|
|
3519
|
-
}
|
|
3520
|
-
currentTerminalDisplay = targetSentinel;
|
|
3521
|
-
vncLog("ensure-terminal", { action: "launch-complete", transport, sentinel: targetSentinel, windowPresent: true });
|
|
3522
|
-
return { ok: true };
|
|
3523
|
-
}
|
|
3524
|
-
function killTerminal() {
|
|
3525
|
-
spawnSync("bash", [VNC_SCRIPT, "kill-terminal"], { stdio: "pipe", timeout: 5e3 });
|
|
3526
|
-
currentTerminalDisplay = null;
|
|
3527
|
-
}
|
|
3528
|
-
async function ensureTerminalUpgrade(transport = "vnc") {
|
|
3529
|
-
const targetSentinel = ":99";
|
|
3530
|
-
vncLog("ensure-terminal", {
|
|
3531
|
-
action: "launch-upgrade",
|
|
3532
|
-
transport,
|
|
3533
|
-
cmd: "npx -y @rubytech/create-maxy@latest"
|
|
3534
|
-
});
|
|
3535
|
-
killTerminal();
|
|
3536
|
-
await sleep(500);
|
|
3537
|
-
if (transport === "vnc") {
|
|
3538
|
-
const xAlive = await waitForPort(5900, 1e3);
|
|
3539
|
-
if (!xAlive) {
|
|
3540
|
-
console.error("[ensureTerminalUpgrade] X server down on :5900 \u2014 escalating to full VNC restart");
|
|
3541
|
-
vncLog("ensure-terminal", { action: "escalate-vnc-restart", reason: "x-down", transport, upgrade: true });
|
|
3542
|
-
const vncOk = await ensureVnc();
|
|
3543
|
-
if (!vncOk) {
|
|
3544
|
-
console.error("[ensureTerminalUpgrade] Full VNC restart failed \u2014 upgrade degraded");
|
|
3545
|
-
vncLog("ensure-terminal", { action: "launch-upgrade-failed", transport, windowPresent: false, err: "VNC failed to start after recovery attempt" });
|
|
3546
|
-
return { ok: false, error: "VNC failed to start after recovery attempt" };
|
|
3547
|
-
}
|
|
3548
|
-
}
|
|
3549
|
-
}
|
|
3550
|
-
console.error(`[ensureTerminalUpgrade] Launching upgrade terminal transport=${transport}`);
|
|
3551
|
-
const result = spawnSync("bash", [VNC_SCRIPT, "start-terminal-upgrade"], {
|
|
3552
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
3553
|
-
timeout: 1e4
|
|
3554
|
-
});
|
|
3555
|
-
if (result.status !== 0) {
|
|
3556
|
-
const errorLine = extractFailureLine(result.stderr?.toString(), result.signal);
|
|
3557
|
-
vncLog("ensure-terminal", { action: "launch-upgrade-failed", transport, windowPresent: false, err: errorLine });
|
|
3558
|
-
return { ok: false, error: errorLine };
|
|
3559
|
-
}
|
|
3560
|
-
currentTerminalDisplay = targetSentinel;
|
|
3561
|
-
vncLog("ensure-terminal", {
|
|
3562
|
-
action: "launch-upgrade-complete",
|
|
3563
|
-
transport,
|
|
3564
|
-
sentinel: targetSentinel,
|
|
3565
|
-
windowPresent: true,
|
|
3566
|
-
cmd: "npx -y @rubytech/create-maxy@latest"
|
|
3567
|
-
});
|
|
3568
|
-
return { ok: true };
|
|
3569
|
-
}
|
|
3570
3437
|
function writeChromiumWrapper() {
|
|
3571
3438
|
mkdirSync2(BIN_DIR, { recursive: true });
|
|
3572
3439
|
const wrapperPath = resolve2(BIN_DIR, "chromium");
|
|
@@ -5803,6 +5670,101 @@ async function criticAndRecord(opts) {
|
|
|
5803
5670
|
}
|
|
5804
5671
|
}
|
|
5805
5672
|
|
|
5673
|
+
// app/lib/admin-schema-block.ts
|
|
5674
|
+
import { readFileSync as readFileSync6 } from "fs";
|
|
5675
|
+
var EDGE_TAXONOMY = [
|
|
5676
|
+
{ type: "PART_OF", direction: "(Message)-[:PART_OF]->(Conversation)", note: "Messages belong to exactly one Conversation. Do NOT use :HAS_MESSAGE \u2014 that edge does not exist." },
|
|
5677
|
+
{ type: "NEXT", direction: "(Message)-[:NEXT]->(Message)", note: "Chain order within a Conversation. Each Message has at most one NEXT successor." },
|
|
5678
|
+
{ type: "BELONGS_TO", direction: "(Conversation|Task|...)-[:BELONGS_TO]->(LocalBusiness)", note: "Account scope. Universal \u2014 almost every tenant-owned node has one." },
|
|
5679
|
+
{ type: "ADMIN_OF", direction: "(AdminUser)-[:ADMIN_OF]->(LocalBusiness)", note: "Device-level admin membership (see admin-add / admin-remove)." },
|
|
5680
|
+
{ type: "AUTHORED_BY", direction: "(Message)-[:AUTHORED_BY]->(Person)", note: "Message authorship (when the author is an identified Person)." },
|
|
5681
|
+
{ type: "HAS_TOOL_CALL", direction: "(Message)-[:HAS_TOOL_CALL]->(ToolCall)", note: "Tool calls attached to an assistant message." },
|
|
5682
|
+
{ type: "HAS_RESULT", direction: "(WorkflowStep|ToolCall)-[:HAS_RESULT]->(StepResult)", note: "Workflow step / tool-call outputs." },
|
|
5683
|
+
{ type: "HAS_STEP", direction: "(Workflow)-[:HAS_STEP]->(WorkflowStep)", note: "Workflow composition." },
|
|
5684
|
+
{ type: "RUN_OF", direction: "(WorkflowRun)-[:RUN_OF]->(Workflow)", note: "Workflow execution instance." },
|
|
5685
|
+
{ type: "HAS_SECTION", direction: "(KnowledgeDocument)-[:HAS_SECTION]->(Section)", note: "Document hierarchy." },
|
|
5686
|
+
{ type: "HAS_CHUNK", direction: "(Section)-[:HAS_CHUNK]->(Chunk)", note: "Section-to-embeddable-chunk." },
|
|
5687
|
+
{ type: "HAS_PREFERENCE", direction: "(Person)-[:HAS_PREFERENCE]->(Preference)", note: "Person-scoped preferences (profile memory)." },
|
|
5688
|
+
{ type: "HAS_ACCESS", direction: "(Person)-[:HAS_ACCESS]->(AccessGrant)", note: "Public agent access grants." },
|
|
5689
|
+
{ type: "HAS_TASK", direction: "(Person|LocalBusiness)-[:HAS_TASK]->(Task)", note: "Task ownership / assignment." },
|
|
5690
|
+
{ type: "HAS_PRICING", direction: "(Service)-[:HAS_PRICING]->(PriceSpecification)", note: "Service pricing." },
|
|
5691
|
+
{ type: "HAS_HOURS", direction: "(LocalBusiness)-[:HAS_HOURS]->(OpeningHoursSpecification)", note: "Opening hours." },
|
|
5692
|
+
{ type: "HAS_FAQ", direction: "(LocalBusiness)-[:HAS_FAQ]->(Question)", note: "FAQ attached to business." },
|
|
5693
|
+
{ type: "HAS_BRAND_ASSET", direction: "(LocalBusiness)-[:HAS_BRAND_ASSET]->(DigitalDocument|ImageObject)", note: "Branding assets." },
|
|
5694
|
+
{ type: "OFFERS", direction: "(LocalBusiness)-[:OFFERS]->(Service)", note: "Service catalogue." },
|
|
5695
|
+
{ type: "CONTAINS", direction: "(KnowledgeDocument)-[:CONTAINS]->(Chunk)", note: "Flat document-to-chunk (alternative to HAS_SECTION then HAS_CHUNK)." },
|
|
5696
|
+
{ type: "REFERENCES", direction: "(Message|KnowledgeDocument)-[:REFERENCES]->(*)", note: "Soft reference link." },
|
|
5697
|
+
{ type: "ABOUT", direction: "(Review|Message)-[:ABOUT]->(*)", note: "Subject pointer." },
|
|
5698
|
+
{ type: "REPLY_TO", direction: "(Email)-[:REPLY_TO]->(Email)", note: "Email threading." },
|
|
5699
|
+
{ type: "RECEIVED_BY", direction: "(Email)-[:RECEIVED_BY]->(Person)", note: "Email recipient." },
|
|
5700
|
+
{ type: "RAISED_BY", direction: "(ReviewAlert)-[:RAISED_BY]->(*)", note: "Alert provenance." },
|
|
5701
|
+
{ type: "AFFECTS", direction: "(ReviewAlert)-[:AFFECTS]->(*)", note: "Alert impact surface." },
|
|
5702
|
+
{ type: "BLOCKS", direction: "(Task)-[:BLOCKS]->(Task)", note: "Task dependency." },
|
|
5703
|
+
{ type: "OBSERVED_IN", direction: "(*)-[:OBSERVED_IN]->(Conversation)", note: "Observation provenance." }
|
|
5704
|
+
];
|
|
5705
|
+
var SUBLABELS = [
|
|
5706
|
+
{ base: "Conversation", sub: "AdminConversation", note: "Admin-only conversation (admin chat, not public)." },
|
|
5707
|
+
{ base: "Conversation", sub: "PublicConversation", note: "Public agent conversation (visitor-facing)." },
|
|
5708
|
+
{ base: "Message", sub: "UserMessage", note: "Message authored by the human user." },
|
|
5709
|
+
{ base: "Message", sub: "AssistantMessage", note: "Message authored by the assistant." }
|
|
5710
|
+
];
|
|
5711
|
+
var LABEL_PATTERN = /FOR\s*\(\s*\w+\s*:\s*(\w+)\s*\)/g;
|
|
5712
|
+
function parseLabelsFromSchemaCypher(schemaCypher) {
|
|
5713
|
+
const found = /* @__PURE__ */ new Set();
|
|
5714
|
+
for (const match2 of schemaCypher.matchAll(LABEL_PATTERN)) {
|
|
5715
|
+
found.add(match2[1]);
|
|
5716
|
+
}
|
|
5717
|
+
return [...found].sort();
|
|
5718
|
+
}
|
|
5719
|
+
function buildSchemaBlock(schemaCypherText) {
|
|
5720
|
+
const baseLabels = parseLabelsFromSchemaCypher(schemaCypherText);
|
|
5721
|
+
const sublabels = SUBLABELS.map((s) => s.sub);
|
|
5722
|
+
const lines = [];
|
|
5723
|
+
lines.push("# SCHEMA (Neo4j graph, canonical reference)");
|
|
5724
|
+
lines.push("");
|
|
5725
|
+
lines.push("The Neo4j instance backing this admin session contains exactly the labels and relationship types below. Never invent names outside this list. If you need cypher against a token not listed here, first invoke `maxy-graph-get_neo4j_schema` to confirm it exists \u2014 do not guess.");
|
|
5726
|
+
lines.push("");
|
|
5727
|
+
lines.push("## Labels (from platform/neo4j/schema.cypher)");
|
|
5728
|
+
lines.push("");
|
|
5729
|
+
for (const label of baseLabels) {
|
|
5730
|
+
lines.push(`- :${label}`);
|
|
5731
|
+
}
|
|
5732
|
+
lines.push("");
|
|
5733
|
+
lines.push("### Sublabels (Task 633 role-cue variants)");
|
|
5734
|
+
lines.push("");
|
|
5735
|
+
for (const s of SUBLABELS) {
|
|
5736
|
+
lines.push(`- :${s.sub} (on :${s.base}) \u2014 ${s.note}`);
|
|
5737
|
+
}
|
|
5738
|
+
lines.push("");
|
|
5739
|
+
lines.push("## Relationship types (from .docs/neo4j.md)");
|
|
5740
|
+
lines.push("");
|
|
5741
|
+
for (const e of EDGE_TAXONOMY) {
|
|
5742
|
+
lines.push(`- :${e.type} \u2014 ${e.direction} \u2014 ${e.note}`);
|
|
5743
|
+
}
|
|
5744
|
+
lines.push("");
|
|
5745
|
+
lines.push("The cypher MCP validator (graph-mcp proxy, Task 654) rejects write cypher that references unknown labels or edges and warns on read cypher. Stick to the taxonomy above; if you believe a token is missing, invoke `maxy-graph-get_neo4j_schema` for the live snapshot.");
|
|
5746
|
+
const text = lines.join("\n");
|
|
5747
|
+
return {
|
|
5748
|
+
text,
|
|
5749
|
+
labelCount: baseLabels.length + sublabels.length,
|
|
5750
|
+
relationshipTypeCount: EDGE_TAXONOMY.length,
|
|
5751
|
+
bytes: Buffer.byteLength(text, "utf-8")
|
|
5752
|
+
};
|
|
5753
|
+
}
|
|
5754
|
+
function loadAdminSchemaBlock(schemaCypherPath) {
|
|
5755
|
+
let text;
|
|
5756
|
+
try {
|
|
5757
|
+
text = readFileSync6(schemaCypherPath, "utf-8");
|
|
5758
|
+
} catch (err) {
|
|
5759
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
5760
|
+
console.error(
|
|
5761
|
+
`[admin-identity] schema.cypher unreadable path=${schemaCypherPath} error="${msg.replace(/"/g, "'")}" block=omitted`
|
|
5762
|
+
);
|
|
5763
|
+
return null;
|
|
5764
|
+
}
|
|
5765
|
+
return buildSchemaBlock(text);
|
|
5766
|
+
}
|
|
5767
|
+
|
|
5806
5768
|
// app/lib/claude-agent.ts
|
|
5807
5769
|
var LOG_RETENTION_DAYS = 7;
|
|
5808
5770
|
var BROWSER_TOOL_PREFIXES = [
|
|
@@ -6063,7 +6025,7 @@ function sampleProcState(pid) {
|
|
|
6063
6025
|
let sockets2 = 0;
|
|
6064
6026
|
for (const tcpFile of ["/proc/" + pid + "/net/tcp", "/proc/" + pid + "/net/tcp6"]) {
|
|
6065
6027
|
try {
|
|
6066
|
-
const raw2 =
|
|
6028
|
+
const raw2 = readFileSync7(tcpFile, "utf-8");
|
|
6067
6029
|
const lines2 = raw2.split("\n");
|
|
6068
6030
|
for (let i = 1; i < lines2.length; i++) {
|
|
6069
6031
|
const line = lines2[i].trim();
|
|
@@ -6079,7 +6041,7 @@ function sampleProcState(pid) {
|
|
|
6079
6041
|
}
|
|
6080
6042
|
let rssMb = 0;
|
|
6081
6043
|
try {
|
|
6082
|
-
const statm =
|
|
6044
|
+
const statm = readFileSync7(`/proc/${pid}/statm`, "utf-8").trim().split(/\s+/);
|
|
6083
6045
|
const rssPages = parseInt(statm[1] ?? "0", 10);
|
|
6084
6046
|
if (Number.isFinite(rssPages)) rssMb = Math.round(rssPages * 4096 / (1024 * 1024));
|
|
6085
6047
|
} catch {
|
|
@@ -6126,7 +6088,7 @@ function resolveAccount() {
|
|
|
6126
6088
|
let usersJsonUserId = null;
|
|
6127
6089
|
if (existsSync5(usersFilePath)) {
|
|
6128
6090
|
try {
|
|
6129
|
-
const raw2 =
|
|
6091
|
+
const raw2 = readFileSync7(usersFilePath, "utf-8").trim();
|
|
6130
6092
|
if (raw2) {
|
|
6131
6093
|
const users = JSON.parse(raw2);
|
|
6132
6094
|
if (users.length > 0) {
|
|
@@ -6142,7 +6104,7 @@ function resolveAccount() {
|
|
|
6142
6104
|
if (!entry.isDirectory()) continue;
|
|
6143
6105
|
const configPath2 = resolve5(ACCOUNTS_DIR, entry.name, "account.json");
|
|
6144
6106
|
if (!existsSync5(configPath2)) continue;
|
|
6145
|
-
const raw2 =
|
|
6107
|
+
const raw2 = readFileSync7(configPath2, "utf-8");
|
|
6146
6108
|
let config;
|
|
6147
6109
|
try {
|
|
6148
6110
|
config = JSON.parse(raw2);
|
|
@@ -6177,7 +6139,7 @@ function resolveAccount() {
|
|
|
6177
6139
|
function readAgentFile(accountDir, agentName, filename) {
|
|
6178
6140
|
const filePath = resolve5(accountDir, "agents", agentName, filename);
|
|
6179
6141
|
if (!existsSync5(filePath)) return null;
|
|
6180
|
-
return
|
|
6142
|
+
return readFileSync7(filePath, "utf-8");
|
|
6181
6143
|
}
|
|
6182
6144
|
function readIdentity(accountDir, agentName) {
|
|
6183
6145
|
return readAgentFile(accountDir, agentName, "IDENTITY.md");
|
|
@@ -6219,7 +6181,7 @@ function resolveDefaultAgentSlug(accountDir) {
|
|
|
6219
6181
|
}
|
|
6220
6182
|
let config;
|
|
6221
6183
|
try {
|
|
6222
|
-
config = JSON.parse(
|
|
6184
|
+
config = JSON.parse(readFileSync7(configPath2, "utf-8"));
|
|
6223
6185
|
} catch (err) {
|
|
6224
6186
|
console.error("[agent-resolve] failed to read account.json:", err);
|
|
6225
6187
|
return null;
|
|
@@ -6310,14 +6272,14 @@ function resolveAgentConfig(accountDir, agentName) {
|
|
|
6310
6272
|
const knowledgeMtime = statSync3(knowledgePath).mtimeMs;
|
|
6311
6273
|
const summaryMtime = statSync3(summaryPath).mtimeMs;
|
|
6312
6274
|
if (summaryMtime >= knowledgeMtime) {
|
|
6313
|
-
knowledge =
|
|
6275
|
+
knowledge = readFileSync7(summaryPath, "utf-8");
|
|
6314
6276
|
} else {
|
|
6315
6277
|
console.warn(`[agent-config] ${agentName}: KNOWLEDGE-SUMMARY.md is stale (KNOWLEDGE.md is newer) \u2014 using full knowledge`);
|
|
6316
|
-
knowledge =
|
|
6278
|
+
knowledge = readFileSync7(knowledgePath, "utf-8");
|
|
6317
6279
|
}
|
|
6318
6280
|
knowledgeBaked = true;
|
|
6319
6281
|
} else if (hasKnowledge) {
|
|
6320
|
-
knowledge =
|
|
6282
|
+
knowledge = readFileSync7(knowledgePath, "utf-8");
|
|
6321
6283
|
knowledgeBaked = true;
|
|
6322
6284
|
}
|
|
6323
6285
|
let budget = null;
|
|
@@ -6343,7 +6305,7 @@ function parsePluginFrontmatter(pluginDir) {
|
|
|
6343
6305
|
if (!existsSync5(pluginPath)) return null;
|
|
6344
6306
|
let raw2;
|
|
6345
6307
|
try {
|
|
6346
|
-
raw2 =
|
|
6308
|
+
raw2 = readFileSync7(pluginPath, "utf-8");
|
|
6347
6309
|
} catch {
|
|
6348
6310
|
console.warn(`[plugins] cannot read ${pluginPath}`);
|
|
6349
6311
|
return null;
|
|
@@ -6419,7 +6381,7 @@ function autoDeliverPremiumPlugins(purchasedPlugins) {
|
|
|
6419
6381
|
if (isBundle) {
|
|
6420
6382
|
let bundleRaw;
|
|
6421
6383
|
try {
|
|
6422
|
-
bundleRaw =
|
|
6384
|
+
bundleRaw = readFileSync7(bundlePath, "utf-8");
|
|
6423
6385
|
} catch (err) {
|
|
6424
6386
|
console.log(`${TAG19} ${pluginName}: cannot read BUNDLE.md \u2014 ${err instanceof Error ? err.message : String(err)}`);
|
|
6425
6387
|
continue;
|
|
@@ -6512,7 +6474,7 @@ function migratePluginRenames(accountDir, config) {
|
|
|
6512
6474
|
if (!changed) return;
|
|
6513
6475
|
const configPath2 = resolve5(accountDir, "account.json");
|
|
6514
6476
|
try {
|
|
6515
|
-
const raw2 =
|
|
6477
|
+
const raw2 = readFileSync7(configPath2, "utf-8");
|
|
6516
6478
|
const parsed = JSON.parse(raw2);
|
|
6517
6479
|
parsed.enabledPlugins = migrated;
|
|
6518
6480
|
writeFileSync5(configPath2, JSON.stringify(parsed, null, 2) + "\n");
|
|
@@ -6546,7 +6508,7 @@ function autoDeliverBundleAgents(accountDir, purchasedPlugins) {
|
|
|
6546
6508
|
const agentsmdPath = resolve5(accountDir, "agents", "admin", "AGENTS.md");
|
|
6547
6509
|
let agentsmd = "";
|
|
6548
6510
|
try {
|
|
6549
|
-
agentsmd = existsSync5(agentsmdPath) ?
|
|
6511
|
+
agentsmd = existsSync5(agentsmdPath) ? readFileSync7(agentsmdPath, "utf-8") : "";
|
|
6550
6512
|
} catch {
|
|
6551
6513
|
}
|
|
6552
6514
|
let delivered = 0;
|
|
@@ -6570,7 +6532,7 @@ function autoDeliverBundleAgents(accountDir, purchasedPlugins) {
|
|
|
6570
6532
|
continue;
|
|
6571
6533
|
}
|
|
6572
6534
|
try {
|
|
6573
|
-
const content =
|
|
6535
|
+
const content = readFileSync7(target, "utf-8");
|
|
6574
6536
|
const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
6575
6537
|
if (fmMatch) {
|
|
6576
6538
|
const nameMatch = fmMatch[1].match(/^name:\s*(.+)/m);
|
|
@@ -6606,7 +6568,7 @@ function assemblePublicPluginContent(pluginDir) {
|
|
|
6606
6568
|
const pluginPath = resolve5(pluginRoot, "PLUGIN.md");
|
|
6607
6569
|
let raw2;
|
|
6608
6570
|
try {
|
|
6609
|
-
raw2 =
|
|
6571
|
+
raw2 = readFileSync7(pluginPath, "utf-8");
|
|
6610
6572
|
} catch {
|
|
6611
6573
|
return null;
|
|
6612
6574
|
}
|
|
@@ -6627,7 +6589,7 @@ function assemblePublicPluginContent(pluginDir) {
|
|
|
6627
6589
|
const skillMdPath = resolve5(skillDir, "SKILL.md");
|
|
6628
6590
|
let skillRaw;
|
|
6629
6591
|
try {
|
|
6630
|
-
skillRaw =
|
|
6592
|
+
skillRaw = readFileSync7(skillMdPath, "utf-8");
|
|
6631
6593
|
} catch {
|
|
6632
6594
|
continue;
|
|
6633
6595
|
}
|
|
@@ -6678,7 +6640,7 @@ function assemblePublicPluginContent(pluginDir) {
|
|
|
6678
6640
|
}
|
|
6679
6641
|
for (const refFile of refFiles) {
|
|
6680
6642
|
try {
|
|
6681
|
-
const refContent =
|
|
6643
|
+
const refContent = readFileSync7(resolve5(refsDir, refFile), "utf-8").trim();
|
|
6682
6644
|
if (refContent) {
|
|
6683
6645
|
parts.push(`
|
|
6684
6646
|
<!-- reference: ${refFile} -->`);
|
|
@@ -6752,7 +6714,7 @@ function loadEmbeddedPlugins(agentType, selectedPlugins, enabledPlugins) {
|
|
|
6752
6714
|
const pluginPath = resolve5(pluginsDir, dir, "PLUGIN.md");
|
|
6753
6715
|
let raw2;
|
|
6754
6716
|
try {
|
|
6755
|
-
raw2 =
|
|
6717
|
+
raw2 = readFileSync7(pluginPath, "utf-8");
|
|
6756
6718
|
} catch (err) {
|
|
6757
6719
|
console.warn(`[plugins] ${dir}: failed to read PLUGIN.md for ${agentType} embed: ${String(err)}`);
|
|
6758
6720
|
continue;
|
|
@@ -7098,7 +7060,7 @@ function resolveUserAccounts(userId) {
|
|
|
7098
7060
|
if (!existsSync5(configPath2)) continue;
|
|
7099
7061
|
let config;
|
|
7100
7062
|
try {
|
|
7101
|
-
config = JSON.parse(
|
|
7063
|
+
config = JSON.parse(readFileSync7(configPath2, "utf-8"));
|
|
7102
7064
|
} catch {
|
|
7103
7065
|
console.error(`[session] account.json corrupt at ${configPath2} \u2014 skipping`);
|
|
7104
7066
|
continue;
|
|
@@ -7414,7 +7376,7 @@ function readBrandHostname() {
|
|
|
7414
7376
|
if (cachedBrandHostname !== null) return cachedBrandHostname;
|
|
7415
7377
|
try {
|
|
7416
7378
|
const brandPath = resolve5(PLATFORM_ROOT3, "config", "brand.json");
|
|
7417
|
-
const parsed = JSON.parse(
|
|
7379
|
+
const parsed = JSON.parse(readFileSync7(brandPath, "utf-8"));
|
|
7418
7380
|
cachedBrandHostname = typeof parsed.hostname === "string" && parsed.hostname.length > 0 ? parsed.hostname : "maxy";
|
|
7419
7381
|
} catch {
|
|
7420
7382
|
cachedBrandHostname = "maxy";
|
|
@@ -10219,7 +10181,7 @@ ${sessionContext}`;
|
|
|
10219
10181
|
const skillPath = resolve5(PLATFORM_ROOT3, "plugins/admin/skills/onboarding/SKILL.md");
|
|
10220
10182
|
let skillContent = "";
|
|
10221
10183
|
try {
|
|
10222
|
-
skillContent =
|
|
10184
|
+
skillContent = readFileSync7(skillPath, "utf-8");
|
|
10223
10185
|
} catch (err) {
|
|
10224
10186
|
console.error(`[onboarding-inject] accountId=${accountId.slice(0, 8)}\u2026 error=skill-read-failed path=${skillPath} reason=${err instanceof Error ? err.message : String(err)}`);
|
|
10225
10187
|
}
|
|
@@ -10271,13 +10233,23 @@ ${manifest}`;
|
|
|
10271
10233
|
}
|
|
10272
10234
|
const graphRefPath = resolve5(PLATFORM_ROOT3, "plugins/memory/references/graph-primitives.md");
|
|
10273
10235
|
try {
|
|
10274
|
-
const graphRef =
|
|
10236
|
+
const graphRef = readFileSync7(graphRefPath, "utf-8");
|
|
10275
10237
|
baseSystemPrompt += `
|
|
10276
10238
|
|
|
10277
10239
|
${graphRef}`;
|
|
10278
10240
|
} catch (err) {
|
|
10279
10241
|
console.error(`[graph-primitives] reference missing at ${graphRefPath} \u2014 admin session will have no Cypher cookbook: ${err instanceof Error ? err.message : String(err)}`);
|
|
10280
10242
|
}
|
|
10243
|
+
const schemaCypherPath = resolve5(PLATFORM_ROOT3, "neo4j/schema.cypher");
|
|
10244
|
+
const schemaBlock = loadAdminSchemaBlock(schemaCypherPath);
|
|
10245
|
+
if (schemaBlock) {
|
|
10246
|
+
baseSystemPrompt += `
|
|
10247
|
+
|
|
10248
|
+
${schemaBlock.text}`;
|
|
10249
|
+
console.log(
|
|
10250
|
+
`[admin-identity] schemaBlockBytes=${schemaBlock.bytes} labels=${schemaBlock.labelCount} relationshipTypes=${schemaBlock.relationshipTypeCount}`
|
|
10251
|
+
);
|
|
10252
|
+
}
|
|
10281
10253
|
}
|
|
10282
10254
|
if (agentConfig?.budget) {
|
|
10283
10255
|
const pluginTokens = embeddedPlugins.reduce((sum, p) => sum + estimateTokens(p.body), 0);
|
|
@@ -10486,7 +10458,7 @@ var clientIpMiddleware = async (c, next) => {
|
|
|
10486
10458
|
};
|
|
10487
10459
|
|
|
10488
10460
|
// server/routes/health.ts
|
|
10489
|
-
import { existsSync as existsSync10, readFileSync as
|
|
10461
|
+
import { existsSync as existsSync10, readFileSync as readFileSync12 } from "fs";
|
|
10490
10462
|
import { createConnection as createConnection2 } from "net";
|
|
10491
10463
|
|
|
10492
10464
|
// app/lib/network.ts
|
|
@@ -10511,7 +10483,7 @@ function getLanIp() {
|
|
|
10511
10483
|
import { basename as basename2 } from "path";
|
|
10512
10484
|
|
|
10513
10485
|
// app/lib/review-detector/rules.ts
|
|
10514
|
-
import { readFileSync as
|
|
10486
|
+
import { readFileSync as readFileSync8, writeFileSync as writeFileSync6, existsSync as existsSync6, statSync as statSync4, mkdirSync as mkdirSync5, renameSync as renameSync2 } from "fs";
|
|
10515
10487
|
import { resolve as resolve6, dirname as dirname3 } from "path";
|
|
10516
10488
|
var DEFAULT_SCAN_INTERVAL_MS = 5e3;
|
|
10517
10489
|
var RATE_LIMIT_PATTERN = "rate[- ]?limit(?:ed| reached| hit)|(?:HTTP|status)[^a-z]{0,3}429|too many requests";
|
|
@@ -10959,7 +10931,7 @@ function loadRules(configDir2) {
|
|
|
10959
10931
|
if (!existsSync6(path2)) {
|
|
10960
10932
|
throw new Error(`rules file missing at ${path2}`);
|
|
10961
10933
|
}
|
|
10962
|
-
const raw2 =
|
|
10934
|
+
const raw2 = readFileSync8(path2, "utf-8");
|
|
10963
10935
|
let parsed;
|
|
10964
10936
|
try {
|
|
10965
10937
|
parsed = JSON.parse(raw2);
|
|
@@ -11124,7 +11096,7 @@ function validateRule(input, label, seenIds) {
|
|
|
11124
11096
|
}
|
|
11125
11097
|
|
|
11126
11098
|
// app/lib/review-detector/sources.ts
|
|
11127
|
-
import { existsSync as existsSync7, readdirSync as readdirSync3, statSync as statSync5, writeFileSync as writeFileSync7, renameSync as renameSync3, mkdirSync as mkdirSync6, openSync as openSync3, readSync as readSync3, closeSync as closeSync3, readFileSync as
|
|
11099
|
+
import { existsSync as existsSync7, readdirSync as readdirSync3, statSync as statSync5, writeFileSync as writeFileSync7, renameSync as renameSync3, mkdirSync as mkdirSync6, openSync as openSync3, readSync as readSync3, closeSync as closeSync3, readFileSync as readFileSync9 } from "fs";
|
|
11128
11100
|
import { resolve as resolve7, join as join4, basename, dirname as dirname4 } from "path";
|
|
11129
11101
|
function tailStatePath(configDir2) {
|
|
11130
11102
|
return resolve7(configDir2, "review-state.json");
|
|
@@ -11133,7 +11105,7 @@ function loadTailState(configDir2) {
|
|
|
11133
11105
|
const path2 = tailStatePath(configDir2);
|
|
11134
11106
|
if (!existsSync7(path2)) return {};
|
|
11135
11107
|
try {
|
|
11136
|
-
const raw2 =
|
|
11108
|
+
const raw2 = readFileSync9(path2, "utf-8");
|
|
11137
11109
|
const parsed = JSON.parse(raw2);
|
|
11138
11110
|
if (!parsed || typeof parsed !== "object") return {};
|
|
11139
11111
|
const clean = {};
|
|
@@ -11303,7 +11275,7 @@ function sourceKey(file) {
|
|
|
11303
11275
|
}
|
|
11304
11276
|
|
|
11305
11277
|
// app/lib/review-detector/writer.ts
|
|
11306
|
-
import { appendFileSync as appendFileSync2, existsSync as existsSync8, mkdirSync as mkdirSync7, readFileSync as
|
|
11278
|
+
import { appendFileSync as appendFileSync2, existsSync as existsSync8, mkdirSync as mkdirSync7, readFileSync as readFileSync10, writeFileSync as writeFileSync8, renameSync as renameSync4, statSync as statSync6 } from "fs";
|
|
11307
11279
|
import { resolve as resolve8, dirname as dirname5 } from "path";
|
|
11308
11280
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
11309
11281
|
function reviewLogPath(configDir2) {
|
|
@@ -11442,7 +11414,7 @@ function queueAlert(configDir2, accountId, match2) {
|
|
|
11442
11414
|
async function drainPendingAlerts(configDir2) {
|
|
11443
11415
|
const path2 = pendingAlertsPath(configDir2);
|
|
11444
11416
|
if (!existsSync8(path2)) return { drained: 0, remaining: 0 };
|
|
11445
|
-
const raw2 =
|
|
11417
|
+
const raw2 = readFileSync10(path2, "utf-8");
|
|
11446
11418
|
const lines = raw2.split("\n").filter((l) => l.trim().length > 0);
|
|
11447
11419
|
if (lines.length === 0) return { drained: 0, remaining: 0 };
|
|
11448
11420
|
const remaining = [];
|
|
@@ -12105,7 +12077,7 @@ var WhatsAppConfigSchema = z.object({
|
|
|
12105
12077
|
});
|
|
12106
12078
|
|
|
12107
12079
|
// app/lib/whatsapp/config-persist.ts
|
|
12108
|
-
import { readFileSync as
|
|
12080
|
+
import { readFileSync as readFileSync11, writeFileSync as writeFileSync9, existsSync as existsSync9 } from "fs";
|
|
12109
12081
|
import { resolve as resolve10, join as join5 } from "path";
|
|
12110
12082
|
var TAG3 = "[whatsapp:config]";
|
|
12111
12083
|
function configPath(accountDir) {
|
|
@@ -12114,7 +12086,7 @@ function configPath(accountDir) {
|
|
|
12114
12086
|
function readConfig(accountDir) {
|
|
12115
12087
|
const path2 = configPath(accountDir);
|
|
12116
12088
|
if (!existsSync9(path2)) throw new Error(`account.json not found at ${path2}`);
|
|
12117
|
-
return JSON.parse(
|
|
12089
|
+
return JSON.parse(readFileSync11(path2, "utf-8"));
|
|
12118
12090
|
}
|
|
12119
12091
|
function writeConfig(accountDir, config) {
|
|
12120
12092
|
const path2 = configPath(accountDir);
|
|
@@ -14406,7 +14378,7 @@ app.get("/", async (c) => {
|
|
|
14406
14378
|
let pinConfigured = false;
|
|
14407
14379
|
try {
|
|
14408
14380
|
if (existsSync10(USERS_FILE)) {
|
|
14409
|
-
const raw2 =
|
|
14381
|
+
const raw2 = readFileSync12(USERS_FILE, "utf-8").trim();
|
|
14410
14382
|
if (raw2) {
|
|
14411
14383
|
const users = JSON.parse(raw2);
|
|
14412
14384
|
pinConfigured = Array.isArray(users) && users.length > 0;
|
|
@@ -15523,7 +15495,7 @@ var group_default = app4;
|
|
|
15523
15495
|
|
|
15524
15496
|
// app/lib/access-gate.ts
|
|
15525
15497
|
import neo4j2 from "neo4j-driver";
|
|
15526
|
-
import { readFileSync as
|
|
15498
|
+
import { readFileSync as readFileSync13 } from "fs";
|
|
15527
15499
|
import { resolve as resolve13 } from "path";
|
|
15528
15500
|
import { randomUUID as randomUUID7, randomInt } from "crypto";
|
|
15529
15501
|
var PLATFORM_ROOT5 = process.env.MAXY_PLATFORM_ROOT ?? resolve13(process.cwd(), "..");
|
|
@@ -15532,7 +15504,7 @@ function readPassword2() {
|
|
|
15532
15504
|
if (process.env.NEO4J_PASSWORD) return process.env.NEO4J_PASSWORD;
|
|
15533
15505
|
const passwordFile = resolve13(PLATFORM_ROOT5, "config/.neo4j-password");
|
|
15534
15506
|
try {
|
|
15535
|
-
return
|
|
15507
|
+
return readFileSync13(passwordFile, "utf-8").trim();
|
|
15536
15508
|
} catch {
|
|
15537
15509
|
throw new Error(
|
|
15538
15510
|
`Neo4j password not found. Expected at ${passwordFile} or in NEO4J_PASSWORD env var.`
|
|
@@ -15843,7 +15815,7 @@ async function findActiveGrantByContact(contactValue, agentSlug, accountId) {
|
|
|
15843
15815
|
}
|
|
15844
15816
|
|
|
15845
15817
|
// app/lib/brevo-sms.ts
|
|
15846
|
-
import { readFileSync as
|
|
15818
|
+
import { readFileSync as readFileSync14, writeFileSync as writeFileSync11, mkdirSync as mkdirSync9, existsSync as existsSync12, chmodSync } from "fs";
|
|
15847
15819
|
import { dirname as dirname6 } from "path";
|
|
15848
15820
|
import { resolve as resolve14 } from "path";
|
|
15849
15821
|
var BREVO_API_KEY_FILE = resolve14(MAXY_DIR, ".brevo-api-key");
|
|
@@ -15855,7 +15827,7 @@ if (platformRoot) {
|
|
|
15855
15827
|
try {
|
|
15856
15828
|
const brandPath = resolve14(platformRoot, "config", "brand.json");
|
|
15857
15829
|
if (existsSync12(brandPath)) {
|
|
15858
|
-
const brand = JSON.parse(
|
|
15830
|
+
const brand = JSON.parse(readFileSync14(brandPath, "utf-8"));
|
|
15859
15831
|
if (brand.productName) BREVO_SENDER = brand.productName;
|
|
15860
15832
|
}
|
|
15861
15833
|
} catch {
|
|
@@ -15863,7 +15835,7 @@ if (platformRoot) {
|
|
|
15863
15835
|
}
|
|
15864
15836
|
function readBrevoApiKey() {
|
|
15865
15837
|
try {
|
|
15866
|
-
const key =
|
|
15838
|
+
const key = readFileSync14(BREVO_API_KEY_FILE, "utf-8").trim();
|
|
15867
15839
|
if (!key) {
|
|
15868
15840
|
throw new Error(`Brevo API key file is empty: ${BREVO_API_KEY_FILE}`);
|
|
15869
15841
|
}
|
|
@@ -16294,7 +16266,7 @@ app5.post("/send-otp", async (c) => {
|
|
|
16294
16266
|
var access_default = app5;
|
|
16295
16267
|
|
|
16296
16268
|
// server/routes/telegram.ts
|
|
16297
|
-
import { existsSync as existsSync13, readFileSync as
|
|
16269
|
+
import { existsSync as existsSync13, readFileSync as readFileSync15 } from "fs";
|
|
16298
16270
|
import { timingSafeEqual } from "crypto";
|
|
16299
16271
|
|
|
16300
16272
|
// app/lib/telegram/access-control.ts
|
|
@@ -16332,7 +16304,7 @@ function getWebhookSecret(botType) {
|
|
|
16332
16304
|
const filePath = botType === "admin" ? TELEGRAM_ADMIN_WEBHOOK_SECRET_FILE : TELEGRAM_WEBHOOK_SECRET_FILE;
|
|
16333
16305
|
try {
|
|
16334
16306
|
if (!existsSync13(filePath)) return null;
|
|
16335
|
-
const secret =
|
|
16307
|
+
const secret = readFileSync15(filePath, "utf-8").trim();
|
|
16336
16308
|
return secret || null;
|
|
16337
16309
|
} catch {
|
|
16338
16310
|
return null;
|
|
@@ -16492,7 +16464,7 @@ var telegram_default = app6;
|
|
|
16492
16464
|
// server/routes/whatsapp.ts
|
|
16493
16465
|
import { join as join8, resolve as resolve15, basename as basename4 } from "path";
|
|
16494
16466
|
import { readFile as readFile2, stat as stat3 } from "fs/promises";
|
|
16495
|
-
import { realpathSync as realpathSync2, readdirSync as readdirSync4, readFileSync as
|
|
16467
|
+
import { realpathSync as realpathSync2, readdirSync as readdirSync4, readFileSync as readFileSync16, existsSync as existsSync14 } from "fs";
|
|
16496
16468
|
|
|
16497
16469
|
// app/lib/whatsapp/login.ts
|
|
16498
16470
|
import { randomUUID as randomUUID8 } from "crypto";
|
|
@@ -16980,7 +16952,7 @@ app7.post("/config", async (c) => {
|
|
|
16980
16952
|
const configPath2 = resolve15(agentsDir, entry.name, "config.json");
|
|
16981
16953
|
if (!existsSync14(configPath2)) continue;
|
|
16982
16954
|
try {
|
|
16983
|
-
const config = JSON.parse(
|
|
16955
|
+
const config = JSON.parse(readFileSync16(configPath2, "utf-8"));
|
|
16984
16956
|
agents.push({ slug: entry.name, displayName: config.displayName ?? entry.name });
|
|
16985
16957
|
} catch {
|
|
16986
16958
|
console.error(`${TAG18} config action=list-public-agents error="failed to parse config.json for agent ${entry.name}" \u2014 skipping`);
|
|
@@ -17192,7 +17164,7 @@ var whatsapp_default = app7;
|
|
|
17192
17164
|
|
|
17193
17165
|
// server/routes/onboarding.ts
|
|
17194
17166
|
import { spawn as spawn3, execFileSync as execFileSync2 } from "child_process";
|
|
17195
|
-
import { openSync as openSync4, closeSync as closeSync4, writeFileSync as writeFileSync12, writeSync, existsSync as existsSync15, mkdirSync as mkdirSync10, readFileSync as
|
|
17167
|
+
import { openSync as openSync4, closeSync as closeSync4, writeFileSync as writeFileSync12, writeSync, existsSync as existsSync15, mkdirSync as mkdirSync10, readFileSync as readFileSync17, unlinkSync as unlinkSync4 } from "fs";
|
|
17196
17168
|
import { resolve as resolve16, dirname as dirname7 } from "path";
|
|
17197
17169
|
import { createHash, randomUUID as randomUUID9 } from "crypto";
|
|
17198
17170
|
var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT || "";
|
|
@@ -17201,7 +17173,7 @@ function hashPin(pin) {
|
|
|
17201
17173
|
}
|
|
17202
17174
|
function readUsersFile() {
|
|
17203
17175
|
if (!existsSync15(USERS_FILE)) return null;
|
|
17204
|
-
const raw2 =
|
|
17176
|
+
const raw2 = readFileSync17(USERS_FILE, "utf-8").trim();
|
|
17205
17177
|
if (!raw2) return [];
|
|
17206
17178
|
return JSON.parse(raw2);
|
|
17207
17179
|
}
|
|
@@ -17312,7 +17284,7 @@ app8.post("/set-pin", async (c) => {
|
|
|
17312
17284
|
const account = resolveAccount();
|
|
17313
17285
|
if (account) {
|
|
17314
17286
|
try {
|
|
17315
|
-
const config = JSON.parse(
|
|
17287
|
+
const config = JSON.parse(readFileSync17(`${account.accountDir}/account.json`, "utf-8"));
|
|
17316
17288
|
if (!config.admins) config.admins = [];
|
|
17317
17289
|
if (!config.admins.some((a) => a.userId === userId)) {
|
|
17318
17290
|
config.admins.push({ userId, role: "owner" });
|
|
@@ -17370,7 +17342,7 @@ app8.post("/skip", async (c) => {
|
|
|
17370
17342
|
const brandPath = PLATFORM_ROOT7 ? resolve16(PLATFORM_ROOT7, "config", "brand.json") : "";
|
|
17371
17343
|
if (brandPath && existsSync15(brandPath)) {
|
|
17372
17344
|
try {
|
|
17373
|
-
const brand = JSON.parse(
|
|
17345
|
+
const brand = JSON.parse(readFileSync17(brandPath, "utf-8"));
|
|
17374
17346
|
if (brand.productName) agentName = brand.productName;
|
|
17375
17347
|
} catch (err) {
|
|
17376
17348
|
console.error(`[onboarding-skip] brand.json read failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -17564,14 +17536,14 @@ app9.post("/", async (c) => {
|
|
|
17564
17536
|
var client_error_default = app9;
|
|
17565
17537
|
|
|
17566
17538
|
// server/routes/admin/session.ts
|
|
17567
|
-
import { readFileSync as
|
|
17539
|
+
import { readFileSync as readFileSync18, existsSync as existsSync17 } from "fs";
|
|
17568
17540
|
import { createHash as createHash2 } from "crypto";
|
|
17569
17541
|
function hashPin2(pin) {
|
|
17570
17542
|
return createHash2("sha256").update(pin).digest("hex");
|
|
17571
17543
|
}
|
|
17572
17544
|
function readUsersFile2() {
|
|
17573
17545
|
if (!existsSync17(USERS_FILE)) return null;
|
|
17574
|
-
const raw2 =
|
|
17546
|
+
const raw2 = readFileSync18(USERS_FILE, "utf-8").trim();
|
|
17575
17547
|
if (!raw2) return [];
|
|
17576
17548
|
return JSON.parse(raw2);
|
|
17577
17549
|
}
|
|
@@ -18267,7 +18239,7 @@ app12.post("/", requireAdminSession, async (c) => {
|
|
|
18267
18239
|
var compact_default = app12;
|
|
18268
18240
|
|
|
18269
18241
|
// server/routes/admin/logs.ts
|
|
18270
|
-
import { existsSync as existsSync18, readdirSync as readdirSync5, readFileSync as
|
|
18242
|
+
import { existsSync as existsSync18, readdirSync as readdirSync5, readFileSync as readFileSync19, statSync as statSync9 } from "fs";
|
|
18271
18243
|
import { resolve as resolve18, basename as basename5 } from "path";
|
|
18272
18244
|
var TAIL_BYTES = 8192;
|
|
18273
18245
|
var app13 = new Hono2();
|
|
@@ -18286,7 +18258,7 @@ app13.get("/", async (c) => {
|
|
|
18286
18258
|
const filePath = resolve18(dir, safe);
|
|
18287
18259
|
searched.push(filePath);
|
|
18288
18260
|
try {
|
|
18289
|
-
const content =
|
|
18261
|
+
const content = readFileSync19(filePath, "utf-8");
|
|
18290
18262
|
const headers = { "Content-Type": "text/plain; charset=utf-8" };
|
|
18291
18263
|
if (download) headers["Content-Disposition"] = `attachment; filename="${safe}"`;
|
|
18292
18264
|
return new Response(content, { headers });
|
|
@@ -18328,7 +18300,7 @@ app13.get("/", async (c) => {
|
|
|
18328
18300
|
const filePath = resolve18(dir, fileName);
|
|
18329
18301
|
searched.push(filePath);
|
|
18330
18302
|
try {
|
|
18331
|
-
const content =
|
|
18303
|
+
const content = readFileSync19(filePath, "utf-8");
|
|
18332
18304
|
const headers = { "Content-Type": "text/plain; charset=utf-8" };
|
|
18333
18305
|
if (download) headers["Content-Disposition"] = `attachment; filename="${fileName}"`;
|
|
18334
18306
|
return new Response(content, { headers });
|
|
@@ -18355,7 +18327,7 @@ app13.get("/", async (c) => {
|
|
|
18355
18327
|
files.filter((f) => !seen.has(f)).map((f) => ({ name: f, mtime: statSync9(resolve18(dir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime).forEach(({ name }) => {
|
|
18356
18328
|
seen.add(name);
|
|
18357
18329
|
try {
|
|
18358
|
-
const content =
|
|
18330
|
+
const content = readFileSync19(resolve18(dir, name));
|
|
18359
18331
|
const tail = content.length > TAIL_BYTES ? content.subarray(content.length - TAIL_BYTES).toString("utf-8") : content.toString("utf-8");
|
|
18360
18332
|
logs[name] = tail.trim() || "(empty)";
|
|
18361
18333
|
} catch (err) {
|
|
@@ -18440,7 +18412,7 @@ app15.get("/:attachmentId", requireAdminSession, async (c) => {
|
|
|
18440
18412
|
var attachment_default = app15;
|
|
18441
18413
|
|
|
18442
18414
|
// server/routes/admin/account.ts
|
|
18443
|
-
import { readFileSync as
|
|
18415
|
+
import { readFileSync as readFileSync20, writeFileSync as writeFileSync13 } from "fs";
|
|
18444
18416
|
import { resolve as resolve20 } from "path";
|
|
18445
18417
|
var VALID_CONTEXT_MODES = ["managed", "claude-code"];
|
|
18446
18418
|
var app16 = new Hono2();
|
|
@@ -18459,7 +18431,7 @@ app16.patch("/", requireAdminSession, async (c) => {
|
|
|
18459
18431
|
if (!account) return c.json({ error: "No account configured" }, 500);
|
|
18460
18432
|
const configPath2 = resolve20(account.accountDir, "account.json");
|
|
18461
18433
|
try {
|
|
18462
|
-
const raw2 =
|
|
18434
|
+
const raw2 = readFileSync20(configPath2, "utf-8");
|
|
18463
18435
|
const config = JSON.parse(raw2);
|
|
18464
18436
|
config.contextMode = contextMode;
|
|
18465
18437
|
writeFileSync13(configPath2, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
@@ -18474,7 +18446,7 @@ var account_default = app16;
|
|
|
18474
18446
|
|
|
18475
18447
|
// server/routes/admin/agents.ts
|
|
18476
18448
|
import { resolve as resolve21 } from "path";
|
|
18477
|
-
import { readdirSync as readdirSync6, readFileSync as
|
|
18449
|
+
import { readdirSync as readdirSync6, readFileSync as readFileSync21, existsSync as existsSync20, rmSync as rmSync3 } from "fs";
|
|
18478
18450
|
var app17 = new Hono2();
|
|
18479
18451
|
app17.get("/", (c) => {
|
|
18480
18452
|
const account = resolveAccount();
|
|
@@ -18490,7 +18462,7 @@ app17.get("/", (c) => {
|
|
|
18490
18462
|
const configPath2 = resolve21(agentsDir, entry.name, "config.json");
|
|
18491
18463
|
if (!existsSync20(configPath2)) continue;
|
|
18492
18464
|
try {
|
|
18493
|
-
const config = JSON.parse(
|
|
18465
|
+
const config = JSON.parse(readFileSync21(configPath2, "utf-8"));
|
|
18494
18466
|
agents.push({
|
|
18495
18467
|
slug: entry.name,
|
|
18496
18468
|
displayName: config.displayName ?? entry.name,
|
|
@@ -18532,7 +18504,7 @@ app17.delete("/:slug", (c) => {
|
|
|
18532
18504
|
var agents_default = app17;
|
|
18533
18505
|
|
|
18534
18506
|
// server/routes/admin/version.ts
|
|
18535
|
-
import { existsSync as existsSync21, readFileSync as
|
|
18507
|
+
import { existsSync as existsSync21, readFileSync as readFileSync22 } from "fs";
|
|
18536
18508
|
import { resolve as resolve22, join as join10 } from "path";
|
|
18537
18509
|
var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT ?? resolve22(process.cwd(), "..");
|
|
18538
18510
|
var brandHostname = "maxy";
|
|
@@ -18540,7 +18512,7 @@ var brandNpmPackage = "@rubytech/create-maxy";
|
|
|
18540
18512
|
var brandJsonPath = join10(PLATFORM_ROOT8, "config", "brand.json");
|
|
18541
18513
|
if (existsSync21(brandJsonPath)) {
|
|
18542
18514
|
try {
|
|
18543
|
-
const brand = JSON.parse(
|
|
18515
|
+
const brand = JSON.parse(readFileSync22(brandJsonPath, "utf-8"));
|
|
18544
18516
|
if (brand.hostname) brandHostname = brand.hostname;
|
|
18545
18517
|
if (brand.npm?.packageName) brandNpmPackage = brand.npm.packageName;
|
|
18546
18518
|
} catch {
|
|
@@ -18552,7 +18524,7 @@ var REGISTRY_URL = `https://registry.npmjs.org/${NPM_PACKAGE}/latest`;
|
|
|
18552
18524
|
var FETCH_TIMEOUT_MS = 5e3;
|
|
18553
18525
|
function readInstalled() {
|
|
18554
18526
|
if (!existsSync21(VERSION_FILE)) return "unknown";
|
|
18555
|
-
const content =
|
|
18527
|
+
const content = readFileSync22(VERSION_FILE, "utf-8").trim();
|
|
18556
18528
|
return content || "unknown";
|
|
18557
18529
|
}
|
|
18558
18530
|
async function fetchLatest() {
|
|
@@ -18806,66 +18778,6 @@ app20.post("/launch", async (c) => {
|
|
|
18806
18778
|
});
|
|
18807
18779
|
var browser_default = app20;
|
|
18808
18780
|
|
|
18809
|
-
// server/routes/admin/terminal.ts
|
|
18810
|
-
var app21 = new Hono2();
|
|
18811
|
-
app21.post("/launch", async (c) => {
|
|
18812
|
-
try {
|
|
18813
|
-
const transport = resolveBrowserTransport(c.req.raw, c.env?.incoming?.socket?.remoteAddress);
|
|
18814
|
-
if (transport === "vnc") {
|
|
18815
|
-
const vncOk = await ensureVnc();
|
|
18816
|
-
if (!vncOk) {
|
|
18817
|
-
return c.json({ ok: false, error: "VNC failed to start" }, 502);
|
|
18818
|
-
}
|
|
18819
|
-
}
|
|
18820
|
-
const terminalResult = await ensureTerminal(transport);
|
|
18821
|
-
if (!terminalResult.ok) {
|
|
18822
|
-
return c.json({ ok: false, error: terminalResult.error ?? "Terminal failed to start" }, 502);
|
|
18823
|
-
}
|
|
18824
|
-
return c.json({ ok: true, transport });
|
|
18825
|
-
} catch (err) {
|
|
18826
|
-
console.error("[admin/terminal/launch] Failed to start terminal:", err);
|
|
18827
|
-
return c.json(
|
|
18828
|
-
{ ok: false, error: err instanceof Error ? err.message : "Unknown error" },
|
|
18829
|
-
500
|
|
18830
|
-
);
|
|
18831
|
-
}
|
|
18832
|
-
});
|
|
18833
|
-
app21.post("/launch-upgrade", async (c) => {
|
|
18834
|
-
try {
|
|
18835
|
-
const transport = resolveBrowserTransport(c.req.raw, c.env?.incoming?.socket?.remoteAddress);
|
|
18836
|
-
if (transport === "vnc") {
|
|
18837
|
-
const vncOk = await ensureVnc();
|
|
18838
|
-
if (!vncOk) {
|
|
18839
|
-
return c.json({ ok: false, error: "VNC failed to start" }, 502);
|
|
18840
|
-
}
|
|
18841
|
-
}
|
|
18842
|
-
const result = await ensureTerminalUpgrade(transport);
|
|
18843
|
-
if (!result.ok) {
|
|
18844
|
-
return c.json({ ok: false, error: result.error ?? "Upgrade terminal failed to start" }, 502);
|
|
18845
|
-
}
|
|
18846
|
-
return c.json({ ok: true, transport });
|
|
18847
|
-
} catch (err) {
|
|
18848
|
-
console.error("[admin/terminal/launch-upgrade] Failed to start upgrade terminal:", err);
|
|
18849
|
-
return c.json(
|
|
18850
|
-
{ ok: false, error: err instanceof Error ? err.message : "Unknown error" },
|
|
18851
|
-
500
|
|
18852
|
-
);
|
|
18853
|
-
}
|
|
18854
|
-
});
|
|
18855
|
-
app21.post("/close", (c) => {
|
|
18856
|
-
try {
|
|
18857
|
-
killTerminal();
|
|
18858
|
-
return c.json({ ok: true });
|
|
18859
|
-
} catch (err) {
|
|
18860
|
-
console.error("[admin/terminal/close] kill failed:", err);
|
|
18861
|
-
return c.json(
|
|
18862
|
-
{ ok: false, error: err instanceof Error ? err.message : "Unknown error" },
|
|
18863
|
-
500
|
|
18864
|
-
);
|
|
18865
|
-
}
|
|
18866
|
-
});
|
|
18867
|
-
var terminal_default = app21;
|
|
18868
|
-
|
|
18869
18781
|
// app/lib/cdp-client.ts
|
|
18870
18782
|
var CDP_HOST = "127.0.0.1";
|
|
18871
18783
|
var CDP_PORT = 9222;
|
|
@@ -18907,8 +18819,8 @@ async function cdpNavigateNewTab(url, opts = {}) {
|
|
|
18907
18819
|
}
|
|
18908
18820
|
|
|
18909
18821
|
// server/routes/admin/device-browser.ts
|
|
18910
|
-
var
|
|
18911
|
-
|
|
18822
|
+
var app21 = new Hono2();
|
|
18823
|
+
app21.post("/navigate", async (c) => {
|
|
18912
18824
|
const TAG19 = "[device-url:click]";
|
|
18913
18825
|
let body;
|
|
18914
18826
|
try {
|
|
@@ -18995,7 +18907,7 @@ app22.post("/navigate", async (c) => {
|
|
|
18995
18907
|
targetId: outcome.targetId
|
|
18996
18908
|
});
|
|
18997
18909
|
});
|
|
18998
|
-
var device_browser_default =
|
|
18910
|
+
var device_browser_default = app21;
|
|
18999
18911
|
|
|
19000
18912
|
// server/routes/admin/events.ts
|
|
19001
18913
|
var ALLOWED_EVENTS = /* @__PURE__ */ new Set([
|
|
@@ -19004,8 +18916,8 @@ var ALLOWED_EVENTS = /* @__PURE__ */ new Set([
|
|
|
19004
18916
|
"device-url:vnc-surface-shown",
|
|
19005
18917
|
"device-url:malformed"
|
|
19006
18918
|
]);
|
|
19007
|
-
var
|
|
19008
|
-
|
|
18919
|
+
var app22 = new Hono2();
|
|
18920
|
+
app22.post("/", async (c) => {
|
|
19009
18921
|
const TAG19 = "[admin:events]";
|
|
19010
18922
|
let body;
|
|
19011
18923
|
try {
|
|
@@ -19036,12 +18948,12 @@ app23.post("/", async (c) => {
|
|
|
19036
18948
|
console.error(`[${event}] ${formatted}`);
|
|
19037
18949
|
return c.json({ ok: true });
|
|
19038
18950
|
});
|
|
19039
|
-
var events_default =
|
|
18951
|
+
var events_default = app22;
|
|
19040
18952
|
|
|
19041
18953
|
// server/routes/admin/cloudflare.ts
|
|
19042
18954
|
import { homedir as homedir3 } from "os";
|
|
19043
18955
|
import { resolve as resolve24 } from "path";
|
|
19044
|
-
import { readFileSync as
|
|
18956
|
+
import { readFileSync as readFileSync24 } from "fs";
|
|
19045
18957
|
|
|
19046
18958
|
// app/lib/dns-label.ts
|
|
19047
18959
|
var VALID_LABEL = /^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$/;
|
|
@@ -19057,14 +18969,14 @@ function isValidDomain(value) {
|
|
|
19057
18969
|
}
|
|
19058
18970
|
|
|
19059
18971
|
// app/lib/alias-domains.ts
|
|
19060
|
-
import { existsSync as existsSync22, mkdirSync as mkdirSync12, readFileSync as
|
|
18972
|
+
import { existsSync as existsSync22, mkdirSync as mkdirSync12, readFileSync as readFileSync23, writeFileSync as writeFileSync14 } from "fs";
|
|
19061
18973
|
import { dirname as dirname9 } from "path";
|
|
19062
18974
|
import { resolve as resolve23 } from "path";
|
|
19063
18975
|
var ALIAS_DOMAINS_PATH = resolve23(MAXY_DIR, "alias-domains.json");
|
|
19064
18976
|
function readExisting() {
|
|
19065
18977
|
if (!existsSync22(ALIAS_DOMAINS_PATH)) return /* @__PURE__ */ new Set();
|
|
19066
18978
|
try {
|
|
19067
|
-
const parsed = JSON.parse(
|
|
18979
|
+
const parsed = JSON.parse(readFileSync23(ALIAS_DOMAINS_PATH, "utf-8"));
|
|
19068
18980
|
if (!Array.isArray(parsed)) return /* @__PURE__ */ new Set();
|
|
19069
18981
|
return new Set(parsed.filter((h) => typeof h === "string"));
|
|
19070
18982
|
} catch {
|
|
@@ -19086,7 +18998,7 @@ function loadBrandInfo() {
|
|
|
19086
18998
|
const platformRoot2 = process.env.MAXY_PLATFORM_ROOT ?? resolve24(process.cwd(), "..");
|
|
19087
18999
|
const brandPath = resolve24(platformRoot2, "config", "brand.json");
|
|
19088
19000
|
try {
|
|
19089
|
-
const parsed = JSON.parse(
|
|
19001
|
+
const parsed = JSON.parse(readFileSync24(brandPath, "utf-8"));
|
|
19090
19002
|
const hostname2 = typeof parsed.hostname === "string" && parsed.hostname ? parsed.hostname : "maxy";
|
|
19091
19003
|
const configDir2 = typeof parsed.configDir === "string" && parsed.configDir ? parsed.configDir : ".maxy";
|
|
19092
19004
|
return { hostname: hostname2, configDir: configDir2 };
|
|
@@ -19129,7 +19041,7 @@ function validateBody(body) {
|
|
|
19129
19041
|
}
|
|
19130
19042
|
return null;
|
|
19131
19043
|
}
|
|
19132
|
-
var
|
|
19044
|
+
var app23 = new Hono2();
|
|
19133
19045
|
function fieldFromReason(reason) {
|
|
19134
19046
|
switch (reason) {
|
|
19135
19047
|
case "not-signed-in":
|
|
@@ -19146,7 +19058,7 @@ function fieldFromReason(reason) {
|
|
|
19146
19058
|
return "script";
|
|
19147
19059
|
}
|
|
19148
19060
|
}
|
|
19149
|
-
|
|
19061
|
+
app23.get("/domains", requireAdminSession, async (c) => {
|
|
19150
19062
|
const started = Date.now();
|
|
19151
19063
|
const sessionKey = c.var.sessionKey;
|
|
19152
19064
|
let correlationId;
|
|
@@ -19239,7 +19151,7 @@ ${result.stderr}` : ""}`;
|
|
|
19239
19151
|
);
|
|
19240
19152
|
return c.json(success, 200);
|
|
19241
19153
|
});
|
|
19242
|
-
|
|
19154
|
+
app23.post("/setup", requireAdminSession, async (c) => {
|
|
19243
19155
|
const started = Date.now();
|
|
19244
19156
|
const sessionKey = c.var.sessionKey;
|
|
19245
19157
|
let correlationId;
|
|
@@ -19377,7 +19289,7 @@ ${result.stderr}` : ""}`;
|
|
|
19377
19289
|
log2(`phase=response-sent`);
|
|
19378
19290
|
return resp;
|
|
19379
19291
|
});
|
|
19380
|
-
var cloudflare_default =
|
|
19292
|
+
var cloudflare_default = app23;
|
|
19381
19293
|
|
|
19382
19294
|
// server/routes/admin/files.ts
|
|
19383
19295
|
import { createReadStream as createReadStream3 } from "fs";
|
|
@@ -19489,25 +19401,72 @@ async function trashNode(params) {
|
|
|
19489
19401
|
const setNullClauses = Object.keys(originalKeys).map((k) => `n.\`${k}\` = null`).join(", ");
|
|
19490
19402
|
const setNullSuffix = setNullClauses ? `, ${setNullClauses}` : "";
|
|
19491
19403
|
const trashedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
19492
|
-
|
|
19493
|
-
|
|
19494
|
-
|
|
19495
|
-
|
|
19496
|
-
|
|
19497
|
-
|
|
19498
|
-
|
|
19499
|
-
|
|
19500
|
-
|
|
19501
|
-
|
|
19502
|
-
|
|
19503
|
-
|
|
19504
|
-
|
|
19404
|
+
const isConversation = baseLabels.includes("Conversation");
|
|
19405
|
+
const messageUniqueKeys = UNIQUE_KEYS_BY_LABEL["Message"] ?? [];
|
|
19406
|
+
let cascadedMessageCount = 0;
|
|
19407
|
+
await session.executeWrite(async (tx) => {
|
|
19408
|
+
await tx.run(
|
|
19409
|
+
`MATCH (n) WHERE elementId(n) = $eid
|
|
19410
|
+
SET n:Trashed,
|
|
19411
|
+
n.trashedAt = datetime($trashedAt),
|
|
19412
|
+
n.trashedBy = $by,
|
|
19413
|
+
n.trashReason = $reason,
|
|
19414
|
+
n._trashedKeys = $trashedKeysJson${setNullSuffix}`,
|
|
19415
|
+
{
|
|
19416
|
+
eid: elementId,
|
|
19417
|
+
trashedAt,
|
|
19418
|
+
by,
|
|
19419
|
+
reason: reason ?? null,
|
|
19420
|
+
trashedKeysJson: JSON.stringify(originalKeys)
|
|
19421
|
+
}
|
|
19422
|
+
);
|
|
19423
|
+
if (isConversation) {
|
|
19424
|
+
const collectKeys = messageUniqueKeys.length > 0 ? messageUniqueKeys.map((k) => `\`${k}\`: m.\`${k}\``).join(", ") : "";
|
|
19425
|
+
const collectMsgProps = collectKeys ? `, {${collectKeys}}` : ", {}";
|
|
19426
|
+
const collected = await tx.run(
|
|
19427
|
+
`MATCH (c) WHERE elementId(c) = $eid
|
|
19428
|
+
MATCH (m:Message)-[:PART_OF]->(c)
|
|
19429
|
+
WHERE NOT m:Trashed
|
|
19430
|
+
RETURN elementId(m) AS meid${collectMsgProps} AS keys`,
|
|
19431
|
+
{ eid: elementId }
|
|
19432
|
+
);
|
|
19433
|
+
for (const rec of collected.records) {
|
|
19434
|
+
const meid = rec.get("meid");
|
|
19435
|
+
const keys = rec.get("keys");
|
|
19436
|
+
const liveKeys = {};
|
|
19437
|
+
for (const k of messageUniqueKeys) {
|
|
19438
|
+
if (keys[k] !== void 0 && keys[k] !== null) liveKeys[k] = keys[k];
|
|
19439
|
+
}
|
|
19440
|
+
const msgSetNulls = Object.keys(liveKeys).length > 0 ? ", " + Object.keys(liveKeys).map((k) => `m.\`${k}\` = null`).join(", ") : "";
|
|
19441
|
+
await tx.run(
|
|
19442
|
+
`MATCH (m) WHERE elementId(m) = $meid
|
|
19443
|
+
SET m:Trashed,
|
|
19444
|
+
m.trashedAt = datetime($trashedAt),
|
|
19445
|
+
m.trashedBy = $by,
|
|
19446
|
+
m.trashReason = $reason,
|
|
19447
|
+
m._trashedKeys = $trashedKeysJson${msgSetNulls}`,
|
|
19448
|
+
{
|
|
19449
|
+
meid,
|
|
19450
|
+
trashedAt,
|
|
19451
|
+
by: `${by}:cascade-from-conversation`,
|
|
19452
|
+
reason: reason ?? `cascade from Conversation ${elementId}`,
|
|
19453
|
+
trashedKeysJson: JSON.stringify(liveKeys)
|
|
19454
|
+
}
|
|
19455
|
+
);
|
|
19456
|
+
}
|
|
19457
|
+
cascadedMessageCount = collected.records.length;
|
|
19505
19458
|
}
|
|
19506
|
-
);
|
|
19459
|
+
});
|
|
19507
19460
|
process.stderr.write(
|
|
19508
19461
|
`[trash:marked] accountId=${accountId} elementId=${elementId} labels=${baseLabels.join(",")} by=${by} reason=${reason ?? "null"}
|
|
19509
19462
|
`
|
|
19510
19463
|
);
|
|
19464
|
+
if (isConversation) {
|
|
19465
|
+
process.stderr.write(
|
|
19466
|
+
`[trash:cascaded] accountId=${accountId} conversationElementId=${elementId} messageCount=${cascadedMessageCount} by=${by}
|
|
19467
|
+
`
|
|
19468
|
+
);
|
|
19469
|
+
}
|
|
19511
19470
|
return {
|
|
19512
19471
|
trashed: true,
|
|
19513
19472
|
alreadyTrashed: false,
|
|
@@ -19558,16 +19517,50 @@ async function restoreNode(params) {
|
|
|
19558
19517
|
const setSuffix = setClauses ? `, ${setClauses}` : "";
|
|
19559
19518
|
const setParams = { eid: elementId };
|
|
19560
19519
|
for (const [k, v] of Object.entries(originalKeys)) setParams[`val_${k}`] = v;
|
|
19561
|
-
|
|
19562
|
-
|
|
19563
|
-
|
|
19564
|
-
|
|
19565
|
-
|
|
19566
|
-
|
|
19520
|
+
const isConversation = baseLabels.includes("Conversation");
|
|
19521
|
+
let cascadedMessageCount = 0;
|
|
19522
|
+
await session.executeWrite(async (tx) => {
|
|
19523
|
+
await tx.run(
|
|
19524
|
+
`MATCH (n:Trashed) WHERE elementId(n) = $eid
|
|
19525
|
+
REMOVE n:Trashed, n.trashedAt, n.trashedBy, n.trashReason, n._trashedKeys
|
|
19526
|
+
SET n.restoredAt = datetime()${setSuffix}`,
|
|
19527
|
+
setParams
|
|
19528
|
+
);
|
|
19529
|
+
if (isConversation) {
|
|
19530
|
+
const collected = await tx.run(
|
|
19531
|
+
`MATCH (c) WHERE elementId(c) = $eid
|
|
19532
|
+
MATCH (m:Trashed:Message)-[:PART_OF]->(c)
|
|
19533
|
+
WHERE m.trashedBy ENDS WITH ':cascade-from-conversation'
|
|
19534
|
+
RETURN elementId(m) AS meid, m._trashedKeys AS keysJson`,
|
|
19535
|
+
{ eid: elementId }
|
|
19536
|
+
);
|
|
19537
|
+
for (const rec of collected.records) {
|
|
19538
|
+
const meid = rec.get("meid");
|
|
19539
|
+
const keysJson2 = rec.get("keysJson");
|
|
19540
|
+
const keys = keysJson2 ? JSON.parse(keysJson2) : {};
|
|
19541
|
+
const setClause = Object.keys(keys).length > 0 ? ", " + Object.keys(keys).map((k) => `m.\`${k}\` = $val_${k}`).join(", ") : "";
|
|
19542
|
+
const msgParams = { meid };
|
|
19543
|
+
for (const [k, v] of Object.entries(keys)) msgParams[`val_${k}`] = v;
|
|
19544
|
+
await tx.run(
|
|
19545
|
+
`MATCH (m) WHERE elementId(m) = $meid
|
|
19546
|
+
REMOVE m:Trashed, m.trashedAt, m.trashedBy, m.trashReason, m._trashedKeys
|
|
19547
|
+
SET m.restoredAt = datetime()${setClause}`,
|
|
19548
|
+
msgParams
|
|
19549
|
+
);
|
|
19550
|
+
}
|
|
19551
|
+
cascadedMessageCount = collected.records.length;
|
|
19552
|
+
}
|
|
19553
|
+
});
|
|
19567
19554
|
process.stderr.write(
|
|
19568
19555
|
`[trash:restored] accountId=${accountId} elementId=${elementId} labels=${baseLabels.join(",")}
|
|
19569
19556
|
`
|
|
19570
19557
|
);
|
|
19558
|
+
if (isConversation) {
|
|
19559
|
+
process.stderr.write(
|
|
19560
|
+
`[trash:cascade-restored] accountId=${accountId} conversationElementId=${elementId} messageCount=${cascadedMessageCount}
|
|
19561
|
+
`
|
|
19562
|
+
);
|
|
19563
|
+
}
|
|
19571
19564
|
return {
|
|
19572
19565
|
restored: true,
|
|
19573
19566
|
nodeId: elementId,
|
|
@@ -19729,8 +19722,8 @@ function buildDisplayPath(relPath, accountNames) {
|
|
|
19729
19722
|
return dn ? { name: seg, displayName: dn } : { name: seg };
|
|
19730
19723
|
});
|
|
19731
19724
|
}
|
|
19732
|
-
var
|
|
19733
|
-
|
|
19725
|
+
var app24 = new Hono2();
|
|
19726
|
+
app24.get("/", requireAdminSession, async (c) => {
|
|
19734
19727
|
const sessionKey = c.var.sessionKey;
|
|
19735
19728
|
if (!getAccountIdForSession(sessionKey)) {
|
|
19736
19729
|
console.error(`[data] auth-rejected endpoint="/api/admin/files" reason="no account for session"`);
|
|
@@ -19791,7 +19784,7 @@ app25.get("/", requireAdminSession, async (c) => {
|
|
|
19791
19784
|
return c.json({ error: message }, 500);
|
|
19792
19785
|
}
|
|
19793
19786
|
});
|
|
19794
|
-
|
|
19787
|
+
app24.get("/download", requireAdminSession, async (c) => {
|
|
19795
19788
|
const sessionKey = c.var.sessionKey;
|
|
19796
19789
|
if (!getAccountIdForSession(sessionKey)) {
|
|
19797
19790
|
console.error(`[data] auth-rejected endpoint="/api/admin/files/download" reason="no account for session"`);
|
|
@@ -19839,7 +19832,7 @@ app25.get("/download", requireAdminSession, async (c) => {
|
|
|
19839
19832
|
return c.json({ error: message }, 500);
|
|
19840
19833
|
}
|
|
19841
19834
|
});
|
|
19842
|
-
|
|
19835
|
+
app24.post("/upload", requireAdminSession, async (c) => {
|
|
19843
19836
|
const sessionKey = c.var.sessionKey;
|
|
19844
19837
|
const accountId = getAccountIdForSession(sessionKey);
|
|
19845
19838
|
if (!accountId) {
|
|
@@ -19897,7 +19890,7 @@ app25.post("/upload", requireAdminSession, async (c) => {
|
|
|
19897
19890
|
mimeType: file.type
|
|
19898
19891
|
});
|
|
19899
19892
|
});
|
|
19900
|
-
|
|
19893
|
+
app24.delete("/", requireAdminSession, async (c) => {
|
|
19901
19894
|
const sessionKey = c.var.sessionKey;
|
|
19902
19895
|
const accountId = getAccountIdForSession(sessionKey);
|
|
19903
19896
|
if (!accountId) {
|
|
@@ -19964,13 +19957,13 @@ app25.delete("/", requireAdminSession, async (c) => {
|
|
|
19964
19957
|
return c.json({ error: message }, 500);
|
|
19965
19958
|
}
|
|
19966
19959
|
});
|
|
19967
|
-
var files_default =
|
|
19960
|
+
var files_default = app24;
|
|
19968
19961
|
|
|
19969
19962
|
// server/routes/admin/graph-search.ts
|
|
19970
19963
|
var DEFAULT_LIMIT = 20;
|
|
19971
19964
|
var MAX_LIMIT = 100;
|
|
19972
|
-
var
|
|
19973
|
-
|
|
19965
|
+
var app25 = new Hono2();
|
|
19966
|
+
app25.get("/", requireAdminSession, async (c) => {
|
|
19974
19967
|
const sessionKey = c.var.sessionKey;
|
|
19975
19968
|
const q = (c.req.query("q") ?? "").trim();
|
|
19976
19969
|
const rawLimit = c.req.query("limit");
|
|
@@ -19995,7 +19988,7 @@ app26.get("/", requireAdminSession, async (c) => {
|
|
|
19995
19988
|
return c.json({ error: `Graph search unavailable: ${message}` }, 503);
|
|
19996
19989
|
}
|
|
19997
19990
|
});
|
|
19998
|
-
var graph_search_default =
|
|
19991
|
+
var graph_search_default = app25;
|
|
19999
19992
|
|
|
20000
19993
|
// server/routes/admin/graph-subgraph.ts
|
|
20001
19994
|
import neo4j3 from "neo4j-driver";
|
|
@@ -20124,8 +20117,8 @@ var STRIPPED_PROPERTIES = /* @__PURE__ */ new Set([
|
|
|
20124
20117
|
"otpCode",
|
|
20125
20118
|
"sessionKey"
|
|
20126
20119
|
]);
|
|
20127
|
-
var
|
|
20128
|
-
|
|
20120
|
+
var app26 = new Hono2();
|
|
20121
|
+
app26.get("/", requireAdminSession, async (c) => {
|
|
20129
20122
|
const sessionKey = c.var.sessionKey;
|
|
20130
20123
|
const accountId = getAccountIdForSession(sessionKey);
|
|
20131
20124
|
if (!accountId) {
|
|
@@ -20401,12 +20394,12 @@ function pruneNode(node, warnedClasses) {
|
|
|
20401
20394
|
const labels = (node.labels ?? []).filter((l) => l !== "Trashed");
|
|
20402
20395
|
return trashed ? { id: node.id, labels, properties, trashed: true } : { id: node.id, labels, properties };
|
|
20403
20396
|
}
|
|
20404
|
-
var graph_subgraph_default =
|
|
20397
|
+
var graph_subgraph_default = app26;
|
|
20405
20398
|
|
|
20406
20399
|
// server/routes/admin/graph-delete.ts
|
|
20407
20400
|
var ALLOWED_BY = ["graph-page", "graph-drag-trash"];
|
|
20408
|
-
var
|
|
20409
|
-
|
|
20401
|
+
var app27 = new Hono2();
|
|
20402
|
+
app27.post("/", requireAdminSession, async (c) => {
|
|
20410
20403
|
const sessionKey = c.var.sessionKey;
|
|
20411
20404
|
const accountId = getAccountIdForSession(sessionKey);
|
|
20412
20405
|
if (!accountId) {
|
|
@@ -20477,11 +20470,11 @@ app28.post("/", requireAdminSession, async (c) => {
|
|
|
20477
20470
|
}
|
|
20478
20471
|
}
|
|
20479
20472
|
});
|
|
20480
|
-
var graph_delete_default =
|
|
20473
|
+
var graph_delete_default = app27;
|
|
20481
20474
|
|
|
20482
20475
|
// server/routes/admin/graph-restore.ts
|
|
20483
|
-
var
|
|
20484
|
-
|
|
20476
|
+
var app28 = new Hono2();
|
|
20477
|
+
app28.post("/", requireAdminSession, async (c) => {
|
|
20485
20478
|
const sessionKey = c.var.sessionKey;
|
|
20486
20479
|
const accountId = getAccountIdForSession(sessionKey);
|
|
20487
20480
|
if (!accountId) {
|
|
@@ -20545,11 +20538,11 @@ app29.post("/", requireAdminSession, async (c) => {
|
|
|
20545
20538
|
}
|
|
20546
20539
|
}
|
|
20547
20540
|
});
|
|
20548
|
-
var graph_restore_default =
|
|
20541
|
+
var graph_restore_default = app28;
|
|
20549
20542
|
|
|
20550
20543
|
// server/routes/admin/graph-labels-in-graph.ts
|
|
20551
|
-
var
|
|
20552
|
-
|
|
20544
|
+
var app29 = new Hono2();
|
|
20545
|
+
app29.get("/", requireAdminSession, async (c) => {
|
|
20553
20546
|
const sessionKey = c.var.sessionKey;
|
|
20554
20547
|
const accountId = getAccountIdForSession(sessionKey);
|
|
20555
20548
|
if (!accountId) {
|
|
@@ -20610,11 +20603,11 @@ var LABELS_IN_GRAPH_CYPHER = `
|
|
|
20610
20603
|
sum(halfEdges) AS relDegree
|
|
20611
20604
|
RETURN label, nodeCount, relDegree
|
|
20612
20605
|
`;
|
|
20613
|
-
var graph_labels_in_graph_default =
|
|
20606
|
+
var graph_labels_in_graph_default = app29;
|
|
20614
20607
|
|
|
20615
20608
|
// server/routes/admin/graph-default-view.ts
|
|
20616
|
-
var
|
|
20617
|
-
|
|
20609
|
+
var app30 = new Hono2();
|
|
20610
|
+
app30.get("/", requireAdminSession, async (c) => {
|
|
20618
20611
|
const sessionKey = c.var.sessionKey;
|
|
20619
20612
|
const accountId = getAccountIdForSession(sessionKey);
|
|
20620
20613
|
const userId = getUserIdForSession(sessionKey);
|
|
@@ -20652,7 +20645,7 @@ app31.get("/", requireAdminSession, async (c) => {
|
|
|
20652
20645
|
}
|
|
20653
20646
|
}
|
|
20654
20647
|
});
|
|
20655
|
-
|
|
20648
|
+
app30.put("/", requireAdminSession, async (c) => {
|
|
20656
20649
|
const sessionKey = c.var.sessionKey;
|
|
20657
20650
|
const accountId = getAccountIdForSession(sessionKey);
|
|
20658
20651
|
const userId = getUserIdForSession(sessionKey);
|
|
@@ -20734,11 +20727,11 @@ var WRITE_CYPHER = `
|
|
|
20734
20727
|
p.updatedAt = $updatedAt
|
|
20735
20728
|
RETURN p.labels AS labels
|
|
20736
20729
|
`;
|
|
20737
|
-
var graph_default_view_default =
|
|
20730
|
+
var graph_default_view_default = app30;
|
|
20738
20731
|
|
|
20739
20732
|
// server/routes/admin/file-attach.ts
|
|
20740
|
-
var
|
|
20741
|
-
|
|
20733
|
+
var app31 = new Hono2();
|
|
20734
|
+
app31.post("/", async (c) => {
|
|
20742
20735
|
try {
|
|
20743
20736
|
const body = await c.req.json();
|
|
20744
20737
|
const { filePath, accountId } = body;
|
|
@@ -20761,11 +20754,11 @@ app32.post("/", async (c) => {
|
|
|
20761
20754
|
return c.json({ error: message }, 500);
|
|
20762
20755
|
}
|
|
20763
20756
|
});
|
|
20764
|
-
var file_attach_default =
|
|
20757
|
+
var file_attach_default = app31;
|
|
20765
20758
|
|
|
20766
20759
|
// server/routes/admin/adherence.ts
|
|
20767
|
-
var
|
|
20768
|
-
|
|
20760
|
+
var app32 = new Hono2();
|
|
20761
|
+
app32.get("/", requireAdminSession, async (c) => {
|
|
20769
20762
|
const agent = c.req.query("agent") ?? "admin";
|
|
20770
20763
|
const includeBlock = c.req.query("block") === "1";
|
|
20771
20764
|
const account = resolveAccount();
|
|
@@ -20786,35 +20779,34 @@ app33.get("/", requireAdminSession, async (c) => {
|
|
|
20786
20779
|
return c.json({ error: "Failed to read adherence ledger", agent }, 500);
|
|
20787
20780
|
}
|
|
20788
20781
|
});
|
|
20789
|
-
var adherence_default =
|
|
20782
|
+
var adherence_default = app32;
|
|
20790
20783
|
|
|
20791
20784
|
// server/routes/admin/index.ts
|
|
20792
|
-
var
|
|
20793
|
-
|
|
20794
|
-
|
|
20795
|
-
|
|
20796
|
-
|
|
20797
|
-
|
|
20798
|
-
|
|
20799
|
-
|
|
20800
|
-
|
|
20801
|
-
|
|
20802
|
-
|
|
20803
|
-
|
|
20804
|
-
|
|
20805
|
-
|
|
20806
|
-
|
|
20807
|
-
|
|
20808
|
-
|
|
20809
|
-
|
|
20810
|
-
|
|
20811
|
-
|
|
20812
|
-
|
|
20813
|
-
|
|
20814
|
-
|
|
20815
|
-
|
|
20816
|
-
|
|
20817
|
-
var admin_default = app34;
|
|
20785
|
+
var app33 = new Hono2();
|
|
20786
|
+
app33.route("/session", session_default2);
|
|
20787
|
+
app33.route("/chat", chat_default2);
|
|
20788
|
+
app33.route("/compact", compact_default);
|
|
20789
|
+
app33.route("/logs", logs_default);
|
|
20790
|
+
app33.route("/claude-info", claude_info_default);
|
|
20791
|
+
app33.route("/attachment", attachment_default);
|
|
20792
|
+
app33.route("/account", account_default);
|
|
20793
|
+
app33.route("/agents", agents_default);
|
|
20794
|
+
app33.route("/version", version_default);
|
|
20795
|
+
app33.route("/sessions", sessions_default);
|
|
20796
|
+
app33.route("/browser", browser_default);
|
|
20797
|
+
app33.route("/device-browser", device_browser_default);
|
|
20798
|
+
app33.route("/events", events_default);
|
|
20799
|
+
app33.route("/cloudflare", cloudflare_default);
|
|
20800
|
+
app33.route("/files", files_default);
|
|
20801
|
+
app33.route("/graph-search", graph_search_default);
|
|
20802
|
+
app33.route("/graph-subgraph", graph_subgraph_default);
|
|
20803
|
+
app33.route("/graph-delete", graph_delete_default);
|
|
20804
|
+
app33.route("/graph-restore", graph_restore_default);
|
|
20805
|
+
app33.route("/graph-labels-in-graph", graph_labels_in_graph_default);
|
|
20806
|
+
app33.route("/graph-default-view", graph_default_view_default);
|
|
20807
|
+
app33.route("/file-attach", file_attach_default);
|
|
20808
|
+
app33.route("/adherence", adherence_default);
|
|
20809
|
+
var admin_default = app33;
|
|
20818
20810
|
|
|
20819
20811
|
// server/index.ts
|
|
20820
20812
|
var PLATFORM_ROOT10 = process.env.MAXY_PLATFORM_ROOT || "";
|
|
@@ -20825,7 +20817,7 @@ if (BRAND_JSON_PATH && !existsSync23(BRAND_JSON_PATH)) {
|
|
|
20825
20817
|
}
|
|
20826
20818
|
if (BRAND_JSON_PATH && existsSync23(BRAND_JSON_PATH)) {
|
|
20827
20819
|
try {
|
|
20828
|
-
const parsed = JSON.parse(
|
|
20820
|
+
const parsed = JSON.parse(readFileSync25(BRAND_JSON_PATH, "utf-8"));
|
|
20829
20821
|
BRAND = { ...BRAND, ...parsed };
|
|
20830
20822
|
} catch (err) {
|
|
20831
20823
|
console.error(`[brand] Failed to parse brand.json: ${err.message}`);
|
|
@@ -20848,7 +20840,7 @@ var ALIAS_DOMAINS_PATH2 = join12(homedir4(), BRAND.configDir, "alias-domains.jso
|
|
|
20848
20840
|
function loadAliasDomains() {
|
|
20849
20841
|
try {
|
|
20850
20842
|
if (!existsSync23(ALIAS_DOMAINS_PATH2)) return null;
|
|
20851
|
-
const parsed = JSON.parse(
|
|
20843
|
+
const parsed = JSON.parse(readFileSync25(ALIAS_DOMAINS_PATH2, "utf-8"));
|
|
20852
20844
|
if (!Array.isArray(parsed)) {
|
|
20853
20845
|
console.error("[alias-domains] malformed alias-domains.json \u2014 expected array");
|
|
20854
20846
|
return null;
|
|
@@ -20872,9 +20864,9 @@ watchFile(ALIAS_DOMAINS_PATH2, { interval: 2e3 }, () => {
|
|
|
20872
20864
|
function isPublicHost(host) {
|
|
20873
20865
|
return host.startsWith("public.") || aliasDomains.has(host);
|
|
20874
20866
|
}
|
|
20875
|
-
var
|
|
20876
|
-
|
|
20877
|
-
|
|
20867
|
+
var app34 = new Hono2();
|
|
20868
|
+
app34.use("*", clientIpMiddleware);
|
|
20869
|
+
app34.use("*", async (c, next) => {
|
|
20878
20870
|
await next();
|
|
20879
20871
|
c.header("X-Content-Type-Options", "nosniff");
|
|
20880
20872
|
c.header("Referrer-Policy", "strict-origin-when-cross-origin");
|
|
@@ -20897,7 +20889,7 @@ var PUBLIC_ALLOWED_PREFIXES = [
|
|
|
20897
20889
|
"/g/"
|
|
20898
20890
|
];
|
|
20899
20891
|
var PUBLIC_ALLOWED_EXACT = ["/favicon.ico"];
|
|
20900
|
-
|
|
20892
|
+
app34.use("*", async (c, next) => {
|
|
20901
20893
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
20902
20894
|
if (!isPublicHost(host)) {
|
|
20903
20895
|
await next();
|
|
@@ -20937,7 +20929,7 @@ function resolveRemoteAuthOpts() {
|
|
|
20937
20929
|
return brandLoginOpts;
|
|
20938
20930
|
}
|
|
20939
20931
|
var MAX_LOGIN_BODY = 8 * 1024;
|
|
20940
|
-
|
|
20932
|
+
app34.post("/__remote-auth/login", async (c) => {
|
|
20941
20933
|
const clientIp = c.var.clientIp || "unknown";
|
|
20942
20934
|
const rateLimited = checkRateLimit(clientIp);
|
|
20943
20935
|
if (rateLimited) {
|
|
@@ -20973,10 +20965,7 @@ app35.post("/__remote-auth/login", async (c) => {
|
|
|
20973
20965
|
}
|
|
20974
20966
|
});
|
|
20975
20967
|
});
|
|
20976
|
-
|
|
20977
|
-
const cookieHeader = c.req.header("cookie");
|
|
20978
|
-
const token = parseCookie(cookieHeader, "__remote_session");
|
|
20979
|
-
if (token) invalidateRemoteSession(token);
|
|
20968
|
+
app34.get("/__remote-auth/logout", () => {
|
|
20980
20969
|
return new Response(null, {
|
|
20981
20970
|
status: 302,
|
|
20982
20971
|
headers: {
|
|
@@ -20986,7 +20975,7 @@ app35.get("/__remote-auth/logout", (c) => {
|
|
|
20986
20975
|
}
|
|
20987
20976
|
});
|
|
20988
20977
|
});
|
|
20989
|
-
|
|
20978
|
+
app34.post("/__remote-auth/change-password", async (c) => {
|
|
20990
20979
|
const clientIp = c.var.clientIp || "unknown";
|
|
20991
20980
|
const rateLimited = checkRateLimit(clientIp);
|
|
20992
20981
|
if (rateLimited) {
|
|
@@ -21035,13 +21024,13 @@ app35.post("/__remote-auth/change-password", async (c) => {
|
|
|
21035
21024
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "change", changeError: "Failed to save password", redirect }), 200);
|
|
21036
21025
|
}
|
|
21037
21026
|
});
|
|
21038
|
-
|
|
21027
|
+
app34.get("/__remote-auth/setup", (c) => {
|
|
21039
21028
|
if (isRemoteAuthConfigured()) {
|
|
21040
21029
|
return c.redirect("/");
|
|
21041
21030
|
}
|
|
21042
21031
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "setup" }), 200);
|
|
21043
21032
|
});
|
|
21044
|
-
|
|
21033
|
+
app34.post("/__remote-auth/set-initial-password", async (c) => {
|
|
21045
21034
|
if (isRemoteAuthConfigured()) {
|
|
21046
21035
|
return c.redirect("/");
|
|
21047
21036
|
}
|
|
@@ -21077,10 +21066,10 @@ app35.post("/__remote-auth/set-initial-password", async (c) => {
|
|
|
21077
21066
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "setup", setupError: "Failed to save password. Please try again." }), 200);
|
|
21078
21067
|
}
|
|
21079
21068
|
});
|
|
21080
|
-
|
|
21069
|
+
app34.get("/api/remote-auth/status", (c) => {
|
|
21081
21070
|
return c.json({ configured: isRemoteAuthConfigured() });
|
|
21082
21071
|
});
|
|
21083
|
-
|
|
21072
|
+
app34.post("/api/remote-auth/set-password", async (c) => {
|
|
21084
21073
|
let body;
|
|
21085
21074
|
try {
|
|
21086
21075
|
body = await c.req.json();
|
|
@@ -21110,9 +21099,9 @@ app35.post("/api/remote-auth/set-password", async (c) => {
|
|
|
21110
21099
|
return c.json({ error: "Failed to save password" }, 500);
|
|
21111
21100
|
}
|
|
21112
21101
|
});
|
|
21113
|
-
|
|
21102
|
+
app34.route("/api/_client-error", client_error_default);
|
|
21114
21103
|
console.log("[client-error-route] mounted");
|
|
21115
|
-
|
|
21104
|
+
app34.use("*", async (c, next) => {
|
|
21116
21105
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
21117
21106
|
const path2 = c.req.path;
|
|
21118
21107
|
if (path2 === "/favicon.ico" || path2.startsWith("/assets/") || path2.startsWith("/brand/")) {
|
|
@@ -21142,25 +21131,15 @@ app35.use("*", async (c, next) => {
|
|
|
21142
21131
|
console.error(`[remote-auth] login required ip=${clientIp} path=${path2}`);
|
|
21143
21132
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), redirect: path2 }), 200);
|
|
21144
21133
|
});
|
|
21145
|
-
|
|
21146
|
-
|
|
21147
|
-
|
|
21148
|
-
|
|
21149
|
-
|
|
21150
|
-
|
|
21151
|
-
|
|
21152
|
-
|
|
21153
|
-
|
|
21154
|
-
}
|
|
21155
|
-
app35.route("/api/health", health_default);
|
|
21156
|
-
app35.route("/api/session", session_default);
|
|
21157
|
-
app35.route("/api/chat", chat_default);
|
|
21158
|
-
app35.route("/api/group", group_default);
|
|
21159
|
-
app35.route("/api/access", access_default);
|
|
21160
|
-
app35.route("/api/telegram", telegram_default);
|
|
21161
|
-
app35.route("/api/whatsapp", whatsapp_default);
|
|
21162
|
-
app35.route("/api/onboarding", onboarding_default);
|
|
21163
|
-
app35.route("/api/admin", admin_default);
|
|
21134
|
+
app34.route("/api/health", health_default);
|
|
21135
|
+
app34.route("/api/session", session_default);
|
|
21136
|
+
app34.route("/api/chat", chat_default);
|
|
21137
|
+
app34.route("/api/group", group_default);
|
|
21138
|
+
app34.route("/api/access", access_default);
|
|
21139
|
+
app34.route("/api/telegram", telegram_default);
|
|
21140
|
+
app34.route("/api/whatsapp", whatsapp_default);
|
|
21141
|
+
app34.route("/api/onboarding", onboarding_default);
|
|
21142
|
+
app34.route("/api/admin", admin_default);
|
|
21164
21143
|
var SAFE_SLUG_RE = /^[a-z][a-z0-9-]{2,49}$/;
|
|
21165
21144
|
var SAFE_FILENAME_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
|
|
21166
21145
|
var IMAGE_MIME = {
|
|
@@ -21172,7 +21151,7 @@ var IMAGE_MIME = {
|
|
|
21172
21151
|
".svg": "image/svg+xml",
|
|
21173
21152
|
".ico": "image/x-icon"
|
|
21174
21153
|
};
|
|
21175
|
-
|
|
21154
|
+
app34.get("/agent-assets/:slug/:filename", (c) => {
|
|
21176
21155
|
const slug = c.req.param("slug");
|
|
21177
21156
|
const filename = c.req.param("filename");
|
|
21178
21157
|
if (!SAFE_SLUG_RE.test(slug)) {
|
|
@@ -21201,13 +21180,13 @@ app35.get("/agent-assets/:slug/:filename", (c) => {
|
|
|
21201
21180
|
const ext = "." + filename.split(".").pop()?.toLowerCase();
|
|
21202
21181
|
const contentType = IMAGE_MIME[ext] || "application/octet-stream";
|
|
21203
21182
|
console.log(`[agent-assets] serve slug=${slug} file=${filename} status=200`);
|
|
21204
|
-
const body =
|
|
21183
|
+
const body = readFileSync25(filePath);
|
|
21205
21184
|
return c.body(body, 200, {
|
|
21206
21185
|
"Content-Type": contentType,
|
|
21207
21186
|
"Cache-Control": "public, max-age=3600"
|
|
21208
21187
|
});
|
|
21209
21188
|
});
|
|
21210
|
-
|
|
21189
|
+
app34.get("/generated/:filename", (c) => {
|
|
21211
21190
|
const filename = c.req.param("filename");
|
|
21212
21191
|
if (!SAFE_FILENAME_RE.test(filename) || filename.includes("..")) {
|
|
21213
21192
|
console.error(`[generated] serve file=${filename} status=403`);
|
|
@@ -21231,7 +21210,7 @@ app35.get("/generated/:filename", (c) => {
|
|
|
21231
21210
|
const ext = "." + filename.split(".").pop()?.toLowerCase();
|
|
21232
21211
|
const contentType = IMAGE_MIME[ext] || "application/octet-stream";
|
|
21233
21212
|
console.log(`[generated] serve file=${filename} status=200`);
|
|
21234
|
-
const body =
|
|
21213
|
+
const body = readFileSync25(filePath);
|
|
21235
21214
|
return c.body(body, 200, {
|
|
21236
21215
|
"Content-Type": contentType,
|
|
21237
21216
|
"Cache-Control": "public, max-age=86400"
|
|
@@ -21242,7 +21221,7 @@ var brandLogoPath = "/brand/maxy-monochrome.png";
|
|
|
21242
21221
|
var brandIconPath = "/brand/maxy-monochrome.png";
|
|
21243
21222
|
if (BRAND_JSON_PATH && existsSync23(BRAND_JSON_PATH)) {
|
|
21244
21223
|
try {
|
|
21245
|
-
const fullBrand = JSON.parse(
|
|
21224
|
+
const fullBrand = JSON.parse(readFileSync25(BRAND_JSON_PATH, "utf-8"));
|
|
21246
21225
|
if (fullBrand.assets?.logo) brandLogoPath = `/brand/${fullBrand.assets.logo}`;
|
|
21247
21226
|
brandIconPath = fullBrand.assets?.icon ? `/brand/${fullBrand.assets.icon}` : brandLogoPath;
|
|
21248
21227
|
} catch {
|
|
@@ -21261,7 +21240,7 @@ function readInstalledVersion() {
|
|
|
21261
21240
|
if (!PLATFORM_ROOT10) return "unknown";
|
|
21262
21241
|
const versionFile = join12(PLATFORM_ROOT10, "config", `.${BRAND.hostname}-version`);
|
|
21263
21242
|
if (!existsSync23(versionFile)) return "unknown";
|
|
21264
|
-
const content =
|
|
21243
|
+
const content = readFileSync25(versionFile, "utf-8").trim();
|
|
21265
21244
|
return content || "unknown";
|
|
21266
21245
|
} catch {
|
|
21267
21246
|
return "unknown";
|
|
@@ -21302,7 +21281,7 @@ var clientErrorReporterScript = `<script>
|
|
|
21302
21281
|
function cachedHtml(file) {
|
|
21303
21282
|
let html = htmlCache.get(file);
|
|
21304
21283
|
if (!html) {
|
|
21305
|
-
html =
|
|
21284
|
+
html = readFileSync25(resolve27(process.cwd(), "public", file), "utf-8");
|
|
21306
21285
|
html = html.replace("<title>Maxy</title>", `<title>${escapeHtml(BRAND.productName)}</title>`);
|
|
21307
21286
|
html = html.replace('href="/favicon.ico"', `href="${escapeHtml(brandFaviconPath)}"`);
|
|
21308
21287
|
const headInjection = file === "index.html" ? `${brandScript}
|
|
@@ -21321,12 +21300,12 @@ function loadBrandingCache(agentSlug) {
|
|
|
21321
21300
|
try {
|
|
21322
21301
|
const accountJsonPath = join12(configDir2, "account.json");
|
|
21323
21302
|
if (!existsSync23(accountJsonPath)) return null;
|
|
21324
|
-
const account = JSON.parse(
|
|
21303
|
+
const account = JSON.parse(readFileSync25(accountJsonPath, "utf-8"));
|
|
21325
21304
|
const accountId = account.accountId;
|
|
21326
21305
|
if (!accountId) return null;
|
|
21327
21306
|
const cachePath = join12(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
|
|
21328
21307
|
if (!existsSync23(cachePath)) return null;
|
|
21329
|
-
return JSON.parse(
|
|
21308
|
+
return JSON.parse(readFileSync25(cachePath, "utf-8"));
|
|
21330
21309
|
} catch {
|
|
21331
21310
|
return null;
|
|
21332
21311
|
}
|
|
@@ -21336,7 +21315,7 @@ function resolveDefaultSlug() {
|
|
|
21336
21315
|
const configDir2 = join12(homedir4(), BRAND.configDir);
|
|
21337
21316
|
const accountJsonPath = join12(configDir2, "account.json");
|
|
21338
21317
|
if (!existsSync23(accountJsonPath)) return null;
|
|
21339
|
-
const account = JSON.parse(
|
|
21318
|
+
const account = JSON.parse(readFileSync25(accountJsonPath, "utf-8"));
|
|
21340
21319
|
return account.defaultAgent || null;
|
|
21341
21320
|
} catch {
|
|
21342
21321
|
return null;
|
|
@@ -21372,7 +21351,7 @@ function brandedPublicHtml(agentSlug) {
|
|
|
21372
21351
|
function escapeHtml(s) {
|
|
21373
21352
|
return s.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
21374
21353
|
}
|
|
21375
|
-
|
|
21354
|
+
app34.get("/", (c) => {
|
|
21376
21355
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
21377
21356
|
if (isPublicHost(host)) {
|
|
21378
21357
|
const defaultSlug = resolveDefaultSlug();
|
|
@@ -21380,12 +21359,12 @@ app35.get("/", (c) => {
|
|
|
21380
21359
|
}
|
|
21381
21360
|
return c.html(cachedHtml("index.html"));
|
|
21382
21361
|
});
|
|
21383
|
-
|
|
21362
|
+
app34.get("/public", (c) => {
|
|
21384
21363
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
21385
21364
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
21386
21365
|
return c.html(cachedHtml("public.html"));
|
|
21387
21366
|
});
|
|
21388
|
-
|
|
21367
|
+
app34.get("/chat", (c) => {
|
|
21389
21368
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
21390
21369
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
21391
21370
|
return c.html(cachedHtml("public.html"));
|
|
@@ -21404,12 +21383,12 @@ async function logViewerFetch(c, next) {
|
|
|
21404
21383
|
duration_ms: Date.now() - start
|
|
21405
21384
|
});
|
|
21406
21385
|
}
|
|
21407
|
-
|
|
21408
|
-
|
|
21409
|
-
|
|
21386
|
+
app34.use("/vnc-viewer.html", logViewerFetch);
|
|
21387
|
+
app34.use("/vnc-popout.html", logViewerFetch);
|
|
21388
|
+
app34.get("/vnc-popout.html", (c) => {
|
|
21410
21389
|
let html = htmlCache.get("vnc-popout.html");
|
|
21411
21390
|
if (!html) {
|
|
21412
|
-
html =
|
|
21391
|
+
html = readFileSync25(resolve27(process.cwd(), "public", "vnc-popout.html"), "utf-8");
|
|
21413
21392
|
const name = escapeHtml(BRAND.productName);
|
|
21414
21393
|
html = html.replace("<title>Browser \u2014 Maxy</title>", `<title>${name}</title>`);
|
|
21415
21394
|
html = html.replace("</head>", ` ${brandScript}
|
|
@@ -21419,7 +21398,7 @@ app35.get("/vnc-popout.html", (c) => {
|
|
|
21419
21398
|
}
|
|
21420
21399
|
return c.html(html);
|
|
21421
21400
|
});
|
|
21422
|
-
|
|
21401
|
+
app34.post("/api/vnc/client-event", async (c) => {
|
|
21423
21402
|
let body;
|
|
21424
21403
|
try {
|
|
21425
21404
|
body = await c.req.json();
|
|
@@ -21440,20 +21419,20 @@ app35.post("/api/vnc/client-event", async (c) => {
|
|
|
21440
21419
|
});
|
|
21441
21420
|
return c.json({ ok: true });
|
|
21442
21421
|
});
|
|
21443
|
-
|
|
21422
|
+
app34.get("/g/:slug", (c) => {
|
|
21444
21423
|
return c.html(brandedPublicHtml());
|
|
21445
21424
|
});
|
|
21446
|
-
|
|
21425
|
+
app34.get("/graph", (c) => {
|
|
21447
21426
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
21448
21427
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
21449
21428
|
return c.html(cachedHtml("graph.html"));
|
|
21450
21429
|
});
|
|
21451
|
-
|
|
21430
|
+
app34.get("/data", (c) => {
|
|
21452
21431
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
21453
21432
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
21454
21433
|
return c.html(cachedHtml("data.html"));
|
|
21455
21434
|
});
|
|
21456
|
-
|
|
21435
|
+
app34.get("/:slug", async (c, next) => {
|
|
21457
21436
|
const slug = c.req.param("slug");
|
|
21458
21437
|
if (AGENT_SLUG_PATTERN.test(`/${slug}`)) {
|
|
21459
21438
|
const branding = loadBrandingCache(slug);
|
|
@@ -21462,10 +21441,10 @@ app35.get("/:slug", async (c, next) => {
|
|
|
21462
21441
|
}
|
|
21463
21442
|
await next();
|
|
21464
21443
|
});
|
|
21465
|
-
|
|
21444
|
+
app34.use("/*", serveStatic({ root: "./public" }));
|
|
21466
21445
|
var port = parseInt(process.env.PORT ?? "19199", 10);
|
|
21467
21446
|
var hostname = process.env.HOSTNAME ?? "127.0.0.1";
|
|
21468
|
-
var httpServer = serve({ fetch:
|
|
21447
|
+
var httpServer = serve({ fetch: app34.fetch, port, hostname });
|
|
21469
21448
|
console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
21470
21449
|
var SUBAPP_MANIFEST = [
|
|
21471
21450
|
{ prefix: "/api/health", file: "server/routes/health.ts", subapp: health_default },
|
|
@@ -21485,7 +21464,7 @@ for (const m of SUBAPP_MANIFEST) {
|
|
|
21485
21464
|
}
|
|
21486
21465
|
try {
|
|
21487
21466
|
const registered = [];
|
|
21488
|
-
for (const r of
|
|
21467
|
+
for (const r of app34.routes ?? []) {
|
|
21489
21468
|
if (typeof r.path !== "string" || r.path.includes(":") || r.path.includes("*")) continue;
|
|
21490
21469
|
if (AGENT_SLUG_PATTERN.test(r.path)) {
|
|
21491
21470
|
registered.push({ method: (r.method ?? "ALL").toUpperCase(), path: r.path });
|
|
@@ -21500,7 +21479,7 @@ try {
|
|
|
21500
21479
|
try {
|
|
21501
21480
|
let userId = "";
|
|
21502
21481
|
if (existsSync23(USERS_FILE)) {
|
|
21503
|
-
const users = JSON.parse(
|
|
21482
|
+
const users = JSON.parse(readFileSync25(USERS_FILE, "utf-8").trim() || "[]");
|
|
21504
21483
|
userId = users[0]?.userId ?? "";
|
|
21505
21484
|
}
|
|
21506
21485
|
await backfillNullUserIdConversations(userId);
|