@rubytech/create-realagent 1.0.825 → 1.0.828
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/payload/platform/lib/task-secrets/dist/index.d.ts +40 -0
- package/payload/platform/lib/task-secrets/dist/index.d.ts.map +1 -0
- package/payload/platform/lib/task-secrets/dist/index.js +44 -0
- package/payload/platform/lib/task-secrets/dist/index.js.map +1 -0
- package/payload/platform/lib/task-secrets/src/__tests__/redact-secrets.test.ts +127 -0
- package/payload/platform/lib/task-secrets/src/index.ts +77 -0
- package/payload/platform/lib/task-secrets/tsconfig.json +9 -0
- package/payload/platform/lib/task-secrets/vitest.config.ts +9 -0
- package/payload/platform/neo4j/schema.cypher +34 -2
- package/payload/platform/package.json +2 -2
- package/payload/platform/plugins/admin/hooks/archive-ingest-surface-gate.sh +19 -13
- package/payload/platform/plugins/admin/skills/business-profile/SKILL.md +2 -2
- package/payload/platform/plugins/admin/skills/onboarding/SKILL.md +13 -12
- package/payload/platform/plugins/admin/skills/plugin-management/SKILL.md +4 -4
- package/payload/platform/plugins/admin/skills/public-agent-manager/SKILL.md +2 -2
- package/payload/platform/plugins/admin/skills/stream-log-review/SKILL.md +6 -6
- package/payload/platform/plugins/admin/skills/unzip-attachment/references/safety.md +1 -1
- package/payload/platform/plugins/cloudflare/references/manual-setup.md +3 -3
- package/payload/platform/plugins/cloudflare/skills/setup-tunnel/SKILL.md +4 -4
- package/payload/platform/plugins/docs/references/cloudflare.md +2 -2
- package/payload/platform/plugins/docs/references/internals.md +2 -2
- package/payload/platform/plugins/docs/references/plugins-guide.md +1 -1
- package/payload/platform/plugins/docs/references/troubleshooting.md +2 -1
- package/payload/platform/plugins/linkedin-import/skills/linkedin-import/SKILL.md +2 -2
- package/payload/platform/plugins/linkedin-import/skills/linkedin-import/references/connections.md +1 -1
- package/payload/platform/plugins/memory/PLUGIN.md +1 -1
- package/payload/platform/plugins/memory/mcp/dist/index.js +6 -41
- package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/llm-classifier.test.js +51 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/llm-classifier.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/llm-classifier.d.ts +19 -4
- package/payload/platform/plugins/memory/mcp/dist/lib/llm-classifier.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/llm-classifier.js +139 -56
- package/payload/platform/plugins/memory/mcp/dist/lib/llm-classifier.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest.test.js +61 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.d.ts +34 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js +241 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js.map +1 -1
- package/payload/platform/plugins/memory/references/graph-primitives.md +5 -5
- package/payload/platform/plugins/memory/references/schema-base.md +6 -3
- package/payload/platform/plugins/memory/skills/document-ingest/SKILL.md +6 -6
- package/payload/platform/plugins/tasks/PLUGIN.md +1 -1
- package/payload/platform/plugins/tasks/mcp/dist/index.js +11 -2
- package/payload/platform/plugins/tasks/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/tasks/mcp/dist/tools/task-create.d.ts +19 -2
- package/payload/platform/plugins/tasks/mcp/dist/tools/task-create.d.ts.map +1 -1
- package/payload/platform/plugins/tasks/mcp/dist/tools/task-create.js +17 -1
- package/payload/platform/plugins/tasks/mcp/dist/tools/task-create.js.map +1 -1
- package/payload/platform/plugins/whatsapp-import/PLUGIN.md +17 -15
- package/payload/platform/plugins/whatsapp-import/bin/ingest.mjs +313 -366
- package/payload/platform/plugins/whatsapp-import/bin/whatsapp-ingest.sh +27 -60
- package/payload/platform/plugins/whatsapp-import/lib/dist/delta-cursor.d.ts +18 -0
- package/payload/platform/plugins/whatsapp-import/lib/dist/delta-cursor.d.ts.map +1 -0
- package/payload/platform/plugins/whatsapp-import/lib/dist/delta-cursor.js +31 -0
- package/payload/platform/plugins/whatsapp-import/lib/dist/delta-cursor.js.map +1 -0
- package/payload/platform/plugins/whatsapp-import/lib/dist/derive-keys.d.ts +27 -12
- package/payload/platform/plugins/whatsapp-import/lib/dist/derive-keys.d.ts.map +1 -1
- package/payload/platform/plugins/whatsapp-import/lib/dist/derive-keys.js +40 -20
- package/payload/platform/plugins/whatsapp-import/lib/dist/derive-keys.js.map +1 -1
- package/payload/platform/plugins/whatsapp-import/lib/dist/index.d.ts +7 -4
- package/payload/platform/plugins/whatsapp-import/lib/dist/index.d.ts.map +1 -1
- package/payload/platform/plugins/whatsapp-import/lib/dist/index.js +9 -6
- package/payload/platform/plugins/whatsapp-import/lib/dist/index.js.map +1 -1
- package/payload/platform/plugins/whatsapp-import/lib/dist/sessionize.d.ts +25 -0
- package/payload/platform/plugins/whatsapp-import/lib/dist/sessionize.d.ts.map +1 -0
- package/payload/platform/plugins/whatsapp-import/lib/dist/sessionize.js +48 -0
- package/payload/platform/plugins/whatsapp-import/lib/dist/sessionize.js.map +1 -0
- package/payload/platform/plugins/whatsapp-import/lib/dist/to-classifier-input.d.ts +3 -0
- package/payload/platform/plugins/whatsapp-import/lib/dist/to-classifier-input.d.ts.map +1 -0
- package/payload/platform/plugins/whatsapp-import/lib/dist/to-classifier-input.js +47 -0
- package/payload/platform/plugins/whatsapp-import/lib/dist/to-classifier-input.js.map +1 -0
- package/payload/platform/plugins/whatsapp-import/lib/src/__tests__/delta-append.test.ts +163 -0
- package/payload/platform/plugins/whatsapp-import/lib/src/__tests__/sessionize.test.ts +91 -0
- package/payload/platform/plugins/whatsapp-import/lib/src/__tests__/to-classifier-input.test.ts +59 -0
- package/payload/platform/plugins/whatsapp-import/lib/src/delta-cursor.ts +54 -0
- package/payload/platform/plugins/whatsapp-import/lib/src/derive-keys.ts +55 -32
- package/payload/platform/plugins/whatsapp-import/lib/src/index.ts +9 -6
- package/payload/platform/plugins/whatsapp-import/lib/src/sessionize.ts +81 -0
- package/payload/platform/plugins/whatsapp-import/lib/src/to-classifier-input.ts +48 -0
- package/payload/platform/plugins/whatsapp-import/skills/whatsapp-import/SKILL.md +66 -73
- package/payload/platform/plugins/whatsapp-import/skills/whatsapp-import/references/conversation-archive-shape.md +143 -0
- package/payload/platform/plugins/whatsapp-import/skills/whatsapp-import/references/export-parse.md +2 -2
- package/payload/platform/templates/specialists/agents/database-operator.md +17 -18
- package/payload/server/chunk-T2OPNP3L.js +654 -0
- package/payload/server/chunk-ZTBTX3IO.js +642 -0
- package/payload/server/cloudflare-task-tracker-BAMJY4MH.js +17 -0
- package/payload/server/cloudflare-task-tracker-CR6TL4VL.js +19 -0
- package/payload/server/public/assets/{admin-DOkUspG1.js → admin-BNwPsMhJ.js} +2 -2
- package/payload/server/public/assets/{graph-LLMJa4Ch.js → graph-N_Bw-8oT.js} +1 -1
- package/payload/server/public/assets/{page-DoaF3DB0.js → page-BKLGP-th.js} +1 -1
- package/payload/server/public/graph.html +2 -2
- package/payload/server/public/index.html +2 -2
- package/payload/server/server.js +291 -172
- package/payload/platform/plugins/whatsapp-import/lib/src/__tests__/filter-gate.test.ts +0 -172
- package/payload/platform/plugins/whatsapp-import/lib/src/__tests__/ingest-idempotence.test.ts +0 -141
- package/payload/platform/plugins/whatsapp-import/lib/src/filter.ts +0 -136
- package/payload/platform/plugins/whatsapp-import/skills/whatsapp-import-enrich/SKILL.md +0 -333
package/payload/server/server.js
CHANGED
|
@@ -95,8 +95,9 @@ import {
|
|
|
95
95
|
appendCloudflareSteps,
|
|
96
96
|
completeCloudflareTask,
|
|
97
97
|
openCloudflareTask,
|
|
98
|
-
readTunnelState
|
|
99
|
-
|
|
98
|
+
readTunnelState,
|
|
99
|
+
resolveUnitGoneVerdict
|
|
100
|
+
} from "./chunk-T2OPNP3L.js";
|
|
100
101
|
import {
|
|
101
102
|
GREETING_DIRECTIVE,
|
|
102
103
|
HAIKU_MODEL,
|
|
@@ -627,8 +628,8 @@ var serveStatic = (options = { root: "" }) => {
|
|
|
627
628
|
};
|
|
628
629
|
|
|
629
630
|
// server/index.ts
|
|
630
|
-
import { readFileSync as
|
|
631
|
-
import { resolve as
|
|
631
|
+
import { readFileSync as readFileSync16, existsSync as existsSync22, watchFile } from "fs";
|
|
632
|
+
import { resolve as resolve22, join as join10, basename as basename5 } from "path";
|
|
632
633
|
import { homedir as homedir2 } from "os";
|
|
633
634
|
|
|
634
635
|
// app/lib/agent-slug-pattern.ts
|
|
@@ -1272,7 +1273,7 @@ var credsSaveQueue = Promise.resolve();
|
|
|
1272
1273
|
async function drainCredsSaveQueue(timeoutMs = 5e3) {
|
|
1273
1274
|
console.error(`${TAG3} draining credential save queue\u2026`);
|
|
1274
1275
|
const timer2 = new Promise(
|
|
1275
|
-
(
|
|
1276
|
+
(resolve23) => setTimeout(() => resolve23("timeout"), timeoutMs)
|
|
1276
1277
|
);
|
|
1277
1278
|
const result = await Promise.race([
|
|
1278
1279
|
credsSaveQueue.then(() => "drained"),
|
|
@@ -1400,11 +1401,11 @@ async function createWaSocket(opts) {
|
|
|
1400
1401
|
return sock;
|
|
1401
1402
|
}
|
|
1402
1403
|
async function waitForConnection(sock) {
|
|
1403
|
-
return new Promise((
|
|
1404
|
+
return new Promise((resolve23, reject) => {
|
|
1404
1405
|
const handler = (update) => {
|
|
1405
1406
|
if (update.connection === "open") {
|
|
1406
1407
|
sock.ev.off("connection.update", handler);
|
|
1407
|
-
|
|
1408
|
+
resolve23();
|
|
1408
1409
|
}
|
|
1409
1410
|
if (update.connection === "close") {
|
|
1410
1411
|
sock.ev.off("connection.update", handler);
|
|
@@ -1518,14 +1519,14 @@ ${inspected}`;
|
|
|
1518
1519
|
return inspect2(err, INSPECT_OPTS2);
|
|
1519
1520
|
}
|
|
1520
1521
|
function withTimeout(label, promise, timeoutMs) {
|
|
1521
|
-
return new Promise((
|
|
1522
|
+
return new Promise((resolve23, reject) => {
|
|
1522
1523
|
const timer2 = setTimeout(() => {
|
|
1523
1524
|
reject(new Error(`${label} timed out after ${timeoutMs}ms`));
|
|
1524
1525
|
}, timeoutMs);
|
|
1525
1526
|
promise.then(
|
|
1526
1527
|
(value) => {
|
|
1527
1528
|
clearTimeout(timer2);
|
|
1528
|
-
|
|
1529
|
+
resolve23(value);
|
|
1529
1530
|
},
|
|
1530
1531
|
(err) => {
|
|
1531
1532
|
clearTimeout(timer2);
|
|
@@ -2060,8 +2061,8 @@ async function persistWhatsAppMessage(input) {
|
|
|
2060
2061
|
const { givenName, familyName } = splitName(input.pushName);
|
|
2061
2062
|
const prev = sessionWriteLocks.get(input.sessionKey);
|
|
2062
2063
|
let release;
|
|
2063
|
-
const mine = new Promise((
|
|
2064
|
-
release =
|
|
2064
|
+
const mine = new Promise((resolve23) => {
|
|
2065
|
+
release = resolve23;
|
|
2065
2066
|
});
|
|
2066
2067
|
const chained = (prev ?? Promise.resolve()).then(() => mine);
|
|
2067
2068
|
sessionWriteLocks.set(input.sessionKey, chained);
|
|
@@ -3068,11 +3069,11 @@ async function connectWithReconnect(conn) {
|
|
|
3068
3069
|
console.error(
|
|
3069
3070
|
`${TAG13} reconnecting account=${conn.accountId} in ${delay}ms (attempt ${decision.nextAttempts}/${maxAttempts})`
|
|
3070
3071
|
);
|
|
3071
|
-
await new Promise((
|
|
3072
|
-
const timer2 = setTimeout(
|
|
3072
|
+
await new Promise((resolve23) => {
|
|
3073
|
+
const timer2 = setTimeout(resolve23, delay);
|
|
3073
3074
|
conn.abortController.signal.addEventListener("abort", () => {
|
|
3074
3075
|
clearTimeout(timer2);
|
|
3075
|
-
|
|
3076
|
+
resolve23();
|
|
3076
3077
|
}, { once: true });
|
|
3077
3078
|
});
|
|
3078
3079
|
}
|
|
@@ -3080,16 +3081,16 @@ async function connectWithReconnect(conn) {
|
|
|
3080
3081
|
}
|
|
3081
3082
|
}
|
|
3082
3083
|
function waitForDisconnectEvent(conn) {
|
|
3083
|
-
return new Promise((
|
|
3084
|
+
return new Promise((resolve23) => {
|
|
3084
3085
|
if (!conn.sock) {
|
|
3085
|
-
|
|
3086
|
+
resolve23();
|
|
3086
3087
|
return;
|
|
3087
3088
|
}
|
|
3088
3089
|
const sock = conn.sock;
|
|
3089
3090
|
const handler = (update) => {
|
|
3090
3091
|
if (update.connection === "close") {
|
|
3091
3092
|
sock.ev.off("connection.update", handler);
|
|
3092
|
-
|
|
3093
|
+
resolve23();
|
|
3093
3094
|
}
|
|
3094
3095
|
};
|
|
3095
3096
|
sock.ev.on("connection.update", handler);
|
|
@@ -3350,8 +3351,8 @@ async function handleInboundMessage(conn, msg) {
|
|
|
3350
3351
|
const conversationKey = isGroup ? remoteJid : senderPhone;
|
|
3351
3352
|
const debounceKey = `${conn.accountId}:${conversationKey}:${senderPhone}`;
|
|
3352
3353
|
let resolvePending;
|
|
3353
|
-
const sttPending = new Promise((
|
|
3354
|
-
resolvePending =
|
|
3354
|
+
const sttPending = new Promise((resolve23) => {
|
|
3355
|
+
resolvePending = resolve23;
|
|
3355
3356
|
});
|
|
3356
3357
|
if (conn.debouncer) conn.debouncer.registerPending(debounceKey, sttPending);
|
|
3357
3358
|
try {
|
|
@@ -3472,20 +3473,20 @@ async function probeApiKey() {
|
|
|
3472
3473
|
return result.status;
|
|
3473
3474
|
}
|
|
3474
3475
|
function checkPort(port2, timeoutMs = 500) {
|
|
3475
|
-
return new Promise((
|
|
3476
|
+
return new Promise((resolve23) => {
|
|
3476
3477
|
const socket = createConnection(port2, "127.0.0.1");
|
|
3477
3478
|
socket.setTimeout(timeoutMs);
|
|
3478
3479
|
socket.once("connect", () => {
|
|
3479
3480
|
socket.destroy();
|
|
3480
|
-
|
|
3481
|
+
resolve23(true);
|
|
3481
3482
|
});
|
|
3482
3483
|
socket.once("error", () => {
|
|
3483
3484
|
socket.destroy();
|
|
3484
|
-
|
|
3485
|
+
resolve23(false);
|
|
3485
3486
|
});
|
|
3486
3487
|
socket.once("timeout", () => {
|
|
3487
3488
|
socket.destroy();
|
|
3488
|
-
|
|
3489
|
+
resolve23(false);
|
|
3489
3490
|
});
|
|
3490
3491
|
});
|
|
3491
3492
|
}
|
|
@@ -5686,8 +5687,8 @@ async function startLogin(opts) {
|
|
|
5686
5687
|
resetActiveLogin(accountId);
|
|
5687
5688
|
let resolveQr = null;
|
|
5688
5689
|
let rejectQr = null;
|
|
5689
|
-
const qrPromise = new Promise((
|
|
5690
|
-
resolveQr =
|
|
5690
|
+
const qrPromise = new Promise((resolve23, reject) => {
|
|
5691
|
+
resolveQr = resolve23;
|
|
5691
5692
|
rejectQr = reject;
|
|
5692
5693
|
});
|
|
5693
5694
|
const qrTimer = setTimeout(
|
|
@@ -8039,6 +8040,17 @@ var agents_default = app16;
|
|
|
8039
8040
|
import crypto2 from "crypto";
|
|
8040
8041
|
import { resolve as resolvePath } from "path";
|
|
8041
8042
|
import { appendFileSync as appendFileSync4, existsSync as existsSync15 } from "fs";
|
|
8043
|
+
|
|
8044
|
+
// app/lib/synthetic-marker.ts
|
|
8045
|
+
var CLOUDFLARE_MARKER_PREFIX = "Cloudflare setup completed (actionId: ";
|
|
8046
|
+
var COMPONENT_DONE_PREFIX = '{"_componentDone"';
|
|
8047
|
+
var LIFECYCLE_PREFIX = '{"_lifecycle"';
|
|
8048
|
+
function isSyntheticUserMarker(content) {
|
|
8049
|
+
if (typeof content !== "string" || content.length === 0) return false;
|
|
8050
|
+
return content.startsWith(COMPONENT_DONE_PREFIX) || content.startsWith(LIFECYCLE_PREFIX) || content.startsWith(CLOUDFLARE_MARKER_PREFIX);
|
|
8051
|
+
}
|
|
8052
|
+
|
|
8053
|
+
// server/routes/admin/sessions.ts
|
|
8042
8054
|
function validateAndShapeAttachments(raws, conversationAccountId, conversationId, messageId, streamLogPath) {
|
|
8043
8055
|
const chips = [];
|
|
8044
8056
|
let valid = 0;
|
|
@@ -8310,6 +8322,7 @@ app17.post("/:id/resume", async (c) => {
|
|
|
8310
8322
|
let totalComponents = 0;
|
|
8311
8323
|
let totalAttachments = 0;
|
|
8312
8324
|
let totalAttachmentInvalid = 0;
|
|
8325
|
+
let syntheticHidden = 0;
|
|
8313
8326
|
const rehydrated = messages.map((m) => {
|
|
8314
8327
|
const components = m.components ?? [];
|
|
8315
8328
|
const rawAttachments = m.attachments ?? [];
|
|
@@ -8318,6 +8331,7 @@ app17.post("/:id/resume", async (c) => {
|
|
|
8318
8331
|
totalAttachments += valid2;
|
|
8319
8332
|
totalAttachmentInvalid += invalid2;
|
|
8320
8333
|
const cleanedContent = chips.length > 0 ? stripAttachmentMetaSuffix(m.content) : m.content;
|
|
8334
|
+
if (m.role === "user" && isSyntheticUserMarker(cleanedContent)) syntheticHidden += 1;
|
|
8321
8335
|
return {
|
|
8322
8336
|
messageId: m.messageId,
|
|
8323
8337
|
role: m.role,
|
|
@@ -8344,7 +8358,7 @@ app17.post("/:id/resume", async (c) => {
|
|
|
8344
8358
|
const userMessageCount = rehydrated.filter((m) => m.role !== "assistant").length;
|
|
8345
8359
|
const reason = bridged ? "post-restart" : "page-refresh";
|
|
8346
8360
|
try {
|
|
8347
|
-
appendFileSync4(streamLogPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] [admin-resume] reason=${reason} sessionKey=${sessionKey.slice(0, 8)} conversationId=${conversationId.slice(0, 8)} ${tag} loadedMessages=${messages.length} componentCount=${totalComponents} userAttachmentCount=${totalAttachments}
|
|
8361
|
+
appendFileSync4(streamLogPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] [admin-resume] reason=${reason} sessionKey=${sessionKey.slice(0, 8)} conversationId=${conversationId.slice(0, 8)} ${tag} loadedMessages=${messages.length} componentCount=${totalComponents} userAttachmentCount=${totalAttachments} syntheticHidden=${syntheticHidden}
|
|
8348
8362
|
`);
|
|
8349
8363
|
if (totalComponents > 0) {
|
|
8350
8364
|
appendFileSync4(streamLogPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] [component-rehydrate] conversationId=${conversationId.slice(0, 8)} count=${totalComponents} valid=${totalValid} invalid=${totalInvalid} textRuns=${textRuns}
|
|
@@ -8357,7 +8371,7 @@ app17.post("/:id/resume", async (c) => {
|
|
|
8357
8371
|
} catch {
|
|
8358
8372
|
}
|
|
8359
8373
|
const age = formatAge(updatedAt);
|
|
8360
|
-
console.log(`[admin-resume] ${(/* @__PURE__ */ new Date()).toISOString()} reason=${reason} conversationId=${conversationId.slice(0, 8)}\u2026 age=${age} loaded=${messages.length} messages ${tag} components=${totalComponents} attachments=${totalAttachments} sessionKey=${sessionKey.slice(0, 8)}\u2026`);
|
|
8374
|
+
console.log(`[admin-resume] ${(/* @__PURE__ */ new Date()).toISOString()} reason=${reason} conversationId=${conversationId.slice(0, 8)}\u2026 age=${age} loaded=${messages.length} messages ${tag} components=${totalComponents} attachments=${totalAttachments} syntheticHidden=${syntheticHidden} sessionKey=${sessionKey.slice(0, 8)}\u2026`);
|
|
8361
8375
|
return c.json({ conversationId, messages: rehydrated });
|
|
8362
8376
|
});
|
|
8363
8377
|
app17.post("/:id/label", requireAdminSession, async (c) => {
|
|
@@ -8654,6 +8668,11 @@ function addAliasDomain(hostname2) {
|
|
|
8654
8668
|
writeFileSync6(ALIAS_DOMAINS_PATH, JSON.stringify([...existing], null, 2) + "\n", "utf-8");
|
|
8655
8669
|
}
|
|
8656
8670
|
|
|
8671
|
+
// app/lib/cloudflare-setup-types.ts
|
|
8672
|
+
var CLOUDFLARE_SETUP_FORM_SCHEMA = {
|
|
8673
|
+
secretFields: ["password", "session_key", "messageId"]
|
|
8674
|
+
};
|
|
8675
|
+
|
|
8657
8676
|
// server/routes/admin/cloudflare.ts
|
|
8658
8677
|
var SETUP_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
8659
8678
|
var DOMAINS_TIMEOUT_MS = 40 * 1e3;
|
|
@@ -8875,8 +8894,8 @@ app21.get("/tunnels", requireAdminSession, async (c) => {
|
|
|
8875
8894
|
if (!correlationId) return err("session", "No active conversation for session \u2014 refresh chat.");
|
|
8876
8895
|
streamLogPath = streamLogPathFor(accountId, correlationId).streamLogPath;
|
|
8877
8896
|
const certPath = resolve14(homedir(), brand.configDir, "cloudflared", "cert.pem");
|
|
8878
|
-
const { existsSync:
|
|
8879
|
-
if (!
|
|
8897
|
+
const { existsSync: existsSync23 } = await import("fs");
|
|
8898
|
+
if (!existsSync23(certPath)) {
|
|
8880
8899
|
return err("cert", `Cloudflare origin certificate is not on disk yet (${certPath}). Complete the Cloudflare login first by submitting the form once \u2014 the OAuth flow writes cert.pem.`);
|
|
8881
8900
|
}
|
|
8882
8901
|
const result = await runFormSpawn({
|
|
@@ -9012,19 +9031,20 @@ app21.post("/setup", requireAdminSession, async (c) => {
|
|
|
9012
9031
|
if (await isActionActive("cloudflare-setup")) {
|
|
9013
9032
|
return err("request", "Another Cloudflare setup is already running. Wait for it to finish before starting a new one.");
|
|
9014
9033
|
}
|
|
9034
|
+
const taskInputs = {};
|
|
9035
|
+
for (const [key, value] of Object.entries(body)) {
|
|
9036
|
+
if (value !== void 0 && value !== null && value !== "") {
|
|
9037
|
+
taskInputs[key] = value;
|
|
9038
|
+
}
|
|
9039
|
+
}
|
|
9015
9040
|
let cloudflareTask;
|
|
9016
9041
|
try {
|
|
9017
9042
|
cloudflareTask = await openCloudflareTask({
|
|
9018
9043
|
accountId,
|
|
9019
9044
|
conversationKey: sessionKey,
|
|
9020
|
-
inputsProvided:
|
|
9021
|
-
inputs:
|
|
9022
|
-
|
|
9023
|
-
adminDomain: body.adminDomain,
|
|
9024
|
-
publicLabel: body.publicLabel,
|
|
9025
|
-
publicDomain: body.publicDomain,
|
|
9026
|
-
apex: body.apex
|
|
9027
|
-
},
|
|
9045
|
+
inputsProvided: Object.keys(taskInputs),
|
|
9046
|
+
inputs: taskInputs,
|
|
9047
|
+
inputSchema: CLOUDFLARE_SETUP_FORM_SCHEMA,
|
|
9028
9048
|
messageId: typeof body.messageId === "string" && body.messageId.length > 0 ? body.messageId : void 0
|
|
9029
9049
|
});
|
|
9030
9050
|
log(`phase=task-opened taskId=${cloudflareTask.taskId}`);
|
|
@@ -9055,38 +9075,63 @@ app21.post("/setup", requireAdminSession, async (c) => {
|
|
|
9055
9075
|
} catch (e) {
|
|
9056
9076
|
logErr(`phase=task-steps-append-failed reason="${e instanceof Error ? e.message : String(e)}"`);
|
|
9057
9077
|
}
|
|
9058
|
-
|
|
9059
|
-
|
|
9078
|
+
let unitGoneWithDiskProof = false;
|
|
9079
|
+
if (status === null) {
|
|
9080
|
+
const verdict = resolveUnitGoneVerdict({
|
|
9081
|
+
tunnelState: readTunnelState(brand.configDir),
|
|
9082
|
+
expected: { tunnelName: body.tunnelName, tunnelId: body.tunnelId }
|
|
9083
|
+
});
|
|
9084
|
+
const resolution = verdict.kind === "close-completed" ? "close-completed" : "close-failed-diagnostic";
|
|
9085
|
+
log(`phase=post-exit-disk-check tunnel-state-found=${verdict.tunnelStateFound} identity-match=${verdict.identityMatch} resolution=${resolution}`);
|
|
9086
|
+
if (verdict.kind === "close-failed") {
|
|
9087
|
+
try {
|
|
9088
|
+
await completeCloudflareTask({
|
|
9089
|
+
taskId: cloudflareTask.taskId,
|
|
9090
|
+
taskElementId: cloudflareTask.taskElementId,
|
|
9091
|
+
accountId,
|
|
9092
|
+
conversationKey: sessionKey,
|
|
9093
|
+
status: "failed",
|
|
9094
|
+
errorMessage: CLOUDFLARE_TASK_DIAGNOSTICS.endpointDiedPreReconcile
|
|
9095
|
+
});
|
|
9096
|
+
} catch (e) {
|
|
9097
|
+
logErr(`phase=task-close-failed status=failed reason="${e instanceof Error ? e.message : String(e)}"`);
|
|
9098
|
+
}
|
|
9099
|
+
return;
|
|
9100
|
+
}
|
|
9101
|
+
unitGoneWithDiskProof = true;
|
|
9102
|
+
} else if (status.execMainStatus !== 0) {
|
|
9103
|
+
logErr(`phase=post-exit-skipped reason=exit=${status.execMainStatus} id=${actionId}`);
|
|
9060
9104
|
try {
|
|
9061
|
-
const diagnostic = status ? `${CLOUDFLARE_TASK_DIAGNOSTICS.scriptExitedNonzero} exit=${status.execMainStatus}` : CLOUDFLARE_TASK_DIAGNOSTICS.endpointDiedPreReconcile;
|
|
9062
9105
|
await completeCloudflareTask({
|
|
9063
9106
|
taskId: cloudflareTask.taskId,
|
|
9064
9107
|
taskElementId: cloudflareTask.taskElementId,
|
|
9065
9108
|
accountId,
|
|
9066
9109
|
conversationKey: sessionKey,
|
|
9067
9110
|
status: "failed",
|
|
9068
|
-
errorMessage:
|
|
9111
|
+
errorMessage: `${CLOUDFLARE_TASK_DIAGNOSTICS.scriptExitedNonzero} exit=${status.execMainStatus}`
|
|
9069
9112
|
});
|
|
9070
9113
|
} catch (e) {
|
|
9071
9114
|
logErr(`phase=task-close-failed status=failed reason="${e instanceof Error ? e.message : String(e)}"`);
|
|
9072
9115
|
}
|
|
9073
9116
|
return;
|
|
9074
9117
|
}
|
|
9075
|
-
|
|
9076
|
-
|
|
9077
|
-
|
|
9078
|
-
|
|
9079
|
-
|
|
9080
|
-
|
|
9081
|
-
|
|
9082
|
-
|
|
9083
|
-
|
|
9084
|
-
|
|
9085
|
-
|
|
9086
|
-
|
|
9087
|
-
|
|
9088
|
-
|
|
9089
|
-
|
|
9118
|
+
if (!unitGoneWithDiskProof) {
|
|
9119
|
+
const candidates = [publicFqdn, apex].filter((h) => typeof h === "string" && h.length > 0);
|
|
9120
|
+
for (const host of candidates) {
|
|
9121
|
+
if (host === adminFqdn) {
|
|
9122
|
+
log(`phase=alias-domain-write host=${host} result=skipped-admin`);
|
|
9123
|
+
continue;
|
|
9124
|
+
}
|
|
9125
|
+
if (host.startsWith("public.")) {
|
|
9126
|
+
log(`phase=alias-domain-write host=${host} result=skipped-public-prefix`);
|
|
9127
|
+
continue;
|
|
9128
|
+
}
|
|
9129
|
+
try {
|
|
9130
|
+
addAliasDomain(host);
|
|
9131
|
+
log(`phase=alias-domain-write host=${host} result=written`);
|
|
9132
|
+
} catch (e) {
|
|
9133
|
+
logErr(`phase=alias-domain-write host=${host} result=error reason="${e instanceof Error ? e.message : String(e)}"`);
|
|
9134
|
+
}
|
|
9090
9135
|
}
|
|
9091
9136
|
}
|
|
9092
9137
|
try {
|
|
@@ -10270,6 +10315,11 @@ var GRAPH_LABEL_COLOURS = {
|
|
|
10270
10315
|
AccessGrant: "#66381F",
|
|
10271
10316
|
// Knowledge — moss family (organic)
|
|
10272
10317
|
KnowledgeDocument: "#6E8A5A",
|
|
10318
|
+
// Task 891 — chunked WhatsApp/messaging archive parent. Sits in the
|
|
10319
|
+
// knowledge moss family because it's structurally a document parent
|
|
10320
|
+
// (HAS_SECTION → :Section:Conversation chunks); the conversational
|
|
10321
|
+
// plum family is reserved for the live Conversation/Message labels.
|
|
10322
|
+
ConversationArchive: "#82A06A",
|
|
10273
10323
|
Section: "#8AA876",
|
|
10274
10324
|
Chunk: "#A6C194",
|
|
10275
10325
|
DigitalDocument: "#5A7548",
|
|
@@ -11736,37 +11786,106 @@ app33.get("/", requireAdminSession, async (c) => {
|
|
|
11736
11786
|
});
|
|
11737
11787
|
var sidebar_artefact_content_default = app33;
|
|
11738
11788
|
|
|
11739
|
-
// server/routes/admin/
|
|
11789
|
+
// server/routes/admin/health.ts
|
|
11790
|
+
import { existsSync as existsSync20, readFileSync as readFileSync14 } from "fs";
|
|
11791
|
+
import { resolve as resolve20, join as join9 } from "path";
|
|
11792
|
+
var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT ?? resolve20(process.cwd(), "..");
|
|
11793
|
+
var brandHostname = "maxy";
|
|
11794
|
+
var brandJsonPath = join9(PLATFORM_ROOT7, "config", "brand.json");
|
|
11795
|
+
if (existsSync20(brandJsonPath)) {
|
|
11796
|
+
try {
|
|
11797
|
+
const brand = JSON.parse(readFileSync14(brandJsonPath, "utf-8"));
|
|
11798
|
+
if (brand.hostname) brandHostname = brand.hostname;
|
|
11799
|
+
} catch {
|
|
11800
|
+
}
|
|
11801
|
+
}
|
|
11802
|
+
var VERSION_FILE = resolve20(PLATFORM_ROOT7, `config/.${brandHostname}-version`);
|
|
11803
|
+
var PROCESS_STARTED_AT = (/* @__PURE__ */ new Date()).toISOString();
|
|
11804
|
+
var PROBE_TIMEOUT_MS = 1e3;
|
|
11805
|
+
function readVersion() {
|
|
11806
|
+
if (!existsSync20(VERSION_FILE)) return "unknown";
|
|
11807
|
+
return readFileSync14(VERSION_FILE, "utf-8").trim() || "unknown";
|
|
11808
|
+
}
|
|
11809
|
+
async function probeConversationDb() {
|
|
11810
|
+
let session;
|
|
11811
|
+
try {
|
|
11812
|
+
session = getSession();
|
|
11813
|
+
} catch (err) {
|
|
11814
|
+
return { state: "error", reason: err instanceof Error ? err.message : String(err) };
|
|
11815
|
+
}
|
|
11816
|
+
let timer2;
|
|
11817
|
+
try {
|
|
11818
|
+
const probe = session.run("RETURN 1");
|
|
11819
|
+
const timeout = new Promise((_, reject) => {
|
|
11820
|
+
timer2 = setTimeout(() => reject(new Error("timeout")), PROBE_TIMEOUT_MS);
|
|
11821
|
+
});
|
|
11822
|
+
await Promise.race([probe, timeout]);
|
|
11823
|
+
return { state: "ok" };
|
|
11824
|
+
} catch (err) {
|
|
11825
|
+
return { state: "error", reason: err instanceof Error ? err.message : String(err) };
|
|
11826
|
+
} finally {
|
|
11827
|
+
if (timer2) clearTimeout(timer2);
|
|
11828
|
+
session.close().catch(() => {
|
|
11829
|
+
});
|
|
11830
|
+
}
|
|
11831
|
+
}
|
|
11740
11832
|
var app34 = new Hono();
|
|
11741
|
-
app34.
|
|
11742
|
-
|
|
11743
|
-
|
|
11744
|
-
|
|
11745
|
-
|
|
11746
|
-
|
|
11747
|
-
|
|
11748
|
-
|
|
11749
|
-
|
|
11750
|
-
|
|
11751
|
-
|
|
11752
|
-
|
|
11753
|
-
|
|
11754
|
-
|
|
11755
|
-
|
|
11756
|
-
|
|
11757
|
-
|
|
11758
|
-
|
|
11759
|
-
|
|
11760
|
-
|
|
11761
|
-
|
|
11762
|
-
|
|
11763
|
-
app34
|
|
11764
|
-
|
|
11765
|
-
|
|
11833
|
+
app34.get("/", async (c) => {
|
|
11834
|
+
const version = readVersion();
|
|
11835
|
+
const probe = await probeConversationDb();
|
|
11836
|
+
const uptimeMs = Date.now() - new Date(PROCESS_STARTED_AT).getTime();
|
|
11837
|
+
if (probe.state === "error") {
|
|
11838
|
+
const reason = (probe.reason ?? "").replace(/\s+/g, " ").trim() || "unknown";
|
|
11839
|
+
console.log(
|
|
11840
|
+
`[admin/health-brand] processStartedAt=${PROCESS_STARTED_AT} uptimeMs=${uptimeMs} version=${version} conversationDb=error errorReason=${reason}`
|
|
11841
|
+
);
|
|
11842
|
+
} else {
|
|
11843
|
+
console.log(
|
|
11844
|
+
`[admin/health-brand] processStartedAt=${PROCESS_STARTED_AT} uptimeMs=${uptimeMs} version=${version} conversationDb=ok`
|
|
11845
|
+
);
|
|
11846
|
+
}
|
|
11847
|
+
return c.json({
|
|
11848
|
+
ok: true,
|
|
11849
|
+
processStartedAt: PROCESS_STARTED_AT,
|
|
11850
|
+
version,
|
|
11851
|
+
conversationDb: probe.state,
|
|
11852
|
+
uptimeMs
|
|
11853
|
+
});
|
|
11854
|
+
});
|
|
11855
|
+
var health_default2 = app34;
|
|
11856
|
+
|
|
11857
|
+
// server/routes/admin/index.ts
|
|
11858
|
+
var app35 = new Hono();
|
|
11859
|
+
app35.route("/session", session_default2);
|
|
11860
|
+
app35.route("/chat", chat_default2);
|
|
11861
|
+
app35.route("/compact", compact_default);
|
|
11862
|
+
app35.route("/logs", logs_default);
|
|
11863
|
+
app35.route("/claude-info", claude_info_default);
|
|
11864
|
+
app35.route("/attachment", attachment_default);
|
|
11865
|
+
app35.route("/agents", agents_default);
|
|
11866
|
+
app35.route("/sessions", sessions_default);
|
|
11867
|
+
app35.route("/browser", browser_default);
|
|
11868
|
+
app35.route("/device-browser", device_browser_default);
|
|
11869
|
+
app35.route("/events", events_default);
|
|
11870
|
+
app35.route("/cloudflare", cloudflare_default);
|
|
11871
|
+
app35.route("/files", files_default);
|
|
11872
|
+
app35.route("/graph-search", graph_search_default);
|
|
11873
|
+
app35.route("/graph-subgraph", graph_subgraph_default);
|
|
11874
|
+
app35.route("/graph-delete", graph_delete_default);
|
|
11875
|
+
app35.route("/graph-restore", graph_restore_default);
|
|
11876
|
+
app35.route("/graph-labels-in-graph", graph_labels_in_graph_default);
|
|
11877
|
+
app35.route("/graph-default-view", graph_default_view_default);
|
|
11878
|
+
app35.route("/file-attach", file_attach_default);
|
|
11879
|
+
app35.route("/adherence", adherence_default);
|
|
11880
|
+
app35.route("/sidebar-artefacts", sidebar_artefacts_default);
|
|
11881
|
+
app35.route("/sidebar-artefact-save", sidebar_artefact_save_default);
|
|
11882
|
+
app35.route("/sidebar-artefact-content", sidebar_artefact_content_default);
|
|
11883
|
+
app35.route("/health-brand", health_default2);
|
|
11884
|
+
var admin_default = app35;
|
|
11766
11885
|
|
|
11767
11886
|
// server/routes/sites.ts
|
|
11768
|
-
import { existsSync as
|
|
11769
|
-
import { resolve as
|
|
11887
|
+
import { existsSync as existsSync21, readFileSync as readFileSync15, realpathSync as realpathSync5, statSync as statSync5 } from "fs";
|
|
11888
|
+
import { resolve as resolve21 } from "path";
|
|
11770
11889
|
var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
|
|
11771
11890
|
var MIME = {
|
|
11772
11891
|
".html": "text/html; charset=utf-8",
|
|
@@ -11797,8 +11916,8 @@ function getExt(p) {
|
|
|
11797
11916
|
if (idx < p.lastIndexOf("/")) return "";
|
|
11798
11917
|
return p.slice(idx).toLowerCase();
|
|
11799
11918
|
}
|
|
11800
|
-
var
|
|
11801
|
-
|
|
11919
|
+
var app36 = new Hono();
|
|
11920
|
+
app36.get("/:rel{.*}", (c) => {
|
|
11802
11921
|
const reqPath = c.req.path;
|
|
11803
11922
|
const rawRel = c.req.param("rel") ?? "";
|
|
11804
11923
|
const trimmed = rawRel.replace(/^\/+/, "").replace(/\/+$/, "");
|
|
@@ -11824,28 +11943,28 @@ app35.get("/:rel{.*}", (c) => {
|
|
|
11824
11943
|
}
|
|
11825
11944
|
segments.push(seg);
|
|
11826
11945
|
}
|
|
11827
|
-
const rootDir =
|
|
11828
|
-
let filePath = segments.length === 0 ? rootDir :
|
|
11946
|
+
const rootDir = resolve21(account.accountDir, "sites");
|
|
11947
|
+
let filePath = segments.length === 0 ? rootDir : resolve21(rootDir, ...segments);
|
|
11829
11948
|
if (filePath !== rootDir && !filePath.startsWith(rootDir + "/")) {
|
|
11830
11949
|
console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
|
|
11831
11950
|
return c.text("Forbidden", 403);
|
|
11832
11951
|
}
|
|
11833
11952
|
let stat7;
|
|
11834
11953
|
try {
|
|
11835
|
-
stat7 =
|
|
11954
|
+
stat7 = existsSync21(filePath) ? statSync5(filePath) : null;
|
|
11836
11955
|
} catch {
|
|
11837
11956
|
stat7 = null;
|
|
11838
11957
|
}
|
|
11839
11958
|
if (stat7?.isDirectory()) {
|
|
11840
|
-
filePath =
|
|
11959
|
+
filePath = resolve21(filePath, "index.html");
|
|
11841
11960
|
} else if (stat7 === null && isDirRequest) {
|
|
11842
|
-
filePath =
|
|
11961
|
+
filePath = resolve21(filePath, "index.html");
|
|
11843
11962
|
}
|
|
11844
11963
|
if (!filePath.startsWith(rootDir + "/")) {
|
|
11845
11964
|
console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
|
|
11846
11965
|
return c.text("Forbidden", 403);
|
|
11847
11966
|
}
|
|
11848
|
-
if (!
|
|
11967
|
+
if (!existsSync21(filePath)) {
|
|
11849
11968
|
console.error(`[sites] not-found path=${reqPath} status=404`);
|
|
11850
11969
|
return c.text("Not found", 404);
|
|
11851
11970
|
}
|
|
@@ -11864,7 +11983,7 @@ app35.get("/:rel{.*}", (c) => {
|
|
|
11864
11983
|
}
|
|
11865
11984
|
let body;
|
|
11866
11985
|
try {
|
|
11867
|
-
body =
|
|
11986
|
+
body = readFileSync15(realPath);
|
|
11868
11987
|
} catch (err) {
|
|
11869
11988
|
const code = err?.code;
|
|
11870
11989
|
if (code === "EISDIR") {
|
|
@@ -11896,7 +12015,7 @@ app35.get("/:rel{.*}", (c) => {
|
|
|
11896
12015
|
"X-Content-Type-Options": "nosniff"
|
|
11897
12016
|
});
|
|
11898
12017
|
});
|
|
11899
|
-
var sites_default =
|
|
12018
|
+
var sites_default = app36;
|
|
11900
12019
|
|
|
11901
12020
|
// app/lib/graph-health.ts
|
|
11902
12021
|
var HOUR_MS = 60 * 60 * 1e3;
|
|
@@ -11995,15 +12114,15 @@ function clientFrom(c) {
|
|
|
11995
12114
|
c.req.header("x-forwarded-for")
|
|
11996
12115
|
);
|
|
11997
12116
|
}
|
|
11998
|
-
var
|
|
11999
|
-
var BRAND_JSON_PATH =
|
|
12117
|
+
var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT || "";
|
|
12118
|
+
var BRAND_JSON_PATH = PLATFORM_ROOT8 ? join10(PLATFORM_ROOT8, "config", "brand.json") : "";
|
|
12000
12119
|
var BRAND = { productName: "Maxy", hostname: "maxy", configDir: ".maxy", domain: "getmaxy.com" };
|
|
12001
|
-
if (BRAND_JSON_PATH && !
|
|
12120
|
+
if (BRAND_JSON_PATH && !existsSync22(BRAND_JSON_PATH)) {
|
|
12002
12121
|
console.error(`[brand] WARNING: brand.json not found at ${BRAND_JSON_PATH} \u2014 using Maxy defaults`);
|
|
12003
12122
|
}
|
|
12004
|
-
if (BRAND_JSON_PATH &&
|
|
12123
|
+
if (BRAND_JSON_PATH && existsSync22(BRAND_JSON_PATH)) {
|
|
12005
12124
|
try {
|
|
12006
|
-
const parsed = JSON.parse(
|
|
12125
|
+
const parsed = JSON.parse(readFileSync16(BRAND_JSON_PATH, "utf-8"));
|
|
12007
12126
|
BRAND = { ...BRAND, ...parsed };
|
|
12008
12127
|
} catch (err) {
|
|
12009
12128
|
console.error(`[brand] Failed to parse brand.json: ${err.message}`);
|
|
@@ -12022,11 +12141,11 @@ var brandLoginOpts = {
|
|
|
12022
12141
|
bodyFont: BRAND.defaultFonts?.body,
|
|
12023
12142
|
logoContainsName: !!BRAND.logoContainsName
|
|
12024
12143
|
};
|
|
12025
|
-
var ALIAS_DOMAINS_PATH2 =
|
|
12144
|
+
var ALIAS_DOMAINS_PATH2 = join10(homedir2(), BRAND.configDir, "alias-domains.json");
|
|
12026
12145
|
function loadAliasDomains() {
|
|
12027
12146
|
try {
|
|
12028
|
-
if (!
|
|
12029
|
-
const parsed = JSON.parse(
|
|
12147
|
+
if (!existsSync22(ALIAS_DOMAINS_PATH2)) return null;
|
|
12148
|
+
const parsed = JSON.parse(readFileSync16(ALIAS_DOMAINS_PATH2, "utf-8"));
|
|
12030
12149
|
if (!Array.isArray(parsed)) {
|
|
12031
12150
|
console.error("[alias-domains] malformed alias-domains.json \u2014 expected array");
|
|
12032
12151
|
return null;
|
|
@@ -12050,9 +12169,9 @@ watchFile(ALIAS_DOMAINS_PATH2, { interval: 2e3 }, () => {
|
|
|
12050
12169
|
function isPublicHost(host) {
|
|
12051
12170
|
return host.startsWith("public.") || aliasDomains.has(host);
|
|
12052
12171
|
}
|
|
12053
|
-
var
|
|
12054
|
-
|
|
12055
|
-
|
|
12172
|
+
var app37 = new Hono();
|
|
12173
|
+
app37.use("*", clientIpMiddleware);
|
|
12174
|
+
app37.use("*", async (c, next) => {
|
|
12056
12175
|
await next();
|
|
12057
12176
|
c.header("X-Content-Type-Options", "nosniff");
|
|
12058
12177
|
c.header("Referrer-Policy", "strict-origin-when-cross-origin");
|
|
@@ -12076,7 +12195,7 @@ var PUBLIC_ALLOWED_PREFIXES = [
|
|
|
12076
12195
|
"/sites/"
|
|
12077
12196
|
];
|
|
12078
12197
|
var PUBLIC_ALLOWED_EXACT = ["/favicon.ico"];
|
|
12079
|
-
|
|
12198
|
+
app37.use("*", async (c, next) => {
|
|
12080
12199
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
12081
12200
|
if (!isPublicHost(host)) {
|
|
12082
12201
|
await next();
|
|
@@ -12116,7 +12235,7 @@ function resolveRemoteAuthOpts() {
|
|
|
12116
12235
|
return brandLoginOpts;
|
|
12117
12236
|
}
|
|
12118
12237
|
var MAX_LOGIN_BODY = 8 * 1024;
|
|
12119
|
-
|
|
12238
|
+
app37.post("/__remote-auth/login", async (c) => {
|
|
12120
12239
|
const client = clientFrom(c);
|
|
12121
12240
|
const clientIp = client.ip || "unknown";
|
|
12122
12241
|
if (!requestIsTlsTerminated(c)) {
|
|
@@ -12160,7 +12279,7 @@ app36.post("/__remote-auth/login", async (c) => {
|
|
|
12160
12279
|
}
|
|
12161
12280
|
});
|
|
12162
12281
|
});
|
|
12163
|
-
|
|
12282
|
+
app37.get("/__remote-auth/logout", (c) => {
|
|
12164
12283
|
return new Response(null, {
|
|
12165
12284
|
status: 302,
|
|
12166
12285
|
headers: {
|
|
@@ -12170,7 +12289,7 @@ app36.get("/__remote-auth/logout", (c) => {
|
|
|
12170
12289
|
}
|
|
12171
12290
|
});
|
|
12172
12291
|
});
|
|
12173
|
-
|
|
12292
|
+
app37.post("/__remote-auth/change-password", async (c) => {
|
|
12174
12293
|
const client = clientFrom(c);
|
|
12175
12294
|
const clientIp = client.ip || "unknown";
|
|
12176
12295
|
const rateLimited = checkRateLimit(client);
|
|
@@ -12220,13 +12339,13 @@ app36.post("/__remote-auth/change-password", async (c) => {
|
|
|
12220
12339
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "change", changeError: "Failed to save password", redirect }), 200);
|
|
12221
12340
|
}
|
|
12222
12341
|
});
|
|
12223
|
-
|
|
12342
|
+
app37.get("/__remote-auth/setup", (c) => {
|
|
12224
12343
|
if (isRemoteAuthConfigured()) {
|
|
12225
12344
|
return c.redirect("/");
|
|
12226
12345
|
}
|
|
12227
12346
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "setup" }), 200);
|
|
12228
12347
|
});
|
|
12229
|
-
|
|
12348
|
+
app37.post("/__remote-auth/set-initial-password", async (c) => {
|
|
12230
12349
|
if (isRemoteAuthConfigured()) {
|
|
12231
12350
|
return c.redirect("/");
|
|
12232
12351
|
}
|
|
@@ -12262,10 +12381,10 @@ app36.post("/__remote-auth/set-initial-password", async (c) => {
|
|
|
12262
12381
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "setup", setupError: "Failed to save password. Please try again." }), 200);
|
|
12263
12382
|
}
|
|
12264
12383
|
});
|
|
12265
|
-
|
|
12384
|
+
app37.get("/api/remote-auth/status", (c) => {
|
|
12266
12385
|
return c.json({ configured: isRemoteAuthConfigured() });
|
|
12267
12386
|
});
|
|
12268
|
-
|
|
12387
|
+
app37.post("/api/remote-auth/set-password", async (c) => {
|
|
12269
12388
|
let body;
|
|
12270
12389
|
try {
|
|
12271
12390
|
body = await c.req.json();
|
|
@@ -12295,9 +12414,9 @@ app36.post("/api/remote-auth/set-password", async (c) => {
|
|
|
12295
12414
|
return c.json({ error: "Failed to save password" }, 500);
|
|
12296
12415
|
}
|
|
12297
12416
|
});
|
|
12298
|
-
|
|
12417
|
+
app37.route("/api/_client-error", client_error_default);
|
|
12299
12418
|
console.log("[client-error-route] mounted");
|
|
12300
|
-
|
|
12419
|
+
app37.use("*", async (c, next) => {
|
|
12301
12420
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
12302
12421
|
const path2 = c.req.path;
|
|
12303
12422
|
if (path2 === "/favicon.ico" || path2.startsWith("/assets/") || path2.startsWith("/brand/")) {
|
|
@@ -12330,15 +12449,15 @@ app36.use("*", async (c, next) => {
|
|
|
12330
12449
|
console.error(`[remote-auth] login required ip=${clientIp} path=${path2} ${disambig}`);
|
|
12331
12450
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), redirect: path2 }), 200);
|
|
12332
12451
|
});
|
|
12333
|
-
|
|
12334
|
-
|
|
12335
|
-
|
|
12336
|
-
|
|
12337
|
-
|
|
12338
|
-
|
|
12339
|
-
|
|
12340
|
-
|
|
12341
|
-
|
|
12452
|
+
app37.route("/api/health", health_default);
|
|
12453
|
+
app37.route("/api/session", session_default);
|
|
12454
|
+
app37.route("/api/chat", chat_default);
|
|
12455
|
+
app37.route("/api/group", group_default);
|
|
12456
|
+
app37.route("/api/access", access_default);
|
|
12457
|
+
app37.route("/api/telegram", telegram_default);
|
|
12458
|
+
app37.route("/api/whatsapp", whatsapp_default);
|
|
12459
|
+
app37.route("/api/onboarding", onboarding_default);
|
|
12460
|
+
app37.route("/api/admin", admin_default);
|
|
12342
12461
|
var SAFE_SLUG_RE = /^[a-z][a-z0-9-]{2,49}$/;
|
|
12343
12462
|
var SAFE_FILENAME_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
|
|
12344
12463
|
var IMAGE_MIME = {
|
|
@@ -12350,7 +12469,7 @@ var IMAGE_MIME = {
|
|
|
12350
12469
|
".svg": "image/svg+xml",
|
|
12351
12470
|
".ico": "image/x-icon"
|
|
12352
12471
|
};
|
|
12353
|
-
|
|
12472
|
+
app37.get("/agent-assets/:slug/:filename", (c) => {
|
|
12354
12473
|
const slug = c.req.param("slug");
|
|
12355
12474
|
const filename = c.req.param("filename");
|
|
12356
12475
|
if (!SAFE_SLUG_RE.test(slug)) {
|
|
@@ -12366,26 +12485,26 @@ app36.get("/agent-assets/:slug/:filename", (c) => {
|
|
|
12366
12485
|
console.error(`[agent-assets] no-account slug=${slug} file=${filename}`);
|
|
12367
12486
|
return c.text("Not found", 404);
|
|
12368
12487
|
}
|
|
12369
|
-
const filePath =
|
|
12370
|
-
const expectedDir =
|
|
12488
|
+
const filePath = resolve22(account.accountDir, "agents", slug, "assets", filename);
|
|
12489
|
+
const expectedDir = resolve22(account.accountDir, "agents", slug, "assets");
|
|
12371
12490
|
if (!filePath.startsWith(expectedDir + "/")) {
|
|
12372
12491
|
console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
|
|
12373
12492
|
return c.text("Forbidden", 403);
|
|
12374
12493
|
}
|
|
12375
|
-
if (!
|
|
12494
|
+
if (!existsSync22(filePath)) {
|
|
12376
12495
|
console.error(`[agent-assets] serve slug=${slug} file=${filename} status=404`);
|
|
12377
12496
|
return c.text("Not found", 404);
|
|
12378
12497
|
}
|
|
12379
12498
|
const ext = "." + filename.split(".").pop()?.toLowerCase();
|
|
12380
12499
|
const contentType = IMAGE_MIME[ext] || "application/octet-stream";
|
|
12381
12500
|
console.log(`[agent-assets] serve slug=${slug} file=${filename} status=200`);
|
|
12382
|
-
const body =
|
|
12501
|
+
const body = readFileSync16(filePath);
|
|
12383
12502
|
return c.body(body, 200, {
|
|
12384
12503
|
"Content-Type": contentType,
|
|
12385
12504
|
"Cache-Control": "public, max-age=3600"
|
|
12386
12505
|
});
|
|
12387
12506
|
});
|
|
12388
|
-
|
|
12507
|
+
app37.get("/generated/:filename", (c) => {
|
|
12389
12508
|
const filename = c.req.param("filename");
|
|
12390
12509
|
if (!SAFE_FILENAME_RE.test(filename) || filename.includes("..")) {
|
|
12391
12510
|
console.error(`[generated] serve file=${filename} status=403`);
|
|
@@ -12396,32 +12515,32 @@ app36.get("/generated/:filename", (c) => {
|
|
|
12396
12515
|
console.error(`[generated] serve file=${filename} status=404`);
|
|
12397
12516
|
return c.text("Not found", 404);
|
|
12398
12517
|
}
|
|
12399
|
-
const filePath =
|
|
12400
|
-
const expectedDir =
|
|
12518
|
+
const filePath = resolve22(account.accountDir, "generated", filename);
|
|
12519
|
+
const expectedDir = resolve22(account.accountDir, "generated");
|
|
12401
12520
|
if (!filePath.startsWith(expectedDir + "/")) {
|
|
12402
12521
|
console.error(`[generated] serve file=${filename} status=403`);
|
|
12403
12522
|
return c.text("Forbidden", 403);
|
|
12404
12523
|
}
|
|
12405
|
-
if (!
|
|
12524
|
+
if (!existsSync22(filePath)) {
|
|
12406
12525
|
console.error(`[generated] serve file=${filename} status=404`);
|
|
12407
12526
|
return c.text("Not found", 404);
|
|
12408
12527
|
}
|
|
12409
12528
|
const ext = "." + filename.split(".").pop()?.toLowerCase();
|
|
12410
12529
|
const contentType = IMAGE_MIME[ext] || "application/octet-stream";
|
|
12411
12530
|
console.log(`[generated] serve file=${filename} status=200`);
|
|
12412
|
-
const body =
|
|
12531
|
+
const body = readFileSync16(filePath);
|
|
12413
12532
|
return c.body(body, 200, {
|
|
12414
12533
|
"Content-Type": contentType,
|
|
12415
12534
|
"Cache-Control": "public, max-age=86400"
|
|
12416
12535
|
});
|
|
12417
12536
|
});
|
|
12418
|
-
|
|
12537
|
+
app37.route("/sites", sites_default);
|
|
12419
12538
|
var htmlCache = /* @__PURE__ */ new Map();
|
|
12420
12539
|
var brandLogoPath = "/brand/maxy-monochrome.png";
|
|
12421
12540
|
var brandIconPath = "/brand/maxy-monochrome.png";
|
|
12422
|
-
if (BRAND_JSON_PATH &&
|
|
12541
|
+
if (BRAND_JSON_PATH && existsSync22(BRAND_JSON_PATH)) {
|
|
12423
12542
|
try {
|
|
12424
|
-
const fullBrand = JSON.parse(
|
|
12543
|
+
const fullBrand = JSON.parse(readFileSync16(BRAND_JSON_PATH, "utf-8"));
|
|
12425
12544
|
if (fullBrand.assets?.logo) brandLogoPath = `/brand/${fullBrand.assets.logo}`;
|
|
12426
12545
|
brandIconPath = fullBrand.assets?.icon ? `/brand/${fullBrand.assets.icon}` : brandLogoPath;
|
|
12427
12546
|
} catch {
|
|
@@ -12437,10 +12556,10 @@ var brandScript = `<script>window.__BRAND__=${JSON.stringify({
|
|
|
12437
12556
|
})}</script>`;
|
|
12438
12557
|
function readInstalledVersion() {
|
|
12439
12558
|
try {
|
|
12440
|
-
if (!
|
|
12441
|
-
const versionFile =
|
|
12442
|
-
if (!
|
|
12443
|
-
const content =
|
|
12559
|
+
if (!PLATFORM_ROOT8) return "unknown";
|
|
12560
|
+
const versionFile = join10(PLATFORM_ROOT8, "config", `.${BRAND.hostname}-version`);
|
|
12561
|
+
if (!existsSync22(versionFile)) return "unknown";
|
|
12562
|
+
const content = readFileSync16(versionFile, "utf-8").trim();
|
|
12444
12563
|
return content || "unknown";
|
|
12445
12564
|
} catch {
|
|
12446
12565
|
return "unknown";
|
|
@@ -12481,7 +12600,7 @@ var clientErrorReporterScript = `<script>
|
|
|
12481
12600
|
function cachedHtml(file) {
|
|
12482
12601
|
let html = htmlCache.get(file);
|
|
12483
12602
|
if (!html) {
|
|
12484
|
-
html =
|
|
12603
|
+
html = readFileSync16(resolve22(process.cwd(), "public", file), "utf-8");
|
|
12485
12604
|
const productNameEsc = escapeHtml(BRAND.productName);
|
|
12486
12605
|
html = html.replace(/<title>([^<]*)<\/title>/, (_match, inner) => `<title>${escapeHtml(inner).replace(/Maxy/g, productNameEsc)}</title>`);
|
|
12487
12606
|
html = html.replace('href="/favicon.ico"', `href="${escapeHtml(brandFaviconPath)}"`);
|
|
@@ -12497,26 +12616,26 @@ ${clientErrorReporterScript}
|
|
|
12497
12616
|
}
|
|
12498
12617
|
var brandedHtmlCache = /* @__PURE__ */ new Map();
|
|
12499
12618
|
function loadBrandingCache(agentSlug) {
|
|
12500
|
-
const configDir2 =
|
|
12619
|
+
const configDir2 = join10(homedir2(), BRAND.configDir);
|
|
12501
12620
|
try {
|
|
12502
|
-
const accountJsonPath =
|
|
12503
|
-
if (!
|
|
12504
|
-
const account = JSON.parse(
|
|
12621
|
+
const accountJsonPath = join10(configDir2, "account.json");
|
|
12622
|
+
if (!existsSync22(accountJsonPath)) return null;
|
|
12623
|
+
const account = JSON.parse(readFileSync16(accountJsonPath, "utf-8"));
|
|
12505
12624
|
const accountId = account.accountId;
|
|
12506
12625
|
if (!accountId) return null;
|
|
12507
|
-
const cachePath =
|
|
12508
|
-
if (!
|
|
12509
|
-
return JSON.parse(
|
|
12626
|
+
const cachePath = join10(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
|
|
12627
|
+
if (!existsSync22(cachePath)) return null;
|
|
12628
|
+
return JSON.parse(readFileSync16(cachePath, "utf-8"));
|
|
12510
12629
|
} catch {
|
|
12511
12630
|
return null;
|
|
12512
12631
|
}
|
|
12513
12632
|
}
|
|
12514
12633
|
function resolveDefaultSlug() {
|
|
12515
12634
|
try {
|
|
12516
|
-
const configDir2 =
|
|
12517
|
-
const accountJsonPath =
|
|
12518
|
-
if (!
|
|
12519
|
-
const account = JSON.parse(
|
|
12635
|
+
const configDir2 = join10(homedir2(), BRAND.configDir);
|
|
12636
|
+
const accountJsonPath = join10(configDir2, "account.json");
|
|
12637
|
+
if (!existsSync22(accountJsonPath)) return null;
|
|
12638
|
+
const account = JSON.parse(readFileSync16(accountJsonPath, "utf-8"));
|
|
12520
12639
|
return account.defaultAgent || null;
|
|
12521
12640
|
} catch {
|
|
12522
12641
|
return null;
|
|
@@ -12552,7 +12671,7 @@ function brandedPublicHtml(agentSlug) {
|
|
|
12552
12671
|
function escapeHtml(s) {
|
|
12553
12672
|
return s.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
12554
12673
|
}
|
|
12555
|
-
|
|
12674
|
+
app37.get("/", (c) => {
|
|
12556
12675
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
12557
12676
|
if (isPublicHost(host)) {
|
|
12558
12677
|
const defaultSlug = resolveDefaultSlug();
|
|
@@ -12560,12 +12679,12 @@ app36.get("/", (c) => {
|
|
|
12560
12679
|
}
|
|
12561
12680
|
return c.html(cachedHtml("index.html"));
|
|
12562
12681
|
});
|
|
12563
|
-
|
|
12682
|
+
app37.get("/public", (c) => {
|
|
12564
12683
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
12565
12684
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
12566
12685
|
return c.html(cachedHtml("public.html"));
|
|
12567
12686
|
});
|
|
12568
|
-
|
|
12687
|
+
app37.get("/chat", (c) => {
|
|
12569
12688
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
12570
12689
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
12571
12690
|
return c.html(cachedHtml("public.html"));
|
|
@@ -12584,12 +12703,12 @@ async function logViewerFetch(c, next) {
|
|
|
12584
12703
|
duration_ms: Date.now() - start
|
|
12585
12704
|
});
|
|
12586
12705
|
}
|
|
12587
|
-
|
|
12588
|
-
|
|
12589
|
-
|
|
12706
|
+
app37.use("/vnc-viewer.html", logViewerFetch);
|
|
12707
|
+
app37.use("/vnc-popout.html", logViewerFetch);
|
|
12708
|
+
app37.get("/vnc-popout.html", (c) => {
|
|
12590
12709
|
let html = htmlCache.get("vnc-popout.html");
|
|
12591
12710
|
if (!html) {
|
|
12592
|
-
html =
|
|
12711
|
+
html = readFileSync16(resolve22(process.cwd(), "public", "vnc-popout.html"), "utf-8");
|
|
12593
12712
|
const name = escapeHtml(BRAND.productName);
|
|
12594
12713
|
html = html.replace("<title>Browser \u2014 Maxy</title>", `<title>${name}</title>`);
|
|
12595
12714
|
html = html.replace("</head>", ` ${brandScript}
|
|
@@ -12599,7 +12718,7 @@ app36.get("/vnc-popout.html", (c) => {
|
|
|
12599
12718
|
}
|
|
12600
12719
|
return c.html(html);
|
|
12601
12720
|
});
|
|
12602
|
-
|
|
12721
|
+
app37.post("/api/vnc/client-event", async (c) => {
|
|
12603
12722
|
let body;
|
|
12604
12723
|
try {
|
|
12605
12724
|
body = await c.req.json();
|
|
@@ -12620,20 +12739,20 @@ app36.post("/api/vnc/client-event", async (c) => {
|
|
|
12620
12739
|
});
|
|
12621
12740
|
return c.json({ ok: true });
|
|
12622
12741
|
});
|
|
12623
|
-
|
|
12742
|
+
app37.get("/g/:slug", (c) => {
|
|
12624
12743
|
return c.html(brandedPublicHtml());
|
|
12625
12744
|
});
|
|
12626
|
-
|
|
12745
|
+
app37.get("/graph", (c) => {
|
|
12627
12746
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
12628
12747
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
12629
12748
|
return c.html(cachedHtml("graph.html"));
|
|
12630
12749
|
});
|
|
12631
|
-
|
|
12750
|
+
app37.get("/data", (c) => {
|
|
12632
12751
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
12633
12752
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
12634
12753
|
return c.html(cachedHtml("data.html"));
|
|
12635
12754
|
});
|
|
12636
|
-
|
|
12755
|
+
app37.get("/:slug", async (c, next) => {
|
|
12637
12756
|
const slug = c.req.param("slug");
|
|
12638
12757
|
if (AGENT_SLUG_PATTERN.test(`/${slug}`)) {
|
|
12639
12758
|
const branding = loadBrandingCache(slug);
|
|
@@ -12642,10 +12761,10 @@ app36.get("/:slug", async (c, next) => {
|
|
|
12642
12761
|
}
|
|
12643
12762
|
await next();
|
|
12644
12763
|
});
|
|
12645
|
-
|
|
12764
|
+
app37.use("/*", serveStatic({ root: "./public" }));
|
|
12646
12765
|
var port = parseInt(process.env.MAXY_UI_INTERNAL_PORT ?? process.env.PORT ?? "19199", 10);
|
|
12647
12766
|
var hostname = process.env.HOSTNAME ?? "127.0.0.1";
|
|
12648
|
-
var httpServer = serve({ fetch:
|
|
12767
|
+
var httpServer = serve({ fetch: app37.fetch, port, hostname });
|
|
12649
12768
|
console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
12650
12769
|
var SUBAPP_MANIFEST = [
|
|
12651
12770
|
{ prefix: "/api/health", file: "server/routes/health.ts", subapp: health_default },
|
|
@@ -12665,7 +12784,7 @@ for (const m of SUBAPP_MANIFEST) {
|
|
|
12665
12784
|
}
|
|
12666
12785
|
try {
|
|
12667
12786
|
const registered = [];
|
|
12668
|
-
for (const r of
|
|
12787
|
+
for (const r of app37.routes ?? []) {
|
|
12669
12788
|
if (typeof r.path !== "string" || r.path.includes(":") || r.path.includes("*")) continue;
|
|
12670
12789
|
if (AGENT_SLUG_PATTERN.test(r.path)) {
|
|
12671
12790
|
registered.push({ method: (r.method ?? "ALL").toUpperCase(), path: r.path });
|
|
@@ -12679,8 +12798,8 @@ try {
|
|
|
12679
12798
|
(async () => {
|
|
12680
12799
|
try {
|
|
12681
12800
|
let userId = "";
|
|
12682
|
-
if (
|
|
12683
|
-
const users = JSON.parse(
|
|
12801
|
+
if (existsSync22(USERS_FILE)) {
|
|
12802
|
+
const users = JSON.parse(readFileSync16(USERS_FILE, "utf-8").trim() || "[]");
|
|
12684
12803
|
userId = users[0]?.userId ?? "";
|
|
12685
12804
|
}
|
|
12686
12805
|
await backfillNullUserIdConversations(userId);
|
|
@@ -12713,7 +12832,7 @@ autoDeliverPremiumPlugins(bootEntitlement?.purchasedPlugins ?? void 0);
|
|
|
12713
12832
|
(async () => {
|
|
12714
12833
|
if (!bootAccount) return;
|
|
12715
12834
|
try {
|
|
12716
|
-
const { recoverRunningCloudflareTasks } = await import("./cloudflare-task-tracker-
|
|
12835
|
+
const { recoverRunningCloudflareTasks } = await import("./cloudflare-task-tracker-CR6TL4VL.js");
|
|
12717
12836
|
const result = await recoverRunningCloudflareTasks(
|
|
12718
12837
|
bootAccount.accountId,
|
|
12719
12838
|
configDirForWhatsApp,
|
|
@@ -12763,7 +12882,7 @@ if (bootAccountConfig?.whatsapp) {
|
|
|
12763
12882
|
}
|
|
12764
12883
|
init({
|
|
12765
12884
|
configDir: configDirForWhatsApp,
|
|
12766
|
-
platformRoot:
|
|
12885
|
+
platformRoot: resolve22(process.env.MAXY_PLATFORM_ROOT ?? join10(__dirname, "..")),
|
|
12767
12886
|
accountConfig: bootAccountConfig,
|
|
12768
12887
|
onMessage: async (msg) => {
|
|
12769
12888
|
try {
|