@rubytech/create-maxy-code 0.1.474 → 0.1.475
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +16 -7
- package/payload/platform/plugins/docs/references/google-guide.md +15 -6
- package/payload/platform/plugins/google/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/google/PLUGIN.md +60 -12
- package/payload/platform/plugins/google/mcp/dist/__tests__/account-audit.test.d.ts +2 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/account-audit.test.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/account-audit.test.js +229 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/account-audit.test.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/account-register.test.js +9 -9
- package/payload/platform/plugins/google/mcp/dist/__tests__/account-register.test.js.map +1 -1
- package/payload/platform/plugins/google/mcp/dist/__tests__/consent-url-redirect.test.d.ts +2 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/consent-url-redirect.test.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/consent-url-redirect.test.js +17 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/consent-url-redirect.test.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/loopback-listener.test.d.ts +2 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/loopback-listener.test.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/loopback-listener.test.js +146 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/loopback-listener.test.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/pending-redirect.test.d.ts +2 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/pending-redirect.test.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/pending-redirect.test.js +19 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/pending-redirect.test.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/register-redirect-chain.test.d.ts +2 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/register-redirect-chain.test.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/register-redirect-chain.test.js +41 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/register-redirect-chain.test.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/auth/account-audit.d.ts +44 -0
- package/payload/platform/plugins/google/mcp/dist/auth/account-audit.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/auth/account-audit.js +112 -0
- package/payload/platform/plugins/google/mcp/dist/auth/account-audit.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/auth/loopback-listener.d.ts +17 -0
- package/payload/platform/plugins/google/mcp/dist/auth/loopback-listener.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/auth/loopback-listener.js +143 -0
- package/payload/platform/plugins/google/mcp/dist/auth/loopback-listener.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/auth/pending-store.d.ts +9 -0
- package/payload/platform/plugins/google/mcp/dist/auth/pending-store.d.ts.map +1 -1
- package/payload/platform/plugins/google/mcp/dist/auth/pending-store.js.map +1 -1
- package/payload/platform/plugins/google/mcp/dist/index.js +73 -5
- package/payload/platform/plugins/google/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/google/mcp/dist/scripts/account-audit.d.ts +2 -0
- package/payload/platform/plugins/google/mcp/dist/scripts/account-audit.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/scripts/account-audit.js +37 -0
- package/payload/platform/plugins/google/mcp/dist/scripts/account-audit.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/tools/account-register.d.ts +20 -4
- package/payload/platform/plugins/google/mcp/dist/tools/account-register.d.ts.map +1 -1
- package/payload/platform/plugins/google/mcp/dist/tools/account-register.js +19 -9
- package/payload/platform/plugins/google/mcp/dist/tools/account-register.js.map +1 -1
- package/payload/platform/plugins/google/references/auth.md +93 -14
- package/payload/platform/services/claude-session-manager/dist/activity-rows.d.ts +21 -3
- package/payload/platform/services/claude-session-manager/dist/activity-rows.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/activity-rows.js +6 -2
- package/payload/platform/services/claude-session-manager/dist/activity-rows.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/fs-watcher.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/fs-watcher.js +43 -5
- package/payload/platform/services/claude-session-manager/dist/fs-watcher.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/jsonl-enumerator.d.ts +9 -0
- package/payload/platform/services/claude-session-manager/dist/jsonl-enumerator.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/jsonl-enumerator.js +78 -0
- package/payload/platform/services/claude-session-manager/dist/jsonl-enumerator.js.map +1 -1
- package/payload/server/public/activity.html +1 -1
- package/payload/server/public/assets/activity-Mz1BhgB1.js +1 -0
- package/payload/server/server.js +368 -300
- package/payload/server/public/assets/activity-CdipMTDp.js +0 -1
package/payload/server/server.js
CHANGED
|
@@ -1534,10 +1534,10 @@ var serveStatic = (options = { root: "" }) => {
|
|
|
1534
1534
|
};
|
|
1535
1535
|
|
|
1536
1536
|
// server/index.ts
|
|
1537
|
-
import { readFileSync as readFileSync41, existsSync as
|
|
1537
|
+
import { readFileSync as readFileSync41, existsSync as existsSync38, watchFile, readdirSync as readdirSync26, statSync as statSync17 } from "fs";
|
|
1538
1538
|
import { spawn as spawn3 } from "child_process";
|
|
1539
1539
|
import { createHash as createHash7 } from "crypto";
|
|
1540
|
-
import { resolve as resolve36, join as
|
|
1540
|
+
import { resolve as resolve36, join as join42, basename as basename12 } from "path";
|
|
1541
1541
|
import { homedir as homedir4 } from "os";
|
|
1542
1542
|
import { monitorEventLoopDelay } from "perf_hooks";
|
|
1543
1543
|
|
|
@@ -9687,46 +9687,74 @@ async function runPagesAudit(root) {
|
|
|
9687
9687
|
}
|
|
9688
9688
|
}
|
|
9689
9689
|
|
|
9690
|
+
// server/google-pending-audit.ts
|
|
9691
|
+
import { existsSync as existsSync10, readdirSync as readdirSync9, statSync as statSync4 } from "fs";
|
|
9692
|
+
import { join as join14 } from "path";
|
|
9693
|
+
var GOOGLE_PENDING_LIFETIME_SEC = 600;
|
|
9694
|
+
var UUID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
9695
|
+
function runGooglePendingAudit(accountsDir, nowMs, emit, readMtimeMs = (path3) => statSync4(path3).mtimeMs) {
|
|
9696
|
+
let scanned = 0;
|
|
9697
|
+
let stranded = 0;
|
|
9698
|
+
if (existsSync10(accountsDir)) {
|
|
9699
|
+
for (const accountId of readdirSync9(accountsDir)) {
|
|
9700
|
+
if (!UUID_RE2.test(accountId)) continue;
|
|
9701
|
+
const pendingPath2 = join14(accountsDir, accountId, "secrets", "google", "pending-oauth.enc");
|
|
9702
|
+
try {
|
|
9703
|
+
if (!existsSync10(pendingPath2)) continue;
|
|
9704
|
+
const ageSec = Math.max(0, Math.floor((nowMs - readMtimeMs(pendingPath2)) / 1e3));
|
|
9705
|
+
scanned += 1;
|
|
9706
|
+
if (ageSec >= GOOGLE_PENDING_LIFETIME_SEC) {
|
|
9707
|
+
stranded += 1;
|
|
9708
|
+
emit(`[google-oauth] op=pending-stranded account=${accountId} ageSec=${ageSec}`);
|
|
9709
|
+
}
|
|
9710
|
+
} catch {
|
|
9711
|
+
}
|
|
9712
|
+
}
|
|
9713
|
+
}
|
|
9714
|
+
emit(`[google-oauth] op=pending-audit scanned=${scanned} stranded=${stranded}`);
|
|
9715
|
+
return { scanned, stranded };
|
|
9716
|
+
}
|
|
9717
|
+
|
|
9690
9718
|
// server/routes/whatsapp-reader.ts
|
|
9691
|
-
import { readFileSync as readFileSync19, watch, statSync as
|
|
9692
|
-
import { basename as basename4, dirname as dirname5, isAbsolute, join as
|
|
9719
|
+
import { readFileSync as readFileSync19, watch, statSync as statSync7, openSync, readSync, closeSync, existsSync as existsSync13, readdirSync as readdirSync14, realpathSync as realpathSync5 } from "fs";
|
|
9720
|
+
import { basename as basename4, dirname as dirname5, isAbsolute, join as join19, relative as relative2, resolve as resolve13, sep as sep3 } from "path";
|
|
9693
9721
|
|
|
9694
9722
|
// server/routes/admin/sidebar-sessions.ts
|
|
9695
|
-
import { readdirSync as
|
|
9696
|
-
import { dirname as dirname4, join as
|
|
9723
|
+
import { readdirSync as readdirSync12, readFileSync as readFileSync17, statSync as statSync6 } from "fs";
|
|
9724
|
+
import { dirname as dirname4, join as join17, resolve as resolve12 } from "path";
|
|
9697
9725
|
|
|
9698
9726
|
// ../services/claude-session-manager/src/jsonl-path.ts
|
|
9699
|
-
import { existsSync as
|
|
9727
|
+
import { existsSync as existsSync11, readdirSync as readdirSync10 } from "fs";
|
|
9700
9728
|
import { homedir } from "os";
|
|
9701
|
-
import { join as
|
|
9729
|
+
import { join as join15 } from "path";
|
|
9702
9730
|
function findExistingJsonlForSessionId(claudeConfigDir2, sessionId) {
|
|
9703
|
-
const projectsRoot =
|
|
9704
|
-
if (!
|
|
9731
|
+
const projectsRoot = join15(claudeConfigDir2, "projects");
|
|
9732
|
+
if (!existsSync11(projectsRoot)) return null;
|
|
9705
9733
|
let slugs;
|
|
9706
9734
|
try {
|
|
9707
|
-
slugs =
|
|
9735
|
+
slugs = readdirSync10(projectsRoot, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
9708
9736
|
} catch {
|
|
9709
9737
|
return null;
|
|
9710
9738
|
}
|
|
9711
9739
|
const basename13 = `${sessionId}.jsonl`;
|
|
9712
9740
|
for (const slug of slugs) {
|
|
9713
|
-
const live =
|
|
9714
|
-
if (
|
|
9715
|
-
const archived =
|
|
9716
|
-
if (
|
|
9741
|
+
const live = join15(projectsRoot, slug, basename13);
|
|
9742
|
+
if (existsSync11(live)) return live;
|
|
9743
|
+
const archived = join15(projectsRoot, slug, "archive", basename13);
|
|
9744
|
+
if (existsSync11(archived)) return archived;
|
|
9717
9745
|
}
|
|
9718
9746
|
return null;
|
|
9719
9747
|
}
|
|
9720
9748
|
|
|
9721
9749
|
// app/lib/admin-identity/pin-validator.ts
|
|
9722
9750
|
import { createHash as createHash3 } from "crypto";
|
|
9723
|
-
import { existsSync as
|
|
9724
|
-
import { join as
|
|
9751
|
+
import { existsSync as existsSync12, readFileSync as readFileSync16, readdirSync as readdirSync11, statSync as statSync5 } from "fs";
|
|
9752
|
+
import { join as join16 } from "path";
|
|
9725
9753
|
function hashPin(pin) {
|
|
9726
9754
|
return createHash3("sha256").update(pin).digest("hex");
|
|
9727
9755
|
}
|
|
9728
9756
|
function readUsersFile(usersFilePath) {
|
|
9729
|
-
if (!
|
|
9757
|
+
if (!existsSync12(usersFilePath)) return null;
|
|
9730
9758
|
const raw = readFileSync16(usersFilePath, "utf-8").trim();
|
|
9731
9759
|
if (!raw) return [];
|
|
9732
9760
|
return JSON.parse(raw);
|
|
@@ -9846,16 +9874,16 @@ function enumerateJsonls(projectsRoot) {
|
|
|
9846
9874
|
const out = [];
|
|
9847
9875
|
let slugs;
|
|
9848
9876
|
try {
|
|
9849
|
-
slugs =
|
|
9877
|
+
slugs = readdirSync12(projectsRoot, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
9850
9878
|
} catch (err) {
|
|
9851
9879
|
if (err.code === "ENOENT") return out;
|
|
9852
9880
|
throw err;
|
|
9853
9881
|
}
|
|
9854
9882
|
for (const slug of slugs) {
|
|
9855
|
-
const slugDir =
|
|
9883
|
+
const slugDir = join17(projectsRoot, slug);
|
|
9856
9884
|
let entries;
|
|
9857
9885
|
try {
|
|
9858
|
-
entries =
|
|
9886
|
+
entries = readdirSync12(slugDir, { withFileTypes: true });
|
|
9859
9887
|
} catch (err) {
|
|
9860
9888
|
const code = err.code ?? "unknown";
|
|
9861
9889
|
console.error(`[admin-sessions-list] slug-skipped slug=${slug} code=${code}`);
|
|
@@ -9863,12 +9891,12 @@ function enumerateJsonls(projectsRoot) {
|
|
|
9863
9891
|
}
|
|
9864
9892
|
for (const entry of entries) {
|
|
9865
9893
|
if (entry.isFile() && SESSION_ID_RE.test(entry.name)) {
|
|
9866
|
-
out.push({ path:
|
|
9894
|
+
out.push({ path: join17(slugDir, entry.name), isSubagent: false, archived: false });
|
|
9867
9895
|
} else if (entry.isDirectory() && entry.name === "subagents") {
|
|
9868
|
-
const subDir =
|
|
9896
|
+
const subDir = join17(slugDir, entry.name);
|
|
9869
9897
|
let subEntries;
|
|
9870
9898
|
try {
|
|
9871
|
-
subEntries =
|
|
9899
|
+
subEntries = readdirSync12(subDir, { withFileTypes: true });
|
|
9872
9900
|
} catch (err) {
|
|
9873
9901
|
const code = err.code ?? "unknown";
|
|
9874
9902
|
console.error(`[admin-sessions-list] subagents-skipped slug=${slug} code=${code}`);
|
|
@@ -9876,14 +9904,14 @@ function enumerateJsonls(projectsRoot) {
|
|
|
9876
9904
|
}
|
|
9877
9905
|
for (const sub of subEntries) {
|
|
9878
9906
|
if (sub.isFile() && SESSION_ID_RE.test(sub.name)) {
|
|
9879
|
-
out.push({ path:
|
|
9907
|
+
out.push({ path: join17(subDir, sub.name), isSubagent: true, archived: false });
|
|
9880
9908
|
}
|
|
9881
9909
|
}
|
|
9882
9910
|
} else if (entry.isDirectory() && entry.name === "archive") {
|
|
9883
|
-
const archiveDir =
|
|
9911
|
+
const archiveDir = join17(slugDir, entry.name);
|
|
9884
9912
|
let archiveEntries;
|
|
9885
9913
|
try {
|
|
9886
|
-
archiveEntries =
|
|
9914
|
+
archiveEntries = readdirSync12(archiveDir, { withFileTypes: true });
|
|
9887
9915
|
} catch (err) {
|
|
9888
9916
|
const code = err.code ?? "unknown";
|
|
9889
9917
|
console.error(`[admin-sessions-list] archive-skipped slug=${slug} code=${code}`);
|
|
@@ -9891,7 +9919,7 @@ function enumerateJsonls(projectsRoot) {
|
|
|
9891
9919
|
}
|
|
9892
9920
|
for (const arc of archiveEntries) {
|
|
9893
9921
|
if (arc.isFile() && SESSION_ID_RE.test(arc.name)) {
|
|
9894
|
-
out.push({ path:
|
|
9922
|
+
out.push({ path: join17(archiveDir, arc.name), isSubagent: false, archived: true });
|
|
9895
9923
|
}
|
|
9896
9924
|
}
|
|
9897
9925
|
}
|
|
@@ -9924,7 +9952,7 @@ async function fetchLiveSessions() {
|
|
|
9924
9952
|
function loadUserTitles(accountDir) {
|
|
9925
9953
|
const out = /* @__PURE__ */ new Map();
|
|
9926
9954
|
if (!accountDir) return out;
|
|
9927
|
-
const path3 =
|
|
9955
|
+
const path3 = join17(accountDir, "session-titles.json");
|
|
9928
9956
|
let raw;
|
|
9929
9957
|
try {
|
|
9930
9958
|
raw = readFileSync17(path3, "utf8");
|
|
@@ -10051,7 +10079,7 @@ app4.get("/", requireAdminSession, async (c) => {
|
|
|
10051
10079
|
console.error("[admin-sessions-list] CLAUDE_CONFIG_DIR not set; returning empty list");
|
|
10052
10080
|
return c.json({ sessions: [], accountId: scopeAccountId });
|
|
10053
10081
|
}
|
|
10054
|
-
const projectsRoot =
|
|
10082
|
+
const projectsRoot = join17(configDir2, "projects");
|
|
10055
10083
|
const jsonls = enumerateJsonls(projectsRoot);
|
|
10056
10084
|
const liveSessions = await fetchLiveSessions();
|
|
10057
10085
|
const accountDir = scopeAccountId ? resolve12(ACCOUNTS_DIR, scopeAccountId) : null;
|
|
@@ -10096,7 +10124,7 @@ app4.get("/", requireAdminSession, async (c) => {
|
|
|
10096
10124
|
let mtimeMs;
|
|
10097
10125
|
try {
|
|
10098
10126
|
body = readFileSync17(path3, "utf8");
|
|
10099
|
-
mtimeMs =
|
|
10127
|
+
mtimeMs = statSync6(path3).mtimeMs;
|
|
10100
10128
|
} catch {
|
|
10101
10129
|
continue;
|
|
10102
10130
|
}
|
|
@@ -10104,7 +10132,7 @@ app4.get("/", requireAdminSession, async (c) => {
|
|
|
10104
10132
|
const pid = live ? liveSessions.get(sessionId) ?? null : null;
|
|
10105
10133
|
const resolved = resolveTitle(body, sessionId, userTitles);
|
|
10106
10134
|
titleSourceCounts[resolved.source] += 1;
|
|
10107
|
-
const metaPath =
|
|
10135
|
+
const metaPath = join17(projectDir, `${sessionId}.meta.json`);
|
|
10108
10136
|
const { bridgeIds, role, channel: sidecarChannel, senderId, personId, adminUserId, accountId: rowAccountId } = readSidecarMeta(metaPath);
|
|
10109
10137
|
if (multiAccount) {
|
|
10110
10138
|
if (rowAccountId === null) untaggedCount += 1;
|
|
@@ -10517,8 +10545,8 @@ function parseTranscript(lines, queuedPendingSuppress = /* @__PURE__ */ new Map(
|
|
|
10517
10545
|
}
|
|
10518
10546
|
|
|
10519
10547
|
// app/lib/whatsapp-reader/enrich-attachments.ts
|
|
10520
|
-
import { readFileSync as readFileSync18, readdirSync as
|
|
10521
|
-
import { join as
|
|
10548
|
+
import { readFileSync as readFileSync18, readdirSync as readdirSync13 } from "fs";
|
|
10549
|
+
import { join as join18 } from "path";
|
|
10522
10550
|
var ADMIN_UPLOAD_PATH = /\/uploads\/(?!public\/)([0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12})\//gi;
|
|
10523
10551
|
function adminAttachmentIds(text) {
|
|
10524
10552
|
const ids = [];
|
|
@@ -10531,7 +10559,7 @@ function adminAttachmentIds(text) {
|
|
|
10531
10559
|
function adminAttachmentsFromText(text, uploadsBase) {
|
|
10532
10560
|
const out = [];
|
|
10533
10561
|
for (const id of adminAttachmentIds(text)) {
|
|
10534
|
-
const meta = readAttachmentMeta(
|
|
10562
|
+
const meta = readAttachmentMeta(join18(uploadsBase, id));
|
|
10535
10563
|
if (meta) out.push(meta);
|
|
10536
10564
|
}
|
|
10537
10565
|
return out;
|
|
@@ -10539,7 +10567,7 @@ function adminAttachmentsFromText(text, uploadsBase) {
|
|
|
10539
10567
|
function readSidecar(dir, attachmentId) {
|
|
10540
10568
|
let parsed;
|
|
10541
10569
|
try {
|
|
10542
|
-
parsed = JSON.parse(readFileSync18(
|
|
10570
|
+
parsed = JSON.parse(readFileSync18(join18(dir, `${attachmentId}.meta.json`), "utf8"));
|
|
10543
10571
|
} catch {
|
|
10544
10572
|
return null;
|
|
10545
10573
|
}
|
|
@@ -10562,13 +10590,13 @@ function readAttachmentMeta(dir) {
|
|
|
10562
10590
|
function listSessionAttachmentsInDir(dir) {
|
|
10563
10591
|
let entries;
|
|
10564
10592
|
try {
|
|
10565
|
-
entries =
|
|
10593
|
+
entries = readdirSync13(dir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
10566
10594
|
} catch {
|
|
10567
10595
|
return [];
|
|
10568
10596
|
}
|
|
10569
10597
|
const sidecars = [];
|
|
10570
10598
|
for (const name of entries) {
|
|
10571
|
-
const sidecar = readSidecar(
|
|
10599
|
+
const sidecar = readSidecar(join18(dir, name), name);
|
|
10572
10600
|
if (sidecar) sidecars.push(sidecar);
|
|
10573
10601
|
}
|
|
10574
10602
|
sidecars.sort((a, b) => a.storedAt.localeCompare(b.storedAt));
|
|
@@ -10728,14 +10756,14 @@ app5.get("/conversations", requireAdminSession, async (c) => {
|
|
|
10728
10756
|
}
|
|
10729
10757
|
const cfg = claudeConfigDir();
|
|
10730
10758
|
if (!cfg) return c.json({ conversations: [] });
|
|
10731
|
-
const projectsRoot =
|
|
10759
|
+
const projectsRoot = join19(cfg, "projects");
|
|
10732
10760
|
const userTitles = loadUserTitles(ACCOUNTS_DIR ?? null);
|
|
10733
10761
|
const rows = [];
|
|
10734
10762
|
let sessionRowsExcludedUntagged = 0;
|
|
10735
10763
|
for (const { path: path3 } of enumerateJsonls(projectsRoot)) {
|
|
10736
10764
|
const sessionId = basename4(path3).replace(/\.jsonl$/, "");
|
|
10737
10765
|
const projectDir = dirname5(path3);
|
|
10738
|
-
const meta = readSidecarMeta(
|
|
10766
|
+
const meta = readSidecarMeta(join19(projectDir, `${sessionId}.meta.json`));
|
|
10739
10767
|
if (!isReaderChannelSession(meta.role, meta.channel)) continue;
|
|
10740
10768
|
if (multiAccount) {
|
|
10741
10769
|
if (meta.accountId === null) sessionRowsExcludedUntagged += 1;
|
|
@@ -10827,7 +10855,7 @@ app5.get("/conversations", requireAdminSession, async (c) => {
|
|
|
10827
10855
|
return c.json({ conversations: [...sessionConversations, ...allStoreRows] });
|
|
10828
10856
|
});
|
|
10829
10857
|
function readFrom(path3, from) {
|
|
10830
|
-
const end =
|
|
10858
|
+
const end = statSync7(path3).size;
|
|
10831
10859
|
if (end <= from) return { buf: Buffer.alloc(0), end: from };
|
|
10832
10860
|
const fd = openSync(path3, "r");
|
|
10833
10861
|
try {
|
|
@@ -10912,7 +10940,7 @@ function openTaskKey(turns) {
|
|
|
10912
10940
|
}
|
|
10913
10941
|
function readSubagentMeta(dir, hex) {
|
|
10914
10942
|
try {
|
|
10915
|
-
const m = JSON.parse(readFileSync19(
|
|
10943
|
+
const m = JSON.parse(readFileSync19(join19(dir, `agent-${hex}.meta.json`), "utf8"));
|
|
10916
10944
|
if (typeof m.agentType === "string" && typeof m.description === "string" && typeof m.toolUseId === "string") {
|
|
10917
10945
|
return { agentType: m.agentType, description: m.description, toolUseId: m.toolUseId };
|
|
10918
10946
|
}
|
|
@@ -10935,7 +10963,7 @@ function runActivityTick(c) {
|
|
|
10935
10963
|
c.parentGrewThisTick = false;
|
|
10936
10964
|
let names = [];
|
|
10937
10965
|
try {
|
|
10938
|
-
names =
|
|
10966
|
+
names = readdirSync14(c.subagentsDir).filter((n) => AGENT_JSONL_RE.test(n));
|
|
10939
10967
|
} catch {
|
|
10940
10968
|
}
|
|
10941
10969
|
const entries = [];
|
|
@@ -10944,7 +10972,7 @@ function runActivityTick(c) {
|
|
|
10944
10972
|
let size = 0;
|
|
10945
10973
|
let mtimeMs = 0;
|
|
10946
10974
|
try {
|
|
10947
|
-
const st =
|
|
10975
|
+
const st = statSync7(join19(c.subagentsDir, name));
|
|
10948
10976
|
size = st.size;
|
|
10949
10977
|
mtimeMs = st.mtimeMs;
|
|
10950
10978
|
} catch {
|
|
@@ -10989,11 +11017,11 @@ app5.get("/stream", requireAdminSession, (c) => {
|
|
|
10989
11017
|
const sessionId = c.req.query("sessionId") ?? "";
|
|
10990
11018
|
const projectDir = c.req.query("projectDir") ?? "";
|
|
10991
11019
|
const cfg = claudeConfigDir();
|
|
10992
|
-
const projectsRoot = cfg ? resolve13(
|
|
11020
|
+
const projectsRoot = cfg ? resolve13(join19(cfg, "projects")) : null;
|
|
10993
11021
|
if (!cfg || !projectsRoot || !SESSION_ID_RE2.test(sessionId)) {
|
|
10994
11022
|
return c.json({ error: "bad session reference" }, 400);
|
|
10995
11023
|
}
|
|
10996
|
-
const jsonlPath = resolve13(
|
|
11024
|
+
const jsonlPath = resolve13(join19(projectDir, `${sessionId}.jsonl`));
|
|
10997
11025
|
if (!jsonlPath.startsWith(projectsRoot + sep3)) {
|
|
10998
11026
|
return c.json({ error: "bad session reference" }, 400);
|
|
10999
11027
|
}
|
|
@@ -11012,7 +11040,7 @@ data: ${JSON.stringify(turn)}
|
|
|
11012
11040
|
start(controller) {
|
|
11013
11041
|
const fileEnd0 = (() => {
|
|
11014
11042
|
try {
|
|
11015
|
-
return
|
|
11043
|
+
return statSync7(jsonlPath).size;
|
|
11016
11044
|
} catch {
|
|
11017
11045
|
return 0;
|
|
11018
11046
|
}
|
|
@@ -11020,9 +11048,9 @@ data: ${JSON.stringify(turn)}
|
|
|
11020
11048
|
let offset = resumeOffset(lastEventId, fileEnd0);
|
|
11021
11049
|
console.log(`[wa-stream] op=open conn=${connId} sessionId=${sessionId} channel=reader resume=${offset}`);
|
|
11022
11050
|
const sessionKey = c.req.query("session_key") ?? "";
|
|
11023
|
-
const subagentsDir = resolve13(
|
|
11051
|
+
const subagentsDir = resolve13(join19(projectDir, sessionId, "subagents"));
|
|
11024
11052
|
console.log(
|
|
11025
|
-
`[webchat-activity] op=watch-subagents key=${sessionKey} dir=${subagentsDir} exists=${
|
|
11053
|
+
`[webchat-activity] op=watch-subagents key=${sessionKey} dir=${subagentsDir} exists=${existsSync13(subagentsDir)}`
|
|
11026
11054
|
);
|
|
11027
11055
|
const actx = makeActivityCtx({
|
|
11028
11056
|
subagentsDir,
|
|
@@ -11136,10 +11164,10 @@ app5.get("/directives", requireAdminSession, (c) => {
|
|
|
11136
11164
|
const sessionId = c.req.query("sessionId") ?? "";
|
|
11137
11165
|
if (!SESSION_ID_RE2.test(sessionId)) return c.json({ error: "bad session reference" }, 400);
|
|
11138
11166
|
const dir = directiveStoreDir(sessionId);
|
|
11139
|
-
if (!dir || !
|
|
11167
|
+
if (!dir || !existsSync13(dir)) return c.json({ entries: [] });
|
|
11140
11168
|
let names;
|
|
11141
11169
|
try {
|
|
11142
|
-
names =
|
|
11170
|
+
names = readdirSync14(dir).filter((n) => DIRECTIVE_NAME_RE.test(n));
|
|
11143
11171
|
} catch {
|
|
11144
11172
|
return c.json({ entries: [] });
|
|
11145
11173
|
}
|
|
@@ -11149,7 +11177,7 @@ app5.get("/directives", requireAdminSession, (c) => {
|
|
|
11149
11177
|
const pid = Number(pidPart);
|
|
11150
11178
|
let len = 0;
|
|
11151
11179
|
try {
|
|
11152
|
-
len =
|
|
11180
|
+
len = statSync7(join19(dir, name)).size;
|
|
11153
11181
|
} catch {
|
|
11154
11182
|
}
|
|
11155
11183
|
return { name, secs, pid, ts: Number.isFinite(secs) ? new Date(secs * 1e3).toISOString() : null, len };
|
|
@@ -11164,7 +11192,7 @@ app5.get("/directive", requireAdminSession, (c) => {
|
|
|
11164
11192
|
}
|
|
11165
11193
|
const dir = directiveStoreDir(sessionId);
|
|
11166
11194
|
if (!dir) return c.json({ error: "no account" }, 404);
|
|
11167
|
-
const path3 = resolve13(
|
|
11195
|
+
const path3 = resolve13(join19(dir, name));
|
|
11168
11196
|
if (!path3.startsWith(dir + sep3)) return c.json({ error: "bad reference" }, 400);
|
|
11169
11197
|
let body;
|
|
11170
11198
|
try {
|
|
@@ -11222,7 +11250,7 @@ app5.get("/store-stream", requireAdminSession, (c) => {
|
|
|
11222
11250
|
console.log(`[wa-reader] op=store-quote msgId=${r.msgKeyId} quoted=${!!q}`);
|
|
11223
11251
|
}
|
|
11224
11252
|
if (r.attachmentId) {
|
|
11225
|
-
const meta = readAttachmentMeta(
|
|
11253
|
+
const meta = readAttachmentMeta(join19(uploadsBase, r.attachmentId));
|
|
11226
11254
|
if (meta) return { ...turn, attachments: [meta] };
|
|
11227
11255
|
}
|
|
11228
11256
|
return turn;
|
|
@@ -11255,7 +11283,7 @@ data: ${JSON.stringify(payload)}
|
|
|
11255
11283
|
};
|
|
11256
11284
|
const fileEnd0 = (() => {
|
|
11257
11285
|
try {
|
|
11258
|
-
return
|
|
11286
|
+
return statSync7(file).size;
|
|
11259
11287
|
} catch {
|
|
11260
11288
|
return 0;
|
|
11261
11289
|
}
|
|
@@ -11473,7 +11501,7 @@ app5.post("/reply", requireAdminSession, async (c) => {
|
|
|
11473
11501
|
const absolute = resolved.absolute;
|
|
11474
11502
|
let size = -1;
|
|
11475
11503
|
try {
|
|
11476
|
-
const st =
|
|
11504
|
+
const st = statSync7(absolute);
|
|
11477
11505
|
size = st.isFile() ? st.size : -1;
|
|
11478
11506
|
} catch {
|
|
11479
11507
|
size = -1;
|
|
@@ -11597,8 +11625,8 @@ app5.post("/reply", requireAdminSession, async (c) => {
|
|
|
11597
11625
|
var whatsapp_reader_default = app5;
|
|
11598
11626
|
|
|
11599
11627
|
// server/routes/public-reader.ts
|
|
11600
|
-
import { statSync as
|
|
11601
|
-
import { basename as basename5, dirname as dirname6, join as
|
|
11628
|
+
import { statSync as statSync8, openSync as openSync2, readSync as readSync2, closeSync as closeSync2, watch as watch2, readFileSync as readFileSync20, readdirSync as readdirSync15 } from "fs";
|
|
11629
|
+
import { basename as basename5, dirname as dirname6, join as join20, resolve as resolve14, sep as sep4 } from "path";
|
|
11602
11630
|
|
|
11603
11631
|
// app/lib/whatsapp-reader/delivered-kinds.ts
|
|
11604
11632
|
var PUBLIC_DELIVERED_KINDS = /* @__PURE__ */ new Set([
|
|
@@ -11672,10 +11700,10 @@ function enumeratePublicRows() {
|
|
|
11672
11700
|
const cfg = claudeConfigDir();
|
|
11673
11701
|
if (!cfg) return [];
|
|
11674
11702
|
const rows = [];
|
|
11675
|
-
for (const { path: path3 } of enumerateJsonls(
|
|
11703
|
+
for (const { path: path3 } of enumerateJsonls(join20(cfg, "projects"))) {
|
|
11676
11704
|
const sessionId = basename5(path3).replace(/\.jsonl$/, "");
|
|
11677
11705
|
const projectDir = dirname6(path3);
|
|
11678
|
-
const meta = readSidecarMeta(
|
|
11706
|
+
const meta = readSidecarMeta(join20(projectDir, `${sessionId}.meta.json`));
|
|
11679
11707
|
rows.push({
|
|
11680
11708
|
sessionId,
|
|
11681
11709
|
projectDir,
|
|
@@ -11731,7 +11759,7 @@ function enrichPublicAttachments(turns, sessionAttachments, cursor) {
|
|
|
11731
11759
|
}
|
|
11732
11760
|
}
|
|
11733
11761
|
function readFrom2(path3, from) {
|
|
11734
|
-
const end =
|
|
11762
|
+
const end = statSync8(path3).size;
|
|
11735
11763
|
if (end <= from) return { buf: Buffer.alloc(0), end: from };
|
|
11736
11764
|
const fd = openSync2(path3, "r");
|
|
11737
11765
|
try {
|
|
@@ -11751,15 +11779,15 @@ app6.get("/stream", (c) => {
|
|
|
11751
11779
|
const sessionId = c.req.query("sessionId") ?? "";
|
|
11752
11780
|
const projectDir = c.req.query("projectDir") ?? "";
|
|
11753
11781
|
const cfg = claudeConfigDir();
|
|
11754
|
-
const projectsRoot = cfg ? resolve14(
|
|
11782
|
+
const projectsRoot = cfg ? resolve14(join20(cfg, "projects")) : null;
|
|
11755
11783
|
if (!cfg || !projectsRoot || !SESSION_ID_RE2.test(sessionId)) {
|
|
11756
11784
|
return c.json({ error: "bad session reference" }, 400);
|
|
11757
11785
|
}
|
|
11758
|
-
const jsonlPath = resolve14(
|
|
11786
|
+
const jsonlPath = resolve14(join20(projectDir, `${sessionId}.jsonl`));
|
|
11759
11787
|
if (!jsonlPath.startsWith(projectsRoot + sep4)) {
|
|
11760
11788
|
return c.json({ error: "bad session reference" }, 400);
|
|
11761
11789
|
}
|
|
11762
|
-
const meta = readSidecarMeta(
|
|
11790
|
+
const meta = readSidecarMeta(join20(projectDir, `${sessionId}.meta.json`));
|
|
11763
11791
|
const isPublicWebchat = meta.role === "public" && meta.channel === "webchat";
|
|
11764
11792
|
const owns = visitor.kind === "person" ? meta.personId === visitor.personId : meta.personId === null && meta.visitorId === visitor.visitorId;
|
|
11765
11793
|
if (!(isPublicWebchat && owns)) {
|
|
@@ -11872,7 +11900,7 @@ app6.get("/attachment/:attachmentId", (c) => {
|
|
|
11872
11900
|
let dataFile;
|
|
11873
11901
|
let buffer;
|
|
11874
11902
|
try {
|
|
11875
|
-
dataFile =
|
|
11903
|
+
dataFile = readdirSync15(dir).find((f) => !f.endsWith(".meta.json") && !f.endsWith(EXTRACTED_TEXT_SUFFIX));
|
|
11876
11904
|
if (!dataFile) throw new Error("no data file");
|
|
11877
11905
|
buffer = readFileSync20(resolve14(dir, dataFile));
|
|
11878
11906
|
} catch {
|
|
@@ -11896,16 +11924,16 @@ var public_reader_default = app6;
|
|
|
11896
11924
|
|
|
11897
11925
|
// server/routes/webchat.ts
|
|
11898
11926
|
import { basename as basename6, dirname as dirname7 } from "path";
|
|
11899
|
-
import { join as
|
|
11900
|
-
import { existsSync as
|
|
11927
|
+
import { join as join23 } from "path";
|
|
11928
|
+
import { existsSync as existsSync15, readdirSync as readdirSync17, readFileSync as readFileSync23, renameSync as renameSync4, statSync as statSync9, writeFileSync as writeFileSync8 } from "fs";
|
|
11901
11929
|
|
|
11902
11930
|
// server/canonical-webchat-override.ts
|
|
11903
11931
|
import { readFileSync as readFileSync21, writeFileSync as writeFileSync6, renameSync as renameSync2 } from "fs";
|
|
11904
|
-
import { join as
|
|
11932
|
+
import { join as join21 } from "path";
|
|
11905
11933
|
var FILE = "canonical-webchat-session.json";
|
|
11906
11934
|
var UUID = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
|
|
11907
11935
|
function canonicalOverridePath(accountDir) {
|
|
11908
|
-
return
|
|
11936
|
+
return join21(accountDir, FILE);
|
|
11909
11937
|
}
|
|
11910
11938
|
function readRaw(accountDir) {
|
|
11911
11939
|
try {
|
|
@@ -11984,8 +12012,8 @@ function isNewSessionEffortLevel(value) {
|
|
|
11984
12012
|
}
|
|
11985
12013
|
|
|
11986
12014
|
// ../services/claude-session-manager/src/sidecar-store.ts
|
|
11987
|
-
import { existsSync as
|
|
11988
|
-
import { join as
|
|
12015
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync4, readdirSync as readdirSync16, readFileSync as readFileSync22, renameSync as renameSync3, unlinkSync as unlinkSync2, writeFileSync as writeFileSync7 } from "fs";
|
|
12016
|
+
import { join as join22 } from "path";
|
|
11989
12017
|
function escapeRegExp(s) {
|
|
11990
12018
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
11991
12019
|
}
|
|
@@ -11993,7 +12021,7 @@ function createSidecarStore(config) {
|
|
|
11993
12021
|
const { suffix, validate: validate2 } = config;
|
|
11994
12022
|
const suffixRe = new RegExp(`${escapeRegExp(suffix)}$`);
|
|
11995
12023
|
function pathFor(sessionsDir, id) {
|
|
11996
|
-
return
|
|
12024
|
+
return join22(sessionsDir, `${id}${suffix}`);
|
|
11997
12025
|
}
|
|
11998
12026
|
function write(sessionsDir, id, record) {
|
|
11999
12027
|
mkdirSync4(sessionsDir, { recursive: true });
|
|
@@ -12005,7 +12033,7 @@ function createSidecarStore(config) {
|
|
|
12005
12033
|
return { ok: true };
|
|
12006
12034
|
} catch (error) {
|
|
12007
12035
|
try {
|
|
12008
|
-
if (
|
|
12036
|
+
if (existsSync14(tmp)) unlinkSync2(tmp);
|
|
12009
12037
|
} catch {
|
|
12010
12038
|
}
|
|
12011
12039
|
return { ok: false, error };
|
|
@@ -12030,14 +12058,14 @@ function createSidecarStore(config) {
|
|
|
12030
12058
|
function readAll(sessionsDir, onSkip) {
|
|
12031
12059
|
let names;
|
|
12032
12060
|
try {
|
|
12033
|
-
names =
|
|
12061
|
+
names = readdirSync16(sessionsDir, { withFileTypes: true }).filter((entry) => entry.isFile()).map((entry) => entry.name);
|
|
12034
12062
|
} catch {
|
|
12035
12063
|
return [];
|
|
12036
12064
|
}
|
|
12037
12065
|
const out = [];
|
|
12038
12066
|
for (const name of names) {
|
|
12039
12067
|
if (!suffixRe.test(name)) continue;
|
|
12040
|
-
const path3 =
|
|
12068
|
+
const path3 = join22(sessionsDir, name);
|
|
12041
12069
|
let raw;
|
|
12042
12070
|
try {
|
|
12043
12071
|
raw = readFileSync22(path3, "utf8");
|
|
@@ -12061,7 +12089,7 @@ function createSidecarStore(config) {
|
|
|
12061
12089
|
function clear(sessionsDir, id) {
|
|
12062
12090
|
const path3 = pathFor(sessionsDir, id);
|
|
12063
12091
|
try {
|
|
12064
|
-
if (
|
|
12092
|
+
if (existsSync14(path3)) {
|
|
12065
12093
|
unlinkSync2(path3);
|
|
12066
12094
|
return { ok: true, removed: true };
|
|
12067
12095
|
}
|
|
@@ -12114,22 +12142,22 @@ var UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9
|
|
|
12114
12142
|
function locateSession(sessionId) {
|
|
12115
12143
|
const dir = findSessionProjectDir(sessionId);
|
|
12116
12144
|
if (!dir) return { projectDir: null, channel: null, accountId: null };
|
|
12117
|
-
const meta = readSidecarMeta(
|
|
12145
|
+
const meta = readSidecarMeta(join23(dir, `${sessionId}.meta.json`));
|
|
12118
12146
|
return { projectDir: dir, channel: meta.channel, accountId: meta.accountId };
|
|
12119
12147
|
}
|
|
12120
12148
|
function locateSidecar(sessionId) {
|
|
12121
12149
|
const cfg = claudeConfigDir();
|
|
12122
12150
|
if (!cfg) return null;
|
|
12123
|
-
const projectsRoot =
|
|
12151
|
+
const projectsRoot = join23(cfg, "projects");
|
|
12124
12152
|
let slugs;
|
|
12125
12153
|
try {
|
|
12126
|
-
slugs =
|
|
12154
|
+
slugs = readdirSync17(projectsRoot, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
12127
12155
|
} catch {
|
|
12128
12156
|
return null;
|
|
12129
12157
|
}
|
|
12130
12158
|
for (const slug of slugs) {
|
|
12131
|
-
const metaPath =
|
|
12132
|
-
if (
|
|
12159
|
+
const metaPath = join23(projectsRoot, slug, `${sessionId}.meta.json`);
|
|
12160
|
+
if (existsSync15(metaPath)) {
|
|
12133
12161
|
const meta = readSidecarMeta(metaPath);
|
|
12134
12162
|
return { channel: meta.channel, adminUserId: meta.adminUserId, accountId: meta.accountId };
|
|
12135
12163
|
}
|
|
@@ -12141,7 +12169,7 @@ function readTargetOwner(sessionId) {
|
|
|
12141
12169
|
if (sidecar !== null) return { found: true, owner: sidecar.adminUserId };
|
|
12142
12170
|
const { projectDir } = locateSession(sessionId);
|
|
12143
12171
|
if (projectDir !== null) {
|
|
12144
|
-
return { found: true, owner: readSidecarMeta(
|
|
12172
|
+
return { found: true, owner: readSidecarMeta(join23(projectDir, `${sessionId}.meta.json`)).adminUserId };
|
|
12145
12173
|
}
|
|
12146
12174
|
return { found: false, owner: null };
|
|
12147
12175
|
}
|
|
@@ -12155,7 +12183,7 @@ function sessionSidecarExists(sessionId) {
|
|
|
12155
12183
|
function jsonlSizeBytes(projectDir, sessionId) {
|
|
12156
12184
|
if (projectDir === null) return null;
|
|
12157
12185
|
try {
|
|
12158
|
-
return
|
|
12186
|
+
return statSync9(join23(projectDir, `${sessionId}.jsonl`)).size;
|
|
12159
12187
|
} catch {
|
|
12160
12188
|
return null;
|
|
12161
12189
|
}
|
|
@@ -12291,15 +12319,15 @@ function latestAdminWebchatSessionId(requesterUserId, primaryUserId, scopeAccoun
|
|
|
12291
12319
|
const cfg = claudeConfigDir();
|
|
12292
12320
|
if (!cfg) return null;
|
|
12293
12321
|
let best = null;
|
|
12294
|
-
for (const { path: path3, isSubagent, archived } of enumerateJsonls(
|
|
12322
|
+
for (const { path: path3, isSubagent, archived } of enumerateJsonls(join23(cfg, "projects"))) {
|
|
12295
12323
|
if (isSubagent || archived) continue;
|
|
12296
12324
|
const id = basename6(path3).slice(0, -".jsonl".length);
|
|
12297
|
-
const meta = readSidecarMeta(
|
|
12325
|
+
const meta = readSidecarMeta(join23(dirname7(path3), `${id}.meta.json`));
|
|
12298
12326
|
if (meta.role !== "admin" || meta.channel !== "webchat") continue;
|
|
12299
12327
|
if (multiAccount && meta.accountId !== scopeAccountId) continue;
|
|
12300
12328
|
let mtimeMs;
|
|
12301
12329
|
try {
|
|
12302
|
-
mtimeMs =
|
|
12330
|
+
mtimeMs = statSync9(path3).mtimeMs;
|
|
12303
12331
|
} catch {
|
|
12304
12332
|
continue;
|
|
12305
12333
|
}
|
|
@@ -12616,7 +12644,7 @@ ${note}` : note;
|
|
|
12616
12644
|
console.error(`[webchat:settings] op=${op} outcome=refused value=${value} reason=account-unresolved`);
|
|
12617
12645
|
return c.json({ error: "account unresolved" }, 503);
|
|
12618
12646
|
}
|
|
12619
|
-
const accountJsonPath =
|
|
12647
|
+
const accountJsonPath = join23(account.accountDir, "account.json");
|
|
12620
12648
|
try {
|
|
12621
12649
|
const parsed = JSON.parse(readFileSync23(accountJsonPath, "utf8"));
|
|
12622
12650
|
if (op === "model") parsed.adminModel = value;
|
|
@@ -12664,7 +12692,7 @@ ${note}` : note;
|
|
|
12664
12692
|
const cfg2 = claudeConfigDir();
|
|
12665
12693
|
if (cfg2) {
|
|
12666
12694
|
const source2 = resolveBridgeSource(
|
|
12667
|
-
|
|
12695
|
+
join23(cfg2, "sessions"),
|
|
12668
12696
|
target,
|
|
12669
12697
|
(id) => locateSession(id).projectDir !== null
|
|
12670
12698
|
);
|
|
@@ -12696,7 +12724,7 @@ ${note}` : note;
|
|
|
12696
12724
|
const cfg = claudeConfigDir();
|
|
12697
12725
|
let projectDir = null;
|
|
12698
12726
|
if (cfg) {
|
|
12699
|
-
for (const { path: path3 } of enumerateJsonls(
|
|
12727
|
+
for (const { path: path3 } of enumerateJsonls(join23(cfg, "projects"))) {
|
|
12700
12728
|
if (basename6(path3) === `${sessionId}.jsonl`) {
|
|
12701
12729
|
projectDir = dirname7(path3);
|
|
12702
12730
|
break;
|
|
@@ -12704,7 +12732,7 @@ ${note}` : note;
|
|
|
12704
12732
|
}
|
|
12705
12733
|
}
|
|
12706
12734
|
if (source === "latest" && requesterUserId !== null) {
|
|
12707
|
-
const owner = readSidecarMeta(
|
|
12735
|
+
const owner = readSidecarMeta(join23(projectDir ?? "", `${sessionId}.meta.json`)).adminUserId;
|
|
12708
12736
|
if (owner !== null && owner !== requesterUserId && requesterUserId !== primaryUserId) {
|
|
12709
12737
|
console.error(`[webchat:inbound] op=session-resolve-foreign key=${sessionId.slice(0, 8)} owner=${owner.slice(0, 8)} requester=${requesterUserId.slice(0, 8)}`);
|
|
12710
12738
|
}
|
|
@@ -12736,8 +12764,8 @@ ${note}` : note;
|
|
|
12736
12764
|
import { resolve as resolve15 } from "path";
|
|
12737
12765
|
|
|
12738
12766
|
// app/lib/claude-agent/specialist-roster.ts
|
|
12739
|
-
import { existsSync as
|
|
12740
|
-
import { join as
|
|
12767
|
+
import { existsSync as existsSync16, readFileSync as readFileSync24, readdirSync as readdirSync18 } from "fs";
|
|
12768
|
+
import { join as join24 } from "path";
|
|
12741
12769
|
function field(fm, name) {
|
|
12742
12770
|
const m = fm.match(new RegExp(`^${name}:\\s*(.*?)\\r?$`, "m"));
|
|
12743
12771
|
if (!m) return null;
|
|
@@ -12748,15 +12776,15 @@ function field(fm, name) {
|
|
|
12748
12776
|
return value || null;
|
|
12749
12777
|
}
|
|
12750
12778
|
function readSpecialistRoster(specialistsDir) {
|
|
12751
|
-
if (!
|
|
12752
|
-
const entries =
|
|
12779
|
+
if (!existsSync16(specialistsDir)) return { specialists: [], skipped: [] };
|
|
12780
|
+
const entries = readdirSync18(specialistsDir);
|
|
12753
12781
|
const specialists = [];
|
|
12754
12782
|
const skipped = [];
|
|
12755
12783
|
for (const file of entries.sort()) {
|
|
12756
12784
|
if (!file.endsWith(".md")) continue;
|
|
12757
12785
|
let raw;
|
|
12758
12786
|
try {
|
|
12759
|
-
raw = readFileSync24(
|
|
12787
|
+
raw = readFileSync24(join24(specialistsDir, file), "utf-8");
|
|
12760
12788
|
} catch (err) {
|
|
12761
12789
|
skipped.push({ file, reason: err instanceof Error ? err.message : String(err) });
|
|
12762
12790
|
continue;
|
|
@@ -12873,8 +12901,8 @@ var webchat_greeting_default = app7;
|
|
|
12873
12901
|
|
|
12874
12902
|
// server/routes/telegram.ts
|
|
12875
12903
|
import { homedir as homedir2 } from "os";
|
|
12876
|
-
import { resolve as resolve16, join as
|
|
12877
|
-
import { existsSync as
|
|
12904
|
+
import { resolve as resolve16, join as join25 } from "path";
|
|
12905
|
+
import { existsSync as existsSync17, readFileSync as readFileSync25 } from "fs";
|
|
12878
12906
|
|
|
12879
12907
|
// app/lib/telegram/gateway/instance.ts
|
|
12880
12908
|
var instance = null;
|
|
@@ -12933,8 +12961,8 @@ function routeTelegramUpdate(input) {
|
|
|
12933
12961
|
var TAG27 = "[telegram-inbound]";
|
|
12934
12962
|
function configDirName() {
|
|
12935
12963
|
const platformRoot5 = process.env.MAXY_PLATFORM_ROOT ?? resolve16(process.cwd(), "..");
|
|
12936
|
-
const brandPath =
|
|
12937
|
-
if (
|
|
12964
|
+
const brandPath = join25(platformRoot5, "config", "brand.json");
|
|
12965
|
+
if (existsSync17(brandPath)) {
|
|
12938
12966
|
try {
|
|
12939
12967
|
return JSON.parse(readFileSync25(brandPath, "utf-8")).configDir ?? ".maxy";
|
|
12940
12968
|
} catch {
|
|
@@ -12955,7 +12983,7 @@ app8.post("/", async (c) => {
|
|
|
12955
12983
|
return c.json({ ok: false }, 400);
|
|
12956
12984
|
}
|
|
12957
12985
|
const sp = secretPath(botType);
|
|
12958
|
-
if (!
|
|
12986
|
+
if (!existsSync17(sp)) {
|
|
12959
12987
|
console.error(`${TAG27} op=reject reason=no-secret-file botType=${botType}`);
|
|
12960
12988
|
return c.json({ ok: false }, 401);
|
|
12961
12989
|
}
|
|
@@ -13022,21 +13050,21 @@ app8.post("/", async (c) => {
|
|
|
13022
13050
|
var telegram_default = app8;
|
|
13023
13051
|
|
|
13024
13052
|
// server/routes/quickbooks.ts
|
|
13025
|
-
import { join as
|
|
13026
|
-
import { existsSync as
|
|
13053
|
+
import { join as join26 } from "path";
|
|
13054
|
+
import { existsSync as existsSync18, readFileSync as readFileSync26, writeFileSync as writeFileSync9, mkdirSync as mkdirSync5, rmSync, renameSync as renameSync5 } from "fs";
|
|
13027
13055
|
var TAG28 = "[quickbooks]";
|
|
13028
13056
|
var INTUIT_TOKEN_URL = "https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer";
|
|
13029
13057
|
var STATE_RE = /^[A-Za-z0-9_-]+$/;
|
|
13030
13058
|
function pendingPath(accountDir, state) {
|
|
13031
|
-
return
|
|
13059
|
+
return join26(accountDir, "secrets", "quickbooks-pending", `${state}.json`);
|
|
13032
13060
|
}
|
|
13033
13061
|
function storePath(accountDir) {
|
|
13034
|
-
return
|
|
13062
|
+
return join26(accountDir, "secrets", "quickbooks.json");
|
|
13035
13063
|
}
|
|
13036
13064
|
async function completeConsent(args) {
|
|
13037
13065
|
const { accountDir, code, realmId } = args;
|
|
13038
13066
|
const state = args.state;
|
|
13039
|
-
if (!state || !STATE_RE.test(state) || !
|
|
13067
|
+
if (!state || !STATE_RE.test(state) || !existsSync18(pendingPath(accountDir, state))) {
|
|
13040
13068
|
console.error(`${TAG28} op=callback state=${state ?? ""} stateValid=false realmId=${realmId ?? ""}`);
|
|
13041
13069
|
return { ok: false, status: 400, message: "Invalid or unknown authorization state.", stateValid: false };
|
|
13042
13070
|
}
|
|
@@ -13063,7 +13091,7 @@ async function completeConsent(args) {
|
|
|
13063
13091
|
if (!code || !realmId) {
|
|
13064
13092
|
return { ok: false, status: 400, message: "Missing code or realmId in the callback.", stateValid: true };
|
|
13065
13093
|
}
|
|
13066
|
-
if (!
|
|
13094
|
+
if (!existsSync18(storePath(accountDir))) {
|
|
13067
13095
|
return { ok: false, status: 500, message: "No QuickBooks credentials are stored for this account.", stateValid: true };
|
|
13068
13096
|
}
|
|
13069
13097
|
const store2 = JSON.parse(readFileSync26(storePath(accountDir), "utf-8"));
|
|
@@ -13098,7 +13126,7 @@ async function completeConsent(args) {
|
|
|
13098
13126
|
refreshTokenExpiry: now + (body.x_refresh_token_expires_in ?? 864e4) * 1e3,
|
|
13099
13127
|
lastRefresh: now
|
|
13100
13128
|
};
|
|
13101
|
-
mkdirSync5(
|
|
13129
|
+
mkdirSync5(join26(accountDir, "secrets"), { recursive: true });
|
|
13102
13130
|
writeFileSync9(storePath(accountDir), JSON.stringify(store2, null, 2), { mode: 384 });
|
|
13103
13131
|
const persisted = JSON.parse(readFileSync26(storePath(accountDir), "utf-8")).connections?.[realmId]?.refreshToken === body.refresh_token;
|
|
13104
13132
|
console.error(`${TAG28} op=token-exchange realmId=${realmId} persisted=${persisted}`);
|
|
@@ -13131,7 +13159,7 @@ var quickbooks_default = app9;
|
|
|
13131
13159
|
|
|
13132
13160
|
// server/routes/onboarding.ts
|
|
13133
13161
|
import { spawn, spawnSync as spawnSync2, execFileSync as execFileSync3 } from "child_process";
|
|
13134
|
-
import { openSync as openSync3, closeSync as closeSync3, writeFileSync as writeFileSync11, writeSync, existsSync as
|
|
13162
|
+
import { openSync as openSync3, closeSync as closeSync3, writeFileSync as writeFileSync11, writeSync, existsSync as existsSync20, readFileSync as readFileSync28, unlinkSync as unlinkSync3, renameSync as renameSync7 } from "fs";
|
|
13135
13163
|
import { createHash as createHash4, randomUUID as randomUUID8 } from "crypto";
|
|
13136
13164
|
|
|
13137
13165
|
// app/lib/claude-spawn-env.ts
|
|
@@ -13140,7 +13168,7 @@ function claudeBin() {
|
|
|
13140
13168
|
}
|
|
13141
13169
|
|
|
13142
13170
|
// server/routes/onboarding.ts
|
|
13143
|
-
import { dirname as dirname9, join as
|
|
13171
|
+
import { dirname as dirname9, join as join28 } from "path";
|
|
13144
13172
|
|
|
13145
13173
|
// app/lib/claude-keychain.ts
|
|
13146
13174
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
@@ -13269,8 +13297,8 @@ function readHostCredsBlob(service) {
|
|
|
13269
13297
|
}
|
|
13270
13298
|
|
|
13271
13299
|
// ../lib/admins-write/src/index.ts
|
|
13272
|
-
import { existsSync as
|
|
13273
|
-
import { dirname as dirname8, join as
|
|
13300
|
+
import { existsSync as existsSync19, readFileSync as readFileSync27, writeFileSync as writeFileSync10, renameSync as renameSync6, mkdirSync as mkdirSync6, readdirSync as readdirSync19, statSync as statSync10, appendFileSync as appendFileSync3 } from "fs";
|
|
13301
|
+
import { dirname as dirname8, join as join27 } from "path";
|
|
13274
13302
|
function id8(value) {
|
|
13275
13303
|
return value.slice(0, 8);
|
|
13276
13304
|
}
|
|
@@ -13311,7 +13339,7 @@ function writeAdminEntry(input) {
|
|
|
13311
13339
|
const result = { usersJsonResult: "noop", accountJsonResult: "noop" };
|
|
13312
13340
|
try {
|
|
13313
13341
|
let users = [];
|
|
13314
|
-
if (
|
|
13342
|
+
if (existsSync19(input.usersFile)) {
|
|
13315
13343
|
const raw = readFileSync27(input.usersFile, "utf-8").trim();
|
|
13316
13344
|
if (raw) {
|
|
13317
13345
|
const parsed = JSON.parse(raw);
|
|
@@ -13343,8 +13371,8 @@ function writeAdminEntry(input) {
|
|
|
13343
13371
|
return result;
|
|
13344
13372
|
}
|
|
13345
13373
|
try {
|
|
13346
|
-
const accountJsonPath =
|
|
13347
|
-
if (!
|
|
13374
|
+
const accountJsonPath = join27(input.accountDir, "account.json");
|
|
13375
|
+
if (!existsSync19(accountJsonPath)) {
|
|
13348
13376
|
throw new Error(`account.json not found at ${accountJsonPath}`);
|
|
13349
13377
|
}
|
|
13350
13378
|
const config = JSON.parse(readFileSync27(accountJsonPath, "utf-8"));
|
|
@@ -13367,7 +13395,7 @@ function writeAdminEntry(input) {
|
|
|
13367
13395
|
function computeAdminStoreDivergence(input) {
|
|
13368
13396
|
const result = { divergences: 0, accountWithoutUsers: [], usersWithoutAccount: [], errors: [] };
|
|
13369
13397
|
const usersUserIds = /* @__PURE__ */ new Set();
|
|
13370
|
-
if (
|
|
13398
|
+
if (existsSync19(input.usersFile)) {
|
|
13371
13399
|
try {
|
|
13372
13400
|
const raw = readFileSync27(input.usersFile, "utf-8").trim();
|
|
13373
13401
|
if (raw) {
|
|
@@ -13381,24 +13409,24 @@ function computeAdminStoreDivergence(input) {
|
|
|
13381
13409
|
}
|
|
13382
13410
|
}
|
|
13383
13411
|
const accountUserIds = /* @__PURE__ */ new Set();
|
|
13384
|
-
if (
|
|
13412
|
+
if (existsSync19(input.accountsDir)) {
|
|
13385
13413
|
let entries;
|
|
13386
13414
|
try {
|
|
13387
|
-
entries =
|
|
13415
|
+
entries = readdirSync19(input.accountsDir);
|
|
13388
13416
|
} catch (err) {
|
|
13389
13417
|
result.errors.push({ source: input.accountsDir, detail: err instanceof Error ? err.message : String(err) });
|
|
13390
13418
|
return result;
|
|
13391
13419
|
}
|
|
13392
13420
|
for (const entry of entries) {
|
|
13393
13421
|
if (entry.startsWith(".")) continue;
|
|
13394
|
-
const accountDir =
|
|
13422
|
+
const accountDir = join27(input.accountsDir, entry);
|
|
13395
13423
|
try {
|
|
13396
|
-
if (!
|
|
13424
|
+
if (!statSync10(accountDir).isDirectory()) continue;
|
|
13397
13425
|
} catch {
|
|
13398
13426
|
continue;
|
|
13399
13427
|
}
|
|
13400
|
-
const accountJsonPath =
|
|
13401
|
-
if (!
|
|
13428
|
+
const accountJsonPath = join27(accountDir, "account.json");
|
|
13429
|
+
if (!existsSync19(accountJsonPath)) continue;
|
|
13402
13430
|
let admins = [];
|
|
13403
13431
|
try {
|
|
13404
13432
|
const config = JSON.parse(readFileSync27(accountJsonPath, "utf-8"));
|
|
@@ -13449,7 +13477,7 @@ function hashPin2(pin) {
|
|
|
13449
13477
|
return createHash4("sha256").update(pin).digest("hex");
|
|
13450
13478
|
}
|
|
13451
13479
|
function readUsersFile2() {
|
|
13452
|
-
if (!
|
|
13480
|
+
if (!existsSync20(USERS_FILE)) return null;
|
|
13453
13481
|
const raw = readFileSync28(USERS_FILE, "utf-8").trim();
|
|
13454
13482
|
if (!raw) return [];
|
|
13455
13483
|
return JSON.parse(raw);
|
|
@@ -13509,7 +13537,7 @@ app10.post("/claude-auth", async (c) => {
|
|
|
13509
13537
|
} catch (err) {
|
|
13510
13538
|
logoutError = err instanceof Error ? err.message : String(err);
|
|
13511
13539
|
}
|
|
13512
|
-
const credentialsPresent =
|
|
13540
|
+
const credentialsPresent = existsSync20(CLAUDE_CREDENTIALS_FILE);
|
|
13513
13541
|
const ranMs = Date.now() - start;
|
|
13514
13542
|
console.log(`[onboarding] op=claude-logout credentialsPresent=${credentialsPresent} ranMs=${ranMs} logoutError=${logoutError ? JSON.stringify(logoutError.slice(0, 120)) : "none"}`);
|
|
13515
13543
|
return c.json({ logged_out: !credentialsPresent });
|
|
@@ -13575,7 +13603,7 @@ app10.post("/claude-auth", async (c) => {
|
|
|
13575
13603
|
});
|
|
13576
13604
|
persistKeychainService(
|
|
13577
13605
|
writebackResult,
|
|
13578
|
-
(service) => writeFileSync11(
|
|
13606
|
+
(service) => writeFileSync11(join28(dirname9(CLAUDE_CREDENTIALS_FILE), ".keychain-service"), service, { mode: 384 }),
|
|
13579
13607
|
(line) => console.log(line)
|
|
13580
13608
|
);
|
|
13581
13609
|
if (darwinAuthChild === claudeProc2) darwinAuthChild = null;
|
|
@@ -13658,7 +13686,7 @@ app10.post("/set-pin", async (c) => {
|
|
|
13658
13686
|
console.log(`[set-pin] wrote users.json + account.json admins: userId=${userId.slice(0, 8)}\u2026 role=owner`);
|
|
13659
13687
|
if (process.platform === "linux") {
|
|
13660
13688
|
let installOwner = null;
|
|
13661
|
-
if (
|
|
13689
|
+
if (existsSync20(INSTALL_OWNER_FILE)) {
|
|
13662
13690
|
try {
|
|
13663
13691
|
const raw = readFileSync28(INSTALL_OWNER_FILE, "utf-8").trim();
|
|
13664
13692
|
if (raw.length > 0) installOwner = raw;
|
|
@@ -13806,7 +13834,7 @@ app10.put("/set-pin", requireAdminSession, async (c) => {
|
|
|
13806
13834
|
console.log(`[set-pin] changed PIN in place: userId=${sessionUserId.slice(0, 8)}\u2026`);
|
|
13807
13835
|
if (process.platform === "linux") {
|
|
13808
13836
|
let installOwner = null;
|
|
13809
|
-
if (
|
|
13837
|
+
if (existsSync20(INSTALL_OWNER_FILE)) {
|
|
13810
13838
|
try {
|
|
13811
13839
|
const raw = readFileSync28(INSTALL_OWNER_FILE, "utf-8").trim();
|
|
13812
13840
|
if (raw.length > 0) installOwner = raw;
|
|
@@ -13840,9 +13868,9 @@ ${body.newPin}
|
|
|
13840
13868
|
var onboarding_default = app10;
|
|
13841
13869
|
|
|
13842
13870
|
// server/routes/client-error.ts
|
|
13843
|
-
import { appendFileSync as appendFileSync4, existsSync as
|
|
13844
|
-
import { join as
|
|
13845
|
-
var CLIENT_ERRORS_LOG =
|
|
13871
|
+
import { appendFileSync as appendFileSync4, existsSync as existsSync21, renameSync as renameSync8, statSync as statSync11 } from "fs";
|
|
13872
|
+
import { join as join29 } from "path";
|
|
13873
|
+
var CLIENT_ERRORS_LOG = join29(LOG_DIR, "client-errors.log");
|
|
13846
13874
|
var MAX_LOG_SIZE = 10 * 1024 * 1024;
|
|
13847
13875
|
var MAX_BODY_SIZE = 8 * 1024;
|
|
13848
13876
|
var MAX_STACK_LEN = 2e3;
|
|
@@ -13890,8 +13918,8 @@ function stackHead(stack) {
|
|
|
13890
13918
|
}
|
|
13891
13919
|
function rotateIfNeeded() {
|
|
13892
13920
|
try {
|
|
13893
|
-
if (!
|
|
13894
|
-
const stats =
|
|
13921
|
+
if (!existsSync21(CLIENT_ERRORS_LOG)) return;
|
|
13922
|
+
const stats = statSync11(CLIENT_ERRORS_LOG);
|
|
13895
13923
|
if (stats.size < MAX_LOG_SIZE) return;
|
|
13896
13924
|
renameSync8(CLIENT_ERRORS_LOG, CLIENT_ERRORS_LOG + ".1");
|
|
13897
13925
|
} catch (err) {
|
|
@@ -14217,18 +14245,18 @@ app13.get("/", requireAdminSession, async (c) => {
|
|
|
14217
14245
|
var accounts_default = app13;
|
|
14218
14246
|
|
|
14219
14247
|
// server/routes/admin/logs.ts
|
|
14220
|
-
import { existsSync as
|
|
14248
|
+
import { existsSync as existsSync23, readdirSync as readdirSync20, readFileSync as readFileSync29, statSync as statSync12 } from "fs";
|
|
14221
14249
|
import { resolve as resolve17, basename as basename7 } from "path";
|
|
14222
14250
|
|
|
14223
14251
|
// app/lib/logs-read-resolve.ts
|
|
14224
|
-
import { existsSync as
|
|
14225
|
-
import { join as
|
|
14252
|
+
import { existsSync as existsSync22 } from "fs";
|
|
14253
|
+
import { join as join30 } from "path";
|
|
14226
14254
|
function resolveSessionLogPaths(filename, logDirs) {
|
|
14227
14255
|
const tried = [filename];
|
|
14228
14256
|
const hits = [];
|
|
14229
14257
|
for (const dir of logDirs) {
|
|
14230
|
-
const fullPath =
|
|
14231
|
-
if (
|
|
14258
|
+
const fullPath = join30(dir, filename);
|
|
14259
|
+
if (existsSync22(fullPath)) {
|
|
14232
14260
|
hits.push({ path: fullPath, dir });
|
|
14233
14261
|
}
|
|
14234
14262
|
}
|
|
@@ -14257,7 +14285,7 @@ app14.get("/", async (c) => {
|
|
|
14257
14285
|
searched.push(filePath);
|
|
14258
14286
|
try {
|
|
14259
14287
|
const buffer = readFileSync29(filePath);
|
|
14260
|
-
const onDiskBytes =
|
|
14288
|
+
const onDiskBytes = statSync12(filePath).size;
|
|
14261
14289
|
const headers = {
|
|
14262
14290
|
"Content-Type": "text/plain; charset=utf-8",
|
|
14263
14291
|
"Content-Length": String(buffer.byteLength)
|
|
@@ -14322,7 +14350,7 @@ app14.get("/", async (c) => {
|
|
|
14322
14350
|
try {
|
|
14323
14351
|
const filename = basename7(hit.path);
|
|
14324
14352
|
const buffer = readFileSync29(hit.path);
|
|
14325
|
-
const onDiskBytes =
|
|
14353
|
+
const onDiskBytes = statSync12(hit.path).size;
|
|
14326
14354
|
const headers = {
|
|
14327
14355
|
"Content-Type": "text/plain; charset=utf-8",
|
|
14328
14356
|
"Content-Length": String(buffer.byteLength)
|
|
@@ -14356,16 +14384,16 @@ app14.get("/", async (c) => {
|
|
|
14356
14384
|
const seen = /* @__PURE__ */ new Set();
|
|
14357
14385
|
const logs = {};
|
|
14358
14386
|
for (const dir of logDirs) {
|
|
14359
|
-
if (!
|
|
14387
|
+
if (!existsSync23(dir)) continue;
|
|
14360
14388
|
let files;
|
|
14361
14389
|
try {
|
|
14362
|
-
files =
|
|
14390
|
+
files = readdirSync20(dir).filter((f) => f.endsWith(".log"));
|
|
14363
14391
|
} catch (err) {
|
|
14364
14392
|
const reason = err instanceof Error ? err.message : String(err);
|
|
14365
14393
|
console.warn(`[admin/logs] readdir-fail dir=${dir} reason=${reason}`);
|
|
14366
14394
|
continue;
|
|
14367
14395
|
}
|
|
14368
|
-
files.filter((f) => !seen.has(f)).map((f) => ({ name: f, mtime:
|
|
14396
|
+
files.filter((f) => !seen.has(f)).map((f) => ({ name: f, mtime: statSync12(resolve17(dir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime).forEach(({ name }) => {
|
|
14369
14397
|
seen.add(name);
|
|
14370
14398
|
try {
|
|
14371
14399
|
const content = readFileSync29(resolve17(dir, name));
|
|
@@ -14408,7 +14436,7 @@ var claude_info_default = app15;
|
|
|
14408
14436
|
|
|
14409
14437
|
// server/routes/admin/attachment.ts
|
|
14410
14438
|
import { readFile as readFile2, readdir } from "fs/promises";
|
|
14411
|
-
import { existsSync as
|
|
14439
|
+
import { existsSync as existsSync24 } from "fs";
|
|
14412
14440
|
import { resolve as resolve18 } from "path";
|
|
14413
14441
|
var app16 = new Hono();
|
|
14414
14442
|
var ATTACHMENT_ID_RE3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
|
|
@@ -14431,12 +14459,12 @@ app16.get("/:attachmentId", requireAdminSession, async (c) => {
|
|
|
14431
14459
|
}
|
|
14432
14460
|
let accountId = pinnedAccountId;
|
|
14433
14461
|
let dir = uploadsDirFor2(accountId, attachmentId);
|
|
14434
|
-
let found =
|
|
14462
|
+
let found = existsSync24(dir);
|
|
14435
14463
|
if (!found) {
|
|
14436
14464
|
for (const candidate of listValidAccounts()) {
|
|
14437
14465
|
if (candidate.accountId === pinnedAccountId) continue;
|
|
14438
14466
|
const candidateDir = uploadsDirFor2(candidate.accountId, attachmentId);
|
|
14439
|
-
if (
|
|
14467
|
+
if (existsSync24(candidateDir)) {
|
|
14440
14468
|
accountId = candidate.accountId;
|
|
14441
14469
|
dir = candidateDir;
|
|
14442
14470
|
found = true;
|
|
@@ -14451,7 +14479,7 @@ app16.get("/:attachmentId", requireAdminSession, async (c) => {
|
|
|
14451
14479
|
return new Response("Not found", { status: 404 });
|
|
14452
14480
|
}
|
|
14453
14481
|
const metaPath = resolve18(dir, `${attachmentId}.meta.json`);
|
|
14454
|
-
if (!
|
|
14482
|
+
if (!existsSync24(metaPath)) {
|
|
14455
14483
|
return new Response("Not found", { status: 404 });
|
|
14456
14484
|
}
|
|
14457
14485
|
let meta;
|
|
@@ -14485,21 +14513,21 @@ var attachment_default = app16;
|
|
|
14485
14513
|
|
|
14486
14514
|
// server/routes/admin/agents.ts
|
|
14487
14515
|
import { resolve as resolve19 } from "path";
|
|
14488
|
-
import { readdirSync as
|
|
14516
|
+
import { readdirSync as readdirSync21, readFileSync as readFileSync30, existsSync as existsSync25, rmSync as rmSync2 } from "fs";
|
|
14489
14517
|
var app17 = new Hono();
|
|
14490
14518
|
app17.get("/", (c) => {
|
|
14491
14519
|
const account = resolveAccount();
|
|
14492
14520
|
if (!account) return c.json({ agents: [] });
|
|
14493
14521
|
const agentsDir = resolve19(account.accountDir, "agents");
|
|
14494
|
-
if (!
|
|
14522
|
+
if (!existsSync25(agentsDir)) return c.json({ agents: [] });
|
|
14495
14523
|
const agents = [];
|
|
14496
14524
|
try {
|
|
14497
|
-
const entries =
|
|
14525
|
+
const entries = readdirSync21(agentsDir, { withFileTypes: true });
|
|
14498
14526
|
for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
14499
14527
|
if (!entry.isDirectory()) continue;
|
|
14500
14528
|
if (entry.name === "admin") continue;
|
|
14501
14529
|
const configPath2 = resolve19(agentsDir, entry.name, "config.json");
|
|
14502
|
-
if (!
|
|
14530
|
+
if (!existsSync25(configPath2)) continue;
|
|
14503
14531
|
try {
|
|
14504
14532
|
const config = JSON.parse(readFileSync30(configPath2, "utf-8"));
|
|
14505
14533
|
agents.push({
|
|
@@ -14528,7 +14556,7 @@ app17.delete("/:slug", async (c) => {
|
|
|
14528
14556
|
return c.json({ error: "Invalid agent slug" }, 400);
|
|
14529
14557
|
}
|
|
14530
14558
|
const agentDir = resolve19(account.accountDir, "agents", slug);
|
|
14531
|
-
if (!
|
|
14559
|
+
if (!existsSync25(agentDir)) {
|
|
14532
14560
|
return c.json({ error: "Agent not found" }, 404);
|
|
14533
14561
|
}
|
|
14534
14562
|
try {
|
|
@@ -14558,7 +14586,7 @@ app17.post("/:slug/project", async (c) => {
|
|
|
14558
14586
|
return c.json({ error: "Invalid agent slug" }, 400);
|
|
14559
14587
|
}
|
|
14560
14588
|
const agentDir = resolve19(account.accountDir, "agents", slug);
|
|
14561
|
-
if (!
|
|
14589
|
+
if (!existsSync25(agentDir)) {
|
|
14562
14590
|
return c.json({ error: "Agent not found on disk" }, 404);
|
|
14563
14591
|
}
|
|
14564
14592
|
try {
|
|
@@ -14574,7 +14602,7 @@ var agents_default = app17;
|
|
|
14574
14602
|
// server/routes/admin/sessions.ts
|
|
14575
14603
|
import crypto2 from "crypto";
|
|
14576
14604
|
import { resolve as resolvePath } from "path";
|
|
14577
|
-
import { existsSync as
|
|
14605
|
+
import { existsSync as existsSync26, mkdirSync as mkdirSync7, createWriteStream } from "fs";
|
|
14578
14606
|
|
|
14579
14607
|
// ../lib/admin-conversation-purge/src/index.ts
|
|
14580
14608
|
async function purgeAdminConversationJsonls(args) {
|
|
@@ -14734,7 +14762,7 @@ function validateAndShapeAttachments(raws, conversationAccountId, sessionId, mes
|
|
|
14734
14762
|
let reason = null;
|
|
14735
14763
|
if (!a.attachmentId || !a.filename || !a.mimeType || !a.storagePath) reason = "schema-fail";
|
|
14736
14764
|
else if (a.accountId !== conversationAccountId) reason = "account-mismatch";
|
|
14737
|
-
else if (!
|
|
14765
|
+
else if (!existsSync26(a.storagePath)) reason = "missing-file";
|
|
14738
14766
|
if (reason) {
|
|
14739
14767
|
invalid++;
|
|
14740
14768
|
try {
|
|
@@ -15260,8 +15288,8 @@ app18.put("/:id/label", requireAdminSession, async (c) => {
|
|
|
15260
15288
|
var sessions_default = app18;
|
|
15261
15289
|
|
|
15262
15290
|
// app/lib/claude-agent/spawn-context.ts
|
|
15263
|
-
import { existsSync as
|
|
15264
|
-
import { dirname as dirname10, resolve as resolve20, join as
|
|
15291
|
+
import { existsSync as existsSync27, readFileSync as readFileSync31, readdirSync as readdirSync22, statSync as statSync13 } from "fs";
|
|
15292
|
+
import { dirname as dirname10, resolve as resolve20, join as join31 } from "path";
|
|
15265
15293
|
async function resolveOwnerProfileBlock(accountId, userId) {
|
|
15266
15294
|
if (!userId) return { ok: false, reason: "missing-user-id" };
|
|
15267
15295
|
try {
|
|
@@ -15302,12 +15330,12 @@ function frontmatterField(manifest, field2) {
|
|
|
15302
15330
|
function extractPluginToolDescriptions(pluginDir) {
|
|
15303
15331
|
const out = /* @__PURE__ */ new Map();
|
|
15304
15332
|
const candidates = [
|
|
15305
|
-
|
|
15306
|
-
|
|
15333
|
+
join31(pluginDir, "mcp/dist/index.js"),
|
|
15334
|
+
join31(pluginDir, "mcp/src/index.ts")
|
|
15307
15335
|
];
|
|
15308
15336
|
let raw = null;
|
|
15309
15337
|
for (const path3 of candidates) {
|
|
15310
|
-
if (!
|
|
15338
|
+
if (!existsSync27(path3)) continue;
|
|
15311
15339
|
try {
|
|
15312
15340
|
raw = readFileSync31(path3, "utf-8");
|
|
15313
15341
|
break;
|
|
@@ -15359,25 +15387,25 @@ function parseSkillPathsFromFrontmatter(fm) {
|
|
|
15359
15387
|
function listPluginDirs() {
|
|
15360
15388
|
const out = /* @__PURE__ */ new Map();
|
|
15361
15389
|
const platformPlugins = resolve20(PLATFORM_ROOT, "plugins");
|
|
15362
|
-
if (
|
|
15363
|
-
for (const name of
|
|
15364
|
-
const dir =
|
|
15390
|
+
if (existsSync27(platformPlugins)) {
|
|
15391
|
+
for (const name of readdirSync22(platformPlugins)) {
|
|
15392
|
+
const dir = join31(platformPlugins, name);
|
|
15365
15393
|
try {
|
|
15366
|
-
if (
|
|
15394
|
+
if (statSync13(dir).isDirectory()) out.set(name, dir);
|
|
15367
15395
|
} catch {
|
|
15368
15396
|
}
|
|
15369
15397
|
}
|
|
15370
15398
|
}
|
|
15371
15399
|
const premiumRoot = resolve20(dirname10(PLATFORM_ROOT), "premium-plugins");
|
|
15372
|
-
if (
|
|
15373
|
-
for (const bundle of
|
|
15374
|
-
const bundlePlugins =
|
|
15375
|
-
if (!
|
|
15400
|
+
if (existsSync27(premiumRoot)) {
|
|
15401
|
+
for (const bundle of readdirSync22(premiumRoot)) {
|
|
15402
|
+
const bundlePlugins = join31(premiumRoot, bundle, "plugins");
|
|
15403
|
+
if (!existsSync27(bundlePlugins)) continue;
|
|
15376
15404
|
try {
|
|
15377
|
-
for (const name of
|
|
15378
|
-
const dir =
|
|
15405
|
+
for (const name of readdirSync22(bundlePlugins)) {
|
|
15406
|
+
const dir = join31(bundlePlugins, name);
|
|
15379
15407
|
try {
|
|
15380
|
-
if (
|
|
15408
|
+
if (statSync13(dir).isDirectory()) out.set(name, dir);
|
|
15381
15409
|
} catch {
|
|
15382
15410
|
}
|
|
15383
15411
|
}
|
|
@@ -15389,7 +15417,7 @@ function listPluginDirs() {
|
|
|
15389
15417
|
}
|
|
15390
15418
|
function readEnabledPlugins(accountId) {
|
|
15391
15419
|
const accountFile = resolve20(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
|
|
15392
|
-
if (!
|
|
15420
|
+
if (!existsSync27(accountFile)) return /* @__PURE__ */ new Set();
|
|
15393
15421
|
try {
|
|
15394
15422
|
const parsed = JSON.parse(readFileSync31(accountFile, "utf-8"));
|
|
15395
15423
|
return new Set(
|
|
@@ -15400,7 +15428,7 @@ function readEnabledPlugins(accountId) {
|
|
|
15400
15428
|
}
|
|
15401
15429
|
}
|
|
15402
15430
|
function readFrontmatter(path3) {
|
|
15403
|
-
if (!
|
|
15431
|
+
if (!existsSync27(path3)) return null;
|
|
15404
15432
|
let raw;
|
|
15405
15433
|
try {
|
|
15406
15434
|
raw = readFileSync31(path3, "utf-8");
|
|
@@ -15418,7 +15446,7 @@ function computeActivePlugins(accountId) {
|
|
|
15418
15446
|
for (const name of Array.from(enabled).sort()) {
|
|
15419
15447
|
const dir = pluginDirs.get(name);
|
|
15420
15448
|
if (!dir) continue;
|
|
15421
|
-
const fm = readFrontmatter(
|
|
15449
|
+
const fm = readFrontmatter(join31(dir, "PLUGIN.md"));
|
|
15422
15450
|
if (!fm) continue;
|
|
15423
15451
|
const description = frontmatterField(`---
|
|
15424
15452
|
${fm}
|
|
@@ -15435,7 +15463,7 @@ ${fm}
|
|
|
15435
15463
|
`plugin-manifest-tool-coverage plugin=${name} tools=${tools.length} with-desc=${withDesc}`
|
|
15436
15464
|
);
|
|
15437
15465
|
if (toolNames.length > 0 && descMap.size === 0) {
|
|
15438
|
-
const hasSource =
|
|
15466
|
+
const hasSource = existsSync27(join31(dir, "mcp/dist/index.js")) || existsSync27(join31(dir, "mcp/src/index.ts"));
|
|
15439
15467
|
if (hasSource) {
|
|
15440
15468
|
console.warn(
|
|
15441
15469
|
`[spawn-context] WARN plugin=${name} mcp source present but tool-description regex matched zero entries \u2014 SDK upgrade may have changed the registration shape`
|
|
@@ -15445,7 +15473,7 @@ ${fm}
|
|
|
15445
15473
|
const skillPaths = parseSkillPathsFromFrontmatter(fm);
|
|
15446
15474
|
const skills = [];
|
|
15447
15475
|
for (const relPath of skillPaths) {
|
|
15448
|
-
const skillPath =
|
|
15476
|
+
const skillPath = join31(dir, relPath);
|
|
15449
15477
|
const skillFm = readFrontmatter(skillPath);
|
|
15450
15478
|
if (!skillFm) continue;
|
|
15451
15479
|
const skillName = frontmatterField(`---
|
|
@@ -15462,10 +15490,10 @@ ${skillFm}
|
|
|
15462
15490
|
}
|
|
15463
15491
|
function computeSpecialistDomains(accountId) {
|
|
15464
15492
|
const specialistsDir = resolve20(PLATFORM_ROOT, "..", "data/accounts", accountId, "specialists", "agents");
|
|
15465
|
-
if (!
|
|
15493
|
+
if (!existsSync27(specialistsDir)) return [];
|
|
15466
15494
|
let entries;
|
|
15467
15495
|
try {
|
|
15468
|
-
entries =
|
|
15496
|
+
entries = readdirSync22(specialistsDir);
|
|
15469
15497
|
} catch {
|
|
15470
15498
|
return [];
|
|
15471
15499
|
}
|
|
@@ -15489,7 +15517,7 @@ function computeSpecialistDomains(accountId) {
|
|
|
15489
15517
|
const out = [];
|
|
15490
15518
|
for (const file of entries.sort()) {
|
|
15491
15519
|
if (!file.endsWith(".md")) continue;
|
|
15492
|
-
const fm = readFrontmatter(
|
|
15520
|
+
const fm = readFrontmatter(join31(specialistsDir, file));
|
|
15493
15521
|
if (!fm) continue;
|
|
15494
15522
|
const wrapped = `---
|
|
15495
15523
|
${fm}
|
|
@@ -15508,7 +15536,7 @@ ${fm}
|
|
|
15508
15536
|
}
|
|
15509
15537
|
function computeDormantPlugins(accountId) {
|
|
15510
15538
|
const accountFile = resolve20(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
|
|
15511
|
-
if (!
|
|
15539
|
+
if (!existsSync27(accountFile)) return [];
|
|
15512
15540
|
let enabled;
|
|
15513
15541
|
try {
|
|
15514
15542
|
const raw = readFileSync31(accountFile, "utf-8");
|
|
@@ -15523,10 +15551,10 @@ function computeDormantPlugins(accountId) {
|
|
|
15523
15551
|
return [];
|
|
15524
15552
|
}
|
|
15525
15553
|
const pluginsDir = resolve20(PLATFORM_ROOT, "plugins");
|
|
15526
|
-
if (!
|
|
15554
|
+
if (!existsSync27(pluginsDir)) return [];
|
|
15527
15555
|
let entries;
|
|
15528
15556
|
try {
|
|
15529
|
-
entries =
|
|
15557
|
+
entries = readdirSync22(pluginsDir);
|
|
15530
15558
|
} catch {
|
|
15531
15559
|
return [];
|
|
15532
15560
|
}
|
|
@@ -15534,7 +15562,7 @@ function computeDormantPlugins(accountId) {
|
|
|
15534
15562
|
for (const name of entries) {
|
|
15535
15563
|
if (enabled.has(name)) continue;
|
|
15536
15564
|
const manifestPath = resolve20(pluginsDir, name, "PLUGIN.md");
|
|
15537
|
-
if (!
|
|
15565
|
+
if (!existsSync27(manifestPath)) continue;
|
|
15538
15566
|
let manifest;
|
|
15539
15567
|
try {
|
|
15540
15568
|
manifest = readFileSync31(manifestPath, "utf-8");
|
|
@@ -15551,11 +15579,11 @@ function computeDormantPlugins(accountId) {
|
|
|
15551
15579
|
}
|
|
15552
15580
|
|
|
15553
15581
|
// server/routes/admin/claude-sessions.ts
|
|
15554
|
-
import { existsSync as
|
|
15582
|
+
import { existsSync as existsSync28, readFileSync as readFileSync32 } from "fs";
|
|
15555
15583
|
import { resolve as resolve21 } from "path";
|
|
15556
15584
|
function readTunnelState(brandConfigDir) {
|
|
15557
15585
|
const statePath = `${process.env.HOME ?? ""}/${brandConfigDir}/cloudflared/tunnel.state`;
|
|
15558
|
-
if (!
|
|
15586
|
+
if (!existsSync28(statePath)) return null;
|
|
15559
15587
|
try {
|
|
15560
15588
|
const parsed = JSON.parse(readFileSync32(statePath, "utf-8"));
|
|
15561
15589
|
const tunnelId = typeof parsed.tunnelId === "string" ? parsed.tunnelId : null;
|
|
@@ -15813,11 +15841,11 @@ app21.post("/", async (c) => {
|
|
|
15813
15841
|
var events_default = app21;
|
|
15814
15842
|
|
|
15815
15843
|
// server/routes/admin/files.ts
|
|
15816
|
-
import { createReadStream as createReadStream2, createWriteStream as createWriteStream2, existsSync as
|
|
15844
|
+
import { createReadStream as createReadStream2, createWriteStream as createWriteStream2, existsSync as existsSync29 } from "fs";
|
|
15817
15845
|
import { readdir as readdir3, readFile as readFile4, stat as stat4, mkdir as mkdir3, unlink as unlink2, rename, rmdir } from "fs/promises";
|
|
15818
15846
|
import { realpathSync as realpathSync6 } from "fs";
|
|
15819
15847
|
import { randomUUID as randomUUID10 } from "crypto";
|
|
15820
|
-
import { basename as basename9, dirname as dirname11, join as
|
|
15848
|
+
import { basename as basename9, dirname as dirname11, join as join33, relative as relative4, resolve as resolve23, sep as sep6 } from "path";
|
|
15821
15849
|
import { Readable as Readable2 } from "stream";
|
|
15822
15850
|
|
|
15823
15851
|
// ../lib/graph-trash/src/index.ts
|
|
@@ -16054,7 +16082,7 @@ async function restoreNode(params) {
|
|
|
16054
16082
|
}
|
|
16055
16083
|
|
|
16056
16084
|
// app/lib/file-delete-cascade.ts
|
|
16057
|
-
var
|
|
16085
|
+
var UUID_RE3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
16058
16086
|
function parseAttachmentPath(relPath) {
|
|
16059
16087
|
const segments = relPath.split("/").filter(Boolean);
|
|
16060
16088
|
if (segments.length !== 5) return null;
|
|
@@ -16062,7 +16090,7 @@ function parseAttachmentPath(relPath) {
|
|
|
16062
16090
|
const accountId = segments[1];
|
|
16063
16091
|
const attachmentId = segments[3];
|
|
16064
16092
|
const filename = segments[4];
|
|
16065
|
-
if (!
|
|
16093
|
+
if (!UUID_RE3.test(accountId) || !UUID_RE3.test(attachmentId)) return null;
|
|
16066
16094
|
const dot = filename.lastIndexOf(".");
|
|
16067
16095
|
if (dot === -1) return null;
|
|
16068
16096
|
const stem = filename.slice(0, dot);
|
|
@@ -16135,7 +16163,7 @@ async function cascadeDeleteDocument(params) {
|
|
|
16135
16163
|
|
|
16136
16164
|
// app/lib/file-index.ts
|
|
16137
16165
|
import * as fsp from "fs/promises";
|
|
16138
|
-
import { resolve as resolve22, relative as relative3, join as
|
|
16166
|
+
import { resolve as resolve22, relative as relative3, join as join32, basename as basename8, extname as extname2, sep as sep5 } from "path";
|
|
16139
16167
|
import { tmpdir as tmpdir2 } from "os";
|
|
16140
16168
|
import { execFile as execFile2 } from "child_process";
|
|
16141
16169
|
import { promisify as promisify2 } from "util";
|
|
@@ -16217,7 +16245,7 @@ async function extractPdf(absolute) {
|
|
|
16217
16245
|
return stdout.trim();
|
|
16218
16246
|
}
|
|
16219
16247
|
async function ocrPdf(absolute) {
|
|
16220
|
-
const outPdf =
|
|
16248
|
+
const outPdf = join32(tmpdir2(), `file-index-ocr-${process.pid}-${Date.now()}.pdf`);
|
|
16221
16249
|
try {
|
|
16222
16250
|
await execFileAsync2(
|
|
16223
16251
|
"ocrmypdf",
|
|
@@ -16279,7 +16307,7 @@ async function readDisplayName(absolute) {
|
|
|
16279
16307
|
const stem = dot === -1 ? base : base.slice(0, dot);
|
|
16280
16308
|
if (base === `${stem}.meta.json`) return null;
|
|
16281
16309
|
try {
|
|
16282
|
-
const raw = await fsp.readFile(
|
|
16310
|
+
const raw = await fsp.readFile(join32(dir, `${stem}.meta.json`), "utf-8");
|
|
16283
16311
|
const meta = JSON.parse(raw);
|
|
16284
16312
|
const dn = meta.displayName ?? meta.filename;
|
|
16285
16313
|
return typeof dn === "string" && dn.length > 0 ? dn : null;
|
|
@@ -16300,7 +16328,7 @@ async function walkSubtree(root, dataRoot, out) {
|
|
|
16300
16328
|
for (const entry of entries) {
|
|
16301
16329
|
if (entry.isSymbolicLink()) continue;
|
|
16302
16330
|
if (entry.isDirectory() && entry.name === ".uploads-tmp") continue;
|
|
16303
|
-
const abs =
|
|
16331
|
+
const abs = join32(root, entry.name);
|
|
16304
16332
|
if (entry.isDirectory()) {
|
|
16305
16333
|
const sub = await walkSubtree(abs, dataRoot, out);
|
|
16306
16334
|
if (!sub.clean) clean = false;
|
|
@@ -16653,10 +16681,10 @@ function buildZip(entries) {
|
|
|
16653
16681
|
|
|
16654
16682
|
// server/routes/admin/files.ts
|
|
16655
16683
|
var UPLOAD_TMP_DIR = ".uploads-tmp";
|
|
16656
|
-
var
|
|
16684
|
+
var UUID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
16657
16685
|
async function readMeta(absDir, baseName) {
|
|
16658
16686
|
try {
|
|
16659
|
-
const raw = await readFile4(
|
|
16687
|
+
const raw = await readFile4(join33(absDir, `${baseName}.meta.json`), "utf8");
|
|
16660
16688
|
const parsed = JSON.parse(raw);
|
|
16661
16689
|
if (typeof parsed?.filename === "string") {
|
|
16662
16690
|
return { filename: parsed.filename, mimeType: typeof parsed.mimeType === "string" ? parsed.mimeType : void 0 };
|
|
@@ -16675,7 +16703,7 @@ async function readAccountNames() {
|
|
|
16675
16703
|
return map;
|
|
16676
16704
|
}
|
|
16677
16705
|
for (const name of names) {
|
|
16678
|
-
if (!
|
|
16706
|
+
if (!UUID_RE4.test(name)) continue;
|
|
16679
16707
|
const configPath2 = resolve23(accountsDir, name, "account.json");
|
|
16680
16708
|
try {
|
|
16681
16709
|
const raw = await readFile4(configPath2, "utf8");
|
|
@@ -16710,8 +16738,8 @@ async function servableFilesIn(dirAbs, uuid) {
|
|
|
16710
16738
|
return out;
|
|
16711
16739
|
}
|
|
16712
16740
|
async function enrich(absolute, entry, accountNames) {
|
|
16713
|
-
if (entry.kind === "directory" &&
|
|
16714
|
-
const dirAbs =
|
|
16741
|
+
if (entry.kind === "directory" && UUID_RE4.test(entry.name)) {
|
|
16742
|
+
const dirAbs = join33(absolute, entry.name);
|
|
16715
16743
|
const meta = await readMeta(dirAbs, entry.name);
|
|
16716
16744
|
if (meta?.filename) {
|
|
16717
16745
|
const servable = await servableFilesIn(dirAbs, entry.name);
|
|
@@ -16720,7 +16748,7 @@ async function enrich(absolute, entry, accountNames) {
|
|
|
16720
16748
|
let size = null;
|
|
16721
16749
|
let modifiedAt = entry.modifiedAt;
|
|
16722
16750
|
try {
|
|
16723
|
-
const st = await stat4(
|
|
16751
|
+
const st = await stat4(join33(dirAbs, innerName));
|
|
16724
16752
|
size = st.size;
|
|
16725
16753
|
modifiedAt = st.mtime.toISOString();
|
|
16726
16754
|
} catch {
|
|
@@ -16745,7 +16773,7 @@ async function enrich(absolute, entry, accountNames) {
|
|
|
16745
16773
|
if (entry.kind === "file") {
|
|
16746
16774
|
const dot = entry.name.lastIndexOf(".");
|
|
16747
16775
|
const base = dot === -1 ? entry.name : entry.name.slice(0, dot);
|
|
16748
|
-
if (
|
|
16776
|
+
if (UUID_RE4.test(base)) {
|
|
16749
16777
|
const meta = await readMeta(absolute, base);
|
|
16750
16778
|
if (meta?.filename) {
|
|
16751
16779
|
entry.displayName = meta.filename;
|
|
@@ -16758,7 +16786,7 @@ async function enrich(absolute, entry, accountNames) {
|
|
|
16758
16786
|
function buildDisplayPath(relPath, accountNames) {
|
|
16759
16787
|
if (relPath === "." || relPath === "") return [];
|
|
16760
16788
|
return relPath.split("/").filter(Boolean).map((seg) => {
|
|
16761
|
-
const dn =
|
|
16789
|
+
const dn = UUID_RE4.test(seg) ? accountNames.get(seg) : void 0;
|
|
16762
16790
|
return dn ? { name: seg, displayName: dn } : { name: seg };
|
|
16763
16791
|
});
|
|
16764
16792
|
}
|
|
@@ -16808,11 +16836,11 @@ function isProtectedFromRename(relPath) {
|
|
|
16808
16836
|
if (segments.length === 3 && segments[0] === "accounts" && segments[2] === "uploads") {
|
|
16809
16837
|
return true;
|
|
16810
16838
|
}
|
|
16811
|
-
if (segments.length === 4 && segments[0] === "accounts" && segments[2] === "uploads" &&
|
|
16839
|
+
if (segments.length === 4 && segments[0] === "accounts" && segments[2] === "uploads" && UUID_RE4.test(segments[3])) {
|
|
16812
16840
|
return true;
|
|
16813
16841
|
}
|
|
16814
16842
|
if (parseAttachmentPath(relPath) !== null) return true;
|
|
16815
|
-
if (
|
|
16843
|
+
if (UUID_RE4.test(base.replace(/\.meta\.json$/, "")) && base.endsWith(".meta.json")) {
|
|
16816
16844
|
return true;
|
|
16817
16845
|
}
|
|
16818
16846
|
return false;
|
|
@@ -16886,16 +16914,16 @@ app22.get("/", requireAdminSession, async (c) => {
|
|
|
16886
16914
|
const isAccountParent = segs.length === 1 && segs[0] === "accounts";
|
|
16887
16915
|
const entries = [];
|
|
16888
16916
|
for (const name of names) {
|
|
16889
|
-
if (
|
|
16917
|
+
if (UUID_RE4.test(name.replace(/\.meta\.json$/, "")) && name.endsWith(".meta.json")) {
|
|
16890
16918
|
continue;
|
|
16891
16919
|
}
|
|
16892
|
-
if (isAccountParent &&
|
|
16920
|
+
if (isAccountParent && UUID_RE4.test(name) && name !== accountId) {
|
|
16893
16921
|
continue;
|
|
16894
16922
|
}
|
|
16895
16923
|
const childRel = relPath === "" || relPath === "." ? name : `${relPath}/${name}`;
|
|
16896
16924
|
const protectedEntry = isProtectedFromDeletion(childRel).protected;
|
|
16897
16925
|
try {
|
|
16898
|
-
const entryPath =
|
|
16926
|
+
const entryPath = join33(absolute, name);
|
|
16899
16927
|
const s = await stat4(entryPath);
|
|
16900
16928
|
entries.push({
|
|
16901
16929
|
name,
|
|
@@ -16958,7 +16986,7 @@ app22.get("/download", requireAdminSession, async (c) => {
|
|
|
16958
16986
|
console.error(`[data] op=scratchpad-no-session sessionId="${sessionId.slice(0, 8)}\u2026"`);
|
|
16959
16987
|
return c.json({ error: "Not found" }, 404);
|
|
16960
16988
|
}
|
|
16961
|
-
const meta = readSidecarMeta(
|
|
16989
|
+
const meta = readSidecarMeta(join33(projectDir, `${sessionId}.meta.json`));
|
|
16962
16990
|
if (!meta.accountId || meta.accountId !== accountId) {
|
|
16963
16991
|
console.error(`[data] account-scope-blocked root="scratchpad" sessionId="${sessionId.slice(0, 8)}\u2026" account=${accountId.slice(0, 8)}\u2026`);
|
|
16964
16992
|
return c.json({ error: "Not found" }, 404);
|
|
@@ -17053,7 +17081,7 @@ async function* walkRegularFiles(dirAbsolute) {
|
|
|
17053
17081
|
const dirents = await readdir3(dirAbsolute, { withFileTypes: true });
|
|
17054
17082
|
for (const d of dirents) {
|
|
17055
17083
|
if (d.isSymbolicLink()) continue;
|
|
17056
|
-
const child =
|
|
17084
|
+
const child = join33(dirAbsolute, d.name);
|
|
17057
17085
|
if (d.isDirectory()) {
|
|
17058
17086
|
yield* walkRegularFiles(child);
|
|
17059
17087
|
continue;
|
|
@@ -17163,7 +17191,7 @@ async function resolveUploadTarget(c, accountId, uid) {
|
|
|
17163
17191
|
const base = resolveOwnAccountWrite(rawDir, accountId, "POST /api/admin/files/upload");
|
|
17164
17192
|
if (!base.ok) return { ok: false, status: base.status, error: base.error };
|
|
17165
17193
|
const relDir = relpath ? dirname11(relpath) : ".";
|
|
17166
|
-
const destRel = relDir === "." ? base.relative :
|
|
17194
|
+
const destRel = relDir === "." ? base.relative : join33(base.relative, relDir);
|
|
17167
17195
|
if (crossesForeignAccountPartition(destRel, accountId)) {
|
|
17168
17196
|
console.error(`[data] account-scope-blocked endpoint="POST /api/admin/files/upload" path="${destRel}" account=${accountId.slice(0, 8)}\u2026`);
|
|
17169
17197
|
return { ok: false, status: 404, error: "Not found" };
|
|
@@ -17237,7 +17265,7 @@ app22.post("/upload", requireAdminSession, async (c) => {
|
|
|
17237
17265
|
});
|
|
17238
17266
|
await unlink2(tmpPath).catch(() => {
|
|
17239
17267
|
});
|
|
17240
|
-
const tempRemoved = !
|
|
17268
|
+
const tempRemoved = !existsSync29(tmpPath);
|
|
17241
17269
|
console.error(`[data-upload] op=cleanup uid=${uid} tempRemoved=${tempRemoved}`);
|
|
17242
17270
|
};
|
|
17243
17271
|
const reader = body.getReader();
|
|
@@ -17311,7 +17339,7 @@ async function discardChunkUpload(uploadId, state) {
|
|
|
17311
17339
|
});
|
|
17312
17340
|
await unlink2(state.tmpPath).catch(() => {
|
|
17313
17341
|
});
|
|
17314
|
-
const tempRemoved = !
|
|
17342
|
+
const tempRemoved = !existsSync29(state.tmpPath);
|
|
17315
17343
|
console.error(`[data-upload] op=cleanup uid=${uploadId} tempRemoved=${tempRemoved}`);
|
|
17316
17344
|
}
|
|
17317
17345
|
async function writeChunkBody(body, out, alreadyReceived, ceiling) {
|
|
@@ -17540,8 +17568,8 @@ app22.delete("/", requireAdminSession, async (c) => {
|
|
|
17540
17568
|
const dot = base.lastIndexOf(".");
|
|
17541
17569
|
const stem = dot === -1 ? base : base.slice(0, dot);
|
|
17542
17570
|
const containerDir = dirname11(absolute);
|
|
17543
|
-
const sidecarPath =
|
|
17544
|
-
const isAttachmentContainer =
|
|
17571
|
+
const sidecarPath = UUID_RE4.test(stem) && base !== `${stem}.meta.json` ? join33(containerDir, `${stem}.meta.json`) : null;
|
|
17572
|
+
const isAttachmentContainer = UUID_RE4.test(stem) && basename9(containerDir) === stem;
|
|
17545
17573
|
await unlink2(absolute);
|
|
17546
17574
|
if (sidecarPath) {
|
|
17547
17575
|
try {
|
|
@@ -17550,7 +17578,7 @@ app22.delete("/", requireAdminSession, async (c) => {
|
|
|
17550
17578
|
}
|
|
17551
17579
|
}
|
|
17552
17580
|
if (isAttachmentContainer) {
|
|
17553
|
-
await unlink2(
|
|
17581
|
+
await unlink2(join33(containerDir, `${stem}${EXTRACTED_TEXT_SUFFIX}`)).catch(() => {
|
|
17554
17582
|
});
|
|
17555
17583
|
await rmdir(containerDir).catch(() => {
|
|
17556
17584
|
});
|
|
@@ -18654,8 +18682,8 @@ function isHiddenByDefault(label) {
|
|
|
18654
18682
|
}
|
|
18655
18683
|
|
|
18656
18684
|
// server/lib/top-level-labels.ts
|
|
18657
|
-
import { readdirSync as
|
|
18658
|
-
import { join as
|
|
18685
|
+
import { readdirSync as readdirSync23, readFileSync as readFileSync33 } from "fs";
|
|
18686
|
+
import { join as join34, resolve as resolve24 } from "path";
|
|
18659
18687
|
var STATIC_TOP_LEVEL_LABELS = Object.freeze(
|
|
18660
18688
|
/* @__PURE__ */ new Set([
|
|
18661
18689
|
// Base-schema infra (schema-base.md has no top-level section).
|
|
@@ -18748,7 +18776,7 @@ function parseTopLevelLabels(content) {
|
|
|
18748
18776
|
}
|
|
18749
18777
|
function resolveReferencesDir() {
|
|
18750
18778
|
if (process.env.MAXY_PLATFORM_ROOT) {
|
|
18751
|
-
return
|
|
18779
|
+
return join34(process.env.MAXY_PLATFORM_ROOT, "plugins", "memory", "references");
|
|
18752
18780
|
}
|
|
18753
18781
|
return resolve24(import.meta.dirname, "../../../plugins/memory/references");
|
|
18754
18782
|
}
|
|
@@ -18756,9 +18784,9 @@ function parseTableTopLevelLabels(referencesDir) {
|
|
|
18756
18784
|
const labels = /* @__PURE__ */ new Set();
|
|
18757
18785
|
const contributingFiles = [];
|
|
18758
18786
|
try {
|
|
18759
|
-
const fileNames =
|
|
18787
|
+
const fileNames = readdirSync23(referencesDir).filter((f) => f.startsWith("schema-") && f.endsWith(".md")).sort();
|
|
18760
18788
|
for (const fileName of fileNames) {
|
|
18761
|
-
const content = readFileSync33(
|
|
18789
|
+
const content = readFileSync33(join34(referencesDir, fileName), "utf-8");
|
|
18762
18790
|
const parsed = parseTopLevelLabels(content);
|
|
18763
18791
|
if (parsed.length > 0) contributingFiles.push(fileName);
|
|
18764
18792
|
for (const label of parsed) labels.add(label);
|
|
@@ -19912,7 +19940,7 @@ var graph_default_view_default = app28;
|
|
|
19912
19940
|
// server/routes/admin/sidebar-artefacts.ts
|
|
19913
19941
|
import { readdir as readdir4, stat as stat5 } from "fs/promises";
|
|
19914
19942
|
import { resolve as resolve25, relative as relative5, isAbsolute as isAbsolute2, sep as sep7, basename as basename10 } from "path";
|
|
19915
|
-
import { existsSync as
|
|
19943
|
+
import { existsSync as existsSync30 } from "fs";
|
|
19916
19944
|
var LIMIT = 50;
|
|
19917
19945
|
var ADMIN_AGENT_FILES = ["IDENTITY.md", "SOUL.md", "KNOWLEDGE.md"];
|
|
19918
19946
|
function toDataRootRelPath(absPath) {
|
|
@@ -20019,7 +20047,7 @@ async function fetchAgentTemplateRows(accountDir) {
|
|
|
20019
20047
|
async function unionSpecialistFilenames(overrideDir, bundledDir) {
|
|
20020
20048
|
const names = /* @__PURE__ */ new Set();
|
|
20021
20049
|
for (const dir of [overrideDir, bundledDir]) {
|
|
20022
|
-
if (!
|
|
20050
|
+
if (!existsSync30(dir)) continue;
|
|
20023
20051
|
try {
|
|
20024
20052
|
const entries = await readdir4(dir);
|
|
20025
20053
|
for (const entry of entries) {
|
|
@@ -20034,7 +20062,7 @@ async function unionSpecialistFilenames(overrideDir, bundledDir) {
|
|
|
20034
20062
|
}
|
|
20035
20063
|
async function readAgentTemplateRow(inp) {
|
|
20036
20064
|
let chosenPath = null;
|
|
20037
|
-
if (
|
|
20065
|
+
if (existsSync30(inp.overridePath)) {
|
|
20038
20066
|
try {
|
|
20039
20067
|
validateFilePathInAccount(inp.overridePath, inp.overrideRoot);
|
|
20040
20068
|
chosenPath = inp.overridePath;
|
|
@@ -20045,7 +20073,7 @@ async function readAgentTemplateRow(inp) {
|
|
|
20045
20073
|
);
|
|
20046
20074
|
return null;
|
|
20047
20075
|
}
|
|
20048
|
-
} else if (
|
|
20076
|
+
} else if (existsSync30(inp.bundledPath)) {
|
|
20049
20077
|
if (!isWithin(inp.bundledPath, inp.bundledRoot)) {
|
|
20050
20078
|
console.error(
|
|
20051
20079
|
`[admin/sidebar-artefacts] agent-template-read-failed agent=${inp.displayName} kind=${inp.logName} error="bundled path outside PLATFORM_ROOT"`
|
|
@@ -20647,12 +20675,12 @@ app37.get("/", async (c) => {
|
|
|
20647
20675
|
var system_stats_default = app37;
|
|
20648
20676
|
|
|
20649
20677
|
// server/routes/admin/health.ts
|
|
20650
|
-
import { existsSync as
|
|
20651
|
-
import { resolve as resolve26, join as
|
|
20678
|
+
import { existsSync as existsSync31, readFileSync as readFileSync34 } from "fs";
|
|
20679
|
+
import { resolve as resolve26, join as join35 } from "path";
|
|
20652
20680
|
var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve26(process.cwd(), "..");
|
|
20653
20681
|
var brandHostname = "maxy";
|
|
20654
|
-
var brandJsonPath =
|
|
20655
|
-
if (
|
|
20682
|
+
var brandJsonPath = join35(PLATFORM_ROOT6, "config", "brand.json");
|
|
20683
|
+
if (existsSync31(brandJsonPath)) {
|
|
20656
20684
|
try {
|
|
20657
20685
|
const brand = JSON.parse(readFileSync34(brandJsonPath, "utf-8"));
|
|
20658
20686
|
if (brand.hostname) brandHostname = brand.hostname;
|
|
@@ -20663,7 +20691,7 @@ var VERSION_FILE = resolve26(PLATFORM_ROOT6, `config/.${brandHostname}-version`)
|
|
|
20663
20691
|
var PROCESS_STARTED_AT = (/* @__PURE__ */ new Date()).toISOString();
|
|
20664
20692
|
var PROBE_TIMEOUT_MS = 1e3;
|
|
20665
20693
|
function readVersion() {
|
|
20666
|
-
if (!
|
|
20694
|
+
if (!existsSync31(VERSION_FILE)) return "unknown";
|
|
20667
20695
|
return readFileSync34(VERSION_FILE, "utf-8").trim() || "unknown";
|
|
20668
20696
|
}
|
|
20669
20697
|
async function probeConversationDb() {
|
|
@@ -21440,8 +21468,8 @@ app45.post("/launch", requireAdminSession, async (c) => {
|
|
|
21440
21468
|
var browser_default = app45;
|
|
21441
21469
|
|
|
21442
21470
|
// server/routes/admin/calendar.ts
|
|
21443
|
-
import { existsSync as
|
|
21444
|
-
import { join as
|
|
21471
|
+
import { existsSync as existsSync32 } from "fs";
|
|
21472
|
+
import { join as join37 } from "path";
|
|
21445
21473
|
|
|
21446
21474
|
// server/lib/calendar-ics.ts
|
|
21447
21475
|
var CRLF = "\r\n";
|
|
@@ -21541,7 +21569,7 @@ function countVEvents(ics) {
|
|
|
21541
21569
|
|
|
21542
21570
|
// server/lib/calendar-availability.ts
|
|
21543
21571
|
import { readFileSync as readFileSync35 } from "fs";
|
|
21544
|
-
import { join as
|
|
21572
|
+
import { join as join36 } from "path";
|
|
21545
21573
|
var AVAILABILITY_FILENAME = "calendar-availability.json";
|
|
21546
21574
|
var REQUIRED_KEYS = [
|
|
21547
21575
|
"timezone",
|
|
@@ -21550,7 +21578,7 @@ var REQUIRED_KEYS = [
|
|
|
21550
21578
|
"weekly"
|
|
21551
21579
|
];
|
|
21552
21580
|
function readAvailabilityConfig(accountDir) {
|
|
21553
|
-
const path3 =
|
|
21581
|
+
const path3 = join36(accountDir, AVAILABILITY_FILENAME);
|
|
21554
21582
|
let raw;
|
|
21555
21583
|
try {
|
|
21556
21584
|
raw = readFileSync35(path3, "utf-8");
|
|
@@ -21912,7 +21940,7 @@ app46.get("/booking-link", requireAdminSession, (c) => {
|
|
|
21912
21940
|
console.error('[calendar] op=booking-link-fail err="no account configured"');
|
|
21913
21941
|
return c.json({ bookingDomain: null });
|
|
21914
21942
|
}
|
|
21915
|
-
if (!
|
|
21943
|
+
if (!existsSync32(join37(account.accountDir, AVAILABILITY_FILENAME))) {
|
|
21916
21944
|
console.log("[calendar] op=booking-link bookingDomain=none source=availability-config");
|
|
21917
21945
|
return c.json({ bookingDomain: null });
|
|
21918
21946
|
}
|
|
@@ -22269,7 +22297,7 @@ app51.post("/", requireAdminSession, async (c) => {
|
|
|
22269
22297
|
var task_time_adjust_default = app51;
|
|
22270
22298
|
|
|
22271
22299
|
// server/routes/admin/activity.ts
|
|
22272
|
-
import { readdirSync as
|
|
22300
|
+
import { readdirSync as readdirSync24 } from "fs";
|
|
22273
22301
|
var app52 = new Hono();
|
|
22274
22302
|
var TAG42 = "[activity]";
|
|
22275
22303
|
function resolveHouseAccountId(accounts) {
|
|
@@ -22285,7 +22313,7 @@ function requestToken() {
|
|
|
22285
22313
|
var short = (id) => id ? id.slice(0, 8) : "unset";
|
|
22286
22314
|
function countAccountDirsOnDisk() {
|
|
22287
22315
|
try {
|
|
22288
|
-
return
|
|
22316
|
+
return readdirSync24(ACCOUNTS_DIR, { withFileTypes: true }).filter(
|
|
22289
22317
|
(e) => e.isDirectory() && !e.name.startsWith(".")
|
|
22290
22318
|
).length;
|
|
22291
22319
|
} catch {
|
|
@@ -22340,8 +22368,10 @@ app52.get("/", requireAdminSession, async (c) => {
|
|
|
22340
22368
|
const untaggedCount = rows.filter((r) => r.accountId === null).length;
|
|
22341
22369
|
const meteringFailed = rows.filter((r) => r.meteringError !== null).length;
|
|
22342
22370
|
const censusAgeMs = census ? Date.now() - census.sampleAtMs : null;
|
|
22371
|
+
const ageNull = rows.filter((r) => r.ageMs === null).length;
|
|
22372
|
+
const sidecarNull = rows.filter((r) => r.sidecarMissing).length;
|
|
22343
22373
|
console.log(
|
|
22344
|
-
`${TAG42} op=census req=${req} ageMs=${censusAgeMs ?? "none"} live=${census?.live ?? "none"} cpuNull=${census?.cpuNull ?? "none"}`
|
|
22374
|
+
`${TAG42} op=census req=${req} ageMs=${censusAgeMs ?? "none"} live=${census?.live ?? "none"} cpuNull=${census?.cpuNull ?? "none"} rows=${rows.length} ageNull=${ageNull} sidecarNull=${sidecarNull}`
|
|
22345
22375
|
);
|
|
22346
22376
|
console.log(
|
|
22347
22377
|
`${TAG42} op=response req=${req} rows=${rows.length} accounts=${valid.length} untagged=${untaggedCount} meteringFailed=${meteringFailed} ms=${Date.now() - start}`
|
|
@@ -22649,7 +22679,7 @@ app56.route("/request-magic-link", request_magic_link_default);
|
|
|
22649
22679
|
var access_default = app56;
|
|
22650
22680
|
|
|
22651
22681
|
// server/routes/sites.ts
|
|
22652
|
-
import { existsSync as
|
|
22682
|
+
import { existsSync as existsSync33, readFileSync as readFileSync36, realpathSync as realpathSync7, statSync as statSync14 } from "fs";
|
|
22653
22683
|
import { resolve as resolve28 } from "path";
|
|
22654
22684
|
var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
|
|
22655
22685
|
var MIME = {
|
|
@@ -22715,7 +22745,7 @@ app57.get("/:rel{.*}", (c) => {
|
|
|
22715
22745
|
}
|
|
22716
22746
|
let stat8;
|
|
22717
22747
|
try {
|
|
22718
|
-
stat8 =
|
|
22748
|
+
stat8 = existsSync33(filePath) ? statSync14(filePath) : null;
|
|
22719
22749
|
} catch {
|
|
22720
22750
|
stat8 = null;
|
|
22721
22751
|
}
|
|
@@ -22734,7 +22764,7 @@ app57.get("/:rel{.*}", (c) => {
|
|
|
22734
22764
|
console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
|
|
22735
22765
|
return c.text("Forbidden", 403);
|
|
22736
22766
|
}
|
|
22737
|
-
if (!
|
|
22767
|
+
if (!existsSync33(filePath)) {
|
|
22738
22768
|
console.error(`[sites] not-found path=${reqPath} status=404`);
|
|
22739
22769
|
return c.text("Not found", 404);
|
|
22740
22770
|
}
|
|
@@ -22865,8 +22895,8 @@ var VISITOR_COOKIE_NAME = "mxy_v";
|
|
|
22865
22895
|
var VISITOR_COOKIE_MAX_AGE_SECONDS = Math.floor(DEFAULT_TTL_MS / 1e3);
|
|
22866
22896
|
|
|
22867
22897
|
// app/lib/brand-config.ts
|
|
22868
|
-
import { existsSync as
|
|
22869
|
-
import { join as
|
|
22898
|
+
import { existsSync as existsSync34, readFileSync as readFileSync38 } from "fs";
|
|
22899
|
+
import { join as join38 } from "path";
|
|
22870
22900
|
var cached2 = null;
|
|
22871
22901
|
var cachedAttempted = false;
|
|
22872
22902
|
function readBrandConfig() {
|
|
@@ -22874,8 +22904,8 @@ function readBrandConfig() {
|
|
|
22874
22904
|
cachedAttempted = true;
|
|
22875
22905
|
const platformRoot5 = process.env.MAXY_PLATFORM_ROOT;
|
|
22876
22906
|
if (!platformRoot5) return null;
|
|
22877
|
-
const brandPath =
|
|
22878
|
-
if (!
|
|
22907
|
+
const brandPath = join38(platformRoot5, "config", "brand.json");
|
|
22908
|
+
if (!existsSync34(brandPath)) return null;
|
|
22879
22909
|
try {
|
|
22880
22910
|
cached2 = JSON.parse(readFileSync38(brandPath, "utf-8"));
|
|
22881
22911
|
return cached2;
|
|
@@ -23366,8 +23396,8 @@ var visitor_event_default = app60;
|
|
|
23366
23396
|
|
|
23367
23397
|
// server/routes/session.ts
|
|
23368
23398
|
import { resolve as resolve29 } from "path";
|
|
23369
|
-
import { existsSync as
|
|
23370
|
-
var
|
|
23399
|
+
import { existsSync as existsSync35, writeFileSync as writeFileSync13, mkdirSync as mkdirSync9 } from "fs";
|
|
23400
|
+
var UUID_RE5 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
23371
23401
|
function writeBrandingCache(accountId, agentSlug, branding) {
|
|
23372
23402
|
try {
|
|
23373
23403
|
const cacheDir = resolve29(MAXY_DIR, "branding-cache", accountId);
|
|
@@ -23382,7 +23412,7 @@ function parseVisitorCookie2(cookieHeader) {
|
|
|
23382
23412
|
const match = cookieHeader.match(/(?:^|;\s*)maxy_visitor=([^;]*)/);
|
|
23383
23413
|
if (!match) return null;
|
|
23384
23414
|
const value = decodeURIComponent(match[1]).trim();
|
|
23385
|
-
return
|
|
23415
|
+
return UUID_RE5.test(value) ? value : null;
|
|
23386
23416
|
}
|
|
23387
23417
|
function parseAccessSessionId2(cookieHeader) {
|
|
23388
23418
|
if (!cookieHeader) return null;
|
|
@@ -23450,7 +23480,7 @@ app61.post("/", async (c) => {
|
|
|
23450
23480
|
let agentConfig = null;
|
|
23451
23481
|
if (account) {
|
|
23452
23482
|
const agentDir = resolve29(account.accountDir, "agents", agentSlug);
|
|
23453
|
-
if (!
|
|
23483
|
+
if (!existsSync35(agentDir) || !existsSync35(resolve29(agentDir, "config.json"))) {
|
|
23454
23484
|
return c.json({ error: "Agent not found" }, 404);
|
|
23455
23485
|
}
|
|
23456
23486
|
agentConfig = resolveAgentConfig(account.accountDir, agentSlug);
|
|
@@ -23480,7 +23510,7 @@ app61.post("/", async (c) => {
|
|
|
23480
23510
|
);
|
|
23481
23511
|
}
|
|
23482
23512
|
}
|
|
23483
|
-
if (body.session_key && typeof body.session_key === "string" &&
|
|
23513
|
+
if (body.session_key && typeof body.session_key === "string" && UUID_RE5.test(body.session_key)) {
|
|
23484
23514
|
if (visitorId) {
|
|
23485
23515
|
const recent = await findRecentConversation(visitorId, accountId, agentSlug).catch(() => null);
|
|
23486
23516
|
if (recent) {
|
|
@@ -23782,8 +23812,8 @@ function startTimeEntryCensus(openSession, opts = {}) {
|
|
|
23782
23812
|
}
|
|
23783
23813
|
|
|
23784
23814
|
// app/lib/ledger-census.ts
|
|
23785
|
-
import { readdirSync as
|
|
23786
|
-
import { join as
|
|
23815
|
+
import { readdirSync as readdirSync25, readFileSync as readFileSync39, statSync as statSync15 } from "fs";
|
|
23816
|
+
import { join as join39 } from "path";
|
|
23787
23817
|
|
|
23788
23818
|
// ../lib/ledger-core/dist/reconcile.js
|
|
23789
23819
|
var LEDGER_INDEX_NAMES = [
|
|
@@ -23831,15 +23861,15 @@ var DAY_MS = 864e5;
|
|
|
23831
23861
|
function countWriteRejects24h(logDir, now) {
|
|
23832
23862
|
let entries;
|
|
23833
23863
|
try {
|
|
23834
|
-
entries =
|
|
23864
|
+
entries = readdirSync25(logDir).filter((f) => f.startsWith("mcp-ledger-") && f.endsWith(".log"));
|
|
23835
23865
|
} catch {
|
|
23836
23866
|
return 0;
|
|
23837
23867
|
}
|
|
23838
23868
|
let total = 0;
|
|
23839
23869
|
for (const name of entries) {
|
|
23840
|
-
const path3 =
|
|
23870
|
+
const path3 = join39(logDir, name);
|
|
23841
23871
|
try {
|
|
23842
|
-
if (now -
|
|
23872
|
+
if (now - statSync15(path3).mtimeMs > DAY_MS) continue;
|
|
23843
23873
|
for (const line of readFileSync39(path3, "utf8").split("\n")) {
|
|
23844
23874
|
if (line.includes("[graph-write] reject")) total += 1;
|
|
23845
23875
|
}
|
|
@@ -24327,8 +24357,8 @@ async function migrateUploads(opts = {}) {
|
|
|
24327
24357
|
|
|
24328
24358
|
// app/lib/migrate-admin-webchat-sidecars.ts
|
|
24329
24359
|
import { readdir as readdir6, readFile as readFile6, rename as rename3, writeFile as writeFile4, unlink as unlink3 } from "fs/promises";
|
|
24330
|
-
import { existsSync as
|
|
24331
|
-
import { join as
|
|
24360
|
+
import { existsSync as existsSync36 } from "fs";
|
|
24361
|
+
import { join as join40 } from "path";
|
|
24332
24362
|
var ADMIN_ROLE2 = "admin";
|
|
24333
24363
|
var WEBCHAT_CHANNEL2 = "webchat";
|
|
24334
24364
|
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;
|
|
@@ -24357,7 +24387,7 @@ async function writeRaw(path3, obj) {
|
|
|
24357
24387
|
await rename3(tmp, path3);
|
|
24358
24388
|
} catch (err) {
|
|
24359
24389
|
try {
|
|
24360
|
-
if (
|
|
24390
|
+
if (existsSync36(tmp)) await unlink3(tmp);
|
|
24361
24391
|
} catch {
|
|
24362
24392
|
}
|
|
24363
24393
|
throw err;
|
|
@@ -24373,7 +24403,7 @@ async function collectLiveSidecars(projectsRoot) {
|
|
|
24373
24403
|
}
|
|
24374
24404
|
for (const slug of slugs) {
|
|
24375
24405
|
if (!slug.isDirectory()) continue;
|
|
24376
|
-
const slugDir =
|
|
24406
|
+
const slugDir = join40(projectsRoot, slug.name);
|
|
24377
24407
|
let entries;
|
|
24378
24408
|
try {
|
|
24379
24409
|
entries = await readdir6(slugDir, { withFileTypes: true });
|
|
@@ -24382,9 +24412,9 @@ async function collectLiveSidecars(projectsRoot) {
|
|
|
24382
24412
|
}
|
|
24383
24413
|
for (const entry of entries) {
|
|
24384
24414
|
if (entry.isFile() && SESSION_META_RE.test(entry.name)) {
|
|
24385
|
-
out.push(
|
|
24415
|
+
out.push(join40(slugDir, entry.name));
|
|
24386
24416
|
} else if (entry.isDirectory() && entry.name === "subagents") {
|
|
24387
|
-
const subDir =
|
|
24417
|
+
const subDir = join40(slugDir, entry.name);
|
|
24388
24418
|
let subs;
|
|
24389
24419
|
try {
|
|
24390
24420
|
subs = await readdir6(subDir, { withFileTypes: true });
|
|
@@ -24392,7 +24422,7 @@ async function collectLiveSidecars(projectsRoot) {
|
|
|
24392
24422
|
continue;
|
|
24393
24423
|
}
|
|
24394
24424
|
for (const s of subs) {
|
|
24395
|
-
if (s.isFile() && SESSION_META_RE.test(s.name)) out.push(
|
|
24425
|
+
if (s.isFile() && SESSION_META_RE.test(s.name)) out.push(join40(subDir, s.name));
|
|
24396
24426
|
}
|
|
24397
24427
|
}
|
|
24398
24428
|
}
|
|
@@ -24404,7 +24434,7 @@ function shortId(path3) {
|
|
|
24404
24434
|
return base.slice(0, 8);
|
|
24405
24435
|
}
|
|
24406
24436
|
async function migrateAdminWebchatSidecars(opts = {}) {
|
|
24407
|
-
const projectsRoot = opts.projectsRoot ?? (process.env.CLAUDE_CONFIG_DIR ?
|
|
24437
|
+
const projectsRoot = opts.projectsRoot ?? (process.env.CLAUDE_CONFIG_DIR ? join40(process.env.CLAUDE_CONFIG_DIR, "projects") : null) ?? "";
|
|
24408
24438
|
const usersFile = opts.usersFile ?? USERS_FILE;
|
|
24409
24439
|
const accountId = opts.accountId ?? resolveAccount()?.accountId ?? null;
|
|
24410
24440
|
const resolveName = opts.resolveName ?? defaultResolveName;
|
|
@@ -26767,12 +26797,12 @@ function startTelegramNativeFileFollower(input) {
|
|
|
26767
26797
|
}
|
|
26768
26798
|
|
|
26769
26799
|
// server/telegram-descriptor.ts
|
|
26770
|
-
import { resolve as resolve34, join as
|
|
26800
|
+
import { resolve as resolve34, join as join41 } from "path";
|
|
26771
26801
|
function telegramGatewayUrl() {
|
|
26772
26802
|
return `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`;
|
|
26773
26803
|
}
|
|
26774
26804
|
function telegramServerPath() {
|
|
26775
|
-
return process.env.MAXY_TELEGRAM_CHANNEL_SERVER_PATH ?? resolve34(process.env.MAXY_PLATFORM_ROOT ??
|
|
26805
|
+
return process.env.MAXY_TELEGRAM_CHANNEL_SERVER_PATH ?? resolve34(process.env.MAXY_PLATFORM_ROOT ?? join41(__dirname, ".."), "services/telegram-channel/dist/server.js");
|
|
26776
26806
|
}
|
|
26777
26807
|
|
|
26778
26808
|
// app/lib/channel-pty-bridge/public-session-end-review.ts
|
|
@@ -27059,7 +27089,7 @@ function broadcastAdminShutdown(reason) {
|
|
|
27059
27089
|
|
|
27060
27090
|
// ../lib/entitlement/src/index.ts
|
|
27061
27091
|
import { createPublicKey, createHash as createHash6, verify as cryptoVerify } from "crypto";
|
|
27062
|
-
import { existsSync as
|
|
27092
|
+
import { existsSync as existsSync37, readFileSync as readFileSync40, statSync as statSync16 } from "fs";
|
|
27063
27093
|
import { resolve as resolve35 } from "path";
|
|
27064
27094
|
|
|
27065
27095
|
// ../lib/entitlement/src/canonicalize.ts
|
|
@@ -27108,10 +27138,10 @@ function resolveEntitlement(brand, account) {
|
|
|
27108
27138
|
return logResolved(implicitTrust(account), null);
|
|
27109
27139
|
}
|
|
27110
27140
|
const entitlementPath = resolve35(brand.configDir, "entitlement.json");
|
|
27111
|
-
if (!
|
|
27141
|
+
if (!existsSync37(entitlementPath)) {
|
|
27112
27142
|
return logResolved(anonymousFallback("missing"), { reason: "missing" });
|
|
27113
27143
|
}
|
|
27114
|
-
const stat8 =
|
|
27144
|
+
const stat8 = statSync16(entitlementPath);
|
|
27115
27145
|
const key = memoKey(stat8.mtimeMs, account);
|
|
27116
27146
|
if (memo && memo.key === key) {
|
|
27117
27147
|
return memo.result;
|
|
@@ -27299,12 +27329,12 @@ function clientFrom(c) {
|
|
|
27299
27329
|
}
|
|
27300
27330
|
installMediaDownloadGuard();
|
|
27301
27331
|
var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT || "";
|
|
27302
|
-
var BRAND_JSON_PATH = PLATFORM_ROOT8 ?
|
|
27332
|
+
var BRAND_JSON_PATH = PLATFORM_ROOT8 ? join42(PLATFORM_ROOT8, "config", "brand.json") : "";
|
|
27303
27333
|
var BRAND = { productName: "Maxy", hostname: "maxy", configDir: ".maxy", marketingUrl: "https://getmaxy.com" };
|
|
27304
|
-
if (BRAND_JSON_PATH && !
|
|
27334
|
+
if (BRAND_JSON_PATH && !existsSync38(BRAND_JSON_PATH)) {
|
|
27305
27335
|
console.error(`[brand] WARNING: brand.json not found at ${BRAND_JSON_PATH} \u2014 using Maxy defaults`);
|
|
27306
27336
|
}
|
|
27307
|
-
if (BRAND_JSON_PATH &&
|
|
27337
|
+
if (BRAND_JSON_PATH && existsSync38(BRAND_JSON_PATH)) {
|
|
27308
27338
|
try {
|
|
27309
27339
|
const parsed = JSON.parse(readFileSync41(BRAND_JSON_PATH, "utf-8"));
|
|
27310
27340
|
BRAND = { ...BRAND, ...parsed };
|
|
@@ -27338,10 +27368,10 @@ var brandLoginOpts = {
|
|
|
27338
27368
|
appleTouchIconPath: brandAppIcon512Path,
|
|
27339
27369
|
themeColor: BRAND.defaultColors?.primary
|
|
27340
27370
|
};
|
|
27341
|
-
var ALIAS_DOMAINS_PATH =
|
|
27371
|
+
var ALIAS_DOMAINS_PATH = join42(homedir4(), BRAND.configDir, "alias-domains.json");
|
|
27342
27372
|
function loadAliasDomains() {
|
|
27343
27373
|
try {
|
|
27344
|
-
if (!
|
|
27374
|
+
if (!existsSync38(ALIAS_DOMAINS_PATH)) return null;
|
|
27345
27375
|
const parsed = JSON.parse(readFileSync41(ALIAS_DOMAINS_PATH, "utf-8"));
|
|
27346
27376
|
if (!Array.isArray(parsed)) {
|
|
27347
27377
|
console.error("[alias-domains] malformed alias-domains.json \u2014 expected array");
|
|
@@ -27406,7 +27436,7 @@ async function recordPassiveDispatch(input) {
|
|
|
27406
27436
|
var waGateway = new WaGateway({
|
|
27407
27437
|
fetchStandingRules: fetchAccountStandingRules,
|
|
27408
27438
|
gatewayUrl: `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`,
|
|
27409
|
-
serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve36(process.env.MAXY_PLATFORM_ROOT ??
|
|
27439
|
+
serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve36(process.env.MAXY_PLATFORM_ROOT ?? join42(__dirname, ".."), "services/whatsapp-channel/dist/server.js"),
|
|
27410
27440
|
// Task 751 / 1390 — file delivery on the native channel. `maxyAccountId` (the
|
|
27411
27441
|
// path-validation scope) is the sender's effective SESSION account, resolved
|
|
27412
27442
|
// once at the inbound gate and threaded here via the gateway's per-sender doc
|
|
@@ -27421,7 +27451,7 @@ var waGateway = new WaGateway({
|
|
|
27421
27451
|
caption,
|
|
27422
27452
|
accountId,
|
|
27423
27453
|
maxyAccountId,
|
|
27424
|
-
platformRoot: resolve36(process.env.MAXY_PLATFORM_ROOT ??
|
|
27454
|
+
platformRoot: resolve36(process.env.MAXY_PLATFORM_ROOT ?? join42(__dirname, ".."))
|
|
27425
27455
|
});
|
|
27426
27456
|
return result.ok ? { ok: true, messageId: result.messageId } : { ok: false, error: result.error };
|
|
27427
27457
|
},
|
|
@@ -27525,7 +27555,7 @@ function runDuplicateSenderAudit() {
|
|
|
27525
27555
|
try {
|
|
27526
27556
|
const configDir2 = process.env.CLAUDE_CONFIG_DIR;
|
|
27527
27557
|
if (!configDir2) return;
|
|
27528
|
-
const projectsRoot =
|
|
27558
|
+
const projectsRoot = join42(configDir2, "projects");
|
|
27529
27559
|
const records = [];
|
|
27530
27560
|
for (const { path: jsonlPath, isSubagent, archived } of enumerateJsonls(projectsRoot)) {
|
|
27531
27561
|
if (isSubagent || archived) continue;
|
|
@@ -28077,7 +28107,7 @@ app63.get("/agent-assets/:slug/:filename", (c) => {
|
|
|
28077
28107
|
console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
|
|
28078
28108
|
return c.text("Forbidden", 403);
|
|
28079
28109
|
}
|
|
28080
|
-
if (!
|
|
28110
|
+
if (!existsSync38(filePath)) {
|
|
28081
28111
|
console.error(`[agent-assets] serve slug=${slug} file=${filename} status=404`);
|
|
28082
28112
|
return c.text("Not found", 404);
|
|
28083
28113
|
}
|
|
@@ -28107,7 +28137,7 @@ app63.get("/generated/:filename", (c) => {
|
|
|
28107
28137
|
console.error(`[generated] serve file=${filename} status=403`);
|
|
28108
28138
|
return c.text("Forbidden", 403);
|
|
28109
28139
|
}
|
|
28110
|
-
if (!
|
|
28140
|
+
if (!existsSync38(filePath)) {
|
|
28111
28141
|
console.error(`[generated] serve file=${filename} status=404`);
|
|
28112
28142
|
return c.text("Not found", 404);
|
|
28113
28143
|
}
|
|
@@ -28127,7 +28157,7 @@ app63.route("/v", visitor_consent_default);
|
|
|
28127
28157
|
var htmlCache = /* @__PURE__ */ new Map();
|
|
28128
28158
|
var brandLogoPath = "/brand/maxy-monochrome.png";
|
|
28129
28159
|
var brandIconPath = "/brand/maxy-monochrome.png";
|
|
28130
|
-
if (BRAND_JSON_PATH &&
|
|
28160
|
+
if (BRAND_JSON_PATH && existsSync38(BRAND_JSON_PATH)) {
|
|
28131
28161
|
try {
|
|
28132
28162
|
const fullBrand = JSON.parse(readFileSync41(BRAND_JSON_PATH, "utf-8"));
|
|
28133
28163
|
if (fullBrand.assets?.logo) brandLogoPath = `/brand/${fullBrand.assets.logo}`;
|
|
@@ -28156,7 +28186,7 @@ var brandScript = `<script>window.__BRAND__=${JSON.stringify({
|
|
|
28156
28186
|
var brandThemeColor = BRAND.defaultColors?.primary ?? "#000000";
|
|
28157
28187
|
var brandBackgroundColor = BRAND.defaultColors?.background ?? "#ffffff";
|
|
28158
28188
|
var brandAppIconsExist = [brandAppIcon192Path, brandAppIcon512Path, brandMaskableIconPath].every(
|
|
28159
|
-
(p) =>
|
|
28189
|
+
(p) => existsSync38(resolve36(process.cwd(), "public", p.replace(/^\//, "")))
|
|
28160
28190
|
);
|
|
28161
28191
|
var SW_SOURCE = (() => {
|
|
28162
28192
|
try {
|
|
@@ -28168,8 +28198,8 @@ var SW_SOURCE = (() => {
|
|
|
28168
28198
|
function readInstalledVersion() {
|
|
28169
28199
|
try {
|
|
28170
28200
|
if (!PLATFORM_ROOT8) return "unknown";
|
|
28171
|
-
const versionFile =
|
|
28172
|
-
if (!
|
|
28201
|
+
const versionFile = join42(PLATFORM_ROOT8, "config", `.${BRAND.hostname}-version`);
|
|
28202
|
+
if (!existsSync38(versionFile)) return "unknown";
|
|
28173
28203
|
const content = readFileSync41(versionFile, "utf-8").trim();
|
|
28174
28204
|
return content || "unknown";
|
|
28175
28205
|
} catch {
|
|
@@ -28228,12 +28258,12 @@ ${clientErrorReporterScript}
|
|
|
28228
28258
|
return html;
|
|
28229
28259
|
}
|
|
28230
28260
|
function loadBrandingCache(agentSlug) {
|
|
28231
|
-
const configDir2 =
|
|
28261
|
+
const configDir2 = join42(homedir4(), BRAND.configDir);
|
|
28232
28262
|
try {
|
|
28233
28263
|
const accountId = getDefaultAccountId();
|
|
28234
28264
|
if (!accountId) return null;
|
|
28235
|
-
const cachePath =
|
|
28236
|
-
if (!
|
|
28265
|
+
const cachePath = join42(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
|
|
28266
|
+
if (!existsSync38(cachePath)) return null;
|
|
28237
28267
|
return JSON.parse(readFileSync41(cachePath, "utf-8"));
|
|
28238
28268
|
} catch {
|
|
28239
28269
|
return null;
|
|
@@ -28466,11 +28496,11 @@ var hostname = process.env.HOSTNAME ?? "127.0.0.1";
|
|
|
28466
28496
|
var httpServer = serve({ fetch: app63.fetch, port, hostname });
|
|
28467
28497
|
console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
28468
28498
|
{
|
|
28469
|
-
const reconcilePlatformRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
28499
|
+
const reconcilePlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join42(__dirname, "..");
|
|
28470
28500
|
const reconcileScript = resolve36(reconcilePlatformRoot, "plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js");
|
|
28471
28501
|
const RECONCILE_INTERVAL_MS = 12e4;
|
|
28472
28502
|
const runReconcile = () => {
|
|
28473
|
-
if (!
|
|
28503
|
+
if (!existsSync38(reconcileScript)) return;
|
|
28474
28504
|
try {
|
|
28475
28505
|
const child = spawn3(process.execPath, [reconcileScript], {
|
|
28476
28506
|
env: { ...process.env, PLATFORM_ROOT: reconcilePlatformRoot },
|
|
@@ -28488,11 +28518,11 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
28488
28518
|
loop.unref();
|
|
28489
28519
|
}
|
|
28490
28520
|
{
|
|
28491
|
-
const outlookPlatformRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
28521
|
+
const outlookPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join42(__dirname, "..");
|
|
28492
28522
|
const outlookScript = resolve36(outlookPlatformRoot, "plugins/outlook/mcp/dist/scripts/complete-registration.js");
|
|
28493
28523
|
const OUTLOOK_COMPLETE_INTERVAL_MS = 3e4;
|
|
28494
28524
|
const runOutlookComplete = () => {
|
|
28495
|
-
if (!
|
|
28525
|
+
if (!existsSync38(outlookScript)) return;
|
|
28496
28526
|
try {
|
|
28497
28527
|
const child = spawn3(process.execPath, [outlookScript], {
|
|
28498
28528
|
env: { ...process.env, PLATFORM_ROOT: outlookPlatformRoot },
|
|
@@ -28510,20 +28540,20 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
28510
28540
|
outlookLoop.unref();
|
|
28511
28541
|
}
|
|
28512
28542
|
{
|
|
28513
|
-
const auditRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
28543
|
+
const auditRoot = process.env.MAXY_PLATFORM_ROOT ?? join42(__dirname, "..");
|
|
28514
28544
|
const strandedAccountsDir = resolve36(auditRoot, "..", "data/accounts");
|
|
28515
28545
|
const STRANDED_AUDIT_INTERVAL_MS = 3e5;
|
|
28516
28546
|
const STRANDED_AGE_MS = 16 * 6e4;
|
|
28517
28547
|
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;
|
|
28518
28548
|
const runStrandedAudit = () => {
|
|
28519
28549
|
try {
|
|
28520
|
-
if (!
|
|
28550
|
+
if (!existsSync38(strandedAccountsDir)) return;
|
|
28521
28551
|
const now = Date.now();
|
|
28522
|
-
for (const name of
|
|
28552
|
+
for (const name of readdirSync26(strandedAccountsDir)) {
|
|
28523
28553
|
if (!STRANDED_UUID_RE.test(name)) continue;
|
|
28524
28554
|
const pendingPath2 = resolve36(strandedAccountsDir, name, "secrets/outlook/pending-devicecode.enc");
|
|
28525
|
-
if (!
|
|
28526
|
-
const ageMs = now -
|
|
28555
|
+
if (!existsSync38(pendingPath2)) continue;
|
|
28556
|
+
const ageMs = now - statSync17(pendingPath2).mtimeMs;
|
|
28527
28557
|
if (ageMs > STRANDED_AGE_MS) {
|
|
28528
28558
|
console.error(`[outlook-mcp] devicecode-stranded account=${name} ageSec=${Math.floor(ageMs / 1e3)}`);
|
|
28529
28559
|
}
|
|
@@ -28538,7 +28568,45 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
28538
28568
|
strandedLoop.unref();
|
|
28539
28569
|
}
|
|
28540
28570
|
{
|
|
28541
|
-
const
|
|
28571
|
+
const googleRoot = process.env.MAXY_PLATFORM_ROOT ?? join42(__dirname, "..");
|
|
28572
|
+
const googleAccountsDir = resolve36(googleRoot, "..", "data/accounts");
|
|
28573
|
+
const GOOGLE_PENDING_AUDIT_INTERVAL_MS = 3e5;
|
|
28574
|
+
const runGooglePendingAuditSafe = () => {
|
|
28575
|
+
try {
|
|
28576
|
+
runGooglePendingAudit(googleAccountsDir, Date.now(), (line) => console.error(line));
|
|
28577
|
+
} catch (err) {
|
|
28578
|
+
console.error(`[google-oauth] op=pending-audit-error error="${err.message}"`);
|
|
28579
|
+
}
|
|
28580
|
+
};
|
|
28581
|
+
const googlePendingFirst = setTimeout(runGooglePendingAuditSafe, 27e3);
|
|
28582
|
+
googlePendingFirst.unref();
|
|
28583
|
+
const googlePendingLoop = setInterval(runGooglePendingAuditSafe, GOOGLE_PENDING_AUDIT_INTERVAL_MS);
|
|
28584
|
+
googlePendingLoop.unref();
|
|
28585
|
+
const googleAuditScript = resolve36(googleRoot, "plugins/google/mcp/dist/scripts/account-audit.js");
|
|
28586
|
+
const GOOGLE_ACCOUNT_AUDIT_INTERVAL_MS = 36e5;
|
|
28587
|
+
const runGoogleAccountAudit = () => {
|
|
28588
|
+
if (!existsSync38(googleAuditScript)) return;
|
|
28589
|
+
try {
|
|
28590
|
+
const child = spawn3(process.execPath, [googleAuditScript], {
|
|
28591
|
+
env: { ...process.env, PLATFORM_ROOT: googleRoot },
|
|
28592
|
+
stdio: "inherit"
|
|
28593
|
+
});
|
|
28594
|
+
child.unref();
|
|
28595
|
+
child.on(
|
|
28596
|
+
"error",
|
|
28597
|
+
(err) => console.error(`[google-account-audit] op=spawn-failed error="${err.message}"`)
|
|
28598
|
+
);
|
|
28599
|
+
} catch (err) {
|
|
28600
|
+
console.error(`[google-account-audit] op=spawn-failed error="${err.message}"`);
|
|
28601
|
+
}
|
|
28602
|
+
};
|
|
28603
|
+
const googleAuditFirst = setTimeout(runGoogleAccountAudit, 45e3);
|
|
28604
|
+
googleAuditFirst.unref();
|
|
28605
|
+
const googleAuditLoop = setInterval(runGoogleAccountAudit, GOOGLE_ACCOUNT_AUDIT_INTERVAL_MS);
|
|
28606
|
+
googleAuditLoop.unref();
|
|
28607
|
+
}
|
|
28608
|
+
{
|
|
28609
|
+
const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join42(__dirname, "..");
|
|
28542
28610
|
const STORAGE_AUDIT_INTERVAL_MS = 3e5;
|
|
28543
28611
|
const runStorageAuditSafe = () => {
|
|
28544
28612
|
runStorageAudit(auditPlatformRoot).catch(
|
|
@@ -28560,7 +28628,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
28560
28628
|
pagesAuditLoop.unref();
|
|
28561
28629
|
}
|
|
28562
28630
|
{
|
|
28563
|
-
const publishPlatformRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
28631
|
+
const publishPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join42(__dirname, "..");
|
|
28564
28632
|
const publishScript = resolve36(publishPlatformRoot, "plugins/scheduling/mcp/dist/scripts/publish-availability.js");
|
|
28565
28633
|
const PUBLISH_INTERVAL_MS = 3e5;
|
|
28566
28634
|
const currentAccount = () => {
|
|
@@ -28572,7 +28640,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
28572
28640
|
}
|
|
28573
28641
|
};
|
|
28574
28642
|
const spawnPublish = (account) => {
|
|
28575
|
-
if (!
|
|
28643
|
+
if (!existsSync38(publishScript)) return;
|
|
28576
28644
|
try {
|
|
28577
28645
|
const child = spawn3(process.execPath, [publishScript], {
|
|
28578
28646
|
env: {
|
|
@@ -28593,7 +28661,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
28593
28661
|
const availPath = resolve36(account.accountDir, "calendar-availability.json");
|
|
28594
28662
|
let hasBookingSite = false;
|
|
28595
28663
|
try {
|
|
28596
|
-
if (
|
|
28664
|
+
if (existsSync38(availPath)) {
|
|
28597
28665
|
const cfg = JSON.parse(readFileSync41(availPath, "utf-8"));
|
|
28598
28666
|
hasBookingSite = typeof cfg.bookingDbName === "string" && cfg.bookingDbName.length > 0;
|
|
28599
28667
|
}
|
|
@@ -28602,7 +28670,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
28602
28670
|
if (!hasBookingSite) return;
|
|
28603
28671
|
const statePath = resolve36(account.accountDir, "state", "booking-availability", "last-publish.json");
|
|
28604
28672
|
let lastSuccessAt = null;
|
|
28605
|
-
if (
|
|
28673
|
+
if (existsSync38(statePath)) {
|
|
28606
28674
|
try {
|
|
28607
28675
|
const rec = JSON.parse(readFileSync41(statePath, "utf-8"));
|
|
28608
28676
|
lastSuccessAt = rec.lastSuccessAt ?? null;
|
|
@@ -28629,12 +28697,12 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
28629
28697
|
startTimeEntryCensus(() => getSession());
|
|
28630
28698
|
startLedgerCensus(() => getSession());
|
|
28631
28699
|
{
|
|
28632
|
-
const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
28700
|
+
const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join42(__dirname, "..");
|
|
28633
28701
|
const auditScript = resolve36(auditPlatformRoot, "plugins/connector/mcp/dist/scripts/audit-connectors.js");
|
|
28634
28702
|
const auditLogDir = process.env.LOG_DIR ?? LOG_DIR;
|
|
28635
28703
|
const CONNECTOR_AUDIT_INTERVAL_MS = 3e5;
|
|
28636
28704
|
const runConnectorAudit = () => {
|
|
28637
|
-
if (!
|
|
28705
|
+
if (!existsSync38(auditScript)) return;
|
|
28638
28706
|
try {
|
|
28639
28707
|
const child = spawn3(process.execPath, [auditScript], {
|
|
28640
28708
|
env: { ...process.env, PLATFORM_ROOT: auditPlatformRoot, LOG_DIR: auditLogDir },
|
|
@@ -28745,7 +28813,7 @@ try {
|
|
|
28745
28813
|
var ADMINUSER_RECONCILE_INTERVAL_MS = 60 * 60 * 1e3;
|
|
28746
28814
|
async function runAdminUserReconcileTick() {
|
|
28747
28815
|
try {
|
|
28748
|
-
if (!
|
|
28816
|
+
if (!existsSync38(USERS_FILE)) {
|
|
28749
28817
|
console.error("[adminuser-self-heal] skip reason=no-users-file");
|
|
28750
28818
|
return;
|
|
28751
28819
|
}
|
|
@@ -28790,7 +28858,7 @@ var ingestAuditTimer = setInterval(runIngestAuditTick, INGEST_AUDIT_INTERVAL_MS)
|
|
|
28790
28858
|
if (typeof ingestAuditTimer.unref === "function") ingestAuditTimer.unref();
|
|
28791
28859
|
var USERS_RECONCILE_INTERVAL_MS = 60 * 60 * 1e3;
|
|
28792
28860
|
function countUsersRows() {
|
|
28793
|
-
if (!
|
|
28861
|
+
if (!existsSync38(USERS_FILE)) return 0;
|
|
28794
28862
|
const raw = readFileSync41(USERS_FILE, "utf-8").trim();
|
|
28795
28863
|
if (!raw) return 0;
|
|
28796
28864
|
const users = JSON.parse(raw);
|
|
@@ -28911,7 +28979,7 @@ if (bootAccountConfig?.whatsapp) {
|
|
|
28911
28979
|
}
|
|
28912
28980
|
init({
|
|
28913
28981
|
configDir: configDirForWhatsApp,
|
|
28914
|
-
platformRoot: resolve36(process.env.MAXY_PLATFORM_ROOT ??
|
|
28982
|
+
platformRoot: resolve36(process.env.MAXY_PLATFORM_ROOT ?? join42(__dirname, "..")),
|
|
28915
28983
|
accountConfig: bootAccountConfig,
|
|
28916
28984
|
onMessage: async (msg) => {
|
|
28917
28985
|
if (msg.isOwnerMirror) {
|