@rubytech/create-realagent 1.0.663 → 1.0.665
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 +5 -1
- package/package.json +1 -1
- package/payload/platform/neo4j/schema.cypher +34 -1
- package/payload/platform/plugins/docs/references/memory-guide.md +2 -2
- package/payload/platform/plugins/docs/references/platform.md +1 -1
- package/payload/platform/plugins/docs/references/troubleshooting.md +24 -6
- package/payload/platform/scripts/vnc.sh +174 -2
- package/payload/server/public/assets/{admin-C9qoVb2l.js → admin-Brug36E-.js} +5 -5
- package/payload/server/public/assets/data-woLf2Tmp.js +1 -0
- package/payload/server/public/assets/{file-lmzx24EO.js → file-rN5uuyaV.js} +1 -1
- package/payload/server/public/assets/{graph-DkjvCb8B.js → graph-BYaOEZUg.js} +16 -16
- package/payload/server/public/assets/{house-ClhI06TA.js → house-DnFgpCt2.js} +1 -1
- package/payload/server/public/assets/jsx-runtime-CSCPZpLN.css +1 -0
- package/payload/server/public/assets/{public-Dz33-dIE.js → public-BRrqpeVH.js} +1 -1
- package/payload/server/public/assets/{share-2-MZ4MqbjS.js → share-2-DLjRUEiG.js} +1 -1
- package/payload/server/public/assets/{useVoiceRecorder-Cm0G51D_.js → useVoiceRecorder-D_efR3Nx.js} +1 -1
- package/payload/server/public/assets/{x-CLhtM_Mh.js → x-L6KPMfIN.js} +1 -1
- package/payload/server/public/data.html +6 -6
- package/payload/server/public/graph.html +6 -6
- package/payload/server/public/index.html +7 -7
- package/payload/server/public/public.html +4 -4
- package/payload/server/server.js +360 -126
- package/payload/platform/plugins/admin/mcp/dist/lib/onboarding.test.d.ts +0 -2
- package/payload/platform/plugins/admin/mcp/dist/lib/onboarding.test.d.ts.map +0 -1
- package/payload/platform/plugins/admin/mcp/dist/lib/onboarding.test.js +0 -224
- package/payload/platform/plugins/admin/mcp/dist/lib/onboarding.test.js.map +0 -1
- package/payload/platform/plugins/documents/mcp/dist/index.d.ts +0 -2
- package/payload/platform/plugins/documents/mcp/dist/index.d.ts.map +0 -1
- package/payload/platform/plugins/documents/mcp/dist/index.js +0 -98
- package/payload/platform/plugins/documents/mcp/dist/index.js.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/semantic-chunker.test.d.ts +0 -2
- package/payload/platform/plugins/memory/mcp/dist/lib/semantic-chunker.test.d.ts.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/semantic-chunker.test.js +0 -233
- package/payload/platform/plugins/memory/mcp/dist/lib/semantic-chunker.test.js.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/scripts/graph-prune.d.ts +0 -18
- package/payload/platform/plugins/memory/mcp/dist/scripts/graph-prune.d.ts.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/scripts/graph-prune.js +0 -80
- package/payload/platform/plugins/memory/mcp/dist/scripts/graph-prune.js.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/graph-prune-run.d.ts +0 -7
- package/payload/platform/plugins/memory/mcp/dist/tools/graph-prune-run.d.ts.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/graph-prune-run.js +0 -10
- package/payload/platform/plugins/memory/mcp/dist/tools/graph-prune-run.js.map +0 -1
- package/payload/platform/plugins/waitlist/mcp/dist/lib/anthropic.d.ts +0 -23
- package/payload/platform/plugins/waitlist/mcp/dist/lib/anthropic.d.ts.map +0 -1
- package/payload/platform/plugins/waitlist/mcp/dist/lib/anthropic.js +0 -115
- package/payload/platform/plugins/waitlist/mcp/dist/lib/anthropic.js.map +0 -1
- package/payload/platform/plugins/waitlist/mcp/dist/tools/waitlist-extract.d.ts +0 -12
- package/payload/platform/plugins/waitlist/mcp/dist/tools/waitlist-extract.d.ts.map +0 -1
- package/payload/platform/plugins/waitlist/mcp/dist/tools/waitlist-extract.js +0 -197
- package/payload/platform/plugins/waitlist/mcp/dist/tools/waitlist-extract.js.map +0 -1
- package/payload/server/public/assets/data-C-WE3FGr.js +0 -1
- package/payload/server/public/assets/jsx-runtime-CLCFnMYD.css +0 -1
- /package/payload/server/public/assets/{jsx-runtime-ImbU973I.js → jsx-runtime-XWiDQoTG.js} +0 -0
package/payload/server/server.js
CHANGED
|
@@ -1201,14 +1201,14 @@ var Hono = class _Hono {
|
|
|
1201
1201
|
* app.route("/api", app2) // GET /api/user
|
|
1202
1202
|
* ```
|
|
1203
1203
|
*/
|
|
1204
|
-
route(path2,
|
|
1204
|
+
route(path2, app36) {
|
|
1205
1205
|
const subApp = this.basePath(path2);
|
|
1206
|
-
|
|
1206
|
+
app36.routes.map((r) => {
|
|
1207
1207
|
let handler;
|
|
1208
|
-
if (
|
|
1208
|
+
if (app36.errorHandler === errorHandler) {
|
|
1209
1209
|
handler = r.handler;
|
|
1210
1210
|
} else {
|
|
1211
|
-
handler = async (c, next) => (await compose([],
|
|
1211
|
+
handler = async (c, next) => (await compose([], app36.errorHandler)(c, () => r.handler(c, next))).res;
|
|
1212
1212
|
handler[COMPOSED_HANDLER] = r.handler;
|
|
1213
1213
|
}
|
|
1214
1214
|
subApp.#addRoute(r.method, r.path, handler);
|
|
@@ -4501,6 +4501,7 @@ function resolveBrowserTransport(req, remoteAddress) {
|
|
|
4501
4501
|
return transport;
|
|
4502
4502
|
}
|
|
4503
4503
|
var currentCdpDisplay = null;
|
|
4504
|
+
var currentTerminalDisplay = null;
|
|
4504
4505
|
function discoverNativeDisplay() {
|
|
4505
4506
|
const fallback = { sessionType: "x11", display: ":0", waylandDisplay: "" };
|
|
4506
4507
|
try {
|
|
@@ -4671,6 +4672,73 @@ async function ensureCdp(transport = "vnc") {
|
|
|
4671
4672
|
function killChromium() {
|
|
4672
4673
|
spawnSync("pkill", ["-f", "chromium"], { stdio: "pipe" });
|
|
4673
4674
|
}
|
|
4675
|
+
function terminalAlive() {
|
|
4676
|
+
const result = spawnSync("bash", [VNC_SCRIPT, "status-terminal"], {
|
|
4677
|
+
stdio: "pipe",
|
|
4678
|
+
timeout: 2e3
|
|
4679
|
+
});
|
|
4680
|
+
return result.status === 0;
|
|
4681
|
+
}
|
|
4682
|
+
async function ensureTerminal(transport = "vnc") {
|
|
4683
|
+
const targetSentinel = transport === "native" ? "native" : ":99";
|
|
4684
|
+
if (terminalAlive()) {
|
|
4685
|
+
if (currentTerminalDisplay !== null && currentTerminalDisplay !== targetSentinel) {
|
|
4686
|
+
console.error(`[ensureTerminal] Display switch: ${currentTerminalDisplay} \u2192 ${targetSentinel}`);
|
|
4687
|
+
vncLog("ensure-terminal", {
|
|
4688
|
+
action: "display-switch",
|
|
4689
|
+
transport,
|
|
4690
|
+
from_display: currentTerminalDisplay,
|
|
4691
|
+
to_display: targetSentinel
|
|
4692
|
+
});
|
|
4693
|
+
killTerminal();
|
|
4694
|
+
await sleep(500);
|
|
4695
|
+
} else {
|
|
4696
|
+
if (currentTerminalDisplay === null) {
|
|
4697
|
+
currentTerminalDisplay = targetSentinel;
|
|
4698
|
+
}
|
|
4699
|
+
vncLog("ensure-terminal", { action: "already-running", transport });
|
|
4700
|
+
return true;
|
|
4701
|
+
}
|
|
4702
|
+
}
|
|
4703
|
+
const vncCommand = transport === "native" ? "start-terminal-native" : "start-terminal";
|
|
4704
|
+
if (transport === "vnc") {
|
|
4705
|
+
const xAlive = await waitForPort(5900, 1e3);
|
|
4706
|
+
if (!xAlive) {
|
|
4707
|
+
console.error("[ensureTerminal] X server down on :5900 \u2014 escalating to full VNC restart");
|
|
4708
|
+
vncLog("ensure-terminal", { action: "escalate-vnc-restart", reason: "x-down", transport });
|
|
4709
|
+
const vncOk = await ensureVnc();
|
|
4710
|
+
if (!vncOk) {
|
|
4711
|
+
console.error("[ensureTerminal] Full VNC restart failed \u2014 terminal degraded");
|
|
4712
|
+
vncLog("ensure-terminal", { action: "degraded", reason: "vnc-restart-failed", transport });
|
|
4713
|
+
return false;
|
|
4714
|
+
}
|
|
4715
|
+
}
|
|
4716
|
+
}
|
|
4717
|
+
if (transport === "native") {
|
|
4718
|
+
const nativeInfo = discoverNativeDisplay();
|
|
4719
|
+
vncLog("ensure-terminal", {
|
|
4720
|
+
action: "native-display-resolved",
|
|
4721
|
+
transport,
|
|
4722
|
+
session_type: nativeInfo.sessionType,
|
|
4723
|
+
display: nativeInfo.display
|
|
4724
|
+
});
|
|
4725
|
+
}
|
|
4726
|
+
console.error(`[ensureTerminal] Launching terminal (${vncCommand}) for transport=${transport}`);
|
|
4727
|
+
vncLog("ensure-terminal", { action: `launch-${vncCommand}`, transport });
|
|
4728
|
+
try {
|
|
4729
|
+
execFileSync("bash", [VNC_SCRIPT, vncCommand], { timeout: 1e4 });
|
|
4730
|
+
} catch (err) {
|
|
4731
|
+
vncLog("ensure-terminal", { action: "launch-failed", transport, err: err.message });
|
|
4732
|
+
return false;
|
|
4733
|
+
}
|
|
4734
|
+
currentTerminalDisplay = targetSentinel;
|
|
4735
|
+
vncLog("ensure-terminal", { action: "launch-complete", transport, sentinel: targetSentinel });
|
|
4736
|
+
return true;
|
|
4737
|
+
}
|
|
4738
|
+
function killTerminal() {
|
|
4739
|
+
spawnSync("bash", [VNC_SCRIPT, "kill-terminal"], { stdio: "pipe", timeout: 5e3 });
|
|
4740
|
+
currentTerminalDisplay = null;
|
|
4741
|
+
}
|
|
4674
4742
|
function writeChromiumWrapper() {
|
|
4675
4743
|
mkdirSync4(BIN_DIR, { recursive: true });
|
|
4676
4744
|
const wrapperPath = resolve5(BIN_DIR, "chromium");
|
|
@@ -5212,9 +5280,11 @@ async function persistToolCall(record) {
|
|
|
5212
5280
|
await session.close();
|
|
5213
5281
|
}
|
|
5214
5282
|
}
|
|
5283
|
+
var SUMMARY_MAX_LEN = 200;
|
|
5215
5284
|
async function persistMessage(conversationId, role, content, accountId, tokens, createdAt, sender) {
|
|
5216
5285
|
if (!content) return null;
|
|
5217
5286
|
const messageId = randomUUID();
|
|
5287
|
+
const summary = role === "user" ? content.slice(0, SUMMARY_MAX_LEN).trim() : "";
|
|
5218
5288
|
let embedding = null;
|
|
5219
5289
|
try {
|
|
5220
5290
|
embedding = await embed(content);
|
|
@@ -5223,8 +5293,17 @@ async function persistMessage(conversationId, role, content, accountId, tokens,
|
|
|
5223
5293
|
}
|
|
5224
5294
|
const session = getSession();
|
|
5225
5295
|
try {
|
|
5226
|
-
await session.run(
|
|
5227
|
-
`
|
|
5296
|
+
const result = await session.run(
|
|
5297
|
+
`MATCH (c:Conversation {conversationId: $conversationId})
|
|
5298
|
+
OPTIONAL MATCH (tail:Message)-[:PART_OF]->(c)
|
|
5299
|
+
WHERE NOT (tail)-[:NEXT]->(:Message)
|
|
5300
|
+
// Capture whether THIS write's guard will fire. Read c.summary
|
|
5301
|
+
// before the SET so the boolean reflects the pre-state, not the
|
|
5302
|
+
// post-state \u2014 a false positive otherwise when a new user message
|
|
5303
|
+
// happens to equal an already-set summary (verbatim retry, short
|
|
5304
|
+
// catchphrase) and fooled a post-state equality check.
|
|
5305
|
+
WITH c, tail, (c.summary IS NULL AND $role = 'user' AND $summary <> '') AS summarySetThisWrite
|
|
5306
|
+
CREATE (m:Message {
|
|
5228
5307
|
messageId: $messageId,
|
|
5229
5308
|
conversationId: $conversationId,
|
|
5230
5309
|
accountId: $accountId,
|
|
@@ -5238,16 +5317,24 @@ async function persistMessage(conversationId, role, content, accountId, tokens,
|
|
|
5238
5317
|
${tokens?.cacheReadTokens != null ? ", cacheReadTokens: $cacheReadTokens" : ""}
|
|
5239
5318
|
${tokens?.cacheCreationTokens != null ? ", cacheCreationTokens: $cacheCreationTokens" : ""}
|
|
5240
5319
|
})
|
|
5241
|
-
WITH m
|
|
5242
|
-
MATCH (c:Conversation {conversationId: $conversationId})
|
|
5243
5320
|
SET c.updatedAt = datetime()
|
|
5244
|
-
CREATE (m)-[:PART_OF]->(c)
|
|
5321
|
+
CREATE (m)-[:PART_OF]->(c)
|
|
5322
|
+
FOREACH (prev IN CASE WHEN tail IS NULL THEN [] ELSE [tail] END |
|
|
5323
|
+
CREATE (prev)-[:NEXT]->(m)
|
|
5324
|
+
)
|
|
5325
|
+
FOREACH (_ IN CASE WHEN summarySetThisWrite THEN [1] ELSE [] END |
|
|
5326
|
+
SET c.summary = $summary
|
|
5327
|
+
)
|
|
5328
|
+
RETURN tail.messageId AS prevMessageId,
|
|
5329
|
+
summarySetThisWrite,
|
|
5330
|
+
size([(m2:Message)-[:PART_OF]->(c) | m2]) AS chainLen`,
|
|
5245
5331
|
{
|
|
5246
5332
|
messageId,
|
|
5247
5333
|
conversationId,
|
|
5248
5334
|
accountId,
|
|
5249
5335
|
role,
|
|
5250
5336
|
content,
|
|
5337
|
+
summary,
|
|
5251
5338
|
...createdAt ? { createdAt } : {},
|
|
5252
5339
|
...embedding ? { embedding } : {},
|
|
5253
5340
|
...sender ? { senderVisitorId: sender.visitorId, senderName: sender.displayName } : {},
|
|
@@ -5257,6 +5344,19 @@ async function persistMessage(conversationId, role, content, accountId, tokens,
|
|
|
5257
5344
|
...tokens?.cacheCreationTokens != null ? { cacheCreationTokens: neo4j.int(tokens.cacheCreationTokens) } : {}
|
|
5258
5345
|
}
|
|
5259
5346
|
);
|
|
5347
|
+
if (result.records.length === 0) {
|
|
5348
|
+
console.error(`[persist] Neo4j write skipped \u2014 conversation not found: ${conversationId.slice(0, 8)}\u2026`);
|
|
5349
|
+
return null;
|
|
5350
|
+
}
|
|
5351
|
+
const record = result.records[0];
|
|
5352
|
+
const prevMessageId = record.get("prevMessageId") ?? null;
|
|
5353
|
+
const summarySetThisWrite = record.get("summarySetThisWrite") === true;
|
|
5354
|
+
const chainLenRaw = record.get("chainLen");
|
|
5355
|
+
const chainLen = typeof chainLenRaw === "bigint" ? Number(chainLenRaw) : typeof chainLenRaw?.toNumber === "function" ? chainLenRaw.toNumber() : Number(chainLenRaw ?? 0);
|
|
5356
|
+
console.error(`[neo4j-store] append-message conversationId=${conversationId.slice(0, 8)}\u2026 messageId=${messageId.slice(0, 8)}\u2026 prev=${prevMessageId ? prevMessageId.slice(0, 8) + "\u2026" : "null"} chainLen=${chainLen}`);
|
|
5357
|
+
if (summarySetThisWrite) {
|
|
5358
|
+
console.error(`[neo4j-store] conversation-summary-set conversationId=${conversationId.slice(0, 8)}\u2026 len=${summary.length}`);
|
|
5359
|
+
}
|
|
5260
5360
|
console.error(`[persist] ${(/* @__PURE__ */ new Date()).toISOString()} conversationId=${conversationId.slice(0, 8)}\u2026 role=${role} len=${content.length}${sender ? ` sender=${sender.displayName}` : ""}`);
|
|
5261
5361
|
return messageId;
|
|
5262
5362
|
} catch (err) {
|
|
@@ -18461,7 +18561,16 @@ app9.post("/", async (c) => {
|
|
|
18461
18561
|
return c.text("Invalid JSON", 400);
|
|
18462
18562
|
}
|
|
18463
18563
|
const kindRaw = typeof body.kind === "string" ? body.kind : "unknown";
|
|
18464
|
-
const allowedKinds = /* @__PURE__ */ new Set([
|
|
18564
|
+
const allowedKinds = /* @__PURE__ */ new Set([
|
|
18565
|
+
"uncaught",
|
|
18566
|
+
"unhandled-rejection",
|
|
18567
|
+
"subresource",
|
|
18568
|
+
"test",
|
|
18569
|
+
"unknown",
|
|
18570
|
+
"graph-labels-in-graph",
|
|
18571
|
+
"graph-default-view",
|
|
18572
|
+
"graph-neighbourhood-pivot"
|
|
18573
|
+
]);
|
|
18465
18574
|
const kind = allowedKinds.has(kindRaw) ? kindRaw : "unknown";
|
|
18466
18575
|
const msg = truncate2(body.msg, MAX_MSG_LEN);
|
|
18467
18576
|
const url = truncate2(body.url, MAX_URL_LEN);
|
|
@@ -18550,6 +18659,41 @@ async function createAdminSession(accountId, thinkingView, userId, userName) {
|
|
|
18550
18659
|
};
|
|
18551
18660
|
}
|
|
18552
18661
|
var app10 = new Hono2();
|
|
18662
|
+
app10.get("/", async (c) => {
|
|
18663
|
+
const sessionKey = c.req.query("session_key");
|
|
18664
|
+
if (!sessionKey || !validateSession(sessionKey, "admin")) {
|
|
18665
|
+
return c.json({ error: "Invalid or expired admin session" }, 401);
|
|
18666
|
+
}
|
|
18667
|
+
const accountId = getAccountIdForSession(sessionKey);
|
|
18668
|
+
if (!accountId) {
|
|
18669
|
+
return c.json({ error: "Session has no account binding" }, 401);
|
|
18670
|
+
}
|
|
18671
|
+
const account = resolveAccount();
|
|
18672
|
+
const thinkingView = account?.config.thinkingView ?? "default";
|
|
18673
|
+
let onboardingComplete = true;
|
|
18674
|
+
try {
|
|
18675
|
+
const step = await loadOnboardingStep(accountId);
|
|
18676
|
+
onboardingComplete = step === null || step >= 8;
|
|
18677
|
+
} catch (err) {
|
|
18678
|
+
console.error(`[session] restore onboarding query failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
18679
|
+
}
|
|
18680
|
+
let businessName;
|
|
18681
|
+
try {
|
|
18682
|
+
const branding = await fetchBranding(accountId);
|
|
18683
|
+
businessName = branding?.name || void 0;
|
|
18684
|
+
} catch {
|
|
18685
|
+
}
|
|
18686
|
+
return c.json({
|
|
18687
|
+
session_key: sessionKey,
|
|
18688
|
+
agent_id: "admin",
|
|
18689
|
+
userId: getUserIdForSession(sessionKey),
|
|
18690
|
+
userName: getUserNameForSession(sessionKey),
|
|
18691
|
+
thinkingView,
|
|
18692
|
+
onboardingComplete,
|
|
18693
|
+
businessName,
|
|
18694
|
+
conversationId: getConversationIdForSession(sessionKey) ?? null
|
|
18695
|
+
});
|
|
18696
|
+
});
|
|
18553
18697
|
app10.post("/", async (c) => {
|
|
18554
18698
|
let body;
|
|
18555
18699
|
try {
|
|
@@ -19721,6 +19865,44 @@ app20.post("/launch", async (c) => {
|
|
|
19721
19865
|
});
|
|
19722
19866
|
var browser_default = app20;
|
|
19723
19867
|
|
|
19868
|
+
// server/routes/admin/terminal.ts
|
|
19869
|
+
var app21 = new Hono2();
|
|
19870
|
+
app21.post("/launch", async (c) => {
|
|
19871
|
+
try {
|
|
19872
|
+
const transport = resolveBrowserTransport(c.req.raw, c.env?.incoming?.socket?.remoteAddress);
|
|
19873
|
+
if (transport === "vnc") {
|
|
19874
|
+
const vncOk = await ensureVnc();
|
|
19875
|
+
if (!vncOk) {
|
|
19876
|
+
return c.json({ ok: false, error: "VNC failed to start" }, 502);
|
|
19877
|
+
}
|
|
19878
|
+
}
|
|
19879
|
+
const terminalOk = await ensureTerminal(transport);
|
|
19880
|
+
if (!terminalOk) {
|
|
19881
|
+
return c.json({ ok: false, error: "Terminal failed to start" }, 502);
|
|
19882
|
+
}
|
|
19883
|
+
return c.json({ ok: true, transport });
|
|
19884
|
+
} catch (err) {
|
|
19885
|
+
console.error("[admin/terminal/launch] Failed to start terminal:", err);
|
|
19886
|
+
return c.json(
|
|
19887
|
+
{ ok: false, error: err instanceof Error ? err.message : "Unknown error" },
|
|
19888
|
+
500
|
|
19889
|
+
);
|
|
19890
|
+
}
|
|
19891
|
+
});
|
|
19892
|
+
app21.post("/close", (c) => {
|
|
19893
|
+
try {
|
|
19894
|
+
killTerminal();
|
|
19895
|
+
return c.json({ ok: true });
|
|
19896
|
+
} catch (err) {
|
|
19897
|
+
console.error("[admin/terminal/close] kill failed:", err);
|
|
19898
|
+
return c.json(
|
|
19899
|
+
{ ok: false, error: err instanceof Error ? err.message : "Unknown error" },
|
|
19900
|
+
500
|
|
19901
|
+
);
|
|
19902
|
+
}
|
|
19903
|
+
});
|
|
19904
|
+
var terminal_default = app21;
|
|
19905
|
+
|
|
19724
19906
|
// app/lib/cdp-client.ts
|
|
19725
19907
|
var CDP_HOST = "127.0.0.1";
|
|
19726
19908
|
var CDP_PORT = 9222;
|
|
@@ -19762,8 +19944,8 @@ async function cdpNavigateNewTab(url, opts = {}) {
|
|
|
19762
19944
|
}
|
|
19763
19945
|
|
|
19764
19946
|
// server/routes/admin/device-browser.ts
|
|
19765
|
-
var
|
|
19766
|
-
|
|
19947
|
+
var app22 = new Hono2();
|
|
19948
|
+
app22.post("/navigate", async (c) => {
|
|
19767
19949
|
const TAG19 = "[device-url:click]";
|
|
19768
19950
|
let body;
|
|
19769
19951
|
try {
|
|
@@ -19850,7 +20032,7 @@ app21.post("/navigate", async (c) => {
|
|
|
19850
20032
|
targetId: outcome.targetId
|
|
19851
20033
|
});
|
|
19852
20034
|
});
|
|
19853
|
-
var device_browser_default =
|
|
20035
|
+
var device_browser_default = app22;
|
|
19854
20036
|
|
|
19855
20037
|
// server/routes/admin/events.ts
|
|
19856
20038
|
var ALLOWED_EVENTS = /* @__PURE__ */ new Set([
|
|
@@ -19859,8 +20041,8 @@ var ALLOWED_EVENTS = /* @__PURE__ */ new Set([
|
|
|
19859
20041
|
"device-url:vnc-surface-shown",
|
|
19860
20042
|
"device-url:malformed"
|
|
19861
20043
|
]);
|
|
19862
|
-
var
|
|
19863
|
-
|
|
20044
|
+
var app23 = new Hono2();
|
|
20045
|
+
app23.post("/", async (c) => {
|
|
19864
20046
|
const TAG19 = "[admin:events]";
|
|
19865
20047
|
let body;
|
|
19866
20048
|
try {
|
|
@@ -19891,7 +20073,7 @@ app22.post("/", async (c) => {
|
|
|
19891
20073
|
console.error(`[${event}] ${formatted}`);
|
|
19892
20074
|
return c.json({ ok: true });
|
|
19893
20075
|
});
|
|
19894
|
-
var events_default =
|
|
20076
|
+
var events_default = app23;
|
|
19895
20077
|
|
|
19896
20078
|
// server/routes/admin/cloudflare.ts
|
|
19897
20079
|
import { homedir as homedir4 } from "os";
|
|
@@ -19984,7 +20166,7 @@ function validateBody(body) {
|
|
|
19984
20166
|
}
|
|
19985
20167
|
return null;
|
|
19986
20168
|
}
|
|
19987
|
-
var
|
|
20169
|
+
var app24 = new Hono2();
|
|
19988
20170
|
function fieldFromReason(reason) {
|
|
19989
20171
|
switch (reason) {
|
|
19990
20172
|
case "not-signed-in":
|
|
@@ -20001,7 +20183,7 @@ function fieldFromReason(reason) {
|
|
|
20001
20183
|
return "script";
|
|
20002
20184
|
}
|
|
20003
20185
|
}
|
|
20004
|
-
|
|
20186
|
+
app24.get("/domains", requireAdminSession, async (c) => {
|
|
20005
20187
|
const started = Date.now();
|
|
20006
20188
|
const sessionKey = c.var.sessionKey;
|
|
20007
20189
|
let correlationId;
|
|
@@ -20094,7 +20276,7 @@ ${result.stderr}` : ""}`;
|
|
|
20094
20276
|
);
|
|
20095
20277
|
return c.json(success, 200);
|
|
20096
20278
|
});
|
|
20097
|
-
|
|
20279
|
+
app24.post("/setup", requireAdminSession, async (c) => {
|
|
20098
20280
|
const started = Date.now();
|
|
20099
20281
|
const sessionKey = c.var.sessionKey;
|
|
20100
20282
|
let correlationId;
|
|
@@ -20232,7 +20414,7 @@ ${result.stderr}` : ""}`;
|
|
|
20232
20414
|
log2(`phase=response-sent`);
|
|
20233
20415
|
return resp;
|
|
20234
20416
|
});
|
|
20235
|
-
var cloudflare_default =
|
|
20417
|
+
var cloudflare_default = app24;
|
|
20236
20418
|
|
|
20237
20419
|
// server/routes/admin/files.ts
|
|
20238
20420
|
import { createReadStream as createReadStream3 } from "fs";
|
|
@@ -20584,8 +20766,8 @@ function buildDisplayPath(relPath, accountNames) {
|
|
|
20584
20766
|
return dn ? { name: seg, displayName: dn } : { name: seg };
|
|
20585
20767
|
});
|
|
20586
20768
|
}
|
|
20587
|
-
var
|
|
20588
|
-
|
|
20769
|
+
var app25 = new Hono2();
|
|
20770
|
+
app25.get("/", requireAdminSession, async (c) => {
|
|
20589
20771
|
const sessionKey = c.var.sessionKey;
|
|
20590
20772
|
if (!getAccountIdForSession(sessionKey)) {
|
|
20591
20773
|
console.error(`[data] auth-rejected endpoint="/api/admin/files" reason="no account for session"`);
|
|
@@ -20646,7 +20828,7 @@ app24.get("/", requireAdminSession, async (c) => {
|
|
|
20646
20828
|
return c.json({ error: message }, 500);
|
|
20647
20829
|
}
|
|
20648
20830
|
});
|
|
20649
|
-
|
|
20831
|
+
app25.get("/download", requireAdminSession, async (c) => {
|
|
20650
20832
|
const sessionKey = c.var.sessionKey;
|
|
20651
20833
|
if (!getAccountIdForSession(sessionKey)) {
|
|
20652
20834
|
console.error(`[data] auth-rejected endpoint="/api/admin/files/download" reason="no account for session"`);
|
|
@@ -20694,7 +20876,7 @@ app24.get("/download", requireAdminSession, async (c) => {
|
|
|
20694
20876
|
return c.json({ error: message }, 500);
|
|
20695
20877
|
}
|
|
20696
20878
|
});
|
|
20697
|
-
|
|
20879
|
+
app25.post("/upload", requireAdminSession, async (c) => {
|
|
20698
20880
|
const sessionKey = c.var.sessionKey;
|
|
20699
20881
|
const accountId = getAccountIdForSession(sessionKey);
|
|
20700
20882
|
if (!accountId) {
|
|
@@ -20752,7 +20934,7 @@ app24.post("/upload", requireAdminSession, async (c) => {
|
|
|
20752
20934
|
mimeType: file.type
|
|
20753
20935
|
});
|
|
20754
20936
|
});
|
|
20755
|
-
|
|
20937
|
+
app25.delete("/", requireAdminSession, async (c) => {
|
|
20756
20938
|
const sessionKey = c.var.sessionKey;
|
|
20757
20939
|
const accountId = getAccountIdForSession(sessionKey);
|
|
20758
20940
|
if (!accountId) {
|
|
@@ -20819,13 +21001,13 @@ app24.delete("/", requireAdminSession, async (c) => {
|
|
|
20819
21001
|
return c.json({ error: message }, 500);
|
|
20820
21002
|
}
|
|
20821
21003
|
});
|
|
20822
|
-
var files_default =
|
|
21004
|
+
var files_default = app25;
|
|
20823
21005
|
|
|
20824
21006
|
// server/routes/admin/graph-search.ts
|
|
20825
21007
|
var DEFAULT_LIMIT = 20;
|
|
20826
21008
|
var MAX_LIMIT = 100;
|
|
20827
|
-
var
|
|
20828
|
-
|
|
21009
|
+
var app26 = new Hono2();
|
|
21010
|
+
app26.get("/", requireAdminSession, async (c) => {
|
|
20829
21011
|
const sessionKey = c.var.sessionKey;
|
|
20830
21012
|
const q = (c.req.query("q") ?? "").trim();
|
|
20831
21013
|
const rawLimit = c.req.query("limit");
|
|
@@ -20850,7 +21032,10 @@ app25.get("/", requireAdminSession, async (c) => {
|
|
|
20850
21032
|
return c.json({ error: `Graph search unavailable: ${message}` }, 503);
|
|
20851
21033
|
}
|
|
20852
21034
|
});
|
|
20853
|
-
var graph_search_default =
|
|
21035
|
+
var graph_search_default = app26;
|
|
21036
|
+
|
|
21037
|
+
// server/routes/admin/graph-subgraph.ts
|
|
21038
|
+
import neo4j3 from "neo4j-driver";
|
|
20854
21039
|
|
|
20855
21040
|
// app/lib/graph-labels.ts
|
|
20856
21041
|
var GRAPH_LABEL_COLOURS = {
|
|
@@ -20893,7 +21078,13 @@ var GRAPH_LABEL_COLOURS = {
|
|
|
20893
21078
|
OnboardingState: "#8B5CF6",
|
|
20894
21079
|
// Email
|
|
20895
21080
|
Email: "#65A30D",
|
|
20896
|
-
EmailAccount: "#84CC16"
|
|
21081
|
+
EmailAccount: "#84CC16",
|
|
21082
|
+
// Review signals (Task 626 — previously written by review-detector but
|
|
21083
|
+
// unregistered here, producing an `unknown label` 400 whenever the
|
|
21084
|
+
// filter popover advertised the label. Registry reconciled so every
|
|
21085
|
+
// label written anywhere in the codebase has a colour + a 200 from
|
|
21086
|
+
// graph-subgraph default mode).
|
|
21087
|
+
ReviewAlert: "#DC2626"
|
|
20897
21088
|
};
|
|
20898
21089
|
var ALL_GRAPH_LABELS = Object.freeze(
|
|
20899
21090
|
Object.keys(GRAPH_LABEL_COLOURS)
|
|
@@ -20901,6 +21092,9 @@ var ALL_GRAPH_LABELS = Object.freeze(
|
|
|
20901
21092
|
var HIDDEN_BY_DEFAULT_LABELS = Object.freeze(
|
|
20902
21093
|
/* @__PURE__ */ new Set(["Chunk", "GraphPreference"])
|
|
20903
21094
|
);
|
|
21095
|
+
var FILTER_EXCLUDED_LABELS = Object.freeze(
|
|
21096
|
+
/* @__PURE__ */ new Set(["ToolCall", "WorkflowRun", "WorkflowStep", "ReviewAlert"])
|
|
21097
|
+
);
|
|
20904
21098
|
function isKnownLabel(label) {
|
|
20905
21099
|
return Object.prototype.hasOwnProperty.call(GRAPH_LABEL_COLOURS, label);
|
|
20906
21100
|
}
|
|
@@ -20917,8 +21111,8 @@ var STRIPPED_PROPERTIES = /* @__PURE__ */ new Set([
|
|
|
20917
21111
|
"otpCode",
|
|
20918
21112
|
"sessionKey"
|
|
20919
21113
|
]);
|
|
20920
|
-
var
|
|
20921
|
-
|
|
21114
|
+
var app27 = new Hono2();
|
|
21115
|
+
app27.get("/", requireAdminSession, async (c) => {
|
|
20922
21116
|
const sessionKey = c.var.sessionKey;
|
|
20923
21117
|
const accountId = getAccountIdForSession(sessionKey);
|
|
20924
21118
|
if (!accountId) {
|
|
@@ -21143,22 +21337,31 @@ var NEIGHBOURHOOD_CYPHER = `
|
|
|
21143
21337
|
[x IN windowNodes | {id: elementId(x), labels: labels(x), properties: properties(x)}] AS nodes,
|
|
21144
21338
|
[e IN rawEdges WHERE e IS NOT NULL] AS edges
|
|
21145
21339
|
`;
|
|
21340
|
+
function convertNeo4jValue(value) {
|
|
21341
|
+
if (neo4j3.isDateTime(value) || neo4j3.isDate(value) || neo4j3.isLocalDateTime(value) || neo4j3.isLocalTime(value) || neo4j3.isTime(value) || neo4j3.isDuration(value)) {
|
|
21342
|
+
return value.toString();
|
|
21343
|
+
}
|
|
21344
|
+
if (neo4j3.isInt(value)) {
|
|
21345
|
+
return value.inSafeRange() ? value.toNumber() : value.toString();
|
|
21346
|
+
}
|
|
21347
|
+
return value;
|
|
21348
|
+
}
|
|
21146
21349
|
function pruneNode(node) {
|
|
21147
21350
|
const properties = {};
|
|
21148
21351
|
for (const [key, value] of Object.entries(node.properties ?? {})) {
|
|
21149
21352
|
if (STRIPPED_PROPERTIES.has(key)) continue;
|
|
21150
|
-
properties[key] = value;
|
|
21353
|
+
properties[key] = convertNeo4jValue(value);
|
|
21151
21354
|
}
|
|
21152
21355
|
const trashed = (node.labels ?? []).includes("Trashed");
|
|
21153
21356
|
const labels = (node.labels ?? []).filter((l) => l !== "Trashed");
|
|
21154
21357
|
return trashed ? { id: node.id, labels, properties, trashed: true } : { id: node.id, labels, properties };
|
|
21155
21358
|
}
|
|
21156
|
-
var graph_subgraph_default =
|
|
21359
|
+
var graph_subgraph_default = app27;
|
|
21157
21360
|
|
|
21158
21361
|
// server/routes/admin/graph-delete.ts
|
|
21159
21362
|
var ALLOWED_BY = ["graph-page", "graph-drag-trash"];
|
|
21160
|
-
var
|
|
21161
|
-
|
|
21363
|
+
var app28 = new Hono2();
|
|
21364
|
+
app28.post("/", requireAdminSession, async (c) => {
|
|
21162
21365
|
const sessionKey = c.var.sessionKey;
|
|
21163
21366
|
const accountId = getAccountIdForSession(sessionKey);
|
|
21164
21367
|
if (!accountId) {
|
|
@@ -21229,11 +21432,11 @@ app27.post("/", requireAdminSession, async (c) => {
|
|
|
21229
21432
|
}
|
|
21230
21433
|
}
|
|
21231
21434
|
});
|
|
21232
|
-
var graph_delete_default =
|
|
21435
|
+
var graph_delete_default = app28;
|
|
21233
21436
|
|
|
21234
21437
|
// server/routes/admin/graph-restore.ts
|
|
21235
|
-
var
|
|
21236
|
-
|
|
21438
|
+
var app29 = new Hono2();
|
|
21439
|
+
app29.post("/", requireAdminSession, async (c) => {
|
|
21237
21440
|
const sessionKey = c.var.sessionKey;
|
|
21238
21441
|
const accountId = getAccountIdForSession(sessionKey);
|
|
21239
21442
|
if (!accountId) {
|
|
@@ -21297,11 +21500,11 @@ app28.post("/", requireAdminSession, async (c) => {
|
|
|
21297
21500
|
}
|
|
21298
21501
|
}
|
|
21299
21502
|
});
|
|
21300
|
-
var graph_restore_default =
|
|
21503
|
+
var graph_restore_default = app29;
|
|
21301
21504
|
|
|
21302
21505
|
// server/routes/admin/graph-labels-in-graph.ts
|
|
21303
|
-
var
|
|
21304
|
-
|
|
21506
|
+
var app30 = new Hono2();
|
|
21507
|
+
app30.get("/", requireAdminSession, async (c) => {
|
|
21305
21508
|
const sessionKey = c.var.sessionKey;
|
|
21306
21509
|
const accountId = getAccountIdForSession(sessionKey);
|
|
21307
21510
|
if (!accountId) {
|
|
@@ -21311,16 +21514,23 @@ app29.get("/", requireAdminSession, async (c) => {
|
|
|
21311
21514
|
const started = Date.now();
|
|
21312
21515
|
const session = getSession();
|
|
21313
21516
|
try {
|
|
21314
|
-
const
|
|
21517
|
+
const excluded = [...HIDDEN_BY_DEFAULT_LABELS, ...FILTER_EXCLUDED_LABELS];
|
|
21315
21518
|
const result = await session.executeRead(async (tx) => {
|
|
21316
|
-
return await tx.run(LABELS_IN_GRAPH_CYPHER, { accountId,
|
|
21519
|
+
return await tx.run(LABELS_IN_GRAPH_CYPHER, { accountId, excluded });
|
|
21520
|
+
});
|
|
21521
|
+
const labels = result.records.map((r) => ({
|
|
21522
|
+
label: String(r.get("label")),
|
|
21523
|
+
nodeCount: toNumber(r.get("nodeCount")),
|
|
21524
|
+
relDegree: toNumber(r.get("relDegree")),
|
|
21525
|
+
childOnly: toBool(r.get("childOnly"))
|
|
21526
|
+
})).filter((row) => row.nodeCount > 0).sort((a, b) => {
|
|
21527
|
+
if (b.relDegree !== a.relDegree) return b.relDegree - a.relDegree;
|
|
21528
|
+
return a.label.localeCompare(b.label);
|
|
21317
21529
|
});
|
|
21318
|
-
const record = result.records[0];
|
|
21319
|
-
const rawLabels = record?.get("labels") ?? [];
|
|
21320
|
-
const labels = [...new Set(rawLabels)].sort();
|
|
21321
21530
|
const elapsed = Date.now() - started;
|
|
21531
|
+
const summary = labels.map((l) => `${l.label}:${l.nodeCount}:${l.relDegree}:${l.childOnly ? 1 : 0}`).join(",");
|
|
21322
21532
|
console.error(
|
|
21323
|
-
`[graph-page] labels-in-graph account=${accountId} labels=${
|
|
21533
|
+
`[graph-page] labels-in-graph account=${accountId} labels=${summary} ms=${elapsed}`
|
|
21324
21534
|
);
|
|
21325
21535
|
return c.json({ labels });
|
|
21326
21536
|
} catch (err) {
|
|
@@ -21337,21 +21547,44 @@ app29.get("/", requireAdminSession, async (c) => {
|
|
|
21337
21547
|
}
|
|
21338
21548
|
}
|
|
21339
21549
|
});
|
|
21550
|
+
function toNumber(v) {
|
|
21551
|
+
if (typeof v === "bigint") return Number(v);
|
|
21552
|
+
if (typeof v === "number") return v;
|
|
21553
|
+
return Number(v ?? 0);
|
|
21554
|
+
}
|
|
21555
|
+
function toBool(v) {
|
|
21556
|
+
return v === true;
|
|
21557
|
+
}
|
|
21340
21558
|
var LABELS_IN_GRAPH_CYPHER = `
|
|
21341
21559
|
MATCH (n)
|
|
21342
21560
|
WHERE n.accountId = $accountId
|
|
21343
21561
|
AND NOT n:Trashed
|
|
21344
21562
|
AND n.deletedAt IS NULL
|
|
21345
|
-
|
|
21346
|
-
|
|
21347
|
-
|
|
21348
|
-
|
|
21563
|
+
WITH n,
|
|
21564
|
+
[l IN labels(n) WHERE NOT l IN $excluded] AS keptLabels,
|
|
21565
|
+
size([(n)--() | 1]) AS halfEdges
|
|
21566
|
+
UNWIND keptLabels AS label
|
|
21567
|
+
WITH label, n, halfEdges,
|
|
21568
|
+
EXISTS {
|
|
21569
|
+
MATCH (other)-[]->(n)
|
|
21570
|
+
WHERE NOT other:Trashed
|
|
21571
|
+
AND other.deletedAt IS NULL
|
|
21572
|
+
AND NONE(ol IN labels(other) WHERE ol = label)
|
|
21573
|
+
} AS hasNonSelfInbound
|
|
21574
|
+
WITH label,
|
|
21575
|
+
count(DISTINCT n) AS nodeCount,
|
|
21576
|
+
sum(halfEdges) AS relDegree,
|
|
21577
|
+
count(DISTINCT CASE WHEN hasNonSelfInbound THEN n END) AS qualifyingCount
|
|
21578
|
+
RETURN label,
|
|
21579
|
+
nodeCount,
|
|
21580
|
+
relDegree,
|
|
21581
|
+
(nodeCount > 0 AND qualifyingCount = nodeCount) AS childOnly
|
|
21349
21582
|
`;
|
|
21350
|
-
var graph_labels_in_graph_default =
|
|
21583
|
+
var graph_labels_in_graph_default = app30;
|
|
21351
21584
|
|
|
21352
21585
|
// server/routes/admin/graph-default-view.ts
|
|
21353
|
-
var
|
|
21354
|
-
|
|
21586
|
+
var app31 = new Hono2();
|
|
21587
|
+
app31.get("/", requireAdminSession, async (c) => {
|
|
21355
21588
|
const sessionKey = c.var.sessionKey;
|
|
21356
21589
|
const accountId = getAccountIdForSession(sessionKey);
|
|
21357
21590
|
const userId = getUserIdForSession(sessionKey);
|
|
@@ -21389,7 +21622,7 @@ app30.get("/", requireAdminSession, async (c) => {
|
|
|
21389
21622
|
}
|
|
21390
21623
|
}
|
|
21391
21624
|
});
|
|
21392
|
-
|
|
21625
|
+
app31.put("/", requireAdminSession, async (c) => {
|
|
21393
21626
|
const sessionKey = c.var.sessionKey;
|
|
21394
21627
|
const accountId = getAccountIdForSession(sessionKey);
|
|
21395
21628
|
const userId = getUserIdForSession(sessionKey);
|
|
@@ -21471,11 +21704,11 @@ var WRITE_CYPHER = `
|
|
|
21471
21704
|
p.updatedAt = $updatedAt
|
|
21472
21705
|
RETURN p.labels AS labels
|
|
21473
21706
|
`;
|
|
21474
|
-
var graph_default_view_default =
|
|
21707
|
+
var graph_default_view_default = app31;
|
|
21475
21708
|
|
|
21476
21709
|
// server/routes/admin/file-attach.ts
|
|
21477
|
-
var
|
|
21478
|
-
|
|
21710
|
+
var app32 = new Hono2();
|
|
21711
|
+
app32.post("/", async (c) => {
|
|
21479
21712
|
try {
|
|
21480
21713
|
const body = await c.req.json();
|
|
21481
21714
|
const { filePath, accountId } = body;
|
|
@@ -21498,11 +21731,11 @@ app31.post("/", async (c) => {
|
|
|
21498
21731
|
return c.json({ error: message }, 500);
|
|
21499
21732
|
}
|
|
21500
21733
|
});
|
|
21501
|
-
var file_attach_default =
|
|
21734
|
+
var file_attach_default = app32;
|
|
21502
21735
|
|
|
21503
21736
|
// server/routes/admin/adherence.ts
|
|
21504
|
-
var
|
|
21505
|
-
|
|
21737
|
+
var app33 = new Hono2();
|
|
21738
|
+
app33.get("/", requireAdminSession, async (c) => {
|
|
21506
21739
|
const agent = c.req.query("agent") ?? "admin";
|
|
21507
21740
|
const includeBlock = c.req.query("block") === "1";
|
|
21508
21741
|
const account = resolveAccount();
|
|
@@ -21523,34 +21756,35 @@ app32.get("/", requireAdminSession, async (c) => {
|
|
|
21523
21756
|
return c.json({ error: "Failed to read adherence ledger", agent }, 500);
|
|
21524
21757
|
}
|
|
21525
21758
|
});
|
|
21526
|
-
var adherence_default =
|
|
21759
|
+
var adherence_default = app33;
|
|
21527
21760
|
|
|
21528
21761
|
// server/routes/admin/index.ts
|
|
21529
|
-
var
|
|
21530
|
-
|
|
21531
|
-
|
|
21532
|
-
|
|
21533
|
-
|
|
21534
|
-
|
|
21535
|
-
|
|
21536
|
-
|
|
21537
|
-
|
|
21538
|
-
|
|
21539
|
-
|
|
21540
|
-
|
|
21541
|
-
|
|
21542
|
-
|
|
21543
|
-
|
|
21544
|
-
|
|
21545
|
-
|
|
21546
|
-
|
|
21547
|
-
|
|
21548
|
-
|
|
21549
|
-
|
|
21550
|
-
|
|
21551
|
-
|
|
21552
|
-
|
|
21553
|
-
|
|
21762
|
+
var app34 = new Hono2();
|
|
21763
|
+
app34.route("/session", session_default2);
|
|
21764
|
+
app34.route("/chat", chat_default2);
|
|
21765
|
+
app34.route("/compact", compact_default);
|
|
21766
|
+
app34.route("/logs", logs_default);
|
|
21767
|
+
app34.route("/claude-info", claude_info_default);
|
|
21768
|
+
app34.route("/attachment", attachment_default);
|
|
21769
|
+
app34.route("/account", account_default);
|
|
21770
|
+
app34.route("/agents", agents_default);
|
|
21771
|
+
app34.route("/version", version_default);
|
|
21772
|
+
app34.route("/sessions", sessions_default);
|
|
21773
|
+
app34.route("/browser", browser_default);
|
|
21774
|
+
app34.route("/terminal", terminal_default);
|
|
21775
|
+
app34.route("/device-browser", device_browser_default);
|
|
21776
|
+
app34.route("/events", events_default);
|
|
21777
|
+
app34.route("/cloudflare", cloudflare_default);
|
|
21778
|
+
app34.route("/files", files_default);
|
|
21779
|
+
app34.route("/graph-search", graph_search_default);
|
|
21780
|
+
app34.route("/graph-subgraph", graph_subgraph_default);
|
|
21781
|
+
app34.route("/graph-delete", graph_delete_default);
|
|
21782
|
+
app34.route("/graph-restore", graph_restore_default);
|
|
21783
|
+
app34.route("/graph-labels-in-graph", graph_labels_in_graph_default);
|
|
21784
|
+
app34.route("/graph-default-view", graph_default_view_default);
|
|
21785
|
+
app34.route("/file-attach", file_attach_default);
|
|
21786
|
+
app34.route("/adherence", adherence_default);
|
|
21787
|
+
var admin_default = app34;
|
|
21554
21788
|
|
|
21555
21789
|
// server/index.ts
|
|
21556
21790
|
var PLATFORM_ROOT11 = process.env.MAXY_PLATFORM_ROOT || "";
|
|
@@ -21608,9 +21842,9 @@ watchFile(ALIAS_DOMAINS_PATH2, { interval: 2e3 }, () => {
|
|
|
21608
21842
|
function isPublicHost(host) {
|
|
21609
21843
|
return host.startsWith("public.") || aliasDomains.has(host);
|
|
21610
21844
|
}
|
|
21611
|
-
var
|
|
21612
|
-
|
|
21613
|
-
|
|
21845
|
+
var app35 = new Hono2();
|
|
21846
|
+
app35.use("*", clientIpMiddleware);
|
|
21847
|
+
app35.use("*", async (c, next) => {
|
|
21614
21848
|
await next();
|
|
21615
21849
|
c.header("X-Content-Type-Options", "nosniff");
|
|
21616
21850
|
c.header("Referrer-Policy", "strict-origin-when-cross-origin");
|
|
@@ -21633,7 +21867,7 @@ var PUBLIC_ALLOWED_PREFIXES = [
|
|
|
21633
21867
|
"/g/"
|
|
21634
21868
|
];
|
|
21635
21869
|
var PUBLIC_ALLOWED_EXACT = ["/favicon.ico"];
|
|
21636
|
-
|
|
21870
|
+
app35.use("*", async (c, next) => {
|
|
21637
21871
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
21638
21872
|
if (!isPublicHost(host)) {
|
|
21639
21873
|
await next();
|
|
@@ -21673,7 +21907,7 @@ function resolveRemoteAuthOpts() {
|
|
|
21673
21907
|
return brandLoginOpts;
|
|
21674
21908
|
}
|
|
21675
21909
|
var MAX_LOGIN_BODY = 8 * 1024;
|
|
21676
|
-
|
|
21910
|
+
app35.post("/__remote-auth/login", async (c) => {
|
|
21677
21911
|
const clientIp = c.var.clientIp || "unknown";
|
|
21678
21912
|
const rateLimited = checkRateLimit(clientIp);
|
|
21679
21913
|
if (rateLimited) {
|
|
@@ -21709,7 +21943,7 @@ app34.post("/__remote-auth/login", async (c) => {
|
|
|
21709
21943
|
}
|
|
21710
21944
|
});
|
|
21711
21945
|
});
|
|
21712
|
-
|
|
21946
|
+
app35.get("/__remote-auth/logout", (c) => {
|
|
21713
21947
|
const cookieHeader = c.req.header("cookie");
|
|
21714
21948
|
const token = parseCookie(cookieHeader, "__remote_session");
|
|
21715
21949
|
if (token) invalidateRemoteSession(token);
|
|
@@ -21722,7 +21956,7 @@ app34.get("/__remote-auth/logout", (c) => {
|
|
|
21722
21956
|
}
|
|
21723
21957
|
});
|
|
21724
21958
|
});
|
|
21725
|
-
|
|
21959
|
+
app35.post("/__remote-auth/change-password", async (c) => {
|
|
21726
21960
|
const clientIp = c.var.clientIp || "unknown";
|
|
21727
21961
|
const rateLimited = checkRateLimit(clientIp);
|
|
21728
21962
|
if (rateLimited) {
|
|
@@ -21771,13 +22005,13 @@ app34.post("/__remote-auth/change-password", async (c) => {
|
|
|
21771
22005
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "change", changeError: "Failed to save password", redirect }), 200);
|
|
21772
22006
|
}
|
|
21773
22007
|
});
|
|
21774
|
-
|
|
22008
|
+
app35.get("/__remote-auth/setup", (c) => {
|
|
21775
22009
|
if (isRemoteAuthConfigured()) {
|
|
21776
22010
|
return c.redirect("/");
|
|
21777
22011
|
}
|
|
21778
22012
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "setup" }), 200);
|
|
21779
22013
|
});
|
|
21780
|
-
|
|
22014
|
+
app35.post("/__remote-auth/set-initial-password", async (c) => {
|
|
21781
22015
|
if (isRemoteAuthConfigured()) {
|
|
21782
22016
|
return c.redirect("/");
|
|
21783
22017
|
}
|
|
@@ -21813,10 +22047,10 @@ app34.post("/__remote-auth/set-initial-password", async (c) => {
|
|
|
21813
22047
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "setup", setupError: "Failed to save password. Please try again." }), 200);
|
|
21814
22048
|
}
|
|
21815
22049
|
});
|
|
21816
|
-
|
|
22050
|
+
app35.get("/api/remote-auth/status", (c) => {
|
|
21817
22051
|
return c.json({ configured: isRemoteAuthConfigured() });
|
|
21818
22052
|
});
|
|
21819
|
-
|
|
22053
|
+
app35.post("/api/remote-auth/set-password", async (c) => {
|
|
21820
22054
|
let body;
|
|
21821
22055
|
try {
|
|
21822
22056
|
body = await c.req.json();
|
|
@@ -21846,9 +22080,9 @@ app34.post("/api/remote-auth/set-password", async (c) => {
|
|
|
21846
22080
|
return c.json({ error: "Failed to save password" }, 500);
|
|
21847
22081
|
}
|
|
21848
22082
|
});
|
|
21849
|
-
|
|
22083
|
+
app35.route("/api/_client-error", client_error_default);
|
|
21850
22084
|
console.log("[client-error-route] mounted");
|
|
21851
|
-
|
|
22085
|
+
app35.use("*", async (c, next) => {
|
|
21852
22086
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
21853
22087
|
const path2 = c.req.path;
|
|
21854
22088
|
if (path2 === "/favicon.ico" || path2.startsWith("/assets/") || path2.startsWith("/brand/")) {
|
|
@@ -21888,15 +22122,15 @@ function parseCookie(cookieHeader, name) {
|
|
|
21888
22122
|
return null;
|
|
21889
22123
|
}
|
|
21890
22124
|
}
|
|
21891
|
-
|
|
21892
|
-
|
|
21893
|
-
|
|
21894
|
-
|
|
21895
|
-
|
|
21896
|
-
|
|
21897
|
-
|
|
21898
|
-
|
|
21899
|
-
|
|
22125
|
+
app35.route("/api/health", health_default);
|
|
22126
|
+
app35.route("/api/session", session_default);
|
|
22127
|
+
app35.route("/api/chat", chat_default);
|
|
22128
|
+
app35.route("/api/group", group_default);
|
|
22129
|
+
app35.route("/api/access", access_default);
|
|
22130
|
+
app35.route("/api/telegram", telegram_default);
|
|
22131
|
+
app35.route("/api/whatsapp", whatsapp_default);
|
|
22132
|
+
app35.route("/api/onboarding", onboarding_default);
|
|
22133
|
+
app35.route("/api/admin", admin_default);
|
|
21900
22134
|
var SAFE_SLUG_RE = /^[a-z][a-z0-9-]{2,49}$/;
|
|
21901
22135
|
var SAFE_FILENAME_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
|
|
21902
22136
|
var IMAGE_MIME = {
|
|
@@ -21908,7 +22142,7 @@ var IMAGE_MIME = {
|
|
|
21908
22142
|
".svg": "image/svg+xml",
|
|
21909
22143
|
".ico": "image/x-icon"
|
|
21910
22144
|
};
|
|
21911
|
-
|
|
22145
|
+
app35.get("/agent-assets/:slug/:filename", (c) => {
|
|
21912
22146
|
const slug = c.req.param("slug");
|
|
21913
22147
|
const filename = c.req.param("filename");
|
|
21914
22148
|
if (!SAFE_SLUG_RE.test(slug)) {
|
|
@@ -21943,7 +22177,7 @@ app34.get("/agent-assets/:slug/:filename", (c) => {
|
|
|
21943
22177
|
"Cache-Control": "public, max-age=3600"
|
|
21944
22178
|
});
|
|
21945
22179
|
});
|
|
21946
|
-
|
|
22180
|
+
app35.get("/generated/:filename", (c) => {
|
|
21947
22181
|
const filename = c.req.param("filename");
|
|
21948
22182
|
if (!SAFE_FILENAME_RE.test(filename) || filename.includes("..")) {
|
|
21949
22183
|
console.error(`[generated] serve file=${filename} status=403`);
|
|
@@ -22108,7 +22342,7 @@ function brandedPublicHtml(agentSlug) {
|
|
|
22108
22342
|
function escapeHtml2(s) {
|
|
22109
22343
|
return s.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
22110
22344
|
}
|
|
22111
|
-
|
|
22345
|
+
app35.get("/", (c) => {
|
|
22112
22346
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
22113
22347
|
if (isPublicHost(host)) {
|
|
22114
22348
|
const defaultSlug = resolveDefaultSlug();
|
|
@@ -22116,12 +22350,12 @@ app34.get("/", (c) => {
|
|
|
22116
22350
|
}
|
|
22117
22351
|
return c.html(cachedHtml("index.html"));
|
|
22118
22352
|
});
|
|
22119
|
-
|
|
22353
|
+
app35.get("/public", (c) => {
|
|
22120
22354
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
22121
22355
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
22122
22356
|
return c.html(cachedHtml("public.html"));
|
|
22123
22357
|
});
|
|
22124
|
-
|
|
22358
|
+
app35.get("/chat", (c) => {
|
|
22125
22359
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
22126
22360
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
22127
22361
|
return c.html(cachedHtml("public.html"));
|
|
@@ -22140,9 +22374,9 @@ async function logViewerFetch(c, next) {
|
|
|
22140
22374
|
duration_ms: Date.now() - start
|
|
22141
22375
|
});
|
|
22142
22376
|
}
|
|
22143
|
-
|
|
22144
|
-
|
|
22145
|
-
|
|
22377
|
+
app35.use("/vnc-viewer.html", logViewerFetch);
|
|
22378
|
+
app35.use("/vnc-popout.html", logViewerFetch);
|
|
22379
|
+
app35.get("/vnc-popout.html", (c) => {
|
|
22146
22380
|
let html = htmlCache.get("vnc-popout.html");
|
|
22147
22381
|
if (!html) {
|
|
22148
22382
|
html = readFileSync26(resolve30(process.cwd(), "public", "vnc-popout.html"), "utf-8");
|
|
@@ -22155,7 +22389,7 @@ app34.get("/vnc-popout.html", (c) => {
|
|
|
22155
22389
|
}
|
|
22156
22390
|
return c.html(html);
|
|
22157
22391
|
});
|
|
22158
|
-
|
|
22392
|
+
app35.post("/api/vnc/client-event", async (c) => {
|
|
22159
22393
|
let body;
|
|
22160
22394
|
try {
|
|
22161
22395
|
body = await c.req.json();
|
|
@@ -22176,20 +22410,20 @@ app34.post("/api/vnc/client-event", async (c) => {
|
|
|
22176
22410
|
});
|
|
22177
22411
|
return c.json({ ok: true });
|
|
22178
22412
|
});
|
|
22179
|
-
|
|
22413
|
+
app35.get("/g/:slug", (c) => {
|
|
22180
22414
|
return c.html(brandedPublicHtml());
|
|
22181
22415
|
});
|
|
22182
|
-
|
|
22416
|
+
app35.get("/graph", (c) => {
|
|
22183
22417
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
22184
22418
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
22185
22419
|
return c.html(cachedHtml("graph.html"));
|
|
22186
22420
|
});
|
|
22187
|
-
|
|
22421
|
+
app35.get("/data", (c) => {
|
|
22188
22422
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
22189
22423
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
22190
22424
|
return c.html(cachedHtml("data.html"));
|
|
22191
22425
|
});
|
|
22192
|
-
|
|
22426
|
+
app35.get("/:slug", async (c, next) => {
|
|
22193
22427
|
const slug = c.req.param("slug");
|
|
22194
22428
|
if (AGENT_SLUG_PATTERN.test(`/${slug}`)) {
|
|
22195
22429
|
const branding = loadBrandingCache(slug);
|
|
@@ -22198,10 +22432,10 @@ app34.get("/:slug", async (c, next) => {
|
|
|
22198
22432
|
}
|
|
22199
22433
|
await next();
|
|
22200
22434
|
});
|
|
22201
|
-
|
|
22435
|
+
app35.use("/*", serveStatic({ root: "./public" }));
|
|
22202
22436
|
var port = parseInt(process.env.PORT ?? "19200", 10);
|
|
22203
22437
|
var hostname = process.env.HOSTNAME ?? "0.0.0.0";
|
|
22204
|
-
var httpServer = serve({ fetch:
|
|
22438
|
+
var httpServer = serve({ fetch: app35.fetch, port, hostname });
|
|
22205
22439
|
attachVncWsProxy(httpServer, {
|
|
22206
22440
|
isPublicHost,
|
|
22207
22441
|
upstreamHost: "127.0.0.1",
|
|
@@ -22247,7 +22481,7 @@ for (const m of SUBAPP_MANIFEST) {
|
|
|
22247
22481
|
}
|
|
22248
22482
|
try {
|
|
22249
22483
|
const registered = [];
|
|
22250
|
-
for (const r of
|
|
22484
|
+
for (const r of app35.routes ?? []) {
|
|
22251
22485
|
if (typeof r.path !== "string" || r.path.includes(":") || r.path.includes("*")) continue;
|
|
22252
22486
|
if (AGENT_SLUG_PATTERN.test(r.path)) {
|
|
22253
22487
|
registered.push({ method: (r.method ?? "ALL").toUpperCase(), path: r.path });
|