@rubytech/create-maxy-code 0.1.501 → 0.1.502
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/docs/superpowers/plans/2026-07-25-task-1974-uploads-intake-inbox.md +235 -0
- package/payload/platform/docs/superpowers/plans/2026-07-25-task-1976-intra-folder-hygiene.md +215 -0
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +2 -2
- package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +7 -0
- package/payload/platform/plugins/docs/references/internals.md +1 -1
- package/payload/platform/templates/account-schema/SCHEMA.md +36 -1
- package/payload/platform/templates/specialists/agents/data-manager.md +4 -2
- package/payload/server/public/activity.html +5 -5
- package/payload/server/public/assets/AdminLoginScreens-Bv_bKKeL.js +1 -0
- package/payload/server/public/assets/AdminShell-Gq8DU_ig.js +2 -0
- package/payload/server/public/assets/{activity-CVdVSw5V.js → activity-DZFYDHNA.js} +1 -1
- package/payload/server/public/assets/{admin-If1QLlS3.js → admin-DLUOixl6.js} +1 -1
- package/payload/server/public/assets/{bot-8b26IlQY.js → bot-CrEhKW1l.js} +1 -1
- package/payload/server/public/assets/{browser-F40DXfKA.js → browser-Bt4-LKLU.js} +1 -1
- package/payload/server/public/assets/{calendar-DZiHiBwV.js → calendar-D0qIvLUR.js} +1 -1
- package/payload/server/public/assets/chat-geSkx0j2.js +1 -0
- package/payload/server/public/assets/chevron-left-CQ8rcBoO.js +1 -0
- package/payload/server/public/assets/chevron-right-CSRSqblN.js +1 -0
- package/payload/server/public/assets/clock-B7Ba8AZL.js +1 -0
- package/payload/server/public/assets/data-BdlGqjKM.js +1 -0
- package/payload/server/public/assets/{file-text-B1HjPFbM.js → file-text-BpLcZKld.js} +1 -1
- package/payload/server/public/assets/{graph-CIC-mgKR.js → graph-HB0199x-.js} +3 -3
- package/payload/server/public/assets/{graph-labels-BnpHCHaQ.js → graph-labels-Bx19ZYvJ.js} +1 -1
- package/payload/server/public/assets/{maximize-2-BL7QVTcQ.js → maximize-2-BhR-Ec21.js} +1 -1
- package/payload/server/public/assets/operator-DejfJlvi.js +1 -0
- package/payload/server/public/assets/page-DomkejEB.js +32 -0
- package/payload/server/public/assets/page-FnCmAeHc.js +1 -0
- package/payload/server/public/assets/{public-BI21tOkm.js → public-Be_Galv6.js} +1 -1
- package/payload/server/public/assets/{rotate-ccw-C_20Bc3E.js → rotate-ccw-D9qOBLig.js} +1 -1
- package/payload/server/public/assets/{routines-Ci3N8wqV.js → routines-lGiYaMiX.js} +1 -1
- package/payload/server/public/assets/{skills-CiflzOko.js → skills-D9nWOqoz.js} +1 -1
- package/payload/server/public/assets/{tasks-DC2Yf2Ev.js → tasks-Cyc1EfLA.js} +1 -1
- package/payload/server/public/assets/{time-entry-format-CNcjs2HV.js → time-entry-format-RkCW7hKu.js} +1 -1
- package/payload/server/public/assets/{triangle-alert-CngnWtjD.js → triangle-alert-k8ulav-N.js} +1 -1
- package/payload/server/public/assets/{useCopyFeedback-DZ9Bw5CI.js → useCopyFeedback-DN1WA5vU.js} +1 -1
- package/payload/server/public/assets/useSubAccountSwitcher-fvBunpOC.css +1 -0
- package/payload/server/public/assets/useSubAccountSwitcher-iQGqNJhI.js +9 -0
- package/payload/server/public/assets/useVoiceRecorder-v--TIxaM.js +2 -0
- package/payload/server/public/assets/{wrench-dky2-13x.js → wrench-CKhz8KnQ.js} +1 -1
- package/payload/server/public/browser.html +4 -4
- package/payload/server/public/calendar.html +7 -7
- package/payload/server/public/chat.html +14 -14
- package/payload/server/public/data.html +11 -11
- package/payload/server/public/graph.html +9 -9
- package/payload/server/public/index.html +15 -15
- package/payload/server/public/operator.html +15 -15
- package/payload/server/public/public.html +14 -14
- package/payload/server/public/routines.html +6 -6
- package/payload/server/public/skills.html +5 -5
- package/payload/server/public/tasks.html +6 -6
- package/payload/server/server.js +840 -748
- package/payload/server/public/assets/AdminLoginScreens-C3LZOPIY.js +0 -1
- package/payload/server/public/assets/AdminShell-BlbUNAPc.js +0 -2
- package/payload/server/public/assets/chat-uD28FVCS.js +0 -1
- package/payload/server/public/assets/chevron-left-lBxD57tD.js +0 -1
- package/payload/server/public/assets/chevron-right-C-lDig9Y.js +0 -1
- package/payload/server/public/assets/clock-DqRNsY40.js +0 -1
- package/payload/server/public/assets/data-BsFyBN85.js +0 -1
- package/payload/server/public/assets/operator-B62h_TaC.js +0 -1
- package/payload/server/public/assets/page-BUUBseJZ.js +0 -32
- package/payload/server/public/assets/page-Bw-tYjw7.js +0 -1
- package/payload/server/public/assets/useSubAccountSwitcher-CHwQhkaI.js +0 -9
- package/payload/server/public/assets/useSubAccountSwitcher-yFQqnpQ8.css +0 -1
- package/payload/server/public/assets/useVoiceRecorder-C3G6aqZr.js +0 -2
package/payload/server/server.js
CHANGED
|
@@ -1753,10 +1753,10 @@ var serveStatic = (options = { root: "" }) => {
|
|
|
1753
1753
|
};
|
|
1754
1754
|
|
|
1755
1755
|
// server/index.ts
|
|
1756
|
-
import { readFileSync as readFileSync46, existsSync as
|
|
1756
|
+
import { readFileSync as readFileSync46, existsSync as existsSync45, watchFile, readdirSync as readdirSync27, statSync as statSync20 } from "fs";
|
|
1757
1757
|
import { spawn as spawn3 } from "child_process";
|
|
1758
1758
|
import { createHash as createHash7 } from "crypto";
|
|
1759
|
-
import { resolve as
|
|
1759
|
+
import { resolve as resolve43, join as join47, basename as basename14 } from "path";
|
|
1760
1760
|
import { homedir as homedir4 } from "os";
|
|
1761
1761
|
import { monitorEventLoopDelay } from "perf_hooks";
|
|
1762
1762
|
|
|
@@ -3030,7 +3030,7 @@ var credsSaveQueue = Promise.resolve();
|
|
|
3030
3030
|
async function drainCredsSaveQueue(timeoutMs = 5e3) {
|
|
3031
3031
|
console.error(`${TAG6} draining credential save queue\u2026`);
|
|
3032
3032
|
const timer = new Promise(
|
|
3033
|
-
(
|
|
3033
|
+
(resolve44) => setTimeout(() => resolve44("timeout"), timeoutMs)
|
|
3034
3034
|
);
|
|
3035
3035
|
const result = await Promise.race([
|
|
3036
3036
|
credsSaveQueue.then(() => "drained"),
|
|
@@ -3207,11 +3207,11 @@ async function createWaSocket(opts) {
|
|
|
3207
3207
|
return sock;
|
|
3208
3208
|
}
|
|
3209
3209
|
async function waitForConnection(sock) {
|
|
3210
|
-
return new Promise((
|
|
3210
|
+
return new Promise((resolve44, reject) => {
|
|
3211
3211
|
const handler = (update) => {
|
|
3212
3212
|
if (update.connection === "open") {
|
|
3213
3213
|
sock.ev.off("connection.update", handler);
|
|
3214
|
-
|
|
3214
|
+
resolve44();
|
|
3215
3215
|
}
|
|
3216
3216
|
if (update.connection === "close") {
|
|
3217
3217
|
sock.ev.off("connection.update", handler);
|
|
@@ -3319,7 +3319,7 @@ function isTimeoutError(err) {
|
|
|
3319
3319
|
return Boolean(err?.__maxyTimeout);
|
|
3320
3320
|
}
|
|
3321
3321
|
function withTimeout(label, promise, timeoutMs) {
|
|
3322
|
-
return new Promise((
|
|
3322
|
+
return new Promise((resolve44, reject) => {
|
|
3323
3323
|
const timer = setTimeout(() => {
|
|
3324
3324
|
const err = new Error(`${label} timed out after ${timeoutMs}ms`);
|
|
3325
3325
|
err.__maxyTimeout = true;
|
|
@@ -3329,7 +3329,7 @@ function withTimeout(label, promise, timeoutMs) {
|
|
|
3329
3329
|
promise.then(
|
|
3330
3330
|
(value) => {
|
|
3331
3331
|
clearTimeout(timer);
|
|
3332
|
-
|
|
3332
|
+
resolve44(value);
|
|
3333
3333
|
},
|
|
3334
3334
|
(err) => {
|
|
3335
3335
|
clearTimeout(timer);
|
|
@@ -4394,8 +4394,8 @@ async function persistWhatsAppMessage(input) {
|
|
|
4394
4394
|
const { givenName, familyName } = splitName(input.pushName);
|
|
4395
4395
|
const prev = sessionWriteLocks.get(input.cacheKey);
|
|
4396
4396
|
let release;
|
|
4397
|
-
const mine = new Promise((
|
|
4398
|
-
release =
|
|
4397
|
+
const mine = new Promise((resolve44) => {
|
|
4398
|
+
release = resolve44;
|
|
4399
4399
|
});
|
|
4400
4400
|
const chained = (prev ?? Promise.resolve()).then(() => mine);
|
|
4401
4401
|
sessionWriteLocks.set(input.cacheKey, chained);
|
|
@@ -6132,11 +6132,11 @@ async function connectWithReconnect(conn) {
|
|
|
6132
6132
|
console.error(
|
|
6133
6133
|
`${TAG17} reconnecting account=${conn.accountId} in ${delay}ms (attempt ${decision.nextAttempts}/${maxAttempts})`
|
|
6134
6134
|
);
|
|
6135
|
-
await new Promise((
|
|
6136
|
-
const timer = setTimeout(
|
|
6135
|
+
await new Promise((resolve44) => {
|
|
6136
|
+
const timer = setTimeout(resolve44, delay);
|
|
6137
6137
|
conn.abortController.signal.addEventListener("abort", () => {
|
|
6138
6138
|
clearTimeout(timer);
|
|
6139
|
-
|
|
6139
|
+
resolve44();
|
|
6140
6140
|
}, { once: true });
|
|
6141
6141
|
});
|
|
6142
6142
|
}
|
|
@@ -6144,16 +6144,16 @@ async function connectWithReconnect(conn) {
|
|
|
6144
6144
|
}
|
|
6145
6145
|
}
|
|
6146
6146
|
function waitForDisconnectEvent(conn) {
|
|
6147
|
-
return new Promise((
|
|
6147
|
+
return new Promise((resolve44) => {
|
|
6148
6148
|
if (!conn.sock) {
|
|
6149
|
-
|
|
6149
|
+
resolve44();
|
|
6150
6150
|
return;
|
|
6151
6151
|
}
|
|
6152
6152
|
const sock = conn.sock;
|
|
6153
6153
|
const handler = (update) => {
|
|
6154
6154
|
if (update.connection === "close") {
|
|
6155
6155
|
sock.ev.off("connection.update", handler);
|
|
6156
|
-
|
|
6156
|
+
resolve44();
|
|
6157
6157
|
}
|
|
6158
6158
|
};
|
|
6159
6159
|
sock.ev.on("connection.update", handler);
|
|
@@ -6627,8 +6627,8 @@ async function handleInboundMessage(conn, msg) {
|
|
|
6627
6627
|
const conversationKey = isGroup ? remoteJid : senderPhone;
|
|
6628
6628
|
const debounceKey = `${conn.accountId}:${conversationKey}:${senderPhone}`;
|
|
6629
6629
|
let resolvePending;
|
|
6630
|
-
const sttPending = new Promise((
|
|
6631
|
-
resolvePending =
|
|
6630
|
+
const sttPending = new Promise((resolve44) => {
|
|
6631
|
+
resolvePending = resolve44;
|
|
6632
6632
|
});
|
|
6633
6633
|
if (conn.debouncer) conn.debouncer.registerPending(debounceKey, sttPending);
|
|
6634
6634
|
try {
|
|
@@ -7017,20 +7017,20 @@ function buildX11Env(chromiumWrapperPath, transport = "vnc") {
|
|
|
7017
7017
|
|
|
7018
7018
|
// server/routes/health.ts
|
|
7019
7019
|
function checkPort(port2, timeoutMs = 500) {
|
|
7020
|
-
return new Promise((
|
|
7020
|
+
return new Promise((resolve44) => {
|
|
7021
7021
|
const socket = createConnection2(port2, "127.0.0.1");
|
|
7022
7022
|
socket.setTimeout(timeoutMs);
|
|
7023
7023
|
socket.once("connect", () => {
|
|
7024
7024
|
socket.destroy();
|
|
7025
|
-
|
|
7025
|
+
resolve44(true);
|
|
7026
7026
|
});
|
|
7027
7027
|
socket.once("error", () => {
|
|
7028
7028
|
socket.destroy();
|
|
7029
|
-
|
|
7029
|
+
resolve44(false);
|
|
7030
7030
|
});
|
|
7031
7031
|
socket.once("timeout", () => {
|
|
7032
7032
|
socket.destroy();
|
|
7033
|
-
|
|
7033
|
+
resolve44(false);
|
|
7034
7034
|
});
|
|
7035
7035
|
});
|
|
7036
7036
|
}
|
|
@@ -7285,8 +7285,8 @@ function webchatTurnTimeoutMs() {
|
|
|
7285
7285
|
return Number(process.env.WEBCHAT_TURN_TIMEOUT_MS ?? String(2 * 6e4));
|
|
7286
7286
|
}
|
|
7287
7287
|
function createChatRoutes(deps) {
|
|
7288
|
-
const
|
|
7289
|
-
|
|
7288
|
+
const app68 = new Hono();
|
|
7289
|
+
app68.post("/", async (c) => {
|
|
7290
7290
|
console.log(`[chat-route] entered route=public method=POST`);
|
|
7291
7291
|
const contentType = c.req.header("content-type") ?? "";
|
|
7292
7292
|
const account = resolveAccount();
|
|
@@ -7550,7 +7550,7 @@ ${result.result.text}` : result.result.text;
|
|
|
7550
7550
|
}
|
|
7551
7551
|
});
|
|
7552
7552
|
});
|
|
7553
|
-
return
|
|
7553
|
+
return app68;
|
|
7554
7554
|
}
|
|
7555
7555
|
|
|
7556
7556
|
// app/lib/channel-pty-bridge/admin-session-id.ts
|
|
@@ -7584,8 +7584,8 @@ function isLoopbackAddr(addr) {
|
|
|
7584
7584
|
return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
|
|
7585
7585
|
}
|
|
7586
7586
|
function createScheduleInjectRoutes(deps) {
|
|
7587
|
-
const
|
|
7588
|
-
|
|
7587
|
+
const app68 = new Hono();
|
|
7588
|
+
app68.post("/", async (c) => {
|
|
7589
7589
|
const env = c.env;
|
|
7590
7590
|
const remoteAddr = env?.incoming?.socket?.remoteAddress ?? "";
|
|
7591
7591
|
if (!isLoopbackAddr(remoteAddr)) {
|
|
@@ -7686,7 +7686,7 @@ function createScheduleInjectRoutes(deps) {
|
|
|
7686
7686
|
console.error(`${TAG20} op=inject-spawn eventId=${eventId} sessionId=${sessionId} result=ok status=-`);
|
|
7687
7687
|
return c.json({ ok: true }, 200);
|
|
7688
7688
|
});
|
|
7689
|
-
return
|
|
7689
|
+
return app68;
|
|
7690
7690
|
}
|
|
7691
7691
|
|
|
7692
7692
|
// server/index.ts
|
|
@@ -8369,8 +8369,8 @@ async function startLogin(opts) {
|
|
|
8369
8369
|
await clearAuth(authDir);
|
|
8370
8370
|
let resolveCode = null;
|
|
8371
8371
|
let rejectCode = null;
|
|
8372
|
-
const codePromise = new Promise((
|
|
8373
|
-
resolveCode =
|
|
8372
|
+
const codePromise = new Promise((resolve44, reject) => {
|
|
8373
|
+
resolveCode = resolve44;
|
|
8374
8374
|
rejectCode = reject;
|
|
8375
8375
|
});
|
|
8376
8376
|
const codeTimer = setTimeout(
|
|
@@ -11164,8 +11164,8 @@ function runReconcileLivenessAudit(statePath, nowMs, intervalMs, emit) {
|
|
|
11164
11164
|
}
|
|
11165
11165
|
|
|
11166
11166
|
// server/routes/whatsapp-reader.ts
|
|
11167
|
-
import { readFileSync as readFileSync21, watch, statSync as
|
|
11168
|
-
import { basename as
|
|
11167
|
+
import { readFileSync as readFileSync21, watch, statSync as statSync8, openSync, readSync, closeSync, existsSync as existsSync17, readdirSync as readdirSync14, realpathSync as realpathSync6 } from "fs";
|
|
11168
|
+
import { basename as basename6, dirname as dirname7, isAbsolute, join as join21, relative as relative3, resolve as resolve16, sep as sep5 } from "path";
|
|
11169
11169
|
|
|
11170
11170
|
// server/routes/admin/sidebar-sessions.ts
|
|
11171
11171
|
import { readdirSync as readdirSync12, readFileSync as readFileSync19, statSync as statSync6 } from "fs";
|
|
@@ -11184,11 +11184,11 @@ function findExistingJsonlForSessionId(claudeConfigDir2, sessionId) {
|
|
|
11184
11184
|
} catch {
|
|
11185
11185
|
return null;
|
|
11186
11186
|
}
|
|
11187
|
-
const
|
|
11187
|
+
const basename15 = `${sessionId}.jsonl`;
|
|
11188
11188
|
for (const slug of slugs) {
|
|
11189
|
-
const live = join17(projectsRoot, slug,
|
|
11189
|
+
const live = join17(projectsRoot, slug, basename15);
|
|
11190
11190
|
if (existsSync14(live)) return live;
|
|
11191
|
-
const archived = join17(projectsRoot, slug, "archive",
|
|
11191
|
+
const archived = join17(projectsRoot, slug, "archive", basename15);
|
|
11192
11192
|
if (existsSync14(archived)) return archived;
|
|
11193
11193
|
}
|
|
11194
11194
|
return null;
|
|
@@ -11982,8 +11982,8 @@ function parseTranscript(lines, queuedPendingSuppress = /* @__PURE__ */ new Map(
|
|
|
11982
11982
|
}
|
|
11983
11983
|
|
|
11984
11984
|
// app/lib/whatsapp-reader/enrich-attachments.ts
|
|
11985
|
-
import { readFileSync as readFileSync20, readdirSync as readdirSync13 } from "fs";
|
|
11986
|
-
import { join as join20 } from "path";
|
|
11985
|
+
import { readFileSync as readFileSync20, readdirSync as readdirSync13, existsSync as existsSync16, statSync as statSync7, realpathSync as realpathSync5 } from "fs";
|
|
11986
|
+
import { basename as basename5, dirname as dirname6, join as join20, resolve as resolve15, sep as sep4 } from "path";
|
|
11987
11987
|
var ADMIN_UPLOAD_PATH = /\/uploads\/(?!public\/)([0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12})\//gi;
|
|
11988
11988
|
function adminAttachmentIds(text) {
|
|
11989
11989
|
const ids = [];
|
|
@@ -12001,6 +12001,48 @@ function adminAttachmentsFromText(text, uploadsBase) {
|
|
|
12001
12001
|
}
|
|
12002
12002
|
return out;
|
|
12003
12003
|
}
|
|
12004
|
+
function claudeUploadsRoot() {
|
|
12005
|
+
return process.env.CLAUDE_CONFIG_DIR ? resolve15(process.env.CLAUDE_CONFIG_DIR, "uploads") : null;
|
|
12006
|
+
}
|
|
12007
|
+
var CC_MENTION_RE = /@"([^"]+)"/g;
|
|
12008
|
+
function claudeUploadAttachmentsFromText(text, sessionId) {
|
|
12009
|
+
const root = claudeUploadsRoot();
|
|
12010
|
+
if (!root) return { attachments: [], strippedText: text };
|
|
12011
|
+
const sessionDir = resolve15(root, sessionId);
|
|
12012
|
+
const attachments = [];
|
|
12013
|
+
const accepted = [];
|
|
12014
|
+
for (const m of text.matchAll(CC_MENTION_RE)) {
|
|
12015
|
+
let abs;
|
|
12016
|
+
try {
|
|
12017
|
+
abs = resolve15(m[1]);
|
|
12018
|
+
} catch {
|
|
12019
|
+
continue;
|
|
12020
|
+
}
|
|
12021
|
+
if (dirname6(abs) !== sessionDir) continue;
|
|
12022
|
+
if (abs !== sessionDir + sep4 + basename5(abs)) continue;
|
|
12023
|
+
if (!existsSync16(abs)) continue;
|
|
12024
|
+
let real;
|
|
12025
|
+
try {
|
|
12026
|
+
real = realpathSync5(abs);
|
|
12027
|
+
} catch {
|
|
12028
|
+
continue;
|
|
12029
|
+
}
|
|
12030
|
+
if (dirname6(real) !== realpathSync5(sessionDir)) continue;
|
|
12031
|
+
const filename = basename5(abs);
|
|
12032
|
+
attachments.push({
|
|
12033
|
+
attachmentId: filename,
|
|
12034
|
+
filename,
|
|
12035
|
+
mimeType: detectMimeType(filename),
|
|
12036
|
+
sizeBytes: statSync7(real).size,
|
|
12037
|
+
source: "claude-upload"
|
|
12038
|
+
});
|
|
12039
|
+
accepted.push(m[0]);
|
|
12040
|
+
}
|
|
12041
|
+
if (accepted.length === 0) return { attachments, strippedText: text };
|
|
12042
|
+
let strippedText = text;
|
|
12043
|
+
for (const tok of accepted) strippedText = strippedText.split(tok).join("");
|
|
12044
|
+
return { attachments, strippedText: strippedText.trim() };
|
|
12045
|
+
}
|
|
12004
12046
|
function readSidecar(dir, attachmentId) {
|
|
12005
12047
|
let parsed;
|
|
12006
12048
|
try {
|
|
@@ -12198,8 +12240,8 @@ app5.get("/conversations", requireAdminSession, async (c) => {
|
|
|
12198
12240
|
const rows = [];
|
|
12199
12241
|
let sessionRowsExcludedUntagged = 0;
|
|
12200
12242
|
for (const { path: path3 } of enumerateJsonls(projectsRoot)) {
|
|
12201
|
-
const sessionId =
|
|
12202
|
-
const projectDir =
|
|
12243
|
+
const sessionId = basename6(path3).replace(/\.jsonl$/, "");
|
|
12244
|
+
const projectDir = dirname7(path3);
|
|
12203
12245
|
const meta = readSidecarMeta(join21(projectDir, `${sessionId}.meta.json`));
|
|
12204
12246
|
if (!isReaderChannelSession(meta.role, meta.channel)) continue;
|
|
12205
12247
|
if (multiAccount) {
|
|
@@ -12337,8 +12379,8 @@ app5.get("/conversations-all", requireAdminSession, async (c) => {
|
|
|
12337
12379
|
const houseIds = new Set(validAccounts.filter((a) => a.config.role === "house").map((a) => a.accountId));
|
|
12338
12380
|
const rawByAccount = /* @__PURE__ */ new Map();
|
|
12339
12381
|
for (const { path: path3 } of enumerateJsonls(projectsRoot)) {
|
|
12340
|
-
const sessionId =
|
|
12341
|
-
const projectDir =
|
|
12382
|
+
const sessionId = basename6(path3).replace(/\.jsonl$/, "");
|
|
12383
|
+
const projectDir = dirname7(path3);
|
|
12342
12384
|
const meta = readSidecarMeta(join21(projectDir, `${sessionId}.meta.json`));
|
|
12343
12385
|
if (!isReaderChannelSession(meta.role, meta.channel)) continue;
|
|
12344
12386
|
if (meta.accountId === null || !validIds.has(meta.accountId)) continue;
|
|
@@ -12407,7 +12449,7 @@ app5.get("/conversations-all", requireAdminSession, async (c) => {
|
|
|
12407
12449
|
return c.json({ conversations });
|
|
12408
12450
|
});
|
|
12409
12451
|
function readFrom(path3, from) {
|
|
12410
|
-
const end =
|
|
12452
|
+
const end = statSync8(path3).size;
|
|
12411
12453
|
if (end <= from) return { buf: Buffer.alloc(0), end: from };
|
|
12412
12454
|
const fd = openSync(path3, "r");
|
|
12413
12455
|
try {
|
|
@@ -12431,7 +12473,7 @@ function enrichDownloads(turn, scratchpadRoot) {
|
|
|
12431
12473
|
if (turn.kind !== "agent-file") return turn;
|
|
12432
12474
|
let scratchpadReal = null;
|
|
12433
12475
|
try {
|
|
12434
|
-
scratchpadReal =
|
|
12476
|
+
scratchpadReal = realpathSync6(scratchpadRoot);
|
|
12435
12477
|
} catch {
|
|
12436
12478
|
scratchpadReal = null;
|
|
12437
12479
|
}
|
|
@@ -12442,8 +12484,8 @@ function enrichDownloads(turn, scratchpadRoot) {
|
|
|
12442
12484
|
}
|
|
12443
12485
|
if (scratchpadReal) {
|
|
12444
12486
|
try {
|
|
12445
|
-
const fileReal =
|
|
12446
|
-
if (fileReal === scratchpadReal || fileReal.startsWith(scratchpadReal +
|
|
12487
|
+
const fileReal = realpathSync6(f);
|
|
12488
|
+
if (fileReal === scratchpadReal || fileReal.startsWith(scratchpadReal + sep5)) {
|
|
12447
12489
|
return { root: "scratchpad", path: relative3(scratchpadReal, fileReal) };
|
|
12448
12490
|
}
|
|
12449
12491
|
} catch {
|
|
@@ -12454,13 +12496,19 @@ function enrichDownloads(turn, scratchpadRoot) {
|
|
|
12454
12496
|
});
|
|
12455
12497
|
return { ...turn, downloads };
|
|
12456
12498
|
}
|
|
12457
|
-
function enrichAdminAttachments(turn) {
|
|
12499
|
+
function enrichAdminAttachments(turn, sessionId) {
|
|
12458
12500
|
if (turn.kind !== "operator-inbound") return turn;
|
|
12459
|
-
if (adminAttachmentIds(turn.text).length === 0) return turn;
|
|
12501
|
+
if (!turn.text.includes('@"') && adminAttachmentIds(turn.text).length === 0) return turn;
|
|
12460
12502
|
const account = resolveAccount();
|
|
12461
|
-
|
|
12462
|
-
const
|
|
12463
|
-
|
|
12503
|
+
const store2 = account ? adminAttachmentsFromText(turn.text, resolve16(DATA_ROOT, "accounts", account.accountId, "uploads")) : [];
|
|
12504
|
+
const cc = claudeUploadAttachmentsFromText(turn.text, sessionId);
|
|
12505
|
+
if (cc.attachments.length > 0) {
|
|
12506
|
+
console.log(`[session-upload-shape] op=mention accepted=${cc.attachments.length} session=${sessionId.slice(0, 8)}`);
|
|
12507
|
+
}
|
|
12508
|
+
const attachments = [...store2, ...cc.attachments];
|
|
12509
|
+
if (attachments.length === 0) return turn;
|
|
12510
|
+
const text = cc.attachments.length > 0 ? cc.strippedText : turn.text;
|
|
12511
|
+
return { ...turn, attachments, text };
|
|
12464
12512
|
}
|
|
12465
12513
|
var CONCURRENCY_WINDOW_MS = 3e5;
|
|
12466
12514
|
var AGENT_JSONL_RE = /^agent-([0-9a-f]+)\.jsonl$/;
|
|
@@ -12527,7 +12575,7 @@ function runActivityTick(c) {
|
|
|
12527
12575
|
let size = 0;
|
|
12528
12576
|
let mtimeMs = 0;
|
|
12529
12577
|
try {
|
|
12530
|
-
const st =
|
|
12578
|
+
const st = statSync8(join21(c.subagentsDir, name));
|
|
12531
12579
|
size = st.size;
|
|
12532
12580
|
mtimeMs = st.mtimeMs;
|
|
12533
12581
|
} catch {
|
|
@@ -12572,12 +12620,12 @@ app5.get("/stream", requireAdminSession, (c) => {
|
|
|
12572
12620
|
const sessionId = c.req.query("sessionId") ?? "";
|
|
12573
12621
|
const projectDir = c.req.query("projectDir") ?? "";
|
|
12574
12622
|
const cfg = claudeConfigDir();
|
|
12575
|
-
const projectsRoot = cfg ?
|
|
12623
|
+
const projectsRoot = cfg ? resolve16(join21(cfg, "projects")) : null;
|
|
12576
12624
|
if (!cfg || !projectsRoot || !SESSION_ID_RE2.test(sessionId)) {
|
|
12577
12625
|
return c.json({ error: "bad session reference" }, 400);
|
|
12578
12626
|
}
|
|
12579
|
-
const jsonlPath =
|
|
12580
|
-
if (!jsonlPath.startsWith(projectsRoot +
|
|
12627
|
+
const jsonlPath = resolve16(join21(projectDir, `${sessionId}.jsonl`));
|
|
12628
|
+
if (!jsonlPath.startsWith(projectsRoot + sep5)) {
|
|
12581
12629
|
return c.json({ error: "bad session reference" }, 400);
|
|
12582
12630
|
}
|
|
12583
12631
|
const scratchpadRoot = sessionScratchpadRoot(projectDir, sessionId);
|
|
@@ -12595,7 +12643,7 @@ data: ${JSON.stringify(turn)}
|
|
|
12595
12643
|
start(controller) {
|
|
12596
12644
|
const fileEnd0 = (() => {
|
|
12597
12645
|
try {
|
|
12598
|
-
return
|
|
12646
|
+
return statSync8(jsonlPath).size;
|
|
12599
12647
|
} catch {
|
|
12600
12648
|
return 0;
|
|
12601
12649
|
}
|
|
@@ -12603,9 +12651,9 @@ data: ${JSON.stringify(turn)}
|
|
|
12603
12651
|
let offset = resumeOffset(lastEventId, fileEnd0);
|
|
12604
12652
|
console.log(`[wa-stream] op=open conn=${connId} sessionId=${sessionId} channel=reader resume=${offset}`);
|
|
12605
12653
|
const sessionKey = c.req.query("session_key") ?? "";
|
|
12606
|
-
const subagentsDir =
|
|
12654
|
+
const subagentsDir = resolve16(join21(projectDir, sessionId, "subagents"));
|
|
12607
12655
|
console.log(
|
|
12608
|
-
`[webchat-activity] op=watch-subagents key=${sessionKey} dir=${subagentsDir} exists=${
|
|
12656
|
+
`[webchat-activity] op=watch-subagents key=${sessionKey} dir=${subagentsDir} exists=${existsSync17(subagentsDir)}`
|
|
12609
12657
|
);
|
|
12610
12658
|
const actx = makeActivityCtx({
|
|
12611
12659
|
subagentsDir,
|
|
@@ -12631,7 +12679,7 @@ data: ${JSON.stringify(obj)}
|
|
|
12631
12679
|
offset = nextOffset;
|
|
12632
12680
|
let n = 0;
|
|
12633
12681
|
for (const turn of parseTranscript(lines, queuedPendingSuppress, turnCtx)) {
|
|
12634
|
-
send(controller, enrichAdminAttachments(enrichDownloads(turn, scratchpadRoot)), offset);
|
|
12682
|
+
send(controller, enrichAdminAttachments(enrichDownloads(turn, scratchpadRoot), sessionId), offset);
|
|
12635
12683
|
actx.lastParentTurns.push(turn);
|
|
12636
12684
|
if (turn.kind === "agent-error") {
|
|
12637
12685
|
console.log(`[wa-stream] op=agent-error conn=${connId} sessionId=${sessionId} code=${turn.code} source=jsonl`);
|
|
@@ -12651,7 +12699,7 @@ data: ${JSON.stringify(obj)}
|
|
|
12651
12699
|
offset = end;
|
|
12652
12700
|
let n = 0;
|
|
12653
12701
|
for (const turn of parseTranscript(buf.toString("utf8").split("\n"), queuedPendingSuppress, turnCtx)) {
|
|
12654
|
-
send(controller, enrichAdminAttachments(enrichDownloads(turn, scratchpadRoot)), offset);
|
|
12702
|
+
send(controller, enrichAdminAttachments(enrichDownloads(turn, scratchpadRoot), sessionId), offset);
|
|
12655
12703
|
actx.lastParentTurns.push(turn);
|
|
12656
12704
|
if (turn.kind === "agent-error") {
|
|
12657
12705
|
console.log(`[wa-stream] op=agent-error conn=${connId} sessionId=${sessionId} code=${turn.code} source=jsonl`);
|
|
@@ -12713,13 +12761,13 @@ var DIRECTIVE_NAME_RE = /^\d+-\d+\.txt$/;
|
|
|
12713
12761
|
function directiveStoreDir(sessionId) {
|
|
12714
12762
|
const account = resolveAccount();
|
|
12715
12763
|
if (!account) return null;
|
|
12716
|
-
return
|
|
12764
|
+
return resolve16(account.accountDir, "logs", "prompt-optimiser-directives", sessionId);
|
|
12717
12765
|
}
|
|
12718
12766
|
app5.get("/directives", requireAdminSession, (c) => {
|
|
12719
12767
|
const sessionId = c.req.query("sessionId") ?? "";
|
|
12720
12768
|
if (!SESSION_ID_RE2.test(sessionId)) return c.json({ error: "bad session reference" }, 400);
|
|
12721
12769
|
const dir = directiveStoreDir(sessionId);
|
|
12722
|
-
if (!dir || !
|
|
12770
|
+
if (!dir || !existsSync17(dir)) return c.json({ entries: [] });
|
|
12723
12771
|
let names;
|
|
12724
12772
|
try {
|
|
12725
12773
|
names = readdirSync14(dir).filter((n) => DIRECTIVE_NAME_RE.test(n));
|
|
@@ -12732,7 +12780,7 @@ app5.get("/directives", requireAdminSession, (c) => {
|
|
|
12732
12780
|
const pid = Number(pidPart);
|
|
12733
12781
|
let len = 0;
|
|
12734
12782
|
try {
|
|
12735
|
-
len =
|
|
12783
|
+
len = statSync8(join21(dir, name)).size;
|
|
12736
12784
|
} catch {
|
|
12737
12785
|
}
|
|
12738
12786
|
return { name, secs, pid, ts: Number.isFinite(secs) ? new Date(secs * 1e3).toISOString() : null, len };
|
|
@@ -12747,8 +12795,8 @@ app5.get("/directive", requireAdminSession, (c) => {
|
|
|
12747
12795
|
}
|
|
12748
12796
|
const dir = directiveStoreDir(sessionId);
|
|
12749
12797
|
if (!dir) return c.json({ error: "no account" }, 404);
|
|
12750
|
-
const path3 =
|
|
12751
|
-
if (!path3.startsWith(dir +
|
|
12798
|
+
const path3 = resolve16(join21(dir, name));
|
|
12799
|
+
if (!path3.startsWith(dir + sep5)) return c.json({ error: "bad reference" }, 400);
|
|
12752
12800
|
let body;
|
|
12753
12801
|
try {
|
|
12754
12802
|
body = readFileSync21(path3, "utf8");
|
|
@@ -12777,7 +12825,7 @@ app5.get("/store-stream", requireAdminSession, (c) => {
|
|
|
12777
12825
|
const connId = `${remoteJid.slice(0, 12)}-${process.hrtime.bigint().toString(36).slice(-6)}`;
|
|
12778
12826
|
const startedAt = Date.now();
|
|
12779
12827
|
const lastEventId = c.req.header("Last-Event-ID");
|
|
12780
|
-
const uploadsBase =
|
|
12828
|
+
const uploadsBase = resolve16(DATA_ROOT, "accounts", accountId, "uploads");
|
|
12781
12829
|
const byMsgKeyId = /* @__PURE__ */ new Map();
|
|
12782
12830
|
const reactionRecords = [];
|
|
12783
12831
|
const reactionsForTarget = (msgKeyId) => foldReactions(reactionRecords).get(msgKeyId);
|
|
@@ -12838,7 +12886,7 @@ data: ${JSON.stringify(payload)}
|
|
|
12838
12886
|
};
|
|
12839
12887
|
const fileEnd0 = (() => {
|
|
12840
12888
|
try {
|
|
12841
|
-
return
|
|
12889
|
+
return statSync8(file).size;
|
|
12842
12890
|
} catch {
|
|
12843
12891
|
return 0;
|
|
12844
12892
|
}
|
|
@@ -13056,7 +13104,7 @@ app5.post("/reply", requireAdminSession, async (c) => {
|
|
|
13056
13104
|
const absolute = resolved.absolute;
|
|
13057
13105
|
let size = -1;
|
|
13058
13106
|
try {
|
|
13059
|
-
const st =
|
|
13107
|
+
const st = statSync8(absolute);
|
|
13060
13108
|
size = st.isFile() ? st.size : -1;
|
|
13061
13109
|
} catch {
|
|
13062
13110
|
size = -1;
|
|
@@ -13069,7 +13117,7 @@ app5.post("/reply", requireAdminSession, async (c) => {
|
|
|
13069
13117
|
console.log(`${MANUAL_TAG} op=reply-file-ref sendId=${sendId} path=${ref} owner=${owner8} sendAccount=${acct8} sessionAccount=${sess8} via=${decision.via} reason=none ok=true`);
|
|
13070
13118
|
if (size > MAX_FILE_BYTES) {
|
|
13071
13119
|
exit("rejected");
|
|
13072
|
-
return c.json({ error: `"${
|
|
13120
|
+
return c.json({ error: `"${basename6(absolute)}" exceeds the 50 MB limit` }, 400);
|
|
13073
13121
|
}
|
|
13074
13122
|
const mime = detectMimeType(absolute);
|
|
13075
13123
|
if (!isMimeAdmitted(mime, SUPPORTED_MIME_SET)) {
|
|
@@ -13166,7 +13214,7 @@ app5.post("/reply", requireAdminSession, async (c) => {
|
|
|
13166
13214
|
}
|
|
13167
13215
|
for (let i = 0; i < resolvedRefs.length; i++) {
|
|
13168
13216
|
const { absolute, mime } = resolvedRefs[i];
|
|
13169
|
-
const file = new File([readFileSync21(absolute)],
|
|
13217
|
+
const file = new File([readFileSync21(absolute)], basename6(absolute), { type: mime });
|
|
13170
13218
|
const out = await sendStagedFile(file, `ref=${i}`);
|
|
13171
13219
|
if (!out.ok) {
|
|
13172
13220
|
exit("error");
|
|
@@ -13185,8 +13233,8 @@ app5.post("/reply", requireAdminSession, async (c) => {
|
|
|
13185
13233
|
var whatsapp_reader_default = app5;
|
|
13186
13234
|
|
|
13187
13235
|
// server/routes/public-reader.ts
|
|
13188
|
-
import { statSync as
|
|
13189
|
-
import { basename as
|
|
13236
|
+
import { statSync as statSync9, openSync as openSync2, readSync as readSync2, closeSync as closeSync2, watch as watch2, readFileSync as readFileSync22, readdirSync as readdirSync15 } from "fs";
|
|
13237
|
+
import { basename as basename7, dirname as dirname8, join as join22, resolve as resolve17, sep as sep6 } from "path";
|
|
13190
13238
|
|
|
13191
13239
|
// app/lib/whatsapp-reader/delivered-kinds.ts
|
|
13192
13240
|
var PUBLIC_DELIVERED_KINDS = /* @__PURE__ */ new Set([
|
|
@@ -13261,8 +13309,8 @@ function enumeratePublicRows() {
|
|
|
13261
13309
|
if (!cfg) return [];
|
|
13262
13310
|
const rows = [];
|
|
13263
13311
|
for (const { path: path3 } of enumerateJsonls(join22(cfg, "projects"))) {
|
|
13264
|
-
const sessionId =
|
|
13265
|
-
const projectDir =
|
|
13312
|
+
const sessionId = basename7(path3).replace(/\.jsonl$/, "");
|
|
13313
|
+
const projectDir = dirname8(path3);
|
|
13266
13314
|
const meta = readSidecarMeta(join22(projectDir, `${sessionId}.meta.json`));
|
|
13267
13315
|
rows.push({
|
|
13268
13316
|
sessionId,
|
|
@@ -13308,7 +13356,7 @@ app6.get("/session", (c) => {
|
|
|
13308
13356
|
return c.json({ sessionId: null, projectDir: null, sessionKey });
|
|
13309
13357
|
});
|
|
13310
13358
|
function publicUploadsDir(accountId, sessionId) {
|
|
13311
|
-
return
|
|
13359
|
+
return resolve17(DATA_ROOT, "accounts", accountId, "uploads", "public", sessionId);
|
|
13312
13360
|
}
|
|
13313
13361
|
function enrichPublicAttachments(turns, sessionAttachments, cursor) {
|
|
13314
13362
|
for (const turn of turns) {
|
|
@@ -13319,7 +13367,7 @@ function enrichPublicAttachments(turns, sessionAttachments, cursor) {
|
|
|
13319
13367
|
}
|
|
13320
13368
|
}
|
|
13321
13369
|
function readFrom2(path3, from) {
|
|
13322
|
-
const end =
|
|
13370
|
+
const end = statSync9(path3).size;
|
|
13323
13371
|
if (end <= from) return { buf: Buffer.alloc(0), end: from };
|
|
13324
13372
|
const fd = openSync2(path3, "r");
|
|
13325
13373
|
try {
|
|
@@ -13339,12 +13387,12 @@ app6.get("/stream", (c) => {
|
|
|
13339
13387
|
const sessionId = c.req.query("sessionId") ?? "";
|
|
13340
13388
|
const projectDir = c.req.query("projectDir") ?? "";
|
|
13341
13389
|
const cfg = claudeConfigDir();
|
|
13342
|
-
const projectsRoot = cfg ?
|
|
13390
|
+
const projectsRoot = cfg ? resolve17(join22(cfg, "projects")) : null;
|
|
13343
13391
|
if (!cfg || !projectsRoot || !SESSION_ID_RE2.test(sessionId)) {
|
|
13344
13392
|
return c.json({ error: "bad session reference" }, 400);
|
|
13345
13393
|
}
|
|
13346
|
-
const jsonlPath =
|
|
13347
|
-
if (!jsonlPath.startsWith(projectsRoot +
|
|
13394
|
+
const jsonlPath = resolve17(join22(projectDir, `${sessionId}.jsonl`));
|
|
13395
|
+
if (!jsonlPath.startsWith(projectsRoot + sep6)) {
|
|
13348
13396
|
return c.json({ error: "bad session reference" }, 400);
|
|
13349
13397
|
}
|
|
13350
13398
|
const meta = readSidecarMeta(join22(projectDir, `${sessionId}.meta.json`));
|
|
@@ -13447,8 +13495,8 @@ app6.get("/attachment/:attachmentId", (c) => {
|
|
|
13447
13495
|
return new Response("Not found", { status: 404 });
|
|
13448
13496
|
}
|
|
13449
13497
|
const uploadsRoot = publicUploadsDir(account.accountId, sessionId);
|
|
13450
|
-
const dir =
|
|
13451
|
-
if (!dir.startsWith(uploadsRoot +
|
|
13498
|
+
const dir = resolve17(uploadsRoot, attachmentId);
|
|
13499
|
+
if (!dir.startsWith(uploadsRoot + sep6)) {
|
|
13452
13500
|
console.error(`${ATT_TAG} op=denied session=${ses} att=${at} reason=bad-id`);
|
|
13453
13501
|
return new Response("Not found", { status: 404 });
|
|
13454
13502
|
}
|
|
@@ -13462,7 +13510,7 @@ app6.get("/attachment/:attachmentId", (c) => {
|
|
|
13462
13510
|
try {
|
|
13463
13511
|
dataFile = readdirSync15(dir).find((f) => !f.endsWith(".meta.json") && !f.endsWith(EXTRACTED_TEXT_SUFFIX));
|
|
13464
13512
|
if (!dataFile) throw new Error("no data file");
|
|
13465
|
-
buffer = readFileSync22(
|
|
13513
|
+
buffer = readFileSync22(resolve17(dir, dataFile));
|
|
13466
13514
|
} catch {
|
|
13467
13515
|
console.error(`${ATT_TAG} op=denied session=${ses} att=${at} reason=not-found`);
|
|
13468
13516
|
return new Response("Not found", { status: 404 });
|
|
@@ -13483,9 +13531,9 @@ app6.get("/attachment/:attachmentId", (c) => {
|
|
|
13483
13531
|
var public_reader_default = app6;
|
|
13484
13532
|
|
|
13485
13533
|
// server/routes/webchat.ts
|
|
13486
|
-
import { basename as
|
|
13534
|
+
import { basename as basename8, dirname as dirname9 } from "path";
|
|
13487
13535
|
import { join as join25 } from "path";
|
|
13488
|
-
import { existsSync as
|
|
13536
|
+
import { existsSync as existsSync19, readdirSync as readdirSync17, readFileSync as readFileSync25, renameSync as renameSync4, statSync as statSync10, writeFileSync as writeFileSync9 } from "fs";
|
|
13489
13537
|
|
|
13490
13538
|
// server/canonical-webchat-override.ts
|
|
13491
13539
|
import { readFileSync as readFileSync23, writeFileSync as writeFileSync7, renameSync as renameSync2 } from "fs";
|
|
@@ -13572,7 +13620,7 @@ function isNewSessionEffortLevel(value) {
|
|
|
13572
13620
|
}
|
|
13573
13621
|
|
|
13574
13622
|
// ../services/claude-session-manager/src/sidecar-store.ts
|
|
13575
|
-
import { existsSync as
|
|
13623
|
+
import { existsSync as existsSync18, mkdirSync as mkdirSync4, readdirSync as readdirSync16, readFileSync as readFileSync24, renameSync as renameSync3, unlinkSync as unlinkSync2, writeFileSync as writeFileSync8 } from "fs";
|
|
13576
13624
|
import { join as join24 } from "path";
|
|
13577
13625
|
function escapeRegExp(s) {
|
|
13578
13626
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -13593,7 +13641,7 @@ function createSidecarStore(config) {
|
|
|
13593
13641
|
return { ok: true };
|
|
13594
13642
|
} catch (error) {
|
|
13595
13643
|
try {
|
|
13596
|
-
if (
|
|
13644
|
+
if (existsSync18(tmp)) unlinkSync2(tmp);
|
|
13597
13645
|
} catch {
|
|
13598
13646
|
}
|
|
13599
13647
|
return { ok: false, error };
|
|
@@ -13649,7 +13697,7 @@ function createSidecarStore(config) {
|
|
|
13649
13697
|
function clear(sessionsDir, id) {
|
|
13650
13698
|
const path3 = pathFor(sessionsDir, id);
|
|
13651
13699
|
try {
|
|
13652
|
-
if (
|
|
13700
|
+
if (existsSync18(path3)) {
|
|
13653
13701
|
unlinkSync2(path3);
|
|
13654
13702
|
return { ok: true, removed: true };
|
|
13655
13703
|
}
|
|
@@ -13717,7 +13765,7 @@ function locateSidecar(sessionId) {
|
|
|
13717
13765
|
}
|
|
13718
13766
|
for (const slug of slugs) {
|
|
13719
13767
|
const metaPath = join25(projectsRoot, slug, `${sessionId}.meta.json`);
|
|
13720
|
-
if (
|
|
13768
|
+
if (existsSync19(metaPath)) return readSidecarMeta(metaPath);
|
|
13721
13769
|
}
|
|
13722
13770
|
return null;
|
|
13723
13771
|
}
|
|
@@ -13747,7 +13795,7 @@ function sessionSidecarExists(sessionId) {
|
|
|
13747
13795
|
function jsonlSizeBytes(projectDir, sessionId) {
|
|
13748
13796
|
if (projectDir === null) return null;
|
|
13749
13797
|
try {
|
|
13750
|
-
return
|
|
13798
|
+
return statSync10(join25(projectDir, `${sessionId}.jsonl`)).size;
|
|
13751
13799
|
} catch {
|
|
13752
13800
|
return null;
|
|
13753
13801
|
}
|
|
@@ -13885,13 +13933,13 @@ function latestAdminWebchatSessionId(requesterUserId, primaryUserId, scopeAccoun
|
|
|
13885
13933
|
let best = null;
|
|
13886
13934
|
for (const { path: path3, isSubagent, archived } of enumerateJsonls(join25(cfg, "projects"))) {
|
|
13887
13935
|
if (isSubagent || archived) continue;
|
|
13888
|
-
const id =
|
|
13889
|
-
const meta = readSidecarMeta(join25(
|
|
13936
|
+
const id = basename8(path3).slice(0, -".jsonl".length);
|
|
13937
|
+
const meta = readSidecarMeta(join25(dirname9(path3), `${id}.meta.json`));
|
|
13890
13938
|
if (meta.role !== "admin" || meta.channel !== "webchat") continue;
|
|
13891
13939
|
if (multiAccount && meta.accountId !== scopeAccountId) continue;
|
|
13892
13940
|
let mtimeMs;
|
|
13893
13941
|
try {
|
|
13894
|
-
mtimeMs =
|
|
13942
|
+
mtimeMs = statSync10(path3).mtimeMs;
|
|
13895
13943
|
} catch {
|
|
13896
13944
|
continue;
|
|
13897
13945
|
}
|
|
@@ -13909,7 +13957,7 @@ function latestAdminWebchatSessionId(requesterUserId, primaryUserId, scopeAccoun
|
|
|
13909
13957
|
function overrideKnownNonArchived(id) {
|
|
13910
13958
|
const { projectDir } = locateSession(id);
|
|
13911
13959
|
if (projectDir === null) return sessionSidecarExists(id);
|
|
13912
|
-
return
|
|
13960
|
+
return basename8(projectDir) !== "archive";
|
|
13913
13961
|
}
|
|
13914
13962
|
function resolveCanonical(accountId, accountDir, requesterUserId, primaryUserId, scopeAccountId, multiAccount) {
|
|
13915
13963
|
const bootstrapAccountId = scopeAccountId ?? accountId;
|
|
@@ -13945,8 +13993,8 @@ async function reapplyLeversViaManager() {
|
|
|
13945
13993
|
var WEBCHAT_SEND_TURN_WINDOW_MS = Number(process.env.WEBCHAT_SEND_TURN_WINDOW_MS ?? String(15e3));
|
|
13946
13994
|
var sendSeq = 0;
|
|
13947
13995
|
function createWebchatRoutes(deps) {
|
|
13948
|
-
const
|
|
13949
|
-
|
|
13996
|
+
const app68 = new Hono();
|
|
13997
|
+
app68.post("/send", requireAdminSession, async (c) => {
|
|
13950
13998
|
let accountId;
|
|
13951
13999
|
try {
|
|
13952
14000
|
accountId = resolvePlatformAccountId();
|
|
@@ -14149,7 +14197,7 @@ ${note}` : note;
|
|
|
14149
14197
|
if (turnTimer.unref) turnTimer.unref();
|
|
14150
14198
|
return c.json({ ok: true });
|
|
14151
14199
|
});
|
|
14152
|
-
|
|
14200
|
+
app68.post("/interrupt", requireAdminSession, async (c) => {
|
|
14153
14201
|
const cacheKey = c.get("cacheKey");
|
|
14154
14202
|
const requesterUserId = (cacheKey ? getUserIdForSession(cacheKey) : void 0) ?? null;
|
|
14155
14203
|
const primaryUserId = resolvePrimaryAdminUserId();
|
|
@@ -14177,7 +14225,7 @@ ${note}` : note;
|
|
|
14177
14225
|
}
|
|
14178
14226
|
return c.json({ ok: true, stopped: outcome.stopped, intId: outcome.intId, deadChild: outcome.deadChild }, 200);
|
|
14179
14227
|
});
|
|
14180
|
-
|
|
14228
|
+
app68.post("/settings", requireAdminSession, async (c) => {
|
|
14181
14229
|
const body = await c.req.json().catch(() => null);
|
|
14182
14230
|
const op = body?.op;
|
|
14183
14231
|
const value = body?.value;
|
|
@@ -14217,7 +14265,7 @@ ${note}` : note;
|
|
|
14217
14265
|
console.log(`[webchat:settings] op=${op} outcome=accepted value=${value} settingsApplied=${settingsApplied}`);
|
|
14218
14266
|
return c.json({ ok: true, settingsApplied });
|
|
14219
14267
|
});
|
|
14220
|
-
|
|
14268
|
+
app68.get("/session", requireAdminSession, async (c) => {
|
|
14221
14269
|
let accountId;
|
|
14222
14270
|
try {
|
|
14223
14271
|
accountId = resolvePlatformAccountId();
|
|
@@ -14280,8 +14328,8 @@ ${note}` : note;
|
|
|
14280
14328
|
let projectDir = null;
|
|
14281
14329
|
if (cfg) {
|
|
14282
14330
|
for (const { path: path3 } of enumerateJsonls(join25(cfg, "projects"))) {
|
|
14283
|
-
if (
|
|
14284
|
-
projectDir =
|
|
14331
|
+
if (basename8(path3) === `${sessionId}.jsonl`) {
|
|
14332
|
+
projectDir = dirname9(path3);
|
|
14285
14333
|
break;
|
|
14286
14334
|
}
|
|
14287
14335
|
}
|
|
@@ -14295,7 +14343,7 @@ ${note}` : note;
|
|
|
14295
14343
|
const indicators = await fetchComposerIndicators(sessionId);
|
|
14296
14344
|
return c.json({ sessionId, projectDir, source, sizeBytes: jsonlSizeBytes(projectDir, sessionId), pendingPermissionPrompt: deps.pendingPromptFor?.(`session:${sessionId}`) ?? null, deliveryFailure: deps.deliveryFailureFor?.(`session:${sessionId}`) ?? null, ...indicators, ...readLevers(account) });
|
|
14297
14345
|
});
|
|
14298
|
-
|
|
14346
|
+
app68.post("/permission-verdict", requireAdminSession, async (c) => {
|
|
14299
14347
|
const body = await c.req.json().catch(() => null);
|
|
14300
14348
|
const sessionId = body?.sessionId;
|
|
14301
14349
|
const requestId = body?.request_id;
|
|
@@ -14312,14 +14360,14 @@ ${note}` : note;
|
|
|
14312
14360
|
const ok = deps.resolvePermissionVerdict?.(`session:${sessionId}`, requestId, behavior) ?? false;
|
|
14313
14361
|
return c.json({ ok });
|
|
14314
14362
|
});
|
|
14315
|
-
return
|
|
14363
|
+
return app68;
|
|
14316
14364
|
}
|
|
14317
14365
|
|
|
14318
14366
|
// server/routes/webchat-greeting.ts
|
|
14319
|
-
import { resolve as
|
|
14367
|
+
import { resolve as resolve18 } from "path";
|
|
14320
14368
|
|
|
14321
14369
|
// app/lib/claude-agent/specialist-roster.ts
|
|
14322
|
-
import { existsSync as
|
|
14370
|
+
import { existsSync as existsSync20, readFileSync as readFileSync26, readdirSync as readdirSync18 } from "fs";
|
|
14323
14371
|
import { join as join26 } from "path";
|
|
14324
14372
|
function field(fm, name) {
|
|
14325
14373
|
const m = fm.match(new RegExp(`^${name}:\\s*(.*?)\\r?$`, "m"));
|
|
@@ -14331,7 +14379,7 @@ function field(fm, name) {
|
|
|
14331
14379
|
return value || null;
|
|
14332
14380
|
}
|
|
14333
14381
|
function readSpecialistRoster(specialistsDir) {
|
|
14334
|
-
if (!
|
|
14382
|
+
if (!existsSync20(specialistsDir)) return { specialists: [], skipped: [] };
|
|
14335
14383
|
const entries = readdirSync18(specialistsDir);
|
|
14336
14384
|
const specialists = [];
|
|
14337
14385
|
const skipped = [];
|
|
@@ -14421,7 +14469,7 @@ app7.get("/", requireAdminSession, async (c) => {
|
|
|
14421
14469
|
let specialists = [];
|
|
14422
14470
|
try {
|
|
14423
14471
|
const roster = readSpecialistRoster(
|
|
14424
|
-
|
|
14472
|
+
resolve18(ACCOUNTS_DIR, accountId, "specialists", "agents")
|
|
14425
14473
|
);
|
|
14426
14474
|
specialists = roster.specialists;
|
|
14427
14475
|
for (const s of roster.skipped) {
|
|
@@ -14456,8 +14504,8 @@ var webchat_greeting_default = app7;
|
|
|
14456
14504
|
|
|
14457
14505
|
// server/routes/telegram.ts
|
|
14458
14506
|
import { homedir as homedir2 } from "os";
|
|
14459
|
-
import { resolve as
|
|
14460
|
-
import { existsSync as
|
|
14507
|
+
import { resolve as resolve19, join as join27 } from "path";
|
|
14508
|
+
import { existsSync as existsSync21, readFileSync as readFileSync27 } from "fs";
|
|
14461
14509
|
|
|
14462
14510
|
// app/lib/telegram/gateway/instance.ts
|
|
14463
14511
|
var instance = null;
|
|
@@ -14515,9 +14563,9 @@ function routeTelegramUpdate(input) {
|
|
|
14515
14563
|
// server/routes/telegram.ts
|
|
14516
14564
|
var TAG29 = "[telegram-inbound]";
|
|
14517
14565
|
function configDirName() {
|
|
14518
|
-
const platformRoot5 = process.env.MAXY_PLATFORM_ROOT ??
|
|
14566
|
+
const platformRoot5 = process.env.MAXY_PLATFORM_ROOT ?? resolve19(process.cwd(), "..");
|
|
14519
14567
|
const brandPath = join27(platformRoot5, "config", "brand.json");
|
|
14520
|
-
if (
|
|
14568
|
+
if (existsSync21(brandPath)) {
|
|
14521
14569
|
try {
|
|
14522
14570
|
return JSON.parse(readFileSync27(brandPath, "utf-8")).configDir ?? ".maxy";
|
|
14523
14571
|
} catch {
|
|
@@ -14527,7 +14575,7 @@ function configDirName() {
|
|
|
14527
14575
|
}
|
|
14528
14576
|
function secretPath(botType) {
|
|
14529
14577
|
const filename = botType === "admin" ? ".telegram-admin-webhook-secret" : ".telegram-webhook-secret";
|
|
14530
|
-
return
|
|
14578
|
+
return resolve19(homedir2(), configDirName(), filename);
|
|
14531
14579
|
}
|
|
14532
14580
|
var app8 = new Hono();
|
|
14533
14581
|
app8.post("/", async (c) => {
|
|
@@ -14538,7 +14586,7 @@ app8.post("/", async (c) => {
|
|
|
14538
14586
|
return c.json({ ok: false }, 400);
|
|
14539
14587
|
}
|
|
14540
14588
|
const sp = secretPath(botType);
|
|
14541
|
-
if (!
|
|
14589
|
+
if (!existsSync21(sp)) {
|
|
14542
14590
|
console.error(`${TAG29} op=reject reason=no-secret-file botType=${botType}`);
|
|
14543
14591
|
return c.json({ ok: false }, 401);
|
|
14544
14592
|
}
|
|
@@ -14606,7 +14654,7 @@ var telegram_default = app8;
|
|
|
14606
14654
|
|
|
14607
14655
|
// server/routes/quickbooks.ts
|
|
14608
14656
|
import { join as join28 } from "path";
|
|
14609
|
-
import { existsSync as
|
|
14657
|
+
import { existsSync as existsSync22, readFileSync as readFileSync28, writeFileSync as writeFileSync10, mkdirSync as mkdirSync5, rmSync, renameSync as renameSync5 } from "fs";
|
|
14610
14658
|
var TAG30 = "[quickbooks]";
|
|
14611
14659
|
var INTUIT_TOKEN_URL = "https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer";
|
|
14612
14660
|
var STATE_RE = /^[A-Za-z0-9_-]+$/;
|
|
@@ -14619,7 +14667,7 @@ function storePath(accountDir) {
|
|
|
14619
14667
|
async function completeConsent(args) {
|
|
14620
14668
|
const { accountDir, code, realmId } = args;
|
|
14621
14669
|
const state = args.state;
|
|
14622
|
-
if (!state || !STATE_RE.test(state) || !
|
|
14670
|
+
if (!state || !STATE_RE.test(state) || !existsSync22(pendingPath(accountDir, state))) {
|
|
14623
14671
|
console.error(`${TAG30} op=callback state=${state ?? ""} stateValid=false realmId=${realmId ?? ""}`);
|
|
14624
14672
|
return { ok: false, status: 400, message: "Invalid or unknown authorization state.", stateValid: false };
|
|
14625
14673
|
}
|
|
@@ -14646,7 +14694,7 @@ async function completeConsent(args) {
|
|
|
14646
14694
|
if (!code || !realmId) {
|
|
14647
14695
|
return { ok: false, status: 400, message: "Missing code or realmId in the callback.", stateValid: true };
|
|
14648
14696
|
}
|
|
14649
|
-
if (!
|
|
14697
|
+
if (!existsSync22(storePath(accountDir))) {
|
|
14650
14698
|
return { ok: false, status: 500, message: "No QuickBooks credentials are stored for this account.", stateValid: true };
|
|
14651
14699
|
}
|
|
14652
14700
|
const store2 = JSON.parse(readFileSync28(storePath(accountDir), "utf-8"));
|
|
@@ -14714,7 +14762,7 @@ var quickbooks_default = app9;
|
|
|
14714
14762
|
|
|
14715
14763
|
// server/routes/onboarding.ts
|
|
14716
14764
|
import { spawn, spawnSync as spawnSync2, execFileSync as execFileSync4 } from "child_process";
|
|
14717
|
-
import { openSync as openSync3, closeSync as closeSync3, writeFileSync as writeFileSync12, writeSync, existsSync as
|
|
14765
|
+
import { openSync as openSync3, closeSync as closeSync3, writeFileSync as writeFileSync12, writeSync, existsSync as existsSync24, readFileSync as readFileSync30, unlinkSync as unlinkSync3, renameSync as renameSync7 } from "fs";
|
|
14718
14766
|
import { createHash as createHash4, randomUUID as randomUUID8 } from "crypto";
|
|
14719
14767
|
|
|
14720
14768
|
// app/lib/claude-spawn-env.ts
|
|
@@ -14723,7 +14771,7 @@ function claudeBin() {
|
|
|
14723
14771
|
}
|
|
14724
14772
|
|
|
14725
14773
|
// server/routes/onboarding.ts
|
|
14726
|
-
import { dirname as
|
|
14774
|
+
import { dirname as dirname11, join as join30 } from "path";
|
|
14727
14775
|
|
|
14728
14776
|
// app/lib/claude-keychain.ts
|
|
14729
14777
|
import { execFileSync as execFileSync3 } from "child_process";
|
|
@@ -14852,8 +14900,8 @@ function readHostCredsBlob(service) {
|
|
|
14852
14900
|
}
|
|
14853
14901
|
|
|
14854
14902
|
// ../lib/admins-write/src/index.ts
|
|
14855
|
-
import { existsSync as
|
|
14856
|
-
import { dirname as
|
|
14903
|
+
import { existsSync as existsSync23, readFileSync as readFileSync29, writeFileSync as writeFileSync11, renameSync as renameSync6, mkdirSync as mkdirSync6, readdirSync as readdirSync19, statSync as statSync11, appendFileSync as appendFileSync3 } from "fs";
|
|
14904
|
+
import { dirname as dirname10, join as join29 } from "path";
|
|
14857
14905
|
function id8(value) {
|
|
14858
14906
|
return value.slice(0, 8);
|
|
14859
14907
|
}
|
|
@@ -14867,7 +14915,7 @@ function appendUsersAuditLine(audit, fields) {
|
|
|
14867
14915
|
const line = `[users-audit] action=${fields.action} actor=${actor}${targetFields}${sess} field=${fields.field} rowsBefore=${fields.rowsBefore} rowsAfter=${fields.rowsAfter} ts=${(/* @__PURE__ */ new Date()).toISOString()}
|
|
14868
14916
|
`;
|
|
14869
14917
|
try {
|
|
14870
|
-
mkdirSync6(
|
|
14918
|
+
mkdirSync6(dirname10(audit.logFile), { recursive: true, mode: 448 });
|
|
14871
14919
|
appendFileSync3(audit.logFile, line, { mode: 384 });
|
|
14872
14920
|
} catch (err) {
|
|
14873
14921
|
console.error(
|
|
@@ -14885,7 +14933,7 @@ function logLine(input, result) {
|
|
|
14885
14933
|
);
|
|
14886
14934
|
}
|
|
14887
14935
|
function writeFileAtomic(filePath, contents, mode) {
|
|
14888
|
-
mkdirSync6(
|
|
14936
|
+
mkdirSync6(dirname10(filePath), { recursive: true });
|
|
14889
14937
|
const tempPath = `${filePath}.tmp-${process.pid}-${Date.now()}`;
|
|
14890
14938
|
writeFileSync11(tempPath, contents, mode !== void 0 ? { mode } : void 0);
|
|
14891
14939
|
renameSync6(tempPath, filePath);
|
|
@@ -14894,7 +14942,7 @@ function writeAdminEntry(input) {
|
|
|
14894
14942
|
const result = { usersJsonResult: "noop", accountJsonResult: "noop" };
|
|
14895
14943
|
try {
|
|
14896
14944
|
let users = [];
|
|
14897
|
-
if (
|
|
14945
|
+
if (existsSync23(input.usersFile)) {
|
|
14898
14946
|
const raw = readFileSync29(input.usersFile, "utf-8").trim();
|
|
14899
14947
|
if (raw) {
|
|
14900
14948
|
const parsed = JSON.parse(raw);
|
|
@@ -14927,7 +14975,7 @@ function writeAdminEntry(input) {
|
|
|
14927
14975
|
}
|
|
14928
14976
|
try {
|
|
14929
14977
|
const accountJsonPath = join29(input.accountDir, "account.json");
|
|
14930
|
-
if (!
|
|
14978
|
+
if (!existsSync23(accountJsonPath)) {
|
|
14931
14979
|
throw new Error(`account.json not found at ${accountJsonPath}`);
|
|
14932
14980
|
}
|
|
14933
14981
|
const config = JSON.parse(readFileSync29(accountJsonPath, "utf-8"));
|
|
@@ -14950,7 +14998,7 @@ function writeAdminEntry(input) {
|
|
|
14950
14998
|
function computeAdminStoreDivergence(input) {
|
|
14951
14999
|
const result = { divergences: 0, accountWithoutUsers: [], usersWithoutAccount: [], errors: [] };
|
|
14952
15000
|
const usersUserIds = /* @__PURE__ */ new Set();
|
|
14953
|
-
if (
|
|
15001
|
+
if (existsSync23(input.usersFile)) {
|
|
14954
15002
|
try {
|
|
14955
15003
|
const raw = readFileSync29(input.usersFile, "utf-8").trim();
|
|
14956
15004
|
if (raw) {
|
|
@@ -14964,7 +15012,7 @@ function computeAdminStoreDivergence(input) {
|
|
|
14964
15012
|
}
|
|
14965
15013
|
}
|
|
14966
15014
|
const accountUserIds = /* @__PURE__ */ new Set();
|
|
14967
|
-
if (
|
|
15015
|
+
if (existsSync23(input.accountsDir)) {
|
|
14968
15016
|
let entries;
|
|
14969
15017
|
try {
|
|
14970
15018
|
entries = readdirSync19(input.accountsDir);
|
|
@@ -14976,12 +15024,12 @@ function computeAdminStoreDivergence(input) {
|
|
|
14976
15024
|
if (entry.startsWith(".")) continue;
|
|
14977
15025
|
const accountDir = join29(input.accountsDir, entry);
|
|
14978
15026
|
try {
|
|
14979
|
-
if (!
|
|
15027
|
+
if (!statSync11(accountDir).isDirectory()) continue;
|
|
14980
15028
|
} catch {
|
|
14981
15029
|
continue;
|
|
14982
15030
|
}
|
|
14983
15031
|
const accountJsonPath = join29(accountDir, "account.json");
|
|
14984
|
-
if (!
|
|
15032
|
+
if (!existsSync23(accountJsonPath)) continue;
|
|
14985
15033
|
let admins = [];
|
|
14986
15034
|
try {
|
|
14987
15035
|
const config = JSON.parse(readFileSync29(accountJsonPath, "utf-8"));
|
|
@@ -15032,7 +15080,7 @@ function hashPin2(pin) {
|
|
|
15032
15080
|
return createHash4("sha256").update(pin).digest("hex");
|
|
15033
15081
|
}
|
|
15034
15082
|
function readUsersFile2() {
|
|
15035
|
-
if (!
|
|
15083
|
+
if (!existsSync24(USERS_FILE)) return null;
|
|
15036
15084
|
const raw = readFileSync30(USERS_FILE, "utf-8").trim();
|
|
15037
15085
|
if (!raw) return [];
|
|
15038
15086
|
return JSON.parse(raw);
|
|
@@ -15092,7 +15140,7 @@ app10.post("/claude-auth", async (c) => {
|
|
|
15092
15140
|
} catch (err) {
|
|
15093
15141
|
logoutError = err instanceof Error ? err.message : String(err);
|
|
15094
15142
|
}
|
|
15095
|
-
const credentialsPresent =
|
|
15143
|
+
const credentialsPresent = existsSync24(CLAUDE_CREDENTIALS_FILE);
|
|
15096
15144
|
const ranMs = Date.now() - start;
|
|
15097
15145
|
console.log(`[onboarding] op=claude-logout credentialsPresent=${credentialsPresent} ranMs=${ranMs} logoutError=${logoutError ? JSON.stringify(logoutError.slice(0, 120)) : "none"}`);
|
|
15098
15146
|
return c.json({ logged_out: !credentialsPresent });
|
|
@@ -15158,7 +15206,7 @@ app10.post("/claude-auth", async (c) => {
|
|
|
15158
15206
|
});
|
|
15159
15207
|
persistKeychainService(
|
|
15160
15208
|
writebackResult,
|
|
15161
|
-
(service) => writeFileSync12(join30(
|
|
15209
|
+
(service) => writeFileSync12(join30(dirname11(CLAUDE_CREDENTIALS_FILE), ".keychain-service"), service, { mode: 384 }),
|
|
15162
15210
|
(line) => console.log(line)
|
|
15163
15211
|
);
|
|
15164
15212
|
if (darwinAuthChild === claudeProc2) darwinAuthChild = null;
|
|
@@ -15241,7 +15289,7 @@ app10.post("/set-pin", async (c) => {
|
|
|
15241
15289
|
console.log(`[set-pin] wrote users.json + account.json admins: userId=${userId.slice(0, 8)}\u2026 role=owner`);
|
|
15242
15290
|
if (process.platform === "linux") {
|
|
15243
15291
|
let installOwner = null;
|
|
15244
|
-
if (
|
|
15292
|
+
if (existsSync24(INSTALL_OWNER_FILE)) {
|
|
15245
15293
|
try {
|
|
15246
15294
|
const raw = readFileSync30(INSTALL_OWNER_FILE, "utf-8").trim();
|
|
15247
15295
|
if (raw.length > 0) installOwner = raw;
|
|
@@ -15389,7 +15437,7 @@ app10.put("/set-pin", requireAdminSession, async (c) => {
|
|
|
15389
15437
|
console.log(`[set-pin] changed PIN in place: userId=${sessionUserId.slice(0, 8)}\u2026`);
|
|
15390
15438
|
if (process.platform === "linux") {
|
|
15391
15439
|
let installOwner = null;
|
|
15392
|
-
if (
|
|
15440
|
+
if (existsSync24(INSTALL_OWNER_FILE)) {
|
|
15393
15441
|
try {
|
|
15394
15442
|
const raw = readFileSync30(INSTALL_OWNER_FILE, "utf-8").trim();
|
|
15395
15443
|
if (raw.length > 0) installOwner = raw;
|
|
@@ -15423,7 +15471,7 @@ ${body.newPin}
|
|
|
15423
15471
|
var onboarding_default = app10;
|
|
15424
15472
|
|
|
15425
15473
|
// server/routes/client-error.ts
|
|
15426
|
-
import { appendFileSync as appendFileSync4, existsSync as
|
|
15474
|
+
import { appendFileSync as appendFileSync4, existsSync as existsSync25, renameSync as renameSync8, statSync as statSync12 } from "fs";
|
|
15427
15475
|
import { join as join31 } from "path";
|
|
15428
15476
|
var CLIENT_ERRORS_LOG = join31(LOG_DIR, "client-errors.log");
|
|
15429
15477
|
var MAX_LOG_SIZE = 10 * 1024 * 1024;
|
|
@@ -15482,8 +15530,8 @@ function stackHead(stack) {
|
|
|
15482
15530
|
}
|
|
15483
15531
|
function rotateIfNeeded() {
|
|
15484
15532
|
try {
|
|
15485
|
-
if (!
|
|
15486
|
-
const stats =
|
|
15533
|
+
if (!existsSync25(CLIENT_ERRORS_LOG)) return;
|
|
15534
|
+
const stats = statSync12(CLIENT_ERRORS_LOG);
|
|
15487
15535
|
if (stats.size < MAX_LOG_SIZE) return;
|
|
15488
15536
|
renameSync8(CLIENT_ERRORS_LOG, CLIENT_ERRORS_LOG + ".1");
|
|
15489
15537
|
} catch (err) {
|
|
@@ -15668,15 +15716,15 @@ function operatorRoleFor(config, userId) {
|
|
|
15668
15716
|
async function buildAccountOptionList(accounts, userId) {
|
|
15669
15717
|
const houseAccount = accounts.find((a) => a.config.role === "house");
|
|
15670
15718
|
console.log(`[admin-accounts] op=list count=${accounts.length} house=${houseAccount?.accountId ?? "none"}`);
|
|
15671
|
-
const
|
|
15719
|
+
const resolve44 = async (a) => {
|
|
15672
15720
|
const businessName = await fetchAccountName(a.accountId) || void 0;
|
|
15673
15721
|
return { accountId: a.accountId, businessName, role: operatorRoleFor(a.config, userId), isHouse: a.config.role === "house" };
|
|
15674
15722
|
};
|
|
15675
15723
|
const houseOptions = await Promise.all(
|
|
15676
|
-
accounts.filter((a) => a.config.role === "house").map(
|
|
15724
|
+
accounts.filter((a) => a.config.role === "house").map(resolve44)
|
|
15677
15725
|
);
|
|
15678
15726
|
const nonHouseOptions = await Promise.all(
|
|
15679
|
-
accounts.filter((a) => a.config.role !== "house").map(
|
|
15727
|
+
accounts.filter((a) => a.config.role !== "house").map(resolve44)
|
|
15680
15728
|
);
|
|
15681
15729
|
const sortKey = (o) => (o.businessName || o.accountId).toLowerCase();
|
|
15682
15730
|
nonHouseOptions.sort((x, y) => {
|
|
@@ -15809,18 +15857,18 @@ app13.get("/", requireAdminSession, async (c) => {
|
|
|
15809
15857
|
var accounts_default = app13;
|
|
15810
15858
|
|
|
15811
15859
|
// server/routes/admin/logs.ts
|
|
15812
|
-
import { existsSync as
|
|
15813
|
-
import { resolve as
|
|
15860
|
+
import { existsSync as existsSync27, readdirSync as readdirSync20, readFileSync as readFileSync31, statSync as statSync13 } from "fs";
|
|
15861
|
+
import { resolve as resolve20, basename as basename9 } from "path";
|
|
15814
15862
|
|
|
15815
15863
|
// app/lib/logs-read-resolve.ts
|
|
15816
|
-
import { existsSync as
|
|
15864
|
+
import { existsSync as existsSync26 } from "fs";
|
|
15817
15865
|
import { join as join32 } from "path";
|
|
15818
15866
|
function resolveSessionLogPaths(filename, logDirs) {
|
|
15819
15867
|
const tried = [filename];
|
|
15820
15868
|
const hits = [];
|
|
15821
15869
|
for (const dir of logDirs) {
|
|
15822
15870
|
const fullPath = join32(dir, filename);
|
|
15823
|
-
if (
|
|
15871
|
+
if (existsSync26(fullPath)) {
|
|
15824
15872
|
hits.push({ path: fullPath, dir });
|
|
15825
15873
|
}
|
|
15826
15874
|
}
|
|
@@ -15837,19 +15885,19 @@ app14.get("/", async (c) => {
|
|
|
15837
15885
|
const cacheKeyParam = c.req.query("cacheKey");
|
|
15838
15886
|
const download = c.req.query("download") === "1";
|
|
15839
15887
|
const account = resolveAccount();
|
|
15840
|
-
const accountLogDir = account ?
|
|
15888
|
+
const accountLogDir = account ? resolve20(account.accountDir, "logs") : null;
|
|
15841
15889
|
const logDirs = [];
|
|
15842
15890
|
if (accountLogDir) logDirs.push(accountLogDir);
|
|
15843
15891
|
logDirs.push(LOG_DIR);
|
|
15844
15892
|
if (fileParam) {
|
|
15845
|
-
const safe =
|
|
15893
|
+
const safe = basename9(fileParam);
|
|
15846
15894
|
const searched = [];
|
|
15847
15895
|
for (const dir of logDirs) {
|
|
15848
|
-
const filePath =
|
|
15896
|
+
const filePath = resolve20(dir, safe);
|
|
15849
15897
|
searched.push(filePath);
|
|
15850
15898
|
try {
|
|
15851
15899
|
const buffer = readFileSync31(filePath);
|
|
15852
|
-
const onDiskBytes =
|
|
15900
|
+
const onDiskBytes = statSync13(filePath).size;
|
|
15853
15901
|
const headers = {
|
|
15854
15902
|
"Content-Type": "text/plain; charset=utf-8",
|
|
15855
15903
|
"Content-Length": String(buffer.byteLength)
|
|
@@ -15912,9 +15960,9 @@ app14.get("/", async (c) => {
|
|
|
15912
15960
|
if (hit) {
|
|
15913
15961
|
console.info(`[admin/logs] resolved cacheKey=${cacheKeySlice} sessionId=${sessionIdSlice} via=${primaryId === cacheKey ? "cacheKey" : primaryId === sessionKeyFromConv ? "reverse-lookup" : "sessionId-fallback"}`);
|
|
15914
15962
|
try {
|
|
15915
|
-
const filename =
|
|
15963
|
+
const filename = basename9(hit.path);
|
|
15916
15964
|
const buffer = readFileSync31(hit.path);
|
|
15917
|
-
const onDiskBytes =
|
|
15965
|
+
const onDiskBytes = statSync13(hit.path).size;
|
|
15918
15966
|
const headers = {
|
|
15919
15967
|
"Content-Type": "text/plain; charset=utf-8",
|
|
15920
15968
|
"Content-Length": String(buffer.byteLength)
|
|
@@ -15948,7 +15996,7 @@ app14.get("/", async (c) => {
|
|
|
15948
15996
|
const seen = /* @__PURE__ */ new Set();
|
|
15949
15997
|
const logs = {};
|
|
15950
15998
|
for (const dir of logDirs) {
|
|
15951
|
-
if (!
|
|
15999
|
+
if (!existsSync27(dir)) continue;
|
|
15952
16000
|
let files;
|
|
15953
16001
|
try {
|
|
15954
16002
|
files = readdirSync20(dir).filter((f) => f.endsWith(".log"));
|
|
@@ -15957,10 +16005,10 @@ app14.get("/", async (c) => {
|
|
|
15957
16005
|
console.warn(`[admin/logs] readdir-fail dir=${dir} reason=${reason}`);
|
|
15958
16006
|
continue;
|
|
15959
16007
|
}
|
|
15960
|
-
files.filter((f) => !seen.has(f)).map((f) => ({ name: f, mtime:
|
|
16008
|
+
files.filter((f) => !seen.has(f)).map((f) => ({ name: f, mtime: statSync13(resolve20(dir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime).forEach(({ name }) => {
|
|
15961
16009
|
seen.add(name);
|
|
15962
16010
|
try {
|
|
15963
|
-
const content = readFileSync31(
|
|
16011
|
+
const content = readFileSync31(resolve20(dir, name));
|
|
15964
16012
|
const tail = content.length > TAIL_BYTES ? content.subarray(content.length - TAIL_BYTES).toString("utf-8") : content.toString("utf-8");
|
|
15965
16013
|
logs[name] = tail.trim() || "(empty)";
|
|
15966
16014
|
} catch (err) {
|
|
@@ -16000,12 +16048,12 @@ var claude_info_default = app15;
|
|
|
16000
16048
|
|
|
16001
16049
|
// server/routes/admin/attachment.ts
|
|
16002
16050
|
import { readFile as readFile4, readdir as readdir2 } from "fs/promises";
|
|
16003
|
-
import { existsSync as
|
|
16004
|
-
import { resolve as
|
|
16051
|
+
import { existsSync as existsSync28 } from "fs";
|
|
16052
|
+
import { resolve as resolve21 } from "path";
|
|
16005
16053
|
var app16 = new Hono();
|
|
16006
16054
|
var ATTACHMENT_ID_RE3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
|
|
16007
16055
|
function uploadsDirFor2(accountId, attachmentId) {
|
|
16008
|
-
return
|
|
16056
|
+
return resolve21(DATA_ROOT, "accounts", accountId, "uploads", attachmentId);
|
|
16009
16057
|
}
|
|
16010
16058
|
app16.get("/:attachmentId", requireAdminSession, async (c) => {
|
|
16011
16059
|
const attachmentId = c.req.param("attachmentId");
|
|
@@ -16023,12 +16071,12 @@ app16.get("/:attachmentId", requireAdminSession, async (c) => {
|
|
|
16023
16071
|
}
|
|
16024
16072
|
let accountId = pinnedAccountId;
|
|
16025
16073
|
let dir = uploadsDirFor2(accountId, attachmentId);
|
|
16026
|
-
let found =
|
|
16074
|
+
let found = existsSync28(dir);
|
|
16027
16075
|
if (!found) {
|
|
16028
16076
|
for (const candidate of listValidAccounts()) {
|
|
16029
16077
|
if (candidate.accountId === pinnedAccountId) continue;
|
|
16030
16078
|
const candidateDir = uploadsDirFor2(candidate.accountId, attachmentId);
|
|
16031
|
-
if (
|
|
16079
|
+
if (existsSync28(candidateDir)) {
|
|
16032
16080
|
accountId = candidate.accountId;
|
|
16033
16081
|
dir = candidateDir;
|
|
16034
16082
|
found = true;
|
|
@@ -16042,8 +16090,8 @@ app16.get("/:attachmentId", requireAdminSession, async (c) => {
|
|
|
16042
16090
|
if (!found) {
|
|
16043
16091
|
return new Response("Not found", { status: 404 });
|
|
16044
16092
|
}
|
|
16045
|
-
const metaPath =
|
|
16046
|
-
if (!
|
|
16093
|
+
const metaPath = resolve21(dir, `${attachmentId}.meta.json`);
|
|
16094
|
+
if (!existsSync28(metaPath)) {
|
|
16047
16095
|
return new Response("Not found", { status: 404 });
|
|
16048
16096
|
}
|
|
16049
16097
|
let meta;
|
|
@@ -16057,7 +16105,7 @@ app16.get("/:attachmentId", requireAdminSession, async (c) => {
|
|
|
16057
16105
|
if (!dataFile) {
|
|
16058
16106
|
return new Response("Not found", { status: 404 });
|
|
16059
16107
|
}
|
|
16060
|
-
const filePath =
|
|
16108
|
+
const filePath = resolve21(dir, dataFile);
|
|
16061
16109
|
const buffer = await readFile4(filePath);
|
|
16062
16110
|
const inlineSafe = isInlineSafeMime(meta.mimeType);
|
|
16063
16111
|
const safeName = meta.filename.replace(/["\\\r\n]/g, "_");
|
|
@@ -16075,23 +16123,66 @@ app16.get("/:attachmentId", requireAdminSession, async (c) => {
|
|
|
16075
16123
|
});
|
|
16076
16124
|
var attachment_default = app16;
|
|
16077
16125
|
|
|
16078
|
-
// server/routes/admin/
|
|
16079
|
-
import {
|
|
16080
|
-
import {
|
|
16126
|
+
// server/routes/admin/session-upload.ts
|
|
16127
|
+
import { readFile as readFile5 } from "fs/promises";
|
|
16128
|
+
import { existsSync as existsSync29, statSync as statSync14 } from "fs";
|
|
16081
16129
|
var app17 = new Hono();
|
|
16082
|
-
app17.get("/", (c) => {
|
|
16130
|
+
app17.get("/", requireAdminSession, async (c) => {
|
|
16131
|
+
const cacheKey = c.var.cacheKey;
|
|
16132
|
+
const sessionId = c.req.query("session_id") ?? "";
|
|
16133
|
+
const file = c.req.query("file") ?? "";
|
|
16134
|
+
const short2 = sessionId.slice(0, 8);
|
|
16135
|
+
if (!SESSION_ID_RE2.test(sessionId) || !file || file.includes("/") || file.includes("\\") || file.includes("..")) {
|
|
16136
|
+
console.log(`[session-upload] op=miss session=${short2} status=400 reason=bad-param`);
|
|
16137
|
+
return c.json({ error: "bad request" }, 400);
|
|
16138
|
+
}
|
|
16139
|
+
const accountId = getAccountIdForSession(cacheKey);
|
|
16140
|
+
if (!accountId) {
|
|
16141
|
+
console.log(`[session-upload] op=miss session=${short2} status=401 reason=no-account`);
|
|
16142
|
+
return c.json({ error: "Unauthorized" }, 401);
|
|
16143
|
+
}
|
|
16144
|
+
if (await verifyAndGetConversationUpdatedAt(sessionId, accountId) === null) {
|
|
16145
|
+
console.log(`[session-upload] op=miss session=${short2} status=404 reason=not-owned account=${accountId.slice(0, 8)}`);
|
|
16146
|
+
return c.json({ error: "Not found" }, 404);
|
|
16147
|
+
}
|
|
16148
|
+
const resolution = resolveClaudeUploadsPath(`${sessionId}/${file}`);
|
|
16149
|
+
if (!resolution.ok || !existsSync29(resolution.absolute) || !statSync14(resolution.absolute).isFile()) {
|
|
16150
|
+
console.log(`[session-upload] op=miss session=${short2} file=${file} status=404 reason=absent`);
|
|
16151
|
+
return c.json({ error: "Not found" }, 404);
|
|
16152
|
+
}
|
|
16153
|
+
const mimeType = detectMimeType(file);
|
|
16154
|
+
const inlineSafe = isInlineSafeMime(mimeType);
|
|
16155
|
+
const safeName = file.replace(/["\\\r\n]/g, "_");
|
|
16156
|
+
console.log(`[session-upload] op=served session=${short2} file=${file} disposition=${inlineSafe ? "inline" : "attachment"} mime=${mimeType}`);
|
|
16157
|
+
const buffer = await readFile5(resolution.absolute);
|
|
16158
|
+
return new Response(new Uint8Array(buffer), {
|
|
16159
|
+
headers: {
|
|
16160
|
+
"Content-Type": mimeType,
|
|
16161
|
+
"Content-Disposition": `${inlineSafe ? "inline" : "attachment"}; filename="${safeName}"`,
|
|
16162
|
+
"X-Content-Type-Options": "nosniff",
|
|
16163
|
+
"Cache-Control": "private, max-age=3600"
|
|
16164
|
+
}
|
|
16165
|
+
});
|
|
16166
|
+
});
|
|
16167
|
+
var session_upload_default = app17;
|
|
16168
|
+
|
|
16169
|
+
// server/routes/admin/agents.ts
|
|
16170
|
+
import { resolve as resolve22 } from "path";
|
|
16171
|
+
import { readdirSync as readdirSync21, readFileSync as readFileSync32, existsSync as existsSync30, rmSync as rmSync2 } from "fs";
|
|
16172
|
+
var app18 = new Hono();
|
|
16173
|
+
app18.get("/", (c) => {
|
|
16083
16174
|
const account = resolveAccount();
|
|
16084
16175
|
if (!account) return c.json({ agents: [] });
|
|
16085
|
-
const agentsDir =
|
|
16086
|
-
if (!
|
|
16176
|
+
const agentsDir = resolve22(account.accountDir, "agents");
|
|
16177
|
+
if (!existsSync30(agentsDir)) return c.json({ agents: [] });
|
|
16087
16178
|
const agents = [];
|
|
16088
16179
|
try {
|
|
16089
16180
|
const entries = readdirSync21(agentsDir, { withFileTypes: true });
|
|
16090
16181
|
for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
16091
16182
|
if (!entry.isDirectory()) continue;
|
|
16092
16183
|
if (entry.name === "admin") continue;
|
|
16093
|
-
const configPath2 =
|
|
16094
|
-
if (!
|
|
16184
|
+
const configPath2 = resolve22(agentsDir, entry.name, "config.json");
|
|
16185
|
+
if (!existsSync30(configPath2)) continue;
|
|
16095
16186
|
try {
|
|
16096
16187
|
const config = JSON.parse(readFileSync32(configPath2, "utf-8"));
|
|
16097
16188
|
agents.push({
|
|
@@ -16109,7 +16200,7 @@ app17.get("/", (c) => {
|
|
|
16109
16200
|
}
|
|
16110
16201
|
return c.json({ agents });
|
|
16111
16202
|
});
|
|
16112
|
-
|
|
16203
|
+
app18.delete("/:slug", async (c) => {
|
|
16113
16204
|
const slug = c.req.param("slug");
|
|
16114
16205
|
const account = resolveAccount();
|
|
16115
16206
|
if (!account) return c.json({ error: "No account resolved" }, 400);
|
|
@@ -16119,8 +16210,8 @@ app17.delete("/:slug", async (c) => {
|
|
|
16119
16210
|
if (slug.includes("/") || slug.includes("..") || slug.includes("\\")) {
|
|
16120
16211
|
return c.json({ error: "Invalid agent slug" }, 400);
|
|
16121
16212
|
}
|
|
16122
|
-
const agentDir =
|
|
16123
|
-
if (!
|
|
16213
|
+
const agentDir = resolve22(account.accountDir, "agents", slug);
|
|
16214
|
+
if (!existsSync30(agentDir)) {
|
|
16124
16215
|
return c.json({ error: "Agent not found" }, 404);
|
|
16125
16216
|
}
|
|
16126
16217
|
try {
|
|
@@ -16139,7 +16230,7 @@ app17.delete("/:slug", async (c) => {
|
|
|
16139
16230
|
return c.json({ error: "Failed to delete agent" }, 500);
|
|
16140
16231
|
}
|
|
16141
16232
|
});
|
|
16142
|
-
|
|
16233
|
+
app18.post("/:slug/project", async (c) => {
|
|
16143
16234
|
const slug = c.req.param("slug");
|
|
16144
16235
|
const account = resolveAccount();
|
|
16145
16236
|
if (!account) return c.json({ error: "No account resolved" }, 400);
|
|
@@ -16149,8 +16240,8 @@ app17.post("/:slug/project", async (c) => {
|
|
|
16149
16240
|
if (slug.includes("/") || slug.includes("..") || slug.includes("\\")) {
|
|
16150
16241
|
return c.json({ error: "Invalid agent slug" }, 400);
|
|
16151
16242
|
}
|
|
16152
|
-
const agentDir =
|
|
16153
|
-
if (!
|
|
16243
|
+
const agentDir = resolve22(account.accountDir, "agents", slug);
|
|
16244
|
+
if (!existsSync30(agentDir)) {
|
|
16154
16245
|
return c.json({ error: "Agent not found on disk" }, 404);
|
|
16155
16246
|
}
|
|
16156
16247
|
try {
|
|
@@ -16161,12 +16252,12 @@ app17.post("/:slug/project", async (c) => {
|
|
|
16161
16252
|
return c.json({ error: `Projection failed: ${msg}` }, 500);
|
|
16162
16253
|
}
|
|
16163
16254
|
});
|
|
16164
|
-
var agents_default =
|
|
16255
|
+
var agents_default = app18;
|
|
16165
16256
|
|
|
16166
16257
|
// server/routes/admin/sessions.ts
|
|
16167
16258
|
import crypto2 from "crypto";
|
|
16168
16259
|
import { resolve as resolvePath } from "path";
|
|
16169
|
-
import { existsSync as
|
|
16260
|
+
import { existsSync as existsSync31, mkdirSync as mkdirSync7, createWriteStream } from "fs";
|
|
16170
16261
|
|
|
16171
16262
|
// ../lib/admin-conversation-purge/src/index.ts
|
|
16172
16263
|
async function purgeAdminConversationJsonls(args) {
|
|
@@ -16326,7 +16417,7 @@ function validateAndShapeAttachments(raws, conversationAccountId, sessionId, mes
|
|
|
16326
16417
|
let reason = null;
|
|
16327
16418
|
if (!a.attachmentId || !a.filename || !a.mimeType || !a.storagePath) reason = "schema-fail";
|
|
16328
16419
|
else if (a.accountId !== conversationAccountId) reason = "account-mismatch";
|
|
16329
|
-
else if (!
|
|
16420
|
+
else if (!existsSync31(a.storagePath)) reason = "missing-file";
|
|
16330
16421
|
if (reason) {
|
|
16331
16422
|
invalid++;
|
|
16332
16423
|
try {
|
|
@@ -16433,8 +16524,8 @@ function formatAge(updatedAtStr) {
|
|
|
16433
16524
|
return "unknown";
|
|
16434
16525
|
}
|
|
16435
16526
|
}
|
|
16436
|
-
var
|
|
16437
|
-
|
|
16527
|
+
var app19 = new Hono();
|
|
16528
|
+
app19.get("/", requireAdminSession, async (c) => {
|
|
16438
16529
|
const cacheKey = c.var.cacheKey;
|
|
16439
16530
|
const accountId = getAccountIdForSession(cacheKey);
|
|
16440
16531
|
if (!accountId) return c.json({ error: "Account not found for session" }, 401);
|
|
@@ -16464,7 +16555,7 @@ app18.get("/", requireAdminSession, async (c) => {
|
|
|
16464
16555
|
return c.json({ error: "Failed to fetch sessions" }, 500);
|
|
16465
16556
|
}
|
|
16466
16557
|
});
|
|
16467
|
-
|
|
16558
|
+
app19.post("/new", requireAdminSession, async (c) => {
|
|
16468
16559
|
const oldCacheKey = c.var.cacheKey;
|
|
16469
16560
|
console.log(`[admin-chat] new-conversation outcome=ingress cacheKey=${oldCacheKey.slice(0, 8)}`);
|
|
16470
16561
|
const accountId = getAccountIdForSession(oldCacheKey);
|
|
@@ -16481,7 +16572,7 @@ app18.post("/new", requireAdminSession, async (c) => {
|
|
|
16481
16572
|
console.log(`[admin-chat] new-conversation outcome=ok oldKey=${oldCacheKey.slice(0, 8)} newKey=${newCacheKey.slice(0, 8)}`);
|
|
16482
16573
|
return c.json({ session_key: newSignedSessionToken, sessionId: null });
|
|
16483
16574
|
});
|
|
16484
|
-
|
|
16575
|
+
app19.post("/switch", requireAdminSession, async (c) => {
|
|
16485
16576
|
const cacheKey = c.var.cacheKey;
|
|
16486
16577
|
const accountId = getAccountIdForSession(cacheKey);
|
|
16487
16578
|
const userId = getUserIdForSession(cacheKey);
|
|
@@ -16509,7 +16600,7 @@ app18.post("/switch", requireAdminSession, async (c) => {
|
|
|
16509
16600
|
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)}`);
|
|
16510
16601
|
return c.json({ session_key: targetSignedSessionToken, sessionId: targetSessionId });
|
|
16511
16602
|
});
|
|
16512
|
-
|
|
16603
|
+
app19.delete("/:id", requireAdminSession, async (c) => {
|
|
16513
16604
|
const sessionId = c.req.param("id");
|
|
16514
16605
|
const cacheKey = c.var.cacheKey;
|
|
16515
16606
|
const accountId = getAccountIdForSession(cacheKey);
|
|
@@ -16554,7 +16645,7 @@ app18.delete("/:id", requireAdminSession, async (c) => {
|
|
|
16554
16645
|
500
|
|
16555
16646
|
);
|
|
16556
16647
|
});
|
|
16557
|
-
|
|
16648
|
+
app19.post("/:id/resume", async (c) => {
|
|
16558
16649
|
const sessionId = c.req.param("id");
|
|
16559
16650
|
const t0 = Date.now();
|
|
16560
16651
|
const signedSessionToken = c.req.query("session_key") ?? "";
|
|
@@ -16823,7 +16914,7 @@ app18.post("/:id/resume", async (c) => {
|
|
|
16823
16914
|
}
|
|
16824
16915
|
});
|
|
16825
16916
|
});
|
|
16826
|
-
|
|
16917
|
+
app19.put("/:id/label", requireAdminSession, async (c) => {
|
|
16827
16918
|
const sessionId = c.req.param("id");
|
|
16828
16919
|
const cacheKey = c.var.cacheKey;
|
|
16829
16920
|
let body;
|
|
@@ -16849,11 +16940,11 @@ app18.put("/:id/label", requireAdminSession, async (c) => {
|
|
|
16849
16940
|
return c.json({ error: "Failed to rename session" }, 500);
|
|
16850
16941
|
}
|
|
16851
16942
|
});
|
|
16852
|
-
var sessions_default =
|
|
16943
|
+
var sessions_default = app19;
|
|
16853
16944
|
|
|
16854
16945
|
// app/lib/claude-agent/spawn-context.ts
|
|
16855
|
-
import { existsSync as
|
|
16856
|
-
import { dirname as
|
|
16946
|
+
import { existsSync as existsSync32, readFileSync as readFileSync33, readdirSync as readdirSync22, statSync as statSync15 } from "fs";
|
|
16947
|
+
import { dirname as dirname12, resolve as resolve23, join as join33 } from "path";
|
|
16857
16948
|
async function resolveOwnerProfileBlock(accountId, userId) {
|
|
16858
16949
|
if (!userId) return { ok: false, reason: "missing-user-id" };
|
|
16859
16950
|
try {
|
|
@@ -16899,7 +16990,7 @@ function extractPluginToolDescriptions(pluginDir) {
|
|
|
16899
16990
|
];
|
|
16900
16991
|
let raw = null;
|
|
16901
16992
|
for (const path3 of candidates) {
|
|
16902
|
-
if (!
|
|
16993
|
+
if (!existsSync32(path3)) continue;
|
|
16903
16994
|
try {
|
|
16904
16995
|
raw = readFileSync33(path3, "utf-8");
|
|
16905
16996
|
break;
|
|
@@ -16950,26 +17041,26 @@ function parseSkillPathsFromFrontmatter(fm) {
|
|
|
16950
17041
|
}
|
|
16951
17042
|
function listPluginDirs(accountPluginsDir) {
|
|
16952
17043
|
const out = /* @__PURE__ */ new Map();
|
|
16953
|
-
const platformPlugins =
|
|
16954
|
-
if (
|
|
17044
|
+
const platformPlugins = resolve23(PLATFORM_ROOT, "plugins");
|
|
17045
|
+
if (existsSync32(platformPlugins)) {
|
|
16955
17046
|
for (const name of readdirSync22(platformPlugins)) {
|
|
16956
17047
|
const dir = join33(platformPlugins, name);
|
|
16957
17048
|
try {
|
|
16958
|
-
if (
|
|
17049
|
+
if (statSync15(dir).isDirectory()) out.set(name, dir);
|
|
16959
17050
|
} catch {
|
|
16960
17051
|
}
|
|
16961
17052
|
}
|
|
16962
17053
|
}
|
|
16963
|
-
const premiumRoot =
|
|
16964
|
-
if (
|
|
17054
|
+
const premiumRoot = resolve23(dirname12(PLATFORM_ROOT), "premium-plugins");
|
|
17055
|
+
if (existsSync32(premiumRoot)) {
|
|
16965
17056
|
for (const bundle of readdirSync22(premiumRoot)) {
|
|
16966
17057
|
const bundlePlugins = join33(premiumRoot, bundle, "plugins");
|
|
16967
|
-
if (!
|
|
17058
|
+
if (!existsSync32(bundlePlugins)) continue;
|
|
16968
17059
|
try {
|
|
16969
17060
|
for (const name of readdirSync22(bundlePlugins)) {
|
|
16970
17061
|
const dir = join33(bundlePlugins, name);
|
|
16971
17062
|
try {
|
|
16972
|
-
if (
|
|
17063
|
+
if (statSync15(dir).isDirectory()) out.set(name, dir);
|
|
16973
17064
|
} catch {
|
|
16974
17065
|
}
|
|
16975
17066
|
}
|
|
@@ -16977,13 +17068,13 @@ function listPluginDirs(accountPluginsDir) {
|
|
|
16977
17068
|
}
|
|
16978
17069
|
}
|
|
16979
17070
|
}
|
|
16980
|
-
if (accountPluginsDir &&
|
|
17071
|
+
if (accountPluginsDir && existsSync32(accountPluginsDir)) {
|
|
16981
17072
|
try {
|
|
16982
17073
|
for (const name of readdirSync22(accountPluginsDir)) {
|
|
16983
17074
|
if (out.has(name)) continue;
|
|
16984
17075
|
const dir = join33(accountPluginsDir, name);
|
|
16985
17076
|
try {
|
|
16986
|
-
if (
|
|
17077
|
+
if (statSync15(dir).isDirectory()) out.set(name, dir);
|
|
16987
17078
|
} catch {
|
|
16988
17079
|
}
|
|
16989
17080
|
}
|
|
@@ -16993,14 +17084,14 @@ function listPluginDirs(accountPluginsDir) {
|
|
|
16993
17084
|
return out;
|
|
16994
17085
|
}
|
|
16995
17086
|
function accountPluginsDirFor(accountId) {
|
|
16996
|
-
return
|
|
17087
|
+
return resolve23(PLATFORM_ROOT, "..", "data/accounts", accountId, "plugins");
|
|
16997
17088
|
}
|
|
16998
17089
|
function listAccountPluginNames(accountPluginsDir) {
|
|
16999
|
-
if (!
|
|
17090
|
+
if (!existsSync32(accountPluginsDir)) return [];
|
|
17000
17091
|
try {
|
|
17001
17092
|
return readdirSync22(accountPluginsDir).filter((name) => {
|
|
17002
17093
|
try {
|
|
17003
|
-
return
|
|
17094
|
+
return statSync15(join33(accountPluginsDir, name)).isDirectory();
|
|
17004
17095
|
} catch {
|
|
17005
17096
|
return false;
|
|
17006
17097
|
}
|
|
@@ -17010,8 +17101,8 @@ function listAccountPluginNames(accountPluginsDir) {
|
|
|
17010
17101
|
}
|
|
17011
17102
|
}
|
|
17012
17103
|
function readEnabledPlugins(accountId) {
|
|
17013
|
-
const accountFile =
|
|
17014
|
-
if (!
|
|
17104
|
+
const accountFile = resolve23(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
|
|
17105
|
+
if (!existsSync32(accountFile)) return /* @__PURE__ */ new Set();
|
|
17015
17106
|
try {
|
|
17016
17107
|
const parsed = JSON.parse(readFileSync33(accountFile, "utf-8"));
|
|
17017
17108
|
return new Set(
|
|
@@ -17022,7 +17113,7 @@ function readEnabledPlugins(accountId) {
|
|
|
17022
17113
|
}
|
|
17023
17114
|
}
|
|
17024
17115
|
function readFrontmatter(path3) {
|
|
17025
|
-
if (!
|
|
17116
|
+
if (!existsSync32(path3)) return null;
|
|
17026
17117
|
let raw;
|
|
17027
17118
|
try {
|
|
17028
17119
|
raw = readFileSync33(path3, "utf-8");
|
|
@@ -17060,7 +17151,7 @@ ${fm}
|
|
|
17060
17151
|
`plugin-manifest-tool-coverage plugin=${name} tools=${tools.length} with-desc=${withDesc}`
|
|
17061
17152
|
);
|
|
17062
17153
|
if (toolNames.length > 0 && descMap.size === 0) {
|
|
17063
|
-
const hasSource =
|
|
17154
|
+
const hasSource = existsSync32(join33(dir, "mcp/dist/index.js")) || existsSync32(join33(dir, "mcp/src/index.ts"));
|
|
17064
17155
|
if (hasSource) {
|
|
17065
17156
|
console.warn(
|
|
17066
17157
|
`[spawn-context] WARN plugin=${name} mcp source present but tool-description regex matched zero entries \u2014 SDK upgrade may have changed the registration shape`
|
|
@@ -17086,8 +17177,8 @@ ${skillFm}
|
|
|
17086
17177
|
return out;
|
|
17087
17178
|
}
|
|
17088
17179
|
function computeSpecialistDomains(accountId) {
|
|
17089
|
-
const specialistsDir =
|
|
17090
|
-
if (!
|
|
17180
|
+
const specialistsDir = resolve23(PLATFORM_ROOT, "..", "data/accounts", accountId, "specialists", "agents");
|
|
17181
|
+
if (!existsSync32(specialistsDir)) return [];
|
|
17091
17182
|
let entries;
|
|
17092
17183
|
try {
|
|
17093
17184
|
entries = readdirSync22(specialistsDir);
|
|
@@ -17099,10 +17190,10 @@ function computeSpecialistDomains(accountId) {
|
|
|
17099
17190
|
const resolveDesc = (qualified) => {
|
|
17100
17191
|
if (!qualified.startsWith("mcp__")) return void 0;
|
|
17101
17192
|
const rest = qualified.slice(5);
|
|
17102
|
-
const
|
|
17103
|
-
if (
|
|
17104
|
-
const plugin = rest.slice(0,
|
|
17105
|
-
const tool = rest.slice(
|
|
17193
|
+
const sep12 = rest.indexOf("__");
|
|
17194
|
+
if (sep12 < 0) return void 0;
|
|
17195
|
+
const plugin = rest.slice(0, sep12);
|
|
17196
|
+
const tool = rest.slice(sep12 + 2);
|
|
17106
17197
|
let map = descByPlugin.get(plugin);
|
|
17107
17198
|
if (!map) {
|
|
17108
17199
|
const dir = pluginDirs.get(plugin);
|
|
@@ -17132,8 +17223,8 @@ ${fm}
|
|
|
17132
17223
|
return out;
|
|
17133
17224
|
}
|
|
17134
17225
|
function computeDormantPlugins(accountId) {
|
|
17135
|
-
const accountFile =
|
|
17136
|
-
if (!
|
|
17226
|
+
const accountFile = resolve23(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
|
|
17227
|
+
if (!existsSync32(accountFile)) return [];
|
|
17137
17228
|
let enabled;
|
|
17138
17229
|
try {
|
|
17139
17230
|
const raw = readFileSync33(accountFile, "utf-8");
|
|
@@ -17147,8 +17238,8 @@ function computeDormantPlugins(accountId) {
|
|
|
17147
17238
|
);
|
|
17148
17239
|
return [];
|
|
17149
17240
|
}
|
|
17150
|
-
const pluginsDir =
|
|
17151
|
-
if (!
|
|
17241
|
+
const pluginsDir = resolve23(PLATFORM_ROOT, "plugins");
|
|
17242
|
+
if (!existsSync32(pluginsDir)) return [];
|
|
17152
17243
|
let entries;
|
|
17153
17244
|
try {
|
|
17154
17245
|
entries = readdirSync22(pluginsDir);
|
|
@@ -17158,8 +17249,8 @@ function computeDormantPlugins(accountId) {
|
|
|
17158
17249
|
const out = [];
|
|
17159
17250
|
for (const name of entries) {
|
|
17160
17251
|
if (enabled.has(name)) continue;
|
|
17161
|
-
const manifestPath =
|
|
17162
|
-
if (!
|
|
17252
|
+
const manifestPath = resolve23(pluginsDir, name, "PLUGIN.md");
|
|
17253
|
+
if (!existsSync32(manifestPath)) continue;
|
|
17163
17254
|
let manifest;
|
|
17164
17255
|
try {
|
|
17165
17256
|
manifest = readFileSync33(manifestPath, "utf-8");
|
|
@@ -17176,11 +17267,11 @@ function computeDormantPlugins(accountId) {
|
|
|
17176
17267
|
}
|
|
17177
17268
|
|
|
17178
17269
|
// server/routes/admin/claude-sessions.ts
|
|
17179
|
-
import { existsSync as
|
|
17180
|
-
import { resolve as
|
|
17270
|
+
import { existsSync as existsSync33, readFileSync as readFileSync34 } from "fs";
|
|
17271
|
+
import { resolve as resolve24 } from "path";
|
|
17181
17272
|
function readTunnelState(brandConfigDir) {
|
|
17182
17273
|
const statePath = `${process.env.HOME ?? ""}/${brandConfigDir}/cloudflared/tunnel.state`;
|
|
17183
|
-
if (!
|
|
17274
|
+
if (!existsSync33(statePath)) return null;
|
|
17184
17275
|
try {
|
|
17185
17276
|
const parsed = JSON.parse(readFileSync34(statePath, "utf-8"));
|
|
17186
17277
|
const tunnelId = typeof parsed.tunnelId === "string" ? parsed.tunnelId : null;
|
|
@@ -17193,10 +17284,10 @@ function readTunnelState(brandConfigDir) {
|
|
|
17193
17284
|
}
|
|
17194
17285
|
}
|
|
17195
17286
|
function resolveTunnelUrl() {
|
|
17196
|
-
const platformRoot5 = process.env.MAXY_PLATFORM_ROOT ?? process.env.PLATFORM_ROOT ??
|
|
17287
|
+
const platformRoot5 = process.env.MAXY_PLATFORM_ROOT ?? process.env.PLATFORM_ROOT ?? resolve24(process.cwd(), "..");
|
|
17197
17288
|
let brand;
|
|
17198
17289
|
try {
|
|
17199
|
-
brand = JSON.parse(readFileSync34(
|
|
17290
|
+
brand = JSON.parse(readFileSync34(resolve24(platformRoot5, "config", "brand.json"), "utf-8"));
|
|
17200
17291
|
} catch {
|
|
17201
17292
|
return null;
|
|
17202
17293
|
}
|
|
@@ -17219,7 +17310,7 @@ async function refuseIfClaudeAuthDead(c, route, sessionId) {
|
|
|
17219
17310
|
503
|
|
17220
17311
|
);
|
|
17221
17312
|
}
|
|
17222
|
-
var
|
|
17313
|
+
var app20 = new Hono();
|
|
17223
17314
|
async function performSpawnWithInitialMessage(args) {
|
|
17224
17315
|
const ownerStart = Date.now();
|
|
17225
17316
|
const aboutOwner = await resolveOwnerProfileBlock(args.senderId, args.userId);
|
|
@@ -17296,8 +17387,8 @@ function mintTranscriptEdge(sessionId, claudeSessionId, accountId) {
|
|
|
17296
17387
|
if (!sessionId || !claudeSessionId) return;
|
|
17297
17388
|
void linkConversationTranscript(sessionId, claudeSessionId, accountId);
|
|
17298
17389
|
}
|
|
17299
|
-
|
|
17300
|
-
|
|
17390
|
+
app20.use("*", requireAdminSession);
|
|
17391
|
+
app20.post("/", async (c) => {
|
|
17301
17392
|
const routeStart = Date.now();
|
|
17302
17393
|
const cacheKey = c.get("cacheKey") ?? "";
|
|
17303
17394
|
let body = {};
|
|
@@ -17340,18 +17431,18 @@ app19.post("/", async (c) => {
|
|
|
17340
17431
|
console.log(`${TAG31} route-done surface=cookie status=${response.status} route-ms=${Date.now() - routeStart}`);
|
|
17341
17432
|
return response;
|
|
17342
17433
|
});
|
|
17343
|
-
var claude_sessions_default =
|
|
17434
|
+
var claude_sessions_default = app20;
|
|
17344
17435
|
|
|
17345
17436
|
// server/routes/admin/log-ingest.ts
|
|
17346
17437
|
var TAG32 = "[log-ingest]";
|
|
17347
17438
|
var TAG_PATTERN = /^[A-Za-z0-9_:-]{1,32}$/;
|
|
17348
17439
|
var LEVELS = /* @__PURE__ */ new Set(["debug", "info", "warn", "error"]);
|
|
17349
17440
|
var MAX_LINE_BYTES = 4096;
|
|
17350
|
-
var
|
|
17441
|
+
var app21 = new Hono();
|
|
17351
17442
|
function isLoopbackAddr2(addr) {
|
|
17352
17443
|
return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
|
|
17353
17444
|
}
|
|
17354
|
-
|
|
17445
|
+
app21.post("/", async (c) => {
|
|
17355
17446
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
17356
17447
|
if (!isLoopbackAddr2(remoteAddr)) {
|
|
17357
17448
|
console.error(`${TAG32} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
@@ -17394,7 +17485,7 @@ app20.post("/", async (c) => {
|
|
|
17394
17485
|
else console.log(formatted);
|
|
17395
17486
|
return c.json({ ok: true }, 200);
|
|
17396
17487
|
});
|
|
17397
|
-
var log_ingest_default =
|
|
17488
|
+
var log_ingest_default = app21;
|
|
17398
17489
|
|
|
17399
17490
|
// server/routes/admin/events.ts
|
|
17400
17491
|
var ALLOWED_EVENTS = /* @__PURE__ */ new Set([
|
|
@@ -17403,8 +17494,8 @@ var ALLOWED_EVENTS = /* @__PURE__ */ new Set([
|
|
|
17403
17494
|
"device-url:vnc-surface-shown",
|
|
17404
17495
|
"device-url:malformed"
|
|
17405
17496
|
]);
|
|
17406
|
-
var
|
|
17407
|
-
|
|
17497
|
+
var app22 = new Hono();
|
|
17498
|
+
app22.post("/", async (c) => {
|
|
17408
17499
|
const TAG56 = "[admin:events]";
|
|
17409
17500
|
let body;
|
|
17410
17501
|
try {
|
|
@@ -17435,14 +17526,14 @@ app21.post("/", async (c) => {
|
|
|
17435
17526
|
console.error(`[${event}] ${formatted}`);
|
|
17436
17527
|
return c.json({ ok: true });
|
|
17437
17528
|
});
|
|
17438
|
-
var events_default =
|
|
17529
|
+
var events_default = app22;
|
|
17439
17530
|
|
|
17440
17531
|
// server/routes/admin/files.ts
|
|
17441
|
-
import { createReadStream as createReadStream2, createWriteStream as createWriteStream2, existsSync as
|
|
17442
|
-
import { readdir as readdir4, readFile as
|
|
17443
|
-
import { realpathSync as
|
|
17532
|
+
import { createReadStream as createReadStream2, createWriteStream as createWriteStream2, existsSync as existsSync34 } from "fs";
|
|
17533
|
+
import { readdir as readdir4, readFile as readFile7, stat as stat6, mkdir as mkdir4, unlink as unlink3, rename as rename2, rmdir } from "fs/promises";
|
|
17534
|
+
import { realpathSync as realpathSync7 } from "fs";
|
|
17444
17535
|
import { randomUUID as randomUUID10 } from "crypto";
|
|
17445
|
-
import { basename as
|
|
17536
|
+
import { basename as basename11, dirname as dirname13, join as join35, relative as relative5, resolve as resolve26, sep as sep8 } from "path";
|
|
17446
17537
|
import { Readable as Readable2 } from "stream";
|
|
17447
17538
|
|
|
17448
17539
|
// ../lib/graph-trash/src/index.ts
|
|
@@ -17760,7 +17851,7 @@ async function cascadeDeleteDocument(params) {
|
|
|
17760
17851
|
|
|
17761
17852
|
// app/lib/file-index.ts
|
|
17762
17853
|
import * as fsp from "fs/promises";
|
|
17763
|
-
import { resolve as
|
|
17854
|
+
import { resolve as resolve25, relative as relative4, join as join34, basename as basename10, extname as extname2, sep as sep7 } from "path";
|
|
17764
17855
|
import { tmpdir as tmpdir2 } from "os";
|
|
17765
17856
|
import { execFile as execFile2 } from "child_process";
|
|
17766
17857
|
import { promisify as promisify2 } from "util";
|
|
@@ -17898,8 +17989,8 @@ async function extractFileContent(absolute) {
|
|
|
17898
17989
|
}
|
|
17899
17990
|
}
|
|
17900
17991
|
async function readDisplayName(absolute) {
|
|
17901
|
-
const dir = absolute.slice(0, absolute.length -
|
|
17902
|
-
const base =
|
|
17992
|
+
const dir = absolute.slice(0, absolute.length - basename10(absolute).length);
|
|
17993
|
+
const base = basename10(absolute);
|
|
17903
17994
|
const dot = base.lastIndexOf(".");
|
|
17904
17995
|
const stem = dot === -1 ? base : base.slice(0, dot);
|
|
17905
17996
|
if (base === `${stem}.meta.json`) return null;
|
|
@@ -17934,7 +18025,7 @@ async function walkSubtree(root, dataRoot, out) {
|
|
|
17934
18025
|
const st = await fsp.stat(abs);
|
|
17935
18026
|
out.push({
|
|
17936
18027
|
absolute: abs,
|
|
17937
|
-
relativePath: relative4(dataRoot, abs).split(
|
|
18028
|
+
relativePath: relative4(dataRoot, abs).split(sep7).join("/"),
|
|
17938
18029
|
sizeBytes: st.size,
|
|
17939
18030
|
modifiedAt: st.mtime.toISOString()
|
|
17940
18031
|
});
|
|
@@ -18037,7 +18128,7 @@ async function cascadeTrashLinkedKnowledgeDocs(session, accountId, relativePaths
|
|
|
18037
18128
|
return { kds, sections, chunks };
|
|
18038
18129
|
}
|
|
18039
18130
|
async function buildArtifact(accountId, wf, embed2) {
|
|
18040
|
-
const name =
|
|
18131
|
+
const name = basename10(wf.absolute);
|
|
18041
18132
|
const { content, route } = await extractFileContent(wf.absolute);
|
|
18042
18133
|
const displayName = await readDisplayName(wf.absolute);
|
|
18043
18134
|
const embedInput = `${name}
|
|
@@ -18080,7 +18171,7 @@ async function reconcileFileIndex(accountId, opts) {
|
|
|
18080
18171
|
return withSession(opts, async (session) => {
|
|
18081
18172
|
const walked = [];
|
|
18082
18173
|
const subtreeRoots = [
|
|
18083
|
-
|
|
18174
|
+
resolve25(dataRoot, "accounts", accountId)
|
|
18084
18175
|
];
|
|
18085
18176
|
let clean = true;
|
|
18086
18177
|
for (const root of subtreeRoots) {
|
|
@@ -18163,7 +18254,7 @@ async function reconcileFileIndexDebounced(accountId, opts) {
|
|
|
18163
18254
|
async function indexFile(accountId, relativePath, opts) {
|
|
18164
18255
|
const dataRoot = opts?.dataRoot ?? DATA_ROOT;
|
|
18165
18256
|
const embed2 = opts?.embed ?? embed;
|
|
18166
|
-
const absolute =
|
|
18257
|
+
const absolute = resolve25(dataRoot, relativePath);
|
|
18167
18258
|
await withSession(opts, async (session) => {
|
|
18168
18259
|
const st = await fsp.stat(absolute);
|
|
18169
18260
|
const wf = {
|
|
@@ -18281,7 +18372,7 @@ var UPLOAD_TMP_DIR = ".uploads-tmp";
|
|
|
18281
18372
|
var UUID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
18282
18373
|
async function readMeta(absDir, baseName) {
|
|
18283
18374
|
try {
|
|
18284
|
-
const raw = await
|
|
18375
|
+
const raw = await readFile7(join35(absDir, `${baseName}.meta.json`), "utf8");
|
|
18285
18376
|
const parsed = JSON.parse(raw);
|
|
18286
18377
|
if (typeof parsed?.filename === "string") {
|
|
18287
18378
|
return { filename: parsed.filename, mimeType: typeof parsed.mimeType === "string" ? parsed.mimeType : void 0 };
|
|
@@ -18292,7 +18383,7 @@ async function readMeta(absDir, baseName) {
|
|
|
18292
18383
|
}
|
|
18293
18384
|
async function readAccountNames() {
|
|
18294
18385
|
const map = /* @__PURE__ */ new Map();
|
|
18295
|
-
const accountsDir =
|
|
18386
|
+
const accountsDir = resolve26(DATA_ROOT, "accounts");
|
|
18296
18387
|
let names;
|
|
18297
18388
|
try {
|
|
18298
18389
|
names = await readdir4(accountsDir);
|
|
@@ -18301,9 +18392,9 @@ async function readAccountNames() {
|
|
|
18301
18392
|
}
|
|
18302
18393
|
for (const name of names) {
|
|
18303
18394
|
if (!UUID_RE4.test(name)) continue;
|
|
18304
|
-
const configPath2 =
|
|
18395
|
+
const configPath2 = resolve26(accountsDir, name, "account.json");
|
|
18305
18396
|
try {
|
|
18306
|
-
const raw = await
|
|
18397
|
+
const raw = await readFile7(configPath2, "utf8");
|
|
18307
18398
|
const parsed = JSON.parse(raw);
|
|
18308
18399
|
if (typeof parsed?.name === "string" && parsed.name.length > 0) {
|
|
18309
18400
|
map.set(name, parsed.name);
|
|
@@ -18480,8 +18571,8 @@ async function knowledgeDocOwnedByAccount(accountId, attachmentId) {
|
|
|
18480
18571
|
await session.close();
|
|
18481
18572
|
}
|
|
18482
18573
|
}
|
|
18483
|
-
var
|
|
18484
|
-
|
|
18574
|
+
var app23 = new Hono();
|
|
18575
|
+
app23.get("/", requireAdminSession, async (c) => {
|
|
18485
18576
|
const cacheKey = c.var.cacheKey;
|
|
18486
18577
|
const accountId = getAccountIdForSession(cacheKey);
|
|
18487
18578
|
if (!accountId) {
|
|
@@ -18560,7 +18651,7 @@ app22.get("/", requireAdminSession, async (c) => {
|
|
|
18560
18651
|
return c.json({ error: message }, 500);
|
|
18561
18652
|
}
|
|
18562
18653
|
});
|
|
18563
|
-
|
|
18654
|
+
app23.get("/download", requireAdminSession, async (c) => {
|
|
18564
18655
|
const cacheKey = c.var.cacheKey;
|
|
18565
18656
|
const accountId = getAccountIdForSession(cacheKey);
|
|
18566
18657
|
if (!accountId) {
|
|
@@ -18614,7 +18705,7 @@ app22.get("/download", requireAdminSession, async (c) => {
|
|
|
18614
18705
|
if (!info.isFile()) {
|
|
18615
18706
|
return c.json({ error: "Path is not a file" }, 400);
|
|
18616
18707
|
}
|
|
18617
|
-
const filename =
|
|
18708
|
+
const filename = basename11(absolute);
|
|
18618
18709
|
const mimeType = detectMimeType(absolute);
|
|
18619
18710
|
const nodeStream = createReadStream2(absolute);
|
|
18620
18711
|
const webStream = Readable2.toWeb(nodeStream);
|
|
@@ -18638,7 +18729,7 @@ app22.get("/download", requireAdminSession, async (c) => {
|
|
|
18638
18729
|
if (root === "data") {
|
|
18639
18730
|
const parsed = parseAttachmentPath(relPath);
|
|
18640
18731
|
if (parsed) {
|
|
18641
|
-
const meta = await readMeta(
|
|
18732
|
+
const meta = await readMeta(dirname13(absolute), parsed.attachmentId);
|
|
18642
18733
|
if (meta?.filename) downloadName = meta.filename;
|
|
18643
18734
|
}
|
|
18644
18735
|
}
|
|
@@ -18686,7 +18777,7 @@ async function* walkRegularFiles(dirAbsolute) {
|
|
|
18686
18777
|
if (d.isFile()) yield child;
|
|
18687
18778
|
}
|
|
18688
18779
|
}
|
|
18689
|
-
|
|
18780
|
+
app23.get("/download-zip", requireAdminSession, async (c) => {
|
|
18690
18781
|
const cacheKey = c.var.cacheKey;
|
|
18691
18782
|
const accountId = getAccountIdForSession(cacheKey);
|
|
18692
18783
|
if (!accountId) {
|
|
@@ -18707,7 +18798,7 @@ app22.get("/download-zip", requireAdminSession, async (c) => {
|
|
|
18707
18798
|
if (entries.length >= maxFiles) return c.json({ error: `Too many files (max ${maxFiles})` }, 413);
|
|
18708
18799
|
total += size;
|
|
18709
18800
|
if (total > maxTotalBytes) return c.json({ error: "Selection too large to zip" }, 413);
|
|
18710
|
-
entries.push({ name: member, data: await
|
|
18801
|
+
entries.push({ name: member, data: await readFile7(absolute) });
|
|
18711
18802
|
return null;
|
|
18712
18803
|
};
|
|
18713
18804
|
for (const rawPath of rawPaths) {
|
|
@@ -18727,21 +18818,21 @@ app22.get("/download-zip", requireAdminSession, async (c) => {
|
|
|
18727
18818
|
const info = await stat6(absolute);
|
|
18728
18819
|
if (info.isDirectory()) {
|
|
18729
18820
|
dirsWalked++;
|
|
18730
|
-
const parentAbs =
|
|
18821
|
+
const parentAbs = dirname13(absolute);
|
|
18731
18822
|
for await (const fileAbs of walkRegularFiles(absolute)) {
|
|
18732
|
-
const within = relative5(absolute, fileAbs).split(
|
|
18823
|
+
const within = relative5(absolute, fileAbs).split(sep8).join("/");
|
|
18733
18824
|
const fileRel = relPath === "" || relPath === "." ? within : `${relPath}/${within}`;
|
|
18734
18825
|
if (crossesForeignAccountPartition(fileRel, accountId)) continue;
|
|
18735
18826
|
const fileInfo = await stat6(fileAbs);
|
|
18736
|
-
const member = relative5(parentAbs, fileAbs).split(
|
|
18827
|
+
const member = relative5(parentAbs, fileAbs).split(sep8).join("/");
|
|
18737
18828
|
const over = await addFile(fileAbs, fileInfo.size, member);
|
|
18738
18829
|
if (over) return over;
|
|
18739
18830
|
}
|
|
18740
18831
|
} else if (info.isFile()) {
|
|
18741
|
-
let member =
|
|
18832
|
+
let member = basename11(absolute);
|
|
18742
18833
|
const parsed = parseAttachmentPath(relPath);
|
|
18743
18834
|
if (parsed) {
|
|
18744
|
-
const meta = await readMeta(
|
|
18835
|
+
const meta = await readMeta(dirname13(absolute), parsed.attachmentId);
|
|
18745
18836
|
if (meta?.filename) member = meta.filename;
|
|
18746
18837
|
}
|
|
18747
18838
|
const over = await addFile(absolute, info.size, member);
|
|
@@ -18773,12 +18864,12 @@ function dataUploadCeiling() {
|
|
|
18773
18864
|
}
|
|
18774
18865
|
async function resolveUploadTarget(c, accountId, uid) {
|
|
18775
18866
|
const rawName = c.req.query("filename") ?? "";
|
|
18776
|
-
const safeName =
|
|
18867
|
+
const safeName = basename11(rawName).replace(/[\0/\\]/g, "_");
|
|
18777
18868
|
if (!safeName) return { ok: false, status: 400, error: "filename query param required" };
|
|
18778
18869
|
const rawRelpath = c.req.query("relpath") ?? "";
|
|
18779
18870
|
const relpath = rawRelpath !== "" ? rawRelpath : null;
|
|
18780
18871
|
const token = c.req.query("token") ?? "";
|
|
18781
|
-
const finalName = relpath ?
|
|
18872
|
+
const finalName = relpath ? basename11(relpath).replace(/[\0/\\]/g, "_") : `${Date.now()}-${safeName}`;
|
|
18782
18873
|
const mimeType = (c.req.header("content-type") ?? "").split(";")[0].trim();
|
|
18783
18874
|
if (!SUPPORTED_MIME_TYPES.has(mimeType)) {
|
|
18784
18875
|
console.error(`[data-upload] op=reject-mime uid=${uid} mime="${mimeType}" token=${token} rel="${relpath ?? ""}"`);
|
|
@@ -18787,7 +18878,7 @@ async function resolveUploadTarget(c, accountId, uid) {
|
|
|
18787
18878
|
const rawDir = c.req.query("path") ?? "";
|
|
18788
18879
|
const base = resolveOwnAccountWrite(rawDir, accountId, "POST /api/admin/files/upload");
|
|
18789
18880
|
if (!base.ok) return { ok: false, status: base.status, error: base.error };
|
|
18790
|
-
const relDir = relpath ?
|
|
18881
|
+
const relDir = relpath ? dirname13(relpath) : ".";
|
|
18791
18882
|
const destRel = relDir === "." ? base.relative : join35(base.relative, relDir);
|
|
18792
18883
|
if (crossesForeignAccountPartition(destRel, accountId)) {
|
|
18793
18884
|
console.error(`[data] account-scope-blocked endpoint="POST /api/admin/files/upload" path="${destRel}" account=${accountId.slice(0, 8)}\u2026`);
|
|
@@ -18797,8 +18888,8 @@ async function resolveUploadTarget(c, accountId, uid) {
|
|
|
18797
18888
|
console.error(`[data] write-scope-blocked endpoint="POST /api/admin/files/upload" path="${destRel}" account=${accountId.slice(0, 8)}\u2026`);
|
|
18798
18889
|
return { ok: false, status: 403, error: "Path is outside your account folder" };
|
|
18799
18890
|
}
|
|
18800
|
-
const destDir = relDir === "." ? base.absolute :
|
|
18801
|
-
const destPath =
|
|
18891
|
+
const destDir = relDir === "." ? base.absolute : resolve26(base.absolute, relDir);
|
|
18892
|
+
const destPath = resolve26(destDir, finalName);
|
|
18802
18893
|
if (relpath) {
|
|
18803
18894
|
const firstCreated = await mkdir4(destDir, { recursive: true });
|
|
18804
18895
|
if (firstCreated) console.error(`[data-upload] op=mkdir uid=${uid} token=${token} dir="${destRel}"`);
|
|
@@ -18806,16 +18897,16 @@ async function resolveUploadTarget(c, accountId, uid) {
|
|
|
18806
18897
|
const info = await stat6(destDir).catch(() => null);
|
|
18807
18898
|
if (!info || !info.isDirectory()) return { ok: false, status: 400, error: "Upload destination is not a directory" };
|
|
18808
18899
|
}
|
|
18809
|
-
const dataRootReal =
|
|
18810
|
-
const destDirReal =
|
|
18811
|
-
if (destDirReal !== dataRootReal && !destDirReal.startsWith(dataRootReal +
|
|
18900
|
+
const dataRootReal = realpathSync7(DATA_ROOT);
|
|
18901
|
+
const destDirReal = realpathSync7(destDir);
|
|
18902
|
+
if (destDirReal !== dataRootReal && !destDirReal.startsWith(dataRootReal + sep8)) {
|
|
18812
18903
|
console.error(`[data-upload] op=path-traversal-blocked uid=${uid} requested="${destRel}" resolved="${destDirReal}"`);
|
|
18813
18904
|
return { ok: false, status: 403, error: "Upload destination escapes DATA_ROOT" };
|
|
18814
18905
|
}
|
|
18815
18906
|
return { ok: true, destDir, destPath, destRel, finalName, mimeType, relpath, token };
|
|
18816
18907
|
}
|
|
18817
18908
|
async function logUploadsTmpCensus(accountId) {
|
|
18818
|
-
const tmpDir =
|
|
18909
|
+
const tmpDir = resolve26(DATA_ROOT, "accounts", accountId, UPLOAD_TMP_DIR);
|
|
18819
18910
|
let live = 0;
|
|
18820
18911
|
try {
|
|
18821
18912
|
live = (await readdir4(tmpDir)).length;
|
|
@@ -18823,7 +18914,7 @@ async function logUploadsTmpCensus(accountId) {
|
|
|
18823
18914
|
}
|
|
18824
18915
|
console.error(`[uploads-tmp-census] dir=${accountId} live=${live}`);
|
|
18825
18916
|
}
|
|
18826
|
-
|
|
18917
|
+
app23.post("/upload", requireAdminSession, async (c) => {
|
|
18827
18918
|
const cacheKey = c.var.cacheKey;
|
|
18828
18919
|
const accountId = getAccountIdForSession(cacheKey);
|
|
18829
18920
|
if (!accountId) {
|
|
@@ -18842,9 +18933,9 @@ app22.post("/upload", requireAdminSession, async (c) => {
|
|
|
18842
18933
|
if (!body) return c.json({ error: "Empty request body" }, 400);
|
|
18843
18934
|
console.error(`[data-upload] op=request uid=${uid} account=${accountId} dir="${destRel}" token=${token} rel="${relpath ?? ""}" declaredBytes=${declaredBytes}`);
|
|
18844
18935
|
const ceiling = dataUploadCeiling();
|
|
18845
|
-
const tmpDir =
|
|
18936
|
+
const tmpDir = resolve26(DATA_ROOT, "accounts", accountId, UPLOAD_TMP_DIR);
|
|
18846
18937
|
await mkdir4(tmpDir, { recursive: true });
|
|
18847
|
-
const tmpPath =
|
|
18938
|
+
const tmpPath = resolve26(tmpDir, `${uid}.part`);
|
|
18848
18939
|
const out = createWriteStream2(tmpPath);
|
|
18849
18940
|
const t0 = Date.now();
|
|
18850
18941
|
let received = 0;
|
|
@@ -18862,7 +18953,7 @@ app22.post("/upload", requireAdminSession, async (c) => {
|
|
|
18862
18953
|
});
|
|
18863
18954
|
await unlink3(tmpPath).catch(() => {
|
|
18864
18955
|
});
|
|
18865
|
-
const tempRemoved = !
|
|
18956
|
+
const tempRemoved = !existsSync34(tmpPath);
|
|
18866
18957
|
console.error(`[data-upload] op=cleanup uid=${uid} tempRemoved=${tempRemoved}`);
|
|
18867
18958
|
};
|
|
18868
18959
|
const reader = body.getReader();
|
|
@@ -18936,7 +19027,7 @@ async function discardChunkUpload(uploadId, state) {
|
|
|
18936
19027
|
});
|
|
18937
19028
|
await unlink3(state.tmpPath).catch(() => {
|
|
18938
19029
|
});
|
|
18939
|
-
const tempRemoved = !
|
|
19030
|
+
const tempRemoved = !existsSync34(state.tmpPath);
|
|
18940
19031
|
console.error(`[data-upload] op=cleanup uid=${uploadId} tempRemoved=${tempRemoved}`);
|
|
18941
19032
|
}
|
|
18942
19033
|
async function writeChunkBody(body, out, alreadyReceived, ceiling) {
|
|
@@ -18991,9 +19082,9 @@ async function handleChunkUpload(c, accountId) {
|
|
|
18991
19082
|
}
|
|
18992
19083
|
const target = await resolveUploadTarget(c, accountId, uploadId);
|
|
18993
19084
|
if (!target.ok) return c.json({ error: target.error }, target.status);
|
|
18994
|
-
const tmpDir =
|
|
19085
|
+
const tmpDir = resolve26(DATA_ROOT, "accounts", accountId, UPLOAD_TMP_DIR);
|
|
18995
19086
|
await mkdir4(tmpDir, { recursive: true });
|
|
18996
|
-
const tmpPath =
|
|
19087
|
+
const tmpPath = resolve26(tmpDir, `${uploadId}.part`);
|
|
18997
19088
|
const out = createWriteStream2(tmpPath);
|
|
18998
19089
|
const state2 = {
|
|
18999
19090
|
accountId,
|
|
@@ -19099,7 +19190,7 @@ async function evictStaleChunkUploads(ttlMs) {
|
|
|
19099
19190
|
return evicted;
|
|
19100
19191
|
}
|
|
19101
19192
|
async function sweepStaleUploadTemps() {
|
|
19102
|
-
const accountsRoot =
|
|
19193
|
+
const accountsRoot = resolve26(DATA_ROOT, "accounts");
|
|
19103
19194
|
let accounts;
|
|
19104
19195
|
try {
|
|
19105
19196
|
accounts = await readdir4(accountsRoot, { withFileTypes: true });
|
|
@@ -19109,7 +19200,7 @@ async function sweepStaleUploadTemps() {
|
|
|
19109
19200
|
let removed = 0;
|
|
19110
19201
|
for (const acc of accounts) {
|
|
19111
19202
|
if (!acc.isDirectory()) continue;
|
|
19112
|
-
const tmpDir =
|
|
19203
|
+
const tmpDir = resolve26(accountsRoot, acc.name, UPLOAD_TMP_DIR);
|
|
19113
19204
|
let entries;
|
|
19114
19205
|
try {
|
|
19115
19206
|
entries = await readdir4(tmpDir);
|
|
@@ -19118,7 +19209,7 @@ async function sweepStaleUploadTemps() {
|
|
|
19118
19209
|
}
|
|
19119
19210
|
for (const name of entries) {
|
|
19120
19211
|
try {
|
|
19121
|
-
await unlink3(
|
|
19212
|
+
await unlink3(resolve26(tmpDir, name));
|
|
19122
19213
|
removed++;
|
|
19123
19214
|
} catch {
|
|
19124
19215
|
}
|
|
@@ -19127,7 +19218,7 @@ async function sweepStaleUploadTemps() {
|
|
|
19127
19218
|
if (removed > 0) console.error(`[data-upload] op=sweep removed=${removed}`);
|
|
19128
19219
|
return removed;
|
|
19129
19220
|
}
|
|
19130
|
-
|
|
19221
|
+
app23.delete("/", requireAdminSession, async (c) => {
|
|
19131
19222
|
const cacheKey = c.var.cacheKey;
|
|
19132
19223
|
const accountId = getAccountIdForSession(cacheKey);
|
|
19133
19224
|
if (!accountId) {
|
|
@@ -19148,7 +19239,7 @@ app22.delete("/", requireAdminSession, async (c) => {
|
|
|
19148
19239
|
console.error(`[data] account-scope-blocked endpoint="DELETE /api/admin/files" path="${relPath}" account=${accountId.slice(0, 8)}\u2026`);
|
|
19149
19240
|
return c.json({ error: "Not found" }, 404);
|
|
19150
19241
|
}
|
|
19151
|
-
const base =
|
|
19242
|
+
const base = basename11(absolute);
|
|
19152
19243
|
const protection = isProtectedFromDeletion(relPath);
|
|
19153
19244
|
if (protection.protected) {
|
|
19154
19245
|
console.error(`[data] file-delete blocked path="${relPath}" reason="protected" rule="${protection.rule}"`);
|
|
@@ -19164,9 +19255,9 @@ app22.delete("/", requireAdminSession, async (c) => {
|
|
|
19164
19255
|
}
|
|
19165
19256
|
const dot = base.lastIndexOf(".");
|
|
19166
19257
|
const stem = dot === -1 ? base : base.slice(0, dot);
|
|
19167
|
-
const containerDir =
|
|
19258
|
+
const containerDir = dirname13(absolute);
|
|
19168
19259
|
const sidecarPath = UUID_RE4.test(stem) && base !== `${stem}.meta.json` ? join35(containerDir, `${stem}.meta.json`) : null;
|
|
19169
|
-
const isAttachmentContainer = UUID_RE4.test(stem) &&
|
|
19260
|
+
const isAttachmentContainer = UUID_RE4.test(stem) && basename11(containerDir) === stem;
|
|
19170
19261
|
await unlink3(absolute);
|
|
19171
19262
|
if (sidecarPath) {
|
|
19172
19263
|
try {
|
|
@@ -19211,7 +19302,7 @@ app22.delete("/", requireAdminSession, async (c) => {
|
|
|
19211
19302
|
return c.json({ error: message }, 500);
|
|
19212
19303
|
}
|
|
19213
19304
|
});
|
|
19214
|
-
|
|
19305
|
+
app23.post("/folder", requireAdminSession, async (c) => {
|
|
19215
19306
|
const cacheKey = c.var.cacheKey;
|
|
19216
19307
|
const accountId = getAccountIdForSession(cacheKey);
|
|
19217
19308
|
if (!accountId) {
|
|
@@ -19229,7 +19320,7 @@ app22.post("/folder", requireAdminSession, async (c) => {
|
|
|
19229
19320
|
if (!isValidEntryName(name)) return c.json({ error: "Invalid folder name" }, 400);
|
|
19230
19321
|
const parent = resolveOwnAccountWrite(rawPath, accountId, "POST /api/admin/files/folder");
|
|
19231
19322
|
if (!parent.ok) return c.json({ error: parent.error }, parent.status);
|
|
19232
|
-
const newAbs =
|
|
19323
|
+
const newAbs = resolve26(parent.absolute, name);
|
|
19233
19324
|
const newRel = `${parent.relative}/${name}`;
|
|
19234
19325
|
try {
|
|
19235
19326
|
const info = await stat6(parent.absolute);
|
|
@@ -19246,7 +19337,7 @@ app22.post("/folder", requireAdminSession, async (c) => {
|
|
|
19246
19337
|
console.error(`[data] folder-create path="${newRel}"`);
|
|
19247
19338
|
return c.json({ path: newRel });
|
|
19248
19339
|
});
|
|
19249
|
-
|
|
19340
|
+
app23.post("/rename", requireAdminSession, async (c) => {
|
|
19250
19341
|
const cacheKey = c.var.cacheKey;
|
|
19251
19342
|
const accountId = getAccountIdForSession(cacheKey);
|
|
19252
19343
|
if (!accountId) {
|
|
@@ -19268,8 +19359,8 @@ app22.post("/rename", requireAdminSession, async (c) => {
|
|
|
19268
19359
|
console.error(`[data] file-rename blocked path="${src.relative}" reason="protected"`);
|
|
19269
19360
|
return c.json({ error: "Protected entry \u2014 refusing to rename" }, 403);
|
|
19270
19361
|
}
|
|
19271
|
-
const destAbs =
|
|
19272
|
-
const newRel = `${
|
|
19362
|
+
const destAbs = resolve26(dirname13(src.absolute), newName);
|
|
19363
|
+
const newRel = `${dirname13(src.relative)}/${newName}`.replace(/^\.\//, "");
|
|
19273
19364
|
if (isProtectedFromRename(newRel)) {
|
|
19274
19365
|
console.error(`[data] file-rename blocked path="${newRel}" reason="protected-target"`);
|
|
19275
19366
|
return c.json({ error: "That name is reserved" }, 403);
|
|
@@ -19296,7 +19387,7 @@ app22.post("/rename", requireAdminSession, async (c) => {
|
|
|
19296
19387
|
});
|
|
19297
19388
|
return c.json({ path: newRel });
|
|
19298
19389
|
});
|
|
19299
|
-
var files_default =
|
|
19390
|
+
var files_default = app23;
|
|
19300
19391
|
|
|
19301
19392
|
// ../lib/graph-search/src/index.ts
|
|
19302
19393
|
var import_dist = __toESM(require_dist2());
|
|
@@ -20054,8 +20145,8 @@ var DEFAULT_LIMIT = 20;
|
|
|
20054
20145
|
var MAX_LIMIT = 2e3;
|
|
20055
20146
|
var MESSAGE_FAMILY_LABELS = ["Message", "UserMessage", "AssistantMessage"];
|
|
20056
20147
|
var CONVERSATION_PARENT_LABELS = /* @__PURE__ */ new Set(["AdminConversation", "PublicConversation"]);
|
|
20057
|
-
var
|
|
20058
|
-
|
|
20148
|
+
var app24 = new Hono();
|
|
20149
|
+
app24.get("/", requireAdminSession, async (c) => {
|
|
20059
20150
|
const cacheKey = c.var.cacheKey;
|
|
20060
20151
|
const q2 = (c.req.query("q") ?? "").trim();
|
|
20061
20152
|
const rawLimit = c.req.query("limit");
|
|
@@ -20086,7 +20177,7 @@ app23.get("/", requireAdminSession, async (c) => {
|
|
|
20086
20177
|
const wantsBodyFulltext = !allLabels && labels.some((l) => CONVERSATION_PARENT_LABELS.has(l));
|
|
20087
20178
|
const forwardedLabels = allLabels ? void 0 : wantsBodyFulltext ? Array.from(/* @__PURE__ */ new Set([...labels, ...MESSAGE_FAMILY_LABELS])) : labels;
|
|
20088
20179
|
if (labels.includes("FileArtifact")) {
|
|
20089
|
-
|
|
20180
|
+
void reconcileFileIndexDebounced(accountId);
|
|
20090
20181
|
}
|
|
20091
20182
|
const started = Date.now();
|
|
20092
20183
|
const session = getSession();
|
|
@@ -20191,7 +20282,7 @@ app23.get("/", requireAdminSession, async (c) => {
|
|
|
20191
20282
|
await session.close();
|
|
20192
20283
|
}
|
|
20193
20284
|
});
|
|
20194
|
-
var graph_search_default =
|
|
20285
|
+
var graph_search_default = app24;
|
|
20195
20286
|
|
|
20196
20287
|
// server/routes/admin/graph-subgraph.ts
|
|
20197
20288
|
import neo4j2 from "neo4j-driver";
|
|
@@ -20285,7 +20376,7 @@ function isHiddenByDefault(label) {
|
|
|
20285
20376
|
// server/lib/top-level-labels.ts
|
|
20286
20377
|
var import_dist4 = __toESM(require_dist3(), 1);
|
|
20287
20378
|
import { readdirSync as readdirSync23, readFileSync as readFileSync35 } from "fs";
|
|
20288
|
-
import { join as join36, resolve as
|
|
20379
|
+
import { join as join36, resolve as resolve27 } from "path";
|
|
20289
20380
|
var STATIC_TOP_LEVEL_LABELS = Object.freeze(
|
|
20290
20381
|
/* @__PURE__ */ new Set([
|
|
20291
20382
|
// Base-schema infra (schema-base.md has no top-level section).
|
|
@@ -20369,8 +20460,8 @@ function parseTopLevelLabels(content) {
|
|
|
20369
20460
|
const line = lines[i];
|
|
20370
20461
|
if (line.startsWith("## ")) return [];
|
|
20371
20462
|
if (!line.includes("|")) continue;
|
|
20372
|
-
const
|
|
20373
|
-
if (!/^\s*\|?[\s:|-]+\|?\s*$/.test(
|
|
20463
|
+
const sep12 = lines[i + 1];
|
|
20464
|
+
if (!/^\s*\|?[\s:|-]+\|?\s*$/.test(sep12) || !sep12.includes("-")) continue;
|
|
20374
20465
|
const headers = splitPipeRow(line).map((h) => stripBackticks(h).toLowerCase());
|
|
20375
20466
|
const labelCol = headers.findIndex((h) => h === "neo4j label");
|
|
20376
20467
|
if (labelCol === -1) return [];
|
|
@@ -20391,7 +20482,7 @@ function resolveReferencesDir() {
|
|
|
20391
20482
|
if (process.env.MAXY_PLATFORM_ROOT) {
|
|
20392
20483
|
return join36(process.env.MAXY_PLATFORM_ROOT, "plugins", "memory", "references");
|
|
20393
20484
|
}
|
|
20394
|
-
return
|
|
20485
|
+
return resolve27(import.meta.dirname, "../../../plugins/memory/references");
|
|
20395
20486
|
}
|
|
20396
20487
|
function parseTableTopLevelLabels(referencesDir) {
|
|
20397
20488
|
const labels = /* @__PURE__ */ new Set();
|
|
@@ -20444,8 +20535,8 @@ var STRIPPED_PROPERTIES = /* @__PURE__ */ new Set([
|
|
|
20444
20535
|
"otpCode",
|
|
20445
20536
|
"cacheKey"
|
|
20446
20537
|
]);
|
|
20447
|
-
var
|
|
20448
|
-
|
|
20538
|
+
var app25 = new Hono();
|
|
20539
|
+
app25.get("/", requireAdminSession, async (c) => {
|
|
20449
20540
|
const cacheKey = c.var.cacheKey;
|
|
20450
20541
|
const accountId = getAccountIdForSession(cacheKey);
|
|
20451
20542
|
if (!accountId) {
|
|
@@ -21116,12 +21207,12 @@ function pruneNode(node, warnedClasses, conversationWarnings) {
|
|
|
21116
21207
|
}
|
|
21117
21208
|
return trashed ? { id: node.id, labels, properties, trashed: true } : { id: node.id, labels, properties };
|
|
21118
21209
|
}
|
|
21119
|
-
var graph_subgraph_default =
|
|
21210
|
+
var graph_subgraph_default = app25;
|
|
21120
21211
|
|
|
21121
21212
|
// server/routes/admin/graph-delete.ts
|
|
21122
21213
|
var ALLOWED_BY = ["graph-page", "graph-drag-trash", "graph-side-panel-trash"];
|
|
21123
|
-
var
|
|
21124
|
-
|
|
21214
|
+
var app26 = new Hono();
|
|
21215
|
+
app26.post("/", requireAdminSession, async (c) => {
|
|
21125
21216
|
const cacheKey = c.var.cacheKey;
|
|
21126
21217
|
const accountId = getAccountIdForSession(cacheKey);
|
|
21127
21218
|
if (!accountId) {
|
|
@@ -21283,11 +21374,11 @@ app25.post("/", requireAdminSession, async (c) => {
|
|
|
21283
21374
|
}
|
|
21284
21375
|
}
|
|
21285
21376
|
});
|
|
21286
|
-
var graph_delete_default =
|
|
21377
|
+
var graph_delete_default = app26;
|
|
21287
21378
|
|
|
21288
21379
|
// server/routes/admin/graph-restore.ts
|
|
21289
|
-
var
|
|
21290
|
-
|
|
21380
|
+
var app27 = new Hono();
|
|
21381
|
+
app27.post("/", requireAdminSession, async (c) => {
|
|
21291
21382
|
const cacheKey = c.var.cacheKey;
|
|
21292
21383
|
const accountId = getAccountIdForSession(cacheKey);
|
|
21293
21384
|
if (!accountId) {
|
|
@@ -21351,11 +21442,11 @@ app26.post("/", requireAdminSession, async (c) => {
|
|
|
21351
21442
|
}
|
|
21352
21443
|
}
|
|
21353
21444
|
});
|
|
21354
|
-
var graph_restore_default =
|
|
21445
|
+
var graph_restore_default = app27;
|
|
21355
21446
|
|
|
21356
21447
|
// server/routes/admin/graph-labels-in-graph.ts
|
|
21357
|
-
var
|
|
21358
|
-
|
|
21448
|
+
var app28 = new Hono();
|
|
21449
|
+
app28.get("/", requireAdminSession, async (c) => {
|
|
21359
21450
|
const cacheKey = c.var.cacheKey;
|
|
21360
21451
|
const accountId = getAccountIdForSession(cacheKey);
|
|
21361
21452
|
if (!accountId) {
|
|
@@ -21421,11 +21512,11 @@ var LABELS_IN_GRAPH_CYPHER = `
|
|
|
21421
21512
|
sum(halfEdges) AS relDegree
|
|
21422
21513
|
RETURN label, nodeCount, relDegree
|
|
21423
21514
|
`;
|
|
21424
|
-
var graph_labels_in_graph_default =
|
|
21515
|
+
var graph_labels_in_graph_default = app28;
|
|
21425
21516
|
|
|
21426
21517
|
// server/routes/admin/graph-default-view.ts
|
|
21427
|
-
var
|
|
21428
|
-
|
|
21518
|
+
var app29 = new Hono();
|
|
21519
|
+
app29.get("/", requireAdminSession, async (c) => {
|
|
21429
21520
|
const cacheKey = c.var.cacheKey;
|
|
21430
21521
|
const accountId = getAccountIdForSession(cacheKey);
|
|
21431
21522
|
const userId = getUserIdForSession(cacheKey);
|
|
@@ -21463,7 +21554,7 @@ app28.get("/", requireAdminSession, async (c) => {
|
|
|
21463
21554
|
}
|
|
21464
21555
|
}
|
|
21465
21556
|
});
|
|
21466
|
-
|
|
21557
|
+
app29.put("/", requireAdminSession, async (c) => {
|
|
21467
21558
|
const cacheKey = c.var.cacheKey;
|
|
21468
21559
|
const accountId = getAccountIdForSession(cacheKey);
|
|
21469
21560
|
const userId = getUserIdForSession(cacheKey);
|
|
@@ -21552,20 +21643,20 @@ var WRITE_CYPHER = `
|
|
|
21552
21643
|
p.updatedAt = $updatedAt
|
|
21553
21644
|
RETURN p.labels AS labels
|
|
21554
21645
|
`;
|
|
21555
|
-
var graph_default_view_default =
|
|
21646
|
+
var graph_default_view_default = app29;
|
|
21556
21647
|
|
|
21557
21648
|
// server/routes/admin/sidebar-artefacts.ts
|
|
21558
21649
|
import { readdir as readdir5, stat as stat7 } from "fs/promises";
|
|
21559
|
-
import { resolve as
|
|
21560
|
-
import { existsSync as
|
|
21650
|
+
import { resolve as resolve28, relative as relative6, isAbsolute as isAbsolute2, sep as sep9, basename as basename12 } from "path";
|
|
21651
|
+
import { existsSync as existsSync35 } from "fs";
|
|
21561
21652
|
var LIMIT = 50;
|
|
21562
21653
|
var ADMIN_AGENT_FILES = ["IDENTITY.md", "SOUL.md", "KNOWLEDGE.md"];
|
|
21563
21654
|
function toDataRootRelPath(absPath) {
|
|
21564
|
-
if (absPath !== DATA_ROOT && !absPath.startsWith(DATA_ROOT +
|
|
21655
|
+
if (absPath !== DATA_ROOT && !absPath.startsWith(DATA_ROOT + sep9)) return null;
|
|
21565
21656
|
return relative6(DATA_ROOT, absPath);
|
|
21566
21657
|
}
|
|
21567
|
-
var
|
|
21568
|
-
|
|
21658
|
+
var app30 = new Hono();
|
|
21659
|
+
app30.get("/", requireAdminSession, async (c) => {
|
|
21569
21660
|
const cacheKey = c.var.cacheKey;
|
|
21570
21661
|
const accountId = getAccountIdForSession(cacheKey);
|
|
21571
21662
|
if (!accountId) {
|
|
@@ -21576,7 +21667,7 @@ app29.get("/", requireAdminSession, async (c) => {
|
|
|
21576
21667
|
if (accountFiles === null) {
|
|
21577
21668
|
return c.json({ error: "Failed to load artefacts" }, 500);
|
|
21578
21669
|
}
|
|
21579
|
-
const accountDir =
|
|
21670
|
+
const accountDir = resolve28(ACCOUNTS_DIR, accountId);
|
|
21580
21671
|
const agents = await fetchAgentTemplateRows(accountDir);
|
|
21581
21672
|
const artefacts = [...accountFiles, ...agents].sort(
|
|
21582
21673
|
(a, b) => (b.updatedAt ?? "").localeCompare(a.updatedAt ?? "")
|
|
@@ -21609,7 +21700,7 @@ async function fetchAccountFileArtefacts(accountId) {
|
|
|
21609
21700
|
const modifiedAt = r.get("modifiedAt") ?? "";
|
|
21610
21701
|
return {
|
|
21611
21702
|
id: `account-file:${relativePath}`,
|
|
21612
|
-
name: displayName ??
|
|
21703
|
+
name: displayName ?? basename12(relativePath),
|
|
21613
21704
|
kind: "account-file",
|
|
21614
21705
|
updatedAt: modifiedAt,
|
|
21615
21706
|
mimeType,
|
|
@@ -21628,8 +21719,8 @@ async function fetchAccountFileArtefacts(accountId) {
|
|
|
21628
21719
|
async function fetchAgentTemplateRows(accountDir) {
|
|
21629
21720
|
const rows = [];
|
|
21630
21721
|
for (const filename of ADMIN_AGENT_FILES) {
|
|
21631
|
-
const overridePath =
|
|
21632
|
-
const bundledPath =
|
|
21722
|
+
const overridePath = resolve28(accountDir, "agents", "admin", filename);
|
|
21723
|
+
const bundledPath = resolve28(PLATFORM_ROOT, "templates", "agents", "admin", filename);
|
|
21633
21724
|
const labelStem = filename.replace(/\.md$/, "");
|
|
21634
21725
|
const row = await readAgentTemplateRow({
|
|
21635
21726
|
id: `agent-template:admin:${filename}`,
|
|
@@ -21642,12 +21733,12 @@ async function fetchAgentTemplateRows(accountDir) {
|
|
|
21642
21733
|
});
|
|
21643
21734
|
if (row) rows.push(row);
|
|
21644
21735
|
}
|
|
21645
|
-
const overrideDir =
|
|
21646
|
-
const bundledDir =
|
|
21736
|
+
const overrideDir = resolve28(accountDir, "specialists", "agents");
|
|
21737
|
+
const bundledDir = resolve28(PLATFORM_ROOT, "templates", "specialists", "agents");
|
|
21647
21738
|
const specialistNames = await unionSpecialistFilenames(overrideDir, bundledDir);
|
|
21648
21739
|
for (const filename of specialistNames) {
|
|
21649
|
-
const overridePath =
|
|
21650
|
-
const bundledPath =
|
|
21740
|
+
const overridePath = resolve28(overrideDir, filename);
|
|
21741
|
+
const bundledPath = resolve28(bundledDir, filename);
|
|
21651
21742
|
const row = await readAgentTemplateRow({
|
|
21652
21743
|
id: `agent-template:specialist:${filename}`,
|
|
21653
21744
|
displayName: filename.replace(/\.md$/, ""),
|
|
@@ -21664,7 +21755,7 @@ async function fetchAgentTemplateRows(accountDir) {
|
|
|
21664
21755
|
async function unionSpecialistFilenames(overrideDir, bundledDir) {
|
|
21665
21756
|
const names = /* @__PURE__ */ new Set();
|
|
21666
21757
|
for (const dir of [overrideDir, bundledDir]) {
|
|
21667
|
-
if (!
|
|
21758
|
+
if (!existsSync35(dir)) continue;
|
|
21668
21759
|
try {
|
|
21669
21760
|
const entries = await readdir5(dir);
|
|
21670
21761
|
for (const entry of entries) {
|
|
@@ -21679,7 +21770,7 @@ async function unionSpecialistFilenames(overrideDir, bundledDir) {
|
|
|
21679
21770
|
}
|
|
21680
21771
|
async function readAgentTemplateRow(inp) {
|
|
21681
21772
|
let chosenPath = null;
|
|
21682
|
-
if (
|
|
21773
|
+
if (existsSync35(inp.overridePath)) {
|
|
21683
21774
|
try {
|
|
21684
21775
|
validateFilePathInAccount(inp.overridePath, inp.overrideRoot);
|
|
21685
21776
|
chosenPath = inp.overridePath;
|
|
@@ -21690,7 +21781,7 @@ async function readAgentTemplateRow(inp) {
|
|
|
21690
21781
|
);
|
|
21691
21782
|
return null;
|
|
21692
21783
|
}
|
|
21693
|
-
} else if (
|
|
21784
|
+
} else if (existsSync35(inp.bundledPath)) {
|
|
21694
21785
|
if (!isWithin(inp.bundledPath, inp.bundledRoot)) {
|
|
21695
21786
|
console.error(
|
|
21696
21787
|
`[admin/sidebar-artefacts] agent-template-read-failed agent=${inp.displayName} kind=${inp.logName} error="bundled path outside PLATFORM_ROOT"`
|
|
@@ -21729,7 +21820,7 @@ function isWithin(target, root) {
|
|
|
21729
21820
|
const rel = relative6(root, target);
|
|
21730
21821
|
return !rel.startsWith("..") && !isAbsolute2(rel);
|
|
21731
21822
|
}
|
|
21732
|
-
var sidebar_artefacts_default =
|
|
21823
|
+
var sidebar_artefacts_default = app30;
|
|
21733
21824
|
|
|
21734
21825
|
// server/channel-session-override.ts
|
|
21735
21826
|
import { readFileSync as readFileSync36, writeFileSync as writeFileSync13, renameSync as renameSync9 } from "fs";
|
|
@@ -21802,8 +21893,8 @@ function clearForwardPointers(sessionId) {
|
|
|
21802
21893
|
}
|
|
21803
21894
|
|
|
21804
21895
|
// server/routes/admin/session-delete.ts
|
|
21805
|
-
var
|
|
21806
|
-
|
|
21896
|
+
var app31 = new Hono();
|
|
21897
|
+
app31.post("/", requireAdminSession, async (c) => {
|
|
21807
21898
|
let body;
|
|
21808
21899
|
try {
|
|
21809
21900
|
body = await c.req.json();
|
|
@@ -21842,11 +21933,11 @@ app30.post("/", requireAdminSession, async (c) => {
|
|
|
21842
21933
|
console.error(`[session-delete] sessionId=${sessionId} delete-status=${del.status}`);
|
|
21843
21934
|
return c.json({ error: `manager-status-${del.status}` }, 502);
|
|
21844
21935
|
});
|
|
21845
|
-
var session_delete_default =
|
|
21936
|
+
var session_delete_default = app31;
|
|
21846
21937
|
|
|
21847
21938
|
// server/routes/admin/session-stop.ts
|
|
21848
|
-
var
|
|
21849
|
-
|
|
21939
|
+
var app32 = new Hono();
|
|
21940
|
+
app32.post("/", requireAdminSession, async (c) => {
|
|
21850
21941
|
let body;
|
|
21851
21942
|
try {
|
|
21852
21943
|
body = await c.req.json();
|
|
@@ -21871,11 +21962,11 @@ app31.post("/", requireAdminSession, async (c) => {
|
|
|
21871
21962
|
console.error(`[session-stop] sessionId=${sessionId} manager-status=${res.status}`);
|
|
21872
21963
|
return c.json({ error: `manager-status-${res.status}` }, 502);
|
|
21873
21964
|
});
|
|
21874
|
-
var session_stop_default =
|
|
21965
|
+
var session_stop_default = app32;
|
|
21875
21966
|
|
|
21876
21967
|
// server/routes/admin/session-archive.ts
|
|
21877
|
-
var
|
|
21878
|
-
|
|
21968
|
+
var app33 = new Hono();
|
|
21969
|
+
app33.post("/", requireAdminSession, async (c) => {
|
|
21879
21970
|
let body;
|
|
21880
21971
|
try {
|
|
21881
21972
|
body = await c.req.json();
|
|
@@ -21924,11 +22015,11 @@ app32.post("/", requireAdminSession, async (c) => {
|
|
|
21924
22015
|
console.error(`[session-archive] sessionId=${sessionId.slice(0, 8)} manager-status=${res.status}`);
|
|
21925
22016
|
return c.json({ error: `manager-status-${res.status}` }, 502);
|
|
21926
22017
|
});
|
|
21927
|
-
var session_archive_default =
|
|
22018
|
+
var session_archive_default = app33;
|
|
21928
22019
|
|
|
21929
22020
|
// server/routes/admin/session-rename.ts
|
|
21930
|
-
var
|
|
21931
|
-
|
|
22021
|
+
var app34 = new Hono();
|
|
22022
|
+
app34.post("/", requireAdminSession, async (c) => {
|
|
21932
22023
|
let body;
|
|
21933
22024
|
try {
|
|
21934
22025
|
body = await c.req.json();
|
|
@@ -21967,11 +22058,11 @@ app33.post("/", requireAdminSession, async (c) => {
|
|
|
21967
22058
|
console.error(`[session-rename] sessionId=${sessionId.slice(0, 8)} manager-status=${res.status}`);
|
|
21968
22059
|
return c.json({ error: `manager-status-${res.status}` }, 502);
|
|
21969
22060
|
});
|
|
21970
|
-
var session_rename_default =
|
|
22061
|
+
var session_rename_default = app34;
|
|
21971
22062
|
|
|
21972
22063
|
// server/routes/admin/session-usage.ts
|
|
21973
|
-
var
|
|
21974
|
-
|
|
22064
|
+
var app35 = new Hono();
|
|
22065
|
+
app35.get("/", requireAdminSession, async (c) => {
|
|
21975
22066
|
const sessionId = c.req.query("sessionId") ?? "";
|
|
21976
22067
|
if (!SESSION_ID_RE2.test(sessionId)) {
|
|
21977
22068
|
return c.json({ error: "sessionId must be a v4 UUID" }, 400);
|
|
@@ -21997,7 +22088,7 @@ app34.get("/", requireAdminSession, async (c) => {
|
|
|
21997
22088
|
console.error(`[session-usage] sessionId=${sessionId.slice(0, 8)} manager-status=${res.status}`);
|
|
21998
22089
|
return c.json({ error: `manager-status-${res.status}` }, 502);
|
|
21999
22090
|
});
|
|
22000
|
-
var session_usage_default =
|
|
22091
|
+
var session_usage_default = app35;
|
|
22001
22092
|
|
|
22002
22093
|
// server/routes/admin/session-rc-spawn.ts
|
|
22003
22094
|
import { randomUUID as randomUUID11 } from "crypto";
|
|
@@ -22044,8 +22135,8 @@ function shapeWebchatResponse(sessionId, manager) {
|
|
|
22044
22135
|
const landed = redirected ? manager.sessionId : sessionId;
|
|
22045
22136
|
return { sessionId: landed, outcome, target: `/chat?session=${landed}` };
|
|
22046
22137
|
}
|
|
22047
|
-
var
|
|
22048
|
-
|
|
22138
|
+
var app36 = new Hono();
|
|
22139
|
+
app36.post("/", requireAdminSession, async (c) => {
|
|
22049
22140
|
let body;
|
|
22050
22141
|
try {
|
|
22051
22142
|
body = await c.req.json();
|
|
@@ -22127,30 +22218,30 @@ app35.post("/", requireAdminSession, async (c) => {
|
|
|
22127
22218
|
}
|
|
22128
22219
|
return c.json(parsed ?? {});
|
|
22129
22220
|
});
|
|
22130
|
-
var session_rc_spawn_default =
|
|
22221
|
+
var session_rc_spawn_default = app36;
|
|
22131
22222
|
|
|
22132
22223
|
// server/routes/admin/session-reseat.ts
|
|
22133
22224
|
import { randomUUID as randomUUID12 } from "crypto";
|
|
22134
22225
|
|
|
22135
22226
|
// server/wa-descriptor.ts
|
|
22136
|
-
import { resolve as
|
|
22227
|
+
import { resolve as resolve29, join as join38 } from "path";
|
|
22137
22228
|
function waGatewayUrl() {
|
|
22138
22229
|
return `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`;
|
|
22139
22230
|
}
|
|
22140
22231
|
function waServerPath() {
|
|
22141
|
-
return process.env.MAXY_WA_CHANNEL_SERVER_PATH ??
|
|
22232
|
+
return process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve29(process.env.MAXY_PLATFORM_ROOT ?? join38(__dirname, ".."), "services/whatsapp-channel/dist/server.js");
|
|
22142
22233
|
}
|
|
22143
22234
|
function waChannelDescriptor(senderId) {
|
|
22144
22235
|
return { senderId, gatewayUrl: waGatewayUrl(), serverPath: waServerPath() };
|
|
22145
22236
|
}
|
|
22146
22237
|
|
|
22147
22238
|
// server/telegram-descriptor.ts
|
|
22148
|
-
import { resolve as
|
|
22239
|
+
import { resolve as resolve30, join as join39 } from "path";
|
|
22149
22240
|
function telegramGatewayUrl() {
|
|
22150
22241
|
return `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`;
|
|
22151
22242
|
}
|
|
22152
22243
|
function telegramServerPath() {
|
|
22153
|
-
return process.env.MAXY_TELEGRAM_CHANNEL_SERVER_PATH ??
|
|
22244
|
+
return process.env.MAXY_TELEGRAM_CHANNEL_SERVER_PATH ?? resolve30(process.env.MAXY_PLATFORM_ROOT ?? join39(__dirname, ".."), "services/telegram-channel/dist/server.js");
|
|
22154
22245
|
}
|
|
22155
22246
|
function telegramChannelDescriptor(senderId) {
|
|
22156
22247
|
return { senderId, gatewayUrl: telegramGatewayUrl(), serverPath: telegramServerPath() };
|
|
@@ -22193,9 +22284,9 @@ function resolveReseatPlan(body, mintId = randomUUID12, adminUserId, authenticat
|
|
|
22193
22284
|
if (authenticatedName) payload.authenticatedName = authenticatedName;
|
|
22194
22285
|
return { sessionId, payload };
|
|
22195
22286
|
}
|
|
22196
|
-
var
|
|
22287
|
+
var app37 = new Hono();
|
|
22197
22288
|
var reseatsInFlight = /* @__PURE__ */ new Set();
|
|
22198
|
-
|
|
22289
|
+
app37.post("/", requireAdminSession, async (c) => {
|
|
22199
22290
|
let body;
|
|
22200
22291
|
try {
|
|
22201
22292
|
body = await c.req.json();
|
|
@@ -22310,10 +22401,10 @@ app36.post("/", requireAdminSession, async (c) => {
|
|
|
22310
22401
|
reseatsInFlight.delete(fromSessionId);
|
|
22311
22402
|
}
|
|
22312
22403
|
});
|
|
22313
|
-
var session_reseat_default =
|
|
22404
|
+
var session_reseat_default = app37;
|
|
22314
22405
|
|
|
22315
22406
|
// server/routes/admin/system-stats.ts
|
|
22316
|
-
import { readFile as
|
|
22407
|
+
import { readFile as readFile8 } from "fs/promises";
|
|
22317
22408
|
import { cpus, loadavg, totalmem, freemem } from "os";
|
|
22318
22409
|
function parseCpuStat(blob) {
|
|
22319
22410
|
const line = blob.split("\n", 1)[0] ?? "";
|
|
@@ -22357,11 +22448,11 @@ function parseMeminfo(blob) {
|
|
|
22357
22448
|
}
|
|
22358
22449
|
var SAMPLE_DELAY_MS = 100;
|
|
22359
22450
|
async function sampleLinux() {
|
|
22360
|
-
const a = parseCpuStat(await
|
|
22451
|
+
const a = parseCpuStat(await readFile8("/proc/stat", "utf-8"));
|
|
22361
22452
|
await new Promise((r) => setTimeout(r, SAMPLE_DELAY_MS));
|
|
22362
|
-
const b = parseCpuStat(await
|
|
22363
|
-
const meminfo = parseMeminfo(await
|
|
22364
|
-
const loadavgRaw = (await
|
|
22453
|
+
const b = parseCpuStat(await readFile8("/proc/stat", "utf-8"));
|
|
22454
|
+
const meminfo = parseMeminfo(await readFile8("/proc/meminfo", "utf-8"));
|
|
22455
|
+
const loadavgRaw = (await readFile8("/proc/loadavg", "utf-8")).trim();
|
|
22365
22456
|
const [l1, l5, l15] = loadavgRaw.split(/\s+/, 3).map(Number);
|
|
22366
22457
|
if (![l1, l5, l15].every(Number.isFinite)) {
|
|
22367
22458
|
throw new Error(`malformed /proc/loadavg: ${loadavgRaw}`);
|
|
@@ -22407,8 +22498,8 @@ async function sample() {
|
|
|
22407
22498
|
if (process.platform === "linux") return sampleLinux();
|
|
22408
22499
|
return sampleOsFallback();
|
|
22409
22500
|
}
|
|
22410
|
-
var
|
|
22411
|
-
|
|
22501
|
+
var app38 = new Hono();
|
|
22502
|
+
app38.get("/", async (c) => {
|
|
22412
22503
|
const started = Date.now();
|
|
22413
22504
|
if (!inflight) {
|
|
22414
22505
|
inflight = sample().finally(() => {
|
|
@@ -22431,26 +22522,26 @@ app37.get("/", async (c) => {
|
|
|
22431
22522
|
return c.json({ degraded: true, reason, sampledAtMs: Date.now() });
|
|
22432
22523
|
}
|
|
22433
22524
|
});
|
|
22434
|
-
var system_stats_default =
|
|
22525
|
+
var system_stats_default = app38;
|
|
22435
22526
|
|
|
22436
22527
|
// server/routes/admin/health.ts
|
|
22437
|
-
import { existsSync as
|
|
22438
|
-
import { resolve as
|
|
22439
|
-
var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ??
|
|
22528
|
+
import { existsSync as existsSync36, readFileSync as readFileSync37 } from "fs";
|
|
22529
|
+
import { resolve as resolve31, join as join40 } from "path";
|
|
22530
|
+
var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve31(process.cwd(), "..");
|
|
22440
22531
|
var brandHostname = "maxy";
|
|
22441
22532
|
var brandJsonPath = join40(PLATFORM_ROOT6, "config", "brand.json");
|
|
22442
|
-
if (
|
|
22533
|
+
if (existsSync36(brandJsonPath)) {
|
|
22443
22534
|
try {
|
|
22444
22535
|
const brand = JSON.parse(readFileSync37(brandJsonPath, "utf-8"));
|
|
22445
22536
|
if (brand.hostname) brandHostname = brand.hostname;
|
|
22446
22537
|
} catch {
|
|
22447
22538
|
}
|
|
22448
22539
|
}
|
|
22449
|
-
var VERSION_FILE =
|
|
22540
|
+
var VERSION_FILE = resolve31(PLATFORM_ROOT6, `config/.${brandHostname}-version`);
|
|
22450
22541
|
var PROCESS_STARTED_AT = (/* @__PURE__ */ new Date()).toISOString();
|
|
22451
22542
|
var PROBE_TIMEOUT_MS = 1e3;
|
|
22452
22543
|
function readVersion() {
|
|
22453
|
-
if (!
|
|
22544
|
+
if (!existsSync36(VERSION_FILE)) return "unknown";
|
|
22454
22545
|
return readFileSync37(VERSION_FILE, "utf-8").trim() || "unknown";
|
|
22455
22546
|
}
|
|
22456
22547
|
async function probeConversationDb() {
|
|
@@ -22476,8 +22567,8 @@ async function probeConversationDb() {
|
|
|
22476
22567
|
});
|
|
22477
22568
|
}
|
|
22478
22569
|
}
|
|
22479
|
-
var
|
|
22480
|
-
|
|
22570
|
+
var app39 = new Hono();
|
|
22571
|
+
app39.get("/", async (c) => {
|
|
22481
22572
|
const version = readVersion();
|
|
22482
22573
|
const probe = await probeConversationDb();
|
|
22483
22574
|
const uptimeMs = Date.now() - new Date(PROCESS_STARTED_AT).getTime();
|
|
@@ -22499,7 +22590,7 @@ app38.get("/", async (c) => {
|
|
|
22499
22590
|
uptimeMs
|
|
22500
22591
|
});
|
|
22501
22592
|
});
|
|
22502
|
-
var health_default2 =
|
|
22593
|
+
var health_default2 = app39;
|
|
22503
22594
|
|
|
22504
22595
|
// server/routes/admin/linkedin-ingest.ts
|
|
22505
22596
|
import { randomUUID as randomUUID13 } from "crypto";
|
|
@@ -22728,8 +22819,8 @@ function buildInitialMessage(env) {
|
|
|
22728
22819
|
}
|
|
22729
22820
|
return header;
|
|
22730
22821
|
}
|
|
22731
|
-
var
|
|
22732
|
-
|
|
22822
|
+
var app40 = new Hono();
|
|
22823
|
+
app40.post("/", requireAdminSession, async (c) => {
|
|
22733
22824
|
let body;
|
|
22734
22825
|
try {
|
|
22735
22826
|
body = await c.req.json();
|
|
@@ -22774,7 +22865,7 @@ app39.post("/", requireAdminSession, async (c) => {
|
|
|
22774
22865
|
);
|
|
22775
22866
|
return c.json({ ok: true, dispatchId: envelope.dispatchId, taskId: spawned.sessionId }, 202);
|
|
22776
22867
|
});
|
|
22777
|
-
var linkedin_ingest_default =
|
|
22868
|
+
var linkedin_ingest_default = app40;
|
|
22778
22869
|
|
|
22779
22870
|
// server/routes/admin/post-turn-context.ts
|
|
22780
22871
|
import neo4j3 from "neo4j-driver";
|
|
@@ -22816,8 +22907,8 @@ function pruneProperties(raw) {
|
|
|
22816
22907
|
}
|
|
22817
22908
|
return out;
|
|
22818
22909
|
}
|
|
22819
|
-
var
|
|
22820
|
-
|
|
22910
|
+
var app41 = new Hono();
|
|
22911
|
+
app41.get("/", async (c) => {
|
|
22821
22912
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
22822
22913
|
if (!isLoopbackAddr3(remoteAddr)) {
|
|
22823
22914
|
console.error(`${TAG34} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
@@ -22877,7 +22968,7 @@ app40.get("/", async (c) => {
|
|
|
22877
22968
|
await session.close();
|
|
22878
22969
|
}
|
|
22879
22970
|
});
|
|
22880
|
-
var post_turn_context_default =
|
|
22971
|
+
var post_turn_context_default = app41;
|
|
22881
22972
|
|
|
22882
22973
|
// app/lib/slice-writes.ts
|
|
22883
22974
|
import neo4j4 from "neo4j-driver";
|
|
@@ -22987,8 +23078,8 @@ var TAG35 = "[public-session-context]";
|
|
|
22987
23078
|
function isLoopbackAddr4(addr) {
|
|
22988
23079
|
return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
|
|
22989
23080
|
}
|
|
22990
|
-
var
|
|
22991
|
-
|
|
23081
|
+
var app42 = new Hono();
|
|
23082
|
+
app42.get("/", async (c) => {
|
|
22992
23083
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
22993
23084
|
if (!isLoopbackAddr4(remoteAddr)) {
|
|
22994
23085
|
console.error(`${TAG35} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
@@ -23028,7 +23119,7 @@ app41.get("/", async (c) => {
|
|
|
23028
23119
|
await session.close();
|
|
23029
23120
|
}
|
|
23030
23121
|
});
|
|
23031
|
-
var public_session_context_default =
|
|
23122
|
+
var public_session_context_default = app42;
|
|
23032
23123
|
|
|
23033
23124
|
// app/lib/webchat/gateway/instance.ts
|
|
23034
23125
|
var instance2 = null;
|
|
@@ -23044,8 +23135,8 @@ var TAG36 = "[public-session-exit-route]";
|
|
|
23044
23135
|
function isLoopbackAddr5(addr) {
|
|
23045
23136
|
return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
|
|
23046
23137
|
}
|
|
23047
|
-
var
|
|
23048
|
-
|
|
23138
|
+
var app43 = new Hono();
|
|
23139
|
+
app43.post("/", async (c) => {
|
|
23049
23140
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
23050
23141
|
if (!isLoopbackAddr5(remoteAddr)) {
|
|
23051
23142
|
console.error(`${TAG36} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
@@ -23077,15 +23168,15 @@ app42.post("/", async (c) => {
|
|
|
23077
23168
|
gateway.handlePublicSessionExit(sessionId);
|
|
23078
23169
|
return c.json({ ok: true });
|
|
23079
23170
|
});
|
|
23080
|
-
var public_session_exit_default =
|
|
23171
|
+
var public_session_exit_default = app43;
|
|
23081
23172
|
|
|
23082
23173
|
// server/routes/admin/access-session-evict.ts
|
|
23083
23174
|
var TAG37 = "[access-session-evict]";
|
|
23084
23175
|
function isLoopbackAddr6(addr) {
|
|
23085
23176
|
return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
|
|
23086
23177
|
}
|
|
23087
|
-
var
|
|
23088
|
-
|
|
23178
|
+
var app44 = new Hono();
|
|
23179
|
+
app44.post("/", async (c) => {
|
|
23089
23180
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
23090
23181
|
if (!isLoopbackAddr6(remoteAddr)) {
|
|
23091
23182
|
console.error(`${TAG37} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
@@ -23113,7 +23204,7 @@ app43.post("/", async (c) => {
|
|
|
23113
23204
|
console.log(`${TAG37} grantId=${grantId} dropped=${dropped}`);
|
|
23114
23205
|
return c.json({ ok: true, dropped });
|
|
23115
23206
|
});
|
|
23116
|
-
var access_session_evict_default =
|
|
23207
|
+
var access_session_evict_default = app44;
|
|
23117
23208
|
|
|
23118
23209
|
// server/routes/admin/enrol-person.ts
|
|
23119
23210
|
var TAG38 = "[enrol]";
|
|
@@ -23121,8 +23212,8 @@ function isLoopbackAddr7(addr) {
|
|
|
23121
23212
|
return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
|
|
23122
23213
|
}
|
|
23123
23214
|
var EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
23124
|
-
var
|
|
23125
|
-
|
|
23215
|
+
var app45 = new Hono();
|
|
23216
|
+
app45.post("/", async (c) => {
|
|
23126
23217
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
23127
23218
|
if (!isLoopbackAddr7(remoteAddr)) {
|
|
23128
23219
|
console.error(`${TAG38} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
@@ -23185,11 +23276,11 @@ app44.post("/", async (c) => {
|
|
|
23185
23276
|
);
|
|
23186
23277
|
return c.json({ personId, grant }, 200);
|
|
23187
23278
|
});
|
|
23188
|
-
var enrol_person_default =
|
|
23279
|
+
var enrol_person_default = app45;
|
|
23189
23280
|
|
|
23190
23281
|
// server/routes/admin/browser.ts
|
|
23191
|
-
var
|
|
23192
|
-
|
|
23282
|
+
var app46 = new Hono();
|
|
23283
|
+
app46.post("/launch", requireAdminSession, async (c) => {
|
|
23193
23284
|
try {
|
|
23194
23285
|
if (process.platform !== "linux") {
|
|
23195
23286
|
console.error("[admin/browser/launch] op=skipped platform=darwin reason=no-display-stack");
|
|
@@ -23224,10 +23315,10 @@ app45.post("/launch", requireAdminSession, async (c) => {
|
|
|
23224
23315
|
);
|
|
23225
23316
|
}
|
|
23226
23317
|
});
|
|
23227
|
-
var browser_default =
|
|
23318
|
+
var browser_default = app46;
|
|
23228
23319
|
|
|
23229
23320
|
// server/routes/admin/calendar.ts
|
|
23230
|
-
import { existsSync as
|
|
23321
|
+
import { existsSync as existsSync37 } from "fs";
|
|
23231
23322
|
import { join as join42 } from "path";
|
|
23232
23323
|
|
|
23233
23324
|
// server/lib/calendar-ics.ts
|
|
@@ -23370,7 +23461,7 @@ function readAvailabilityConfig(accountDir) {
|
|
|
23370
23461
|
}
|
|
23371
23462
|
|
|
23372
23463
|
// server/routes/admin/calendar.ts
|
|
23373
|
-
var
|
|
23464
|
+
var app47 = new Hono();
|
|
23374
23465
|
function normalizeAttendees(raw) {
|
|
23375
23466
|
if (!Array.isArray(raw)) return [];
|
|
23376
23467
|
return raw.map((a) => {
|
|
@@ -23401,7 +23492,7 @@ function mapMeeting(r) {
|
|
|
23401
23492
|
privateNote: r.get("privateNote")
|
|
23402
23493
|
};
|
|
23403
23494
|
}
|
|
23404
|
-
|
|
23495
|
+
app47.get("/meetings", requireAdminSession, async (c) => {
|
|
23405
23496
|
const cacheKey = c.var.cacheKey;
|
|
23406
23497
|
const accountId = getAccountIdForSession(cacheKey);
|
|
23407
23498
|
if (!accountId) {
|
|
@@ -23464,7 +23555,7 @@ function icsFilename(title) {
|
|
|
23464
23555
|
const slug = (title ?? "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 60);
|
|
23465
23556
|
return `${slug || "meeting"}.ics`;
|
|
23466
23557
|
}
|
|
23467
|
-
|
|
23558
|
+
app47.get("/meetings/:id/ics", requireAdminSession, async (c) => {
|
|
23468
23559
|
const cacheKey = c.var.cacheKey;
|
|
23469
23560
|
const accountId = getAccountIdForSession(cacheKey);
|
|
23470
23561
|
if (!accountId) {
|
|
@@ -23522,7 +23613,7 @@ app46.get("/meetings/:id/ics", requireAdminSession, async (c) => {
|
|
|
23522
23613
|
await session.close();
|
|
23523
23614
|
}
|
|
23524
23615
|
});
|
|
23525
|
-
|
|
23616
|
+
app47.patch("/meetings/:id", requireAdminSession, async (c) => {
|
|
23526
23617
|
const cacheKey = c.var.cacheKey;
|
|
23527
23618
|
const accountId = getAccountIdForSession(cacheKey);
|
|
23528
23619
|
if (!accountId) {
|
|
@@ -23566,7 +23657,7 @@ app46.patch("/meetings/:id", requireAdminSession, async (c) => {
|
|
|
23566
23657
|
await session.close();
|
|
23567
23658
|
}
|
|
23568
23659
|
});
|
|
23569
|
-
|
|
23660
|
+
app47.post("/meetings/:id/attendees", requireAdminSession, async (c) => {
|
|
23570
23661
|
const cacheKey = c.var.cacheKey;
|
|
23571
23662
|
const accountId = getAccountIdForSession(cacheKey);
|
|
23572
23663
|
if (!accountId) {
|
|
@@ -23616,7 +23707,7 @@ app46.post("/meetings/:id/attendees", requireAdminSession, async (c) => {
|
|
|
23616
23707
|
await session.close();
|
|
23617
23708
|
}
|
|
23618
23709
|
});
|
|
23619
|
-
|
|
23710
|
+
app47.delete("/meetings/:id/attendees", requireAdminSession, async (c) => {
|
|
23620
23711
|
const cacheKey = c.var.cacheKey;
|
|
23621
23712
|
const accountId = getAccountIdForSession(cacheKey);
|
|
23622
23713
|
if (!accountId) {
|
|
@@ -23662,7 +23753,7 @@ app46.delete("/meetings/:id/attendees", requireAdminSession, async (c) => {
|
|
|
23662
23753
|
await session.close();
|
|
23663
23754
|
}
|
|
23664
23755
|
});
|
|
23665
|
-
|
|
23756
|
+
app47.delete("/meetings/:id", requireAdminSession, async (c) => {
|
|
23666
23757
|
const cacheKey = c.var.cacheKey;
|
|
23667
23758
|
const accountId = getAccountIdForSession(cacheKey);
|
|
23668
23759
|
if (!accountId) {
|
|
@@ -23692,14 +23783,14 @@ app46.delete("/meetings/:id", requireAdminSession, async (c) => {
|
|
|
23692
23783
|
await session.close();
|
|
23693
23784
|
}
|
|
23694
23785
|
});
|
|
23695
|
-
|
|
23786
|
+
app47.get("/booking-link", requireAdminSession, (c) => {
|
|
23696
23787
|
try {
|
|
23697
23788
|
const account = resolveAccount();
|
|
23698
23789
|
if (!account) {
|
|
23699
23790
|
console.error('[calendar] op=booking-link-fail err="no account configured"');
|
|
23700
23791
|
return c.json({ bookingDomain: null });
|
|
23701
23792
|
}
|
|
23702
|
-
if (!
|
|
23793
|
+
if (!existsSync37(join42(account.accountDir, AVAILABILITY_FILENAME))) {
|
|
23703
23794
|
console.log("[calendar] op=booking-link bookingDomain=none source=availability-config");
|
|
23704
23795
|
return c.json({ bookingDomain: null });
|
|
23705
23796
|
}
|
|
@@ -23715,12 +23806,12 @@ app46.get("/booking-link", requireAdminSession, (c) => {
|
|
|
23715
23806
|
return c.json({ bookingDomain: null });
|
|
23716
23807
|
}
|
|
23717
23808
|
});
|
|
23718
|
-
var calendar_default =
|
|
23809
|
+
var calendar_default = app47;
|
|
23719
23810
|
|
|
23720
23811
|
// server/routes/admin/routines.ts
|
|
23721
23812
|
import cronParser from "cron-parser";
|
|
23722
23813
|
var { parseExpression } = cronParser;
|
|
23723
|
-
var
|
|
23814
|
+
var app48 = new Hono();
|
|
23724
23815
|
var AUTOMATION_WHERE = "(e.recurrence IS NOT NULL OR e.agentChannel IS NOT NULL OR e.actionPlugin IS NOT NULL)";
|
|
23725
23816
|
var ROUTINE_COLS = `e.eventId AS eventId, e.name AS name, e.eventStatus AS eventStatus,
|
|
23726
23817
|
e.recurrence AS recurrence, e.nextRun AS nextRun, e.lastTriggered AS lastTriggered,
|
|
@@ -23750,7 +23841,7 @@ function mapRoutine(r) {
|
|
|
23750
23841
|
lastDispatchAt: g("lastDispatchAt")
|
|
23751
23842
|
};
|
|
23752
23843
|
}
|
|
23753
|
-
|
|
23844
|
+
app48.get("/", requireAdminSession, async (c) => {
|
|
23754
23845
|
const accountId = getAccountIdForSession(c.var.cacheKey);
|
|
23755
23846
|
if (!accountId) {
|
|
23756
23847
|
console.error('[admin:routines] op=list auth-rejected reason="no account for session"');
|
|
@@ -23776,7 +23867,7 @@ app47.get("/", requireAdminSession, async (c) => {
|
|
|
23776
23867
|
await session.close();
|
|
23777
23868
|
}
|
|
23778
23869
|
});
|
|
23779
|
-
|
|
23870
|
+
app48.get("/:eventId", requireAdminSession, async (c) => {
|
|
23780
23871
|
const accountId = getAccountIdForSession(c.var.cacheKey);
|
|
23781
23872
|
if (!accountId) return c.json({ error: "Account not found for session" }, 401);
|
|
23782
23873
|
const eventId = c.req.param("eventId");
|
|
@@ -23800,7 +23891,7 @@ app47.get("/:eventId", requireAdminSession, async (c) => {
|
|
|
23800
23891
|
await session.close();
|
|
23801
23892
|
}
|
|
23802
23893
|
});
|
|
23803
|
-
|
|
23894
|
+
app48.patch("/:eventId", requireAdminSession, async (c) => {
|
|
23804
23895
|
const accountId = getAccountIdForSession(c.var.cacheKey);
|
|
23805
23896
|
if (!accountId) return c.json({ error: "Account not found for session" }, 401);
|
|
23806
23897
|
const eventId = c.req.param("eventId");
|
|
@@ -23870,7 +23961,7 @@ app47.patch("/:eventId", requireAdminSession, async (c) => {
|
|
|
23870
23961
|
await session.close();
|
|
23871
23962
|
}
|
|
23872
23963
|
});
|
|
23873
|
-
|
|
23964
|
+
app48.delete("/:eventId", requireAdminSession, async (c) => {
|
|
23874
23965
|
const accountId = getAccountIdForSession(c.var.cacheKey);
|
|
23875
23966
|
if (!accountId) {
|
|
23876
23967
|
console.error('[admin:routines] op=delete auth-rejected reason="no account for session"');
|
|
@@ -23898,12 +23989,12 @@ app47.delete("/:eventId", requireAdminSession, async (c) => {
|
|
|
23898
23989
|
await session.close();
|
|
23899
23990
|
}
|
|
23900
23991
|
});
|
|
23901
|
-
var routines_default =
|
|
23992
|
+
var routines_default = app48;
|
|
23902
23993
|
|
|
23903
23994
|
// server/routes/admin/skills.ts
|
|
23904
|
-
import { existsSync as
|
|
23905
|
-
import { resolve as
|
|
23906
|
-
var
|
|
23995
|
+
import { existsSync as existsSync38, readdirSync as readdirSync24, readFileSync as readFileSync39, rmSync as rmSync3 } from "fs";
|
|
23996
|
+
import { resolve as resolve32 } from "path";
|
|
23997
|
+
var app49 = new Hono();
|
|
23907
23998
|
var NAME_RE = /^[a-z0-9][a-z0-9-]*$/;
|
|
23908
23999
|
function splitSkillMd(text) {
|
|
23909
24000
|
const m = text.match(/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/);
|
|
@@ -23931,32 +24022,32 @@ function accountDirForSession(cacheKey) {
|
|
|
23931
24022
|
return match ? { accountId, accountDir: match.accountDir } : null;
|
|
23932
24023
|
}
|
|
23933
24024
|
function subdirs(dir) {
|
|
23934
|
-
if (!
|
|
24025
|
+
if (!existsSync38(dir)) return [];
|
|
23935
24026
|
try {
|
|
23936
24027
|
return readdirSync24(dir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
|
|
23937
24028
|
} catch {
|
|
23938
24029
|
return [];
|
|
23939
24030
|
}
|
|
23940
24031
|
}
|
|
23941
|
-
|
|
24032
|
+
app49.get("/", requireAdminSession, async (c) => {
|
|
23942
24033
|
const acct = accountDirForSession(c.var.cacheKey);
|
|
23943
24034
|
if (!acct) {
|
|
23944
24035
|
console.error('[admin:skills] op=list auth-rejected reason="no account for session"');
|
|
23945
24036
|
return c.json({ error: "Account not found for session" }, 401);
|
|
23946
24037
|
}
|
|
23947
|
-
const pluginsDir =
|
|
24038
|
+
const pluginsDir = resolve32(acct.accountDir, "plugins");
|
|
23948
24039
|
const skills = [];
|
|
23949
24040
|
let pluginCount = 0;
|
|
23950
24041
|
for (const plugin of subdirs(pluginsDir)) {
|
|
23951
24042
|
pluginCount++;
|
|
23952
|
-
const skillsDir =
|
|
24043
|
+
const skillsDir = resolve32(pluginsDir, plugin, "skills");
|
|
23953
24044
|
for (const skill of subdirs(skillsDir)) {
|
|
23954
|
-
const skillMd =
|
|
23955
|
-
if (!
|
|
24045
|
+
const skillMd = resolve32(skillsDir, skill, "SKILL.md");
|
|
24046
|
+
if (!existsSync38(skillMd)) continue;
|
|
23956
24047
|
try {
|
|
23957
24048
|
const { frontmatter } = splitSkillMd(readFileSync39(skillMd, "utf-8"));
|
|
23958
|
-
const refsDir =
|
|
23959
|
-
const refCount =
|
|
24049
|
+
const refsDir = resolve32(skillsDir, skill, "references");
|
|
24050
|
+
const refCount = existsSync38(refsDir) ? readdirSync24(refsDir, { withFileTypes: true }).filter((e) => e.isFile()).length : 0;
|
|
23960
24051
|
skills.push({ plugin, skill, description: frontmatter.description, refCount });
|
|
23961
24052
|
} catch (err) {
|
|
23962
24053
|
console.error(`[admin:skills] op=list-skip plugin=${plugin} skill=${skill} reason="${err instanceof Error ? err.message : String(err)}"`);
|
|
@@ -23967,7 +24058,7 @@ app48.get("/", requireAdminSession, async (c) => {
|
|
|
23967
24058
|
console.log(`[admin:skills] op=list accountId=${acct.accountId.slice(0, 8)} plugins=${pluginCount} skills=${skills.length}`);
|
|
23968
24059
|
return c.json({ skills });
|
|
23969
24060
|
});
|
|
23970
|
-
|
|
24061
|
+
app49.get("/:plugin/:skill", requireAdminSession, async (c) => {
|
|
23971
24062
|
const acct = accountDirForSession(c.var.cacheKey);
|
|
23972
24063
|
if (!acct) return c.json({ error: "Account not found for session" }, 401);
|
|
23973
24064
|
const plugin = c.req.param("plugin");
|
|
@@ -23976,15 +24067,15 @@ app48.get("/:plugin/:skill", requireAdminSession, async (c) => {
|
|
|
23976
24067
|
console.error(`[admin:skills] op=get outcome=rejected reason=invalid-name plugin="${plugin}" skill="${skill}"`);
|
|
23977
24068
|
return c.json({ error: "Invalid plugin or skill name" }, 400);
|
|
23978
24069
|
}
|
|
23979
|
-
const skillDir =
|
|
23980
|
-
const skillMd =
|
|
23981
|
-
const found =
|
|
24070
|
+
const skillDir = resolve32(acct.accountDir, "plugins", plugin, "skills", skill);
|
|
24071
|
+
const skillMd = resolve32(skillDir, "SKILL.md");
|
|
24072
|
+
const found = existsSync38(skillMd);
|
|
23982
24073
|
console.log(`[admin:skills] op=get plugin=${plugin} skill=${skill} found=${found}`);
|
|
23983
24074
|
if (!found) return c.json({ error: "Skill not found" }, 404);
|
|
23984
24075
|
try {
|
|
23985
24076
|
const { frontmatter, body } = splitSkillMd(readFileSync39(skillMd, "utf-8"));
|
|
23986
|
-
const refsDir =
|
|
23987
|
-
const references =
|
|
24077
|
+
const refsDir = resolve32(skillDir, "references");
|
|
24078
|
+
const references = existsSync38(refsDir) ? readdirSync24(refsDir, { withFileTypes: true }).filter((e) => e.isFile()).map((e) => e.name).sort() : [];
|
|
23988
24079
|
return c.json({ skill: { plugin, skill, frontmatter, body, references } });
|
|
23989
24080
|
} catch (err) {
|
|
23990
24081
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -23992,7 +24083,7 @@ app48.get("/:plugin/:skill", requireAdminSession, async (c) => {
|
|
|
23992
24083
|
return c.json({ error: `Skill unavailable: ${message}` }, 503);
|
|
23993
24084
|
}
|
|
23994
24085
|
});
|
|
23995
|
-
|
|
24086
|
+
app49.delete("/:plugin/:skill", requireAdminSession, async (c) => {
|
|
23996
24087
|
const acct = accountDirForSession(c.var.cacheKey);
|
|
23997
24088
|
if (!acct) return c.json({ error: "Account not found for session" }, 401);
|
|
23998
24089
|
const plugin = c.req.param("plugin");
|
|
@@ -24001,10 +24092,10 @@ app48.delete("/:plugin/:skill", requireAdminSession, async (c) => {
|
|
|
24001
24092
|
console.error(`[admin:skills] op=delete outcome=rejected reason=invalid-name plugin="${plugin}" skill="${skill}"`);
|
|
24002
24093
|
return c.json({ error: "Invalid plugin or skill name" }, 400);
|
|
24003
24094
|
}
|
|
24004
|
-
const pluginDir =
|
|
24005
|
-
const skillsDir =
|
|
24006
|
-
const skillDir =
|
|
24007
|
-
if (!
|
|
24095
|
+
const pluginDir = resolve32(acct.accountDir, "plugins", plugin);
|
|
24096
|
+
const skillsDir = resolve32(pluginDir, "skills");
|
|
24097
|
+
const skillDir = resolve32(skillsDir, skill);
|
|
24098
|
+
if (!existsSync38(resolve32(skillDir, "SKILL.md"))) {
|
|
24008
24099
|
console.error(`[admin:skills] op=delete outcome=rejected reason=not-found plugin=${plugin} skill=${skill}`);
|
|
24009
24100
|
return c.json({ error: "Skill not found" }, 404);
|
|
24010
24101
|
}
|
|
@@ -24012,7 +24103,7 @@ app48.delete("/:plugin/:skill", requireAdminSession, async (c) => {
|
|
|
24012
24103
|
rmSync3(skillDir, { recursive: true, force: true });
|
|
24013
24104
|
const pluginDirRemoved = subdirs(skillsDir).length === 0;
|
|
24014
24105
|
if (pluginDirRemoved) rmSync3(pluginDir, { recursive: true, force: true });
|
|
24015
|
-
const skillDirGone = !
|
|
24106
|
+
const skillDirGone = !existsSync38(skillDir);
|
|
24016
24107
|
if (!skillDirGone) {
|
|
24017
24108
|
console.error(`[admin:skills] op=delete plugin=${plugin} skill=${skill} outcome=rejected reason=rm-incomplete skillDirGone=false`);
|
|
24018
24109
|
return c.json({ error: "Delete did not remove the skill directory" }, 503);
|
|
@@ -24025,7 +24116,7 @@ app48.delete("/:plugin/:skill", requireAdminSession, async (c) => {
|
|
|
24025
24116
|
return c.json({ error: `Delete failed: ${message}` }, 503);
|
|
24026
24117
|
}
|
|
24027
24118
|
});
|
|
24028
|
-
var skills_default =
|
|
24119
|
+
var skills_default = app49;
|
|
24029
24120
|
|
|
24030
24121
|
// app/lib/time-entry-format.ts
|
|
24031
24122
|
function secondsBetween(startIso, endIso) {
|
|
@@ -24048,8 +24139,8 @@ function toNum(v) {
|
|
|
24048
24139
|
var TAG39 = "[task-timer]";
|
|
24049
24140
|
var COMPLETED = /* @__PURE__ */ new Set(["completed"]);
|
|
24050
24141
|
var HIDDEN_FROM_OPEN = /* @__PURE__ */ new Set(["completed", "cancelled"]);
|
|
24051
|
-
var
|
|
24052
|
-
|
|
24142
|
+
var app50 = new Hono();
|
|
24143
|
+
app50.get("/", requireAdminSession, async (c) => {
|
|
24053
24144
|
const cacheKey = c.var.cacheKey;
|
|
24054
24145
|
const accountId = getAccountIdForSession(cacheKey);
|
|
24055
24146
|
if (!accountId) {
|
|
@@ -24136,13 +24227,13 @@ app49.get("/", requireAdminSession, async (c) => {
|
|
|
24136
24227
|
await session.close();
|
|
24137
24228
|
}
|
|
24138
24229
|
});
|
|
24139
|
-
var tasks_list_default =
|
|
24230
|
+
var tasks_list_default = app50;
|
|
24140
24231
|
|
|
24141
24232
|
// server/routes/admin/task-timer-start.ts
|
|
24142
24233
|
import { randomUUID as randomUUID14 } from "crypto";
|
|
24143
24234
|
var TAG40 = "[task-timer]";
|
|
24144
|
-
var
|
|
24145
|
-
|
|
24235
|
+
var app51 = new Hono();
|
|
24236
|
+
app51.post("/", requireAdminSession, async (c) => {
|
|
24146
24237
|
const cacheKey = c.var.cacheKey;
|
|
24147
24238
|
const accountId = getAccountIdForSession(cacheKey);
|
|
24148
24239
|
if (!accountId) return c.json({ error: "Account not found for session" }, 401);
|
|
@@ -24197,13 +24288,13 @@ app50.post("/", requireAdminSession, async (c) => {
|
|
|
24197
24288
|
await session.close();
|
|
24198
24289
|
}
|
|
24199
24290
|
});
|
|
24200
|
-
var task_timer_start_default =
|
|
24291
|
+
var task_timer_start_default = app51;
|
|
24201
24292
|
|
|
24202
24293
|
// server/routes/admin/task-timer-stop.ts
|
|
24203
24294
|
import neo4j5 from "neo4j-driver";
|
|
24204
24295
|
var TAG41 = "[task-timer]";
|
|
24205
|
-
var
|
|
24206
|
-
|
|
24296
|
+
var app52 = new Hono();
|
|
24297
|
+
app52.post("/", requireAdminSession, async (c) => {
|
|
24207
24298
|
const cacheKey = c.var.cacheKey;
|
|
24208
24299
|
const accountId = getAccountIdForSession(cacheKey);
|
|
24209
24300
|
if (!accountId) return c.json({ error: "Account not found for session" }, 401);
|
|
@@ -24270,12 +24361,12 @@ app51.post("/", requireAdminSession, async (c) => {
|
|
|
24270
24361
|
await session.close();
|
|
24271
24362
|
}
|
|
24272
24363
|
});
|
|
24273
|
-
var task_timer_stop_default =
|
|
24364
|
+
var task_timer_stop_default = app52;
|
|
24274
24365
|
|
|
24275
24366
|
// server/routes/admin/task-complete.ts
|
|
24276
24367
|
var TAG42 = "[task-timer]";
|
|
24277
|
-
var
|
|
24278
|
-
|
|
24368
|
+
var app53 = new Hono();
|
|
24369
|
+
app53.post("/", requireAdminSession, async (c) => {
|
|
24279
24370
|
const cacheKey = c.var.cacheKey;
|
|
24280
24371
|
const accountId = getAccountIdForSession(cacheKey);
|
|
24281
24372
|
if (!accountId) return c.json({ error: "Account not found for session" }, 401);
|
|
@@ -24313,14 +24404,14 @@ app52.post("/", requireAdminSession, async (c) => {
|
|
|
24313
24404
|
await session.close();
|
|
24314
24405
|
}
|
|
24315
24406
|
});
|
|
24316
|
-
var task_complete_default =
|
|
24407
|
+
var task_complete_default = app53;
|
|
24317
24408
|
|
|
24318
24409
|
// server/routes/admin/task-time-adjust.ts
|
|
24319
24410
|
import { randomUUID as randomUUID15 } from "crypto";
|
|
24320
24411
|
import neo4j6 from "neo4j-driver";
|
|
24321
24412
|
var TAG43 = "[task-time-adjust]";
|
|
24322
|
-
var
|
|
24323
|
-
|
|
24413
|
+
var app54 = new Hono();
|
|
24414
|
+
app54.post("/", requireAdminSession, async (c) => {
|
|
24324
24415
|
const cacheKey = c.var.cacheKey;
|
|
24325
24416
|
const accountId = getAccountIdForSession(cacheKey);
|
|
24326
24417
|
if (!accountId) return c.json({ error: "Account not found for session" }, 401);
|
|
@@ -24394,11 +24485,11 @@ app53.post("/", requireAdminSession, async (c) => {
|
|
|
24394
24485
|
await session.close();
|
|
24395
24486
|
}
|
|
24396
24487
|
});
|
|
24397
|
-
var task_time_adjust_default =
|
|
24488
|
+
var task_time_adjust_default = app54;
|
|
24398
24489
|
|
|
24399
24490
|
// server/routes/admin/activity.ts
|
|
24400
24491
|
import { readdirSync as readdirSync25 } from "fs";
|
|
24401
|
-
var
|
|
24492
|
+
var app55 = new Hono();
|
|
24402
24493
|
var TAG44 = "[activity]";
|
|
24403
24494
|
function resolveHouseAccountId(accounts) {
|
|
24404
24495
|
const houses = accounts.filter((a) => a.config.role === "house");
|
|
@@ -24420,7 +24511,7 @@ function countAccountDirsOnDisk() {
|
|
|
24420
24511
|
return null;
|
|
24421
24512
|
}
|
|
24422
24513
|
}
|
|
24423
|
-
|
|
24514
|
+
app55.get("/", requireAdminSession, async (c) => {
|
|
24424
24515
|
const req = requestToken();
|
|
24425
24516
|
const cacheKey = c.var.cacheKey;
|
|
24426
24517
|
const caller2 = getAccountIdForSession(cacheKey) ?? null;
|
|
@@ -24529,62 +24620,63 @@ app54.get("/", requireAdminSession, async (c) => {
|
|
|
24529
24620
|
}
|
|
24530
24621
|
});
|
|
24531
24622
|
});
|
|
24532
|
-
var activity_default =
|
|
24623
|
+
var activity_default = app55;
|
|
24533
24624
|
|
|
24534
24625
|
// server/routes/admin/index.ts
|
|
24535
|
-
var
|
|
24536
|
-
|
|
24537
|
-
|
|
24538
|
-
|
|
24539
|
-
|
|
24540
|
-
|
|
24541
|
-
|
|
24542
|
-
|
|
24543
|
-
|
|
24544
|
-
|
|
24545
|
-
|
|
24546
|
-
|
|
24547
|
-
|
|
24548
|
-
|
|
24549
|
-
|
|
24550
|
-
|
|
24551
|
-
|
|
24552
|
-
|
|
24553
|
-
|
|
24554
|
-
|
|
24555
|
-
|
|
24556
|
-
|
|
24557
|
-
|
|
24558
|
-
|
|
24559
|
-
|
|
24560
|
-
|
|
24561
|
-
|
|
24562
|
-
|
|
24563
|
-
|
|
24564
|
-
|
|
24565
|
-
|
|
24566
|
-
|
|
24567
|
-
|
|
24568
|
-
|
|
24569
|
-
|
|
24570
|
-
|
|
24571
|
-
|
|
24572
|
-
|
|
24573
|
-
|
|
24574
|
-
|
|
24575
|
-
|
|
24576
|
-
|
|
24577
|
-
|
|
24578
|
-
|
|
24579
|
-
|
|
24580
|
-
|
|
24626
|
+
var app56 = new Hono();
|
|
24627
|
+
app56.route("/session", session_default);
|
|
24628
|
+
app56.route("/accounts", accounts_default);
|
|
24629
|
+
app56.route("/logs", logs_default);
|
|
24630
|
+
app56.route("/claude-info", claude_info_default);
|
|
24631
|
+
app56.route("/attachment", attachment_default);
|
|
24632
|
+
app56.route("/session-upload", session_upload_default);
|
|
24633
|
+
app56.route("/agents", agents_default);
|
|
24634
|
+
app56.route("/sessions", sessions_default);
|
|
24635
|
+
app56.route("/claude-sessions", claude_sessions_default);
|
|
24636
|
+
app56.route("/log-ingest", log_ingest_default);
|
|
24637
|
+
app56.route("/events", events_default);
|
|
24638
|
+
app56.route("/files", files_default);
|
|
24639
|
+
app56.route("/graph-search", graph_search_default);
|
|
24640
|
+
app56.route("/graph-subgraph", graph_subgraph_default);
|
|
24641
|
+
app56.route("/graph-delete", graph_delete_default);
|
|
24642
|
+
app56.route("/graph-restore", graph_restore_default);
|
|
24643
|
+
app56.route("/graph-labels-in-graph", graph_labels_in_graph_default);
|
|
24644
|
+
app56.route("/graph-default-view", graph_default_view_default);
|
|
24645
|
+
app56.route("/sidebar-artefacts", sidebar_artefacts_default);
|
|
24646
|
+
app56.route("/sidebar-sessions", sidebar_sessions_default);
|
|
24647
|
+
app56.route("/session-delete", session_delete_default);
|
|
24648
|
+
app56.route("/session-stop", session_stop_default);
|
|
24649
|
+
app56.route("/session-archive", session_archive_default);
|
|
24650
|
+
app56.route("/session-rename", session_rename_default);
|
|
24651
|
+
app56.route("/session-usage", session_usage_default);
|
|
24652
|
+
app56.route("/browser", browser_default);
|
|
24653
|
+
app56.route("/session-rc-spawn", session_rc_spawn_default);
|
|
24654
|
+
app56.route("/session-reseat", session_reseat_default);
|
|
24655
|
+
app56.route("/system-stats", system_stats_default);
|
|
24656
|
+
app56.route("/health-brand", health_default2);
|
|
24657
|
+
app56.route("/linkedin-ingest", linkedin_ingest_default);
|
|
24658
|
+
app56.route("/post-turn-context", post_turn_context_default);
|
|
24659
|
+
app56.route("/public-session-context", public_session_context_default);
|
|
24660
|
+
app56.route("/public-session-exit", public_session_exit_default);
|
|
24661
|
+
app56.route("/access-session-evict", access_session_evict_default);
|
|
24662
|
+
app56.route("/enrol-person", enrol_person_default);
|
|
24663
|
+
app56.route("/calendar", calendar_default);
|
|
24664
|
+
app56.route("/routines", routines_default);
|
|
24665
|
+
app56.route("/skills", skills_default);
|
|
24666
|
+
app56.route("/tasks-list", tasks_list_default);
|
|
24667
|
+
app56.route("/task-timer-start", task_timer_start_default);
|
|
24668
|
+
app56.route("/task-timer-stop", task_timer_stop_default);
|
|
24669
|
+
app56.route("/task-complete", task_complete_default);
|
|
24670
|
+
app56.route("/task-time-adjust", task_time_adjust_default);
|
|
24671
|
+
app56.route("/activity", activity_default);
|
|
24672
|
+
var admin_default = app56;
|
|
24581
24673
|
|
|
24582
24674
|
// server/routes/access/verify-token.ts
|
|
24583
24675
|
var TAG45 = "[access-verify]";
|
|
24584
24676
|
var MINT_TAG = "[access-session-mint]";
|
|
24585
24677
|
var COOKIE_NAME = "__access_session";
|
|
24586
|
-
var
|
|
24587
|
-
|
|
24678
|
+
var app57 = new Hono();
|
|
24679
|
+
app57.post("/", async (c) => {
|
|
24588
24680
|
const ip = c.var.clientIp || "unknown";
|
|
24589
24681
|
let body;
|
|
24590
24682
|
try {
|
|
@@ -24666,13 +24758,13 @@ app56.post("/", async (c) => {
|
|
|
24666
24758
|
displayName: grant.displayName
|
|
24667
24759
|
});
|
|
24668
24760
|
});
|
|
24669
|
-
var verify_token_default =
|
|
24761
|
+
var verify_token_default = app57;
|
|
24670
24762
|
|
|
24671
24763
|
// app/lib/access-email.ts
|
|
24672
24764
|
import { spawn as spawn2 } from "child_process";
|
|
24673
|
-
import { resolve as
|
|
24674
|
-
var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT ??
|
|
24675
|
-
var SEND_SCRIPT =
|
|
24765
|
+
import { resolve as resolve33 } from "path";
|
|
24766
|
+
var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT ?? resolve33(process.cwd(), "..");
|
|
24767
|
+
var SEND_SCRIPT = resolve33(
|
|
24676
24768
|
PLATFORM_ROOT7,
|
|
24677
24769
|
"plugins",
|
|
24678
24770
|
"email",
|
|
@@ -24729,9 +24821,9 @@ async function sendMagicLinkEmail(payload) {
|
|
|
24729
24821
|
|
|
24730
24822
|
// server/routes/access/request-magic-link.ts
|
|
24731
24823
|
var TAG46 = "[access-request-link]";
|
|
24732
|
-
var
|
|
24824
|
+
var app58 = new Hono();
|
|
24733
24825
|
var VISITOR_MESSAGE = "If that email is on the invite list, a fresh link is on the way.";
|
|
24734
|
-
|
|
24826
|
+
app58.post("/", async (c) => {
|
|
24735
24827
|
let body;
|
|
24736
24828
|
try {
|
|
24737
24829
|
body = await c.req.json();
|
|
@@ -24805,17 +24897,17 @@ app57.post("/", async (c) => {
|
|
|
24805
24897
|
);
|
|
24806
24898
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
24807
24899
|
});
|
|
24808
|
-
var request_magic_link_default =
|
|
24900
|
+
var request_magic_link_default = app58;
|
|
24809
24901
|
|
|
24810
24902
|
// server/routes/access/index.ts
|
|
24811
|
-
var
|
|
24812
|
-
|
|
24813
|
-
|
|
24814
|
-
var access_default =
|
|
24903
|
+
var app59 = new Hono();
|
|
24904
|
+
app59.route("/verify-token", verify_token_default);
|
|
24905
|
+
app59.route("/request-magic-link", request_magic_link_default);
|
|
24906
|
+
var access_default = app59;
|
|
24815
24907
|
|
|
24816
24908
|
// server/routes/sites.ts
|
|
24817
|
-
import { existsSync as
|
|
24818
|
-
import { resolve as
|
|
24909
|
+
import { existsSync as existsSync39, readFileSync as readFileSync40, realpathSync as realpathSync8, statSync as statSync17 } from "fs";
|
|
24910
|
+
import { resolve as resolve34 } from "path";
|
|
24819
24911
|
var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
|
|
24820
24912
|
var MIME = {
|
|
24821
24913
|
".html": "text/html; charset=utf-8",
|
|
@@ -24846,8 +24938,8 @@ function getExt(p) {
|
|
|
24846
24938
|
if (idx < p.lastIndexOf("/")) return "";
|
|
24847
24939
|
return p.slice(idx).toLowerCase();
|
|
24848
24940
|
}
|
|
24849
|
-
var
|
|
24850
|
-
|
|
24941
|
+
var app60 = new Hono();
|
|
24942
|
+
app60.get("/:rel{.*}", (c) => {
|
|
24851
24943
|
const reqPath = c.req.path;
|
|
24852
24944
|
const rawRel = c.req.param("rel") ?? "";
|
|
24853
24945
|
const trimmed = rawRel.replace(/^\/+/, "").replace(/\/+$/, "");
|
|
@@ -24872,15 +24964,15 @@ app59.get("/:rel{.*}", (c) => {
|
|
|
24872
24964
|
}
|
|
24873
24965
|
segments.push(seg);
|
|
24874
24966
|
}
|
|
24875
|
-
const rootDir =
|
|
24876
|
-
let filePath = segments.length === 0 ? rootDir :
|
|
24967
|
+
const rootDir = resolve34(account.accountDir, "sites");
|
|
24968
|
+
let filePath = segments.length === 0 ? rootDir : resolve34(rootDir, ...segments);
|
|
24877
24969
|
if (filePath !== rootDir && !filePath.startsWith(rootDir + "/")) {
|
|
24878
24970
|
console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
|
|
24879
24971
|
return c.text("Forbidden", 403);
|
|
24880
24972
|
}
|
|
24881
24973
|
let stat11;
|
|
24882
24974
|
try {
|
|
24883
|
-
stat11 =
|
|
24975
|
+
stat11 = existsSync39(filePath) ? statSync17(filePath) : null;
|
|
24884
24976
|
} catch {
|
|
24885
24977
|
stat11 = null;
|
|
24886
24978
|
}
|
|
@@ -24893,21 +24985,21 @@ app59.get("/:rel{.*}", (c) => {
|
|
|
24893
24985
|
return c.redirect(target, 301);
|
|
24894
24986
|
}
|
|
24895
24987
|
if (stat11?.isDirectory()) {
|
|
24896
|
-
filePath =
|
|
24988
|
+
filePath = resolve34(filePath, "index.html");
|
|
24897
24989
|
}
|
|
24898
24990
|
if (!filePath.startsWith(rootDir + "/")) {
|
|
24899
24991
|
console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
|
|
24900
24992
|
return c.text("Forbidden", 403);
|
|
24901
24993
|
}
|
|
24902
|
-
if (!
|
|
24994
|
+
if (!existsSync39(filePath)) {
|
|
24903
24995
|
console.error(`[sites] not-found path=${reqPath} status=404`);
|
|
24904
24996
|
return c.text("Not found", 404);
|
|
24905
24997
|
}
|
|
24906
24998
|
let realPath;
|
|
24907
24999
|
let realRoot;
|
|
24908
25000
|
try {
|
|
24909
|
-
realPath =
|
|
24910
|
-
realRoot =
|
|
25001
|
+
realPath = realpathSync8(filePath);
|
|
25002
|
+
realRoot = realpathSync8(rootDir);
|
|
24911
25003
|
} catch {
|
|
24912
25004
|
console.error(`[sites] not-found path=${reqPath} status=404`);
|
|
24913
25005
|
return c.text("Not found", 404);
|
|
@@ -24950,12 +25042,12 @@ app59.get("/:rel{.*}", (c) => {
|
|
|
24950
25042
|
"X-Content-Type-Options": "nosniff"
|
|
24951
25043
|
});
|
|
24952
25044
|
});
|
|
24953
|
-
var sites_default =
|
|
25045
|
+
var sites_default = app60;
|
|
24954
25046
|
|
|
24955
25047
|
// app/lib/visitor-token.ts
|
|
24956
25048
|
import { createHmac, randomBytes, timingSafeEqual } from "crypto";
|
|
24957
25049
|
import { mkdirSync as mkdirSync8, readFileSync as readFileSync41, writeFileSync as writeFileSync14 } from "fs";
|
|
24958
|
-
import { dirname as
|
|
25050
|
+
import { dirname as dirname14 } from "path";
|
|
24959
25051
|
var TOKEN_PREFIX = "v1.";
|
|
24960
25052
|
var SECRET_BYTES = 32;
|
|
24961
25053
|
var DEFAULT_TTL_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
@@ -24972,7 +25064,7 @@ function getSecret() {
|
|
|
24972
25064
|
}
|
|
24973
25065
|
const fresh = randomBytes(SECRET_BYTES).toString("hex");
|
|
24974
25066
|
try {
|
|
24975
|
-
mkdirSync8(
|
|
25067
|
+
mkdirSync8(dirname14(VISITOR_TOKEN_SECRET_FILE), { recursive: true, mode: 448 });
|
|
24976
25068
|
writeFileSync14(VISITOR_TOKEN_SECRET_FILE, fresh, { mode: 384, flag: "wx" });
|
|
24977
25069
|
console.log(`[visitor-token] secret minted path=${VISITOR_TOKEN_SECRET_FILE}`);
|
|
24978
25070
|
} catch {
|
|
@@ -25030,7 +25122,7 @@ var VISITOR_COOKIE_NAME = "mxy_v";
|
|
|
25030
25122
|
var VISITOR_COOKIE_MAX_AGE_SECONDS = Math.floor(DEFAULT_TTL_MS / 1e3);
|
|
25031
25123
|
|
|
25032
25124
|
// app/lib/brand-config.ts
|
|
25033
|
-
import { existsSync as
|
|
25125
|
+
import { existsSync as existsSync40, readFileSync as readFileSync42 } from "fs";
|
|
25034
25126
|
import { join as join43 } from "path";
|
|
25035
25127
|
var cached2 = null;
|
|
25036
25128
|
var cachedAttempted = false;
|
|
@@ -25040,7 +25132,7 @@ function readBrandConfig() {
|
|
|
25040
25132
|
const platformRoot5 = process.env.MAXY_PLATFORM_ROOT;
|
|
25041
25133
|
if (!platformRoot5) return null;
|
|
25042
25134
|
const brandPath = join43(platformRoot5, "config", "brand.json");
|
|
25043
|
-
if (!
|
|
25135
|
+
if (!existsSync40(brandPath)) return null;
|
|
25044
25136
|
try {
|
|
25045
25137
|
cached2 = JSON.parse(readFileSync42(brandPath, "utf-8"));
|
|
25046
25138
|
return cached2;
|
|
@@ -25050,7 +25142,7 @@ function readBrandConfig() {
|
|
|
25050
25142
|
}
|
|
25051
25143
|
|
|
25052
25144
|
// server/routes/visitor-consent.ts
|
|
25053
|
-
var
|
|
25145
|
+
var app61 = new Hono();
|
|
25054
25146
|
var CONSENT_COOKIE_NAME = "mxy_consent";
|
|
25055
25147
|
var CONSENT_COOKIE_MAX_AGE_SECONDS = 60 * 60 * 24 * 365;
|
|
25056
25148
|
var DEFAULT_CONSENT_COPY = {
|
|
@@ -25095,17 +25187,17 @@ function siteSlugFromReferer(referer) {
|
|
|
25095
25187
|
return "";
|
|
25096
25188
|
}
|
|
25097
25189
|
}
|
|
25098
|
-
|
|
25190
|
+
app61.options("/consent", (c) => {
|
|
25099
25191
|
const origin = getOrigin(c);
|
|
25100
25192
|
setCorsHeaders(c, origin);
|
|
25101
25193
|
return c.body(null, 204);
|
|
25102
25194
|
});
|
|
25103
|
-
|
|
25195
|
+
app61.options("/brand-config", (c) => {
|
|
25104
25196
|
const origin = getOrigin(c);
|
|
25105
25197
|
setCorsHeaders(c, origin);
|
|
25106
25198
|
return c.body(null, 204);
|
|
25107
25199
|
});
|
|
25108
|
-
|
|
25200
|
+
app61.post("/consent", async (c) => {
|
|
25109
25201
|
const origin = getOrigin(c);
|
|
25110
25202
|
setCorsHeaders(c, origin);
|
|
25111
25203
|
let raw;
|
|
@@ -25145,7 +25237,7 @@ app60.post("/consent", async (c) => {
|
|
|
25145
25237
|
console.log(`[consent] ${parsed.decision} site=${site} brand=${brandName} tokenBound=${tokenBound}`);
|
|
25146
25238
|
return c.body(null, 204);
|
|
25147
25239
|
});
|
|
25148
|
-
|
|
25240
|
+
app61.get("/brand-config", (c) => {
|
|
25149
25241
|
const origin = getOrigin(c);
|
|
25150
25242
|
setCorsHeaders(c, origin);
|
|
25151
25243
|
const brand = readBrandConfig();
|
|
@@ -25155,7 +25247,7 @@ app60.get("/brand-config", (c) => {
|
|
|
25155
25247
|
c.header("Cache-Control", "public, max-age=300");
|
|
25156
25248
|
return c.json({ consent: { copy, palette } });
|
|
25157
25249
|
});
|
|
25158
|
-
var visitor_consent_default =
|
|
25250
|
+
var visitor_consent_default = app61;
|
|
25159
25251
|
|
|
25160
25252
|
// server/routes/listings.ts
|
|
25161
25253
|
function getCookie(headerValue, name) {
|
|
@@ -25176,14 +25268,14 @@ function appendConsentParams(pageUrl, token) {
|
|
|
25176
25268
|
const hashIdx = pageUrl.indexOf("#");
|
|
25177
25269
|
const hash = hashIdx >= 0 ? pageUrl.slice(hashIdx) : "";
|
|
25178
25270
|
const base = hashIdx >= 0 ? pageUrl.slice(0, hashIdx) : pageUrl;
|
|
25179
|
-
const
|
|
25180
|
-
return base +
|
|
25271
|
+
const sep12 = base.indexOf("?") >= 0 ? "&" : "?";
|
|
25272
|
+
return base + sep12 + `consent=needed&v=${encodeURIComponent(token)}` + hash;
|
|
25181
25273
|
}
|
|
25182
25274
|
}
|
|
25183
25275
|
var SAFE_SLUG_RE = /^[a-z0-9](?:[a-z0-9-]{0,118}[a-z0-9])?$/;
|
|
25184
25276
|
var CHAT_SESSION_KEY_RE = /^[A-Za-z0-9][A-Za-z0-9_-]{7,127}$/;
|
|
25185
|
-
var
|
|
25186
|
-
|
|
25277
|
+
var app62 = new Hono();
|
|
25278
|
+
app62.get("/:slug/click", async (c) => {
|
|
25187
25279
|
const slug = c.req.param("slug") ?? "";
|
|
25188
25280
|
const rawSession = c.req.query("session") ?? "";
|
|
25189
25281
|
const sessionKey = CHAT_SESSION_KEY_RE.test(rawSession) ? rawSession : "invalid";
|
|
@@ -25247,10 +25339,10 @@ app61.get("/:slug/click", async (c) => {
|
|
|
25247
25339
|
console.log(`[property-card-click] sessionKey=${sessionKey} listingSlug=${slug} consent=${consentCookie ?? "absent"} ts=${(/* @__PURE__ */ new Date()).toISOString()}`);
|
|
25248
25340
|
return c.redirect(redirectUrl, 302);
|
|
25249
25341
|
});
|
|
25250
|
-
var listings_default =
|
|
25342
|
+
var listings_default = app62;
|
|
25251
25343
|
|
|
25252
25344
|
// server/routes/visitor-event.ts
|
|
25253
|
-
var
|
|
25345
|
+
var app63 = new Hono();
|
|
25254
25346
|
var BOT_UA_RE = /\b(bot|crawl|spider|slurp|headlesschrome|phantomjs|googlebot|bingbot|yandex|baiduspider|ahrefsbot|semrushbot|mj12bot|dotbot|petalbot)\b/i;
|
|
25255
25347
|
var buckets = /* @__PURE__ */ new Map();
|
|
25256
25348
|
var RATE_LIMIT = 60;
|
|
@@ -25326,12 +25418,12 @@ function originAllowed(origin, allowlist) {
|
|
|
25326
25418
|
return false;
|
|
25327
25419
|
}
|
|
25328
25420
|
}
|
|
25329
|
-
|
|
25421
|
+
app63.options("/event", (c) => {
|
|
25330
25422
|
const origin = getOrigin2(c);
|
|
25331
25423
|
setCorsHeaders2(c, origin);
|
|
25332
25424
|
return c.body(null, 204);
|
|
25333
25425
|
});
|
|
25334
|
-
|
|
25426
|
+
app63.post("/event", async (c) => {
|
|
25335
25427
|
const origin = getOrigin2(c);
|
|
25336
25428
|
setCorsHeaders2(c, origin);
|
|
25337
25429
|
const ua = c.req.header("user-agent") ?? "";
|
|
@@ -25536,17 +25628,17 @@ async function writeEvent(opts) {
|
|
|
25536
25628
|
);
|
|
25537
25629
|
}
|
|
25538
25630
|
}
|
|
25539
|
-
var visitor_event_default =
|
|
25631
|
+
var visitor_event_default = app63;
|
|
25540
25632
|
|
|
25541
25633
|
// server/routes/session.ts
|
|
25542
|
-
import { resolve as
|
|
25543
|
-
import { existsSync as
|
|
25634
|
+
import { resolve as resolve35 } from "path";
|
|
25635
|
+
import { existsSync as existsSync41, writeFileSync as writeFileSync15, mkdirSync as mkdirSync9 } from "fs";
|
|
25544
25636
|
var UUID_RE5 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
25545
25637
|
function writeBrandingCache(accountId, agentSlug, branding) {
|
|
25546
25638
|
try {
|
|
25547
|
-
const cacheDir =
|
|
25639
|
+
const cacheDir = resolve35(MAXY_DIR, "branding-cache", accountId);
|
|
25548
25640
|
mkdirSync9(cacheDir, { recursive: true });
|
|
25549
|
-
writeFileSync15(
|
|
25641
|
+
writeFileSync15(resolve35(cacheDir, `${agentSlug}.json`), JSON.stringify(branding), "utf-8");
|
|
25550
25642
|
} catch (err) {
|
|
25551
25643
|
console.error(`[branding] cache write failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
25552
25644
|
}
|
|
@@ -25582,8 +25674,8 @@ function withVisitorCookie(response, visitorId) {
|
|
|
25582
25674
|
headers
|
|
25583
25675
|
});
|
|
25584
25676
|
}
|
|
25585
|
-
var
|
|
25586
|
-
|
|
25677
|
+
var app64 = new Hono();
|
|
25678
|
+
app64.post("/", async (c) => {
|
|
25587
25679
|
let body;
|
|
25588
25680
|
try {
|
|
25589
25681
|
body = await c.req.json();
|
|
@@ -25623,8 +25715,8 @@ app63.post("/", async (c) => {
|
|
|
25623
25715
|
}
|
|
25624
25716
|
let agentConfig = null;
|
|
25625
25717
|
if (account) {
|
|
25626
|
-
const agentDir =
|
|
25627
|
-
if (!
|
|
25718
|
+
const agentDir = resolve35(account.accountDir, "agents", agentSlug);
|
|
25719
|
+
if (!existsSync41(agentDir) || !existsSync41(resolve35(agentDir, "config.json"))) {
|
|
25628
25720
|
return c.json({ error: "Agent not found" }, 404);
|
|
25629
25721
|
}
|
|
25630
25722
|
agentConfig = resolveAgentConfig(account.accountDir, agentSlug);
|
|
@@ -25730,7 +25822,7 @@ app63.post("/", async (c) => {
|
|
|
25730
25822
|
newVisitorId
|
|
25731
25823
|
);
|
|
25732
25824
|
});
|
|
25733
|
-
var session_default2 =
|
|
25825
|
+
var session_default2 = app64;
|
|
25734
25826
|
|
|
25735
25827
|
// server/lib/calendar-slots.ts
|
|
25736
25828
|
var WEEKDAYS = ["sun", "mon", "tue", "wed", "thu", "fri", "sat"];
|
|
@@ -25813,17 +25905,17 @@ function computeOpenSlots(config, busy, fromISO, toISO) {
|
|
|
25813
25905
|
}
|
|
25814
25906
|
|
|
25815
25907
|
// server/routes/calendar-public.ts
|
|
25816
|
-
var
|
|
25908
|
+
var app65 = new Hono();
|
|
25817
25909
|
function setCors(c) {
|
|
25818
25910
|
c.header("Access-Control-Allow-Origin", "*");
|
|
25819
25911
|
c.header("Access-Control-Allow-Methods", "GET, OPTIONS");
|
|
25820
25912
|
c.header("Access-Control-Allow-Headers", "content-type");
|
|
25821
25913
|
}
|
|
25822
|
-
|
|
25914
|
+
app65.options("/free-busy", (c) => {
|
|
25823
25915
|
setCors(c);
|
|
25824
25916
|
return c.body(null, 204);
|
|
25825
25917
|
});
|
|
25826
|
-
|
|
25918
|
+
app65.get("/free-busy", async (c) => {
|
|
25827
25919
|
setCors(c);
|
|
25828
25920
|
const from = c.req.query("from");
|
|
25829
25921
|
const to = c.req.query("to");
|
|
@@ -25879,14 +25971,14 @@ app64.get("/free-busy", async (c) => {
|
|
|
25879
25971
|
await session.close();
|
|
25880
25972
|
}
|
|
25881
25973
|
});
|
|
25882
|
-
var calendar_public_default =
|
|
25974
|
+
var calendar_public_default = app65;
|
|
25883
25975
|
|
|
25884
25976
|
// server/routes/portal-fetch.ts
|
|
25885
25977
|
import { createReadStream as createReadStream3 } from "fs";
|
|
25886
|
-
import { stat as stat8, readFile as
|
|
25887
|
-
import { join as join44, resolve as
|
|
25978
|
+
import { stat as stat8, readFile as readFile9, realpath } from "fs/promises";
|
|
25979
|
+
import { join as join44, resolve as resolve36, sep as sep10 } from "path";
|
|
25888
25980
|
import { Readable as Readable3 } from "stream";
|
|
25889
|
-
var
|
|
25981
|
+
var app66 = new Hono();
|
|
25890
25982
|
var TAG47 = "[portal-fetch]";
|
|
25891
25983
|
async function verifySignature(secret, accountId, relPath, expiresAtMs, signature, nowMs) {
|
|
25892
25984
|
if (!secret || !signature) return false;
|
|
@@ -25937,10 +26029,10 @@ ${expiresAtMs}`)
|
|
|
25937
26029
|
return diff === 0;
|
|
25938
26030
|
}
|
|
25939
26031
|
async function readAccountSecret(accountId) {
|
|
25940
|
-
const path3 =
|
|
26032
|
+
const path3 = resolve36(DATA_ROOT, "accounts", accountId, "secrets", "data-portal.env");
|
|
25941
26033
|
let text;
|
|
25942
26034
|
try {
|
|
25943
|
-
text = await
|
|
26035
|
+
text = await readFile9(path3, "utf8");
|
|
25944
26036
|
} catch {
|
|
25945
26037
|
console.error(`${TAG47} op=no-secret account="${accountId}" path="${path3}"`);
|
|
25946
26038
|
return "";
|
|
@@ -25957,7 +26049,7 @@ function isValidAccountId2(value) {
|
|
|
25957
26049
|
}
|
|
25958
26050
|
async function readExposeFolders2(accountDir) {
|
|
25959
26051
|
try {
|
|
25960
|
-
const cfg = JSON.parse(await
|
|
26052
|
+
const cfg = JSON.parse(await readFile9(join44(accountDir, "data-portal.json"), "utf8"));
|
|
25961
26053
|
return Array.isArray(cfg?.exposeFolders) ? cfg.exposeFolders.filter((f) => typeof f === "string") : [];
|
|
25962
26054
|
} catch {
|
|
25963
26055
|
return [];
|
|
@@ -25966,14 +26058,14 @@ async function readExposeFolders2(accountDir) {
|
|
|
25966
26058
|
async function resolveFetchTarget(accountDir, relPath, ownerId) {
|
|
25967
26059
|
let schemaText = null;
|
|
25968
26060
|
try {
|
|
25969
|
-
schemaText = await
|
|
26061
|
+
schemaText = await readFile9(join44(accountDir, "SCHEMA.md"), "utf8");
|
|
25970
26062
|
} catch {
|
|
25971
26063
|
schemaText = null;
|
|
25972
26064
|
}
|
|
25973
26065
|
const exposeFolders = await readExposeFolders2(accountDir);
|
|
25974
26066
|
const { exposed } = resolveExposedDirs(schemaText, exposeFolders);
|
|
25975
26067
|
if (exposed.length === 0 && !ownerId) return { ok: false, reason: "not-exposed" };
|
|
25976
|
-
const lexical =
|
|
26068
|
+
const lexical = resolve36(accountDir, relPath);
|
|
25977
26069
|
let root;
|
|
25978
26070
|
let absolute;
|
|
25979
26071
|
try {
|
|
@@ -25982,11 +26074,11 @@ async function resolveFetchTarget(accountDir, relPath, ownerId) {
|
|
|
25982
26074
|
} catch {
|
|
25983
26075
|
return { ok: false, reason: "enoent" };
|
|
25984
26076
|
}
|
|
25985
|
-
if (absolute === root || !absolute.startsWith(root +
|
|
26077
|
+
if (absolute === root || !absolute.startsWith(root + sep10)) return { ok: false, reason: "not-exposed" };
|
|
25986
26078
|
const rel = absolute.slice(root.length + 1);
|
|
25987
|
-
const top = rel.split(
|
|
26079
|
+
const top = rel.split(sep10)[0];
|
|
25988
26080
|
if (ownerId) {
|
|
25989
|
-
const own = `uploads${
|
|
26081
|
+
const own = `uploads${sep10}${ownerId}${sep10}`;
|
|
25990
26082
|
if (!rel.startsWith(own)) return { ok: false, reason: "not-exposed" };
|
|
25991
26083
|
} else if (!exposed.includes(top)) {
|
|
25992
26084
|
return { ok: false, reason: "not-exposed" };
|
|
@@ -26022,7 +26114,7 @@ async function handle(c, headOnly) {
|
|
|
26022
26114
|
return c.json({ ok: false, error: "denied" }, 401);
|
|
26023
26115
|
}
|
|
26024
26116
|
const target = await resolveFetchTarget(
|
|
26025
|
-
|
|
26117
|
+
resolve36(DATA_ROOT, "accounts", accountId),
|
|
26026
26118
|
relPath,
|
|
26027
26119
|
owner || void 0
|
|
26028
26120
|
);
|
|
@@ -26049,9 +26141,9 @@ async function handle(c, headOnly) {
|
|
|
26049
26141
|
}
|
|
26050
26142
|
});
|
|
26051
26143
|
}
|
|
26052
|
-
|
|
26053
|
-
|
|
26054
|
-
var portal_fetch_default =
|
|
26144
|
+
app66.get("/fetch", (c) => handle(c, false));
|
|
26145
|
+
app66.on("HEAD", "/fetch", (c) => handle(c, true));
|
|
26146
|
+
var portal_fetch_default = app66;
|
|
26055
26147
|
|
|
26056
26148
|
// app/lib/timeentry-census.ts
|
|
26057
26149
|
var TAG48 = "[timeentry-census]";
|
|
@@ -26136,7 +26228,7 @@ function startTimeEntryCensus(openSession, opts = {}) {
|
|
|
26136
26228
|
}
|
|
26137
26229
|
|
|
26138
26230
|
// app/lib/ledger-census.ts
|
|
26139
|
-
import { readdirSync as readdirSync26, readFileSync as readFileSync43, statSync as
|
|
26231
|
+
import { readdirSync as readdirSync26, readFileSync as readFileSync43, statSync as statSync18 } from "fs";
|
|
26140
26232
|
import { join as join45 } from "path";
|
|
26141
26233
|
|
|
26142
26234
|
// ../lib/ledger-core/dist/reconcile.js
|
|
@@ -26193,7 +26285,7 @@ function countWriteRejects24h(logDir, now) {
|
|
|
26193
26285
|
for (const name of entries) {
|
|
26194
26286
|
const path3 = join45(logDir, name);
|
|
26195
26287
|
try {
|
|
26196
|
-
if (now -
|
|
26288
|
+
if (now - statSync18(path3).mtimeMs > DAY_MS) continue;
|
|
26197
26289
|
for (const line of readFileSync43(path3, "utf8").split("\n")) {
|
|
26198
26290
|
if (line.includes("[graph-write] reject")) total += 1;
|
|
26199
26291
|
}
|
|
@@ -26463,13 +26555,13 @@ function startGraphHealthTimer() {
|
|
|
26463
26555
|
|
|
26464
26556
|
// app/lib/file-watcher.ts
|
|
26465
26557
|
import * as fsp2 from "fs/promises";
|
|
26466
|
-
import { resolve as
|
|
26558
|
+
import { resolve as resolve37, sep as sep11 } from "path";
|
|
26467
26559
|
var ACCOUNT_UUID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
26468
26560
|
var DEFAULT_COALESCE_MS = 500;
|
|
26469
26561
|
var ROOTS = ["accounts"];
|
|
26470
26562
|
function _routeEvent(rootName, filename) {
|
|
26471
26563
|
if (!filename) return null;
|
|
26472
|
-
const segs = filename.split(
|
|
26564
|
+
const segs = filename.split(sep11).filter(Boolean);
|
|
26473
26565
|
if (segs.length < 2) return null;
|
|
26474
26566
|
const accountId = segs[0];
|
|
26475
26567
|
if (!ACCOUNT_UUID_RE4.test(accountId)) return null;
|
|
@@ -26482,7 +26574,7 @@ async function startFileWatcher(opts = {}) {
|
|
|
26482
26574
|
const dropFn = opts.drop ?? dropFileIndex;
|
|
26483
26575
|
for (const r of ROOTS) {
|
|
26484
26576
|
try {
|
|
26485
|
-
await fsp2.mkdir(
|
|
26577
|
+
await fsp2.mkdir(resolve37(dataRoot, r), { recursive: true });
|
|
26486
26578
|
} catch (err) {
|
|
26487
26579
|
console.error(
|
|
26488
26580
|
`[file-watcher] start-failed root="${r}" err="${err.message}" \u2014 index will be maintained by the 5-min reconcile backstop only`
|
|
@@ -26503,7 +26595,7 @@ async function startFileWatcher(opts = {}) {
|
|
|
26503
26595
|
timers.set(relativePath, t);
|
|
26504
26596
|
}
|
|
26505
26597
|
async function runHook(relativePath, accountId) {
|
|
26506
|
-
const absolute =
|
|
26598
|
+
const absolute = resolve37(dataRoot, relativePath);
|
|
26507
26599
|
let exists = false;
|
|
26508
26600
|
try {
|
|
26509
26601
|
const st = await fsp2.stat(absolute);
|
|
@@ -26527,7 +26619,7 @@ async function startFileWatcher(opts = {}) {
|
|
|
26527
26619
|
}
|
|
26528
26620
|
}
|
|
26529
26621
|
async function watchRoot(rootName) {
|
|
26530
|
-
const absRoot =
|
|
26622
|
+
const absRoot = resolve37(dataRoot, rootName);
|
|
26531
26623
|
try {
|
|
26532
26624
|
const iter = fsp2.watch(absRoot, { recursive: true, signal: controller.signal });
|
|
26533
26625
|
for await (const event of iter) {
|
|
@@ -26566,7 +26658,7 @@ async function startFileWatcher(opts = {}) {
|
|
|
26566
26658
|
|
|
26567
26659
|
// app/lib/migrate-uploads.ts
|
|
26568
26660
|
import { mkdir as mkdir6, readdir as readdir6, rename as rename3, rm as rm3 } from "fs/promises";
|
|
26569
|
-
import { dirname as
|
|
26661
|
+
import { dirname as dirname15, relative as relative7, resolve as resolve38 } from "path";
|
|
26570
26662
|
var ACCOUNT_UUID_RE5 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
26571
26663
|
async function walkFiles(dir) {
|
|
26572
26664
|
const out = [];
|
|
@@ -26577,7 +26669,7 @@ async function walkFiles(dir) {
|
|
|
26577
26669
|
return out;
|
|
26578
26670
|
}
|
|
26579
26671
|
for (const e of entries) {
|
|
26580
|
-
const abs =
|
|
26672
|
+
const abs = resolve38(dir, e.name);
|
|
26581
26673
|
if (e.isDirectory()) {
|
|
26582
26674
|
out.push(...await walkFiles(abs));
|
|
26583
26675
|
} else if (e.isFile()) {
|
|
@@ -26597,8 +26689,8 @@ async function relocateTree(srcDir, destDir, dataRoot, accountId, session) {
|
|
|
26597
26689
|
let moved = 0;
|
|
26598
26690
|
for (const oldAbs of files) {
|
|
26599
26691
|
const suffix = relative7(srcDir, oldAbs);
|
|
26600
|
-
const newAbs =
|
|
26601
|
-
await mkdir6(
|
|
26692
|
+
const newAbs = resolve38(destDir, suffix);
|
|
26693
|
+
await mkdir6(dirname15(newAbs), { recursive: true });
|
|
26602
26694
|
await rename3(oldAbs, newAbs);
|
|
26603
26695
|
moved++;
|
|
26604
26696
|
const oldRel = relative7(dataRoot, oldAbs);
|
|
@@ -26624,7 +26716,7 @@ async function relocateTree(srcDir, destDir, dataRoot, accountId, session) {
|
|
|
26624
26716
|
}
|
|
26625
26717
|
async function migrateUploads(opts = {}) {
|
|
26626
26718
|
const dataRoot = opts.dataRoot ?? DATA_ROOT;
|
|
26627
|
-
const oldRoot =
|
|
26719
|
+
const oldRoot = resolve38(dataRoot, "uploads");
|
|
26628
26720
|
let topEntries;
|
|
26629
26721
|
try {
|
|
26630
26722
|
topEntries = await readdir6(oldRoot, { withFileTypes: true });
|
|
@@ -26645,8 +26737,8 @@ async function migrateUploads(opts = {}) {
|
|
|
26645
26737
|
const name = entry.name;
|
|
26646
26738
|
if (ACCOUNT_UUID_RE5.test(name)) {
|
|
26647
26739
|
moved += await relocateTree(
|
|
26648
|
-
|
|
26649
|
-
|
|
26740
|
+
resolve38(oldRoot, name),
|
|
26741
|
+
resolve38(dataRoot, "accounts", name, "uploads"),
|
|
26650
26742
|
dataRoot,
|
|
26651
26743
|
name,
|
|
26652
26744
|
session
|
|
@@ -26658,8 +26750,8 @@ async function migrateUploads(opts = {}) {
|
|
|
26658
26750
|
continue;
|
|
26659
26751
|
}
|
|
26660
26752
|
moved += await relocateTree(
|
|
26661
|
-
|
|
26662
|
-
|
|
26753
|
+
resolve38(oldRoot, "public"),
|
|
26754
|
+
resolve38(dataRoot, "accounts", installAccountId, "uploads", "public"),
|
|
26663
26755
|
dataRoot,
|
|
26664
26756
|
null,
|
|
26665
26757
|
// public uploads carry no graph nodes
|
|
@@ -26688,8 +26780,8 @@ async function migrateUploads(opts = {}) {
|
|
|
26688
26780
|
}
|
|
26689
26781
|
|
|
26690
26782
|
// app/lib/migrate-admin-webchat-sidecars.ts
|
|
26691
|
-
import { readdir as readdir7, readFile as
|
|
26692
|
-
import { existsSync as
|
|
26783
|
+
import { readdir as readdir7, readFile as readFile10, rename as rename4, writeFile as writeFile5, unlink as unlink4 } from "fs/promises";
|
|
26784
|
+
import { existsSync as existsSync42 } from "fs";
|
|
26693
26785
|
import { join as join46 } from "path";
|
|
26694
26786
|
var ADMIN_ROLE2 = "admin";
|
|
26695
26787
|
var WEBCHAT_CHANNEL2 = "webchat";
|
|
@@ -26701,7 +26793,7 @@ var defaultResolveName = async (_accountId, userId) => {
|
|
|
26701
26793
|
async function readRaw3(path3) {
|
|
26702
26794
|
let raw;
|
|
26703
26795
|
try {
|
|
26704
|
-
raw = await
|
|
26796
|
+
raw = await readFile10(path3, "utf8");
|
|
26705
26797
|
} catch {
|
|
26706
26798
|
return null;
|
|
26707
26799
|
}
|
|
@@ -26719,7 +26811,7 @@ async function writeRaw(path3, obj) {
|
|
|
26719
26811
|
await rename4(tmp, path3);
|
|
26720
26812
|
} catch (err) {
|
|
26721
26813
|
try {
|
|
26722
|
-
if (
|
|
26814
|
+
if (existsSync42(tmp)) await unlink4(tmp);
|
|
26723
26815
|
} catch {
|
|
26724
26816
|
}
|
|
26725
26817
|
throw err;
|
|
@@ -27108,8 +27200,8 @@ var streamSSE = (c, cb, onError) => {
|
|
|
27108
27200
|
|
|
27109
27201
|
// app/lib/whatsapp/gateway/routes.ts
|
|
27110
27202
|
function createWaChannelRoutes(deps) {
|
|
27111
|
-
const
|
|
27112
|
-
|
|
27203
|
+
const app68 = new Hono();
|
|
27204
|
+
app68.get("/wa-channel/inbound", (c) => {
|
|
27113
27205
|
const senderId = c.req.query("senderId");
|
|
27114
27206
|
if (!senderId) return c.json({ error: "senderId required" }, 400);
|
|
27115
27207
|
return streamSSE(c, async (stream2) => {
|
|
@@ -27127,7 +27219,7 @@ function createWaChannelRoutes(deps) {
|
|
|
27127
27219
|
}
|
|
27128
27220
|
});
|
|
27129
27221
|
});
|
|
27130
|
-
|
|
27222
|
+
app68.post("/wa-channel/reply", async (c) => {
|
|
27131
27223
|
const body = await c.req.json().catch(() => null);
|
|
27132
27224
|
const senderId = body?.senderId;
|
|
27133
27225
|
const text = body?.text;
|
|
@@ -27148,7 +27240,7 @@ function createWaChannelRoutes(deps) {
|
|
|
27148
27240
|
console.error(`[whatsapp-native] op=reply-dispatch senderId=${senderId} bytes=${bytes}`);
|
|
27149
27241
|
return c.json({ ok: true });
|
|
27150
27242
|
});
|
|
27151
|
-
|
|
27243
|
+
app68.post("/wa-channel/reply-document", async (c) => {
|
|
27152
27244
|
const body = await c.req.json().catch(() => null);
|
|
27153
27245
|
const senderId = body?.senderId;
|
|
27154
27246
|
const files = body?.files;
|
|
@@ -27187,7 +27279,7 @@ function createWaChannelRoutes(deps) {
|
|
|
27187
27279
|
}
|
|
27188
27280
|
return c.json({ ok: true, results });
|
|
27189
27281
|
});
|
|
27190
|
-
|
|
27282
|
+
app68.post("/wa-channel/ready", async (c) => {
|
|
27191
27283
|
const body = await c.req.json().catch(() => null);
|
|
27192
27284
|
const senderId = body?.senderId;
|
|
27193
27285
|
if (typeof senderId !== "string") {
|
|
@@ -27196,7 +27288,7 @@ function createWaChannelRoutes(deps) {
|
|
|
27196
27288
|
deps.onReady?.(senderId);
|
|
27197
27289
|
return c.json({ ok: true });
|
|
27198
27290
|
});
|
|
27199
|
-
|
|
27291
|
+
app68.post("/wa-channel/received", async (c) => {
|
|
27200
27292
|
const body = await c.req.json().catch(() => null);
|
|
27201
27293
|
const senderId = body?.senderId;
|
|
27202
27294
|
const waMessageId = body?.waMessageId;
|
|
@@ -27206,7 +27298,7 @@ function createWaChannelRoutes(deps) {
|
|
|
27206
27298
|
deps.onReceived?.(senderId, waMessageId);
|
|
27207
27299
|
return c.json({ ok: true });
|
|
27208
27300
|
});
|
|
27209
|
-
|
|
27301
|
+
app68.post("/wa-channel/turn-end", async (c) => {
|
|
27210
27302
|
const body = await c.req.json().catch(() => null);
|
|
27211
27303
|
const senderId = body?.senderId;
|
|
27212
27304
|
const sessionId = body?.sessionId;
|
|
@@ -27239,7 +27331,7 @@ function createWaChannelRoutes(deps) {
|
|
|
27239
27331
|
console.error(`[whatsapp-native] op=turn-end sessionId=${sid} replied=no delivered=none`);
|
|
27240
27332
|
return c.json({ ok: true, delivered: "none" });
|
|
27241
27333
|
});
|
|
27242
|
-
return
|
|
27334
|
+
return app68;
|
|
27243
27335
|
}
|
|
27244
27336
|
|
|
27245
27337
|
// app/lib/whatsapp/gateway/wa-gateway.ts
|
|
@@ -27654,8 +27746,8 @@ var InboundHub2 = class {
|
|
|
27654
27746
|
|
|
27655
27747
|
// app/lib/webchat/gateway/routes.ts
|
|
27656
27748
|
function createWebchatChannelRoutes(deps) {
|
|
27657
|
-
const
|
|
27658
|
-
|
|
27749
|
+
const app68 = new Hono();
|
|
27750
|
+
app68.get("/webchat-channel/inbound", (c) => {
|
|
27659
27751
|
const key = c.req.query("key");
|
|
27660
27752
|
if (!key) return c.json({ error: "key required" }, 400);
|
|
27661
27753
|
return streamSSE(c, async (stream2) => {
|
|
@@ -27673,7 +27765,7 @@ function createWebchatChannelRoutes(deps) {
|
|
|
27673
27765
|
}
|
|
27674
27766
|
});
|
|
27675
27767
|
});
|
|
27676
|
-
|
|
27768
|
+
app68.post("/webchat-channel/reply", async (c) => {
|
|
27677
27769
|
const body = await c.req.json().catch(() => null);
|
|
27678
27770
|
const key = body?.key;
|
|
27679
27771
|
const text = body?.text;
|
|
@@ -27683,7 +27775,7 @@ function createWebchatChannelRoutes(deps) {
|
|
|
27683
27775
|
deps.onReply?.(key, text);
|
|
27684
27776
|
return c.json({ ok: true });
|
|
27685
27777
|
});
|
|
27686
|
-
|
|
27778
|
+
app68.post("/webchat-channel/connector-auth", async (c) => {
|
|
27687
27779
|
const body = await c.req.json().catch(() => null);
|
|
27688
27780
|
const key = body?.key;
|
|
27689
27781
|
const sessionId = body?.sessionId;
|
|
@@ -27696,7 +27788,7 @@ function createWebchatChannelRoutes(deps) {
|
|
|
27696
27788
|
const result = await deps.onConnectorAuth({ key, sessionId, name, completed });
|
|
27697
27789
|
return c.json(result);
|
|
27698
27790
|
});
|
|
27699
|
-
|
|
27791
|
+
app68.post("/webchat-channel/ready", async (c) => {
|
|
27700
27792
|
const body = await c.req.json().catch(() => null);
|
|
27701
27793
|
const key = body?.key;
|
|
27702
27794
|
if (typeof key !== "string") {
|
|
@@ -27705,7 +27797,7 @@ function createWebchatChannelRoutes(deps) {
|
|
|
27705
27797
|
deps.onReady?.(key);
|
|
27706
27798
|
return c.json({ ok: true });
|
|
27707
27799
|
});
|
|
27708
|
-
|
|
27800
|
+
app68.post("/webchat-channel/permission-request", async (c) => {
|
|
27709
27801
|
const body = await c.req.json().catch(() => null);
|
|
27710
27802
|
const key = body?.key;
|
|
27711
27803
|
const requestId = body?.request_id;
|
|
@@ -27719,7 +27811,7 @@ function createWebchatChannelRoutes(deps) {
|
|
|
27719
27811
|
const verdict = await deps.awaitPermissionVerdict({ key, requestId, toolName, description, inputPreview });
|
|
27720
27812
|
return c.json(verdict);
|
|
27721
27813
|
});
|
|
27722
|
-
|
|
27814
|
+
app68.post("/webchat-channel/received", async (c) => {
|
|
27723
27815
|
const body = await c.req.json().catch(() => null);
|
|
27724
27816
|
const key = body?.key;
|
|
27725
27817
|
const messageId = body?.messageId;
|
|
@@ -27729,7 +27821,7 @@ function createWebchatChannelRoutes(deps) {
|
|
|
27729
27821
|
deps.onReceived?.(key, messageId);
|
|
27730
27822
|
return c.json({ ok: true });
|
|
27731
27823
|
});
|
|
27732
|
-
|
|
27824
|
+
app68.post("/webchat-channel/turn-end", async (c) => {
|
|
27733
27825
|
const body = await c.req.json().catch(() => null);
|
|
27734
27826
|
const key = body?.key;
|
|
27735
27827
|
const sessionId = body?.sessionId;
|
|
@@ -27743,7 +27835,7 @@ function createWebchatChannelRoutes(deps) {
|
|
|
27743
27835
|
console.error(`[webchat-native] op=turn-end channel=webchat key=${k} sessionId=${sid} replied=${replied ? "yes" : "no"} trailing=${finalBytes}`);
|
|
27744
27836
|
return c.json({ ok: true });
|
|
27745
27837
|
});
|
|
27746
|
-
return
|
|
27838
|
+
return app68;
|
|
27747
27839
|
}
|
|
27748
27840
|
|
|
27749
27841
|
// app/lib/webchat/gateway/webchat-gateway.ts
|
|
@@ -27801,16 +27893,16 @@ var WebchatGateway = class _WebchatGateway {
|
|
|
27801
27893
|
* The public /api/chat route awaits this to return the reply on the same SSE
|
|
27802
27894
|
* response, preserving the pre-756 POST→single-blob browser contract. */
|
|
27803
27895
|
awaitReply(key, timeoutMs) {
|
|
27804
|
-
return new Promise((
|
|
27896
|
+
return new Promise((resolve44) => {
|
|
27805
27897
|
const timer = setTimeout(() => {
|
|
27806
27898
|
this.replyAwaiters.delete(key);
|
|
27807
|
-
|
|
27899
|
+
resolve44({ timeout: true });
|
|
27808
27900
|
}, timeoutMs);
|
|
27809
27901
|
if (timer.unref) timer.unref();
|
|
27810
27902
|
this.replyAwaiters.set(key, (r) => {
|
|
27811
27903
|
clearTimeout(timer);
|
|
27812
27904
|
this.replyAwaiters.delete(key);
|
|
27813
|
-
|
|
27905
|
+
resolve44(r);
|
|
27814
27906
|
});
|
|
27815
27907
|
});
|
|
27816
27908
|
}
|
|
@@ -27821,11 +27913,11 @@ var WebchatGateway = class _WebchatGateway {
|
|
|
27821
27913
|
* terminal dialog stays answerable). */
|
|
27822
27914
|
awaitPermissionVerdict(p, timeoutMs) {
|
|
27823
27915
|
const k = _WebchatGateway.promptKey(p.key, p.requestId);
|
|
27824
|
-
return new Promise((
|
|
27916
|
+
return new Promise((resolve44) => {
|
|
27825
27917
|
this.pendingPrompts.get(k)?.resolve({ timeout: true });
|
|
27826
27918
|
const timer = setTimeout(() => {
|
|
27827
27919
|
this.pendingPrompts.delete(k);
|
|
27828
|
-
|
|
27920
|
+
resolve44({ timeout: true });
|
|
27829
27921
|
}, timeoutMs);
|
|
27830
27922
|
if (timer.unref) timer.unref();
|
|
27831
27923
|
this.pendingPrompts.set(k, {
|
|
@@ -27834,7 +27926,7 @@ var WebchatGateway = class _WebchatGateway {
|
|
|
27834
27926
|
resolve: (r) => {
|
|
27835
27927
|
clearTimeout(timer);
|
|
27836
27928
|
this.pendingPrompts.delete(k);
|
|
27837
|
-
|
|
27929
|
+
resolve44(r);
|
|
27838
27930
|
}
|
|
27839
27931
|
});
|
|
27840
27932
|
console.error(`[webchat:perm] op=open key=${keyDisplay(p.key)} id=${p.requestId} tool=${p.toolName}`);
|
|
@@ -28398,8 +28490,8 @@ async function fanOut(subscribers, text, onError, tag) {
|
|
|
28398
28490
|
}
|
|
28399
28491
|
|
|
28400
28492
|
// app/lib/webchat/file-delivery.ts
|
|
28401
|
-
import { realpathSync as
|
|
28402
|
-
import { resolve as
|
|
28493
|
+
import { realpathSync as realpathSync9 } from "fs";
|
|
28494
|
+
import { resolve as resolve39 } from "path";
|
|
28403
28495
|
|
|
28404
28496
|
// app/lib/channel-pty-bridge/file-delivery.ts
|
|
28405
28497
|
var SEND_USER_FILE = "SendUserFile";
|
|
@@ -28500,10 +28592,10 @@ function makeWebchatSendFile(entry) {
|
|
|
28500
28592
|
console.error(`${TAG51} file-delivery reject reason=no-account sender=${entry.senderId}`);
|
|
28501
28593
|
return { ok: false, error: "no-account" };
|
|
28502
28594
|
}
|
|
28503
|
-
const accountDir =
|
|
28595
|
+
const accountDir = resolve39(platformRoot2(), "..", "data/accounts", entry.accountId);
|
|
28504
28596
|
try {
|
|
28505
|
-
const resolved =
|
|
28506
|
-
const accountResolved =
|
|
28597
|
+
const resolved = realpathSync9(filePath);
|
|
28598
|
+
const accountResolved = realpathSync9(accountDir);
|
|
28507
28599
|
if (!resolved.startsWith(accountResolved + "/")) {
|
|
28508
28600
|
console.error(`${TAG51} file-delivery reject reason=outside_account_directory sender=${entry.senderId}`);
|
|
28509
28601
|
return { ok: false, error: "outside-account" };
|
|
@@ -28827,8 +28919,8 @@ var InboundHub3 = class {
|
|
|
28827
28919
|
|
|
28828
28920
|
// app/lib/telegram/gateway/routes.ts
|
|
28829
28921
|
function createTelegramChannelRoutes(deps) {
|
|
28830
|
-
const
|
|
28831
|
-
|
|
28922
|
+
const app68 = new Hono();
|
|
28923
|
+
app68.get("/tg-channel/inbound", (c) => {
|
|
28832
28924
|
const key = c.req.query("key");
|
|
28833
28925
|
if (!key) return c.json({ error: "key required" }, 400);
|
|
28834
28926
|
return streamSSE(c, async (stream2) => {
|
|
@@ -28846,7 +28938,7 @@ function createTelegramChannelRoutes(deps) {
|
|
|
28846
28938
|
}
|
|
28847
28939
|
});
|
|
28848
28940
|
});
|
|
28849
|
-
|
|
28941
|
+
app68.post("/tg-channel/reply", async (c) => {
|
|
28850
28942
|
const body = await c.req.json().catch(() => null);
|
|
28851
28943
|
const key = body?.key;
|
|
28852
28944
|
const text = body?.text;
|
|
@@ -28862,7 +28954,7 @@ function createTelegramChannelRoutes(deps) {
|
|
|
28862
28954
|
console.error(`[telegram-native] op=reply key=${key} bytes=${Buffer.byteLength(text, "utf8")}`);
|
|
28863
28955
|
return c.json({ ok: true });
|
|
28864
28956
|
});
|
|
28865
|
-
|
|
28957
|
+
app68.post("/tg-channel/ready", async (c) => {
|
|
28866
28958
|
const body = await c.req.json().catch(() => null);
|
|
28867
28959
|
const key = body?.key;
|
|
28868
28960
|
if (typeof key !== "string") {
|
|
@@ -28871,7 +28963,7 @@ function createTelegramChannelRoutes(deps) {
|
|
|
28871
28963
|
deps.onReady?.(key);
|
|
28872
28964
|
return c.json({ ok: true });
|
|
28873
28965
|
});
|
|
28874
|
-
|
|
28966
|
+
app68.post("/tg-channel/received", async (c) => {
|
|
28875
28967
|
const body = await c.req.json().catch(() => null);
|
|
28876
28968
|
const key = body?.key;
|
|
28877
28969
|
const messageId = body?.messageId;
|
|
@@ -28881,7 +28973,7 @@ function createTelegramChannelRoutes(deps) {
|
|
|
28881
28973
|
deps.onReceived?.(key, messageId);
|
|
28882
28974
|
return c.json({ ok: true });
|
|
28883
28975
|
});
|
|
28884
|
-
|
|
28976
|
+
app68.post("/tg-channel/turn-end", async (c) => {
|
|
28885
28977
|
const body = await c.req.json().catch(() => null);
|
|
28886
28978
|
const key = body?.key;
|
|
28887
28979
|
const sessionId = body?.sessionId;
|
|
@@ -28914,7 +29006,7 @@ function createTelegramChannelRoutes(deps) {
|
|
|
28914
29006
|
console.error(`[telegram-native] op=turn-end key=${key} sessionId=${sid} replied=no delivered=none`);
|
|
28915
29007
|
return c.json({ ok: true, delivered: "none" });
|
|
28916
29008
|
});
|
|
28917
|
-
return
|
|
29009
|
+
return app68;
|
|
28918
29010
|
}
|
|
28919
29011
|
|
|
28920
29012
|
// app/lib/telegram/gateway/telegram-gateway.ts
|
|
@@ -29062,9 +29154,9 @@ function buildTelegramSpawnRequest(input) {
|
|
|
29062
29154
|
}
|
|
29063
29155
|
|
|
29064
29156
|
// app/lib/telegram/outbound/send-document.ts
|
|
29065
|
-
import { realpathSync as
|
|
29066
|
-
import { readFile as
|
|
29067
|
-
import { resolve as
|
|
29157
|
+
import { realpathSync as realpathSync10 } from "fs";
|
|
29158
|
+
import { readFile as readFile11, stat as stat10 } from "fs/promises";
|
|
29159
|
+
import { resolve as resolve40, basename as basename13 } from "path";
|
|
29068
29160
|
var TAG53 = "[telegram:outbound]";
|
|
29069
29161
|
var TELEGRAM_DOCUMENT_MAX_BYTES = 50 * 1024 * 1024;
|
|
29070
29162
|
async function sendTelegramDocument(input) {
|
|
@@ -29075,10 +29167,10 @@ async function sendTelegramDocument(input) {
|
|
|
29075
29167
|
if (!maxyAccountId || !platformRoot5) {
|
|
29076
29168
|
return { ok: false, status: 400, error: "Cannot validate file path: missing account or platform context" };
|
|
29077
29169
|
}
|
|
29078
|
-
const accountDir =
|
|
29170
|
+
const accountDir = resolve40(platformRoot5, "..", "data/accounts", maxyAccountId);
|
|
29079
29171
|
let accountResolved;
|
|
29080
29172
|
try {
|
|
29081
|
-
accountResolved =
|
|
29173
|
+
accountResolved = realpathSync10(accountDir);
|
|
29082
29174
|
} catch (err) {
|
|
29083
29175
|
const code = err.code;
|
|
29084
29176
|
if (code === "ENOENT") {
|
|
@@ -29090,7 +29182,7 @@ async function sendTelegramDocument(input) {
|
|
|
29090
29182
|
}
|
|
29091
29183
|
let resolvedPath;
|
|
29092
29184
|
try {
|
|
29093
|
-
resolvedPath =
|
|
29185
|
+
resolvedPath = realpathSync10(filePath);
|
|
29094
29186
|
} catch (err) {
|
|
29095
29187
|
const code = err.code;
|
|
29096
29188
|
if (code === "ENOENT") {
|
|
@@ -29112,8 +29204,8 @@ async function sendTelegramDocument(input) {
|
|
|
29112
29204
|
error: `File exceeds 50 MB limit (${(fileStat.size / 1024 / 1024).toFixed(1)} MB)`
|
|
29113
29205
|
};
|
|
29114
29206
|
}
|
|
29115
|
-
const filename =
|
|
29116
|
-
const buffer = Buffer.from(await
|
|
29207
|
+
const filename = basename13(resolvedPath);
|
|
29208
|
+
const buffer = Buffer.from(await readFile11(resolvedPath));
|
|
29117
29209
|
const form = new FormData();
|
|
29118
29210
|
form.append("chat_id", String(chatId));
|
|
29119
29211
|
if (caption) form.append("caption", caption);
|
|
@@ -29467,12 +29559,12 @@ function warnOnChannelAdminBindingDrift() {
|
|
|
29467
29559
|
}
|
|
29468
29560
|
|
|
29469
29561
|
// server/lib/booking-site-accounts.ts
|
|
29470
|
-
import { existsSync as
|
|
29471
|
-
import { resolve as
|
|
29562
|
+
import { existsSync as existsSync43, readFileSync as readFileSync44 } from "fs";
|
|
29563
|
+
import { resolve as resolve41 } from "path";
|
|
29472
29564
|
function listBookingSiteAccounts(accounts) {
|
|
29473
29565
|
return accounts.filter((a) => {
|
|
29474
|
-
const availPath =
|
|
29475
|
-
if (!
|
|
29566
|
+
const availPath = resolve41(a.accountDir, "calendar-availability.json");
|
|
29567
|
+
if (!existsSync43(availPath)) return false;
|
|
29476
29568
|
try {
|
|
29477
29569
|
const cfg = JSON.parse(readFileSync44(availPath, "utf-8"));
|
|
29478
29570
|
return typeof cfg.bookingDbName === "string" && cfg.bookingDbName.length > 0;
|
|
@@ -29512,8 +29604,8 @@ function broadcastAdminShutdown(reason) {
|
|
|
29512
29604
|
|
|
29513
29605
|
// ../lib/entitlement/src/index.ts
|
|
29514
29606
|
import { createPublicKey, createHash as createHash6, verify as cryptoVerify } from "crypto";
|
|
29515
|
-
import { existsSync as
|
|
29516
|
-
import { resolve as
|
|
29607
|
+
import { existsSync as existsSync44, readFileSync as readFileSync45, statSync as statSync19 } from "fs";
|
|
29608
|
+
import { resolve as resolve42 } from "path";
|
|
29517
29609
|
|
|
29518
29610
|
// ../lib/entitlement/src/canonicalize.ts
|
|
29519
29611
|
function canonicalize(value) {
|
|
@@ -29548,7 +29640,7 @@ var PUBKEY_SHA256 = "8eee6bcb33545fd13b16d3199a5735ca5db5062834c7b49dfe4f23801d9
|
|
|
29548
29640
|
var GRACE_DAYS = 7;
|
|
29549
29641
|
var GRACE_MS = GRACE_DAYS * 24 * 60 * 60 * 1e3;
|
|
29550
29642
|
function pubkeyPath(brand) {
|
|
29551
|
-
return
|
|
29643
|
+
return resolve42(brand.platformRoot, "lib", "entitlement", "rubytech-pubkey.pem");
|
|
29552
29644
|
}
|
|
29553
29645
|
var memo = null;
|
|
29554
29646
|
function memoKey(mtimeMs, account) {
|
|
@@ -29560,11 +29652,11 @@ function resolveEntitlement(brand, account) {
|
|
|
29560
29652
|
if (brand.commercialMode !== true) {
|
|
29561
29653
|
return logResolved(implicitTrust(account), null);
|
|
29562
29654
|
}
|
|
29563
|
-
const entitlementPath =
|
|
29564
|
-
if (!
|
|
29655
|
+
const entitlementPath = resolve42(brand.configDir, "entitlement.json");
|
|
29656
|
+
if (!existsSync44(entitlementPath)) {
|
|
29565
29657
|
return logResolved(anonymousFallback("missing"), { reason: "missing" });
|
|
29566
29658
|
}
|
|
29567
|
-
const stat11 =
|
|
29659
|
+
const stat11 = statSync19(entitlementPath);
|
|
29568
29660
|
const key = memoKey(stat11.mtimeMs, account);
|
|
29569
29661
|
if (memo && memo.key === key) {
|
|
29570
29662
|
return memo.result;
|
|
@@ -29754,10 +29846,10 @@ installMediaDownloadGuard();
|
|
|
29754
29846
|
var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT || "";
|
|
29755
29847
|
var BRAND_JSON_PATH = PLATFORM_ROOT8 ? join47(PLATFORM_ROOT8, "config", "brand.json") : "";
|
|
29756
29848
|
var BRAND = { productName: "Maxy", hostname: "maxy", configDir: ".maxy", marketingUrl: "https://getmaxy.com" };
|
|
29757
|
-
if (BRAND_JSON_PATH && !
|
|
29849
|
+
if (BRAND_JSON_PATH && !existsSync45(BRAND_JSON_PATH)) {
|
|
29758
29850
|
console.error(`[brand] WARNING: brand.json not found at ${BRAND_JSON_PATH} \u2014 using Maxy defaults`);
|
|
29759
29851
|
}
|
|
29760
|
-
if (BRAND_JSON_PATH &&
|
|
29852
|
+
if (BRAND_JSON_PATH && existsSync45(BRAND_JSON_PATH)) {
|
|
29761
29853
|
try {
|
|
29762
29854
|
const parsed = JSON.parse(readFileSync46(BRAND_JSON_PATH, "utf-8"));
|
|
29763
29855
|
BRAND = { ...BRAND, ...parsed };
|
|
@@ -29794,7 +29886,7 @@ var brandLoginOpts = {
|
|
|
29794
29886
|
var ALIAS_DOMAINS_PATH = join47(homedir4(), BRAND.configDir, "alias-domains.json");
|
|
29795
29887
|
function loadAliasDomains() {
|
|
29796
29888
|
try {
|
|
29797
|
-
if (!
|
|
29889
|
+
if (!existsSync45(ALIAS_DOMAINS_PATH)) return null;
|
|
29798
29890
|
const parsed = JSON.parse(readFileSync46(ALIAS_DOMAINS_PATH, "utf-8"));
|
|
29799
29891
|
if (!Array.isArray(parsed)) {
|
|
29800
29892
|
console.error("[alias-domains] malformed alias-domains.json \u2014 expected array");
|
|
@@ -29819,7 +29911,7 @@ watchFile(ALIAS_DOMAINS_PATH, { interval: 2e3 }, () => {
|
|
|
29819
29911
|
function isPublicHost(host) {
|
|
29820
29912
|
return host.startsWith("public.") || aliasDomains.has(host);
|
|
29821
29913
|
}
|
|
29822
|
-
var
|
|
29914
|
+
var app67 = new Hono();
|
|
29823
29915
|
function resolveChannelOverride(accountId, channel, senderId) {
|
|
29824
29916
|
try {
|
|
29825
29917
|
const dir = listValidAccounts().find((a) => a.accountId === accountId)?.accountDir;
|
|
@@ -29868,7 +29960,7 @@ var waGateway = new WaGateway({
|
|
|
29868
29960
|
fetchStandingRules: fetchAccountStandingRules,
|
|
29869
29961
|
resolveSessionOverride: (accountId, senderId) => resolveChannelOverride(accountId, "whatsapp", senderId),
|
|
29870
29962
|
gatewayUrl: `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`,
|
|
29871
|
-
serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ??
|
|
29963
|
+
serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve43(process.env.MAXY_PLATFORM_ROOT ?? join47(__dirname, ".."), "services/whatsapp-channel/dist/server.js"),
|
|
29872
29964
|
// Task 751 / 1390 — file delivery on the native channel. `maxyAccountId` (the
|
|
29873
29965
|
// path-validation scope) is the sender's effective SESSION account, resolved
|
|
29874
29966
|
// once at the inbound gate and threaded here via the gateway's per-sender doc
|
|
@@ -29883,7 +29975,7 @@ var waGateway = new WaGateway({
|
|
|
29883
29975
|
caption,
|
|
29884
29976
|
accountId,
|
|
29885
29977
|
maxyAccountId,
|
|
29886
|
-
platformRoot:
|
|
29978
|
+
platformRoot: resolve43(process.env.MAXY_PLATFORM_ROOT ?? join47(__dirname, ".."))
|
|
29887
29979
|
});
|
|
29888
29980
|
return result.ok ? { ok: true, messageId: result.messageId } : { ok: false, error: result.error };
|
|
29889
29981
|
},
|
|
@@ -29995,7 +30087,7 @@ var waGateway = new WaGateway({
|
|
|
29995
30087
|
nativeFileFollowers.set(senderId, ac);
|
|
29996
30088
|
}
|
|
29997
30089
|
});
|
|
29998
|
-
|
|
30090
|
+
app67.route("/", waGateway.routes());
|
|
29999
30091
|
waGateway.startSweeper();
|
|
30000
30092
|
function runDuplicateSenderAudit() {
|
|
30001
30093
|
try {
|
|
@@ -30118,7 +30210,7 @@ var webchatGateway = new WebchatGateway({
|
|
|
30118
30210
|
firePublicSessionEndReview: (input) => firePublicSessionEndReview(input)
|
|
30119
30211
|
});
|
|
30120
30212
|
setWebchatGateway(webchatGateway);
|
|
30121
|
-
|
|
30213
|
+
app67.route("/", webchatGateway.routes());
|
|
30122
30214
|
webchatGateway.startSweeper();
|
|
30123
30215
|
webchatGateway.startPublicReaper();
|
|
30124
30216
|
var telegramFileFollowers = /* @__PURE__ */ new Map();
|
|
@@ -30162,7 +30254,7 @@ var telegramGateway = new TelegramGateway({
|
|
|
30162
30254
|
}
|
|
30163
30255
|
});
|
|
30164
30256
|
setTelegramGateway(telegramGateway);
|
|
30165
|
-
|
|
30257
|
+
app67.route("/", telegramGateway.routes());
|
|
30166
30258
|
telegramGateway.startSweeper();
|
|
30167
30259
|
var chatRoutes = createChatRoutes({
|
|
30168
30260
|
handleInbound: (input) => webchatGateway.handleInbound(input),
|
|
@@ -30196,19 +30288,19 @@ var scheduleInjectRoutes = createScheduleInjectRoutes({
|
|
|
30196
30288
|
return managed.account;
|
|
30197
30289
|
}
|
|
30198
30290
|
});
|
|
30199
|
-
|
|
30200
|
-
|
|
30291
|
+
app67.route("/api/channel/schedule-inject", scheduleInjectRoutes);
|
|
30292
|
+
app67.use("*", clientIpMiddleware);
|
|
30201
30293
|
function allowsSameOriginFraming(path3) {
|
|
30202
|
-
return path3 === "/vnc-viewer.html" || path3.startsWith("/api/admin/attachment/") || path3.startsWith("/api/public-reader/attachment/") || path3 === "/api/admin/files/download";
|
|
30294
|
+
return path3 === "/vnc-viewer.html" || path3.startsWith("/api/admin/attachment/") || path3.startsWith("/api/public-reader/attachment/") || path3 === "/api/admin/files/download" || path3 === "/api/admin/session-upload";
|
|
30203
30295
|
}
|
|
30204
|
-
|
|
30296
|
+
app67.use("*", async (c, next) => {
|
|
30205
30297
|
await next();
|
|
30206
30298
|
c.header("X-Content-Type-Options", "nosniff");
|
|
30207
30299
|
c.header("Referrer-Policy", "strict-origin-when-cross-origin");
|
|
30208
30300
|
c.header("X-Frame-Options", allowsSameOriginFraming(c.req.path) ? "SAMEORIGIN" : "DENY");
|
|
30209
30301
|
});
|
|
30210
30302
|
var HTTP_LOG_PATHS = /* @__PURE__ */ new Set(["/vnc-viewer.html", "/vnc-popout.html"]);
|
|
30211
|
-
|
|
30303
|
+
app67.use("*", async (c, next) => {
|
|
30212
30304
|
if (!HTTP_LOG_PATHS.has(c.req.path)) {
|
|
30213
30305
|
await next();
|
|
30214
30306
|
return;
|
|
@@ -30226,7 +30318,7 @@ app66.use("*", async (c, next) => {
|
|
|
30226
30318
|
});
|
|
30227
30319
|
}
|
|
30228
30320
|
});
|
|
30229
|
-
|
|
30321
|
+
app67.use("*", async (c, next) => {
|
|
30230
30322
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
30231
30323
|
if (isOperatorHost(host, getOperatorDomains()) || !isPublicHost(host)) {
|
|
30232
30324
|
await next();
|
|
@@ -30264,7 +30356,7 @@ function resolveRemoteAuthOpts(c) {
|
|
|
30264
30356
|
return { ...brandLoginOpts, origin };
|
|
30265
30357
|
}
|
|
30266
30358
|
var MAX_LOGIN_BODY = 8 * 1024;
|
|
30267
|
-
|
|
30359
|
+
app67.post("/__remote-auth/login", async (c) => {
|
|
30268
30360
|
const client = clientFrom(c);
|
|
30269
30361
|
const clientIp = client.ip || "unknown";
|
|
30270
30362
|
if (!requestIsTlsTerminated(c)) {
|
|
@@ -30309,7 +30401,7 @@ app66.post("/__remote-auth/login", async (c) => {
|
|
|
30309
30401
|
}
|
|
30310
30402
|
});
|
|
30311
30403
|
});
|
|
30312
|
-
|
|
30404
|
+
app67.get("/__remote-auth/logout", (c) => {
|
|
30313
30405
|
const client = clientFrom(c);
|
|
30314
30406
|
const clientIp = client.ip || "unknown";
|
|
30315
30407
|
console.error(`[remote-auth] logout ip=${clientIp}`);
|
|
@@ -30322,7 +30414,7 @@ app66.get("/__remote-auth/logout", (c) => {
|
|
|
30322
30414
|
}
|
|
30323
30415
|
});
|
|
30324
30416
|
});
|
|
30325
|
-
|
|
30417
|
+
app67.post("/__remote-auth/change-password", async (c) => {
|
|
30326
30418
|
const client = clientFrom(c);
|
|
30327
30419
|
const clientIp = client.ip || "unknown";
|
|
30328
30420
|
const rateLimited = checkRateLimit(client);
|
|
@@ -30381,13 +30473,13 @@ app66.post("/__remote-auth/change-password", async (c) => {
|
|
|
30381
30473
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(c), mode: "change", changeError: "Failed to save password", redirect }), 200);
|
|
30382
30474
|
}
|
|
30383
30475
|
});
|
|
30384
|
-
|
|
30476
|
+
app67.get("/__remote-auth/setup", (c) => {
|
|
30385
30477
|
if (isRemoteAuthConfigured()) {
|
|
30386
30478
|
return c.redirect("/");
|
|
30387
30479
|
}
|
|
30388
30480
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(c), mode: "setup" }), 200);
|
|
30389
30481
|
});
|
|
30390
|
-
|
|
30482
|
+
app67.post("/__remote-auth/set-initial-password", async (c) => {
|
|
30391
30483
|
if (isRemoteAuthConfigured()) {
|
|
30392
30484
|
return c.redirect("/");
|
|
30393
30485
|
}
|
|
@@ -30425,10 +30517,10 @@ app66.post("/__remote-auth/set-initial-password", async (c) => {
|
|
|
30425
30517
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(c), mode: "setup", setupError: "Failed to save password. Please try again." }), 200);
|
|
30426
30518
|
}
|
|
30427
30519
|
});
|
|
30428
|
-
|
|
30520
|
+
app67.get("/api/remote-auth/status", (c) => {
|
|
30429
30521
|
return c.json({ configured: isRemoteAuthConfigured() });
|
|
30430
30522
|
});
|
|
30431
|
-
|
|
30523
|
+
app67.post("/api/remote-auth/set-password", async (c) => {
|
|
30432
30524
|
let body;
|
|
30433
30525
|
try {
|
|
30434
30526
|
body = await c.req.json();
|
|
@@ -30467,10 +30559,10 @@ app66.post("/api/remote-auth/set-password", async (c) => {
|
|
|
30467
30559
|
return c.json({ error: "Failed to save password" }, 500);
|
|
30468
30560
|
}
|
|
30469
30561
|
});
|
|
30470
|
-
|
|
30562
|
+
app67.route("/api/_client-error", client_error_default);
|
|
30471
30563
|
console.log("[client-error-route] mounted");
|
|
30472
30564
|
var PWA_PUBLIC_PATHS = /* @__PURE__ */ new Set(["/sw.js", ...PWA_SURFACES.map((s) => s.manifestPath)]);
|
|
30473
|
-
|
|
30565
|
+
app67.use("*", async (c, next) => {
|
|
30474
30566
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
30475
30567
|
const path3 = c.req.path;
|
|
30476
30568
|
if (path3 === "/favicon.ico" || path3.startsWith("/assets/") || path3.startsWith("/brand/") || // Public free/busy is read by the booking page (a separate Cloudflare Pages
|
|
@@ -30514,28 +30606,28 @@ app66.use("*", async (c, next) => {
|
|
|
30514
30606
|
}
|
|
30515
30607
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(c), redirect: path3 }), 200);
|
|
30516
30608
|
});
|
|
30517
|
-
|
|
30518
|
-
|
|
30519
|
-
|
|
30520
|
-
|
|
30521
|
-
|
|
30522
|
-
|
|
30523
|
-
|
|
30609
|
+
app67.route("/api/health", health_default);
|
|
30610
|
+
app67.route("/api/chat", chatRoutes);
|
|
30611
|
+
app67.route("/api/whatsapp", whatsapp_default);
|
|
30612
|
+
app67.route("/api/storage", storage_broker_default);
|
|
30613
|
+
app67.route("/api/whatsapp-reader", whatsapp_reader_default);
|
|
30614
|
+
app67.route("/api/public-reader", public_reader_default);
|
|
30615
|
+
app67.route("/api/webchat", createWebchatRoutes({
|
|
30524
30616
|
handleInbound: (input) => webchatGateway.handleInbound(input),
|
|
30525
30617
|
// Task 940 — the permission relay's pointer read + verdict write.
|
|
30526
30618
|
pendingPromptFor: (key) => webchatGateway.pendingPromptFor(key),
|
|
30527
30619
|
deliveryFailureFor: (key) => webchatGateway.deliveryFailureFor(key),
|
|
30528
30620
|
resolvePermissionVerdict: (key, requestId, behavior) => webchatGateway.resolvePermissionVerdict(key, requestId, behavior)
|
|
30529
30621
|
}));
|
|
30530
|
-
|
|
30531
|
-
|
|
30532
|
-
|
|
30533
|
-
|
|
30534
|
-
|
|
30535
|
-
|
|
30536
|
-
|
|
30537
|
-
|
|
30538
|
-
|
|
30622
|
+
app67.route("/api/webchat/greeting", webchat_greeting_default);
|
|
30623
|
+
app67.route("/api/telegram", telegram_default);
|
|
30624
|
+
app67.route("/api/quickbooks", quickbooks_default);
|
|
30625
|
+
app67.route("/api/onboarding", onboarding_default);
|
|
30626
|
+
app67.route("/api/admin", admin_default);
|
|
30627
|
+
app67.route("/api/access", access_default);
|
|
30628
|
+
app67.route("/api/session", session_default2);
|
|
30629
|
+
app67.route("/api/calendar", calendar_public_default);
|
|
30630
|
+
app67.route("/api/portal", portal_fetch_default);
|
|
30539
30631
|
var SAFE_SLUG_RE2 = /^[a-z][a-z0-9-]{2,49}$/;
|
|
30540
30632
|
var SAFE_FILENAME_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
|
|
30541
30633
|
var IMAGE_MIME = {
|
|
@@ -30547,7 +30639,7 @@ var IMAGE_MIME = {
|
|
|
30547
30639
|
".svg": "image/svg+xml",
|
|
30548
30640
|
".ico": "image/x-icon"
|
|
30549
30641
|
};
|
|
30550
|
-
|
|
30642
|
+
app67.get("/agent-assets/:slug/:filename", (c) => {
|
|
30551
30643
|
const slug = c.req.param("slug");
|
|
30552
30644
|
const filename = c.req.param("filename");
|
|
30553
30645
|
if (!SAFE_SLUG_RE2.test(slug)) {
|
|
@@ -30563,13 +30655,13 @@ app66.get("/agent-assets/:slug/:filename", (c) => {
|
|
|
30563
30655
|
console.error(`[agent-assets] no-account slug=${slug} file=${filename}`);
|
|
30564
30656
|
return c.text("Not found", 404);
|
|
30565
30657
|
}
|
|
30566
|
-
const filePath =
|
|
30567
|
-
const expectedDir =
|
|
30658
|
+
const filePath = resolve43(account.accountDir, "agents", slug, "assets", filename);
|
|
30659
|
+
const expectedDir = resolve43(account.accountDir, "agents", slug, "assets");
|
|
30568
30660
|
if (!filePath.startsWith(expectedDir + "/")) {
|
|
30569
30661
|
console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
|
|
30570
30662
|
return c.text("Forbidden", 403);
|
|
30571
30663
|
}
|
|
30572
|
-
if (!
|
|
30664
|
+
if (!existsSync45(filePath)) {
|
|
30573
30665
|
console.error(`[agent-assets] serve slug=${slug} file=${filename} status=404`);
|
|
30574
30666
|
return c.text("Not found", 404);
|
|
30575
30667
|
}
|
|
@@ -30582,7 +30674,7 @@ app66.get("/agent-assets/:slug/:filename", (c) => {
|
|
|
30582
30674
|
"Cache-Control": "public, max-age=3600"
|
|
30583
30675
|
});
|
|
30584
30676
|
});
|
|
30585
|
-
|
|
30677
|
+
app67.get("/generated/:filename", (c) => {
|
|
30586
30678
|
const filename = c.req.param("filename");
|
|
30587
30679
|
if (!SAFE_FILENAME_RE.test(filename) || filename.includes("..")) {
|
|
30588
30680
|
console.error(`[generated] serve file=${filename} status=403`);
|
|
@@ -30593,13 +30685,13 @@ app66.get("/generated/:filename", (c) => {
|
|
|
30593
30685
|
console.error(`[generated] serve file=${filename} status=404`);
|
|
30594
30686
|
return c.text("Not found", 404);
|
|
30595
30687
|
}
|
|
30596
|
-
const filePath =
|
|
30597
|
-
const expectedDir =
|
|
30688
|
+
const filePath = resolve43(account.accountDir, "generated", filename);
|
|
30689
|
+
const expectedDir = resolve43(account.accountDir, "generated");
|
|
30598
30690
|
if (!filePath.startsWith(expectedDir + "/")) {
|
|
30599
30691
|
console.error(`[generated] serve file=${filename} status=403`);
|
|
30600
30692
|
return c.text("Forbidden", 403);
|
|
30601
30693
|
}
|
|
30602
|
-
if (!
|
|
30694
|
+
if (!existsSync45(filePath)) {
|
|
30603
30695
|
console.error(`[generated] serve file=${filename} status=404`);
|
|
30604
30696
|
return c.text("Not found", 404);
|
|
30605
30697
|
}
|
|
@@ -30612,14 +30704,14 @@ app66.get("/generated/:filename", (c) => {
|
|
|
30612
30704
|
"Cache-Control": "public, max-age=86400"
|
|
30613
30705
|
});
|
|
30614
30706
|
});
|
|
30615
|
-
|
|
30616
|
-
|
|
30617
|
-
|
|
30618
|
-
|
|
30707
|
+
app67.route("/sites", sites_default);
|
|
30708
|
+
app67.route("/listings", listings_default);
|
|
30709
|
+
app67.route("/v", visitor_event_default);
|
|
30710
|
+
app67.route("/v", visitor_consent_default);
|
|
30619
30711
|
var htmlCache = /* @__PURE__ */ new Map();
|
|
30620
30712
|
var brandLogoPath = "/brand/maxy-monochrome.png";
|
|
30621
30713
|
var brandIconPath = "/brand/maxy-monochrome.png";
|
|
30622
|
-
if (BRAND_JSON_PATH &&
|
|
30714
|
+
if (BRAND_JSON_PATH && existsSync45(BRAND_JSON_PATH)) {
|
|
30623
30715
|
try {
|
|
30624
30716
|
const fullBrand = JSON.parse(readFileSync46(BRAND_JSON_PATH, "utf-8"));
|
|
30625
30717
|
if (fullBrand.assets?.logo) brandLogoPath = `/brand/${fullBrand.assets.logo}`;
|
|
@@ -30648,11 +30740,11 @@ var brandScript = `<script>window.__BRAND__=${JSON.stringify({
|
|
|
30648
30740
|
var brandThemeColor = BRAND.defaultColors?.primary ?? "#000000";
|
|
30649
30741
|
var brandBackgroundColor = BRAND.defaultColors?.background ?? "#ffffff";
|
|
30650
30742
|
var brandAppIconsExist = [brandAppIcon192Path, brandAppIcon512Path, brandMaskableIconPath].every(
|
|
30651
|
-
(p) =>
|
|
30743
|
+
(p) => existsSync45(resolve43(process.cwd(), "public", p.replace(/^\//, "")))
|
|
30652
30744
|
);
|
|
30653
30745
|
var SW_SOURCE = (() => {
|
|
30654
30746
|
try {
|
|
30655
|
-
return readFileSync46(
|
|
30747
|
+
return readFileSync46(resolve43(process.cwd(), "public", "sw.js"), "utf-8");
|
|
30656
30748
|
} catch {
|
|
30657
30749
|
return null;
|
|
30658
30750
|
}
|
|
@@ -30661,7 +30753,7 @@ function readInstalledVersion() {
|
|
|
30661
30753
|
try {
|
|
30662
30754
|
if (!PLATFORM_ROOT8) return "unknown";
|
|
30663
30755
|
const versionFile = join47(PLATFORM_ROOT8, "config", `.${BRAND.hostname}-version`);
|
|
30664
|
-
if (!
|
|
30756
|
+
if (!existsSync45(versionFile)) return "unknown";
|
|
30665
30757
|
const content = readFileSync46(versionFile, "utf-8").trim();
|
|
30666
30758
|
return content || "unknown";
|
|
30667
30759
|
} catch {
|
|
@@ -30703,7 +30795,7 @@ var clientErrorReporterScript = `<script>
|
|
|
30703
30795
|
function cachedHtml(file) {
|
|
30704
30796
|
let html = htmlCache.get(file);
|
|
30705
30797
|
if (!html) {
|
|
30706
|
-
html = readFileSync46(
|
|
30798
|
+
html = readFileSync46(resolve43(process.cwd(), "public", file), "utf-8");
|
|
30707
30799
|
const productNameEsc = escapeHtml(BRAND.productName);
|
|
30708
30800
|
html = html.replace(/<title>([^<]*)<\/title>/, (_match, inner) => `<title>${escapeHtml(inner).replace(/Maxy/g, productNameEsc)}</title>`);
|
|
30709
30801
|
html = html.replace('href="/favicon.ico"', `href="${escapeHtml(brandFaviconPath)}"`);
|
|
@@ -30725,7 +30817,7 @@ function loadBrandingCache(agentSlug) {
|
|
|
30725
30817
|
const accountId = getDefaultAccountId();
|
|
30726
30818
|
if (!accountId) return null;
|
|
30727
30819
|
const cachePath = join47(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
|
|
30728
|
-
if (!
|
|
30820
|
+
if (!existsSync45(cachePath)) return null;
|
|
30729
30821
|
return JSON.parse(readFileSync46(cachePath, "utf-8"));
|
|
30730
30822
|
} catch {
|
|
30731
30823
|
return null;
|
|
@@ -30770,7 +30862,7 @@ function brandedPublicHtml(agentSlug) {
|
|
|
30770
30862
|
function agentUnavailableHtml() {
|
|
30771
30863
|
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>`;
|
|
30772
30864
|
}
|
|
30773
|
-
|
|
30865
|
+
app67.get("/", (c) => {
|
|
30774
30866
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
30775
30867
|
const klass = classifyHost(host, getOperatorDomains(), isPublicHost);
|
|
30776
30868
|
if (klass === "operator") {
|
|
@@ -30792,12 +30884,12 @@ app66.get("/", (c) => {
|
|
|
30792
30884
|
console.log(`[host-class] host=${host} class=admin served=index.html`);
|
|
30793
30885
|
return c.html(cachedHtml("index.html"));
|
|
30794
30886
|
});
|
|
30795
|
-
|
|
30887
|
+
app67.get("/public", (c) => {
|
|
30796
30888
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
30797
30889
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
30798
30890
|
return c.html(cachedHtml("public.html"));
|
|
30799
30891
|
});
|
|
30800
|
-
|
|
30892
|
+
app67.get("/public-chat", (c) => {
|
|
30801
30893
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
30802
30894
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
30803
30895
|
return c.html(cachedHtml("public.html"));
|
|
@@ -30816,12 +30908,12 @@ async function logViewerFetch(c, next) {
|
|
|
30816
30908
|
duration_ms: Date.now() - start
|
|
30817
30909
|
});
|
|
30818
30910
|
}
|
|
30819
|
-
|
|
30820
|
-
|
|
30821
|
-
|
|
30911
|
+
app67.use("/vnc-viewer.html", logViewerFetch);
|
|
30912
|
+
app67.use("/vnc-popout.html", logViewerFetch);
|
|
30913
|
+
app67.get("/vnc-popout.html", (c) => {
|
|
30822
30914
|
let html = htmlCache.get("vnc-popout.html");
|
|
30823
30915
|
if (!html) {
|
|
30824
|
-
html = readFileSync46(
|
|
30916
|
+
html = readFileSync46(resolve43(process.cwd(), "public", "vnc-popout.html"), "utf-8");
|
|
30825
30917
|
const name = escapeHtml(BRAND.productName);
|
|
30826
30918
|
html = html.replace("<title>Browser \u2014 Maxy</title>", `<title>${name}</title>`);
|
|
30827
30919
|
html = html.replace("</head>", ` ${brandScript}
|
|
@@ -30831,7 +30923,7 @@ app66.get("/vnc-popout.html", (c) => {
|
|
|
30831
30923
|
}
|
|
30832
30924
|
return c.html(html);
|
|
30833
30925
|
});
|
|
30834
|
-
|
|
30926
|
+
app67.post("/api/vnc/client-event", async (c) => {
|
|
30835
30927
|
let body;
|
|
30836
30928
|
try {
|
|
30837
30929
|
body = await c.req.json();
|
|
@@ -30852,11 +30944,11 @@ app66.post("/api/vnc/client-event", async (c) => {
|
|
|
30852
30944
|
});
|
|
30853
30945
|
return c.json({ ok: true });
|
|
30854
30946
|
});
|
|
30855
|
-
|
|
30947
|
+
app67.get("/g/:slug", (c) => {
|
|
30856
30948
|
return c.html(brandedPublicHtml(resolveDefaultSlug() ?? void 0));
|
|
30857
30949
|
});
|
|
30858
30950
|
for (const pwa of PWA_SURFACES) {
|
|
30859
|
-
|
|
30951
|
+
app67.get(pwa.manifestPath, (c) => {
|
|
30860
30952
|
const manifest = buildManifest(pwa, {
|
|
30861
30953
|
productName: BRAND.productName,
|
|
30862
30954
|
appIcon192: brandAppIcon192Path,
|
|
@@ -30872,7 +30964,7 @@ for (const pwa of PWA_SURFACES) {
|
|
|
30872
30964
|
return c.body(JSON.stringify(manifest));
|
|
30873
30965
|
});
|
|
30874
30966
|
}
|
|
30875
|
-
|
|
30967
|
+
app67.get("/sw.js", (c) => {
|
|
30876
30968
|
if (SW_SOURCE == null) {
|
|
30877
30969
|
console.error("[pwa] op=sw status=500 reason=sw-source-missing");
|
|
30878
30970
|
return c.text("Service worker unavailable", 500);
|
|
@@ -30881,12 +30973,12 @@ app66.get("/sw.js", (c) => {
|
|
|
30881
30973
|
console.log(`[pwa] op=sw status=200 ct=${SW_CONTENT_TYPE}`);
|
|
30882
30974
|
return c.body(SW_SOURCE);
|
|
30883
30975
|
});
|
|
30884
|
-
|
|
30976
|
+
app67.get("/graph", (c) => {
|
|
30885
30977
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
30886
30978
|
if (isPublicHost(host) || isOperatorHost(host, getOperatorDomains())) return c.text("Not found", 404);
|
|
30887
30979
|
return c.html(cachedHtml("graph.html"));
|
|
30888
30980
|
});
|
|
30889
|
-
|
|
30981
|
+
app67.get("/chat", (c) => {
|
|
30890
30982
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
30891
30983
|
if (isOperatorHost(host, getOperatorDomains())) {
|
|
30892
30984
|
console.log(`[host-class] host=${host} class=operator served=operator.html`);
|
|
@@ -30895,42 +30987,42 @@ app66.get("/chat", (c) => {
|
|
|
30895
30987
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
30896
30988
|
return c.html(cachedHtml("chat.html"));
|
|
30897
30989
|
});
|
|
30898
|
-
|
|
30990
|
+
app67.get("/data", (c) => {
|
|
30899
30991
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
30900
30992
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
30901
30993
|
return c.html(cachedHtml("data.html"));
|
|
30902
30994
|
});
|
|
30903
|
-
|
|
30995
|
+
app67.get("/tasks", (c) => {
|
|
30904
30996
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
30905
30997
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
30906
30998
|
return c.html(cachedHtml("tasks.html"));
|
|
30907
30999
|
});
|
|
30908
|
-
|
|
31000
|
+
app67.get("/activity", (c) => {
|
|
30909
31001
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
30910
31002
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
30911
31003
|
return c.html(cachedHtml("activity.html"));
|
|
30912
31004
|
});
|
|
30913
|
-
|
|
31005
|
+
app67.get("/calendar", (c) => {
|
|
30914
31006
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
30915
31007
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
30916
31008
|
return c.html(cachedHtml("calendar.html"));
|
|
30917
31009
|
});
|
|
30918
|
-
|
|
31010
|
+
app67.get("/routines", (c) => {
|
|
30919
31011
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
30920
31012
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
30921
31013
|
return c.html(cachedHtml("routines.html"));
|
|
30922
31014
|
});
|
|
30923
|
-
|
|
31015
|
+
app67.get("/skills", (c) => {
|
|
30924
31016
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
30925
31017
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
30926
31018
|
return c.html(cachedHtml("skills.html"));
|
|
30927
31019
|
});
|
|
30928
|
-
|
|
31020
|
+
app67.get("/browser", (c) => {
|
|
30929
31021
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
30930
31022
|
if (isPublicHost(host) || isOperatorHost(host, getOperatorDomains())) return c.text("Not found", 404);
|
|
30931
31023
|
return c.html(cachedHtml("browser.html"));
|
|
30932
31024
|
});
|
|
30933
|
-
|
|
31025
|
+
app67.get("/:slug", async (c, next) => {
|
|
30934
31026
|
const slug = c.req.param("slug");
|
|
30935
31027
|
if (AGENT_SLUG_PATTERN.test(`/${slug}`)) {
|
|
30936
31028
|
const account = resolveAccount();
|
|
@@ -30945,13 +31037,13 @@ app66.get("/:slug", async (c, next) => {
|
|
|
30945
31037
|
await next();
|
|
30946
31038
|
});
|
|
30947
31039
|
if (brandFaviconPath !== "/favicon.ico") {
|
|
30948
|
-
|
|
31040
|
+
app67.get("/favicon.ico", (c) => {
|
|
30949
31041
|
c.header("Cache-Control", "public, max-age=300");
|
|
30950
31042
|
return c.redirect(brandFaviconPath, 302);
|
|
30951
31043
|
});
|
|
30952
31044
|
}
|
|
30953
|
-
|
|
30954
|
-
|
|
31045
|
+
app67.use("/*", serveStatic({ root: "./public" }));
|
|
31046
|
+
app67.all("*", (c) => {
|
|
30955
31047
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
30956
31048
|
const path3 = c.req.path;
|
|
30957
31049
|
if (isPublicHost(host)) {
|
|
@@ -30965,13 +31057,13 @@ app66.all("*", (c) => {
|
|
|
30965
31057
|
});
|
|
30966
31058
|
var port = requirePortEnv("MAXY_UI_INTERNAL_PORT", { tag: "ui-server" });
|
|
30967
31059
|
var hostname = process.env.HOSTNAME ?? "127.0.0.1";
|
|
30968
|
-
var httpServer = serve({ fetch:
|
|
31060
|
+
var httpServer = serve({ fetch: app67.fetch, port, hostname });
|
|
30969
31061
|
console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
30970
31062
|
{
|
|
30971
31063
|
const reconcilePlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join47(__dirname, "..");
|
|
30972
|
-
const reconcileScript =
|
|
31064
|
+
const reconcileScript = resolve43(reconcilePlatformRoot, "plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js");
|
|
30973
31065
|
const runReconcile = (ctx) => {
|
|
30974
|
-
if (!
|
|
31066
|
+
if (!existsSync45(reconcileScript)) return;
|
|
30975
31067
|
try {
|
|
30976
31068
|
const child = spawn3(process.execPath, [reconcileScript], {
|
|
30977
31069
|
env: { ...process.env, PLATFORM_ROOT: reconcilePlatformRoot },
|
|
@@ -31010,14 +31102,14 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
31010
31102
|
{
|
|
31011
31103
|
const DREAM_CYCLE_SWEEP_INTERVAL_MS = 36e5;
|
|
31012
31104
|
const dreamPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join47(__dirname, "..");
|
|
31013
|
-
const dreamSweepScript =
|
|
31105
|
+
const dreamSweepScript = resolve43(dreamPlatformRoot, "plugins/memory/mcp/dist/scripts/dream-cycle-sweep.js");
|
|
31014
31106
|
registerLoop({
|
|
31015
31107
|
name: "dream-cycle-sweep",
|
|
31016
31108
|
intervalMs: DREAM_CYCLE_SWEEP_INTERVAL_MS,
|
|
31017
31109
|
firstRunDelayMs: 3e4,
|
|
31018
31110
|
detached: true,
|
|
31019
31111
|
run: (ctx) => {
|
|
31020
|
-
if (!
|
|
31112
|
+
if (!existsSync45(dreamSweepScript)) return;
|
|
31021
31113
|
try {
|
|
31022
31114
|
const child = spawn3(process.execPath, [dreamSweepScript], {
|
|
31023
31115
|
env: { ...process.env, PLATFORM_ROOT: dreamPlatformRoot },
|
|
@@ -31034,10 +31126,10 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
31034
31126
|
}
|
|
31035
31127
|
{
|
|
31036
31128
|
const outlookPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join47(__dirname, "..");
|
|
31037
|
-
const outlookScript =
|
|
31129
|
+
const outlookScript = resolve43(outlookPlatformRoot, "plugins/outlook/mcp/dist/scripts/complete-registration.js");
|
|
31038
31130
|
const OUTLOOK_COMPLETE_INTERVAL_MS = 3e4;
|
|
31039
31131
|
const runOutlookComplete = (ctx) => {
|
|
31040
|
-
if (!
|
|
31132
|
+
if (!existsSync45(outlookScript)) return;
|
|
31041
31133
|
try {
|
|
31042
31134
|
const child = spawn3(process.execPath, [outlookScript], {
|
|
31043
31135
|
env: { ...process.env, PLATFORM_ROOT: outlookPlatformRoot },
|
|
@@ -31060,19 +31152,19 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
31060
31152
|
}
|
|
31061
31153
|
{
|
|
31062
31154
|
const auditRoot = process.env.MAXY_PLATFORM_ROOT ?? join47(__dirname, "..");
|
|
31063
|
-
const strandedAccountsDir =
|
|
31155
|
+
const strandedAccountsDir = resolve43(auditRoot, "..", "data/accounts");
|
|
31064
31156
|
const STRANDED_AUDIT_INTERVAL_MS = 3e5;
|
|
31065
31157
|
const STRANDED_AGE_MS = 16 * 6e4;
|
|
31066
31158
|
const STRANDED_UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
31067
31159
|
const runStrandedAudit = () => {
|
|
31068
31160
|
try {
|
|
31069
|
-
if (!
|
|
31161
|
+
if (!existsSync45(strandedAccountsDir)) return;
|
|
31070
31162
|
const now = Date.now();
|
|
31071
31163
|
for (const name of readdirSync27(strandedAccountsDir)) {
|
|
31072
31164
|
if (!STRANDED_UUID_RE.test(name)) continue;
|
|
31073
|
-
const pendingPath2 =
|
|
31074
|
-
if (!
|
|
31075
|
-
const ageMs2 = now -
|
|
31165
|
+
const pendingPath2 = resolve43(strandedAccountsDir, name, "secrets/outlook/pending-devicecode.enc");
|
|
31166
|
+
if (!existsSync45(pendingPath2)) continue;
|
|
31167
|
+
const ageMs2 = now - statSync20(pendingPath2).mtimeMs;
|
|
31076
31168
|
if (ageMs2 > STRANDED_AGE_MS) {
|
|
31077
31169
|
console.error(`[outlook-mcp] devicecode-stranded account=${name} ageSec=${Math.floor(ageMs2 / 1e3)}`);
|
|
31078
31170
|
}
|
|
@@ -31090,7 +31182,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
31090
31182
|
}
|
|
31091
31183
|
{
|
|
31092
31184
|
const googleRoot = process.env.MAXY_PLATFORM_ROOT ?? join47(__dirname, "..");
|
|
31093
|
-
const googleAccountsDir =
|
|
31185
|
+
const googleAccountsDir = resolve43(googleRoot, "..", "data/accounts");
|
|
31094
31186
|
const GOOGLE_PENDING_AUDIT_INTERVAL_MS = 3e5;
|
|
31095
31187
|
const runGooglePendingAuditSafe = () => {
|
|
31096
31188
|
try {
|
|
@@ -31105,10 +31197,10 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
31105
31197
|
firstRunDelayMs: 27e3,
|
|
31106
31198
|
run: runGooglePendingAuditSafe
|
|
31107
31199
|
});
|
|
31108
|
-
const googleAuditScript =
|
|
31200
|
+
const googleAuditScript = resolve43(googleRoot, "plugins/google/mcp/dist/scripts/account-audit.js");
|
|
31109
31201
|
const GOOGLE_ACCOUNT_AUDIT_INTERVAL_MS = 36e5;
|
|
31110
31202
|
const runGoogleAccountAudit = (ctx) => {
|
|
31111
|
-
if (!
|
|
31203
|
+
if (!existsSync45(googleAuditScript)) return;
|
|
31112
31204
|
try {
|
|
31113
31205
|
const child = spawn3(process.execPath, [googleAuditScript], {
|
|
31114
31206
|
env: { ...process.env, PLATFORM_ROOT: googleRoot },
|
|
@@ -31180,7 +31272,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
31180
31272
|
}
|
|
31181
31273
|
{
|
|
31182
31274
|
const publishPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join47(__dirname, "..");
|
|
31183
|
-
const publishScript =
|
|
31275
|
+
const publishScript = resolve43(publishPlatformRoot, "plugins/scheduling/mcp/dist/scripts/publish-availability.js");
|
|
31184
31276
|
const PUBLISH_INTERVAL_MS = 3e5;
|
|
31185
31277
|
const bookingAccounts = () => {
|
|
31186
31278
|
try {
|
|
@@ -31191,7 +31283,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
31191
31283
|
}
|
|
31192
31284
|
};
|
|
31193
31285
|
const spawnPublish = (account, ctx) => {
|
|
31194
|
-
if (!
|
|
31286
|
+
if (!existsSync45(publishScript)) return;
|
|
31195
31287
|
try {
|
|
31196
31288
|
const child = spawn3(process.execPath, [publishScript], {
|
|
31197
31289
|
env: {
|
|
@@ -31210,19 +31302,19 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
31210
31302
|
}
|
|
31211
31303
|
};
|
|
31212
31304
|
const auditSnapshotAge = (account) => {
|
|
31213
|
-
const availPath =
|
|
31305
|
+
const availPath = resolve43(account.accountDir, "calendar-availability.json");
|
|
31214
31306
|
let hasBookingSite = false;
|
|
31215
31307
|
try {
|
|
31216
|
-
if (
|
|
31308
|
+
if (existsSync45(availPath)) {
|
|
31217
31309
|
const cfg = JSON.parse(readFileSync46(availPath, "utf-8"));
|
|
31218
31310
|
hasBookingSite = typeof cfg.bookingDbName === "string" && cfg.bookingDbName.length > 0;
|
|
31219
31311
|
}
|
|
31220
31312
|
} catch {
|
|
31221
31313
|
}
|
|
31222
31314
|
if (!hasBookingSite) return;
|
|
31223
|
-
const statePath =
|
|
31315
|
+
const statePath = resolve43(account.accountDir, "state", "booking-availability", "last-publish.json");
|
|
31224
31316
|
let lastSuccessAt = null;
|
|
31225
|
-
if (
|
|
31317
|
+
if (existsSync45(statePath)) {
|
|
31226
31318
|
try {
|
|
31227
31319
|
const rec = JSON.parse(readFileSync46(statePath, "utf-8"));
|
|
31228
31320
|
lastSuccessAt = rec.lastSuccessAt ?? null;
|
|
@@ -31257,11 +31349,11 @@ startTimeEntryCensus(() => getSession());
|
|
|
31257
31349
|
startLedgerCensus(() => getSession());
|
|
31258
31350
|
{
|
|
31259
31351
|
const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join47(__dirname, "..");
|
|
31260
|
-
const auditScript =
|
|
31352
|
+
const auditScript = resolve43(auditPlatformRoot, "plugins/connector/mcp/dist/scripts/audit-connectors.js");
|
|
31261
31353
|
const auditLogDir = process.env.LOG_DIR ?? LOG_DIR;
|
|
31262
31354
|
const CONNECTOR_AUDIT_INTERVAL_MS = 3e5;
|
|
31263
31355
|
const runConnectorAudit = (ctx) => {
|
|
31264
|
-
if (!
|
|
31356
|
+
if (!existsSync45(auditScript)) return;
|
|
31265
31357
|
try {
|
|
31266
31358
|
const child = spawn3(process.execPath, [auditScript], {
|
|
31267
31359
|
env: { ...process.env, PLATFORM_ROOT: auditPlatformRoot, LOG_DIR: auditLogDir },
|
|
@@ -31341,7 +31433,7 @@ for (const m of SUBAPP_MANIFEST) {
|
|
|
31341
31433
|
}
|
|
31342
31434
|
try {
|
|
31343
31435
|
const registered = [];
|
|
31344
|
-
for (const r of
|
|
31436
|
+
for (const r of app67.routes ?? []) {
|
|
31345
31437
|
if (typeof r.path !== "string" || r.path.includes(":") || r.path.includes("*")) continue;
|
|
31346
31438
|
if (AGENT_SLUG_PATTERN.test(r.path)) {
|
|
31347
31439
|
registered.push({ method: (r.method ?? "ALL").toUpperCase(), path: r.path });
|
|
@@ -31381,7 +31473,7 @@ try {
|
|
|
31381
31473
|
var ADMINUSER_RECONCILE_INTERVAL_MS = 60 * 60 * 1e3;
|
|
31382
31474
|
async function runAdminUserReconcileTick() {
|
|
31383
31475
|
try {
|
|
31384
|
-
if (!
|
|
31476
|
+
if (!existsSync45(USERS_FILE)) {
|
|
31385
31477
|
console.error("[adminuser-self-heal] skip reason=no-users-file");
|
|
31386
31478
|
return;
|
|
31387
31479
|
}
|
|
@@ -31432,7 +31524,7 @@ registerLoop({
|
|
|
31432
31524
|
});
|
|
31433
31525
|
var USERS_RECONCILE_INTERVAL_MS = 60 * 60 * 1e3;
|
|
31434
31526
|
function countUsersRows() {
|
|
31435
|
-
if (!
|
|
31527
|
+
if (!existsSync45(USERS_FILE)) return 0;
|
|
31436
31528
|
const raw = readFileSync46(USERS_FILE, "utf-8").trim();
|
|
31437
31529
|
if (!raw) return 0;
|
|
31438
31530
|
const users = JSON.parse(raw);
|
|
@@ -31502,7 +31594,7 @@ try {
|
|
|
31502
31594
|
} catch (err) {
|
|
31503
31595
|
console.error(`[graph-health] account-enumeration unavailable reason=${err instanceof Error ? err.message : String(err)}`);
|
|
31504
31596
|
}
|
|
31505
|
-
var configDirForWhatsApp =
|
|
31597
|
+
var configDirForWhatsApp = basename14(MAXY_DIR) || ".maxy";
|
|
31506
31598
|
var bootAccount = resolveAccount();
|
|
31507
31599
|
if (bootAccount) {
|
|
31508
31600
|
migrateRemovedConfigKeys(bootAccount.accountDir);
|
|
@@ -31566,7 +31658,7 @@ if (bootAccountConfig?.whatsapp) {
|
|
|
31566
31658
|
}
|
|
31567
31659
|
init({
|
|
31568
31660
|
configDir: configDirForWhatsApp,
|
|
31569
|
-
platformRoot:
|
|
31661
|
+
platformRoot: resolve43(process.env.MAXY_PLATFORM_ROOT ?? join47(__dirname, "..")),
|
|
31570
31662
|
accountConfig: bootAccountConfig,
|
|
31571
31663
|
onMessage: async (msg) => {
|
|
31572
31664
|
if (isObserveAccount(msg.accountId)) {
|