@rubytech/create-sitedesk-code 0.1.508 → 0.1.509
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/dist/index.js +53 -0
- package/package.json +1 -1
- package/payload/platform/docs/superpowers/plans/2026-07-26-task-1926-portal-push-concurrency-guard.md +482 -0
- package/payload/platform/docs/superpowers/specs/2026-07-26-task-1926-portal-push-concurrency-guard-design.md +200 -0
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +11 -6
- package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +6 -0
- package/payload/platform/plugins/cloudflare/bin/portal-index-push.mjs +68 -28
- package/payload/platform/plugins/cloudflare/mcp/__tests__/portal-index-push.test.ts +271 -29
- package/payload/platform/plugins/cloudflare/skills/data-portal/schema.sql +5 -4
- package/payload/platform/plugins/docs/references/admin-ui.md +10 -5
- package/payload/platform/scripts/__tests__/check-brand-cache.test.sh +231 -0
- package/payload/platform/scripts/check-brand-cache.sh +138 -0
- package/payload/server/maxy-edge.js +15 -10
- package/payload/server/public/activity.html +5 -5
- package/payload/server/public/agents.html +4 -4
- package/payload/server/public/assets/{AdminLoginScreens-DKeCt1uf.js → AdminLoginScreens-8Jk7hnWH.js} +1 -1
- package/payload/server/public/assets/{AdminShell-HeELCCjJ.js → AdminShell-BMPEWNZk.js} +1 -1
- package/payload/server/public/assets/{activity-BEIDAxDA.js → activity-ByWYF5dC.js} +1 -1
- package/payload/server/public/assets/admin-CnUWbKcx.js +1 -0
- package/payload/server/public/assets/agents-C0rTfrYd.js +1 -0
- package/payload/server/public/assets/{browser-GkVTGqlb.js → browser-4tTaem8N.js} +1 -1
- package/payload/server/public/assets/{calendar-CSqJeFEg.js → calendar-BEjnkKG1.js} +1 -1
- package/payload/server/public/assets/chat-DBgzjDIE.js +1 -0
- package/payload/server/public/assets/chevron-left-DqYv3oFh.js +1 -0
- package/payload/server/public/assets/chevron-right-CQfPGsFb.js +1 -0
- package/payload/server/public/assets/clock-Dn6FHB51.js +1 -0
- package/payload/server/public/assets/data-D_e6Vdfd.js +1 -0
- package/payload/server/public/assets/{file-text-DiscM2pP.js → file-text-DMKw3nIk.js} +1 -1
- package/payload/server/public/assets/{graph-CRP5DM8C.js → graph-C3vW8lvw.js} +1 -1
- package/payload/server/public/assets/{graph-labels-Du-6KoBE.js → graph-labels-BZgd0L6n.js} +1 -1
- package/payload/server/public/assets/{maximize-2-D-H_uIV-.js → maximize-2-la3IBA3M.js} +1 -1
- package/payload/server/public/assets/{operator-D5rA76YY.js → operator-RRRdqoRQ.js} +1 -1
- package/payload/server/public/assets/{page-CHK1415C.js → page-BWFHRIAH.js} +1 -1
- package/payload/server/public/assets/{page-DZE3H_n4.js → page-DC11gesX.js} +1 -1
- package/payload/server/public/assets/{public-DFHXVkdD.js → public-DQbbLHQN.js} +1 -1
- package/payload/server/public/assets/{rotate-ccw-CesEJsuO.js → rotate-ccw-OQD5si8N.js} +1 -1
- package/payload/server/public/assets/{routines-DYMYY_r8.js → routines-asrBGZUR.js} +1 -1
- package/payload/server/public/assets/{skills-67jtJ16D.js → skills-D4ECwoxa.js} +1 -1
- package/payload/server/public/assets/{tasks-D2C2a-uk.js → tasks-U3QdbUsO.js} +1 -1
- package/payload/server/public/assets/{time-entry-format-BixTGQAd.js → time-entry-format-BgdTKgYr.js} +1 -1
- package/payload/server/public/assets/{triangle-alert-Co9RWb9q.js → triangle-alert-Ck_3VhT9.js} +1 -1
- package/payload/server/public/assets/{useCopyFeedback-7zwf9_w4.js → useCopyFeedback-BdUwyNpa.js} +1 -1
- package/payload/server/public/assets/{useSubAccountSwitcher-DE4v5_Fz.css → useSubAccountSwitcher-DOWQXDT8.css} +1 -1
- package/payload/server/public/assets/{useVoiceRecorder-CZDDiwMD.js → useVoiceRecorder-ChnBrzbZ.js} +1 -1
- package/payload/server/public/assets/{wrench-CjQqdj4P.js → wrench-Cpee3C3J.js} +1 -1
- package/payload/server/public/browser.html +4 -4
- package/payload/server/public/calendar.html +7 -7
- package/payload/server/public/chat.html +13 -13
- package/payload/server/public/data.html +11 -11
- package/payload/server/public/graph.html +9 -9
- package/payload/server/public/index.html +14 -14
- package/payload/server/public/operator.html +14 -14
- package/payload/server/public/public.html +13 -13
- package/payload/server/public/routines.html +6 -6
- package/payload/server/public/skills.html +5 -5
- package/payload/server/public/tasks.html +6 -6
- package/payload/server/server.js +364 -283
- package/payload/server/public/assets/admin-C0-WU1sf.js +0 -1
- package/payload/server/public/assets/agents-DjUvMFTj.js +0 -1
- package/payload/server/public/assets/chat-C0Ps84U5.js +0 -1
- package/payload/server/public/assets/chevron-left-DQ2uNlu9.js +0 -1
- package/payload/server/public/assets/chevron-right-C4QCiRGD.js +0 -1
- package/payload/server/public/assets/clock-BEeQ7JxX.js +0 -1
- package/payload/server/public/assets/data-CGuNfym7.js +0 -1
- /package/payload/server/public/assets/{useSubAccountSwitcher-Bg72hdQ8.js → useSubAccountSwitcher-CJKjEPNN.js} +0 -0
package/payload/server/server.js
CHANGED
|
@@ -1824,10 +1824,10 @@ var serveStatic = (options = { root: "" }) => {
|
|
|
1824
1824
|
};
|
|
1825
1825
|
|
|
1826
1826
|
// server/index.ts
|
|
1827
|
-
import { readFileSync as readFileSync48, existsSync as existsSync47, watchFile, readdirSync as readdirSync29, statSync as
|
|
1827
|
+
import { readFileSync as readFileSync48, existsSync as existsSync47, watchFile, readdirSync as readdirSync29, statSync as statSync22 } from "fs";
|
|
1828
1828
|
import { spawn as spawn3 } from "child_process";
|
|
1829
1829
|
import { createHash as createHash8 } from "crypto";
|
|
1830
|
-
import { resolve as resolve45, join as
|
|
1830
|
+
import { resolve as resolve45, join as join49, basename as basename14 } from "path";
|
|
1831
1831
|
import { homedir as homedir4 } from "os";
|
|
1832
1832
|
|
|
1833
1833
|
// server/lib/route-cache-watchers.ts
|
|
@@ -2386,6 +2386,79 @@ async function connectLoop(signal) {
|
|
|
2386
2386
|
// server/index.ts
|
|
2387
2387
|
import { monitorEventLoopDelay } from "perf_hooks";
|
|
2388
2388
|
|
|
2389
|
+
// server/lib/event-loop-lag.ts
|
|
2390
|
+
function readAndResetWindow(hist, windowMs) {
|
|
2391
|
+
const toMs = (ns) => Math.round(ns / 1e6);
|
|
2392
|
+
const w = {
|
|
2393
|
+
p50Ms: toMs(hist.percentile(50)),
|
|
2394
|
+
p99Ms: toMs(hist.percentile(99)),
|
|
2395
|
+
maxMs: toMs(hist.max),
|
|
2396
|
+
// Read before the reset.
|
|
2397
|
+
count: hist.count,
|
|
2398
|
+
windowMs
|
|
2399
|
+
};
|
|
2400
|
+
hist.reset();
|
|
2401
|
+
return w;
|
|
2402
|
+
}
|
|
2403
|
+
function formatLagWindow(w) {
|
|
2404
|
+
return `[event-loop] op=lag-window p50=${w.p50Ms} p99=${w.p99Ms} max=${w.maxMs} n=${w.count} windowMs=${w.windowMs}`;
|
|
2405
|
+
}
|
|
2406
|
+
|
|
2407
|
+
// server/lib/static-cache.ts
|
|
2408
|
+
import { statSync as statSync3 } from "fs";
|
|
2409
|
+
import { join as join3 } from "path";
|
|
2410
|
+
var IMMUTABLE = "public, max-age=31536000, immutable";
|
|
2411
|
+
var REVALIDATE = "public, no-cache";
|
|
2412
|
+
function statOrNull(path3) {
|
|
2413
|
+
try {
|
|
2414
|
+
return statSync3(path3);
|
|
2415
|
+
} catch {
|
|
2416
|
+
return null;
|
|
2417
|
+
}
|
|
2418
|
+
}
|
|
2419
|
+
function tryDecodeURI2(str) {
|
|
2420
|
+
try {
|
|
2421
|
+
return decodeURI(str);
|
|
2422
|
+
} catch {
|
|
2423
|
+
return str.replace(/(?:%[0-9A-Fa-f]{2})+/g, (match) => {
|
|
2424
|
+
try {
|
|
2425
|
+
return decodeURI(match);
|
|
2426
|
+
} catch {
|
|
2427
|
+
return match;
|
|
2428
|
+
}
|
|
2429
|
+
});
|
|
2430
|
+
}
|
|
2431
|
+
}
|
|
2432
|
+
function resolveStaticFile(root, reqPath) {
|
|
2433
|
+
const filename = tryDecodeURI2(reqPath);
|
|
2434
|
+
if (/(?:^|[/\\])\.\.(?:$|[/\\])/.test(filename)) return null;
|
|
2435
|
+
let path3 = join3(root, filename);
|
|
2436
|
+
let stats = statOrNull(path3);
|
|
2437
|
+
if (stats?.isDirectory()) {
|
|
2438
|
+
path3 = join3(path3, "index.html");
|
|
2439
|
+
stats = statOrNull(path3);
|
|
2440
|
+
}
|
|
2441
|
+
if (!stats?.isFile()) return null;
|
|
2442
|
+
return { path: path3, stats, filename };
|
|
2443
|
+
}
|
|
2444
|
+
function staticCacheHeaders(root) {
|
|
2445
|
+
return async (c, next) => {
|
|
2446
|
+
if (c.finalized) return next();
|
|
2447
|
+
const hit = resolveStaticFile(root, c.req.path);
|
|
2448
|
+
if (!hit) return next();
|
|
2449
|
+
if (hit.filename.startsWith("/assets/")) {
|
|
2450
|
+
c.header("Cache-Control", IMMUTABLE);
|
|
2451
|
+
return next();
|
|
2452
|
+
}
|
|
2453
|
+
const etag = `"${hit.stats.size}-${hit.stats.mtimeMs}"`;
|
|
2454
|
+
c.header("Cache-Control", REVALIDATE);
|
|
2455
|
+
c.header("Last-Modified", hit.stats.mtime.toUTCString());
|
|
2456
|
+
c.header("ETag", etag);
|
|
2457
|
+
if (c.req.header("If-None-Match") === etag) return c.body(null, 304);
|
|
2458
|
+
return next();
|
|
2459
|
+
};
|
|
2460
|
+
}
|
|
2461
|
+
|
|
2389
2462
|
// app/lib/whatsapp/inbound/media-download-guard.ts
|
|
2390
2463
|
var TAG2 = "[media-guard]";
|
|
2391
2464
|
var inFlight2 = 0;
|
|
@@ -2452,14 +2525,14 @@ function installMediaDownloadGuard() {
|
|
|
2452
2525
|
}
|
|
2453
2526
|
|
|
2454
2527
|
// app/lib/whatsapp/ingest-audit.ts
|
|
2455
|
-
import { readdirSync as readdirSync4, readFileSync as readFileSync4, statSync as
|
|
2456
|
-
import { join as
|
|
2528
|
+
import { readdirSync as readdirSync4, readFileSync as readFileSync4, statSync as statSync4 } from "fs";
|
|
2529
|
+
import { join as join5 } from "path";
|
|
2457
2530
|
|
|
2458
2531
|
// app/lib/whatsapp/ingest-ledger.ts
|
|
2459
2532
|
import { existsSync as existsSync3, mkdirSync as mkdirSync2, appendFileSync as appendFileSync2, readFileSync as readFileSync3, writeFileSync, readdirSync as readdirSync3 } from "fs";
|
|
2460
|
-
import { join as
|
|
2533
|
+
import { join as join4 } from "path";
|
|
2461
2534
|
var TAG3 = "[wa-ingest-ledger]";
|
|
2462
|
-
var LEDGER_ROOT = () =>
|
|
2535
|
+
var LEDGER_ROOT = () => join4(process.env.MAXY_DIR_OVERRIDE ?? MAXY_DIR, "data", "whatsapp-ingest-ledger");
|
|
2463
2536
|
var ensuredRoots = /* @__PURE__ */ new Set();
|
|
2464
2537
|
function ledgerFilePath(account) {
|
|
2465
2538
|
const root = LEDGER_ROOT();
|
|
@@ -2467,7 +2540,7 @@ function ledgerFilePath(account) {
|
|
|
2467
2540
|
if (!existsSync3(root)) mkdirSync2(root, { recursive: true });
|
|
2468
2541
|
ensuredRoots.add(root);
|
|
2469
2542
|
}
|
|
2470
|
-
return
|
|
2543
|
+
return join4(root, `${account}.jsonl`);
|
|
2471
2544
|
}
|
|
2472
2545
|
function appendStanza(entry) {
|
|
2473
2546
|
try {
|
|
@@ -2573,16 +2646,16 @@ function readAllConversationsCached(accountId) {
|
|
|
2573
2646
|
const out = /* @__PURE__ */ new Map();
|
|
2574
2647
|
let dir;
|
|
2575
2648
|
try {
|
|
2576
|
-
dir = readdirSync4(
|
|
2649
|
+
dir = readdirSync4(join5(STORE_ROOT(), accountId));
|
|
2577
2650
|
} catch {
|
|
2578
2651
|
return out;
|
|
2579
2652
|
}
|
|
2580
2653
|
for (const file of dir) {
|
|
2581
2654
|
if (!file.endsWith(".jsonl")) continue;
|
|
2582
|
-
const path3 =
|
|
2655
|
+
const path3 = join5(STORE_ROOT(), accountId, file);
|
|
2583
2656
|
let stat11;
|
|
2584
2657
|
try {
|
|
2585
|
-
stat11 =
|
|
2658
|
+
stat11 = statSync4(path3);
|
|
2586
2659
|
} catch {
|
|
2587
2660
|
continue;
|
|
2588
2661
|
}
|
|
@@ -2756,12 +2829,12 @@ function pwaCensus(d) {
|
|
|
2756
2829
|
}
|
|
2757
2830
|
|
|
2758
2831
|
// server/webchat-descriptor.ts
|
|
2759
|
-
import { resolve as resolve3, join as
|
|
2832
|
+
import { resolve as resolve3, join as join6 } from "path";
|
|
2760
2833
|
function webchatGatewayUrl() {
|
|
2761
2834
|
return `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`;
|
|
2762
2835
|
}
|
|
2763
2836
|
function webchatServerPath() {
|
|
2764
|
-
return process.env.MAXY_WEBCHAT_CHANNEL_SERVER_PATH ?? resolve3(process.env.MAXY_PLATFORM_ROOT ??
|
|
2837
|
+
return process.env.MAXY_WEBCHAT_CHANNEL_SERVER_PATH ?? resolve3(process.env.MAXY_PLATFORM_ROOT ?? join6(__dirname, ".."), "services/webchat-channel/dist/server.js");
|
|
2765
2838
|
}
|
|
2766
2839
|
function webchatChannelDescriptor(key) {
|
|
2767
2840
|
return { key, gatewayUrl: webchatGatewayUrl(), serverPath: webchatServerPath() };
|
|
@@ -4983,7 +5056,7 @@ function resolvePlatformAccountId(accountsDir = ACCOUNTS_DIR) {
|
|
|
4983
5056
|
}
|
|
4984
5057
|
|
|
4985
5058
|
// app/lib/managed-service.ts
|
|
4986
|
-
import { join as
|
|
5059
|
+
import { join as join7 } from "path";
|
|
4987
5060
|
import { readFileSync as readFileSync9 } from "fs";
|
|
4988
5061
|
function isHouseManagedService(accountsDir = ACCOUNTS_DIR) {
|
|
4989
5062
|
let houseId;
|
|
@@ -4994,7 +5067,7 @@ function isHouseManagedService(accountsDir = ACCOUNTS_DIR) {
|
|
|
4994
5067
|
}
|
|
4995
5068
|
try {
|
|
4996
5069
|
const cfg = JSON.parse(
|
|
4997
|
-
readFileSync9(
|
|
5070
|
+
readFileSync9(join7(accountsDir, houseId, "account.json"), "utf-8")
|
|
4998
5071
|
);
|
|
4999
5072
|
return cfg.managedService === true;
|
|
5000
5073
|
} catch {
|
|
@@ -5008,7 +5081,7 @@ function isCustomerTurnSuppressed(role, managedService) {
|
|
|
5008
5081
|
// app/lib/whatsapp/inbound/media.ts
|
|
5009
5082
|
import { randomUUID as randomUUID4, createHash } from "crypto";
|
|
5010
5083
|
import { writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
|
|
5011
|
-
import { join as
|
|
5084
|
+
import { join as join9 } from "path";
|
|
5012
5085
|
import {
|
|
5013
5086
|
downloadMediaMessage,
|
|
5014
5087
|
downloadContentFromMessage,
|
|
@@ -5023,7 +5096,7 @@ import { resolve as resolve7, extname } from "path";
|
|
|
5023
5096
|
|
|
5024
5097
|
// app/lib/data-path.ts
|
|
5025
5098
|
import { realpathSync } from "fs";
|
|
5026
|
-
import { resolve as resolve6, normalize, sep as sep2, relative, basename, join as
|
|
5099
|
+
import { resolve as resolve6, normalize, sep as sep2, relative, basename, join as join8 } from "path";
|
|
5027
5100
|
var PLATFORM_ROOT3 = process.env.MAXY_PLATFORM_ROOT ?? resolve6(process.cwd(), "../platform");
|
|
5028
5101
|
var DATA_ROOT = resolve6(PLATFORM_ROOT3, "..", "data");
|
|
5029
5102
|
var CLAUDE_UPLOADS_ROOT = process.env.CLAUDE_CONFIG_DIR ? resolve6(process.env.CLAUDE_CONFIG_DIR, "uploads") : null;
|
|
@@ -5091,7 +5164,7 @@ function scratchpadTmpBase() {
|
|
|
5091
5164
|
}
|
|
5092
5165
|
function sessionScratchpadRoot(projectDir, sessionId) {
|
|
5093
5166
|
const uid = typeof process.geteuid === "function" ? process.geteuid() : 0;
|
|
5094
|
-
return
|
|
5167
|
+
return join8(scratchpadTmpBase(), `claude-${uid}`, basename(projectDir), sessionId, "scratchpad");
|
|
5095
5168
|
}
|
|
5096
5169
|
function resolveScratchpadPath(raw, scratchpadRootAbs) {
|
|
5097
5170
|
return resolveUnderRoot(raw, scratchpadRootAbs, "scratchpad");
|
|
@@ -5634,7 +5707,7 @@ async function downloadInboundMedia(msg, sock, opts) {
|
|
|
5634
5707
|
if (!res) return void 0;
|
|
5635
5708
|
await mkdir2(MEDIA_DIR, { recursive: true });
|
|
5636
5709
|
const ext = mimeToExt(res.mimetype);
|
|
5637
|
-
const filePath =
|
|
5710
|
+
const filePath = join9(MEDIA_DIR, `${randomUUID4()}.${ext}`);
|
|
5638
5711
|
await writeFile2(filePath, res.buffer);
|
|
5639
5712
|
const sizeKB = (res.buffer.length / 1024).toFixed(0);
|
|
5640
5713
|
console.error(`${TAG14} media downloaded type=${res.mimetype} size=${sizeKB}KB path=${filePath}`);
|
|
@@ -7436,7 +7509,7 @@ var health_default = app;
|
|
|
7436
7509
|
// app/lib/stt/voice-note.ts
|
|
7437
7510
|
import { writeFile as writeFile3, mkdtemp, rm } from "fs/promises";
|
|
7438
7511
|
import { tmpdir } from "os";
|
|
7439
|
-
import { join as
|
|
7512
|
+
import { join as join10 } from "path";
|
|
7440
7513
|
|
|
7441
7514
|
// app/lib/stt/audio-mime.ts
|
|
7442
7515
|
var AUDIO_MIME_TYPES = /* @__PURE__ */ new Set([
|
|
@@ -7490,9 +7563,9 @@ async function transcribeVoiceNote(file, source) {
|
|
|
7490
7563
|
let tempDir;
|
|
7491
7564
|
let tempPath;
|
|
7492
7565
|
try {
|
|
7493
|
-
tempDir = await mkdtemp(
|
|
7566
|
+
tempDir = await mkdtemp(join10(tmpdir(), "voice-"));
|
|
7494
7567
|
const ext = audioExtension(mimeType);
|
|
7495
|
-
tempPath =
|
|
7568
|
+
tempPath = join10(tempDir, `recording${ext}`);
|
|
7496
7569
|
const buffer = Buffer.from(await file.arrayBuffer());
|
|
7497
7570
|
await writeFile3(tempPath, buffer);
|
|
7498
7571
|
} catch (err) {
|
|
@@ -8068,7 +8141,7 @@ async function sendTelegramText(botToken, chatId, text) {
|
|
|
8068
8141
|
}
|
|
8069
8142
|
|
|
8070
8143
|
// server/routes/whatsapp.ts
|
|
8071
|
-
import { join as
|
|
8144
|
+
import { join as join13, resolve as resolve11 } from "path";
|
|
8072
8145
|
import { readdirSync as readdirSync7, readFileSync as readFileSync14, existsSync as existsSync8 } from "fs";
|
|
8073
8146
|
|
|
8074
8147
|
// app/lib/whatsapp/login.ts
|
|
@@ -8076,7 +8149,7 @@ import { randomUUID as randomUUID6 } from "crypto";
|
|
|
8076
8149
|
|
|
8077
8150
|
// app/lib/whatsapp/config-persist.ts
|
|
8078
8151
|
import { readFileSync as readFileSync13, writeFileSync as writeFileSync5, existsSync as existsSync7 } from "fs";
|
|
8079
|
-
import { resolve as resolve9, join as
|
|
8152
|
+
import { resolve as resolve9, join as join11, dirname as dirname2, basename as basename2 } from "path";
|
|
8080
8153
|
var TAG22 = "[whatsapp:config]";
|
|
8081
8154
|
function configPath(accountDir) {
|
|
8082
8155
|
return resolve9(accountDir, "account.json");
|
|
@@ -8423,7 +8496,7 @@ function setPublicAgent(accountDir, slug) {
|
|
|
8423
8496
|
if (!trimmed) {
|
|
8424
8497
|
return { ok: false, error: "Agent slug cannot be empty." };
|
|
8425
8498
|
}
|
|
8426
|
-
const agentConfigPath =
|
|
8499
|
+
const agentConfigPath = join11(accountDir, "agents", trimmed, "config.json");
|
|
8427
8500
|
if (!existsSync7(agentConfigPath)) {
|
|
8428
8501
|
return { ok: false, error: `Agent "${trimmed}" not found \u2014 no config.json at ${agentConfigPath}. Check the agent slug and try again.` };
|
|
8429
8502
|
}
|
|
@@ -9060,12 +9133,12 @@ function serializeWhatsAppSchema() {
|
|
|
9060
9133
|
|
|
9061
9134
|
// app/lib/whatsapp/status-reconcile.ts
|
|
9062
9135
|
import { readdirSync as readdirSync6 } from "fs";
|
|
9063
|
-
import { join as
|
|
9136
|
+
import { join as join12 } from "path";
|
|
9064
9137
|
var TAG25 = "[whatsapp:reconcile]";
|
|
9065
9138
|
var HALF_REGISTERED_MIN_AGE_MS = 5 * 6e4;
|
|
9066
9139
|
function listCredsAccountIds(credsRoot) {
|
|
9067
9140
|
try {
|
|
9068
|
-
return readdirSync6(credsRoot, { withFileTypes: true }).filter((e) => e.isDirectory() && hasCredsSync(
|
|
9141
|
+
return readdirSync6(credsRoot, { withFileTypes: true }).filter((e) => e.isDirectory() && hasCredsSync(join12(credsRoot, e.name))).map((e) => e.name);
|
|
9069
9142
|
} catch {
|
|
9070
9143
|
return [];
|
|
9071
9144
|
}
|
|
@@ -9080,7 +9153,7 @@ function reconcileCredsOnDisk(opts) {
|
|
|
9080
9153
|
const entries2 = [];
|
|
9081
9154
|
for (const accountId of listCredsAccountIds(credsRoot)) {
|
|
9082
9155
|
if (liveAccountIds.has(accountId)) continue;
|
|
9083
|
-
const authDir =
|
|
9156
|
+
const authDir = join12(credsRoot, accountId);
|
|
9084
9157
|
const census = credsCensus(authDir);
|
|
9085
9158
|
if (census.registered && !census.hasAccountSignature) {
|
|
9086
9159
|
const inFlight3 = activeLoginAccountIds.has(accountId);
|
|
@@ -9317,7 +9390,7 @@ app2.get("/status", (c) => {
|
|
|
9317
9390
|
const live = getStatus();
|
|
9318
9391
|
const liveIds = new Set(live.map((a) => a.accountId));
|
|
9319
9392
|
const activeLoginIds = new Set(listActiveLoginAccountIds());
|
|
9320
|
-
const credsRoot =
|
|
9393
|
+
const credsRoot = join13(MAXY_DIR, "credentials", "whatsapp");
|
|
9321
9394
|
const accountDir = resolveAccount()?.accountDir ?? null;
|
|
9322
9395
|
const reconciled = reconcileCredsOnDisk({ credsRoot, accountDir, liveAccountIds: liveIds, activeLoginAccountIds: activeLoginIds });
|
|
9323
9396
|
const cfg = getWhatsAppConfig();
|
|
@@ -9354,7 +9427,7 @@ app2.post("/login/start", async (c) => {
|
|
|
9354
9427
|
if (!phone) {
|
|
9355
9428
|
return c.json({ error: 'Missing required field "phone" (E.164, e.g. +441234567890).' }, 400);
|
|
9356
9429
|
}
|
|
9357
|
-
const authDir =
|
|
9430
|
+
const authDir = join13(MAXY_DIR, "credentials", "whatsapp", accountId);
|
|
9358
9431
|
const accountDir = resolveAccount()?.accountDir ?? null;
|
|
9359
9432
|
const result = await startLogin({ accountId, authDir, phone, accountDir, force });
|
|
9360
9433
|
console.error(`${TAG26} login/start result account=${accountId} hasCode=${!!result.pairingCode}${result.selfPhone ? ` phone=${result.selfPhone}` : ""}`);
|
|
@@ -10001,12 +10074,12 @@ var bodyLimit = (options) => {
|
|
|
10001
10074
|
};
|
|
10002
10075
|
|
|
10003
10076
|
// server/routes/storage-broker.ts
|
|
10004
|
-
import { join as
|
|
10077
|
+
import { join as join14, resolve as resolve12 } from "path";
|
|
10005
10078
|
import { readdirSync as readdirSync8, readFileSync as readFileSync15, existsSync as existsSync9, realpathSync as realpathSync4 } from "fs";
|
|
10006
10079
|
import { randomUUID as randomUUID7 } from "crypto";
|
|
10007
10080
|
var app3 = new Hono();
|
|
10008
10081
|
function platformRoot() {
|
|
10009
|
-
return process.env.MAXY_PLATFORM_ROOT ?? process.env.PLATFORM_ROOT ??
|
|
10082
|
+
return process.env.MAXY_PLATFORM_ROOT ?? process.env.PLATFORM_ROOT ?? join14(__dirname, "..", "..");
|
|
10010
10083
|
}
|
|
10011
10084
|
function caller(c) {
|
|
10012
10085
|
return c.req.header("x-maxy-caller-account")?.trim() || null;
|
|
@@ -10541,7 +10614,7 @@ async function runStorageAudit(root) {
|
|
|
10541
10614
|
if (!existsSync9(accountsDir)) return [];
|
|
10542
10615
|
const files = [];
|
|
10543
10616
|
for (const accountId of readdirSync8(accountsDir)) {
|
|
10544
|
-
const p =
|
|
10617
|
+
const p = join14(accountsDir, accountId, "secrets", "cloudflare.env");
|
|
10545
10618
|
if (existsSync9(p)) files.push({ accountId, path: p, contents: readFileSync15(p, "utf8") });
|
|
10546
10619
|
}
|
|
10547
10620
|
return files;
|
|
@@ -10640,7 +10713,7 @@ function discoverPortalAccounts(accountsDir) {
|
|
|
10640
10713
|
if (!existsSync9(accountsDir)) return [];
|
|
10641
10714
|
const found = [];
|
|
10642
10715
|
for (const accountId of readdirSync8(accountsDir)) {
|
|
10643
|
-
const configPath2 =
|
|
10716
|
+
const configPath2 = join14(accountsDir, accountId, "data-portal.json");
|
|
10644
10717
|
if (!existsSync9(configPath2)) continue;
|
|
10645
10718
|
try {
|
|
10646
10719
|
const cfg = JSON.parse(readFileSync15(configPath2, "utf-8"));
|
|
@@ -10723,7 +10796,7 @@ async function runDataPortalAudit(root) {
|
|
|
10723
10796
|
// server/portal-uploads-pull.ts
|
|
10724
10797
|
import { existsSync as existsSync10 } from "fs";
|
|
10725
10798
|
import { mkdir as mkdir3, readFile as readFile2, rename, stat as stat3, unlink as unlink2, writeFile as writeFile4 } from "fs/promises";
|
|
10726
|
-
import { basename as basename4, dirname as dirname4, join as
|
|
10799
|
+
import { basename as basename4, dirname as dirname4, join as join15, relative as relative2, resolve as resolve13, sep as sep3 } from "path";
|
|
10727
10800
|
|
|
10728
10801
|
// ../plugins/cloudflare/bin/schema-exposed-dirs.mjs
|
|
10729
10802
|
var ONT_START = "<!-- ontology-buckets:start -->";
|
|
@@ -10821,19 +10894,19 @@ function resolveDestination(accountDir, row, exposed) {
|
|
|
10821
10894
|
if (!segments.every(safeSegment)) return { ok: false, reason: "bad-target" };
|
|
10822
10895
|
if (!exposed.includes(segments[0])) return { ok: false, reason: "bad-target" };
|
|
10823
10896
|
root = resolve13(accountDir);
|
|
10824
|
-
dir =
|
|
10897
|
+
dir = join15(root, ...segments);
|
|
10825
10898
|
} else {
|
|
10826
10899
|
root = resolve13(accountDir, "uploads");
|
|
10827
|
-
dir =
|
|
10900
|
+
dir = join15(root, row.ownerId);
|
|
10828
10901
|
}
|
|
10829
|
-
const final =
|
|
10902
|
+
const final = join15(dir, row.filename);
|
|
10830
10903
|
if (!final.startsWith(root + sep3)) {
|
|
10831
10904
|
return { ok: false, reason: row.targetPath ? "bad-target" : "bad-filename" };
|
|
10832
10905
|
}
|
|
10833
10906
|
return {
|
|
10834
10907
|
ok: true,
|
|
10835
10908
|
dir,
|
|
10836
|
-
tmp:
|
|
10909
|
+
tmp: join15(dir, ".uploads-tmp", row.filename),
|
|
10837
10910
|
final,
|
|
10838
10911
|
relative: relative2(resolve13(accountDir), final).split(sep3).join("/")
|
|
10839
10912
|
};
|
|
@@ -10846,7 +10919,7 @@ function nextFreePath(final) {
|
|
|
10846
10919
|
const stem = dot > 0 ? base.slice(0, dot) : base;
|
|
10847
10920
|
const ext = dot > 0 ? base.slice(dot) : "";
|
|
10848
10921
|
for (let n = 2; ; n++) {
|
|
10849
|
-
const candidate =
|
|
10922
|
+
const candidate = join15(dir, `${stem} (${n})${ext}`);
|
|
10850
10923
|
if (!existsSync10(candidate)) return candidate;
|
|
10851
10924
|
}
|
|
10852
10925
|
}
|
|
@@ -10950,7 +11023,7 @@ async function withdrawRow(opts) {
|
|
|
10950
11023
|
log2(`${head} removed=false result=bad-path`);
|
|
10951
11024
|
return false;
|
|
10952
11025
|
}
|
|
10953
|
-
const absolute =
|
|
11026
|
+
const absolute = join15(resolve13(accountDir), ...segments);
|
|
10954
11027
|
if (!absolute.startsWith(resolve13(accountDir) + sep3)) {
|
|
10955
11028
|
log2(`${head} removed=false result=bad-path`);
|
|
10956
11029
|
return false;
|
|
@@ -11015,13 +11088,13 @@ function parsePendingRows(raw) {
|
|
|
11015
11088
|
async function readExposedDirs(accountDir) {
|
|
11016
11089
|
let schemaText = null;
|
|
11017
11090
|
try {
|
|
11018
|
-
schemaText = await readFile2(
|
|
11091
|
+
schemaText = await readFile2(join15(accountDir, "SCHEMA.md"), "utf8");
|
|
11019
11092
|
} catch {
|
|
11020
11093
|
schemaText = null;
|
|
11021
11094
|
}
|
|
11022
11095
|
let exposeFolders = [];
|
|
11023
11096
|
try {
|
|
11024
|
-
const cfg = JSON.parse(await readFile2(
|
|
11097
|
+
const cfg = JSON.parse(await readFile2(join15(accountDir, "data-portal.json"), "utf8"));
|
|
11025
11098
|
exposeFolders = Array.isArray(cfg?.exposeFolders) ? cfg.exposeFolders.filter((f) => typeof f === "string") : [];
|
|
11026
11099
|
} catch {
|
|
11027
11100
|
exposeFolders = [];
|
|
@@ -11046,7 +11119,7 @@ async function runPortalUploadsPull(root) {
|
|
|
11046
11119
|
console.error(`${TAG27} op=malformed account=${portal.accountId} rows=${malformed}`);
|
|
11047
11120
|
}
|
|
11048
11121
|
if (rows.length === 0) continue;
|
|
11049
|
-
const accountDir =
|
|
11122
|
+
const accountDir = join15(accountsRoot, portal.accountId);
|
|
11050
11123
|
const r = await pullAccount({
|
|
11051
11124
|
accountDir,
|
|
11052
11125
|
accountId: portal.accountId,
|
|
@@ -11079,7 +11152,7 @@ async function runPortalUploadsPull(root) {
|
|
|
11079
11152
|
import { readFile as readFile3, readdir, stat as stat4 } from "fs/promises";
|
|
11080
11153
|
import { existsSync as existsSync11, readFileSync as readFileSync16, writeFileSync as writeFileSync6 } from "fs";
|
|
11081
11154
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
11082
|
-
import { join as
|
|
11155
|
+
import { join as join16, resolve as resolve14 } from "path";
|
|
11083
11156
|
import { fileURLToPath } from "url";
|
|
11084
11157
|
|
|
11085
11158
|
// ../plugins/cloudflare/bin/d1-http.mjs
|
|
@@ -11155,7 +11228,7 @@ function readEnvFile(path3) {
|
|
|
11155
11228
|
}
|
|
11156
11229
|
async function readExposeFolders(accountDir) {
|
|
11157
11230
|
try {
|
|
11158
|
-
const cfg = JSON.parse(await readFile3(
|
|
11231
|
+
const cfg = JSON.parse(await readFile3(join16(accountDir, "data-portal.json"), "utf8"));
|
|
11159
11232
|
return Array.isArray(cfg?.exposeFolders) ? cfg.exposeFolders.filter((f) => typeof f === "string") : [];
|
|
11160
11233
|
} catch {
|
|
11161
11234
|
return [];
|
|
@@ -11166,12 +11239,12 @@ async function walkExposed(accountDir, exposed) {
|
|
|
11166
11239
|
async function walk(rel) {
|
|
11167
11240
|
let entries2;
|
|
11168
11241
|
try {
|
|
11169
|
-
entries2 = await readdir(
|
|
11242
|
+
entries2 = await readdir(join16(accountDir, rel), { withFileTypes: true });
|
|
11170
11243
|
} catch {
|
|
11171
11244
|
return;
|
|
11172
11245
|
}
|
|
11173
11246
|
try {
|
|
11174
|
-
const st = await stat4(
|
|
11247
|
+
const st = await stat4(join16(accountDir, rel));
|
|
11175
11248
|
out.push({ relPath: rel, sizeBytes: 0, modifiedAt: st.mtime.toISOString(), isDir: true });
|
|
11176
11249
|
} catch {
|
|
11177
11250
|
}
|
|
@@ -11182,7 +11255,7 @@ async function walkExposed(accountDir, exposed) {
|
|
|
11182
11255
|
await walk(childRel);
|
|
11183
11256
|
} else if (e.isFile()) {
|
|
11184
11257
|
try {
|
|
11185
|
-
const st = await stat4(
|
|
11258
|
+
const st = await stat4(join16(accountDir, childRel));
|
|
11186
11259
|
out.push({
|
|
11187
11260
|
relPath: childRel,
|
|
11188
11261
|
sizeBytes: st.size,
|
|
@@ -11201,7 +11274,7 @@ async function pushAccount(opts) {
|
|
|
11201
11274
|
const { accountDir, accountId, client, log: log2, nowIso } = opts;
|
|
11202
11275
|
let schemaText = null;
|
|
11203
11276
|
try {
|
|
11204
|
-
schemaText = await readFile3(
|
|
11277
|
+
schemaText = await readFile3(join16(accountDir, "SCHEMA.md"), "utf8");
|
|
11205
11278
|
} catch {
|
|
11206
11279
|
schemaText = null;
|
|
11207
11280
|
}
|
|
@@ -11231,19 +11304,11 @@ async function pushAccount(opts) {
|
|
|
11231
11304
|
[accountId]
|
|
11232
11305
|
);
|
|
11233
11306
|
const current = Number(state[0]?.currentGeneration ?? 0);
|
|
11234
|
-
const
|
|
11235
|
-
|
|
11236
|
-
|
|
11237
|
-
[accountId, next]
|
|
11307
|
+
const staged = await client.query(
|
|
11308
|
+
"SELECT MAX(generation) AS g FROM directory WHERE accountId = ?",
|
|
11309
|
+
[accountId]
|
|
11238
11310
|
);
|
|
11239
|
-
const
|
|
11240
|
-
if (orphanCount > 0) {
|
|
11241
|
-
await client.query("DELETE FROM directory WHERE accountId = ? AND generation = ?", [
|
|
11242
|
-
accountId,
|
|
11243
|
-
next
|
|
11244
|
-
]);
|
|
11245
|
-
log2(`${TAG28} op=stage-clear account=${accountId} generation=${next} cleared=${orphanCount}`);
|
|
11246
|
-
}
|
|
11311
|
+
const next = Math.max(current, Number(staged[0]?.g ?? 0)) + 1;
|
|
11247
11312
|
for (const row of rows) {
|
|
11248
11313
|
await client.query(
|
|
11249
11314
|
"INSERT INTO directory (accountId, relPath, sizeBytes, modifiedAt, indexedAt, isDir, generation) VALUES (?, ?, ?, ?, ?, ?, ?)",
|
|
@@ -11252,12 +11317,29 @@ async function pushAccount(opts) {
|
|
|
11252
11317
|
}
|
|
11253
11318
|
log2(`${TAG28} op=stage account=${accountId} generation=${next} inserted=${rows.length}`);
|
|
11254
11319
|
await client.query(
|
|
11255
|
-
"INSERT INTO directory_state (accountId, currentGeneration) VALUES (?, ?) ON CONFLICT (accountId) DO UPDATE SET currentGeneration = excluded.currentGeneration",
|
|
11320
|
+
"INSERT INTO directory_state (accountId, currentGeneration) VALUES (?, ?) ON CONFLICT (accountId) DO UPDATE SET currentGeneration = excluded.currentGeneration WHERE excluded.currentGeneration > directory_state.currentGeneration",
|
|
11256
11321
|
[accountId, next]
|
|
11257
11322
|
);
|
|
11323
|
+
const flipped = await client.query(
|
|
11324
|
+
"SELECT currentGeneration FROM directory_state WHERE accountId = ?",
|
|
11325
|
+
[accountId]
|
|
11326
|
+
);
|
|
11327
|
+
const pointer = Number(flipped[0]?.currentGeneration ?? 0);
|
|
11328
|
+
if (pointer !== next) {
|
|
11329
|
+
log2(
|
|
11330
|
+
`${TAG28} op=stage-contended account=${accountId} generation=${next} pointer=${pointer} action=superseded`
|
|
11331
|
+
);
|
|
11332
|
+
return {
|
|
11333
|
+
exposed: r.exposed,
|
|
11334
|
+
rows: rows.length,
|
|
11335
|
+
schemaPresent: true,
|
|
11336
|
+
generation: next,
|
|
11337
|
+
superseded: true
|
|
11338
|
+
};
|
|
11339
|
+
}
|
|
11258
11340
|
log2(`${TAG28} op=flip account=${accountId} generation=${next}`);
|
|
11259
11341
|
try {
|
|
11260
|
-
await client.query("DELETE FROM directory WHERE accountId = ? AND generation
|
|
11342
|
+
await client.query("DELETE FROM directory WHERE accountId = ? AND generation < ?", [
|
|
11261
11343
|
accountId,
|
|
11262
11344
|
next
|
|
11263
11345
|
]);
|
|
@@ -11309,9 +11391,9 @@ async function portalAccounts(accountsRoot) {
|
|
|
11309
11391
|
return out;
|
|
11310
11392
|
}
|
|
11311
11393
|
for (const accountId of names) {
|
|
11312
|
-
const accountDir =
|
|
11394
|
+
const accountDir = join16(accountsRoot, accountId);
|
|
11313
11395
|
try {
|
|
11314
|
-
const cfg = JSON.parse(await readFile3(
|
|
11396
|
+
const cfg = JSON.parse(await readFile3(join16(accountDir, "data-portal.json"), "utf8"));
|
|
11315
11397
|
if (typeof cfg?.portalDbName === "string" && cfg.portalDbName) {
|
|
11316
11398
|
const exposeFolders = Array.isArray(cfg?.exposeFolders) ? cfg.exposeFolders.filter((f) => typeof f === "string") : [];
|
|
11317
11399
|
out.push({ accountDir, accountId, dbName: cfg.portalDbName, exposeFolders });
|
|
@@ -11324,11 +11406,11 @@ async function portalAccounts(accountsRoot) {
|
|
|
11324
11406
|
return out;
|
|
11325
11407
|
}
|
|
11326
11408
|
function resolveCloudflareCredentials(platformRoot5) {
|
|
11327
|
-
const houseEnvPath =
|
|
11409
|
+
const houseEnvPath = join16(platformRoot5, "config", "cloudflare-house.env");
|
|
11328
11410
|
const house = readEnvFile(houseEnvPath);
|
|
11329
11411
|
if (!house.CLOUDFLARE_API_TOKEN) return { error: "no-house-cloudflare-credential" };
|
|
11330
11412
|
if (!house.CLOUDFLARE_ACCOUNT_ID) return { error: "no-house-cloudflare-account-id" };
|
|
11331
|
-
const cfTokenSh =
|
|
11413
|
+
const cfTokenSh = join16(platformRoot5, "plugins", "cloudflare", "bin", "cf-token.sh");
|
|
11332
11414
|
if (!existsSync11(cfTokenSh)) return { error: "cf-token-sh-missing" };
|
|
11333
11415
|
let keyName;
|
|
11334
11416
|
try {
|
|
@@ -11434,17 +11516,17 @@ async function runPortalIndexPush(root) {
|
|
|
11434
11516
|
}
|
|
11435
11517
|
|
|
11436
11518
|
// server/google-pending-audit.ts
|
|
11437
|
-
import { existsSync as existsSync12, readdirSync as readdirSync9, statSync as
|
|
11438
|
-
import { join as
|
|
11519
|
+
import { existsSync as existsSync12, readdirSync as readdirSync9, statSync as statSync5 } from "fs";
|
|
11520
|
+
import { join as join17 } from "path";
|
|
11439
11521
|
var GOOGLE_PENDING_LIFETIME_SEC = 600;
|
|
11440
11522
|
var UUID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
11441
|
-
function runGooglePendingAudit(accountsDir, nowMs, emit, readMtimeMs = (path3) =>
|
|
11523
|
+
function runGooglePendingAudit(accountsDir, nowMs, emit, readMtimeMs = (path3) => statSync5(path3).mtimeMs) {
|
|
11442
11524
|
let scanned = 0;
|
|
11443
11525
|
let stranded = 0;
|
|
11444
11526
|
if (existsSync12(accountsDir)) {
|
|
11445
11527
|
for (const accountId of readdirSync9(accountsDir)) {
|
|
11446
11528
|
if (!UUID_RE2.test(accountId)) continue;
|
|
11447
|
-
const pendingPath2 =
|
|
11529
|
+
const pendingPath2 = join17(accountsDir, accountId, "secrets", "google", "pending-oauth.enc");
|
|
11448
11530
|
try {
|
|
11449
11531
|
if (!existsSync12(pendingPath2)) continue;
|
|
11450
11532
|
const ageSec = Math.max(0, Math.floor((nowMs - readMtimeMs(pendingPath2)) / 1e3));
|
|
@@ -11501,19 +11583,19 @@ function runReconcileLivenessAudit(statePath, nowMs, intervalMs, emit) {
|
|
|
11501
11583
|
}
|
|
11502
11584
|
|
|
11503
11585
|
// server/routes/whatsapp-reader.ts
|
|
11504
|
-
import { readFileSync as readFileSync21, watch as watch2, statSync as
|
|
11505
|
-
import { basename as basename6, dirname as dirname7, isAbsolute, join as
|
|
11586
|
+
import { readFileSync as readFileSync21, watch as watch2, statSync as statSync9, openSync, readSync, closeSync, existsSync as existsSync17, readdirSync as readdirSync14, realpathSync as realpathSync6 } from "fs";
|
|
11587
|
+
import { basename as basename6, dirname as dirname7, isAbsolute, join as join22, relative as relative3, resolve as resolve17, sep as sep5 } from "path";
|
|
11506
11588
|
|
|
11507
11589
|
// server/routes/admin/sidebar-sessions.ts
|
|
11508
|
-
import { readdirSync as readdirSync12, readFileSync as readFileSync19, statSync as
|
|
11509
|
-
import { dirname as dirname5, join as
|
|
11590
|
+
import { readdirSync as readdirSync12, readFileSync as readFileSync19, statSync as statSync7 } from "fs";
|
|
11591
|
+
import { dirname as dirname5, join as join20, resolve as resolve15 } from "path";
|
|
11510
11592
|
|
|
11511
11593
|
// ../services/claude-session-manager/src/jsonl-path.ts
|
|
11512
11594
|
import { existsSync as existsSync14, readdirSync as readdirSync10 } from "fs";
|
|
11513
11595
|
import { homedir } from "os";
|
|
11514
|
-
import { join as
|
|
11596
|
+
import { join as join18 } from "path";
|
|
11515
11597
|
function findExistingJsonlForSessionId(claudeConfigDir2, sessionId) {
|
|
11516
|
-
const projectsRoot =
|
|
11598
|
+
const projectsRoot = join18(claudeConfigDir2, "projects");
|
|
11517
11599
|
if (!existsSync14(projectsRoot)) return null;
|
|
11518
11600
|
let slugs;
|
|
11519
11601
|
try {
|
|
@@ -11523,9 +11605,9 @@ function findExistingJsonlForSessionId(claudeConfigDir2, sessionId) {
|
|
|
11523
11605
|
}
|
|
11524
11606
|
const basename15 = `${sessionId}.jsonl`;
|
|
11525
11607
|
for (const slug of slugs) {
|
|
11526
|
-
const live =
|
|
11608
|
+
const live = join18(projectsRoot, slug, basename15);
|
|
11527
11609
|
if (existsSync14(live)) return live;
|
|
11528
|
-
const archived =
|
|
11610
|
+
const archived = join18(projectsRoot, slug, "archive", basename15);
|
|
11529
11611
|
if (existsSync14(archived)) return archived;
|
|
11530
11612
|
}
|
|
11531
11613
|
return null;
|
|
@@ -11533,8 +11615,8 @@ function findExistingJsonlForSessionId(claudeConfigDir2, sessionId) {
|
|
|
11533
11615
|
|
|
11534
11616
|
// app/lib/admin-identity/pin-validator.ts
|
|
11535
11617
|
import { createHash as createHash3 } from "crypto";
|
|
11536
|
-
import { existsSync as existsSync15, readFileSync as readFileSync18, readdirSync as readdirSync11, statSync as
|
|
11537
|
-
import { join as
|
|
11618
|
+
import { existsSync as existsSync15, readFileSync as readFileSync18, readdirSync as readdirSync11, statSync as statSync6 } from "fs";
|
|
11619
|
+
import { join as join19 } from "path";
|
|
11538
11620
|
function hashPin(pin) {
|
|
11539
11621
|
return createHash3("sha256").update(pin).digest("hex");
|
|
11540
11622
|
}
|
|
@@ -11665,7 +11747,7 @@ function enumerateJsonls(projectsRoot) {
|
|
|
11665
11747
|
throw err;
|
|
11666
11748
|
}
|
|
11667
11749
|
for (const slug of slugs) {
|
|
11668
|
-
const slugDir =
|
|
11750
|
+
const slugDir = join20(projectsRoot, slug);
|
|
11669
11751
|
let entries2;
|
|
11670
11752
|
try {
|
|
11671
11753
|
entries2 = readdirSync12(slugDir, { withFileTypes: true });
|
|
@@ -11676,9 +11758,9 @@ function enumerateJsonls(projectsRoot) {
|
|
|
11676
11758
|
}
|
|
11677
11759
|
for (const entry of entries2) {
|
|
11678
11760
|
if (entry.isFile() && SESSION_ID_RE.test(entry.name)) {
|
|
11679
|
-
out.push({ path:
|
|
11761
|
+
out.push({ path: join20(slugDir, entry.name), isSubagent: false, archived: false });
|
|
11680
11762
|
} else if (entry.isDirectory() && entry.name === "subagents") {
|
|
11681
|
-
const subDir =
|
|
11763
|
+
const subDir = join20(slugDir, entry.name);
|
|
11682
11764
|
let subEntries;
|
|
11683
11765
|
try {
|
|
11684
11766
|
subEntries = readdirSync12(subDir, { withFileTypes: true });
|
|
@@ -11689,11 +11771,11 @@ function enumerateJsonls(projectsRoot) {
|
|
|
11689
11771
|
}
|
|
11690
11772
|
for (const sub of subEntries) {
|
|
11691
11773
|
if (sub.isFile() && SESSION_ID_RE.test(sub.name)) {
|
|
11692
|
-
out.push({ path:
|
|
11774
|
+
out.push({ path: join20(subDir, sub.name), isSubagent: true, archived: false });
|
|
11693
11775
|
}
|
|
11694
11776
|
}
|
|
11695
11777
|
} else if (entry.isDirectory() && entry.name === "archive") {
|
|
11696
|
-
const archiveDir =
|
|
11778
|
+
const archiveDir = join20(slugDir, entry.name);
|
|
11697
11779
|
let archiveEntries;
|
|
11698
11780
|
try {
|
|
11699
11781
|
archiveEntries = readdirSync12(archiveDir, { withFileTypes: true });
|
|
@@ -11704,7 +11786,7 @@ function enumerateJsonls(projectsRoot) {
|
|
|
11704
11786
|
}
|
|
11705
11787
|
for (const arc of archiveEntries) {
|
|
11706
11788
|
if (arc.isFile() && SESSION_ID_RE.test(arc.name)) {
|
|
11707
|
-
out.push({ path:
|
|
11789
|
+
out.push({ path: join20(archiveDir, arc.name), isSubagent: false, archived: true });
|
|
11708
11790
|
}
|
|
11709
11791
|
}
|
|
11710
11792
|
}
|
|
@@ -11737,7 +11819,7 @@ async function fetchLiveSessions() {
|
|
|
11737
11819
|
function loadUserTitles(accountDir) {
|
|
11738
11820
|
const out = /* @__PURE__ */ new Map();
|
|
11739
11821
|
if (!accountDir) return out;
|
|
11740
|
-
const path3 =
|
|
11822
|
+
const path3 = join20(accountDir, "session-titles.json");
|
|
11741
11823
|
let raw;
|
|
11742
11824
|
try {
|
|
11743
11825
|
raw = readFileSync19(path3, "utf8");
|
|
@@ -11877,7 +11959,7 @@ async function computeSessionList(scopeAccountId) {
|
|
|
11877
11959
|
console.error("[admin-sessions-list] CLAUDE_CONFIG_DIR not set; returning empty list");
|
|
11878
11960
|
return { sessions: [], accountId: scopeAccountId };
|
|
11879
11961
|
}
|
|
11880
|
-
const projectsRoot =
|
|
11962
|
+
const projectsRoot = join20(configDir2, "projects");
|
|
11881
11963
|
const jsonls = enumerateJsonls(projectsRoot);
|
|
11882
11964
|
const liveSessions = await fetchLiveSessions();
|
|
11883
11965
|
const accountDir = scopeAccountId ? resolve15(ACCOUNTS_DIR, scopeAccountId) : null;
|
|
@@ -11922,7 +12004,7 @@ async function computeSessionList(scopeAccountId) {
|
|
|
11922
12004
|
let mtimeMs;
|
|
11923
12005
|
try {
|
|
11924
12006
|
body = readFileSync19(path3, "utf8");
|
|
11925
|
-
mtimeMs =
|
|
12007
|
+
mtimeMs = statSync7(path3).mtimeMs;
|
|
11926
12008
|
} catch {
|
|
11927
12009
|
continue;
|
|
11928
12010
|
}
|
|
@@ -11930,7 +12012,7 @@ async function computeSessionList(scopeAccountId) {
|
|
|
11930
12012
|
const pid = live ? liveSessions.get(sessionId) ?? null : null;
|
|
11931
12013
|
const resolved = resolveTitle(body, sessionId, userTitles);
|
|
11932
12014
|
titleSourceCounts[resolved.source] += 1;
|
|
11933
|
-
const metaPath =
|
|
12015
|
+
const metaPath = join20(projectDir, `${sessionId}.meta.json`);
|
|
11934
12016
|
const { bridgeIds, role, channel: sidecarChannel, senderId, personId, adminUserId, accountId: rowAccountId } = readSidecarMeta(metaPath);
|
|
11935
12017
|
if (multiAccount) {
|
|
11936
12018
|
if (rowAccountId === null) untaggedCount += 1;
|
|
@@ -12332,8 +12414,8 @@ function parseTranscript(lines, queuedPendingSuppress = /* @__PURE__ */ new Map(
|
|
|
12332
12414
|
}
|
|
12333
12415
|
|
|
12334
12416
|
// app/lib/whatsapp-reader/enrich-attachments.ts
|
|
12335
|
-
import { readFileSync as readFileSync20, readdirSync as readdirSync13, existsSync as existsSync16, statSync as
|
|
12336
|
-
import { basename as basename5, dirname as dirname6, join as
|
|
12417
|
+
import { readFileSync as readFileSync20, readdirSync as readdirSync13, existsSync as existsSync16, statSync as statSync8, realpathSync as realpathSync5 } from "fs";
|
|
12418
|
+
import { basename as basename5, dirname as dirname6, join as join21, resolve as resolve16, sep as sep4 } from "path";
|
|
12337
12419
|
var ADMIN_UPLOAD_PATH = /\/uploads\/(?!public\/)([0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12})\//gi;
|
|
12338
12420
|
function adminAttachmentIds(text) {
|
|
12339
12421
|
const ids = [];
|
|
@@ -12346,7 +12428,7 @@ function adminAttachmentIds(text) {
|
|
|
12346
12428
|
function adminAttachmentsFromText(text, uploadsBase) {
|
|
12347
12429
|
const out = [];
|
|
12348
12430
|
for (const id of adminAttachmentIds(text)) {
|
|
12349
|
-
const meta = readAttachmentMeta(
|
|
12431
|
+
const meta = readAttachmentMeta(join21(uploadsBase, id));
|
|
12350
12432
|
if (meta) out.push(meta);
|
|
12351
12433
|
}
|
|
12352
12434
|
return out;
|
|
@@ -12383,7 +12465,7 @@ function claudeUploadAttachmentsFromText(text, sessionId) {
|
|
|
12383
12465
|
attachmentId: filename,
|
|
12384
12466
|
filename,
|
|
12385
12467
|
mimeType: detectMimeType(filename),
|
|
12386
|
-
sizeBytes:
|
|
12468
|
+
sizeBytes: statSync8(real).size,
|
|
12387
12469
|
source: "claude-upload"
|
|
12388
12470
|
});
|
|
12389
12471
|
accepted.push(m[0]);
|
|
@@ -12396,7 +12478,7 @@ function claudeUploadAttachmentsFromText(text, sessionId) {
|
|
|
12396
12478
|
function readSidecar(dir, attachmentId) {
|
|
12397
12479
|
let parsed;
|
|
12398
12480
|
try {
|
|
12399
|
-
parsed = JSON.parse(readFileSync20(
|
|
12481
|
+
parsed = JSON.parse(readFileSync20(join21(dir, `${attachmentId}.meta.json`), "utf8"));
|
|
12400
12482
|
} catch {
|
|
12401
12483
|
return null;
|
|
12402
12484
|
}
|
|
@@ -12425,7 +12507,7 @@ function listSessionAttachmentsInDir(dir) {
|
|
|
12425
12507
|
}
|
|
12426
12508
|
const sidecars = [];
|
|
12427
12509
|
for (const name of entries2) {
|
|
12428
|
-
const sidecar = readSidecar(
|
|
12510
|
+
const sidecar = readSidecar(join21(dir, name), name);
|
|
12429
12511
|
if (sidecar) sidecars.push(sidecar);
|
|
12430
12512
|
}
|
|
12431
12513
|
sidecars.sort((a, b) => a.storedAt.localeCompare(b.storedAt));
|
|
@@ -12585,14 +12667,14 @@ app5.get("/conversations", requireAdminSession, async (c) => {
|
|
|
12585
12667
|
}
|
|
12586
12668
|
const cfg = claudeConfigDir();
|
|
12587
12669
|
if (!cfg) return c.json({ conversations: [] });
|
|
12588
|
-
const projectsRoot =
|
|
12670
|
+
const projectsRoot = join22(cfg, "projects");
|
|
12589
12671
|
const userTitles = loadUserTitles(ACCOUNTS_DIR ?? null);
|
|
12590
12672
|
const rows = [];
|
|
12591
12673
|
let sessionRowsExcludedUntagged = 0;
|
|
12592
12674
|
for (const { path: path3 } of enumerateJsonls(projectsRoot)) {
|
|
12593
12675
|
const sessionId = basename6(path3).replace(/\.jsonl$/, "");
|
|
12594
12676
|
const projectDir = dirname7(path3);
|
|
12595
|
-
const meta = readSidecarMeta(
|
|
12677
|
+
const meta = readSidecarMeta(join22(projectDir, `${sessionId}.meta.json`));
|
|
12596
12678
|
if (!isReaderChannelSession(meta.role, meta.channel)) continue;
|
|
12597
12679
|
if (multiAccount) {
|
|
12598
12680
|
if (meta.accountId === null) sessionRowsExcludedUntagged += 1;
|
|
@@ -12723,7 +12805,7 @@ app5.get("/conversations-all", requireAdminSession, async (c) => {
|
|
|
12723
12805
|
const { value, state } = await getOrCompute("conversations-all", houseId, async () => {
|
|
12724
12806
|
const cfg = claudeConfigDir();
|
|
12725
12807
|
if (!cfg) return { conversations: [] };
|
|
12726
|
-
const projectsRoot =
|
|
12808
|
+
const projectsRoot = join22(cfg, "projects");
|
|
12727
12809
|
const userTitles = loadUserTitles(ACCOUNTS_DIR ?? null);
|
|
12728
12810
|
const validAccounts = listValidAccounts();
|
|
12729
12811
|
const validIds = new Set(validAccounts.map((a) => a.accountId));
|
|
@@ -12732,7 +12814,7 @@ app5.get("/conversations-all", requireAdminSession, async (c) => {
|
|
|
12732
12814
|
for (const { path: path3 } of enumerateJsonls(projectsRoot)) {
|
|
12733
12815
|
const sessionId = basename6(path3).replace(/\.jsonl$/, "");
|
|
12734
12816
|
const projectDir = dirname7(path3);
|
|
12735
|
-
const meta = readSidecarMeta(
|
|
12817
|
+
const meta = readSidecarMeta(join22(projectDir, `${sessionId}.meta.json`));
|
|
12736
12818
|
if (!isReaderChannelSession(meta.role, meta.channel)) continue;
|
|
12737
12819
|
if (meta.accountId === null || !validIds.has(meta.accountId)) continue;
|
|
12738
12820
|
let body = "";
|
|
@@ -12803,7 +12885,7 @@ app5.get("/conversations-all", requireAdminSession, async (c) => {
|
|
|
12803
12885
|
return c.json(value);
|
|
12804
12886
|
});
|
|
12805
12887
|
function readFrom(path3, from) {
|
|
12806
|
-
const end =
|
|
12888
|
+
const end = statSync9(path3).size;
|
|
12807
12889
|
if (end <= from) return { buf: Buffer.alloc(0), end: from };
|
|
12808
12890
|
const fd = openSync(path3, "r");
|
|
12809
12891
|
try {
|
|
@@ -12897,7 +12979,7 @@ function openTaskKey(turns) {
|
|
|
12897
12979
|
}
|
|
12898
12980
|
function readSubagentMeta(dir, hex) {
|
|
12899
12981
|
try {
|
|
12900
|
-
const m = JSON.parse(readFileSync21(
|
|
12982
|
+
const m = JSON.parse(readFileSync21(join22(dir, `agent-${hex}.meta.json`), "utf8"));
|
|
12901
12983
|
if (typeof m.agentType === "string" && typeof m.description === "string" && typeof m.toolUseId === "string") {
|
|
12902
12984
|
return { agentType: m.agentType, description: m.description, toolUseId: m.toolUseId };
|
|
12903
12985
|
}
|
|
@@ -12929,7 +13011,7 @@ function runActivityTick(c) {
|
|
|
12929
13011
|
let size = 0;
|
|
12930
13012
|
let mtimeMs = 0;
|
|
12931
13013
|
try {
|
|
12932
|
-
const st =
|
|
13014
|
+
const st = statSync9(join22(c.subagentsDir, name));
|
|
12933
13015
|
size = st.size;
|
|
12934
13016
|
mtimeMs = st.mtimeMs;
|
|
12935
13017
|
} catch {
|
|
@@ -12974,11 +13056,11 @@ app5.get("/stream", requireAdminSession, (c) => {
|
|
|
12974
13056
|
const sessionId = c.req.query("sessionId") ?? "";
|
|
12975
13057
|
const projectDir = c.req.query("projectDir") ?? "";
|
|
12976
13058
|
const cfg = claudeConfigDir();
|
|
12977
|
-
const projectsRoot = cfg ? resolve17(
|
|
13059
|
+
const projectsRoot = cfg ? resolve17(join22(cfg, "projects")) : null;
|
|
12978
13060
|
if (!cfg || !projectsRoot || !SESSION_ID_RE2.test(sessionId)) {
|
|
12979
13061
|
return c.json({ error: "bad session reference" }, 400);
|
|
12980
13062
|
}
|
|
12981
|
-
const jsonlPath = resolve17(
|
|
13063
|
+
const jsonlPath = resolve17(join22(projectDir, `${sessionId}.jsonl`));
|
|
12982
13064
|
if (!jsonlPath.startsWith(projectsRoot + sep5)) {
|
|
12983
13065
|
return c.json({ error: "bad session reference" }, 400);
|
|
12984
13066
|
}
|
|
@@ -12997,7 +13079,7 @@ data: ${JSON.stringify(turn)}
|
|
|
12997
13079
|
start(controller) {
|
|
12998
13080
|
const fileEnd0 = (() => {
|
|
12999
13081
|
try {
|
|
13000
|
-
return
|
|
13082
|
+
return statSync9(jsonlPath).size;
|
|
13001
13083
|
} catch {
|
|
13002
13084
|
return 0;
|
|
13003
13085
|
}
|
|
@@ -13005,7 +13087,7 @@ data: ${JSON.stringify(turn)}
|
|
|
13005
13087
|
let offset = resumeOffset(lastEventId, fileEnd0);
|
|
13006
13088
|
console.log(`[wa-stream] op=open conn=${connId} sessionId=${sessionId} channel=reader resume=${offset}`);
|
|
13007
13089
|
const sessionKey = c.req.query("session_key") ?? "";
|
|
13008
|
-
const subagentsDir = resolve17(
|
|
13090
|
+
const subagentsDir = resolve17(join22(projectDir, sessionId, "subagents"));
|
|
13009
13091
|
console.log(
|
|
13010
13092
|
`[webchat-activity] op=watch-subagents key=${sessionKey} dir=${subagentsDir} exists=${existsSync17(subagentsDir)}`
|
|
13011
13093
|
);
|
|
@@ -13134,7 +13216,7 @@ app5.get("/directives", requireAdminSession, (c) => {
|
|
|
13134
13216
|
const pid = Number(pidPart);
|
|
13135
13217
|
let len = 0;
|
|
13136
13218
|
try {
|
|
13137
|
-
len =
|
|
13219
|
+
len = statSync9(join22(dir, name)).size;
|
|
13138
13220
|
} catch {
|
|
13139
13221
|
}
|
|
13140
13222
|
return { name, secs, pid, ts: Number.isFinite(secs) ? new Date(secs * 1e3).toISOString() : null, len };
|
|
@@ -13149,7 +13231,7 @@ app5.get("/directive", requireAdminSession, (c) => {
|
|
|
13149
13231
|
}
|
|
13150
13232
|
const dir = directiveStoreDir(sessionId);
|
|
13151
13233
|
if (!dir) return c.json({ error: "no account" }, 404);
|
|
13152
|
-
const path3 = resolve17(
|
|
13234
|
+
const path3 = resolve17(join22(dir, name));
|
|
13153
13235
|
if (!path3.startsWith(dir + sep5)) return c.json({ error: "bad reference" }, 400);
|
|
13154
13236
|
let body;
|
|
13155
13237
|
try {
|
|
@@ -13207,7 +13289,7 @@ app5.get("/store-stream", requireAdminSession, (c) => {
|
|
|
13207
13289
|
console.log(`[wa-reader] op=store-quote msgId=${r.msgKeyId} quoted=${!!q2}`);
|
|
13208
13290
|
}
|
|
13209
13291
|
if (r.attachmentId) {
|
|
13210
|
-
const meta = readAttachmentMeta(
|
|
13292
|
+
const meta = readAttachmentMeta(join22(uploadsBase, r.attachmentId));
|
|
13211
13293
|
if (meta) return { ...turn, attachments: [meta] };
|
|
13212
13294
|
}
|
|
13213
13295
|
return turn;
|
|
@@ -13240,7 +13322,7 @@ data: ${JSON.stringify(payload)}
|
|
|
13240
13322
|
};
|
|
13241
13323
|
const fileEnd0 = (() => {
|
|
13242
13324
|
try {
|
|
13243
|
-
return
|
|
13325
|
+
return statSync9(file).size;
|
|
13244
13326
|
} catch {
|
|
13245
13327
|
return 0;
|
|
13246
13328
|
}
|
|
@@ -13458,7 +13540,7 @@ app5.post("/reply", requireAdminSession, async (c) => {
|
|
|
13458
13540
|
const absolute = resolved.absolute;
|
|
13459
13541
|
let size = -1;
|
|
13460
13542
|
try {
|
|
13461
|
-
const st =
|
|
13543
|
+
const st = statSync9(absolute);
|
|
13462
13544
|
size = st.isFile() ? st.size : -1;
|
|
13463
13545
|
} catch {
|
|
13464
13546
|
size = -1;
|
|
@@ -13587,8 +13669,8 @@ app5.post("/reply", requireAdminSession, async (c) => {
|
|
|
13587
13669
|
var whatsapp_reader_default = app5;
|
|
13588
13670
|
|
|
13589
13671
|
// server/routes/public-reader.ts
|
|
13590
|
-
import { statSync as
|
|
13591
|
-
import { basename as basename7, dirname as dirname8, join as
|
|
13672
|
+
import { statSync as statSync10, openSync as openSync2, readSync as readSync2, closeSync as closeSync2, watch as watch3, readFileSync as readFileSync22, readdirSync as readdirSync15 } from "fs";
|
|
13673
|
+
import { basename as basename7, dirname as dirname8, join as join23, resolve as resolve18, sep as sep6 } from "path";
|
|
13592
13674
|
|
|
13593
13675
|
// app/lib/whatsapp-reader/delivered-kinds.ts
|
|
13594
13676
|
var PUBLIC_DELIVERED_KINDS = /* @__PURE__ */ new Set([
|
|
@@ -13662,10 +13744,10 @@ function enumeratePublicRows() {
|
|
|
13662
13744
|
const cfg = claudeConfigDir();
|
|
13663
13745
|
if (!cfg) return [];
|
|
13664
13746
|
const rows = [];
|
|
13665
|
-
for (const { path: path3 } of enumerateJsonls(
|
|
13747
|
+
for (const { path: path3 } of enumerateJsonls(join23(cfg, "projects"))) {
|
|
13666
13748
|
const sessionId = basename7(path3).replace(/\.jsonl$/, "");
|
|
13667
13749
|
const projectDir = dirname8(path3);
|
|
13668
|
-
const meta = readSidecarMeta(
|
|
13750
|
+
const meta = readSidecarMeta(join23(projectDir, `${sessionId}.meta.json`));
|
|
13669
13751
|
rows.push({
|
|
13670
13752
|
sessionId,
|
|
13671
13753
|
projectDir,
|
|
@@ -13721,7 +13803,7 @@ function enrichPublicAttachments(turns, sessionAttachments, cursor) {
|
|
|
13721
13803
|
}
|
|
13722
13804
|
}
|
|
13723
13805
|
function readFrom2(path3, from) {
|
|
13724
|
-
const end =
|
|
13806
|
+
const end = statSync10(path3).size;
|
|
13725
13807
|
if (end <= from) return { buf: Buffer.alloc(0), end: from };
|
|
13726
13808
|
const fd = openSync2(path3, "r");
|
|
13727
13809
|
try {
|
|
@@ -13741,15 +13823,15 @@ app6.get("/stream", (c) => {
|
|
|
13741
13823
|
const sessionId = c.req.query("sessionId") ?? "";
|
|
13742
13824
|
const projectDir = c.req.query("projectDir") ?? "";
|
|
13743
13825
|
const cfg = claudeConfigDir();
|
|
13744
|
-
const projectsRoot = cfg ? resolve18(
|
|
13826
|
+
const projectsRoot = cfg ? resolve18(join23(cfg, "projects")) : null;
|
|
13745
13827
|
if (!cfg || !projectsRoot || !SESSION_ID_RE2.test(sessionId)) {
|
|
13746
13828
|
return c.json({ error: "bad session reference" }, 400);
|
|
13747
13829
|
}
|
|
13748
|
-
const jsonlPath = resolve18(
|
|
13830
|
+
const jsonlPath = resolve18(join23(projectDir, `${sessionId}.jsonl`));
|
|
13749
13831
|
if (!jsonlPath.startsWith(projectsRoot + sep6)) {
|
|
13750
13832
|
return c.json({ error: "bad session reference" }, 400);
|
|
13751
13833
|
}
|
|
13752
|
-
const meta = readSidecarMeta(
|
|
13834
|
+
const meta = readSidecarMeta(join23(projectDir, `${sessionId}.meta.json`));
|
|
13753
13835
|
const isPublicWebchat = meta.role === "public" && meta.channel === "webchat";
|
|
13754
13836
|
const owns = visitor.kind === "person" ? meta.personId === visitor.personId : meta.personId === null && meta.visitorId === visitor.visitorId;
|
|
13755
13837
|
if (!(isPublicWebchat && owns)) {
|
|
@@ -13886,16 +13968,16 @@ var public_reader_default = app6;
|
|
|
13886
13968
|
|
|
13887
13969
|
// server/routes/webchat.ts
|
|
13888
13970
|
import { basename as basename8, dirname as dirname9 } from "path";
|
|
13889
|
-
import { join as
|
|
13890
|
-
import { existsSync as existsSync19, readdirSync as readdirSync17, readFileSync as readFileSync25, renameSync as renameSync4, statSync as
|
|
13971
|
+
import { join as join26 } from "path";
|
|
13972
|
+
import { existsSync as existsSync19, readdirSync as readdirSync17, readFileSync as readFileSync25, renameSync as renameSync4, statSync as statSync11, writeFileSync as writeFileSync9 } from "fs";
|
|
13891
13973
|
|
|
13892
13974
|
// server/canonical-webchat-override.ts
|
|
13893
13975
|
import { readFileSync as readFileSync23, writeFileSync as writeFileSync7, renameSync as renameSync2 } from "fs";
|
|
13894
|
-
import { join as
|
|
13976
|
+
import { join as join24 } from "path";
|
|
13895
13977
|
var FILE = "canonical-webchat-session.json";
|
|
13896
13978
|
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}$/;
|
|
13897
13979
|
function canonicalOverridePath(accountDir) {
|
|
13898
|
-
return
|
|
13980
|
+
return join24(accountDir, FILE);
|
|
13899
13981
|
}
|
|
13900
13982
|
function readRaw(accountDir) {
|
|
13901
13983
|
try {
|
|
@@ -13975,7 +14057,7 @@ function isNewSessionEffortLevel(value) {
|
|
|
13975
14057
|
|
|
13976
14058
|
// ../services/claude-session-manager/src/sidecar-store.ts
|
|
13977
14059
|
import { existsSync as existsSync18, mkdirSync as mkdirSync4, readdirSync as readdirSync16, readFileSync as readFileSync24, renameSync as renameSync3, unlinkSync as unlinkSync2, writeFileSync as writeFileSync8 } from "fs";
|
|
13978
|
-
import { join as
|
|
14060
|
+
import { join as join25 } from "path";
|
|
13979
14061
|
function escapeRegExp(s) {
|
|
13980
14062
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
13981
14063
|
}
|
|
@@ -13983,7 +14065,7 @@ function createSidecarStore(config) {
|
|
|
13983
14065
|
const { suffix, validate: validate2 } = config;
|
|
13984
14066
|
const suffixRe = new RegExp(`${escapeRegExp(suffix)}$`);
|
|
13985
14067
|
function pathFor(sessionsDir, id) {
|
|
13986
|
-
return
|
|
14068
|
+
return join25(sessionsDir, `${id}${suffix}`);
|
|
13987
14069
|
}
|
|
13988
14070
|
function write(sessionsDir, id, record) {
|
|
13989
14071
|
mkdirSync4(sessionsDir, { recursive: true });
|
|
@@ -14027,7 +14109,7 @@ function createSidecarStore(config) {
|
|
|
14027
14109
|
const out = [];
|
|
14028
14110
|
for (const name of names) {
|
|
14029
14111
|
if (!suffixRe.test(name)) continue;
|
|
14030
|
-
const path3 =
|
|
14112
|
+
const path3 = join25(sessionsDir, name);
|
|
14031
14113
|
let raw;
|
|
14032
14114
|
try {
|
|
14033
14115
|
raw = readFileSync24(path3, "utf8");
|
|
@@ -14104,13 +14186,13 @@ var UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9
|
|
|
14104
14186
|
function locateSession(sessionId) {
|
|
14105
14187
|
const dir = findSessionProjectDir(sessionId);
|
|
14106
14188
|
if (!dir) return { projectDir: null, channel: null, accountId: null };
|
|
14107
|
-
const meta = readSidecarMeta(
|
|
14189
|
+
const meta = readSidecarMeta(join26(dir, `${sessionId}.meta.json`));
|
|
14108
14190
|
return { projectDir: dir, channel: meta.channel, accountId: meta.accountId };
|
|
14109
14191
|
}
|
|
14110
14192
|
function locateSidecar(sessionId) {
|
|
14111
14193
|
const cfg = claudeConfigDir();
|
|
14112
14194
|
if (!cfg) return null;
|
|
14113
|
-
const projectsRoot =
|
|
14195
|
+
const projectsRoot = join26(cfg, "projects");
|
|
14114
14196
|
let slugs;
|
|
14115
14197
|
try {
|
|
14116
14198
|
slugs = readdirSync17(projectsRoot, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
@@ -14118,7 +14200,7 @@ function locateSidecar(sessionId) {
|
|
|
14118
14200
|
return null;
|
|
14119
14201
|
}
|
|
14120
14202
|
for (const slug of slugs) {
|
|
14121
|
-
const metaPath =
|
|
14203
|
+
const metaPath = join26(projectsRoot, slug, `${sessionId}.meta.json`);
|
|
14122
14204
|
if (existsSync19(metaPath)) return readSidecarMeta(metaPath);
|
|
14123
14205
|
}
|
|
14124
14206
|
return null;
|
|
@@ -14128,7 +14210,7 @@ function readTargetOwner(sessionId) {
|
|
|
14128
14210
|
if (sidecar !== null) return { found: true, owner: sidecar.adminUserId };
|
|
14129
14211
|
const { projectDir } = locateSession(sessionId);
|
|
14130
14212
|
if (projectDir !== null) {
|
|
14131
|
-
return { found: true, owner: readSidecarMeta(
|
|
14213
|
+
return { found: true, owner: readSidecarMeta(join26(projectDir, `${sessionId}.meta.json`)).adminUserId };
|
|
14132
14214
|
}
|
|
14133
14215
|
return { found: false, owner: null };
|
|
14134
14216
|
}
|
|
@@ -14136,7 +14218,7 @@ function readSourceRowMeta(sessionId) {
|
|
|
14136
14218
|
const sidecar = locateSidecar(sessionId);
|
|
14137
14219
|
if (sidecar !== null) return sidecar;
|
|
14138
14220
|
const { projectDir } = locateSession(sessionId);
|
|
14139
|
-
if (projectDir !== null) return readSidecarMeta(
|
|
14221
|
+
if (projectDir !== null) return readSidecarMeta(join26(projectDir, `${sessionId}.meta.json`));
|
|
14140
14222
|
return null;
|
|
14141
14223
|
}
|
|
14142
14224
|
function ownedByRequester(owner, requesterUserId, primaryUserId) {
|
|
@@ -14149,7 +14231,7 @@ function sessionSidecarExists(sessionId) {
|
|
|
14149
14231
|
function jsonlSizeBytes(projectDir, sessionId) {
|
|
14150
14232
|
if (projectDir === null) return null;
|
|
14151
14233
|
try {
|
|
14152
|
-
return
|
|
14234
|
+
return statSync11(join26(projectDir, `${sessionId}.jsonl`)).size;
|
|
14153
14235
|
} catch {
|
|
14154
14236
|
return null;
|
|
14155
14237
|
}
|
|
@@ -14285,15 +14367,15 @@ function latestAdminWebchatSessionId(requesterUserId, primaryUserId, scopeAccoun
|
|
|
14285
14367
|
const cfg = claudeConfigDir();
|
|
14286
14368
|
if (!cfg) return null;
|
|
14287
14369
|
let best = null;
|
|
14288
|
-
for (const { path: path3, isSubagent, archived } of enumerateJsonls(
|
|
14370
|
+
for (const { path: path3, isSubagent, archived } of enumerateJsonls(join26(cfg, "projects"))) {
|
|
14289
14371
|
if (isSubagent || archived) continue;
|
|
14290
14372
|
const id = basename8(path3).slice(0, -".jsonl".length);
|
|
14291
|
-
const meta = readSidecarMeta(
|
|
14373
|
+
const meta = readSidecarMeta(join26(dirname9(path3), `${id}.meta.json`));
|
|
14292
14374
|
if (meta.role !== "admin" || meta.channel !== "webchat") continue;
|
|
14293
14375
|
if (multiAccount && meta.accountId !== scopeAccountId) continue;
|
|
14294
14376
|
let mtimeMs;
|
|
14295
14377
|
try {
|
|
14296
|
-
mtimeMs =
|
|
14378
|
+
mtimeMs = statSync11(path3).mtimeMs;
|
|
14297
14379
|
} catch {
|
|
14298
14380
|
continue;
|
|
14299
14381
|
}
|
|
@@ -14601,7 +14683,7 @@ ${note}` : note;
|
|
|
14601
14683
|
console.error(`[webchat:settings] op=${op} outcome=refused value=${value} reason=account-unresolved`);
|
|
14602
14684
|
return c.json({ error: "account unresolved" }, 503);
|
|
14603
14685
|
}
|
|
14604
|
-
const accountJsonPath =
|
|
14686
|
+
const accountJsonPath = join26(account.accountDir, "account.json");
|
|
14605
14687
|
try {
|
|
14606
14688
|
const parsed = JSON.parse(readFileSync25(accountJsonPath, "utf8"));
|
|
14607
14689
|
if (op === "model") parsed.adminModel = value;
|
|
@@ -14649,7 +14731,7 @@ ${note}` : note;
|
|
|
14649
14731
|
const cfg2 = claudeConfigDir();
|
|
14650
14732
|
if (cfg2) {
|
|
14651
14733
|
const source2 = resolveBridgeSource(
|
|
14652
|
-
|
|
14734
|
+
join26(cfg2, "sessions"),
|
|
14653
14735
|
target,
|
|
14654
14736
|
(id) => locateSession(id).projectDir !== null
|
|
14655
14737
|
);
|
|
@@ -14681,7 +14763,7 @@ ${note}` : note;
|
|
|
14681
14763
|
const cfg = claudeConfigDir();
|
|
14682
14764
|
let projectDir = null;
|
|
14683
14765
|
if (cfg) {
|
|
14684
|
-
for (const { path: path3 } of enumerateJsonls(
|
|
14766
|
+
for (const { path: path3 } of enumerateJsonls(join26(cfg, "projects"))) {
|
|
14685
14767
|
if (basename8(path3) === `${sessionId}.jsonl`) {
|
|
14686
14768
|
projectDir = dirname9(path3);
|
|
14687
14769
|
break;
|
|
@@ -14689,7 +14771,7 @@ ${note}` : note;
|
|
|
14689
14771
|
}
|
|
14690
14772
|
}
|
|
14691
14773
|
if (source === "latest" && requesterUserId !== null) {
|
|
14692
|
-
const owner = readSidecarMeta(
|
|
14774
|
+
const owner = readSidecarMeta(join26(projectDir ?? "", `${sessionId}.meta.json`)).adminUserId;
|
|
14693
14775
|
if (owner !== null && owner !== requesterUserId && requesterUserId !== primaryUserId) {
|
|
14694
14776
|
console.error(`[webchat:inbound] op=session-resolve-foreign key=${sessionId.slice(0, 8)} owner=${owner.slice(0, 8)} requester=${requesterUserId.slice(0, 8)}`);
|
|
14695
14777
|
}
|
|
@@ -14722,7 +14804,7 @@ import { resolve as resolve19 } from "path";
|
|
|
14722
14804
|
|
|
14723
14805
|
// app/lib/claude-agent/specialist-roster.ts
|
|
14724
14806
|
import { existsSync as existsSync20, readFileSync as readFileSync26, readdirSync as readdirSync18 } from "fs";
|
|
14725
|
-
import { join as
|
|
14807
|
+
import { join as join27 } from "path";
|
|
14726
14808
|
function field(fm, name) {
|
|
14727
14809
|
const m = fm.match(new RegExp(`^${name}:\\s*(.*?)\\r?$`, "m"));
|
|
14728
14810
|
if (!m) return null;
|
|
@@ -14741,7 +14823,7 @@ function readSpecialistRoster(specialistsDir) {
|
|
|
14741
14823
|
if (!file.endsWith(".md")) continue;
|
|
14742
14824
|
let raw;
|
|
14743
14825
|
try {
|
|
14744
|
-
raw = readFileSync26(
|
|
14826
|
+
raw = readFileSync26(join27(specialistsDir, file), "utf-8");
|
|
14745
14827
|
} catch (err) {
|
|
14746
14828
|
skipped.push({ file, reason: err instanceof Error ? err.message : String(err) });
|
|
14747
14829
|
continue;
|
|
@@ -14858,7 +14940,7 @@ var webchat_greeting_default = app7;
|
|
|
14858
14940
|
|
|
14859
14941
|
// server/routes/telegram.ts
|
|
14860
14942
|
import { homedir as homedir2 } from "os";
|
|
14861
|
-
import { resolve as resolve20, join as
|
|
14943
|
+
import { resolve as resolve20, join as join28 } from "path";
|
|
14862
14944
|
import { existsSync as existsSync21, readFileSync as readFileSync27 } from "fs";
|
|
14863
14945
|
|
|
14864
14946
|
// app/lib/telegram/gateway/instance.ts
|
|
@@ -14918,7 +15000,7 @@ function routeTelegramUpdate(input) {
|
|
|
14918
15000
|
var TAG30 = "[telegram-inbound]";
|
|
14919
15001
|
function configDirName() {
|
|
14920
15002
|
const platformRoot5 = process.env.MAXY_PLATFORM_ROOT ?? resolve20(process.cwd(), "..");
|
|
14921
|
-
const brandPath =
|
|
15003
|
+
const brandPath = join28(platformRoot5, "config", "brand.json");
|
|
14922
15004
|
if (existsSync21(brandPath)) {
|
|
14923
15005
|
try {
|
|
14924
15006
|
return JSON.parse(readFileSync27(brandPath, "utf-8")).configDir ?? ".maxy";
|
|
@@ -15007,16 +15089,16 @@ app8.post("/", async (c) => {
|
|
|
15007
15089
|
var telegram_default = app8;
|
|
15008
15090
|
|
|
15009
15091
|
// server/routes/quickbooks.ts
|
|
15010
|
-
import { join as
|
|
15092
|
+
import { join as join29 } from "path";
|
|
15011
15093
|
import { existsSync as existsSync22, readFileSync as readFileSync28, writeFileSync as writeFileSync10, mkdirSync as mkdirSync5, rmSync, renameSync as renameSync5 } from "fs";
|
|
15012
15094
|
var TAG31 = "[quickbooks]";
|
|
15013
15095
|
var INTUIT_TOKEN_URL = "https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer";
|
|
15014
15096
|
var STATE_RE = /^[A-Za-z0-9_-]+$/;
|
|
15015
15097
|
function pendingPath(accountDir, state) {
|
|
15016
|
-
return
|
|
15098
|
+
return join29(accountDir, "secrets", "quickbooks-pending", `${state}.json`);
|
|
15017
15099
|
}
|
|
15018
15100
|
function storePath(accountDir) {
|
|
15019
|
-
return
|
|
15101
|
+
return join29(accountDir, "secrets", "quickbooks.json");
|
|
15020
15102
|
}
|
|
15021
15103
|
async function completeConsent(args) {
|
|
15022
15104
|
const { accountDir, code, realmId } = args;
|
|
@@ -15083,7 +15165,7 @@ async function completeConsent(args) {
|
|
|
15083
15165
|
refreshTokenExpiry: now + (body.x_refresh_token_expires_in ?? 864e4) * 1e3,
|
|
15084
15166
|
lastRefresh: now
|
|
15085
15167
|
};
|
|
15086
|
-
mkdirSync5(
|
|
15168
|
+
mkdirSync5(join29(accountDir, "secrets"), { recursive: true });
|
|
15087
15169
|
writeFileSync10(storePath(accountDir), JSON.stringify(store2, null, 2), { mode: 384 });
|
|
15088
15170
|
const persisted = JSON.parse(readFileSync28(storePath(accountDir), "utf-8")).connections?.[realmId]?.refreshToken === body.refresh_token;
|
|
15089
15171
|
console.error(`${TAG31} op=token-exchange realmId=${realmId} persisted=${persisted}`);
|
|
@@ -15125,7 +15207,7 @@ function claudeBin() {
|
|
|
15125
15207
|
}
|
|
15126
15208
|
|
|
15127
15209
|
// server/routes/onboarding.ts
|
|
15128
|
-
import { dirname as dirname11, join as
|
|
15210
|
+
import { dirname as dirname11, join as join31 } from "path";
|
|
15129
15211
|
|
|
15130
15212
|
// app/lib/claude-keychain.ts
|
|
15131
15213
|
import { execFileSync as execFileSync3 } from "child_process";
|
|
@@ -15254,8 +15336,8 @@ function readHostCredsBlob(service) {
|
|
|
15254
15336
|
}
|
|
15255
15337
|
|
|
15256
15338
|
// ../lib/admins-write/src/index.ts
|
|
15257
|
-
import { existsSync as existsSync23, readFileSync as readFileSync29, writeFileSync as writeFileSync11, renameSync as renameSync6, mkdirSync as mkdirSync6, readdirSync as readdirSync19, statSync as
|
|
15258
|
-
import { dirname as dirname10, join as
|
|
15339
|
+
import { existsSync as existsSync23, readFileSync as readFileSync29, writeFileSync as writeFileSync11, renameSync as renameSync6, mkdirSync as mkdirSync6, readdirSync as readdirSync19, statSync as statSync12, appendFileSync as appendFileSync3 } from "fs";
|
|
15340
|
+
import { dirname as dirname10, join as join30 } from "path";
|
|
15259
15341
|
function id8(value) {
|
|
15260
15342
|
return value.slice(0, 8);
|
|
15261
15343
|
}
|
|
@@ -15328,7 +15410,7 @@ function writeAdminEntry(input) {
|
|
|
15328
15410
|
return result;
|
|
15329
15411
|
}
|
|
15330
15412
|
try {
|
|
15331
|
-
const accountJsonPath =
|
|
15413
|
+
const accountJsonPath = join30(input.accountDir, "account.json");
|
|
15332
15414
|
if (!existsSync23(accountJsonPath)) {
|
|
15333
15415
|
throw new Error(`account.json not found at ${accountJsonPath}`);
|
|
15334
15416
|
}
|
|
@@ -15376,13 +15458,13 @@ function computeAdminStoreDivergence(input) {
|
|
|
15376
15458
|
}
|
|
15377
15459
|
for (const entry of entries2) {
|
|
15378
15460
|
if (entry.startsWith(".")) continue;
|
|
15379
|
-
const accountDir =
|
|
15461
|
+
const accountDir = join30(input.accountsDir, entry);
|
|
15380
15462
|
try {
|
|
15381
|
-
if (!
|
|
15463
|
+
if (!statSync12(accountDir).isDirectory()) continue;
|
|
15382
15464
|
} catch {
|
|
15383
15465
|
continue;
|
|
15384
15466
|
}
|
|
15385
|
-
const accountJsonPath =
|
|
15467
|
+
const accountJsonPath = join30(accountDir, "account.json");
|
|
15386
15468
|
if (!existsSync23(accountJsonPath)) continue;
|
|
15387
15469
|
let admins = [];
|
|
15388
15470
|
try {
|
|
@@ -15560,7 +15642,7 @@ app10.post("/claude-auth", async (c) => {
|
|
|
15560
15642
|
});
|
|
15561
15643
|
persistKeychainService(
|
|
15562
15644
|
writebackResult,
|
|
15563
|
-
(service) => writeFileSync12(
|
|
15645
|
+
(service) => writeFileSync12(join31(dirname11(CLAUDE_CREDENTIALS_FILE), ".keychain-service"), service, { mode: 384 }),
|
|
15564
15646
|
(line) => console.log(line)
|
|
15565
15647
|
);
|
|
15566
15648
|
if (darwinAuthChild === claudeProc2) darwinAuthChild = null;
|
|
@@ -15825,9 +15907,9 @@ ${body.newPin}
|
|
|
15825
15907
|
var onboarding_default = app10;
|
|
15826
15908
|
|
|
15827
15909
|
// server/routes/client-error.ts
|
|
15828
|
-
import { appendFileSync as appendFileSync4, existsSync as existsSync25, renameSync as renameSync8, statSync as
|
|
15829
|
-
import { join as
|
|
15830
|
-
var CLIENT_ERRORS_LOG =
|
|
15910
|
+
import { appendFileSync as appendFileSync4, existsSync as existsSync25, renameSync as renameSync8, statSync as statSync13 } from "fs";
|
|
15911
|
+
import { join as join32 } from "path";
|
|
15912
|
+
var CLIENT_ERRORS_LOG = join32(LOG_DIR, "client-errors.log");
|
|
15831
15913
|
var MAX_LOG_SIZE = 10 * 1024 * 1024;
|
|
15832
15914
|
var MAX_BODY_SIZE = 8 * 1024;
|
|
15833
15915
|
var MAX_STACK_LEN = 2e3;
|
|
@@ -15885,7 +15967,7 @@ function stackHead(stack) {
|
|
|
15885
15967
|
function rotateIfNeeded() {
|
|
15886
15968
|
try {
|
|
15887
15969
|
if (!existsSync25(CLIENT_ERRORS_LOG)) return;
|
|
15888
|
-
const stats =
|
|
15970
|
+
const stats = statSync13(CLIENT_ERRORS_LOG);
|
|
15889
15971
|
if (stats.size < MAX_LOG_SIZE) return;
|
|
15890
15972
|
renameSync8(CLIENT_ERRORS_LOG, CLIENT_ERRORS_LOG + ".1");
|
|
15891
15973
|
} catch (err) {
|
|
@@ -15971,7 +16053,7 @@ app11.post("/", async (c) => {
|
|
|
15971
16053
|
const safe = typeof v === "string" ? truncate(v, 200) : typeof v === "number" || typeof v === "boolean" ? String(v) : JSON.stringify(v).slice(0, 200);
|
|
15972
16054
|
return `${k}=${safe}`;
|
|
15973
16055
|
}).join(" ");
|
|
15974
|
-
const TAGGED_PREFIX_SOURCES = /* @__PURE__ */ new Set(["stream-log-click", "pwa", "graph-settle"]);
|
|
16056
|
+
const TAGGED_PREFIX_SOURCES = /* @__PURE__ */ new Set(["stream-log-click", "pwa", "graph-settle", "dashboard-load"]);
|
|
15975
16057
|
if (TAGGED_PREFIX_SOURCES.has(source)) {
|
|
15976
16058
|
console.log(
|
|
15977
16059
|
`[${source}] ts=${ts} ip=${ip} version=${version || "unknown"}${extra ? " " + extra : ""}`
|
|
@@ -16211,17 +16293,17 @@ app13.get("/", requireAdminSession, async (c) => {
|
|
|
16211
16293
|
var accounts_default = app13;
|
|
16212
16294
|
|
|
16213
16295
|
// server/routes/admin/logs.ts
|
|
16214
|
-
import { existsSync as existsSync27, readdirSync as readdirSync20, readFileSync as readFileSync31, statSync as
|
|
16296
|
+
import { existsSync as existsSync27, readdirSync as readdirSync20, readFileSync as readFileSync31, statSync as statSync14 } from "fs";
|
|
16215
16297
|
import { resolve as resolve21, basename as basename9 } from "path";
|
|
16216
16298
|
|
|
16217
16299
|
// app/lib/logs-read-resolve.ts
|
|
16218
16300
|
import { existsSync as existsSync26 } from "fs";
|
|
16219
|
-
import { join as
|
|
16301
|
+
import { join as join33 } from "path";
|
|
16220
16302
|
function resolveSessionLogPaths(filename, logDirs) {
|
|
16221
16303
|
const tried = [filename];
|
|
16222
16304
|
const hits = [];
|
|
16223
16305
|
for (const dir of logDirs) {
|
|
16224
|
-
const fullPath =
|
|
16306
|
+
const fullPath = join33(dir, filename);
|
|
16225
16307
|
if (existsSync26(fullPath)) {
|
|
16226
16308
|
hits.push({ path: fullPath, dir });
|
|
16227
16309
|
}
|
|
@@ -16251,7 +16333,7 @@ app14.get("/", async (c) => {
|
|
|
16251
16333
|
searched.push(filePath);
|
|
16252
16334
|
try {
|
|
16253
16335
|
const buffer = readFileSync31(filePath);
|
|
16254
|
-
const onDiskBytes =
|
|
16336
|
+
const onDiskBytes = statSync14(filePath).size;
|
|
16255
16337
|
const headers = {
|
|
16256
16338
|
"Content-Type": "text/plain; charset=utf-8",
|
|
16257
16339
|
"Content-Length": String(buffer.byteLength)
|
|
@@ -16316,7 +16398,7 @@ app14.get("/", async (c) => {
|
|
|
16316
16398
|
try {
|
|
16317
16399
|
const filename = basename9(hit.path);
|
|
16318
16400
|
const buffer = readFileSync31(hit.path);
|
|
16319
|
-
const onDiskBytes =
|
|
16401
|
+
const onDiskBytes = statSync14(hit.path).size;
|
|
16320
16402
|
const headers = {
|
|
16321
16403
|
"Content-Type": "text/plain; charset=utf-8",
|
|
16322
16404
|
"Content-Length": String(buffer.byteLength)
|
|
@@ -16359,7 +16441,7 @@ app14.get("/", async (c) => {
|
|
|
16359
16441
|
console.warn(`[admin/logs] readdir-fail dir=${dir} reason=${reason}`);
|
|
16360
16442
|
continue;
|
|
16361
16443
|
}
|
|
16362
|
-
files.filter((f) => !seen.has(f)).map((f) => ({ name: f, mtime:
|
|
16444
|
+
files.filter((f) => !seen.has(f)).map((f) => ({ name: f, mtime: statSync14(resolve21(dir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime).forEach(({ name }) => {
|
|
16363
16445
|
seen.add(name);
|
|
16364
16446
|
try {
|
|
16365
16447
|
const content = readFileSync31(resolve21(dir, name));
|
|
@@ -16479,7 +16561,7 @@ var attachment_default = app16;
|
|
|
16479
16561
|
|
|
16480
16562
|
// server/routes/admin/session-upload.ts
|
|
16481
16563
|
import { readFile as readFile5 } from "fs/promises";
|
|
16482
|
-
import { existsSync as existsSync29, statSync as
|
|
16564
|
+
import { existsSync as existsSync29, statSync as statSync15 } from "fs";
|
|
16483
16565
|
var app17 = new Hono();
|
|
16484
16566
|
app17.get("/", requireAdminSession, async (c) => {
|
|
16485
16567
|
const cacheKey = c.var.cacheKey;
|
|
@@ -16500,7 +16582,7 @@ app17.get("/", requireAdminSession, async (c) => {
|
|
|
16500
16582
|
return c.json({ error: "Not found" }, 404);
|
|
16501
16583
|
}
|
|
16502
16584
|
const resolution = resolveClaudeUploadsPath(`${sessionId}/${file}`);
|
|
16503
|
-
if (!resolution.ok || !existsSync29(resolution.absolute) || !
|
|
16585
|
+
if (!resolution.ok || !existsSync29(resolution.absolute) || !statSync15(resolution.absolute).isFile()) {
|
|
16504
16586
|
console.log(`[session-upload] op=miss session=${short2} file=${file} status=404 reason=absent`);
|
|
16505
16587
|
return c.json({ error: "Not found" }, 404);
|
|
16506
16588
|
}
|
|
@@ -16550,9 +16632,9 @@ async function authorizeAccountWrite(c, accountId) {
|
|
|
16550
16632
|
}
|
|
16551
16633
|
|
|
16552
16634
|
// ../services/claude-session-manager/src/tool-surface.ts
|
|
16553
|
-
import { readFileSync as readFileSync32, readdirSync as readdirSync21, statSync as
|
|
16635
|
+
import { readFileSync as readFileSync32, readdirSync as readdirSync21, statSync as statSync16, existsSync as existsSync30 } from "fs";
|
|
16554
16636
|
import { createHash as createHash5 } from "crypto";
|
|
16555
|
-
import { join as
|
|
16637
|
+
import { join as join34 } from "path";
|
|
16556
16638
|
|
|
16557
16639
|
// ../services/claude-session-manager/src/canonical-tool-names.ts
|
|
16558
16640
|
function canonicalToolName(plugin, tool) {
|
|
@@ -16805,13 +16887,13 @@ function loadToolSurface(pluginsRoots) {
|
|
|
16805
16887
|
const riskByTool = /* @__PURE__ */ new Map();
|
|
16806
16888
|
const manifestPaths = /* @__PURE__ */ new Map();
|
|
16807
16889
|
const loadOne = (pluginsRoot, plugin) => {
|
|
16808
|
-
const pluginDir =
|
|
16890
|
+
const pluginDir = join34(pluginsRoot, plugin);
|
|
16809
16891
|
try {
|
|
16810
|
-
if (!
|
|
16892
|
+
if (!statSync16(pluginDir).isDirectory()) return;
|
|
16811
16893
|
} catch {
|
|
16812
16894
|
return;
|
|
16813
16895
|
}
|
|
16814
|
-
const manifestPath =
|
|
16896
|
+
const manifestPath = join34(pluginDir, "PLUGIN.md");
|
|
16815
16897
|
if (!existsSync30(manifestPath)) return;
|
|
16816
16898
|
const raw = readFileSync32(manifestPath, "utf-8");
|
|
16817
16899
|
const frontmatter = extractFrontmatter(raw, plugin);
|
|
@@ -16857,12 +16939,12 @@ function loadToolSurface(pluginsRoots) {
|
|
|
16857
16939
|
for (const root of roots) {
|
|
16858
16940
|
const entries2 = readdirSync21(root).sort();
|
|
16859
16941
|
for (const plugin of entries2) {
|
|
16860
|
-
const pluginDir =
|
|
16942
|
+
const pluginDir = join34(root, plugin);
|
|
16861
16943
|
loadOne(root, plugin);
|
|
16862
|
-
const subRoot =
|
|
16944
|
+
const subRoot = join34(pluginDir, "plugins");
|
|
16863
16945
|
let subEntries;
|
|
16864
16946
|
try {
|
|
16865
|
-
if (!
|
|
16947
|
+
if (!statSync16(subRoot).isDirectory()) continue;
|
|
16866
16948
|
subEntries = readdirSync21(subRoot).sort();
|
|
16867
16949
|
} catch {
|
|
16868
16950
|
continue;
|
|
@@ -16905,7 +16987,7 @@ function agentRiskClass(tools, riskByTool) {
|
|
|
16905
16987
|
const byTool = [];
|
|
16906
16988
|
const unresolved = [];
|
|
16907
16989
|
let worst = null;
|
|
16908
|
-
let
|
|
16990
|
+
let riskiestTool = null;
|
|
16909
16991
|
for (const tool of tools) {
|
|
16910
16992
|
const cls = BUILTIN_TOOL_RISK[tool] ?? riskByTool.get(tool) ?? null;
|
|
16911
16993
|
byTool.push({ tool, risk: cls });
|
|
@@ -16915,16 +16997,16 @@ function agentRiskClass(tools, riskByTool) {
|
|
|
16915
16997
|
}
|
|
16916
16998
|
if (worst === null || SEVERITY[cls] > SEVERITY[worst]) {
|
|
16917
16999
|
worst = cls;
|
|
16918
|
-
|
|
17000
|
+
riskiestTool = tool;
|
|
16919
17001
|
}
|
|
16920
17002
|
}
|
|
16921
17003
|
if (unresolved.length > 0) {
|
|
16922
|
-
return { risk: "red",
|
|
17004
|
+
return { risk: "red", riskiestTool: unresolved[0], unresolved, byTool };
|
|
16923
17005
|
}
|
|
16924
17006
|
if (worst === null) {
|
|
16925
|
-
return { risk: "red",
|
|
17007
|
+
return { risk: "red", riskiestTool: null, unresolved, byTool };
|
|
16926
17008
|
}
|
|
16927
|
-
return { risk: AGENT_CLASS[worst],
|
|
17009
|
+
return { risk: AGENT_CLASS[worst], riskiestTool, unresolved, byTool };
|
|
16928
17010
|
}
|
|
16929
17011
|
|
|
16930
17012
|
// server/routes/admin/agents.ts
|
|
@@ -17024,7 +17106,7 @@ function listShipped(accountDir, riskByTool, disabled, riskSurfaceFailed) {
|
|
|
17024
17106
|
plugin: "",
|
|
17025
17107
|
description: fm.description ?? "",
|
|
17026
17108
|
risk: r.risk,
|
|
17027
|
-
|
|
17109
|
+
riskiestTool: r.riskiestTool,
|
|
17028
17110
|
unresolved: r.unresolved,
|
|
17029
17111
|
toolCount: tools.length,
|
|
17030
17112
|
// The DIRECTORY is the ground truth, not the store. `spawn-context.ts`
|
|
@@ -17046,7 +17128,7 @@ function parseToolsLine(raw) {
|
|
|
17046
17128
|
}
|
|
17047
17129
|
function classify(tools, riskByTool, riskSurfaceFailed) {
|
|
17048
17130
|
if (riskSurfaceFailed) {
|
|
17049
|
-
return { risk: "red",
|
|
17131
|
+
return { risk: "red", riskiestTool: null, unresolved: [], byTool: tools.map((t) => ({ tool: t, risk: null })) };
|
|
17050
17132
|
}
|
|
17051
17133
|
return agentRiskClass(tools, riskByTool);
|
|
17052
17134
|
}
|
|
@@ -17082,7 +17164,7 @@ function listSpecialists(accountDir, riskByTool, riskSurfaceFailed) {
|
|
|
17082
17164
|
plugin,
|
|
17083
17165
|
description: fm.description ?? "",
|
|
17084
17166
|
risk: r.risk,
|
|
17085
|
-
|
|
17167
|
+
riskiestTool: r.riskiestTool,
|
|
17086
17168
|
unresolved: r.unresolved,
|
|
17087
17169
|
toolCount: specialistTools.length,
|
|
17088
17170
|
// A user-created specialist lives under the account plugins tree,
|
|
@@ -17133,7 +17215,7 @@ app18.get("/", requireAdminSession, (c) => {
|
|
|
17133
17215
|
kind: "public",
|
|
17134
17216
|
origin: "public",
|
|
17135
17217
|
risk: null,
|
|
17136
|
-
|
|
17218
|
+
riskiestTool: null,
|
|
17137
17219
|
unresolved: [],
|
|
17138
17220
|
disabled: false
|
|
17139
17221
|
});
|
|
@@ -17153,7 +17235,7 @@ app18.get("/", requireAdminSession, (c) => {
|
|
|
17153
17235
|
for (const row of rows) {
|
|
17154
17236
|
if (row.risk === null) continue;
|
|
17155
17237
|
console.log(
|
|
17156
|
-
`[admin/agents] op=classify account=${acct} agent=${row.slug} origin=${row.origin} risk=${row.risk}
|
|
17238
|
+
`[admin/agents] op=classify account=${acct} agent=${row.slug} origin=${row.origin} risk=${row.risk} riskiestTool=${row.riskiestTool ?? "none"} tools=${row.toolCount} unresolved=${row.unresolved.length > 0 ? row.unresolved.join(",") : "none"} disabled=${row.disabled}`
|
|
17157
17239
|
);
|
|
17158
17240
|
}
|
|
17159
17241
|
console.log(`[admin/agents] op=list accountId=${acct} agents=${agents.length} specialists=${specialists.length} shipped=${shipped.length} skipped=${skipped} specialistsSkipped=${specialistsSkipped} shippedSkipped=${shippedSkipped}`);
|
|
@@ -17196,7 +17278,7 @@ app18.get("/:slug", requireAdminSession, (c) => {
|
|
|
17196
17278
|
systemPrompt: body.trim(),
|
|
17197
17279
|
skills: [],
|
|
17198
17280
|
risk: r.risk,
|
|
17199
|
-
|
|
17281
|
+
riskiestTool: r.riskiestTool,
|
|
17200
17282
|
unresolved: r.unresolved,
|
|
17201
17283
|
byTool: r.byTool,
|
|
17202
17284
|
disabled: readDisabledStore(account.accountDir).has(`${slug}.md`)
|
|
@@ -17227,7 +17309,7 @@ app18.get("/:slug", requireAdminSession, (c) => {
|
|
|
17227
17309
|
systemPrompt: body.trim(),
|
|
17228
17310
|
skills,
|
|
17229
17311
|
risk: r.risk,
|
|
17230
|
-
|
|
17312
|
+
riskiestTool: r.riskiestTool,
|
|
17231
17313
|
unresolved: r.unresolved,
|
|
17232
17314
|
byTool: r.byTool,
|
|
17233
17315
|
disabled: false
|
|
@@ -18126,8 +18208,8 @@ app19.put("/:id/label", requireAdminSession, async (c) => {
|
|
|
18126
18208
|
var sessions_default = app19;
|
|
18127
18209
|
|
|
18128
18210
|
// app/lib/claude-agent/spawn-context.ts
|
|
18129
|
-
import { existsSync as existsSync33, readFileSync as readFileSync34, readdirSync as readdirSync23, statSync as
|
|
18130
|
-
import { dirname as dirname12, resolve as resolve24, join as
|
|
18211
|
+
import { existsSync as existsSync33, readFileSync as readFileSync34, readdirSync as readdirSync23, statSync as statSync17 } from "fs";
|
|
18212
|
+
import { dirname as dirname12, resolve as resolve24, join as join35 } from "path";
|
|
18131
18213
|
async function resolveOwnerProfileBlock(accountId, userId) {
|
|
18132
18214
|
if (!userId) return { ok: false, reason: "missing-user-id" };
|
|
18133
18215
|
try {
|
|
@@ -18168,8 +18250,8 @@ function frontmatterField(manifest, field2) {
|
|
|
18168
18250
|
function extractPluginToolDescriptions(pluginDir) {
|
|
18169
18251
|
const out = /* @__PURE__ */ new Map();
|
|
18170
18252
|
const candidates = [
|
|
18171
|
-
|
|
18172
|
-
|
|
18253
|
+
join35(pluginDir, "mcp/dist/index.js"),
|
|
18254
|
+
join35(pluginDir, "mcp/src/index.ts")
|
|
18173
18255
|
];
|
|
18174
18256
|
let raw = null;
|
|
18175
18257
|
for (const path3 of candidates) {
|
|
@@ -18227,9 +18309,9 @@ function listPluginDirs(accountPluginsDir) {
|
|
|
18227
18309
|
const platformPlugins = resolve24(PLATFORM_ROOT, "plugins");
|
|
18228
18310
|
if (existsSync33(platformPlugins)) {
|
|
18229
18311
|
for (const name of readdirSync23(platformPlugins)) {
|
|
18230
|
-
const dir =
|
|
18312
|
+
const dir = join35(platformPlugins, name);
|
|
18231
18313
|
try {
|
|
18232
|
-
if (
|
|
18314
|
+
if (statSync17(dir).isDirectory()) out.set(name, dir);
|
|
18233
18315
|
} catch {
|
|
18234
18316
|
}
|
|
18235
18317
|
}
|
|
@@ -18237,13 +18319,13 @@ function listPluginDirs(accountPluginsDir) {
|
|
|
18237
18319
|
const premiumRoot = resolve24(dirname12(PLATFORM_ROOT), "premium-plugins");
|
|
18238
18320
|
if (existsSync33(premiumRoot)) {
|
|
18239
18321
|
for (const bundle of readdirSync23(premiumRoot)) {
|
|
18240
|
-
const bundlePlugins =
|
|
18322
|
+
const bundlePlugins = join35(premiumRoot, bundle, "plugins");
|
|
18241
18323
|
if (!existsSync33(bundlePlugins)) continue;
|
|
18242
18324
|
try {
|
|
18243
18325
|
for (const name of readdirSync23(bundlePlugins)) {
|
|
18244
|
-
const dir =
|
|
18326
|
+
const dir = join35(bundlePlugins, name);
|
|
18245
18327
|
try {
|
|
18246
|
-
if (
|
|
18328
|
+
if (statSync17(dir).isDirectory()) out.set(name, dir);
|
|
18247
18329
|
} catch {
|
|
18248
18330
|
}
|
|
18249
18331
|
}
|
|
@@ -18255,9 +18337,9 @@ function listPluginDirs(accountPluginsDir) {
|
|
|
18255
18337
|
try {
|
|
18256
18338
|
for (const name of readdirSync23(accountPluginsDir)) {
|
|
18257
18339
|
if (out.has(name)) continue;
|
|
18258
|
-
const dir =
|
|
18340
|
+
const dir = join35(accountPluginsDir, name);
|
|
18259
18341
|
try {
|
|
18260
|
-
if (
|
|
18342
|
+
if (statSync17(dir).isDirectory()) out.set(name, dir);
|
|
18261
18343
|
} catch {
|
|
18262
18344
|
}
|
|
18263
18345
|
}
|
|
@@ -18274,7 +18356,7 @@ function listAccountPluginNames(accountPluginsDir) {
|
|
|
18274
18356
|
try {
|
|
18275
18357
|
return readdirSync23(accountPluginsDir).filter((name) => {
|
|
18276
18358
|
try {
|
|
18277
|
-
return
|
|
18359
|
+
return statSync17(join35(accountPluginsDir, name)).isDirectory();
|
|
18278
18360
|
} catch {
|
|
18279
18361
|
return false;
|
|
18280
18362
|
}
|
|
@@ -18317,7 +18399,7 @@ function computeActivePlugins(accountId) {
|
|
|
18317
18399
|
for (const name of emitNames) {
|
|
18318
18400
|
const dir = pluginDirs.get(name);
|
|
18319
18401
|
if (!dir) continue;
|
|
18320
|
-
const fm = readFrontmatter(
|
|
18402
|
+
const fm = readFrontmatter(join35(dir, "PLUGIN.md"));
|
|
18321
18403
|
if (!fm) continue;
|
|
18322
18404
|
const description = frontmatterField(`---
|
|
18323
18405
|
${fm}
|
|
@@ -18334,7 +18416,7 @@ ${fm}
|
|
|
18334
18416
|
`plugin-manifest-tool-coverage plugin=${name} tools=${tools.length} with-desc=${withDesc}`
|
|
18335
18417
|
);
|
|
18336
18418
|
if (toolNames.length > 0 && descMap.size === 0) {
|
|
18337
|
-
const hasSource = existsSync33(
|
|
18419
|
+
const hasSource = existsSync33(join35(dir, "mcp/dist/index.js")) || existsSync33(join35(dir, "mcp/src/index.ts"));
|
|
18338
18420
|
if (hasSource) {
|
|
18339
18421
|
console.warn(
|
|
18340
18422
|
`[spawn-context] WARN plugin=${name} mcp source present but tool-description regex matched zero entries \u2014 SDK upgrade may have changed the registration shape`
|
|
@@ -18344,7 +18426,7 @@ ${fm}
|
|
|
18344
18426
|
const skillPaths = parseSkillPathsFromFrontmatter(fm);
|
|
18345
18427
|
const skills = [];
|
|
18346
18428
|
for (const relPath of skillPaths) {
|
|
18347
|
-
const skillPath =
|
|
18429
|
+
const skillPath = join35(dir, relPath);
|
|
18348
18430
|
const skillFm = readFrontmatter(skillPath);
|
|
18349
18431
|
if (!skillFm) continue;
|
|
18350
18432
|
const skillName = frontmatterField(`---
|
|
@@ -18388,7 +18470,7 @@ function computeSpecialistDomains(accountId) {
|
|
|
18388
18470
|
const out = [];
|
|
18389
18471
|
for (const file of entries2.sort()) {
|
|
18390
18472
|
if (!file.endsWith(".md")) continue;
|
|
18391
|
-
const fm = readFrontmatter(
|
|
18473
|
+
const fm = readFrontmatter(join35(specialistsDir, file));
|
|
18392
18474
|
if (!fm) continue;
|
|
18393
18475
|
const wrapped = `---
|
|
18394
18476
|
${fm}
|
|
@@ -18787,7 +18869,7 @@ import { createReadStream as createReadStream2, createWriteStream as createWrite
|
|
|
18787
18869
|
import { readdir as readdir4, readFile as readFile7, stat as stat6, mkdir as mkdir4, unlink as unlink3, rename as rename2, rmdir } from "fs/promises";
|
|
18788
18870
|
import { realpathSync as realpathSync7 } from "fs";
|
|
18789
18871
|
import { randomUUID as randomUUID10 } from "crypto";
|
|
18790
|
-
import { basename as basename11, dirname as dirname13, join as
|
|
18872
|
+
import { basename as basename11, dirname as dirname13, join as join37, relative as relative5, resolve as resolve27, sep as sep8 } from "path";
|
|
18791
18873
|
import { Readable as Readable2 } from "stream";
|
|
18792
18874
|
|
|
18793
18875
|
// ../lib/graph-trash/src/index.ts
|
|
@@ -19105,7 +19187,7 @@ async function cascadeDeleteDocument(params) {
|
|
|
19105
19187
|
|
|
19106
19188
|
// app/lib/file-index.ts
|
|
19107
19189
|
import * as fsp from "fs/promises";
|
|
19108
|
-
import { resolve as resolve26, relative as relative4, join as
|
|
19190
|
+
import { resolve as resolve26, relative as relative4, join as join36, basename as basename10, extname as extname2, sep as sep7 } from "path";
|
|
19109
19191
|
import { tmpdir as tmpdir2 } from "os";
|
|
19110
19192
|
import { execFile as execFile2 } from "child_process";
|
|
19111
19193
|
import { promisify as promisify2 } from "util";
|
|
@@ -19187,7 +19269,7 @@ async function extractPdf(absolute) {
|
|
|
19187
19269
|
return stdout.trim();
|
|
19188
19270
|
}
|
|
19189
19271
|
async function ocrPdf(absolute) {
|
|
19190
|
-
const outPdf =
|
|
19272
|
+
const outPdf = join36(tmpdir2(), `file-index-ocr-${process.pid}-${Date.now()}.pdf`);
|
|
19191
19273
|
try {
|
|
19192
19274
|
await execFileAsync2(
|
|
19193
19275
|
"ocrmypdf",
|
|
@@ -19249,7 +19331,7 @@ async function readDisplayName(absolute) {
|
|
|
19249
19331
|
const stem = dot === -1 ? base : base.slice(0, dot);
|
|
19250
19332
|
if (base === `${stem}.meta.json`) return null;
|
|
19251
19333
|
try {
|
|
19252
|
-
const raw = await fsp.readFile(
|
|
19334
|
+
const raw = await fsp.readFile(join36(dir, `${stem}.meta.json`), "utf-8");
|
|
19253
19335
|
const meta = JSON.parse(raw);
|
|
19254
19336
|
const dn = meta.displayName ?? meta.filename;
|
|
19255
19337
|
return typeof dn === "string" && dn.length > 0 ? dn : null;
|
|
@@ -19270,7 +19352,7 @@ async function walkSubtree(root, dataRoot, out) {
|
|
|
19270
19352
|
for (const entry of entries2) {
|
|
19271
19353
|
if (entry.isSymbolicLink()) continue;
|
|
19272
19354
|
if (entry.isDirectory() && entry.name === ".uploads-tmp") continue;
|
|
19273
|
-
const abs =
|
|
19355
|
+
const abs = join36(root, entry.name);
|
|
19274
19356
|
if (entry.isDirectory()) {
|
|
19275
19357
|
const sub = await walkSubtree(abs, dataRoot, out);
|
|
19276
19358
|
if (!sub.clean) clean = false;
|
|
@@ -19643,7 +19725,7 @@ var UPLOAD_TMP_DIR = ".uploads-tmp";
|
|
|
19643
19725
|
var UUID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
19644
19726
|
async function readMeta(absDir, baseName) {
|
|
19645
19727
|
try {
|
|
19646
|
-
const raw = await readFile7(
|
|
19728
|
+
const raw = await readFile7(join37(absDir, `${baseName}.meta.json`), "utf8");
|
|
19647
19729
|
const parsed = JSON.parse(raw);
|
|
19648
19730
|
if (typeof parsed?.filename === "string") {
|
|
19649
19731
|
return { filename: parsed.filename, mimeType: typeof parsed.mimeType === "string" ? parsed.mimeType : void 0 };
|
|
@@ -19698,7 +19780,7 @@ async function servableFilesIn(dirAbs, uuid) {
|
|
|
19698
19780
|
}
|
|
19699
19781
|
async function enrich(absolute, entry, accountNames) {
|
|
19700
19782
|
if (entry.kind === "directory" && UUID_RE4.test(entry.name)) {
|
|
19701
|
-
const dirAbs =
|
|
19783
|
+
const dirAbs = join37(absolute, entry.name);
|
|
19702
19784
|
const meta = await readMeta(dirAbs, entry.name);
|
|
19703
19785
|
if (meta?.filename) {
|
|
19704
19786
|
const servable = await servableFilesIn(dirAbs, entry.name);
|
|
@@ -19707,7 +19789,7 @@ async function enrich(absolute, entry, accountNames) {
|
|
|
19707
19789
|
let size = null;
|
|
19708
19790
|
let modifiedAt = entry.modifiedAt;
|
|
19709
19791
|
try {
|
|
19710
|
-
const st = await stat6(
|
|
19792
|
+
const st = await stat6(join37(dirAbs, innerName));
|
|
19711
19793
|
size = st.size;
|
|
19712
19794
|
modifiedAt = st.mtime.toISOString();
|
|
19713
19795
|
} catch {
|
|
@@ -19900,7 +19982,7 @@ app23.get("/", requireAdminSession, async (c) => {
|
|
|
19900
19982
|
const childRel = relPath === "" || relPath === "." ? name : `${relPath}/${name}`;
|
|
19901
19983
|
const protectedEntry = isProtectedFromDeletion(childRel).protected;
|
|
19902
19984
|
try {
|
|
19903
|
-
const entryPath =
|
|
19985
|
+
const entryPath = join37(absolute, name);
|
|
19904
19986
|
const s = await stat6(entryPath);
|
|
19905
19987
|
entries2.push({
|
|
19906
19988
|
name,
|
|
@@ -19929,7 +20011,7 @@ app23.get("/", requireAdminSession, async (c) => {
|
|
|
19929
20011
|
const displayPath = buildDisplayPath(relPath, accountNames);
|
|
19930
20012
|
if (groupReq || isAccountRoot(relPath)) {
|
|
19931
20013
|
const acctId = relPath.split("/")[1] ?? accountId;
|
|
19932
|
-
const schemaMd = await readFile7(
|
|
20014
|
+
const schemaMd = await readFile7(join37(absolute, "SCHEMA.md"), "utf8").catch(() => null);
|
|
19933
20015
|
const groups = classifyAccountRoot(schemaMd, entries2.map((e) => e.name));
|
|
19934
20016
|
console.error(
|
|
19935
20017
|
`[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"}`
|
|
@@ -19967,7 +20049,7 @@ app23.get("/", requireAdminSession, async (c) => {
|
|
|
19967
20049
|
for (const name of homeDirs) {
|
|
19968
20050
|
const base = byName.get(name);
|
|
19969
20051
|
try {
|
|
19970
|
-
const dirents = await readdir4(
|
|
20052
|
+
const dirents = await readdir4(join37(absolute, name), { withFileTypes: true });
|
|
19971
20053
|
const visible = dirents.filter((d) => !d.name.startsWith("."));
|
|
19972
20054
|
visible.sort((a, b) => {
|
|
19973
20055
|
const ad = a.isDirectory() ? 0 : 1;
|
|
@@ -20032,7 +20114,7 @@ app23.get("/download", requireAdminSession, async (c) => {
|
|
|
20032
20114
|
console.error(`[data] op=scratchpad-no-session sessionId="${sessionId.slice(0, 8)}\u2026"`);
|
|
20033
20115
|
return c.json({ error: "Not found" }, 404);
|
|
20034
20116
|
}
|
|
20035
|
-
const meta = readSidecarMeta(
|
|
20117
|
+
const meta = readSidecarMeta(join37(projectDir, `${sessionId}.meta.json`));
|
|
20036
20118
|
if (!meta.accountId || meta.accountId !== accountId) {
|
|
20037
20119
|
console.error(`[data] account-scope-blocked root="scratchpad" sessionId="${sessionId.slice(0, 8)}\u2026" account=${accountId.slice(0, 8)}\u2026`);
|
|
20038
20120
|
return c.json({ error: "Not found" }, 404);
|
|
@@ -20127,7 +20209,7 @@ async function* walkRegularFiles(dirAbsolute) {
|
|
|
20127
20209
|
const dirents = await readdir4(dirAbsolute, { withFileTypes: true });
|
|
20128
20210
|
for (const d of dirents) {
|
|
20129
20211
|
if (d.isSymbolicLink()) continue;
|
|
20130
|
-
const child =
|
|
20212
|
+
const child = join37(dirAbsolute, d.name);
|
|
20131
20213
|
if (d.isDirectory()) {
|
|
20132
20214
|
yield* walkRegularFiles(child);
|
|
20133
20215
|
continue;
|
|
@@ -20237,7 +20319,7 @@ async function resolveUploadTarget(c, accountId, uid) {
|
|
|
20237
20319
|
const base = resolveOwnAccountWrite(rawDir, accountId, "POST /api/admin/files/upload");
|
|
20238
20320
|
if (!base.ok) return { ok: false, status: base.status, error: base.error };
|
|
20239
20321
|
const relDir = relpath ? dirname13(relpath) : ".";
|
|
20240
|
-
const destRel = relDir === "." ? base.relative :
|
|
20322
|
+
const destRel = relDir === "." ? base.relative : join37(base.relative, relDir);
|
|
20241
20323
|
if (crossesForeignAccountPartition(destRel, accountId)) {
|
|
20242
20324
|
console.error(`[data] account-scope-blocked endpoint="POST /api/admin/files/upload" path="${destRel}" account=${accountId.slice(0, 8)}\u2026`);
|
|
20243
20325
|
return { ok: false, status: 404, error: "Not found" };
|
|
@@ -20614,7 +20696,7 @@ app23.delete("/", requireAdminSession, async (c) => {
|
|
|
20614
20696
|
const dot = base.lastIndexOf(".");
|
|
20615
20697
|
const stem = dot === -1 ? base : base.slice(0, dot);
|
|
20616
20698
|
const containerDir = dirname13(absolute);
|
|
20617
|
-
const sidecarPath = UUID_RE4.test(stem) && base !== `${stem}.meta.json` ?
|
|
20699
|
+
const sidecarPath = UUID_RE4.test(stem) && base !== `${stem}.meta.json` ? join37(containerDir, `${stem}.meta.json`) : null;
|
|
20618
20700
|
const isAttachmentContainer = UUID_RE4.test(stem) && basename11(containerDir) === stem;
|
|
20619
20701
|
await unlink3(absolute);
|
|
20620
20702
|
if (sidecarPath) {
|
|
@@ -20624,7 +20706,7 @@ app23.delete("/", requireAdminSession, async (c) => {
|
|
|
20624
20706
|
}
|
|
20625
20707
|
}
|
|
20626
20708
|
if (isAttachmentContainer) {
|
|
20627
|
-
await unlink3(
|
|
20709
|
+
await unlink3(join37(containerDir, `${stem}${EXTRACTED_TEXT_SUFFIX}`)).catch(() => {
|
|
20628
20710
|
});
|
|
20629
20711
|
await rmdir(containerDir).catch(() => {
|
|
20630
20712
|
});
|
|
@@ -21734,7 +21816,7 @@ function isHiddenByDefault(label) {
|
|
|
21734
21816
|
// server/lib/top-level-labels.ts
|
|
21735
21817
|
var import_dist5 = __toESM(require_dist4(), 1);
|
|
21736
21818
|
import { readdirSync as readdirSync24, readFileSync as readFileSync36 } from "fs";
|
|
21737
|
-
import { join as
|
|
21819
|
+
import { join as join38, resolve as resolve28 } from "path";
|
|
21738
21820
|
var STATIC_TOP_LEVEL_LABELS = Object.freeze(
|
|
21739
21821
|
/* @__PURE__ */ new Set([
|
|
21740
21822
|
// Base-schema infra (schema-base.md has no top-level section).
|
|
@@ -21838,7 +21920,7 @@ function parseTopLevelLabels(content) {
|
|
|
21838
21920
|
}
|
|
21839
21921
|
function resolveReferencesDir() {
|
|
21840
21922
|
if (process.env.MAXY_PLATFORM_ROOT) {
|
|
21841
|
-
return
|
|
21923
|
+
return join38(process.env.MAXY_PLATFORM_ROOT, "plugins", "memory", "references");
|
|
21842
21924
|
}
|
|
21843
21925
|
return resolve28(import.meta.dirname, "../../../plugins/memory/references");
|
|
21844
21926
|
}
|
|
@@ -21848,7 +21930,7 @@ function parseTableTopLevelLabels(referencesDir) {
|
|
|
21848
21930
|
try {
|
|
21849
21931
|
const fileNames = readdirSync24(referencesDir).filter((f) => f.startsWith("schema-") && f.endsWith(".md")).sort();
|
|
21850
21932
|
for (const fileName of fileNames) {
|
|
21851
|
-
const content = readFileSync36(
|
|
21933
|
+
const content = readFileSync36(join38(referencesDir, fileName), "utf-8");
|
|
21852
21934
|
const parsed = parseTopLevelLabels(content);
|
|
21853
21935
|
if (parsed.length > 0) contributingFiles.push(fileName);
|
|
21854
21936
|
for (const label of parsed) labels.add(label);
|
|
@@ -23187,11 +23269,11 @@ var sidebar_artefacts_default = app30;
|
|
|
23187
23269
|
|
|
23188
23270
|
// server/channel-session-override.ts
|
|
23189
23271
|
import { readFileSync as readFileSync37, writeFileSync as writeFileSync14, renameSync as renameSync10 } from "fs";
|
|
23190
|
-
import { join as
|
|
23272
|
+
import { join as join39 } from "path";
|
|
23191
23273
|
var FILE2 = "channel-session-override.json";
|
|
23192
23274
|
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}$/;
|
|
23193
23275
|
function channelOverridePath(accountDir) {
|
|
23194
|
-
return
|
|
23276
|
+
return join39(accountDir, FILE2);
|
|
23195
23277
|
}
|
|
23196
23278
|
function senderKey(channel, senderId) {
|
|
23197
23279
|
return `${channel}:${senderId}`;
|
|
@@ -23587,24 +23669,24 @@ var session_rc_spawn_default = app36;
|
|
|
23587
23669
|
import { randomUUID as randomUUID12 } from "crypto";
|
|
23588
23670
|
|
|
23589
23671
|
// server/wa-descriptor.ts
|
|
23590
|
-
import { resolve as resolve30, join as
|
|
23672
|
+
import { resolve as resolve30, join as join40 } from "path";
|
|
23591
23673
|
function waGatewayUrl() {
|
|
23592
23674
|
return `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`;
|
|
23593
23675
|
}
|
|
23594
23676
|
function waServerPath() {
|
|
23595
|
-
return process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve30(process.env.MAXY_PLATFORM_ROOT ??
|
|
23677
|
+
return process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve30(process.env.MAXY_PLATFORM_ROOT ?? join40(__dirname, ".."), "services/whatsapp-channel/dist/server.js");
|
|
23596
23678
|
}
|
|
23597
23679
|
function waChannelDescriptor(senderId) {
|
|
23598
23680
|
return { senderId, gatewayUrl: waGatewayUrl(), serverPath: waServerPath() };
|
|
23599
23681
|
}
|
|
23600
23682
|
|
|
23601
23683
|
// server/telegram-descriptor.ts
|
|
23602
|
-
import { resolve as resolve31, join as
|
|
23684
|
+
import { resolve as resolve31, join as join41 } from "path";
|
|
23603
23685
|
function telegramGatewayUrl() {
|
|
23604
23686
|
return `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`;
|
|
23605
23687
|
}
|
|
23606
23688
|
function telegramServerPath() {
|
|
23607
|
-
return process.env.MAXY_TELEGRAM_CHANNEL_SERVER_PATH ?? resolve31(process.env.MAXY_PLATFORM_ROOT ??
|
|
23689
|
+
return process.env.MAXY_TELEGRAM_CHANNEL_SERVER_PATH ?? resolve31(process.env.MAXY_PLATFORM_ROOT ?? join41(__dirname, ".."), "services/telegram-channel/dist/server.js");
|
|
23608
23690
|
}
|
|
23609
23691
|
function telegramChannelDescriptor(senderId) {
|
|
23610
23692
|
return { senderId, gatewayUrl: telegramGatewayUrl(), serverPath: telegramServerPath() };
|
|
@@ -23889,10 +23971,10 @@ var system_stats_default = app38;
|
|
|
23889
23971
|
|
|
23890
23972
|
// server/routes/admin/health.ts
|
|
23891
23973
|
import { existsSync as existsSync37, readFileSync as readFileSync38 } from "fs";
|
|
23892
|
-
import { resolve as resolve32, join as
|
|
23974
|
+
import { resolve as resolve32, join as join42 } from "path";
|
|
23893
23975
|
var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve32(process.cwd(), "..");
|
|
23894
23976
|
var brandHostname = "maxy";
|
|
23895
|
-
var brandJsonPath =
|
|
23977
|
+
var brandJsonPath = join42(PLATFORM_ROOT6, "config", "brand.json");
|
|
23896
23978
|
if (existsSync37(brandJsonPath)) {
|
|
23897
23979
|
try {
|
|
23898
23980
|
const brand = JSON.parse(readFileSync38(brandJsonPath, "utf-8"));
|
|
@@ -24682,7 +24764,7 @@ var browser_default = app46;
|
|
|
24682
24764
|
|
|
24683
24765
|
// server/routes/admin/calendar.ts
|
|
24684
24766
|
import { existsSync as existsSync38 } from "fs";
|
|
24685
|
-
import { join as
|
|
24767
|
+
import { join as join44 } from "path";
|
|
24686
24768
|
|
|
24687
24769
|
// server/lib/calendar-ics.ts
|
|
24688
24770
|
var CRLF = "\r\n";
|
|
@@ -24782,7 +24864,7 @@ function countVEvents(ics) {
|
|
|
24782
24864
|
|
|
24783
24865
|
// server/lib/calendar-availability.ts
|
|
24784
24866
|
import { readFileSync as readFileSync39 } from "fs";
|
|
24785
|
-
import { join as
|
|
24867
|
+
import { join as join43 } from "path";
|
|
24786
24868
|
var AVAILABILITY_FILENAME = "calendar-availability.json";
|
|
24787
24869
|
var REQUIRED_KEYS = [
|
|
24788
24870
|
"timezone",
|
|
@@ -24791,7 +24873,7 @@ var REQUIRED_KEYS = [
|
|
|
24791
24873
|
"weekly"
|
|
24792
24874
|
];
|
|
24793
24875
|
function readAvailabilityConfig(accountDir) {
|
|
24794
|
-
const path3 =
|
|
24876
|
+
const path3 = join43(accountDir, AVAILABILITY_FILENAME);
|
|
24795
24877
|
let raw;
|
|
24796
24878
|
try {
|
|
24797
24879
|
raw = readFileSync39(path3, "utf-8");
|
|
@@ -25153,7 +25235,7 @@ app47.get("/booking-link", requireAdminSession, (c) => {
|
|
|
25153
25235
|
console.error('[calendar] op=booking-link-fail err="no account configured"');
|
|
25154
25236
|
return c.json({ bookingDomain: null });
|
|
25155
25237
|
}
|
|
25156
|
-
if (!existsSync38(
|
|
25238
|
+
if (!existsSync38(join44(account.accountDir, AVAILABILITY_FILENAME))) {
|
|
25157
25239
|
console.log("[calendar] op=booking-link bookingDomain=none source=availability-config");
|
|
25158
25240
|
return c.json({ bookingDomain: null });
|
|
25159
25241
|
}
|
|
@@ -26486,7 +26568,7 @@ app61.route("/request-magic-link", request_magic_link_default);
|
|
|
26486
26568
|
var access_default = app61;
|
|
26487
26569
|
|
|
26488
26570
|
// server/routes/sites.ts
|
|
26489
|
-
import { existsSync as existsSync41, readFileSync as readFileSync42, realpathSync as realpathSync8, statSync as
|
|
26571
|
+
import { existsSync as existsSync41, readFileSync as readFileSync42, realpathSync as realpathSync8, statSync as statSync19 } from "fs";
|
|
26490
26572
|
import { resolve as resolve36 } from "path";
|
|
26491
26573
|
var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
|
|
26492
26574
|
var MIME = {
|
|
@@ -26552,7 +26634,7 @@ app62.get("/:rel{.*}", (c) => {
|
|
|
26552
26634
|
}
|
|
26553
26635
|
let stat11;
|
|
26554
26636
|
try {
|
|
26555
|
-
stat11 = existsSync41(filePath) ?
|
|
26637
|
+
stat11 = existsSync41(filePath) ? statSync19(filePath) : null;
|
|
26556
26638
|
} catch {
|
|
26557
26639
|
stat11 = null;
|
|
26558
26640
|
}
|
|
@@ -26703,7 +26785,7 @@ var VISITOR_COOKIE_MAX_AGE_SECONDS = Math.floor(DEFAULT_TTL_MS / 1e3);
|
|
|
26703
26785
|
|
|
26704
26786
|
// app/lib/brand-config.ts
|
|
26705
26787
|
import { existsSync as existsSync42, readFileSync as readFileSync44 } from "fs";
|
|
26706
|
-
import { join as
|
|
26788
|
+
import { join as join45 } from "path";
|
|
26707
26789
|
var cached2 = null;
|
|
26708
26790
|
var cachedAttempted = false;
|
|
26709
26791
|
function readBrandConfig() {
|
|
@@ -26711,7 +26793,7 @@ function readBrandConfig() {
|
|
|
26711
26793
|
cachedAttempted = true;
|
|
26712
26794
|
const platformRoot5 = process.env.MAXY_PLATFORM_ROOT;
|
|
26713
26795
|
if (!platformRoot5) return null;
|
|
26714
|
-
const brandPath =
|
|
26796
|
+
const brandPath = join45(platformRoot5, "config", "brand.json");
|
|
26715
26797
|
if (!existsSync42(brandPath)) return null;
|
|
26716
26798
|
try {
|
|
26717
26799
|
cached2 = JSON.parse(readFileSync44(brandPath, "utf-8"));
|
|
@@ -27556,7 +27638,7 @@ var calendar_public_default = app67;
|
|
|
27556
27638
|
// server/routes/portal-fetch.ts
|
|
27557
27639
|
import { createReadStream as createReadStream3 } from "fs";
|
|
27558
27640
|
import { stat as stat8, readFile as readFile9, realpath } from "fs/promises";
|
|
27559
|
-
import { join as
|
|
27641
|
+
import { join as join46, resolve as resolve38, sep as sep10 } from "path";
|
|
27560
27642
|
import { Readable as Readable3 } from "stream";
|
|
27561
27643
|
var app68 = new Hono();
|
|
27562
27644
|
var TAG50 = "[portal-fetch]";
|
|
@@ -27629,7 +27711,7 @@ function isValidAccountId2(value) {
|
|
|
27629
27711
|
}
|
|
27630
27712
|
async function readExposeFolders2(accountDir) {
|
|
27631
27713
|
try {
|
|
27632
|
-
const cfg = JSON.parse(await readFile9(
|
|
27714
|
+
const cfg = JSON.parse(await readFile9(join46(accountDir, "data-portal.json"), "utf8"));
|
|
27633
27715
|
return Array.isArray(cfg?.exposeFolders) ? cfg.exposeFolders.filter((f) => typeof f === "string") : [];
|
|
27634
27716
|
} catch {
|
|
27635
27717
|
return [];
|
|
@@ -27638,7 +27720,7 @@ async function readExposeFolders2(accountDir) {
|
|
|
27638
27720
|
async function resolveFetchTarget(accountDir, relPath, ownerId) {
|
|
27639
27721
|
let schemaText = null;
|
|
27640
27722
|
try {
|
|
27641
|
-
schemaText = await readFile9(
|
|
27723
|
+
schemaText = await readFile9(join46(accountDir, "SCHEMA.md"), "utf8");
|
|
27642
27724
|
} catch {
|
|
27643
27725
|
schemaText = null;
|
|
27644
27726
|
}
|
|
@@ -27808,8 +27890,8 @@ function startTimeEntryCensus(openSession, opts = {}) {
|
|
|
27808
27890
|
}
|
|
27809
27891
|
|
|
27810
27892
|
// app/lib/ledger-census.ts
|
|
27811
|
-
import { readdirSync as readdirSync28, readFileSync as readFileSync45, statSync as
|
|
27812
|
-
import { join as
|
|
27893
|
+
import { readdirSync as readdirSync28, readFileSync as readFileSync45, statSync as statSync20 } from "fs";
|
|
27894
|
+
import { join as join47 } from "path";
|
|
27813
27895
|
|
|
27814
27896
|
// ../lib/ledger-core/dist/reconcile.js
|
|
27815
27897
|
var LEDGER_INDEX_NAMES = [
|
|
@@ -27863,9 +27945,9 @@ function countWriteRejects24h(logDir, now) {
|
|
|
27863
27945
|
}
|
|
27864
27946
|
let total = 0;
|
|
27865
27947
|
for (const name of entries2) {
|
|
27866
|
-
const path3 =
|
|
27948
|
+
const path3 = join47(logDir, name);
|
|
27867
27949
|
try {
|
|
27868
|
-
if (now -
|
|
27950
|
+
if (now - statSync20(path3).mtimeMs > DAY_MS) continue;
|
|
27869
27951
|
for (const line of readFileSync45(path3, "utf8").split("\n")) {
|
|
27870
27952
|
if (line.includes("[graph-write] reject")) total += 1;
|
|
27871
27953
|
}
|
|
@@ -28362,7 +28444,7 @@ async function migrateUploads(opts = {}) {
|
|
|
28362
28444
|
// app/lib/migrate-admin-webchat-sidecars.ts
|
|
28363
28445
|
import { readdir as readdir7, readFile as readFile10, rename as rename4, writeFile as writeFile5, unlink as unlink4 } from "fs/promises";
|
|
28364
28446
|
import { existsSync as existsSync44 } from "fs";
|
|
28365
|
-
import { join as
|
|
28447
|
+
import { join as join48 } from "path";
|
|
28366
28448
|
var ADMIN_ROLE2 = "admin";
|
|
28367
28449
|
var WEBCHAT_CHANNEL2 = "webchat";
|
|
28368
28450
|
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;
|
|
@@ -28407,7 +28489,7 @@ async function collectLiveSidecars(projectsRoot) {
|
|
|
28407
28489
|
}
|
|
28408
28490
|
for (const slug of slugs) {
|
|
28409
28491
|
if (!slug.isDirectory()) continue;
|
|
28410
|
-
const slugDir =
|
|
28492
|
+
const slugDir = join48(projectsRoot, slug.name);
|
|
28411
28493
|
let entries2;
|
|
28412
28494
|
try {
|
|
28413
28495
|
entries2 = await readdir7(slugDir, { withFileTypes: true });
|
|
@@ -28416,9 +28498,9 @@ async function collectLiveSidecars(projectsRoot) {
|
|
|
28416
28498
|
}
|
|
28417
28499
|
for (const entry of entries2) {
|
|
28418
28500
|
if (entry.isFile() && SESSION_META_RE.test(entry.name)) {
|
|
28419
|
-
out.push(
|
|
28501
|
+
out.push(join48(slugDir, entry.name));
|
|
28420
28502
|
} else if (entry.isDirectory() && entry.name === "subagents") {
|
|
28421
|
-
const subDir =
|
|
28503
|
+
const subDir = join48(slugDir, entry.name);
|
|
28422
28504
|
let subs;
|
|
28423
28505
|
try {
|
|
28424
28506
|
subs = await readdir7(subDir, { withFileTypes: true });
|
|
@@ -28426,7 +28508,7 @@ async function collectLiveSidecars(projectsRoot) {
|
|
|
28426
28508
|
continue;
|
|
28427
28509
|
}
|
|
28428
28510
|
for (const s of subs) {
|
|
28429
|
-
if (s.isFile() && SESSION_META_RE.test(s.name)) out.push(
|
|
28511
|
+
if (s.isFile() && SESSION_META_RE.test(s.name)) out.push(join48(subDir, s.name));
|
|
28430
28512
|
}
|
|
28431
28513
|
}
|
|
28432
28514
|
}
|
|
@@ -28438,7 +28520,7 @@ function shortId(path3) {
|
|
|
28438
28520
|
return base.slice(0, 8);
|
|
28439
28521
|
}
|
|
28440
28522
|
async function migrateAdminWebchatSidecars(opts = {}) {
|
|
28441
|
-
const projectsRoot = opts.projectsRoot ?? (process.env.CLAUDE_CONFIG_DIR ?
|
|
28523
|
+
const projectsRoot = opts.projectsRoot ?? (process.env.CLAUDE_CONFIG_DIR ? join48(process.env.CLAUDE_CONFIG_DIR, "projects") : null) ?? "";
|
|
28442
28524
|
const usersFile = opts.usersFile ?? USERS_FILE;
|
|
28443
28525
|
const accountId = opts.accountId ?? resolveAccount()?.accountId ?? null;
|
|
28444
28526
|
const resolveName = opts.resolveName ?? defaultResolveName;
|
|
@@ -31186,7 +31268,7 @@ function broadcastAdminShutdown(reason) {
|
|
|
31186
31268
|
|
|
31187
31269
|
// ../lib/entitlement/src/index.ts
|
|
31188
31270
|
import { createPublicKey, createHash as createHash7, verify as cryptoVerify } from "crypto";
|
|
31189
|
-
import { existsSync as existsSync46, readFileSync as readFileSync47, statSync as
|
|
31271
|
+
import { existsSync as existsSync46, readFileSync as readFileSync47, statSync as statSync21 } from "fs";
|
|
31190
31272
|
import { resolve as resolve44 } from "path";
|
|
31191
31273
|
|
|
31192
31274
|
// ../lib/entitlement/src/canonicalize.ts
|
|
@@ -31238,7 +31320,7 @@ function resolveEntitlement(brand, account) {
|
|
|
31238
31320
|
if (!existsSync46(entitlementPath)) {
|
|
31239
31321
|
return logResolved(anonymousFallback("missing"), { reason: "missing" });
|
|
31240
31322
|
}
|
|
31241
|
-
const stat11 =
|
|
31323
|
+
const stat11 = statSync21(entitlementPath);
|
|
31242
31324
|
const key = memoKey(stat11.mtimeMs, account);
|
|
31243
31325
|
if (memo && memo.key === key) {
|
|
31244
31326
|
return memo.result;
|
|
@@ -31426,7 +31508,7 @@ function clientFrom(c) {
|
|
|
31426
31508
|
}
|
|
31427
31509
|
installMediaDownloadGuard();
|
|
31428
31510
|
var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT || "";
|
|
31429
|
-
var BRAND_JSON_PATH = PLATFORM_ROOT8 ?
|
|
31511
|
+
var BRAND_JSON_PATH = PLATFORM_ROOT8 ? join49(PLATFORM_ROOT8, "config", "brand.json") : "";
|
|
31430
31512
|
var BRAND = { productName: "Maxy", hostname: "maxy", configDir: ".maxy", marketingUrl: "https://getmaxy.com" };
|
|
31431
31513
|
if (BRAND_JSON_PATH && !existsSync47(BRAND_JSON_PATH)) {
|
|
31432
31514
|
console.error(`[brand] WARNING: brand.json not found at ${BRAND_JSON_PATH} \u2014 using Maxy defaults`);
|
|
@@ -31465,7 +31547,7 @@ var brandLoginOpts = {
|
|
|
31465
31547
|
appleTouchIconPath: brandAppIcon512Path,
|
|
31466
31548
|
themeColor: BRAND.defaultColors?.primary
|
|
31467
31549
|
};
|
|
31468
|
-
var ALIAS_DOMAINS_PATH =
|
|
31550
|
+
var ALIAS_DOMAINS_PATH = join49(homedir4(), BRAND.configDir, "alias-domains.json");
|
|
31469
31551
|
function loadAliasDomains() {
|
|
31470
31552
|
try {
|
|
31471
31553
|
if (!existsSync47(ALIAS_DOMAINS_PATH)) return null;
|
|
@@ -31544,7 +31626,7 @@ var waGateway = new WaGateway({
|
|
|
31544
31626
|
fetchStandingRules: fetchAccountStandingRules,
|
|
31545
31627
|
resolveSessionOverride: (accountId, senderId) => resolveChannelOverride(accountId, "whatsapp", senderId),
|
|
31546
31628
|
gatewayUrl: `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`,
|
|
31547
|
-
serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve45(process.env.MAXY_PLATFORM_ROOT ??
|
|
31629
|
+
serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve45(process.env.MAXY_PLATFORM_ROOT ?? join49(__dirname, ".."), "services/whatsapp-channel/dist/server.js"),
|
|
31548
31630
|
// Task 751 / 1390 — file delivery on the native channel. `maxyAccountId` (the
|
|
31549
31631
|
// path-validation scope) is the sender's effective SESSION account, resolved
|
|
31550
31632
|
// once at the inbound gate and threaded here via the gateway's per-sender doc
|
|
@@ -31559,7 +31641,7 @@ var waGateway = new WaGateway({
|
|
|
31559
31641
|
caption,
|
|
31560
31642
|
accountId,
|
|
31561
31643
|
maxyAccountId,
|
|
31562
|
-
platformRoot: resolve45(process.env.MAXY_PLATFORM_ROOT ??
|
|
31644
|
+
platformRoot: resolve45(process.env.MAXY_PLATFORM_ROOT ?? join49(__dirname, ".."))
|
|
31563
31645
|
});
|
|
31564
31646
|
return result.ok ? { ok: true, messageId: result.messageId } : { ok: false, error: result.error };
|
|
31565
31647
|
},
|
|
@@ -31677,7 +31759,7 @@ function runDuplicateSenderAudit() {
|
|
|
31677
31759
|
try {
|
|
31678
31760
|
const configDir2 = process.env.CLAUDE_CONFIG_DIR;
|
|
31679
31761
|
if (!configDir2) return;
|
|
31680
|
-
const projectsRoot =
|
|
31762
|
+
const projectsRoot = join49(configDir2, "projects");
|
|
31681
31763
|
const records = [];
|
|
31682
31764
|
for (const { path: jsonlPath, isSubagent, archived } of enumerateJsonls(projectsRoot)) {
|
|
31683
31765
|
if (isSubagent || archived) continue;
|
|
@@ -32343,7 +32425,7 @@ var SW_SOURCE = (() => {
|
|
|
32343
32425
|
function readInstalledVersion() {
|
|
32344
32426
|
try {
|
|
32345
32427
|
if (!PLATFORM_ROOT8) return "unknown";
|
|
32346
|
-
const versionFile =
|
|
32428
|
+
const versionFile = join49(PLATFORM_ROOT8, "config", `.${BRAND.hostname}-version`);
|
|
32347
32429
|
if (!existsSync47(versionFile)) return "unknown";
|
|
32348
32430
|
const content = readFileSync48(versionFile, "utf-8").trim();
|
|
32349
32431
|
return content || "unknown";
|
|
@@ -32403,11 +32485,11 @@ ${clientErrorReporterScript}
|
|
|
32403
32485
|
return html;
|
|
32404
32486
|
}
|
|
32405
32487
|
function loadBrandingCache(agentSlug) {
|
|
32406
|
-
const configDir2 =
|
|
32488
|
+
const configDir2 = join49(homedir4(), BRAND.configDir);
|
|
32407
32489
|
try {
|
|
32408
32490
|
const accountId = getDefaultAccountId();
|
|
32409
32491
|
if (!accountId) return null;
|
|
32410
|
-
const cachePath =
|
|
32492
|
+
const cachePath = join49(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
|
|
32411
32493
|
if (!existsSync47(cachePath)) return null;
|
|
32412
32494
|
return JSON.parse(readFileSync48(cachePath, "utf-8"));
|
|
32413
32495
|
} catch {
|
|
@@ -32638,6 +32720,7 @@ if (brandFaviconPath !== "/favicon.ico") {
|
|
|
32638
32720
|
return c.redirect(brandFaviconPath, 302);
|
|
32639
32721
|
});
|
|
32640
32722
|
}
|
|
32723
|
+
app69.use("/*", staticCacheHeaders("./public"));
|
|
32641
32724
|
app69.use("/*", serveStatic({ root: "./public" }));
|
|
32642
32725
|
app69.all("*", (c) => {
|
|
32643
32726
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
@@ -32656,7 +32739,7 @@ var hostname = process.env.HOSTNAME ?? "127.0.0.1";
|
|
|
32656
32739
|
var httpServer = serve({ fetch: app69.fetch, port, hostname });
|
|
32657
32740
|
console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
32658
32741
|
{
|
|
32659
|
-
const reconcilePlatformRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
32742
|
+
const reconcilePlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join49(__dirname, "..");
|
|
32660
32743
|
const reconcileScript = resolve45(reconcilePlatformRoot, "plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js");
|
|
32661
32744
|
const runReconcile = (ctx) => {
|
|
32662
32745
|
if (!existsSync47(reconcileScript)) return;
|
|
@@ -32679,7 +32762,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
32679
32762
|
detached: true,
|
|
32680
32763
|
run: runReconcile
|
|
32681
32764
|
});
|
|
32682
|
-
const reconcileStatePath =
|
|
32765
|
+
const reconcileStatePath = join49(MAXY_DIR, "booking-reconcile-state.json");
|
|
32683
32766
|
registerLoop({
|
|
32684
32767
|
name: "calendar-reconcile-liveness",
|
|
32685
32768
|
intervalMs: 6e5,
|
|
@@ -32697,7 +32780,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
32697
32780
|
}
|
|
32698
32781
|
{
|
|
32699
32782
|
const DREAM_CYCLE_SWEEP_INTERVAL_MS = 36e5;
|
|
32700
|
-
const dreamPlatformRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
32783
|
+
const dreamPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join49(__dirname, "..");
|
|
32701
32784
|
const dreamSweepScript = resolve45(dreamPlatformRoot, "plugins/memory/mcp/dist/scripts/dream-cycle-sweep.js");
|
|
32702
32785
|
registerLoop({
|
|
32703
32786
|
name: "dream-cycle-sweep",
|
|
@@ -32721,7 +32804,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
32721
32804
|
});
|
|
32722
32805
|
}
|
|
32723
32806
|
{
|
|
32724
|
-
const outlookPlatformRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
32807
|
+
const outlookPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join49(__dirname, "..");
|
|
32725
32808
|
const outlookScript = resolve45(outlookPlatformRoot, "plugins/outlook/mcp/dist/scripts/complete-registration.js");
|
|
32726
32809
|
const OUTLOOK_COMPLETE_INTERVAL_MS = 3e4;
|
|
32727
32810
|
const runOutlookComplete = (ctx) => {
|
|
@@ -32747,7 +32830,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
32747
32830
|
});
|
|
32748
32831
|
}
|
|
32749
32832
|
{
|
|
32750
|
-
const auditRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
32833
|
+
const auditRoot = process.env.MAXY_PLATFORM_ROOT ?? join49(__dirname, "..");
|
|
32751
32834
|
const strandedAccountsDir = resolve45(auditRoot, "..", "data/accounts");
|
|
32752
32835
|
const STRANDED_AUDIT_INTERVAL_MS = 3e5;
|
|
32753
32836
|
const STRANDED_AGE_MS = 16 * 6e4;
|
|
@@ -32760,7 +32843,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
32760
32843
|
if (!STRANDED_UUID_RE.test(name)) continue;
|
|
32761
32844
|
const pendingPath2 = resolve45(strandedAccountsDir, name, "secrets/outlook/pending-devicecode.enc");
|
|
32762
32845
|
if (!existsSync47(pendingPath2)) continue;
|
|
32763
|
-
const ageMs2 = now -
|
|
32846
|
+
const ageMs2 = now - statSync22(pendingPath2).mtimeMs;
|
|
32764
32847
|
if (ageMs2 > STRANDED_AGE_MS) {
|
|
32765
32848
|
console.error(`[outlook-mcp] devicecode-stranded account=${name} ageSec=${Math.floor(ageMs2 / 1e3)}`);
|
|
32766
32849
|
}
|
|
@@ -32777,7 +32860,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
32777
32860
|
});
|
|
32778
32861
|
}
|
|
32779
32862
|
{
|
|
32780
|
-
const googleRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
32863
|
+
const googleRoot = process.env.MAXY_PLATFORM_ROOT ?? join49(__dirname, "..");
|
|
32781
32864
|
const googleAccountsDir = resolve45(googleRoot, "..", "data/accounts");
|
|
32782
32865
|
const GOOGLE_PENDING_AUDIT_INTERVAL_MS = 3e5;
|
|
32783
32866
|
const runGooglePendingAuditSafe = () => {
|
|
@@ -32821,7 +32904,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
32821
32904
|
});
|
|
32822
32905
|
}
|
|
32823
32906
|
{
|
|
32824
|
-
const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
32907
|
+
const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join49(__dirname, "..");
|
|
32825
32908
|
const STORAGE_AUDIT_INTERVAL_MS = 3e5;
|
|
32826
32909
|
const runStorageAuditSafe = () => runStorageAudit(auditPlatformRoot).catch((err) => {
|
|
32827
32910
|
console.error(`[storage-audit] error="${err.message}"`);
|
|
@@ -32867,7 +32950,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
32867
32950
|
});
|
|
32868
32951
|
}
|
|
32869
32952
|
{
|
|
32870
|
-
const publishPlatformRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
32953
|
+
const publishPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join49(__dirname, "..");
|
|
32871
32954
|
const publishScript = resolve45(publishPlatformRoot, "plugins/scheduling/mcp/dist/scripts/publish-availability.js");
|
|
32872
32955
|
const PUBLISH_INTERVAL_MS = 3e5;
|
|
32873
32956
|
const bookingAccounts = () => {
|
|
@@ -32944,7 +33027,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
32944
33027
|
startTimeEntryCensus(() => getSession());
|
|
32945
33028
|
startLedgerCensus(() => getSession());
|
|
32946
33029
|
{
|
|
32947
|
-
const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
33030
|
+
const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join49(__dirname, "..");
|
|
32948
33031
|
const auditScript = resolve45(auditPlatformRoot, "plugins/connector/mcp/dist/scripts/audit-connectors.js");
|
|
32949
33032
|
const auditLogDir = process.env.LOG_DIR ?? LOG_DIR;
|
|
32950
33033
|
const CONNECTOR_AUDIT_INTERVAL_MS = 3e5;
|
|
@@ -32989,19 +33072,17 @@ startAuthHealthHeartbeat();
|
|
|
32989
33072
|
{
|
|
32990
33073
|
const loopHist = monitorEventLoopDelay({ resolution: 50 });
|
|
32991
33074
|
loopHist.enable();
|
|
32992
|
-
const
|
|
33075
|
+
const LOUD_THRESHOLD_MS = 1e3;
|
|
32993
33076
|
const WINDOW_MS2 = 3e4;
|
|
32994
33077
|
registerLoop({
|
|
32995
33078
|
name: "event-loop-lag",
|
|
32996
33079
|
intervalMs: WINDOW_MS2,
|
|
32997
33080
|
run: () => {
|
|
32998
|
-
const
|
|
32999
|
-
const
|
|
33000
|
-
|
|
33001
|
-
|
|
33002
|
-
|
|
33003
|
-
}
|
|
33004
|
-
return `p99 ${Math.round(p99Ms)}ms, max ${Math.round(maxMs)}ms`;
|
|
33081
|
+
const w = readAndResetWindow(loopHist, WINDOW_MS2);
|
|
33082
|
+
const line = formatLagWindow(w);
|
|
33083
|
+
if (w.maxMs >= LOUD_THRESHOLD_MS) console.error(line);
|
|
33084
|
+
else console.log(line);
|
|
33085
|
+
return `p99 ${w.p99Ms}ms, max ${w.maxMs}ms`;
|
|
33005
33086
|
}
|
|
33006
33087
|
});
|
|
33007
33088
|
}
|
|
@@ -33254,7 +33335,7 @@ if (bootAccountConfig?.whatsapp) {
|
|
|
33254
33335
|
}
|
|
33255
33336
|
init({
|
|
33256
33337
|
configDir: configDirForWhatsApp,
|
|
33257
|
-
platformRoot: resolve45(process.env.MAXY_PLATFORM_ROOT ??
|
|
33338
|
+
platformRoot: resolve45(process.env.MAXY_PLATFORM_ROOT ?? join49(__dirname, "..")),
|
|
33258
33339
|
accountConfig: bootAccountConfig,
|
|
33259
33340
|
onMessage: async (msg) => {
|
|
33260
33341
|
if (isObserveAccount(msg.accountId)) {
|