@rubytech/create-realagent 1.0.759 → 1.0.761
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/package.json +2 -2
- package/payload/platform/plugins/docs/references/platform.md +1 -1
- package/payload/platform/plugins/memory/PLUGIN.md +2 -0
- package/payload/platform/plugins/memory/mcp/dist/index.js +133 -1
- package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-write.test.js +42 -2
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-write.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.d.ts +15 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.js +34 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/whatsapp-export-insight-write.d.ts +27 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/whatsapp-export-insight-write.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/whatsapp-export-insight-write.js +160 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/whatsapp-export-insight-write.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/whatsapp-export-parse.d.ts +9 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/whatsapp-export-parse.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/whatsapp-export-parse.js +29 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/whatsapp-export-parse.js.map +1 -0
- package/payload/platform/plugins/whatsapp-import/lib/dist/index.d.ts +3 -0
- package/payload/platform/plugins/whatsapp-import/lib/dist/index.d.ts.map +1 -0
- package/payload/platform/plugins/whatsapp-import/lib/dist/index.js +6 -0
- package/payload/platform/plugins/whatsapp-import/lib/dist/index.js.map +1 -0
- package/payload/platform/plugins/whatsapp-import/lib/dist/parse-export.d.ts +33 -0
- package/payload/platform/plugins/whatsapp-import/lib/dist/parse-export.d.ts.map +1 -0
- package/payload/platform/plugins/whatsapp-import/lib/dist/parse-export.js +253 -0
- package/payload/platform/plugins/whatsapp-import/lib/dist/parse-export.js.map +1 -0
- package/payload/platform/plugins/whatsapp-import/lib/src/__tests__/parse-export.test.ts +503 -0
- package/payload/platform/plugins/whatsapp-import/lib/src/index.ts +7 -0
- package/payload/platform/plugins/whatsapp-import/lib/src/parse-export.ts +385 -0
- package/payload/platform/plugins/whatsapp-import/lib/tsconfig.json +9 -0
- package/payload/platform/plugins/whatsapp-import/lib/vitest.config.ts +9 -0
- package/payload/platform/plugins/whatsapp-import/skills/whatsapp-import/SKILL.md +9 -11
- package/payload/platform/plugins/whatsapp-import/skills/whatsapp-import/references/export-parse.md +10 -5
- package/payload/platform/plugins/whatsapp-import/skills/whatsapp-import/references/insight-extraction.md +18 -15
- package/payload/platform/templates/specialists/agents/database-operator.md +1 -1
- package/payload/server/chunk-43JK6WNK.js +3057 -0
- package/payload/server/chunk-QXAUMZXQ.js +9512 -0
- package/payload/server/chunk-WW464F23.js +9512 -0
- package/payload/server/client-pool-SGPHSYLK.js +28 -0
- package/payload/server/maxy-edge.js +2 -2
- package/payload/server/public/assets/admin-GIIfvDj1.js +352 -0
- package/payload/server/public/index.html +1 -1
- package/payload/server/server.js +222 -94
- package/payload/server/public/assets/admin-DHg5a2u2.js +0 -352
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
6
|
<title>Real Agent</title>
|
|
7
7
|
<link rel="icon" href="/favicon.ico">
|
|
8
|
-
<script type="module" crossorigin src="/assets/admin-
|
|
8
|
+
<script type="module" crossorigin src="/assets/admin-GIIfvDj1.js"></script>
|
|
9
9
|
<link rel="modulepreload" crossorigin href="/assets/chunk-DD-I1_y5.js">
|
|
10
10
|
<link rel="modulepreload" crossorigin href="/assets/jsx-runtime-CFleUYzT.js">
|
|
11
11
|
<link rel="modulepreload" crossorigin href="/assets/preload-helper-BEFjQwLd.js">
|
package/payload/server/server.js
CHANGED
|
@@ -47,7 +47,7 @@ import {
|
|
|
47
47
|
vncLog,
|
|
48
48
|
waitForExit,
|
|
49
49
|
writeChromiumWrapper
|
|
50
|
-
} from "./chunk-
|
|
50
|
+
} from "./chunk-QXAUMZXQ.js";
|
|
51
51
|
import {
|
|
52
52
|
ACCOUNTS_DIR,
|
|
53
53
|
GREETING_DIRECTIVE,
|
|
@@ -77,6 +77,7 @@ import {
|
|
|
77
77
|
getGroupSlugForSession,
|
|
78
78
|
getMessagesSince,
|
|
79
79
|
getRecentMessages,
|
|
80
|
+
getRoleForSession,
|
|
80
81
|
getSession,
|
|
81
82
|
getSessionMessages,
|
|
82
83
|
getUserIdForSession,
|
|
@@ -106,7 +107,7 @@ import {
|
|
|
106
107
|
validateSession,
|
|
107
108
|
verifyAndGetConversationUpdatedAt,
|
|
108
109
|
verifyConversationOwnership
|
|
109
|
-
} from "./chunk-
|
|
110
|
+
} from "./chunk-43JK6WNK.js";
|
|
110
111
|
|
|
111
112
|
// ../lib/graph-trash/dist/index.js
|
|
112
113
|
var require_dist = __commonJS({
|
|
@@ -606,7 +607,7 @@ var serveStatic = (options = { root: "" }) => {
|
|
|
606
607
|
|
|
607
608
|
// server/index.ts
|
|
608
609
|
import { readFileSync as readFileSync16, existsSync as existsSync19, watchFile } from "fs";
|
|
609
|
-
import { resolve as
|
|
610
|
+
import { resolve as resolve21, join as join10, basename as basename7 } from "path";
|
|
610
611
|
import { homedir as homedir2 } from "os";
|
|
611
612
|
|
|
612
613
|
// app/lib/agent-slug-pattern.ts
|
|
@@ -2691,7 +2692,7 @@ var credsSaveQueue = Promise.resolve();
|
|
|
2691
2692
|
async function drainCredsSaveQueue(timeoutMs = 5e3) {
|
|
2692
2693
|
console.error(`${TAG3} draining credential save queue\u2026`);
|
|
2693
2694
|
const timer2 = new Promise(
|
|
2694
|
-
(
|
|
2695
|
+
(resolve22) => setTimeout(() => resolve22("timeout"), timeoutMs)
|
|
2695
2696
|
);
|
|
2696
2697
|
const result = await Promise.race([
|
|
2697
2698
|
credsSaveQueue.then(() => "drained"),
|
|
@@ -2819,11 +2820,11 @@ async function createWaSocket(opts) {
|
|
|
2819
2820
|
return sock;
|
|
2820
2821
|
}
|
|
2821
2822
|
async function waitForConnection(sock) {
|
|
2822
|
-
return new Promise((
|
|
2823
|
+
return new Promise((resolve22, reject) => {
|
|
2823
2824
|
const handler = (update) => {
|
|
2824
2825
|
if (update.connection === "open") {
|
|
2825
2826
|
sock.ev.off("connection.update", handler);
|
|
2826
|
-
|
|
2827
|
+
resolve22();
|
|
2827
2828
|
}
|
|
2828
2829
|
if (update.connection === "close") {
|
|
2829
2830
|
sock.ev.off("connection.update", handler);
|
|
@@ -2937,14 +2938,14 @@ ${inspected}`;
|
|
|
2937
2938
|
return inspect2(err, INSPECT_OPTS2);
|
|
2938
2939
|
}
|
|
2939
2940
|
function withTimeout(label, promise, timeoutMs) {
|
|
2940
|
-
return new Promise((
|
|
2941
|
+
return new Promise((resolve22, reject) => {
|
|
2941
2942
|
const timer2 = setTimeout(() => {
|
|
2942
2943
|
reject(new Error(`${label} timed out after ${timeoutMs}ms`));
|
|
2943
2944
|
}, timeoutMs);
|
|
2944
2945
|
promise.then(
|
|
2945
2946
|
(value) => {
|
|
2946
2947
|
clearTimeout(timer2);
|
|
2947
|
-
|
|
2948
|
+
resolve22(value);
|
|
2948
2949
|
},
|
|
2949
2950
|
(err) => {
|
|
2950
2951
|
clearTimeout(timer2);
|
|
@@ -4158,11 +4159,11 @@ async function connectWithReconnect(conn) {
|
|
|
4158
4159
|
console.error(
|
|
4159
4160
|
`${TAG11} reconnecting account=${conn.accountId} in ${delay}ms (attempt ${decision.nextAttempts}/${maxAttempts})`
|
|
4160
4161
|
);
|
|
4161
|
-
await new Promise((
|
|
4162
|
-
const timer2 = setTimeout(
|
|
4162
|
+
await new Promise((resolve22) => {
|
|
4163
|
+
const timer2 = setTimeout(resolve22, delay);
|
|
4163
4164
|
conn.abortController.signal.addEventListener("abort", () => {
|
|
4164
4165
|
clearTimeout(timer2);
|
|
4165
|
-
|
|
4166
|
+
resolve22();
|
|
4166
4167
|
}, { once: true });
|
|
4167
4168
|
});
|
|
4168
4169
|
}
|
|
@@ -4170,16 +4171,16 @@ async function connectWithReconnect(conn) {
|
|
|
4170
4171
|
}
|
|
4171
4172
|
}
|
|
4172
4173
|
function waitForDisconnectEvent(conn) {
|
|
4173
|
-
return new Promise((
|
|
4174
|
+
return new Promise((resolve22) => {
|
|
4174
4175
|
if (!conn.sock) {
|
|
4175
|
-
|
|
4176
|
+
resolve22();
|
|
4176
4177
|
return;
|
|
4177
4178
|
}
|
|
4178
4179
|
const sock = conn.sock;
|
|
4179
4180
|
const handler = (update) => {
|
|
4180
4181
|
if (update.connection === "close") {
|
|
4181
4182
|
sock.ev.off("connection.update", handler);
|
|
4182
|
-
|
|
4183
|
+
resolve22();
|
|
4183
4184
|
}
|
|
4184
4185
|
};
|
|
4185
4186
|
sock.ev.on("connection.update", handler);
|
|
@@ -4396,8 +4397,8 @@ async function handleInboundMessage(conn, msg) {
|
|
|
4396
4397
|
const conversationKey = isGroup ? remoteJid : senderPhone;
|
|
4397
4398
|
const debounceKey = `${conn.accountId}:${conversationKey}:${senderPhone}`;
|
|
4398
4399
|
let resolvePending;
|
|
4399
|
-
const sttPending = new Promise((
|
|
4400
|
-
resolvePending =
|
|
4400
|
+
const sttPending = new Promise((resolve22) => {
|
|
4401
|
+
resolvePending = resolve22;
|
|
4401
4402
|
});
|
|
4402
4403
|
if (conn.debouncer) conn.debouncer.registerPending(debounceKey, sttPending);
|
|
4403
4404
|
try {
|
|
@@ -4510,20 +4511,20 @@ async function probeApiKey() {
|
|
|
4510
4511
|
return result.status;
|
|
4511
4512
|
}
|
|
4512
4513
|
function checkPort(port2, timeoutMs = 500) {
|
|
4513
|
-
return new Promise((
|
|
4514
|
+
return new Promise((resolve22) => {
|
|
4514
4515
|
const socket = createConnection(port2, "127.0.0.1");
|
|
4515
4516
|
socket.setTimeout(timeoutMs);
|
|
4516
4517
|
socket.once("connect", () => {
|
|
4517
4518
|
socket.destroy();
|
|
4518
|
-
|
|
4519
|
+
resolve22(true);
|
|
4519
4520
|
});
|
|
4520
4521
|
socket.once("error", () => {
|
|
4521
4522
|
socket.destroy();
|
|
4522
|
-
|
|
4523
|
+
resolve22(false);
|
|
4523
4524
|
});
|
|
4524
4525
|
socket.once("timeout", () => {
|
|
4525
4526
|
socket.destroy();
|
|
4526
|
-
|
|
4527
|
+
resolve22(false);
|
|
4527
4528
|
});
|
|
4528
4529
|
});
|
|
4529
4530
|
}
|
|
@@ -5042,6 +5043,14 @@ function detectMimeType(filePath) {
|
|
|
5042
5043
|
const ext = extname(filePath).toLowerCase();
|
|
5043
5044
|
return MIME_BY_EXT[ext] ?? "application/octet-stream";
|
|
5044
5045
|
}
|
|
5046
|
+
function validateFilePathInAccount(filePath, accountDir) {
|
|
5047
|
+
const resolved = realpathSync(filePath);
|
|
5048
|
+
const accountResolved = realpathSync(accountDir);
|
|
5049
|
+
if (!resolved.startsWith(accountResolved + "/")) {
|
|
5050
|
+
throw new Error(`File path is outside the account directory`);
|
|
5051
|
+
}
|
|
5052
|
+
return resolved;
|
|
5053
|
+
}
|
|
5045
5054
|
async function storeGeneratedFile(accountId, filePath) {
|
|
5046
5055
|
const fileStat = await stat2(filePath);
|
|
5047
5056
|
if (fileStat.size > MAX_FILE_SIZE_BYTES) {
|
|
@@ -6725,8 +6734,8 @@ async function startLogin(opts) {
|
|
|
6725
6734
|
resetActiveLogin(accountId);
|
|
6726
6735
|
let resolveQr = null;
|
|
6727
6736
|
let rejectQr = null;
|
|
6728
|
-
const qrPromise = new Promise((
|
|
6729
|
-
resolveQr =
|
|
6737
|
+
const qrPromise = new Promise((resolve22, reject) => {
|
|
6738
|
+
resolveQr = resolve22;
|
|
6730
6739
|
rejectQr = reject;
|
|
6731
6740
|
});
|
|
6732
6741
|
const qrTimer = setTimeout(
|
|
@@ -7705,11 +7714,11 @@ function readUsersFile2() {
|
|
|
7705
7714
|
if (!raw) return [];
|
|
7706
7715
|
return JSON.parse(raw);
|
|
7707
7716
|
}
|
|
7708
|
-
async function createAdminSession(accountId, thinkingView, userId, userName) {
|
|
7717
|
+
async function createAdminSession(accountId, thinkingView, userId, userName, role) {
|
|
7709
7718
|
const account = resolveAccount();
|
|
7710
7719
|
const effectiveThinkingView = thinkingView ?? account?.config.thinkingView ?? "default";
|
|
7711
7720
|
const sessionKey = crypto.randomUUID();
|
|
7712
|
-
registerSession(sessionKey, "admin", accountId, void 0, userId, userName);
|
|
7721
|
+
registerSession(sessionKey, "admin", accountId, void 0, userId, userName, role);
|
|
7713
7722
|
let onboardingComplete = true;
|
|
7714
7723
|
try {
|
|
7715
7724
|
const step = await loadOnboardingStep(accountId);
|
|
@@ -7724,11 +7733,13 @@ async function createAdminSession(accountId, thinkingView, userId, userName) {
|
|
|
7724
7733
|
} catch {
|
|
7725
7734
|
}
|
|
7726
7735
|
console.log(`[session] ${(/* @__PURE__ */ new Date()).toISOString()} admin session created: userId=${userId ?? "\u2013"} userName=${userName ?? "\u2013"} accountId=${accountId} conversationId=deferred sessionKey=${sessionKey.slice(0, 8)}`);
|
|
7736
|
+
console.log(`[admin-session] role=${role ?? "null"} sessionKey=${sessionKey.slice(0, 8)} phase=create`);
|
|
7727
7737
|
return {
|
|
7728
7738
|
session_key: sessionKey,
|
|
7729
7739
|
agent_id: "admin",
|
|
7730
7740
|
userId,
|
|
7731
7741
|
userName,
|
|
7742
|
+
role: role ?? null,
|
|
7732
7743
|
thinkingView: effectiveThinkingView,
|
|
7733
7744
|
onboardingComplete,
|
|
7734
7745
|
businessName,
|
|
@@ -7760,11 +7771,14 @@ app10.get("/", async (c) => {
|
|
|
7760
7771
|
businessName = branding?.name || void 0;
|
|
7761
7772
|
} catch {
|
|
7762
7773
|
}
|
|
7774
|
+
const role = getRoleForSession(sessionKey);
|
|
7775
|
+
console.log(`[admin-session] role=${role ?? "null"} sessionKey=${sessionKey.slice(0, 8)} phase=restore`);
|
|
7763
7776
|
return c.json({
|
|
7764
7777
|
session_key: sessionKey,
|
|
7765
7778
|
agent_id: "admin",
|
|
7766
7779
|
userId: getUserIdForSession(sessionKey),
|
|
7767
7780
|
userName: getUserNameForSession(sessionKey),
|
|
7781
|
+
role: role ?? null,
|
|
7768
7782
|
thinkingView,
|
|
7769
7783
|
onboardingComplete,
|
|
7770
7784
|
businessName,
|
|
@@ -7821,7 +7835,7 @@ app10.post("/", async (c) => {
|
|
|
7821
7835
|
console.log(`[session] account selection invalid: userId=${userId} requested=${body.accountId}`);
|
|
7822
7836
|
return c.json({ error: "Invalid account selection." }, 403);
|
|
7823
7837
|
}
|
|
7824
|
-
const payload = await createAdminSession(selected.accountId, selected.config.thinkingView, userId, userName);
|
|
7838
|
+
const payload = await createAdminSession(selected.accountId, selected.config.thinkingView, userId, userName, selected.role);
|
|
7825
7839
|
return c.json(payload);
|
|
7826
7840
|
});
|
|
7827
7841
|
var session_default2 = app10;
|
|
@@ -8118,7 +8132,7 @@ var app11 = new Hono();
|
|
|
8118
8132
|
app11.post("/cancel", requireAdminSession, async (c) => {
|
|
8119
8133
|
const session_key = c.var.sessionKey;
|
|
8120
8134
|
try {
|
|
8121
|
-
const { interruptClient: interruptClient2 } = await import("./client-pool-
|
|
8135
|
+
const { interruptClient: interruptClient2 } = await import("./client-pool-SGPHSYLK.js");
|
|
8122
8136
|
await interruptClient2(session_key);
|
|
8123
8137
|
return c.json({ ok: true });
|
|
8124
8138
|
} catch (err) {
|
|
@@ -11563,30 +11577,144 @@ app30.get("/", requireAdminSession, async (c) => {
|
|
|
11563
11577
|
});
|
|
11564
11578
|
var adherence_default = app30;
|
|
11565
11579
|
|
|
11566
|
-
// server/routes/admin/
|
|
11580
|
+
// server/routes/admin/sidebar-projects.ts
|
|
11581
|
+
var LIMIT = 50;
|
|
11567
11582
|
var app31 = new Hono();
|
|
11568
|
-
app31.
|
|
11569
|
-
|
|
11570
|
-
|
|
11571
|
-
|
|
11572
|
-
|
|
11573
|
-
|
|
11574
|
-
|
|
11575
|
-
|
|
11576
|
-
|
|
11577
|
-
|
|
11578
|
-
|
|
11579
|
-
|
|
11580
|
-
|
|
11581
|
-
|
|
11582
|
-
|
|
11583
|
-
|
|
11584
|
-
|
|
11585
|
-
|
|
11586
|
-
|
|
11587
|
-
|
|
11588
|
-
|
|
11589
|
-
|
|
11583
|
+
app31.get("/", requireAdminSession, async (c) => {
|
|
11584
|
+
const sessionKey = c.var.sessionKey;
|
|
11585
|
+
const accountId = getAccountIdForSession(sessionKey);
|
|
11586
|
+
if (!accountId) {
|
|
11587
|
+
return c.json({ error: "Account not found for session" }, 401);
|
|
11588
|
+
}
|
|
11589
|
+
const start = Date.now();
|
|
11590
|
+
const session = getSession();
|
|
11591
|
+
try {
|
|
11592
|
+
const result = await session.run(
|
|
11593
|
+
`MATCH (p:Project { accountId: $accountId })
|
|
11594
|
+
WHERE NOT p:Trashed
|
|
11595
|
+
RETURN p.taskId AS id, p.name AS name, p.updatedAt AS updatedAt
|
|
11596
|
+
ORDER BY p.updatedAt DESC
|
|
11597
|
+
LIMIT $limit`,
|
|
11598
|
+
{ accountId, limit: LIMIT }
|
|
11599
|
+
);
|
|
11600
|
+
const projects = result.records.map((r) => ({
|
|
11601
|
+
id: r.get("id"),
|
|
11602
|
+
name: r.get("name") ?? "",
|
|
11603
|
+
updatedAt: r.get("updatedAt") ?? ""
|
|
11604
|
+
}));
|
|
11605
|
+
const ms = Date.now() - start;
|
|
11606
|
+
console.log(`[admin/sidebar-projects] account=${accountId} count=${projects.length} ms=${ms}`);
|
|
11607
|
+
return c.json({ projects });
|
|
11608
|
+
} catch (err) {
|
|
11609
|
+
const ms = Date.now() - start;
|
|
11610
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
11611
|
+
console.error(`[admin/sidebar-projects] account=${accountId} error="${message}" ms=${ms}`);
|
|
11612
|
+
return c.json({ error: "Failed to load projects" }, 500);
|
|
11613
|
+
} finally {
|
|
11614
|
+
await session.close();
|
|
11615
|
+
}
|
|
11616
|
+
});
|
|
11617
|
+
var sidebar_projects_default = app31;
|
|
11618
|
+
|
|
11619
|
+
// server/routes/admin/sidebar-artefacts.ts
|
|
11620
|
+
import { readFile as readFile5, readdir as readdir3 } from "fs/promises";
|
|
11621
|
+
import { resolve as resolve20 } from "path";
|
|
11622
|
+
var LIMIT2 = 50;
|
|
11623
|
+
var TEXT_MIME_PREFIXES = ["text/", "application/json", "application/markdown"];
|
|
11624
|
+
var app32 = new Hono();
|
|
11625
|
+
app32.get("/", requireAdminSession, async (c) => {
|
|
11626
|
+
const sessionKey = c.var.sessionKey;
|
|
11627
|
+
const accountId = getAccountIdForSession(sessionKey);
|
|
11628
|
+
if (!accountId) {
|
|
11629
|
+
return c.json({ error: "Account not found for session" }, 401);
|
|
11630
|
+
}
|
|
11631
|
+
const start = Date.now();
|
|
11632
|
+
const session = getSession();
|
|
11633
|
+
let metas = [];
|
|
11634
|
+
try {
|
|
11635
|
+
const result = await session.run(
|
|
11636
|
+
`MATCH (d:KnowledgeDocument { accountId: $accountId })
|
|
11637
|
+
WHERE d.deletedAt IS NULL AND NOT d:Trashed
|
|
11638
|
+
RETURN d.attachmentId AS id, d.name AS name, d.updatedAt AS updatedAt,
|
|
11639
|
+
d.attachmentId AS attachmentId, d.encodingFormat AS mimeType
|
|
11640
|
+
ORDER BY d.updatedAt DESC
|
|
11641
|
+
LIMIT $limit`,
|
|
11642
|
+
{ accountId, limit: LIMIT2 }
|
|
11643
|
+
);
|
|
11644
|
+
metas = result.records.map((r) => ({
|
|
11645
|
+
id: r.get("id"),
|
|
11646
|
+
name: r.get("name") ?? "",
|
|
11647
|
+
updatedAt: r.get("updatedAt") ?? "",
|
|
11648
|
+
attachmentId: r.get("attachmentId"),
|
|
11649
|
+
mimeType: r.get("mimeType") ?? ""
|
|
11650
|
+
}));
|
|
11651
|
+
} catch (err) {
|
|
11652
|
+
const ms2 = Date.now() - start;
|
|
11653
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
11654
|
+
console.error(`[admin/sidebar-artefacts] account=${accountId} error="${message}" ms=${ms2}`);
|
|
11655
|
+
await session.close();
|
|
11656
|
+
return c.json({ error: "Failed to load artefacts" }, 500);
|
|
11657
|
+
} finally {
|
|
11658
|
+
await session.close();
|
|
11659
|
+
}
|
|
11660
|
+
const artefacts = await Promise.all(metas.map(async (m) => {
|
|
11661
|
+
const content = await readArtefactContent(accountId, m.attachmentId, m.mimeType);
|
|
11662
|
+
return { id: m.id, name: m.name, updatedAt: m.updatedAt, content };
|
|
11663
|
+
}));
|
|
11664
|
+
const ms = Date.now() - start;
|
|
11665
|
+
console.log(`[admin/sidebar-artefacts] account=${accountId} count=${artefacts.length} ms=${ms}`);
|
|
11666
|
+
return c.json({ artefacts });
|
|
11667
|
+
});
|
|
11668
|
+
async function readArtefactContent(accountId, attachmentId, mimeType) {
|
|
11669
|
+
if (!attachmentId) return "";
|
|
11670
|
+
const isText = TEXT_MIME_PREFIXES.some((p) => mimeType.startsWith(p));
|
|
11671
|
+
if (!isText) return "";
|
|
11672
|
+
const accountDir = resolve20(ATTACHMENTS_ROOT, accountId);
|
|
11673
|
+
const dir = resolve20(accountDir, attachmentId);
|
|
11674
|
+
try {
|
|
11675
|
+
validateFilePathInAccount(dir, accountDir);
|
|
11676
|
+
} catch {
|
|
11677
|
+
return "";
|
|
11678
|
+
}
|
|
11679
|
+
try {
|
|
11680
|
+
const entries = await readdir3(dir);
|
|
11681
|
+
const dataFile = entries.find((f) => !f.endsWith(".meta.json"));
|
|
11682
|
+
if (!dataFile) return "";
|
|
11683
|
+
return await readFile5(resolve20(dir, dataFile), "utf-8");
|
|
11684
|
+
} catch (err) {
|
|
11685
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
11686
|
+
console.error(`[admin/sidebar-artefacts] read-failed attachmentId=${attachmentId.slice(0, 8)} error="${message}"`);
|
|
11687
|
+
return "";
|
|
11688
|
+
}
|
|
11689
|
+
}
|
|
11690
|
+
var sidebar_artefacts_default = app32;
|
|
11691
|
+
|
|
11692
|
+
// server/routes/admin/index.ts
|
|
11693
|
+
var app33 = new Hono();
|
|
11694
|
+
app33.route("/session", session_default2);
|
|
11695
|
+
app33.route("/chat", chat_default2);
|
|
11696
|
+
app33.route("/compact", compact_default);
|
|
11697
|
+
app33.route("/logs", logs_default);
|
|
11698
|
+
app33.route("/claude-info", claude_info_default);
|
|
11699
|
+
app33.route("/attachment", attachment_default);
|
|
11700
|
+
app33.route("/agents", agents_default);
|
|
11701
|
+
app33.route("/sessions", sessions_default);
|
|
11702
|
+
app33.route("/browser", browser_default);
|
|
11703
|
+
app33.route("/device-browser", device_browser_default);
|
|
11704
|
+
app33.route("/events", events_default);
|
|
11705
|
+
app33.route("/cloudflare", cloudflare_default);
|
|
11706
|
+
app33.route("/files", files_default);
|
|
11707
|
+
app33.route("/graph-search", graph_search_default);
|
|
11708
|
+
app33.route("/graph-subgraph", graph_subgraph_default);
|
|
11709
|
+
app33.route("/graph-delete", graph_delete_default);
|
|
11710
|
+
app33.route("/graph-restore", graph_restore_default);
|
|
11711
|
+
app33.route("/graph-labels-in-graph", graph_labels_in_graph_default);
|
|
11712
|
+
app33.route("/graph-default-view", graph_default_view_default);
|
|
11713
|
+
app33.route("/file-attach", file_attach_default);
|
|
11714
|
+
app33.route("/adherence", adherence_default);
|
|
11715
|
+
app33.route("/sidebar-projects", sidebar_projects_default);
|
|
11716
|
+
app33.route("/sidebar-artefacts", sidebar_artefacts_default);
|
|
11717
|
+
var admin_default = app33;
|
|
11590
11718
|
|
|
11591
11719
|
// app/lib/graph-health.ts
|
|
11592
11720
|
var HOUR_MS = 60 * 60 * 1e3;
|
|
@@ -11740,9 +11868,9 @@ watchFile(ALIAS_DOMAINS_PATH2, { interval: 2e3 }, () => {
|
|
|
11740
11868
|
function isPublicHost(host) {
|
|
11741
11869
|
return host.startsWith("public.") || aliasDomains.has(host);
|
|
11742
11870
|
}
|
|
11743
|
-
var
|
|
11744
|
-
|
|
11745
|
-
|
|
11871
|
+
var app34 = new Hono();
|
|
11872
|
+
app34.use("*", clientIpMiddleware);
|
|
11873
|
+
app34.use("*", async (c, next) => {
|
|
11746
11874
|
await next();
|
|
11747
11875
|
c.header("X-Content-Type-Options", "nosniff");
|
|
11748
11876
|
c.header("Referrer-Policy", "strict-origin-when-cross-origin");
|
|
@@ -11765,7 +11893,7 @@ var PUBLIC_ALLOWED_PREFIXES = [
|
|
|
11765
11893
|
"/g/"
|
|
11766
11894
|
];
|
|
11767
11895
|
var PUBLIC_ALLOWED_EXACT = ["/favicon.ico"];
|
|
11768
|
-
|
|
11896
|
+
app34.use("*", async (c, next) => {
|
|
11769
11897
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
11770
11898
|
if (!isPublicHost(host)) {
|
|
11771
11899
|
await next();
|
|
@@ -11805,7 +11933,7 @@ function resolveRemoteAuthOpts() {
|
|
|
11805
11933
|
return brandLoginOpts;
|
|
11806
11934
|
}
|
|
11807
11935
|
var MAX_LOGIN_BODY = 8 * 1024;
|
|
11808
|
-
|
|
11936
|
+
app34.post("/__remote-auth/login", async (c) => {
|
|
11809
11937
|
const client = clientFrom(c);
|
|
11810
11938
|
const clientIp = client.ip || "unknown";
|
|
11811
11939
|
if (!requestIsTlsTerminated(c)) {
|
|
@@ -11849,7 +11977,7 @@ app32.post("/__remote-auth/login", async (c) => {
|
|
|
11849
11977
|
}
|
|
11850
11978
|
});
|
|
11851
11979
|
});
|
|
11852
|
-
|
|
11980
|
+
app34.get("/__remote-auth/logout", (c) => {
|
|
11853
11981
|
return new Response(null, {
|
|
11854
11982
|
status: 302,
|
|
11855
11983
|
headers: {
|
|
@@ -11859,7 +11987,7 @@ app32.get("/__remote-auth/logout", (c) => {
|
|
|
11859
11987
|
}
|
|
11860
11988
|
});
|
|
11861
11989
|
});
|
|
11862
|
-
|
|
11990
|
+
app34.post("/__remote-auth/change-password", async (c) => {
|
|
11863
11991
|
const client = clientFrom(c);
|
|
11864
11992
|
const clientIp = client.ip || "unknown";
|
|
11865
11993
|
const rateLimited = checkRateLimit(client);
|
|
@@ -11909,13 +12037,13 @@ app32.post("/__remote-auth/change-password", async (c) => {
|
|
|
11909
12037
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "change", changeError: "Failed to save password", redirect }), 200);
|
|
11910
12038
|
}
|
|
11911
12039
|
});
|
|
11912
|
-
|
|
12040
|
+
app34.get("/__remote-auth/setup", (c) => {
|
|
11913
12041
|
if (isRemoteAuthConfigured()) {
|
|
11914
12042
|
return c.redirect("/");
|
|
11915
12043
|
}
|
|
11916
12044
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "setup" }), 200);
|
|
11917
12045
|
});
|
|
11918
|
-
|
|
12046
|
+
app34.post("/__remote-auth/set-initial-password", async (c) => {
|
|
11919
12047
|
if (isRemoteAuthConfigured()) {
|
|
11920
12048
|
return c.redirect("/");
|
|
11921
12049
|
}
|
|
@@ -11951,10 +12079,10 @@ app32.post("/__remote-auth/set-initial-password", async (c) => {
|
|
|
11951
12079
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "setup", setupError: "Failed to save password. Please try again." }), 200);
|
|
11952
12080
|
}
|
|
11953
12081
|
});
|
|
11954
|
-
|
|
12082
|
+
app34.get("/api/remote-auth/status", (c) => {
|
|
11955
12083
|
return c.json({ configured: isRemoteAuthConfigured() });
|
|
11956
12084
|
});
|
|
11957
|
-
|
|
12085
|
+
app34.post("/api/remote-auth/set-password", async (c) => {
|
|
11958
12086
|
let body;
|
|
11959
12087
|
try {
|
|
11960
12088
|
body = await c.req.json();
|
|
@@ -11984,9 +12112,9 @@ app32.post("/api/remote-auth/set-password", async (c) => {
|
|
|
11984
12112
|
return c.json({ error: "Failed to save password" }, 500);
|
|
11985
12113
|
}
|
|
11986
12114
|
});
|
|
11987
|
-
|
|
12115
|
+
app34.route("/api/_client-error", client_error_default);
|
|
11988
12116
|
console.log("[client-error-route] mounted");
|
|
11989
|
-
|
|
12117
|
+
app34.use("*", async (c, next) => {
|
|
11990
12118
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
11991
12119
|
const path2 = c.req.path;
|
|
11992
12120
|
if (path2 === "/favicon.ico" || path2.startsWith("/assets/") || path2.startsWith("/brand/")) {
|
|
@@ -12019,15 +12147,15 @@ app32.use("*", async (c, next) => {
|
|
|
12019
12147
|
console.error(`[remote-auth] login required ip=${clientIp} path=${path2} ${disambig}`);
|
|
12020
12148
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), redirect: path2 }), 200);
|
|
12021
12149
|
});
|
|
12022
|
-
|
|
12023
|
-
|
|
12024
|
-
|
|
12025
|
-
|
|
12026
|
-
|
|
12027
|
-
|
|
12028
|
-
|
|
12029
|
-
|
|
12030
|
-
|
|
12150
|
+
app34.route("/api/health", health_default);
|
|
12151
|
+
app34.route("/api/session", session_default);
|
|
12152
|
+
app34.route("/api/chat", chat_default);
|
|
12153
|
+
app34.route("/api/group", group_default);
|
|
12154
|
+
app34.route("/api/access", access_default);
|
|
12155
|
+
app34.route("/api/telegram", telegram_default);
|
|
12156
|
+
app34.route("/api/whatsapp", whatsapp_default);
|
|
12157
|
+
app34.route("/api/onboarding", onboarding_default);
|
|
12158
|
+
app34.route("/api/admin", admin_default);
|
|
12031
12159
|
var SAFE_SLUG_RE = /^[a-z][a-z0-9-]{2,49}$/;
|
|
12032
12160
|
var SAFE_FILENAME_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
|
|
12033
12161
|
var IMAGE_MIME = {
|
|
@@ -12039,7 +12167,7 @@ var IMAGE_MIME = {
|
|
|
12039
12167
|
".svg": "image/svg+xml",
|
|
12040
12168
|
".ico": "image/x-icon"
|
|
12041
12169
|
};
|
|
12042
|
-
|
|
12170
|
+
app34.get("/agent-assets/:slug/:filename", (c) => {
|
|
12043
12171
|
const slug = c.req.param("slug");
|
|
12044
12172
|
const filename = c.req.param("filename");
|
|
12045
12173
|
if (!SAFE_SLUG_RE.test(slug)) {
|
|
@@ -12055,8 +12183,8 @@ app32.get("/agent-assets/:slug/:filename", (c) => {
|
|
|
12055
12183
|
console.error(`[agent-assets] no-account slug=${slug} file=${filename}`);
|
|
12056
12184
|
return c.text("Not found", 404);
|
|
12057
12185
|
}
|
|
12058
|
-
const filePath =
|
|
12059
|
-
const expectedDir =
|
|
12186
|
+
const filePath = resolve21(account.accountDir, "agents", slug, "assets", filename);
|
|
12187
|
+
const expectedDir = resolve21(account.accountDir, "agents", slug, "assets");
|
|
12060
12188
|
if (!filePath.startsWith(expectedDir + "/")) {
|
|
12061
12189
|
console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
|
|
12062
12190
|
return c.text("Forbidden", 403);
|
|
@@ -12074,7 +12202,7 @@ app32.get("/agent-assets/:slug/:filename", (c) => {
|
|
|
12074
12202
|
"Cache-Control": "public, max-age=3600"
|
|
12075
12203
|
});
|
|
12076
12204
|
});
|
|
12077
|
-
|
|
12205
|
+
app34.get("/generated/:filename", (c) => {
|
|
12078
12206
|
const filename = c.req.param("filename");
|
|
12079
12207
|
if (!SAFE_FILENAME_RE.test(filename) || filename.includes("..")) {
|
|
12080
12208
|
console.error(`[generated] serve file=${filename} status=403`);
|
|
@@ -12085,8 +12213,8 @@ app32.get("/generated/:filename", (c) => {
|
|
|
12085
12213
|
console.error(`[generated] serve file=${filename} status=404`);
|
|
12086
12214
|
return c.text("Not found", 404);
|
|
12087
12215
|
}
|
|
12088
|
-
const filePath =
|
|
12089
|
-
const expectedDir =
|
|
12216
|
+
const filePath = resolve21(account.accountDir, "generated", filename);
|
|
12217
|
+
const expectedDir = resolve21(account.accountDir, "generated");
|
|
12090
12218
|
if (!filePath.startsWith(expectedDir + "/")) {
|
|
12091
12219
|
console.error(`[generated] serve file=${filename} status=403`);
|
|
12092
12220
|
return c.text("Forbidden", 403);
|
|
@@ -12169,7 +12297,7 @@ var clientErrorReporterScript = `<script>
|
|
|
12169
12297
|
function cachedHtml(file) {
|
|
12170
12298
|
let html = htmlCache.get(file);
|
|
12171
12299
|
if (!html) {
|
|
12172
|
-
html = readFileSync16(
|
|
12300
|
+
html = readFileSync16(resolve21(process.cwd(), "public", file), "utf-8");
|
|
12173
12301
|
const productNameEsc = escapeHtml(BRAND.productName);
|
|
12174
12302
|
html = html.replace(/<title>([^<]*)<\/title>/, (_match, inner) => `<title>${escapeHtml(inner).replace(/Maxy/g, productNameEsc)}</title>`);
|
|
12175
12303
|
html = html.replace('href="/favicon.ico"', `href="${escapeHtml(brandFaviconPath)}"`);
|
|
@@ -12240,7 +12368,7 @@ function brandedPublicHtml(agentSlug) {
|
|
|
12240
12368
|
function escapeHtml(s) {
|
|
12241
12369
|
return s.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
12242
12370
|
}
|
|
12243
|
-
|
|
12371
|
+
app34.get("/", (c) => {
|
|
12244
12372
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
12245
12373
|
if (isPublicHost(host)) {
|
|
12246
12374
|
const defaultSlug = resolveDefaultSlug();
|
|
@@ -12248,12 +12376,12 @@ app32.get("/", (c) => {
|
|
|
12248
12376
|
}
|
|
12249
12377
|
return c.html(cachedHtml("index.html"));
|
|
12250
12378
|
});
|
|
12251
|
-
|
|
12379
|
+
app34.get("/public", (c) => {
|
|
12252
12380
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
12253
12381
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
12254
12382
|
return c.html(cachedHtml("public.html"));
|
|
12255
12383
|
});
|
|
12256
|
-
|
|
12384
|
+
app34.get("/chat", (c) => {
|
|
12257
12385
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
12258
12386
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
12259
12387
|
return c.html(cachedHtml("public.html"));
|
|
@@ -12272,12 +12400,12 @@ async function logViewerFetch(c, next) {
|
|
|
12272
12400
|
duration_ms: Date.now() - start
|
|
12273
12401
|
});
|
|
12274
12402
|
}
|
|
12275
|
-
|
|
12276
|
-
|
|
12277
|
-
|
|
12403
|
+
app34.use("/vnc-viewer.html", logViewerFetch);
|
|
12404
|
+
app34.use("/vnc-popout.html", logViewerFetch);
|
|
12405
|
+
app34.get("/vnc-popout.html", (c) => {
|
|
12278
12406
|
let html = htmlCache.get("vnc-popout.html");
|
|
12279
12407
|
if (!html) {
|
|
12280
|
-
html = readFileSync16(
|
|
12408
|
+
html = readFileSync16(resolve21(process.cwd(), "public", "vnc-popout.html"), "utf-8");
|
|
12281
12409
|
const name = escapeHtml(BRAND.productName);
|
|
12282
12410
|
html = html.replace("<title>Browser \u2014 Maxy</title>", `<title>${name}</title>`);
|
|
12283
12411
|
html = html.replace("</head>", ` ${brandScript}
|
|
@@ -12287,7 +12415,7 @@ app32.get("/vnc-popout.html", (c) => {
|
|
|
12287
12415
|
}
|
|
12288
12416
|
return c.html(html);
|
|
12289
12417
|
});
|
|
12290
|
-
|
|
12418
|
+
app34.post("/api/vnc/client-event", async (c) => {
|
|
12291
12419
|
let body;
|
|
12292
12420
|
try {
|
|
12293
12421
|
body = await c.req.json();
|
|
@@ -12308,20 +12436,20 @@ app32.post("/api/vnc/client-event", async (c) => {
|
|
|
12308
12436
|
});
|
|
12309
12437
|
return c.json({ ok: true });
|
|
12310
12438
|
});
|
|
12311
|
-
|
|
12439
|
+
app34.get("/g/:slug", (c) => {
|
|
12312
12440
|
return c.html(brandedPublicHtml());
|
|
12313
12441
|
});
|
|
12314
|
-
|
|
12442
|
+
app34.get("/graph", (c) => {
|
|
12315
12443
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
12316
12444
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
12317
12445
|
return c.html(cachedHtml("graph.html"));
|
|
12318
12446
|
});
|
|
12319
|
-
|
|
12447
|
+
app34.get("/data", (c) => {
|
|
12320
12448
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
12321
12449
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
12322
12450
|
return c.html(cachedHtml("data.html"));
|
|
12323
12451
|
});
|
|
12324
|
-
|
|
12452
|
+
app34.get("/:slug", async (c, next) => {
|
|
12325
12453
|
const slug = c.req.param("slug");
|
|
12326
12454
|
if (AGENT_SLUG_PATTERN.test(`/${slug}`)) {
|
|
12327
12455
|
const branding = loadBrandingCache(slug);
|
|
@@ -12330,10 +12458,10 @@ app32.get("/:slug", async (c, next) => {
|
|
|
12330
12458
|
}
|
|
12331
12459
|
await next();
|
|
12332
12460
|
});
|
|
12333
|
-
|
|
12461
|
+
app34.use("/*", serveStatic({ root: "./public" }));
|
|
12334
12462
|
var port = parseInt(process.env.MAXY_UI_INTERNAL_PORT ?? process.env.PORT ?? "19199", 10);
|
|
12335
12463
|
var hostname = process.env.HOSTNAME ?? "127.0.0.1";
|
|
12336
|
-
var httpServer = serve({ fetch:
|
|
12464
|
+
var httpServer = serve({ fetch: app34.fetch, port, hostname });
|
|
12337
12465
|
console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
12338
12466
|
var SUBAPP_MANIFEST = [
|
|
12339
12467
|
{ prefix: "/api/health", file: "server/routes/health.ts", subapp: health_default },
|
|
@@ -12353,7 +12481,7 @@ for (const m of SUBAPP_MANIFEST) {
|
|
|
12353
12481
|
}
|
|
12354
12482
|
try {
|
|
12355
12483
|
const registered = [];
|
|
12356
|
-
for (const r of
|
|
12484
|
+
for (const r of app34.routes ?? []) {
|
|
12357
12485
|
if (typeof r.path !== "string" || r.path.includes(":") || r.path.includes("*")) continue;
|
|
12358
12486
|
if (AGENT_SLUG_PATTERN.test(r.path)) {
|
|
12359
12487
|
registered.push({ method: (r.method ?? "ALL").toUpperCase(), path: r.path });
|
|
@@ -12420,7 +12548,7 @@ if (bootAccountConfig?.whatsapp) {
|
|
|
12420
12548
|
}
|
|
12421
12549
|
init({
|
|
12422
12550
|
configDir: configDirForWhatsApp,
|
|
12423
|
-
platformRoot:
|
|
12551
|
+
platformRoot: resolve21(process.env.MAXY_PLATFORM_ROOT ?? join10(__dirname, "..")),
|
|
12424
12552
|
accountConfig: bootAccountConfig,
|
|
12425
12553
|
onMessage: async (msg) => {
|
|
12426
12554
|
try {
|