@rubytech/create-sitedesk-code 0.1.609 → 0.1.611
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/plugins/admin/skills/platform-architecture/SKILL.md +45 -23
- package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +9 -0
- package/payload/platform/plugins/docs/references/telegram-guide.md +44 -22
- package/payload/server/public/activity.html +6 -6
- package/payload/server/public/agents.html +5 -5
- package/payload/server/public/assets/{AdminLoginScreens-BBKEIEjY.js → AdminLoginScreens-Bjsr45ed.js} +1 -1
- package/payload/server/public/assets/AdminLoginScreens-Bjsr45ed.js.br +0 -0
- package/payload/server/public/assets/AdminLoginScreens-Bjsr45ed.js.gz +0 -0
- package/payload/server/public/assets/AdminShell-Dm_nY4jF.js +3 -0
- package/payload/server/public/assets/AdminShell-Dm_nY4jF.js.br +0 -0
- package/payload/server/public/assets/AdminShell-Dm_nY4jF.js.gz +0 -0
- package/payload/server/public/assets/{activity-CbR3vaq1.js → activity-Dz5eWZze.js} +1 -1
- package/payload/server/public/assets/activity-Dz5eWZze.js.br +0 -0
- package/payload/server/public/assets/activity-Dz5eWZze.js.gz +0 -0
- package/payload/server/public/assets/admin-B2IkUoSc.js +1 -0
- package/payload/server/public/assets/admin-B2IkUoSc.js.br +0 -0
- package/payload/server/public/assets/admin-B2IkUoSc.js.gz +0 -0
- package/payload/server/public/assets/{agents-8gAQjRqI.js → agents-DjDwemOg.js} +1 -1
- package/payload/server/public/assets/agents-DjDwemOg.js.br +0 -0
- package/payload/server/public/assets/agents-DjDwemOg.js.gz +0 -0
- package/payload/server/public/assets/{browser-jAje5ILy.js → browser-BDFx14YM.js} +1 -1
- package/payload/server/public/assets/browser-BDFx14YM.js.br +0 -0
- package/payload/server/public/assets/browser-BDFx14YM.js.gz +0 -0
- package/payload/server/public/assets/{calendar-xEmCJif9.js → calendar-BbUsdMKW.js} +1 -1
- package/payload/server/public/assets/calendar-BbUsdMKW.js.br +0 -0
- package/payload/server/public/assets/calendar-BbUsdMKW.js.gz +0 -0
- package/payload/server/public/assets/chat-fP4sE4pU.js +1 -0
- package/payload/server/public/assets/chat-fP4sE4pU.js.br +2 -0
- package/payload/server/public/assets/chat-fP4sE4pU.js.gz +0 -0
- package/payload/server/public/assets/{chevron-left-DV8gIVC9.js → chevron-left-D3_hiHLC.js} +1 -1
- package/payload/server/public/assets/chevron-left-D3_hiHLC.js.br +0 -0
- package/payload/server/public/assets/clock-kLje910u.js +1 -0
- package/payload/server/public/assets/clock-kLje910u.js.br +0 -0
- package/payload/server/public/assets/clock-kLje910u.js.gz +0 -0
- package/payload/server/public/assets/copy-Dnw0TkVh.js +1 -0
- package/payload/server/public/assets/copy-Dnw0TkVh.js.br +0 -0
- package/payload/server/public/assets/copy-Dnw0TkVh.js.gz +0 -0
- package/payload/server/public/assets/data-DKz9_73S.js +1 -0
- package/payload/server/public/assets/data-DKz9_73S.js.br +1 -0
- package/payload/server/public/assets/data-DKz9_73S.js.gz +0 -0
- package/payload/server/public/assets/{field-CiIsn-47.js → field-mhgbdofr.js} +1 -1
- package/payload/server/public/assets/field-mhgbdofr.js.br +0 -0
- package/payload/server/public/assets/field-mhgbdofr.js.gz +0 -0
- package/payload/server/public/assets/{file-text-Cy-IjCf8.js → file-text-CVZAL3Er.js} +1 -1
- package/payload/server/public/assets/file-text-CVZAL3Er.js.br +0 -0
- package/payload/server/public/assets/file-text-CVZAL3Er.js.gz +0 -0
- package/payload/server/public/assets/graph-NmOxFNdx.js +51 -0
- package/payload/server/public/assets/graph-NmOxFNdx.js.br +0 -0
- package/payload/server/public/assets/graph-NmOxFNdx.js.gz +0 -0
- package/payload/server/public/assets/{graph-labels-3bstML8n.js → graph-labels-BTFUSc63.js} +1 -1
- package/payload/server/public/assets/graph-labels-BTFUSc63.js.br +0 -0
- package/payload/server/public/assets/graph-labels-BTFUSc63.js.gz +0 -0
- package/payload/server/public/assets/{jsx-runtime-JxxB_2S6.css → jsx-runtime-dao9WPN0.css} +1 -1
- package/payload/server/public/assets/jsx-runtime-dao9WPN0.css.br +0 -0
- package/payload/server/public/assets/{jsx-runtime-JxxB_2S6.css.gz → jsx-runtime-dao9WPN0.css.gz} +0 -0
- package/payload/server/public/assets/{operator-D7L2SA16.js → operator-CO5ma-ky.js} +1 -1
- package/payload/server/public/assets/operator-CO5ma-ky.js.br +0 -0
- package/payload/server/public/assets/operator-CO5ma-ky.js.gz +0 -0
- package/payload/server/public/assets/page-BBRWbFzG.js +32 -0
- package/payload/server/public/assets/page-BBRWbFzG.js.br +0 -0
- package/payload/server/public/assets/page-BBRWbFzG.js.gz +0 -0
- package/payload/server/public/assets/page-CdRrpkky.js +1 -0
- package/payload/server/public/assets/page-CdRrpkky.js.br +0 -0
- package/payload/server/public/assets/page-CdRrpkky.js.gz +0 -0
- package/payload/server/public/assets/play-eeQX0FtC.js +1 -0
- package/payload/server/public/assets/play-eeQX0FtC.js.br +0 -0
- package/payload/server/public/assets/play-eeQX0FtC.js.gz +0 -0
- package/payload/server/public/assets/{public-CEXKl8wg.js → public-2mLo4k7L.js} +1 -1
- package/payload/server/public/assets/public-2mLo4k7L.js.br +0 -0
- package/payload/server/public/assets/public-2mLo4k7L.js.gz +0 -0
- package/payload/server/public/assets/{rotate-ccw-ckXDebK2.js → rotate-ccw-D-2d4YGp.js} +1 -1
- package/payload/server/public/assets/rotate-ccw-D-2d4YGp.js.br +0 -0
- package/payload/server/public/assets/rotate-ccw-D-2d4YGp.js.gz +0 -0
- package/payload/server/public/assets/{routines-Dwc2meN2.js → routines-CMW8sm10.js} +2 -2
- package/payload/server/public/assets/routines-CMW8sm10.js.br +0 -0
- package/payload/server/public/assets/routines-CMW8sm10.js.gz +0 -0
- package/payload/server/public/assets/{skills-DdHKHl4Z.js → skills-BQC7SM0J.js} +1 -1
- package/payload/server/public/assets/skills-BQC7SM0J.js.br +0 -0
- package/payload/server/public/assets/skills-BQC7SM0J.js.gz +0 -0
- package/payload/server/public/assets/tasks-CIs0y00-.js +3 -0
- package/payload/server/public/assets/tasks-CIs0y00-.js.br +0 -0
- package/payload/server/public/assets/tasks-CIs0y00-.js.gz +0 -0
- package/payload/server/public/assets/{triangle-alert-C-7A00P0.js → triangle-alert-C_68TrTq.js} +1 -1
- package/payload/server/public/assets/triangle-alert-C_68TrTq.js.br +0 -0
- package/payload/server/public/assets/triangle-alert-C_68TrTq.js.gz +0 -0
- package/payload/server/public/assets/{useCopyFeedback-CWvSi-Qe.js → useCopyFeedback-1MKNUzp3.js} +1 -1
- package/payload/server/public/assets/useCopyFeedback-1MKNUzp3.js.br +0 -0
- package/payload/server/public/assets/useCopyFeedback-1MKNUzp3.js.gz +0 -0
- package/payload/server/public/assets/useMediaQuery-e4ciNiuO.js +6 -0
- package/payload/server/public/assets/useMediaQuery-e4ciNiuO.js.br +0 -0
- package/payload/server/public/assets/useMediaQuery-e4ciNiuO.js.gz +0 -0
- package/payload/server/public/assets/useVoiceRecorder-D7_wLtrS.js +2 -0
- package/payload/server/public/assets/useVoiceRecorder-D7_wLtrS.js.br +0 -0
- package/payload/server/public/assets/useVoiceRecorder-D7_wLtrS.js.gz +0 -0
- package/payload/server/public/assets/{wrench-Cl6TUm2T.js → wrench-BI28h1JF.js} +1 -1
- package/payload/server/public/assets/wrench-BI28h1JF.js.br +0 -0
- package/payload/server/public/assets/wrench-BI28h1JF.js.gz +0 -0
- package/payload/server/public/browser.html +5 -5
- package/payload/server/public/calendar.html +8 -8
- package/payload/server/public/chat.html +14 -14
- package/payload/server/public/data.html +12 -12
- package/payload/server/public/field.html +3 -3
- package/payload/server/public/graph.html +10 -10
- package/payload/server/public/index.html +14 -14
- package/payload/server/public/operator.html +15 -15
- package/payload/server/public/public.html +14 -14
- package/payload/server/public/routines.html +8 -8
- package/payload/server/public/skills.html +6 -6
- package/payload/server/public/tasks.html +7 -7
- package/payload/server/server.js +650 -528
- package/payload/server/public/assets/AdminLoginScreens-BBKEIEjY.js.br +0 -0
- package/payload/server/public/assets/AdminLoginScreens-BBKEIEjY.js.gz +0 -0
- package/payload/server/public/assets/AdminShell-CrCdEMNW.js +0 -3
- package/payload/server/public/assets/AdminShell-CrCdEMNW.js.br +0 -0
- package/payload/server/public/assets/AdminShell-CrCdEMNW.js.gz +0 -0
- package/payload/server/public/assets/activity-CbR3vaq1.js.br +0 -0
- package/payload/server/public/assets/activity-CbR3vaq1.js.gz +0 -0
- package/payload/server/public/assets/admin-D8qKnmhE.js +0 -1
- package/payload/server/public/assets/admin-D8qKnmhE.js.br +0 -0
- package/payload/server/public/assets/admin-D8qKnmhE.js.gz +0 -0
- package/payload/server/public/assets/agents-8gAQjRqI.js.br +0 -0
- package/payload/server/public/assets/agents-8gAQjRqI.js.gz +0 -0
- package/payload/server/public/assets/browser-jAje5ILy.js.br +0 -0
- package/payload/server/public/assets/browser-jAje5ILy.js.gz +0 -0
- package/payload/server/public/assets/calendar-xEmCJif9.js.br +0 -0
- package/payload/server/public/assets/calendar-xEmCJif9.js.gz +0 -0
- package/payload/server/public/assets/chat-Ct5RDmv6.js +0 -1
- package/payload/server/public/assets/chat-Ct5RDmv6.js.br +0 -0
- package/payload/server/public/assets/chat-Ct5RDmv6.js.gz +0 -0
- package/payload/server/public/assets/chevron-left-DV8gIVC9.js.br +0 -0
- package/payload/server/public/assets/clock-PnR4Tlg9.js +0 -1
- package/payload/server/public/assets/clock-PnR4Tlg9.js.br +0 -0
- package/payload/server/public/assets/copy-b6MpzRz9.js +0 -1
- package/payload/server/public/assets/copy-b6MpzRz9.js.br +0 -0
- package/payload/server/public/assets/copy-b6MpzRz9.js.gz +0 -0
- package/payload/server/public/assets/data-BxFc9wPl.js +0 -1
- package/payload/server/public/assets/data-BxFc9wPl.js.br +0 -2
- package/payload/server/public/assets/data-BxFc9wPl.js.gz +0 -0
- package/payload/server/public/assets/field-CiIsn-47.js.br +0 -0
- package/payload/server/public/assets/field-CiIsn-47.js.gz +0 -0
- package/payload/server/public/assets/file-text-Cy-IjCf8.js.br +0 -0
- package/payload/server/public/assets/file-text-Cy-IjCf8.js.gz +0 -0
- package/payload/server/public/assets/graph-BdC2IGOT.js +0 -51
- package/payload/server/public/assets/graph-BdC2IGOT.js.br +0 -0
- package/payload/server/public/assets/graph-BdC2IGOT.js.gz +0 -0
- package/payload/server/public/assets/graph-labels-3bstML8n.js.br +0 -0
- package/payload/server/public/assets/graph-labels-3bstML8n.js.gz +0 -0
- package/payload/server/public/assets/jsx-runtime-JxxB_2S6.css.br +0 -0
- package/payload/server/public/assets/operator-D7L2SA16.js.br +0 -0
- package/payload/server/public/assets/operator-D7L2SA16.js.gz +0 -0
- package/payload/server/public/assets/page-DspGbDgK.js +0 -32
- package/payload/server/public/assets/page-DspGbDgK.js.br +0 -0
- package/payload/server/public/assets/page-DspGbDgK.js.gz +0 -0
- package/payload/server/public/assets/page-ObXxk8ol.js +0 -1
- package/payload/server/public/assets/page-ObXxk8ol.js.br +0 -0
- package/payload/server/public/assets/page-ObXxk8ol.js.gz +0 -0
- package/payload/server/public/assets/play-BL4ztD3m.js +0 -1
- package/payload/server/public/assets/play-BL4ztD3m.js.br +0 -0
- package/payload/server/public/assets/play-BL4ztD3m.js.gz +0 -0
- package/payload/server/public/assets/public-CEXKl8wg.js.br +0 -0
- package/payload/server/public/assets/public-CEXKl8wg.js.gz +0 -0
- package/payload/server/public/assets/rotate-ccw-ckXDebK2.js.br +0 -0
- package/payload/server/public/assets/rotate-ccw-ckXDebK2.js.gz +0 -0
- package/payload/server/public/assets/routines-Dwc2meN2.js.br +0 -0
- package/payload/server/public/assets/routines-Dwc2meN2.js.gz +0 -0
- package/payload/server/public/assets/skills-DdHKHl4Z.js.br +0 -0
- package/payload/server/public/assets/skills-DdHKHl4Z.js.gz +0 -0
- package/payload/server/public/assets/tasks-C_yWRvOG.js +0 -3
- package/payload/server/public/assets/tasks-C_yWRvOG.js.br +0 -0
- package/payload/server/public/assets/tasks-C_yWRvOG.js.gz +0 -0
- package/payload/server/public/assets/triangle-alert-C-7A00P0.js.br +0 -0
- package/payload/server/public/assets/triangle-alert-C-7A00P0.js.gz +0 -0
- package/payload/server/public/assets/useCopyFeedback-CWvSi-Qe.js.br +0 -2
- package/payload/server/public/assets/useCopyFeedback-CWvSi-Qe.js.gz +0 -0
- package/payload/server/public/assets/useMediaQuery-CLVRXJMp.js +0 -6
- package/payload/server/public/assets/useMediaQuery-CLVRXJMp.js.br +0 -0
- package/payload/server/public/assets/useMediaQuery-CLVRXJMp.js.gz +0 -0
- package/payload/server/public/assets/useVoiceRecorder-BbJad9CQ.js +0 -2
- package/payload/server/public/assets/useVoiceRecorder-BbJad9CQ.js.br +0 -0
- package/payload/server/public/assets/useVoiceRecorder-BbJad9CQ.js.gz +0 -0
- package/payload/server/public/assets/wrench-Cl6TUm2T.js.br +0 -0
- package/payload/server/public/assets/wrench-Cl6TUm2T.js.gz +0 -0
- /package/payload/server/public/assets/{jsx-runtime-BCAZhYqz.js → jsx-runtime-BY35JYDT.js} +0 -0
- /package/payload/server/public/assets/{jsx-runtime-BCAZhYqz.js.br → jsx-runtime-BY35JYDT.js.br} +0 -0
- /package/payload/server/public/assets/{jsx-runtime-BCAZhYqz.js.gz → jsx-runtime-BY35JYDT.js.gz} +0 -0
package/payload/server/server.js
CHANGED
|
@@ -362,15 +362,15 @@ var require_dist2 = __commonJS({
|
|
|
362
362
|
return out;
|
|
363
363
|
}
|
|
364
364
|
function scanStore(storeDir) {
|
|
365
|
-
const
|
|
365
|
+
const newest = /* @__PURE__ */ new Map();
|
|
366
366
|
let storeRows = 0;
|
|
367
367
|
if (!storeDir || !(0, node_fs_1.existsSync)(storeDir))
|
|
368
|
-
return { newest
|
|
368
|
+
return { newest, storeRows };
|
|
369
369
|
let entries2;
|
|
370
370
|
try {
|
|
371
371
|
entries2 = (0, node_fs_1.readdirSync)(storeDir);
|
|
372
372
|
} catch {
|
|
373
|
-
return { newest
|
|
373
|
+
return { newest, storeRows };
|
|
374
374
|
}
|
|
375
375
|
for (const entry3 of entries2) {
|
|
376
376
|
if (!entry3.endsWith(".jsonl"))
|
|
@@ -402,10 +402,10 @@ var require_dist2 = __commonJS({
|
|
|
402
402
|
if (chatId !== senderId)
|
|
403
403
|
continue;
|
|
404
404
|
const key2 = `${botId}:${senderId}`;
|
|
405
|
-
const prev =
|
|
405
|
+
const prev = newest.get(key2);
|
|
406
406
|
if (prev !== void 0 && prev.dateSent.localeCompare(dateSent) >= 0)
|
|
407
407
|
continue;
|
|
408
|
-
|
|
408
|
+
newest.set(key2, {
|
|
409
409
|
chatId,
|
|
410
410
|
senderId,
|
|
411
411
|
senderName: typeof row.senderName === "string" ? row.senderName : null,
|
|
@@ -413,16 +413,16 @@ var require_dist2 = __commonJS({
|
|
|
413
413
|
});
|
|
414
414
|
}
|
|
415
415
|
}
|
|
416
|
-
return { newest
|
|
416
|
+
return { newest, storeRows };
|
|
417
417
|
}
|
|
418
418
|
function collectTelegramReach2(input) {
|
|
419
|
-
const { newest
|
|
419
|
+
const { newest, storeRows } = scanStore(input.storeDir);
|
|
420
420
|
const bots = input.bots.map((bot) => {
|
|
421
421
|
const adminUsers = bot.adminUsers ?? [];
|
|
422
422
|
const adminSet = new Set(adminUsers.map((u) => String(u)));
|
|
423
423
|
const chats = [];
|
|
424
424
|
const seen = /* @__PURE__ */ new Set();
|
|
425
|
-
for (const [key2, row] of
|
|
425
|
+
for (const [key2, row] of newest) {
|
|
426
426
|
if (key2.slice(0, key2.indexOf(":")) !== bot.id)
|
|
427
427
|
continue;
|
|
428
428
|
seen.add(row.senderId);
|
|
@@ -3220,10 +3220,10 @@ var require_dist10 = __commonJS({
|
|
|
3220
3220
|
});
|
|
3221
3221
|
|
|
3222
3222
|
// server/index.ts
|
|
3223
|
-
import { readFileSync as
|
|
3223
|
+
import { readFileSync as readFileSync63, existsSync as existsSync63, watchFile, readdirSync as readdirSync37, statSync as statSync33 } from "fs";
|
|
3224
3224
|
import { spawn as spawn3 } from "child_process";
|
|
3225
3225
|
import { createHash as createHash8 } from "crypto";
|
|
3226
|
-
import { resolve as resolve55, join as
|
|
3226
|
+
import { resolve as resolve55, join as join77, basename as basename19 } from "path";
|
|
3227
3227
|
import { homedir as homedir5 } from "os";
|
|
3228
3228
|
|
|
3229
3229
|
// server/lib/route-cache-watchers.ts
|
|
@@ -3470,15 +3470,15 @@ function readRows(accountId, channelKey) {
|
|
|
3470
3470
|
}
|
|
3471
3471
|
}
|
|
3472
3472
|
function newestInboundTelegramDate(accountId, channelKey) {
|
|
3473
|
-
let
|
|
3473
|
+
let newest = null;
|
|
3474
3474
|
for (const row of readRows(accountId, channelKey)) {
|
|
3475
3475
|
if (isUpdateRecord(row)) continue;
|
|
3476
3476
|
if (row.fromMe) continue;
|
|
3477
3477
|
const d = row.telegramDate;
|
|
3478
3478
|
if (typeof d !== "number" || !Number.isFinite(d)) continue;
|
|
3479
|
-
if (
|
|
3479
|
+
if (newest === null || d > newest) newest = d;
|
|
3480
3480
|
}
|
|
3481
|
-
return
|
|
3481
|
+
return newest;
|
|
3482
3482
|
}
|
|
3483
3483
|
function readConversation2(accountId, channelKey) {
|
|
3484
3484
|
if (!(0, import_dist2.isStorableChannelKey)(channelKey)) return [];
|
|
@@ -15432,7 +15432,7 @@ var whatsapp_reader_default = app5;
|
|
|
15432
15432
|
|
|
15433
15433
|
// server/routes/telegram-reader.ts
|
|
15434
15434
|
import { statSync as statSync14, watch as watch3 } from "fs";
|
|
15435
|
-
import { join as
|
|
15435
|
+
import { join as join29, resolve as resolve19 } from "path";
|
|
15436
15436
|
|
|
15437
15437
|
// app/lib/telegram/outbound/get-chat.ts
|
|
15438
15438
|
async function getTelegramChat(botToken, chatId) {
|
|
@@ -15458,43 +15458,48 @@ var records3 = [];
|
|
|
15458
15458
|
function prune2(now) {
|
|
15459
15459
|
records3 = records3.filter((r) => now - r.at <= WINDOW_MS3);
|
|
15460
15460
|
}
|
|
15461
|
-
function
|
|
15462
|
-
|
|
15463
|
-
return void 0;
|
|
15461
|
+
function oldestPending(key2) {
|
|
15462
|
+
return records3.find((r) => r.key === key2 && r.mechanism === null && r.skipped === null);
|
|
15464
15463
|
}
|
|
15465
15464
|
function noteManualSent(key2, now) {
|
|
15466
|
-
records3.push({ key: key2, at: now,
|
|
15465
|
+
records3.push({ key: key2, at: now, mechanism: null, skipped: null, suppressed: false });
|
|
15467
15466
|
}
|
|
15468
15467
|
function noteManualRecorded(key2, _now) {
|
|
15469
|
-
const r =
|
|
15470
|
-
if (r) r.
|
|
15468
|
+
const r = oldestPending(key2);
|
|
15469
|
+
if (r) r.mechanism = "inject";
|
|
15470
|
+
}
|
|
15471
|
+
function noteManualWritten(key2, _now) {
|
|
15472
|
+
const r = oldestPending(key2);
|
|
15473
|
+
if (r) r.mechanism = "append";
|
|
15471
15474
|
}
|
|
15472
15475
|
function noteManualSkipped(key2, reason, _now) {
|
|
15473
|
-
const r =
|
|
15476
|
+
const r = oldestPending(key2);
|
|
15474
15477
|
if (r) r.skipped = reason;
|
|
15475
15478
|
}
|
|
15476
15479
|
function noteManualSuppressed(key2, _now) {
|
|
15477
|
-
const r = records3.find((x) => x.key === key2 && x.
|
|
15480
|
+
const r = records3.find((x) => x.key === key2 && x.mechanism === "inject" && !x.suppressed);
|
|
15478
15481
|
if (r) r.suppressed = true;
|
|
15479
15482
|
}
|
|
15480
15483
|
function readManualSendCensus(now) {
|
|
15481
15484
|
prune2(now);
|
|
15482
|
-
let
|
|
15485
|
+
let injected = 0;
|
|
15486
|
+
let written = 0;
|
|
15483
15487
|
let suppressed = 0;
|
|
15484
15488
|
let unrecorded = 0;
|
|
15485
15489
|
let skipped = 0;
|
|
15486
15490
|
let leaked = 0;
|
|
15487
15491
|
for (const r of records3) {
|
|
15488
|
-
if (r.
|
|
15492
|
+
if (r.mechanism === "inject") injected += 1;
|
|
15493
|
+
else if (r.mechanism === "append") written += 1;
|
|
15489
15494
|
else if (r.skipped !== null) skipped += 1;
|
|
15490
15495
|
else if (now - r.at > RECORD_THRESHOLD_MS) unrecorded += 1;
|
|
15491
15496
|
if (r.suppressed) suppressed += 1;
|
|
15492
|
-
else if (r.
|
|
15497
|
+
else if (r.mechanism === "inject" && now - r.at > SUPPRESSION_THRESHOLD_MS) leaked += 1;
|
|
15493
15498
|
}
|
|
15494
|
-
return { sent: records3.length,
|
|
15499
|
+
return { sent: records3.length, injected, written, suppressed, unrecorded, skipped, leaked };
|
|
15495
15500
|
}
|
|
15496
15501
|
function buildManualSendCensusLine(c) {
|
|
15497
|
-
return `[telegram-manual-census] sent=${c.sent}
|
|
15502
|
+
return `[telegram-manual-census] sent=${c.sent} injected=${c.injected} written=${c.written} suppressed=${c.suppressed} unrecorded=${c.unrecorded} skipped=${c.skipped} leaked=${c.leaked} window=60m`;
|
|
15498
15503
|
}
|
|
15499
15504
|
function runTelegramManualSendCensus(now) {
|
|
15500
15505
|
console.error(buildManualSendCensusLine(readManualSendCensus(now)));
|
|
@@ -15504,15 +15509,32 @@ function runTelegramManualSendCensus(now) {
|
|
|
15504
15509
|
async function recordManualSendContext(input, deps) {
|
|
15505
15510
|
const refuse2 = (reason) => {
|
|
15506
15511
|
noteManualSkipped(input.channelKey, reason, deps.now());
|
|
15507
|
-
return { recorded: false, reason };
|
|
15512
|
+
return { recorded: false, mechanism: "none", reason };
|
|
15508
15513
|
};
|
|
15514
|
+
const failed2 = (mechanism, reason) => ({
|
|
15515
|
+
recorded: false,
|
|
15516
|
+
mechanism,
|
|
15517
|
+
reason
|
|
15518
|
+
});
|
|
15509
15519
|
if (input.entry.role !== "public") return refuse2("not-public-bot");
|
|
15510
|
-
if (!deps.entryActive(input.entry, input.accountDir, input.botId)) return refuse2("agent-inactive");
|
|
15511
15520
|
const businessKey = telegramBusinessChannelKey(input.botId, String(input.chatId));
|
|
15512
15521
|
if (deps.newestInboundTelegramDate(input.accountId, businessKey) !== null) {
|
|
15513
15522
|
return refuse2("business-chat");
|
|
15514
15523
|
}
|
|
15515
|
-
|
|
15524
|
+
const projectDir = deps.findSessionProjectDir(input.sessionId);
|
|
15525
|
+
if (projectDir === null) return refuse2("no-transcript");
|
|
15526
|
+
const live = deps.isLive(input.channelKey);
|
|
15527
|
+
const active = deps.entryActive(input.entry, input.accountDir, input.botId);
|
|
15528
|
+
if (!(live && active)) {
|
|
15529
|
+
const res = deps.appendTranscript(
|
|
15530
|
+
input.sessionId,
|
|
15531
|
+
projectDir,
|
|
15532
|
+
input.text,
|
|
15533
|
+
new Date(deps.now())
|
|
15534
|
+
);
|
|
15535
|
+
if (!res.written) return failed2("append", res.reason);
|
|
15536
|
+
return { recorded: true, mechanism: "append", reason: "-" };
|
|
15537
|
+
}
|
|
15516
15538
|
try {
|
|
15517
15539
|
await deps.handleInbound({
|
|
15518
15540
|
accountId: input.accountId,
|
|
@@ -15548,16 +15570,83 @@ async function recordManualSendContext(input, deps) {
|
|
|
15548
15570
|
})
|
|
15549
15571
|
});
|
|
15550
15572
|
} catch (err) {
|
|
15551
|
-
return
|
|
15573
|
+
return failed2("inject", `inject-error:${err instanceof Error ? err.message : String(err)}`);
|
|
15552
15574
|
}
|
|
15553
|
-
return { recorded: true, reason: "-" };
|
|
15575
|
+
return { recorded: true, mechanism: "inject", reason: "-" };
|
|
15554
15576
|
}
|
|
15555
15577
|
|
|
15556
|
-
// app/lib/
|
|
15557
|
-
import {
|
|
15578
|
+
// app/lib/telegram/session-transcript-append.ts
|
|
15579
|
+
import { appendFileSync as appendFileSync2, existsSync as existsSync19, readFileSync as readFileSync22 } from "fs";
|
|
15580
|
+
import { randomUUID as randomUUID4 } from "crypto";
|
|
15558
15581
|
import { join as join27 } from "path";
|
|
15582
|
+
function isStr(v) {
|
|
15583
|
+
return typeof v === "string" && v.length > 0;
|
|
15584
|
+
}
|
|
15585
|
+
function appendAssistantRecord(input) {
|
|
15586
|
+
const path = join27(input.projectDir, `${input.sessionId}.jsonl`);
|
|
15587
|
+
if (!existsSync19(path)) return { written: false, reason: "no-transcript-file" };
|
|
15588
|
+
const raw = readFileSync22(path, "utf-8");
|
|
15589
|
+
const recs = [];
|
|
15590
|
+
for (const line of raw.split("\n")) {
|
|
15591
|
+
if (!line.trim()) continue;
|
|
15592
|
+
try {
|
|
15593
|
+
recs.push(JSON.parse(line));
|
|
15594
|
+
} catch {
|
|
15595
|
+
}
|
|
15596
|
+
}
|
|
15597
|
+
let parentUuid = null;
|
|
15598
|
+
for (let i = recs.length - 1; i >= 0; i--) {
|
|
15599
|
+
if (isStr(recs[i].uuid)) {
|
|
15600
|
+
parentUuid = recs[i].uuid;
|
|
15601
|
+
break;
|
|
15602
|
+
}
|
|
15603
|
+
}
|
|
15604
|
+
if (!parentUuid) return { written: false, reason: "no-chain-leaf" };
|
|
15605
|
+
let donor = null;
|
|
15606
|
+
for (let i = recs.length - 1; i >= 0; i--) {
|
|
15607
|
+
if (isStr(recs[i].cwd) && isStr(recs[i].version)) {
|
|
15608
|
+
donor = recs[i];
|
|
15609
|
+
break;
|
|
15610
|
+
}
|
|
15611
|
+
}
|
|
15612
|
+
if (!donor) return { written: false, reason: "no-envelope" };
|
|
15613
|
+
const uuid = randomUUID4();
|
|
15614
|
+
const record = {
|
|
15615
|
+
parentUuid,
|
|
15616
|
+
isSidechain: false,
|
|
15617
|
+
type: "assistant",
|
|
15618
|
+
message: {
|
|
15619
|
+
role: "assistant",
|
|
15620
|
+
type: "message",
|
|
15621
|
+
content: [{ type: "text", text: input.text }]
|
|
15622
|
+
},
|
|
15623
|
+
uuid,
|
|
15624
|
+
timestamp: input.at.toISOString(),
|
|
15625
|
+
sessionId: input.sessionId,
|
|
15626
|
+
session_id: input.sessionId,
|
|
15627
|
+
userType: isStr(donor.userType) ? donor.userType : "external",
|
|
15628
|
+
entrypoint: isStr(donor.entrypoint) ? donor.entrypoint : "cli",
|
|
15629
|
+
cwd: donor.cwd,
|
|
15630
|
+
version: donor.version
|
|
15631
|
+
};
|
|
15632
|
+
const boundary = raw.length === 0 || raw.endsWith("\n") ? "" : "\n";
|
|
15633
|
+
appendFileSync2(path, boundary + JSON.stringify(record) + "\n");
|
|
15634
|
+
const reread = readFileSync22(path, "utf-8").split("\n").some((l) => {
|
|
15635
|
+
if (!l.trim()) return false;
|
|
15636
|
+
try {
|
|
15637
|
+
return JSON.parse(l).uuid === uuid;
|
|
15638
|
+
} catch {
|
|
15639
|
+
return false;
|
|
15640
|
+
}
|
|
15641
|
+
});
|
|
15642
|
+
return reread ? { written: true, reason: "-" } : { written: false, reason: "reread-missing" };
|
|
15643
|
+
}
|
|
15644
|
+
|
|
15645
|
+
// app/lib/claude-agent/specialist-roster.ts
|
|
15646
|
+
import { existsSync as existsSync20, readFileSync as readFileSync23, readdirSync as readdirSync14 } from "fs";
|
|
15647
|
+
import { join as join28 } from "path";
|
|
15559
15648
|
function listSpecialistCardNames(specialistsDir) {
|
|
15560
|
-
if (!
|
|
15649
|
+
if (!existsSync20(specialistsDir)) return [];
|
|
15561
15650
|
return readdirSync14(specialistsDir).filter((f) => f.endsWith(".md")).map((f) => f.slice(0, -3)).sort();
|
|
15562
15651
|
}
|
|
15563
15652
|
function field(fm, name) {
|
|
@@ -15570,7 +15659,7 @@ function field(fm, name) {
|
|
|
15570
15659
|
return value || null;
|
|
15571
15660
|
}
|
|
15572
15661
|
function readSpecialistRoster(specialistsDir) {
|
|
15573
|
-
if (!
|
|
15662
|
+
if (!existsSync20(specialistsDir)) return { specialists: [], skipped: [] };
|
|
15574
15663
|
const entries2 = readdirSync14(specialistsDir);
|
|
15575
15664
|
const specialists = [];
|
|
15576
15665
|
const skipped = [];
|
|
@@ -15578,7 +15667,7 @@ function readSpecialistRoster(specialistsDir) {
|
|
|
15578
15667
|
if (!file.endsWith(".md")) continue;
|
|
15579
15668
|
let raw;
|
|
15580
15669
|
try {
|
|
15581
|
-
raw =
|
|
15670
|
+
raw = readFileSync23(join28(specialistsDir, file), "utf-8");
|
|
15582
15671
|
} catch (err) {
|
|
15583
15672
|
skipped.push({ file, reason: err instanceof Error ? err.message : String(err) });
|
|
15584
15673
|
continue;
|
|
@@ -15623,7 +15712,7 @@ function foldPatches(rows, uploadsBase) {
|
|
|
15623
15712
|
for (const id of row.attachmentIds) {
|
|
15624
15713
|
if (already.has(id)) continue;
|
|
15625
15714
|
already.add(id);
|
|
15626
|
-
const meta = readAttachmentMeta(
|
|
15715
|
+
const meta = readAttachmentMeta(join29(uploadsBase, id));
|
|
15627
15716
|
if (meta) metas.push(meta);
|
|
15628
15717
|
}
|
|
15629
15718
|
seen.set(row.targetMessageId, already);
|
|
@@ -15897,6 +15986,11 @@ function manualSendContextDeps() {
|
|
|
15897
15986
|
specialistCards: (dir) => listSpecialistCardNames(dir),
|
|
15898
15987
|
log: (line) => console.error(line)
|
|
15899
15988
|
}),
|
|
15989
|
+
// Task 2737 — the gateway's own predicate, never a second one. A null gateway
|
|
15990
|
+
// is not live by the only definition that matters here: an inject could not
|
|
15991
|
+
// land, so the append branch is the correct one.
|
|
15992
|
+
isLive: (channelKey) => getTelegramGateway()?.isLive(channelKey) ?? false,
|
|
15993
|
+
appendTranscript: (sessionId, projectDir, text, at) => appendAssistantRecord({ sessionId, projectDir, text, at }),
|
|
15900
15994
|
newestInboundTelegramDate,
|
|
15901
15995
|
findSessionProjectDir,
|
|
15902
15996
|
handleInbound: async (inbound) => {
|
|
@@ -16039,10 +16133,18 @@ app6.post("/send", requireAdminSession, async (c) => {
|
|
|
16039
16133
|
manualSendContextDeps()
|
|
16040
16134
|
);
|
|
16041
16135
|
console.error(
|
|
16042
|
-
`${MANUAL_TAG2} op=context
|
|
16136
|
+
`${MANUAL_TAG2} op=context sendId=${sendId} chatId=${chatId} sessionId=${contextSessionId} mechanism=${ctx.mechanism} written=${ctx.recorded ? "yes" : "no"} reason=${ctx.reason}`
|
|
16043
16137
|
);
|
|
16138
|
+
if (ctx.recorded && ctx.mechanism === "append") noteManualWritten(channelKey, Date.now());
|
|
16044
16139
|
exit("delivered");
|
|
16045
|
-
return c.json(
|
|
16140
|
+
return c.json(
|
|
16141
|
+
{
|
|
16142
|
+
ok: true,
|
|
16143
|
+
recorded: reread,
|
|
16144
|
+
context: { written: ctx.recorded, mechanism: ctx.mechanism, reason: ctx.reason }
|
|
16145
|
+
},
|
|
16146
|
+
200
|
|
16147
|
+
);
|
|
16046
16148
|
});
|
|
16047
16149
|
var telegram_reader_default = app6;
|
|
16048
16150
|
|
|
@@ -16085,8 +16187,8 @@ function runTelegramStoreCensus() {
|
|
|
16085
16187
|
|
|
16086
16188
|
// app/lib/telegram/reach-census.ts
|
|
16087
16189
|
var import_dist4 = __toESM(require_dist2(), 1);
|
|
16088
|
-
import { existsSync as
|
|
16089
|
-
import { join as
|
|
16190
|
+
import { existsSync as existsSync21 } from "fs";
|
|
16191
|
+
import { join as join30 } from "path";
|
|
16090
16192
|
function collectTelegramReachCensus(accounts) {
|
|
16091
16193
|
const out = {
|
|
16092
16194
|
accounts: accounts.length,
|
|
@@ -16096,7 +16198,7 @@ function collectTelegramReachCensus(accounts) {
|
|
|
16096
16198
|
};
|
|
16097
16199
|
for (const account of accounts) {
|
|
16098
16200
|
const reach = (0, import_dist4.collectTelegramReach)({
|
|
16099
|
-
storeDir:
|
|
16201
|
+
storeDir: join30(STORE_ROOT2(), account.accountId),
|
|
16100
16202
|
bots: account.bots
|
|
16101
16203
|
});
|
|
16102
16204
|
for (const bot of reach.bots) {
|
|
@@ -16112,7 +16214,7 @@ function runTelegramReachCensus(accounts) {
|
|
|
16112
16214
|
const c = collectTelegramReachCensus(accounts);
|
|
16113
16215
|
const root = STORE_ROOT2();
|
|
16114
16216
|
console.error(
|
|
16115
|
-
`[telegram-reach-census] accounts=${c.accounts} bots=${c.bots} chatsKnown=${c.chatsKnown} botsWithNoChats=${c.botsWithNoChats} storeRoot=${root} exists=${
|
|
16217
|
+
`[telegram-reach-census] accounts=${c.accounts} bots=${c.bots} chatsKnown=${c.chatsKnown} botsWithNoChats=${c.botsWithNoChats} storeRoot=${root} exists=${existsSync21(root)}`
|
|
16116
16218
|
);
|
|
16117
16219
|
return c;
|
|
16118
16220
|
}
|
|
@@ -16150,7 +16252,7 @@ function runTelegramCheckoutCensus(bots, now) {
|
|
|
16150
16252
|
}
|
|
16151
16253
|
|
|
16152
16254
|
// app/lib/telegram/media-census.ts
|
|
16153
|
-
import { join as
|
|
16255
|
+
import { join as join31, resolve as resolve20 } from "path";
|
|
16154
16256
|
function idsByTarget(rows) {
|
|
16155
16257
|
const out = /* @__PURE__ */ new Map();
|
|
16156
16258
|
for (const row of rows) {
|
|
@@ -16231,8 +16333,8 @@ function readWaOperatorTurns() {
|
|
|
16231
16333
|
}
|
|
16232
16334
|
|
|
16233
16335
|
// server/routes/session-reader.ts
|
|
16234
|
-
import { readFileSync as
|
|
16235
|
-
import { isAbsolute as isAbsolute2, join as
|
|
16336
|
+
import { readFileSync as readFileSync24, watch as watch4, statSync as statSync15, existsSync as existsSync22, readdirSync as readdirSync15, realpathSync as realpathSync5 } from "fs";
|
|
16337
|
+
import { isAbsolute as isAbsolute2, join as join32, relative as relative3, resolve as resolve21, sep as sep5 } from "path";
|
|
16236
16338
|
|
|
16237
16339
|
// server/routes/admin/manager-client.ts
|
|
16238
16340
|
var SESSION_ID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
@@ -16248,10 +16350,10 @@ function managerBase(tag) {
|
|
|
16248
16350
|
function pickActivity(entries2, grown, nowMs, concurrencyWindowMs) {
|
|
16249
16351
|
const candidates = entries2.filter((e) => grown.has(e.hex));
|
|
16250
16352
|
if (candidates.length === 0) return null;
|
|
16251
|
-
let
|
|
16252
|
-
for (const e of candidates) if (e.mtimeMs >
|
|
16353
|
+
let newest = candidates[0];
|
|
16354
|
+
for (const e of candidates) if (e.mtimeMs > newest.mtimeMs) newest = e;
|
|
16253
16355
|
const count = candidates.filter((e) => nowMs - e.mtimeMs < concurrencyWindowMs).length;
|
|
16254
|
-
return { hex:
|
|
16356
|
+
return { hex: newest.hex, lastEmitAt: newest.mtimeMs, count };
|
|
16255
16357
|
}
|
|
16256
16358
|
|
|
16257
16359
|
// server/routes/session-reader.ts
|
|
@@ -16337,7 +16439,7 @@ function openTaskKey(turns) {
|
|
|
16337
16439
|
}
|
|
16338
16440
|
function readSubagentMeta(dir, hex) {
|
|
16339
16441
|
try {
|
|
16340
|
-
const m = JSON.parse(
|
|
16442
|
+
const m = JSON.parse(readFileSync24(join32(dir, `agent-${hex}.meta.json`), "utf8"));
|
|
16341
16443
|
if (typeof m.agentType === "string" && typeof m.description === "string" && typeof m.toolUseId === "string") {
|
|
16342
16444
|
return { agentType: m.agentType, description: m.description, toolUseId: m.toolUseId };
|
|
16343
16445
|
}
|
|
@@ -16369,7 +16471,7 @@ function runActivityTick(c) {
|
|
|
16369
16471
|
let size = 0;
|
|
16370
16472
|
let mtimeMs = 0;
|
|
16371
16473
|
try {
|
|
16372
|
-
const st = statSync15(
|
|
16474
|
+
const st = statSync15(join32(c.subagentsDir, name));
|
|
16373
16475
|
size = st.size;
|
|
16374
16476
|
mtimeMs = st.mtimeMs;
|
|
16375
16477
|
} catch {
|
|
@@ -16414,11 +16516,11 @@ app7.get("/stream", requireAdminSession, (c) => {
|
|
|
16414
16516
|
const sessionId = c.req.query("sessionId") ?? "";
|
|
16415
16517
|
const projectDir = c.req.query("projectDir") ?? "";
|
|
16416
16518
|
const cfg = claudeConfigDir();
|
|
16417
|
-
const projectsRoot = cfg ? resolve21(
|
|
16519
|
+
const projectsRoot = cfg ? resolve21(join32(cfg, "projects")) : null;
|
|
16418
16520
|
if (!cfg || !projectsRoot || !SESSION_ID_RE2.test(sessionId)) {
|
|
16419
16521
|
return c.json({ error: "bad session reference" }, 400);
|
|
16420
16522
|
}
|
|
16421
|
-
const jsonlPath = resolve21(
|
|
16523
|
+
const jsonlPath = resolve21(join32(projectDir, `${sessionId}.jsonl`));
|
|
16422
16524
|
if (!jsonlPath.startsWith(projectsRoot + sep5)) {
|
|
16423
16525
|
return c.json({ error: "bad session reference" }, 400);
|
|
16424
16526
|
}
|
|
@@ -16446,9 +16548,9 @@ data: ${JSON.stringify(turn)}
|
|
|
16446
16548
|
let offset = resumeOffset(lastEventId, fileEnd0);
|
|
16447
16549
|
console.log(`[wa-stream] op=open conn=${connId} sessionId=${sessionId} channel=reader resume=${offset}`);
|
|
16448
16550
|
const sessionKey = c.req.query("session_key") ?? "";
|
|
16449
|
-
const subagentsDir = resolve21(
|
|
16551
|
+
const subagentsDir = resolve21(join32(projectDir, sessionId, "subagents"));
|
|
16450
16552
|
console.log(
|
|
16451
|
-
`[webchat-activity] op=watch-subagents key=${sessionKey} dir=${subagentsDir} exists=${
|
|
16553
|
+
`[webchat-activity] op=watch-subagents key=${sessionKey} dir=${subagentsDir} exists=${existsSync22(subagentsDir)}`
|
|
16452
16554
|
);
|
|
16453
16555
|
const actx = makeActivityCtx({
|
|
16454
16556
|
subagentsDir,
|
|
@@ -16599,11 +16701,11 @@ app7.get("/backfill", requireAdminSession, (c) => {
|
|
|
16599
16701
|
const beforeRaw = c.req.query("before") ?? "";
|
|
16600
16702
|
const before = Number(beforeRaw);
|
|
16601
16703
|
const cfg = claudeConfigDir();
|
|
16602
|
-
const projectsRoot = cfg ? resolve21(
|
|
16704
|
+
const projectsRoot = cfg ? resolve21(join32(cfg, "projects")) : null;
|
|
16603
16705
|
if (!cfg || !projectsRoot || !SESSION_ID_RE2.test(sessionId) || beforeRaw === "" || !Number.isFinite(before) || before < 0) {
|
|
16604
16706
|
return c.json({ error: "bad session reference" }, 400);
|
|
16605
16707
|
}
|
|
16606
|
-
const jsonlPath = resolve21(
|
|
16708
|
+
const jsonlPath = resolve21(join32(projectDir, `${sessionId}.jsonl`));
|
|
16607
16709
|
if (!jsonlPath.startsWith(projectsRoot + sep5)) {
|
|
16608
16710
|
return c.json({ error: "bad session reference" }, 400);
|
|
16609
16711
|
}
|
|
@@ -16655,7 +16757,7 @@ app7.get("/directives", requireAdminSession, (c) => {
|
|
|
16655
16757
|
const sessionId = c.req.query("sessionId") ?? "";
|
|
16656
16758
|
if (!SESSION_ID_RE2.test(sessionId)) return c.json({ error: "bad session reference" }, 400);
|
|
16657
16759
|
const dir = directiveStoreDir(sessionId);
|
|
16658
|
-
if (!dir || !
|
|
16760
|
+
if (!dir || !existsSync22(dir)) return c.json({ entries: [] });
|
|
16659
16761
|
let names;
|
|
16660
16762
|
try {
|
|
16661
16763
|
names = readdirSync15(dir).filter((n) => DIRECTIVE_NAME_RE.test(n));
|
|
@@ -16668,7 +16770,7 @@ app7.get("/directives", requireAdminSession, (c) => {
|
|
|
16668
16770
|
const pid = Number(pidPart);
|
|
16669
16771
|
let len = 0;
|
|
16670
16772
|
try {
|
|
16671
|
-
len = statSync15(
|
|
16773
|
+
len = statSync15(join32(dir, name)).size;
|
|
16672
16774
|
} catch {
|
|
16673
16775
|
}
|
|
16674
16776
|
return { name, secs, pid, ts: Number.isFinite(secs) ? new Date(secs * 1e3).toISOString() : null, len };
|
|
@@ -16683,11 +16785,11 @@ app7.get("/directive", requireAdminSession, (c) => {
|
|
|
16683
16785
|
}
|
|
16684
16786
|
const dir = directiveStoreDir(sessionId);
|
|
16685
16787
|
if (!dir) return c.json({ error: "no account" }, 404);
|
|
16686
|
-
const path = resolve21(
|
|
16788
|
+
const path = resolve21(join32(dir, name));
|
|
16687
16789
|
if (!path.startsWith(dir + sep5)) return c.json({ error: "bad reference" }, 400);
|
|
16688
16790
|
let body;
|
|
16689
16791
|
try {
|
|
16690
|
-
body =
|
|
16792
|
+
body = readFileSync24(path, "utf8");
|
|
16691
16793
|
} catch {
|
|
16692
16794
|
return c.json({ error: "not found" }, 404);
|
|
16693
16795
|
}
|
|
@@ -16696,8 +16798,8 @@ app7.get("/directive", requireAdminSession, (c) => {
|
|
|
16696
16798
|
var session_reader_default = app7;
|
|
16697
16799
|
|
|
16698
16800
|
// server/routes/operator-conversations.ts
|
|
16699
|
-
import { readFileSync as
|
|
16700
|
-
import { basename as basename9, dirname as dirname9, join as
|
|
16801
|
+
import { readFileSync as readFileSync25 } from "fs";
|
|
16802
|
+
import { basename as basename9, dirname as dirname9, join as join33 } from "path";
|
|
16701
16803
|
|
|
16702
16804
|
// app/lib/reader/operator-conversations.ts
|
|
16703
16805
|
function operatorConvName(row) {
|
|
@@ -16785,7 +16887,7 @@ app8.get("/conversations", requireAdminSession, async (c) => {
|
|
|
16785
16887
|
}
|
|
16786
16888
|
const cfg = claudeConfigDir();
|
|
16787
16889
|
if (!cfg) return c.json({ conversations: [] });
|
|
16788
|
-
const projectsRoot =
|
|
16890
|
+
const projectsRoot = join33(cfg, "projects");
|
|
16789
16891
|
const userTitles = loadUserTitles(ACCOUNTS_DIR ?? null);
|
|
16790
16892
|
const rows = [];
|
|
16791
16893
|
let sessionRowsExcludedUntagged = 0;
|
|
@@ -16803,7 +16905,7 @@ app8.get("/conversations", requireAdminSession, async (c) => {
|
|
|
16803
16905
|
enumeratedCount += 1;
|
|
16804
16906
|
const sessionId = basename9(path).replace(/\.jsonl$/, "");
|
|
16805
16907
|
const projectDir = dirname9(path);
|
|
16806
|
-
const meta = readSidecarMeta(
|
|
16908
|
+
const meta = readSidecarMeta(join33(projectDir, `${sessionId}.meta.json`));
|
|
16807
16909
|
if (!isReaderChannelSession(meta.role, meta.channel)) continue;
|
|
16808
16910
|
if (multiAccount) {
|
|
16809
16911
|
if (meta.accountId === null) {
|
|
@@ -16815,7 +16917,7 @@ app8.get("/conversations", requireAdminSession, async (c) => {
|
|
|
16815
16917
|
let body = "";
|
|
16816
16918
|
let bodyRead = false;
|
|
16817
16919
|
try {
|
|
16818
|
-
body =
|
|
16920
|
+
body = readFileSync25(path, "utf8");
|
|
16819
16921
|
bodyRead = true;
|
|
16820
16922
|
bodyReadCount += 1;
|
|
16821
16923
|
} catch (err) {
|
|
@@ -16991,7 +17093,7 @@ app8.get("/conversations-all", requireAdminSession, async (c) => {
|
|
|
16991
17093
|
const { value, state } = await getOrCompute("conversations-all", houseId, async () => {
|
|
16992
17094
|
const cfg = claudeConfigDir();
|
|
16993
17095
|
if (!cfg) return { conversations: [] };
|
|
16994
|
-
const projectsRoot =
|
|
17096
|
+
const projectsRoot = join33(cfg, "projects");
|
|
16995
17097
|
const userTitles = loadUserTitles(ACCOUNTS_DIR ?? null);
|
|
16996
17098
|
const validAccounts = listValidAccounts();
|
|
16997
17099
|
const validIds = new Set(validAccounts.map((a) => a.accountId));
|
|
@@ -17011,7 +17113,7 @@ app8.get("/conversations-all", requireAdminSession, async (c) => {
|
|
|
17011
17113
|
enumeratedCount += 1;
|
|
17012
17114
|
const sessionId = basename9(path).replace(/\.jsonl$/, "");
|
|
17013
17115
|
const projectDir = dirname9(path);
|
|
17014
|
-
const meta = readSidecarMeta(
|
|
17116
|
+
const meta = readSidecarMeta(join33(projectDir, `${sessionId}.meta.json`));
|
|
17015
17117
|
if (!isReaderChannelSession(meta.role, meta.channel)) continue;
|
|
17016
17118
|
if (meta.accountId === null) {
|
|
17017
17119
|
untaggedCount += 1;
|
|
@@ -17022,7 +17124,7 @@ app8.get("/conversations-all", requireAdminSession, async (c) => {
|
|
|
17022
17124
|
let body = "";
|
|
17023
17125
|
let bodyRead = false;
|
|
17024
17126
|
try {
|
|
17025
|
-
body =
|
|
17127
|
+
body = readFileSync25(path, "utf8");
|
|
17026
17128
|
bodyRead = true;
|
|
17027
17129
|
bodyReadCount += 1;
|
|
17028
17130
|
} catch (err) {
|
|
@@ -17147,8 +17249,8 @@ app8.get("/conversations-all", requireAdminSession, async (c) => {
|
|
|
17147
17249
|
var operator_conversations_default = app8;
|
|
17148
17250
|
|
|
17149
17251
|
// server/routes/public-reader.ts
|
|
17150
|
-
import { statSync as statSync17, watch as watch6, readFileSync as
|
|
17151
|
-
import { basename as basename10, dirname as dirname10, join as
|
|
17252
|
+
import { statSync as statSync17, watch as watch6, readFileSync as readFileSync26, readdirSync as readdirSync17 } from "fs";
|
|
17253
|
+
import { basename as basename10, dirname as dirname10, join as join34, resolve as resolve23, sep as sep7 } from "path";
|
|
17152
17254
|
|
|
17153
17255
|
// app/lib/reader/delivered-kinds.ts
|
|
17154
17256
|
var PUBLIC_DELIVERED_KINDS = /* @__PURE__ */ new Set([
|
|
@@ -17237,10 +17339,10 @@ function enumeratePublicRows() {
|
|
|
17237
17339
|
const cfg = claudeConfigDir();
|
|
17238
17340
|
if (!cfg) return [];
|
|
17239
17341
|
const rows = [];
|
|
17240
|
-
for (const { path } of enumerateJsonls(
|
|
17342
|
+
for (const { path } of enumerateJsonls(join34(cfg, "projects"))) {
|
|
17241
17343
|
const sessionId = basename10(path).replace(/\.jsonl$/, "");
|
|
17242
17344
|
const projectDir = dirname10(path);
|
|
17243
|
-
const meta = readSidecarMeta(
|
|
17345
|
+
const meta = readSidecarMeta(join34(projectDir, `${sessionId}.meta.json`));
|
|
17244
17346
|
rows.push({
|
|
17245
17347
|
sessionId,
|
|
17246
17348
|
projectDir,
|
|
@@ -17307,15 +17409,15 @@ app9.get("/backfill", (c) => {
|
|
|
17307
17409
|
const beforeRaw = c.req.query("before") ?? "";
|
|
17308
17410
|
const before = Number(beforeRaw);
|
|
17309
17411
|
const cfg = claudeConfigDir();
|
|
17310
|
-
const projectsRoot = cfg ? resolve23(
|
|
17412
|
+
const projectsRoot = cfg ? resolve23(join34(cfg, "projects")) : null;
|
|
17311
17413
|
if (!cfg || !projectsRoot || !SESSION_ID_RE2.test(sessionId) || beforeRaw === "" || !Number.isFinite(before) || before < 0) {
|
|
17312
17414
|
return c.json({ error: "bad session reference" }, 400);
|
|
17313
17415
|
}
|
|
17314
|
-
const jsonlPath = resolve23(
|
|
17416
|
+
const jsonlPath = resolve23(join34(projectDir, `${sessionId}.jsonl`));
|
|
17315
17417
|
if (!jsonlPath.startsWith(projectsRoot + sep7)) {
|
|
17316
17418
|
return c.json({ error: "bad session reference" }, 400);
|
|
17317
17419
|
}
|
|
17318
|
-
const meta = readSidecarMeta(
|
|
17420
|
+
const meta = readSidecarMeta(join34(projectDir, `${sessionId}.meta.json`));
|
|
17319
17421
|
const isPublicWebchat = meta.role === "public" && meta.channel === "webchat";
|
|
17320
17422
|
const owns = visitor.kind === "person" ? meta.personId === visitor.personId : meta.personId === null && meta.visitorId === visitor.visitorId;
|
|
17321
17423
|
if (!(isPublicWebchat && owns)) {
|
|
@@ -17374,15 +17476,15 @@ app9.get("/stream", (c) => {
|
|
|
17374
17476
|
const sessionId = c.req.query("sessionId") ?? "";
|
|
17375
17477
|
const projectDir = c.req.query("projectDir") ?? "";
|
|
17376
17478
|
const cfg = claudeConfigDir();
|
|
17377
|
-
const projectsRoot = cfg ? resolve23(
|
|
17479
|
+
const projectsRoot = cfg ? resolve23(join34(cfg, "projects")) : null;
|
|
17378
17480
|
if (!cfg || !projectsRoot || !SESSION_ID_RE2.test(sessionId)) {
|
|
17379
17481
|
return c.json({ error: "bad session reference" }, 400);
|
|
17380
17482
|
}
|
|
17381
|
-
const jsonlPath = resolve23(
|
|
17483
|
+
const jsonlPath = resolve23(join34(projectDir, `${sessionId}.jsonl`));
|
|
17382
17484
|
if (!jsonlPath.startsWith(projectsRoot + sep7)) {
|
|
17383
17485
|
return c.json({ error: "bad session reference" }, 400);
|
|
17384
17486
|
}
|
|
17385
|
-
const meta = readSidecarMeta(
|
|
17487
|
+
const meta = readSidecarMeta(join34(projectDir, `${sessionId}.meta.json`));
|
|
17386
17488
|
const isPublicWebchat = meta.role === "public" && meta.channel === "webchat";
|
|
17387
17489
|
const owns = visitor.kind === "person" ? meta.personId === visitor.personId : meta.personId === null && meta.visitorId === visitor.visitorId;
|
|
17388
17490
|
if (!(isPublicWebchat && owns)) {
|
|
@@ -17528,7 +17630,7 @@ app9.get("/attachment/:attachmentId", (c) => {
|
|
|
17528
17630
|
try {
|
|
17529
17631
|
dataFile = readdirSync17(dir).find((f) => !f.endsWith(".meta.json") && !f.endsWith(EXTRACTED_TEXT_SUFFIX));
|
|
17530
17632
|
if (!dataFile) throw new Error("no data file");
|
|
17531
|
-
buffer =
|
|
17633
|
+
buffer = readFileSync26(resolve23(dir, dataFile));
|
|
17532
17634
|
} catch {
|
|
17533
17635
|
console.error(`${ATT_TAG} op=denied session=${ses} att=${at} reason=not-found`);
|
|
17534
17636
|
return new Response("Not found", { status: 404 });
|
|
@@ -17550,20 +17652,20 @@ var public_reader_default = app9;
|
|
|
17550
17652
|
|
|
17551
17653
|
// server/routes/webchat.ts
|
|
17552
17654
|
import { basename as basename11, dirname as dirname11 } from "path";
|
|
17553
|
-
import { join as
|
|
17554
|
-
import { existsSync as
|
|
17655
|
+
import { join as join37 } from "path";
|
|
17656
|
+
import { existsSync as existsSync25, readdirSync as readdirSync19, readFileSync as readFileSync29, renameSync as renameSync4, statSync as statSync18, writeFileSync as writeFileSync11 } from "fs";
|
|
17555
17657
|
|
|
17556
17658
|
// server/canonical-webchat-override.ts
|
|
17557
|
-
import { readFileSync as
|
|
17558
|
-
import { join as
|
|
17659
|
+
import { readFileSync as readFileSync27, writeFileSync as writeFileSync9, renameSync as renameSync2 } from "fs";
|
|
17660
|
+
import { join as join35 } from "path";
|
|
17559
17661
|
var FILE = "canonical-webchat-session.json";
|
|
17560
17662
|
var UUID2 = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
|
|
17561
17663
|
function canonicalOverridePath(accountDir) {
|
|
17562
|
-
return
|
|
17664
|
+
return join35(accountDir, FILE);
|
|
17563
17665
|
}
|
|
17564
17666
|
function readRaw(accountDir) {
|
|
17565
17667
|
try {
|
|
17566
|
-
return JSON.parse(
|
|
17668
|
+
return JSON.parse(readFileSync27(canonicalOverridePath(accountDir), "utf8"));
|
|
17567
17669
|
} catch {
|
|
17568
17670
|
return null;
|
|
17569
17671
|
}
|
|
@@ -17676,8 +17778,8 @@ function isNewSessionEffortLevel(value) {
|
|
|
17676
17778
|
}
|
|
17677
17779
|
|
|
17678
17780
|
// ../services/claude-session-manager/src/sidecar-store.ts
|
|
17679
|
-
import { existsSync as
|
|
17680
|
-
import { join as
|
|
17781
|
+
import { existsSync as existsSync24, mkdirSync as mkdirSync4, readdirSync as readdirSync18, readFileSync as readFileSync28, renameSync as renameSync3, unlinkSync as unlinkSync2, writeFileSync as writeFileSync10 } from "fs";
|
|
17782
|
+
import { join as join36 } from "path";
|
|
17681
17783
|
function escapeRegExp(s) {
|
|
17682
17784
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
17683
17785
|
}
|
|
@@ -17685,7 +17787,7 @@ function createSidecarStore(config) {
|
|
|
17685
17787
|
const { suffix, validate: validate3 } = config;
|
|
17686
17788
|
const suffixRe = new RegExp(`${escapeRegExp(suffix)}$`);
|
|
17687
17789
|
function pathFor(sessionsDir, id) {
|
|
17688
|
-
return
|
|
17790
|
+
return join36(sessionsDir, `${id}${suffix}`);
|
|
17689
17791
|
}
|
|
17690
17792
|
function write(sessionsDir, id, record) {
|
|
17691
17793
|
mkdirSync4(sessionsDir, { recursive: true });
|
|
@@ -17697,7 +17799,7 @@ function createSidecarStore(config) {
|
|
|
17697
17799
|
return { ok: true };
|
|
17698
17800
|
} catch (error) {
|
|
17699
17801
|
try {
|
|
17700
|
-
if (
|
|
17802
|
+
if (existsSync24(tmp)) unlinkSync2(tmp);
|
|
17701
17803
|
} catch {
|
|
17702
17804
|
}
|
|
17703
17805
|
return { ok: false, error };
|
|
@@ -17706,7 +17808,7 @@ function createSidecarStore(config) {
|
|
|
17706
17808
|
function readFileAt(path) {
|
|
17707
17809
|
let raw;
|
|
17708
17810
|
try {
|
|
17709
|
-
raw =
|
|
17811
|
+
raw = readFileSync28(path, "utf8");
|
|
17710
17812
|
} catch {
|
|
17711
17813
|
return null;
|
|
17712
17814
|
}
|
|
@@ -17729,10 +17831,10 @@ function createSidecarStore(config) {
|
|
|
17729
17831
|
const out = [];
|
|
17730
17832
|
for (const name of names) {
|
|
17731
17833
|
if (!suffixRe.test(name)) continue;
|
|
17732
|
-
const path =
|
|
17834
|
+
const path = join36(sessionsDir, name);
|
|
17733
17835
|
let raw;
|
|
17734
17836
|
try {
|
|
17735
|
-
raw =
|
|
17837
|
+
raw = readFileSync28(path, "utf8");
|
|
17736
17838
|
} catch {
|
|
17737
17839
|
onSkip?.(name, "unreadable");
|
|
17738
17840
|
continue;
|
|
@@ -17753,7 +17855,7 @@ function createSidecarStore(config) {
|
|
|
17753
17855
|
function clear(sessionsDir, id) {
|
|
17754
17856
|
const path = pathFor(sessionsDir, id);
|
|
17755
17857
|
try {
|
|
17756
|
-
if (
|
|
17858
|
+
if (existsSync24(path)) {
|
|
17757
17859
|
unlinkSync2(path);
|
|
17758
17860
|
return { ok: true, removed: true };
|
|
17759
17861
|
}
|
|
@@ -17805,7 +17907,7 @@ var UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9
|
|
|
17805
17907
|
function locateSession(sessionId) {
|
|
17806
17908
|
const dir = findSessionProjectDir(sessionId);
|
|
17807
17909
|
if (!dir) return { projectDir: null, channel: null, accountId: null };
|
|
17808
|
-
const meta = readSidecarMeta(
|
|
17910
|
+
const meta = readSidecarMeta(join37(dir, `${sessionId}.meta.json`));
|
|
17809
17911
|
return { projectDir: dir, channel: meta.channel, accountId: meta.accountId };
|
|
17810
17912
|
}
|
|
17811
17913
|
function resolveQuoted(sessionId, quotedUuid, sendId) {
|
|
@@ -17823,7 +17925,7 @@ function resolveQuoted(sessionId, quotedUuid, sendId) {
|
|
|
17823
17925
|
let line;
|
|
17824
17926
|
try {
|
|
17825
17927
|
const needle = `"uuid":"${quotedUuid}"`;
|
|
17826
|
-
line =
|
|
17928
|
+
line = readFileSync29(join37(projectDir, `${sessionId}.jsonl`), "utf8").split("\n").find((l) => l.includes(needle));
|
|
17827
17929
|
} catch {
|
|
17828
17930
|
log2(false, 0);
|
|
17829
17931
|
return void 0;
|
|
@@ -17840,7 +17942,7 @@ function resolveQuoted(sessionId, quotedUuid, sendId) {
|
|
|
17840
17942
|
function locateSidecar(sessionId) {
|
|
17841
17943
|
const cfg = claudeConfigDir();
|
|
17842
17944
|
if (!cfg) return null;
|
|
17843
|
-
const projectsRoot =
|
|
17945
|
+
const projectsRoot = join37(cfg, "projects");
|
|
17844
17946
|
let slugs;
|
|
17845
17947
|
try {
|
|
17846
17948
|
slugs = readdirSync19(projectsRoot, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
@@ -17848,8 +17950,8 @@ function locateSidecar(sessionId) {
|
|
|
17848
17950
|
return null;
|
|
17849
17951
|
}
|
|
17850
17952
|
for (const slug of slugs) {
|
|
17851
|
-
const metaPath =
|
|
17852
|
-
if (
|
|
17953
|
+
const metaPath = join37(projectsRoot, slug, `${sessionId}.meta.json`);
|
|
17954
|
+
if (existsSync25(metaPath)) return readSidecarMeta(metaPath);
|
|
17853
17955
|
}
|
|
17854
17956
|
return null;
|
|
17855
17957
|
}
|
|
@@ -17858,7 +17960,7 @@ function readTargetOwner(sessionId) {
|
|
|
17858
17960
|
if (sidecar !== null) return { found: true, owner: sidecar.adminUserId };
|
|
17859
17961
|
const { projectDir } = locateSession(sessionId);
|
|
17860
17962
|
if (projectDir !== null) {
|
|
17861
|
-
return { found: true, owner: readSidecarMeta(
|
|
17963
|
+
return { found: true, owner: readSidecarMeta(join37(projectDir, `${sessionId}.meta.json`)).adminUserId };
|
|
17862
17964
|
}
|
|
17863
17965
|
return { found: false, owner: null };
|
|
17864
17966
|
}
|
|
@@ -17866,7 +17968,7 @@ function readSourceRowMeta(sessionId) {
|
|
|
17866
17968
|
const sidecar = locateSidecar(sessionId);
|
|
17867
17969
|
if (sidecar !== null) return sidecar;
|
|
17868
17970
|
const { projectDir } = locateSession(sessionId);
|
|
17869
|
-
if (projectDir !== null) return readSidecarMeta(
|
|
17971
|
+
if (projectDir !== null) return readSidecarMeta(join37(projectDir, `${sessionId}.meta.json`));
|
|
17870
17972
|
return null;
|
|
17871
17973
|
}
|
|
17872
17974
|
function ownedByRequester(owner, requesterUserId, primaryUserId) {
|
|
@@ -17879,7 +17981,7 @@ function sessionSidecarExists(sessionId) {
|
|
|
17879
17981
|
function jsonlSizeBytes(projectDir, sessionId) {
|
|
17880
17982
|
if (projectDir === null) return null;
|
|
17881
17983
|
try {
|
|
17882
|
-
return statSync18(
|
|
17984
|
+
return statSync18(join37(projectDir, `${sessionId}.jsonl`)).size;
|
|
17883
17985
|
} catch {
|
|
17884
17986
|
return null;
|
|
17885
17987
|
}
|
|
@@ -18007,10 +18109,10 @@ function latestAdminWebchatSessionId(requesterUserId, primaryUserId, scopeAccoun
|
|
|
18007
18109
|
const cfg = claudeConfigDir();
|
|
18008
18110
|
if (!cfg) return null;
|
|
18009
18111
|
let best = null;
|
|
18010
|
-
for (const { path, isSubagent, archived } of enumerateJsonls(
|
|
18112
|
+
for (const { path, isSubagent, archived } of enumerateJsonls(join37(cfg, "projects"))) {
|
|
18011
18113
|
if (isSubagent || archived) continue;
|
|
18012
18114
|
const id = basename11(path).slice(0, -".jsonl".length);
|
|
18013
|
-
const meta = readSidecarMeta(
|
|
18115
|
+
const meta = readSidecarMeta(join37(dirname11(path), `${id}.meta.json`));
|
|
18014
18116
|
if (meta.role !== "admin" || meta.channel !== "webchat") continue;
|
|
18015
18117
|
if (multiAccount && meta.accountId !== scopeAccountId) continue;
|
|
18016
18118
|
let mtimeMs;
|
|
@@ -18370,9 +18472,9 @@ ${timeline}`;
|
|
|
18370
18472
|
console.error(`[webchat:settings] op=${op} outcome=refused value=${value} accountId=none reason=no-account-for-session`);
|
|
18371
18473
|
return c.json({ error: "account unresolved" }, 503);
|
|
18372
18474
|
}
|
|
18373
|
-
const accountJsonPath =
|
|
18475
|
+
const accountJsonPath = join37(account.accountDir, "account.json");
|
|
18374
18476
|
try {
|
|
18375
|
-
const parsed = JSON.parse(
|
|
18477
|
+
const parsed = JSON.parse(readFileSync29(accountJsonPath, "utf8"));
|
|
18376
18478
|
if (op === "model") parsed.adminModel = value;
|
|
18377
18479
|
else if (op === "effort") parsed.effort = value;
|
|
18378
18480
|
else parsed.adminPermissionMode = value;
|
|
@@ -18418,7 +18520,7 @@ ${timeline}`;
|
|
|
18418
18520
|
const cfg2 = claudeConfigDir();
|
|
18419
18521
|
if (cfg2) {
|
|
18420
18522
|
const source2 = resolveBridgeSource(
|
|
18421
|
-
|
|
18523
|
+
join37(cfg2, "sessions"),
|
|
18422
18524
|
target,
|
|
18423
18525
|
(id) => locateSession(id).projectDir !== null
|
|
18424
18526
|
);
|
|
@@ -18445,7 +18547,7 @@ ${timeline}`;
|
|
|
18445
18547
|
const cfg = claudeConfigDir();
|
|
18446
18548
|
let projectDir = null;
|
|
18447
18549
|
if (cfg) {
|
|
18448
|
-
for (const { path } of enumerateJsonls(
|
|
18550
|
+
for (const { path } of enumerateJsonls(join37(cfg, "projects"))) {
|
|
18449
18551
|
if (basename11(path) === `${sessionId}.jsonl`) {
|
|
18450
18552
|
projectDir = dirname11(path);
|
|
18451
18553
|
break;
|
|
@@ -18453,7 +18555,7 @@ ${timeline}`;
|
|
|
18453
18555
|
}
|
|
18454
18556
|
}
|
|
18455
18557
|
if (source === "latest" && requesterUserId !== null) {
|
|
18456
|
-
const owner = readSidecarMeta(
|
|
18558
|
+
const owner = readSidecarMeta(join37(projectDir ?? "", `${sessionId}.meta.json`)).adminUserId;
|
|
18457
18559
|
if (owner !== null && owner !== requesterUserId && requesterUserId !== primaryUserId) {
|
|
18458
18560
|
console.error(`[webchat:inbound] op=session-resolve-foreign key=${sessionId.slice(0, 8)} owner=${owner.slice(0, 8)} requester=${requesterUserId.slice(0, 8)}`);
|
|
18459
18561
|
}
|
|
@@ -18578,13 +18680,13 @@ var webchat_greeting_default = app10;
|
|
|
18578
18680
|
|
|
18579
18681
|
// server/routes/telegram.ts
|
|
18580
18682
|
import { homedir as homedir2 } from "os";
|
|
18581
|
-
import { resolve as resolve25, join as
|
|
18582
|
-
import { existsSync as
|
|
18683
|
+
import { resolve as resolve25, join as join42 } from "path";
|
|
18684
|
+
import { existsSync as existsSync29, readFileSync as readFileSync33 } from "fs";
|
|
18583
18685
|
|
|
18584
18686
|
// ../lib/telegram-managed-bot/src/index.ts
|
|
18585
18687
|
import { randomBytes } from "crypto";
|
|
18586
|
-
import { existsSync as
|
|
18587
|
-
import { dirname as dirname12, join as
|
|
18688
|
+
import { existsSync as existsSync26, readFileSync as readFileSync30, writeFileSync as writeFileSync12, mkdirSync as mkdirSync5 } from "fs";
|
|
18689
|
+
import { dirname as dirname12, join as join38 } from "path";
|
|
18588
18690
|
var TELEGRAM_API = "https://api.telegram.org";
|
|
18589
18691
|
var TELEGRAM_ALLOWED_UPDATES = [
|
|
18590
18692
|
"message",
|
|
@@ -18651,13 +18753,13 @@ async function setTelegramWebhook(botToken, webhookUrl, secretFilePath, fetchImp
|
|
|
18651
18753
|
return { ok: true, secret };
|
|
18652
18754
|
}
|
|
18653
18755
|
function writeTelegramBotEntry(accountDir, entry3) {
|
|
18654
|
-
const configPath3 =
|
|
18655
|
-
if (!
|
|
18756
|
+
const configPath3 = join38(accountDir, "account.json");
|
|
18757
|
+
if (!existsSync26(configPath3)) {
|
|
18656
18758
|
return { ok: false, error: `account.json not found at ${configPath3}` };
|
|
18657
18759
|
}
|
|
18658
18760
|
let config;
|
|
18659
18761
|
try {
|
|
18660
|
-
config = JSON.parse(
|
|
18762
|
+
config = JSON.parse(readFileSync30(configPath3, "utf-8"));
|
|
18661
18763
|
} catch (e) {
|
|
18662
18764
|
return { ok: false, error: `account.json parse failed: ${e.message}` };
|
|
18663
18765
|
}
|
|
@@ -19628,7 +19730,7 @@ function routeTelegramUpdate(input) {
|
|
|
19628
19730
|
|
|
19629
19731
|
// app/lib/telegram/inbound/media.ts
|
|
19630
19732
|
var import_dist5 = __toESM(require_dist4(), 1);
|
|
19631
|
-
import { join as
|
|
19733
|
+
import { join as join39 } from "path";
|
|
19632
19734
|
var TAG30 = "[telegram-inbound]";
|
|
19633
19735
|
var TELEGRAM_MEDIA_DIR = "/tmp/maxy-media";
|
|
19634
19736
|
var DOWNLOAD_TIMEOUT_MS = 45e3;
|
|
@@ -19656,7 +19758,7 @@ async function downloadTelegramMedia(input) {
|
|
|
19656
19758
|
if (!meta.ok) {
|
|
19657
19759
|
result = { ...base, failure: meta.failure };
|
|
19658
19760
|
} else {
|
|
19659
|
-
const path =
|
|
19761
|
+
const path = join39(
|
|
19660
19762
|
dir,
|
|
19661
19763
|
`tg-${(0, import_dist5.pathSafe)(input.botId)}-${(0, import_dist5.pathSafe)(item.fileUniqueId)}.${(0, import_dist5.extensionFor)(meta.filePath, item.mimetype)}`
|
|
19662
19764
|
);
|
|
@@ -20523,8 +20625,8 @@ async function handleDispatchMedia(p) {
|
|
|
20523
20625
|
}
|
|
20524
20626
|
|
|
20525
20627
|
// app/lib/telegram/live-location.ts
|
|
20526
|
-
import { existsSync as
|
|
20527
|
-
import { join as
|
|
20628
|
+
import { existsSync as existsSync27, mkdirSync as mkdirSync6, readFileSync as readFileSync31, readdirSync as readdirSync20, statSync as statSync19, writeFileSync as writeFileSync13 } from "fs";
|
|
20629
|
+
import { join as join40 } from "path";
|
|
20528
20630
|
var TAG37 = "[telegram-inbound]";
|
|
20529
20631
|
var LIVE_LOCATION_FILE = "telegram-live-location.json";
|
|
20530
20632
|
var LIVE_LOCATION_CENSUS_TAG = "[telegram-live-location-census]";
|
|
@@ -20537,9 +20639,9 @@ function isRecord(v) {
|
|
|
20537
20639
|
return typeof r.lat === "number" && Number.isFinite(r.lat) && typeof r.lon === "number" && Number.isFinite(r.lon) && typeof r.at === "number" && Number.isFinite(r.at) && typeof r.botId === "string" && typeof r.livePeriodS === "number" && Number.isFinite(r.livePeriodS);
|
|
20538
20640
|
}
|
|
20539
20641
|
function readAll(path) {
|
|
20540
|
-
if (!
|
|
20642
|
+
if (!existsSync27(path)) return {};
|
|
20541
20643
|
try {
|
|
20542
|
-
const parsed = JSON.parse(
|
|
20644
|
+
const parsed = JSON.parse(readFileSync31(path, "utf-8"));
|
|
20543
20645
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return {};
|
|
20544
20646
|
const out = {};
|
|
20545
20647
|
for (const [k, v] of Object.entries(parsed)) {
|
|
@@ -20556,7 +20658,7 @@ function isExpired(rec, now) {
|
|
|
20556
20658
|
function writeLiveLocation(input) {
|
|
20557
20659
|
const { accountDir, botId, senderId, now, emit } = input;
|
|
20558
20660
|
const key2 = liveLocationKey(botId, senderId);
|
|
20559
|
-
const path =
|
|
20661
|
+
const path = join40(accountDir, LIVE_LOCATION_FILE);
|
|
20560
20662
|
const stored = readAll(path);
|
|
20561
20663
|
const livePeriodS = input.livePeriodS ?? stored[key2]?.livePeriodS ?? null;
|
|
20562
20664
|
if (livePeriodS === null) {
|
|
@@ -20606,8 +20708,8 @@ function liveLocationCensusLine(accountsRoot, now) {
|
|
|
20606
20708
|
let oldestAgeMs = 0;
|
|
20607
20709
|
try {
|
|
20608
20710
|
for (const entry3 of readdirSync20(accountsRoot)) {
|
|
20609
|
-
const path =
|
|
20610
|
-
if (!
|
|
20711
|
+
const path = join40(accountsRoot, entry3, LIVE_LOCATION_FILE);
|
|
20712
|
+
if (!existsSync27(path) || !statSync19(path).isFile()) continue;
|
|
20611
20713
|
for (const rec of Object.values(readAll(path))) {
|
|
20612
20714
|
records5 += 1;
|
|
20613
20715
|
if (isExpired(rec, now)) expired += 1;
|
|
@@ -20626,8 +20728,8 @@ function liveLocationCensusLine(accountsRoot, now) {
|
|
|
20626
20728
|
}
|
|
20627
20729
|
|
|
20628
20730
|
// app/lib/telegram/business-connection.ts
|
|
20629
|
-
import { existsSync as
|
|
20630
|
-
import { join as
|
|
20731
|
+
import { existsSync as existsSync28, mkdirSync as mkdirSync7, readFileSync as readFileSync32, writeFileSync as writeFileSync14 } from "fs";
|
|
20732
|
+
import { join as join41 } from "path";
|
|
20631
20733
|
var TAG38 = "[telegram-inbound]";
|
|
20632
20734
|
var BUSINESS_CONNECTION_FILE = "telegram-business-connection.json";
|
|
20633
20735
|
function truncateConnectionId(id) {
|
|
@@ -20639,9 +20741,9 @@ function isRecord2(v) {
|
|
|
20639
20741
|
return typeof r.id === "string" && r.id.length > 0 && typeof r.isEnabled === "boolean";
|
|
20640
20742
|
}
|
|
20641
20743
|
function readAll2(path) {
|
|
20642
|
-
if (!
|
|
20744
|
+
if (!existsSync28(path)) return {};
|
|
20643
20745
|
try {
|
|
20644
|
-
const parsed = JSON.parse(
|
|
20746
|
+
const parsed = JSON.parse(readFileSync32(path, "utf-8"));
|
|
20645
20747
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return {};
|
|
20646
20748
|
const out = {};
|
|
20647
20749
|
for (const [k, v] of Object.entries(parsed)) {
|
|
@@ -20677,7 +20779,7 @@ function writeBusinessConnection(input) {
|
|
|
20677
20779
|
rights,
|
|
20678
20780
|
at: now
|
|
20679
20781
|
};
|
|
20680
|
-
const path =
|
|
20782
|
+
const path = join41(accountDir, BUSINESS_CONNECTION_FILE);
|
|
20681
20783
|
const all = readAll2(path);
|
|
20682
20784
|
all[botId] = next;
|
|
20683
20785
|
try {
|
|
@@ -20691,12 +20793,12 @@ function writeBusinessConnection(input) {
|
|
|
20691
20793
|
return { written: true, reason: "ok" };
|
|
20692
20794
|
}
|
|
20693
20795
|
function readBusinessConnection(accountDir, botId) {
|
|
20694
|
-
const rec = readAll2(
|
|
20796
|
+
const rec = readAll2(join41(accountDir, BUSINESS_CONNECTION_FILE))[botId];
|
|
20695
20797
|
if (!rec || !rec.isEnabled) return null;
|
|
20696
20798
|
return rec;
|
|
20697
20799
|
}
|
|
20698
20800
|
function readAllBusinessConnections(accountDir) {
|
|
20699
|
-
return readAll2(
|
|
20801
|
+
return readAll2(join41(accountDir, BUSINESS_CONNECTION_FILE));
|
|
20700
20802
|
}
|
|
20701
20803
|
|
|
20702
20804
|
// app/lib/telegram/business-window.ts
|
|
@@ -20752,10 +20854,10 @@ function logValue4(v) {
|
|
|
20752
20854
|
}
|
|
20753
20855
|
function configDirName() {
|
|
20754
20856
|
const platformRoot5 = process.env.MAXY_PLATFORM_ROOT ?? resolve25(process.cwd(), "..");
|
|
20755
|
-
const brandPath =
|
|
20756
|
-
if (
|
|
20857
|
+
const brandPath = join42(platformRoot5, "config", "brand.json");
|
|
20858
|
+
if (existsSync29(brandPath)) {
|
|
20757
20859
|
try {
|
|
20758
|
-
return JSON.parse(
|
|
20860
|
+
return JSON.parse(readFileSync33(brandPath, "utf-8")).configDir ?? ".maxy";
|
|
20759
20861
|
} catch {
|
|
20760
20862
|
}
|
|
20761
20863
|
}
|
|
@@ -20783,7 +20885,7 @@ function provisionedWebhookUrl(c, botId) {
|
|
|
20783
20885
|
}
|
|
20784
20886
|
function accountConfig(accountDir) {
|
|
20785
20887
|
try {
|
|
20786
|
-
return JSON.parse(
|
|
20888
|
+
return JSON.parse(readFileSync33(join42(accountDir, "account.json"), "utf-8"));
|
|
20787
20889
|
} catch {
|
|
20788
20890
|
return {};
|
|
20789
20891
|
}
|
|
@@ -20861,11 +20963,11 @@ app11.post("/", async (c) => {
|
|
|
20861
20963
|
const agentSlug = entryAgentSlug(entry3);
|
|
20862
20964
|
console.error(`${TAG39} op=entry botId=${botId} accountId=${accountId} role=${entry3.role} agent=${agentSlug}`);
|
|
20863
20965
|
const sp = secretPath(botId);
|
|
20864
|
-
if (!
|
|
20966
|
+
if (!existsSync29(sp)) {
|
|
20865
20967
|
console.error(`${TAG39} op=secret botId=${botId} result=missing-file`);
|
|
20866
20968
|
return c.json({ ok: false }, 401);
|
|
20867
20969
|
}
|
|
20868
|
-
const expected =
|
|
20970
|
+
const expected = readFileSync33(sp, "utf-8").trim();
|
|
20869
20971
|
const got = c.req.header("x-telegram-bot-api-secret-token") ?? "";
|
|
20870
20972
|
if (got !== expected) {
|
|
20871
20973
|
console.error(`${TAG39} op=secret botId=${botId} result=mismatch`);
|
|
@@ -21810,21 +21912,21 @@ function mountTelegramRoutes(app81, telegramRoutes) {
|
|
|
21810
21912
|
}
|
|
21811
21913
|
|
|
21812
21914
|
// server/routes/quickbooks.ts
|
|
21813
|
-
import { join as
|
|
21814
|
-
import { existsSync as
|
|
21915
|
+
import { join as join43 } from "path";
|
|
21916
|
+
import { existsSync as existsSync30, readFileSync as readFileSync34, writeFileSync as writeFileSync15, mkdirSync as mkdirSync8, rmSync as rmSync4, renameSync as renameSync5 } from "fs";
|
|
21815
21917
|
var TAG40 = "[quickbooks]";
|
|
21816
21918
|
var INTUIT_TOKEN_URL = "https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer";
|
|
21817
21919
|
var STATE_RE = /^[A-Za-z0-9_-]+$/;
|
|
21818
21920
|
function pendingPath(accountDir, state) {
|
|
21819
|
-
return
|
|
21921
|
+
return join43(accountDir, "secrets", "quickbooks-pending", `${state}.json`);
|
|
21820
21922
|
}
|
|
21821
21923
|
function storePath(accountDir) {
|
|
21822
|
-
return
|
|
21924
|
+
return join43(accountDir, "secrets", "quickbooks.json");
|
|
21823
21925
|
}
|
|
21824
21926
|
async function completeConsent(args) {
|
|
21825
21927
|
const { accountDir, code, realmId } = args;
|
|
21826
21928
|
const state = args.state;
|
|
21827
|
-
if (!state || !STATE_RE.test(state) || !
|
|
21929
|
+
if (!state || !STATE_RE.test(state) || !existsSync30(pendingPath(accountDir, state))) {
|
|
21828
21930
|
console.error(`${TAG40} op=callback state=${state ?? ""} stateValid=false realmId=${realmId ?? ""}`);
|
|
21829
21931
|
return { ok: false, status: 400, message: "Invalid or unknown authorization state.", stateValid: false };
|
|
21830
21932
|
}
|
|
@@ -21838,7 +21940,7 @@ async function completeConsent(args) {
|
|
|
21838
21940
|
try {
|
|
21839
21941
|
let pending;
|
|
21840
21942
|
try {
|
|
21841
|
-
pending = JSON.parse(
|
|
21943
|
+
pending = JSON.parse(readFileSync34(claimFile, "utf-8"));
|
|
21842
21944
|
} catch {
|
|
21843
21945
|
console.error(`${TAG40} op=callback state=${state} stateValid=false realmId=${realmId ?? ""}`);
|
|
21844
21946
|
return { ok: false, status: 400, message: "Authorization state could not be read.", stateValid: false };
|
|
@@ -21851,10 +21953,10 @@ async function completeConsent(args) {
|
|
|
21851
21953
|
if (!code || !realmId) {
|
|
21852
21954
|
return { ok: false, status: 400, message: "Missing code or realmId in the callback.", stateValid: true };
|
|
21853
21955
|
}
|
|
21854
|
-
if (!
|
|
21956
|
+
if (!existsSync30(storePath(accountDir))) {
|
|
21855
21957
|
return { ok: false, status: 500, message: "No QuickBooks credentials are stored for this account.", stateValid: true };
|
|
21856
21958
|
}
|
|
21857
|
-
const store2 = JSON.parse(
|
|
21959
|
+
const store2 = JSON.parse(readFileSync34(storePath(accountDir), "utf-8"));
|
|
21858
21960
|
const form = new URLSearchParams({
|
|
21859
21961
|
grant_type: "authorization_code",
|
|
21860
21962
|
code,
|
|
@@ -21886,9 +21988,9 @@ async function completeConsent(args) {
|
|
|
21886
21988
|
refreshTokenExpiry: now + (body.x_refresh_token_expires_in ?? 864e4) * 1e3,
|
|
21887
21989
|
lastRefresh: now
|
|
21888
21990
|
};
|
|
21889
|
-
mkdirSync8(
|
|
21991
|
+
mkdirSync8(join43(accountDir, "secrets"), { recursive: true });
|
|
21890
21992
|
writeFileSync15(storePath(accountDir), JSON.stringify(store2, null, 2), { mode: 384 });
|
|
21891
|
-
const persisted = JSON.parse(
|
|
21993
|
+
const persisted = JSON.parse(readFileSync34(storePath(accountDir), "utf-8")).connections?.[realmId]?.refreshToken === body.refresh_token;
|
|
21892
21994
|
console.error(`${TAG40} op=token-exchange realmId=${realmId} persisted=${persisted}`);
|
|
21893
21995
|
return { ok: persisted, status: persisted ? 200 : 500, message: persisted ? `Connected company ${realmId}.` : "Failed to persist the connection.", stateValid: true };
|
|
21894
21996
|
} finally {
|
|
@@ -21919,8 +22021,8 @@ var quickbooks_default = app12;
|
|
|
21919
22021
|
|
|
21920
22022
|
// server/routes/onboarding.ts
|
|
21921
22023
|
import { spawn, spawnSync as spawnSync2, execFileSync as execFileSync4 } from "child_process";
|
|
21922
|
-
import { openSync as openSync8, closeSync as closeSync8, appendFileSync as
|
|
21923
|
-
import { createHash as createHash4, randomUUID as
|
|
22024
|
+
import { openSync as openSync8, closeSync as closeSync8, appendFileSync as appendFileSync4, writeFileSync as writeFileSync17, writeSync, existsSync as existsSync32, readFileSync as readFileSync36, unlinkSync as unlinkSync3 } from "fs";
|
|
22025
|
+
import { createHash as createHash4, randomUUID as randomUUID5 } from "crypto";
|
|
21924
22026
|
|
|
21925
22027
|
// app/lib/claude-spawn-env.ts
|
|
21926
22028
|
function claudeBin() {
|
|
@@ -21928,7 +22030,7 @@ function claudeBin() {
|
|
|
21928
22030
|
}
|
|
21929
22031
|
|
|
21930
22032
|
// server/routes/onboarding.ts
|
|
21931
|
-
import { dirname as dirname14, join as
|
|
22033
|
+
import { dirname as dirname14, join as join45 } from "path";
|
|
21932
22034
|
|
|
21933
22035
|
// app/lib/claude-keychain.ts
|
|
21934
22036
|
import { execFileSync as execFileSync3 } from "child_process";
|
|
@@ -22059,8 +22161,8 @@ function readHostCredsBlob(service) {
|
|
|
22059
22161
|
}
|
|
22060
22162
|
|
|
22061
22163
|
// ../lib/admins-write/src/index.ts
|
|
22062
|
-
import { existsSync as
|
|
22063
|
-
import { dirname as dirname13, join as
|
|
22164
|
+
import { existsSync as existsSync31, readFileSync as readFileSync35, writeFileSync as writeFileSync16, renameSync as renameSync6, mkdirSync as mkdirSync9, readdirSync as readdirSync21, statSync as statSync20, appendFileSync as appendFileSync3 } from "fs";
|
|
22165
|
+
import { dirname as dirname13, join as join44 } from "path";
|
|
22064
22166
|
function id8(value) {
|
|
22065
22167
|
return value.slice(0, 8);
|
|
22066
22168
|
}
|
|
@@ -22075,7 +22177,7 @@ function appendUsersAuditLine(audit, fields) {
|
|
|
22075
22177
|
`;
|
|
22076
22178
|
try {
|
|
22077
22179
|
mkdirSync9(dirname13(audit.logFile), { recursive: true, mode: 448 });
|
|
22078
|
-
|
|
22180
|
+
appendFileSync3(audit.logFile, line, { mode: 384 });
|
|
22079
22181
|
} catch (err) {
|
|
22080
22182
|
console.error(
|
|
22081
22183
|
`[users-audit] op=write-failed logFile=${audit.logFile} error=${err instanceof Error ? err.message : String(err)}`
|
|
@@ -22101,8 +22203,8 @@ function writeAdminEntry(input) {
|
|
|
22101
22203
|
const result = { usersJsonResult: "noop", accountJsonResult: "noop" };
|
|
22102
22204
|
try {
|
|
22103
22205
|
let users = [];
|
|
22104
|
-
if (
|
|
22105
|
-
const raw =
|
|
22206
|
+
if (existsSync31(input.usersFile)) {
|
|
22207
|
+
const raw = readFileSync35(input.usersFile, "utf-8").trim();
|
|
22106
22208
|
if (raw) {
|
|
22107
22209
|
const parsed = JSON.parse(raw);
|
|
22108
22210
|
if (!Array.isArray(parsed)) {
|
|
@@ -22144,11 +22246,11 @@ function writeAdminEntry(input) {
|
|
|
22144
22246
|
return result;
|
|
22145
22247
|
}
|
|
22146
22248
|
try {
|
|
22147
|
-
const accountJsonPath =
|
|
22148
|
-
if (!
|
|
22249
|
+
const accountJsonPath = join44(input.accountDir, "account.json");
|
|
22250
|
+
if (!existsSync31(accountJsonPath)) {
|
|
22149
22251
|
throw new Error(`account.json not found at ${accountJsonPath}`);
|
|
22150
22252
|
}
|
|
22151
|
-
const config = JSON.parse(
|
|
22253
|
+
const config = JSON.parse(readFileSync35(accountJsonPath, "utf-8"));
|
|
22152
22254
|
const admins = config.admins ?? [];
|
|
22153
22255
|
if (admins.some((a) => a.userId === input.userId)) {
|
|
22154
22256
|
result.accountJsonResult = "noop";
|
|
@@ -22168,9 +22270,9 @@ function writeAdminEntry(input) {
|
|
|
22168
22270
|
function computeAdminStoreDivergence(input) {
|
|
22169
22271
|
const result = { divergences: 0, accountWithoutUsers: [], usersWithoutAccount: [], errors: [] };
|
|
22170
22272
|
const usersUserIds = /* @__PURE__ */ new Set();
|
|
22171
|
-
if (
|
|
22273
|
+
if (existsSync31(input.usersFile)) {
|
|
22172
22274
|
try {
|
|
22173
|
-
const raw =
|
|
22275
|
+
const raw = readFileSync35(input.usersFile, "utf-8").trim();
|
|
22174
22276
|
if (raw) {
|
|
22175
22277
|
const users = JSON.parse(raw);
|
|
22176
22278
|
for (const u of users) {
|
|
@@ -22182,7 +22284,7 @@ function computeAdminStoreDivergence(input) {
|
|
|
22182
22284
|
}
|
|
22183
22285
|
}
|
|
22184
22286
|
const accountUserIds = /* @__PURE__ */ new Set();
|
|
22185
|
-
if (
|
|
22287
|
+
if (existsSync31(input.accountsDir)) {
|
|
22186
22288
|
let entries2;
|
|
22187
22289
|
try {
|
|
22188
22290
|
entries2 = readdirSync21(input.accountsDir);
|
|
@@ -22192,17 +22294,17 @@ function computeAdminStoreDivergence(input) {
|
|
|
22192
22294
|
}
|
|
22193
22295
|
for (const entry3 of entries2) {
|
|
22194
22296
|
if (entry3.startsWith(".")) continue;
|
|
22195
|
-
const accountDir =
|
|
22297
|
+
const accountDir = join44(input.accountsDir, entry3);
|
|
22196
22298
|
try {
|
|
22197
22299
|
if (!statSync20(accountDir).isDirectory()) continue;
|
|
22198
22300
|
} catch {
|
|
22199
22301
|
continue;
|
|
22200
22302
|
}
|
|
22201
|
-
const accountJsonPath =
|
|
22202
|
-
if (!
|
|
22303
|
+
const accountJsonPath = join44(accountDir, "account.json");
|
|
22304
|
+
if (!existsSync31(accountJsonPath)) continue;
|
|
22203
22305
|
let admins = [];
|
|
22204
22306
|
try {
|
|
22205
|
-
const config = JSON.parse(
|
|
22307
|
+
const config = JSON.parse(readFileSync35(accountJsonPath, "utf-8"));
|
|
22206
22308
|
admins = config.admins ?? [];
|
|
22207
22309
|
} catch (err) {
|
|
22208
22310
|
result.errors.push({ source: accountJsonPath, detail: err instanceof Error ? err.message : String(err) });
|
|
@@ -22250,8 +22352,8 @@ function hashPin2(pin) {
|
|
|
22250
22352
|
return createHash4("sha256").update(pin).digest("hex");
|
|
22251
22353
|
}
|
|
22252
22354
|
function readUsersFile2() {
|
|
22253
|
-
if (!
|
|
22254
|
-
const raw =
|
|
22355
|
+
if (!existsSync32(USERS_FILE)) return null;
|
|
22356
|
+
const raw = readFileSync36(USERS_FILE, "utf-8").trim();
|
|
22255
22357
|
if (!raw) return [];
|
|
22256
22358
|
return JSON.parse(raw);
|
|
22257
22359
|
}
|
|
@@ -22342,7 +22444,7 @@ app13.post("/claude-auth", async (c) => {
|
|
|
22342
22444
|
} catch (err) {
|
|
22343
22445
|
logoutError = err instanceof Error ? err.message : String(err);
|
|
22344
22446
|
}
|
|
22345
|
-
const credentialsPresent =
|
|
22447
|
+
const credentialsPresent = existsSync32(CLAUDE_CREDENTIALS_FILE);
|
|
22346
22448
|
const ranMs = Date.now() - start;
|
|
22347
22449
|
console.log(`[onboarding] op=claude-logout credentialsPresent=${credentialsPresent} ranMs=${ranMs} logoutError=${logoutError ? JSON.stringify(logoutError.slice(0, 120)) : "none"}`);
|
|
22348
22450
|
return c.json({ logged_out: !credentialsPresent });
|
|
@@ -22375,12 +22477,12 @@ app13.post("/claude-auth", async (c) => {
|
|
|
22375
22477
|
const cdpReady = await ensureCdp(transport);
|
|
22376
22478
|
return c.json({ launched: cdpReady });
|
|
22377
22479
|
}
|
|
22378
|
-
const attemptId =
|
|
22480
|
+
const attemptId = randomUUID5().slice(0, 8);
|
|
22379
22481
|
const superseded = pendingAuthLogin;
|
|
22380
22482
|
pendingAuthLogin = { child: null, attemptId, startedAt: Date.now() };
|
|
22381
22483
|
const ended = await endLogin(superseded);
|
|
22382
22484
|
ensureLogDir();
|
|
22383
|
-
|
|
22485
|
+
appendFileSync4(logPath("claude-auth"), `==== attempt ${attemptId} ${(/* @__PURE__ */ new Date()).toISOString()} ====
|
|
22384
22486
|
`);
|
|
22385
22487
|
const claudeAuthLogFd = openSync8(logPath("claude-auth"), "a");
|
|
22386
22488
|
const onClaudeOutput = (chunk) => writeSync(claudeAuthLogFd, chunk);
|
|
@@ -22412,7 +22514,7 @@ app13.post("/claude-auth", async (c) => {
|
|
|
22412
22514
|
});
|
|
22413
22515
|
persistKeychainService(
|
|
22414
22516
|
writebackResult,
|
|
22415
|
-
(service) => writeFileSync17(
|
|
22517
|
+
(service) => writeFileSync17(join45(dirname14(CLAUDE_CREDENTIALS_FILE), ".keychain-service"), service, { mode: 384 }),
|
|
22416
22518
|
(line) => console.log(line)
|
|
22417
22519
|
);
|
|
22418
22520
|
if (pendingAuthLogin?.child === claudeProc2) pendingAuthLogin = null;
|
|
@@ -22470,7 +22572,7 @@ app13.post("/set-pin", async (c) => {
|
|
|
22470
22572
|
const hash = hashPin2(body.pin);
|
|
22471
22573
|
const account = resolveAccount();
|
|
22472
22574
|
const existingOwnerUserId = account?.config.admins?.find((a) => a.role === "owner")?.userId;
|
|
22473
|
-
const userId = existingOwnerUserId ??
|
|
22575
|
+
const userId = existingOwnerUserId ?? randomUUID5();
|
|
22474
22576
|
if (existingOwnerUserId) {
|
|
22475
22577
|
console.log(`[set-pin] reusing existing owner userId=${userId.slice(0, 8)}\u2026 (change-PIN preserves identity)`);
|
|
22476
22578
|
} else {
|
|
@@ -22500,9 +22602,9 @@ app13.post("/set-pin", async (c) => {
|
|
|
22500
22602
|
console.log(`[set-pin] wrote users.json + account.json admins: userId=${userId.slice(0, 8)}\u2026 role=owner`);
|
|
22501
22603
|
if (process.platform === "linux") {
|
|
22502
22604
|
let installOwner = null;
|
|
22503
|
-
if (
|
|
22605
|
+
if (existsSync32(INSTALL_OWNER_FILE)) {
|
|
22504
22606
|
try {
|
|
22505
|
-
const raw =
|
|
22607
|
+
const raw = readFileSync36(INSTALL_OWNER_FILE, "utf-8").trim();
|
|
22506
22608
|
if (raw.length > 0) installOwner = raw;
|
|
22507
22609
|
} catch (err) {
|
|
22508
22610
|
console.error(`[set-pin] install-owner-read-failed path=${INSTALL_OWNER_FILE} error=${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -22648,9 +22750,9 @@ app13.put("/set-pin", requireAdminSession, async (c) => {
|
|
|
22648
22750
|
console.log(`[set-pin] changed PIN in place: userId=${sessionUserId.slice(0, 8)}\u2026`);
|
|
22649
22751
|
if (process.platform === "linux") {
|
|
22650
22752
|
let installOwner = null;
|
|
22651
|
-
if (
|
|
22753
|
+
if (existsSync32(INSTALL_OWNER_FILE)) {
|
|
22652
22754
|
try {
|
|
22653
|
-
const raw =
|
|
22755
|
+
const raw = readFileSync36(INSTALL_OWNER_FILE, "utf-8").trim();
|
|
22654
22756
|
if (raw.length > 0) installOwner = raw;
|
|
22655
22757
|
} catch (err) {
|
|
22656
22758
|
console.error(`[set-pin] install-owner-read-failed path=${INSTALL_OWNER_FILE} error=${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -23107,9 +23209,9 @@ app14.post("/probe", async (c) => {
|
|
|
23107
23209
|
var field_default = app14;
|
|
23108
23210
|
|
|
23109
23211
|
// server/routes/client-error.ts
|
|
23110
|
-
import { appendFileSync as
|
|
23111
|
-
import { join as
|
|
23112
|
-
var CLIENT_ERRORS_LOG =
|
|
23212
|
+
import { appendFileSync as appendFileSync5, existsSync as existsSync33, renameSync as renameSync8, statSync as statSync21 } from "fs";
|
|
23213
|
+
import { join as join46 } from "path";
|
|
23214
|
+
var CLIENT_ERRORS_LOG = join46(LOG_DIR, "client-errors.log");
|
|
23113
23215
|
var MAX_LOG_SIZE = 10 * 1024 * 1024;
|
|
23114
23216
|
var MAX_BODY_SIZE = 8 * 1024;
|
|
23115
23217
|
var MAX_STACK_LEN = 2e3;
|
|
@@ -23166,7 +23268,7 @@ function stackHead(stack) {
|
|
|
23166
23268
|
}
|
|
23167
23269
|
function rotateIfNeeded() {
|
|
23168
23270
|
try {
|
|
23169
|
-
if (!
|
|
23271
|
+
if (!existsSync33(CLIENT_ERRORS_LOG)) return;
|
|
23170
23272
|
const stats = statSync21(CLIENT_ERRORS_LOG);
|
|
23171
23273
|
if (stats.size < MAX_LOG_SIZE) return;
|
|
23172
23274
|
renameSync8(CLIENT_ERRORS_LOG, CLIENT_ERRORS_LOG + ".1");
|
|
@@ -23294,7 +23396,7 @@ app15.post("/", async (c) => {
|
|
|
23294
23396
|
tag: typeof body.tag === "string" ? truncate(body.tag, 32) : void 0,
|
|
23295
23397
|
status: typeof body.status === "number" ? body.status : void 0
|
|
23296
23398
|
};
|
|
23297
|
-
|
|
23399
|
+
appendFileSync5(CLIENT_ERRORS_LOG, JSON.stringify(payload) + "\n", "utf-8");
|
|
23298
23400
|
} catch (err) {
|
|
23299
23401
|
console.error(`[client-error] append failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
23300
23402
|
}
|
|
@@ -23304,7 +23406,7 @@ app15.post("/", async (c) => {
|
|
|
23304
23406
|
var client_error_default = app15;
|
|
23305
23407
|
|
|
23306
23408
|
// server/routes/admin/session.ts
|
|
23307
|
-
import { randomUUID as
|
|
23409
|
+
import { randomUUID as randomUUID6 } from "crypto";
|
|
23308
23410
|
|
|
23309
23411
|
// server/lib/session-timezone.ts
|
|
23310
23412
|
async function resolveSessionTimezone(accountId) {
|
|
@@ -23334,7 +23436,7 @@ async function resolveUserIdentity(accountId, userId) {
|
|
|
23334
23436
|
async function createAdminSession(accountId, thinkingView, userId, userName, role, avatar) {
|
|
23335
23437
|
const account = validateAccountId2(accountId);
|
|
23336
23438
|
const effectiveThinkingView = thinkingView ?? account?.config.thinkingView ?? "default";
|
|
23337
|
-
const signedSessionToken =
|
|
23439
|
+
const signedSessionToken = randomUUID6();
|
|
23338
23440
|
const cacheKey = fingerprintSessionKey(signedSessionToken);
|
|
23339
23441
|
registerSession(cacheKey, "admin", accountId, void 0, userId, userName ?? void 0, role);
|
|
23340
23442
|
if (userId) setWantsPriorConversation(cacheKey);
|
|
@@ -23523,18 +23625,18 @@ app17.get("/", requireAdminSession, async (c) => {
|
|
|
23523
23625
|
var accounts_default = app17;
|
|
23524
23626
|
|
|
23525
23627
|
// server/routes/admin/logs.ts
|
|
23526
|
-
import { existsSync as
|
|
23628
|
+
import { existsSync as existsSync35, readdirSync as readdirSync22, readFileSync as readFileSync37, statSync as statSync22 } from "fs";
|
|
23527
23629
|
import { resolve as resolve26, basename as basename13 } from "path";
|
|
23528
23630
|
|
|
23529
23631
|
// app/lib/logs-read-resolve.ts
|
|
23530
|
-
import { existsSync as
|
|
23531
|
-
import { join as
|
|
23632
|
+
import { existsSync as existsSync34 } from "fs";
|
|
23633
|
+
import { join as join47 } from "path";
|
|
23532
23634
|
function resolveSessionLogPaths(filename, logDirs) {
|
|
23533
23635
|
const tried = [filename];
|
|
23534
23636
|
const hits = [];
|
|
23535
23637
|
for (const dir of logDirs) {
|
|
23536
|
-
const fullPath =
|
|
23537
|
-
if (
|
|
23638
|
+
const fullPath = join47(dir, filename);
|
|
23639
|
+
if (existsSync34(fullPath)) {
|
|
23538
23640
|
hits.push({ path: fullPath, dir });
|
|
23539
23641
|
}
|
|
23540
23642
|
}
|
|
@@ -23559,7 +23661,7 @@ app18.get("/", async (c) => {
|
|
|
23559
23661
|
const filePath = resolve26(dir, safe);
|
|
23560
23662
|
searched.push(filePath);
|
|
23561
23663
|
try {
|
|
23562
|
-
const buffer =
|
|
23664
|
+
const buffer = readFileSync37(filePath);
|
|
23563
23665
|
const onDiskBytes = statSync22(filePath).size;
|
|
23564
23666
|
const headers = {
|
|
23565
23667
|
"Content-Type": "text/plain; charset=utf-8",
|
|
@@ -23624,7 +23726,7 @@ app18.get("/", async (c) => {
|
|
|
23624
23726
|
console.info(`[admin/logs] resolved cacheKey=${cacheKeySlice} sessionId=${sessionIdSlice} via=${primaryId === cacheKey ? "cacheKey" : primaryId === sessionKeyFromConv ? "reverse-lookup" : "sessionId-fallback"}`);
|
|
23625
23727
|
try {
|
|
23626
23728
|
const filename = basename13(hit.path);
|
|
23627
|
-
const buffer =
|
|
23729
|
+
const buffer = readFileSync37(hit.path);
|
|
23628
23730
|
const onDiskBytes = statSync22(hit.path).size;
|
|
23629
23731
|
const headers = {
|
|
23630
23732
|
"Content-Type": "text/plain; charset=utf-8",
|
|
@@ -23659,7 +23761,7 @@ app18.get("/", async (c) => {
|
|
|
23659
23761
|
const seen = /* @__PURE__ */ new Set();
|
|
23660
23762
|
const logs = {};
|
|
23661
23763
|
for (const dir of logDirs) {
|
|
23662
|
-
if (!
|
|
23764
|
+
if (!existsSync35(dir)) continue;
|
|
23663
23765
|
let files;
|
|
23664
23766
|
try {
|
|
23665
23767
|
files = readdirSync22(dir).filter((f) => f.endsWith(".log"));
|
|
@@ -23671,7 +23773,7 @@ app18.get("/", async (c) => {
|
|
|
23671
23773
|
files.filter((f) => !seen.has(f)).map((f) => ({ name: f, mtime: statSync22(resolve26(dir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime).forEach(({ name }) => {
|
|
23672
23774
|
seen.add(name);
|
|
23673
23775
|
try {
|
|
23674
|
-
const content =
|
|
23776
|
+
const content = readFileSync37(resolve26(dir, name));
|
|
23675
23777
|
const tail = content.length > TAIL_BYTES ? content.subarray(content.length - TAIL_BYTES).toString("utf-8") : content.toString("utf-8");
|
|
23676
23778
|
logs[name] = tail.trim() || "(empty)";
|
|
23677
23779
|
} catch (err) {
|
|
@@ -23716,7 +23818,7 @@ var claude_info_default = app19;
|
|
|
23716
23818
|
|
|
23717
23819
|
// server/routes/admin/attachment.ts
|
|
23718
23820
|
import { readFile as readFile7, readdir as readdir2 } from "fs/promises";
|
|
23719
|
-
import { existsSync as
|
|
23821
|
+
import { existsSync as existsSync36 } from "fs";
|
|
23720
23822
|
import { resolve as resolve27 } from "path";
|
|
23721
23823
|
var app20 = new Hono();
|
|
23722
23824
|
var ATTACHMENT_ID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
|
|
@@ -23739,12 +23841,12 @@ app20.get("/:attachmentId", requireAdminSession, async (c) => {
|
|
|
23739
23841
|
}
|
|
23740
23842
|
let accountId = pinnedAccountId;
|
|
23741
23843
|
let dir = uploadsDirFor(accountId, attachmentId);
|
|
23742
|
-
let found =
|
|
23844
|
+
let found = existsSync36(dir);
|
|
23743
23845
|
if (!found) {
|
|
23744
23846
|
for (const candidate of listValidAccounts()) {
|
|
23745
23847
|
if (candidate.accountId === pinnedAccountId) continue;
|
|
23746
23848
|
const candidateDir = uploadsDirFor(candidate.accountId, attachmentId);
|
|
23747
|
-
if (
|
|
23849
|
+
if (existsSync36(candidateDir)) {
|
|
23748
23850
|
accountId = candidate.accountId;
|
|
23749
23851
|
dir = candidateDir;
|
|
23750
23852
|
found = true;
|
|
@@ -23759,7 +23861,7 @@ app20.get("/:attachmentId", requireAdminSession, async (c) => {
|
|
|
23759
23861
|
return new Response("Not found", { status: 404 });
|
|
23760
23862
|
}
|
|
23761
23863
|
const metaPath = resolve27(dir, `${attachmentId}.meta.json`);
|
|
23762
|
-
if (!
|
|
23864
|
+
if (!existsSync36(metaPath)) {
|
|
23763
23865
|
return new Response("Not found", { status: 404 });
|
|
23764
23866
|
}
|
|
23765
23867
|
let meta;
|
|
@@ -23793,7 +23895,7 @@ var attachment_default = app20;
|
|
|
23793
23895
|
|
|
23794
23896
|
// server/routes/admin/session-upload.ts
|
|
23795
23897
|
import { readFile as readFile8 } from "fs/promises";
|
|
23796
|
-
import { existsSync as
|
|
23898
|
+
import { existsSync as existsSync37, statSync as statSync23 } from "fs";
|
|
23797
23899
|
var app21 = new Hono();
|
|
23798
23900
|
app21.get("/", requireAdminSession, async (c) => {
|
|
23799
23901
|
const cacheKey = c.var.cacheKey;
|
|
@@ -23814,7 +23916,7 @@ app21.get("/", requireAdminSession, async (c) => {
|
|
|
23814
23916
|
return c.json({ error: "Not found" }, 404);
|
|
23815
23917
|
}
|
|
23816
23918
|
const resolution = resolveClaudeUploadsPath(`${sessionId}/${file}`);
|
|
23817
|
-
if (!resolution.ok || !
|
|
23919
|
+
if (!resolution.ok || !existsSync37(resolution.absolute) || !statSync23(resolution.absolute).isFile()) {
|
|
23818
23920
|
console.log(`[session-upload] op=miss session=${short2} file=${file} status=404 reason=absent`);
|
|
23819
23921
|
return c.json({ error: "Not found" }, 404);
|
|
23820
23922
|
}
|
|
@@ -23836,13 +23938,13 @@ var session_upload_default = app21;
|
|
|
23836
23938
|
|
|
23837
23939
|
// server/routes/admin/agents.ts
|
|
23838
23940
|
import { resolve as resolve28 } from "path";
|
|
23839
|
-
import { readdirSync as readdirSync24, readFileSync as
|
|
23941
|
+
import { readdirSync as readdirSync24, readFileSync as readFileSync39, existsSync as existsSync39, rmSync as rmSync5, renameSync as renameSync9, mkdirSync as mkdirSync10, writeFileSync as writeFileSync18, chmodSync } from "fs";
|
|
23840
23942
|
import { execFileSync as execFileSync6 } from "child_process";
|
|
23841
23943
|
|
|
23842
23944
|
// ../services/claude-session-manager/src/tool-surface.ts
|
|
23843
|
-
import { readFileSync as
|
|
23945
|
+
import { readFileSync as readFileSync38, readdirSync as readdirSync23, statSync as statSync24, existsSync as existsSync38 } from "fs";
|
|
23844
23946
|
import { createHash as createHash5 } from "crypto";
|
|
23845
|
-
import { join as
|
|
23947
|
+
import { join as join48 } from "path";
|
|
23846
23948
|
|
|
23847
23949
|
// ../services/claude-session-manager/src/canonical-tool-names.ts
|
|
23848
23950
|
function canonicalToolName(plugin, tool) {
|
|
@@ -24086,7 +24188,7 @@ function parseMcpBlock(frontmatter, pluginDir) {
|
|
|
24086
24188
|
function loadToolSurface(pluginsRoots) {
|
|
24087
24189
|
const roots = Array.isArray(pluginsRoots) ? pluginsRoots : [pluginsRoots];
|
|
24088
24190
|
for (const r of roots) {
|
|
24089
|
-
if (!
|
|
24191
|
+
if (!existsSync38(r)) throw new ToolSurfaceError("plugins-root-missing", r);
|
|
24090
24192
|
}
|
|
24091
24193
|
const admin = /* @__PURE__ */ new Set();
|
|
24092
24194
|
const pub = /* @__PURE__ */ new Set();
|
|
@@ -24095,15 +24197,15 @@ function loadToolSurface(pluginsRoots) {
|
|
|
24095
24197
|
const riskByTool = /* @__PURE__ */ new Map();
|
|
24096
24198
|
const manifestPaths = /* @__PURE__ */ new Map();
|
|
24097
24199
|
const loadOne = (pluginsRoot, plugin) => {
|
|
24098
|
-
const pluginDir =
|
|
24200
|
+
const pluginDir = join48(pluginsRoot, plugin);
|
|
24099
24201
|
try {
|
|
24100
24202
|
if (!statSync24(pluginDir).isDirectory()) return;
|
|
24101
24203
|
} catch {
|
|
24102
24204
|
return;
|
|
24103
24205
|
}
|
|
24104
|
-
const manifestPath =
|
|
24105
|
-
if (!
|
|
24106
|
-
const raw =
|
|
24206
|
+
const manifestPath = join48(pluginDir, "PLUGIN.md");
|
|
24207
|
+
if (!existsSync38(manifestPath)) return;
|
|
24208
|
+
const raw = readFileSync38(manifestPath, "utf-8");
|
|
24107
24209
|
const frontmatter = extractFrontmatter(raw, plugin);
|
|
24108
24210
|
const tools = parseToolsBlock(frontmatter, plugin);
|
|
24109
24211
|
if (tools.length === 0) return;
|
|
@@ -24122,7 +24224,7 @@ function loadToolSurface(pluginsRoots) {
|
|
|
24122
24224
|
`${plugin}: mcpServers has entry but manifestPaths is missing \u2014 invariant violated, both maps must be written together`
|
|
24123
24225
|
);
|
|
24124
24226
|
}
|
|
24125
|
-
const priorSha = createHash5("sha256").update(
|
|
24227
|
+
const priorSha = createHash5("sha256").update(readFileSync38(priorPath)).digest("hex").slice(0, 8);
|
|
24126
24228
|
const newSha = createHash5("sha256").update(raw).digest("hex").slice(0, 8);
|
|
24127
24229
|
throw new ToolSurfaceError(
|
|
24128
24230
|
"mcp-plugin-duplicate",
|
|
@@ -24147,9 +24249,9 @@ function loadToolSurface(pluginsRoots) {
|
|
|
24147
24249
|
for (const root of roots) {
|
|
24148
24250
|
const entries2 = readdirSync23(root).sort();
|
|
24149
24251
|
for (const plugin of entries2) {
|
|
24150
|
-
const pluginDir =
|
|
24252
|
+
const pluginDir = join48(root, plugin);
|
|
24151
24253
|
loadOne(root, plugin);
|
|
24152
|
-
const subRoot =
|
|
24254
|
+
const subRoot = join48(pluginDir, "plugins");
|
|
24153
24255
|
let subEntries;
|
|
24154
24256
|
try {
|
|
24155
24257
|
if (!statSync24(subRoot).isDirectory()) continue;
|
|
@@ -24283,7 +24385,7 @@ function agentRiskClass(tools, riskByTool) {
|
|
|
24283
24385
|
// server/routes/admin/agents.ts
|
|
24284
24386
|
var SLUG_UNSAFE = (s) => s.includes("/") || s.includes("..") || s.includes("\\");
|
|
24285
24387
|
function subdirs(dir) {
|
|
24286
|
-
if (!
|
|
24388
|
+
if (!existsSync39(dir)) return [];
|
|
24287
24389
|
try {
|
|
24288
24390
|
return readdirSync24(dir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
|
|
24289
24391
|
} catch {
|
|
@@ -24304,7 +24406,7 @@ var SPECIALISTS_DIR = ["specialists", "agents"];
|
|
|
24304
24406
|
var QUARANTINE_DIR = ["specialists", "agents-disabled"];
|
|
24305
24407
|
var DISABLED_STORE = "agents-disabled.json";
|
|
24306
24408
|
function loadRiskSurface() {
|
|
24307
|
-
const roots = [resolve28(PLATFORM_ROOT, "plugins"), resolve28(PLATFORM_ROOT, "..", "premium-plugins")].filter((r) =>
|
|
24409
|
+
const roots = [resolve28(PLATFORM_ROOT, "plugins"), resolve28(PLATFORM_ROOT, "..", "premium-plugins")].filter((r) => existsSync39(r));
|
|
24308
24410
|
try {
|
|
24309
24411
|
return { riskByTool: loadToolSurface(roots).riskByTool, failed: null };
|
|
24310
24412
|
} catch (err) {
|
|
@@ -24316,8 +24418,8 @@ function loadRiskSurface() {
|
|
|
24316
24418
|
}
|
|
24317
24419
|
function readDisabledStoreStrict(accountDir) {
|
|
24318
24420
|
const p = resolve28(accountDir, DISABLED_STORE);
|
|
24319
|
-
if (!
|
|
24320
|
-
const parsed = JSON.parse(
|
|
24421
|
+
if (!existsSync39(p)) return /* @__PURE__ */ new Set();
|
|
24422
|
+
const parsed = JSON.parse(readFileSync39(p, "utf-8"));
|
|
24321
24423
|
if (!Array.isArray(parsed.disabled)) throw new Error("disabled is not an array");
|
|
24322
24424
|
return new Set(parsed.disabled.filter((x) => typeof x === "string"));
|
|
24323
24425
|
}
|
|
@@ -24335,7 +24437,7 @@ function authoredAgentFiles(accountDir) {
|
|
|
24335
24437
|
const byName = /* @__PURE__ */ new Map();
|
|
24336
24438
|
for (const plugin of subdirs(pluginsDir)) {
|
|
24337
24439
|
const dir = resolve28(pluginsDir, plugin, "agents");
|
|
24338
|
-
if (!
|
|
24440
|
+
if (!existsSync39(dir)) continue;
|
|
24339
24441
|
try {
|
|
24340
24442
|
for (const entry3 of readdirSync24(dir)) {
|
|
24341
24443
|
if (!entry3.endsWith(".md")) continue;
|
|
@@ -24358,7 +24460,7 @@ function shippedSourceDirs(accountDir) {
|
|
|
24358
24460
|
];
|
|
24359
24461
|
}
|
|
24360
24462
|
function readRowFields(path) {
|
|
24361
|
-
const { fm } = splitFrontmatter(
|
|
24463
|
+
const { fm } = splitFrontmatter(readFileSync39(path, "utf-8"));
|
|
24362
24464
|
return {
|
|
24363
24465
|
name: fm.name ?? "",
|
|
24364
24466
|
description: fm.description ?? "",
|
|
@@ -24409,7 +24511,7 @@ function listShipped(accountDir, riskByTool, disabled, riskSurfaceFailed, author
|
|
|
24409
24511
|
const dirs = shippedSourceDirs(accountDir);
|
|
24410
24512
|
const names = /* @__PURE__ */ new Set();
|
|
24411
24513
|
for (const dir of dirs) {
|
|
24412
|
-
if (!
|
|
24514
|
+
if (!existsSync39(dir)) continue;
|
|
24413
24515
|
try {
|
|
24414
24516
|
for (const entry3 of readdirSync24(dir)) if (entry3.endsWith(".md")) names.add(entry3);
|
|
24415
24517
|
} catch (err) {
|
|
@@ -24421,7 +24523,7 @@ function listShipped(accountDir, riskByTool, disabled, riskSurfaceFailed, author
|
|
|
24421
24523
|
let deduped = 0;
|
|
24422
24524
|
let divergent = 0;
|
|
24423
24525
|
for (const filename of [...names].sort()) {
|
|
24424
|
-
const source = dirs.find((d) =>
|
|
24526
|
+
const source = dirs.find((d) => existsSync39(resolve28(d, filename)));
|
|
24425
24527
|
if (!source) continue;
|
|
24426
24528
|
const authoredPaths = source === dirs[0] || source === dirs[1] ? authoredFiles.get(filename) : void 0;
|
|
24427
24529
|
if (authoredPaths) {
|
|
@@ -24439,7 +24541,7 @@ function listShipped(accountDir, riskByTool, disabled, riskSurfaceFailed, author
|
|
|
24439
24541
|
}
|
|
24440
24542
|
}
|
|
24441
24543
|
try {
|
|
24442
|
-
const { fm } = splitFrontmatter(
|
|
24544
|
+
const { fm } = splitFrontmatter(readFileSync39(resolve28(source, filename), "utf-8"));
|
|
24443
24545
|
if (!fm.name) {
|
|
24444
24546
|
shippedSkipped++;
|
|
24445
24547
|
console.error(`[admin/agents] op=list-shipped-skip file=${filename} reason=no-name`);
|
|
@@ -24498,7 +24600,7 @@ function listSpecialists(accountDir, riskByTool, riskSurfaceFailed) {
|
|
|
24498
24600
|
let specialistsSkipped = 0;
|
|
24499
24601
|
for (const plugin of subdirs(pluginsDir).sort()) {
|
|
24500
24602
|
const agentsDirP = resolve28(pluginsDir, plugin, "agents");
|
|
24501
|
-
if (!
|
|
24603
|
+
if (!existsSync39(agentsDirP)) continue;
|
|
24502
24604
|
let entries2;
|
|
24503
24605
|
try {
|
|
24504
24606
|
entries2 = readdirSync24(agentsDirP, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
|
|
@@ -24508,7 +24610,7 @@ function listSpecialists(accountDir, riskByTool, riskSurfaceFailed) {
|
|
|
24508
24610
|
for (const entry3 of entries2) {
|
|
24509
24611
|
if (!entry3.isFile() || !entry3.name.endsWith(".md")) continue;
|
|
24510
24612
|
try {
|
|
24511
|
-
const { fm } = splitFrontmatter(
|
|
24613
|
+
const { fm } = splitFrontmatter(readFileSync39(resolve28(agentsDirP, entry3.name), "utf-8"));
|
|
24512
24614
|
if (!fm.name) {
|
|
24513
24615
|
specialistsSkipped++;
|
|
24514
24616
|
console.error(`[admin/agents] op=list-specialist-skip plugin=${plugin} file=${entry3.name}`);
|
|
@@ -24540,7 +24642,7 @@ function listSpecialists(accountDir, riskByTool, riskSurfaceFailed) {
|
|
|
24540
24642
|
// have the surface claim an agent is stopped while it is still being
|
|
24541
24643
|
// spawned. Absence from the live dir alone is also not the test: a
|
|
24542
24644
|
// specialist that was never activated was never switched off either.
|
|
24543
|
-
disabled:
|
|
24645
|
+
disabled: existsSync39(resolve28(accountDir, ...QUARANTINE_DIR, entry3.name)) && !existsSync39(resolve28(accountDir, ...SPECIALISTS_DIR, entry3.name))
|
|
24544
24646
|
});
|
|
24545
24647
|
} catch {
|
|
24546
24648
|
specialistsSkipped++;
|
|
@@ -24568,16 +24670,16 @@ app22.get("/", requireAdminSession, (c) => {
|
|
|
24568
24670
|
const agents = [];
|
|
24569
24671
|
let skipped = 0;
|
|
24570
24672
|
const agentsDir = resolve28(account.accountDir, "agents");
|
|
24571
|
-
if (
|
|
24673
|
+
if (existsSync39(agentsDir)) {
|
|
24572
24674
|
try {
|
|
24573
24675
|
const entries2 = readdirSync24(agentsDir, { withFileTypes: true });
|
|
24574
24676
|
for (const entry3 of entries2.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
24575
24677
|
if (!entry3.isDirectory()) continue;
|
|
24576
24678
|
if (entry3.name === "admin") continue;
|
|
24577
24679
|
const configPath3 = resolve28(agentsDir, entry3.name, "config.json");
|
|
24578
|
-
if (!
|
|
24680
|
+
if (!existsSync39(configPath3)) continue;
|
|
24579
24681
|
try {
|
|
24580
|
-
const config = JSON.parse(
|
|
24682
|
+
const config = JSON.parse(readFileSync39(configPath3, "utf-8"));
|
|
24581
24683
|
agents.push({
|
|
24582
24684
|
slug: entry3.name,
|
|
24583
24685
|
displayName: config.displayName ?? entry3.name,
|
|
@@ -24657,9 +24759,9 @@ app22.get("/:slug", requireAdminSession, (c) => {
|
|
|
24657
24759
|
if (SLUG_UNSAFE(slug)) return c.json({ error: "Invalid agent slug" }, 400);
|
|
24658
24760
|
if (c.req.query("origin") === "shipped") {
|
|
24659
24761
|
const dirs = shippedSourceDirs(account.accountDir);
|
|
24660
|
-
const source = dirs.find((d) =>
|
|
24762
|
+
const source = dirs.find((d) => existsSync39(resolve28(d, `${slug}.md`)));
|
|
24661
24763
|
if (!source) return c.json({ error: "Agent not found" }, 404);
|
|
24662
|
-
const { fm, body } = splitFrontmatter(
|
|
24764
|
+
const { fm, body } = splitFrontmatter(readFileSync39(resolve28(source, `${slug}.md`), "utf-8"));
|
|
24663
24765
|
const { riskByTool, failed: failed2 } = loadRiskSurface();
|
|
24664
24766
|
const tools = parseToolsLine(fm.tools);
|
|
24665
24767
|
const r = classify(tools, riskByTool, failed2 !== null);
|
|
@@ -24690,8 +24792,8 @@ app22.get("/:slug", requireAdminSession, (c) => {
|
|
|
24690
24792
|
if (pluginParam) {
|
|
24691
24793
|
if (SLUG_UNSAFE(pluginParam)) return c.json({ error: "Invalid plugin" }, 400);
|
|
24692
24794
|
const file = resolve28(account.accountDir, "plugins", pluginParam, "agents", `${slug}.md`);
|
|
24693
|
-
if (!
|
|
24694
|
-
const { fm, body } = splitFrontmatter(
|
|
24795
|
+
if (!existsSync39(file)) return c.json({ error: "Agent not found" }, 404);
|
|
24796
|
+
const { fm, body } = splitFrontmatter(readFileSync39(file, "utf-8"));
|
|
24695
24797
|
const skills = subdirs(resolve28(account.accountDir, "plugins", pluginParam, "skills"));
|
|
24696
24798
|
const { riskByTool, failed: failed2 } = loadRiskSurface();
|
|
24697
24799
|
const tools = parseToolsLine(fm.tools);
|
|
@@ -24721,10 +24823,10 @@ app22.get("/:slug", requireAdminSession, (c) => {
|
|
|
24721
24823
|
}
|
|
24722
24824
|
const agentDir = resolve28(account.accountDir, "agents", slug);
|
|
24723
24825
|
const configPath3 = resolve28(agentDir, "config.json");
|
|
24724
|
-
if (!
|
|
24826
|
+
if (!existsSync39(configPath3)) return c.json({ error: "Agent not found" }, 404);
|
|
24725
24827
|
let config;
|
|
24726
24828
|
try {
|
|
24727
|
-
config = JSON.parse(
|
|
24829
|
+
config = JSON.parse(readFileSync39(configPath3, "utf-8"));
|
|
24728
24830
|
} catch {
|
|
24729
24831
|
console.error(`[admin/agents] op=detail slug=${slug} error="config.json parse failed"`);
|
|
24730
24832
|
return c.json({ error: "Agent config unreadable" }, 500);
|
|
@@ -24734,8 +24836,8 @@ app22.get("/:slug", requireAdminSession, (c) => {
|
|
|
24734
24836
|
for (const { file, key: key2 } of OWNED_DOCS) {
|
|
24735
24837
|
const p = resolve28(agentDir, file);
|
|
24736
24838
|
try {
|
|
24737
|
-
if (
|
|
24738
|
-
docs[key2] =
|
|
24839
|
+
if (existsSync39(p)) {
|
|
24840
|
+
docs[key2] = readFileSync39(p, "utf-8");
|
|
24739
24841
|
present[key2] = true;
|
|
24740
24842
|
} else {
|
|
24741
24843
|
docs[key2] = "";
|
|
@@ -24795,11 +24897,11 @@ function reconcileRoutingProse(accountDir, accountId, op, slug) {
|
|
|
24795
24897
|
}
|
|
24796
24898
|
function reconcileAuthoredRoutingLine(accountDir, accountId, op, source) {
|
|
24797
24899
|
const agentsMd = resolve28(accountDir, "agents", "admin", "AGENTS.md");
|
|
24798
|
-
if (!
|
|
24900
|
+
if (!existsSync39(agentsMd) || !existsSync39(source)) return false;
|
|
24799
24901
|
try {
|
|
24800
|
-
const { fm } = splitFrontmatter(
|
|
24902
|
+
const { fm } = splitFrontmatter(readFileSync39(source, "utf-8"));
|
|
24801
24903
|
if (!fm.name) return false;
|
|
24802
|
-
const lines =
|
|
24904
|
+
const lines = readFileSync39(agentsMd, "utf-8").split("\n");
|
|
24803
24905
|
const prefix = `- **specialists:${fm.name}**:`;
|
|
24804
24906
|
const without = lines.filter((l) => !l.startsWith(prefix));
|
|
24805
24907
|
const next = op === "disable" ? without : [...without, `${prefix} ${fm.description ?? ""}`.trimEnd()];
|
|
@@ -24824,7 +24926,7 @@ app22.post("/:slug/disable", async (c) => {
|
|
|
24824
24926
|
console.error(`[admin/agents] op=disable accountId=${resolved.accountId.slice(0, 8)} slug=${slug} origin=not-authored eligible=false outcome=refused reason=not-user-created`);
|
|
24825
24927
|
return c.json({ error: "Only an agent you created can be switched off here. A shipped agent is stopped by suspending the routines that dispatch it." }, 404);
|
|
24826
24928
|
}
|
|
24827
|
-
if (!
|
|
24929
|
+
if (!existsSync39(live)) {
|
|
24828
24930
|
console.error(`[admin/agents] op=disable accountId=${resolved.accountId.slice(0, 8)} slug=${slug} origin=specialist eligible=true outcome=refused reason=not-dispatchable`);
|
|
24829
24931
|
return c.json({ error: "This agent is not in the dispatchable set, so there is nothing to switch off." }, 409);
|
|
24830
24932
|
}
|
|
@@ -24853,7 +24955,7 @@ app22.post("/:slug/enable", async (c) => {
|
|
|
24853
24955
|
let restored = false;
|
|
24854
24956
|
try {
|
|
24855
24957
|
if (authored) {
|
|
24856
|
-
if (!
|
|
24958
|
+
if (!existsSync39(quarantined)) {
|
|
24857
24959
|
console.error(`[admin/agents] op=enable accountId=${resolved.accountId.slice(0, 8)} slug=${slug} origin=specialist eligible=true outcome=refused reason=not-disabled`);
|
|
24858
24960
|
return c.json({ error: "This agent is not disabled" }, 404);
|
|
24859
24961
|
}
|
|
@@ -24862,11 +24964,11 @@ app22.post("/:slug/enable", async (c) => {
|
|
|
24862
24964
|
restored = true;
|
|
24863
24965
|
} else {
|
|
24864
24966
|
const disabled = readDisabledStoreStrict(resolved.accountDir);
|
|
24865
|
-
if (!
|
|
24967
|
+
if (!existsSync39(quarantined) && !disabled.has(filename)) {
|
|
24866
24968
|
console.error(`[admin/agents] op=enable accountId=${resolved.accountId.slice(0, 8)} slug=${slug} origin=shipped eligible=true outcome=refused reason=not-disabled`);
|
|
24867
24969
|
return c.json({ error: "This agent is not disabled" }, 404);
|
|
24868
24970
|
}
|
|
24869
|
-
if (
|
|
24971
|
+
if (existsSync39(quarantined)) {
|
|
24870
24972
|
mkdirSync10(resolve28(resolved.accountDir, ...SPECIALISTS_DIR), { recursive: true });
|
|
24871
24973
|
renameSync9(quarantined, live);
|
|
24872
24974
|
restored = true;
|
|
@@ -24909,7 +25011,7 @@ app22.delete("/:slug", async (c) => {
|
|
|
24909
25011
|
return c.json({ error: "Not authorized for this account" }, 403);
|
|
24910
25012
|
}
|
|
24911
25013
|
const agentDir = resolve28(account.accountDir, "agents", slug);
|
|
24912
|
-
if (!
|
|
25014
|
+
if (!existsSync39(agentDir)) {
|
|
24913
25015
|
return c.json({ error: "Agent not found" }, 404);
|
|
24914
25016
|
}
|
|
24915
25017
|
try {
|
|
@@ -24952,7 +25054,7 @@ app22.post("/:slug/project", async (c) => {
|
|
|
24952
25054
|
return c.json({ error: "Not authorized for this account" }, 403);
|
|
24953
25055
|
}
|
|
24954
25056
|
const agentDir = resolve28(account.accountDir, "agents", slug);
|
|
24955
|
-
if (!
|
|
25057
|
+
if (!existsSync39(agentDir)) {
|
|
24956
25058
|
console.error(`[admin/agents] op=project rejected reason=agent-not-on-disk accountId=${account.accountId.slice(0, 8)} slug=${slug} probed=${agentDir}`);
|
|
24957
25059
|
return c.json({ error: "Agent not found on disk" }, 404);
|
|
24958
25060
|
}
|
|
@@ -24971,7 +25073,7 @@ var agents_default = app22;
|
|
|
24971
25073
|
// server/routes/admin/sessions.ts
|
|
24972
25074
|
import crypto2 from "crypto";
|
|
24973
25075
|
import { resolve as resolvePath } from "path";
|
|
24974
|
-
import { existsSync as
|
|
25076
|
+
import { existsSync as existsSync40, mkdirSync as mkdirSync11, createWriteStream } from "fs";
|
|
24975
25077
|
|
|
24976
25078
|
// ../lib/admin-conversation-purge/src/index.ts
|
|
24977
25079
|
async function purgeAdminConversationJsonls(args) {
|
|
@@ -25131,7 +25233,7 @@ function validateAndShapeAttachments(raws, conversationAccountId, sessionId, mes
|
|
|
25131
25233
|
let reason = null;
|
|
25132
25234
|
if (!a.attachmentId || !a.filename || !a.mimeType || !a.storagePath) reason = "schema-fail";
|
|
25133
25235
|
else if (a.accountId !== conversationAccountId) reason = "account-mismatch";
|
|
25134
|
-
else if (!
|
|
25236
|
+
else if (!existsSync40(a.storagePath)) reason = "missing-file";
|
|
25135
25237
|
if (reason) {
|
|
25136
25238
|
invalid++;
|
|
25137
25239
|
try {
|
|
@@ -25657,8 +25759,8 @@ app23.put("/:id/label", requireAdminSession, async (c) => {
|
|
|
25657
25759
|
var sessions_default = app23;
|
|
25658
25760
|
|
|
25659
25761
|
// app/lib/claude-agent/spawn-context.ts
|
|
25660
|
-
import { existsSync as
|
|
25661
|
-
import { dirname as dirname15, resolve as resolve29, join as
|
|
25762
|
+
import { existsSync as existsSync41, readFileSync as readFileSync40, readdirSync as readdirSync25, statSync as statSync25 } from "fs";
|
|
25763
|
+
import { dirname as dirname15, resolve as resolve29, join as join49 } from "path";
|
|
25662
25764
|
async function resolveOwnerProfileBlock(accountId, userId) {
|
|
25663
25765
|
if (!userId) return { ok: false, reason: "missing-user-id" };
|
|
25664
25766
|
try {
|
|
@@ -25699,14 +25801,14 @@ function frontmatterField(manifest, field2) {
|
|
|
25699
25801
|
function extractPluginToolDescriptions(pluginDir) {
|
|
25700
25802
|
const out = /* @__PURE__ */ new Map();
|
|
25701
25803
|
const candidates = [
|
|
25702
|
-
|
|
25703
|
-
|
|
25804
|
+
join49(pluginDir, "mcp/dist/index.js"),
|
|
25805
|
+
join49(pluginDir, "mcp/src/index.ts")
|
|
25704
25806
|
];
|
|
25705
25807
|
let raw = null;
|
|
25706
25808
|
for (const path of candidates) {
|
|
25707
|
-
if (!
|
|
25809
|
+
if (!existsSync41(path)) continue;
|
|
25708
25810
|
try {
|
|
25709
|
-
raw =
|
|
25811
|
+
raw = readFileSync40(path, "utf-8");
|
|
25710
25812
|
break;
|
|
25711
25813
|
} catch {
|
|
25712
25814
|
}
|
|
@@ -25756,9 +25858,9 @@ function parseSkillPathsFromFrontmatter(fm) {
|
|
|
25756
25858
|
function listPluginDirs(accountPluginsDir) {
|
|
25757
25859
|
const out = /* @__PURE__ */ new Map();
|
|
25758
25860
|
const platformPlugins = resolve29(PLATFORM_ROOT, "plugins");
|
|
25759
|
-
if (
|
|
25861
|
+
if (existsSync41(platformPlugins)) {
|
|
25760
25862
|
for (const name of readdirSync25(platformPlugins)) {
|
|
25761
|
-
const dir =
|
|
25863
|
+
const dir = join49(platformPlugins, name);
|
|
25762
25864
|
try {
|
|
25763
25865
|
if (statSync25(dir).isDirectory()) out.set(name, dir);
|
|
25764
25866
|
} catch {
|
|
@@ -25766,13 +25868,13 @@ function listPluginDirs(accountPluginsDir) {
|
|
|
25766
25868
|
}
|
|
25767
25869
|
}
|
|
25768
25870
|
const premiumRoot = resolve29(dirname15(PLATFORM_ROOT), "premium-plugins");
|
|
25769
|
-
if (
|
|
25871
|
+
if (existsSync41(premiumRoot)) {
|
|
25770
25872
|
for (const bundle of readdirSync25(premiumRoot)) {
|
|
25771
|
-
const bundlePlugins =
|
|
25772
|
-
if (!
|
|
25873
|
+
const bundlePlugins = join49(premiumRoot, bundle, "plugins");
|
|
25874
|
+
if (!existsSync41(bundlePlugins)) continue;
|
|
25773
25875
|
try {
|
|
25774
25876
|
for (const name of readdirSync25(bundlePlugins)) {
|
|
25775
|
-
const dir =
|
|
25877
|
+
const dir = join49(bundlePlugins, name);
|
|
25776
25878
|
try {
|
|
25777
25879
|
if (statSync25(dir).isDirectory()) out.set(name, dir);
|
|
25778
25880
|
} catch {
|
|
@@ -25782,11 +25884,11 @@ function listPluginDirs(accountPluginsDir) {
|
|
|
25782
25884
|
}
|
|
25783
25885
|
}
|
|
25784
25886
|
}
|
|
25785
|
-
if (accountPluginsDir &&
|
|
25887
|
+
if (accountPluginsDir && existsSync41(accountPluginsDir)) {
|
|
25786
25888
|
try {
|
|
25787
25889
|
for (const name of readdirSync25(accountPluginsDir)) {
|
|
25788
25890
|
if (out.has(name)) continue;
|
|
25789
|
-
const dir =
|
|
25891
|
+
const dir = join49(accountPluginsDir, name);
|
|
25790
25892
|
try {
|
|
25791
25893
|
if (statSync25(dir).isDirectory()) out.set(name, dir);
|
|
25792
25894
|
} catch {
|
|
@@ -25801,11 +25903,11 @@ function accountPluginsDirFor(accountId) {
|
|
|
25801
25903
|
return resolve29(PLATFORM_ROOT, "..", "data/accounts", accountId, "plugins");
|
|
25802
25904
|
}
|
|
25803
25905
|
function listAccountPluginNames(accountPluginsDir) {
|
|
25804
|
-
if (!
|
|
25906
|
+
if (!existsSync41(accountPluginsDir)) return [];
|
|
25805
25907
|
try {
|
|
25806
25908
|
return readdirSync25(accountPluginsDir).filter((name) => {
|
|
25807
25909
|
try {
|
|
25808
|
-
return statSync25(
|
|
25910
|
+
return statSync25(join49(accountPluginsDir, name)).isDirectory();
|
|
25809
25911
|
} catch {
|
|
25810
25912
|
return false;
|
|
25811
25913
|
}
|
|
@@ -25816,9 +25918,9 @@ function listAccountPluginNames(accountPluginsDir) {
|
|
|
25816
25918
|
}
|
|
25817
25919
|
function readEnabledPlugins(accountId) {
|
|
25818
25920
|
const accountFile = resolve29(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
|
|
25819
|
-
if (!
|
|
25921
|
+
if (!existsSync41(accountFile)) return /* @__PURE__ */ new Set();
|
|
25820
25922
|
try {
|
|
25821
|
-
const parsed = JSON.parse(
|
|
25923
|
+
const parsed = JSON.parse(readFileSync40(accountFile, "utf-8"));
|
|
25822
25924
|
return new Set(
|
|
25823
25925
|
Array.isArray(parsed.enabledPlugins) ? parsed.enabledPlugins.filter((p) => typeof p === "string") : []
|
|
25824
25926
|
);
|
|
@@ -25827,10 +25929,10 @@ function readEnabledPlugins(accountId) {
|
|
|
25827
25929
|
}
|
|
25828
25930
|
}
|
|
25829
25931
|
function readFrontmatter(path) {
|
|
25830
|
-
if (!
|
|
25932
|
+
if (!existsSync41(path)) return null;
|
|
25831
25933
|
let raw;
|
|
25832
25934
|
try {
|
|
25833
|
-
raw =
|
|
25935
|
+
raw = readFileSync40(path, "utf-8");
|
|
25834
25936
|
} catch {
|
|
25835
25937
|
return null;
|
|
25836
25938
|
}
|
|
@@ -25848,7 +25950,7 @@ function computeActivePlugins(accountId) {
|
|
|
25848
25950
|
for (const name of emitNames) {
|
|
25849
25951
|
const dir = pluginDirs.get(name);
|
|
25850
25952
|
if (!dir) continue;
|
|
25851
|
-
const fm = readFrontmatter(
|
|
25953
|
+
const fm = readFrontmatter(join49(dir, "PLUGIN.md"));
|
|
25852
25954
|
if (!fm) continue;
|
|
25853
25955
|
const description = frontmatterField(`---
|
|
25854
25956
|
${fm}
|
|
@@ -25865,7 +25967,7 @@ ${fm}
|
|
|
25865
25967
|
`plugin-manifest-tool-coverage plugin=${name} tools=${tools.length} with-desc=${withDesc}`
|
|
25866
25968
|
);
|
|
25867
25969
|
if (toolNames.length > 0 && descMap.size === 0) {
|
|
25868
|
-
const hasSource =
|
|
25970
|
+
const hasSource = existsSync41(join49(dir, "mcp/dist/index.js")) || existsSync41(join49(dir, "mcp/src/index.ts"));
|
|
25869
25971
|
if (hasSource) {
|
|
25870
25972
|
console.warn(
|
|
25871
25973
|
`[spawn-context] WARN plugin=${name} mcp source present but tool-description regex matched zero entries \u2014 SDK upgrade may have changed the registration shape`
|
|
@@ -25875,7 +25977,7 @@ ${fm}
|
|
|
25875
25977
|
const skillPaths = parseSkillPathsFromFrontmatter(fm);
|
|
25876
25978
|
const skills = [];
|
|
25877
25979
|
for (const relPath of skillPaths) {
|
|
25878
|
-
const skillPath =
|
|
25980
|
+
const skillPath = join49(dir, relPath);
|
|
25879
25981
|
const skillFm = readFrontmatter(skillPath);
|
|
25880
25982
|
if (!skillFm) continue;
|
|
25881
25983
|
const skillName = frontmatterField(`---
|
|
@@ -25892,7 +25994,7 @@ ${skillFm}
|
|
|
25892
25994
|
}
|
|
25893
25995
|
function computeSpecialistDomains(accountId) {
|
|
25894
25996
|
const specialistsDir = resolve29(PLATFORM_ROOT, "..", "data/accounts", accountId, "specialists", "agents");
|
|
25895
|
-
if (!
|
|
25997
|
+
if (!existsSync41(specialistsDir)) return [];
|
|
25896
25998
|
let entries2;
|
|
25897
25999
|
try {
|
|
25898
26000
|
entries2 = readdirSync25(specialistsDir);
|
|
@@ -25919,7 +26021,7 @@ function computeSpecialistDomains(accountId) {
|
|
|
25919
26021
|
const out = [];
|
|
25920
26022
|
for (const file of entries2.sort()) {
|
|
25921
26023
|
if (!file.endsWith(".md")) continue;
|
|
25922
|
-
const fm = readFrontmatter(
|
|
26024
|
+
const fm = readFrontmatter(join49(specialistsDir, file));
|
|
25923
26025
|
if (!fm) continue;
|
|
25924
26026
|
const wrapped = `---
|
|
25925
26027
|
${fm}
|
|
@@ -25938,10 +26040,10 @@ ${fm}
|
|
|
25938
26040
|
}
|
|
25939
26041
|
function computeDormantPlugins(accountId) {
|
|
25940
26042
|
const accountFile = resolve29(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
|
|
25941
|
-
if (!
|
|
26043
|
+
if (!existsSync41(accountFile)) return [];
|
|
25942
26044
|
let enabled;
|
|
25943
26045
|
try {
|
|
25944
|
-
const raw =
|
|
26046
|
+
const raw = readFileSync40(accountFile, "utf-8");
|
|
25945
26047
|
const parsed = JSON.parse(raw);
|
|
25946
26048
|
enabled = new Set(
|
|
25947
26049
|
Array.isArray(parsed.enabledPlugins) ? parsed.enabledPlugins.filter((p) => typeof p === "string") : []
|
|
@@ -25953,7 +26055,7 @@ function computeDormantPlugins(accountId) {
|
|
|
25953
26055
|
return [];
|
|
25954
26056
|
}
|
|
25955
26057
|
const pluginsDir = resolve29(PLATFORM_ROOT, "plugins");
|
|
25956
|
-
if (!
|
|
26058
|
+
if (!existsSync41(pluginsDir)) return [];
|
|
25957
26059
|
let entries2;
|
|
25958
26060
|
try {
|
|
25959
26061
|
entries2 = readdirSync25(pluginsDir);
|
|
@@ -25964,10 +26066,10 @@ function computeDormantPlugins(accountId) {
|
|
|
25964
26066
|
for (const name of entries2) {
|
|
25965
26067
|
if (enabled.has(name)) continue;
|
|
25966
26068
|
const manifestPath = resolve29(pluginsDir, name, "PLUGIN.md");
|
|
25967
|
-
if (!
|
|
26069
|
+
if (!existsSync41(manifestPath)) continue;
|
|
25968
26070
|
let manifest;
|
|
25969
26071
|
try {
|
|
25970
|
-
manifest =
|
|
26072
|
+
manifest = readFileSync40(manifestPath, "utf-8");
|
|
25971
26073
|
} catch {
|
|
25972
26074
|
continue;
|
|
25973
26075
|
}
|
|
@@ -25981,13 +26083,13 @@ function computeDormantPlugins(accountId) {
|
|
|
25981
26083
|
}
|
|
25982
26084
|
|
|
25983
26085
|
// server/routes/admin/claude-sessions.ts
|
|
25984
|
-
import { existsSync as
|
|
26086
|
+
import { existsSync as existsSync42, readFileSync as readFileSync41 } from "fs";
|
|
25985
26087
|
import { resolve as resolve30 } from "path";
|
|
25986
26088
|
function readTunnelState(brandConfigDir) {
|
|
25987
26089
|
const statePath = `${process.env.HOME ?? ""}/${brandConfigDir}/cloudflared/tunnel.state`;
|
|
25988
|
-
if (!
|
|
26090
|
+
if (!existsSync42(statePath)) return null;
|
|
25989
26091
|
try {
|
|
25990
|
-
const parsed = JSON.parse(
|
|
26092
|
+
const parsed = JSON.parse(readFileSync41(statePath, "utf-8"));
|
|
25991
26093
|
const tunnelId = typeof parsed.tunnelId === "string" ? parsed.tunnelId : null;
|
|
25992
26094
|
const tunnelName = typeof parsed.tunnelName === "string" ? parsed.tunnelName : null;
|
|
25993
26095
|
const domain = typeof parsed.domain === "string" ? parsed.domain : null;
|
|
@@ -26001,7 +26103,7 @@ function resolveTunnelUrl() {
|
|
|
26001
26103
|
const platformRoot5 = process.env.MAXY_PLATFORM_ROOT ?? process.env.PLATFORM_ROOT ?? resolve30(process.cwd(), "..");
|
|
26002
26104
|
let brand;
|
|
26003
26105
|
try {
|
|
26004
|
-
brand = JSON.parse(
|
|
26106
|
+
brand = JSON.parse(readFileSync41(resolve30(platformRoot5, "config", "brand.json"), "utf-8"));
|
|
26005
26107
|
} catch {
|
|
26006
26108
|
return null;
|
|
26007
26109
|
}
|
|
@@ -26202,7 +26304,7 @@ app25.post("/", async (c) => {
|
|
|
26202
26304
|
var log_ingest_default = app25;
|
|
26203
26305
|
|
|
26204
26306
|
// server/routes/admin/session-blocked.ts
|
|
26205
|
-
import { join as
|
|
26307
|
+
import { join as join50 } from "path";
|
|
26206
26308
|
var TAG44 = "[blocked-tool-notify]";
|
|
26207
26309
|
function isLoopbackAddr4(addr) {
|
|
26208
26310
|
return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
|
|
@@ -26249,7 +26351,7 @@ app26.post("/", async (c) => {
|
|
|
26249
26351
|
if (!tool) return c.json({ error: "tool-required" }, 400);
|
|
26250
26352
|
const text = blockedNotificationText({ sessionId, agentId, tool, blockedForMs });
|
|
26251
26353
|
const projectDir = findSessionProjectDir(sessionId);
|
|
26252
|
-
const meta = projectDir ? readSidecarMeta(
|
|
26354
|
+
const meta = projectDir ? readSidecarMeta(join50(projectDir, `${sessionId}.meta.json`)) : { role: null, channel: null, senderId: null, accountId: null };
|
|
26253
26355
|
const account = validateAccountId2(meta.accountId ?? "");
|
|
26254
26356
|
if (!account) {
|
|
26255
26357
|
console.error(
|
|
@@ -26444,11 +26546,11 @@ app27.get("/", requireAdminSession, async (c) => {
|
|
|
26444
26546
|
var events_default = app27;
|
|
26445
26547
|
|
|
26446
26548
|
// server/routes/admin/files.ts
|
|
26447
|
-
import { createReadStream as createReadStream2, createWriteStream as createWriteStream2, existsSync as
|
|
26549
|
+
import { createReadStream as createReadStream2, createWriteStream as createWriteStream2, existsSync as existsSync43 } from "fs";
|
|
26448
26550
|
import { readdir as readdir4, readFile as readFile10, stat as stat6, mkdir as mkdir2, unlink as unlink3, rename as rename3, rmdir } from "fs/promises";
|
|
26449
26551
|
import { realpathSync as realpathSync7 } from "fs";
|
|
26450
|
-
import { randomUUID as
|
|
26451
|
-
import { basename as basename15, dirname as dirname16, join as
|
|
26552
|
+
import { randomUUID as randomUUID7 } from "crypto";
|
|
26553
|
+
import { basename as basename15, dirname as dirname16, join as join52, relative as relative6, resolve as resolve32, sep as sep9 } from "path";
|
|
26452
26554
|
import { Readable as Readable2 } from "stream";
|
|
26453
26555
|
|
|
26454
26556
|
// ../lib/graph-trash/src/index.ts
|
|
@@ -26766,7 +26868,7 @@ async function cascadeDeleteDocument(params) {
|
|
|
26766
26868
|
|
|
26767
26869
|
// app/lib/file-index.ts
|
|
26768
26870
|
import * as fsp from "fs/promises";
|
|
26769
|
-
import { resolve as resolve31, relative as relative5, join as
|
|
26871
|
+
import { resolve as resolve31, relative as relative5, join as join51, basename as basename14, extname, sep as sep8 } from "path";
|
|
26770
26872
|
import { tmpdir as tmpdir3 } from "os";
|
|
26771
26873
|
import { execFile } from "child_process";
|
|
26772
26874
|
import { promisify } from "util";
|
|
@@ -26848,7 +26950,7 @@ async function extractPdf(absolute) {
|
|
|
26848
26950
|
return stdout.trim();
|
|
26849
26951
|
}
|
|
26850
26952
|
async function ocrPdf(absolute) {
|
|
26851
|
-
const outPdf =
|
|
26953
|
+
const outPdf = join51(tmpdir3(), `file-index-ocr-${process.pid}-${Date.now()}.pdf`);
|
|
26852
26954
|
try {
|
|
26853
26955
|
await execFileAsync(
|
|
26854
26956
|
"ocrmypdf",
|
|
@@ -26910,7 +27012,7 @@ async function readDisplayName(absolute) {
|
|
|
26910
27012
|
const stem = dot === -1 ? base : base.slice(0, dot);
|
|
26911
27013
|
if (base === `${stem}.meta.json`) return null;
|
|
26912
27014
|
try {
|
|
26913
|
-
const raw = await fsp.readFile(
|
|
27015
|
+
const raw = await fsp.readFile(join51(dir, `${stem}.meta.json`), "utf-8");
|
|
26914
27016
|
const meta = JSON.parse(raw);
|
|
26915
27017
|
const dn = meta.displayName ?? meta.filename;
|
|
26916
27018
|
return typeof dn === "string" && dn.length > 0 ? dn : null;
|
|
@@ -26931,7 +27033,7 @@ async function walkSubtree(root, dataRoot, out) {
|
|
|
26931
27033
|
for (const entry3 of entries2) {
|
|
26932
27034
|
if (entry3.isSymbolicLink()) continue;
|
|
26933
27035
|
if (entry3.isDirectory() && entry3.name === ".uploads-tmp") continue;
|
|
26934
|
-
const abs =
|
|
27036
|
+
const abs = join51(root, entry3.name);
|
|
26935
27037
|
if (entry3.isDirectory()) {
|
|
26936
27038
|
const sub = await walkSubtree(abs, dataRoot, out);
|
|
26937
27039
|
if (!sub.clean) clean = false;
|
|
@@ -27304,7 +27406,7 @@ var UPLOAD_TMP_DIR = ".uploads-tmp";
|
|
|
27304
27406
|
var UUID_RE3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
27305
27407
|
async function readMeta2(absDir, baseName) {
|
|
27306
27408
|
try {
|
|
27307
|
-
const raw = await readFile10(
|
|
27409
|
+
const raw = await readFile10(join52(absDir, `${baseName}.meta.json`), "utf8");
|
|
27308
27410
|
const parsed = JSON.parse(raw);
|
|
27309
27411
|
if (typeof parsed?.filename === "string") {
|
|
27310
27412
|
return { filename: parsed.filename, mimeType: typeof parsed.mimeType === "string" ? parsed.mimeType : void 0 };
|
|
@@ -27359,7 +27461,7 @@ async function servableFilesIn(dirAbs, uuid) {
|
|
|
27359
27461
|
}
|
|
27360
27462
|
async function enrich(absolute, entry3, accountNames) {
|
|
27361
27463
|
if (entry3.kind === "directory" && UUID_RE3.test(entry3.name)) {
|
|
27362
|
-
const dirAbs =
|
|
27464
|
+
const dirAbs = join52(absolute, entry3.name);
|
|
27363
27465
|
const meta = await readMeta2(dirAbs, entry3.name);
|
|
27364
27466
|
if (meta?.filename) {
|
|
27365
27467
|
const servable = await servableFilesIn(dirAbs, entry3.name);
|
|
@@ -27368,7 +27470,7 @@ async function enrich(absolute, entry3, accountNames) {
|
|
|
27368
27470
|
let size = null;
|
|
27369
27471
|
let modifiedAt = entry3.modifiedAt;
|
|
27370
27472
|
try {
|
|
27371
|
-
const st = await stat6(
|
|
27473
|
+
const st = await stat6(join52(dirAbs, innerName));
|
|
27372
27474
|
size = st.size;
|
|
27373
27475
|
modifiedAt = st.mtime.toISOString();
|
|
27374
27476
|
} catch {
|
|
@@ -27580,7 +27682,7 @@ app28.get("/", requireAdminSession, async (c) => {
|
|
|
27580
27682
|
const childRel = relPath === "" || relPath === "." ? name : `${relPath}/${name}`;
|
|
27581
27683
|
const protectedEntry = isProtectedFromDeletion(childRel).protected;
|
|
27582
27684
|
try {
|
|
27583
|
-
const entryPath =
|
|
27685
|
+
const entryPath = join52(absolute, name);
|
|
27584
27686
|
const s = await stat6(entryPath);
|
|
27585
27687
|
entries2.push({
|
|
27586
27688
|
name,
|
|
@@ -27609,7 +27711,7 @@ app28.get("/", requireAdminSession, async (c) => {
|
|
|
27609
27711
|
const displayPath = buildDisplayPath(relPath, accountNames);
|
|
27610
27712
|
if (groupReq || isAccountRoot(relPath)) {
|
|
27611
27713
|
const acctId = relPath.split("/")[1] ?? accountId;
|
|
27612
|
-
const schemaMd = await readFile10(
|
|
27714
|
+
const schemaMd = await readFile10(join52(absolute, "SCHEMA.md"), "utf8").catch(() => null);
|
|
27613
27715
|
const groups = classifyAccountRoot(schemaMd, entries2.map((e) => e.name));
|
|
27614
27716
|
console.error(
|
|
27615
27717
|
`[data-schema] op=classify account=${acctId} status=${groups.parsed ? "ok" : "parse-failed"} reason=${groups.reason} entries=${entries2.length} home=${groups.home.join(",") || "none"} system=${groups.system.length} unknown=${groups.unknown.join(",") || "none"}`
|
|
@@ -27647,7 +27749,7 @@ app28.get("/", requireAdminSession, async (c) => {
|
|
|
27647
27749
|
for (const name of homeDirs) {
|
|
27648
27750
|
const base = byName.get(name);
|
|
27649
27751
|
try {
|
|
27650
|
-
const dirents = await readdir4(
|
|
27752
|
+
const dirents = await readdir4(join52(absolute, name), { withFileTypes: true });
|
|
27651
27753
|
const visible = dirents.filter((d) => !d.name.startsWith("."));
|
|
27652
27754
|
visible.sort((a, b) => {
|
|
27653
27755
|
const ad = a.isDirectory() ? 0 : 1;
|
|
@@ -27712,7 +27814,7 @@ app28.get("/download", requireAdminSession, async (c) => {
|
|
|
27712
27814
|
console.error(`[data] op=scratchpad-no-session sessionId="${sessionId.slice(0, 8)}\u2026"`);
|
|
27713
27815
|
return c.json({ error: "Not found" }, 404);
|
|
27714
27816
|
}
|
|
27715
|
-
const meta = readSidecarMeta(
|
|
27817
|
+
const meta = readSidecarMeta(join52(projectDir, `${sessionId}.meta.json`));
|
|
27716
27818
|
if (!meta.accountId || meta.accountId !== accountId) {
|
|
27717
27819
|
console.error(`[data] account-scope-blocked root="scratchpad" sessionId="${sessionId.slice(0, 8)}\u2026" account=${accountId.slice(0, 8)}\u2026`);
|
|
27718
27820
|
return c.json({ error: "Not found" }, 404);
|
|
@@ -27806,7 +27908,7 @@ async function* walkRegularFiles(dirAbsolute) {
|
|
|
27806
27908
|
const dirents = await readdir4(dirAbsolute, { withFileTypes: true });
|
|
27807
27909
|
for (const d of dirents) {
|
|
27808
27910
|
if (d.isSymbolicLink()) continue;
|
|
27809
|
-
const child =
|
|
27911
|
+
const child = join52(dirAbsolute, d.name);
|
|
27810
27912
|
if (d.isDirectory()) {
|
|
27811
27913
|
yield* walkRegularFiles(child);
|
|
27812
27914
|
continue;
|
|
@@ -27912,7 +28014,7 @@ async function resolveUploadTarget(c, accountId, uid) {
|
|
|
27912
28014
|
const base = resolveSharedOrOwnAccountWrite(rawDir, accountId, "POST /api/admin/files/upload");
|
|
27913
28015
|
if (!base.ok) return { ok: false, status: base.status, error: base.error };
|
|
27914
28016
|
const relDir = relpath ? dirname16(relpath) : ".";
|
|
27915
|
-
const destRel = relDir === "." ? base.relative :
|
|
28017
|
+
const destRel = relDir === "." ? base.relative : join52(base.relative, relDir);
|
|
27916
28018
|
if ((0, import_dist.isSharedPath)(destRel)) {
|
|
27917
28019
|
const gate2 = gateSharedWrite(base.absolute, destRel, accountId, "POST /api/admin/files/upload");
|
|
27918
28020
|
if (!gate2.ok) return { ok: false, status: gate2.status, error: gate2.error };
|
|
@@ -27962,7 +28064,7 @@ app28.post("/upload", requireAdminSession, async (c) => {
|
|
|
27962
28064
|
if (c.req.query("uploadId") !== void 0) {
|
|
27963
28065
|
return handleChunkUpload(c, accountId);
|
|
27964
28066
|
}
|
|
27965
|
-
const uid = `${Date.now()}-${
|
|
28067
|
+
const uid = `${Date.now()}-${randomUUID7().slice(0, 8)}`;
|
|
27966
28068
|
const declaredBytes = c.req.header("content-length") ?? "unknown";
|
|
27967
28069
|
const target = await resolveUploadTarget(c, accountId, uid);
|
|
27968
28070
|
if (!target.ok) return c.json({ error: target.error }, target.status);
|
|
@@ -27991,7 +28093,7 @@ app28.post("/upload", requireAdminSession, async (c) => {
|
|
|
27991
28093
|
});
|
|
27992
28094
|
await unlink3(tmpPath).catch(() => {
|
|
27993
28095
|
});
|
|
27994
|
-
const tempRemoved = !
|
|
28096
|
+
const tempRemoved = !existsSync43(tmpPath);
|
|
27995
28097
|
console.error(`[data-upload] op=cleanup uid=${uid} tempRemoved=${tempRemoved}`);
|
|
27996
28098
|
};
|
|
27997
28099
|
const reader = body.getReader();
|
|
@@ -28065,7 +28167,7 @@ async function discardChunkUpload(uploadId, state) {
|
|
|
28065
28167
|
});
|
|
28066
28168
|
await unlink3(state.tmpPath).catch(() => {
|
|
28067
28169
|
});
|
|
28068
|
-
const tempRemoved = !
|
|
28170
|
+
const tempRemoved = !existsSync43(state.tmpPath);
|
|
28069
28171
|
console.error(`[data-upload] op=cleanup uid=${uploadId} tempRemoved=${tempRemoved}`);
|
|
28070
28172
|
}
|
|
28071
28173
|
async function writeChunkBody(body, out, alreadyReceived, ceiling) {
|
|
@@ -28298,7 +28400,7 @@ app28.delete("/", requireAdminSession, async (c) => {
|
|
|
28298
28400
|
const dot = base.lastIndexOf(".");
|
|
28299
28401
|
const stem = dot === -1 ? base : base.slice(0, dot);
|
|
28300
28402
|
const containerDir = dirname16(absolute);
|
|
28301
|
-
const sidecarPath = UUID_RE3.test(stem) && base !== `${stem}.meta.json` ?
|
|
28403
|
+
const sidecarPath = UUID_RE3.test(stem) && base !== `${stem}.meta.json` ? join52(containerDir, `${stem}.meta.json`) : null;
|
|
28302
28404
|
const isAttachmentContainer = UUID_RE3.test(stem) && basename15(containerDir) === stem;
|
|
28303
28405
|
await unlink3(absolute);
|
|
28304
28406
|
if (sidecarPath) {
|
|
@@ -28308,7 +28410,7 @@ app28.delete("/", requireAdminSession, async (c) => {
|
|
|
28308
28410
|
}
|
|
28309
28411
|
}
|
|
28310
28412
|
if (isAttachmentContainer) {
|
|
28311
|
-
await unlink3(
|
|
28413
|
+
await unlink3(join52(containerDir, `${stem}${EXTRACTED_TEXT_SUFFIX}`)).catch(() => {
|
|
28312
28414
|
});
|
|
28313
28415
|
await rmdir(containerDir).catch(() => {
|
|
28314
28416
|
});
|
|
@@ -29423,8 +29525,8 @@ function isHiddenByDefault(label) {
|
|
|
29423
29525
|
|
|
29424
29526
|
// server/lib/top-level-labels.ts
|
|
29425
29527
|
var import_dist14 = __toESM(require_dist9(), 1);
|
|
29426
|
-
import { readdirSync as readdirSync26, readFileSync as
|
|
29427
|
-
import { join as
|
|
29528
|
+
import { readdirSync as readdirSync26, readFileSync as readFileSync42 } from "fs";
|
|
29529
|
+
import { join as join53, resolve as resolve33 } from "path";
|
|
29428
29530
|
var STATIC_TOP_LEVEL_LABELS = Object.freeze(
|
|
29429
29531
|
/* @__PURE__ */ new Set([
|
|
29430
29532
|
// Base-schema infra (schema-base.md has no top-level section).
|
|
@@ -29528,7 +29630,7 @@ function parseTopLevelLabels(content) {
|
|
|
29528
29630
|
}
|
|
29529
29631
|
function resolveReferencesDir() {
|
|
29530
29632
|
if (process.env.MAXY_PLATFORM_ROOT) {
|
|
29531
|
-
return
|
|
29633
|
+
return join53(process.env.MAXY_PLATFORM_ROOT, "plugins", "memory", "references");
|
|
29532
29634
|
}
|
|
29533
29635
|
return resolve33(import.meta.dirname, "../../../plugins/memory/references");
|
|
29534
29636
|
}
|
|
@@ -29538,7 +29640,7 @@ function parseTableTopLevelLabels(referencesDir) {
|
|
|
29538
29640
|
try {
|
|
29539
29641
|
const fileNames = readdirSync26(referencesDir).filter((f) => f.startsWith("schema-") && f.endsWith(".md")).sort();
|
|
29540
29642
|
for (const fileName of fileNames) {
|
|
29541
|
-
const content =
|
|
29643
|
+
const content = readFileSync42(join53(referencesDir, fileName), "utf-8");
|
|
29542
29644
|
const parsed = parseTopLevelLabels(content);
|
|
29543
29645
|
if (parsed.length > 0) contributingFiles.push(fileName);
|
|
29544
29646
|
for (const label of parsed) labels.add(label);
|
|
@@ -30696,7 +30798,7 @@ var graph_default_view_default = app34;
|
|
|
30696
30798
|
// server/routes/admin/sidebar-artefacts.ts
|
|
30697
30799
|
import { readdir as readdir5, stat as stat7 } from "fs/promises";
|
|
30698
30800
|
import { resolve as resolve34, relative as relative7, isAbsolute as isAbsolute4, sep as sep10, basename as basename16 } from "path";
|
|
30699
|
-
import { existsSync as
|
|
30801
|
+
import { existsSync as existsSync44 } from "fs";
|
|
30700
30802
|
var LIMIT = 50;
|
|
30701
30803
|
var ADMIN_AGENT_FILES = ["IDENTITY.md", "SOUL.md", "KNOWLEDGE.md"];
|
|
30702
30804
|
function toDataRootRelPath(absPath) {
|
|
@@ -30808,7 +30910,7 @@ async function fetchAgentTemplateRows(accountDir) {
|
|
|
30808
30910
|
async function unionSpecialistFilenames(overrideDir, bundledDir) {
|
|
30809
30911
|
const names = /* @__PURE__ */ new Set();
|
|
30810
30912
|
for (const dir of [overrideDir, bundledDir]) {
|
|
30811
|
-
if (!
|
|
30913
|
+
if (!existsSync44(dir)) continue;
|
|
30812
30914
|
try {
|
|
30813
30915
|
const entries2 = await readdir5(dir);
|
|
30814
30916
|
for (const entry3 of entries2) {
|
|
@@ -30823,7 +30925,7 @@ async function unionSpecialistFilenames(overrideDir, bundledDir) {
|
|
|
30823
30925
|
}
|
|
30824
30926
|
async function readAgentTemplateRow(inp) {
|
|
30825
30927
|
let chosenPath = null;
|
|
30826
|
-
if (
|
|
30928
|
+
if (existsSync44(inp.overridePath)) {
|
|
30827
30929
|
try {
|
|
30828
30930
|
validateFilePathInAccount(inp.overridePath, inp.overrideRoot);
|
|
30829
30931
|
chosenPath = inp.overridePath;
|
|
@@ -30834,7 +30936,7 @@ async function readAgentTemplateRow(inp) {
|
|
|
30834
30936
|
);
|
|
30835
30937
|
return null;
|
|
30836
30938
|
}
|
|
30837
|
-
} else if (
|
|
30939
|
+
} else if (existsSync44(inp.bundledPath)) {
|
|
30838
30940
|
if (!isWithin(inp.bundledPath, inp.bundledRoot)) {
|
|
30839
30941
|
console.error(
|
|
30840
30942
|
`[admin/sidebar-artefacts] agent-template-read-failed agent=${inp.displayName} kind=${inp.logName} error="bundled path outside PLATFORM_ROOT"`
|
|
@@ -30876,19 +30978,19 @@ function isWithin(target, root) {
|
|
|
30876
30978
|
var sidebar_artefacts_default = app35;
|
|
30877
30979
|
|
|
30878
30980
|
// server/channel-session-override.ts
|
|
30879
|
-
import { readFileSync as
|
|
30880
|
-
import { join as
|
|
30981
|
+
import { readFileSync as readFileSync43, writeFileSync as writeFileSync19, renameSync as renameSync10 } from "fs";
|
|
30982
|
+
import { join as join54 } from "path";
|
|
30881
30983
|
var FILE2 = "channel-session-override.json";
|
|
30882
30984
|
var UUID3 = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
|
|
30883
30985
|
function channelOverridePath(accountDir) {
|
|
30884
|
-
return
|
|
30986
|
+
return join54(accountDir, FILE2);
|
|
30885
30987
|
}
|
|
30886
30988
|
function senderKey(channel, senderId) {
|
|
30887
30989
|
return `${channel}:${senderId}`;
|
|
30888
30990
|
}
|
|
30889
30991
|
function readRaw2(accountDir) {
|
|
30890
30992
|
try {
|
|
30891
|
-
return JSON.parse(
|
|
30993
|
+
return JSON.parse(readFileSync43(channelOverridePath(accountDir), "utf8"));
|
|
30892
30994
|
} catch {
|
|
30893
30995
|
return null;
|
|
30894
30996
|
}
|
|
@@ -31144,9 +31246,9 @@ app40.get("/", requireAdminSession, async (c) => {
|
|
|
31144
31246
|
var session_usage_default = app40;
|
|
31145
31247
|
|
|
31146
31248
|
// server/routes/admin/session-rc-spawn.ts
|
|
31147
|
-
import { randomUUID as
|
|
31249
|
+
import { randomUUID as randomUUID8 } from "crypto";
|
|
31148
31250
|
var ACCOUNT_UUID_RE2 = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
|
|
31149
|
-
function resolveSpawnPlan(host, operatorDomains, body, mintId =
|
|
31251
|
+
function resolveSpawnPlan(host, operatorDomains, body, mintId = randomUUID8, adminUserId, authenticatedName, callerAccountId) {
|
|
31150
31252
|
const operator = isOperatorHost(host, operatorDomains);
|
|
31151
31253
|
const resumeId = typeof body.sessionId === "string" && body.sessionId.length > 0 ? body.sessionId : void 0;
|
|
31152
31254
|
const name = typeof body.name === "string" && body.name.length > 0 ? body.name : void 0;
|
|
@@ -31216,8 +31318,8 @@ app41.post("/", requireAdminSession, async (c) => {
|
|
|
31216
31318
|
const adminUserId = cacheKey ? getUserIdForSession(cacheKey) : void 0;
|
|
31217
31319
|
const accountId = cacheKey ? getAccountIdForSession(cacheKey) : void 0;
|
|
31218
31320
|
const authenticatedName = accountId ? await resolveAuthenticatedName(accountId, adminUserId) : void 0;
|
|
31219
|
-
const plan = resolveSpawnPlan(host, getOperatorDomains(), body,
|
|
31220
|
-
const spawnReqId =
|
|
31321
|
+
const plan = resolveSpawnPlan(host, getOperatorDomains(), body, randomUUID8, adminUserId, authenticatedName, accountId);
|
|
31322
|
+
const spawnReqId = randomUUID8();
|
|
31221
31323
|
console.log(
|
|
31222
31324
|
`[chat-spawn] op=request spawnReqId=${spawnReqId} origin=${plan.origin} kind=${plan.kind} sessionId=${plan.kind === "new" ? "new" : plan.sessionId}`
|
|
31223
31325
|
);
|
|
@@ -31323,27 +31425,27 @@ app41.post("/", requireAdminSession, async (c) => {
|
|
|
31323
31425
|
var session_rc_spawn_default = app41;
|
|
31324
31426
|
|
|
31325
31427
|
// server/routes/admin/session-reseat.ts
|
|
31326
|
-
import { randomUUID as
|
|
31428
|
+
import { randomUUID as randomUUID9 } from "crypto";
|
|
31327
31429
|
|
|
31328
31430
|
// server/wa-descriptor.ts
|
|
31329
|
-
import { resolve as resolve35, join as
|
|
31431
|
+
import { resolve as resolve35, join as join55 } from "path";
|
|
31330
31432
|
function waGatewayUrl() {
|
|
31331
31433
|
return `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`;
|
|
31332
31434
|
}
|
|
31333
31435
|
function waServerPath() {
|
|
31334
|
-
return process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve35(process.env.MAXY_PLATFORM_ROOT ??
|
|
31436
|
+
return process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve35(process.env.MAXY_PLATFORM_ROOT ?? join55(__dirname, ".."), "services/whatsapp-channel/dist/server.js");
|
|
31335
31437
|
}
|
|
31336
31438
|
function waChannelDescriptor(senderId) {
|
|
31337
31439
|
return { senderId, gatewayUrl: waGatewayUrl(), serverPath: waServerPath() };
|
|
31338
31440
|
}
|
|
31339
31441
|
|
|
31340
31442
|
// server/telegram-descriptor.ts
|
|
31341
|
-
import { resolve as resolve36, join as
|
|
31443
|
+
import { resolve as resolve36, join as join56 } from "path";
|
|
31342
31444
|
function telegramGatewayUrl() {
|
|
31343
31445
|
return `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`;
|
|
31344
31446
|
}
|
|
31345
31447
|
function telegramServerPath() {
|
|
31346
|
-
return process.env.MAXY_TELEGRAM_CHANNEL_SERVER_PATH ?? resolve36(process.env.MAXY_PLATFORM_ROOT ??
|
|
31448
|
+
return process.env.MAXY_TELEGRAM_CHANNEL_SERVER_PATH ?? resolve36(process.env.MAXY_PLATFORM_ROOT ?? join56(__dirname, ".."), "services/telegram-channel/dist/server.js");
|
|
31347
31449
|
}
|
|
31348
31450
|
function telegramChannelDescriptor(senderId) {
|
|
31349
31451
|
return { senderId, gatewayUrl: telegramGatewayUrl(), serverPath: telegramServerPath() };
|
|
@@ -31359,7 +31461,7 @@ function shouldWriteChannelForward(source) {
|
|
|
31359
31461
|
function isPublicChannelSource(source) {
|
|
31360
31462
|
return !!source && source.role === "public" && (source.channel === "whatsapp" || source.channel === "telegram");
|
|
31361
31463
|
}
|
|
31362
|
-
function resolveReseatPlan(body, mintId =
|
|
31464
|
+
function resolveReseatPlan(body, mintId = randomUUID9, adminUserId, authenticatedName, source) {
|
|
31363
31465
|
const sessionId = mintId();
|
|
31364
31466
|
const key2 = `session:${sessionId}`;
|
|
31365
31467
|
const payload = {
|
|
@@ -31427,13 +31529,13 @@ app42.post("/", requireAdminSession, async (c) => {
|
|
|
31427
31529
|
}
|
|
31428
31530
|
const plan = resolveReseatPlan(
|
|
31429
31531
|
{ fromSessionId, model, ...permissionMode ? { permissionMode } : {}, ...effort ? { effort } : {} },
|
|
31430
|
-
|
|
31532
|
+
randomUUID9,
|
|
31431
31533
|
adminUserId,
|
|
31432
31534
|
authenticatedName,
|
|
31433
31535
|
source
|
|
31434
31536
|
);
|
|
31435
31537
|
const isChannelFork = isAdminChannelSource(source);
|
|
31436
|
-
const reseatReqId =
|
|
31538
|
+
const reseatReqId = randomUUID9();
|
|
31437
31539
|
console.log(`[chat-reseat] op=request reseatReqId=${reseatReqId} from=${fromSessionId} from-channel=${source?.channel ?? "none"} from-sender=${source?.senderId ?? "none"} to-model=${model} to-mode=${permissionMode ?? "none"} to-effort=${effort ?? "none"} new=${plan.sessionId}`);
|
|
31438
31540
|
let res;
|
|
31439
31541
|
try {
|
|
@@ -31629,14 +31731,14 @@ app43.get("/", async (c) => {
|
|
|
31629
31731
|
var system_stats_default = app43;
|
|
31630
31732
|
|
|
31631
31733
|
// server/routes/admin/health.ts
|
|
31632
|
-
import { existsSync as
|
|
31633
|
-
import { resolve as resolve37, join as
|
|
31734
|
+
import { existsSync as existsSync45, readFileSync as readFileSync44 } from "fs";
|
|
31735
|
+
import { resolve as resolve37, join as join57 } from "path";
|
|
31634
31736
|
var PLATFORM_ROOT4 = process.env.MAXY_PLATFORM_ROOT ?? resolve37(process.cwd(), "..");
|
|
31635
31737
|
var brandHostname = "maxy";
|
|
31636
|
-
var brandJsonPath =
|
|
31637
|
-
if (
|
|
31738
|
+
var brandJsonPath = join57(PLATFORM_ROOT4, "config", "brand.json");
|
|
31739
|
+
if (existsSync45(brandJsonPath)) {
|
|
31638
31740
|
try {
|
|
31639
|
-
const brand = JSON.parse(
|
|
31741
|
+
const brand = JSON.parse(readFileSync44(brandJsonPath, "utf-8"));
|
|
31640
31742
|
if (brand.hostname) brandHostname = brand.hostname;
|
|
31641
31743
|
} catch {
|
|
31642
31744
|
}
|
|
@@ -31645,8 +31747,8 @@ var VERSION_FILE = resolve37(PLATFORM_ROOT4, `config/.${brandHostname}-version`)
|
|
|
31645
31747
|
var PROCESS_STARTED_AT = (/* @__PURE__ */ new Date()).toISOString();
|
|
31646
31748
|
var PROBE_TIMEOUT_MS = 1e3;
|
|
31647
31749
|
function readVersion() {
|
|
31648
|
-
if (!
|
|
31649
|
-
return
|
|
31750
|
+
if (!existsSync45(VERSION_FILE)) return "unknown";
|
|
31751
|
+
return readFileSync44(VERSION_FILE, "utf-8").trim() || "unknown";
|
|
31650
31752
|
}
|
|
31651
31753
|
async function probeConversationDb() {
|
|
31652
31754
|
let session;
|
|
@@ -31697,11 +31799,11 @@ app44.get("/", async (c) => {
|
|
|
31697
31799
|
var health_default2 = app44;
|
|
31698
31800
|
|
|
31699
31801
|
// server/routes/admin/linkedin-ingest.ts
|
|
31700
|
-
import { randomUUID as
|
|
31802
|
+
import { randomUUID as randomUUID10 } from "crypto";
|
|
31701
31803
|
|
|
31702
31804
|
// ../lib/account-ingest-token/src/index.ts
|
|
31703
31805
|
import { randomBytes as randomBytes2, timingSafeEqual as timingSafeEqual2 } from "crypto";
|
|
31704
|
-
import { existsSync as
|
|
31806
|
+
import { existsSync as existsSync46, readdirSync as readdirSync27, readFileSync as readFileSync45, writeFileSync as writeFileSync20 } from "fs";
|
|
31705
31807
|
import { resolve as resolve38 } from "path";
|
|
31706
31808
|
var UUID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
31707
31809
|
var INGEST_TOKEN_FIELD = "ingestToken";
|
|
@@ -31711,9 +31813,9 @@ function configPath2(accountsDir, accountId) {
|
|
|
31711
31813
|
}
|
|
31712
31814
|
function readConfig2(accountsDir, accountId) {
|
|
31713
31815
|
const path = configPath2(accountsDir, accountId);
|
|
31714
|
-
if (!
|
|
31816
|
+
if (!existsSync46(path)) return null;
|
|
31715
31817
|
try {
|
|
31716
|
-
const parsed = JSON.parse(
|
|
31818
|
+
const parsed = JSON.parse(readFileSync45(path, "utf-8"));
|
|
31717
31819
|
return parsed !== null && typeof parsed === "object" ? parsed : null;
|
|
31718
31820
|
} catch {
|
|
31719
31821
|
return null;
|
|
@@ -31724,7 +31826,7 @@ function readIngestToken(accountsDir, accountId) {
|
|
|
31724
31826
|
return typeof value === "string" && TOKEN_RE.test(value) ? value : null;
|
|
31725
31827
|
}
|
|
31726
31828
|
function listAccountIdsOnDisk(accountsDir) {
|
|
31727
|
-
if (!
|
|
31829
|
+
if (!existsSync46(accountsDir)) return [];
|
|
31728
31830
|
let entries2;
|
|
31729
31831
|
try {
|
|
31730
31832
|
entries2 = readdirSync27(accountsDir);
|
|
@@ -31732,7 +31834,7 @@ function listAccountIdsOnDisk(accountsDir) {
|
|
|
31732
31834
|
return [];
|
|
31733
31835
|
}
|
|
31734
31836
|
return entries2.filter(
|
|
31735
|
-
(name) => UUID_RE4.test(name) &&
|
|
31837
|
+
(name) => UUID_RE4.test(name) && existsSync46(resolve38(accountsDir, name, "account.json"))
|
|
31736
31838
|
);
|
|
31737
31839
|
}
|
|
31738
31840
|
function resolveAccountIdByIngestToken(accountsDir, token) {
|
|
@@ -32037,7 +32139,7 @@ app45.post("/", requireIngestToken, async (c) => {
|
|
|
32037
32139
|
);
|
|
32038
32140
|
const initialMessage = buildInitialMessage(envelope);
|
|
32039
32141
|
const spawnStart = Date.now();
|
|
32040
|
-
const sessionId =
|
|
32142
|
+
const sessionId = randomUUID10();
|
|
32041
32143
|
console.log(TAG45 + " route target=rc-spawn dispatchId=" + envelope.dispatchId + " sessionId=" + sessionId.slice(0, 8));
|
|
32042
32144
|
const spawned = await managerRcSpawn({
|
|
32043
32145
|
sessionId,
|
|
@@ -32564,9 +32666,9 @@ app51.delete("/tabs/:id", requireAdminSession, async (c) => {
|
|
|
32564
32666
|
var browser_default = app51;
|
|
32565
32667
|
|
|
32566
32668
|
// server/routes/admin/calendar.ts
|
|
32567
|
-
import { existsSync as
|
|
32568
|
-
import { randomUUID as
|
|
32569
|
-
import { join as
|
|
32669
|
+
import { existsSync as existsSync47 } from "fs";
|
|
32670
|
+
import { randomUUID as randomUUID11 } from "crypto";
|
|
32671
|
+
import { join as join59 } from "path";
|
|
32570
32672
|
|
|
32571
32673
|
// server/lib/calendar-ics.ts
|
|
32572
32674
|
var CRLF = "\r\n";
|
|
@@ -32666,8 +32768,8 @@ function countVEvents(ics) {
|
|
|
32666
32768
|
}
|
|
32667
32769
|
|
|
32668
32770
|
// server/lib/calendar-availability.ts
|
|
32669
|
-
import { readFileSync as
|
|
32670
|
-
import { join as
|
|
32771
|
+
import { readFileSync as readFileSync46 } from "fs";
|
|
32772
|
+
import { join as join58 } from "path";
|
|
32671
32773
|
var AVAILABILITY_FILENAME = "calendar-availability.json";
|
|
32672
32774
|
var REQUIRED_KEYS = [
|
|
32673
32775
|
"timezone",
|
|
@@ -32676,10 +32778,10 @@ var REQUIRED_KEYS = [
|
|
|
32676
32778
|
"weekly"
|
|
32677
32779
|
];
|
|
32678
32780
|
function readAvailabilityConfig(accountDir) {
|
|
32679
|
-
const path =
|
|
32781
|
+
const path = join58(accountDir, AVAILABILITY_FILENAME);
|
|
32680
32782
|
let raw;
|
|
32681
32783
|
try {
|
|
32682
|
-
raw =
|
|
32784
|
+
raw = readFileSync46(path, "utf-8");
|
|
32683
32785
|
} catch {
|
|
32684
32786
|
throw new Error(`availability not configured: ${path} not found`);
|
|
32685
32787
|
}
|
|
@@ -32805,7 +32907,7 @@ var CREATE_FIELDS = EDITABLE_FIELDS;
|
|
|
32805
32907
|
function buildCreateParams(accountId, body) {
|
|
32806
32908
|
const params = {
|
|
32807
32909
|
accountId,
|
|
32808
|
-
uid:
|
|
32910
|
+
uid: randomUUID11(),
|
|
32809
32911
|
source: "admin-ui",
|
|
32810
32912
|
createdBySource: "admin-ui",
|
|
32811
32913
|
scope: "admin",
|
|
@@ -33234,7 +33336,7 @@ app52.get("/booking-link", requireAdminSession, (c) => {
|
|
|
33234
33336
|
}
|
|
33235
33337
|
const id83 = account.accountId.slice(0, 8);
|
|
33236
33338
|
try {
|
|
33237
|
-
if (!
|
|
33339
|
+
if (!existsSync47(join59(account.accountDir, AVAILABILITY_FILENAME))) {
|
|
33238
33340
|
console.log(`[calendar] op=booking-link accountId=${id83} bookingDomain=none source=availability-config`);
|
|
33239
33341
|
return c.json({ bookingDomain: null });
|
|
33240
33342
|
}
|
|
@@ -33253,8 +33355,8 @@ app52.get("/booking-link", requireAdminSession, (c) => {
|
|
|
33253
33355
|
var calendar_default = app52;
|
|
33254
33356
|
|
|
33255
33357
|
// server/routes/admin/data-portal.ts
|
|
33256
|
-
import { existsSync as
|
|
33257
|
-
import { join as
|
|
33358
|
+
import { existsSync as existsSync48, readFileSync as readFileSync47 } from "fs";
|
|
33359
|
+
import { join as join60 } from "path";
|
|
33258
33360
|
var app53 = new Hono();
|
|
33259
33361
|
var PORTAL_FILENAME = "data-portal.json";
|
|
33260
33362
|
app53.get("/portal-link", requireAdminSession, (c) => {
|
|
@@ -33265,12 +33367,12 @@ app53.get("/portal-link", requireAdminSession, (c) => {
|
|
|
33265
33367
|
}
|
|
33266
33368
|
const id83 = account.accountId.slice(0, 8);
|
|
33267
33369
|
try {
|
|
33268
|
-
const path =
|
|
33269
|
-
if (!
|
|
33370
|
+
const path = join60(account.accountDir, PORTAL_FILENAME);
|
|
33371
|
+
if (!existsSync48(path)) {
|
|
33270
33372
|
console.log(`[data-portal] op=portal-link accountId=${id83} portalDomain=none source=data-portal-config`);
|
|
33271
33373
|
return c.json({ portalDomain: null });
|
|
33272
33374
|
}
|
|
33273
|
-
const cfg = JSON.parse(
|
|
33375
|
+
const cfg = JSON.parse(readFileSync47(path, "utf-8"));
|
|
33274
33376
|
const portalDomain = typeof cfg.portalDomain === "string" && cfg.portalDomain.trim() ? cfg.portalDomain.trim() : null;
|
|
33275
33377
|
console.log(`[data-portal] op=portal-link accountId=${id83} portalDomain=${portalDomain ?? "none"} source=data-portal-config`);
|
|
33276
33378
|
return c.json({ portalDomain });
|
|
@@ -33283,8 +33385,8 @@ app53.get("/portal-link", requireAdminSession, (c) => {
|
|
|
33283
33385
|
var data_portal_default = app53;
|
|
33284
33386
|
|
|
33285
33387
|
// server/routes/admin/dispatch-planner.ts
|
|
33286
|
-
import { existsSync as
|
|
33287
|
-
import { join as
|
|
33388
|
+
import { existsSync as existsSync49, readFileSync as readFileSync48 } from "fs";
|
|
33389
|
+
import { join as join61 } from "path";
|
|
33288
33390
|
var app54 = new Hono();
|
|
33289
33391
|
var PORTAL_FILENAME2 = "data-portal.json";
|
|
33290
33392
|
app54.get("/planner-link", requireAdminSession, (c) => {
|
|
@@ -33297,15 +33399,15 @@ app54.get("/planner-link", requireAdminSession, (c) => {
|
|
|
33297
33399
|
}
|
|
33298
33400
|
const id83 = account.accountId.slice(0, 8);
|
|
33299
33401
|
try {
|
|
33300
|
-
const portalPath =
|
|
33301
|
-
const dispatchConfigured =
|
|
33302
|
-
if (!
|
|
33402
|
+
const portalPath = join61(account.accountDir, PORTAL_FILENAME2);
|
|
33403
|
+
const dispatchConfigured = existsSync49(join61(account.accountDir, "dispatch", "config.json"));
|
|
33404
|
+
if (!existsSync49(portalPath) || !dispatchConfigured) {
|
|
33303
33405
|
console.log(
|
|
33304
|
-
`[dispatch-planner] op=planner-link accountId=${id83} plannerUrl=none portal=${
|
|
33406
|
+
`[dispatch-planner] op=planner-link accountId=${id83} plannerUrl=none portal=${existsSync49(portalPath)} dispatch=${dispatchConfigured}`
|
|
33305
33407
|
);
|
|
33306
33408
|
return c.json({ plannerUrl: null });
|
|
33307
33409
|
}
|
|
33308
|
-
const cfg = JSON.parse(
|
|
33410
|
+
const cfg = JSON.parse(readFileSync48(portalPath, "utf-8"));
|
|
33309
33411
|
const domain = typeof cfg.portalDomain === "string" && cfg.portalDomain.trim() ? cfg.portalDomain.trim() : null;
|
|
33310
33412
|
const plannerUrl = domain ? `https://${domain}/planner` : null;
|
|
33311
33413
|
console.log(
|
|
@@ -33323,11 +33425,11 @@ var dispatch_planner_default = app54;
|
|
|
33323
33425
|
// server/routes/admin/routines.ts
|
|
33324
33426
|
import cronParser from "cron-parser";
|
|
33325
33427
|
import { int as int2 } from "neo4j-driver";
|
|
33326
|
-
import { readFileSync as
|
|
33428
|
+
import { readFileSync as readFileSync50 } from "fs";
|
|
33327
33429
|
import { resolve as resolve40 } from "path";
|
|
33328
33430
|
|
|
33329
33431
|
// ../lib/agent-dispatch-rule/src/index.ts
|
|
33330
|
-
import { readFileSync as
|
|
33432
|
+
import { readFileSync as readFileSync49 } from "fs";
|
|
33331
33433
|
import { resolve as resolve39 } from "path";
|
|
33332
33434
|
function normalizeE1642(value) {
|
|
33333
33435
|
let candidate = value.trim().replace(/[\s\-().]/g, "");
|
|
@@ -33345,7 +33447,7 @@ function phonesMatch2(a, b) {
|
|
|
33345
33447
|
function readChannelAdmins(accountDir, channel) {
|
|
33346
33448
|
let config = {};
|
|
33347
33449
|
try {
|
|
33348
|
-
config = JSON.parse(
|
|
33450
|
+
config = JSON.parse(readFileSync49(resolve39(accountDir, "account.json"), "utf-8"));
|
|
33349
33451
|
} catch {
|
|
33350
33452
|
config = {};
|
|
33351
33453
|
}
|
|
@@ -33513,7 +33615,7 @@ function gateWatermarkPath(eventId) {
|
|
|
33513
33615
|
}
|
|
33514
33616
|
function readGateLastCommitAt(eventId) {
|
|
33515
33617
|
try {
|
|
33516
|
-
const parsed = JSON.parse(
|
|
33618
|
+
const parsed = JSON.parse(readFileSync50(gateWatermarkPath(eventId), "utf-8"));
|
|
33517
33619
|
return typeof parsed?.lastCommitAt === "string" ? parsed.lastCommitAt : null;
|
|
33518
33620
|
} catch {
|
|
33519
33621
|
return null;
|
|
@@ -34390,7 +34492,7 @@ app55.delete("/:eventId", requireAdminSession, async (c) => {
|
|
|
34390
34492
|
var routines_default = app55;
|
|
34391
34493
|
|
|
34392
34494
|
// server/routes/admin/skills.ts
|
|
34393
|
-
import { existsSync as
|
|
34495
|
+
import { existsSync as existsSync50, readdirSync as readdirSync28, readFileSync as readFileSync51, rmSync as rmSync6 } from "fs";
|
|
34394
34496
|
import { resolve as resolve41 } from "path";
|
|
34395
34497
|
var app56 = new Hono();
|
|
34396
34498
|
var NAME_RE = /^[a-z0-9][a-z0-9-]*$/;
|
|
@@ -34414,7 +34516,7 @@ function stripQuotes(s) {
|
|
|
34414
34516
|
return s;
|
|
34415
34517
|
}
|
|
34416
34518
|
function subdirs2(dir) {
|
|
34417
|
-
if (!
|
|
34519
|
+
if (!existsSync50(dir)) return [];
|
|
34418
34520
|
try {
|
|
34419
34521
|
return readdirSync28(dir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
|
|
34420
34522
|
} catch {
|
|
@@ -34437,11 +34539,11 @@ app56.get("/", requireAdminSession, async (c) => {
|
|
|
34437
34539
|
const skillsDir = resolve41(pluginsDir, plugin, "skills");
|
|
34438
34540
|
for (const skill of subdirs2(skillsDir)) {
|
|
34439
34541
|
const skillMd = resolve41(skillsDir, skill, "SKILL.md");
|
|
34440
|
-
if (!
|
|
34542
|
+
if (!existsSync50(skillMd)) continue;
|
|
34441
34543
|
try {
|
|
34442
|
-
const { frontmatter } = splitSkillMd(
|
|
34544
|
+
const { frontmatter } = splitSkillMd(readFileSync51(skillMd, "utf-8"));
|
|
34443
34545
|
const refsDir = resolve41(skillsDir, skill, "references");
|
|
34444
|
-
const refCount =
|
|
34546
|
+
const refCount = existsSync50(refsDir) ? readdirSync28(refsDir, { withFileTypes: true }).filter((e) => e.isFile()).length : 0;
|
|
34445
34547
|
skills.push({ plugin, skill, description: frontmatter.description, refCount });
|
|
34446
34548
|
} catch (err) {
|
|
34447
34549
|
console.error(`[admin:skills] op=list-skip plugin=${plugin} skill=${skill} reason="${err instanceof Error ? err.message : String(err)}"`);
|
|
@@ -34465,13 +34567,13 @@ app56.get("/:plugin/:skill", requireAdminSession, async (c) => {
|
|
|
34465
34567
|
}
|
|
34466
34568
|
const skillDir = resolve41(acct.accountDir, "plugins", plugin, "skills", skill);
|
|
34467
34569
|
const skillMd = resolve41(skillDir, "SKILL.md");
|
|
34468
|
-
const found =
|
|
34570
|
+
const found = existsSync50(skillMd);
|
|
34469
34571
|
console.log(`[admin:skills] op=get plugin=${plugin} skill=${skill} found=${found}`);
|
|
34470
34572
|
if (!found) return c.json({ error: "Skill not found" }, 404);
|
|
34471
34573
|
try {
|
|
34472
|
-
const { frontmatter, body } = splitSkillMd(
|
|
34574
|
+
const { frontmatter, body } = splitSkillMd(readFileSync51(skillMd, "utf-8"));
|
|
34473
34575
|
const refsDir = resolve41(skillDir, "references");
|
|
34474
|
-
const references =
|
|
34576
|
+
const references = existsSync50(refsDir) ? readdirSync28(refsDir, { withFileTypes: true }).filter((e) => e.isFile()).map((e) => e.name).sort() : [];
|
|
34475
34577
|
return c.json({ skill: { plugin, skill, frontmatter, body, references } });
|
|
34476
34578
|
} catch (err) {
|
|
34477
34579
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -34491,7 +34593,7 @@ app56.delete("/:plugin/:skill", requireAdminSession, async (c) => {
|
|
|
34491
34593
|
const pluginDir = resolve41(acct.accountDir, "plugins", plugin);
|
|
34492
34594
|
const skillsDir = resolve41(pluginDir, "skills");
|
|
34493
34595
|
const skillDir = resolve41(skillsDir, skill);
|
|
34494
|
-
if (!
|
|
34596
|
+
if (!existsSync50(resolve41(skillDir, "SKILL.md"))) {
|
|
34495
34597
|
console.error(`[admin:skills] op=delete outcome=rejected reason=not-found plugin=${plugin} skill=${skill}`);
|
|
34496
34598
|
return c.json({ error: "Skill not found" }, 404);
|
|
34497
34599
|
}
|
|
@@ -34499,7 +34601,7 @@ app56.delete("/:plugin/:skill", requireAdminSession, async (c) => {
|
|
|
34499
34601
|
rmSync6(skillDir, { recursive: true, force: true });
|
|
34500
34602
|
const pluginDirRemoved = subdirs2(skillsDir).length === 0;
|
|
34501
34603
|
if (pluginDirRemoved) rmSync6(pluginDir, { recursive: true, force: true });
|
|
34502
|
-
const skillDirGone = !
|
|
34604
|
+
const skillDirGone = !existsSync50(skillDir);
|
|
34503
34605
|
if (!skillDirGone) {
|
|
34504
34606
|
console.error(`[admin:skills] op=delete plugin=${plugin} skill=${skill} outcome=rejected reason=rm-incomplete skillDirGone=false`);
|
|
34505
34607
|
return c.json({ error: "Delete did not remove the skill directory" }, 503);
|
|
@@ -34515,7 +34617,7 @@ app56.delete("/:plugin/:skill", requireAdminSession, async (c) => {
|
|
|
34515
34617
|
var skills_default = app56;
|
|
34516
34618
|
|
|
34517
34619
|
// server/routes/admin/tasks-list.ts
|
|
34518
|
-
import { basename as basename17, join as
|
|
34620
|
+
import { basename as basename17, join as join62 } from "path";
|
|
34519
34621
|
|
|
34520
34622
|
// app/lib/time-entry-format.ts
|
|
34521
34623
|
function secondsBetween(startIso, endIso) {
|
|
@@ -34691,7 +34793,7 @@ async function computeTaskList(accountId) {
|
|
|
34691
34793
|
dangling = 0;
|
|
34692
34794
|
} else if (cfg !== null) {
|
|
34693
34795
|
try {
|
|
34694
|
-
const walk = enumerateJsonlsWithSkips(
|
|
34796
|
+
const walk = enumerateJsonlsWithSkips(join62(cfg, "projects"));
|
|
34695
34797
|
if (walk.skipped > 0) {
|
|
34696
34798
|
console.error(
|
|
34697
34799
|
`${TAG51} op=session-dangling-census-incomplete account=${accountId} skipped=${walk.skipped} detail="a slug the walk could not read contributes no session ids, so its links cannot be judged"`
|
|
@@ -34733,7 +34835,7 @@ async function computeTaskList(accountId) {
|
|
|
34733
34835
|
var tasks_list_default = app57;
|
|
34734
34836
|
|
|
34735
34837
|
// server/routes/admin/task-timer-start.ts
|
|
34736
|
-
import { randomUUID as
|
|
34838
|
+
import { randomUUID as randomUUID12 } from "crypto";
|
|
34737
34839
|
var TAG52 = "[task-timer]";
|
|
34738
34840
|
var app58 = new Hono();
|
|
34739
34841
|
app58.post("/", requireAdminSession, async (c) => {
|
|
@@ -34776,7 +34878,7 @@ app58.post("/", requireAdminSession, async (c) => {
|
|
|
34776
34878
|
invalidate("tasks-list", accountId);
|
|
34777
34879
|
return c.json({ ok: true, running: true, entryId: priorEntryId, startedAt: priorStartedAt });
|
|
34778
34880
|
}
|
|
34779
|
-
const entryId =
|
|
34881
|
+
const entryId = randomUUID12();
|
|
34780
34882
|
await session.run(
|
|
34781
34883
|
`MATCH (t:Task {taskId: $taskId, accountId: $accountId})
|
|
34782
34884
|
CREATE (te:TimeEntry {entryId: $entryId, taskId: $taskId, accountId: $accountId, startedAt: $now, endedAt: null})
|
|
@@ -34915,7 +35017,7 @@ app60.post("/", requireAdminSession, async (c) => {
|
|
|
34915
35017
|
var task_complete_default = app60;
|
|
34916
35018
|
|
|
34917
35019
|
// server/routes/admin/task-time-adjust.ts
|
|
34918
|
-
import { randomUUID as
|
|
35020
|
+
import { randomUUID as randomUUID13 } from "crypto";
|
|
34919
35021
|
import neo4j6 from "neo4j-driver";
|
|
34920
35022
|
var TAG55 = "[task-time-adjust]";
|
|
34921
35023
|
var app61 = new Hono();
|
|
@@ -34941,7 +35043,7 @@ app61.post("/", requireAdminSession, async (c) => {
|
|
|
34941
35043
|
console.error(`${TAG55} op=reject reason=invalid-seconds taskId=${taskId} accountId=${accountId}`);
|
|
34942
35044
|
return c.json({ error: "newSeconds must be a non-negative integer" }, 400);
|
|
34943
35045
|
}
|
|
34944
|
-
const adjustmentId =
|
|
35046
|
+
const adjustmentId = randomUUID13();
|
|
34945
35047
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
34946
35048
|
console.log(`${TAG55} op=request adjustmentId=${adjustmentId} taskId=${taskId} accountId=${accountId} newSeconds=${newSeconds}`);
|
|
34947
35049
|
const session = getSession();
|
|
@@ -34997,7 +35099,7 @@ app61.post("/", requireAdminSession, async (c) => {
|
|
|
34997
35099
|
var task_time_adjust_default = app61;
|
|
34998
35100
|
|
|
34999
35101
|
// server/routes/admin/task-delete.ts
|
|
35000
|
-
import { randomUUID as
|
|
35102
|
+
import { randomUUID as randomUUID14 } from "crypto";
|
|
35001
35103
|
var TAG56 = "[task-delete]";
|
|
35002
35104
|
var app62 = new Hono();
|
|
35003
35105
|
app62.post("/", requireAdminSession, async (c) => {
|
|
@@ -35011,7 +35113,7 @@ app62.post("/", requireAdminSession, async (c) => {
|
|
|
35011
35113
|
console.error(`${TAG56} op=reject reason=bad-json`);
|
|
35012
35114
|
return c.json({ error: "invalid-json" }, 400);
|
|
35013
35115
|
}
|
|
35014
|
-
const deletionId =
|
|
35116
|
+
const deletionId = randomUUID14();
|
|
35015
35117
|
const taskId = typeof body.taskId === "string" ? body.taskId : "";
|
|
35016
35118
|
if (!taskId) {
|
|
35017
35119
|
const reason = body.taskId === null ? "null-taskId" : "missing-taskId";
|
|
@@ -35103,7 +35205,7 @@ app62.post("/", requireAdminSession, async (c) => {
|
|
|
35103
35205
|
var task_delete_default = app62;
|
|
35104
35206
|
|
|
35105
35207
|
// app/lib/admin-roster.ts
|
|
35106
|
-
import { existsSync as
|
|
35208
|
+
import { existsSync as existsSync51, readdirSync as readdirSync29, readFileSync as readFileSync52 } from "fs";
|
|
35107
35209
|
import { resolve as resolve42 } from "path";
|
|
35108
35210
|
function readHouseAdminUserIds(accountsDir = ACCOUNTS_DIR) {
|
|
35109
35211
|
let entries2;
|
|
@@ -35114,9 +35216,9 @@ function readHouseAdminUserIds(accountsDir = ACCOUNTS_DIR) {
|
|
|
35114
35216
|
}
|
|
35115
35217
|
for (const entry3 of entries2) {
|
|
35116
35218
|
const cfgPath = resolve42(accountsDir, entry3, "account.json");
|
|
35117
|
-
if (!
|
|
35219
|
+
if (!existsSync51(cfgPath)) continue;
|
|
35118
35220
|
try {
|
|
35119
|
-
const cfg = JSON.parse(
|
|
35221
|
+
const cfg = JSON.parse(readFileSync52(cfgPath, "utf-8"));
|
|
35120
35222
|
if (cfg.role !== "house") continue;
|
|
35121
35223
|
if (!Array.isArray(cfg.admins)) return [];
|
|
35122
35224
|
return cfg.admins.map(
|
|
@@ -35958,7 +36060,7 @@ app72.route("/request-magic-link", request_magic_link_default);
|
|
|
35958
36060
|
var access_default = app72;
|
|
35959
36061
|
|
|
35960
36062
|
// server/routes/sites.ts
|
|
35961
|
-
import { existsSync as
|
|
36063
|
+
import { existsSync as existsSync52, readFileSync as readFileSync53, realpathSync as realpathSync8, statSync as statSync27 } from "fs";
|
|
35962
36064
|
import { resolve as resolve45 } from "path";
|
|
35963
36065
|
var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
|
|
35964
36066
|
var MIME = {
|
|
@@ -36024,7 +36126,7 @@ app73.get("/:rel{.*}", (c) => {
|
|
|
36024
36126
|
}
|
|
36025
36127
|
let stat11;
|
|
36026
36128
|
try {
|
|
36027
|
-
stat11 =
|
|
36129
|
+
stat11 = existsSync52(filePath) ? statSync27(filePath) : null;
|
|
36028
36130
|
} catch {
|
|
36029
36131
|
stat11 = null;
|
|
36030
36132
|
}
|
|
@@ -36043,7 +36145,7 @@ app73.get("/:rel{.*}", (c) => {
|
|
|
36043
36145
|
console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
|
|
36044
36146
|
return c.text("Forbidden", 403);
|
|
36045
36147
|
}
|
|
36046
|
-
if (!
|
|
36148
|
+
if (!existsSync52(filePath)) {
|
|
36047
36149
|
console.error(`[sites] not-found path=${reqPath} status=404`);
|
|
36048
36150
|
return c.text("Not found", 404);
|
|
36049
36151
|
}
|
|
@@ -36062,7 +36164,7 @@ app73.get("/:rel{.*}", (c) => {
|
|
|
36062
36164
|
}
|
|
36063
36165
|
let body;
|
|
36064
36166
|
try {
|
|
36065
|
-
body =
|
|
36167
|
+
body = readFileSync53(realPath);
|
|
36066
36168
|
} catch (err) {
|
|
36067
36169
|
const code = err?.code;
|
|
36068
36170
|
if (code === "EISDIR") {
|
|
@@ -36098,7 +36200,7 @@ var sites_default = app73;
|
|
|
36098
36200
|
|
|
36099
36201
|
// app/lib/visitor-token.ts
|
|
36100
36202
|
import { createHmac as createHmac2, randomBytes as randomBytes3, timingSafeEqual as timingSafeEqual3 } from "crypto";
|
|
36101
|
-
import { mkdirSync as mkdirSync12, readFileSync as
|
|
36203
|
+
import { mkdirSync as mkdirSync12, readFileSync as readFileSync54, writeFileSync as writeFileSync21 } from "fs";
|
|
36102
36204
|
import { dirname as dirname17 } from "path";
|
|
36103
36205
|
var TOKEN_PREFIX = "v1.";
|
|
36104
36206
|
var SECRET_BYTES = 32;
|
|
@@ -36107,7 +36209,7 @@ var cachedSecret = null;
|
|
|
36107
36209
|
function getSecret() {
|
|
36108
36210
|
if (cachedSecret) return cachedSecret;
|
|
36109
36211
|
try {
|
|
36110
|
-
const hex2 =
|
|
36212
|
+
const hex2 = readFileSync54(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
|
|
36111
36213
|
if (hex2.length === SECRET_BYTES * 2) {
|
|
36112
36214
|
cachedSecret = Buffer.from(hex2, "hex");
|
|
36113
36215
|
return cachedSecret;
|
|
@@ -36121,7 +36223,7 @@ function getSecret() {
|
|
|
36121
36223
|
console.log(`[visitor-token] secret minted path=${VISITOR_TOKEN_SECRET_FILE}`);
|
|
36122
36224
|
} catch {
|
|
36123
36225
|
}
|
|
36124
|
-
const hex =
|
|
36226
|
+
const hex = readFileSync54(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
|
|
36125
36227
|
cachedSecret = Buffer.from(hex, "hex");
|
|
36126
36228
|
return cachedSecret;
|
|
36127
36229
|
}
|
|
@@ -36174,8 +36276,8 @@ var VISITOR_COOKIE_NAME = "mxy_v";
|
|
|
36174
36276
|
var VISITOR_COOKIE_MAX_AGE_SECONDS = Math.floor(DEFAULT_TTL_MS / 1e3);
|
|
36175
36277
|
|
|
36176
36278
|
// app/lib/brand-config.ts
|
|
36177
|
-
import { existsSync as
|
|
36178
|
-
import { join as
|
|
36279
|
+
import { existsSync as existsSync53, readFileSync as readFileSync55 } from "fs";
|
|
36280
|
+
import { join as join63 } from "path";
|
|
36179
36281
|
var cached2 = null;
|
|
36180
36282
|
var cachedAttempted = false;
|
|
36181
36283
|
function readBrandConfig() {
|
|
@@ -36183,10 +36285,10 @@ function readBrandConfig() {
|
|
|
36183
36285
|
cachedAttempted = true;
|
|
36184
36286
|
const platformRoot5 = process.env.MAXY_PLATFORM_ROOT;
|
|
36185
36287
|
if (!platformRoot5) return null;
|
|
36186
|
-
const brandPath =
|
|
36187
|
-
if (!
|
|
36288
|
+
const brandPath = join63(platformRoot5, "config", "brand.json");
|
|
36289
|
+
if (!existsSync53(brandPath)) return null;
|
|
36188
36290
|
try {
|
|
36189
|
-
cached2 = JSON.parse(
|
|
36291
|
+
cached2 = JSON.parse(readFileSync55(brandPath, "utf-8"));
|
|
36190
36292
|
return cached2;
|
|
36191
36293
|
} catch {
|
|
36192
36294
|
return null;
|
|
@@ -36684,7 +36786,7 @@ var visitor_event_default = app76;
|
|
|
36684
36786
|
|
|
36685
36787
|
// server/routes/session.ts
|
|
36686
36788
|
import { resolve as resolve46 } from "path";
|
|
36687
|
-
import { existsSync as
|
|
36789
|
+
import { existsSync as existsSync54, writeFileSync as writeFileSync22, mkdirSync as mkdirSync13 } from "fs";
|
|
36688
36790
|
var UUID_RE5 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
36689
36791
|
function writeBrandingCache(accountId, agentSlug, branding) {
|
|
36690
36792
|
try {
|
|
@@ -36772,7 +36874,7 @@ app77.post("/", async (c) => {
|
|
|
36772
36874
|
let agentConfig = null;
|
|
36773
36875
|
if (account) {
|
|
36774
36876
|
const agentDir = resolve46(account.accountDir, "agents", agentSlug);
|
|
36775
|
-
if (!
|
|
36877
|
+
if (!existsSync54(agentDir) || !existsSync54(resolve46(agentDir, "config.json"))) {
|
|
36776
36878
|
return c.json({ error: "Agent not found" }, 404);
|
|
36777
36879
|
}
|
|
36778
36880
|
agentConfig = resolveAgentConfig(account.accountDir, agentSlug);
|
|
@@ -36952,7 +37054,7 @@ var calendar_public_default = app78;
|
|
|
36952
37054
|
// server/routes/portal-fetch.ts
|
|
36953
37055
|
import { createReadStream as createReadStream3 } from "fs";
|
|
36954
37056
|
import { stat as stat8, readFile as readFile12, realpath } from "fs/promises";
|
|
36955
|
-
import { join as
|
|
37057
|
+
import { join as join64, resolve as resolve47, sep as sep11 } from "path";
|
|
36956
37058
|
import { Readable as Readable3 } from "stream";
|
|
36957
37059
|
var app79 = new Hono();
|
|
36958
37060
|
var TAG65 = "[portal-fetch]";
|
|
@@ -37025,7 +37127,7 @@ function isValidAccountId2(value) {
|
|
|
37025
37127
|
}
|
|
37026
37128
|
async function readExposeFolders2(accountDir) {
|
|
37027
37129
|
try {
|
|
37028
|
-
const cfg = JSON.parse(await readFile12(
|
|
37130
|
+
const cfg = JSON.parse(await readFile12(join64(accountDir, "data-portal.json"), "utf8"));
|
|
37029
37131
|
return Array.isArray(cfg?.exposeFolders) ? cfg.exposeFolders.filter((f) => typeof f === "string") : [];
|
|
37030
37132
|
} catch {
|
|
37031
37133
|
return [];
|
|
@@ -37034,7 +37136,7 @@ async function readExposeFolders2(accountDir) {
|
|
|
37034
37136
|
async function resolveFetchTarget(accountDir, relPath, ownerId) {
|
|
37035
37137
|
let schemaText = null;
|
|
37036
37138
|
try {
|
|
37037
|
-
schemaText = await readFile12(
|
|
37139
|
+
schemaText = await readFile12(join64(accountDir, "SCHEMA.md"), "utf8");
|
|
37038
37140
|
} catch {
|
|
37039
37141
|
schemaText = null;
|
|
37040
37142
|
}
|
|
@@ -37204,8 +37306,8 @@ function startTimeEntryCensus(openSession, opts = {}) {
|
|
|
37204
37306
|
}
|
|
37205
37307
|
|
|
37206
37308
|
// app/lib/ledger-census.ts
|
|
37207
|
-
import { readdirSync as readdirSync31, readFileSync as
|
|
37208
|
-
import { join as
|
|
37309
|
+
import { readdirSync as readdirSync31, readFileSync as readFileSync56, statSync as statSync28 } from "fs";
|
|
37310
|
+
import { join as join65 } from "path";
|
|
37209
37311
|
|
|
37210
37312
|
// ../lib/ledger-core/dist/reconcile.js
|
|
37211
37313
|
var LEDGER_INDEX_NAMES = [
|
|
@@ -37259,10 +37361,10 @@ function countWriteRejects24h(logDir, now) {
|
|
|
37259
37361
|
}
|
|
37260
37362
|
let total = 0;
|
|
37261
37363
|
for (const name of entries2) {
|
|
37262
|
-
const path =
|
|
37364
|
+
const path = join65(logDir, name);
|
|
37263
37365
|
try {
|
|
37264
37366
|
if (now - statSync28(path).mtimeMs > DAY_MS) continue;
|
|
37265
|
-
for (const line of
|
|
37367
|
+
for (const line of readFileSync56(path, "utf8").split("\n")) {
|
|
37266
37368
|
if (line.includes("[graph-write] reject")) total += 1;
|
|
37267
37369
|
}
|
|
37268
37370
|
} catch {
|
|
@@ -37363,8 +37465,8 @@ function startLedgerCensus(openSession, opts = {}) {
|
|
|
37363
37465
|
}
|
|
37364
37466
|
|
|
37365
37467
|
// app/lib/dispatch-census.ts
|
|
37366
|
-
import { readFileSync as
|
|
37367
|
-
import { join as
|
|
37468
|
+
import { readFileSync as readFileSync57 } from "fs";
|
|
37469
|
+
import { join as join66 } from "path";
|
|
37368
37470
|
|
|
37369
37471
|
// ../lib/canonical-instant/src/index.ts
|
|
37370
37472
|
var CANONICAL_INSTANT_PATTERN = "\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z";
|
|
@@ -37402,7 +37504,7 @@ function percentile(sortedAsc, p) {
|
|
|
37402
37504
|
function auditConfigFile(accountDir) {
|
|
37403
37505
|
let cfg;
|
|
37404
37506
|
try {
|
|
37405
|
-
cfg = JSON.parse(
|
|
37507
|
+
cfg = JSON.parse(readFileSync57(join66(accountDir, "dispatch", "config.json"), "utf-8"));
|
|
37406
37508
|
} catch {
|
|
37407
37509
|
return null;
|
|
37408
37510
|
}
|
|
@@ -37427,7 +37529,7 @@ function auditConfigFile(accountDir) {
|
|
|
37427
37529
|
function terminalStatuses(accountDir) {
|
|
37428
37530
|
try {
|
|
37429
37531
|
const cfg = JSON.parse(
|
|
37430
|
-
|
|
37532
|
+
readFileSync57(join66(accountDir, "dispatch", "config.json"), "utf-8")
|
|
37431
37533
|
);
|
|
37432
37534
|
return {
|
|
37433
37535
|
job: (cfg.statuses?.job ?? []).filter((s) => s.terminal).map((s) => s.name),
|
|
@@ -37857,8 +37959,8 @@ function startGraphHealthTimer() {
|
|
|
37857
37959
|
}
|
|
37858
37960
|
|
|
37859
37961
|
// app/lib/shared-folder-census.ts
|
|
37860
|
-
import { existsSync as
|
|
37861
|
-
import { join as
|
|
37962
|
+
import { existsSync as existsSync55, statSync as statSync29, readdirSync as readdirSync32 } from "fs";
|
|
37963
|
+
import { join as join67 } from "path";
|
|
37862
37964
|
var import_dist17 = __toESM(require_dist(), 1);
|
|
37863
37965
|
var TAG69 = "[shared-census]";
|
|
37864
37966
|
var WIRED_SURFACES = 3;
|
|
@@ -37871,14 +37973,14 @@ function countFiles(dir) {
|
|
|
37871
37973
|
return 0;
|
|
37872
37974
|
}
|
|
37873
37975
|
for (const e of entries2) {
|
|
37874
|
-
if (e.isDirectory()) n += countFiles(
|
|
37976
|
+
if (e.isDirectory()) n += countFiles(join67(dir, e.name));
|
|
37875
37977
|
else if (e.isFile()) n++;
|
|
37876
37978
|
}
|
|
37877
37979
|
return n;
|
|
37878
37980
|
}
|
|
37879
37981
|
function runSharedFolderCensus(dataRoot = DATA_ROOT) {
|
|
37880
37982
|
const root = (0, import_dist17.sharedRoot)(dataRoot);
|
|
37881
|
-
const exists =
|
|
37983
|
+
const exists = existsSync55(root);
|
|
37882
37984
|
let isDir = false;
|
|
37883
37985
|
if (exists) {
|
|
37884
37986
|
try {
|
|
@@ -37920,9 +38022,9 @@ function startAccountsStateCensus() {
|
|
|
37920
38022
|
}
|
|
37921
38023
|
|
|
37922
38024
|
// app/lib/cred-refresh-census.ts
|
|
37923
|
-
import { readdirSync as readdirSync33, readFileSync as
|
|
38025
|
+
import { readdirSync as readdirSync33, readFileSync as readFileSync58 } from "fs";
|
|
37924
38026
|
import { homedir as homedir4 } from "os";
|
|
37925
|
-
import { join as
|
|
38027
|
+
import { join as join68 } from "path";
|
|
37926
38028
|
var TAG71 = "[claude-auth]";
|
|
37927
38029
|
function refreshTokenLength(raw) {
|
|
37928
38030
|
let data;
|
|
@@ -37947,7 +38049,7 @@ function surveyBrandCredentials(home) {
|
|
|
37947
38049
|
if (!entry3.startsWith(".")) continue;
|
|
37948
38050
|
let raw;
|
|
37949
38051
|
try {
|
|
37950
|
-
raw =
|
|
38052
|
+
raw = readFileSync58(join68(home, entry3, ".claude", ".credentials.json"), "utf-8");
|
|
37951
38053
|
} catch {
|
|
37952
38054
|
continue;
|
|
37953
38055
|
}
|
|
@@ -38208,8 +38310,8 @@ async function migrateUploads(opts = {}) {
|
|
|
38208
38310
|
|
|
38209
38311
|
// app/lib/migrate-admin-webchat-sidecars.ts
|
|
38210
38312
|
import { readdir as readdir7, readFile as readFile13, rename as rename5, writeFile as writeFile4, unlink as unlink4 } from "fs/promises";
|
|
38211
|
-
import { existsSync as
|
|
38212
|
-
import { join as
|
|
38313
|
+
import { existsSync as existsSync56 } from "fs";
|
|
38314
|
+
import { join as join69 } from "path";
|
|
38213
38315
|
var ADMIN_ROLE2 = "admin";
|
|
38214
38316
|
var WEBCHAT_CHANNEL2 = "webchat";
|
|
38215
38317
|
var SESSION_META_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\.meta\.json$/i;
|
|
@@ -38238,7 +38340,7 @@ async function writeRaw(path, obj) {
|
|
|
38238
38340
|
await rename5(tmp, path);
|
|
38239
38341
|
} catch (err) {
|
|
38240
38342
|
try {
|
|
38241
|
-
if (
|
|
38343
|
+
if (existsSync56(tmp)) await unlink4(tmp);
|
|
38242
38344
|
} catch {
|
|
38243
38345
|
}
|
|
38244
38346
|
throw err;
|
|
@@ -38254,7 +38356,7 @@ async function collectLiveSidecars(projectsRoot) {
|
|
|
38254
38356
|
}
|
|
38255
38357
|
for (const slug of slugs) {
|
|
38256
38358
|
if (!slug.isDirectory()) continue;
|
|
38257
|
-
const slugDir =
|
|
38359
|
+
const slugDir = join69(projectsRoot, slug.name);
|
|
38258
38360
|
let entries2;
|
|
38259
38361
|
try {
|
|
38260
38362
|
entries2 = await readdir7(slugDir, { withFileTypes: true });
|
|
@@ -38263,9 +38365,9 @@ async function collectLiveSidecars(projectsRoot) {
|
|
|
38263
38365
|
}
|
|
38264
38366
|
for (const entry3 of entries2) {
|
|
38265
38367
|
if (entry3.isFile() && SESSION_META_RE.test(entry3.name)) {
|
|
38266
|
-
out.push(
|
|
38368
|
+
out.push(join69(slugDir, entry3.name));
|
|
38267
38369
|
} else if (entry3.isDirectory() && entry3.name === "subagents") {
|
|
38268
|
-
const subDir =
|
|
38370
|
+
const subDir = join69(slugDir, entry3.name);
|
|
38269
38371
|
let subs;
|
|
38270
38372
|
try {
|
|
38271
38373
|
subs = await readdir7(subDir, { withFileTypes: true });
|
|
@@ -38273,7 +38375,7 @@ async function collectLiveSidecars(projectsRoot) {
|
|
|
38273
38375
|
continue;
|
|
38274
38376
|
}
|
|
38275
38377
|
for (const s of subs) {
|
|
38276
|
-
if (s.isFile() && SESSION_META_RE.test(s.name)) out.push(
|
|
38378
|
+
if (s.isFile() && SESSION_META_RE.test(s.name)) out.push(join69(subDir, s.name));
|
|
38277
38379
|
}
|
|
38278
38380
|
}
|
|
38279
38381
|
}
|
|
@@ -38285,7 +38387,7 @@ function shortId(path) {
|
|
|
38285
38387
|
return base.slice(0, 8);
|
|
38286
38388
|
}
|
|
38287
38389
|
async function migrateAdminWebchatSidecars(opts = {}) {
|
|
38288
|
-
const projectsRoot = opts.projectsRoot ?? (process.env.CLAUDE_CONFIG_DIR ?
|
|
38390
|
+
const projectsRoot = opts.projectsRoot ?? (process.env.CLAUDE_CONFIG_DIR ? join69(process.env.CLAUDE_CONFIG_DIR, "projects") : null) ?? "";
|
|
38289
38391
|
const usersFile = opts.usersFile ?? USERS_FILE;
|
|
38290
38392
|
const accountId = opts.accountId ?? resolveAccount()?.accountId ?? null;
|
|
38291
38393
|
const resolveName = opts.resolveName ?? defaultResolveName;
|
|
@@ -38361,8 +38463,8 @@ async function migrateAdminWebchatSidecars(opts = {}) {
|
|
|
38361
38463
|
|
|
38362
38464
|
// app/lib/migrate-sidecar-account-ids.ts
|
|
38363
38465
|
import { readdir as readdir8, readFile as readFile14, rename as rename6, writeFile as writeFile5, unlink as unlink5 } from "fs/promises";
|
|
38364
|
-
import { existsSync as
|
|
38365
|
-
import { join as
|
|
38466
|
+
import { existsSync as existsSync57 } from "fs";
|
|
38467
|
+
import { join as join70 } from "path";
|
|
38366
38468
|
var SESSION_META_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\.meta\.json$/i;
|
|
38367
38469
|
function projectSlugForCwd(cwd) {
|
|
38368
38470
|
return cwd.replace(/\//g, "-");
|
|
@@ -38388,7 +38490,7 @@ async function writeRaw2(path, obj) {
|
|
|
38388
38490
|
await rename6(tmp, path);
|
|
38389
38491
|
} catch (err) {
|
|
38390
38492
|
try {
|
|
38391
|
-
if (
|
|
38493
|
+
if (existsSync57(tmp)) await unlink5(tmp);
|
|
38392
38494
|
} catch {
|
|
38393
38495
|
}
|
|
38394
38496
|
throw err;
|
|
@@ -38408,7 +38510,7 @@ async function collectSidecars(projectsRoot) {
|
|
|
38408
38510
|
}
|
|
38409
38511
|
for (const slug of slugs) {
|
|
38410
38512
|
if (!slug.isDirectory()) continue;
|
|
38411
|
-
const slugDir =
|
|
38513
|
+
const slugDir = join70(projectsRoot, slug.name);
|
|
38412
38514
|
let entries2;
|
|
38413
38515
|
try {
|
|
38414
38516
|
entries2 = await readdir8(slugDir, { withFileTypes: true });
|
|
@@ -38417,9 +38519,9 @@ async function collectSidecars(projectsRoot) {
|
|
|
38417
38519
|
}
|
|
38418
38520
|
for (const entry3 of entries2) {
|
|
38419
38521
|
if (entry3.isFile() && SESSION_META_RE2.test(entry3.name)) {
|
|
38420
|
-
out.push({ path:
|
|
38522
|
+
out.push({ path: join70(slugDir, entry3.name), slug: slug.name });
|
|
38421
38523
|
} else if (entry3.isDirectory() && (entry3.name === "subagents" || entry3.name === "archive")) {
|
|
38422
|
-
const subDir =
|
|
38524
|
+
const subDir = join70(slugDir, entry3.name);
|
|
38423
38525
|
let subs;
|
|
38424
38526
|
try {
|
|
38425
38527
|
subs = await readdir8(subDir, { withFileTypes: true });
|
|
@@ -38428,7 +38530,7 @@ async function collectSidecars(projectsRoot) {
|
|
|
38428
38530
|
}
|
|
38429
38531
|
for (const s of subs) {
|
|
38430
38532
|
if (s.isFile() && SESSION_META_RE2.test(s.name)) {
|
|
38431
|
-
out.push({ path:
|
|
38533
|
+
out.push({ path: join70(subDir, s.name), slug: slug.name });
|
|
38432
38534
|
}
|
|
38433
38535
|
}
|
|
38434
38536
|
}
|
|
@@ -38437,7 +38539,7 @@ async function collectSidecars(projectsRoot) {
|
|
|
38437
38539
|
return out;
|
|
38438
38540
|
}
|
|
38439
38541
|
async function migrateSidecarAccountIds(opts = {}) {
|
|
38440
|
-
const projectsRoot = opts.projectsRoot ?? (process.env.CLAUDE_CONFIG_DIR ?
|
|
38542
|
+
const projectsRoot = opts.projectsRoot ?? (process.env.CLAUDE_CONFIG_DIR ? join70(process.env.CLAUDE_CONFIG_DIR, "projects") : null) ?? "";
|
|
38441
38543
|
const accounts = opts.accounts ?? listValidAccounts();
|
|
38442
38544
|
const result = {
|
|
38443
38545
|
scanned: 0,
|
|
@@ -40060,8 +40162,8 @@ function createWebchatChannelRoutes(deps) {
|
|
|
40060
40162
|
}
|
|
40061
40163
|
|
|
40062
40164
|
// app/lib/webchat/gateway/resolve-turn-answer.ts
|
|
40063
|
-
import { existsSync as
|
|
40064
|
-
import { join as
|
|
40165
|
+
import { existsSync as existsSync58, openSync as openSync9, readSync as readSync8, closeSync as closeSync9, readdirSync as readdirSync34 } from "fs";
|
|
40166
|
+
import { join as join71 } from "path";
|
|
40065
40167
|
|
|
40066
40168
|
// app/lib/channel-delivery/outbound-guard.ts
|
|
40067
40169
|
var INTERNAL_LEAK_PATTERNS = [
|
|
@@ -40122,7 +40224,7 @@ function resolveTurnAnswer(p) {
|
|
|
40122
40224
|
return segmentText(guardOutbound(p.senderId, parts.join("\n\n"))).join("\n\n");
|
|
40123
40225
|
}
|
|
40124
40226
|
function findJsonl(projectsRoot, sessionId) {
|
|
40125
|
-
if (!
|
|
40227
|
+
if (!existsSync58(projectsRoot)) return null;
|
|
40126
40228
|
let slugs;
|
|
40127
40229
|
try {
|
|
40128
40230
|
slugs = readdirSync34(projectsRoot, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
@@ -40130,8 +40232,8 @@ function findJsonl(projectsRoot, sessionId) {
|
|
|
40130
40232
|
return null;
|
|
40131
40233
|
}
|
|
40132
40234
|
for (const slug of slugs) {
|
|
40133
|
-
const live =
|
|
40134
|
-
if (
|
|
40235
|
+
const live = join71(projectsRoot, slug, `${sessionId}.jsonl`);
|
|
40236
|
+
if (existsSync58(live)) return live;
|
|
40135
40237
|
}
|
|
40136
40238
|
return null;
|
|
40137
40239
|
}
|
|
@@ -41678,7 +41780,12 @@ var InboundHub3 = class {
|
|
|
41678
41780
|
return this.keys.get(key2)?.subscriber != null;
|
|
41679
41781
|
}
|
|
41680
41782
|
/** Whether a key's channel server is attached AND has signalled readiness.
|
|
41681
|
-
*
|
|
41783
|
+
*
|
|
41784
|
+
* Task 2737 — this DECIDES behaviour, it does not only describe it. Besides
|
|
41785
|
+
* logging delivery=immediate vs queued, it is the gateway's `isLive`, on
|
|
41786
|
+
* which the manual send route chooses between injecting into a running
|
|
41787
|
+
* process and appending to the session transcript. Change what this returns
|
|
41788
|
+
* and you change where an operator's words land. */
|
|
41682
41789
|
isReady(key2) {
|
|
41683
41790
|
const s = this.keys.get(key2);
|
|
41684
41791
|
return s?.subscriber != null && s.ready;
|
|
@@ -42152,6 +42259,21 @@ var TelegramGateway = class {
|
|
|
42152
42259
|
liveReplyTarget(key2) {
|
|
42153
42260
|
return this.replies.get(key2) ?? null;
|
|
42154
42261
|
}
|
|
42262
|
+
/** Task 2737 — is a channel server attached AND ready for this conversation?
|
|
42263
|
+
*
|
|
42264
|
+
* The SAME predicate `deliver` branches on at `inbound-hub.ts:132`, exposed
|
|
42265
|
+
* rather than re-derived. The manual send route routes on it: live and active
|
|
42266
|
+
* injects, everything else appends to the transcript. A second definition
|
|
42267
|
+
* would let that route believe an inject would land while the hub quietly
|
|
42268
|
+
* queued it for a spawn to drain, and the operator's own send must never
|
|
42269
|
+
* cause a spawn.
|
|
42270
|
+
*
|
|
42271
|
+
* Distinct from `liveReplyTarget`, which answers "can I send TO this door?"
|
|
42272
|
+
* off the reply-closure map. This answers "can this door receive a turn right
|
|
42273
|
+
* now?", and a closure can outlive the readiness that makes an inject land. */
|
|
42274
|
+
isLive(key2) {
|
|
42275
|
+
return this.hub.isReady(key2);
|
|
42276
|
+
}
|
|
42155
42277
|
/** Task 2559 — every door this gateway currently holds a live delivery closure
|
|
42156
42278
|
* for, as the `<botId>:<senderId>` channel key the follower registry keys on.
|
|
42157
42279
|
* The twin of `WaGateway.boundTargets()`: the census reconciles against
|
|
@@ -42814,7 +42936,7 @@ function startTelegramNativeFileFollower(input) {
|
|
|
42814
42936
|
}
|
|
42815
42937
|
|
|
42816
42938
|
// server/telegram-background-active.ts
|
|
42817
|
-
import { join as
|
|
42939
|
+
import { join as join72, resolve as resolve52 } from "path";
|
|
42818
42940
|
import { readdirSync as readdirSync35, statSync as statSync30 } from "fs";
|
|
42819
42941
|
var SUBAGENT_STALE_WINDOW_MS = 6e4;
|
|
42820
42942
|
var AGENT_JSONL_RE2 = /^agent-([0-9a-f]+)\.jsonl$/;
|
|
@@ -42833,7 +42955,7 @@ function makeBackgroundActive(sessionId, deps = {}) {
|
|
|
42833
42955
|
if (subagentsDir === null) {
|
|
42834
42956
|
const projectDir = findProjectDir(sessionId);
|
|
42835
42957
|
if (projectDir === null) return false;
|
|
42836
|
-
subagentsDir = resolve52(
|
|
42958
|
+
subagentsDir = resolve52(join72(projectDir, sessionId, "subagents"));
|
|
42837
42959
|
}
|
|
42838
42960
|
let names;
|
|
42839
42961
|
try {
|
|
@@ -42847,7 +42969,7 @@ function makeBackgroundActive(sessionId, deps = {}) {
|
|
|
42847
42969
|
let size;
|
|
42848
42970
|
let mtimeMs;
|
|
42849
42971
|
try {
|
|
42850
|
-
const st = statFile(
|
|
42972
|
+
const st = statFile(join72(subagentsDir, name));
|
|
42851
42973
|
size = st.size;
|
|
42852
42974
|
mtimeMs = st.mtimeMs;
|
|
42853
42975
|
} catch {
|
|
@@ -42926,7 +43048,7 @@ function adminFanTargets(p) {
|
|
|
42926
43048
|
}
|
|
42927
43049
|
|
|
42928
43050
|
// app/lib/channel-pty-bridge/public-session-end-review.ts
|
|
42929
|
-
import { randomUUID as
|
|
43051
|
+
import { randomUUID as randomUUID15 } from "crypto";
|
|
42930
43052
|
var TAG78 = "[public-session-review]";
|
|
42931
43053
|
var CONSUMED_CAP = 500;
|
|
42932
43054
|
var consumed = /* @__PURE__ */ new Set();
|
|
@@ -43014,7 +43136,7 @@ function composeInitialMessage(input) {
|
|
|
43014
43136
|
].join("\n");
|
|
43015
43137
|
}
|
|
43016
43138
|
async function dispatchReviewer(input, initialMessage) {
|
|
43017
|
-
const sessionId =
|
|
43139
|
+
const sessionId = randomUUID15();
|
|
43018
43140
|
console.log(`${TAG78} route target=rc-spawn sessionId=${sessionId.slice(0, 8)} sourceSession=${input.sessionId.slice(0, 8)}`);
|
|
43019
43141
|
const spawned = await managerRcSpawn({
|
|
43020
43142
|
sessionId,
|
|
@@ -43214,7 +43336,7 @@ function runPublicAddressCollisionAudit(deps) {
|
|
|
43214
43336
|
|
|
43215
43337
|
// server/telegram-audit.ts
|
|
43216
43338
|
import { statSync as statSync31 } from "fs";
|
|
43217
|
-
import { join as
|
|
43339
|
+
import { join as join73 } from "path";
|
|
43218
43340
|
function buildTelegramAuditLines(input) {
|
|
43219
43341
|
const lines = [];
|
|
43220
43342
|
const entries2 = input.accounts.flatMap(
|
|
@@ -43322,7 +43444,7 @@ function countTelegramSessionsForAccount(accountId) {
|
|
|
43322
43444
|
function* walkTelegramSidecars() {
|
|
43323
43445
|
const cfg = claudeConfigDir();
|
|
43324
43446
|
if (!cfg) return;
|
|
43325
|
-
const projectsRoot =
|
|
43447
|
+
const projectsRoot = join73(cfg, "projects");
|
|
43326
43448
|
for (const { path } of enumerateSessionSidecars(projectsRoot)) {
|
|
43327
43449
|
const meta = readSidecarMeta(path);
|
|
43328
43450
|
if (meta.channel !== "telegram" || !meta.accountId) continue;
|
|
@@ -43534,8 +43656,8 @@ function businessConnectionCensusLine(c) {
|
|
|
43534
43656
|
}
|
|
43535
43657
|
|
|
43536
43658
|
// app/lib/telegram/business-window-census.ts
|
|
43537
|
-
import { readdirSync as readdirSync36, existsSync as
|
|
43538
|
-
import { join as
|
|
43659
|
+
import { readdirSync as readdirSync36, existsSync as existsSync59 } from "fs";
|
|
43660
|
+
import { join as join74 } from "path";
|
|
43539
43661
|
var BUSINESS_WINDOW_CENSUS_TAG = "[telegram-audit]";
|
|
43540
43662
|
var EXPIRING_SOON_S = 3600;
|
|
43541
43663
|
function collectBusinessWindowCensus(input) {
|
|
@@ -43563,8 +43685,8 @@ function businessWindowCensusLine(c) {
|
|
|
43563
43685
|
function readBusinessChatClocks(accountIds) {
|
|
43564
43686
|
const out = [];
|
|
43565
43687
|
for (const accountId of accountIds) {
|
|
43566
|
-
const dir =
|
|
43567
|
-
if (!
|
|
43688
|
+
const dir = join74(STORE_ROOT2(), accountId);
|
|
43689
|
+
if (!existsSync59(dir)) continue;
|
|
43568
43690
|
let names;
|
|
43569
43691
|
try {
|
|
43570
43692
|
names = readdirSync36(dir);
|
|
@@ -43625,15 +43747,15 @@ async function getTelegramBusinessConnection(botToken, connectionId, opts = {})
|
|
|
43625
43747
|
}
|
|
43626
43748
|
|
|
43627
43749
|
// server/telegram-migrate.ts
|
|
43628
|
-
import { readFileSync as
|
|
43629
|
-
import { dirname as dirname19, join as
|
|
43750
|
+
import { readFileSync as readFileSync59, writeFileSync as writeFileSync23, existsSync as existsSync60, renameSync as renameSync11, mkdirSync as mkdirSync14 } from "fs";
|
|
43751
|
+
import { dirname as dirname19, join as join75 } from "path";
|
|
43630
43752
|
function migrateTelegramTwoSlot(input) {
|
|
43631
43753
|
const out = [];
|
|
43632
43754
|
for (const account of input.accounts) {
|
|
43633
|
-
const configPath3 =
|
|
43755
|
+
const configPath3 = join75(account.accountDir, "account.json");
|
|
43634
43756
|
let config;
|
|
43635
43757
|
try {
|
|
43636
|
-
config = JSON.parse(
|
|
43758
|
+
config = JSON.parse(readFileSync59(configPath3, "utf-8"));
|
|
43637
43759
|
} catch {
|
|
43638
43760
|
console.error(`[telegram-audit] op=migrate-unreadable accountId=${account.accountId}`);
|
|
43639
43761
|
continue;
|
|
@@ -43686,22 +43808,22 @@ function migrateTelegramTwoSlot(input) {
|
|
|
43686
43808
|
return out;
|
|
43687
43809
|
}
|
|
43688
43810
|
function moveSecret(from, to) {
|
|
43689
|
-
if (!
|
|
43811
|
+
if (!existsSync60(from)) return;
|
|
43690
43812
|
mkdirSync14(dirname19(to), { recursive: true, mode: 448 });
|
|
43691
43813
|
renameSync11(from, to);
|
|
43692
43814
|
}
|
|
43693
43815
|
|
|
43694
43816
|
// server/telegram-unadopt.ts
|
|
43695
|
-
import { readFileSync as
|
|
43696
|
-
import { join as
|
|
43817
|
+
import { readFileSync as readFileSync60, writeFileSync as writeFileSync24, renameSync as renameSync12 } from "fs";
|
|
43818
|
+
import { join as join76 } from "path";
|
|
43697
43819
|
var FILE3 = "channel-session-override.json";
|
|
43698
43820
|
function unadoptTelegramPointers(input) {
|
|
43699
43821
|
return input.accounts.map(({ accountId, accountDir }) => {
|
|
43700
43822
|
const out = { accountId, dropped: [], kept: 0, unknown: 0 };
|
|
43701
|
-
const path =
|
|
43823
|
+
const path = join76(accountDir, FILE3);
|
|
43702
43824
|
const bySender = {};
|
|
43703
43825
|
try {
|
|
43704
|
-
const raw = JSON.parse(
|
|
43826
|
+
const raw = JSON.parse(readFileSync60(path, "utf8"));
|
|
43705
43827
|
if (!raw.bySender || typeof raw.bySender !== "object") return out;
|
|
43706
43828
|
for (const [k, v] of Object.entries(raw.bySender)) if (typeof v === "string") bySender[k] = v;
|
|
43707
43829
|
} catch {
|
|
@@ -43772,14 +43894,14 @@ function backfillMisfiledRecords(params) {
|
|
|
43772
43894
|
}
|
|
43773
43895
|
|
|
43774
43896
|
// server/lib/booking-site-accounts.ts
|
|
43775
|
-
import { existsSync as
|
|
43897
|
+
import { existsSync as existsSync61, readFileSync as readFileSync61 } from "fs";
|
|
43776
43898
|
import { resolve as resolve53 } from "path";
|
|
43777
43899
|
function listBookingSiteAccounts(accounts) {
|
|
43778
43900
|
return accounts.filter((a) => {
|
|
43779
43901
|
const availPath = resolve53(a.accountDir, "calendar-availability.json");
|
|
43780
|
-
if (!
|
|
43902
|
+
if (!existsSync61(availPath)) return false;
|
|
43781
43903
|
try {
|
|
43782
|
-
const cfg = JSON.parse(
|
|
43904
|
+
const cfg = JSON.parse(readFileSync61(availPath, "utf-8"));
|
|
43783
43905
|
return typeof cfg.bookingDbName === "string" && cfg.bookingDbName.length > 0;
|
|
43784
43906
|
} catch {
|
|
43785
43907
|
return false;
|
|
@@ -43817,7 +43939,7 @@ function broadcastAdminShutdown(reason) {
|
|
|
43817
43939
|
|
|
43818
43940
|
// ../lib/entitlement/src/index.ts
|
|
43819
43941
|
import { createPublicKey, createHash as createHash7, verify as cryptoVerify } from "crypto";
|
|
43820
|
-
import { existsSync as
|
|
43942
|
+
import { existsSync as existsSync62, readFileSync as readFileSync62, statSync as statSync32 } from "fs";
|
|
43821
43943
|
import { resolve as resolve54 } from "path";
|
|
43822
43944
|
|
|
43823
43945
|
// ../lib/entitlement/src/canonicalize.ts
|
|
@@ -43866,7 +43988,7 @@ function resolveEntitlement(brand, account) {
|
|
|
43866
43988
|
return logResolved(implicitTrust(account), null);
|
|
43867
43989
|
}
|
|
43868
43990
|
const entitlementPath = resolve54(brand.configDir, "entitlement.json");
|
|
43869
|
-
if (!
|
|
43991
|
+
if (!existsSync62(entitlementPath)) {
|
|
43870
43992
|
return logResolved(anonymousFallback("missing"), { reason: "missing" });
|
|
43871
43993
|
}
|
|
43872
43994
|
const stat11 = statSync32(entitlementPath);
|
|
@@ -43881,7 +44003,7 @@ function resolveEntitlement(brand, account) {
|
|
|
43881
44003
|
function verifyAndResolve(brand, entitlementPath, account) {
|
|
43882
44004
|
let pubkeyPem;
|
|
43883
44005
|
try {
|
|
43884
|
-
pubkeyPem =
|
|
44006
|
+
pubkeyPem = readFileSync62(pubkeyPath(brand), "utf-8");
|
|
43885
44007
|
} catch (err) {
|
|
43886
44008
|
return logResolved(anonymousFallback("pubkey-missing"), {
|
|
43887
44009
|
reason: "pubkey-missing"
|
|
@@ -43895,7 +44017,7 @@ function verifyAndResolve(brand, entitlementPath, account) {
|
|
|
43895
44017
|
}
|
|
43896
44018
|
let envelope;
|
|
43897
44019
|
try {
|
|
43898
|
-
envelope = JSON.parse(
|
|
44020
|
+
envelope = JSON.parse(readFileSync62(entitlementPath, "utf-8"));
|
|
43899
44021
|
} catch {
|
|
43900
44022
|
return logResolved(anonymousFallback("malformed"), { reason: "malformed" });
|
|
43901
44023
|
}
|
|
@@ -44057,14 +44179,14 @@ function clientFrom(c) {
|
|
|
44057
44179
|
}
|
|
44058
44180
|
installMediaDownloadGuard();
|
|
44059
44181
|
var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT || "";
|
|
44060
|
-
var BRAND_JSON_PATH = PLATFORM_ROOT6 ?
|
|
44182
|
+
var BRAND_JSON_PATH = PLATFORM_ROOT6 ? join77(PLATFORM_ROOT6, "config", "brand.json") : "";
|
|
44061
44183
|
var BRAND = { productName: "Maxy", hostname: "maxy", configDir: ".maxy", marketingUrl: "https://getmaxy.com" };
|
|
44062
|
-
if (BRAND_JSON_PATH && !
|
|
44184
|
+
if (BRAND_JSON_PATH && !existsSync63(BRAND_JSON_PATH)) {
|
|
44063
44185
|
console.error(`[brand] WARNING: brand.json not found at ${BRAND_JSON_PATH} \u2014 using Maxy defaults`);
|
|
44064
44186
|
}
|
|
44065
|
-
if (BRAND_JSON_PATH &&
|
|
44187
|
+
if (BRAND_JSON_PATH && existsSync63(BRAND_JSON_PATH)) {
|
|
44066
44188
|
try {
|
|
44067
|
-
const parsed = JSON.parse(
|
|
44189
|
+
const parsed = JSON.parse(readFileSync63(BRAND_JSON_PATH, "utf-8"));
|
|
44068
44190
|
BRAND = { ...BRAND, ...parsed };
|
|
44069
44191
|
} catch (err) {
|
|
44070
44192
|
console.error(`[brand] Failed to parse brand.json: ${err.message}`);
|
|
@@ -44096,11 +44218,11 @@ var brandLoginOpts = {
|
|
|
44096
44218
|
appleTouchIconPath: brandAppIcon512Path,
|
|
44097
44219
|
themeColor: BRAND.defaultColors?.primary
|
|
44098
44220
|
};
|
|
44099
|
-
var ALIAS_DOMAINS_PATH =
|
|
44221
|
+
var ALIAS_DOMAINS_PATH = join77(homedir5(), BRAND.configDir, "alias-domains.json");
|
|
44100
44222
|
function loadAliasDomains() {
|
|
44101
44223
|
try {
|
|
44102
|
-
if (!
|
|
44103
|
-
const parsed = JSON.parse(
|
|
44224
|
+
if (!existsSync63(ALIAS_DOMAINS_PATH)) return null;
|
|
44225
|
+
const parsed = JSON.parse(readFileSync63(ALIAS_DOMAINS_PATH, "utf-8"));
|
|
44104
44226
|
if (!Array.isArray(parsed)) {
|
|
44105
44227
|
console.error("[alias-domains] malformed alias-domains.json \u2014 expected array");
|
|
44106
44228
|
return null;
|
|
@@ -44242,7 +44364,7 @@ var waGateway = new WaGateway({
|
|
|
44242
44364
|
// resolver and `fanTargetsFor` is a constructor dep, not a callable method.
|
|
44243
44365
|
fanTargetsFor: whatsappFanTargets,
|
|
44244
44366
|
gatewayUrl: `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`,
|
|
44245
|
-
serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve55(process.env.MAXY_PLATFORM_ROOT ??
|
|
44367
|
+
serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve55(process.env.MAXY_PLATFORM_ROOT ?? join77(__dirname, ".."), "services/whatsapp-channel/dist/server.js"),
|
|
44246
44368
|
// Task 751 / 1390 — file delivery on the native channel. `maxyAccountId` (the
|
|
44247
44369
|
// path-validation scope) is the sender's effective SESSION account, resolved
|
|
44248
44370
|
// once at the inbound gate and threaded here via the gateway's per-sender doc
|
|
@@ -44257,7 +44379,7 @@ var waGateway = new WaGateway({
|
|
|
44257
44379
|
caption,
|
|
44258
44380
|
accountId,
|
|
44259
44381
|
maxyAccountId,
|
|
44260
|
-
platformRoot: resolve55(process.env.MAXY_PLATFORM_ROOT ??
|
|
44382
|
+
platformRoot: resolve55(process.env.MAXY_PLATFORM_ROOT ?? join77(__dirname, ".."))
|
|
44261
44383
|
});
|
|
44262
44384
|
return result.ok ? { ok: true, messageId: result.messageId } : { ok: false, error: result.error };
|
|
44263
44385
|
},
|
|
@@ -44432,7 +44554,7 @@ function runDuplicateSenderAudit() {
|
|
|
44432
44554
|
try {
|
|
44433
44555
|
const configDir = process.env.CLAUDE_CONFIG_DIR;
|
|
44434
44556
|
if (!configDir) return;
|
|
44435
|
-
const projectsRoot =
|
|
44557
|
+
const projectsRoot = join77(configDir, "projects");
|
|
44436
44558
|
const records5 = [];
|
|
44437
44559
|
for (const { path: jsonlPath, isSubagent, archived } of enumerateJsonls(projectsRoot)) {
|
|
44438
44560
|
if (isSubagent || archived) continue;
|
|
@@ -44484,7 +44606,7 @@ var webchatGateway = new WebchatGateway({
|
|
|
44484
44606
|
// rather than hanging the POST.
|
|
44485
44607
|
publicProjectsRoot: () => {
|
|
44486
44608
|
const cfg = claudeConfigDir();
|
|
44487
|
-
return cfg ?
|
|
44609
|
+
return cfg ? join77(cfg, "projects") : "";
|
|
44488
44610
|
},
|
|
44489
44611
|
gatewayUrl: webchatGatewayUrl(),
|
|
44490
44612
|
serverPath: webchatServerPath(),
|
|
@@ -45151,14 +45273,14 @@ app80.get("/agent-assets/:slug/:filename", (c) => {
|
|
|
45151
45273
|
console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
|
|
45152
45274
|
return c.text("Forbidden", 403);
|
|
45153
45275
|
}
|
|
45154
|
-
if (!
|
|
45276
|
+
if (!existsSync63(filePath)) {
|
|
45155
45277
|
console.error(`[agent-assets] serve slug=${slug} file=${filename} status=404`);
|
|
45156
45278
|
return c.text("Not found", 404);
|
|
45157
45279
|
}
|
|
45158
45280
|
const ext = "." + filename.split(".").pop()?.toLowerCase();
|
|
45159
45281
|
const contentType = IMAGE_MIME[ext] || "application/octet-stream";
|
|
45160
45282
|
console.log(`[agent-assets] serve slug=${slug} file=${filename} status=200`);
|
|
45161
|
-
const body =
|
|
45283
|
+
const body = readFileSync63(filePath);
|
|
45162
45284
|
return c.body(body, 200, {
|
|
45163
45285
|
"Content-Type": contentType,
|
|
45164
45286
|
"Cache-Control": "public, max-age=3600"
|
|
@@ -45181,14 +45303,14 @@ app80.get("/generated/:filename", (c) => {
|
|
|
45181
45303
|
console.error(`[generated] serve file=${filename} status=403`);
|
|
45182
45304
|
return c.text("Forbidden", 403);
|
|
45183
45305
|
}
|
|
45184
|
-
if (!
|
|
45306
|
+
if (!existsSync63(filePath)) {
|
|
45185
45307
|
console.error(`[generated] serve file=${filename} status=404`);
|
|
45186
45308
|
return c.text("Not found", 404);
|
|
45187
45309
|
}
|
|
45188
45310
|
const ext = "." + filename.split(".").pop()?.toLowerCase();
|
|
45189
45311
|
const contentType = IMAGE_MIME[ext] || "application/octet-stream";
|
|
45190
45312
|
console.log(`[generated] serve file=${filename} status=200`);
|
|
45191
|
-
const body =
|
|
45313
|
+
const body = readFileSync63(filePath);
|
|
45192
45314
|
return c.body(body, 200, {
|
|
45193
45315
|
"Content-Type": contentType,
|
|
45194
45316
|
"Cache-Control": "public, max-age=86400"
|
|
@@ -45201,9 +45323,9 @@ app80.route("/v", visitor_consent_default);
|
|
|
45201
45323
|
var htmlCache = /* @__PURE__ */ new Map();
|
|
45202
45324
|
var brandLogoPath = "/brand/maxy-monochrome.png";
|
|
45203
45325
|
var brandIconPath = "/brand/maxy-monochrome.png";
|
|
45204
|
-
if (BRAND_JSON_PATH &&
|
|
45326
|
+
if (BRAND_JSON_PATH && existsSync63(BRAND_JSON_PATH)) {
|
|
45205
45327
|
try {
|
|
45206
|
-
const fullBrand = JSON.parse(
|
|
45328
|
+
const fullBrand = JSON.parse(readFileSync63(BRAND_JSON_PATH, "utf-8"));
|
|
45207
45329
|
if (fullBrand.assets?.logo) brandLogoPath = `/brand/${fullBrand.assets.logo}`;
|
|
45208
45330
|
brandIconPath = fullBrand.assets?.icon ? `/brand/${fullBrand.assets.icon}` : brandLogoPath;
|
|
45209
45331
|
} catch {
|
|
@@ -45230,11 +45352,11 @@ var brandScript = `<script>window.__BRAND__=${JSON.stringify({
|
|
|
45230
45352
|
var brandThemeColor = BRAND.defaultColors?.primary ?? "#000000";
|
|
45231
45353
|
var brandBackgroundColor = BRAND.defaultColors?.background ?? "#ffffff";
|
|
45232
45354
|
var brandAppIconsExist = [brandAppIcon192Path, brandAppIcon512Path, brandMaskableIconPath].every(
|
|
45233
|
-
(p) =>
|
|
45355
|
+
(p) => existsSync63(resolve55(process.cwd(), "public", p.replace(/^\//, "")))
|
|
45234
45356
|
);
|
|
45235
45357
|
var SW_SOURCE = (() => {
|
|
45236
45358
|
try {
|
|
45237
|
-
return
|
|
45359
|
+
return readFileSync63(resolve55(process.cwd(), "public", "sw.js"), "utf-8");
|
|
45238
45360
|
} catch {
|
|
45239
45361
|
return null;
|
|
45240
45362
|
}
|
|
@@ -45242,9 +45364,9 @@ var SW_SOURCE = (() => {
|
|
|
45242
45364
|
function readInstalledVersion() {
|
|
45243
45365
|
try {
|
|
45244
45366
|
if (!PLATFORM_ROOT6) return "unknown";
|
|
45245
|
-
const versionFile =
|
|
45246
|
-
if (!
|
|
45247
|
-
const content =
|
|
45367
|
+
const versionFile = join77(PLATFORM_ROOT6, "config", `.${BRAND.hostname}-version`);
|
|
45368
|
+
if (!existsSync63(versionFile)) return "unknown";
|
|
45369
|
+
const content = readFileSync63(versionFile, "utf-8").trim();
|
|
45248
45370
|
return content || "unknown";
|
|
45249
45371
|
} catch {
|
|
45250
45372
|
return "unknown";
|
|
@@ -45255,7 +45377,7 @@ var versionScript = `<script>window.__MAXY_VERSION__=${JSON.stringify(INSTALLED_
|
|
|
45255
45377
|
function cachedHtml(file) {
|
|
45256
45378
|
let html = htmlCache.get(file);
|
|
45257
45379
|
if (!html) {
|
|
45258
|
-
html =
|
|
45380
|
+
html = readFileSync63(resolve55(process.cwd(), "public", file), "utf-8");
|
|
45259
45381
|
const productNameEsc = escapeHtml(BRAND.productName);
|
|
45260
45382
|
html = html.replace(/<title>([^<]*)<\/title>/, (_match, inner) => `<title>${escapeHtml(inner).replace(/Maxy/g, productNameEsc)}</title>`);
|
|
45261
45383
|
html = html.replace('href="/favicon.ico"', `href="${escapeHtml(brandFaviconPath)}"`);
|
|
@@ -45272,14 +45394,14 @@ ${clientErrorReporterScript}
|
|
|
45272
45394
|
return html;
|
|
45273
45395
|
}
|
|
45274
45396
|
function loadBrandingCache(agentSlug) {
|
|
45275
|
-
const configDir =
|
|
45397
|
+
const configDir = join77(homedir5(), BRAND.configDir);
|
|
45276
45398
|
try {
|
|
45277
45399
|
const verdict = resolvePublicAddressFromDisk(agentSlug);
|
|
45278
45400
|
const accountId = verdict.kind === "served" ? verdict.owner.accountId : getDefaultAccountId();
|
|
45279
45401
|
if (!accountId) return null;
|
|
45280
|
-
const cachePath =
|
|
45281
|
-
if (!
|
|
45282
|
-
return JSON.parse(
|
|
45402
|
+
const cachePath = join77(configDir, "branding-cache", accountId, `${agentSlug}.json`);
|
|
45403
|
+
if (!existsSync63(cachePath)) return null;
|
|
45404
|
+
return JSON.parse(readFileSync63(cachePath, "utf-8"));
|
|
45283
45405
|
} catch {
|
|
45284
45406
|
return null;
|
|
45285
45407
|
}
|
|
@@ -45374,7 +45496,7 @@ app80.use("/vnc-popout.html", logViewerFetch);
|
|
|
45374
45496
|
app80.get("/vnc-popout.html", (c) => {
|
|
45375
45497
|
let html = htmlCache.get("vnc-popout.html");
|
|
45376
45498
|
if (!html) {
|
|
45377
|
-
html =
|
|
45499
|
+
html = readFileSync63(resolve55(process.cwd(), "public", "vnc-popout.html"), "utf-8");
|
|
45378
45500
|
const name = escapeHtml(BRAND.productName);
|
|
45379
45501
|
html = html.replace("<title>Browser \u2014 Maxy</title>", `<title>${name}</title>`);
|
|
45380
45502
|
html = html.replace("</head>", ` ${brandScript}
|
|
@@ -45528,10 +45650,10 @@ var hostname = process.env.HOSTNAME ?? "127.0.0.1";
|
|
|
45528
45650
|
var httpServer = serve({ fetch: app80.fetch, port, hostname });
|
|
45529
45651
|
console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
45530
45652
|
{
|
|
45531
|
-
const reconcilePlatformRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
45653
|
+
const reconcilePlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join77(__dirname, "..");
|
|
45532
45654
|
const reconcileScript = resolve55(reconcilePlatformRoot, "plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js");
|
|
45533
45655
|
const runReconcile = (ctx) => {
|
|
45534
|
-
if (!
|
|
45656
|
+
if (!existsSync63(reconcileScript)) return;
|
|
45535
45657
|
try {
|
|
45536
45658
|
const child = spawn3(process.execPath, [reconcileScript], {
|
|
45537
45659
|
env: { ...process.env, PLATFORM_ROOT: reconcilePlatformRoot },
|
|
@@ -45551,7 +45673,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
45551
45673
|
detached: true,
|
|
45552
45674
|
run: runReconcile
|
|
45553
45675
|
});
|
|
45554
|
-
const reconcileStatePath =
|
|
45676
|
+
const reconcileStatePath = join77(MAXY_DIR, "booking-reconcile-state.json");
|
|
45555
45677
|
registerLoop({
|
|
45556
45678
|
name: "calendar-reconcile-liveness",
|
|
45557
45679
|
intervalMs: 6e5,
|
|
@@ -45569,7 +45691,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
45569
45691
|
}
|
|
45570
45692
|
{
|
|
45571
45693
|
const DREAM_CYCLE_SWEEP_INTERVAL_MS = 36e5;
|
|
45572
|
-
const dreamPlatformRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
45694
|
+
const dreamPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join77(__dirname, "..");
|
|
45573
45695
|
const dreamSweepScript = resolve55(dreamPlatformRoot, "plugins/memory/mcp/dist/scripts/dream-cycle-sweep.js");
|
|
45574
45696
|
registerLoop({
|
|
45575
45697
|
name: "dream-cycle-sweep",
|
|
@@ -45577,7 +45699,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
45577
45699
|
firstRunDelayMs: 3e4,
|
|
45578
45700
|
detached: true,
|
|
45579
45701
|
run: (ctx) => {
|
|
45580
|
-
if (!
|
|
45702
|
+
if (!existsSync63(dreamSweepScript)) return;
|
|
45581
45703
|
try {
|
|
45582
45704
|
const child = spawn3(process.execPath, [dreamSweepScript], {
|
|
45583
45705
|
env: { ...process.env, PLATFORM_ROOT: dreamPlatformRoot },
|
|
@@ -45593,11 +45715,11 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
45593
45715
|
});
|
|
45594
45716
|
}
|
|
45595
45717
|
{
|
|
45596
|
-
const outlookPlatformRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
45718
|
+
const outlookPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join77(__dirname, "..");
|
|
45597
45719
|
const outlookScript = resolve55(outlookPlatformRoot, "plugins/outlook/mcp/dist/scripts/complete-registration.js");
|
|
45598
45720
|
const OUTLOOK_COMPLETE_INTERVAL_MS = 3e4;
|
|
45599
45721
|
const runOutlookComplete = (ctx) => {
|
|
45600
|
-
if (!
|
|
45722
|
+
if (!existsSync63(outlookScript)) return;
|
|
45601
45723
|
try {
|
|
45602
45724
|
const child = spawn3(process.execPath, [outlookScript], {
|
|
45603
45725
|
env: { ...process.env, PLATFORM_ROOT: outlookPlatformRoot },
|
|
@@ -45619,19 +45741,19 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
45619
45741
|
});
|
|
45620
45742
|
}
|
|
45621
45743
|
{
|
|
45622
|
-
const auditRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
45744
|
+
const auditRoot = process.env.MAXY_PLATFORM_ROOT ?? join77(__dirname, "..");
|
|
45623
45745
|
const strandedAccountsDir = resolve55(auditRoot, "..", "data/accounts");
|
|
45624
45746
|
const STRANDED_AUDIT_INTERVAL_MS = 3e5;
|
|
45625
45747
|
const STRANDED_AGE_MS = 16 * 6e4;
|
|
45626
45748
|
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;
|
|
45627
45749
|
const runStrandedAudit = () => {
|
|
45628
45750
|
try {
|
|
45629
|
-
if (!
|
|
45751
|
+
if (!existsSync63(strandedAccountsDir)) return;
|
|
45630
45752
|
const now = Date.now();
|
|
45631
45753
|
for (const name of readdirSync37(strandedAccountsDir)) {
|
|
45632
45754
|
if (!STRANDED_UUID_RE.test(name)) continue;
|
|
45633
45755
|
const pendingPath2 = resolve55(strandedAccountsDir, name, "secrets/outlook/pending-devicecode.enc");
|
|
45634
|
-
if (!
|
|
45756
|
+
if (!existsSync63(pendingPath2)) continue;
|
|
45635
45757
|
const ageMs2 = now - statSync33(pendingPath2).mtimeMs;
|
|
45636
45758
|
if (ageMs2 > STRANDED_AGE_MS) {
|
|
45637
45759
|
console.error(`[outlook-mcp] devicecode-stranded account=${name} ageSec=${Math.floor(ageMs2 / 1e3)}`);
|
|
@@ -45649,7 +45771,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
45649
45771
|
});
|
|
45650
45772
|
}
|
|
45651
45773
|
{
|
|
45652
|
-
const googleRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
45774
|
+
const googleRoot = process.env.MAXY_PLATFORM_ROOT ?? join77(__dirname, "..");
|
|
45653
45775
|
const googleAccountsDir = resolve55(googleRoot, "..", "data/accounts");
|
|
45654
45776
|
const GOOGLE_PENDING_AUDIT_INTERVAL_MS = 3e5;
|
|
45655
45777
|
const runGooglePendingAuditSafe = () => {
|
|
@@ -45668,7 +45790,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
45668
45790
|
const googleAuditScript = resolve55(googleRoot, "plugins/google/mcp/dist/scripts/account-audit.js");
|
|
45669
45791
|
const GOOGLE_ACCOUNT_AUDIT_INTERVAL_MS = 36e5;
|
|
45670
45792
|
const runGoogleAccountAudit = (ctx) => {
|
|
45671
|
-
if (!
|
|
45793
|
+
if (!existsSync63(googleAuditScript)) return;
|
|
45672
45794
|
try {
|
|
45673
45795
|
const child = spawn3(process.execPath, [googleAuditScript], {
|
|
45674
45796
|
env: { ...process.env, PLATFORM_ROOT: googleRoot },
|
|
@@ -45705,7 +45827,7 @@ registerLoop({
|
|
|
45705
45827
|
}
|
|
45706
45828
|
});
|
|
45707
45829
|
{
|
|
45708
|
-
const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
45830
|
+
const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join77(__dirname, "..");
|
|
45709
45831
|
const STORAGE_AUDIT_INTERVAL_MS = 3e5;
|
|
45710
45832
|
const runStorageAuditSafe = () => runStorageAudit(auditPlatformRoot).catch((err) => {
|
|
45711
45833
|
console.error(`[storage-audit] error="${err.message}"`);
|
|
@@ -45777,10 +45899,10 @@ registerLoop({
|
|
|
45777
45899
|
}
|
|
45778
45900
|
const lines = buildTelegramAuditLines({
|
|
45779
45901
|
accounts,
|
|
45780
|
-
secretFileExists: (botId) =>
|
|
45902
|
+
secretFileExists: (botId) => existsSync63(secretPath(botId)),
|
|
45781
45903
|
agentActive: isActiveAgentSlug,
|
|
45782
45904
|
// Task 2619 — the card set a specialist binding is reconciled against.
|
|
45783
|
-
specialistCards: (accountDir) => listSpecialistCardNames(
|
|
45905
|
+
specialistCards: (accountDir) => listSpecialistCardNames(join77(accountDir, "specialists", "agents")),
|
|
45784
45906
|
// Task 2619 — the doors that can be sent to right now. The same accessor
|
|
45785
45907
|
// the follower census reads (:1185), so "should have a reader" and "can be
|
|
45786
45908
|
// sent to" stay one fact.
|
|
@@ -46181,7 +46303,7 @@ registerLoop({
|
|
|
46181
46303
|
});
|
|
46182
46304
|
}
|
|
46183
46305
|
{
|
|
46184
|
-
const publishPlatformRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
46306
|
+
const publishPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join77(__dirname, "..");
|
|
46185
46307
|
const publishScript = resolve55(publishPlatformRoot, "plugins/scheduling/mcp/dist/scripts/publish-availability.js");
|
|
46186
46308
|
const PUBLISH_INTERVAL_MS = 3e5;
|
|
46187
46309
|
const bookingAccounts = () => {
|
|
@@ -46193,7 +46315,7 @@ registerLoop({
|
|
|
46193
46315
|
}
|
|
46194
46316
|
};
|
|
46195
46317
|
const spawnPublish = (account, ctx) => {
|
|
46196
|
-
if (!
|
|
46318
|
+
if (!existsSync63(publishScript)) return;
|
|
46197
46319
|
try {
|
|
46198
46320
|
const child = spawn3(process.execPath, [publishScript], {
|
|
46199
46321
|
env: {
|
|
@@ -46215,8 +46337,8 @@ registerLoop({
|
|
|
46215
46337
|
const availPath = resolve55(account.accountDir, "calendar-availability.json");
|
|
46216
46338
|
let hasBookingSite = false;
|
|
46217
46339
|
try {
|
|
46218
|
-
if (
|
|
46219
|
-
const cfg = JSON.parse(
|
|
46340
|
+
if (existsSync63(availPath)) {
|
|
46341
|
+
const cfg = JSON.parse(readFileSync63(availPath, "utf-8"));
|
|
46220
46342
|
hasBookingSite = typeof cfg.bookingDbName === "string" && cfg.bookingDbName.length > 0;
|
|
46221
46343
|
}
|
|
46222
46344
|
} catch {
|
|
@@ -46224,9 +46346,9 @@ registerLoop({
|
|
|
46224
46346
|
if (!hasBookingSite) return;
|
|
46225
46347
|
const statePath = resolve55(account.accountDir, "state", "booking-availability", "last-publish.json");
|
|
46226
46348
|
let lastSuccessAt = null;
|
|
46227
|
-
if (
|
|
46349
|
+
if (existsSync63(statePath)) {
|
|
46228
46350
|
try {
|
|
46229
|
-
const rec = JSON.parse(
|
|
46351
|
+
const rec = JSON.parse(readFileSync63(statePath, "utf-8"));
|
|
46230
46352
|
lastSuccessAt = rec.lastSuccessAt ?? null;
|
|
46231
46353
|
} catch {
|
|
46232
46354
|
console.error(`[calendar-availability] op=audit accountId=${account.accountId} snapshotAgeMs=na reason=bad-state-file`);
|
|
@@ -46261,12 +46383,12 @@ startDispatchCensus(() => getSession());
|
|
|
46261
46383
|
startDispatchFieldCensus(() => getSession());
|
|
46262
46384
|
startDispatchTgCensus(() => getSession());
|
|
46263
46385
|
{
|
|
46264
|
-
const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
46386
|
+
const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join77(__dirname, "..");
|
|
46265
46387
|
const auditScript = resolve55(auditPlatformRoot, "plugins/connector/mcp/dist/scripts/audit-connectors.js");
|
|
46266
46388
|
const auditLogDir = process.env.LOG_DIR ?? LOG_DIR;
|
|
46267
46389
|
const CONNECTOR_AUDIT_INTERVAL_MS = 3e5;
|
|
46268
46390
|
const runConnectorAudit = (ctx) => {
|
|
46269
|
-
if (!
|
|
46391
|
+
if (!existsSync63(auditScript)) return;
|
|
46270
46392
|
try {
|
|
46271
46393
|
const child = spawn3(process.execPath, [auditScript], {
|
|
46272
46394
|
env: { ...process.env, PLATFORM_ROOT: auditPlatformRoot, LOG_DIR: auditLogDir },
|
|
@@ -46388,11 +46510,11 @@ try {
|
|
|
46388
46510
|
var ADMINUSER_RECONCILE_INTERVAL_MS = 60 * 60 * 1e3;
|
|
46389
46511
|
async function runAdminUserReconcileTick() {
|
|
46390
46512
|
try {
|
|
46391
|
-
if (!
|
|
46513
|
+
if (!existsSync63(USERS_FILE)) {
|
|
46392
46514
|
console.error("[adminuser-self-heal] skip reason=no-users-file");
|
|
46393
46515
|
return;
|
|
46394
46516
|
}
|
|
46395
|
-
const usersRaw =
|
|
46517
|
+
const usersRaw = readFileSync63(USERS_FILE, "utf-8").trim();
|
|
46396
46518
|
if (!usersRaw) {
|
|
46397
46519
|
console.error("[adminuser-self-heal] skip reason=empty-users-file");
|
|
46398
46520
|
return;
|
|
@@ -46474,8 +46596,8 @@ var runIngestAuditTick = () => {
|
|
|
46474
46596
|
},
|
|
46475
46597
|
agentExists: (accountId, slug) => {
|
|
46476
46598
|
if (!house) return false;
|
|
46477
|
-
const dir = isHouseAccountKey(house.accountId, accountId) ? house.accountDir :
|
|
46478
|
-
return
|
|
46599
|
+
const dir = isHouseAccountKey(house.accountId, accountId) ? house.accountDir : join77(ACCOUNTS_DIR, accountId);
|
|
46600
|
+
return existsSync63(join77(dir, "agents", slug, "config.json"));
|
|
46479
46601
|
}
|
|
46480
46602
|
});
|
|
46481
46603
|
} catch (err) {
|
|
@@ -46523,8 +46645,8 @@ registerLoop({
|
|
|
46523
46645
|
runPublicAddressCollisionAudit({
|
|
46524
46646
|
houseAccountId: () => resolveAccount()?.accountId ?? null,
|
|
46525
46647
|
activeSlugs: () => listValidAccounts().map((a) => {
|
|
46526
|
-
const agentsRoot =
|
|
46527
|
-
if (!
|
|
46648
|
+
const agentsRoot = join77(a.accountDir, "agents");
|
|
46649
|
+
if (!existsSync63(agentsRoot)) return { accountId: a.accountId, slugs: [] };
|
|
46528
46650
|
const slugs = readdirSync37(agentsRoot, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name).filter((slug) => isActiveAgentSlug(a.accountDir, slug));
|
|
46529
46651
|
return { accountId: a.accountId, slugs };
|
|
46530
46652
|
})
|
|
@@ -46538,8 +46660,8 @@ registerLoop({
|
|
|
46538
46660
|
});
|
|
46539
46661
|
var USERS_RECONCILE_INTERVAL_MS = 60 * 60 * 1e3;
|
|
46540
46662
|
function countUsersRows() {
|
|
46541
|
-
if (!
|
|
46542
|
-
const raw =
|
|
46663
|
+
if (!existsSync63(USERS_FILE)) return 0;
|
|
46664
|
+
const raw = readFileSync63(USERS_FILE, "utf-8").trim();
|
|
46543
46665
|
if (!raw) return 0;
|
|
46544
46666
|
const users = JSON.parse(raw);
|
|
46545
46667
|
return users.filter((u) => typeof u.userId === "string").length;
|
|
@@ -46642,7 +46764,7 @@ function sessionChannelResolver() {
|
|
|
46642
46764
|
byId = /* @__PURE__ */ new Map();
|
|
46643
46765
|
const cfg = claudeConfigDir();
|
|
46644
46766
|
if (cfg) {
|
|
46645
|
-
for (const { path } of enumerateSessionSidecars(
|
|
46767
|
+
for (const { path } of enumerateSessionSidecars(join77(cfg, "projects"))) {
|
|
46646
46768
|
const channel = readSidecarMeta(path).channel;
|
|
46647
46769
|
if (channel) byId.set(basename19(path).replace(/\.meta\.json$/, ""), channel);
|
|
46648
46770
|
}
|
|
@@ -46717,7 +46839,7 @@ if (bootAccountConfig?.whatsapp) {
|
|
|
46717
46839
|
}
|
|
46718
46840
|
init({
|
|
46719
46841
|
configDir: configDirForWhatsApp,
|
|
46720
|
-
platformRoot: resolve55(process.env.MAXY_PLATFORM_ROOT ??
|
|
46842
|
+
platformRoot: resolve55(process.env.MAXY_PLATFORM_ROOT ?? join77(__dirname, "..")),
|
|
46721
46843
|
accountConfig: bootAccountConfig,
|
|
46722
46844
|
// Task 2074 — enrich with the sub-account name and fan out to every open
|
|
46723
46845
|
// admin SSE stream. Fire-and-forget: the manager's persist path must not
|