@rubytech/create-maxy-code 0.1.282 → 0.1.283
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/config/brand.json +0 -1
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +4 -4
- package/payload/platform/plugins/cloudflare/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/cloudflare/PLUGIN.md +5 -5
- package/payload/platform/plugins/cloudflare/references/api.md +76 -37
- package/payload/platform/plugins/cloudflare/references/d1-data-capture.md +27 -21
- package/payload/platform/plugins/cloudflare/references/dashboard-guide.md +3 -2
- package/payload/platform/plugins/cloudflare/references/hosting-sites.md +7 -5
- package/payload/platform/plugins/cloudflare/references/manual-setup.md +3 -2
- package/payload/platform/plugins/cloudflare/skills/cloudflare/SKILL.md +6 -6
- package/payload/platform/plugins/docs/references/telegram-guide.md +3 -3
- package/payload/platform/plugins/telegram/PLUGIN.md +7 -2
- package/payload/platform/plugins/telegram/mcp/dist/index.js +66 -11
- package/payload/platform/plugins/telegram/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/lib/account-token.d.ts +6 -0
- package/payload/platform/plugins/telegram/mcp/dist/lib/account-token.d.ts.map +1 -0
- package/payload/platform/plugins/telegram/mcp/dist/lib/account-token.js +20 -0
- package/payload/platform/plugins/telegram/mcp/dist/lib/account-token.js.map +1 -0
- package/payload/platform/plugins/telegram/mcp/dist/lib/account-write.d.ts +21 -0
- package/payload/platform/plugins/telegram/mcp/dist/lib/account-write.d.ts.map +1 -0
- package/payload/platform/plugins/telegram/mcp/dist/lib/account-write.js +52 -0
- package/payload/platform/plugins/telegram/mcp/dist/lib/account-write.js.map +1 -0
- package/payload/platform/plugins/telegram/mcp/dist/tools/message.d.ts.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/tools/message.js +5 -2
- package/payload/platform/plugins/telegram/mcp/dist/tools/message.js.map +1 -1
- package/payload/platform/plugins/telegram/references/setup-guide.md +10 -7
- package/payload/platform/plugins/telegram/skills/configure/SKILL.md +79 -0
- package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.js +17 -0
- package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
- package/payload/server/public/assets/AdminShell-8Y7-maNi.js +1 -0
- package/payload/server/public/assets/{admin-0_VxffD5.js → admin-DyuZ4NT5.js} +1 -1
- package/payload/server/public/assets/{browser-Cxjkhtsk.js → browser-XrVAUQdG.js} +1 -1
- package/payload/server/public/assets/{data-BOgwOWnw.js → data-tcu3MXmK.js} +1 -1
- package/payload/server/public/assets/{graph-BqD2GjQd.js → graph-I4GyC2MW.js} +1 -1
- package/payload/server/public/browser.html +2 -2
- package/payload/server/public/data.html +2 -2
- package/payload/server/public/graph.html +2 -2
- package/payload/server/public/index.html +2 -2
- package/payload/server/server.js +827 -531
- package/payload/server/public/assets/AdminShell-FO766lOW.js +0 -1
package/payload/server/server.js
CHANGED
|
@@ -1201,9 +1201,9 @@ var serveStatic = (options = { root: "" }) => {
|
|
|
1201
1201
|
};
|
|
1202
1202
|
|
|
1203
1203
|
// server/index.ts
|
|
1204
|
-
import { readFileSync as
|
|
1205
|
-
import { resolve as
|
|
1206
|
-
import { homedir as
|
|
1204
|
+
import { readFileSync as readFileSync24, existsSync as existsSync24, watchFile } from "fs";
|
|
1205
|
+
import { resolve as resolve27, join as join19, basename as basename7 } from "path";
|
|
1206
|
+
import { homedir as homedir3 } from "os";
|
|
1207
1207
|
import { monitorEventLoopDelay } from "perf_hooks";
|
|
1208
1208
|
|
|
1209
1209
|
// app/lib/agent-slug-pattern.ts
|
|
@@ -1560,6 +1560,36 @@ var WhatsAppConfigSchema = z.object({
|
|
|
1560
1560
|
message: 'dmPolicy="open" requires allowFrom to include "*"'
|
|
1561
1561
|
});
|
|
1562
1562
|
});
|
|
1563
|
+
function parseWhatsAppConfigTolerant(raw) {
|
|
1564
|
+
const first = WhatsAppConfigSchema.safeParse(raw);
|
|
1565
|
+
if (first.success) {
|
|
1566
|
+
return { ok: true, data: first.data, droppedKeys: [] };
|
|
1567
|
+
}
|
|
1568
|
+
const issues = first.error.issues;
|
|
1569
|
+
const onlyUnknownKeys = issues.length > 0 && issues.every((i) => i.code === "unrecognized_keys");
|
|
1570
|
+
if (!onlyUnknownKeys) {
|
|
1571
|
+
return { ok: false, error: first.error };
|
|
1572
|
+
}
|
|
1573
|
+
const clone = JSON.parse(JSON.stringify(raw));
|
|
1574
|
+
const droppedKeys = [];
|
|
1575
|
+
for (const issue of issues) {
|
|
1576
|
+
if (issue.code !== "unrecognized_keys") continue;
|
|
1577
|
+
const container = issue.path.reduce(
|
|
1578
|
+
(acc, seg) => acc && typeof acc === "object" ? acc[seg] : void 0,
|
|
1579
|
+
clone
|
|
1580
|
+
);
|
|
1581
|
+
if (!container || typeof container !== "object") continue;
|
|
1582
|
+
for (const key of issue.keys) {
|
|
1583
|
+
delete container[key];
|
|
1584
|
+
droppedKeys.push([...issue.path, key].join("."));
|
|
1585
|
+
}
|
|
1586
|
+
}
|
|
1587
|
+
const second = WhatsAppConfigSchema.safeParse(clone);
|
|
1588
|
+
if (second.success) {
|
|
1589
|
+
return { ok: true, data: second.data, droppedKeys };
|
|
1590
|
+
}
|
|
1591
|
+
return { ok: false, error: second.error };
|
|
1592
|
+
}
|
|
1563
1593
|
|
|
1564
1594
|
// app/lib/whatsapp/auth-store.ts
|
|
1565
1595
|
import fsSync from "fs";
|
|
@@ -1751,7 +1781,7 @@ var credsSaveQueue = Promise.resolve();
|
|
|
1751
1781
|
async function drainCredsSaveQueue(timeoutMs = 5e3) {
|
|
1752
1782
|
console.error(`${TAG2} draining credential save queue\u2026`);
|
|
1753
1783
|
const timer2 = new Promise(
|
|
1754
|
-
(
|
|
1784
|
+
(resolve28) => setTimeout(() => resolve28("timeout"), timeoutMs)
|
|
1755
1785
|
);
|
|
1756
1786
|
const result = await Promise.race([
|
|
1757
1787
|
credsSaveQueue.then(() => "drained"),
|
|
@@ -1879,11 +1909,11 @@ async function createWaSocket(opts) {
|
|
|
1879
1909
|
return sock;
|
|
1880
1910
|
}
|
|
1881
1911
|
async function waitForConnection(sock) {
|
|
1882
|
-
return new Promise((
|
|
1912
|
+
return new Promise((resolve28, reject) => {
|
|
1883
1913
|
const handler = (update) => {
|
|
1884
1914
|
if (update.connection === "open") {
|
|
1885
1915
|
sock.ev.off("connection.update", handler);
|
|
1886
|
-
|
|
1916
|
+
resolve28();
|
|
1887
1917
|
}
|
|
1888
1918
|
if (update.connection === "close") {
|
|
1889
1919
|
sock.ev.off("connection.update", handler);
|
|
@@ -1997,14 +2027,14 @@ ${inspected}`;
|
|
|
1997
2027
|
return inspect2(err, INSPECT_OPTS2);
|
|
1998
2028
|
}
|
|
1999
2029
|
function withTimeout(label, promise, timeoutMs) {
|
|
2000
|
-
return new Promise((
|
|
2030
|
+
return new Promise((resolve28, reject) => {
|
|
2001
2031
|
const timer2 = setTimeout(() => {
|
|
2002
2032
|
reject(new Error(`${label} timed out after ${timeoutMs}ms`));
|
|
2003
2033
|
}, timeoutMs);
|
|
2004
2034
|
promise.then(
|
|
2005
2035
|
(value) => {
|
|
2006
2036
|
clearTimeout(timer2);
|
|
2007
|
-
|
|
2037
|
+
resolve28(value);
|
|
2008
2038
|
},
|
|
2009
2039
|
(err) => {
|
|
2010
2040
|
clearTimeout(timer2);
|
|
@@ -2559,8 +2589,8 @@ async function persistWhatsAppMessage(input) {
|
|
|
2559
2589
|
const { givenName, familyName } = splitName(input.pushName);
|
|
2560
2590
|
const prev = sessionWriteLocks.get(input.cacheKey);
|
|
2561
2591
|
let release;
|
|
2562
|
-
const mine = new Promise((
|
|
2563
|
-
release =
|
|
2592
|
+
const mine = new Promise((resolve28) => {
|
|
2593
|
+
release = resolve28;
|
|
2564
2594
|
});
|
|
2565
2595
|
const chained = (prev ?? Promise.resolve()).then(() => mine);
|
|
2566
2596
|
sessionWriteLocks.set(input.cacheKey, chained);
|
|
@@ -3500,13 +3530,20 @@ function loadConfig(accountConfig) {
|
|
|
3500
3530
|
const raw = accountConfig?.whatsapp;
|
|
3501
3531
|
if (raw && typeof raw === "object") {
|
|
3502
3532
|
const wa = raw;
|
|
3503
|
-
const
|
|
3504
|
-
if (
|
|
3505
|
-
whatsAppConfig =
|
|
3533
|
+
const result = parseWhatsAppConfigTolerant(wa);
|
|
3534
|
+
if (result.ok) {
|
|
3535
|
+
whatsAppConfig = result.data;
|
|
3536
|
+
if (result.droppedKeys.length > 0) {
|
|
3537
|
+
console.error(`${TAG12} config: dropped unknown keys=[${result.droppedKeys.join(",")}] preserved known config`);
|
|
3538
|
+
}
|
|
3506
3539
|
} else {
|
|
3507
|
-
console.error(`${TAG12} config validation failed: ${
|
|
3540
|
+
console.error(`${TAG12} config validation failed: ${result.error.message}`);
|
|
3508
3541
|
whatsAppConfig = {};
|
|
3509
3542
|
}
|
|
3543
|
+
const diskAdmin = Array.isArray(wa.adminPhones) ? wa.adminPhones : [];
|
|
3544
|
+
if (diskAdmin.length > 0 && (whatsAppConfig.adminPhones?.length ?? 0) === 0) {
|
|
3545
|
+
console.error(`${TAG12} WARN adminPhones present on disk but empty after load`);
|
|
3546
|
+
}
|
|
3510
3547
|
}
|
|
3511
3548
|
} catch (err) {
|
|
3512
3549
|
console.error(`${TAG12} config load error: ${String(err)}`);
|
|
@@ -3614,11 +3651,11 @@ async function connectWithReconnect(conn) {
|
|
|
3614
3651
|
console.error(
|
|
3615
3652
|
`${TAG12} reconnecting account=${conn.accountId} in ${delay}ms (attempt ${decision.nextAttempts}/${maxAttempts})`
|
|
3616
3653
|
);
|
|
3617
|
-
await new Promise((
|
|
3618
|
-
const timer2 = setTimeout(
|
|
3654
|
+
await new Promise((resolve28) => {
|
|
3655
|
+
const timer2 = setTimeout(resolve28, delay);
|
|
3619
3656
|
conn.abortController.signal.addEventListener("abort", () => {
|
|
3620
3657
|
clearTimeout(timer2);
|
|
3621
|
-
|
|
3658
|
+
resolve28();
|
|
3622
3659
|
}, { once: true });
|
|
3623
3660
|
});
|
|
3624
3661
|
}
|
|
@@ -3626,16 +3663,16 @@ async function connectWithReconnect(conn) {
|
|
|
3626
3663
|
}
|
|
3627
3664
|
}
|
|
3628
3665
|
function waitForDisconnectEvent(conn) {
|
|
3629
|
-
return new Promise((
|
|
3666
|
+
return new Promise((resolve28) => {
|
|
3630
3667
|
if (!conn.sock) {
|
|
3631
|
-
|
|
3668
|
+
resolve28();
|
|
3632
3669
|
return;
|
|
3633
3670
|
}
|
|
3634
3671
|
const sock = conn.sock;
|
|
3635
3672
|
const handler = (update) => {
|
|
3636
3673
|
if (update.connection === "close") {
|
|
3637
3674
|
sock.ev.off("connection.update", handler);
|
|
3638
|
-
|
|
3675
|
+
resolve28();
|
|
3639
3676
|
}
|
|
3640
3677
|
};
|
|
3641
3678
|
sock.ev.on("connection.update", handler);
|
|
@@ -3863,8 +3900,8 @@ async function handleInboundMessage(conn, msg) {
|
|
|
3863
3900
|
const conversationKey = isGroup ? remoteJid : senderPhone;
|
|
3864
3901
|
const debounceKey = `${conn.accountId}:${conversationKey}:${senderPhone}`;
|
|
3865
3902
|
let resolvePending;
|
|
3866
|
-
const sttPending = new Promise((
|
|
3867
|
-
resolvePending =
|
|
3903
|
+
const sttPending = new Promise((resolve28) => {
|
|
3904
|
+
resolvePending = resolve28;
|
|
3868
3905
|
});
|
|
3869
3906
|
if (conn.debouncer) conn.debouncer.registerPending(debounceKey, sttPending);
|
|
3870
3907
|
try {
|
|
@@ -4255,20 +4292,20 @@ function buildX11Env(chromiumWrapperPath, transport = "vnc") {
|
|
|
4255
4292
|
|
|
4256
4293
|
// server/routes/health.ts
|
|
4257
4294
|
function checkPort(port2, timeoutMs = 500) {
|
|
4258
|
-
return new Promise((
|
|
4295
|
+
return new Promise((resolve28) => {
|
|
4259
4296
|
const socket = createConnection2(port2, "127.0.0.1");
|
|
4260
4297
|
socket.setTimeout(timeoutMs);
|
|
4261
4298
|
socket.once("connect", () => {
|
|
4262
4299
|
socket.destroy();
|
|
4263
|
-
|
|
4300
|
+
resolve28(true);
|
|
4264
4301
|
});
|
|
4265
4302
|
socket.once("error", () => {
|
|
4266
4303
|
socket.destroy();
|
|
4267
|
-
|
|
4304
|
+
resolve28(false);
|
|
4268
4305
|
});
|
|
4269
4306
|
socket.once("timeout", () => {
|
|
4270
4307
|
socket.destroy();
|
|
4271
|
-
|
|
4308
|
+
resolve28(false);
|
|
4272
4309
|
});
|
|
4273
4310
|
});
|
|
4274
4311
|
}
|
|
@@ -5356,12 +5393,12 @@ async function dispatchOnce(input) {
|
|
|
5356
5393
|
});
|
|
5357
5394
|
if (!entry) return { error: "spawn-failed" };
|
|
5358
5395
|
entry.lastInboundAt = Date.now();
|
|
5359
|
-
let
|
|
5396
|
+
let resolve28;
|
|
5360
5397
|
const turnPromise = new Promise((r) => {
|
|
5361
|
-
|
|
5398
|
+
resolve28 = r;
|
|
5362
5399
|
});
|
|
5363
5400
|
const listener = (text) => {
|
|
5364
|
-
|
|
5401
|
+
resolve28(text);
|
|
5365
5402
|
};
|
|
5366
5403
|
entry.subscribers.add(listener);
|
|
5367
5404
|
const writeAtMs = Date.now();
|
|
@@ -5979,6 +6016,35 @@ function getConfig(accountDir) {
|
|
|
5979
6016
|
return null;
|
|
5980
6017
|
}
|
|
5981
6018
|
}
|
|
6019
|
+
function migrateRemovedConfigKeys(accountDir) {
|
|
6020
|
+
try {
|
|
6021
|
+
const config = readConfig(accountDir);
|
|
6022
|
+
const wa = config.whatsapp;
|
|
6023
|
+
if (!wa || typeof wa !== "object") return { dropped: [] };
|
|
6024
|
+
const result = parseWhatsAppConfigTolerant(wa);
|
|
6025
|
+
if (!result.ok || result.droppedKeys.length === 0) return { dropped: [] };
|
|
6026
|
+
const block = wa;
|
|
6027
|
+
for (const dotted of result.droppedKeys) {
|
|
6028
|
+
const segs = dotted.split(".");
|
|
6029
|
+
const key = segs.pop();
|
|
6030
|
+
const container = segs.reduce(
|
|
6031
|
+
(acc, seg) => acc && typeof acc === "object" ? acc[seg] : void 0,
|
|
6032
|
+
block
|
|
6033
|
+
);
|
|
6034
|
+
if (container && typeof container === "object") {
|
|
6035
|
+
delete container[key];
|
|
6036
|
+
}
|
|
6037
|
+
}
|
|
6038
|
+
writeConfig(accountDir, config);
|
|
6039
|
+
console.error(
|
|
6040
|
+
`${TAG17} migration: stripped unknown keys=[${result.droppedKeys.join(",")}] from account.json`
|
|
6041
|
+
);
|
|
6042
|
+
return { dropped: result.droppedKeys };
|
|
6043
|
+
} catch (err) {
|
|
6044
|
+
console.error(`${TAG17} migration failed: ${String(err)}`);
|
|
6045
|
+
return { dropped: [] };
|
|
6046
|
+
}
|
|
6047
|
+
}
|
|
5982
6048
|
|
|
5983
6049
|
// app/lib/whatsapp/login.ts
|
|
5984
6050
|
var TAG18 = "[whatsapp:login]";
|
|
@@ -6118,8 +6184,8 @@ async function startLogin(opts) {
|
|
|
6118
6184
|
await clearAuth(authDir);
|
|
6119
6185
|
let resolveCode = null;
|
|
6120
6186
|
let rejectCode = null;
|
|
6121
|
-
const codePromise = new Promise((
|
|
6122
|
-
resolveCode =
|
|
6187
|
+
const codePromise = new Promise((resolve28, reject) => {
|
|
6188
|
+
resolveCode = resolve28;
|
|
6123
6189
|
rejectCode = reject;
|
|
6124
6190
|
});
|
|
6125
6191
|
const codeTimer = setTimeout(
|
|
@@ -6830,7 +6896,7 @@ function enumerateJsonls(projectsRoot) {
|
|
|
6830
6896
|
}
|
|
6831
6897
|
for (const entry of entries) {
|
|
6832
6898
|
if (entry.isFile() && SESSION_ID_RE.test(entry.name)) {
|
|
6833
|
-
out.push({ path: join7(slugDir, entry.name), isSubagent: false });
|
|
6899
|
+
out.push({ path: join7(slugDir, entry.name), isSubagent: false, archived: false });
|
|
6834
6900
|
} else if (entry.isDirectory() && entry.name === "subagents") {
|
|
6835
6901
|
const subDir = join7(slugDir, entry.name);
|
|
6836
6902
|
let subEntries;
|
|
@@ -6843,7 +6909,22 @@ function enumerateJsonls(projectsRoot) {
|
|
|
6843
6909
|
}
|
|
6844
6910
|
for (const sub of subEntries) {
|
|
6845
6911
|
if (sub.isFile() && SESSION_ID_RE.test(sub.name)) {
|
|
6846
|
-
out.push({ path: join7(subDir, sub.name), isSubagent: true });
|
|
6912
|
+
out.push({ path: join7(subDir, sub.name), isSubagent: true, archived: false });
|
|
6913
|
+
}
|
|
6914
|
+
}
|
|
6915
|
+
} else if (entry.isDirectory() && entry.name === "archive") {
|
|
6916
|
+
const archiveDir = join7(slugDir, entry.name);
|
|
6917
|
+
let archiveEntries;
|
|
6918
|
+
try {
|
|
6919
|
+
archiveEntries = readdirSync4(archiveDir, { withFileTypes: true });
|
|
6920
|
+
} catch (err) {
|
|
6921
|
+
const code = err.code ?? "unknown";
|
|
6922
|
+
console.error(`[admin-sessions-list] archive-skipped slug=${slug} code=${code}`);
|
|
6923
|
+
continue;
|
|
6924
|
+
}
|
|
6925
|
+
for (const arc of archiveEntries) {
|
|
6926
|
+
if (arc.isFile() && SESSION_ID_RE.test(arc.name)) {
|
|
6927
|
+
out.push({ path: join7(archiveDir, arc.name), isSubagent: false, archived: true });
|
|
6847
6928
|
}
|
|
6848
6929
|
}
|
|
6849
6930
|
}
|
|
@@ -6983,8 +7064,9 @@ app4.get("/", requireAdminSession, async (c) => {
|
|
|
6983
7064
|
let liveCount = 0;
|
|
6984
7065
|
let subagentCount = 0;
|
|
6985
7066
|
let nonResumableCount = 0;
|
|
7067
|
+
let archivedCount = 0;
|
|
6986
7068
|
const titleSourceCounts = { user: 0, ai: 0, "first-message": 0, prefix: 0 };
|
|
6987
|
-
for (const { path: path2, isSubagent } of jsonls) {
|
|
7069
|
+
for (const { path: path2, isSubagent, archived } of jsonls) {
|
|
6988
7070
|
const lastSlash = path2.lastIndexOf("/");
|
|
6989
7071
|
const base = path2.slice(lastSlash + 1);
|
|
6990
7072
|
const projectDir = path2.slice(0, lastSlash);
|
|
@@ -7019,15 +7101,17 @@ app4.get("/", requireAdminSession, async (c) => {
|
|
|
7019
7101
|
pid,
|
|
7020
7102
|
projectDir,
|
|
7021
7103
|
bridgeIds,
|
|
7022
|
-
resumable
|
|
7104
|
+
resumable,
|
|
7105
|
+
archived
|
|
7023
7106
|
});
|
|
7024
7107
|
if (live) liveCount += 1;
|
|
7025
7108
|
if (isSubagent) subagentCount += 1;
|
|
7026
7109
|
if (!resumable) nonResumableCount += 1;
|
|
7110
|
+
if (archived) archivedCount += 1;
|
|
7027
7111
|
}
|
|
7028
7112
|
rows.sort((a, b) => a.startedAt < b.startedAt ? 1 : -1);
|
|
7029
7113
|
console.log(
|
|
7030
|
-
`[admin-sessions-list] rows=${rows.length} live=${liveCount} subagents=${subagentCount} nonResumable=${nonResumableCount} titles user=${titleSourceCounts.user} ai=${titleSourceCounts.ai} first=${titleSourceCounts["first-message"]} prefix=${titleSourceCounts.prefix} accountId=${accountId ? accountId.slice(0, 8) : "unset"}`
|
|
7114
|
+
`[admin-sessions-list] rows=${rows.length} live=${liveCount} subagents=${subagentCount} archived=${archivedCount} nonResumable=${nonResumableCount} titles user=${titleSourceCounts.user} ai=${titleSourceCounts.ai} first=${titleSourceCounts["first-message"]} prefix=${titleSourceCounts.prefix} accountId=${accountId ? accountId.slice(0, 8) : "unset"}`
|
|
7031
7115
|
);
|
|
7032
7116
|
return c.json({ sessions: rows, accountId });
|
|
7033
7117
|
});
|
|
@@ -7239,14 +7323,168 @@ app5.get("/stream", requireAdminSession, (c) => {
|
|
|
7239
7323
|
});
|
|
7240
7324
|
var whatsapp_reader_default = app5;
|
|
7241
7325
|
|
|
7326
|
+
// server/routes/telegram.ts
|
|
7327
|
+
import { homedir } from "os";
|
|
7328
|
+
import { resolve as resolve10, join as join9 } from "path";
|
|
7329
|
+
import { existsSync as existsSync6, readFileSync as readFileSync10 } from "fs";
|
|
7330
|
+
|
|
7331
|
+
// app/lib/telegram/access-control.ts
|
|
7332
|
+
function checkTelegramAccess(params) {
|
|
7333
|
+
const { senderId, botType, config } = params;
|
|
7334
|
+
if (botType === "admin") {
|
|
7335
|
+
const adminUsers = config.adminUsers ?? [];
|
|
7336
|
+
if (adminUsers.includes(senderId)) {
|
|
7337
|
+
return { allowed: true, reason: "admin-binding", agentType: "admin" };
|
|
7338
|
+
}
|
|
7339
|
+
return { allowed: false, reason: "not-admin-user", agentType: "admin" };
|
|
7340
|
+
}
|
|
7341
|
+
const policy = config.dmPolicy ?? "disabled";
|
|
7342
|
+
switch (policy) {
|
|
7343
|
+
case "open":
|
|
7344
|
+
return { allowed: true, reason: "dm-policy-open", agentType: "public" };
|
|
7345
|
+
case "allowlist": {
|
|
7346
|
+
const allowFrom = config.allowFrom ?? [];
|
|
7347
|
+
if (allowFrom.includes(senderId)) {
|
|
7348
|
+
return { allowed: true, reason: "allowlist-match", agentType: "public" };
|
|
7349
|
+
}
|
|
7350
|
+
return { allowed: false, reason: "not-in-allowlist", agentType: "public" };
|
|
7351
|
+
}
|
|
7352
|
+
case "disabled":
|
|
7353
|
+
return { allowed: false, reason: "dm-policy-disabled", agentType: "public" };
|
|
7354
|
+
default:
|
|
7355
|
+
return { allowed: false, reason: "unknown-dm-policy", agentType: "public" };
|
|
7356
|
+
}
|
|
7357
|
+
}
|
|
7358
|
+
|
|
7359
|
+
// app/lib/telegram/route-inbound.ts
|
|
7360
|
+
function routeTelegramUpdate(input) {
|
|
7361
|
+
const m = input.update.message;
|
|
7362
|
+
if (!m || typeof m.from?.id !== "number" || typeof m.chat?.id !== "number") {
|
|
7363
|
+
return { kind: "ignore", reason: "no-message" };
|
|
7364
|
+
}
|
|
7365
|
+
if (typeof m.text !== "string" || m.text.length === 0) {
|
|
7366
|
+
return { kind: "ignore", reason: "no-text" };
|
|
7367
|
+
}
|
|
7368
|
+
const access = checkTelegramAccess({ senderId: m.from.id, botType: input.botType, config: input.config });
|
|
7369
|
+
if (!access.allowed) {
|
|
7370
|
+
return { kind: "denied", reason: access.reason, agentType: access.agentType };
|
|
7371
|
+
}
|
|
7372
|
+
return { kind: "dispatch", senderId: String(m.from.id), chatId: m.chat.id, text: m.text, agentType: access.agentType };
|
|
7373
|
+
}
|
|
7374
|
+
|
|
7375
|
+
// server/routes/telegram.ts
|
|
7376
|
+
var TAG21 = "[telegram-inbound]";
|
|
7377
|
+
var DISPATCH_TIMEOUT_MS = 12e4;
|
|
7378
|
+
function configDirName() {
|
|
7379
|
+
const platformRoot2 = process.env.MAXY_PLATFORM_ROOT ?? resolve10(process.cwd(), "..");
|
|
7380
|
+
const brandPath = join9(platformRoot2, "config", "brand.json");
|
|
7381
|
+
if (existsSync6(brandPath)) {
|
|
7382
|
+
try {
|
|
7383
|
+
return JSON.parse(readFileSync10(brandPath, "utf-8")).configDir ?? ".maxy";
|
|
7384
|
+
} catch {
|
|
7385
|
+
}
|
|
7386
|
+
}
|
|
7387
|
+
return ".maxy";
|
|
7388
|
+
}
|
|
7389
|
+
function secretPath(botType) {
|
|
7390
|
+
const filename = botType === "admin" ? ".telegram-admin-webhook-secret" : ".telegram-webhook-secret";
|
|
7391
|
+
return resolve10(homedir(), configDirName(), filename);
|
|
7392
|
+
}
|
|
7393
|
+
async function sendTelegram(botToken, chatId, text) {
|
|
7394
|
+
try {
|
|
7395
|
+
const res = await fetch(`https://api.telegram.org/bot${botToken}/sendMessage`, {
|
|
7396
|
+
method: "POST",
|
|
7397
|
+
headers: { "Content-Type": "application/json" },
|
|
7398
|
+
body: JSON.stringify({ chat_id: chatId, text })
|
|
7399
|
+
});
|
|
7400
|
+
const data = await res.json();
|
|
7401
|
+
return data.ok ? { ok: true } : { ok: false, error: data.description ?? "send failed" };
|
|
7402
|
+
} catch (e) {
|
|
7403
|
+
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
7404
|
+
}
|
|
7405
|
+
}
|
|
7406
|
+
var app6 = new Hono();
|
|
7407
|
+
app6.post("/", async (c) => {
|
|
7408
|
+
const botParam = c.req.query("bot");
|
|
7409
|
+
const botType = botParam === "admin" ? "admin" : botParam === "public" ? "public" : null;
|
|
7410
|
+
if (!botType) {
|
|
7411
|
+
console.error(`${TAG21} op=reject reason=missing-bot-param`);
|
|
7412
|
+
return c.json({ ok: false }, 400);
|
|
7413
|
+
}
|
|
7414
|
+
const sp = secretPath(botType);
|
|
7415
|
+
if (!existsSync6(sp)) {
|
|
7416
|
+
console.error(`${TAG21} op=reject reason=no-secret-file botType=${botType}`);
|
|
7417
|
+
return c.json({ ok: false }, 401);
|
|
7418
|
+
}
|
|
7419
|
+
const expected = readFileSync10(sp, "utf-8").trim();
|
|
7420
|
+
const got = c.req.header("x-telegram-bot-api-secret-token") ?? "";
|
|
7421
|
+
if (got !== expected) {
|
|
7422
|
+
console.error(`${TAG21} op=reject reason=bad-secret botType=${botType}`);
|
|
7423
|
+
return c.json({ ok: false }, 401);
|
|
7424
|
+
}
|
|
7425
|
+
let update;
|
|
7426
|
+
try {
|
|
7427
|
+
update = await c.req.json();
|
|
7428
|
+
} catch {
|
|
7429
|
+
return c.json({ ok: true }, 200);
|
|
7430
|
+
}
|
|
7431
|
+
const account = resolveAccount();
|
|
7432
|
+
if (!account) {
|
|
7433
|
+
console.error(`${TAG21} op=reject reason=no-account`);
|
|
7434
|
+
return c.json({ ok: true }, 200);
|
|
7435
|
+
}
|
|
7436
|
+
const decision = routeTelegramUpdate({ update, botType, config: account.config.telegram ?? {} });
|
|
7437
|
+
if (decision.kind === "ignore") {
|
|
7438
|
+
console.error(`${TAG21} op=ignore reason=${decision.reason}`);
|
|
7439
|
+
return c.json({ ok: true }, 200);
|
|
7440
|
+
}
|
|
7441
|
+
if (decision.kind === "denied") {
|
|
7442
|
+
console.error(`${TAG21} op=denied reason=${decision.reason} agentType=${decision.agentType}`);
|
|
7443
|
+
return c.json({ ok: true }, 200);
|
|
7444
|
+
}
|
|
7445
|
+
const role = decision.agentType === "admin" ? "admin" : "public";
|
|
7446
|
+
const agentSlug = role === "admin" ? "admin" : resolveDefaultAgentSlug(account.accountDir);
|
|
7447
|
+
if (!agentSlug) {
|
|
7448
|
+
console.error(`${TAG21} op=reject reason=no-default-agent`);
|
|
7449
|
+
return c.json({ ok: true }, 200);
|
|
7450
|
+
}
|
|
7451
|
+
console.error(`${TAG21} op=update accountId=${account.accountId} from=${decision.senderId}`);
|
|
7452
|
+
const botToken = botType === "admin" ? account.config.telegram?.adminBotToken : account.config.telegram?.publicBotToken;
|
|
7453
|
+
const { senderId, chatId, text } = decision;
|
|
7454
|
+
void (async () => {
|
|
7455
|
+
const result = await dispatchOnce({
|
|
7456
|
+
accountId: account.accountId,
|
|
7457
|
+
senderId,
|
|
7458
|
+
role,
|
|
7459
|
+
channel: "telegram",
|
|
7460
|
+
agentSlug,
|
|
7461
|
+
text,
|
|
7462
|
+
timeoutMs: DISPATCH_TIMEOUT_MS
|
|
7463
|
+
});
|
|
7464
|
+
if ("error" in result) {
|
|
7465
|
+
console.error(`${TAG21} op=dispatch-failed from=${senderId} error=${result.error}`);
|
|
7466
|
+
return;
|
|
7467
|
+
}
|
|
7468
|
+
if (!botToken) {
|
|
7469
|
+
const reason = account.config.telegram ? "no-bot-token" : "no-telegram-config";
|
|
7470
|
+
console.error(`${TAG21} op=reply-dropped reason=${reason} botType=${botType}`);
|
|
7471
|
+
return;
|
|
7472
|
+
}
|
|
7473
|
+
const sent = await sendTelegram(botToken, chatId, result.turnText);
|
|
7474
|
+
console.error(`${TAG21} op=reply-sent from=${senderId} ok=${sent.ok}${sent.ok ? "" : ` error=${sent.error}`}`);
|
|
7475
|
+
})();
|
|
7476
|
+
return c.json({ ok: true }, 200);
|
|
7477
|
+
});
|
|
7478
|
+
var telegram_default = app6;
|
|
7479
|
+
|
|
7242
7480
|
// server/routes/onboarding.ts
|
|
7243
7481
|
import { spawn, spawnSync as spawnSync2, execFileSync as execFileSync2 } from "child_process";
|
|
7244
|
-
import { openSync as openSync2, closeSync as closeSync2, writeFileSync as writeFileSync6, writeSync, existsSync as
|
|
7482
|
+
import { openSync as openSync2, closeSync as closeSync2, writeFileSync as writeFileSync6, writeSync, existsSync as existsSync8, readFileSync as readFileSync12, unlinkSync } from "fs";
|
|
7245
7483
|
import { createHash as createHash2, randomUUID as randomUUID7 } from "crypto";
|
|
7246
7484
|
|
|
7247
7485
|
// ../lib/admins-write/src/index.ts
|
|
7248
|
-
import { existsSync as
|
|
7249
|
-
import { dirname as dirname2, join as
|
|
7486
|
+
import { existsSync as existsSync7, readFileSync as readFileSync11, writeFileSync as writeFileSync5, renameSync, mkdirSync as mkdirSync2, readdirSync as readdirSync5, statSync as statSync4 } from "fs";
|
|
7487
|
+
import { dirname as dirname2, join as join10 } from "path";
|
|
7250
7488
|
function logLine(input, result) {
|
|
7251
7489
|
const userIdShort = input.userId.slice(0, 8);
|
|
7252
7490
|
console.error(
|
|
@@ -7263,8 +7501,8 @@ function writeAdminEntry(input) {
|
|
|
7263
7501
|
const result = { usersJsonResult: "noop", accountJsonResult: "noop" };
|
|
7264
7502
|
try {
|
|
7265
7503
|
let users = [];
|
|
7266
|
-
if (
|
|
7267
|
-
const raw =
|
|
7504
|
+
if (existsSync7(input.usersFile)) {
|
|
7505
|
+
const raw = readFileSync11(input.usersFile, "utf-8").trim();
|
|
7268
7506
|
if (raw) {
|
|
7269
7507
|
const parsed = JSON.parse(raw);
|
|
7270
7508
|
if (!Array.isArray(parsed)) {
|
|
@@ -7288,11 +7526,11 @@ function writeAdminEntry(input) {
|
|
|
7288
7526
|
return result;
|
|
7289
7527
|
}
|
|
7290
7528
|
try {
|
|
7291
|
-
const accountJsonPath =
|
|
7292
|
-
if (!
|
|
7529
|
+
const accountJsonPath = join10(input.accountDir, "account.json");
|
|
7530
|
+
if (!existsSync7(accountJsonPath)) {
|
|
7293
7531
|
throw new Error(`account.json not found at ${accountJsonPath}`);
|
|
7294
7532
|
}
|
|
7295
|
-
const config = JSON.parse(
|
|
7533
|
+
const config = JSON.parse(readFileSync11(accountJsonPath, "utf-8"));
|
|
7296
7534
|
const admins = config.admins ?? [];
|
|
7297
7535
|
if (admins.some((a) => a.userId === input.userId)) {
|
|
7298
7536
|
result.accountJsonResult = "noop";
|
|
@@ -7316,9 +7554,9 @@ function checkAdminAuthInvariant(input) {
|
|
|
7316
7554
|
usersWithoutAccount: []
|
|
7317
7555
|
};
|
|
7318
7556
|
const usersUserIds = /* @__PURE__ */ new Set();
|
|
7319
|
-
if (
|
|
7557
|
+
if (existsSync7(input.usersFile)) {
|
|
7320
7558
|
try {
|
|
7321
|
-
const raw =
|
|
7559
|
+
const raw = readFileSync11(input.usersFile, "utf-8").trim();
|
|
7322
7560
|
if (raw) {
|
|
7323
7561
|
const users = JSON.parse(raw);
|
|
7324
7562
|
for (const u of users) {
|
|
@@ -7331,7 +7569,7 @@ function checkAdminAuthInvariant(input) {
|
|
|
7331
7569
|
}
|
|
7332
7570
|
}
|
|
7333
7571
|
const accountUserIds = /* @__PURE__ */ new Set();
|
|
7334
|
-
if (
|
|
7572
|
+
if (existsSync7(input.accountsDir)) {
|
|
7335
7573
|
let entries;
|
|
7336
7574
|
try {
|
|
7337
7575
|
entries = readdirSync5(input.accountsDir);
|
|
@@ -7343,17 +7581,17 @@ function checkAdminAuthInvariant(input) {
|
|
|
7343
7581
|
}
|
|
7344
7582
|
for (const entry of entries) {
|
|
7345
7583
|
if (entry.startsWith(".")) continue;
|
|
7346
|
-
const accountDir =
|
|
7584
|
+
const accountDir = join10(input.accountsDir, entry);
|
|
7347
7585
|
try {
|
|
7348
7586
|
if (!statSync4(accountDir).isDirectory()) continue;
|
|
7349
7587
|
} catch {
|
|
7350
7588
|
continue;
|
|
7351
7589
|
}
|
|
7352
|
-
const accountJsonPath =
|
|
7353
|
-
if (!
|
|
7590
|
+
const accountJsonPath = join10(accountDir, "account.json");
|
|
7591
|
+
if (!existsSync7(accountJsonPath)) continue;
|
|
7354
7592
|
let admins = [];
|
|
7355
7593
|
try {
|
|
7356
|
-
const config = JSON.parse(
|
|
7594
|
+
const config = JSON.parse(readFileSync11(accountJsonPath, "utf-8"));
|
|
7357
7595
|
admins = config.admins ?? [];
|
|
7358
7596
|
} catch (err) {
|
|
7359
7597
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -7393,8 +7631,8 @@ function hashPin(pin) {
|
|
|
7393
7631
|
return createHash2("sha256").update(pin).digest("hex");
|
|
7394
7632
|
}
|
|
7395
7633
|
function readUsersFile() {
|
|
7396
|
-
if (!
|
|
7397
|
-
const raw =
|
|
7634
|
+
if (!existsSync8(USERS_FILE)) return null;
|
|
7635
|
+
const raw = readFileSync12(USERS_FILE, "utf-8").trim();
|
|
7398
7636
|
if (!raw) return [];
|
|
7399
7637
|
return JSON.parse(raw);
|
|
7400
7638
|
}
|
|
@@ -7424,11 +7662,11 @@ async function waitForAuthPage(timeoutMs = 2e4) {
|
|
|
7424
7662
|
}
|
|
7425
7663
|
return false;
|
|
7426
7664
|
}
|
|
7427
|
-
var
|
|
7428
|
-
|
|
7665
|
+
var app7 = new Hono();
|
|
7666
|
+
app7.get("/claude-auth", async (c) => {
|
|
7429
7667
|
return c.json({ authenticated: await checkAuthStatus() });
|
|
7430
7668
|
});
|
|
7431
|
-
|
|
7669
|
+
app7.post("/claude-auth", async (c) => {
|
|
7432
7670
|
let body = {};
|
|
7433
7671
|
try {
|
|
7434
7672
|
body = await c.req.json();
|
|
@@ -7492,7 +7730,7 @@ app6.post("/claude-auth", async (c) => {
|
|
|
7492
7730
|
await waitForAuthPage(2e4);
|
|
7493
7731
|
return c.json({ started: true, transport });
|
|
7494
7732
|
});
|
|
7495
|
-
|
|
7733
|
+
app7.post("/set-pin", async (c) => {
|
|
7496
7734
|
let existingUsers = null;
|
|
7497
7735
|
try {
|
|
7498
7736
|
existingUsers = readUsersFile();
|
|
@@ -7548,9 +7786,9 @@ app6.post("/set-pin", async (c) => {
|
|
|
7548
7786
|
console.log(`[set-pin] wrote users.json + account.json admins: userId=${userId.slice(0, 8)}\u2026 role=owner`);
|
|
7549
7787
|
if (process.platform === "linux") {
|
|
7550
7788
|
let installOwner = null;
|
|
7551
|
-
if (
|
|
7789
|
+
if (existsSync8(INSTALL_OWNER_FILE)) {
|
|
7552
7790
|
try {
|
|
7553
|
-
const raw =
|
|
7791
|
+
const raw = readFileSync12(INSTALL_OWNER_FILE, "utf-8").trim();
|
|
7554
7792
|
if (raw.length > 0) installOwner = raw;
|
|
7555
7793
|
} catch (err) {
|
|
7556
7794
|
console.error(`[set-pin] install-owner-read-failed path=${INSTALL_OWNER_FILE} error=${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -7594,7 +7832,7 @@ ${body.pin}
|
|
|
7594
7832
|
}
|
|
7595
7833
|
return c.json({ ok: true });
|
|
7596
7834
|
});
|
|
7597
|
-
|
|
7835
|
+
app7.delete("/set-pin", async (c) => {
|
|
7598
7836
|
let users = null;
|
|
7599
7837
|
try {
|
|
7600
7838
|
users = readUsersFile();
|
|
@@ -7628,12 +7866,12 @@ app6.delete("/set-pin", async (c) => {
|
|
|
7628
7866
|
}
|
|
7629
7867
|
return c.json({ ok: true });
|
|
7630
7868
|
});
|
|
7631
|
-
var onboarding_default =
|
|
7869
|
+
var onboarding_default = app7;
|
|
7632
7870
|
|
|
7633
7871
|
// server/routes/client-error.ts
|
|
7634
|
-
import { appendFileSync, existsSync as
|
|
7635
|
-
import { join as
|
|
7636
|
-
var CLIENT_ERRORS_LOG =
|
|
7872
|
+
import { appendFileSync, existsSync as existsSync9, renameSync as renameSync2, statSync as statSync5 } from "fs";
|
|
7873
|
+
import { join as join11 } from "path";
|
|
7874
|
+
var CLIENT_ERRORS_LOG = join11(LOG_DIR, "client-errors.log");
|
|
7637
7875
|
var MAX_LOG_SIZE = 10 * 1024 * 1024;
|
|
7638
7876
|
var MAX_BODY_SIZE = 8 * 1024;
|
|
7639
7877
|
var MAX_STACK_LEN = 2e3;
|
|
@@ -7676,7 +7914,7 @@ function stackHead(stack) {
|
|
|
7676
7914
|
}
|
|
7677
7915
|
function rotateIfNeeded() {
|
|
7678
7916
|
try {
|
|
7679
|
-
if (!
|
|
7917
|
+
if (!existsSync9(CLIENT_ERRORS_LOG)) return;
|
|
7680
7918
|
const stats = statSync5(CLIENT_ERRORS_LOG);
|
|
7681
7919
|
if (stats.size < MAX_LOG_SIZE) return;
|
|
7682
7920
|
renameSync2(CLIENT_ERRORS_LOG, CLIENT_ERRORS_LOG + ".1");
|
|
@@ -7684,8 +7922,8 @@ function rotateIfNeeded() {
|
|
|
7684
7922
|
console.error(`[client-error] log rotation failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
7685
7923
|
}
|
|
7686
7924
|
}
|
|
7687
|
-
var
|
|
7688
|
-
|
|
7925
|
+
var app8 = new Hono();
|
|
7926
|
+
app8.post("/", async (c) => {
|
|
7689
7927
|
const client = resolveClientIp(
|
|
7690
7928
|
c.env?.incoming?.socket?.remoteAddress,
|
|
7691
7929
|
c.req.header("x-forwarded-for")
|
|
@@ -7787,21 +8025,21 @@ app7.post("/", async (c) => {
|
|
|
7787
8025
|
}
|
|
7788
8026
|
return c.json({ ok: true });
|
|
7789
8027
|
});
|
|
7790
|
-
var client_error_default =
|
|
8028
|
+
var client_error_default = app8;
|
|
7791
8029
|
|
|
7792
8030
|
// server/routes/admin/session.ts
|
|
7793
8031
|
import { randomUUID as randomUUID8 } from "crypto";
|
|
7794
8032
|
|
|
7795
8033
|
// app/lib/admin-identity/pin-validator.ts
|
|
7796
8034
|
import { createHash as createHash3 } from "crypto";
|
|
7797
|
-
import { existsSync as
|
|
7798
|
-
import { join as
|
|
8035
|
+
import { existsSync as existsSync10, readFileSync as readFileSync13, readdirSync as readdirSync6, statSync as statSync6 } from "fs";
|
|
8036
|
+
import { join as join12 } from "path";
|
|
7799
8037
|
function hashPin2(pin) {
|
|
7800
8038
|
return createHash3("sha256").update(pin).digest("hex");
|
|
7801
8039
|
}
|
|
7802
8040
|
function readUsersFile2(usersFilePath) {
|
|
7803
|
-
if (!
|
|
7804
|
-
const raw =
|
|
8041
|
+
if (!existsSync10(usersFilePath)) return null;
|
|
8042
|
+
const raw = readFileSync13(usersFilePath, "utf-8").trim();
|
|
7805
8043
|
if (!raw) return [];
|
|
7806
8044
|
return JSON.parse(raw);
|
|
7807
8045
|
}
|
|
@@ -7820,7 +8058,7 @@ function validatePin(pin, usersFilePath) {
|
|
|
7820
8058
|
function scanForOrphanedAccountAdmins(users, accountsDir) {
|
|
7821
8059
|
const known = new Set(users.map((u) => u.userId));
|
|
7822
8060
|
const orphans = [];
|
|
7823
|
-
if (!
|
|
8061
|
+
if (!existsSync10(accountsDir)) return orphans;
|
|
7824
8062
|
let entries;
|
|
7825
8063
|
try {
|
|
7826
8064
|
entries = readdirSync6(accountsDir);
|
|
@@ -7829,16 +8067,16 @@ function scanForOrphanedAccountAdmins(users, accountsDir) {
|
|
|
7829
8067
|
}
|
|
7830
8068
|
for (const entry of entries) {
|
|
7831
8069
|
if (entry.startsWith(".")) continue;
|
|
7832
|
-
const accountDir =
|
|
8070
|
+
const accountDir = join12(accountsDir, entry);
|
|
7833
8071
|
try {
|
|
7834
8072
|
if (!statSync6(accountDir).isDirectory()) continue;
|
|
7835
8073
|
} catch {
|
|
7836
8074
|
continue;
|
|
7837
8075
|
}
|
|
7838
|
-
const accountJsonPath =
|
|
7839
|
-
if (!
|
|
8076
|
+
const accountJsonPath = join12(accountDir, "account.json");
|
|
8077
|
+
if (!existsSync10(accountJsonPath)) continue;
|
|
7840
8078
|
try {
|
|
7841
|
-
const config = JSON.parse(
|
|
8079
|
+
const config = JSON.parse(readFileSync13(accountJsonPath, "utf-8"));
|
|
7842
8080
|
const admins = config.admins ?? [];
|
|
7843
8081
|
for (const a of admins) {
|
|
7844
8082
|
if (typeof a.userId === "string" && !known.has(a.userId)) orphans.push(a.userId);
|
|
@@ -7905,8 +8143,8 @@ async function createAdminSession(accountId, thinkingView, userId, userName, rol
|
|
|
7905
8143
|
sessionId: initialSessionId
|
|
7906
8144
|
};
|
|
7907
8145
|
}
|
|
7908
|
-
var
|
|
7909
|
-
|
|
8146
|
+
var app9 = new Hono();
|
|
8147
|
+
app9.get("/", async (c) => {
|
|
7910
8148
|
const signedSessionToken = c.req.query("session_key");
|
|
7911
8149
|
if (!signedSessionToken) {
|
|
7912
8150
|
return c.json({ error: "Invalid or expired admin session" }, 401);
|
|
@@ -7952,7 +8190,7 @@ app8.get("/", async (c) => {
|
|
|
7952
8190
|
sessionId: getSessionIdForSession(cacheKey) ?? null
|
|
7953
8191
|
});
|
|
7954
8192
|
});
|
|
7955
|
-
|
|
8193
|
+
app9.post("/", async (c) => {
|
|
7956
8194
|
let body;
|
|
7957
8195
|
try {
|
|
7958
8196
|
body = await c.req.json();
|
|
@@ -8015,21 +8253,21 @@ app8.post("/", async (c) => {
|
|
|
8015
8253
|
const payload = await createAdminSession(selected.accountId, selected.config.thinkingView, userId, userName, selected.role, avatar);
|
|
8016
8254
|
return c.json(payload);
|
|
8017
8255
|
});
|
|
8018
|
-
var session_default =
|
|
8256
|
+
var session_default = app9;
|
|
8019
8257
|
|
|
8020
8258
|
// server/routes/admin/logs.ts
|
|
8021
|
-
import { existsSync as
|
|
8022
|
-
import { resolve as
|
|
8259
|
+
import { existsSync as existsSync12, readdirSync as readdirSync7, readFileSync as readFileSync14, statSync as statSync7 } from "fs";
|
|
8260
|
+
import { resolve as resolve11, basename as basename3 } from "path";
|
|
8023
8261
|
|
|
8024
8262
|
// app/lib/logs-read-resolve.ts
|
|
8025
|
-
import { existsSync as
|
|
8026
|
-
import { join as
|
|
8263
|
+
import { existsSync as existsSync11 } from "fs";
|
|
8264
|
+
import { join as join13 } from "path";
|
|
8027
8265
|
function resolveSessionLogPaths(filename, logDirs) {
|
|
8028
8266
|
const tried = [filename];
|
|
8029
8267
|
const hits = [];
|
|
8030
8268
|
for (const dir of logDirs) {
|
|
8031
|
-
const fullPath =
|
|
8032
|
-
if (
|
|
8269
|
+
const fullPath = join13(dir, filename);
|
|
8270
|
+
if (existsSync11(fullPath)) {
|
|
8033
8271
|
hits.push({ path: fullPath, dir });
|
|
8034
8272
|
}
|
|
8035
8273
|
}
|
|
@@ -8038,15 +8276,15 @@ function resolveSessionLogPaths(filename, logDirs) {
|
|
|
8038
8276
|
|
|
8039
8277
|
// server/routes/admin/logs.ts
|
|
8040
8278
|
var TAIL_BYTES = 8192;
|
|
8041
|
-
var
|
|
8042
|
-
|
|
8279
|
+
var app10 = new Hono();
|
|
8280
|
+
app10.get("/", async (c) => {
|
|
8043
8281
|
const fileParam = c.req.query("file");
|
|
8044
8282
|
const typeParam = c.req.query("type");
|
|
8045
8283
|
const sessionIdParam = c.req.query("sessionId");
|
|
8046
8284
|
const cacheKeyParam = c.req.query("cacheKey");
|
|
8047
8285
|
const download = c.req.query("download") === "1";
|
|
8048
8286
|
const account = resolveAccount();
|
|
8049
|
-
const accountLogDir = account ?
|
|
8287
|
+
const accountLogDir = account ? resolve11(account.accountDir, "logs") : null;
|
|
8050
8288
|
const logDirs = [];
|
|
8051
8289
|
if (accountLogDir) logDirs.push(accountLogDir);
|
|
8052
8290
|
logDirs.push(LOG_DIR);
|
|
@@ -8054,10 +8292,10 @@ app9.get("/", async (c) => {
|
|
|
8054
8292
|
const safe = basename3(fileParam);
|
|
8055
8293
|
const searched = [];
|
|
8056
8294
|
for (const dir of logDirs) {
|
|
8057
|
-
const filePath =
|
|
8295
|
+
const filePath = resolve11(dir, safe);
|
|
8058
8296
|
searched.push(filePath);
|
|
8059
8297
|
try {
|
|
8060
|
-
const buffer =
|
|
8298
|
+
const buffer = readFileSync14(filePath);
|
|
8061
8299
|
const onDiskBytes = statSync7(filePath).size;
|
|
8062
8300
|
const headers = {
|
|
8063
8301
|
"Content-Type": "text/plain; charset=utf-8",
|
|
@@ -8122,7 +8360,7 @@ app9.get("/", async (c) => {
|
|
|
8122
8360
|
console.info(`[admin/logs] resolved cacheKey=${cacheKeySlice} sessionId=${sessionIdSlice} via=${primaryId === cacheKey ? "cacheKey" : primaryId === sessionKeyFromConv ? "reverse-lookup" : "sessionId-fallback"}`);
|
|
8123
8361
|
try {
|
|
8124
8362
|
const filename = basename3(hit.path);
|
|
8125
|
-
const buffer =
|
|
8363
|
+
const buffer = readFileSync14(hit.path);
|
|
8126
8364
|
const onDiskBytes = statSync7(hit.path).size;
|
|
8127
8365
|
const headers = {
|
|
8128
8366
|
"Content-Type": "text/plain; charset=utf-8",
|
|
@@ -8157,7 +8395,7 @@ app9.get("/", async (c) => {
|
|
|
8157
8395
|
const seen = /* @__PURE__ */ new Set();
|
|
8158
8396
|
const logs = {};
|
|
8159
8397
|
for (const dir of logDirs) {
|
|
8160
|
-
if (!
|
|
8398
|
+
if (!existsSync12(dir)) continue;
|
|
8161
8399
|
let files;
|
|
8162
8400
|
try {
|
|
8163
8401
|
files = readdirSync7(dir).filter((f) => f.endsWith(".log"));
|
|
@@ -8166,10 +8404,10 @@ app9.get("/", async (c) => {
|
|
|
8166
8404
|
console.warn(`[admin/logs] readdir-fail dir=${dir} reason=${reason}`);
|
|
8167
8405
|
continue;
|
|
8168
8406
|
}
|
|
8169
|
-
files.filter((f) => !seen.has(f)).map((f) => ({ name: f, mtime: statSync7(
|
|
8407
|
+
files.filter((f) => !seen.has(f)).map((f) => ({ name: f, mtime: statSync7(resolve11(dir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime).forEach(({ name }) => {
|
|
8170
8408
|
seen.add(name);
|
|
8171
8409
|
try {
|
|
8172
|
-
const content =
|
|
8410
|
+
const content = readFileSync14(resolve11(dir, name));
|
|
8173
8411
|
const tail = content.length > TAIL_BYTES ? content.subarray(content.length - TAIL_BYTES).toString("utf-8") : content.toString("utf-8");
|
|
8174
8412
|
logs[name] = tail.trim() || "(empty)";
|
|
8175
8413
|
} catch (err) {
|
|
@@ -8181,12 +8419,12 @@ app9.get("/", async (c) => {
|
|
|
8181
8419
|
}
|
|
8182
8420
|
return c.json({ logs });
|
|
8183
8421
|
});
|
|
8184
|
-
var logs_default =
|
|
8422
|
+
var logs_default = app10;
|
|
8185
8423
|
|
|
8186
8424
|
// server/routes/admin/claude-info.ts
|
|
8187
8425
|
import { execFileSync as execFileSync3 } from "child_process";
|
|
8188
|
-
var
|
|
8189
|
-
|
|
8426
|
+
var app11 = new Hono();
|
|
8427
|
+
app11.get("/", (c) => {
|
|
8190
8428
|
let version = "unknown";
|
|
8191
8429
|
try {
|
|
8192
8430
|
const raw = execFileSync3("claude", ["--version"], { encoding: "utf-8", timeout: 5e3 });
|
|
@@ -8204,14 +8442,14 @@ app10.get("/", (c) => {
|
|
|
8204
8442
|
const thinkingView = resolvedAccount?.config.thinkingView ?? "default";
|
|
8205
8443
|
return c.json({ version, account, model, thinkingView });
|
|
8206
8444
|
});
|
|
8207
|
-
var claude_info_default =
|
|
8445
|
+
var claude_info_default = app11;
|
|
8208
8446
|
|
|
8209
8447
|
// server/routes/admin/attachment.ts
|
|
8210
8448
|
import { readFile as readFile2, readdir } from "fs/promises";
|
|
8211
|
-
import { existsSync as
|
|
8212
|
-
import { resolve as
|
|
8213
|
-
var
|
|
8214
|
-
|
|
8449
|
+
import { existsSync as existsSync13 } from "fs";
|
|
8450
|
+
import { resolve as resolve12 } from "path";
|
|
8451
|
+
var app12 = new Hono();
|
|
8452
|
+
app12.get("/:attachmentId", requireAdminSession, async (c) => {
|
|
8215
8453
|
const attachmentId = c.req.param("attachmentId");
|
|
8216
8454
|
const cacheKey = c.var.cacheKey;
|
|
8217
8455
|
const accountId = getAccountIdForSession(cacheKey);
|
|
@@ -8221,12 +8459,12 @@ app11.get("/:attachmentId", requireAdminSession, async (c) => {
|
|
|
8221
8459
|
if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/.test(attachmentId)) {
|
|
8222
8460
|
return new Response("Not found", { status: 404 });
|
|
8223
8461
|
}
|
|
8224
|
-
const dir =
|
|
8225
|
-
if (!
|
|
8462
|
+
const dir = resolve12(ATTACHMENTS_ROOT, accountId, attachmentId);
|
|
8463
|
+
if (!existsSync13(dir)) {
|
|
8226
8464
|
return new Response("Not found", { status: 404 });
|
|
8227
8465
|
}
|
|
8228
|
-
const metaPath =
|
|
8229
|
-
if (!
|
|
8466
|
+
const metaPath = resolve12(dir, `${attachmentId}.meta.json`);
|
|
8467
|
+
if (!existsSync13(metaPath)) {
|
|
8230
8468
|
return new Response("Not found", { status: 404 });
|
|
8231
8469
|
}
|
|
8232
8470
|
let meta;
|
|
@@ -8240,7 +8478,7 @@ app11.get("/:attachmentId", requireAdminSession, async (c) => {
|
|
|
8240
8478
|
if (!dataFile) {
|
|
8241
8479
|
return new Response("Not found", { status: 404 });
|
|
8242
8480
|
}
|
|
8243
|
-
const filePath =
|
|
8481
|
+
const filePath = resolve12(dir, dataFile);
|
|
8244
8482
|
const buffer = await readFile2(filePath);
|
|
8245
8483
|
return new Response(new Uint8Array(buffer), {
|
|
8246
8484
|
headers: {
|
|
@@ -8250,27 +8488,27 @@ app11.get("/:attachmentId", requireAdminSession, async (c) => {
|
|
|
8250
8488
|
}
|
|
8251
8489
|
});
|
|
8252
8490
|
});
|
|
8253
|
-
var attachment_default =
|
|
8491
|
+
var attachment_default = app12;
|
|
8254
8492
|
|
|
8255
8493
|
// server/routes/admin/agents.ts
|
|
8256
|
-
import { resolve as
|
|
8257
|
-
import { readdirSync as readdirSync8, readFileSync as
|
|
8258
|
-
var
|
|
8259
|
-
|
|
8494
|
+
import { resolve as resolve13 } from "path";
|
|
8495
|
+
import { readdirSync as readdirSync8, readFileSync as readFileSync15, existsSync as existsSync14, rmSync } from "fs";
|
|
8496
|
+
var app13 = new Hono();
|
|
8497
|
+
app13.get("/", (c) => {
|
|
8260
8498
|
const account = resolveAccount();
|
|
8261
8499
|
if (!account) return c.json({ agents: [] });
|
|
8262
|
-
const agentsDir =
|
|
8263
|
-
if (!
|
|
8500
|
+
const agentsDir = resolve13(account.accountDir, "agents");
|
|
8501
|
+
if (!existsSync14(agentsDir)) return c.json({ agents: [] });
|
|
8264
8502
|
const agents = [];
|
|
8265
8503
|
try {
|
|
8266
8504
|
const entries = readdirSync8(agentsDir, { withFileTypes: true });
|
|
8267
8505
|
for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
8268
8506
|
if (!entry.isDirectory()) continue;
|
|
8269
8507
|
if (entry.name === "admin") continue;
|
|
8270
|
-
const configPath2 =
|
|
8271
|
-
if (!
|
|
8508
|
+
const configPath2 = resolve13(agentsDir, entry.name, "config.json");
|
|
8509
|
+
if (!existsSync14(configPath2)) continue;
|
|
8272
8510
|
try {
|
|
8273
|
-
const config = JSON.parse(
|
|
8511
|
+
const config = JSON.parse(readFileSync15(configPath2, "utf-8"));
|
|
8274
8512
|
agents.push({
|
|
8275
8513
|
slug: entry.name,
|
|
8276
8514
|
displayName: config.displayName ?? entry.name,
|
|
@@ -8286,7 +8524,7 @@ app12.get("/", (c) => {
|
|
|
8286
8524
|
}
|
|
8287
8525
|
return c.json({ agents });
|
|
8288
8526
|
});
|
|
8289
|
-
|
|
8527
|
+
app13.delete("/:slug", async (c) => {
|
|
8290
8528
|
const slug = c.req.param("slug");
|
|
8291
8529
|
const account = resolveAccount();
|
|
8292
8530
|
if (!account) return c.json({ error: "No account resolved" }, 400);
|
|
@@ -8296,8 +8534,8 @@ app12.delete("/:slug", async (c) => {
|
|
|
8296
8534
|
if (slug.includes("/") || slug.includes("..") || slug.includes("\\")) {
|
|
8297
8535
|
return c.json({ error: "Invalid agent slug" }, 400);
|
|
8298
8536
|
}
|
|
8299
|
-
const agentDir =
|
|
8300
|
-
if (!
|
|
8537
|
+
const agentDir = resolve13(account.accountDir, "agents", slug);
|
|
8538
|
+
if (!existsSync14(agentDir)) {
|
|
8301
8539
|
return c.json({ error: "Agent not found" }, 404);
|
|
8302
8540
|
}
|
|
8303
8541
|
try {
|
|
@@ -8316,7 +8554,7 @@ app12.delete("/:slug", async (c) => {
|
|
|
8316
8554
|
return c.json({ error: "Failed to delete agent" }, 500);
|
|
8317
8555
|
}
|
|
8318
8556
|
});
|
|
8319
|
-
|
|
8557
|
+
app13.post("/:slug/project", async (c) => {
|
|
8320
8558
|
const slug = c.req.param("slug");
|
|
8321
8559
|
const account = resolveAccount();
|
|
8322
8560
|
if (!account) return c.json({ error: "No account resolved" }, 400);
|
|
@@ -8326,8 +8564,8 @@ app12.post("/:slug/project", async (c) => {
|
|
|
8326
8564
|
if (slug.includes("/") || slug.includes("..") || slug.includes("\\")) {
|
|
8327
8565
|
return c.json({ error: "Invalid agent slug" }, 400);
|
|
8328
8566
|
}
|
|
8329
|
-
const agentDir =
|
|
8330
|
-
if (!
|
|
8567
|
+
const agentDir = resolve13(account.accountDir, "agents", slug);
|
|
8568
|
+
if (!existsSync14(agentDir)) {
|
|
8331
8569
|
return c.json({ error: "Agent not found on disk" }, 404);
|
|
8332
8570
|
}
|
|
8333
8571
|
try {
|
|
@@ -8338,12 +8576,12 @@ app12.post("/:slug/project", async (c) => {
|
|
|
8338
8576
|
return c.json({ error: `Projection failed: ${msg}` }, 500);
|
|
8339
8577
|
}
|
|
8340
8578
|
});
|
|
8341
|
-
var agents_default =
|
|
8579
|
+
var agents_default = app13;
|
|
8342
8580
|
|
|
8343
8581
|
// server/routes/admin/sessions.ts
|
|
8344
8582
|
import crypto2 from "crypto";
|
|
8345
8583
|
import { resolve as resolvePath } from "path";
|
|
8346
|
-
import { existsSync as
|
|
8584
|
+
import { existsSync as existsSync15, mkdirSync as mkdirSync3, createWriteStream } from "fs";
|
|
8347
8585
|
|
|
8348
8586
|
// ../lib/admin-conversation-purge/src/index.ts
|
|
8349
8587
|
async function purgeAdminConversationJsonls(args) {
|
|
@@ -8481,7 +8719,7 @@ var replayJsonl = (..._args) => null;
|
|
|
8481
8719
|
var resolveJsonlPath = (..._args) => null;
|
|
8482
8720
|
|
|
8483
8721
|
// server/routes/admin/sessions.ts
|
|
8484
|
-
import { homedir } from "os";
|
|
8722
|
+
import { homedir as homedir2 } from "os";
|
|
8485
8723
|
|
|
8486
8724
|
// app/lib/claude-agent/component-attachment.ts
|
|
8487
8725
|
var pickComponentBytes = (..._args) => null;
|
|
@@ -8503,7 +8741,7 @@ function validateAndShapeAttachments(raws, conversationAccountId, sessionId, mes
|
|
|
8503
8741
|
let reason = null;
|
|
8504
8742
|
if (!a.attachmentId || !a.filename || !a.mimeType || !a.storagePath) reason = "schema-fail";
|
|
8505
8743
|
else if (a.accountId !== conversationAccountId) reason = "account-mismatch";
|
|
8506
|
-
else if (!
|
|
8744
|
+
else if (!existsSync15(a.storagePath)) reason = "missing-file";
|
|
8507
8745
|
if (reason) {
|
|
8508
8746
|
invalid++;
|
|
8509
8747
|
try {
|
|
@@ -8610,8 +8848,8 @@ function formatAge(updatedAtStr) {
|
|
|
8610
8848
|
return "unknown";
|
|
8611
8849
|
}
|
|
8612
8850
|
}
|
|
8613
|
-
var
|
|
8614
|
-
|
|
8851
|
+
var app14 = new Hono();
|
|
8852
|
+
app14.get("/", requireAdminSession, async (c) => {
|
|
8615
8853
|
const cacheKey = c.var.cacheKey;
|
|
8616
8854
|
const accountId = getAccountIdForSession(cacheKey);
|
|
8617
8855
|
if (!accountId) return c.json({ error: "Account not found for session" }, 401);
|
|
@@ -8641,7 +8879,7 @@ app13.get("/", requireAdminSession, async (c) => {
|
|
|
8641
8879
|
return c.json({ error: "Failed to fetch sessions" }, 500);
|
|
8642
8880
|
}
|
|
8643
8881
|
});
|
|
8644
|
-
|
|
8882
|
+
app14.post("/new", requireAdminSession, async (c) => {
|
|
8645
8883
|
const oldCacheKey = c.var.cacheKey;
|
|
8646
8884
|
console.log(`[admin-chat] new-conversation outcome=ingress cacheKey=${oldCacheKey.slice(0, 8)}`);
|
|
8647
8885
|
const accountId = getAccountIdForSession(oldCacheKey);
|
|
@@ -8658,7 +8896,7 @@ app13.post("/new", requireAdminSession, async (c) => {
|
|
|
8658
8896
|
console.log(`[admin-chat] new-conversation outcome=ok oldKey=${oldCacheKey.slice(0, 8)} newKey=${newCacheKey.slice(0, 8)}`);
|
|
8659
8897
|
return c.json({ session_key: newSignedSessionToken, sessionId: null });
|
|
8660
8898
|
});
|
|
8661
|
-
|
|
8899
|
+
app14.post("/switch", requireAdminSession, async (c) => {
|
|
8662
8900
|
const cacheKey = c.var.cacheKey;
|
|
8663
8901
|
const accountId = getAccountIdForSession(cacheKey);
|
|
8664
8902
|
const userId = getUserIdForSession(cacheKey);
|
|
@@ -8686,7 +8924,7 @@ app13.post("/switch", requireAdminSession, async (c) => {
|
|
|
8686
8924
|
console.log(`[session-switch] from=${cacheKey.slice(0, 8)} to=${targetCacheKey.slice(0, 8)} targetConvId=${targetSessionId?.slice(0, 8) ?? "none"} accountId=${accountId.slice(0, 8)}`);
|
|
8687
8925
|
return c.json({ session_key: targetSignedSessionToken, sessionId: targetSessionId });
|
|
8688
8926
|
});
|
|
8689
|
-
|
|
8927
|
+
app14.delete("/:id", requireAdminSession, async (c) => {
|
|
8690
8928
|
const sessionId = c.req.param("id");
|
|
8691
8929
|
const cacheKey = c.var.cacheKey;
|
|
8692
8930
|
const accountId = getAccountIdForSession(cacheKey);
|
|
@@ -8731,7 +8969,7 @@ app13.delete("/:id", requireAdminSession, async (c) => {
|
|
|
8731
8969
|
500
|
|
8732
8970
|
);
|
|
8733
8971
|
});
|
|
8734
|
-
|
|
8972
|
+
app14.post("/:id/resume", async (c) => {
|
|
8735
8973
|
const sessionId = c.req.param("id");
|
|
8736
8974
|
const t0 = Date.now();
|
|
8737
8975
|
const signedSessionToken = c.req.query("session_key") ?? "";
|
|
@@ -8796,7 +9034,7 @@ app13.post("/:id/resume", async (c) => {
|
|
|
8796
9034
|
return c.json({ error: "Failed to load conversation messages" }, 500);
|
|
8797
9035
|
}
|
|
8798
9036
|
if (persistedAgentSessionId) {
|
|
8799
|
-
const jsonlPath = resolveJsonlPath(
|
|
9037
|
+
const jsonlPath = resolveJsonlPath(homedir2(), resolvePath(ACCOUNTS_DIR, accountId), persistedAgentSessionId);
|
|
8800
9038
|
const replay = replayJsonl(jsonlPath);
|
|
8801
9039
|
jsonlMissing = replay.jsonlMissing;
|
|
8802
9040
|
jsonlMalformedLines = replay.malformedLines;
|
|
@@ -9000,7 +9238,7 @@ app13.post("/:id/resume", async (c) => {
|
|
|
9000
9238
|
}
|
|
9001
9239
|
});
|
|
9002
9240
|
});
|
|
9003
|
-
|
|
9241
|
+
app14.put("/:id/label", requireAdminSession, async (c) => {
|
|
9004
9242
|
const sessionId = c.req.param("id");
|
|
9005
9243
|
const cacheKey = c.var.cacheKey;
|
|
9006
9244
|
let body;
|
|
@@ -9026,11 +9264,11 @@ app13.put("/:id/label", requireAdminSession, async (c) => {
|
|
|
9026
9264
|
return c.json({ error: "Failed to rename session" }, 500);
|
|
9027
9265
|
}
|
|
9028
9266
|
});
|
|
9029
|
-
var sessions_default =
|
|
9267
|
+
var sessions_default = app14;
|
|
9030
9268
|
|
|
9031
9269
|
// app/lib/claude-agent/spawn-context.ts
|
|
9032
|
-
import { existsSync as
|
|
9033
|
-
import { dirname as dirname3, resolve as
|
|
9270
|
+
import { existsSync as existsSync16, readFileSync as readFileSync16, readdirSync as readdirSync9, statSync as statSync8 } from "fs";
|
|
9271
|
+
import { dirname as dirname3, resolve as resolve14, join as join14 } from "path";
|
|
9034
9272
|
async function resolveOwnerProfileBlock(accountId, userId) {
|
|
9035
9273
|
if (!userId) return { ok: false, reason: "missing-user-id" };
|
|
9036
9274
|
try {
|
|
@@ -9059,14 +9297,14 @@ function frontmatterField(manifest, field) {
|
|
|
9059
9297
|
function extractPluginToolDescriptions(pluginDir) {
|
|
9060
9298
|
const out = /* @__PURE__ */ new Map();
|
|
9061
9299
|
const candidates = [
|
|
9062
|
-
|
|
9063
|
-
|
|
9300
|
+
join14(pluginDir, "mcp/dist/index.js"),
|
|
9301
|
+
join14(pluginDir, "mcp/src/index.ts")
|
|
9064
9302
|
];
|
|
9065
9303
|
let raw = null;
|
|
9066
9304
|
for (const path2 of candidates) {
|
|
9067
|
-
if (!
|
|
9305
|
+
if (!existsSync16(path2)) continue;
|
|
9068
9306
|
try {
|
|
9069
|
-
raw =
|
|
9307
|
+
raw = readFileSync16(path2, "utf-8");
|
|
9070
9308
|
break;
|
|
9071
9309
|
} catch {
|
|
9072
9310
|
}
|
|
@@ -9115,24 +9353,24 @@ function parseSkillPathsFromFrontmatter(fm) {
|
|
|
9115
9353
|
}
|
|
9116
9354
|
function listPluginDirs() {
|
|
9117
9355
|
const out = /* @__PURE__ */ new Map();
|
|
9118
|
-
const platformPlugins =
|
|
9119
|
-
if (
|
|
9356
|
+
const platformPlugins = resolve14(PLATFORM_ROOT, "plugins");
|
|
9357
|
+
if (existsSync16(platformPlugins)) {
|
|
9120
9358
|
for (const name of readdirSync9(platformPlugins)) {
|
|
9121
|
-
const dir =
|
|
9359
|
+
const dir = join14(platformPlugins, name);
|
|
9122
9360
|
try {
|
|
9123
9361
|
if (statSync8(dir).isDirectory()) out.set(name, dir);
|
|
9124
9362
|
} catch {
|
|
9125
9363
|
}
|
|
9126
9364
|
}
|
|
9127
9365
|
}
|
|
9128
|
-
const premiumRoot =
|
|
9129
|
-
if (
|
|
9366
|
+
const premiumRoot = resolve14(dirname3(PLATFORM_ROOT), "premium-plugins");
|
|
9367
|
+
if (existsSync16(premiumRoot)) {
|
|
9130
9368
|
for (const bundle of readdirSync9(premiumRoot)) {
|
|
9131
|
-
const bundlePlugins =
|
|
9132
|
-
if (!
|
|
9369
|
+
const bundlePlugins = join14(premiumRoot, bundle, "plugins");
|
|
9370
|
+
if (!existsSync16(bundlePlugins)) continue;
|
|
9133
9371
|
try {
|
|
9134
9372
|
for (const name of readdirSync9(bundlePlugins)) {
|
|
9135
|
-
const dir =
|
|
9373
|
+
const dir = join14(bundlePlugins, name);
|
|
9136
9374
|
try {
|
|
9137
9375
|
if (statSync8(dir).isDirectory()) out.set(name, dir);
|
|
9138
9376
|
} catch {
|
|
@@ -9145,10 +9383,10 @@ function listPluginDirs() {
|
|
|
9145
9383
|
return out;
|
|
9146
9384
|
}
|
|
9147
9385
|
function readEnabledPlugins(accountId) {
|
|
9148
|
-
const accountFile =
|
|
9149
|
-
if (!
|
|
9386
|
+
const accountFile = resolve14(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
|
|
9387
|
+
if (!existsSync16(accountFile)) return /* @__PURE__ */ new Set();
|
|
9150
9388
|
try {
|
|
9151
|
-
const parsed = JSON.parse(
|
|
9389
|
+
const parsed = JSON.parse(readFileSync16(accountFile, "utf-8"));
|
|
9152
9390
|
return new Set(
|
|
9153
9391
|
Array.isArray(parsed.enabledPlugins) ? parsed.enabledPlugins.filter((p) => typeof p === "string") : []
|
|
9154
9392
|
);
|
|
@@ -9157,10 +9395,10 @@ function readEnabledPlugins(accountId) {
|
|
|
9157
9395
|
}
|
|
9158
9396
|
}
|
|
9159
9397
|
function readFrontmatter(path2) {
|
|
9160
|
-
if (!
|
|
9398
|
+
if (!existsSync16(path2)) return null;
|
|
9161
9399
|
let raw;
|
|
9162
9400
|
try {
|
|
9163
|
-
raw =
|
|
9401
|
+
raw = readFileSync16(path2, "utf-8");
|
|
9164
9402
|
} catch {
|
|
9165
9403
|
return null;
|
|
9166
9404
|
}
|
|
@@ -9175,7 +9413,7 @@ function computeActivePlugins(accountId) {
|
|
|
9175
9413
|
for (const name of Array.from(enabled).sort()) {
|
|
9176
9414
|
const dir = pluginDirs.get(name);
|
|
9177
9415
|
if (!dir) continue;
|
|
9178
|
-
const fm = readFrontmatter(
|
|
9416
|
+
const fm = readFrontmatter(join14(dir, "PLUGIN.md"));
|
|
9179
9417
|
if (!fm) continue;
|
|
9180
9418
|
const description = frontmatterField(`---
|
|
9181
9419
|
${fm}
|
|
@@ -9192,7 +9430,7 @@ ${fm}
|
|
|
9192
9430
|
`plugin-manifest-tool-coverage plugin=${name} tools=${tools.length} with-desc=${withDesc}`
|
|
9193
9431
|
);
|
|
9194
9432
|
if (toolNames.length > 0 && descMap.size === 0) {
|
|
9195
|
-
const hasSource =
|
|
9433
|
+
const hasSource = existsSync16(join14(dir, "mcp/dist/index.js")) || existsSync16(join14(dir, "mcp/src/index.ts"));
|
|
9196
9434
|
if (hasSource) {
|
|
9197
9435
|
console.warn(
|
|
9198
9436
|
`[spawn-context] WARN plugin=${name} mcp source present but tool-description regex matched zero entries \u2014 SDK upgrade may have changed the registration shape`
|
|
@@ -9202,7 +9440,7 @@ ${fm}
|
|
|
9202
9440
|
const skillPaths = parseSkillPathsFromFrontmatter(fm);
|
|
9203
9441
|
const skills = [];
|
|
9204
9442
|
for (const relPath of skillPaths) {
|
|
9205
|
-
const skillPath =
|
|
9443
|
+
const skillPath = join14(dir, relPath);
|
|
9206
9444
|
const skillFm = readFrontmatter(skillPath);
|
|
9207
9445
|
if (!skillFm) continue;
|
|
9208
9446
|
const skillName = frontmatterField(`---
|
|
@@ -9218,8 +9456,8 @@ ${skillFm}
|
|
|
9218
9456
|
return out;
|
|
9219
9457
|
}
|
|
9220
9458
|
function computeSpecialistDomains(accountId) {
|
|
9221
|
-
const specialistsDir =
|
|
9222
|
-
if (!
|
|
9459
|
+
const specialistsDir = resolve14(PLATFORM_ROOT, "..", "data/accounts", accountId, "specialists", "agents");
|
|
9460
|
+
if (!existsSync16(specialistsDir)) return [];
|
|
9223
9461
|
let entries;
|
|
9224
9462
|
try {
|
|
9225
9463
|
entries = readdirSync9(specialistsDir);
|
|
@@ -9246,7 +9484,7 @@ function computeSpecialistDomains(accountId) {
|
|
|
9246
9484
|
const out = [];
|
|
9247
9485
|
for (const file of entries.sort()) {
|
|
9248
9486
|
if (!file.endsWith(".md")) continue;
|
|
9249
|
-
const fm = readFrontmatter(
|
|
9487
|
+
const fm = readFrontmatter(join14(specialistsDir, file));
|
|
9250
9488
|
if (!fm) continue;
|
|
9251
9489
|
const wrapped = `---
|
|
9252
9490
|
${fm}
|
|
@@ -9264,11 +9502,11 @@ ${fm}
|
|
|
9264
9502
|
return out;
|
|
9265
9503
|
}
|
|
9266
9504
|
function computeDormantPlugins(accountId) {
|
|
9267
|
-
const accountFile =
|
|
9268
|
-
if (!
|
|
9505
|
+
const accountFile = resolve14(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
|
|
9506
|
+
if (!existsSync16(accountFile)) return [];
|
|
9269
9507
|
let enabled;
|
|
9270
9508
|
try {
|
|
9271
|
-
const raw =
|
|
9509
|
+
const raw = readFileSync16(accountFile, "utf-8");
|
|
9272
9510
|
const parsed = JSON.parse(raw);
|
|
9273
9511
|
enabled = new Set(
|
|
9274
9512
|
Array.isArray(parsed.enabledPlugins) ? parsed.enabledPlugins.filter((p) => typeof p === "string") : []
|
|
@@ -9279,8 +9517,8 @@ function computeDormantPlugins(accountId) {
|
|
|
9279
9517
|
);
|
|
9280
9518
|
return [];
|
|
9281
9519
|
}
|
|
9282
|
-
const pluginsDir =
|
|
9283
|
-
if (!
|
|
9520
|
+
const pluginsDir = resolve14(PLATFORM_ROOT, "plugins");
|
|
9521
|
+
if (!existsSync16(pluginsDir)) return [];
|
|
9284
9522
|
let entries;
|
|
9285
9523
|
try {
|
|
9286
9524
|
entries = readdirSync9(pluginsDir);
|
|
@@ -9290,11 +9528,11 @@ function computeDormantPlugins(accountId) {
|
|
|
9290
9528
|
const out = [];
|
|
9291
9529
|
for (const name of entries) {
|
|
9292
9530
|
if (enabled.has(name)) continue;
|
|
9293
|
-
const manifestPath =
|
|
9294
|
-
if (!
|
|
9531
|
+
const manifestPath = resolve14(pluginsDir, name, "PLUGIN.md");
|
|
9532
|
+
if (!existsSync16(manifestPath)) continue;
|
|
9295
9533
|
let manifest;
|
|
9296
9534
|
try {
|
|
9297
|
-
manifest =
|
|
9535
|
+
manifest = readFileSync16(manifestPath, "utf-8");
|
|
9298
9536
|
} catch {
|
|
9299
9537
|
continue;
|
|
9300
9538
|
}
|
|
@@ -9308,13 +9546,13 @@ function computeDormantPlugins(accountId) {
|
|
|
9308
9546
|
}
|
|
9309
9547
|
|
|
9310
9548
|
// server/routes/admin/claude-sessions.ts
|
|
9311
|
-
import { existsSync as
|
|
9312
|
-
import { resolve as
|
|
9549
|
+
import { existsSync as existsSync17, readFileSync as readFileSync17 } from "fs";
|
|
9550
|
+
import { resolve as resolve15 } from "path";
|
|
9313
9551
|
function readTunnelState(brandConfigDir) {
|
|
9314
9552
|
const statePath = `${process.env.HOME ?? ""}/${brandConfigDir}/cloudflared/tunnel.state`;
|
|
9315
|
-
if (!
|
|
9553
|
+
if (!existsSync17(statePath)) return null;
|
|
9316
9554
|
try {
|
|
9317
|
-
const parsed = JSON.parse(
|
|
9555
|
+
const parsed = JSON.parse(readFileSync17(statePath, "utf-8"));
|
|
9318
9556
|
const tunnelId = typeof parsed.tunnelId === "string" ? parsed.tunnelId : null;
|
|
9319
9557
|
const tunnelName = typeof parsed.tunnelName === "string" ? parsed.tunnelName : null;
|
|
9320
9558
|
const domain = typeof parsed.domain === "string" ? parsed.domain : null;
|
|
@@ -9325,10 +9563,10 @@ function readTunnelState(brandConfigDir) {
|
|
|
9325
9563
|
}
|
|
9326
9564
|
}
|
|
9327
9565
|
function resolveTunnelUrl() {
|
|
9328
|
-
const platformRoot2 = process.env.MAXY_PLATFORM_ROOT ?? process.env.PLATFORM_ROOT ??
|
|
9566
|
+
const platformRoot2 = process.env.MAXY_PLATFORM_ROOT ?? process.env.PLATFORM_ROOT ?? resolve15(process.cwd(), "..");
|
|
9329
9567
|
let brand;
|
|
9330
9568
|
try {
|
|
9331
|
-
brand = JSON.parse(
|
|
9569
|
+
brand = JSON.parse(readFileSync17(resolve15(platformRoot2, "config", "brand.json"), "utf-8"));
|
|
9332
9570
|
} catch {
|
|
9333
9571
|
return null;
|
|
9334
9572
|
}
|
|
@@ -9339,7 +9577,7 @@ function resolveTunnelUrl() {
|
|
|
9339
9577
|
if (!state) return null;
|
|
9340
9578
|
return `https://${hostname2}.${state.domain}`;
|
|
9341
9579
|
}
|
|
9342
|
-
var
|
|
9580
|
+
var TAG22 = "[claude-session-manager:wrapper]";
|
|
9343
9581
|
async function refuseIfClaudeAuthDead(c, route, sessionId) {
|
|
9344
9582
|
const auth = await ensureAuth();
|
|
9345
9583
|
if (auth.status !== "dead" && auth.status !== "missing") return null;
|
|
@@ -9351,18 +9589,18 @@ async function refuseIfClaudeAuthDead(c, route, sessionId) {
|
|
|
9351
9589
|
503
|
|
9352
9590
|
);
|
|
9353
9591
|
}
|
|
9354
|
-
var
|
|
9592
|
+
var app15 = new Hono();
|
|
9355
9593
|
async function performSpawnWithInitialMessage(args) {
|
|
9356
9594
|
const ownerStart = Date.now();
|
|
9357
9595
|
const aboutOwner = await resolveOwnerProfileBlock(args.senderId, args.userId);
|
|
9358
9596
|
const ownerMs = Date.now() - ownerStart;
|
|
9359
9597
|
const aboutOwnerStatus = aboutOwner == null ? "absent" : "ok" in aboutOwner && aboutOwner.ok === false ? `unresolved:${aboutOwner.reason}` : "ok";
|
|
9360
|
-
console.log(`${
|
|
9598
|
+
console.log(`${TAG22} about-owner-resolved status=${aboutOwnerStatus} ms=${ownerMs}`);
|
|
9361
9599
|
const dormantPlugins = computeDormantPlugins(args.senderId);
|
|
9362
9600
|
const activePlugins = computeActivePlugins(args.senderId);
|
|
9363
9601
|
const specialistDomains = computeSpecialistDomains(args.senderId);
|
|
9364
9602
|
const tunnelUrl = resolveTunnelUrl();
|
|
9365
|
-
console.log(`${
|
|
9603
|
+
console.log(`${TAG22} tunnel-url-resolved value=${tunnelUrl ?? "null"}`);
|
|
9366
9604
|
const upstreamPayload = JSON.stringify({
|
|
9367
9605
|
senderId: args.senderId,
|
|
9368
9606
|
// Task 205 — pass userId through to the manager so it lands as
|
|
@@ -9389,24 +9627,24 @@ async function performSpawnWithInitialMessage(args) {
|
|
|
9389
9627
|
// unshapely values.
|
|
9390
9628
|
conversationNodeId: args.conversationNodeId
|
|
9391
9629
|
});
|
|
9392
|
-
console.log(`${
|
|
9630
|
+
console.log(`${TAG22} forward-spawn-start managerBase=${managerBase3("claude-session-manager:wrapper")} bytes=${upstreamPayload.length} hidden=${args.hidden} specialist=${args.specialist ?? "none"}`);
|
|
9393
9631
|
const forwardStart = Date.now();
|
|
9394
9632
|
const upstream = await fetch(`${managerBase3("claude-session-manager:wrapper")}/public-spawn`, {
|
|
9395
9633
|
method: "POST",
|
|
9396
9634
|
headers: { "content-type": "application/json" },
|
|
9397
9635
|
body: upstreamPayload
|
|
9398
9636
|
}).catch((err) => {
|
|
9399
|
-
console.error(`${
|
|
9637
|
+
console.error(`${TAG22} fetch-failed op=spawn message=${err instanceof Error ? err.message : String(err)} ms=${Date.now() - forwardStart}`);
|
|
9400
9638
|
return null;
|
|
9401
9639
|
});
|
|
9402
9640
|
if (!upstream) return {
|
|
9403
9641
|
response: new Response(JSON.stringify({ error: "manager-unreachable" }), { status: 503, headers: { "content-type": "application/json" } }),
|
|
9404
9642
|
claudeSessionId: null
|
|
9405
9643
|
};
|
|
9406
|
-
console.log(`${
|
|
9644
|
+
console.log(`${TAG22} forward-spawn-done status=${upstream.status} ms=${Date.now() - forwardStart}`);
|
|
9407
9645
|
if (args.initialMessage) {
|
|
9408
9646
|
const inputBytes = Buffer.byteLength(args.initialMessage, "utf8");
|
|
9409
|
-
console.log(`${
|
|
9647
|
+
console.log(`${TAG22} initial-message-inlined bytes=${inputBytes}`);
|
|
9410
9648
|
}
|
|
9411
9649
|
const bodyText = await upstream.text().catch(() => "");
|
|
9412
9650
|
let claudeSessionId = null;
|
|
@@ -9428,8 +9666,8 @@ function mintTranscriptEdge(sessionId, claudeSessionId, accountId) {
|
|
|
9428
9666
|
if (!sessionId || !claudeSessionId) return;
|
|
9429
9667
|
void linkConversationTranscript(sessionId, claudeSessionId, accountId);
|
|
9430
9668
|
}
|
|
9431
|
-
|
|
9432
|
-
|
|
9669
|
+
app15.use("*", requireAdminSession);
|
|
9670
|
+
app15.post("/", async (c) => {
|
|
9433
9671
|
const routeStart = Date.now();
|
|
9434
9672
|
const cacheKey = c.get("cacheKey") ?? "";
|
|
9435
9673
|
let body = {};
|
|
@@ -9441,7 +9679,7 @@ app14.post("/", async (c) => {
|
|
|
9441
9679
|
if (refusal) return refusal;
|
|
9442
9680
|
const senderId = getAccountIdForSession(cacheKey) ?? "";
|
|
9443
9681
|
if (!senderId) {
|
|
9444
|
-
console.error(`${
|
|
9682
|
+
console.error(`${TAG22} reject reason=no-account-id cacheKey-prefix=${cacheKey.slice(0, 8)}`);
|
|
9445
9683
|
return c.json({ error: "admin-account-not-resolved" }, 500);
|
|
9446
9684
|
}
|
|
9447
9685
|
const userId = getUserIdForSession(cacheKey) ?? void 0;
|
|
@@ -9450,7 +9688,7 @@ app14.post("/", async (c) => {
|
|
|
9450
9688
|
const permissionMode = typeof body.permissionMode === "string" ? body.permissionMode : void 0;
|
|
9451
9689
|
const specialist = typeof body.specialist === "string" && /^[A-Za-z0-9_-]{1,64}$/.test(body.specialist) ? body.specialist : void 0;
|
|
9452
9690
|
const model = typeof body.model === "string" && /^[A-Za-z0-9._-]{1,64}$/.test(body.model) ? body.model : void 0;
|
|
9453
|
-
console.log(`${
|
|
9691
|
+
console.log(`${TAG22} spawn-request-in surface=cookie accountId=${senderId.slice(0, 8)} userId=${userId ? userId.slice(0, 8) : "absent"} channel=${channel} permissionMode=${permissionMode ?? "default"} specialist=${specialist ?? "none"} model=${model ?? "default"} initialMessage=${initialMessage ? "yes" : "no"}`);
|
|
9454
9692
|
const conversationNodeId = cacheKey ? getSessionIdForSession(cacheKey) : void 0;
|
|
9455
9693
|
const { response, claudeSessionId } = await performSpawnWithInitialMessage({
|
|
9456
9694
|
senderId,
|
|
@@ -9469,24 +9707,24 @@ app14.post("/", async (c) => {
|
|
|
9469
9707
|
claudeSessionId,
|
|
9470
9708
|
senderId
|
|
9471
9709
|
);
|
|
9472
|
-
console.log(`${
|
|
9710
|
+
console.log(`${TAG22} route-done surface=cookie status=${response.status} route-ms=${Date.now() - routeStart}`);
|
|
9473
9711
|
return response;
|
|
9474
9712
|
});
|
|
9475
|
-
var claude_sessions_default =
|
|
9713
|
+
var claude_sessions_default = app15;
|
|
9476
9714
|
|
|
9477
9715
|
// server/routes/admin/log-ingest.ts
|
|
9478
|
-
var
|
|
9716
|
+
var TAG23 = "[log-ingest]";
|
|
9479
9717
|
var TAG_PATTERN = /^[A-Za-z0-9_:-]{1,32}$/;
|
|
9480
9718
|
var LEVELS = /* @__PURE__ */ new Set(["debug", "info", "warn", "error"]);
|
|
9481
9719
|
var MAX_LINE_BYTES = 4096;
|
|
9482
|
-
var
|
|
9720
|
+
var app16 = new Hono();
|
|
9483
9721
|
function isLoopbackAddr(addr) {
|
|
9484
9722
|
return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
|
|
9485
9723
|
}
|
|
9486
|
-
|
|
9724
|
+
app16.post("/", async (c) => {
|
|
9487
9725
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
9488
9726
|
if (!isLoopbackAddr(remoteAddr)) {
|
|
9489
|
-
console.error(`${
|
|
9727
|
+
console.error(`${TAG23} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
9490
9728
|
return c.json({ error: "log-ingest-loopback-only" }, 403);
|
|
9491
9729
|
}
|
|
9492
9730
|
const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
|
|
@@ -9495,7 +9733,7 @@ app15.post("/", async (c) => {
|
|
|
9495
9733
|
const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
|
|
9496
9734
|
const offender = tokens.find((t) => !isLoopbackAddr(t));
|
|
9497
9735
|
if (offender !== void 0) {
|
|
9498
|
-
console.error(`${
|
|
9736
|
+
console.error(`${TAG23} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
|
|
9499
9737
|
return c.json({ error: "log-ingest-loopback-only" }, 403);
|
|
9500
9738
|
}
|
|
9501
9739
|
}
|
|
@@ -9526,7 +9764,7 @@ app15.post("/", async (c) => {
|
|
|
9526
9764
|
else console.log(formatted);
|
|
9527
9765
|
return c.json({ ok: true }, 200);
|
|
9528
9766
|
});
|
|
9529
|
-
var log_ingest_default =
|
|
9767
|
+
var log_ingest_default = app16;
|
|
9530
9768
|
|
|
9531
9769
|
// server/routes/admin/events.ts
|
|
9532
9770
|
var ALLOWED_EVENTS = /* @__PURE__ */ new Set([
|
|
@@ -9535,20 +9773,20 @@ var ALLOWED_EVENTS = /* @__PURE__ */ new Set([
|
|
|
9535
9773
|
"device-url:vnc-surface-shown",
|
|
9536
9774
|
"device-url:malformed"
|
|
9537
9775
|
]);
|
|
9538
|
-
var
|
|
9539
|
-
|
|
9540
|
-
const
|
|
9776
|
+
var app17 = new Hono();
|
|
9777
|
+
app17.post("/", async (c) => {
|
|
9778
|
+
const TAG31 = "[admin:events]";
|
|
9541
9779
|
let body;
|
|
9542
9780
|
try {
|
|
9543
9781
|
body = await c.req.json();
|
|
9544
9782
|
} catch (err) {
|
|
9545
9783
|
const detail = err instanceof Error ? err.message : String(err);
|
|
9546
|
-
console.error(`${
|
|
9784
|
+
console.error(`${TAG31} reject reason=body-not-json detail=${detail}`);
|
|
9547
9785
|
return c.json({ ok: false, detail: "Request body was not valid JSON" }, 400);
|
|
9548
9786
|
}
|
|
9549
9787
|
const event = typeof body.event === "string" ? body.event : "";
|
|
9550
9788
|
if (!ALLOWED_EVENTS.has(event)) {
|
|
9551
|
-
console.error(`${
|
|
9789
|
+
console.error(`${TAG31} reject reason=event-not-allowed event=${JSON.stringify(event)}`);
|
|
9552
9790
|
return c.json({ ok: false, detail: `Event "${event}" is not allowed` }, 400);
|
|
9553
9791
|
}
|
|
9554
9792
|
const rawFields = body.fields && typeof body.fields === "object" ? body.fields : {};
|
|
@@ -9567,21 +9805,21 @@ app16.post("/", async (c) => {
|
|
|
9567
9805
|
console.error(`[${event}] ${formatted}`);
|
|
9568
9806
|
return c.json({ ok: true });
|
|
9569
9807
|
});
|
|
9570
|
-
var events_default =
|
|
9808
|
+
var events_default = app17;
|
|
9571
9809
|
|
|
9572
9810
|
// server/routes/admin/files.ts
|
|
9573
9811
|
import { createReadStream as createReadStream2 } from "fs";
|
|
9574
9812
|
import { readdir as readdir3, readFile as readFile4, stat as stat4, mkdir as mkdir3, writeFile as writeFile4, unlink as unlink2 } from "fs/promises";
|
|
9575
9813
|
import { realpathSync as realpathSync4 } from "fs";
|
|
9576
|
-
import { basename as basename5, dirname as dirname4, join as
|
|
9814
|
+
import { basename as basename5, dirname as dirname4, join as join16, resolve as resolve18, sep as sep5 } from "path";
|
|
9577
9815
|
import { Readable as Readable2 } from "stream";
|
|
9578
9816
|
|
|
9579
9817
|
// app/lib/data-path.ts
|
|
9580
9818
|
import { realpathSync as realpathSync3 } from "fs";
|
|
9581
|
-
import { resolve as
|
|
9582
|
-
var PLATFORM_ROOT5 = process.env.MAXY_PLATFORM_ROOT ??
|
|
9583
|
-
var DATA_ROOT =
|
|
9584
|
-
var CLAUDE_UPLOADS_ROOT = process.env.CLAUDE_CONFIG_DIR ?
|
|
9819
|
+
import { resolve as resolve16, normalize, sep as sep3, relative } from "path";
|
|
9820
|
+
var PLATFORM_ROOT5 = process.env.MAXY_PLATFORM_ROOT ?? resolve16(process.cwd(), "../platform");
|
|
9821
|
+
var DATA_ROOT = resolve16(PLATFORM_ROOT5, "..", "data");
|
|
9822
|
+
var CLAUDE_UPLOADS_ROOT = process.env.CLAUDE_CONFIG_DIR ? resolve16(process.env.CLAUDE_CONFIG_DIR, "uploads") : null;
|
|
9585
9823
|
var ACCOUNT_PARTITION_DIRS = /* @__PURE__ */ new Set(["uploads", "accounts"]);
|
|
9586
9824
|
var ACCOUNT_UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
9587
9825
|
function crossesForeignAccountPartition(relPath, accountId) {
|
|
@@ -9594,7 +9832,7 @@ function crossesForeignAccountPartition(relPath, accountId) {
|
|
|
9594
9832
|
}
|
|
9595
9833
|
function resolveUnderRoot(raw, rootAbs, rootLabel) {
|
|
9596
9834
|
const cleaned = normalize("/" + (raw ?? "").replace(/\\/g, "/")).replace(/^\/+/, "");
|
|
9597
|
-
const absolute =
|
|
9835
|
+
const absolute = resolve16(rootAbs, cleaned);
|
|
9598
9836
|
let rootReal;
|
|
9599
9837
|
try {
|
|
9600
9838
|
rootReal = realpathSync3(rootAbs);
|
|
@@ -9953,7 +10191,7 @@ async function cascadeDeleteDocument(params) {
|
|
|
9953
10191
|
|
|
9954
10192
|
// app/lib/file-index.ts
|
|
9955
10193
|
import * as fsp from "fs/promises";
|
|
9956
|
-
import { resolve as
|
|
10194
|
+
import { resolve as resolve17, relative as relative2, join as join15, basename as basename4, extname as extname2, sep as sep4 } from "path";
|
|
9957
10195
|
import { tmpdir as tmpdir2 } from "os";
|
|
9958
10196
|
import { execFile as execFile2 } from "child_process";
|
|
9959
10197
|
import { promisify as promisify2 } from "util";
|
|
@@ -10024,7 +10262,7 @@ async function extractPdf(absolute) {
|
|
|
10024
10262
|
return stdout.trim();
|
|
10025
10263
|
}
|
|
10026
10264
|
async function ocrPdf(absolute) {
|
|
10027
|
-
const outPdf =
|
|
10265
|
+
const outPdf = join15(tmpdir2(), `file-index-ocr-${process.pid}-${Date.now()}.pdf`);
|
|
10028
10266
|
try {
|
|
10029
10267
|
await execFileAsync2(
|
|
10030
10268
|
"ocrmypdf",
|
|
@@ -10086,7 +10324,7 @@ async function readDisplayName(absolute) {
|
|
|
10086
10324
|
const stem = dot === -1 ? base : base.slice(0, dot);
|
|
10087
10325
|
if (base === `${stem}.meta.json`) return null;
|
|
10088
10326
|
try {
|
|
10089
|
-
const raw = await fsp.readFile(
|
|
10327
|
+
const raw = await fsp.readFile(join15(dir, `${stem}.meta.json`), "utf-8");
|
|
10090
10328
|
const meta = JSON.parse(raw);
|
|
10091
10329
|
const dn = meta.displayName ?? meta.filename;
|
|
10092
10330
|
return typeof dn === "string" && dn.length > 0 ? dn : null;
|
|
@@ -10106,7 +10344,7 @@ async function walkSubtree(root, dataRoot, out) {
|
|
|
10106
10344
|
let clean = true;
|
|
10107
10345
|
for (const entry of entries) {
|
|
10108
10346
|
if (entry.isSymbolicLink()) continue;
|
|
10109
|
-
const abs =
|
|
10347
|
+
const abs = join15(root, entry.name);
|
|
10110
10348
|
if (entry.isDirectory()) {
|
|
10111
10349
|
const sub = await walkSubtree(abs, dataRoot, out);
|
|
10112
10350
|
if (!sub.clean) clean = false;
|
|
@@ -10261,8 +10499,8 @@ async function reconcileFileIndex(accountId, opts) {
|
|
|
10261
10499
|
return withSession(opts, async (session) => {
|
|
10262
10500
|
const walked = [];
|
|
10263
10501
|
const subtreeRoots = [
|
|
10264
|
-
|
|
10265
|
-
|
|
10502
|
+
resolve17(dataRoot, "uploads", accountId),
|
|
10503
|
+
resolve17(dataRoot, "accounts", accountId)
|
|
10266
10504
|
];
|
|
10267
10505
|
let clean = true;
|
|
10268
10506
|
for (const root of subtreeRoots) {
|
|
@@ -10343,7 +10581,7 @@ async function reconcileFileIndexDebounced(accountId, opts) {
|
|
|
10343
10581
|
async function indexFile(accountId, relativePath, opts) {
|
|
10344
10582
|
const dataRoot = opts?.dataRoot ?? DATA_ROOT;
|
|
10345
10583
|
const embed2 = opts?.embed ?? embed;
|
|
10346
|
-
const absolute =
|
|
10584
|
+
const absolute = resolve17(dataRoot, relativePath);
|
|
10347
10585
|
await withSession(opts, async (session) => {
|
|
10348
10586
|
const st = await fsp.stat(absolute);
|
|
10349
10587
|
const wf = {
|
|
@@ -10377,7 +10615,7 @@ async function dropFileIndex(accountId, relativePath, opts) {
|
|
|
10377
10615
|
var UUID_RE3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
10378
10616
|
async function readMeta(absDir, baseName) {
|
|
10379
10617
|
try {
|
|
10380
|
-
const raw = await readFile4(
|
|
10618
|
+
const raw = await readFile4(join16(absDir, `${baseName}.meta.json`), "utf8");
|
|
10381
10619
|
const parsed = JSON.parse(raw);
|
|
10382
10620
|
if (typeof parsed?.filename === "string") {
|
|
10383
10621
|
return { filename: parsed.filename, mimeType: typeof parsed.mimeType === "string" ? parsed.mimeType : void 0 };
|
|
@@ -10388,7 +10626,7 @@ async function readMeta(absDir, baseName) {
|
|
|
10388
10626
|
}
|
|
10389
10627
|
async function readAccountNames() {
|
|
10390
10628
|
const map = /* @__PURE__ */ new Map();
|
|
10391
|
-
const accountsDir =
|
|
10629
|
+
const accountsDir = resolve18(DATA_ROOT, "accounts");
|
|
10392
10630
|
let names;
|
|
10393
10631
|
try {
|
|
10394
10632
|
names = await readdir3(accountsDir);
|
|
@@ -10397,7 +10635,7 @@ async function readAccountNames() {
|
|
|
10397
10635
|
}
|
|
10398
10636
|
for (const name of names) {
|
|
10399
10637
|
if (!UUID_RE3.test(name)) continue;
|
|
10400
|
-
const configPath2 =
|
|
10638
|
+
const configPath2 = resolve18(accountsDir, name, "account.json");
|
|
10401
10639
|
try {
|
|
10402
10640
|
const raw = await readFile4(configPath2, "utf8");
|
|
10403
10641
|
const parsed = JSON.parse(raw);
|
|
@@ -10415,7 +10653,7 @@ async function readAccountNames() {
|
|
|
10415
10653
|
}
|
|
10416
10654
|
async function enrich(absolute, entry, accountNames) {
|
|
10417
10655
|
if (entry.kind === "directory" && UUID_RE3.test(entry.name)) {
|
|
10418
|
-
const meta = await readMeta(
|
|
10656
|
+
const meta = await readMeta(join16(absolute, entry.name), entry.name);
|
|
10419
10657
|
if (meta?.filename) {
|
|
10420
10658
|
entry.displayName = meta.filename;
|
|
10421
10659
|
entry.mimeType = meta.mimeType;
|
|
@@ -10475,8 +10713,8 @@ async function knowledgeDocOwnedByAccount(accountId, attachmentId) {
|
|
|
10475
10713
|
await session.close();
|
|
10476
10714
|
}
|
|
10477
10715
|
}
|
|
10478
|
-
var
|
|
10479
|
-
|
|
10716
|
+
var app18 = new Hono();
|
|
10717
|
+
app18.get("/", requireAdminSession, async (c) => {
|
|
10480
10718
|
const cacheKey = c.var.cacheKey;
|
|
10481
10719
|
const accountId = getAccountIdForSession(cacheKey);
|
|
10482
10720
|
if (!accountId) {
|
|
@@ -10513,7 +10751,7 @@ app17.get("/", requireAdminSession, async (c) => {
|
|
|
10513
10751
|
continue;
|
|
10514
10752
|
}
|
|
10515
10753
|
try {
|
|
10516
|
-
const entryPath =
|
|
10754
|
+
const entryPath = join16(absolute, name);
|
|
10517
10755
|
const s = await stat4(entryPath);
|
|
10518
10756
|
entries.push({
|
|
10519
10757
|
name,
|
|
@@ -10542,7 +10780,7 @@ app17.get("/", requireAdminSession, async (c) => {
|
|
|
10542
10780
|
return c.json({ error: message }, 500);
|
|
10543
10781
|
}
|
|
10544
10782
|
});
|
|
10545
|
-
|
|
10783
|
+
app18.get("/download", requireAdminSession, async (c) => {
|
|
10546
10784
|
const cacheKey = c.var.cacheKey;
|
|
10547
10785
|
const accountId = getAccountIdForSession(cacheKey);
|
|
10548
10786
|
if (!accountId) {
|
|
@@ -10606,7 +10844,7 @@ app17.get("/download", requireAdminSession, async (c) => {
|
|
|
10606
10844
|
return c.json({ error: message }, 500);
|
|
10607
10845
|
}
|
|
10608
10846
|
});
|
|
10609
|
-
|
|
10847
|
+
app18.post("/upload", requireAdminSession, async (c) => {
|
|
10610
10848
|
const cacheKey = c.var.cacheKey;
|
|
10611
10849
|
const accountId = getAccountIdForSession(cacheKey);
|
|
10612
10850
|
if (!accountId) {
|
|
@@ -10638,8 +10876,8 @@ app17.post("/upload", requireAdminSession, async (c) => {
|
|
|
10638
10876
|
}
|
|
10639
10877
|
const safeName = basename5(file.name).replace(/[\0/\\]/g, "_");
|
|
10640
10878
|
const finalName = `${Date.now()}-${safeName}`;
|
|
10641
|
-
const destDir =
|
|
10642
|
-
const destPath =
|
|
10879
|
+
const destDir = resolve18(DATA_ROOT, "uploads", accountId);
|
|
10880
|
+
const destPath = resolve18(destDir, finalName);
|
|
10643
10881
|
try {
|
|
10644
10882
|
await mkdir3(destDir, { recursive: true });
|
|
10645
10883
|
const dataRootReal = realpathSync4(DATA_ROOT);
|
|
@@ -10667,7 +10905,7 @@ app17.post("/upload", requireAdminSession, async (c) => {
|
|
|
10667
10905
|
mimeType: file.type
|
|
10668
10906
|
});
|
|
10669
10907
|
});
|
|
10670
|
-
|
|
10908
|
+
app18.delete("/", requireAdminSession, async (c) => {
|
|
10671
10909
|
const cacheKey = c.var.cacheKey;
|
|
10672
10910
|
const accountId = getAccountIdForSession(cacheKey);
|
|
10673
10911
|
if (!accountId) {
|
|
@@ -10704,7 +10942,7 @@ app17.delete("/", requireAdminSession, async (c) => {
|
|
|
10704
10942
|
}
|
|
10705
10943
|
const dot = base.lastIndexOf(".");
|
|
10706
10944
|
const stem = dot === -1 ? base : base.slice(0, dot);
|
|
10707
|
-
const sidecarPath = UUID_RE3.test(stem) && base !== `${stem}.meta.json` ?
|
|
10945
|
+
const sidecarPath = UUID_RE3.test(stem) && base !== `${stem}.meta.json` ? join16(dirname4(absolute), `${stem}.meta.json`) : null;
|
|
10708
10946
|
await unlink2(absolute);
|
|
10709
10947
|
if (sidecarPath) {
|
|
10710
10948
|
try {
|
|
@@ -10743,7 +10981,7 @@ app17.delete("/", requireAdminSession, async (c) => {
|
|
|
10743
10981
|
return c.json({ error: message }, 500);
|
|
10744
10982
|
}
|
|
10745
10983
|
});
|
|
10746
|
-
var files_default =
|
|
10984
|
+
var files_default = app18;
|
|
10747
10985
|
|
|
10748
10986
|
// ../lib/graph-search/src/index.ts
|
|
10749
10987
|
var import_dist = __toESM(require_dist());
|
|
@@ -11508,8 +11746,8 @@ var DEFAULT_LIMIT = 20;
|
|
|
11508
11746
|
var MAX_LIMIT = 2e3;
|
|
11509
11747
|
var MESSAGE_FAMILY_LABELS = ["Message", "UserMessage", "AssistantMessage", "WhatsAppMessage"];
|
|
11510
11748
|
var CONVERSATION_PARENT_LABELS = /* @__PURE__ */ new Set(["AdminConversation", "PublicConversation"]);
|
|
11511
|
-
var
|
|
11512
|
-
|
|
11749
|
+
var app19 = new Hono();
|
|
11750
|
+
app19.get("/", requireAdminSession, async (c) => {
|
|
11513
11751
|
const cacheKey = c.var.cacheKey;
|
|
11514
11752
|
const q = (c.req.query("q") ?? "").trim();
|
|
11515
11753
|
const rawLimit = c.req.query("limit");
|
|
@@ -11645,7 +11883,7 @@ app18.get("/", requireAdminSession, async (c) => {
|
|
|
11645
11883
|
await session.close();
|
|
11646
11884
|
}
|
|
11647
11885
|
});
|
|
11648
|
-
var graph_search_default =
|
|
11886
|
+
var graph_search_default = app19;
|
|
11649
11887
|
|
|
11650
11888
|
// server/routes/admin/graph-subgraph.ts
|
|
11651
11889
|
import neo4j from "neo4j-driver";
|
|
@@ -11723,8 +11961,8 @@ var STRIPPED_PROPERTIES = /* @__PURE__ */ new Set([
|
|
|
11723
11961
|
"otpCode",
|
|
11724
11962
|
"cacheKey"
|
|
11725
11963
|
]);
|
|
11726
|
-
var
|
|
11727
|
-
|
|
11964
|
+
var app20 = new Hono();
|
|
11965
|
+
app20.get("/", requireAdminSession, async (c) => {
|
|
11728
11966
|
const cacheKey = c.var.cacheKey;
|
|
11729
11967
|
const accountId = getAccountIdForSession(cacheKey);
|
|
11730
11968
|
if (!accountId) {
|
|
@@ -12307,12 +12545,12 @@ function pruneNode(node, warnedClasses, conversationWarnings) {
|
|
|
12307
12545
|
}
|
|
12308
12546
|
return trashed ? { id: node.id, labels, properties, trashed: true } : { id: node.id, labels, properties };
|
|
12309
12547
|
}
|
|
12310
|
-
var graph_subgraph_default =
|
|
12548
|
+
var graph_subgraph_default = app20;
|
|
12311
12549
|
|
|
12312
12550
|
// server/routes/admin/graph-delete.ts
|
|
12313
12551
|
var ALLOWED_BY = ["graph-page", "graph-drag-trash", "graph-side-panel-trash"];
|
|
12314
|
-
var
|
|
12315
|
-
|
|
12552
|
+
var app21 = new Hono();
|
|
12553
|
+
app21.post("/", requireAdminSession, async (c) => {
|
|
12316
12554
|
const cacheKey = c.var.cacheKey;
|
|
12317
12555
|
const accountId = getAccountIdForSession(cacheKey);
|
|
12318
12556
|
if (!accountId) {
|
|
@@ -12474,11 +12712,11 @@ app20.post("/", requireAdminSession, async (c) => {
|
|
|
12474
12712
|
}
|
|
12475
12713
|
}
|
|
12476
12714
|
});
|
|
12477
|
-
var graph_delete_default =
|
|
12715
|
+
var graph_delete_default = app21;
|
|
12478
12716
|
|
|
12479
12717
|
// server/routes/admin/graph-restore.ts
|
|
12480
|
-
var
|
|
12481
|
-
|
|
12718
|
+
var app22 = new Hono();
|
|
12719
|
+
app22.post("/", requireAdminSession, async (c) => {
|
|
12482
12720
|
const cacheKey = c.var.cacheKey;
|
|
12483
12721
|
const accountId = getAccountIdForSession(cacheKey);
|
|
12484
12722
|
if (!accountId) {
|
|
@@ -12542,11 +12780,11 @@ app21.post("/", requireAdminSession, async (c) => {
|
|
|
12542
12780
|
}
|
|
12543
12781
|
}
|
|
12544
12782
|
});
|
|
12545
|
-
var graph_restore_default =
|
|
12783
|
+
var graph_restore_default = app22;
|
|
12546
12784
|
|
|
12547
12785
|
// server/routes/admin/graph-labels-in-graph.ts
|
|
12548
|
-
var
|
|
12549
|
-
|
|
12786
|
+
var app23 = new Hono();
|
|
12787
|
+
app23.get("/", requireAdminSession, async (c) => {
|
|
12550
12788
|
const cacheKey = c.var.cacheKey;
|
|
12551
12789
|
const accountId = getAccountIdForSession(cacheKey);
|
|
12552
12790
|
if (!accountId) {
|
|
@@ -12612,11 +12850,11 @@ var LABELS_IN_GRAPH_CYPHER = `
|
|
|
12612
12850
|
sum(halfEdges) AS relDegree
|
|
12613
12851
|
RETURN label, nodeCount, relDegree
|
|
12614
12852
|
`;
|
|
12615
|
-
var graph_labels_in_graph_default =
|
|
12853
|
+
var graph_labels_in_graph_default = app23;
|
|
12616
12854
|
|
|
12617
12855
|
// server/routes/admin/graph-default-view.ts
|
|
12618
|
-
var
|
|
12619
|
-
|
|
12856
|
+
var app24 = new Hono();
|
|
12857
|
+
app24.get("/", requireAdminSession, async (c) => {
|
|
12620
12858
|
const cacheKey = c.var.cacheKey;
|
|
12621
12859
|
const accountId = getAccountIdForSession(cacheKey);
|
|
12622
12860
|
const userId = getUserIdForSession(cacheKey);
|
|
@@ -12654,7 +12892,7 @@ app23.get("/", requireAdminSession, async (c) => {
|
|
|
12654
12892
|
}
|
|
12655
12893
|
}
|
|
12656
12894
|
});
|
|
12657
|
-
|
|
12895
|
+
app24.put("/", requireAdminSession, async (c) => {
|
|
12658
12896
|
const cacheKey = c.var.cacheKey;
|
|
12659
12897
|
const accountId = getAccountIdForSession(cacheKey);
|
|
12660
12898
|
const userId = getUserIdForSession(cacheKey);
|
|
@@ -12743,20 +12981,20 @@ var WRITE_CYPHER = `
|
|
|
12743
12981
|
p.updatedAt = $updatedAt
|
|
12744
12982
|
RETURN p.labels AS labels
|
|
12745
12983
|
`;
|
|
12746
|
-
var graph_default_view_default =
|
|
12984
|
+
var graph_default_view_default = app24;
|
|
12747
12985
|
|
|
12748
12986
|
// server/routes/admin/sidebar-artefacts.ts
|
|
12749
12987
|
import { readdir as readdir4, stat as stat5 } from "fs/promises";
|
|
12750
|
-
import { resolve as
|
|
12751
|
-
import { existsSync as
|
|
12988
|
+
import { resolve as resolve19, relative as relative3, isAbsolute, sep as sep6, basename as basename6 } from "path";
|
|
12989
|
+
import { existsSync as existsSync18 } from "fs";
|
|
12752
12990
|
var LIMIT = 50;
|
|
12753
12991
|
var ADMIN_AGENT_FILES = ["IDENTITY.md", "SOUL.md", "KNOWLEDGE.md"];
|
|
12754
12992
|
function toDataRootRelPath(absPath) {
|
|
12755
12993
|
if (absPath !== DATA_ROOT && !absPath.startsWith(DATA_ROOT + sep6)) return null;
|
|
12756
12994
|
return relative3(DATA_ROOT, absPath);
|
|
12757
12995
|
}
|
|
12758
|
-
var
|
|
12759
|
-
|
|
12996
|
+
var app25 = new Hono();
|
|
12997
|
+
app25.get("/", requireAdminSession, async (c) => {
|
|
12760
12998
|
const cacheKey = c.var.cacheKey;
|
|
12761
12999
|
const accountId = getAccountIdForSession(cacheKey);
|
|
12762
13000
|
if (!accountId) {
|
|
@@ -12767,7 +13005,7 @@ app24.get("/", requireAdminSession, async (c) => {
|
|
|
12767
13005
|
if (accountFiles === null) {
|
|
12768
13006
|
return c.json({ error: "Failed to load artefacts" }, 500);
|
|
12769
13007
|
}
|
|
12770
|
-
const accountDir =
|
|
13008
|
+
const accountDir = resolve19(ACCOUNTS_DIR, accountId);
|
|
12771
13009
|
const agents = await fetchAgentTemplateRows(accountDir);
|
|
12772
13010
|
const artefacts = [...accountFiles, ...agents].sort(
|
|
12773
13011
|
(a, b) => (b.updatedAt ?? "").localeCompare(a.updatedAt ?? "")
|
|
@@ -12818,8 +13056,8 @@ async function fetchAccountFileArtefacts(accountId) {
|
|
|
12818
13056
|
async function fetchAgentTemplateRows(accountDir) {
|
|
12819
13057
|
const rows = [];
|
|
12820
13058
|
for (const filename of ADMIN_AGENT_FILES) {
|
|
12821
|
-
const overridePath =
|
|
12822
|
-
const bundledPath =
|
|
13059
|
+
const overridePath = resolve19(accountDir, "agents", "admin", filename);
|
|
13060
|
+
const bundledPath = resolve19(PLATFORM_ROOT, "templates", "agents", "admin", filename);
|
|
12823
13061
|
const labelStem = filename.replace(/\.md$/, "");
|
|
12824
13062
|
const row = await readAgentTemplateRow({
|
|
12825
13063
|
id: `agent-template:admin:${filename}`,
|
|
@@ -12832,12 +13070,12 @@ async function fetchAgentTemplateRows(accountDir) {
|
|
|
12832
13070
|
});
|
|
12833
13071
|
if (row) rows.push(row);
|
|
12834
13072
|
}
|
|
12835
|
-
const overrideDir =
|
|
12836
|
-
const bundledDir =
|
|
13073
|
+
const overrideDir = resolve19(accountDir, "specialists", "agents");
|
|
13074
|
+
const bundledDir = resolve19(PLATFORM_ROOT, "templates", "specialists", "agents");
|
|
12837
13075
|
const specialistNames = await unionSpecialistFilenames(overrideDir, bundledDir);
|
|
12838
13076
|
for (const filename of specialistNames) {
|
|
12839
|
-
const overridePath =
|
|
12840
|
-
const bundledPath =
|
|
13077
|
+
const overridePath = resolve19(overrideDir, filename);
|
|
13078
|
+
const bundledPath = resolve19(bundledDir, filename);
|
|
12841
13079
|
const row = await readAgentTemplateRow({
|
|
12842
13080
|
id: `agent-template:specialist:${filename}`,
|
|
12843
13081
|
displayName: filename.replace(/\.md$/, ""),
|
|
@@ -12854,7 +13092,7 @@ async function fetchAgentTemplateRows(accountDir) {
|
|
|
12854
13092
|
async function unionSpecialistFilenames(overrideDir, bundledDir) {
|
|
12855
13093
|
const names = /* @__PURE__ */ new Set();
|
|
12856
13094
|
for (const dir of [overrideDir, bundledDir]) {
|
|
12857
|
-
if (!
|
|
13095
|
+
if (!existsSync18(dir)) continue;
|
|
12858
13096
|
try {
|
|
12859
13097
|
const entries = await readdir4(dir);
|
|
12860
13098
|
for (const entry of entries) {
|
|
@@ -12869,7 +13107,7 @@ async function unionSpecialistFilenames(overrideDir, bundledDir) {
|
|
|
12869
13107
|
}
|
|
12870
13108
|
async function readAgentTemplateRow(inp) {
|
|
12871
13109
|
let chosenPath = null;
|
|
12872
|
-
if (
|
|
13110
|
+
if (existsSync18(inp.overridePath)) {
|
|
12873
13111
|
try {
|
|
12874
13112
|
validateFilePathInAccount(inp.overridePath, inp.overrideRoot);
|
|
12875
13113
|
chosenPath = inp.overridePath;
|
|
@@ -12880,7 +13118,7 @@ async function readAgentTemplateRow(inp) {
|
|
|
12880
13118
|
);
|
|
12881
13119
|
return null;
|
|
12882
13120
|
}
|
|
12883
|
-
} else if (
|
|
13121
|
+
} else if (existsSync18(inp.bundledPath)) {
|
|
12884
13122
|
if (!isWithin(inp.bundledPath, inp.bundledRoot)) {
|
|
12885
13123
|
console.error(
|
|
12886
13124
|
`[admin/sidebar-artefacts] agent-template-read-failed agent=${inp.displayName} kind=${inp.logName} error="bundled path outside PLATFORM_ROOT"`
|
|
@@ -12919,11 +13157,11 @@ function isWithin(target, root) {
|
|
|
12919
13157
|
const rel = relative3(root, target);
|
|
12920
13158
|
return !rel.startsWith("..") && !isAbsolute(rel);
|
|
12921
13159
|
}
|
|
12922
|
-
var sidebar_artefacts_default =
|
|
13160
|
+
var sidebar_artefacts_default = app25;
|
|
12923
13161
|
|
|
12924
13162
|
// server/routes/admin/session-delete.ts
|
|
12925
|
-
var
|
|
12926
|
-
|
|
13163
|
+
var app26 = new Hono();
|
|
13164
|
+
app26.post("/", requireAdminSession, async (c) => {
|
|
12927
13165
|
let body;
|
|
12928
13166
|
try {
|
|
12929
13167
|
body = await c.req.json();
|
|
@@ -12961,11 +13199,11 @@ app25.post("/", requireAdminSession, async (c) => {
|
|
|
12961
13199
|
console.error(`[session-delete] sessionId=${sessionId} delete-status=${del.status}`);
|
|
12962
13200
|
return c.json({ error: `manager-status-${del.status}` }, 502);
|
|
12963
13201
|
});
|
|
12964
|
-
var session_delete_default =
|
|
13202
|
+
var session_delete_default = app26;
|
|
12965
13203
|
|
|
12966
13204
|
// server/routes/admin/session-stop.ts
|
|
12967
|
-
var
|
|
12968
|
-
|
|
13205
|
+
var app27 = new Hono();
|
|
13206
|
+
app27.post("/", requireAdminSession, async (c) => {
|
|
12969
13207
|
let body;
|
|
12970
13208
|
try {
|
|
12971
13209
|
body = await c.req.json();
|
|
@@ -12990,11 +13228,63 @@ app26.post("/", requireAdminSession, async (c) => {
|
|
|
12990
13228
|
console.error(`[session-stop] sessionId=${sessionId} manager-status=${res.status}`);
|
|
12991
13229
|
return c.json({ error: `manager-status-${res.status}` }, 502);
|
|
12992
13230
|
});
|
|
12993
|
-
var session_stop_default =
|
|
13231
|
+
var session_stop_default = app27;
|
|
13232
|
+
|
|
13233
|
+
// server/routes/admin/session-archive.ts
|
|
13234
|
+
var app28 = new Hono();
|
|
13235
|
+
app28.post("/", requireAdminSession, async (c) => {
|
|
13236
|
+
let body;
|
|
13237
|
+
try {
|
|
13238
|
+
body = await c.req.json();
|
|
13239
|
+
} catch {
|
|
13240
|
+
return c.json({ error: "invalid JSON body" }, 400);
|
|
13241
|
+
}
|
|
13242
|
+
const sessionId = typeof body.sessionId === "string" ? body.sessionId : "";
|
|
13243
|
+
if (!SESSION_ID_RE2.test(sessionId)) {
|
|
13244
|
+
return c.json({ error: "sessionId must be a v4 UUID" }, 400);
|
|
13245
|
+
}
|
|
13246
|
+
const mode = body.mode;
|
|
13247
|
+
if (mode !== "archive" && mode !== "unarchive") {
|
|
13248
|
+
return c.json({ error: "mode must be 'archive' or 'unarchive'" }, 400);
|
|
13249
|
+
}
|
|
13250
|
+
let res;
|
|
13251
|
+
try {
|
|
13252
|
+
res = await fetch(`${managerBase3("session-archive:wrapper")}/${sessionId}/archive`, {
|
|
13253
|
+
method: "POST",
|
|
13254
|
+
headers: { "Content-Type": "application/json" },
|
|
13255
|
+
body: JSON.stringify({ mode })
|
|
13256
|
+
});
|
|
13257
|
+
} catch (err) {
|
|
13258
|
+
console.error(`[session-archive] sessionId=${sessionId} manager-unreachable err=${err instanceof Error ? err.message : String(err)}`);
|
|
13259
|
+
return c.json({ error: "manager-unreachable" }, 502);
|
|
13260
|
+
}
|
|
13261
|
+
if (res.status === 200) {
|
|
13262
|
+
const dir = mode === "archive" ? "top\u2192archive" : "archive\u2192top";
|
|
13263
|
+
console.log(`[session-archive] sessionId=${sessionId.slice(0, 8)} moved ${dir}`);
|
|
13264
|
+
return c.json({ archived: mode === "archive" });
|
|
13265
|
+
}
|
|
13266
|
+
if (res.status === 409) {
|
|
13267
|
+
console.error(`[session-archive] sessionId=${sessionId.slice(0, 8)} pty-still-alive`);
|
|
13268
|
+
return c.json({ error: "pty-still-alive", detail: "end the session before archiving" }, 409);
|
|
13269
|
+
}
|
|
13270
|
+
if (res.status === 404) {
|
|
13271
|
+
console.error(`[session-archive] sessionId=${sessionId.slice(0, 8)} session-not-found`);
|
|
13272
|
+
return c.json({ error: "session-not-found" }, 404);
|
|
13273
|
+
}
|
|
13274
|
+
if (res.status === 500) {
|
|
13275
|
+
const body2 = await res.json().catch(() => ({}));
|
|
13276
|
+
const detail = typeof body2.detail === "string" ? body2.detail : body2.error ?? "archive-failed";
|
|
13277
|
+
console.error(`[session-archive] sessionId=${sessionId.slice(0, 8)} archive-failed detail=${detail}`);
|
|
13278
|
+
return c.json({ error: "archive-failed", detail }, 502);
|
|
13279
|
+
}
|
|
13280
|
+
console.error(`[session-archive] sessionId=${sessionId.slice(0, 8)} manager-status=${res.status}`);
|
|
13281
|
+
return c.json({ error: `manager-status-${res.status}` }, 502);
|
|
13282
|
+
});
|
|
13283
|
+
var session_archive_default = app28;
|
|
12994
13284
|
|
|
12995
13285
|
// server/routes/admin/session-rc-spawn.ts
|
|
12996
|
-
var
|
|
12997
|
-
|
|
13286
|
+
var app29 = new Hono();
|
|
13287
|
+
app29.post("/", requireAdminSession, async (c) => {
|
|
12998
13288
|
let body;
|
|
12999
13289
|
try {
|
|
13000
13290
|
body = await c.req.json();
|
|
@@ -13028,7 +13318,7 @@ app27.post("/", requireAdminSession, async (c) => {
|
|
|
13028
13318
|
}
|
|
13029
13319
|
return c.json(parsed ?? {});
|
|
13030
13320
|
});
|
|
13031
|
-
var session_rc_spawn_default =
|
|
13321
|
+
var session_rc_spawn_default = app29;
|
|
13032
13322
|
|
|
13033
13323
|
// server/routes/admin/system-stats.ts
|
|
13034
13324
|
import { readFile as readFile5 } from "fs/promises";
|
|
@@ -13125,8 +13415,8 @@ async function sample() {
|
|
|
13125
13415
|
if (process.platform === "linux") return sampleLinux();
|
|
13126
13416
|
return sampleOsFallback();
|
|
13127
13417
|
}
|
|
13128
|
-
var
|
|
13129
|
-
|
|
13418
|
+
var app30 = new Hono();
|
|
13419
|
+
app30.get("/", async (c) => {
|
|
13130
13420
|
const started = Date.now();
|
|
13131
13421
|
if (!inflight) {
|
|
13132
13422
|
inflight = sample().finally(() => {
|
|
@@ -13149,27 +13439,27 @@ app28.get("/", async (c) => {
|
|
|
13149
13439
|
return c.json({ degraded: true, reason, sampledAtMs: Date.now() });
|
|
13150
13440
|
}
|
|
13151
13441
|
});
|
|
13152
|
-
var system_stats_default =
|
|
13442
|
+
var system_stats_default = app30;
|
|
13153
13443
|
|
|
13154
13444
|
// server/routes/admin/health.ts
|
|
13155
|
-
import { existsSync as
|
|
13156
|
-
import { resolve as
|
|
13157
|
-
var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ??
|
|
13445
|
+
import { existsSync as existsSync19, readFileSync as readFileSync18 } from "fs";
|
|
13446
|
+
import { resolve as resolve20, join as join17 } from "path";
|
|
13447
|
+
var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve20(process.cwd(), "..");
|
|
13158
13448
|
var brandHostname = "maxy";
|
|
13159
|
-
var brandJsonPath =
|
|
13160
|
-
if (
|
|
13449
|
+
var brandJsonPath = join17(PLATFORM_ROOT6, "config", "brand.json");
|
|
13450
|
+
if (existsSync19(brandJsonPath)) {
|
|
13161
13451
|
try {
|
|
13162
|
-
const brand = JSON.parse(
|
|
13452
|
+
const brand = JSON.parse(readFileSync18(brandJsonPath, "utf-8"));
|
|
13163
13453
|
if (brand.hostname) brandHostname = brand.hostname;
|
|
13164
13454
|
} catch {
|
|
13165
13455
|
}
|
|
13166
13456
|
}
|
|
13167
|
-
var VERSION_FILE =
|
|
13457
|
+
var VERSION_FILE = resolve20(PLATFORM_ROOT6, `config/.${brandHostname}-version`);
|
|
13168
13458
|
var PROCESS_STARTED_AT = (/* @__PURE__ */ new Date()).toISOString();
|
|
13169
13459
|
var PROBE_TIMEOUT_MS = 1e3;
|
|
13170
13460
|
function readVersion() {
|
|
13171
|
-
if (!
|
|
13172
|
-
return
|
|
13461
|
+
if (!existsSync19(VERSION_FILE)) return "unknown";
|
|
13462
|
+
return readFileSync18(VERSION_FILE, "utf-8").trim() || "unknown";
|
|
13173
13463
|
}
|
|
13174
13464
|
async function probeConversationDb() {
|
|
13175
13465
|
let session;
|
|
@@ -13194,8 +13484,8 @@ async function probeConversationDb() {
|
|
|
13194
13484
|
});
|
|
13195
13485
|
}
|
|
13196
13486
|
}
|
|
13197
|
-
var
|
|
13198
|
-
|
|
13487
|
+
var app31 = new Hono();
|
|
13488
|
+
app31.get("/", async (c) => {
|
|
13199
13489
|
const version = readVersion();
|
|
13200
13490
|
const probe = await probeConversationDb();
|
|
13201
13491
|
const uptimeMs = Date.now() - new Date(PROCESS_STARTED_AT).getTime();
|
|
@@ -13217,11 +13507,11 @@ app29.get("/", async (c) => {
|
|
|
13217
13507
|
uptimeMs
|
|
13218
13508
|
});
|
|
13219
13509
|
});
|
|
13220
|
-
var health_default2 =
|
|
13510
|
+
var health_default2 = app31;
|
|
13221
13511
|
|
|
13222
13512
|
// server/routes/admin/linkedin-ingest.ts
|
|
13223
13513
|
import { randomUUID as randomUUID9 } from "crypto";
|
|
13224
|
-
var
|
|
13514
|
+
var TAG24 = "[linkedin-ingest-route]";
|
|
13225
13515
|
var UUID = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
|
|
13226
13516
|
var ISO = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,3})?(?:Z|[+-]\d{2}:\d{2})$/;
|
|
13227
13517
|
var LINKEDIN_URL = /^https:\/\/www\.linkedin\.com\//;
|
|
@@ -13319,35 +13609,35 @@ function buildInitialMessage(env) {
|
|
|
13319
13609
|
}
|
|
13320
13610
|
return header;
|
|
13321
13611
|
}
|
|
13322
|
-
var
|
|
13323
|
-
|
|
13612
|
+
var app32 = new Hono();
|
|
13613
|
+
app32.post("/", requireAdminSession, async (c) => {
|
|
13324
13614
|
let body;
|
|
13325
13615
|
try {
|
|
13326
13616
|
body = await c.req.json();
|
|
13327
13617
|
} catch {
|
|
13328
|
-
console.error(
|
|
13618
|
+
console.error(TAG24 + " rejected status=400 reason=schema:body-not-json");
|
|
13329
13619
|
return c.json({ ok: false, error: "schema", reason: "body-not-json" }, 400);
|
|
13330
13620
|
}
|
|
13331
13621
|
const v = validate(body);
|
|
13332
13622
|
if (!v.ok) {
|
|
13333
|
-
console.error(
|
|
13623
|
+
console.error(TAG24 + " rejected status=" + v.status + " reason=" + v.reason + " missing=" + v.missing.join(","));
|
|
13334
13624
|
return c.json({ ok: false, error: v.error, reason: v.reason, missing: v.missing }, v.status);
|
|
13335
13625
|
}
|
|
13336
13626
|
const envelope = v.envelope;
|
|
13337
13627
|
const cacheKey = c.var.cacheKey ?? "";
|
|
13338
13628
|
const senderId = getAccountIdForSession(cacheKey) ?? "";
|
|
13339
13629
|
if (!senderId) {
|
|
13340
|
-
console.error(
|
|
13630
|
+
console.error(TAG24 + " rejected status=500 reason=admin-account-not-resolved");
|
|
13341
13631
|
return c.json({ ok: false, error: "admin-account-not-resolved" }, 500);
|
|
13342
13632
|
}
|
|
13343
13633
|
const payloadBytes = JSON.stringify(envelope).length;
|
|
13344
13634
|
console.log(
|
|
13345
|
-
|
|
13635
|
+
TAG24 + " received kind=" + envelope.kind + " account=" + senderId.slice(0, 8) + " pageUrl=" + envelope.pageUrl + " dispatchId=" + envelope.dispatchId + " payloadBytes=" + payloadBytes
|
|
13346
13636
|
);
|
|
13347
13637
|
const initialMessage = buildInitialMessage(envelope);
|
|
13348
13638
|
const spawnStart = Date.now();
|
|
13349
13639
|
const sessionId = randomUUID9();
|
|
13350
|
-
console.log(
|
|
13640
|
+
console.log(TAG24 + " route target=rc-spawn dispatchId=" + envelope.dispatchId + " sessionId=" + sessionId.slice(0, 8));
|
|
13351
13641
|
const spawned = await managerRcSpawn({
|
|
13352
13642
|
sessionId,
|
|
13353
13643
|
initialMessage,
|
|
@@ -13356,20 +13646,20 @@ app30.post("/", requireAdminSession, async (c) => {
|
|
|
13356
13646
|
});
|
|
13357
13647
|
if ("error" in spawned) {
|
|
13358
13648
|
console.error(
|
|
13359
|
-
|
|
13649
|
+
TAG24 + " dispatch-failed dispatchId=" + envelope.dispatchId + " status=" + spawned.status + " ms=" + (Date.now() - spawnStart) + " message=" + spawned.error
|
|
13360
13650
|
);
|
|
13361
13651
|
return c.json({ ok: false, error: "dispatch-failed", upstreamStatus: spawned.status, detail: spawned.error }, 502);
|
|
13362
13652
|
}
|
|
13363
13653
|
console.log(
|
|
13364
|
-
|
|
13654
|
+
TAG24 + " dispatched dispatchId=" + envelope.dispatchId + " taskId=" + spawned.sessionId + " ms=" + (Date.now() - spawnStart)
|
|
13365
13655
|
);
|
|
13366
13656
|
return c.json({ ok: true, dispatchId: envelope.dispatchId, taskId: spawned.sessionId }, 202);
|
|
13367
13657
|
});
|
|
13368
|
-
var linkedin_ingest_default =
|
|
13658
|
+
var linkedin_ingest_default = app32;
|
|
13369
13659
|
|
|
13370
13660
|
// server/routes/admin/post-turn-context.ts
|
|
13371
13661
|
import neo4j2 from "neo4j-driver";
|
|
13372
|
-
var
|
|
13662
|
+
var TAG25 = "[post-turn-context]";
|
|
13373
13663
|
var STRIPPED_PROPERTIES2 = /* @__PURE__ */ new Set([
|
|
13374
13664
|
"embedding",
|
|
13375
13665
|
"passwordHash",
|
|
@@ -13407,11 +13697,11 @@ function pruneProperties(raw) {
|
|
|
13407
13697
|
}
|
|
13408
13698
|
return out;
|
|
13409
13699
|
}
|
|
13410
|
-
var
|
|
13411
|
-
|
|
13700
|
+
var app33 = new Hono();
|
|
13701
|
+
app33.get("/", async (c) => {
|
|
13412
13702
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
13413
13703
|
if (!isLoopbackAddr2(remoteAddr)) {
|
|
13414
|
-
console.error(`${
|
|
13704
|
+
console.error(`${TAG25} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
13415
13705
|
return c.json({ error: "post-turn-context-loopback-only" }, 403);
|
|
13416
13706
|
}
|
|
13417
13707
|
const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
|
|
@@ -13420,7 +13710,7 @@ app31.get("/", async (c) => {
|
|
|
13420
13710
|
const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
|
|
13421
13711
|
const offender = tokens.find((t) => !isLoopbackAddr2(t));
|
|
13422
13712
|
if (offender !== void 0) {
|
|
13423
|
-
console.error(`${
|
|
13713
|
+
console.error(`${TAG25} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
|
|
13424
13714
|
return c.json({ error: "post-turn-context-loopback-only" }, 403);
|
|
13425
13715
|
}
|
|
13426
13716
|
}
|
|
@@ -13452,7 +13742,7 @@ app31.get("/", async (c) => {
|
|
|
13452
13742
|
writes.sort((a, b) => a.sortKey.localeCompare(b.sortKey));
|
|
13453
13743
|
const total = Date.now() - started;
|
|
13454
13744
|
console.log(
|
|
13455
|
-
`${
|
|
13745
|
+
`${TAG25} sessionId=${sessionId} accountId=${accountId} writes=${writes.length} ms=${total}`
|
|
13456
13746
|
);
|
|
13457
13747
|
return c.json({
|
|
13458
13748
|
writes: writes.map(({ elementId, labels, properties }) => ({ elementId, labels, properties }))
|
|
@@ -13461,18 +13751,18 @@ app31.get("/", async (c) => {
|
|
|
13461
13751
|
const elapsed = Date.now() - started;
|
|
13462
13752
|
const message = err instanceof Error ? err.message : String(err);
|
|
13463
13753
|
console.error(
|
|
13464
|
-
`${
|
|
13754
|
+
`${TAG25} neo4j-unreachable sessionId=${sessionId} ms=${elapsed} err="${message}"`
|
|
13465
13755
|
);
|
|
13466
13756
|
return c.json({ error: `post-turn-context unavailable: ${message}` }, 503);
|
|
13467
13757
|
} finally {
|
|
13468
13758
|
await session.close();
|
|
13469
13759
|
}
|
|
13470
13760
|
});
|
|
13471
|
-
var post_turn_context_default =
|
|
13761
|
+
var post_turn_context_default = app33;
|
|
13472
13762
|
|
|
13473
13763
|
// server/routes/admin/public-session-context.ts
|
|
13474
13764
|
import neo4j3 from "neo4j-driver";
|
|
13475
|
-
var
|
|
13765
|
+
var TAG26 = "[public-session-context]";
|
|
13476
13766
|
var STRIPPED_PROPERTIES3 = /* @__PURE__ */ new Set([
|
|
13477
13767
|
"embedding",
|
|
13478
13768
|
"passwordHash",
|
|
@@ -13510,11 +13800,11 @@ function pruneProperties2(raw) {
|
|
|
13510
13800
|
}
|
|
13511
13801
|
return out;
|
|
13512
13802
|
}
|
|
13513
|
-
var
|
|
13514
|
-
|
|
13803
|
+
var app34 = new Hono();
|
|
13804
|
+
app34.get("/", async (c) => {
|
|
13515
13805
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
13516
13806
|
if (!isLoopbackAddr3(remoteAddr)) {
|
|
13517
|
-
console.error(`${
|
|
13807
|
+
console.error(`${TAG26} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
13518
13808
|
return c.json({ error: "public-session-context-loopback-only" }, 403);
|
|
13519
13809
|
}
|
|
13520
13810
|
const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
|
|
@@ -13523,7 +13813,7 @@ app32.get("/", async (c) => {
|
|
|
13523
13813
|
const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
|
|
13524
13814
|
const offender = tokens.find((t) => !isLoopbackAddr3(t));
|
|
13525
13815
|
if (offender !== void 0) {
|
|
13526
|
-
console.error(`${
|
|
13816
|
+
console.error(`${TAG26} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
|
|
13527
13817
|
return c.json({ error: "public-session-context-loopback-only" }, 403);
|
|
13528
13818
|
}
|
|
13529
13819
|
}
|
|
@@ -13554,7 +13844,7 @@ app32.get("/", async (c) => {
|
|
|
13554
13844
|
writes.sort((a, b) => a.sortKey.localeCompare(b.sortKey));
|
|
13555
13845
|
const total = Date.now() - started;
|
|
13556
13846
|
console.log(
|
|
13557
|
-
`${
|
|
13847
|
+
`${TAG26} sliceToken=${sliceToken.slice(0, 8)} writes=${writes.length} ms=${total}`
|
|
13558
13848
|
);
|
|
13559
13849
|
return c.json({
|
|
13560
13850
|
writes: writes.map(({ elementId, labels, properties }) => ({ elementId, labels, properties }))
|
|
@@ -13563,25 +13853,25 @@ app32.get("/", async (c) => {
|
|
|
13563
13853
|
const elapsed = Date.now() - started;
|
|
13564
13854
|
const message = err instanceof Error ? err.message : String(err);
|
|
13565
13855
|
console.error(
|
|
13566
|
-
`${
|
|
13856
|
+
`${TAG26} neo4j-unreachable sliceToken=${sliceToken.slice(0, 8)} ms=${elapsed} err="${message}"`
|
|
13567
13857
|
);
|
|
13568
13858
|
return c.json({ error: `public-session-context unavailable: ${message}` }, 503);
|
|
13569
13859
|
} finally {
|
|
13570
13860
|
await session.close();
|
|
13571
13861
|
}
|
|
13572
13862
|
});
|
|
13573
|
-
var public_session_context_default =
|
|
13863
|
+
var public_session_context_default = app34;
|
|
13574
13864
|
|
|
13575
13865
|
// server/routes/admin/public-session-exit.ts
|
|
13576
|
-
var
|
|
13866
|
+
var TAG27 = "[public-session-exit-route]";
|
|
13577
13867
|
function isLoopbackAddr4(addr) {
|
|
13578
13868
|
return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
|
|
13579
13869
|
}
|
|
13580
|
-
var
|
|
13581
|
-
|
|
13870
|
+
var app35 = new Hono();
|
|
13871
|
+
app35.post("/", async (c) => {
|
|
13582
13872
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
13583
13873
|
if (!isLoopbackAddr4(remoteAddr)) {
|
|
13584
|
-
console.error(`${
|
|
13874
|
+
console.error(`${TAG27} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
13585
13875
|
return c.json({ error: "public-session-exit-loopback-only" }, 403);
|
|
13586
13876
|
}
|
|
13587
13877
|
const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
|
|
@@ -13590,7 +13880,7 @@ app33.post("/", async (c) => {
|
|
|
13590
13880
|
const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
|
|
13591
13881
|
const offender = tokens.find((t) => !isLoopbackAddr4(t));
|
|
13592
13882
|
if (offender !== void 0) {
|
|
13593
|
-
console.error(`${
|
|
13883
|
+
console.error(`${TAG27} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
|
|
13594
13884
|
return c.json({ error: "public-session-exit-loopback-only" }, 403);
|
|
13595
13885
|
}
|
|
13596
13886
|
}
|
|
@@ -13605,18 +13895,18 @@ app33.post("/", async (c) => {
|
|
|
13605
13895
|
handlePublicSessionExit(sessionId);
|
|
13606
13896
|
return c.json({ ok: true });
|
|
13607
13897
|
});
|
|
13608
|
-
var public_session_exit_default =
|
|
13898
|
+
var public_session_exit_default = app35;
|
|
13609
13899
|
|
|
13610
13900
|
// server/routes/admin/access-session-evict.ts
|
|
13611
|
-
var
|
|
13901
|
+
var TAG28 = "[access-session-evict]";
|
|
13612
13902
|
function isLoopbackAddr5(addr) {
|
|
13613
13903
|
return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
|
|
13614
13904
|
}
|
|
13615
|
-
var
|
|
13616
|
-
|
|
13905
|
+
var app36 = new Hono();
|
|
13906
|
+
app36.post("/", async (c) => {
|
|
13617
13907
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
13618
13908
|
if (!isLoopbackAddr5(remoteAddr)) {
|
|
13619
|
-
console.error(`${
|
|
13909
|
+
console.error(`${TAG28} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
13620
13910
|
return c.json({ error: "access-session-evict-loopback-only" }, 403);
|
|
13621
13911
|
}
|
|
13622
13912
|
const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
|
|
@@ -13625,7 +13915,7 @@ app34.post("/", async (c) => {
|
|
|
13625
13915
|
const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
|
|
13626
13916
|
const offender = tokens.find((t) => !isLoopbackAddr5(t));
|
|
13627
13917
|
if (offender !== void 0) {
|
|
13628
|
-
console.error(`${
|
|
13918
|
+
console.error(`${TAG28} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
|
|
13629
13919
|
return c.json({ error: "access-session-evict-loopback-only" }, 403);
|
|
13630
13920
|
}
|
|
13631
13921
|
}
|
|
@@ -13638,14 +13928,14 @@ app34.post("/", async (c) => {
|
|
|
13638
13928
|
const grantId = typeof body.grantId === "string" ? body.grantId.trim() : "";
|
|
13639
13929
|
if (!grantId) return c.json({ error: "grantId required" }, 400);
|
|
13640
13930
|
const dropped = evictAccessSessionsByGrant(grantId);
|
|
13641
|
-
console.log(`${
|
|
13931
|
+
console.log(`${TAG28} grantId=${grantId} dropped=${dropped}`);
|
|
13642
13932
|
return c.json({ ok: true, dropped });
|
|
13643
13933
|
});
|
|
13644
|
-
var access_session_evict_default =
|
|
13934
|
+
var access_session_evict_default = app36;
|
|
13645
13935
|
|
|
13646
13936
|
// server/routes/admin/browser.ts
|
|
13647
|
-
var
|
|
13648
|
-
|
|
13937
|
+
var app37 = new Hono();
|
|
13938
|
+
app37.post("/launch", requireAdminSession, async (c) => {
|
|
13649
13939
|
try {
|
|
13650
13940
|
const transport = resolveBrowserTransport(c.req.raw, c.env?.incoming?.socket?.remoteAddress);
|
|
13651
13941
|
console.error(`[admin/browser/launch] op=request transport=${transport}`);
|
|
@@ -13673,53 +13963,54 @@ app35.post("/launch", requireAdminSession, async (c) => {
|
|
|
13673
13963
|
);
|
|
13674
13964
|
}
|
|
13675
13965
|
});
|
|
13676
|
-
var browser_default =
|
|
13966
|
+
var browser_default = app37;
|
|
13677
13967
|
|
|
13678
13968
|
// server/routes/admin/index.ts
|
|
13679
|
-
var
|
|
13680
|
-
|
|
13681
|
-
|
|
13682
|
-
|
|
13683
|
-
|
|
13684
|
-
|
|
13685
|
-
|
|
13686
|
-
|
|
13687
|
-
|
|
13688
|
-
|
|
13689
|
-
|
|
13690
|
-
|
|
13691
|
-
|
|
13692
|
-
|
|
13693
|
-
|
|
13694
|
-
|
|
13695
|
-
|
|
13696
|
-
|
|
13697
|
-
|
|
13698
|
-
|
|
13699
|
-
|
|
13700
|
-
|
|
13701
|
-
|
|
13702
|
-
|
|
13703
|
-
|
|
13704
|
-
|
|
13705
|
-
|
|
13706
|
-
|
|
13707
|
-
|
|
13708
|
-
|
|
13709
|
-
|
|
13969
|
+
var app38 = new Hono();
|
|
13970
|
+
app38.route("/session", session_default);
|
|
13971
|
+
app38.route("/logs", logs_default);
|
|
13972
|
+
app38.route("/claude-info", claude_info_default);
|
|
13973
|
+
app38.route("/attachment", attachment_default);
|
|
13974
|
+
app38.route("/agents", agents_default);
|
|
13975
|
+
app38.route("/sessions", sessions_default);
|
|
13976
|
+
app38.route("/claude-sessions", claude_sessions_default);
|
|
13977
|
+
app38.route("/log-ingest", log_ingest_default);
|
|
13978
|
+
app38.route("/events", events_default);
|
|
13979
|
+
app38.route("/files", files_default);
|
|
13980
|
+
app38.route("/graph-search", graph_search_default);
|
|
13981
|
+
app38.route("/graph-subgraph", graph_subgraph_default);
|
|
13982
|
+
app38.route("/graph-delete", graph_delete_default);
|
|
13983
|
+
app38.route("/graph-restore", graph_restore_default);
|
|
13984
|
+
app38.route("/graph-labels-in-graph", graph_labels_in_graph_default);
|
|
13985
|
+
app38.route("/graph-default-view", graph_default_view_default);
|
|
13986
|
+
app38.route("/sidebar-artefacts", sidebar_artefacts_default);
|
|
13987
|
+
app38.route("/sidebar-sessions", sidebar_sessions_default);
|
|
13988
|
+
app38.route("/session-delete", session_delete_default);
|
|
13989
|
+
app38.route("/session-stop", session_stop_default);
|
|
13990
|
+
app38.route("/session-archive", session_archive_default);
|
|
13991
|
+
app38.route("/browser", browser_default);
|
|
13992
|
+
app38.route("/session-rc-spawn", session_rc_spawn_default);
|
|
13993
|
+
app38.route("/system-stats", system_stats_default);
|
|
13994
|
+
app38.route("/health-brand", health_default2);
|
|
13995
|
+
app38.route("/linkedin-ingest", linkedin_ingest_default);
|
|
13996
|
+
app38.route("/post-turn-context", post_turn_context_default);
|
|
13997
|
+
app38.route("/public-session-context", public_session_context_default);
|
|
13998
|
+
app38.route("/public-session-exit", public_session_exit_default);
|
|
13999
|
+
app38.route("/access-session-evict", access_session_evict_default);
|
|
14000
|
+
var admin_default = app38;
|
|
13710
14001
|
|
|
13711
14002
|
// app/lib/access-gate.ts
|
|
13712
14003
|
import neo4j4 from "neo4j-driver";
|
|
13713
|
-
import { readFileSync as
|
|
13714
|
-
import { resolve as
|
|
14004
|
+
import { readFileSync as readFileSync19 } from "fs";
|
|
14005
|
+
import { resolve as resolve21 } from "path";
|
|
13715
14006
|
import { randomUUID as randomUUID10 } from "crypto";
|
|
13716
|
-
var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT ??
|
|
14007
|
+
var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT ?? resolve21(process.cwd(), "..");
|
|
13717
14008
|
var driver = null;
|
|
13718
14009
|
function readPassword() {
|
|
13719
14010
|
if (process.env.NEO4J_PASSWORD) return process.env.NEO4J_PASSWORD;
|
|
13720
|
-
const passwordFile =
|
|
14011
|
+
const passwordFile = resolve21(PLATFORM_ROOT7, "config/.neo4j-password");
|
|
13721
14012
|
try {
|
|
13722
|
-
return
|
|
14013
|
+
return readFileSync19(passwordFile, "utf-8").trim();
|
|
13723
14014
|
} catch {
|
|
13724
14015
|
throw new Error(
|
|
13725
14016
|
`Neo4j password not found. Expected at ${passwordFile} or in NEO4J_PASSWORD env var.`
|
|
@@ -13917,11 +14208,11 @@ async function generateNewMagicToken(grantId) {
|
|
|
13917
14208
|
}
|
|
13918
14209
|
|
|
13919
14210
|
// server/routes/access/verify-token.ts
|
|
13920
|
-
var
|
|
14211
|
+
var TAG29 = "[access-verify]";
|
|
13921
14212
|
var MINT_TAG = "[access-session-mint]";
|
|
13922
14213
|
var COOKIE_NAME = "__access_session";
|
|
13923
|
-
var
|
|
13924
|
-
|
|
14214
|
+
var app39 = new Hono();
|
|
14215
|
+
app39.post("/", async (c) => {
|
|
13925
14216
|
const ip = c.var.clientIp || "unknown";
|
|
13926
14217
|
let body;
|
|
13927
14218
|
try {
|
|
@@ -13936,39 +14227,39 @@ app37.post("/", async (c) => {
|
|
|
13936
14227
|
}
|
|
13937
14228
|
const rateMsg = checkAccessRateLimit(ip, agentSlug);
|
|
13938
14229
|
if (rateMsg) {
|
|
13939
|
-
console.error(`${
|
|
14230
|
+
console.error(`${TAG29} grantId=- agentSlug=${agentSlug} result=rate-limited ip=${ip}`);
|
|
13940
14231
|
return c.json({ error: rateMsg }, 429);
|
|
13941
14232
|
}
|
|
13942
14233
|
const grant = await findGrantByMagicToken(token);
|
|
13943
14234
|
if (!grant) {
|
|
13944
14235
|
recordAccessFailedAttempt(ip, agentSlug);
|
|
13945
|
-
console.error(`${
|
|
14236
|
+
console.error(`${TAG29} grantId=- agentSlug=${agentSlug} result=notfound ip=${ip}`);
|
|
13946
14237
|
return c.json({ error: "invalid-or-expired-link" }, 401);
|
|
13947
14238
|
}
|
|
13948
14239
|
if (grant.agentSlug !== agentSlug) {
|
|
13949
14240
|
recordAccessFailedAttempt(ip, agentSlug);
|
|
13950
14241
|
console.error(
|
|
13951
|
-
`${
|
|
14242
|
+
`${TAG29} grantId=${grant.grantId} agentSlug=${agentSlug} result=agent-mismatch grantAgent=${grant.agentSlug} ip=${ip}`
|
|
13952
14243
|
);
|
|
13953
14244
|
return c.json({ error: "invalid-or-expired-link" }, 401);
|
|
13954
14245
|
}
|
|
13955
14246
|
if (grant.status === "expired" || grant.status === "revoked") {
|
|
13956
14247
|
recordAccessFailedAttempt(ip, agentSlug);
|
|
13957
14248
|
console.error(
|
|
13958
|
-
`${
|
|
14249
|
+
`${TAG29} grantId=${grant.grantId} agentSlug=${agentSlug} result=expired status=${grant.status} ip=${ip}`
|
|
13959
14250
|
);
|
|
13960
14251
|
return c.json({ error: "access-no-longer-valid" }, 401);
|
|
13961
14252
|
}
|
|
13962
14253
|
if (grant.expiresAt !== null && grant.expiresAt < Date.now()) {
|
|
13963
14254
|
recordAccessFailedAttempt(ip, agentSlug);
|
|
13964
14255
|
console.error(
|
|
13965
|
-
`${
|
|
14256
|
+
`${TAG29} grantId=${grant.grantId} agentSlug=${agentSlug} result=expired reason=expiresAt-past ip=${ip}`
|
|
13966
14257
|
);
|
|
13967
14258
|
return c.json({ error: "access-no-longer-valid" }, 401);
|
|
13968
14259
|
}
|
|
13969
14260
|
if (!grant.sliceToken) {
|
|
13970
14261
|
console.error(
|
|
13971
|
-
`${
|
|
14262
|
+
`${TAG29} grantId=${grant.grantId} agentSlug=${agentSlug} result=no-slice-token reason=schema-violation`
|
|
13972
14263
|
);
|
|
13973
14264
|
return c.json({ error: "grant-misconfigured" }, 500);
|
|
13974
14265
|
}
|
|
@@ -13984,12 +14275,12 @@ app37.post("/", async (c) => {
|
|
|
13984
14275
|
await consumeMagicTokenAndActivate(grant.grantId);
|
|
13985
14276
|
} catch (err) {
|
|
13986
14277
|
console.error(
|
|
13987
|
-
`${
|
|
14278
|
+
`${TAG29} grantId=${grant.grantId} agentSlug=${agentSlug} result=consume-failed err="${err instanceof Error ? err.message : String(err)}"`
|
|
13988
14279
|
);
|
|
13989
14280
|
return c.json({ error: "verification-failed" }, 500);
|
|
13990
14281
|
}
|
|
13991
14282
|
clearAccessRateLimit(ip, agentSlug);
|
|
13992
|
-
console.log(`${
|
|
14283
|
+
console.log(`${TAG29} grantId=${grant.grantId} agentSlug=${agentSlug} result=ok ip=${ip}`);
|
|
13993
14284
|
console.log(
|
|
13994
14285
|
`${MINT_TAG} grantId=${grant.grantId} sliceToken=${grant.sliceToken.slice(0, 8)} agentSlug=${agentSlug} personId=${grant.personId ?? "none"}`
|
|
13995
14286
|
);
|
|
@@ -14003,13 +14294,13 @@ app37.post("/", async (c) => {
|
|
|
14003
14294
|
displayName: grant.displayName
|
|
14004
14295
|
});
|
|
14005
14296
|
});
|
|
14006
|
-
var verify_token_default =
|
|
14297
|
+
var verify_token_default = app39;
|
|
14007
14298
|
|
|
14008
14299
|
// app/lib/access-email.ts
|
|
14009
14300
|
import { spawn as spawn2 } from "child_process";
|
|
14010
|
-
import { resolve as
|
|
14011
|
-
var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT ??
|
|
14012
|
-
var SEND_SCRIPT =
|
|
14301
|
+
import { resolve as resolve22 } from "path";
|
|
14302
|
+
var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT ?? resolve22(process.cwd(), "..");
|
|
14303
|
+
var SEND_SCRIPT = resolve22(
|
|
14013
14304
|
PLATFORM_ROOT8,
|
|
14014
14305
|
"plugins",
|
|
14015
14306
|
"email",
|
|
@@ -14065,10 +14356,10 @@ async function sendMagicLinkEmail(payload) {
|
|
|
14065
14356
|
}
|
|
14066
14357
|
|
|
14067
14358
|
// server/routes/access/request-magic-link.ts
|
|
14068
|
-
var
|
|
14069
|
-
var
|
|
14359
|
+
var TAG30 = "[access-request-link]";
|
|
14360
|
+
var app40 = new Hono();
|
|
14070
14361
|
var VISITOR_MESSAGE = "If that email is on the invite list, a fresh link is on the way.";
|
|
14071
|
-
|
|
14362
|
+
app40.post("/", async (c) => {
|
|
14072
14363
|
let body;
|
|
14073
14364
|
try {
|
|
14074
14365
|
body = await c.req.json();
|
|
@@ -14082,18 +14373,18 @@ app38.post("/", async (c) => {
|
|
|
14082
14373
|
}
|
|
14083
14374
|
const rateMsg = checkRequestLinkRateLimit(contactValue);
|
|
14084
14375
|
if (rateMsg) {
|
|
14085
|
-
console.error(`${
|
|
14376
|
+
console.error(`${TAG30} contactValue=${maskContact(contactValue)} result=rate-limited`);
|
|
14086
14377
|
return c.json({ error: rateMsg }, 429);
|
|
14087
14378
|
}
|
|
14088
14379
|
recordRequestLinkAttempt(contactValue);
|
|
14089
14380
|
const accountId = process.env.ACCOUNT_ID ?? "";
|
|
14090
14381
|
if (!accountId) {
|
|
14091
|
-
console.error(`${
|
|
14382
|
+
console.error(`${TAG30} contactValue=${maskContact(contactValue)} result=no-account-id`);
|
|
14092
14383
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
14093
14384
|
}
|
|
14094
14385
|
const grant = await findActiveGrantByContact(contactValue, agentSlug, accountId);
|
|
14095
14386
|
if (!grant) {
|
|
14096
|
-
console.log(`${
|
|
14387
|
+
console.log(`${TAG30} contactValue=${maskContact(contactValue)} result=notfound`);
|
|
14097
14388
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
14098
14389
|
}
|
|
14099
14390
|
let token;
|
|
@@ -14101,7 +14392,7 @@ app38.post("/", async (c) => {
|
|
|
14101
14392
|
token = await generateNewMagicToken(grant.grantId);
|
|
14102
14393
|
} catch (err) {
|
|
14103
14394
|
console.error(
|
|
14104
|
-
`${
|
|
14395
|
+
`${TAG30} contactValue=${maskContact(contactValue)} result=mint-failed err="${err instanceof Error ? err.message : String(err)}"`
|
|
14105
14396
|
);
|
|
14106
14397
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
14107
14398
|
}
|
|
@@ -14133,26 +14424,26 @@ app38.post("/", async (c) => {
|
|
|
14133
14424
|
});
|
|
14134
14425
|
if (!sendResult.ok) {
|
|
14135
14426
|
console.error(
|
|
14136
|
-
`${
|
|
14427
|
+
`${TAG30} contactValue=${maskContact(contactValue)} result=send-failed err="${sendResult.error}"`
|
|
14137
14428
|
);
|
|
14138
14429
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
14139
14430
|
}
|
|
14140
14431
|
console.log(
|
|
14141
|
-
`${
|
|
14432
|
+
`${TAG30} contactValue=${maskContact(contactValue)} result=ok messageId=${sendResult.messageId}`
|
|
14142
14433
|
);
|
|
14143
14434
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
14144
14435
|
});
|
|
14145
|
-
var request_magic_link_default =
|
|
14436
|
+
var request_magic_link_default = app40;
|
|
14146
14437
|
|
|
14147
14438
|
// server/routes/access/index.ts
|
|
14148
|
-
var
|
|
14149
|
-
|
|
14150
|
-
|
|
14151
|
-
var access_default =
|
|
14439
|
+
var app41 = new Hono();
|
|
14440
|
+
app41.route("/verify-token", verify_token_default);
|
|
14441
|
+
app41.route("/request-magic-link", request_magic_link_default);
|
|
14442
|
+
var access_default = app41;
|
|
14152
14443
|
|
|
14153
14444
|
// server/routes/sites.ts
|
|
14154
|
-
import { existsSync as
|
|
14155
|
-
import { resolve as
|
|
14445
|
+
import { existsSync as existsSync20, readFileSync as readFileSync20, realpathSync as realpathSync5, statSync as statSync9 } from "fs";
|
|
14446
|
+
import { resolve as resolve23 } from "path";
|
|
14156
14447
|
var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
|
|
14157
14448
|
var MIME = {
|
|
14158
14449
|
".html": "text/html; charset=utf-8",
|
|
@@ -14183,8 +14474,8 @@ function getExt(p) {
|
|
|
14183
14474
|
if (idx < p.lastIndexOf("/")) return "";
|
|
14184
14475
|
return p.slice(idx).toLowerCase();
|
|
14185
14476
|
}
|
|
14186
|
-
var
|
|
14187
|
-
|
|
14477
|
+
var app42 = new Hono();
|
|
14478
|
+
app42.get("/:rel{.*}", (c) => {
|
|
14188
14479
|
const reqPath = c.req.path;
|
|
14189
14480
|
const rawRel = c.req.param("rel") ?? "";
|
|
14190
14481
|
const trimmed = rawRel.replace(/^\/+/, "").replace(/\/+$/, "");
|
|
@@ -14209,15 +14500,15 @@ app40.get("/:rel{.*}", (c) => {
|
|
|
14209
14500
|
}
|
|
14210
14501
|
segments.push(seg);
|
|
14211
14502
|
}
|
|
14212
|
-
const rootDir =
|
|
14213
|
-
let filePath = segments.length === 0 ? rootDir :
|
|
14503
|
+
const rootDir = resolve23(account.accountDir, "sites");
|
|
14504
|
+
let filePath = segments.length === 0 ? rootDir : resolve23(rootDir, ...segments);
|
|
14214
14505
|
if (filePath !== rootDir && !filePath.startsWith(rootDir + "/")) {
|
|
14215
14506
|
console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
|
|
14216
14507
|
return c.text("Forbidden", 403);
|
|
14217
14508
|
}
|
|
14218
14509
|
let stat7;
|
|
14219
14510
|
try {
|
|
14220
|
-
stat7 =
|
|
14511
|
+
stat7 = existsSync20(filePath) ? statSync9(filePath) : null;
|
|
14221
14512
|
} catch {
|
|
14222
14513
|
stat7 = null;
|
|
14223
14514
|
}
|
|
@@ -14230,13 +14521,13 @@ app40.get("/:rel{.*}", (c) => {
|
|
|
14230
14521
|
return c.redirect(target, 301);
|
|
14231
14522
|
}
|
|
14232
14523
|
if (stat7?.isDirectory()) {
|
|
14233
|
-
filePath =
|
|
14524
|
+
filePath = resolve23(filePath, "index.html");
|
|
14234
14525
|
}
|
|
14235
14526
|
if (!filePath.startsWith(rootDir + "/")) {
|
|
14236
14527
|
console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
|
|
14237
14528
|
return c.text("Forbidden", 403);
|
|
14238
14529
|
}
|
|
14239
|
-
if (!
|
|
14530
|
+
if (!existsSync20(filePath)) {
|
|
14240
14531
|
console.error(`[sites] not-found path=${reqPath} status=404`);
|
|
14241
14532
|
return c.text("Not found", 404);
|
|
14242
14533
|
}
|
|
@@ -14255,7 +14546,7 @@ app40.get("/:rel{.*}", (c) => {
|
|
|
14255
14546
|
}
|
|
14256
14547
|
let body;
|
|
14257
14548
|
try {
|
|
14258
|
-
body =
|
|
14549
|
+
body = readFileSync20(realPath);
|
|
14259
14550
|
} catch (err) {
|
|
14260
14551
|
const code = err?.code;
|
|
14261
14552
|
if (code === "EISDIR") {
|
|
@@ -14287,11 +14578,11 @@ app40.get("/:rel{.*}", (c) => {
|
|
|
14287
14578
|
"X-Content-Type-Options": "nosniff"
|
|
14288
14579
|
});
|
|
14289
14580
|
});
|
|
14290
|
-
var sites_default =
|
|
14581
|
+
var sites_default = app42;
|
|
14291
14582
|
|
|
14292
14583
|
// app/lib/visitor-token.ts
|
|
14293
14584
|
import { createHmac, randomBytes, timingSafeEqual } from "crypto";
|
|
14294
|
-
import { mkdirSync as mkdirSync4, readFileSync as
|
|
14585
|
+
import { mkdirSync as mkdirSync4, readFileSync as readFileSync21, writeFileSync as writeFileSync7 } from "fs";
|
|
14295
14586
|
import { dirname as dirname5 } from "path";
|
|
14296
14587
|
var TOKEN_PREFIX = "v1.";
|
|
14297
14588
|
var SECRET_BYTES = 32;
|
|
@@ -14300,7 +14591,7 @@ var cachedSecret = null;
|
|
|
14300
14591
|
function getSecret() {
|
|
14301
14592
|
if (cachedSecret) return cachedSecret;
|
|
14302
14593
|
try {
|
|
14303
|
-
const hex2 =
|
|
14594
|
+
const hex2 = readFileSync21(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
|
|
14304
14595
|
if (hex2.length === SECRET_BYTES * 2) {
|
|
14305
14596
|
cachedSecret = Buffer.from(hex2, "hex");
|
|
14306
14597
|
return cachedSecret;
|
|
@@ -14314,7 +14605,7 @@ function getSecret() {
|
|
|
14314
14605
|
console.log(`[visitor-token] secret minted path=${VISITOR_TOKEN_SECRET_FILE}`);
|
|
14315
14606
|
} catch {
|
|
14316
14607
|
}
|
|
14317
|
-
const hex =
|
|
14608
|
+
const hex = readFileSync21(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
|
|
14318
14609
|
cachedSecret = Buffer.from(hex, "hex");
|
|
14319
14610
|
return cachedSecret;
|
|
14320
14611
|
}
|
|
@@ -14367,8 +14658,8 @@ var VISITOR_COOKIE_NAME = "mxy_v";
|
|
|
14367
14658
|
var VISITOR_COOKIE_MAX_AGE_SECONDS = Math.floor(DEFAULT_TTL_MS / 1e3);
|
|
14368
14659
|
|
|
14369
14660
|
// app/lib/brand-config.ts
|
|
14370
|
-
import { existsSync as
|
|
14371
|
-
import { join as
|
|
14661
|
+
import { existsSync as existsSync21, readFileSync as readFileSync22 } from "fs";
|
|
14662
|
+
import { join as join18 } from "path";
|
|
14372
14663
|
var cached2 = null;
|
|
14373
14664
|
var cachedAttempted = false;
|
|
14374
14665
|
function readBrandConfig() {
|
|
@@ -14376,10 +14667,10 @@ function readBrandConfig() {
|
|
|
14376
14667
|
cachedAttempted = true;
|
|
14377
14668
|
const platformRoot2 = process.env.MAXY_PLATFORM_ROOT;
|
|
14378
14669
|
if (!platformRoot2) return null;
|
|
14379
|
-
const brandPath =
|
|
14380
|
-
if (!
|
|
14670
|
+
const brandPath = join18(platformRoot2, "config", "brand.json");
|
|
14671
|
+
if (!existsSync21(brandPath)) return null;
|
|
14381
14672
|
try {
|
|
14382
|
-
cached2 = JSON.parse(
|
|
14673
|
+
cached2 = JSON.parse(readFileSync22(brandPath, "utf-8"));
|
|
14383
14674
|
return cached2;
|
|
14384
14675
|
} catch {
|
|
14385
14676
|
return null;
|
|
@@ -14387,7 +14678,7 @@ function readBrandConfig() {
|
|
|
14387
14678
|
}
|
|
14388
14679
|
|
|
14389
14680
|
// server/routes/visitor-consent.ts
|
|
14390
|
-
var
|
|
14681
|
+
var app43 = new Hono();
|
|
14391
14682
|
var CONSENT_COOKIE_NAME = "mxy_consent";
|
|
14392
14683
|
var CONSENT_COOKIE_MAX_AGE_SECONDS = 60 * 60 * 24 * 365;
|
|
14393
14684
|
var DEFAULT_CONSENT_COPY = {
|
|
@@ -14432,17 +14723,17 @@ function siteSlugFromReferer(referer) {
|
|
|
14432
14723
|
return "";
|
|
14433
14724
|
}
|
|
14434
14725
|
}
|
|
14435
|
-
|
|
14726
|
+
app43.options("/consent", (c) => {
|
|
14436
14727
|
const origin = getOrigin(c);
|
|
14437
14728
|
setCorsHeaders(c, origin);
|
|
14438
14729
|
return c.body(null, 204);
|
|
14439
14730
|
});
|
|
14440
|
-
|
|
14731
|
+
app43.options("/brand-config", (c) => {
|
|
14441
14732
|
const origin = getOrigin(c);
|
|
14442
14733
|
setCorsHeaders(c, origin);
|
|
14443
14734
|
return c.body(null, 204);
|
|
14444
14735
|
});
|
|
14445
|
-
|
|
14736
|
+
app43.post("/consent", async (c) => {
|
|
14446
14737
|
const origin = getOrigin(c);
|
|
14447
14738
|
setCorsHeaders(c, origin);
|
|
14448
14739
|
let raw;
|
|
@@ -14482,7 +14773,7 @@ app41.post("/consent", async (c) => {
|
|
|
14482
14773
|
console.log(`[consent] ${parsed.decision} site=${site} brand=${brandName} tokenBound=${tokenBound}`);
|
|
14483
14774
|
return c.body(null, 204);
|
|
14484
14775
|
});
|
|
14485
|
-
|
|
14776
|
+
app43.get("/brand-config", (c) => {
|
|
14486
14777
|
const origin = getOrigin(c);
|
|
14487
14778
|
setCorsHeaders(c, origin);
|
|
14488
14779
|
const brand = readBrandConfig();
|
|
@@ -14492,7 +14783,7 @@ app41.get("/brand-config", (c) => {
|
|
|
14492
14783
|
c.header("Cache-Control", "public, max-age=300");
|
|
14493
14784
|
return c.json({ consent: { copy, palette } });
|
|
14494
14785
|
});
|
|
14495
|
-
var visitor_consent_default =
|
|
14786
|
+
var visitor_consent_default = app43;
|
|
14496
14787
|
|
|
14497
14788
|
// server/routes/listings.ts
|
|
14498
14789
|
function getCookie(headerValue, name) {
|
|
@@ -14519,8 +14810,8 @@ function appendConsentParams(pageUrl, token) {
|
|
|
14519
14810
|
}
|
|
14520
14811
|
var SAFE_SLUG_RE = /^[a-z0-9](?:[a-z0-9-]{0,118}[a-z0-9])?$/;
|
|
14521
14812
|
var CHAT_SESSION_KEY_RE = /^[A-Za-z0-9][A-Za-z0-9_-]{7,127}$/;
|
|
14522
|
-
var
|
|
14523
|
-
|
|
14813
|
+
var app44 = new Hono();
|
|
14814
|
+
app44.get("/:slug/click", async (c) => {
|
|
14524
14815
|
const slug = c.req.param("slug") ?? "";
|
|
14525
14816
|
const rawSession = c.req.query("session") ?? "";
|
|
14526
14817
|
const sessionKey = CHAT_SESSION_KEY_RE.test(rawSession) ? rawSession : "invalid";
|
|
@@ -14584,10 +14875,10 @@ app42.get("/:slug/click", async (c) => {
|
|
|
14584
14875
|
console.log(`[property-card-click] sessionKey=${sessionKey} listingSlug=${slug} consent=${consentCookie ?? "absent"} ts=${(/* @__PURE__ */ new Date()).toISOString()}`);
|
|
14585
14876
|
return c.redirect(redirectUrl, 302);
|
|
14586
14877
|
});
|
|
14587
|
-
var listings_default =
|
|
14878
|
+
var listings_default = app44;
|
|
14588
14879
|
|
|
14589
14880
|
// server/routes/visitor-event.ts
|
|
14590
|
-
var
|
|
14881
|
+
var app45 = new Hono();
|
|
14591
14882
|
var BOT_UA_RE = /\b(bot|crawl|spider|slurp|headlesschrome|phantomjs|googlebot|bingbot|yandex|baiduspider|ahrefsbot|semrushbot|mj12bot|dotbot|petalbot)\b/i;
|
|
14592
14883
|
var buckets = /* @__PURE__ */ new Map();
|
|
14593
14884
|
var RATE_LIMIT = 60;
|
|
@@ -14654,12 +14945,12 @@ function originAllowed(origin, allowlist) {
|
|
|
14654
14945
|
return false;
|
|
14655
14946
|
}
|
|
14656
14947
|
}
|
|
14657
|
-
|
|
14948
|
+
app45.options("/event", (c) => {
|
|
14658
14949
|
const origin = getOrigin2(c);
|
|
14659
14950
|
setCorsHeaders2(c, origin);
|
|
14660
14951
|
return c.body(null, 204);
|
|
14661
14952
|
});
|
|
14662
|
-
|
|
14953
|
+
app45.post("/event", async (c) => {
|
|
14663
14954
|
const origin = getOrigin2(c);
|
|
14664
14955
|
setCorsHeaders2(c, origin);
|
|
14665
14956
|
const ua = c.req.header("user-agent") ?? "";
|
|
@@ -14864,17 +15155,17 @@ async function writeEvent(opts) {
|
|
|
14864
15155
|
);
|
|
14865
15156
|
}
|
|
14866
15157
|
}
|
|
14867
|
-
var visitor_event_default =
|
|
15158
|
+
var visitor_event_default = app45;
|
|
14868
15159
|
|
|
14869
15160
|
// server/routes/session.ts
|
|
14870
|
-
import { resolve as
|
|
14871
|
-
import { existsSync as
|
|
15161
|
+
import { resolve as resolve24 } from "path";
|
|
15162
|
+
import { existsSync as existsSync22, writeFileSync as writeFileSync8, mkdirSync as mkdirSync5 } from "fs";
|
|
14872
15163
|
var UUID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
14873
15164
|
function writeBrandingCache(accountId, agentSlug, branding) {
|
|
14874
15165
|
try {
|
|
14875
|
-
const cacheDir =
|
|
15166
|
+
const cacheDir = resolve24(MAXY_DIR, "branding-cache", accountId);
|
|
14876
15167
|
mkdirSync5(cacheDir, { recursive: true });
|
|
14877
|
-
writeFileSync8(
|
|
15168
|
+
writeFileSync8(resolve24(cacheDir, `${agentSlug}.json`), JSON.stringify(branding), "utf-8");
|
|
14878
15169
|
} catch (err) {
|
|
14879
15170
|
console.error(`[branding] cache write failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
14880
15171
|
}
|
|
@@ -14910,8 +15201,8 @@ function withVisitorCookie(response, visitorId) {
|
|
|
14910
15201
|
headers
|
|
14911
15202
|
});
|
|
14912
15203
|
}
|
|
14913
|
-
var
|
|
14914
|
-
|
|
15204
|
+
var app46 = new Hono();
|
|
15205
|
+
app46.post("/", async (c) => {
|
|
14915
15206
|
let body;
|
|
14916
15207
|
try {
|
|
14917
15208
|
body = await c.req.json();
|
|
@@ -14962,8 +15253,8 @@ app44.post("/", async (c) => {
|
|
|
14962
15253
|
}
|
|
14963
15254
|
let agentConfig = null;
|
|
14964
15255
|
if (account) {
|
|
14965
|
-
const agentDir =
|
|
14966
|
-
if (!
|
|
15256
|
+
const agentDir = resolve24(account.accountDir, "agents", agentSlug);
|
|
15257
|
+
if (!existsSync22(agentDir) || !existsSync22(resolve24(agentDir, "config.json"))) {
|
|
14967
15258
|
return c.json({ error: "Agent not found" }, 404);
|
|
14968
15259
|
}
|
|
14969
15260
|
agentConfig = resolveAgentConfig(account.accountDir, agentSlug);
|
|
@@ -15122,7 +15413,7 @@ app44.post("/", async (c) => {
|
|
|
15122
15413
|
newVisitorId
|
|
15123
15414
|
);
|
|
15124
15415
|
});
|
|
15125
|
-
var session_default2 =
|
|
15416
|
+
var session_default2 = app46;
|
|
15126
15417
|
|
|
15127
15418
|
// app/lib/graph-health.ts
|
|
15128
15419
|
var import_dist4 = __toESM(require_dist3(), 1);
|
|
@@ -15243,7 +15534,7 @@ function startGraphHealthTimer() {
|
|
|
15243
15534
|
|
|
15244
15535
|
// app/lib/file-watcher.ts
|
|
15245
15536
|
import * as fsp2 from "fs/promises";
|
|
15246
|
-
import { resolve as
|
|
15537
|
+
import { resolve as resolve25, sep as sep7 } from "path";
|
|
15247
15538
|
var ACCOUNT_UUID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
15248
15539
|
var DEFAULT_COALESCE_MS = 500;
|
|
15249
15540
|
var ROOTS = ["uploads", "accounts"];
|
|
@@ -15262,7 +15553,7 @@ async function startFileWatcher(opts = {}) {
|
|
|
15262
15553
|
const dropFn = opts.drop ?? dropFileIndex;
|
|
15263
15554
|
for (const r of ROOTS) {
|
|
15264
15555
|
try {
|
|
15265
|
-
await fsp2.mkdir(
|
|
15556
|
+
await fsp2.mkdir(resolve25(dataRoot, r), { recursive: true });
|
|
15266
15557
|
} catch (err) {
|
|
15267
15558
|
console.error(
|
|
15268
15559
|
`[file-watcher] start-failed root="${r}" err="${err.message}" \u2014 index will be maintained by the 5-min reconcile backstop only`
|
|
@@ -15283,7 +15574,7 @@ async function startFileWatcher(opts = {}) {
|
|
|
15283
15574
|
timers.set(relativePath, t);
|
|
15284
15575
|
}
|
|
15285
15576
|
async function runHook(relativePath, accountId) {
|
|
15286
|
-
const absolute =
|
|
15577
|
+
const absolute = resolve25(dataRoot, relativePath);
|
|
15287
15578
|
let exists = false;
|
|
15288
15579
|
try {
|
|
15289
15580
|
const st = await fsp2.stat(absolute);
|
|
@@ -15307,7 +15598,7 @@ async function startFileWatcher(opts = {}) {
|
|
|
15307
15598
|
}
|
|
15308
15599
|
}
|
|
15309
15600
|
async function watchRoot(rootName) {
|
|
15310
|
-
const absRoot =
|
|
15601
|
+
const absRoot = resolve25(dataRoot, rootName);
|
|
15311
15602
|
try {
|
|
15312
15603
|
const iter = fsp2.watch(absRoot, { recursive: true, signal: controller.signal });
|
|
15313
15604
|
for await (const event of iter) {
|
|
@@ -15612,8 +15903,8 @@ var streamSSE = (c, cb, onError) => {
|
|
|
15612
15903
|
|
|
15613
15904
|
// app/lib/whatsapp/gateway/routes.ts
|
|
15614
15905
|
function createWaChannelRoutes(deps) {
|
|
15615
|
-
const
|
|
15616
|
-
|
|
15906
|
+
const app48 = new Hono();
|
|
15907
|
+
app48.get("/wa-channel/inbound", (c) => {
|
|
15617
15908
|
const senderId = c.req.query("senderId");
|
|
15618
15909
|
if (!senderId) return c.json({ error: "senderId required" }, 400);
|
|
15619
15910
|
return streamSSE(c, async (stream2) => {
|
|
@@ -15631,7 +15922,7 @@ function createWaChannelRoutes(deps) {
|
|
|
15631
15922
|
}
|
|
15632
15923
|
});
|
|
15633
15924
|
});
|
|
15634
|
-
|
|
15925
|
+
app48.post("/wa-channel/reply", async (c) => {
|
|
15635
15926
|
const body = await c.req.json().catch(() => null);
|
|
15636
15927
|
const senderId = body?.senderId;
|
|
15637
15928
|
const text = body?.text;
|
|
@@ -15652,7 +15943,7 @@ function createWaChannelRoutes(deps) {
|
|
|
15652
15943
|
console.error(`[whatsapp-native] op=reply-dispatch senderId=${senderId} bytes=${bytes}`);
|
|
15653
15944
|
return c.json({ ok: true });
|
|
15654
15945
|
});
|
|
15655
|
-
|
|
15946
|
+
app48.post("/wa-channel/ready", async (c) => {
|
|
15656
15947
|
const body = await c.req.json().catch(() => null);
|
|
15657
15948
|
const senderId = body?.senderId;
|
|
15658
15949
|
if (typeof senderId !== "string") {
|
|
@@ -15661,7 +15952,7 @@ function createWaChannelRoutes(deps) {
|
|
|
15661
15952
|
deps.onReady?.(senderId);
|
|
15662
15953
|
return c.json({ ok: true });
|
|
15663
15954
|
});
|
|
15664
|
-
|
|
15955
|
+
app48.post("/wa-channel/received", async (c) => {
|
|
15665
15956
|
const body = await c.req.json().catch(() => null);
|
|
15666
15957
|
const senderId = body?.senderId;
|
|
15667
15958
|
const waMessageId = body?.waMessageId;
|
|
@@ -15671,7 +15962,7 @@ function createWaChannelRoutes(deps) {
|
|
|
15671
15962
|
deps.onReceived?.(senderId, waMessageId);
|
|
15672
15963
|
return c.json({ ok: true });
|
|
15673
15964
|
});
|
|
15674
|
-
return
|
|
15965
|
+
return app48;
|
|
15675
15966
|
}
|
|
15676
15967
|
|
|
15677
15968
|
// app/lib/whatsapp/gateway/wa-gateway.ts
|
|
@@ -15864,8 +16155,8 @@ function broadcastAdminShutdown(reason) {
|
|
|
15864
16155
|
|
|
15865
16156
|
// ../lib/entitlement/src/index.ts
|
|
15866
16157
|
import { createPublicKey, createHash as createHash5, verify as cryptoVerify } from "crypto";
|
|
15867
|
-
import { existsSync as
|
|
15868
|
-
import { resolve as
|
|
16158
|
+
import { existsSync as existsSync23, readFileSync as readFileSync23, statSync as statSync10 } from "fs";
|
|
16159
|
+
import { resolve as resolve26 } from "path";
|
|
15869
16160
|
|
|
15870
16161
|
// ../lib/entitlement/src/canonicalize.ts
|
|
15871
16162
|
function canonicalize(value) {
|
|
@@ -15900,7 +16191,7 @@ var PUBKEY_SHA256 = "8eee6bcb33545fd13b16d3199a5735ca5db5062834c7b49dfe4f23801d9
|
|
|
15900
16191
|
var GRACE_DAYS = 7;
|
|
15901
16192
|
var GRACE_MS = GRACE_DAYS * 24 * 60 * 60 * 1e3;
|
|
15902
16193
|
function pubkeyPath(brand) {
|
|
15903
|
-
return
|
|
16194
|
+
return resolve26(brand.platformRoot, "lib", "entitlement", "rubytech-pubkey.pem");
|
|
15904
16195
|
}
|
|
15905
16196
|
var memo = null;
|
|
15906
16197
|
function memoKey(mtimeMs, account) {
|
|
@@ -15912,8 +16203,8 @@ function resolveEntitlement(brand, account) {
|
|
|
15912
16203
|
if (brand.commercialMode !== true) {
|
|
15913
16204
|
return logResolved(implicitTrust(account), null);
|
|
15914
16205
|
}
|
|
15915
|
-
const entitlementPath =
|
|
15916
|
-
if (!
|
|
16206
|
+
const entitlementPath = resolve26(brand.configDir, "entitlement.json");
|
|
16207
|
+
if (!existsSync23(entitlementPath)) {
|
|
15917
16208
|
return logResolved(anonymousFallback("missing"), { reason: "missing" });
|
|
15918
16209
|
}
|
|
15919
16210
|
const stat7 = statSync10(entitlementPath);
|
|
@@ -15928,7 +16219,7 @@ function resolveEntitlement(brand, account) {
|
|
|
15928
16219
|
function verifyAndResolve(brand, entitlementPath, account) {
|
|
15929
16220
|
let pubkeyPem;
|
|
15930
16221
|
try {
|
|
15931
|
-
pubkeyPem =
|
|
16222
|
+
pubkeyPem = readFileSync23(pubkeyPath(brand), "utf-8");
|
|
15932
16223
|
} catch (err) {
|
|
15933
16224
|
return logResolved(anonymousFallback("pubkey-missing"), {
|
|
15934
16225
|
reason: "pubkey-missing"
|
|
@@ -15942,7 +16233,7 @@ function verifyAndResolve(brand, entitlementPath, account) {
|
|
|
15942
16233
|
}
|
|
15943
16234
|
let envelope;
|
|
15944
16235
|
try {
|
|
15945
|
-
envelope = JSON.parse(
|
|
16236
|
+
envelope = JSON.parse(readFileSync23(entitlementPath, "utf-8"));
|
|
15946
16237
|
} catch {
|
|
15947
16238
|
return logResolved(anonymousFallback("malformed"), { reason: "malformed" });
|
|
15948
16239
|
}
|
|
@@ -16103,14 +16394,14 @@ function clientFrom(c) {
|
|
|
16103
16394
|
);
|
|
16104
16395
|
}
|
|
16105
16396
|
var PLATFORM_ROOT9 = process.env.MAXY_PLATFORM_ROOT || "";
|
|
16106
|
-
var BRAND_JSON_PATH = PLATFORM_ROOT9 ?
|
|
16397
|
+
var BRAND_JSON_PATH = PLATFORM_ROOT9 ? join19(PLATFORM_ROOT9, "config", "brand.json") : "";
|
|
16107
16398
|
var BRAND = { productName: "Maxy", hostname: "maxy", configDir: ".maxy", marketingUrl: "https://getmaxy.com" };
|
|
16108
|
-
if (BRAND_JSON_PATH && !
|
|
16399
|
+
if (BRAND_JSON_PATH && !existsSync24(BRAND_JSON_PATH)) {
|
|
16109
16400
|
console.error(`[brand] WARNING: brand.json not found at ${BRAND_JSON_PATH} \u2014 using Maxy defaults`);
|
|
16110
16401
|
}
|
|
16111
|
-
if (BRAND_JSON_PATH &&
|
|
16402
|
+
if (BRAND_JSON_PATH && existsSync24(BRAND_JSON_PATH)) {
|
|
16112
16403
|
try {
|
|
16113
|
-
const parsed = JSON.parse(
|
|
16404
|
+
const parsed = JSON.parse(readFileSync24(BRAND_JSON_PATH, "utf-8"));
|
|
16114
16405
|
BRAND = { ...BRAND, ...parsed };
|
|
16115
16406
|
} catch (err) {
|
|
16116
16407
|
console.error(`[brand] Failed to parse brand.json: ${err.message}`);
|
|
@@ -16129,11 +16420,11 @@ var brandLoginOpts = {
|
|
|
16129
16420
|
bodyFont: BRAND.defaultFonts?.body,
|
|
16130
16421
|
logoContainsName: !!BRAND.logoContainsName
|
|
16131
16422
|
};
|
|
16132
|
-
var ALIAS_DOMAINS_PATH =
|
|
16423
|
+
var ALIAS_DOMAINS_PATH = join19(homedir3(), BRAND.configDir, "alias-domains.json");
|
|
16133
16424
|
function loadAliasDomains() {
|
|
16134
16425
|
try {
|
|
16135
|
-
if (!
|
|
16136
|
-
const parsed = JSON.parse(
|
|
16426
|
+
if (!existsSync24(ALIAS_DOMAINS_PATH)) return null;
|
|
16427
|
+
const parsed = JSON.parse(readFileSync24(ALIAS_DOMAINS_PATH, "utf-8"));
|
|
16137
16428
|
if (!Array.isArray(parsed)) {
|
|
16138
16429
|
console.error("[alias-domains] malformed alias-domains.json \u2014 expected array");
|
|
16139
16430
|
return null;
|
|
@@ -16157,10 +16448,10 @@ watchFile(ALIAS_DOMAINS_PATH, { interval: 2e3 }, () => {
|
|
|
16157
16448
|
function isPublicHost(host) {
|
|
16158
16449
|
return host.startsWith("public.") || aliasDomains.has(host);
|
|
16159
16450
|
}
|
|
16160
|
-
var
|
|
16451
|
+
var app47 = new Hono();
|
|
16161
16452
|
var waGateway = new WaGateway({
|
|
16162
16453
|
gatewayUrl: `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`,
|
|
16163
|
-
serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ??
|
|
16454
|
+
serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve27(process.env.MAXY_PLATFORM_ROOT ?? join19(__dirname, ".."), "services/whatsapp-channel/dist/server.js"),
|
|
16164
16455
|
ensureChannelSession: async ({ accountId, senderId, gatewayUrl, serverPath }) => {
|
|
16165
16456
|
const userId = resolveAdminUserId({ accountId, senderPhone: senderId }) ?? void 0;
|
|
16166
16457
|
console.error(`[whatsapp-native] op=admin-identity senderId=${senderId} userId=${userId ?? "owner-fallback"}`);
|
|
@@ -16180,10 +16471,10 @@ var waGateway = new WaGateway({
|
|
|
16180
16471
|
}
|
|
16181
16472
|
}
|
|
16182
16473
|
});
|
|
16183
|
-
|
|
16474
|
+
app47.route("/", waGateway.routes());
|
|
16184
16475
|
waGateway.startSweeper();
|
|
16185
|
-
|
|
16186
|
-
|
|
16476
|
+
app47.use("*", clientIpMiddleware);
|
|
16477
|
+
app47.use("*", async (c, next) => {
|
|
16187
16478
|
await next();
|
|
16188
16479
|
c.header("X-Content-Type-Options", "nosniff");
|
|
16189
16480
|
c.header("Referrer-Policy", "strict-origin-when-cross-origin");
|
|
@@ -16193,7 +16484,7 @@ app45.use("*", async (c, next) => {
|
|
|
16193
16484
|
);
|
|
16194
16485
|
});
|
|
16195
16486
|
var HTTP_LOG_PATHS = /* @__PURE__ */ new Set(["/vnc-viewer.html", "/vnc-popout.html"]);
|
|
16196
|
-
|
|
16487
|
+
app47.use("*", async (c, next) => {
|
|
16197
16488
|
if (!HTTP_LOG_PATHS.has(c.req.path)) {
|
|
16198
16489
|
await next();
|
|
16199
16490
|
return;
|
|
@@ -16211,7 +16502,7 @@ app45.use("*", async (c, next) => {
|
|
|
16211
16502
|
});
|
|
16212
16503
|
}
|
|
16213
16504
|
});
|
|
16214
|
-
|
|
16505
|
+
app47.use("*", async (c, next) => {
|
|
16215
16506
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
16216
16507
|
if (!isPublicHost(host)) {
|
|
16217
16508
|
await next();
|
|
@@ -16242,7 +16533,7 @@ function resolveRemoteAuthOpts() {
|
|
|
16242
16533
|
return brandLoginOpts;
|
|
16243
16534
|
}
|
|
16244
16535
|
var MAX_LOGIN_BODY = 8 * 1024;
|
|
16245
|
-
|
|
16536
|
+
app47.post("/__remote-auth/login", async (c) => {
|
|
16246
16537
|
const client = clientFrom(c);
|
|
16247
16538
|
const clientIp = client.ip || "unknown";
|
|
16248
16539
|
if (!requestIsTlsTerminated(c)) {
|
|
@@ -16287,7 +16578,7 @@ app45.post("/__remote-auth/login", async (c) => {
|
|
|
16287
16578
|
}
|
|
16288
16579
|
});
|
|
16289
16580
|
});
|
|
16290
|
-
|
|
16581
|
+
app47.get("/__remote-auth/logout", (c) => {
|
|
16291
16582
|
const client = clientFrom(c);
|
|
16292
16583
|
const clientIp = client.ip || "unknown";
|
|
16293
16584
|
console.error(`[remote-auth] logout ip=${clientIp}`);
|
|
@@ -16300,7 +16591,7 @@ app45.get("/__remote-auth/logout", (c) => {
|
|
|
16300
16591
|
}
|
|
16301
16592
|
});
|
|
16302
16593
|
});
|
|
16303
|
-
|
|
16594
|
+
app47.post("/__remote-auth/change-password", async (c) => {
|
|
16304
16595
|
const client = clientFrom(c);
|
|
16305
16596
|
const clientIp = client.ip || "unknown";
|
|
16306
16597
|
const rateLimited = checkRateLimit(client);
|
|
@@ -16351,13 +16642,13 @@ app45.post("/__remote-auth/change-password", async (c) => {
|
|
|
16351
16642
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "change", changeError: "Failed to save password", redirect }), 200);
|
|
16352
16643
|
}
|
|
16353
16644
|
});
|
|
16354
|
-
|
|
16645
|
+
app47.get("/__remote-auth/setup", (c) => {
|
|
16355
16646
|
if (isRemoteAuthConfigured()) {
|
|
16356
16647
|
return c.redirect("/");
|
|
16357
16648
|
}
|
|
16358
16649
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "setup" }), 200);
|
|
16359
16650
|
});
|
|
16360
|
-
|
|
16651
|
+
app47.post("/__remote-auth/set-initial-password", async (c) => {
|
|
16361
16652
|
if (isRemoteAuthConfigured()) {
|
|
16362
16653
|
return c.redirect("/");
|
|
16363
16654
|
}
|
|
@@ -16395,10 +16686,10 @@ app45.post("/__remote-auth/set-initial-password", async (c) => {
|
|
|
16395
16686
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "setup", setupError: "Failed to save password. Please try again." }), 200);
|
|
16396
16687
|
}
|
|
16397
16688
|
});
|
|
16398
|
-
|
|
16689
|
+
app47.get("/api/remote-auth/status", (c) => {
|
|
16399
16690
|
return c.json({ configured: isRemoteAuthConfigured() });
|
|
16400
16691
|
});
|
|
16401
|
-
|
|
16692
|
+
app47.post("/api/remote-auth/set-password", async (c) => {
|
|
16402
16693
|
let body;
|
|
16403
16694
|
try {
|
|
16404
16695
|
body = await c.req.json();
|
|
@@ -16429,9 +16720,9 @@ app45.post("/api/remote-auth/set-password", async (c) => {
|
|
|
16429
16720
|
return c.json({ error: "Failed to save password" }, 500);
|
|
16430
16721
|
}
|
|
16431
16722
|
});
|
|
16432
|
-
|
|
16723
|
+
app47.route("/api/_client-error", client_error_default);
|
|
16433
16724
|
console.log("[client-error-route] mounted");
|
|
16434
|
-
|
|
16725
|
+
app47.use("*", async (c, next) => {
|
|
16435
16726
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
16436
16727
|
const path2 = c.req.path;
|
|
16437
16728
|
if (path2 === "/favicon.ico" || path2.startsWith("/assets/") || path2.startsWith("/brand/")) {
|
|
@@ -16464,14 +16755,15 @@ app45.use("*", async (c, next) => {
|
|
|
16464
16755
|
console.error(`[remote-auth] login required ip=${clientIp} path=${path2} ${disambig}`);
|
|
16465
16756
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), redirect: path2 }), 200);
|
|
16466
16757
|
});
|
|
16467
|
-
|
|
16468
|
-
|
|
16469
|
-
|
|
16470
|
-
|
|
16471
|
-
|
|
16472
|
-
|
|
16473
|
-
|
|
16474
|
-
|
|
16758
|
+
app47.route("/api/health", health_default);
|
|
16759
|
+
app47.route("/api/chat", chat_default);
|
|
16760
|
+
app47.route("/api/whatsapp", whatsapp_default);
|
|
16761
|
+
app47.route("/api/whatsapp-reader", whatsapp_reader_default);
|
|
16762
|
+
app47.route("/api/telegram", telegram_default);
|
|
16763
|
+
app47.route("/api/onboarding", onboarding_default);
|
|
16764
|
+
app47.route("/api/admin", admin_default);
|
|
16765
|
+
app47.route("/api/access", access_default);
|
|
16766
|
+
app47.route("/api/session", session_default2);
|
|
16475
16767
|
var SAFE_SLUG_RE2 = /^[a-z][a-z0-9-]{2,49}$/;
|
|
16476
16768
|
var SAFE_FILENAME_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
|
|
16477
16769
|
var IMAGE_MIME = {
|
|
@@ -16483,7 +16775,7 @@ var IMAGE_MIME = {
|
|
|
16483
16775
|
".svg": "image/svg+xml",
|
|
16484
16776
|
".ico": "image/x-icon"
|
|
16485
16777
|
};
|
|
16486
|
-
|
|
16778
|
+
app47.get("/agent-assets/:slug/:filename", (c) => {
|
|
16487
16779
|
const slug = c.req.param("slug");
|
|
16488
16780
|
const filename = c.req.param("filename");
|
|
16489
16781
|
if (!SAFE_SLUG_RE2.test(slug)) {
|
|
@@ -16499,26 +16791,26 @@ app45.get("/agent-assets/:slug/:filename", (c) => {
|
|
|
16499
16791
|
console.error(`[agent-assets] no-account slug=${slug} file=${filename}`);
|
|
16500
16792
|
return c.text("Not found", 404);
|
|
16501
16793
|
}
|
|
16502
|
-
const filePath =
|
|
16503
|
-
const expectedDir =
|
|
16794
|
+
const filePath = resolve27(account.accountDir, "agents", slug, "assets", filename);
|
|
16795
|
+
const expectedDir = resolve27(account.accountDir, "agents", slug, "assets");
|
|
16504
16796
|
if (!filePath.startsWith(expectedDir + "/")) {
|
|
16505
16797
|
console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
|
|
16506
16798
|
return c.text("Forbidden", 403);
|
|
16507
16799
|
}
|
|
16508
|
-
if (!
|
|
16800
|
+
if (!existsSync24(filePath)) {
|
|
16509
16801
|
console.error(`[agent-assets] serve slug=${slug} file=${filename} status=404`);
|
|
16510
16802
|
return c.text("Not found", 404);
|
|
16511
16803
|
}
|
|
16512
16804
|
const ext = "." + filename.split(".").pop()?.toLowerCase();
|
|
16513
16805
|
const contentType = IMAGE_MIME[ext] || "application/octet-stream";
|
|
16514
16806
|
console.log(`[agent-assets] serve slug=${slug} file=${filename} status=200`);
|
|
16515
|
-
const body =
|
|
16807
|
+
const body = readFileSync24(filePath);
|
|
16516
16808
|
return c.body(body, 200, {
|
|
16517
16809
|
"Content-Type": contentType,
|
|
16518
16810
|
"Cache-Control": "public, max-age=3600"
|
|
16519
16811
|
});
|
|
16520
16812
|
});
|
|
16521
|
-
|
|
16813
|
+
app47.get("/generated/:filename", (c) => {
|
|
16522
16814
|
const filename = c.req.param("filename");
|
|
16523
16815
|
if (!SAFE_FILENAME_RE.test(filename) || filename.includes("..")) {
|
|
16524
16816
|
console.error(`[generated] serve file=${filename} status=403`);
|
|
@@ -16529,35 +16821,35 @@ app45.get("/generated/:filename", (c) => {
|
|
|
16529
16821
|
console.error(`[generated] serve file=${filename} status=404`);
|
|
16530
16822
|
return c.text("Not found", 404);
|
|
16531
16823
|
}
|
|
16532
|
-
const filePath =
|
|
16533
|
-
const expectedDir =
|
|
16824
|
+
const filePath = resolve27(account.accountDir, "generated", filename);
|
|
16825
|
+
const expectedDir = resolve27(account.accountDir, "generated");
|
|
16534
16826
|
if (!filePath.startsWith(expectedDir + "/")) {
|
|
16535
16827
|
console.error(`[generated] serve file=${filename} status=403`);
|
|
16536
16828
|
return c.text("Forbidden", 403);
|
|
16537
16829
|
}
|
|
16538
|
-
if (!
|
|
16830
|
+
if (!existsSync24(filePath)) {
|
|
16539
16831
|
console.error(`[generated] serve file=${filename} status=404`);
|
|
16540
16832
|
return c.text("Not found", 404);
|
|
16541
16833
|
}
|
|
16542
16834
|
const ext = "." + filename.split(".").pop()?.toLowerCase();
|
|
16543
16835
|
const contentType = IMAGE_MIME[ext] || "application/octet-stream";
|
|
16544
16836
|
console.log(`[generated] serve file=${filename} status=200`);
|
|
16545
|
-
const body =
|
|
16837
|
+
const body = readFileSync24(filePath);
|
|
16546
16838
|
return c.body(body, 200, {
|
|
16547
16839
|
"Content-Type": contentType,
|
|
16548
16840
|
"Cache-Control": "public, max-age=86400"
|
|
16549
16841
|
});
|
|
16550
16842
|
});
|
|
16551
|
-
|
|
16552
|
-
|
|
16553
|
-
|
|
16554
|
-
|
|
16843
|
+
app47.route("/sites", sites_default);
|
|
16844
|
+
app47.route("/listings", listings_default);
|
|
16845
|
+
app47.route("/v", visitor_event_default);
|
|
16846
|
+
app47.route("/v", visitor_consent_default);
|
|
16555
16847
|
var htmlCache = /* @__PURE__ */ new Map();
|
|
16556
16848
|
var brandLogoPath = "/brand/maxy-monochrome.png";
|
|
16557
16849
|
var brandIconPath = "/brand/maxy-monochrome.png";
|
|
16558
|
-
if (BRAND_JSON_PATH &&
|
|
16850
|
+
if (BRAND_JSON_PATH && existsSync24(BRAND_JSON_PATH)) {
|
|
16559
16851
|
try {
|
|
16560
|
-
const fullBrand = JSON.parse(
|
|
16852
|
+
const fullBrand = JSON.parse(readFileSync24(BRAND_JSON_PATH, "utf-8"));
|
|
16561
16853
|
if (fullBrand.assets?.logo) brandLogoPath = `/brand/${fullBrand.assets.logo}`;
|
|
16562
16854
|
brandIconPath = fullBrand.assets?.icon ? `/brand/${fullBrand.assets.icon}` : brandLogoPath;
|
|
16563
16855
|
} catch {
|
|
@@ -16574,9 +16866,9 @@ var brandScript = `<script>window.__BRAND__=${JSON.stringify({
|
|
|
16574
16866
|
function readInstalledVersion() {
|
|
16575
16867
|
try {
|
|
16576
16868
|
if (!PLATFORM_ROOT9) return "unknown";
|
|
16577
|
-
const versionFile =
|
|
16578
|
-
if (!
|
|
16579
|
-
const content =
|
|
16869
|
+
const versionFile = join19(PLATFORM_ROOT9, "config", `.${BRAND.hostname}-version`);
|
|
16870
|
+
if (!existsSync24(versionFile)) return "unknown";
|
|
16871
|
+
const content = readFileSync24(versionFile, "utf-8").trim();
|
|
16580
16872
|
return content || "unknown";
|
|
16581
16873
|
} catch {
|
|
16582
16874
|
return "unknown";
|
|
@@ -16617,7 +16909,7 @@ var clientErrorReporterScript = `<script>
|
|
|
16617
16909
|
function cachedHtml(file) {
|
|
16618
16910
|
let html = htmlCache.get(file);
|
|
16619
16911
|
if (!html) {
|
|
16620
|
-
html =
|
|
16912
|
+
html = readFileSync24(resolve27(process.cwd(), "public", file), "utf-8");
|
|
16621
16913
|
const productNameEsc = escapeHtml(BRAND.productName);
|
|
16622
16914
|
html = html.replace(/<title>([^<]*)<\/title>/, (_match, inner) => `<title>${escapeHtml(inner).replace(/Maxy/g, productNameEsc)}</title>`);
|
|
16623
16915
|
html = html.replace('href="/favicon.ico"', `href="${escapeHtml(brandFaviconPath)}"`);
|
|
@@ -16633,13 +16925,13 @@ ${clientErrorReporterScript}
|
|
|
16633
16925
|
}
|
|
16634
16926
|
var brandedHtmlCache = /* @__PURE__ */ new Map();
|
|
16635
16927
|
function loadBrandingCache(agentSlug) {
|
|
16636
|
-
const configDir2 =
|
|
16928
|
+
const configDir2 = join19(homedir3(), BRAND.configDir);
|
|
16637
16929
|
try {
|
|
16638
16930
|
const accountId = getDefaultAccountId();
|
|
16639
16931
|
if (!accountId) return null;
|
|
16640
|
-
const cachePath =
|
|
16641
|
-
if (!
|
|
16642
|
-
return JSON.parse(
|
|
16932
|
+
const cachePath = join19(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
|
|
16933
|
+
if (!existsSync24(cachePath)) return null;
|
|
16934
|
+
return JSON.parse(readFileSync24(cachePath, "utf-8"));
|
|
16643
16935
|
} catch {
|
|
16644
16936
|
return null;
|
|
16645
16937
|
}
|
|
@@ -16682,7 +16974,7 @@ function escapeHtml(s) {
|
|
|
16682
16974
|
function agentUnavailableHtml() {
|
|
16683
16975
|
return `<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>${escapeHtml(BRAND.productName)}</title></head><body style="font-family:system-ui,sans-serif;max-width:32rem;margin:4rem auto;padding:0 1.5rem;color:#222"><h1 style="font-size:1.25rem">Agent unavailable</h1><p>This agent isn't available right now. If you reached this page from a saved link, the agent may have been turned off.</p></body></html>`;
|
|
16684
16976
|
}
|
|
16685
|
-
|
|
16977
|
+
app47.get("/", (c) => {
|
|
16686
16978
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
16687
16979
|
if (isPublicHost(host)) {
|
|
16688
16980
|
const defaultSlug = resolveDefaultSlug();
|
|
@@ -16698,12 +16990,12 @@ app45.get("/", (c) => {
|
|
|
16698
16990
|
}
|
|
16699
16991
|
return c.html(cachedHtml("index.html"));
|
|
16700
16992
|
});
|
|
16701
|
-
|
|
16993
|
+
app47.get("/public", (c) => {
|
|
16702
16994
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
16703
16995
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
16704
16996
|
return c.html(cachedHtml("public.html"));
|
|
16705
16997
|
});
|
|
16706
|
-
|
|
16998
|
+
app47.get("/chat", (c) => {
|
|
16707
16999
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
16708
17000
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
16709
17001
|
return c.html(cachedHtml("public.html"));
|
|
@@ -16722,12 +17014,12 @@ async function logViewerFetch(c, next) {
|
|
|
16722
17014
|
duration_ms: Date.now() - start
|
|
16723
17015
|
});
|
|
16724
17016
|
}
|
|
16725
|
-
|
|
16726
|
-
|
|
16727
|
-
|
|
17017
|
+
app47.use("/vnc-viewer.html", logViewerFetch);
|
|
17018
|
+
app47.use("/vnc-popout.html", logViewerFetch);
|
|
17019
|
+
app47.get("/vnc-popout.html", (c) => {
|
|
16728
17020
|
let html = htmlCache.get("vnc-popout.html");
|
|
16729
17021
|
if (!html) {
|
|
16730
|
-
html =
|
|
17022
|
+
html = readFileSync24(resolve27(process.cwd(), "public", "vnc-popout.html"), "utf-8");
|
|
16731
17023
|
const name = escapeHtml(BRAND.productName);
|
|
16732
17024
|
html = html.replace("<title>Browser \u2014 Maxy</title>", `<title>${name}</title>`);
|
|
16733
17025
|
html = html.replace("</head>", ` ${brandScript}
|
|
@@ -16737,7 +17029,7 @@ app45.get("/vnc-popout.html", (c) => {
|
|
|
16737
17029
|
}
|
|
16738
17030
|
return c.html(html);
|
|
16739
17031
|
});
|
|
16740
|
-
|
|
17032
|
+
app47.post("/api/vnc/client-event", async (c) => {
|
|
16741
17033
|
let body;
|
|
16742
17034
|
try {
|
|
16743
17035
|
body = await c.req.json();
|
|
@@ -16758,30 +17050,30 @@ app45.post("/api/vnc/client-event", async (c) => {
|
|
|
16758
17050
|
});
|
|
16759
17051
|
return c.json({ ok: true });
|
|
16760
17052
|
});
|
|
16761
|
-
|
|
17053
|
+
app47.get("/g/:slug", (c) => {
|
|
16762
17054
|
return c.html(brandedPublicHtml());
|
|
16763
17055
|
});
|
|
16764
|
-
|
|
17056
|
+
app47.get("/graph", (c) => {
|
|
16765
17057
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
16766
17058
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
16767
17059
|
return c.html(cachedHtml("graph.html"));
|
|
16768
17060
|
});
|
|
16769
|
-
|
|
17061
|
+
app47.get("/sessions", (c) => {
|
|
16770
17062
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
16771
17063
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
16772
17064
|
return c.html(cachedHtml("sessions.html"));
|
|
16773
17065
|
});
|
|
16774
|
-
|
|
17066
|
+
app47.get("/data", (c) => {
|
|
16775
17067
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
16776
17068
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
16777
17069
|
return c.html(cachedHtml("data.html"));
|
|
16778
17070
|
});
|
|
16779
|
-
|
|
17071
|
+
app47.get("/browser", (c) => {
|
|
16780
17072
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
16781
17073
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
16782
17074
|
return c.html(cachedHtml("browser.html"));
|
|
16783
17075
|
});
|
|
16784
|
-
|
|
17076
|
+
app47.get("/:slug", async (c, next) => {
|
|
16785
17077
|
const slug = c.req.param("slug");
|
|
16786
17078
|
if (AGENT_SLUG_PATTERN.test(`/${slug}`)) {
|
|
16787
17079
|
const account = resolveAccount();
|
|
@@ -16796,13 +17088,13 @@ app45.get("/:slug", async (c, next) => {
|
|
|
16796
17088
|
await next();
|
|
16797
17089
|
});
|
|
16798
17090
|
if (brandFaviconPath !== "/favicon.ico") {
|
|
16799
|
-
|
|
17091
|
+
app47.get("/favicon.ico", (c) => {
|
|
16800
17092
|
c.header("Cache-Control", "public, max-age=300");
|
|
16801
17093
|
return c.redirect(brandFaviconPath, 302);
|
|
16802
17094
|
});
|
|
16803
17095
|
}
|
|
16804
|
-
|
|
16805
|
-
|
|
17096
|
+
app47.use("/*", serveStatic({ root: "./public" }));
|
|
17097
|
+
app47.all("*", (c) => {
|
|
16806
17098
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
16807
17099
|
const path2 = c.req.path;
|
|
16808
17100
|
if (isPublicHost(host)) {
|
|
@@ -16816,7 +17108,7 @@ app45.all("*", (c) => {
|
|
|
16816
17108
|
});
|
|
16817
17109
|
var port = requirePortEnv("MAXY_UI_INTERNAL_PORT", { tag: "ui-server" });
|
|
16818
17110
|
var hostname = process.env.HOSTNAME ?? "127.0.0.1";
|
|
16819
|
-
var httpServer = serve({ fetch:
|
|
17111
|
+
var httpServer = serve({ fetch: app47.fetch, port, hostname });
|
|
16820
17112
|
console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
16821
17113
|
startAuthHealthHeartbeat();
|
|
16822
17114
|
{
|
|
@@ -16839,6 +17131,7 @@ var SUBAPP_MANIFEST = [
|
|
|
16839
17131
|
{ prefix: "/api/chat", file: "server/routes/chat.ts", subapp: chat_default },
|
|
16840
17132
|
{ prefix: "/api/whatsapp", file: "server/routes/whatsapp.ts", subapp: whatsapp_default },
|
|
16841
17133
|
{ prefix: "/api/whatsapp-reader", file: "server/routes/whatsapp-reader.ts", subapp: whatsapp_reader_default },
|
|
17134
|
+
{ prefix: "/api/telegram", file: "server/routes/telegram.ts", subapp: telegram_default },
|
|
16842
17135
|
{ prefix: "/api/onboarding", file: "server/routes/onboarding.ts", subapp: onboarding_default },
|
|
16843
17136
|
{ prefix: "/api/admin", file: "server/routes/admin/index.ts", subapp: admin_default },
|
|
16844
17137
|
{ prefix: "/api/access", file: "server/routes/access/index.ts", subapp: access_default },
|
|
@@ -16854,7 +17147,7 @@ for (const m of SUBAPP_MANIFEST) {
|
|
|
16854
17147
|
}
|
|
16855
17148
|
try {
|
|
16856
17149
|
const registered = [];
|
|
16857
|
-
for (const r of
|
|
17150
|
+
for (const r of app47.routes ?? []) {
|
|
16858
17151
|
if (typeof r.path !== "string" || r.path.includes(":") || r.path.includes("*")) continue;
|
|
16859
17152
|
if (AGENT_SLUG_PATTERN.test(r.path)) {
|
|
16860
17153
|
registered.push({ method: (r.method ?? "ALL").toUpperCase(), path: r.path });
|
|
@@ -16882,11 +17175,11 @@ try {
|
|
|
16882
17175
|
var ADMINUSER_RECONCILE_INTERVAL_MS = 60 * 60 * 1e3;
|
|
16883
17176
|
async function runAdminUserReconcileTick() {
|
|
16884
17177
|
try {
|
|
16885
|
-
if (!
|
|
17178
|
+
if (!existsSync24(USERS_FILE)) {
|
|
16886
17179
|
console.error("[adminuser-self-heal] skip reason=no-users-file");
|
|
16887
17180
|
return;
|
|
16888
17181
|
}
|
|
16889
|
-
const usersRaw =
|
|
17182
|
+
const usersRaw = readFileSync24(USERS_FILE, "utf-8").trim();
|
|
16890
17183
|
if (!usersRaw) {
|
|
16891
17184
|
console.error("[adminuser-self-heal] skip reason=empty-users-file");
|
|
16892
17185
|
return;
|
|
@@ -16936,6 +17229,9 @@ try {
|
|
|
16936
17229
|
}
|
|
16937
17230
|
var configDirForWhatsApp = basename7(MAXY_DIR) || ".maxy";
|
|
16938
17231
|
var bootAccount = resolveAccount();
|
|
17232
|
+
if (bootAccount) {
|
|
17233
|
+
migrateRemovedConfigKeys(bootAccount.accountDir);
|
|
17234
|
+
}
|
|
16939
17235
|
var bootAccountConfig = bootAccount?.config;
|
|
16940
17236
|
var bootPublicAgent = bootAccount ? resolvePublicAgent(bootAccount.accountDir, { accountId: bootAccount.accountId })?.slug ?? null : null;
|
|
16941
17237
|
var bootEntitlement = bootAccountConfig ? resolveEntitlement(
|
|
@@ -16993,7 +17289,7 @@ if (bootAccountConfig?.whatsapp) {
|
|
|
16993
17289
|
}
|
|
16994
17290
|
init({
|
|
16995
17291
|
configDir: configDirForWhatsApp,
|
|
16996
|
-
platformRoot:
|
|
17292
|
+
platformRoot: resolve27(process.env.MAXY_PLATFORM_ROOT ?? join19(__dirname, "..")),
|
|
16997
17293
|
accountConfig: bootAccountConfig,
|
|
16998
17294
|
onMessage: async (msg) => {
|
|
16999
17295
|
if (msg.isOwnerMirror) {
|