@rubytech/create-maxy-code 0.1.614 → 0.1.615
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +5 -0
- package/payload/platform/plugins/browser/PLUGIN.md +1 -1
- package/payload/platform/scripts/__tests__/vnc-cdp-liveness.test.sh +270 -19
- package/payload/platform/scripts/vnc.sh +174 -71
- package/payload/server/server.js +413 -250
package/payload/server/server.js
CHANGED
|
@@ -3220,11 +3220,11 @@ var require_dist10 = __commonJS({
|
|
|
3220
3220
|
});
|
|
3221
3221
|
|
|
3222
3222
|
// server/index.ts
|
|
3223
|
-
import { readFileSync as
|
|
3223
|
+
import { readFileSync as readFileSync65, existsSync as existsSync64, watchFile, readdirSync as readdirSync39, statSync as statSync35 } from "fs";
|
|
3224
3224
|
import { spawn as spawn3 } from "child_process";
|
|
3225
3225
|
import { createHash as createHash8 } from "crypto";
|
|
3226
|
-
import { resolve as
|
|
3227
|
-
import { homedir as
|
|
3226
|
+
import { resolve as resolve56, join as join79, basename as basename20 } from "path";
|
|
3227
|
+
import { homedir as homedir6 } from "os";
|
|
3228
3228
|
|
|
3229
3229
|
// server/lib/route-cache-watchers.ts
|
|
3230
3230
|
import { watch } from "fs";
|
|
@@ -5660,20 +5660,20 @@ function buildX11Env(chromiumWrapperPath, transport = "vnc") {
|
|
|
5660
5660
|
|
|
5661
5661
|
// server/routes/health.ts
|
|
5662
5662
|
function checkPort(port2, timeoutMs = 500) {
|
|
5663
|
-
return new Promise((
|
|
5663
|
+
return new Promise((resolve57) => {
|
|
5664
5664
|
const socket = createConnection2(port2, "127.0.0.1");
|
|
5665
5665
|
socket.setTimeout(timeoutMs);
|
|
5666
5666
|
socket.once("connect", () => {
|
|
5667
5667
|
socket.destroy();
|
|
5668
|
-
|
|
5668
|
+
resolve57(true);
|
|
5669
5669
|
});
|
|
5670
5670
|
socket.once("error", () => {
|
|
5671
5671
|
socket.destroy();
|
|
5672
|
-
|
|
5672
|
+
resolve57(false);
|
|
5673
5673
|
});
|
|
5674
5674
|
socket.once("timeout", () => {
|
|
5675
5675
|
socket.destroy();
|
|
5676
|
-
|
|
5676
|
+
resolve57(false);
|
|
5677
5677
|
});
|
|
5678
5678
|
});
|
|
5679
5679
|
}
|
|
@@ -6590,11 +6590,11 @@ function findExistingJsonlForSessionId(claudeConfigDir2, sessionId) {
|
|
|
6590
6590
|
} catch {
|
|
6591
6591
|
return null;
|
|
6592
6592
|
}
|
|
6593
|
-
const
|
|
6593
|
+
const basename21 = `${sessionId}.jsonl`;
|
|
6594
6594
|
for (const slug of slugs) {
|
|
6595
|
-
const live = join9(projectsRoot, slug,
|
|
6595
|
+
const live = join9(projectsRoot, slug, basename21);
|
|
6596
6596
|
if (existsSync4(live)) return live;
|
|
6597
|
-
const archived = join9(projectsRoot, slug, "archive",
|
|
6597
|
+
const archived = join9(projectsRoot, slug, "archive", basename21);
|
|
6598
6598
|
if (existsSync4(archived)) return archived;
|
|
6599
6599
|
}
|
|
6600
6600
|
return null;
|
|
@@ -8082,7 +8082,7 @@ async function defaultResolve(accountId) {
|
|
|
8082
8082
|
return resolveSocket2(accountId);
|
|
8083
8083
|
}
|
|
8084
8084
|
async function fetchAvatar(accountId, jid, deps = {}) {
|
|
8085
|
-
const
|
|
8085
|
+
const resolve57 = deps.resolve;
|
|
8086
8086
|
const httpGet = deps.httpGet ?? defaultHttpGet;
|
|
8087
8087
|
const maxAgeMs = deps.maxAgeMs ?? DEFAULT_MAX_AGE_MS;
|
|
8088
8088
|
const cached3 = readAvatar(accountId, jid);
|
|
@@ -8092,7 +8092,7 @@ async function fetchAvatar(accountId, jid, deps = {}) {
|
|
|
8092
8092
|
return "fresh";
|
|
8093
8093
|
}
|
|
8094
8094
|
console.log(`${TAG10} op=cache jid=${jid} hit=false ageMs=${ageMs2}`);
|
|
8095
|
-
const res =
|
|
8095
|
+
const res = resolve57 ? resolve57(accountId) : await defaultResolve(accountId);
|
|
8096
8096
|
if (!res.ok) {
|
|
8097
8097
|
console.log(`${TAG10} op=no-socket jid=${jid} account=${accountId.slice(0, 8)} reason=${res.reason}`);
|
|
8098
8098
|
return "no-socket";
|
|
@@ -9867,8 +9867,8 @@ async function startLogin(opts) {
|
|
|
9867
9867
|
await clearAuth(authDir);
|
|
9868
9868
|
let resolveCode = null;
|
|
9869
9869
|
let rejectCode = null;
|
|
9870
|
-
const codePromise = new Promise((
|
|
9871
|
-
resolveCode =
|
|
9870
|
+
const codePromise = new Promise((resolve57, reject) => {
|
|
9871
|
+
resolveCode = resolve57;
|
|
9872
9872
|
rejectCode = reject;
|
|
9873
9873
|
});
|
|
9874
9874
|
const codeTimer = setTimeout(
|
|
@@ -23625,15 +23625,15 @@ function operatorRoleFor(config, userId) {
|
|
|
23625
23625
|
async function buildAccountOptionList(accounts, userId) {
|
|
23626
23626
|
const houseAccount = accounts.find((a) => a.config.role === "house");
|
|
23627
23627
|
console.log(`[admin-accounts] op=list count=${accounts.length} house=${houseAccount?.accountId ?? "none"}`);
|
|
23628
|
-
const
|
|
23628
|
+
const resolve57 = async (a) => {
|
|
23629
23629
|
const businessName = await fetchAccountName(a.accountId) || void 0;
|
|
23630
23630
|
return { accountId: a.accountId, businessName, role: operatorRoleFor(a.config, userId), isHouse: a.config.role === "house" };
|
|
23631
23631
|
};
|
|
23632
23632
|
const houseOptions = await Promise.all(
|
|
23633
|
-
accounts.filter((a) => a.config.role === "house").map(
|
|
23633
|
+
accounts.filter((a) => a.config.role === "house").map(resolve57)
|
|
23634
23634
|
);
|
|
23635
23635
|
const nonHouseOptions = await Promise.all(
|
|
23636
|
-
accounts.filter((a) => a.config.role !== "house").map(
|
|
23636
|
+
accounts.filter((a) => a.config.role !== "house").map(resolve57)
|
|
23637
23637
|
);
|
|
23638
23638
|
const sortKey = (o) => (o.businessName || o.accountId).toLowerCase();
|
|
23639
23639
|
nonHouseOptions.sort((x, y) => {
|
|
@@ -26562,18 +26562,18 @@ var ALLOWED_EVENTS = /* @__PURE__ */ new Set([
|
|
|
26562
26562
|
]);
|
|
26563
26563
|
var app27 = new Hono();
|
|
26564
26564
|
app27.post("/", async (c) => {
|
|
26565
|
-
const
|
|
26565
|
+
const TAG84 = "[admin:events]";
|
|
26566
26566
|
let body;
|
|
26567
26567
|
try {
|
|
26568
26568
|
body = await c.req.json();
|
|
26569
26569
|
} catch (err) {
|
|
26570
26570
|
const detail = err instanceof Error ? err.message : String(err);
|
|
26571
|
-
console.error(`${
|
|
26571
|
+
console.error(`${TAG84} reject reason=body-not-json detail=${detail}`);
|
|
26572
26572
|
return c.json({ ok: false, detail: "Request body was not valid JSON" }, 400);
|
|
26573
26573
|
}
|
|
26574
26574
|
const event = typeof body.event === "string" ? body.event : "";
|
|
26575
26575
|
if (!ALLOWED_EVENTS.has(event)) {
|
|
26576
|
-
console.error(`${
|
|
26576
|
+
console.error(`${TAG84} reject reason=event-not-allowed event=${JSON.stringify(event)}`);
|
|
26577
26577
|
return c.json({ ok: false, detail: `Event "${event}" is not allowed` }, 400);
|
|
26578
26578
|
}
|
|
26579
26579
|
const rawFields = body.fields && typeof body.fields === "object" ? body.fields : {};
|
|
@@ -38163,12 +38163,174 @@ function startSharedFolderCensus() {
|
|
|
38163
38163
|
});
|
|
38164
38164
|
}
|
|
38165
38165
|
|
|
38166
|
+
// app/lib/browser-orphan-census.ts
|
|
38167
|
+
import { readFileSync as readFileSync59, readdirSync as readdirSync34, statSync as statSync31, existsSync as existsSync56 } from "fs";
|
|
38168
|
+
import { join as join69, basename as basename18, dirname as dirname18, resolve as resolve48 } from "path";
|
|
38169
|
+
import { homedir as homedir4 } from "os";
|
|
38170
|
+
var TAG70 = "[browser-census]";
|
|
38171
|
+
var BROWSER_BINARIES = /* @__PURE__ */ new Set([
|
|
38172
|
+
"chrome",
|
|
38173
|
+
"chromium",
|
|
38174
|
+
"chromium-browser",
|
|
38175
|
+
"google-chrome",
|
|
38176
|
+
"google-chrome-stable"
|
|
38177
|
+
]);
|
|
38178
|
+
function readProcess(procRoot, pid) {
|
|
38179
|
+
try {
|
|
38180
|
+
const raw = readFileSync59(join69(procRoot, String(pid), "cmdline"), "utf8");
|
|
38181
|
+
const argv = raw.split("\0").filter((a) => a.length > 0);
|
|
38182
|
+
if (argv.length === 0) return null;
|
|
38183
|
+
const stat11 = readFileSync59(join69(procRoot, String(pid), "stat"), "utf8");
|
|
38184
|
+
const close = stat11.lastIndexOf(")");
|
|
38185
|
+
if (close === -1) return null;
|
|
38186
|
+
const after = stat11.slice(close + 1).trim().split(/\s+/);
|
|
38187
|
+
const ppid = Number(after[1]);
|
|
38188
|
+
if (!Number.isInteger(ppid)) return null;
|
|
38189
|
+
return { pid, ppid, argv, comm: stat11.slice(stat11.indexOf("(") + 1, close) };
|
|
38190
|
+
} catch {
|
|
38191
|
+
return null;
|
|
38192
|
+
}
|
|
38193
|
+
}
|
|
38194
|
+
function readProcSnapshot(procRoot) {
|
|
38195
|
+
let entries2;
|
|
38196
|
+
try {
|
|
38197
|
+
entries2 = readdirSync34(procRoot, { withFileTypes: true });
|
|
38198
|
+
} catch {
|
|
38199
|
+
return [];
|
|
38200
|
+
}
|
|
38201
|
+
const out = [];
|
|
38202
|
+
for (const e of entries2) {
|
|
38203
|
+
if (!e.isDirectory()) continue;
|
|
38204
|
+
const pid = Number(e.name);
|
|
38205
|
+
if (!Number.isInteger(pid) || pid <= 0) continue;
|
|
38206
|
+
const p = readProcess(procRoot, pid);
|
|
38207
|
+
if (p) out.push(p);
|
|
38208
|
+
}
|
|
38209
|
+
return out.sort((a, b) => a.pid - b.pid);
|
|
38210
|
+
}
|
|
38211
|
+
function userDataDir(argv) {
|
|
38212
|
+
const FLAG = "--user-data-dir";
|
|
38213
|
+
for (let i = 0; i < argv.length; i++) {
|
|
38214
|
+
if (argv[i].startsWith(FLAG + "=")) return argv[i].slice(FLAG.length + 1);
|
|
38215
|
+
if (argv[i] === FLAG && i + 1 < argv.length) return argv[i + 1];
|
|
38216
|
+
}
|
|
38217
|
+
return null;
|
|
38218
|
+
}
|
|
38219
|
+
function isTopLevelBrowser(argv) {
|
|
38220
|
+
if (argv.length === 0) return false;
|
|
38221
|
+
if (!BROWSER_BINARIES.has(basename18(argv[0]))) return false;
|
|
38222
|
+
return !argv.some((a) => a.startsWith("--type="));
|
|
38223
|
+
}
|
|
38224
|
+
function isBrandProfile(dir, home) {
|
|
38225
|
+
const path = resolve48(dir);
|
|
38226
|
+
if (basename18(path) !== "chromium-profile") return false;
|
|
38227
|
+
const parent = dirname18(path);
|
|
38228
|
+
if (dirname18(parent) !== resolve48(home)) return false;
|
|
38229
|
+
return basename18(parent).startsWith(".");
|
|
38230
|
+
}
|
|
38231
|
+
function isReparented(p, byPid) {
|
|
38232
|
+
if (p.ppid === 1) return true;
|
|
38233
|
+
const parent = byPid.get(p.ppid);
|
|
38234
|
+
if (!parent) return true;
|
|
38235
|
+
return parent.comm === "systemd" && parent.argv.includes("--user");
|
|
38236
|
+
}
|
|
38237
|
+
var PROFILE_PREFIXES = ["cdp-", "playwright"];
|
|
38238
|
+
function dirBytes(dir) {
|
|
38239
|
+
let total = 0;
|
|
38240
|
+
let entries2;
|
|
38241
|
+
try {
|
|
38242
|
+
entries2 = readdirSync34(dir, { withFileTypes: true });
|
|
38243
|
+
} catch {
|
|
38244
|
+
return total;
|
|
38245
|
+
}
|
|
38246
|
+
for (const e of entries2) {
|
|
38247
|
+
const p = join69(dir, e.name);
|
|
38248
|
+
if (e.isDirectory()) {
|
|
38249
|
+
total += dirBytes(p);
|
|
38250
|
+
} else if (e.isFile()) {
|
|
38251
|
+
try {
|
|
38252
|
+
total += statSync31(p).size;
|
|
38253
|
+
} catch {
|
|
38254
|
+
}
|
|
38255
|
+
}
|
|
38256
|
+
}
|
|
38257
|
+
return total;
|
|
38258
|
+
}
|
|
38259
|
+
function scanProfileDirs(tmpRoot, nowMs) {
|
|
38260
|
+
let entries2;
|
|
38261
|
+
try {
|
|
38262
|
+
entries2 = readdirSync34(tmpRoot, { withFileTypes: true });
|
|
38263
|
+
} catch {
|
|
38264
|
+
return { dirs: [], scanned: 0 };
|
|
38265
|
+
}
|
|
38266
|
+
const dirs = [];
|
|
38267
|
+
for (const e of entries2) {
|
|
38268
|
+
if (!e.isDirectory()) continue;
|
|
38269
|
+
if (!PROFILE_PREFIXES.some((p) => e.name.startsWith(p))) continue;
|
|
38270
|
+
const path = join69(tmpRoot, e.name);
|
|
38271
|
+
let ageSec;
|
|
38272
|
+
try {
|
|
38273
|
+
ageSec = Math.max(0, Math.floor((nowMs - statSync31(path).birthtimeMs) / 1e3));
|
|
38274
|
+
} catch {
|
|
38275
|
+
continue;
|
|
38276
|
+
}
|
|
38277
|
+
dirs.push({ name: e.name, path, ageSec, bytes: dirBytes(path) });
|
|
38278
|
+
}
|
|
38279
|
+
return { dirs, scanned: entries2.length };
|
|
38280
|
+
}
|
|
38281
|
+
function runBrowserOrphanCensus(deps) {
|
|
38282
|
+
const { procRoot, tmpRoot, home, nowMs } = deps;
|
|
38283
|
+
if (!existsSync56(procRoot)) {
|
|
38284
|
+
console.error(`${TAG70} op=browser-orphan-census unsupported=no-proc scanned=0`);
|
|
38285
|
+
return "no /proc \u2014 process census unavailable on this platform";
|
|
38286
|
+
}
|
|
38287
|
+
const procs = readProcSnapshot(procRoot);
|
|
38288
|
+
const byPid = new Map(procs.map((p) => [p.pid, p]));
|
|
38289
|
+
const browsers = procs.filter((p) => isTopLevelBrowser(p.argv));
|
|
38290
|
+
const foreign = browsers.filter((p) => {
|
|
38291
|
+
const dir = userDataDir(p.argv);
|
|
38292
|
+
return dir === null || !isBrandProfile(dir, home);
|
|
38293
|
+
});
|
|
38294
|
+
const reparented = foreign.filter((p) => isReparented(p, byPid));
|
|
38295
|
+
const ownerByDir = /* @__PURE__ */ new Map();
|
|
38296
|
+
for (const b of browsers) {
|
|
38297
|
+
const dir = userDataDir(b.argv);
|
|
38298
|
+
if (dir) ownerByDir.set(resolve48(dir), b);
|
|
38299
|
+
}
|
|
38300
|
+
const { dirs, scanned: tmpScanned } = scanProfileDirs(tmpRoot, nowMs);
|
|
38301
|
+
const dirBytesTotal = dirs.reduce((s, d) => s + d.bytes, 0);
|
|
38302
|
+
const oldestDirAgeSec = dirs.reduce((m, d) => Math.max(m, d.ageSec), 0);
|
|
38303
|
+
console.error(
|
|
38304
|
+
`${TAG70} op=browser-orphan-census scanned=${procs.length} chrome=${browsers.length} brandBound=${browsers.length - foreign.length} foreign=${foreign.length} reparented=${reparented.length} dirs=${dirs.length} dirBytes=${dirBytesTotal} oldestDirAgeSec=${oldestDirAgeSec} tmpScanned=${tmpScanned}`
|
|
38305
|
+
);
|
|
38306
|
+
for (const d of dirs) {
|
|
38307
|
+
const owner = ownerByDir.get(resolve48(d.path));
|
|
38308
|
+
console.error(
|
|
38309
|
+
`${TAG70} op=browser-orphan-profile dir=${d.name} ageSec=${d.ageSec} bytes=${d.bytes} owner=${owner ? owner.pid : "none"} ppid=${owner ? owner.ppid : "-"} parent=${owner ? byPid.get(owner.ppid)?.comm ?? "-" : "-"} reparented=${owner ? isReparented(owner, byPid) : "-"}`
|
|
38310
|
+
);
|
|
38311
|
+
}
|
|
38312
|
+
return `${foreign.length} foreign browser(s), ${dirs.length} profile dir(s), ${dirBytesTotal} bytes`;
|
|
38313
|
+
}
|
|
38314
|
+
function startBrowserOrphanCensus() {
|
|
38315
|
+
registerLoop({
|
|
38316
|
+
name: "browser-orphan-census",
|
|
38317
|
+
intervalMs: 60 * 60 * 1e3,
|
|
38318
|
+
firstRunDelayMs: 6e4,
|
|
38319
|
+
run: () => runBrowserOrphanCensus({
|
|
38320
|
+
procRoot: "/proc",
|
|
38321
|
+
tmpRoot: "/tmp",
|
|
38322
|
+
home: homedir4(),
|
|
38323
|
+
nowMs: Date.now()
|
|
38324
|
+
})
|
|
38325
|
+
});
|
|
38326
|
+
}
|
|
38327
|
+
|
|
38166
38328
|
// app/lib/accounts-state-census.ts
|
|
38167
|
-
var
|
|
38329
|
+
var TAG71 = "[accounts-state]";
|
|
38168
38330
|
function runAccountsStateCensus(accountsDir, nowMs) {
|
|
38169
38331
|
const { dirs, provisioning, abandoned } = censusAccountDirs(accountsDir, nowMs);
|
|
38170
38332
|
console.error(
|
|
38171
|
-
`${
|
|
38333
|
+
`${TAG71} op=stub-census dirs=${dirs} provisioning=${provisioning.length} abandoned=${abandoned.length} abandonedIds=${abandoned.length > 0 ? abandoned.join(",") : "none"}`
|
|
38172
38334
|
);
|
|
38173
38335
|
return `${dirs} account dir(s), ${abandoned.length} abandoned`;
|
|
38174
38336
|
}
|
|
@@ -38182,10 +38344,10 @@ function startAccountsStateCensus() {
|
|
|
38182
38344
|
}
|
|
38183
38345
|
|
|
38184
38346
|
// app/lib/cred-refresh-census.ts
|
|
38185
|
-
import { readdirSync as
|
|
38186
|
-
import { homedir as
|
|
38187
|
-
import { join as
|
|
38188
|
-
var
|
|
38347
|
+
import { readdirSync as readdirSync35, readFileSync as readFileSync60 } from "fs";
|
|
38348
|
+
import { homedir as homedir5 } from "os";
|
|
38349
|
+
import { join as join70 } from "path";
|
|
38350
|
+
var TAG72 = "[claude-auth]";
|
|
38189
38351
|
function refreshTokenLength(raw) {
|
|
38190
38352
|
let data;
|
|
38191
38353
|
try {
|
|
@@ -38200,7 +38362,7 @@ function refreshTokenLength(raw) {
|
|
|
38200
38362
|
function surveyBrandCredentials(home) {
|
|
38201
38363
|
let entries2;
|
|
38202
38364
|
try {
|
|
38203
|
-
entries2 =
|
|
38365
|
+
entries2 = readdirSync35(home);
|
|
38204
38366
|
} catch {
|
|
38205
38367
|
return [];
|
|
38206
38368
|
}
|
|
@@ -38209,7 +38371,7 @@ function surveyBrandCredentials(home) {
|
|
|
38209
38371
|
if (!entry3.startsWith(".")) continue;
|
|
38210
38372
|
let raw;
|
|
38211
38373
|
try {
|
|
38212
|
-
raw =
|
|
38374
|
+
raw = readFileSync60(join70(home, entry3, ".claude", ".credentials.json"), "utf-8");
|
|
38213
38375
|
} catch {
|
|
38214
38376
|
continue;
|
|
38215
38377
|
}
|
|
@@ -38224,12 +38386,12 @@ function censusResult(rows) {
|
|
|
38224
38386
|
if (rows.length === 0) return "no-brands-found";
|
|
38225
38387
|
return rows.some(isBlank) ? "blank-tokens" : "ok";
|
|
38226
38388
|
}
|
|
38227
|
-
function runCredRefreshCensus(home =
|
|
38389
|
+
function runCredRefreshCensus(home = homedir5()) {
|
|
38228
38390
|
const rows = surveyBrandCredentials(home);
|
|
38229
38391
|
const blank = rows.filter(isBlank).length;
|
|
38230
38392
|
const detail = rows.map((r) => `${r.brand}:${r.refreshTokenLen === null ? "unreadable" : r.refreshTokenLen}`).join(",");
|
|
38231
38393
|
console.log(
|
|
38232
|
-
`${
|
|
38394
|
+
`${TAG72} op=cred-refresh-census result=${censusResult(rows)} brands=${rows.length} blank=${blank} detail=${detail}`
|
|
38233
38395
|
);
|
|
38234
38396
|
return `${rows.length} brand(s), ${blank} blank`;
|
|
38235
38397
|
}
|
|
@@ -38244,7 +38406,7 @@ function startCredRefreshCensus() {
|
|
|
38244
38406
|
|
|
38245
38407
|
// app/lib/file-watcher.ts
|
|
38246
38408
|
import * as fsp2 from "fs/promises";
|
|
38247
|
-
import { resolve as
|
|
38409
|
+
import { resolve as resolve49, sep as sep12 } from "path";
|
|
38248
38410
|
var ACCOUNT_UUID_RE3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
38249
38411
|
var DEFAULT_COALESCE_MS = 500;
|
|
38250
38412
|
var ROOTS = ["accounts"];
|
|
@@ -38263,7 +38425,7 @@ async function startFileWatcher(opts = {}) {
|
|
|
38263
38425
|
const dropFn = opts.drop ?? dropFileIndex;
|
|
38264
38426
|
for (const r of ROOTS) {
|
|
38265
38427
|
try {
|
|
38266
|
-
await fsp2.mkdir(
|
|
38428
|
+
await fsp2.mkdir(resolve49(dataRoot, r), { recursive: true });
|
|
38267
38429
|
} catch (err) {
|
|
38268
38430
|
console.error(
|
|
38269
38431
|
`[file-watcher] start-failed root="${r}" err="${err.message}" \u2014 index will be maintained by the 5-min reconcile backstop only`
|
|
@@ -38284,7 +38446,7 @@ async function startFileWatcher(opts = {}) {
|
|
|
38284
38446
|
timers.set(relativePath, t);
|
|
38285
38447
|
}
|
|
38286
38448
|
async function runHook(relativePath, accountId) {
|
|
38287
|
-
const absolute =
|
|
38449
|
+
const absolute = resolve49(dataRoot, relativePath);
|
|
38288
38450
|
let exists = false;
|
|
38289
38451
|
try {
|
|
38290
38452
|
const st = await fsp2.stat(absolute);
|
|
@@ -38308,7 +38470,7 @@ async function startFileWatcher(opts = {}) {
|
|
|
38308
38470
|
}
|
|
38309
38471
|
}
|
|
38310
38472
|
async function watchRoot(rootName) {
|
|
38311
|
-
const absRoot =
|
|
38473
|
+
const absRoot = resolve49(dataRoot, rootName);
|
|
38312
38474
|
try {
|
|
38313
38475
|
const iter = fsp2.watch(absRoot, { recursive: true, signal: controller.signal });
|
|
38314
38476
|
for await (const event of iter) {
|
|
@@ -38347,7 +38509,7 @@ async function startFileWatcher(opts = {}) {
|
|
|
38347
38509
|
|
|
38348
38510
|
// app/lib/migrate-uploads.ts
|
|
38349
38511
|
import { mkdir as mkdir4, readdir as readdir6, rename as rename4, rm as rm3 } from "fs/promises";
|
|
38350
|
-
import { dirname as
|
|
38512
|
+
import { dirname as dirname19, relative as relative8, resolve as resolve50 } from "path";
|
|
38351
38513
|
var ACCOUNT_UUID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
38352
38514
|
async function walkFiles(dir) {
|
|
38353
38515
|
const out = [];
|
|
@@ -38358,7 +38520,7 @@ async function walkFiles(dir) {
|
|
|
38358
38520
|
return out;
|
|
38359
38521
|
}
|
|
38360
38522
|
for (const e of entries2) {
|
|
38361
|
-
const abs =
|
|
38523
|
+
const abs = resolve50(dir, e.name);
|
|
38362
38524
|
if (e.isDirectory()) {
|
|
38363
38525
|
out.push(...await walkFiles(abs));
|
|
38364
38526
|
} else if (e.isFile()) {
|
|
@@ -38378,8 +38540,8 @@ async function relocateTree(srcDir, destDir, dataRoot, accountId, session) {
|
|
|
38378
38540
|
let moved = 0;
|
|
38379
38541
|
for (const oldAbs of files) {
|
|
38380
38542
|
const suffix = relative8(srcDir, oldAbs);
|
|
38381
|
-
const newAbs =
|
|
38382
|
-
await mkdir4(
|
|
38543
|
+
const newAbs = resolve50(destDir, suffix);
|
|
38544
|
+
await mkdir4(dirname19(newAbs), { recursive: true });
|
|
38383
38545
|
await rename4(oldAbs, newAbs);
|
|
38384
38546
|
moved++;
|
|
38385
38547
|
const oldRel = relative8(dataRoot, oldAbs);
|
|
@@ -38405,7 +38567,7 @@ async function relocateTree(srcDir, destDir, dataRoot, accountId, session) {
|
|
|
38405
38567
|
}
|
|
38406
38568
|
async function migrateUploads(opts = {}) {
|
|
38407
38569
|
const dataRoot = opts.dataRoot ?? DATA_ROOT;
|
|
38408
|
-
const oldRoot =
|
|
38570
|
+
const oldRoot = resolve50(dataRoot, "uploads");
|
|
38409
38571
|
let topEntries;
|
|
38410
38572
|
try {
|
|
38411
38573
|
topEntries = await readdir6(oldRoot, { withFileTypes: true });
|
|
@@ -38426,8 +38588,8 @@ async function migrateUploads(opts = {}) {
|
|
|
38426
38588
|
const name = entry3.name;
|
|
38427
38589
|
if (ACCOUNT_UUID_RE4.test(name)) {
|
|
38428
38590
|
moved += await relocateTree(
|
|
38429
|
-
|
|
38430
|
-
|
|
38591
|
+
resolve50(oldRoot, name),
|
|
38592
|
+
resolve50(dataRoot, "accounts", name, "uploads"),
|
|
38431
38593
|
dataRoot,
|
|
38432
38594
|
name,
|
|
38433
38595
|
session
|
|
@@ -38439,8 +38601,8 @@ async function migrateUploads(opts = {}) {
|
|
|
38439
38601
|
continue;
|
|
38440
38602
|
}
|
|
38441
38603
|
moved += await relocateTree(
|
|
38442
|
-
|
|
38443
|
-
|
|
38604
|
+
resolve50(oldRoot, "public"),
|
|
38605
|
+
resolve50(dataRoot, "accounts", installAccountId, "uploads", "public"),
|
|
38444
38606
|
dataRoot,
|
|
38445
38607
|
null,
|
|
38446
38608
|
// public uploads carry no graph nodes
|
|
@@ -38470,8 +38632,8 @@ async function migrateUploads(opts = {}) {
|
|
|
38470
38632
|
|
|
38471
38633
|
// app/lib/migrate-admin-webchat-sidecars.ts
|
|
38472
38634
|
import { readdir as readdir7, readFile as readFile13, rename as rename5, writeFile as writeFile4, unlink as unlink4 } from "fs/promises";
|
|
38473
|
-
import { existsSync as
|
|
38474
|
-
import { join as
|
|
38635
|
+
import { existsSync as existsSync57 } from "fs";
|
|
38636
|
+
import { join as join71 } from "path";
|
|
38475
38637
|
var ADMIN_ROLE2 = "admin";
|
|
38476
38638
|
var WEBCHAT_CHANNEL2 = "webchat";
|
|
38477
38639
|
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;
|
|
@@ -38500,7 +38662,7 @@ async function writeRaw(path, obj) {
|
|
|
38500
38662
|
await rename5(tmp, path);
|
|
38501
38663
|
} catch (err) {
|
|
38502
38664
|
try {
|
|
38503
|
-
if (
|
|
38665
|
+
if (existsSync57(tmp)) await unlink4(tmp);
|
|
38504
38666
|
} catch {
|
|
38505
38667
|
}
|
|
38506
38668
|
throw err;
|
|
@@ -38516,7 +38678,7 @@ async function collectLiveSidecars(projectsRoot) {
|
|
|
38516
38678
|
}
|
|
38517
38679
|
for (const slug of slugs) {
|
|
38518
38680
|
if (!slug.isDirectory()) continue;
|
|
38519
|
-
const slugDir =
|
|
38681
|
+
const slugDir = join71(projectsRoot, slug.name);
|
|
38520
38682
|
let entries2;
|
|
38521
38683
|
try {
|
|
38522
38684
|
entries2 = await readdir7(slugDir, { withFileTypes: true });
|
|
@@ -38525,9 +38687,9 @@ async function collectLiveSidecars(projectsRoot) {
|
|
|
38525
38687
|
}
|
|
38526
38688
|
for (const entry3 of entries2) {
|
|
38527
38689
|
if (entry3.isFile() && SESSION_META_RE.test(entry3.name)) {
|
|
38528
|
-
out.push(
|
|
38690
|
+
out.push(join71(slugDir, entry3.name));
|
|
38529
38691
|
} else if (entry3.isDirectory() && entry3.name === "subagents") {
|
|
38530
|
-
const subDir =
|
|
38692
|
+
const subDir = join71(slugDir, entry3.name);
|
|
38531
38693
|
let subs;
|
|
38532
38694
|
try {
|
|
38533
38695
|
subs = await readdir7(subDir, { withFileTypes: true });
|
|
@@ -38535,7 +38697,7 @@ async function collectLiveSidecars(projectsRoot) {
|
|
|
38535
38697
|
continue;
|
|
38536
38698
|
}
|
|
38537
38699
|
for (const s of subs) {
|
|
38538
|
-
if (s.isFile() && SESSION_META_RE.test(s.name)) out.push(
|
|
38700
|
+
if (s.isFile() && SESSION_META_RE.test(s.name)) out.push(join71(subDir, s.name));
|
|
38539
38701
|
}
|
|
38540
38702
|
}
|
|
38541
38703
|
}
|
|
@@ -38547,7 +38709,7 @@ function shortId(path) {
|
|
|
38547
38709
|
return base.slice(0, 8);
|
|
38548
38710
|
}
|
|
38549
38711
|
async function migrateAdminWebchatSidecars(opts = {}) {
|
|
38550
|
-
const projectsRoot = opts.projectsRoot ?? (process.env.CLAUDE_CONFIG_DIR ?
|
|
38712
|
+
const projectsRoot = opts.projectsRoot ?? (process.env.CLAUDE_CONFIG_DIR ? join71(process.env.CLAUDE_CONFIG_DIR, "projects") : null) ?? "";
|
|
38551
38713
|
const usersFile = opts.usersFile ?? USERS_FILE;
|
|
38552
38714
|
const accountId = opts.accountId ?? resolveAccount()?.accountId ?? null;
|
|
38553
38715
|
const resolveName = opts.resolveName ?? defaultResolveName;
|
|
@@ -38623,8 +38785,8 @@ async function migrateAdminWebchatSidecars(opts = {}) {
|
|
|
38623
38785
|
|
|
38624
38786
|
// app/lib/migrate-sidecar-account-ids.ts
|
|
38625
38787
|
import { readdir as readdir8, readFile as readFile14, rename as rename6, writeFile as writeFile5, unlink as unlink5 } from "fs/promises";
|
|
38626
|
-
import { existsSync as
|
|
38627
|
-
import { join as
|
|
38788
|
+
import { existsSync as existsSync58 } from "fs";
|
|
38789
|
+
import { join as join72 } from "path";
|
|
38628
38790
|
var SESSION_META_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\.meta\.json$/i;
|
|
38629
38791
|
function projectSlugForCwd(cwd) {
|
|
38630
38792
|
return cwd.replace(/\//g, "-");
|
|
@@ -38650,7 +38812,7 @@ async function writeRaw2(path, obj) {
|
|
|
38650
38812
|
await rename6(tmp, path);
|
|
38651
38813
|
} catch (err) {
|
|
38652
38814
|
try {
|
|
38653
|
-
if (
|
|
38815
|
+
if (existsSync58(tmp)) await unlink5(tmp);
|
|
38654
38816
|
} catch {
|
|
38655
38817
|
}
|
|
38656
38818
|
throw err;
|
|
@@ -38670,7 +38832,7 @@ async function collectSidecars(projectsRoot) {
|
|
|
38670
38832
|
}
|
|
38671
38833
|
for (const slug of slugs) {
|
|
38672
38834
|
if (!slug.isDirectory()) continue;
|
|
38673
|
-
const slugDir =
|
|
38835
|
+
const slugDir = join72(projectsRoot, slug.name);
|
|
38674
38836
|
let entries2;
|
|
38675
38837
|
try {
|
|
38676
38838
|
entries2 = await readdir8(slugDir, { withFileTypes: true });
|
|
@@ -38679,9 +38841,9 @@ async function collectSidecars(projectsRoot) {
|
|
|
38679
38841
|
}
|
|
38680
38842
|
for (const entry3 of entries2) {
|
|
38681
38843
|
if (entry3.isFile() && SESSION_META_RE2.test(entry3.name)) {
|
|
38682
|
-
out.push({ path:
|
|
38844
|
+
out.push({ path: join72(slugDir, entry3.name), slug: slug.name });
|
|
38683
38845
|
} else if (entry3.isDirectory() && (entry3.name === "subagents" || entry3.name === "archive")) {
|
|
38684
|
-
const subDir =
|
|
38846
|
+
const subDir = join72(slugDir, entry3.name);
|
|
38685
38847
|
let subs;
|
|
38686
38848
|
try {
|
|
38687
38849
|
subs = await readdir8(subDir, { withFileTypes: true });
|
|
@@ -38690,7 +38852,7 @@ async function collectSidecars(projectsRoot) {
|
|
|
38690
38852
|
}
|
|
38691
38853
|
for (const s of subs) {
|
|
38692
38854
|
if (s.isFile() && SESSION_META_RE2.test(s.name)) {
|
|
38693
|
-
out.push({ path:
|
|
38855
|
+
out.push({ path: join72(subDir, s.name), slug: slug.name });
|
|
38694
38856
|
}
|
|
38695
38857
|
}
|
|
38696
38858
|
}
|
|
@@ -38699,7 +38861,7 @@ async function collectSidecars(projectsRoot) {
|
|
|
38699
38861
|
return out;
|
|
38700
38862
|
}
|
|
38701
38863
|
async function migrateSidecarAccountIds(opts = {}) {
|
|
38702
|
-
const projectsRoot = opts.projectsRoot ?? (process.env.CLAUDE_CONFIG_DIR ?
|
|
38864
|
+
const projectsRoot = opts.projectsRoot ?? (process.env.CLAUDE_CONFIG_DIR ? join72(process.env.CLAUDE_CONFIG_DIR, "projects") : null) ?? "";
|
|
38703
38865
|
const accounts = opts.accounts ?? listValidAccounts();
|
|
38704
38866
|
const result = {
|
|
38705
38867
|
scanned: 0,
|
|
@@ -40322,8 +40484,8 @@ function createWebchatChannelRoutes(deps) {
|
|
|
40322
40484
|
}
|
|
40323
40485
|
|
|
40324
40486
|
// app/lib/webchat/gateway/resolve-turn-answer.ts
|
|
40325
|
-
import { existsSync as
|
|
40326
|
-
import { join as
|
|
40487
|
+
import { existsSync as existsSync59, openSync as openSync10, readSync as readSync9, closeSync as closeSync10, readdirSync as readdirSync36 } from "fs";
|
|
40488
|
+
import { join as join73 } from "path";
|
|
40327
40489
|
|
|
40328
40490
|
// app/lib/channel-delivery/outbound-guard.ts
|
|
40329
40491
|
var INTERNAL_LEAK_PATTERNS = [
|
|
@@ -40384,16 +40546,16 @@ function resolveTurnAnswer(p) {
|
|
|
40384
40546
|
return segmentText(guardOutbound(p.senderId, parts.join("\n\n"))).join("\n\n");
|
|
40385
40547
|
}
|
|
40386
40548
|
function findJsonl(projectsRoot, sessionId) {
|
|
40387
|
-
if (!
|
|
40549
|
+
if (!existsSync59(projectsRoot)) return null;
|
|
40388
40550
|
let slugs;
|
|
40389
40551
|
try {
|
|
40390
|
-
slugs =
|
|
40552
|
+
slugs = readdirSync36(projectsRoot, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
40391
40553
|
} catch {
|
|
40392
40554
|
return null;
|
|
40393
40555
|
}
|
|
40394
40556
|
for (const slug of slugs) {
|
|
40395
|
-
const live =
|
|
40396
|
-
if (
|
|
40557
|
+
const live = join73(projectsRoot, slug, `${sessionId}.jsonl`);
|
|
40558
|
+
if (existsSync59(live)) return live;
|
|
40397
40559
|
}
|
|
40398
40560
|
return null;
|
|
40399
40561
|
}
|
|
@@ -40460,16 +40622,16 @@ var WebchatGateway = class _WebchatGateway {
|
|
|
40460
40622
|
* The public /api/chat route awaits this to return the reply on the same SSE
|
|
40461
40623
|
* response, preserving the pre-756 POST→single-blob browser contract. */
|
|
40462
40624
|
awaitReply(key2, timeoutMs) {
|
|
40463
|
-
return new Promise((
|
|
40625
|
+
return new Promise((resolve57) => {
|
|
40464
40626
|
const timer = setTimeout(() => {
|
|
40465
40627
|
this.replyAwaiters.delete(key2);
|
|
40466
|
-
|
|
40628
|
+
resolve57({ timeout: true });
|
|
40467
40629
|
}, timeoutMs);
|
|
40468
40630
|
if (timer.unref) timer.unref();
|
|
40469
40631
|
this.replyAwaiters.set(key2, (r) => {
|
|
40470
40632
|
clearTimeout(timer);
|
|
40471
40633
|
this.replyAwaiters.delete(key2);
|
|
40472
|
-
|
|
40634
|
+
resolve57(r);
|
|
40473
40635
|
});
|
|
40474
40636
|
});
|
|
40475
40637
|
}
|
|
@@ -40480,11 +40642,11 @@ var WebchatGateway = class _WebchatGateway {
|
|
|
40480
40642
|
* terminal dialog stays answerable). */
|
|
40481
40643
|
awaitPermissionVerdict(p, timeoutMs) {
|
|
40482
40644
|
const k = _WebchatGateway.promptKey(p.key, p.requestId);
|
|
40483
|
-
return new Promise((
|
|
40645
|
+
return new Promise((resolve57) => {
|
|
40484
40646
|
this.pendingPrompts.get(k)?.resolve({ timeout: true });
|
|
40485
40647
|
const timer = setTimeout(() => {
|
|
40486
40648
|
this.pendingPrompts.delete(k);
|
|
40487
|
-
|
|
40649
|
+
resolve57({ timeout: true });
|
|
40488
40650
|
}, timeoutMs);
|
|
40489
40651
|
if (timer.unref) timer.unref();
|
|
40490
40652
|
this.pendingPrompts.set(k, {
|
|
@@ -40494,7 +40656,7 @@ var WebchatGateway = class _WebchatGateway {
|
|
|
40494
40656
|
clearTimeout(timer);
|
|
40495
40657
|
this.pendingPrompts.delete(k);
|
|
40496
40658
|
this.deps.onPointerChange?.(p.key);
|
|
40497
|
-
|
|
40659
|
+
resolve57(r);
|
|
40498
40660
|
}
|
|
40499
40661
|
});
|
|
40500
40662
|
console.error(`[webchat:perm] op=open key=${keyDisplay(p.key)} id=${p.requestId} tool=${p.toolName}`);
|
|
@@ -41339,7 +41501,7 @@ function parityCensusLines() {
|
|
|
41339
41501
|
|
|
41340
41502
|
// app/lib/webchat/file-delivery.ts
|
|
41341
41503
|
import { realpathSync as realpathSync9 } from "fs";
|
|
41342
|
-
import { resolve as
|
|
41504
|
+
import { resolve as resolve51 } from "path";
|
|
41343
41505
|
|
|
41344
41506
|
// app/lib/channel-pty-bridge/file-delivery.ts
|
|
41345
41507
|
var SEND_USER_FILE = "SendUserFile";
|
|
@@ -41430,29 +41592,29 @@ function makeFileDelivery(opts) {
|
|
|
41430
41592
|
}
|
|
41431
41593
|
|
|
41432
41594
|
// app/lib/webchat/file-delivery.ts
|
|
41433
|
-
var
|
|
41595
|
+
var TAG73 = "[webchat-adaptor]";
|
|
41434
41596
|
function platformRoot2() {
|
|
41435
41597
|
return process.env.MAXY_PLATFORM_ROOT || "";
|
|
41436
41598
|
}
|
|
41437
41599
|
function makeWebchatSendFile(entry3) {
|
|
41438
41600
|
return async (filePath) => {
|
|
41439
41601
|
if (!entry3.accountId) {
|
|
41440
|
-
console.error(`${
|
|
41602
|
+
console.error(`${TAG73} file-delivery reject reason=no-account sender=${entry3.senderId}`);
|
|
41441
41603
|
return { ok: false, error: "no-account" };
|
|
41442
41604
|
}
|
|
41443
|
-
const accountDir =
|
|
41605
|
+
const accountDir = resolve51(platformRoot2(), "..", "data/accounts", entry3.accountId);
|
|
41444
41606
|
try {
|
|
41445
41607
|
const resolved = realpathSync9(filePath);
|
|
41446
41608
|
const accountResolved = realpathSync9(accountDir);
|
|
41447
41609
|
if (!resolved.startsWith(accountResolved + "/")) {
|
|
41448
|
-
console.error(`${
|
|
41610
|
+
console.error(`${TAG73} file-delivery reject reason=outside_account_directory sender=${entry3.senderId}`);
|
|
41449
41611
|
return { ok: false, error: "outside-account" };
|
|
41450
41612
|
}
|
|
41451
41613
|
return { ok: true };
|
|
41452
41614
|
} catch (err) {
|
|
41453
41615
|
const code = err.code;
|
|
41454
41616
|
console.error(
|
|
41455
|
-
`${
|
|
41617
|
+
`${TAG73} file-delivery reject reason=${code === "ENOENT" ? "not-found" : "path-error"} sender=${entry3.senderId}`
|
|
41456
41618
|
);
|
|
41457
41619
|
return { ok: false, error: code === "ENOENT" ? "not-found" : "path-error" };
|
|
41458
41620
|
}
|
|
@@ -41461,7 +41623,7 @@ function makeWebchatSendFile(entry3) {
|
|
|
41461
41623
|
function makeWebchatFileDelivery(entry3) {
|
|
41462
41624
|
return makeFileDelivery({
|
|
41463
41625
|
entry: entry3,
|
|
41464
|
-
tag:
|
|
41626
|
+
tag: TAG73,
|
|
41465
41627
|
channel: "webchat",
|
|
41466
41628
|
sendFile: makeWebchatSendFile(entry3),
|
|
41467
41629
|
deferUntilVerdict: true
|
|
@@ -41540,7 +41702,7 @@ function buildPublicWebchatSpawnRequest(input) {
|
|
|
41540
41702
|
}
|
|
41541
41703
|
|
|
41542
41704
|
// app/lib/whatsapp/inbound/file-delivery-bridge.ts
|
|
41543
|
-
var
|
|
41705
|
+
var TAG74 = "[whatsapp-adaptor]";
|
|
41544
41706
|
var SEND_USER_FILE2 = "SendUserFile";
|
|
41545
41707
|
var WHATSAPP_SEND_DOCUMENT = "whatsapp-send-document";
|
|
41546
41708
|
function platformRoot3() {
|
|
@@ -41558,7 +41720,7 @@ function makeWhatsAppSendFile(entry3, maxyAccountId) {
|
|
|
41558
41720
|
});
|
|
41559
41721
|
if (result.ok) return { ok: true };
|
|
41560
41722
|
console.error(
|
|
41561
|
-
`${
|
|
41723
|
+
`${TAG74} file-delivery reject reason=send-failed sender=${entry3.senderId} status=${result.status} message=${result.error}`
|
|
41562
41724
|
);
|
|
41563
41725
|
return { ok: false, error: result.error };
|
|
41564
41726
|
};
|
|
@@ -41566,7 +41728,7 @@ function makeWhatsAppSendFile(entry3, maxyAccountId) {
|
|
|
41566
41728
|
function makeWhatsAppFileDelivery(entry3, maxyAccountId) {
|
|
41567
41729
|
const shared = makeFileDelivery({
|
|
41568
41730
|
entry: entry3,
|
|
41569
|
-
tag:
|
|
41731
|
+
tag: TAG74,
|
|
41570
41732
|
channel: "whatsapp",
|
|
41571
41733
|
sendFile: makeWhatsAppSendFile(entry3, maxyAccountId)
|
|
41572
41734
|
});
|
|
@@ -41601,7 +41763,7 @@ function makeWhatsAppFileDelivery(entry3, maxyAccountId) {
|
|
|
41601
41763
|
if (!delivered) {
|
|
41602
41764
|
const fileField = call2.filePath !== void 0 ? ` file=${call2.filePath}` : "";
|
|
41603
41765
|
console.error(
|
|
41604
|
-
`${
|
|
41766
|
+
`${TAG74} file-delivery-unreconciled sender=${entry3.senderId} sessionId=${sid} tool=${WHATSAPP_SEND_DOCUMENT}${fileField}`
|
|
41605
41767
|
);
|
|
41606
41768
|
}
|
|
41607
41769
|
}
|
|
@@ -41767,7 +41929,7 @@ function whatsappDoorLabel(doorId) {
|
|
|
41767
41929
|
}
|
|
41768
41930
|
|
|
41769
41931
|
// app/lib/channel-delivery/refusal-notice.ts
|
|
41770
|
-
var
|
|
41932
|
+
var TAG75 = "[channel-delivery]";
|
|
41771
41933
|
var notified = /* @__PURE__ */ new Set();
|
|
41772
41934
|
function refusalNoticeText(reason) {
|
|
41773
41935
|
return reason === "claude-auth-dead" ? "Your message arrived but no assistant could be started: the Claude sign-in on this install is not active. An operator has to sign in again; send this again once they have." : `Your message arrived but no assistant could be started (${reason}). Nothing was lost; try again shortly.`;
|
|
@@ -41776,19 +41938,19 @@ async function sendRefusalNotice(input) {
|
|
|
41776
41938
|
if (notified.has(input.doorId)) return;
|
|
41777
41939
|
const fields2 = `channel=${input.channel} sender=${input.sender} reason=${input.reason}`;
|
|
41778
41940
|
if (!input.send) {
|
|
41779
|
-
console.error(`${
|
|
41941
|
+
console.error(`${TAG75} op=refusal-notice-failed ${fields2} error=no-target`);
|
|
41780
41942
|
return;
|
|
41781
41943
|
}
|
|
41782
41944
|
try {
|
|
41783
41945
|
await input.send(guardOutbound(input.sender, refusalNoticeText(input.reason)));
|
|
41784
41946
|
} catch (e) {
|
|
41785
41947
|
console.error(
|
|
41786
|
-
`${
|
|
41948
|
+
`${TAG75} op=refusal-notice-failed ${fields2} error=${e instanceof Error ? e.message : String(e)}`
|
|
41787
41949
|
);
|
|
41788
41950
|
return;
|
|
41789
41951
|
}
|
|
41790
41952
|
notified.add(input.doorId);
|
|
41791
|
-
console.error(`${
|
|
41953
|
+
console.error(`${TAG75} op=refusal-notice ${fields2} status=${input.status}`);
|
|
41792
41954
|
}
|
|
41793
41955
|
function clearRefusalNotice(doorId) {
|
|
41794
41956
|
notified.delete(doorId);
|
|
@@ -42498,10 +42660,10 @@ function buildTelegramSpawnRequest(input) {
|
|
|
42498
42660
|
}
|
|
42499
42661
|
|
|
42500
42662
|
// server/telegram-ensure-session.ts
|
|
42501
|
-
var
|
|
42663
|
+
var TAG76 = "[telegram-inbound]";
|
|
42502
42664
|
function reportReused(botId, channelKey, result) {
|
|
42503
42665
|
if (!result.reused) return;
|
|
42504
|
-
console.error(`${
|
|
42666
|
+
console.error(`${TAG76} op=spawn-reused botId=${botId} key=${channelKey} sessionId=${result.sessionId}`);
|
|
42505
42667
|
}
|
|
42506
42668
|
function buildTelegramEnsureSession(deps) {
|
|
42507
42669
|
return async (input) => {
|
|
@@ -42565,10 +42727,10 @@ function buildTelegramEnsureSession(deps) {
|
|
|
42565
42727
|
return;
|
|
42566
42728
|
}
|
|
42567
42729
|
console.error(
|
|
42568
|
-
`${
|
|
42730
|
+
`${TAG76} op=telegram-spawn-door botId=${input.botId} role=specialist door=rc specialist=${input.specialist}`
|
|
42569
42731
|
);
|
|
42570
42732
|
console.error(
|
|
42571
|
-
`${
|
|
42733
|
+
`${TAG76} op=spawn botId=${input.botId} sessionId=${req.sessionId} targetAccountId=${input.accountId} role=specialist specialist=${input.specialist}`
|
|
42572
42734
|
);
|
|
42573
42735
|
reportReused(input.botId, req.channelKey, result2);
|
|
42574
42736
|
noteSpawnOk2(input.botId);
|
|
@@ -42603,10 +42765,10 @@ function buildTelegramEnsureSession(deps) {
|
|
|
42603
42765
|
return;
|
|
42604
42766
|
}
|
|
42605
42767
|
console.error(
|
|
42606
|
-
`${
|
|
42768
|
+
`${TAG76} op=telegram-spawn-door botId=${input.botId} role=public door=rc agent=${input.agentSlug}`
|
|
42607
42769
|
);
|
|
42608
42770
|
console.error(
|
|
42609
|
-
`${
|
|
42771
|
+
`${TAG76} op=spawn botId=${input.botId} sessionId=${result2.sessionId} targetAccountId=${input.accountId} role=public`
|
|
42610
42772
|
);
|
|
42611
42773
|
reportReused(input.botId, req.channelKey, result2);
|
|
42612
42774
|
noteSpawnOk2(input.botId);
|
|
@@ -42630,7 +42792,7 @@ function buildTelegramEnsureSession(deps) {
|
|
|
42630
42792
|
return;
|
|
42631
42793
|
}
|
|
42632
42794
|
console.error(
|
|
42633
|
-
`${
|
|
42795
|
+
`${TAG76} op=spawn botId=${input.botId} sessionId=${req.sessionId} targetAccountId=${input.accountId} role=admin`
|
|
42634
42796
|
);
|
|
42635
42797
|
reportReused(input.botId, req.channelKey, result);
|
|
42636
42798
|
noteSpawnOk2(input.botId);
|
|
@@ -42648,8 +42810,8 @@ function buildTelegramEnsureSession(deps) {
|
|
|
42648
42810
|
// app/lib/telegram/outbound/send-document.ts
|
|
42649
42811
|
import { realpathSync as realpathSync10 } from "fs";
|
|
42650
42812
|
import { readFile as readFile15, stat as stat10 } from "fs/promises";
|
|
42651
|
-
import { resolve as
|
|
42652
|
-
var
|
|
42813
|
+
import { resolve as resolve52, basename as basename19 } from "path";
|
|
42814
|
+
var TAG77 = "[telegram:outbound]";
|
|
42653
42815
|
var TELEGRAM_DOCUMENT_MAX_BYTES = 50 * 1024 * 1024;
|
|
42654
42816
|
async function sendTelegramDocument(input) {
|
|
42655
42817
|
const { botToken, chatId, filePath, caption, maxyAccountId, platformRoot: platformRoot5 } = input;
|
|
@@ -42659,17 +42821,17 @@ async function sendTelegramDocument(input) {
|
|
|
42659
42821
|
if (!maxyAccountId || !platformRoot5) {
|
|
42660
42822
|
return { ok: false, status: 400, error: "Cannot validate file path: missing account or platform context" };
|
|
42661
42823
|
}
|
|
42662
|
-
const accountDir =
|
|
42824
|
+
const accountDir = resolve52(platformRoot5, "..", "data/accounts", maxyAccountId);
|
|
42663
42825
|
let accountResolved;
|
|
42664
42826
|
try {
|
|
42665
42827
|
accountResolved = realpathSync10(accountDir);
|
|
42666
42828
|
} catch (err) {
|
|
42667
42829
|
const code = err.code;
|
|
42668
42830
|
if (code === "ENOENT") {
|
|
42669
|
-
console.error(`${
|
|
42831
|
+
console.error(`${TAG77} document ENOENT scope=account-dir accountDir=${accountDir} maxyAccountId=${maxyAccountId}`);
|
|
42670
42832
|
return { ok: false, status: 500, error: `Account directory not resolvable for ${maxyAccountId}` };
|
|
42671
42833
|
}
|
|
42672
|
-
console.error(`${
|
|
42834
|
+
console.error(`${TAG77} document path error scope=account-dir maxyAccountId=${maxyAccountId}: ${String(err)}`);
|
|
42673
42835
|
return { ok: false, status: 500, error: String(err) };
|
|
42674
42836
|
}
|
|
42675
42837
|
let resolvedPath;
|
|
@@ -42678,14 +42840,14 @@ async function sendTelegramDocument(input) {
|
|
|
42678
42840
|
} catch (err) {
|
|
42679
42841
|
const code = err.code;
|
|
42680
42842
|
if (code === "ENOENT") {
|
|
42681
|
-
console.error(`${
|
|
42843
|
+
console.error(`${TAG77} document ENOENT scope=file path=${filePath} maxyAccountId=${maxyAccountId}`);
|
|
42682
42844
|
return { ok: false, status: 404, error: `File not found: ${filePath}` };
|
|
42683
42845
|
}
|
|
42684
|
-
console.error(`${
|
|
42846
|
+
console.error(`${TAG77} document path error scope=file maxyAccountId=${maxyAccountId}: ${String(err)}`);
|
|
42685
42847
|
return { ok: false, status: 500, error: String(err) };
|
|
42686
42848
|
}
|
|
42687
42849
|
if (!resolvedPath.startsWith(accountResolved + "/")) {
|
|
42688
|
-
console.error(`${
|
|
42850
|
+
console.error(`${TAG77} document REJECTED reason=outside_account_directory maxyAccountId=${maxyAccountId}`);
|
|
42689
42851
|
return { ok: false, status: 403, error: "Access denied: file is outside the account directory" };
|
|
42690
42852
|
}
|
|
42691
42853
|
const fileStat = await stat10(resolvedPath);
|
|
@@ -42696,7 +42858,7 @@ async function sendTelegramDocument(input) {
|
|
|
42696
42858
|
error: `File exceeds 50 MB limit (${(fileStat.size / 1024 / 1024).toFixed(1)} MB)`
|
|
42697
42859
|
};
|
|
42698
42860
|
}
|
|
42699
|
-
const filename =
|
|
42861
|
+
const filename = basename19(resolvedPath);
|
|
42700
42862
|
const buffer = Buffer.from(await readFile15(resolvedPath));
|
|
42701
42863
|
const form = new FormData();
|
|
42702
42864
|
form.append("chat_id", String(chatId));
|
|
@@ -42718,24 +42880,24 @@ async function sendTelegramDocument(input) {
|
|
|
42718
42880
|
error = e instanceof Error ? e.message : String(e);
|
|
42719
42881
|
}
|
|
42720
42882
|
console.error(
|
|
42721
|
-
`${
|
|
42883
|
+
`${TAG77} sent document to=${chatId} file=${filename} bytes=${fileStat.size} ok=${ok2}` + (messageId !== void 0 ? ` id=${messageId}` : "")
|
|
42722
42884
|
);
|
|
42723
42885
|
return ok2 ? { ok: true, messageId } : { ok: false, status: 500, error };
|
|
42724
42886
|
}
|
|
42725
42887
|
|
|
42726
42888
|
// app/lib/telegram/outbound/file-delivery.ts
|
|
42727
|
-
var
|
|
42889
|
+
var TAG78 = "[telegram:outbound]";
|
|
42728
42890
|
function platformRoot4() {
|
|
42729
42891
|
return process.env.MAXY_PLATFORM_ROOT || "";
|
|
42730
42892
|
}
|
|
42731
42893
|
function makeTelegramSendFile(entry3, botToken) {
|
|
42732
42894
|
return async (filePath, caption) => {
|
|
42733
42895
|
if (!botToken) {
|
|
42734
|
-
console.error(`${
|
|
42896
|
+
console.error(`${TAG78} file-delivery reject reason=no-bot-token sender=${entry3.senderId} role=${entry3.role}`);
|
|
42735
42897
|
return { ok: false, error: "no-bot-token" };
|
|
42736
42898
|
}
|
|
42737
42899
|
if (entry3.replyTarget == null) {
|
|
42738
|
-
console.error(`${
|
|
42900
|
+
console.error(`${TAG78} file-delivery reject reason=no-reply-target sender=${entry3.senderId} role=${entry3.role}`);
|
|
42739
42901
|
return { ok: false, error: "no-reply-target" };
|
|
42740
42902
|
}
|
|
42741
42903
|
const result = await sendTelegramDocument({
|
|
@@ -42752,7 +42914,7 @@ function makeTelegramSendFile(entry3, botToken) {
|
|
|
42752
42914
|
function makeTelegramFileDelivery(entry3, botToken) {
|
|
42753
42915
|
return makeFileDelivery({
|
|
42754
42916
|
entry: entry3,
|
|
42755
|
-
tag:
|
|
42917
|
+
tag: TAG78,
|
|
42756
42918
|
channel: "telegram",
|
|
42757
42919
|
sendFile: makeTelegramSendFile(entry3, botToken)
|
|
42758
42920
|
});
|
|
@@ -42982,15 +43144,15 @@ function startTelegramNativeFileFollower(input) {
|
|
|
42982
43144
|
}
|
|
42983
43145
|
|
|
42984
43146
|
// server/telegram-background-active.ts
|
|
42985
|
-
import { join as
|
|
42986
|
-
import { readdirSync as
|
|
43147
|
+
import { join as join74, resolve as resolve53 } from "path";
|
|
43148
|
+
import { readdirSync as readdirSync37, statSync as statSync32 } from "fs";
|
|
42987
43149
|
var SUBAGENT_STALE_WINDOW_MS = 6e4;
|
|
42988
43150
|
var AGENT_JSONL_RE2 = /^agent-([0-9a-f]+)\.jsonl$/;
|
|
42989
43151
|
function makeBackgroundActive(sessionId, deps = {}) {
|
|
42990
43152
|
const findProjectDir = deps.findProjectDir ?? findSessionProjectDir;
|
|
42991
|
-
const readDir = deps.readDir ?? ((d) =>
|
|
43153
|
+
const readDir = deps.readDir ?? ((d) => readdirSync37(d));
|
|
42992
43154
|
const statFile = deps.statFile ?? ((p) => {
|
|
42993
|
-
const st =
|
|
43155
|
+
const st = statSync32(p);
|
|
42994
43156
|
return { size: st.size, mtimeMs: st.mtimeMs };
|
|
42995
43157
|
});
|
|
42996
43158
|
const now = deps.now ?? (() => Date.now());
|
|
@@ -43001,7 +43163,7 @@ function makeBackgroundActive(sessionId, deps = {}) {
|
|
|
43001
43163
|
if (subagentsDir === null) {
|
|
43002
43164
|
const projectDir = findProjectDir(sessionId);
|
|
43003
43165
|
if (projectDir === null) return false;
|
|
43004
|
-
subagentsDir =
|
|
43166
|
+
subagentsDir = resolve53(join74(projectDir, sessionId, "subagents"));
|
|
43005
43167
|
}
|
|
43006
43168
|
let names;
|
|
43007
43169
|
try {
|
|
@@ -43015,7 +43177,7 @@ function makeBackgroundActive(sessionId, deps = {}) {
|
|
|
43015
43177
|
let size;
|
|
43016
43178
|
let mtimeMs;
|
|
43017
43179
|
try {
|
|
43018
|
-
const st = statFile(
|
|
43180
|
+
const st = statFile(join74(subagentsDir, name));
|
|
43019
43181
|
size = st.size;
|
|
43020
43182
|
mtimeMs = st.mtimeMs;
|
|
43021
43183
|
} catch {
|
|
@@ -43095,7 +43257,7 @@ function adminFanTargets(p) {
|
|
|
43095
43257
|
|
|
43096
43258
|
// app/lib/channel-pty-bridge/public-session-end-review.ts
|
|
43097
43259
|
import { randomUUID as randomUUID15 } from "crypto";
|
|
43098
|
-
var
|
|
43260
|
+
var TAG79 = "[public-session-review]";
|
|
43099
43261
|
var CONSUMED_CAP = 500;
|
|
43100
43262
|
var consumed = /* @__PURE__ */ new Set();
|
|
43101
43263
|
function consumeOnce(sessionId) {
|
|
@@ -43122,7 +43284,7 @@ async function fetchJsonl(sessionId) {
|
|
|
43122
43284
|
return await res.text();
|
|
43123
43285
|
} catch (err) {
|
|
43124
43286
|
console.error(
|
|
43125
|
-
`${
|
|
43287
|
+
`${TAG79} jsonl-fetch-failed sessionId=${sessionId} err="${err instanceof Error ? err.message : String(err)}"`
|
|
43126
43288
|
);
|
|
43127
43289
|
return null;
|
|
43128
43290
|
}
|
|
@@ -43146,7 +43308,7 @@ async function fetchPriorWrites(sliceToken, accountId) {
|
|
|
43146
43308
|
const res = await fetch(url);
|
|
43147
43309
|
if (!res.ok) {
|
|
43148
43310
|
console.error(
|
|
43149
|
-
`${
|
|
43311
|
+
`${TAG79} prior-writes-fetch-failed sliceToken=${sliceToken.slice(0, 8)} status=${res.status}`
|
|
43150
43312
|
);
|
|
43151
43313
|
return [];
|
|
43152
43314
|
}
|
|
@@ -43154,7 +43316,7 @@ async function fetchPriorWrites(sliceToken, accountId) {
|
|
|
43154
43316
|
return Array.isArray(body.writes) ? body.writes : [];
|
|
43155
43317
|
} catch (err) {
|
|
43156
43318
|
console.error(
|
|
43157
|
-
`${
|
|
43319
|
+
`${TAG79} prior-writes-fetch-threw sliceToken=${sliceToken.slice(0, 8)} err="${err instanceof Error ? err.message : String(err)}"`
|
|
43158
43320
|
);
|
|
43159
43321
|
return [];
|
|
43160
43322
|
}
|
|
@@ -43183,7 +43345,7 @@ function composeInitialMessage(input) {
|
|
|
43183
43345
|
}
|
|
43184
43346
|
async function dispatchReviewer(input, initialMessage) {
|
|
43185
43347
|
const sessionId = randomUUID15();
|
|
43186
|
-
console.log(`${
|
|
43348
|
+
console.log(`${TAG79} route target=rc-spawn sessionId=${sessionId.slice(0, 8)} sourceSession=${input.sessionId.slice(0, 8)}`);
|
|
43187
43349
|
const spawned = await managerRcSpawn({
|
|
43188
43350
|
sessionId,
|
|
43189
43351
|
initialMessage,
|
|
@@ -43207,21 +43369,21 @@ async function firePublicSessionEndReview(input) {
|
|
|
43207
43369
|
const dispatchedAt = Date.now();
|
|
43208
43370
|
if (consumed.has(input.sessionId)) {
|
|
43209
43371
|
console.log(
|
|
43210
|
-
`${
|
|
43372
|
+
`${TAG79} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-already-reviewed`
|
|
43211
43373
|
);
|
|
43212
43374
|
return;
|
|
43213
43375
|
}
|
|
43214
43376
|
const jsonl = await fetchJsonl(input.sessionId);
|
|
43215
43377
|
if (!jsonl) {
|
|
43216
43378
|
console.log(
|
|
43217
|
-
`${
|
|
43379
|
+
`${TAG79} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-jsonl-missing`
|
|
43218
43380
|
);
|
|
43219
43381
|
return;
|
|
43220
43382
|
}
|
|
43221
43383
|
const operatorTurns = countOperatorTurns(jsonl);
|
|
43222
43384
|
if (operatorTurns === 0) {
|
|
43223
43385
|
console.log(
|
|
43224
|
-
`${
|
|
43386
|
+
`${TAG79} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-no-turns`
|
|
43225
43387
|
);
|
|
43226
43388
|
return;
|
|
43227
43389
|
}
|
|
@@ -43235,19 +43397,19 @@ async function firePublicSessionEndReview(input) {
|
|
|
43235
43397
|
});
|
|
43236
43398
|
if (!consumeOnce(input.sessionId)) {
|
|
43237
43399
|
console.log(
|
|
43238
|
-
`${
|
|
43400
|
+
`${TAG79} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-already-reviewed`
|
|
43239
43401
|
);
|
|
43240
43402
|
return;
|
|
43241
43403
|
}
|
|
43242
43404
|
const dispatched = await dispatchReviewer(input, initialMessage);
|
|
43243
43405
|
if (!dispatched.ok) {
|
|
43244
43406
|
console.error(
|
|
43245
|
-
`${
|
|
43407
|
+
`${TAG79} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-spawn-failed reason=${dispatched.reason}`
|
|
43246
43408
|
);
|
|
43247
43409
|
return;
|
|
43248
43410
|
}
|
|
43249
43411
|
console.log(
|
|
43250
|
-
`${
|
|
43412
|
+
`${TAG79} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=dispatched managerSessionId=${dispatched.managerSessionId} operatorTurns=${operatorTurns} priorWrites=${priorWrites.length} ms=${Date.now() - dispatchedAt}`
|
|
43251
43413
|
);
|
|
43252
43414
|
}
|
|
43253
43415
|
|
|
@@ -43381,8 +43543,8 @@ function runPublicAddressCollisionAudit(deps) {
|
|
|
43381
43543
|
}
|
|
43382
43544
|
|
|
43383
43545
|
// server/telegram-audit.ts
|
|
43384
|
-
import { statSync as
|
|
43385
|
-
import { join as
|
|
43546
|
+
import { statSync as statSync33 } from "fs";
|
|
43547
|
+
import { join as join75 } from "path";
|
|
43386
43548
|
function buildTelegramAuditLines(input) {
|
|
43387
43549
|
const lines = [];
|
|
43388
43550
|
const entries2 = input.accounts.flatMap(
|
|
@@ -43490,19 +43652,19 @@ function countTelegramSessionsForAccount(accountId) {
|
|
|
43490
43652
|
function* walkTelegramSidecars() {
|
|
43491
43653
|
const cfg = claudeConfigDir();
|
|
43492
43654
|
if (!cfg) return;
|
|
43493
|
-
const projectsRoot =
|
|
43655
|
+
const projectsRoot = join75(cfg, "projects");
|
|
43494
43656
|
for (const { path } of enumerateSessionSidecars(projectsRoot)) {
|
|
43495
43657
|
const meta = readSidecarMeta(path);
|
|
43496
43658
|
if (meta.channel !== "telegram" || !meta.accountId) continue;
|
|
43497
43659
|
let spawnMs;
|
|
43498
43660
|
try {
|
|
43499
|
-
spawnMs =
|
|
43661
|
+
spawnMs = statSync33(path).mtimeMs;
|
|
43500
43662
|
} catch {
|
|
43501
43663
|
continue;
|
|
43502
43664
|
}
|
|
43503
43665
|
let turnMs;
|
|
43504
43666
|
try {
|
|
43505
|
-
turnMs =
|
|
43667
|
+
turnMs = statSync33(path.replace(/\.meta\.json$/, ".jsonl")).mtimeMs;
|
|
43506
43668
|
} catch {
|
|
43507
43669
|
turnMs = null;
|
|
43508
43670
|
}
|
|
@@ -43516,10 +43678,10 @@ function* walkTelegramSidecars() {
|
|
|
43516
43678
|
}
|
|
43517
43679
|
|
|
43518
43680
|
// server/telegram-group-census.ts
|
|
43519
|
-
var
|
|
43681
|
+
var TAG80 = "[telegram-audit]";
|
|
43520
43682
|
var PRESENT_STATUSES = /* @__PURE__ */ new Set(["member", "administrator", "creator"]);
|
|
43521
43683
|
function buildGroupCensusLine(c) {
|
|
43522
|
-
return `${
|
|
43684
|
+
return `${TAG80} op=group-census bots=${c.bots} groups=${c.groups} present=${c.present} absent=${c.absent} privacyOff=${c.privacyOff}`;
|
|
43523
43685
|
}
|
|
43524
43686
|
async function runTelegramGroupCensus(accounts, deps) {
|
|
43525
43687
|
const counts = { bots: 0, groups: 0, present: 0, absent: 0, privacyOff: 0 };
|
|
@@ -43550,10 +43712,10 @@ async function runTelegramGroupCensus(accounts, deps) {
|
|
|
43550
43712
|
}
|
|
43551
43713
|
|
|
43552
43714
|
// server/telegram-channel-census.ts
|
|
43553
|
-
var
|
|
43715
|
+
var TAG81 = "[telegram-audit]";
|
|
43554
43716
|
var ADMIN_STATUSES = /* @__PURE__ */ new Set(["administrator", "creator"]);
|
|
43555
43717
|
function buildChannelCensusLine(c) {
|
|
43556
|
-
return `${
|
|
43718
|
+
return `${TAG81} op=channel-census bots=${c.bots} channels=${c.channels} admin=${c.admin} notAdmin=${c.notAdmin} noPostRight=${c.noPostRight}`;
|
|
43557
43719
|
}
|
|
43558
43720
|
async function runTelegramChannelCensus(accounts, deps) {
|
|
43559
43721
|
const counts = { bots: 0, channels: 0, admin: 0, notAdmin: 0, noPostRight: 0 };
|
|
@@ -43585,7 +43747,7 @@ async function runTelegramChannelCensus(accounts, deps) {
|
|
|
43585
43747
|
}
|
|
43586
43748
|
|
|
43587
43749
|
// server/telegram-graph-duplicate-census.ts
|
|
43588
|
-
var
|
|
43750
|
+
var TAG82 = "[telegram-audit]";
|
|
43589
43751
|
var DUPLICATE_QUERY = `
|
|
43590
43752
|
MATCH (m:Message)
|
|
43591
43753
|
WHERE m.accountId = $accountId AND m.channel = 'telegram'
|
|
@@ -43612,12 +43774,12 @@ async function runTelegramGraphDuplicateCensus(accountIds, deps) {
|
|
|
43612
43774
|
const sessions4 = asSessions(Array.isArray(row.sessions) ? row.sessions : []);
|
|
43613
43775
|
const named = sessions4.length > 0 ? ` ids=${sessions4.join(",")}` : "";
|
|
43614
43776
|
lines.push(
|
|
43615
|
-
`${
|
|
43777
|
+
`${TAG82} op=graph-duplicate accountId=${accountId} messages=${messages} sessions=${sessions4.length}${named}`
|
|
43616
43778
|
);
|
|
43617
43779
|
} catch (err) {
|
|
43618
43780
|
const reason = err instanceof Error ? err.message : String(err);
|
|
43619
43781
|
lines.push(
|
|
43620
|
-
`${
|
|
43782
|
+
`${TAG82} FAIL op=graph-duplicate accountId=${accountId} reason=${reason.slice(0, 100)}`
|
|
43621
43783
|
);
|
|
43622
43784
|
}
|
|
43623
43785
|
}
|
|
@@ -43625,9 +43787,9 @@ async function runTelegramGraphDuplicateCensus(accountIds, deps) {
|
|
|
43625
43787
|
}
|
|
43626
43788
|
|
|
43627
43789
|
// server/telegram-identity-census.ts
|
|
43628
|
-
var
|
|
43790
|
+
var TAG83 = "[telegram-audit]";
|
|
43629
43791
|
function buildIdentityCensusLine(c) {
|
|
43630
|
-
return `${
|
|
43792
|
+
return `${TAG83} op=identity-census bots=${c.bots} ids=${c.ids} bound=${c.bound} unbound=${c.unbound} ambiguous=${c.ambiguous}`;
|
|
43631
43793
|
}
|
|
43632
43794
|
async function runTelegramIdentityCensus(accounts, deps) {
|
|
43633
43795
|
const counts = { bots: 0, ids: 0, bound: 0, unbound: 0, ambiguous: 0 };
|
|
@@ -43702,8 +43864,8 @@ function businessConnectionCensusLine(c) {
|
|
|
43702
43864
|
}
|
|
43703
43865
|
|
|
43704
43866
|
// app/lib/telegram/business-window-census.ts
|
|
43705
|
-
import { readdirSync as
|
|
43706
|
-
import { join as
|
|
43867
|
+
import { readdirSync as readdirSync38, existsSync as existsSync60 } from "fs";
|
|
43868
|
+
import { join as join76 } from "path";
|
|
43707
43869
|
var BUSINESS_WINDOW_CENSUS_TAG = "[telegram-audit]";
|
|
43708
43870
|
var EXPIRING_SOON_S = 3600;
|
|
43709
43871
|
function collectBusinessWindowCensus(input) {
|
|
@@ -43731,11 +43893,11 @@ function businessWindowCensusLine(c) {
|
|
|
43731
43893
|
function readBusinessChatClocks(accountIds) {
|
|
43732
43894
|
const out = [];
|
|
43733
43895
|
for (const accountId of accountIds) {
|
|
43734
|
-
const dir =
|
|
43735
|
-
if (!
|
|
43896
|
+
const dir = join76(STORE_ROOT2(), accountId);
|
|
43897
|
+
if (!existsSync60(dir)) continue;
|
|
43736
43898
|
let names;
|
|
43737
43899
|
try {
|
|
43738
|
-
names =
|
|
43900
|
+
names = readdirSync38(dir);
|
|
43739
43901
|
} catch {
|
|
43740
43902
|
continue;
|
|
43741
43903
|
}
|
|
@@ -43793,15 +43955,15 @@ async function getTelegramBusinessConnection(botToken, connectionId, opts = {})
|
|
|
43793
43955
|
}
|
|
43794
43956
|
|
|
43795
43957
|
// server/telegram-migrate.ts
|
|
43796
|
-
import { readFileSync as
|
|
43797
|
-
import { dirname as
|
|
43958
|
+
import { readFileSync as readFileSync61, writeFileSync as writeFileSync23, existsSync as existsSync61, renameSync as renameSync11, mkdirSync as mkdirSync14 } from "fs";
|
|
43959
|
+
import { dirname as dirname20, join as join77 } from "path";
|
|
43798
43960
|
function migrateTelegramTwoSlot(input) {
|
|
43799
43961
|
const out = [];
|
|
43800
43962
|
for (const account of input.accounts) {
|
|
43801
|
-
const configPath3 =
|
|
43963
|
+
const configPath3 = join77(account.accountDir, "account.json");
|
|
43802
43964
|
let config;
|
|
43803
43965
|
try {
|
|
43804
|
-
config = JSON.parse(
|
|
43966
|
+
config = JSON.parse(readFileSync61(configPath3, "utf-8"));
|
|
43805
43967
|
} catch {
|
|
43806
43968
|
console.error(`[telegram-audit] op=migrate-unreadable accountId=${account.accountId}`);
|
|
43807
43969
|
continue;
|
|
@@ -43854,22 +44016,22 @@ function migrateTelegramTwoSlot(input) {
|
|
|
43854
44016
|
return out;
|
|
43855
44017
|
}
|
|
43856
44018
|
function moveSecret(from, to) {
|
|
43857
|
-
if (!
|
|
43858
|
-
mkdirSync14(
|
|
44019
|
+
if (!existsSync61(from)) return;
|
|
44020
|
+
mkdirSync14(dirname20(to), { recursive: true, mode: 448 });
|
|
43859
44021
|
renameSync11(from, to);
|
|
43860
44022
|
}
|
|
43861
44023
|
|
|
43862
44024
|
// server/telegram-unadopt.ts
|
|
43863
|
-
import { readFileSync as
|
|
43864
|
-
import { join as
|
|
44025
|
+
import { readFileSync as readFileSync62, writeFileSync as writeFileSync24, renameSync as renameSync12 } from "fs";
|
|
44026
|
+
import { join as join78 } from "path";
|
|
43865
44027
|
var FILE3 = "channel-session-override.json";
|
|
43866
44028
|
function unadoptTelegramPointers(input) {
|
|
43867
44029
|
return input.accounts.map(({ accountId, accountDir }) => {
|
|
43868
44030
|
const out = { accountId, dropped: [], kept: 0, unknown: 0 };
|
|
43869
|
-
const path =
|
|
44031
|
+
const path = join78(accountDir, FILE3);
|
|
43870
44032
|
const bySender = {};
|
|
43871
44033
|
try {
|
|
43872
|
-
const raw = JSON.parse(
|
|
44034
|
+
const raw = JSON.parse(readFileSync62(path, "utf8"));
|
|
43873
44035
|
if (!raw.bySender || typeof raw.bySender !== "object") return out;
|
|
43874
44036
|
for (const [k, v] of Object.entries(raw.bySender)) if (typeof v === "string") bySender[k] = v;
|
|
43875
44037
|
} catch {
|
|
@@ -43940,14 +44102,14 @@ function backfillMisfiledRecords(params) {
|
|
|
43940
44102
|
}
|
|
43941
44103
|
|
|
43942
44104
|
// server/lib/booking-site-accounts.ts
|
|
43943
|
-
import { existsSync as
|
|
43944
|
-
import { resolve as
|
|
44105
|
+
import { existsSync as existsSync62, readFileSync as readFileSync63 } from "fs";
|
|
44106
|
+
import { resolve as resolve54 } from "path";
|
|
43945
44107
|
function listBookingSiteAccounts(accounts) {
|
|
43946
44108
|
return accounts.filter((a) => {
|
|
43947
|
-
const availPath =
|
|
43948
|
-
if (!
|
|
44109
|
+
const availPath = resolve54(a.accountDir, "calendar-availability.json");
|
|
44110
|
+
if (!existsSync62(availPath)) return false;
|
|
43949
44111
|
try {
|
|
43950
|
-
const cfg = JSON.parse(
|
|
44112
|
+
const cfg = JSON.parse(readFileSync63(availPath, "utf-8"));
|
|
43951
44113
|
return typeof cfg.bookingDbName === "string" && cfg.bookingDbName.length > 0;
|
|
43952
44114
|
} catch {
|
|
43953
44115
|
return false;
|
|
@@ -43985,8 +44147,8 @@ function broadcastAdminShutdown(reason) {
|
|
|
43985
44147
|
|
|
43986
44148
|
// ../lib/entitlement/src/index.ts
|
|
43987
44149
|
import { createPublicKey, createHash as createHash7, verify as cryptoVerify } from "crypto";
|
|
43988
|
-
import { existsSync as
|
|
43989
|
-
import { resolve as
|
|
44150
|
+
import { existsSync as existsSync63, readFileSync as readFileSync64, statSync as statSync34 } from "fs";
|
|
44151
|
+
import { resolve as resolve55 } from "path";
|
|
43990
44152
|
|
|
43991
44153
|
// ../lib/entitlement/src/canonicalize.ts
|
|
43992
44154
|
function canonicalize(value) {
|
|
@@ -44021,7 +44183,7 @@ var PUBKEY_SHA256 = "8eee6bcb33545fd13b16d3199a5735ca5db5062834c7b49dfe4f23801d9
|
|
|
44021
44183
|
var GRACE_DAYS = 7;
|
|
44022
44184
|
var GRACE_MS = GRACE_DAYS * 24 * 60 * 60 * 1e3;
|
|
44023
44185
|
function pubkeyPath(brand) {
|
|
44024
|
-
return
|
|
44186
|
+
return resolve55(brand.platformRoot, "lib", "entitlement", "rubytech-pubkey.pem");
|
|
44025
44187
|
}
|
|
44026
44188
|
var memo = null;
|
|
44027
44189
|
function memoKey(mtimeMs, account) {
|
|
@@ -44033,11 +44195,11 @@ function resolveEntitlement(brand, account) {
|
|
|
44033
44195
|
if (brand.commercialMode !== true) {
|
|
44034
44196
|
return logResolved(implicitTrust(account), null);
|
|
44035
44197
|
}
|
|
44036
|
-
const entitlementPath =
|
|
44037
|
-
if (!
|
|
44198
|
+
const entitlementPath = resolve55(brand.configDir, "entitlement.json");
|
|
44199
|
+
if (!existsSync63(entitlementPath)) {
|
|
44038
44200
|
return logResolved(anonymousFallback("missing"), { reason: "missing" });
|
|
44039
44201
|
}
|
|
44040
|
-
const stat11 =
|
|
44202
|
+
const stat11 = statSync34(entitlementPath);
|
|
44041
44203
|
const key2 = memoKey(stat11.mtimeMs, account);
|
|
44042
44204
|
if (memo && memo.key === key2) {
|
|
44043
44205
|
return memo.result;
|
|
@@ -44049,7 +44211,7 @@ function resolveEntitlement(brand, account) {
|
|
|
44049
44211
|
function verifyAndResolve(brand, entitlementPath, account) {
|
|
44050
44212
|
let pubkeyPem;
|
|
44051
44213
|
try {
|
|
44052
|
-
pubkeyPem =
|
|
44214
|
+
pubkeyPem = readFileSync64(pubkeyPath(brand), "utf-8");
|
|
44053
44215
|
} catch (err) {
|
|
44054
44216
|
return logResolved(anonymousFallback("pubkey-missing"), {
|
|
44055
44217
|
reason: "pubkey-missing"
|
|
@@ -44063,7 +44225,7 @@ function verifyAndResolve(brand, entitlementPath, account) {
|
|
|
44063
44225
|
}
|
|
44064
44226
|
let envelope;
|
|
44065
44227
|
try {
|
|
44066
|
-
envelope = JSON.parse(
|
|
44228
|
+
envelope = JSON.parse(readFileSync64(entitlementPath, "utf-8"));
|
|
44067
44229
|
} catch {
|
|
44068
44230
|
return logResolved(anonymousFallback("malformed"), { reason: "malformed" });
|
|
44069
44231
|
}
|
|
@@ -44225,14 +44387,14 @@ function clientFrom(c) {
|
|
|
44225
44387
|
}
|
|
44226
44388
|
installMediaDownloadGuard();
|
|
44227
44389
|
var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT || "";
|
|
44228
|
-
var BRAND_JSON_PATH = PLATFORM_ROOT6 ?
|
|
44390
|
+
var BRAND_JSON_PATH = PLATFORM_ROOT6 ? join79(PLATFORM_ROOT6, "config", "brand.json") : "";
|
|
44229
44391
|
var BRAND = { productName: "Maxy", hostname: "maxy", configDir: ".maxy", marketingUrl: "https://getmaxy.com" };
|
|
44230
|
-
if (BRAND_JSON_PATH && !
|
|
44392
|
+
if (BRAND_JSON_PATH && !existsSync64(BRAND_JSON_PATH)) {
|
|
44231
44393
|
console.error(`[brand] WARNING: brand.json not found at ${BRAND_JSON_PATH} \u2014 using Maxy defaults`);
|
|
44232
44394
|
}
|
|
44233
|
-
if (BRAND_JSON_PATH &&
|
|
44395
|
+
if (BRAND_JSON_PATH && existsSync64(BRAND_JSON_PATH)) {
|
|
44234
44396
|
try {
|
|
44235
|
-
const parsed = JSON.parse(
|
|
44397
|
+
const parsed = JSON.parse(readFileSync65(BRAND_JSON_PATH, "utf-8"));
|
|
44236
44398
|
BRAND = { ...BRAND, ...parsed };
|
|
44237
44399
|
} catch (err) {
|
|
44238
44400
|
console.error(`[brand] Failed to parse brand.json: ${err.message}`);
|
|
@@ -44264,11 +44426,11 @@ var brandLoginOpts = {
|
|
|
44264
44426
|
appleTouchIconPath: brandAppIcon512Path,
|
|
44265
44427
|
themeColor: BRAND.defaultColors?.primary
|
|
44266
44428
|
};
|
|
44267
|
-
var ALIAS_DOMAINS_PATH =
|
|
44429
|
+
var ALIAS_DOMAINS_PATH = join79(homedir6(), BRAND.configDir, "alias-domains.json");
|
|
44268
44430
|
function loadAliasDomains() {
|
|
44269
44431
|
try {
|
|
44270
|
-
if (!
|
|
44271
|
-
const parsed = JSON.parse(
|
|
44432
|
+
if (!existsSync64(ALIAS_DOMAINS_PATH)) return null;
|
|
44433
|
+
const parsed = JSON.parse(readFileSync65(ALIAS_DOMAINS_PATH, "utf-8"));
|
|
44272
44434
|
if (!Array.isArray(parsed)) {
|
|
44273
44435
|
console.error("[alias-domains] malformed alias-domains.json \u2014 expected array");
|
|
44274
44436
|
return null;
|
|
@@ -44410,7 +44572,7 @@ var waGateway = new WaGateway({
|
|
|
44410
44572
|
// resolver and `fanTargetsFor` is a constructor dep, not a callable method.
|
|
44411
44573
|
fanTargetsFor: whatsappFanTargets,
|
|
44412
44574
|
gatewayUrl: `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`,
|
|
44413
|
-
serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ??
|
|
44575
|
+
serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve56(process.env.MAXY_PLATFORM_ROOT ?? join79(__dirname, ".."), "services/whatsapp-channel/dist/server.js"),
|
|
44414
44576
|
// Task 751 / 1390 — file delivery on the native channel. `maxyAccountId` (the
|
|
44415
44577
|
// path-validation scope) is the sender's effective SESSION account, resolved
|
|
44416
44578
|
// once at the inbound gate and threaded here via the gateway's per-sender doc
|
|
@@ -44425,7 +44587,7 @@ var waGateway = new WaGateway({
|
|
|
44425
44587
|
caption,
|
|
44426
44588
|
accountId,
|
|
44427
44589
|
maxyAccountId,
|
|
44428
|
-
platformRoot:
|
|
44590
|
+
platformRoot: resolve56(process.env.MAXY_PLATFORM_ROOT ?? join79(__dirname, ".."))
|
|
44429
44591
|
});
|
|
44430
44592
|
return result.ok ? { ok: true, messageId: result.messageId } : { ok: false, error: result.error };
|
|
44431
44593
|
},
|
|
@@ -44600,7 +44762,7 @@ function runDuplicateSenderAudit() {
|
|
|
44600
44762
|
try {
|
|
44601
44763
|
const configDir = process.env.CLAUDE_CONFIG_DIR;
|
|
44602
44764
|
if (!configDir) return;
|
|
44603
|
-
const projectsRoot =
|
|
44765
|
+
const projectsRoot = join79(configDir, "projects");
|
|
44604
44766
|
const records5 = [];
|
|
44605
44767
|
for (const { path: jsonlPath, isSubagent, archived } of enumerateJsonls(projectsRoot)) {
|
|
44606
44768
|
if (isSubagent || archived) continue;
|
|
@@ -44652,7 +44814,7 @@ var webchatGateway = new WebchatGateway({
|
|
|
44652
44814
|
// rather than hanging the POST.
|
|
44653
44815
|
publicProjectsRoot: () => {
|
|
44654
44816
|
const cfg = claudeConfigDir();
|
|
44655
|
-
return cfg ?
|
|
44817
|
+
return cfg ? join79(cfg, "projects") : "";
|
|
44656
44818
|
},
|
|
44657
44819
|
gatewayUrl: webchatGatewayUrl(),
|
|
44658
44820
|
serverPath: webchatServerPath(),
|
|
@@ -45339,20 +45501,20 @@ app80.get("/agent-assets/:slug/:filename", (c) => {
|
|
|
45339
45501
|
console.error(`[agent-assets] no-account slug=${slug} file=${filename}`);
|
|
45340
45502
|
return c.text("Not found", 404);
|
|
45341
45503
|
}
|
|
45342
|
-
const filePath =
|
|
45343
|
-
const expectedDir =
|
|
45504
|
+
const filePath = resolve56(account.accountDir, "agents", slug, "assets", filename);
|
|
45505
|
+
const expectedDir = resolve56(account.accountDir, "agents", slug, "assets");
|
|
45344
45506
|
if (!filePath.startsWith(expectedDir + "/")) {
|
|
45345
45507
|
console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
|
|
45346
45508
|
return c.text("Forbidden", 403);
|
|
45347
45509
|
}
|
|
45348
|
-
if (!
|
|
45510
|
+
if (!existsSync64(filePath)) {
|
|
45349
45511
|
console.error(`[agent-assets] serve slug=${slug} file=${filename} status=404`);
|
|
45350
45512
|
return c.text("Not found", 404);
|
|
45351
45513
|
}
|
|
45352
45514
|
const ext = "." + filename.split(".").pop()?.toLowerCase();
|
|
45353
45515
|
const contentType = IMAGE_MIME[ext] || "application/octet-stream";
|
|
45354
45516
|
console.log(`[agent-assets] serve slug=${slug} file=${filename} status=200`);
|
|
45355
|
-
const body =
|
|
45517
|
+
const body = readFileSync65(filePath);
|
|
45356
45518
|
return c.body(body, 200, {
|
|
45357
45519
|
"Content-Type": contentType,
|
|
45358
45520
|
"Cache-Control": "public, max-age=3600"
|
|
@@ -45369,20 +45531,20 @@ app80.get("/generated/:filename", (c) => {
|
|
|
45369
45531
|
console.error(`[generated] serve file=${filename} status=404`);
|
|
45370
45532
|
return c.text("Not found", 404);
|
|
45371
45533
|
}
|
|
45372
|
-
const filePath =
|
|
45373
|
-
const expectedDir =
|
|
45534
|
+
const filePath = resolve56(account.accountDir, "generated", filename);
|
|
45535
|
+
const expectedDir = resolve56(account.accountDir, "generated");
|
|
45374
45536
|
if (!filePath.startsWith(expectedDir + "/")) {
|
|
45375
45537
|
console.error(`[generated] serve file=${filename} status=403`);
|
|
45376
45538
|
return c.text("Forbidden", 403);
|
|
45377
45539
|
}
|
|
45378
|
-
if (!
|
|
45540
|
+
if (!existsSync64(filePath)) {
|
|
45379
45541
|
console.error(`[generated] serve file=${filename} status=404`);
|
|
45380
45542
|
return c.text("Not found", 404);
|
|
45381
45543
|
}
|
|
45382
45544
|
const ext = "." + filename.split(".").pop()?.toLowerCase();
|
|
45383
45545
|
const contentType = IMAGE_MIME[ext] || "application/octet-stream";
|
|
45384
45546
|
console.log(`[generated] serve file=${filename} status=200`);
|
|
45385
|
-
const body =
|
|
45547
|
+
const body = readFileSync65(filePath);
|
|
45386
45548
|
return c.body(body, 200, {
|
|
45387
45549
|
"Content-Type": contentType,
|
|
45388
45550
|
"Cache-Control": "public, max-age=86400"
|
|
@@ -45395,9 +45557,9 @@ app80.route("/v", visitor_consent_default);
|
|
|
45395
45557
|
var htmlCache = /* @__PURE__ */ new Map();
|
|
45396
45558
|
var brandLogoPath = "/brand/maxy-monochrome.png";
|
|
45397
45559
|
var brandIconPath = "/brand/maxy-monochrome.png";
|
|
45398
|
-
if (BRAND_JSON_PATH &&
|
|
45560
|
+
if (BRAND_JSON_PATH && existsSync64(BRAND_JSON_PATH)) {
|
|
45399
45561
|
try {
|
|
45400
|
-
const fullBrand = JSON.parse(
|
|
45562
|
+
const fullBrand = JSON.parse(readFileSync65(BRAND_JSON_PATH, "utf-8"));
|
|
45401
45563
|
if (fullBrand.assets?.logo) brandLogoPath = `/brand/${fullBrand.assets.logo}`;
|
|
45402
45564
|
brandIconPath = fullBrand.assets?.icon ? `/brand/${fullBrand.assets.icon}` : brandLogoPath;
|
|
45403
45565
|
} catch {
|
|
@@ -45424,11 +45586,11 @@ var brandScript = `<script>window.__BRAND__=${JSON.stringify({
|
|
|
45424
45586
|
var brandThemeColor = BRAND.defaultColors?.primary ?? "#000000";
|
|
45425
45587
|
var brandBackgroundColor = BRAND.defaultColors?.background ?? "#ffffff";
|
|
45426
45588
|
var brandAppIconsExist = [brandAppIcon192Path, brandAppIcon512Path, brandMaskableIconPath].every(
|
|
45427
|
-
(p) =>
|
|
45589
|
+
(p) => existsSync64(resolve56(process.cwd(), "public", p.replace(/^\//, "")))
|
|
45428
45590
|
);
|
|
45429
45591
|
var SW_SOURCE = (() => {
|
|
45430
45592
|
try {
|
|
45431
|
-
return
|
|
45593
|
+
return readFileSync65(resolve56(process.cwd(), "public", "sw.js"), "utf-8");
|
|
45432
45594
|
} catch {
|
|
45433
45595
|
return null;
|
|
45434
45596
|
}
|
|
@@ -45436,9 +45598,9 @@ var SW_SOURCE = (() => {
|
|
|
45436
45598
|
function readInstalledVersion() {
|
|
45437
45599
|
try {
|
|
45438
45600
|
if (!PLATFORM_ROOT6) return "unknown";
|
|
45439
|
-
const versionFile =
|
|
45440
|
-
if (!
|
|
45441
|
-
const content =
|
|
45601
|
+
const versionFile = join79(PLATFORM_ROOT6, "config", `.${BRAND.hostname}-version`);
|
|
45602
|
+
if (!existsSync64(versionFile)) return "unknown";
|
|
45603
|
+
const content = readFileSync65(versionFile, "utf-8").trim();
|
|
45442
45604
|
return content || "unknown";
|
|
45443
45605
|
} catch {
|
|
45444
45606
|
return "unknown";
|
|
@@ -45449,7 +45611,7 @@ var versionScript = `<script>window.__MAXY_VERSION__=${JSON.stringify(INSTALLED_
|
|
|
45449
45611
|
function cachedHtml(file) {
|
|
45450
45612
|
let html = htmlCache.get(file);
|
|
45451
45613
|
if (!html) {
|
|
45452
|
-
html =
|
|
45614
|
+
html = readFileSync65(resolve56(process.cwd(), "public", file), "utf-8");
|
|
45453
45615
|
const productNameEsc = escapeHtml(BRAND.productName);
|
|
45454
45616
|
html = html.replace(/<title>([^<]*)<\/title>/, (_match, inner) => `<title>${escapeHtml(inner).replace(/Maxy/g, productNameEsc)}</title>`);
|
|
45455
45617
|
html = html.replace('href="/favicon.ico"', `href="${escapeHtml(brandFaviconPath)}"`);
|
|
@@ -45466,14 +45628,14 @@ ${clientErrorReporterScript}
|
|
|
45466
45628
|
return html;
|
|
45467
45629
|
}
|
|
45468
45630
|
function loadBrandingCache(agentSlug) {
|
|
45469
|
-
const configDir =
|
|
45631
|
+
const configDir = join79(homedir6(), BRAND.configDir);
|
|
45470
45632
|
try {
|
|
45471
45633
|
const verdict = resolvePublicAddressFromDisk(agentSlug);
|
|
45472
45634
|
const accountId = verdict.kind === "served" ? verdict.owner.accountId : getDefaultAccountId();
|
|
45473
45635
|
if (!accountId) return null;
|
|
45474
|
-
const cachePath =
|
|
45475
|
-
if (!
|
|
45476
|
-
return JSON.parse(
|
|
45636
|
+
const cachePath = join79(configDir, "branding-cache", accountId, `${agentSlug}.json`);
|
|
45637
|
+
if (!existsSync64(cachePath)) return null;
|
|
45638
|
+
return JSON.parse(readFileSync65(cachePath, "utf-8"));
|
|
45477
45639
|
} catch {
|
|
45478
45640
|
return null;
|
|
45479
45641
|
}
|
|
@@ -45568,7 +45730,7 @@ app80.use("/vnc-popout.html", logViewerFetch);
|
|
|
45568
45730
|
app80.get("/vnc-popout.html", (c) => {
|
|
45569
45731
|
let html = htmlCache.get("vnc-popout.html");
|
|
45570
45732
|
if (!html) {
|
|
45571
|
-
html =
|
|
45733
|
+
html = readFileSync65(resolve56(process.cwd(), "public", "vnc-popout.html"), "utf-8");
|
|
45572
45734
|
const name = escapeHtml(BRAND.productName);
|
|
45573
45735
|
html = html.replace("<title>Browser \u2014 Maxy</title>", `<title>${name}</title>`);
|
|
45574
45736
|
html = html.replace("</head>", ` ${brandScript}
|
|
@@ -45722,10 +45884,10 @@ var hostname = process.env.HOSTNAME ?? "127.0.0.1";
|
|
|
45722
45884
|
var httpServer = serve({ fetch: app80.fetch, port, hostname });
|
|
45723
45885
|
console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
45724
45886
|
{
|
|
45725
|
-
const reconcilePlatformRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
45726
|
-
const reconcileScript =
|
|
45887
|
+
const reconcilePlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join79(__dirname, "..");
|
|
45888
|
+
const reconcileScript = resolve56(reconcilePlatformRoot, "plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js");
|
|
45727
45889
|
const runReconcile = (ctx) => {
|
|
45728
|
-
if (!
|
|
45890
|
+
if (!existsSync64(reconcileScript)) return;
|
|
45729
45891
|
try {
|
|
45730
45892
|
const child = spawn3(process.execPath, [reconcileScript], {
|
|
45731
45893
|
env: { ...process.env, PLATFORM_ROOT: reconcilePlatformRoot },
|
|
@@ -45745,7 +45907,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
45745
45907
|
detached: true,
|
|
45746
45908
|
run: runReconcile
|
|
45747
45909
|
});
|
|
45748
|
-
const reconcileStatePath =
|
|
45910
|
+
const reconcileStatePath = join79(MAXY_DIR, "booking-reconcile-state.json");
|
|
45749
45911
|
registerLoop({
|
|
45750
45912
|
name: "calendar-reconcile-liveness",
|
|
45751
45913
|
intervalMs: 6e5,
|
|
@@ -45763,15 +45925,15 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
45763
45925
|
}
|
|
45764
45926
|
{
|
|
45765
45927
|
const DREAM_CYCLE_SWEEP_INTERVAL_MS = 36e5;
|
|
45766
|
-
const dreamPlatformRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
45767
|
-
const dreamSweepScript =
|
|
45928
|
+
const dreamPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join79(__dirname, "..");
|
|
45929
|
+
const dreamSweepScript = resolve56(dreamPlatformRoot, "plugins/memory/mcp/dist/scripts/dream-cycle-sweep.js");
|
|
45768
45930
|
registerLoop({
|
|
45769
45931
|
name: "dream-cycle-sweep",
|
|
45770
45932
|
intervalMs: DREAM_CYCLE_SWEEP_INTERVAL_MS,
|
|
45771
45933
|
firstRunDelayMs: 3e4,
|
|
45772
45934
|
detached: true,
|
|
45773
45935
|
run: (ctx) => {
|
|
45774
|
-
if (!
|
|
45936
|
+
if (!existsSync64(dreamSweepScript)) return;
|
|
45775
45937
|
try {
|
|
45776
45938
|
const child = spawn3(process.execPath, [dreamSweepScript], {
|
|
45777
45939
|
env: { ...process.env, PLATFORM_ROOT: dreamPlatformRoot },
|
|
@@ -45787,11 +45949,11 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
45787
45949
|
});
|
|
45788
45950
|
}
|
|
45789
45951
|
{
|
|
45790
|
-
const outlookPlatformRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
45791
|
-
const outlookScript =
|
|
45952
|
+
const outlookPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join79(__dirname, "..");
|
|
45953
|
+
const outlookScript = resolve56(outlookPlatformRoot, "plugins/outlook/mcp/dist/scripts/complete-registration.js");
|
|
45792
45954
|
const OUTLOOK_COMPLETE_INTERVAL_MS = 3e4;
|
|
45793
45955
|
const runOutlookComplete = (ctx) => {
|
|
45794
|
-
if (!
|
|
45956
|
+
if (!existsSync64(outlookScript)) return;
|
|
45795
45957
|
try {
|
|
45796
45958
|
const child = spawn3(process.execPath, [outlookScript], {
|
|
45797
45959
|
env: { ...process.env, PLATFORM_ROOT: outlookPlatformRoot },
|
|
@@ -45813,20 +45975,20 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
45813
45975
|
});
|
|
45814
45976
|
}
|
|
45815
45977
|
{
|
|
45816
|
-
const auditRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
45817
|
-
const strandedAccountsDir =
|
|
45978
|
+
const auditRoot = process.env.MAXY_PLATFORM_ROOT ?? join79(__dirname, "..");
|
|
45979
|
+
const strandedAccountsDir = resolve56(auditRoot, "..", "data/accounts");
|
|
45818
45980
|
const STRANDED_AUDIT_INTERVAL_MS = 3e5;
|
|
45819
45981
|
const STRANDED_AGE_MS = 16 * 6e4;
|
|
45820
45982
|
const STRANDED_UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
45821
45983
|
const runStrandedAudit = () => {
|
|
45822
45984
|
try {
|
|
45823
|
-
if (!
|
|
45985
|
+
if (!existsSync64(strandedAccountsDir)) return;
|
|
45824
45986
|
const now = Date.now();
|
|
45825
|
-
for (const name of
|
|
45987
|
+
for (const name of readdirSync39(strandedAccountsDir)) {
|
|
45826
45988
|
if (!STRANDED_UUID_RE.test(name)) continue;
|
|
45827
|
-
const pendingPath2 =
|
|
45828
|
-
if (!
|
|
45829
|
-
const ageMs2 = now -
|
|
45989
|
+
const pendingPath2 = resolve56(strandedAccountsDir, name, "secrets/outlook/pending-devicecode.enc");
|
|
45990
|
+
if (!existsSync64(pendingPath2)) continue;
|
|
45991
|
+
const ageMs2 = now - statSync35(pendingPath2).mtimeMs;
|
|
45830
45992
|
if (ageMs2 > STRANDED_AGE_MS) {
|
|
45831
45993
|
console.error(`[outlook-mcp] devicecode-stranded account=${name} ageSec=${Math.floor(ageMs2 / 1e3)}`);
|
|
45832
45994
|
}
|
|
@@ -45843,8 +46005,8 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
45843
46005
|
});
|
|
45844
46006
|
}
|
|
45845
46007
|
{
|
|
45846
|
-
const googleRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
45847
|
-
const googleAccountsDir =
|
|
46008
|
+
const googleRoot = process.env.MAXY_PLATFORM_ROOT ?? join79(__dirname, "..");
|
|
46009
|
+
const googleAccountsDir = resolve56(googleRoot, "..", "data/accounts");
|
|
45848
46010
|
const GOOGLE_PENDING_AUDIT_INTERVAL_MS = 3e5;
|
|
45849
46011
|
const runGooglePendingAuditSafe = () => {
|
|
45850
46012
|
try {
|
|
@@ -45859,10 +46021,10 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
45859
46021
|
firstRunDelayMs: 27e3,
|
|
45860
46022
|
run: runGooglePendingAuditSafe
|
|
45861
46023
|
});
|
|
45862
|
-
const googleAuditScript =
|
|
46024
|
+
const googleAuditScript = resolve56(googleRoot, "plugins/google/mcp/dist/scripts/account-audit.js");
|
|
45863
46025
|
const GOOGLE_ACCOUNT_AUDIT_INTERVAL_MS = 36e5;
|
|
45864
46026
|
const runGoogleAccountAudit = (ctx) => {
|
|
45865
|
-
if (!
|
|
46027
|
+
if (!existsSync64(googleAuditScript)) return;
|
|
45866
46028
|
try {
|
|
45867
46029
|
const child = spawn3(process.execPath, [googleAuditScript], {
|
|
45868
46030
|
env: { ...process.env, PLATFORM_ROOT: googleRoot },
|
|
@@ -45899,7 +46061,7 @@ registerLoop({
|
|
|
45899
46061
|
}
|
|
45900
46062
|
});
|
|
45901
46063
|
{
|
|
45902
|
-
const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
46064
|
+
const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join79(__dirname, "..");
|
|
45903
46065
|
const STORAGE_AUDIT_INTERVAL_MS = 3e5;
|
|
45904
46066
|
const runStorageAuditSafe = () => runStorageAudit(auditPlatformRoot).catch((err) => {
|
|
45905
46067
|
console.error(`[storage-audit] error="${err.message}"`);
|
|
@@ -45934,8 +46096,8 @@ registerLoop({
|
|
|
45934
46096
|
for (const o of migrateTelegramTwoSlot({
|
|
45935
46097
|
accounts: listValidAccounts().map((a) => ({ accountId: a.accountId, accountDir: a.accountDir })),
|
|
45936
46098
|
secretPathFor: secretPath,
|
|
45937
|
-
legacySecretPathFor: (botType, accountId) =>
|
|
45938
|
-
|
|
46099
|
+
legacySecretPathFor: (botType, accountId) => resolve56(
|
|
46100
|
+
homedir6(),
|
|
45939
46101
|
configDirName(),
|
|
45940
46102
|
`${botType === "admin" ? ".telegram-admin-webhook-secret" : ".telegram-webhook-secret"}.${accountId}`
|
|
45941
46103
|
),
|
|
@@ -45966,15 +46128,15 @@ registerLoop({
|
|
|
45966
46128
|
const lastByBot = newestTelegramSessionByBot();
|
|
45967
46129
|
let secretFilesOnDisk = [];
|
|
45968
46130
|
try {
|
|
45969
|
-
secretFilesOnDisk =
|
|
46131
|
+
secretFilesOnDisk = readdirSync39(telegramSecretsDir());
|
|
45970
46132
|
} catch {
|
|
45971
46133
|
}
|
|
45972
46134
|
const lines = buildTelegramAuditLines({
|
|
45973
46135
|
accounts,
|
|
45974
|
-
secretFileExists: (botId) =>
|
|
46136
|
+
secretFileExists: (botId) => existsSync64(secretPath(botId)),
|
|
45975
46137
|
agentActive: isActiveAgentSlug,
|
|
45976
46138
|
// Task 2619 — the card set a specialist binding is reconciled against.
|
|
45977
|
-
specialistCards: (accountDir) => listSpecialistCardNames(
|
|
46139
|
+
specialistCards: (accountDir) => listSpecialistCardNames(join79(accountDir, "specialists", "agents")),
|
|
45978
46140
|
// Task 2619 — the doors that can be sent to right now. The same accessor
|
|
45979
46141
|
// the follower census reads (:1185), so "should have a reader" and "can be
|
|
45980
46142
|
// sent to" stay one fact.
|
|
@@ -46383,8 +46545,8 @@ registerLoop({
|
|
|
46383
46545
|
});
|
|
46384
46546
|
}
|
|
46385
46547
|
{
|
|
46386
|
-
const publishPlatformRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
46387
|
-
const publishScript =
|
|
46548
|
+
const publishPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join79(__dirname, "..");
|
|
46549
|
+
const publishScript = resolve56(publishPlatformRoot, "plugins/scheduling/mcp/dist/scripts/publish-availability.js");
|
|
46388
46550
|
const PUBLISH_INTERVAL_MS = 3e5;
|
|
46389
46551
|
const bookingAccounts = () => {
|
|
46390
46552
|
try {
|
|
@@ -46395,7 +46557,7 @@ registerLoop({
|
|
|
46395
46557
|
}
|
|
46396
46558
|
};
|
|
46397
46559
|
const spawnPublish = (account, ctx) => {
|
|
46398
|
-
if (!
|
|
46560
|
+
if (!existsSync64(publishScript)) return;
|
|
46399
46561
|
try {
|
|
46400
46562
|
const child = spawn3(process.execPath, [publishScript], {
|
|
46401
46563
|
env: {
|
|
@@ -46414,21 +46576,21 @@ registerLoop({
|
|
|
46414
46576
|
}
|
|
46415
46577
|
};
|
|
46416
46578
|
const auditSnapshotAge = (account) => {
|
|
46417
|
-
const availPath =
|
|
46579
|
+
const availPath = resolve56(account.accountDir, "calendar-availability.json");
|
|
46418
46580
|
let hasBookingSite = false;
|
|
46419
46581
|
try {
|
|
46420
|
-
if (
|
|
46421
|
-
const cfg = JSON.parse(
|
|
46582
|
+
if (existsSync64(availPath)) {
|
|
46583
|
+
const cfg = JSON.parse(readFileSync65(availPath, "utf-8"));
|
|
46422
46584
|
hasBookingSite = typeof cfg.bookingDbName === "string" && cfg.bookingDbName.length > 0;
|
|
46423
46585
|
}
|
|
46424
46586
|
} catch {
|
|
46425
46587
|
}
|
|
46426
46588
|
if (!hasBookingSite) return;
|
|
46427
|
-
const statePath =
|
|
46589
|
+
const statePath = resolve56(account.accountDir, "state", "booking-availability", "last-publish.json");
|
|
46428
46590
|
let lastSuccessAt = null;
|
|
46429
|
-
if (
|
|
46591
|
+
if (existsSync64(statePath)) {
|
|
46430
46592
|
try {
|
|
46431
|
-
const rec = JSON.parse(
|
|
46593
|
+
const rec = JSON.parse(readFileSync65(statePath, "utf-8"));
|
|
46432
46594
|
lastSuccessAt = rec.lastSuccessAt ?? null;
|
|
46433
46595
|
} catch {
|
|
46434
46596
|
console.error(`[calendar-availability] op=audit accountId=${account.accountId} snapshotAgeMs=na reason=bad-state-file`);
|
|
@@ -46463,12 +46625,12 @@ startDispatchCensus(() => getSession());
|
|
|
46463
46625
|
startDispatchFieldCensus(() => getSession());
|
|
46464
46626
|
startDispatchTgCensus(() => getSession());
|
|
46465
46627
|
{
|
|
46466
|
-
const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
46467
|
-
const auditScript =
|
|
46628
|
+
const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join79(__dirname, "..");
|
|
46629
|
+
const auditScript = resolve56(auditPlatformRoot, "plugins/connector/mcp/dist/scripts/audit-connectors.js");
|
|
46468
46630
|
const auditLogDir = process.env.LOG_DIR ?? LOG_DIR;
|
|
46469
46631
|
const CONNECTOR_AUDIT_INTERVAL_MS = 3e5;
|
|
46470
46632
|
const runConnectorAudit = (ctx) => {
|
|
46471
|
-
if (!
|
|
46633
|
+
if (!existsSync64(auditScript)) return;
|
|
46472
46634
|
try {
|
|
46473
46635
|
const child = spawn3(process.execPath, [auditScript], {
|
|
46474
46636
|
env: { ...process.env, PLATFORM_ROOT: auditPlatformRoot, LOG_DIR: auditLogDir },
|
|
@@ -46590,11 +46752,11 @@ try {
|
|
|
46590
46752
|
var ADMINUSER_RECONCILE_INTERVAL_MS = 60 * 60 * 1e3;
|
|
46591
46753
|
async function runAdminUserReconcileTick() {
|
|
46592
46754
|
try {
|
|
46593
|
-
if (!
|
|
46755
|
+
if (!existsSync64(USERS_FILE)) {
|
|
46594
46756
|
console.error("[adminuser-self-heal] skip reason=no-users-file");
|
|
46595
46757
|
return;
|
|
46596
46758
|
}
|
|
46597
|
-
const usersRaw =
|
|
46759
|
+
const usersRaw = readFileSync65(USERS_FILE, "utf-8").trim();
|
|
46598
46760
|
if (!usersRaw) {
|
|
46599
46761
|
console.error("[adminuser-self-heal] skip reason=empty-users-file");
|
|
46600
46762
|
return;
|
|
@@ -46676,8 +46838,8 @@ var runIngestAuditTick = () => {
|
|
|
46676
46838
|
},
|
|
46677
46839
|
agentExists: (accountId, slug) => {
|
|
46678
46840
|
if (!house) return false;
|
|
46679
|
-
const dir = isHouseAccountKey(house.accountId, accountId) ? house.accountDir :
|
|
46680
|
-
return
|
|
46841
|
+
const dir = isHouseAccountKey(house.accountId, accountId) ? house.accountDir : join79(ACCOUNTS_DIR, accountId);
|
|
46842
|
+
return existsSync64(join79(dir, "agents", slug, "config.json"));
|
|
46681
46843
|
}
|
|
46682
46844
|
});
|
|
46683
46845
|
} catch (err) {
|
|
@@ -46725,9 +46887,9 @@ registerLoop({
|
|
|
46725
46887
|
runPublicAddressCollisionAudit({
|
|
46726
46888
|
houseAccountId: () => resolveAccount()?.accountId ?? null,
|
|
46727
46889
|
activeSlugs: () => listValidAccounts().map((a) => {
|
|
46728
|
-
const agentsRoot =
|
|
46729
|
-
if (!
|
|
46730
|
-
const slugs =
|
|
46890
|
+
const agentsRoot = join79(a.accountDir, "agents");
|
|
46891
|
+
if (!existsSync64(agentsRoot)) return { accountId: a.accountId, slugs: [] };
|
|
46892
|
+
const slugs = readdirSync39(agentsRoot, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name).filter((slug) => isActiveAgentSlug(a.accountDir, slug));
|
|
46731
46893
|
return { accountId: a.accountId, slugs };
|
|
46732
46894
|
})
|
|
46733
46895
|
});
|
|
@@ -46740,8 +46902,8 @@ registerLoop({
|
|
|
46740
46902
|
});
|
|
46741
46903
|
var USERS_RECONCILE_INTERVAL_MS = 60 * 60 * 1e3;
|
|
46742
46904
|
function countUsersRows() {
|
|
46743
|
-
if (!
|
|
46744
|
-
const raw =
|
|
46905
|
+
if (!existsSync64(USERS_FILE)) return 0;
|
|
46906
|
+
const raw = readFileSync65(USERS_FILE, "utf-8").trim();
|
|
46745
46907
|
if (!raw) return 0;
|
|
46746
46908
|
const users = JSON.parse(raw);
|
|
46747
46909
|
return users.filter((u) => typeof u.userId === "string").length;
|
|
@@ -46772,6 +46934,7 @@ registerLoop({
|
|
|
46772
46934
|
});
|
|
46773
46935
|
startGraphHealthTimer();
|
|
46774
46936
|
startSharedFolderCensus();
|
|
46937
|
+
startBrowserOrphanCensus();
|
|
46775
46938
|
startAccountsStateCensus();
|
|
46776
46939
|
startCredRefreshCensus();
|
|
46777
46940
|
void migrateUploads().catch((err) => console.error(`[uploads-migrate] failed err="${err instanceof Error ? err.message : String(err)}"`)).finally(() => {
|
|
@@ -46844,16 +47007,16 @@ function sessionChannelResolver() {
|
|
|
46844
47007
|
byId = /* @__PURE__ */ new Map();
|
|
46845
47008
|
const cfg = claudeConfigDir();
|
|
46846
47009
|
if (cfg) {
|
|
46847
|
-
for (const { path } of enumerateSessionSidecars(
|
|
47010
|
+
for (const { path } of enumerateSessionSidecars(join79(cfg, "projects"))) {
|
|
46848
47011
|
const channel = readSidecarMeta(path).channel;
|
|
46849
|
-
if (channel) byId.set(
|
|
47012
|
+
if (channel) byId.set(basename20(path).replace(/\.meta\.json$/, ""), channel);
|
|
46850
47013
|
}
|
|
46851
47014
|
}
|
|
46852
47015
|
}
|
|
46853
47016
|
return byId.get(sessionId) ?? null;
|
|
46854
47017
|
};
|
|
46855
47018
|
}
|
|
46856
|
-
var configDirForWhatsApp =
|
|
47019
|
+
var configDirForWhatsApp = basename20(MAXY_DIR) || ".maxy";
|
|
46857
47020
|
var bootAccount = resolveAccount();
|
|
46858
47021
|
if (bootAccount) {
|
|
46859
47022
|
migrateRemovedConfigKeys(bootAccount.accountDir);
|
|
@@ -46919,7 +47082,7 @@ if (bootAccountConfig?.whatsapp) {
|
|
|
46919
47082
|
}
|
|
46920
47083
|
init({
|
|
46921
47084
|
configDir: configDirForWhatsApp,
|
|
46922
|
-
platformRoot:
|
|
47085
|
+
platformRoot: resolve56(process.env.MAXY_PLATFORM_ROOT ?? join79(__dirname, "..")),
|
|
46923
47086
|
accountConfig: bootAccountConfig,
|
|
46924
47087
|
// Task 2074 — enrich with the sub-account name and fan out to every open
|
|
46925
47088
|
// admin SSE stream. Fire-and-forget: the manager's persist path must not
|