@rubytech/create-maxy-code 0.1.473 → 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/dist/__tests__/google-client-id-env.test.js +3 -2
- package/package.json +1 -1
- package/payload/platform/neo4j/schema.cypher +4 -1
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +29 -16
- package/payload/platform/plugins/docs/references/admin-ui.md +1 -1
- package/payload/platform/plugins/docs/references/google-guide.md +25 -12
- package/payload/platform/plugins/docs/references/voice-mirror-guide.md +2 -2
- package/payload/platform/plugins/google/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/google/PLUGIN.md +73 -14
- 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 +331 -367
- package/payload/platform/plugins/voice-mirror/PLUGIN.md +1 -1
- package/payload/platform/plugins/voice-mirror/mcp/dist/index.js +3 -3
- package/payload/platform/plugins/voice-mirror/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/voice-mirror/mcp/dist/lib/voice-corpus.d.ts +14 -1
- package/payload/platform/plugins/voice-mirror/mcp/dist/lib/voice-corpus.d.ts.map +1 -1
- package/payload/platform/plugins/voice-mirror/mcp/dist/lib/voice-corpus.js +15 -0
- package/payload/platform/plugins/voice-mirror/mcp/dist/lib/voice-corpus.js.map +1 -1
- package/payload/platform/plugins/voice-mirror/mcp/dist/tools/voice-distil-profile.d.ts.map +1 -1
- package/payload/platform/plugins/voice-mirror/mcp/dist/tools/voice-distil-profile.js +3 -1
- package/payload/platform/plugins/voice-mirror/mcp/dist/tools/voice-distil-profile.js.map +1 -1
- package/payload/platform/plugins/voice-mirror/mcp/scripts/smoke.mjs +51 -4
- package/payload/platform/plugins/voice-mirror/skills/voice-mirror/SKILL.md +4 -0
- package/payload/platform/scripts/backfill-task-ids.sh +206 -0
- 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 +6 -6
- package/payload/server/public/assets/{AdminLoginScreens-B7TQZV8u.js → AdminLoginScreens-B44KbEuC.js} +1 -1
- package/payload/server/public/assets/{AdminShell-DAuri4Yh.js → AdminShell-BjxV2qkb.js} +2 -2
- package/payload/server/public/assets/{Checkbox-B1XhnhPk.js → Checkbox-DSeZNGNA.js} +1 -1
- package/payload/server/public/assets/activity-Mz1BhgB1.js +1 -0
- package/payload/server/public/assets/{admin-BdcccSb5.js → admin-B4LpTCur.js} +1 -1
- package/payload/server/public/assets/{browser-B6woQ2qX.js → browser-CEFvaWwI.js} +1 -1
- package/payload/server/public/assets/{calendar-CalCeg5T.js → calendar-B3zo6V34.js} +1 -1
- package/payload/server/public/assets/chat-5tJdo9i_.js +1 -0
- package/payload/server/public/assets/chevron-left-BJllrPBj.js +1 -0
- package/payload/server/public/assets/data-Du79EgR-.js +1 -0
- package/payload/server/public/assets/{graph-HeZaatSQ.js → graph-RaOrnSf2.js} +1 -1
- package/payload/server/public/assets/{graph-labels-4W7JuOgG.js → graph-labels-GlTEIYJj.js} +1 -1
- package/payload/server/public/assets/{maximize-2-DKx-aTPb.js → maximize-2-CHDa8p5h.js} +1 -1
- package/payload/server/public/assets/{operator-DD9L2VJM.js → operator-DtqHY4jV.js} +1 -1
- package/payload/server/public/assets/{page-tJxw0zNO.js → page-CkhFj8GQ.js} +1 -1
- package/payload/server/public/assets/{page-Ceado9Kr.js → page-DxnWgPtd.js} +1 -1
- package/payload/server/public/assets/{public-BYFWxyeC.js → public-D5TUfQ3I.js} +1 -1
- package/payload/server/public/assets/{rotate-ccw-DrzdV9h7.js → rotate-ccw-BJjVAQQY.js} +1 -1
- package/payload/server/public/assets/tasks-CM9pYYG1.js +1 -0
- package/payload/server/public/assets/{time-entry-format-Bn79w6tq.js → time-entry-format-C5RYEYjM.js} +1 -1
- package/payload/server/public/assets/{triangle-alert-CjDVh6r-.js → triangle-alert-DLfIsuo_.js} +1 -1
- package/payload/server/public/assets/{useCopyFeedback-DXHkkJw-.js → useCopyFeedback-7yKeiAzV.js} +1 -1
- package/payload/server/public/assets/{useSelectionMode-D2H8jAhE.js → useSelectionMode-CWlh6AEq.js} +1 -1
- package/payload/server/public/assets/{useSubAccountSwitcher-Br7Z6Cpu.css → useSubAccountSwitcher-B2n9QPVI.css} +1 -1
- package/payload/server/public/assets/{useVoiceRecorder-zUvPe55I.js → useVoiceRecorder-j3ZArZ2H.js} +1 -1
- package/payload/server/public/browser.html +5 -5
- package/payload/server/public/calendar.html +6 -6
- package/payload/server/public/chat.html +12 -12
- package/payload/server/public/data.html +11 -11
- package/payload/server/public/graph.html +11 -11
- package/payload/server/public/index.html +14 -14
- package/payload/server/public/operator.html +14 -14
- package/payload/server/public/public.html +12 -12
- package/payload/server/public/tasks.html +5 -5
- package/payload/server/server.js +433 -313
- package/payload/server/public/assets/activity-kRwzxEKU.js +0 -1
- package/payload/server/public/assets/chat-9s2-L06v.js +0 -1
- package/payload/server/public/assets/chevron-left-C3ho8SnB.js +0 -1
- package/payload/server/public/assets/data-Cfr-7ERI.js +0 -1
- package/payload/server/public/assets/tasks-DSwoxGzh.js +0 -1
- /package/payload/server/public/assets/{useSubAccountSwitcher-CUJpgkKI.js → useSubAccountSwitcher-CBlKgwms.js} +0 -0
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
|
|
|
@@ -8448,6 +8448,23 @@ function conversationCounterpartyPhone(remoteJid, earliestSenderTelephone) {
|
|
|
8448
8448
|
function counterpartyBoundToSubAccount(managerPhones, counterpartyPhone) {
|
|
8449
8449
|
return counterpartyPhone != null && managerPhones.some((mp) => phonesMatch(mp, counterpartyPhone));
|
|
8450
8450
|
}
|
|
8451
|
+
function storePushNamesBySender(summaries) {
|
|
8452
|
+
const best = /* @__PURE__ */ new Map();
|
|
8453
|
+
const out = /* @__PURE__ */ new Map();
|
|
8454
|
+
for (const [remoteJid, { first, last, firstNamedSender }] of summaries) {
|
|
8455
|
+
if (!firstNamedSender) continue;
|
|
8456
|
+
const phone = conversationCounterpartyPhone(remoteJid, first.senderTelephone);
|
|
8457
|
+
if (!phone) continue;
|
|
8458
|
+
const key = normalizeE164(phone);
|
|
8459
|
+
if (key.length === 0) continue;
|
|
8460
|
+
const at = last.dateSent ?? "";
|
|
8461
|
+
const seen = best.get(key);
|
|
8462
|
+
if (seen !== void 0 && (seen.at > at || seen.at === at && seen.jid <= remoteJid)) continue;
|
|
8463
|
+
best.set(key, { at, jid: remoteJid });
|
|
8464
|
+
out.set(key, firstNamedSender);
|
|
8465
|
+
}
|
|
8466
|
+
return out;
|
|
8467
|
+
}
|
|
8451
8468
|
function buildStoreConversationRows(accountId, summaries) {
|
|
8452
8469
|
const rows = [];
|
|
8453
8470
|
for (const [remoteJid, { first, last, firstNamedSender }] of summaries) {
|
|
@@ -9670,46 +9687,74 @@ async function runPagesAudit(root) {
|
|
|
9670
9687
|
}
|
|
9671
9688
|
}
|
|
9672
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
|
+
|
|
9673
9718
|
// server/routes/whatsapp-reader.ts
|
|
9674
|
-
import { readFileSync as readFileSync19, watch, statSync as
|
|
9675
|
-
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";
|
|
9676
9721
|
|
|
9677
9722
|
// server/routes/admin/sidebar-sessions.ts
|
|
9678
|
-
import { readdirSync as
|
|
9679
|
-
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";
|
|
9680
9725
|
|
|
9681
9726
|
// ../services/claude-session-manager/src/jsonl-path.ts
|
|
9682
|
-
import { existsSync as
|
|
9727
|
+
import { existsSync as existsSync11, readdirSync as readdirSync10 } from "fs";
|
|
9683
9728
|
import { homedir } from "os";
|
|
9684
|
-
import { join as
|
|
9729
|
+
import { join as join15 } from "path";
|
|
9685
9730
|
function findExistingJsonlForSessionId(claudeConfigDir2, sessionId) {
|
|
9686
|
-
const projectsRoot =
|
|
9687
|
-
if (!
|
|
9731
|
+
const projectsRoot = join15(claudeConfigDir2, "projects");
|
|
9732
|
+
if (!existsSync11(projectsRoot)) return null;
|
|
9688
9733
|
let slugs;
|
|
9689
9734
|
try {
|
|
9690
|
-
slugs =
|
|
9735
|
+
slugs = readdirSync10(projectsRoot, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
9691
9736
|
} catch {
|
|
9692
9737
|
return null;
|
|
9693
9738
|
}
|
|
9694
9739
|
const basename13 = `${sessionId}.jsonl`;
|
|
9695
9740
|
for (const slug of slugs) {
|
|
9696
|
-
const live =
|
|
9697
|
-
if (
|
|
9698
|
-
const archived =
|
|
9699
|
-
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;
|
|
9700
9745
|
}
|
|
9701
9746
|
return null;
|
|
9702
9747
|
}
|
|
9703
9748
|
|
|
9704
9749
|
// app/lib/admin-identity/pin-validator.ts
|
|
9705
9750
|
import { createHash as createHash3 } from "crypto";
|
|
9706
|
-
import { existsSync as
|
|
9707
|
-
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";
|
|
9708
9753
|
function hashPin(pin) {
|
|
9709
9754
|
return createHash3("sha256").update(pin).digest("hex");
|
|
9710
9755
|
}
|
|
9711
9756
|
function readUsersFile(usersFilePath) {
|
|
9712
|
-
if (!
|
|
9757
|
+
if (!existsSync12(usersFilePath)) return null;
|
|
9713
9758
|
const raw = readFileSync16(usersFilePath, "utf-8").trim();
|
|
9714
9759
|
if (!raw) return [];
|
|
9715
9760
|
return JSON.parse(raw);
|
|
@@ -9829,16 +9874,16 @@ function enumerateJsonls(projectsRoot) {
|
|
|
9829
9874
|
const out = [];
|
|
9830
9875
|
let slugs;
|
|
9831
9876
|
try {
|
|
9832
|
-
slugs =
|
|
9877
|
+
slugs = readdirSync12(projectsRoot, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
9833
9878
|
} catch (err) {
|
|
9834
9879
|
if (err.code === "ENOENT") return out;
|
|
9835
9880
|
throw err;
|
|
9836
9881
|
}
|
|
9837
9882
|
for (const slug of slugs) {
|
|
9838
|
-
const slugDir =
|
|
9883
|
+
const slugDir = join17(projectsRoot, slug);
|
|
9839
9884
|
let entries;
|
|
9840
9885
|
try {
|
|
9841
|
-
entries =
|
|
9886
|
+
entries = readdirSync12(slugDir, { withFileTypes: true });
|
|
9842
9887
|
} catch (err) {
|
|
9843
9888
|
const code = err.code ?? "unknown";
|
|
9844
9889
|
console.error(`[admin-sessions-list] slug-skipped slug=${slug} code=${code}`);
|
|
@@ -9846,12 +9891,12 @@ function enumerateJsonls(projectsRoot) {
|
|
|
9846
9891
|
}
|
|
9847
9892
|
for (const entry of entries) {
|
|
9848
9893
|
if (entry.isFile() && SESSION_ID_RE.test(entry.name)) {
|
|
9849
|
-
out.push({ path:
|
|
9894
|
+
out.push({ path: join17(slugDir, entry.name), isSubagent: false, archived: false });
|
|
9850
9895
|
} else if (entry.isDirectory() && entry.name === "subagents") {
|
|
9851
|
-
const subDir =
|
|
9896
|
+
const subDir = join17(slugDir, entry.name);
|
|
9852
9897
|
let subEntries;
|
|
9853
9898
|
try {
|
|
9854
|
-
subEntries =
|
|
9899
|
+
subEntries = readdirSync12(subDir, { withFileTypes: true });
|
|
9855
9900
|
} catch (err) {
|
|
9856
9901
|
const code = err.code ?? "unknown";
|
|
9857
9902
|
console.error(`[admin-sessions-list] subagents-skipped slug=${slug} code=${code}`);
|
|
@@ -9859,14 +9904,14 @@ function enumerateJsonls(projectsRoot) {
|
|
|
9859
9904
|
}
|
|
9860
9905
|
for (const sub of subEntries) {
|
|
9861
9906
|
if (sub.isFile() && SESSION_ID_RE.test(sub.name)) {
|
|
9862
|
-
out.push({ path:
|
|
9907
|
+
out.push({ path: join17(subDir, sub.name), isSubagent: true, archived: false });
|
|
9863
9908
|
}
|
|
9864
9909
|
}
|
|
9865
9910
|
} else if (entry.isDirectory() && entry.name === "archive") {
|
|
9866
|
-
const archiveDir =
|
|
9911
|
+
const archiveDir = join17(slugDir, entry.name);
|
|
9867
9912
|
let archiveEntries;
|
|
9868
9913
|
try {
|
|
9869
|
-
archiveEntries =
|
|
9914
|
+
archiveEntries = readdirSync12(archiveDir, { withFileTypes: true });
|
|
9870
9915
|
} catch (err) {
|
|
9871
9916
|
const code = err.code ?? "unknown";
|
|
9872
9917
|
console.error(`[admin-sessions-list] archive-skipped slug=${slug} code=${code}`);
|
|
@@ -9874,7 +9919,7 @@ function enumerateJsonls(projectsRoot) {
|
|
|
9874
9919
|
}
|
|
9875
9920
|
for (const arc of archiveEntries) {
|
|
9876
9921
|
if (arc.isFile() && SESSION_ID_RE.test(arc.name)) {
|
|
9877
|
-
out.push({ path:
|
|
9922
|
+
out.push({ path: join17(archiveDir, arc.name), isSubagent: false, archived: true });
|
|
9878
9923
|
}
|
|
9879
9924
|
}
|
|
9880
9925
|
}
|
|
@@ -9907,7 +9952,7 @@ async function fetchLiveSessions() {
|
|
|
9907
9952
|
function loadUserTitles(accountDir) {
|
|
9908
9953
|
const out = /* @__PURE__ */ new Map();
|
|
9909
9954
|
if (!accountDir) return out;
|
|
9910
|
-
const path3 =
|
|
9955
|
+
const path3 = join17(accountDir, "session-titles.json");
|
|
9911
9956
|
let raw;
|
|
9912
9957
|
try {
|
|
9913
9958
|
raw = readFileSync17(path3, "utf8");
|
|
@@ -10034,7 +10079,7 @@ app4.get("/", requireAdminSession, async (c) => {
|
|
|
10034
10079
|
console.error("[admin-sessions-list] CLAUDE_CONFIG_DIR not set; returning empty list");
|
|
10035
10080
|
return c.json({ sessions: [], accountId: scopeAccountId });
|
|
10036
10081
|
}
|
|
10037
|
-
const projectsRoot =
|
|
10082
|
+
const projectsRoot = join17(configDir2, "projects");
|
|
10038
10083
|
const jsonls = enumerateJsonls(projectsRoot);
|
|
10039
10084
|
const liveSessions = await fetchLiveSessions();
|
|
10040
10085
|
const accountDir = scopeAccountId ? resolve12(ACCOUNTS_DIR, scopeAccountId) : null;
|
|
@@ -10079,7 +10124,7 @@ app4.get("/", requireAdminSession, async (c) => {
|
|
|
10079
10124
|
let mtimeMs;
|
|
10080
10125
|
try {
|
|
10081
10126
|
body = readFileSync17(path3, "utf8");
|
|
10082
|
-
mtimeMs =
|
|
10127
|
+
mtimeMs = statSync6(path3).mtimeMs;
|
|
10083
10128
|
} catch {
|
|
10084
10129
|
continue;
|
|
10085
10130
|
}
|
|
@@ -10087,7 +10132,7 @@ app4.get("/", requireAdminSession, async (c) => {
|
|
|
10087
10132
|
const pid = live ? liveSessions.get(sessionId) ?? null : null;
|
|
10088
10133
|
const resolved = resolveTitle(body, sessionId, userTitles);
|
|
10089
10134
|
titleSourceCounts[resolved.source] += 1;
|
|
10090
|
-
const metaPath =
|
|
10135
|
+
const metaPath = join17(projectDir, `${sessionId}.meta.json`);
|
|
10091
10136
|
const { bridgeIds, role, channel: sidecarChannel, senderId, personId, adminUserId, accountId: rowAccountId } = readSidecarMeta(metaPath);
|
|
10092
10137
|
if (multiAccount) {
|
|
10093
10138
|
if (rowAccountId === null) untaggedCount += 1;
|
|
@@ -10121,7 +10166,8 @@ app4.get("/", requireAdminSession, async (c) => {
|
|
|
10121
10166
|
personName: null,
|
|
10122
10167
|
model: lastAssistantModel(body),
|
|
10123
10168
|
accountId: rowAccountId,
|
|
10124
|
-
senderId
|
|
10169
|
+
senderId,
|
|
10170
|
+
whatsappName: null
|
|
10125
10171
|
});
|
|
10126
10172
|
if ((sidecarChannel === "whatsapp" || sidecarChannel === "telegram") && resolved.source === "prefix") {
|
|
10127
10173
|
if (senderId) channelSenderBySession.set(sessionId, senderId);
|
|
@@ -10162,20 +10208,36 @@ app4.get("/", requireAdminSession, async (c) => {
|
|
|
10162
10208
|
);
|
|
10163
10209
|
}
|
|
10164
10210
|
let channelNamesResolved = 0;
|
|
10211
|
+
let operatorResolvedCount = 0;
|
|
10212
|
+
let storeResolvedCount = 0;
|
|
10165
10213
|
const channelNameCandidates = channelSenderBySession.size + channelMissNoSender.length;
|
|
10166
10214
|
if (account && channelSenderBySession.size > 0) {
|
|
10167
10215
|
const resolvedNames = await resolveOperatorNamesBySender(channelUsers, channelAdmins, channelSenderBySession.values());
|
|
10216
|
+
let pushNames = /* @__PURE__ */ new Map();
|
|
10217
|
+
try {
|
|
10218
|
+
pushNames = storePushNamesBySender(readConversationSummaries(account.accountId));
|
|
10219
|
+
} catch (err) {
|
|
10220
|
+
console.error(`[admin-sessions-list] op=store-unreadable reason=${err instanceof Error ? err.message : String(err)}`);
|
|
10221
|
+
}
|
|
10168
10222
|
for (const row of rows) {
|
|
10169
10223
|
const rowSenderId = channelSenderBySession.get(row.sessionId);
|
|
10170
10224
|
if (!rowSenderId) continue;
|
|
10171
10225
|
const r = resolvedNames.get(rowSenderId) ?? { name: null, reason: "no-binding" };
|
|
10172
10226
|
if (r.name) {
|
|
10173
10227
|
row.personName = r.name;
|
|
10228
|
+
operatorResolvedCount += 1;
|
|
10174
10229
|
channelNamesResolved += 1;
|
|
10175
|
-
|
|
10176
|
-
const reason = r.reason === "neo4j-unreachable" ? "neo4j-down" : "classify-miss";
|
|
10177
|
-
console.error(`[admin-sessions-list] op=channel-name-unresolved sessionId=${row.sessionId.slice(0, 8)} channel=${row.channel} senderId=${rowSenderId} reason=${reason}`);
|
|
10230
|
+
continue;
|
|
10178
10231
|
}
|
|
10232
|
+
const pushName = row.channel === "whatsapp" && r.reason === "no-binding" ? pushNames.get(normalizeE164(rowSenderId)) ?? null : null;
|
|
10233
|
+
if (pushName) {
|
|
10234
|
+
row.whatsappName = pushName;
|
|
10235
|
+
storeResolvedCount += 1;
|
|
10236
|
+
channelNamesResolved += 1;
|
|
10237
|
+
continue;
|
|
10238
|
+
}
|
|
10239
|
+
const reason = r.reason === "neo4j-unreachable" ? "neo4j-down" : "classify-miss";
|
|
10240
|
+
console.error(`[admin-sessions-list] op=channel-name-unresolved sessionId=${row.sessionId.slice(0, 8)} channel=${row.channel} senderId=${rowSenderId} reason=${reason}`);
|
|
10179
10241
|
}
|
|
10180
10242
|
}
|
|
10181
10243
|
for (const m of channelMissNoSender) {
|
|
@@ -10183,7 +10245,7 @@ app4.get("/", requireAdminSession, async (c) => {
|
|
|
10183
10245
|
}
|
|
10184
10246
|
rows.sort((a, b) => a.startedAt < b.startedAt ? 1 : -1);
|
|
10185
10247
|
console.log(
|
|
10186
|
-
`[admin-sessions-list] rows=${rows.length} live=${liveCount} subagents=${subagentCount} archived=${archivedCount} channelInList=whatsapp:${channelInList.whatsapp},telegram:${channelInList.telegram},webchat:${channelInList.webchat} channelNameCandidates=${channelNameCandidates} channelNamesResolved=${channelNamesResolved} unknownChannel=${unknownChannelCount} excludedPublicWebchat=${excludedPublicWebchatCount} titles user=${titleSourceCounts.user} ai=${titleSourceCounts.ai} first=${titleSourceCounts["first-message"]} prefix=${titleSourceCounts.prefix} personNames=${personNameCount} adminNames=${adminNameCount} accountId=${scopeAccountId ? scopeAccountId.slice(0, 8) : "unset"}`
|
|
10248
|
+
`[admin-sessions-list] rows=${rows.length} live=${liveCount} subagents=${subagentCount} archived=${archivedCount} channelInList=whatsapp:${channelInList.whatsapp},telegram:${channelInList.telegram},webchat:${channelInList.webchat} channelNameCandidates=${channelNameCandidates} channelNamesResolved=${channelNamesResolved} (operator=${operatorResolvedCount} store=${storeResolvedCount}) unknownChannel=${unknownChannelCount} excludedPublicWebchat=${excludedPublicWebchatCount} titles user=${titleSourceCounts.user} ai=${titleSourceCounts.ai} first=${titleSourceCounts["first-message"]} prefix=${titleSourceCounts.prefix} personNames=${personNameCount} adminNames=${adminNameCount} accountId=${scopeAccountId ? scopeAccountId.slice(0, 8) : "unset"}`
|
|
10187
10249
|
);
|
|
10188
10250
|
console.log(
|
|
10189
10251
|
`[admin-sessions-list] accountId=${scopeAccountId ? scopeAccountId.slice(0, 8) : "unset"} scope=${multiAccount ? "scoped" : "all"} rows=${rows.length}`
|
|
@@ -10483,8 +10545,8 @@ function parseTranscript(lines, queuedPendingSuppress = /* @__PURE__ */ new Map(
|
|
|
10483
10545
|
}
|
|
10484
10546
|
|
|
10485
10547
|
// app/lib/whatsapp-reader/enrich-attachments.ts
|
|
10486
|
-
import { readFileSync as readFileSync18, readdirSync as
|
|
10487
|
-
import { join as
|
|
10548
|
+
import { readFileSync as readFileSync18, readdirSync as readdirSync13 } from "fs";
|
|
10549
|
+
import { join as join18 } from "path";
|
|
10488
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;
|
|
10489
10551
|
function adminAttachmentIds(text) {
|
|
10490
10552
|
const ids = [];
|
|
@@ -10497,7 +10559,7 @@ function adminAttachmentIds(text) {
|
|
|
10497
10559
|
function adminAttachmentsFromText(text, uploadsBase) {
|
|
10498
10560
|
const out = [];
|
|
10499
10561
|
for (const id of adminAttachmentIds(text)) {
|
|
10500
|
-
const meta = readAttachmentMeta(
|
|
10562
|
+
const meta = readAttachmentMeta(join18(uploadsBase, id));
|
|
10501
10563
|
if (meta) out.push(meta);
|
|
10502
10564
|
}
|
|
10503
10565
|
return out;
|
|
@@ -10505,7 +10567,7 @@ function adminAttachmentsFromText(text, uploadsBase) {
|
|
|
10505
10567
|
function readSidecar(dir, attachmentId) {
|
|
10506
10568
|
let parsed;
|
|
10507
10569
|
try {
|
|
10508
|
-
parsed = JSON.parse(readFileSync18(
|
|
10570
|
+
parsed = JSON.parse(readFileSync18(join18(dir, `${attachmentId}.meta.json`), "utf8"));
|
|
10509
10571
|
} catch {
|
|
10510
10572
|
return null;
|
|
10511
10573
|
}
|
|
@@ -10528,13 +10590,13 @@ function readAttachmentMeta(dir) {
|
|
|
10528
10590
|
function listSessionAttachmentsInDir(dir) {
|
|
10529
10591
|
let entries;
|
|
10530
10592
|
try {
|
|
10531
|
-
entries =
|
|
10593
|
+
entries = readdirSync13(dir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
10532
10594
|
} catch {
|
|
10533
10595
|
return [];
|
|
10534
10596
|
}
|
|
10535
10597
|
const sidecars = [];
|
|
10536
10598
|
for (const name of entries) {
|
|
10537
|
-
const sidecar = readSidecar(
|
|
10599
|
+
const sidecar = readSidecar(join18(dir, name), name);
|
|
10538
10600
|
if (sidecar) sidecars.push(sidecar);
|
|
10539
10601
|
}
|
|
10540
10602
|
sidecars.sort((a, b) => a.storedAt.localeCompare(b.storedAt));
|
|
@@ -10694,14 +10756,14 @@ app5.get("/conversations", requireAdminSession, async (c) => {
|
|
|
10694
10756
|
}
|
|
10695
10757
|
const cfg = claudeConfigDir();
|
|
10696
10758
|
if (!cfg) return c.json({ conversations: [] });
|
|
10697
|
-
const projectsRoot =
|
|
10759
|
+
const projectsRoot = join19(cfg, "projects");
|
|
10698
10760
|
const userTitles = loadUserTitles(ACCOUNTS_DIR ?? null);
|
|
10699
10761
|
const rows = [];
|
|
10700
10762
|
let sessionRowsExcludedUntagged = 0;
|
|
10701
10763
|
for (const { path: path3 } of enumerateJsonls(projectsRoot)) {
|
|
10702
10764
|
const sessionId = basename4(path3).replace(/\.jsonl$/, "");
|
|
10703
10765
|
const projectDir = dirname5(path3);
|
|
10704
|
-
const meta = readSidecarMeta(
|
|
10766
|
+
const meta = readSidecarMeta(join19(projectDir, `${sessionId}.meta.json`));
|
|
10705
10767
|
if (!isReaderChannelSession(meta.role, meta.channel)) continue;
|
|
10706
10768
|
if (multiAccount) {
|
|
10707
10769
|
if (meta.accountId === null) sessionRowsExcludedUntagged += 1;
|
|
@@ -10793,7 +10855,7 @@ app5.get("/conversations", requireAdminSession, async (c) => {
|
|
|
10793
10855
|
return c.json({ conversations: [...sessionConversations, ...allStoreRows] });
|
|
10794
10856
|
});
|
|
10795
10857
|
function readFrom(path3, from) {
|
|
10796
|
-
const end =
|
|
10858
|
+
const end = statSync7(path3).size;
|
|
10797
10859
|
if (end <= from) return { buf: Buffer.alloc(0), end: from };
|
|
10798
10860
|
const fd = openSync(path3, "r");
|
|
10799
10861
|
try {
|
|
@@ -10878,7 +10940,7 @@ function openTaskKey(turns) {
|
|
|
10878
10940
|
}
|
|
10879
10941
|
function readSubagentMeta(dir, hex) {
|
|
10880
10942
|
try {
|
|
10881
|
-
const m = JSON.parse(readFileSync19(
|
|
10943
|
+
const m = JSON.parse(readFileSync19(join19(dir, `agent-${hex}.meta.json`), "utf8"));
|
|
10882
10944
|
if (typeof m.agentType === "string" && typeof m.description === "string" && typeof m.toolUseId === "string") {
|
|
10883
10945
|
return { agentType: m.agentType, description: m.description, toolUseId: m.toolUseId };
|
|
10884
10946
|
}
|
|
@@ -10901,7 +10963,7 @@ function runActivityTick(c) {
|
|
|
10901
10963
|
c.parentGrewThisTick = false;
|
|
10902
10964
|
let names = [];
|
|
10903
10965
|
try {
|
|
10904
|
-
names =
|
|
10966
|
+
names = readdirSync14(c.subagentsDir).filter((n) => AGENT_JSONL_RE.test(n));
|
|
10905
10967
|
} catch {
|
|
10906
10968
|
}
|
|
10907
10969
|
const entries = [];
|
|
@@ -10910,7 +10972,7 @@ function runActivityTick(c) {
|
|
|
10910
10972
|
let size = 0;
|
|
10911
10973
|
let mtimeMs = 0;
|
|
10912
10974
|
try {
|
|
10913
|
-
const st =
|
|
10975
|
+
const st = statSync7(join19(c.subagentsDir, name));
|
|
10914
10976
|
size = st.size;
|
|
10915
10977
|
mtimeMs = st.mtimeMs;
|
|
10916
10978
|
} catch {
|
|
@@ -10955,11 +11017,11 @@ app5.get("/stream", requireAdminSession, (c) => {
|
|
|
10955
11017
|
const sessionId = c.req.query("sessionId") ?? "";
|
|
10956
11018
|
const projectDir = c.req.query("projectDir") ?? "";
|
|
10957
11019
|
const cfg = claudeConfigDir();
|
|
10958
|
-
const projectsRoot = cfg ? resolve13(
|
|
11020
|
+
const projectsRoot = cfg ? resolve13(join19(cfg, "projects")) : null;
|
|
10959
11021
|
if (!cfg || !projectsRoot || !SESSION_ID_RE2.test(sessionId)) {
|
|
10960
11022
|
return c.json({ error: "bad session reference" }, 400);
|
|
10961
11023
|
}
|
|
10962
|
-
const jsonlPath = resolve13(
|
|
11024
|
+
const jsonlPath = resolve13(join19(projectDir, `${sessionId}.jsonl`));
|
|
10963
11025
|
if (!jsonlPath.startsWith(projectsRoot + sep3)) {
|
|
10964
11026
|
return c.json({ error: "bad session reference" }, 400);
|
|
10965
11027
|
}
|
|
@@ -10978,7 +11040,7 @@ data: ${JSON.stringify(turn)}
|
|
|
10978
11040
|
start(controller) {
|
|
10979
11041
|
const fileEnd0 = (() => {
|
|
10980
11042
|
try {
|
|
10981
|
-
return
|
|
11043
|
+
return statSync7(jsonlPath).size;
|
|
10982
11044
|
} catch {
|
|
10983
11045
|
return 0;
|
|
10984
11046
|
}
|
|
@@ -10986,9 +11048,9 @@ data: ${JSON.stringify(turn)}
|
|
|
10986
11048
|
let offset = resumeOffset(lastEventId, fileEnd0);
|
|
10987
11049
|
console.log(`[wa-stream] op=open conn=${connId} sessionId=${sessionId} channel=reader resume=${offset}`);
|
|
10988
11050
|
const sessionKey = c.req.query("session_key") ?? "";
|
|
10989
|
-
const subagentsDir = resolve13(
|
|
11051
|
+
const subagentsDir = resolve13(join19(projectDir, sessionId, "subagents"));
|
|
10990
11052
|
console.log(
|
|
10991
|
-
`[webchat-activity] op=watch-subagents key=${sessionKey} dir=${subagentsDir} exists=${
|
|
11053
|
+
`[webchat-activity] op=watch-subagents key=${sessionKey} dir=${subagentsDir} exists=${existsSync13(subagentsDir)}`
|
|
10992
11054
|
);
|
|
10993
11055
|
const actx = makeActivityCtx({
|
|
10994
11056
|
subagentsDir,
|
|
@@ -11102,10 +11164,10 @@ app5.get("/directives", requireAdminSession, (c) => {
|
|
|
11102
11164
|
const sessionId = c.req.query("sessionId") ?? "";
|
|
11103
11165
|
if (!SESSION_ID_RE2.test(sessionId)) return c.json({ error: "bad session reference" }, 400);
|
|
11104
11166
|
const dir = directiveStoreDir(sessionId);
|
|
11105
|
-
if (!dir || !
|
|
11167
|
+
if (!dir || !existsSync13(dir)) return c.json({ entries: [] });
|
|
11106
11168
|
let names;
|
|
11107
11169
|
try {
|
|
11108
|
-
names =
|
|
11170
|
+
names = readdirSync14(dir).filter((n) => DIRECTIVE_NAME_RE.test(n));
|
|
11109
11171
|
} catch {
|
|
11110
11172
|
return c.json({ entries: [] });
|
|
11111
11173
|
}
|
|
@@ -11115,7 +11177,7 @@ app5.get("/directives", requireAdminSession, (c) => {
|
|
|
11115
11177
|
const pid = Number(pidPart);
|
|
11116
11178
|
let len = 0;
|
|
11117
11179
|
try {
|
|
11118
|
-
len =
|
|
11180
|
+
len = statSync7(join19(dir, name)).size;
|
|
11119
11181
|
} catch {
|
|
11120
11182
|
}
|
|
11121
11183
|
return { name, secs, pid, ts: Number.isFinite(secs) ? new Date(secs * 1e3).toISOString() : null, len };
|
|
@@ -11130,7 +11192,7 @@ app5.get("/directive", requireAdminSession, (c) => {
|
|
|
11130
11192
|
}
|
|
11131
11193
|
const dir = directiveStoreDir(sessionId);
|
|
11132
11194
|
if (!dir) return c.json({ error: "no account" }, 404);
|
|
11133
|
-
const path3 = resolve13(
|
|
11195
|
+
const path3 = resolve13(join19(dir, name));
|
|
11134
11196
|
if (!path3.startsWith(dir + sep3)) return c.json({ error: "bad reference" }, 400);
|
|
11135
11197
|
let body;
|
|
11136
11198
|
try {
|
|
@@ -11188,7 +11250,7 @@ app5.get("/store-stream", requireAdminSession, (c) => {
|
|
|
11188
11250
|
console.log(`[wa-reader] op=store-quote msgId=${r.msgKeyId} quoted=${!!q}`);
|
|
11189
11251
|
}
|
|
11190
11252
|
if (r.attachmentId) {
|
|
11191
|
-
const meta = readAttachmentMeta(
|
|
11253
|
+
const meta = readAttachmentMeta(join19(uploadsBase, r.attachmentId));
|
|
11192
11254
|
if (meta) return { ...turn, attachments: [meta] };
|
|
11193
11255
|
}
|
|
11194
11256
|
return turn;
|
|
@@ -11221,7 +11283,7 @@ data: ${JSON.stringify(payload)}
|
|
|
11221
11283
|
};
|
|
11222
11284
|
const fileEnd0 = (() => {
|
|
11223
11285
|
try {
|
|
11224
|
-
return
|
|
11286
|
+
return statSync7(file).size;
|
|
11225
11287
|
} catch {
|
|
11226
11288
|
return 0;
|
|
11227
11289
|
}
|
|
@@ -11439,7 +11501,7 @@ app5.post("/reply", requireAdminSession, async (c) => {
|
|
|
11439
11501
|
const absolute = resolved.absolute;
|
|
11440
11502
|
let size = -1;
|
|
11441
11503
|
try {
|
|
11442
|
-
const st =
|
|
11504
|
+
const st = statSync7(absolute);
|
|
11443
11505
|
size = st.isFile() ? st.size : -1;
|
|
11444
11506
|
} catch {
|
|
11445
11507
|
size = -1;
|
|
@@ -11563,8 +11625,8 @@ app5.post("/reply", requireAdminSession, async (c) => {
|
|
|
11563
11625
|
var whatsapp_reader_default = app5;
|
|
11564
11626
|
|
|
11565
11627
|
// server/routes/public-reader.ts
|
|
11566
|
-
import { statSync as
|
|
11567
|
-
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";
|
|
11568
11630
|
|
|
11569
11631
|
// app/lib/whatsapp-reader/delivered-kinds.ts
|
|
11570
11632
|
var PUBLIC_DELIVERED_KINDS = /* @__PURE__ */ new Set([
|
|
@@ -11638,10 +11700,10 @@ function enumeratePublicRows() {
|
|
|
11638
11700
|
const cfg = claudeConfigDir();
|
|
11639
11701
|
if (!cfg) return [];
|
|
11640
11702
|
const rows = [];
|
|
11641
|
-
for (const { path: path3 } of enumerateJsonls(
|
|
11703
|
+
for (const { path: path3 } of enumerateJsonls(join20(cfg, "projects"))) {
|
|
11642
11704
|
const sessionId = basename5(path3).replace(/\.jsonl$/, "");
|
|
11643
11705
|
const projectDir = dirname6(path3);
|
|
11644
|
-
const meta = readSidecarMeta(
|
|
11706
|
+
const meta = readSidecarMeta(join20(projectDir, `${sessionId}.meta.json`));
|
|
11645
11707
|
rows.push({
|
|
11646
11708
|
sessionId,
|
|
11647
11709
|
projectDir,
|
|
@@ -11697,7 +11759,7 @@ function enrichPublicAttachments(turns, sessionAttachments, cursor) {
|
|
|
11697
11759
|
}
|
|
11698
11760
|
}
|
|
11699
11761
|
function readFrom2(path3, from) {
|
|
11700
|
-
const end =
|
|
11762
|
+
const end = statSync8(path3).size;
|
|
11701
11763
|
if (end <= from) return { buf: Buffer.alloc(0), end: from };
|
|
11702
11764
|
const fd = openSync2(path3, "r");
|
|
11703
11765
|
try {
|
|
@@ -11717,15 +11779,15 @@ app6.get("/stream", (c) => {
|
|
|
11717
11779
|
const sessionId = c.req.query("sessionId") ?? "";
|
|
11718
11780
|
const projectDir = c.req.query("projectDir") ?? "";
|
|
11719
11781
|
const cfg = claudeConfigDir();
|
|
11720
|
-
const projectsRoot = cfg ? resolve14(
|
|
11782
|
+
const projectsRoot = cfg ? resolve14(join20(cfg, "projects")) : null;
|
|
11721
11783
|
if (!cfg || !projectsRoot || !SESSION_ID_RE2.test(sessionId)) {
|
|
11722
11784
|
return c.json({ error: "bad session reference" }, 400);
|
|
11723
11785
|
}
|
|
11724
|
-
const jsonlPath = resolve14(
|
|
11786
|
+
const jsonlPath = resolve14(join20(projectDir, `${sessionId}.jsonl`));
|
|
11725
11787
|
if (!jsonlPath.startsWith(projectsRoot + sep4)) {
|
|
11726
11788
|
return c.json({ error: "bad session reference" }, 400);
|
|
11727
11789
|
}
|
|
11728
|
-
const meta = readSidecarMeta(
|
|
11790
|
+
const meta = readSidecarMeta(join20(projectDir, `${sessionId}.meta.json`));
|
|
11729
11791
|
const isPublicWebchat = meta.role === "public" && meta.channel === "webchat";
|
|
11730
11792
|
const owns = visitor.kind === "person" ? meta.personId === visitor.personId : meta.personId === null && meta.visitorId === visitor.visitorId;
|
|
11731
11793
|
if (!(isPublicWebchat && owns)) {
|
|
@@ -11838,7 +11900,7 @@ app6.get("/attachment/:attachmentId", (c) => {
|
|
|
11838
11900
|
let dataFile;
|
|
11839
11901
|
let buffer;
|
|
11840
11902
|
try {
|
|
11841
|
-
dataFile =
|
|
11903
|
+
dataFile = readdirSync15(dir).find((f) => !f.endsWith(".meta.json") && !f.endsWith(EXTRACTED_TEXT_SUFFIX));
|
|
11842
11904
|
if (!dataFile) throw new Error("no data file");
|
|
11843
11905
|
buffer = readFileSync20(resolve14(dir, dataFile));
|
|
11844
11906
|
} catch {
|
|
@@ -11862,16 +11924,16 @@ var public_reader_default = app6;
|
|
|
11862
11924
|
|
|
11863
11925
|
// server/routes/webchat.ts
|
|
11864
11926
|
import { basename as basename6, dirname as dirname7 } from "path";
|
|
11865
|
-
import { join as
|
|
11866
|
-
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";
|
|
11867
11929
|
|
|
11868
11930
|
// server/canonical-webchat-override.ts
|
|
11869
11931
|
import { readFileSync as readFileSync21, writeFileSync as writeFileSync6, renameSync as renameSync2 } from "fs";
|
|
11870
|
-
import { join as
|
|
11932
|
+
import { join as join21 } from "path";
|
|
11871
11933
|
var FILE = "canonical-webchat-session.json";
|
|
11872
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}$/;
|
|
11873
11935
|
function canonicalOverridePath(accountDir) {
|
|
11874
|
-
return
|
|
11936
|
+
return join21(accountDir, FILE);
|
|
11875
11937
|
}
|
|
11876
11938
|
function readRaw(accountDir) {
|
|
11877
11939
|
try {
|
|
@@ -11950,8 +12012,8 @@ function isNewSessionEffortLevel(value) {
|
|
|
11950
12012
|
}
|
|
11951
12013
|
|
|
11952
12014
|
// ../services/claude-session-manager/src/sidecar-store.ts
|
|
11953
|
-
import { existsSync as
|
|
11954
|
-
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";
|
|
11955
12017
|
function escapeRegExp(s) {
|
|
11956
12018
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
11957
12019
|
}
|
|
@@ -11959,7 +12021,7 @@ function createSidecarStore(config) {
|
|
|
11959
12021
|
const { suffix, validate: validate2 } = config;
|
|
11960
12022
|
const suffixRe = new RegExp(`${escapeRegExp(suffix)}$`);
|
|
11961
12023
|
function pathFor(sessionsDir, id) {
|
|
11962
|
-
return
|
|
12024
|
+
return join22(sessionsDir, `${id}${suffix}`);
|
|
11963
12025
|
}
|
|
11964
12026
|
function write(sessionsDir, id, record) {
|
|
11965
12027
|
mkdirSync4(sessionsDir, { recursive: true });
|
|
@@ -11971,7 +12033,7 @@ function createSidecarStore(config) {
|
|
|
11971
12033
|
return { ok: true };
|
|
11972
12034
|
} catch (error) {
|
|
11973
12035
|
try {
|
|
11974
|
-
if (
|
|
12036
|
+
if (existsSync14(tmp)) unlinkSync2(tmp);
|
|
11975
12037
|
} catch {
|
|
11976
12038
|
}
|
|
11977
12039
|
return { ok: false, error };
|
|
@@ -11996,14 +12058,14 @@ function createSidecarStore(config) {
|
|
|
11996
12058
|
function readAll(sessionsDir, onSkip) {
|
|
11997
12059
|
let names;
|
|
11998
12060
|
try {
|
|
11999
|
-
names =
|
|
12061
|
+
names = readdirSync16(sessionsDir, { withFileTypes: true }).filter((entry) => entry.isFile()).map((entry) => entry.name);
|
|
12000
12062
|
} catch {
|
|
12001
12063
|
return [];
|
|
12002
12064
|
}
|
|
12003
12065
|
const out = [];
|
|
12004
12066
|
for (const name of names) {
|
|
12005
12067
|
if (!suffixRe.test(name)) continue;
|
|
12006
|
-
const path3 =
|
|
12068
|
+
const path3 = join22(sessionsDir, name);
|
|
12007
12069
|
let raw;
|
|
12008
12070
|
try {
|
|
12009
12071
|
raw = readFileSync22(path3, "utf8");
|
|
@@ -12027,7 +12089,7 @@ function createSidecarStore(config) {
|
|
|
12027
12089
|
function clear(sessionsDir, id) {
|
|
12028
12090
|
const path3 = pathFor(sessionsDir, id);
|
|
12029
12091
|
try {
|
|
12030
|
-
if (
|
|
12092
|
+
if (existsSync14(path3)) {
|
|
12031
12093
|
unlinkSync2(path3);
|
|
12032
12094
|
return { ok: true, removed: true };
|
|
12033
12095
|
}
|
|
@@ -12080,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
|
|
|
12080
12142
|
function locateSession(sessionId) {
|
|
12081
12143
|
const dir = findSessionProjectDir(sessionId);
|
|
12082
12144
|
if (!dir) return { projectDir: null, channel: null, accountId: null };
|
|
12083
|
-
const meta = readSidecarMeta(
|
|
12145
|
+
const meta = readSidecarMeta(join23(dir, `${sessionId}.meta.json`));
|
|
12084
12146
|
return { projectDir: dir, channel: meta.channel, accountId: meta.accountId };
|
|
12085
12147
|
}
|
|
12086
12148
|
function locateSidecar(sessionId) {
|
|
12087
12149
|
const cfg = claudeConfigDir();
|
|
12088
12150
|
if (!cfg) return null;
|
|
12089
|
-
const projectsRoot =
|
|
12151
|
+
const projectsRoot = join23(cfg, "projects");
|
|
12090
12152
|
let slugs;
|
|
12091
12153
|
try {
|
|
12092
|
-
slugs =
|
|
12154
|
+
slugs = readdirSync17(projectsRoot, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
12093
12155
|
} catch {
|
|
12094
12156
|
return null;
|
|
12095
12157
|
}
|
|
12096
12158
|
for (const slug of slugs) {
|
|
12097
|
-
const metaPath =
|
|
12098
|
-
if (
|
|
12159
|
+
const metaPath = join23(projectsRoot, slug, `${sessionId}.meta.json`);
|
|
12160
|
+
if (existsSync15(metaPath)) {
|
|
12099
12161
|
const meta = readSidecarMeta(metaPath);
|
|
12100
12162
|
return { channel: meta.channel, adminUserId: meta.adminUserId, accountId: meta.accountId };
|
|
12101
12163
|
}
|
|
@@ -12107,7 +12169,7 @@ function readTargetOwner(sessionId) {
|
|
|
12107
12169
|
if (sidecar !== null) return { found: true, owner: sidecar.adminUserId };
|
|
12108
12170
|
const { projectDir } = locateSession(sessionId);
|
|
12109
12171
|
if (projectDir !== null) {
|
|
12110
|
-
return { found: true, owner: readSidecarMeta(
|
|
12172
|
+
return { found: true, owner: readSidecarMeta(join23(projectDir, `${sessionId}.meta.json`)).adminUserId };
|
|
12111
12173
|
}
|
|
12112
12174
|
return { found: false, owner: null };
|
|
12113
12175
|
}
|
|
@@ -12121,7 +12183,7 @@ function sessionSidecarExists(sessionId) {
|
|
|
12121
12183
|
function jsonlSizeBytes(projectDir, sessionId) {
|
|
12122
12184
|
if (projectDir === null) return null;
|
|
12123
12185
|
try {
|
|
12124
|
-
return
|
|
12186
|
+
return statSync9(join23(projectDir, `${sessionId}.jsonl`)).size;
|
|
12125
12187
|
} catch {
|
|
12126
12188
|
return null;
|
|
12127
12189
|
}
|
|
@@ -12257,15 +12319,15 @@ function latestAdminWebchatSessionId(requesterUserId, primaryUserId, scopeAccoun
|
|
|
12257
12319
|
const cfg = claudeConfigDir();
|
|
12258
12320
|
if (!cfg) return null;
|
|
12259
12321
|
let best = null;
|
|
12260
|
-
for (const { path: path3, isSubagent, archived } of enumerateJsonls(
|
|
12322
|
+
for (const { path: path3, isSubagent, archived } of enumerateJsonls(join23(cfg, "projects"))) {
|
|
12261
12323
|
if (isSubagent || archived) continue;
|
|
12262
12324
|
const id = basename6(path3).slice(0, -".jsonl".length);
|
|
12263
|
-
const meta = readSidecarMeta(
|
|
12325
|
+
const meta = readSidecarMeta(join23(dirname7(path3), `${id}.meta.json`));
|
|
12264
12326
|
if (meta.role !== "admin" || meta.channel !== "webchat") continue;
|
|
12265
12327
|
if (multiAccount && meta.accountId !== scopeAccountId) continue;
|
|
12266
12328
|
let mtimeMs;
|
|
12267
12329
|
try {
|
|
12268
|
-
mtimeMs =
|
|
12330
|
+
mtimeMs = statSync9(path3).mtimeMs;
|
|
12269
12331
|
} catch {
|
|
12270
12332
|
continue;
|
|
12271
12333
|
}
|
|
@@ -12582,7 +12644,7 @@ ${note}` : note;
|
|
|
12582
12644
|
console.error(`[webchat:settings] op=${op} outcome=refused value=${value} reason=account-unresolved`);
|
|
12583
12645
|
return c.json({ error: "account unresolved" }, 503);
|
|
12584
12646
|
}
|
|
12585
|
-
const accountJsonPath =
|
|
12647
|
+
const accountJsonPath = join23(account.accountDir, "account.json");
|
|
12586
12648
|
try {
|
|
12587
12649
|
const parsed = JSON.parse(readFileSync23(accountJsonPath, "utf8"));
|
|
12588
12650
|
if (op === "model") parsed.adminModel = value;
|
|
@@ -12630,7 +12692,7 @@ ${note}` : note;
|
|
|
12630
12692
|
const cfg2 = claudeConfigDir();
|
|
12631
12693
|
if (cfg2) {
|
|
12632
12694
|
const source2 = resolveBridgeSource(
|
|
12633
|
-
|
|
12695
|
+
join23(cfg2, "sessions"),
|
|
12634
12696
|
target,
|
|
12635
12697
|
(id) => locateSession(id).projectDir !== null
|
|
12636
12698
|
);
|
|
@@ -12662,7 +12724,7 @@ ${note}` : note;
|
|
|
12662
12724
|
const cfg = claudeConfigDir();
|
|
12663
12725
|
let projectDir = null;
|
|
12664
12726
|
if (cfg) {
|
|
12665
|
-
for (const { path: path3 } of enumerateJsonls(
|
|
12727
|
+
for (const { path: path3 } of enumerateJsonls(join23(cfg, "projects"))) {
|
|
12666
12728
|
if (basename6(path3) === `${sessionId}.jsonl`) {
|
|
12667
12729
|
projectDir = dirname7(path3);
|
|
12668
12730
|
break;
|
|
@@ -12670,7 +12732,7 @@ ${note}` : note;
|
|
|
12670
12732
|
}
|
|
12671
12733
|
}
|
|
12672
12734
|
if (source === "latest" && requesterUserId !== null) {
|
|
12673
|
-
const owner = readSidecarMeta(
|
|
12735
|
+
const owner = readSidecarMeta(join23(projectDir ?? "", `${sessionId}.meta.json`)).adminUserId;
|
|
12674
12736
|
if (owner !== null && owner !== requesterUserId && requesterUserId !== primaryUserId) {
|
|
12675
12737
|
console.error(`[webchat:inbound] op=session-resolve-foreign key=${sessionId.slice(0, 8)} owner=${owner.slice(0, 8)} requester=${requesterUserId.slice(0, 8)}`);
|
|
12676
12738
|
}
|
|
@@ -12702,8 +12764,8 @@ ${note}` : note;
|
|
|
12702
12764
|
import { resolve as resolve15 } from "path";
|
|
12703
12765
|
|
|
12704
12766
|
// app/lib/claude-agent/specialist-roster.ts
|
|
12705
|
-
import { existsSync as
|
|
12706
|
-
import { join as
|
|
12767
|
+
import { existsSync as existsSync16, readFileSync as readFileSync24, readdirSync as readdirSync18 } from "fs";
|
|
12768
|
+
import { join as join24 } from "path";
|
|
12707
12769
|
function field(fm, name) {
|
|
12708
12770
|
const m = fm.match(new RegExp(`^${name}:\\s*(.*?)\\r?$`, "m"));
|
|
12709
12771
|
if (!m) return null;
|
|
@@ -12714,15 +12776,15 @@ function field(fm, name) {
|
|
|
12714
12776
|
return value || null;
|
|
12715
12777
|
}
|
|
12716
12778
|
function readSpecialistRoster(specialistsDir) {
|
|
12717
|
-
if (!
|
|
12718
|
-
const entries =
|
|
12779
|
+
if (!existsSync16(specialistsDir)) return { specialists: [], skipped: [] };
|
|
12780
|
+
const entries = readdirSync18(specialistsDir);
|
|
12719
12781
|
const specialists = [];
|
|
12720
12782
|
const skipped = [];
|
|
12721
12783
|
for (const file of entries.sort()) {
|
|
12722
12784
|
if (!file.endsWith(".md")) continue;
|
|
12723
12785
|
let raw;
|
|
12724
12786
|
try {
|
|
12725
|
-
raw = readFileSync24(
|
|
12787
|
+
raw = readFileSync24(join24(specialistsDir, file), "utf-8");
|
|
12726
12788
|
} catch (err) {
|
|
12727
12789
|
skipped.push({ file, reason: err instanceof Error ? err.message : String(err) });
|
|
12728
12790
|
continue;
|
|
@@ -12839,8 +12901,8 @@ var webchat_greeting_default = app7;
|
|
|
12839
12901
|
|
|
12840
12902
|
// server/routes/telegram.ts
|
|
12841
12903
|
import { homedir as homedir2 } from "os";
|
|
12842
|
-
import { resolve as resolve16, join as
|
|
12843
|
-
import { existsSync as
|
|
12904
|
+
import { resolve as resolve16, join as join25 } from "path";
|
|
12905
|
+
import { existsSync as existsSync17, readFileSync as readFileSync25 } from "fs";
|
|
12844
12906
|
|
|
12845
12907
|
// app/lib/telegram/gateway/instance.ts
|
|
12846
12908
|
var instance = null;
|
|
@@ -12899,8 +12961,8 @@ function routeTelegramUpdate(input) {
|
|
|
12899
12961
|
var TAG27 = "[telegram-inbound]";
|
|
12900
12962
|
function configDirName() {
|
|
12901
12963
|
const platformRoot5 = process.env.MAXY_PLATFORM_ROOT ?? resolve16(process.cwd(), "..");
|
|
12902
|
-
const brandPath =
|
|
12903
|
-
if (
|
|
12964
|
+
const brandPath = join25(platformRoot5, "config", "brand.json");
|
|
12965
|
+
if (existsSync17(brandPath)) {
|
|
12904
12966
|
try {
|
|
12905
12967
|
return JSON.parse(readFileSync25(brandPath, "utf-8")).configDir ?? ".maxy";
|
|
12906
12968
|
} catch {
|
|
@@ -12921,7 +12983,7 @@ app8.post("/", async (c) => {
|
|
|
12921
12983
|
return c.json({ ok: false }, 400);
|
|
12922
12984
|
}
|
|
12923
12985
|
const sp = secretPath(botType);
|
|
12924
|
-
if (!
|
|
12986
|
+
if (!existsSync17(sp)) {
|
|
12925
12987
|
console.error(`${TAG27} op=reject reason=no-secret-file botType=${botType}`);
|
|
12926
12988
|
return c.json({ ok: false }, 401);
|
|
12927
12989
|
}
|
|
@@ -12988,21 +13050,21 @@ app8.post("/", async (c) => {
|
|
|
12988
13050
|
var telegram_default = app8;
|
|
12989
13051
|
|
|
12990
13052
|
// server/routes/quickbooks.ts
|
|
12991
|
-
import { join as
|
|
12992
|
-
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";
|
|
12993
13055
|
var TAG28 = "[quickbooks]";
|
|
12994
13056
|
var INTUIT_TOKEN_URL = "https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer";
|
|
12995
13057
|
var STATE_RE = /^[A-Za-z0-9_-]+$/;
|
|
12996
13058
|
function pendingPath(accountDir, state) {
|
|
12997
|
-
return
|
|
13059
|
+
return join26(accountDir, "secrets", "quickbooks-pending", `${state}.json`);
|
|
12998
13060
|
}
|
|
12999
13061
|
function storePath(accountDir) {
|
|
13000
|
-
return
|
|
13062
|
+
return join26(accountDir, "secrets", "quickbooks.json");
|
|
13001
13063
|
}
|
|
13002
13064
|
async function completeConsent(args) {
|
|
13003
13065
|
const { accountDir, code, realmId } = args;
|
|
13004
13066
|
const state = args.state;
|
|
13005
|
-
if (!state || !STATE_RE.test(state) || !
|
|
13067
|
+
if (!state || !STATE_RE.test(state) || !existsSync18(pendingPath(accountDir, state))) {
|
|
13006
13068
|
console.error(`${TAG28} op=callback state=${state ?? ""} stateValid=false realmId=${realmId ?? ""}`);
|
|
13007
13069
|
return { ok: false, status: 400, message: "Invalid or unknown authorization state.", stateValid: false };
|
|
13008
13070
|
}
|
|
@@ -13029,7 +13091,7 @@ async function completeConsent(args) {
|
|
|
13029
13091
|
if (!code || !realmId) {
|
|
13030
13092
|
return { ok: false, status: 400, message: "Missing code or realmId in the callback.", stateValid: true };
|
|
13031
13093
|
}
|
|
13032
|
-
if (!
|
|
13094
|
+
if (!existsSync18(storePath(accountDir))) {
|
|
13033
13095
|
return { ok: false, status: 500, message: "No QuickBooks credentials are stored for this account.", stateValid: true };
|
|
13034
13096
|
}
|
|
13035
13097
|
const store2 = JSON.parse(readFileSync26(storePath(accountDir), "utf-8"));
|
|
@@ -13064,7 +13126,7 @@ async function completeConsent(args) {
|
|
|
13064
13126
|
refreshTokenExpiry: now + (body.x_refresh_token_expires_in ?? 864e4) * 1e3,
|
|
13065
13127
|
lastRefresh: now
|
|
13066
13128
|
};
|
|
13067
|
-
mkdirSync5(
|
|
13129
|
+
mkdirSync5(join26(accountDir, "secrets"), { recursive: true });
|
|
13068
13130
|
writeFileSync9(storePath(accountDir), JSON.stringify(store2, null, 2), { mode: 384 });
|
|
13069
13131
|
const persisted = JSON.parse(readFileSync26(storePath(accountDir), "utf-8")).connections?.[realmId]?.refreshToken === body.refresh_token;
|
|
13070
13132
|
console.error(`${TAG28} op=token-exchange realmId=${realmId} persisted=${persisted}`);
|
|
@@ -13097,7 +13159,7 @@ var quickbooks_default = app9;
|
|
|
13097
13159
|
|
|
13098
13160
|
// server/routes/onboarding.ts
|
|
13099
13161
|
import { spawn, spawnSync as spawnSync2, execFileSync as execFileSync3 } from "child_process";
|
|
13100
|
-
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";
|
|
13101
13163
|
import { createHash as createHash4, randomUUID as randomUUID8 } from "crypto";
|
|
13102
13164
|
|
|
13103
13165
|
// app/lib/claude-spawn-env.ts
|
|
@@ -13106,7 +13168,7 @@ function claudeBin() {
|
|
|
13106
13168
|
}
|
|
13107
13169
|
|
|
13108
13170
|
// server/routes/onboarding.ts
|
|
13109
|
-
import { dirname as dirname9, join as
|
|
13171
|
+
import { dirname as dirname9, join as join28 } from "path";
|
|
13110
13172
|
|
|
13111
13173
|
// app/lib/claude-keychain.ts
|
|
13112
13174
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
@@ -13235,8 +13297,8 @@ function readHostCredsBlob(service) {
|
|
|
13235
13297
|
}
|
|
13236
13298
|
|
|
13237
13299
|
// ../lib/admins-write/src/index.ts
|
|
13238
|
-
import { existsSync as
|
|
13239
|
-
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";
|
|
13240
13302
|
function id8(value) {
|
|
13241
13303
|
return value.slice(0, 8);
|
|
13242
13304
|
}
|
|
@@ -13277,7 +13339,7 @@ function writeAdminEntry(input) {
|
|
|
13277
13339
|
const result = { usersJsonResult: "noop", accountJsonResult: "noop" };
|
|
13278
13340
|
try {
|
|
13279
13341
|
let users = [];
|
|
13280
|
-
if (
|
|
13342
|
+
if (existsSync19(input.usersFile)) {
|
|
13281
13343
|
const raw = readFileSync27(input.usersFile, "utf-8").trim();
|
|
13282
13344
|
if (raw) {
|
|
13283
13345
|
const parsed = JSON.parse(raw);
|
|
@@ -13309,8 +13371,8 @@ function writeAdminEntry(input) {
|
|
|
13309
13371
|
return result;
|
|
13310
13372
|
}
|
|
13311
13373
|
try {
|
|
13312
|
-
const accountJsonPath =
|
|
13313
|
-
if (!
|
|
13374
|
+
const accountJsonPath = join27(input.accountDir, "account.json");
|
|
13375
|
+
if (!existsSync19(accountJsonPath)) {
|
|
13314
13376
|
throw new Error(`account.json not found at ${accountJsonPath}`);
|
|
13315
13377
|
}
|
|
13316
13378
|
const config = JSON.parse(readFileSync27(accountJsonPath, "utf-8"));
|
|
@@ -13333,7 +13395,7 @@ function writeAdminEntry(input) {
|
|
|
13333
13395
|
function computeAdminStoreDivergence(input) {
|
|
13334
13396
|
const result = { divergences: 0, accountWithoutUsers: [], usersWithoutAccount: [], errors: [] };
|
|
13335
13397
|
const usersUserIds = /* @__PURE__ */ new Set();
|
|
13336
|
-
if (
|
|
13398
|
+
if (existsSync19(input.usersFile)) {
|
|
13337
13399
|
try {
|
|
13338
13400
|
const raw = readFileSync27(input.usersFile, "utf-8").trim();
|
|
13339
13401
|
if (raw) {
|
|
@@ -13347,24 +13409,24 @@ function computeAdminStoreDivergence(input) {
|
|
|
13347
13409
|
}
|
|
13348
13410
|
}
|
|
13349
13411
|
const accountUserIds = /* @__PURE__ */ new Set();
|
|
13350
|
-
if (
|
|
13412
|
+
if (existsSync19(input.accountsDir)) {
|
|
13351
13413
|
let entries;
|
|
13352
13414
|
try {
|
|
13353
|
-
entries =
|
|
13415
|
+
entries = readdirSync19(input.accountsDir);
|
|
13354
13416
|
} catch (err) {
|
|
13355
13417
|
result.errors.push({ source: input.accountsDir, detail: err instanceof Error ? err.message : String(err) });
|
|
13356
13418
|
return result;
|
|
13357
13419
|
}
|
|
13358
13420
|
for (const entry of entries) {
|
|
13359
13421
|
if (entry.startsWith(".")) continue;
|
|
13360
|
-
const accountDir =
|
|
13422
|
+
const accountDir = join27(input.accountsDir, entry);
|
|
13361
13423
|
try {
|
|
13362
|
-
if (!
|
|
13424
|
+
if (!statSync10(accountDir).isDirectory()) continue;
|
|
13363
13425
|
} catch {
|
|
13364
13426
|
continue;
|
|
13365
13427
|
}
|
|
13366
|
-
const accountJsonPath =
|
|
13367
|
-
if (!
|
|
13428
|
+
const accountJsonPath = join27(accountDir, "account.json");
|
|
13429
|
+
if (!existsSync19(accountJsonPath)) continue;
|
|
13368
13430
|
let admins = [];
|
|
13369
13431
|
try {
|
|
13370
13432
|
const config = JSON.parse(readFileSync27(accountJsonPath, "utf-8"));
|
|
@@ -13415,7 +13477,7 @@ function hashPin2(pin) {
|
|
|
13415
13477
|
return createHash4("sha256").update(pin).digest("hex");
|
|
13416
13478
|
}
|
|
13417
13479
|
function readUsersFile2() {
|
|
13418
|
-
if (!
|
|
13480
|
+
if (!existsSync20(USERS_FILE)) return null;
|
|
13419
13481
|
const raw = readFileSync28(USERS_FILE, "utf-8").trim();
|
|
13420
13482
|
if (!raw) return [];
|
|
13421
13483
|
return JSON.parse(raw);
|
|
@@ -13475,7 +13537,7 @@ app10.post("/claude-auth", async (c) => {
|
|
|
13475
13537
|
} catch (err) {
|
|
13476
13538
|
logoutError = err instanceof Error ? err.message : String(err);
|
|
13477
13539
|
}
|
|
13478
|
-
const credentialsPresent =
|
|
13540
|
+
const credentialsPresent = existsSync20(CLAUDE_CREDENTIALS_FILE);
|
|
13479
13541
|
const ranMs = Date.now() - start;
|
|
13480
13542
|
console.log(`[onboarding] op=claude-logout credentialsPresent=${credentialsPresent} ranMs=${ranMs} logoutError=${logoutError ? JSON.stringify(logoutError.slice(0, 120)) : "none"}`);
|
|
13481
13543
|
return c.json({ logged_out: !credentialsPresent });
|
|
@@ -13541,7 +13603,7 @@ app10.post("/claude-auth", async (c) => {
|
|
|
13541
13603
|
});
|
|
13542
13604
|
persistKeychainService(
|
|
13543
13605
|
writebackResult,
|
|
13544
|
-
(service) => writeFileSync11(
|
|
13606
|
+
(service) => writeFileSync11(join28(dirname9(CLAUDE_CREDENTIALS_FILE), ".keychain-service"), service, { mode: 384 }),
|
|
13545
13607
|
(line) => console.log(line)
|
|
13546
13608
|
);
|
|
13547
13609
|
if (darwinAuthChild === claudeProc2) darwinAuthChild = null;
|
|
@@ -13624,7 +13686,7 @@ app10.post("/set-pin", async (c) => {
|
|
|
13624
13686
|
console.log(`[set-pin] wrote users.json + account.json admins: userId=${userId.slice(0, 8)}\u2026 role=owner`);
|
|
13625
13687
|
if (process.platform === "linux") {
|
|
13626
13688
|
let installOwner = null;
|
|
13627
|
-
if (
|
|
13689
|
+
if (existsSync20(INSTALL_OWNER_FILE)) {
|
|
13628
13690
|
try {
|
|
13629
13691
|
const raw = readFileSync28(INSTALL_OWNER_FILE, "utf-8").trim();
|
|
13630
13692
|
if (raw.length > 0) installOwner = raw;
|
|
@@ -13772,7 +13834,7 @@ app10.put("/set-pin", requireAdminSession, async (c) => {
|
|
|
13772
13834
|
console.log(`[set-pin] changed PIN in place: userId=${sessionUserId.slice(0, 8)}\u2026`);
|
|
13773
13835
|
if (process.platform === "linux") {
|
|
13774
13836
|
let installOwner = null;
|
|
13775
|
-
if (
|
|
13837
|
+
if (existsSync20(INSTALL_OWNER_FILE)) {
|
|
13776
13838
|
try {
|
|
13777
13839
|
const raw = readFileSync28(INSTALL_OWNER_FILE, "utf-8").trim();
|
|
13778
13840
|
if (raw.length > 0) installOwner = raw;
|
|
@@ -13806,9 +13868,9 @@ ${body.newPin}
|
|
|
13806
13868
|
var onboarding_default = app10;
|
|
13807
13869
|
|
|
13808
13870
|
// server/routes/client-error.ts
|
|
13809
|
-
import { appendFileSync as appendFileSync4, existsSync as
|
|
13810
|
-
import { join as
|
|
13811
|
-
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");
|
|
13812
13874
|
var MAX_LOG_SIZE = 10 * 1024 * 1024;
|
|
13813
13875
|
var MAX_BODY_SIZE = 8 * 1024;
|
|
13814
13876
|
var MAX_STACK_LEN = 2e3;
|
|
@@ -13856,8 +13918,8 @@ function stackHead(stack) {
|
|
|
13856
13918
|
}
|
|
13857
13919
|
function rotateIfNeeded() {
|
|
13858
13920
|
try {
|
|
13859
|
-
if (!
|
|
13860
|
-
const stats =
|
|
13921
|
+
if (!existsSync21(CLIENT_ERRORS_LOG)) return;
|
|
13922
|
+
const stats = statSync11(CLIENT_ERRORS_LOG);
|
|
13861
13923
|
if (stats.size < MAX_LOG_SIZE) return;
|
|
13862
13924
|
renameSync8(CLIENT_ERRORS_LOG, CLIENT_ERRORS_LOG + ".1");
|
|
13863
13925
|
} catch (err) {
|
|
@@ -14183,18 +14245,18 @@ app13.get("/", requireAdminSession, async (c) => {
|
|
|
14183
14245
|
var accounts_default = app13;
|
|
14184
14246
|
|
|
14185
14247
|
// server/routes/admin/logs.ts
|
|
14186
|
-
import { existsSync as
|
|
14248
|
+
import { existsSync as existsSync23, readdirSync as readdirSync20, readFileSync as readFileSync29, statSync as statSync12 } from "fs";
|
|
14187
14249
|
import { resolve as resolve17, basename as basename7 } from "path";
|
|
14188
14250
|
|
|
14189
14251
|
// app/lib/logs-read-resolve.ts
|
|
14190
|
-
import { existsSync as
|
|
14191
|
-
import { join as
|
|
14252
|
+
import { existsSync as existsSync22 } from "fs";
|
|
14253
|
+
import { join as join30 } from "path";
|
|
14192
14254
|
function resolveSessionLogPaths(filename, logDirs) {
|
|
14193
14255
|
const tried = [filename];
|
|
14194
14256
|
const hits = [];
|
|
14195
14257
|
for (const dir of logDirs) {
|
|
14196
|
-
const fullPath =
|
|
14197
|
-
if (
|
|
14258
|
+
const fullPath = join30(dir, filename);
|
|
14259
|
+
if (existsSync22(fullPath)) {
|
|
14198
14260
|
hits.push({ path: fullPath, dir });
|
|
14199
14261
|
}
|
|
14200
14262
|
}
|
|
@@ -14223,7 +14285,7 @@ app14.get("/", async (c) => {
|
|
|
14223
14285
|
searched.push(filePath);
|
|
14224
14286
|
try {
|
|
14225
14287
|
const buffer = readFileSync29(filePath);
|
|
14226
|
-
const onDiskBytes =
|
|
14288
|
+
const onDiskBytes = statSync12(filePath).size;
|
|
14227
14289
|
const headers = {
|
|
14228
14290
|
"Content-Type": "text/plain; charset=utf-8",
|
|
14229
14291
|
"Content-Length": String(buffer.byteLength)
|
|
@@ -14288,7 +14350,7 @@ app14.get("/", async (c) => {
|
|
|
14288
14350
|
try {
|
|
14289
14351
|
const filename = basename7(hit.path);
|
|
14290
14352
|
const buffer = readFileSync29(hit.path);
|
|
14291
|
-
const onDiskBytes =
|
|
14353
|
+
const onDiskBytes = statSync12(hit.path).size;
|
|
14292
14354
|
const headers = {
|
|
14293
14355
|
"Content-Type": "text/plain; charset=utf-8",
|
|
14294
14356
|
"Content-Length": String(buffer.byteLength)
|
|
@@ -14322,16 +14384,16 @@ app14.get("/", async (c) => {
|
|
|
14322
14384
|
const seen = /* @__PURE__ */ new Set();
|
|
14323
14385
|
const logs = {};
|
|
14324
14386
|
for (const dir of logDirs) {
|
|
14325
|
-
if (!
|
|
14387
|
+
if (!existsSync23(dir)) continue;
|
|
14326
14388
|
let files;
|
|
14327
14389
|
try {
|
|
14328
|
-
files =
|
|
14390
|
+
files = readdirSync20(dir).filter((f) => f.endsWith(".log"));
|
|
14329
14391
|
} catch (err) {
|
|
14330
14392
|
const reason = err instanceof Error ? err.message : String(err);
|
|
14331
14393
|
console.warn(`[admin/logs] readdir-fail dir=${dir} reason=${reason}`);
|
|
14332
14394
|
continue;
|
|
14333
14395
|
}
|
|
14334
|
-
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 }) => {
|
|
14335
14397
|
seen.add(name);
|
|
14336
14398
|
try {
|
|
14337
14399
|
const content = readFileSync29(resolve17(dir, name));
|
|
@@ -14374,7 +14436,7 @@ var claude_info_default = app15;
|
|
|
14374
14436
|
|
|
14375
14437
|
// server/routes/admin/attachment.ts
|
|
14376
14438
|
import { readFile as readFile2, readdir } from "fs/promises";
|
|
14377
|
-
import { existsSync as
|
|
14439
|
+
import { existsSync as existsSync24 } from "fs";
|
|
14378
14440
|
import { resolve as resolve18 } from "path";
|
|
14379
14441
|
var app16 = new Hono();
|
|
14380
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}$/;
|
|
@@ -14397,12 +14459,12 @@ app16.get("/:attachmentId", requireAdminSession, async (c) => {
|
|
|
14397
14459
|
}
|
|
14398
14460
|
let accountId = pinnedAccountId;
|
|
14399
14461
|
let dir = uploadsDirFor2(accountId, attachmentId);
|
|
14400
|
-
let found =
|
|
14462
|
+
let found = existsSync24(dir);
|
|
14401
14463
|
if (!found) {
|
|
14402
14464
|
for (const candidate of listValidAccounts()) {
|
|
14403
14465
|
if (candidate.accountId === pinnedAccountId) continue;
|
|
14404
14466
|
const candidateDir = uploadsDirFor2(candidate.accountId, attachmentId);
|
|
14405
|
-
if (
|
|
14467
|
+
if (existsSync24(candidateDir)) {
|
|
14406
14468
|
accountId = candidate.accountId;
|
|
14407
14469
|
dir = candidateDir;
|
|
14408
14470
|
found = true;
|
|
@@ -14417,7 +14479,7 @@ app16.get("/:attachmentId", requireAdminSession, async (c) => {
|
|
|
14417
14479
|
return new Response("Not found", { status: 404 });
|
|
14418
14480
|
}
|
|
14419
14481
|
const metaPath = resolve18(dir, `${attachmentId}.meta.json`);
|
|
14420
|
-
if (!
|
|
14482
|
+
if (!existsSync24(metaPath)) {
|
|
14421
14483
|
return new Response("Not found", { status: 404 });
|
|
14422
14484
|
}
|
|
14423
14485
|
let meta;
|
|
@@ -14451,21 +14513,21 @@ var attachment_default = app16;
|
|
|
14451
14513
|
|
|
14452
14514
|
// server/routes/admin/agents.ts
|
|
14453
14515
|
import { resolve as resolve19 } from "path";
|
|
14454
|
-
import { readdirSync as
|
|
14516
|
+
import { readdirSync as readdirSync21, readFileSync as readFileSync30, existsSync as existsSync25, rmSync as rmSync2 } from "fs";
|
|
14455
14517
|
var app17 = new Hono();
|
|
14456
14518
|
app17.get("/", (c) => {
|
|
14457
14519
|
const account = resolveAccount();
|
|
14458
14520
|
if (!account) return c.json({ agents: [] });
|
|
14459
14521
|
const agentsDir = resolve19(account.accountDir, "agents");
|
|
14460
|
-
if (!
|
|
14522
|
+
if (!existsSync25(agentsDir)) return c.json({ agents: [] });
|
|
14461
14523
|
const agents = [];
|
|
14462
14524
|
try {
|
|
14463
|
-
const entries =
|
|
14525
|
+
const entries = readdirSync21(agentsDir, { withFileTypes: true });
|
|
14464
14526
|
for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
14465
14527
|
if (!entry.isDirectory()) continue;
|
|
14466
14528
|
if (entry.name === "admin") continue;
|
|
14467
14529
|
const configPath2 = resolve19(agentsDir, entry.name, "config.json");
|
|
14468
|
-
if (!
|
|
14530
|
+
if (!existsSync25(configPath2)) continue;
|
|
14469
14531
|
try {
|
|
14470
14532
|
const config = JSON.parse(readFileSync30(configPath2, "utf-8"));
|
|
14471
14533
|
agents.push({
|
|
@@ -14494,7 +14556,7 @@ app17.delete("/:slug", async (c) => {
|
|
|
14494
14556
|
return c.json({ error: "Invalid agent slug" }, 400);
|
|
14495
14557
|
}
|
|
14496
14558
|
const agentDir = resolve19(account.accountDir, "agents", slug);
|
|
14497
|
-
if (!
|
|
14559
|
+
if (!existsSync25(agentDir)) {
|
|
14498
14560
|
return c.json({ error: "Agent not found" }, 404);
|
|
14499
14561
|
}
|
|
14500
14562
|
try {
|
|
@@ -14524,7 +14586,7 @@ app17.post("/:slug/project", async (c) => {
|
|
|
14524
14586
|
return c.json({ error: "Invalid agent slug" }, 400);
|
|
14525
14587
|
}
|
|
14526
14588
|
const agentDir = resolve19(account.accountDir, "agents", slug);
|
|
14527
|
-
if (!
|
|
14589
|
+
if (!existsSync25(agentDir)) {
|
|
14528
14590
|
return c.json({ error: "Agent not found on disk" }, 404);
|
|
14529
14591
|
}
|
|
14530
14592
|
try {
|
|
@@ -14540,7 +14602,7 @@ var agents_default = app17;
|
|
|
14540
14602
|
// server/routes/admin/sessions.ts
|
|
14541
14603
|
import crypto2 from "crypto";
|
|
14542
14604
|
import { resolve as resolvePath } from "path";
|
|
14543
|
-
import { existsSync as
|
|
14605
|
+
import { existsSync as existsSync26, mkdirSync as mkdirSync7, createWriteStream } from "fs";
|
|
14544
14606
|
|
|
14545
14607
|
// ../lib/admin-conversation-purge/src/index.ts
|
|
14546
14608
|
async function purgeAdminConversationJsonls(args) {
|
|
@@ -14700,7 +14762,7 @@ function validateAndShapeAttachments(raws, conversationAccountId, sessionId, mes
|
|
|
14700
14762
|
let reason = null;
|
|
14701
14763
|
if (!a.attachmentId || !a.filename || !a.mimeType || !a.storagePath) reason = "schema-fail";
|
|
14702
14764
|
else if (a.accountId !== conversationAccountId) reason = "account-mismatch";
|
|
14703
|
-
else if (!
|
|
14765
|
+
else if (!existsSync26(a.storagePath)) reason = "missing-file";
|
|
14704
14766
|
if (reason) {
|
|
14705
14767
|
invalid++;
|
|
14706
14768
|
try {
|
|
@@ -15226,8 +15288,8 @@ app18.put("/:id/label", requireAdminSession, async (c) => {
|
|
|
15226
15288
|
var sessions_default = app18;
|
|
15227
15289
|
|
|
15228
15290
|
// app/lib/claude-agent/spawn-context.ts
|
|
15229
|
-
import { existsSync as
|
|
15230
|
-
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";
|
|
15231
15293
|
async function resolveOwnerProfileBlock(accountId, userId) {
|
|
15232
15294
|
if (!userId) return { ok: false, reason: "missing-user-id" };
|
|
15233
15295
|
try {
|
|
@@ -15268,12 +15330,12 @@ function frontmatterField(manifest, field2) {
|
|
|
15268
15330
|
function extractPluginToolDescriptions(pluginDir) {
|
|
15269
15331
|
const out = /* @__PURE__ */ new Map();
|
|
15270
15332
|
const candidates = [
|
|
15271
|
-
|
|
15272
|
-
|
|
15333
|
+
join31(pluginDir, "mcp/dist/index.js"),
|
|
15334
|
+
join31(pluginDir, "mcp/src/index.ts")
|
|
15273
15335
|
];
|
|
15274
15336
|
let raw = null;
|
|
15275
15337
|
for (const path3 of candidates) {
|
|
15276
|
-
if (!
|
|
15338
|
+
if (!existsSync27(path3)) continue;
|
|
15277
15339
|
try {
|
|
15278
15340
|
raw = readFileSync31(path3, "utf-8");
|
|
15279
15341
|
break;
|
|
@@ -15325,25 +15387,25 @@ function parseSkillPathsFromFrontmatter(fm) {
|
|
|
15325
15387
|
function listPluginDirs() {
|
|
15326
15388
|
const out = /* @__PURE__ */ new Map();
|
|
15327
15389
|
const platformPlugins = resolve20(PLATFORM_ROOT, "plugins");
|
|
15328
|
-
if (
|
|
15329
|
-
for (const name of
|
|
15330
|
-
const dir =
|
|
15390
|
+
if (existsSync27(platformPlugins)) {
|
|
15391
|
+
for (const name of readdirSync22(platformPlugins)) {
|
|
15392
|
+
const dir = join31(platformPlugins, name);
|
|
15331
15393
|
try {
|
|
15332
|
-
if (
|
|
15394
|
+
if (statSync13(dir).isDirectory()) out.set(name, dir);
|
|
15333
15395
|
} catch {
|
|
15334
15396
|
}
|
|
15335
15397
|
}
|
|
15336
15398
|
}
|
|
15337
15399
|
const premiumRoot = resolve20(dirname10(PLATFORM_ROOT), "premium-plugins");
|
|
15338
|
-
if (
|
|
15339
|
-
for (const bundle of
|
|
15340
|
-
const bundlePlugins =
|
|
15341
|
-
if (!
|
|
15400
|
+
if (existsSync27(premiumRoot)) {
|
|
15401
|
+
for (const bundle of readdirSync22(premiumRoot)) {
|
|
15402
|
+
const bundlePlugins = join31(premiumRoot, bundle, "plugins");
|
|
15403
|
+
if (!existsSync27(bundlePlugins)) continue;
|
|
15342
15404
|
try {
|
|
15343
|
-
for (const name of
|
|
15344
|
-
const dir =
|
|
15405
|
+
for (const name of readdirSync22(bundlePlugins)) {
|
|
15406
|
+
const dir = join31(bundlePlugins, name);
|
|
15345
15407
|
try {
|
|
15346
|
-
if (
|
|
15408
|
+
if (statSync13(dir).isDirectory()) out.set(name, dir);
|
|
15347
15409
|
} catch {
|
|
15348
15410
|
}
|
|
15349
15411
|
}
|
|
@@ -15355,7 +15417,7 @@ function listPluginDirs() {
|
|
|
15355
15417
|
}
|
|
15356
15418
|
function readEnabledPlugins(accountId) {
|
|
15357
15419
|
const accountFile = resolve20(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
|
|
15358
|
-
if (!
|
|
15420
|
+
if (!existsSync27(accountFile)) return /* @__PURE__ */ new Set();
|
|
15359
15421
|
try {
|
|
15360
15422
|
const parsed = JSON.parse(readFileSync31(accountFile, "utf-8"));
|
|
15361
15423
|
return new Set(
|
|
@@ -15366,7 +15428,7 @@ function readEnabledPlugins(accountId) {
|
|
|
15366
15428
|
}
|
|
15367
15429
|
}
|
|
15368
15430
|
function readFrontmatter(path3) {
|
|
15369
|
-
if (!
|
|
15431
|
+
if (!existsSync27(path3)) return null;
|
|
15370
15432
|
let raw;
|
|
15371
15433
|
try {
|
|
15372
15434
|
raw = readFileSync31(path3, "utf-8");
|
|
@@ -15384,7 +15446,7 @@ function computeActivePlugins(accountId) {
|
|
|
15384
15446
|
for (const name of Array.from(enabled).sort()) {
|
|
15385
15447
|
const dir = pluginDirs.get(name);
|
|
15386
15448
|
if (!dir) continue;
|
|
15387
|
-
const fm = readFrontmatter(
|
|
15449
|
+
const fm = readFrontmatter(join31(dir, "PLUGIN.md"));
|
|
15388
15450
|
if (!fm) continue;
|
|
15389
15451
|
const description = frontmatterField(`---
|
|
15390
15452
|
${fm}
|
|
@@ -15401,7 +15463,7 @@ ${fm}
|
|
|
15401
15463
|
`plugin-manifest-tool-coverage plugin=${name} tools=${tools.length} with-desc=${withDesc}`
|
|
15402
15464
|
);
|
|
15403
15465
|
if (toolNames.length > 0 && descMap.size === 0) {
|
|
15404
|
-
const hasSource =
|
|
15466
|
+
const hasSource = existsSync27(join31(dir, "mcp/dist/index.js")) || existsSync27(join31(dir, "mcp/src/index.ts"));
|
|
15405
15467
|
if (hasSource) {
|
|
15406
15468
|
console.warn(
|
|
15407
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`
|
|
@@ -15411,7 +15473,7 @@ ${fm}
|
|
|
15411
15473
|
const skillPaths = parseSkillPathsFromFrontmatter(fm);
|
|
15412
15474
|
const skills = [];
|
|
15413
15475
|
for (const relPath of skillPaths) {
|
|
15414
|
-
const skillPath =
|
|
15476
|
+
const skillPath = join31(dir, relPath);
|
|
15415
15477
|
const skillFm = readFrontmatter(skillPath);
|
|
15416
15478
|
if (!skillFm) continue;
|
|
15417
15479
|
const skillName = frontmatterField(`---
|
|
@@ -15428,10 +15490,10 @@ ${skillFm}
|
|
|
15428
15490
|
}
|
|
15429
15491
|
function computeSpecialistDomains(accountId) {
|
|
15430
15492
|
const specialistsDir = resolve20(PLATFORM_ROOT, "..", "data/accounts", accountId, "specialists", "agents");
|
|
15431
|
-
if (!
|
|
15493
|
+
if (!existsSync27(specialistsDir)) return [];
|
|
15432
15494
|
let entries;
|
|
15433
15495
|
try {
|
|
15434
|
-
entries =
|
|
15496
|
+
entries = readdirSync22(specialistsDir);
|
|
15435
15497
|
} catch {
|
|
15436
15498
|
return [];
|
|
15437
15499
|
}
|
|
@@ -15455,7 +15517,7 @@ function computeSpecialistDomains(accountId) {
|
|
|
15455
15517
|
const out = [];
|
|
15456
15518
|
for (const file of entries.sort()) {
|
|
15457
15519
|
if (!file.endsWith(".md")) continue;
|
|
15458
|
-
const fm = readFrontmatter(
|
|
15520
|
+
const fm = readFrontmatter(join31(specialistsDir, file));
|
|
15459
15521
|
if (!fm) continue;
|
|
15460
15522
|
const wrapped = `---
|
|
15461
15523
|
${fm}
|
|
@@ -15474,7 +15536,7 @@ ${fm}
|
|
|
15474
15536
|
}
|
|
15475
15537
|
function computeDormantPlugins(accountId) {
|
|
15476
15538
|
const accountFile = resolve20(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
|
|
15477
|
-
if (!
|
|
15539
|
+
if (!existsSync27(accountFile)) return [];
|
|
15478
15540
|
let enabled;
|
|
15479
15541
|
try {
|
|
15480
15542
|
const raw = readFileSync31(accountFile, "utf-8");
|
|
@@ -15489,10 +15551,10 @@ function computeDormantPlugins(accountId) {
|
|
|
15489
15551
|
return [];
|
|
15490
15552
|
}
|
|
15491
15553
|
const pluginsDir = resolve20(PLATFORM_ROOT, "plugins");
|
|
15492
|
-
if (!
|
|
15554
|
+
if (!existsSync27(pluginsDir)) return [];
|
|
15493
15555
|
let entries;
|
|
15494
15556
|
try {
|
|
15495
|
-
entries =
|
|
15557
|
+
entries = readdirSync22(pluginsDir);
|
|
15496
15558
|
} catch {
|
|
15497
15559
|
return [];
|
|
15498
15560
|
}
|
|
@@ -15500,7 +15562,7 @@ function computeDormantPlugins(accountId) {
|
|
|
15500
15562
|
for (const name of entries) {
|
|
15501
15563
|
if (enabled.has(name)) continue;
|
|
15502
15564
|
const manifestPath = resolve20(pluginsDir, name, "PLUGIN.md");
|
|
15503
|
-
if (!
|
|
15565
|
+
if (!existsSync27(manifestPath)) continue;
|
|
15504
15566
|
let manifest;
|
|
15505
15567
|
try {
|
|
15506
15568
|
manifest = readFileSync31(manifestPath, "utf-8");
|
|
@@ -15517,11 +15579,11 @@ function computeDormantPlugins(accountId) {
|
|
|
15517
15579
|
}
|
|
15518
15580
|
|
|
15519
15581
|
// server/routes/admin/claude-sessions.ts
|
|
15520
|
-
import { existsSync as
|
|
15582
|
+
import { existsSync as existsSync28, readFileSync as readFileSync32 } from "fs";
|
|
15521
15583
|
import { resolve as resolve21 } from "path";
|
|
15522
15584
|
function readTunnelState(brandConfigDir) {
|
|
15523
15585
|
const statePath = `${process.env.HOME ?? ""}/${brandConfigDir}/cloudflared/tunnel.state`;
|
|
15524
|
-
if (!
|
|
15586
|
+
if (!existsSync28(statePath)) return null;
|
|
15525
15587
|
try {
|
|
15526
15588
|
const parsed = JSON.parse(readFileSync32(statePath, "utf-8"));
|
|
15527
15589
|
const tunnelId = typeof parsed.tunnelId === "string" ? parsed.tunnelId : null;
|
|
@@ -15779,11 +15841,11 @@ app21.post("/", async (c) => {
|
|
|
15779
15841
|
var events_default = app21;
|
|
15780
15842
|
|
|
15781
15843
|
// server/routes/admin/files.ts
|
|
15782
|
-
import { createReadStream as createReadStream2, createWriteStream as createWriteStream2, existsSync as
|
|
15844
|
+
import { createReadStream as createReadStream2, createWriteStream as createWriteStream2, existsSync as existsSync29 } from "fs";
|
|
15783
15845
|
import { readdir as readdir3, readFile as readFile4, stat as stat4, mkdir as mkdir3, unlink as unlink2, rename, rmdir } from "fs/promises";
|
|
15784
15846
|
import { realpathSync as realpathSync6 } from "fs";
|
|
15785
15847
|
import { randomUUID as randomUUID10 } from "crypto";
|
|
15786
|
-
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";
|
|
15787
15849
|
import { Readable as Readable2 } from "stream";
|
|
15788
15850
|
|
|
15789
15851
|
// ../lib/graph-trash/src/index.ts
|
|
@@ -16020,7 +16082,7 @@ async function restoreNode(params) {
|
|
|
16020
16082
|
}
|
|
16021
16083
|
|
|
16022
16084
|
// app/lib/file-delete-cascade.ts
|
|
16023
|
-
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;
|
|
16024
16086
|
function parseAttachmentPath(relPath) {
|
|
16025
16087
|
const segments = relPath.split("/").filter(Boolean);
|
|
16026
16088
|
if (segments.length !== 5) return null;
|
|
@@ -16028,7 +16090,7 @@ function parseAttachmentPath(relPath) {
|
|
|
16028
16090
|
const accountId = segments[1];
|
|
16029
16091
|
const attachmentId = segments[3];
|
|
16030
16092
|
const filename = segments[4];
|
|
16031
|
-
if (!
|
|
16093
|
+
if (!UUID_RE3.test(accountId) || !UUID_RE3.test(attachmentId)) return null;
|
|
16032
16094
|
const dot = filename.lastIndexOf(".");
|
|
16033
16095
|
if (dot === -1) return null;
|
|
16034
16096
|
const stem = filename.slice(0, dot);
|
|
@@ -16101,7 +16163,7 @@ async function cascadeDeleteDocument(params) {
|
|
|
16101
16163
|
|
|
16102
16164
|
// app/lib/file-index.ts
|
|
16103
16165
|
import * as fsp from "fs/promises";
|
|
16104
|
-
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";
|
|
16105
16167
|
import { tmpdir as tmpdir2 } from "os";
|
|
16106
16168
|
import { execFile as execFile2 } from "child_process";
|
|
16107
16169
|
import { promisify as promisify2 } from "util";
|
|
@@ -16183,7 +16245,7 @@ async function extractPdf(absolute) {
|
|
|
16183
16245
|
return stdout.trim();
|
|
16184
16246
|
}
|
|
16185
16247
|
async function ocrPdf(absolute) {
|
|
16186
|
-
const outPdf =
|
|
16248
|
+
const outPdf = join32(tmpdir2(), `file-index-ocr-${process.pid}-${Date.now()}.pdf`);
|
|
16187
16249
|
try {
|
|
16188
16250
|
await execFileAsync2(
|
|
16189
16251
|
"ocrmypdf",
|
|
@@ -16245,7 +16307,7 @@ async function readDisplayName(absolute) {
|
|
|
16245
16307
|
const stem = dot === -1 ? base : base.slice(0, dot);
|
|
16246
16308
|
if (base === `${stem}.meta.json`) return null;
|
|
16247
16309
|
try {
|
|
16248
|
-
const raw = await fsp.readFile(
|
|
16310
|
+
const raw = await fsp.readFile(join32(dir, `${stem}.meta.json`), "utf-8");
|
|
16249
16311
|
const meta = JSON.parse(raw);
|
|
16250
16312
|
const dn = meta.displayName ?? meta.filename;
|
|
16251
16313
|
return typeof dn === "string" && dn.length > 0 ? dn : null;
|
|
@@ -16266,7 +16328,7 @@ async function walkSubtree(root, dataRoot, out) {
|
|
|
16266
16328
|
for (const entry of entries) {
|
|
16267
16329
|
if (entry.isSymbolicLink()) continue;
|
|
16268
16330
|
if (entry.isDirectory() && entry.name === ".uploads-tmp") continue;
|
|
16269
|
-
const abs =
|
|
16331
|
+
const abs = join32(root, entry.name);
|
|
16270
16332
|
if (entry.isDirectory()) {
|
|
16271
16333
|
const sub = await walkSubtree(abs, dataRoot, out);
|
|
16272
16334
|
if (!sub.clean) clean = false;
|
|
@@ -16619,10 +16681,10 @@ function buildZip(entries) {
|
|
|
16619
16681
|
|
|
16620
16682
|
// server/routes/admin/files.ts
|
|
16621
16683
|
var UPLOAD_TMP_DIR = ".uploads-tmp";
|
|
16622
|
-
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;
|
|
16623
16685
|
async function readMeta(absDir, baseName) {
|
|
16624
16686
|
try {
|
|
16625
|
-
const raw = await readFile4(
|
|
16687
|
+
const raw = await readFile4(join33(absDir, `${baseName}.meta.json`), "utf8");
|
|
16626
16688
|
const parsed = JSON.parse(raw);
|
|
16627
16689
|
if (typeof parsed?.filename === "string") {
|
|
16628
16690
|
return { filename: parsed.filename, mimeType: typeof parsed.mimeType === "string" ? parsed.mimeType : void 0 };
|
|
@@ -16641,7 +16703,7 @@ async function readAccountNames() {
|
|
|
16641
16703
|
return map;
|
|
16642
16704
|
}
|
|
16643
16705
|
for (const name of names) {
|
|
16644
|
-
if (!
|
|
16706
|
+
if (!UUID_RE4.test(name)) continue;
|
|
16645
16707
|
const configPath2 = resolve23(accountsDir, name, "account.json");
|
|
16646
16708
|
try {
|
|
16647
16709
|
const raw = await readFile4(configPath2, "utf8");
|
|
@@ -16676,8 +16738,8 @@ async function servableFilesIn(dirAbs, uuid) {
|
|
|
16676
16738
|
return out;
|
|
16677
16739
|
}
|
|
16678
16740
|
async function enrich(absolute, entry, accountNames) {
|
|
16679
|
-
if (entry.kind === "directory" &&
|
|
16680
|
-
const dirAbs =
|
|
16741
|
+
if (entry.kind === "directory" && UUID_RE4.test(entry.name)) {
|
|
16742
|
+
const dirAbs = join33(absolute, entry.name);
|
|
16681
16743
|
const meta = await readMeta(dirAbs, entry.name);
|
|
16682
16744
|
if (meta?.filename) {
|
|
16683
16745
|
const servable = await servableFilesIn(dirAbs, entry.name);
|
|
@@ -16686,7 +16748,7 @@ async function enrich(absolute, entry, accountNames) {
|
|
|
16686
16748
|
let size = null;
|
|
16687
16749
|
let modifiedAt = entry.modifiedAt;
|
|
16688
16750
|
try {
|
|
16689
|
-
const st = await stat4(
|
|
16751
|
+
const st = await stat4(join33(dirAbs, innerName));
|
|
16690
16752
|
size = st.size;
|
|
16691
16753
|
modifiedAt = st.mtime.toISOString();
|
|
16692
16754
|
} catch {
|
|
@@ -16711,7 +16773,7 @@ async function enrich(absolute, entry, accountNames) {
|
|
|
16711
16773
|
if (entry.kind === "file") {
|
|
16712
16774
|
const dot = entry.name.lastIndexOf(".");
|
|
16713
16775
|
const base = dot === -1 ? entry.name : entry.name.slice(0, dot);
|
|
16714
|
-
if (
|
|
16776
|
+
if (UUID_RE4.test(base)) {
|
|
16715
16777
|
const meta = await readMeta(absolute, base);
|
|
16716
16778
|
if (meta?.filename) {
|
|
16717
16779
|
entry.displayName = meta.filename;
|
|
@@ -16724,7 +16786,7 @@ async function enrich(absolute, entry, accountNames) {
|
|
|
16724
16786
|
function buildDisplayPath(relPath, accountNames) {
|
|
16725
16787
|
if (relPath === "." || relPath === "") return [];
|
|
16726
16788
|
return relPath.split("/").filter(Boolean).map((seg) => {
|
|
16727
|
-
const dn =
|
|
16789
|
+
const dn = UUID_RE4.test(seg) ? accountNames.get(seg) : void 0;
|
|
16728
16790
|
return dn ? { name: seg, displayName: dn } : { name: seg };
|
|
16729
16791
|
});
|
|
16730
16792
|
}
|
|
@@ -16774,11 +16836,11 @@ function isProtectedFromRename(relPath) {
|
|
|
16774
16836
|
if (segments.length === 3 && segments[0] === "accounts" && segments[2] === "uploads") {
|
|
16775
16837
|
return true;
|
|
16776
16838
|
}
|
|
16777
|
-
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])) {
|
|
16778
16840
|
return true;
|
|
16779
16841
|
}
|
|
16780
16842
|
if (parseAttachmentPath(relPath) !== null) return true;
|
|
16781
|
-
if (
|
|
16843
|
+
if (UUID_RE4.test(base.replace(/\.meta\.json$/, "")) && base.endsWith(".meta.json")) {
|
|
16782
16844
|
return true;
|
|
16783
16845
|
}
|
|
16784
16846
|
return false;
|
|
@@ -16852,16 +16914,16 @@ app22.get("/", requireAdminSession, async (c) => {
|
|
|
16852
16914
|
const isAccountParent = segs.length === 1 && segs[0] === "accounts";
|
|
16853
16915
|
const entries = [];
|
|
16854
16916
|
for (const name of names) {
|
|
16855
|
-
if (
|
|
16917
|
+
if (UUID_RE4.test(name.replace(/\.meta\.json$/, "")) && name.endsWith(".meta.json")) {
|
|
16856
16918
|
continue;
|
|
16857
16919
|
}
|
|
16858
|
-
if (isAccountParent &&
|
|
16920
|
+
if (isAccountParent && UUID_RE4.test(name) && name !== accountId) {
|
|
16859
16921
|
continue;
|
|
16860
16922
|
}
|
|
16861
16923
|
const childRel = relPath === "" || relPath === "." ? name : `${relPath}/${name}`;
|
|
16862
16924
|
const protectedEntry = isProtectedFromDeletion(childRel).protected;
|
|
16863
16925
|
try {
|
|
16864
|
-
const entryPath =
|
|
16926
|
+
const entryPath = join33(absolute, name);
|
|
16865
16927
|
const s = await stat4(entryPath);
|
|
16866
16928
|
entries.push({
|
|
16867
16929
|
name,
|
|
@@ -16924,7 +16986,7 @@ app22.get("/download", requireAdminSession, async (c) => {
|
|
|
16924
16986
|
console.error(`[data] op=scratchpad-no-session sessionId="${sessionId.slice(0, 8)}\u2026"`);
|
|
16925
16987
|
return c.json({ error: "Not found" }, 404);
|
|
16926
16988
|
}
|
|
16927
|
-
const meta = readSidecarMeta(
|
|
16989
|
+
const meta = readSidecarMeta(join33(projectDir, `${sessionId}.meta.json`));
|
|
16928
16990
|
if (!meta.accountId || meta.accountId !== accountId) {
|
|
16929
16991
|
console.error(`[data] account-scope-blocked root="scratchpad" sessionId="${sessionId.slice(0, 8)}\u2026" account=${accountId.slice(0, 8)}\u2026`);
|
|
16930
16992
|
return c.json({ error: "Not found" }, 404);
|
|
@@ -17019,7 +17081,7 @@ async function* walkRegularFiles(dirAbsolute) {
|
|
|
17019
17081
|
const dirents = await readdir3(dirAbsolute, { withFileTypes: true });
|
|
17020
17082
|
for (const d of dirents) {
|
|
17021
17083
|
if (d.isSymbolicLink()) continue;
|
|
17022
|
-
const child =
|
|
17084
|
+
const child = join33(dirAbsolute, d.name);
|
|
17023
17085
|
if (d.isDirectory()) {
|
|
17024
17086
|
yield* walkRegularFiles(child);
|
|
17025
17087
|
continue;
|
|
@@ -17129,7 +17191,7 @@ async function resolveUploadTarget(c, accountId, uid) {
|
|
|
17129
17191
|
const base = resolveOwnAccountWrite(rawDir, accountId, "POST /api/admin/files/upload");
|
|
17130
17192
|
if (!base.ok) return { ok: false, status: base.status, error: base.error };
|
|
17131
17193
|
const relDir = relpath ? dirname11(relpath) : ".";
|
|
17132
|
-
const destRel = relDir === "." ? base.relative :
|
|
17194
|
+
const destRel = relDir === "." ? base.relative : join33(base.relative, relDir);
|
|
17133
17195
|
if (crossesForeignAccountPartition(destRel, accountId)) {
|
|
17134
17196
|
console.error(`[data] account-scope-blocked endpoint="POST /api/admin/files/upload" path="${destRel}" account=${accountId.slice(0, 8)}\u2026`);
|
|
17135
17197
|
return { ok: false, status: 404, error: "Not found" };
|
|
@@ -17203,7 +17265,7 @@ app22.post("/upload", requireAdminSession, async (c) => {
|
|
|
17203
17265
|
});
|
|
17204
17266
|
await unlink2(tmpPath).catch(() => {
|
|
17205
17267
|
});
|
|
17206
|
-
const tempRemoved = !
|
|
17268
|
+
const tempRemoved = !existsSync29(tmpPath);
|
|
17207
17269
|
console.error(`[data-upload] op=cleanup uid=${uid} tempRemoved=${tempRemoved}`);
|
|
17208
17270
|
};
|
|
17209
17271
|
const reader = body.getReader();
|
|
@@ -17277,7 +17339,7 @@ async function discardChunkUpload(uploadId, state) {
|
|
|
17277
17339
|
});
|
|
17278
17340
|
await unlink2(state.tmpPath).catch(() => {
|
|
17279
17341
|
});
|
|
17280
|
-
const tempRemoved = !
|
|
17342
|
+
const tempRemoved = !existsSync29(state.tmpPath);
|
|
17281
17343
|
console.error(`[data-upload] op=cleanup uid=${uploadId} tempRemoved=${tempRemoved}`);
|
|
17282
17344
|
}
|
|
17283
17345
|
async function writeChunkBody(body, out, alreadyReceived, ceiling) {
|
|
@@ -17506,8 +17568,8 @@ app22.delete("/", requireAdminSession, async (c) => {
|
|
|
17506
17568
|
const dot = base.lastIndexOf(".");
|
|
17507
17569
|
const stem = dot === -1 ? base : base.slice(0, dot);
|
|
17508
17570
|
const containerDir = dirname11(absolute);
|
|
17509
|
-
const sidecarPath =
|
|
17510
|
-
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;
|
|
17511
17573
|
await unlink2(absolute);
|
|
17512
17574
|
if (sidecarPath) {
|
|
17513
17575
|
try {
|
|
@@ -17516,7 +17578,7 @@ app22.delete("/", requireAdminSession, async (c) => {
|
|
|
17516
17578
|
}
|
|
17517
17579
|
}
|
|
17518
17580
|
if (isAttachmentContainer) {
|
|
17519
|
-
await unlink2(
|
|
17581
|
+
await unlink2(join33(containerDir, `${stem}${EXTRACTED_TEXT_SUFFIX}`)).catch(() => {
|
|
17520
17582
|
});
|
|
17521
17583
|
await rmdir(containerDir).catch(() => {
|
|
17522
17584
|
});
|
|
@@ -18620,8 +18682,8 @@ function isHiddenByDefault(label) {
|
|
|
18620
18682
|
}
|
|
18621
18683
|
|
|
18622
18684
|
// server/lib/top-level-labels.ts
|
|
18623
|
-
import { readdirSync as
|
|
18624
|
-
import { join as
|
|
18685
|
+
import { readdirSync as readdirSync23, readFileSync as readFileSync33 } from "fs";
|
|
18686
|
+
import { join as join34, resolve as resolve24 } from "path";
|
|
18625
18687
|
var STATIC_TOP_LEVEL_LABELS = Object.freeze(
|
|
18626
18688
|
/* @__PURE__ */ new Set([
|
|
18627
18689
|
// Base-schema infra (schema-base.md has no top-level section).
|
|
@@ -18714,7 +18776,7 @@ function parseTopLevelLabels(content) {
|
|
|
18714
18776
|
}
|
|
18715
18777
|
function resolveReferencesDir() {
|
|
18716
18778
|
if (process.env.MAXY_PLATFORM_ROOT) {
|
|
18717
|
-
return
|
|
18779
|
+
return join34(process.env.MAXY_PLATFORM_ROOT, "plugins", "memory", "references");
|
|
18718
18780
|
}
|
|
18719
18781
|
return resolve24(import.meta.dirname, "../../../plugins/memory/references");
|
|
18720
18782
|
}
|
|
@@ -18722,9 +18784,9 @@ function parseTableTopLevelLabels(referencesDir) {
|
|
|
18722
18784
|
const labels = /* @__PURE__ */ new Set();
|
|
18723
18785
|
const contributingFiles = [];
|
|
18724
18786
|
try {
|
|
18725
|
-
const fileNames =
|
|
18787
|
+
const fileNames = readdirSync23(referencesDir).filter((f) => f.startsWith("schema-") && f.endsWith(".md")).sort();
|
|
18726
18788
|
for (const fileName of fileNames) {
|
|
18727
|
-
const content = readFileSync33(
|
|
18789
|
+
const content = readFileSync33(join34(referencesDir, fileName), "utf-8");
|
|
18728
18790
|
const parsed = parseTopLevelLabels(content);
|
|
18729
18791
|
if (parsed.length > 0) contributingFiles.push(fileName);
|
|
18730
18792
|
for (const label of parsed) labels.add(label);
|
|
@@ -19878,7 +19940,7 @@ var graph_default_view_default = app28;
|
|
|
19878
19940
|
// server/routes/admin/sidebar-artefacts.ts
|
|
19879
19941
|
import { readdir as readdir4, stat as stat5 } from "fs/promises";
|
|
19880
19942
|
import { resolve as resolve25, relative as relative5, isAbsolute as isAbsolute2, sep as sep7, basename as basename10 } from "path";
|
|
19881
|
-
import { existsSync as
|
|
19943
|
+
import { existsSync as existsSync30 } from "fs";
|
|
19882
19944
|
var LIMIT = 50;
|
|
19883
19945
|
var ADMIN_AGENT_FILES = ["IDENTITY.md", "SOUL.md", "KNOWLEDGE.md"];
|
|
19884
19946
|
function toDataRootRelPath(absPath) {
|
|
@@ -19985,7 +20047,7 @@ async function fetchAgentTemplateRows(accountDir) {
|
|
|
19985
20047
|
async function unionSpecialistFilenames(overrideDir, bundledDir) {
|
|
19986
20048
|
const names = /* @__PURE__ */ new Set();
|
|
19987
20049
|
for (const dir of [overrideDir, bundledDir]) {
|
|
19988
|
-
if (!
|
|
20050
|
+
if (!existsSync30(dir)) continue;
|
|
19989
20051
|
try {
|
|
19990
20052
|
const entries = await readdir4(dir);
|
|
19991
20053
|
for (const entry of entries) {
|
|
@@ -20000,7 +20062,7 @@ async function unionSpecialistFilenames(overrideDir, bundledDir) {
|
|
|
20000
20062
|
}
|
|
20001
20063
|
async function readAgentTemplateRow(inp) {
|
|
20002
20064
|
let chosenPath = null;
|
|
20003
|
-
if (
|
|
20065
|
+
if (existsSync30(inp.overridePath)) {
|
|
20004
20066
|
try {
|
|
20005
20067
|
validateFilePathInAccount(inp.overridePath, inp.overrideRoot);
|
|
20006
20068
|
chosenPath = inp.overridePath;
|
|
@@ -20011,7 +20073,7 @@ async function readAgentTemplateRow(inp) {
|
|
|
20011
20073
|
);
|
|
20012
20074
|
return null;
|
|
20013
20075
|
}
|
|
20014
|
-
} else if (
|
|
20076
|
+
} else if (existsSync30(inp.bundledPath)) {
|
|
20015
20077
|
if (!isWithin(inp.bundledPath, inp.bundledRoot)) {
|
|
20016
20078
|
console.error(
|
|
20017
20079
|
`[admin/sidebar-artefacts] agent-template-read-failed agent=${inp.displayName} kind=${inp.logName} error="bundled path outside PLATFORM_ROOT"`
|
|
@@ -20613,12 +20675,12 @@ app37.get("/", async (c) => {
|
|
|
20613
20675
|
var system_stats_default = app37;
|
|
20614
20676
|
|
|
20615
20677
|
// server/routes/admin/health.ts
|
|
20616
|
-
import { existsSync as
|
|
20617
|
-
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";
|
|
20618
20680
|
var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve26(process.cwd(), "..");
|
|
20619
20681
|
var brandHostname = "maxy";
|
|
20620
|
-
var brandJsonPath =
|
|
20621
|
-
if (
|
|
20682
|
+
var brandJsonPath = join35(PLATFORM_ROOT6, "config", "brand.json");
|
|
20683
|
+
if (existsSync31(brandJsonPath)) {
|
|
20622
20684
|
try {
|
|
20623
20685
|
const brand = JSON.parse(readFileSync34(brandJsonPath, "utf-8"));
|
|
20624
20686
|
if (brand.hostname) brandHostname = brand.hostname;
|
|
@@ -20629,7 +20691,7 @@ var VERSION_FILE = resolve26(PLATFORM_ROOT6, `config/.${brandHostname}-version`)
|
|
|
20629
20691
|
var PROCESS_STARTED_AT = (/* @__PURE__ */ new Date()).toISOString();
|
|
20630
20692
|
var PROBE_TIMEOUT_MS = 1e3;
|
|
20631
20693
|
function readVersion() {
|
|
20632
|
-
if (!
|
|
20694
|
+
if (!existsSync31(VERSION_FILE)) return "unknown";
|
|
20633
20695
|
return readFileSync34(VERSION_FILE, "utf-8").trim() || "unknown";
|
|
20634
20696
|
}
|
|
20635
20697
|
async function probeConversationDb() {
|
|
@@ -20894,7 +20956,7 @@ function buildInitialMessage(env) {
|
|
|
20894
20956
|
"Conservative-extraction rules apply (see Task 234 spec):",
|
|
20895
20957
|
"- One :KnowledgeDocument MERGE keyed on sourceUrl=" + env.pageUrl + " with the verbatim transcript as body, plus one :Section:Note child with the summary.",
|
|
20896
20958
|
"- (:KD)-[:PARTICIPANT]->(:Person) for each participant. MERGE :Person on (name, profileUrl) where present.",
|
|
20897
|
-
"- MERGE any derived entity only when assertively stated. Whatever ontology label fits: :Event {startDate, endDate} with ATTENDED_BY edges for scheduled meetings; :Task {kind, name, status} with RAISED_BY/ABOUT edges for actions without a scheduled time; :Service/:PriceSpecification when an offer or price is discussed. Each carries sourceUrl=" + env.pageUrl + ".",
|
|
20959
|
+
"- MERGE any derived entity only when assertively stated. Whatever ontology label fits: :Event {startDate, endDate} with ATTENDED_BY edges for scheduled meetings; :Task {taskId: randomUUID(), kind, name, status} with RAISED_BY/ABOUT edges for actions without a scheduled time; :Service/:PriceSpecification when an offer or price is discussed. Each carries sourceUrl=" + env.pageUrl + ".",
|
|
20898
20960
|
"- (:KD)-[:MENTIONS]->(<derived entity>) for every derived entity. Person-attached insights stay in the :Section:Note body plus a (:KD)-[:MENTIONS]->(:Person) edge \u2014 no standalone insight node.",
|
|
20899
20961
|
"- No :Communication, :ConversationArchive rows (chat transcripts route through the conversation-archive skill), or :Message nodes \u2014 those belong to other flows.",
|
|
20900
20962
|
"",
|
|
@@ -21406,8 +21468,8 @@ app45.post("/launch", requireAdminSession, async (c) => {
|
|
|
21406
21468
|
var browser_default = app45;
|
|
21407
21469
|
|
|
21408
21470
|
// server/routes/admin/calendar.ts
|
|
21409
|
-
import { existsSync as
|
|
21410
|
-
import { join as
|
|
21471
|
+
import { existsSync as existsSync32 } from "fs";
|
|
21472
|
+
import { join as join37 } from "path";
|
|
21411
21473
|
|
|
21412
21474
|
// server/lib/calendar-ics.ts
|
|
21413
21475
|
var CRLF = "\r\n";
|
|
@@ -21507,7 +21569,7 @@ function countVEvents(ics) {
|
|
|
21507
21569
|
|
|
21508
21570
|
// server/lib/calendar-availability.ts
|
|
21509
21571
|
import { readFileSync as readFileSync35 } from "fs";
|
|
21510
|
-
import { join as
|
|
21572
|
+
import { join as join36 } from "path";
|
|
21511
21573
|
var AVAILABILITY_FILENAME = "calendar-availability.json";
|
|
21512
21574
|
var REQUIRED_KEYS = [
|
|
21513
21575
|
"timezone",
|
|
@@ -21516,7 +21578,7 @@ var REQUIRED_KEYS = [
|
|
|
21516
21578
|
"weekly"
|
|
21517
21579
|
];
|
|
21518
21580
|
function readAvailabilityConfig(accountDir) {
|
|
21519
|
-
const path3 =
|
|
21581
|
+
const path3 = join36(accountDir, AVAILABILITY_FILENAME);
|
|
21520
21582
|
let raw;
|
|
21521
21583
|
try {
|
|
21522
21584
|
raw = readFileSync35(path3, "utf-8");
|
|
@@ -21878,7 +21940,7 @@ app46.get("/booking-link", requireAdminSession, (c) => {
|
|
|
21878
21940
|
console.error('[calendar] op=booking-link-fail err="no account configured"');
|
|
21879
21941
|
return c.json({ bookingDomain: null });
|
|
21880
21942
|
}
|
|
21881
|
-
if (!
|
|
21943
|
+
if (!existsSync32(join37(account.accountDir, AVAILABILITY_FILENAME))) {
|
|
21882
21944
|
console.log("[calendar] op=booking-link bookingDomain=none source=availability-config");
|
|
21883
21945
|
return c.json({ bookingDomain: null });
|
|
21884
21946
|
}
|
|
@@ -21933,7 +21995,7 @@ app47.get("/", requireAdminSession, async (c) => {
|
|
|
21933
21995
|
WHERE te.endedAt IS NULL
|
|
21934
21996
|
WITH t, te ORDER BY te.startedAt
|
|
21935
21997
|
WITH t, head(collect(te)) AS openTe
|
|
21936
|
-
RETURN t.taskId AS taskId, t.name AS name, t.clientName AS clientName,
|
|
21998
|
+
RETURN t.taskId AS taskId, elementId(t) AS rowKey, t.name AS name, t.clientName AS clientName,
|
|
21937
21999
|
t.propertyAddress AS propertyAddress, t.fee AS fee, t.status AS status,
|
|
21938
22000
|
coalesce(t.secondsLogged, 0) AS secondsLogged,
|
|
21939
22001
|
openTe.startedAt AS runningStartedAt
|
|
@@ -21942,12 +22004,17 @@ app47.get("/", requireAdminSession, async (c) => {
|
|
|
21942
22004
|
);
|
|
21943
22005
|
const open = [];
|
|
21944
22006
|
const completed = [];
|
|
22007
|
+
let missingTaskId = 0;
|
|
21945
22008
|
for (const rec of result.records) {
|
|
21946
22009
|
const status = rec.get("status") ?? "pending";
|
|
21947
22010
|
const runningStartedAt = rec.get("runningStartedAt") ?? null;
|
|
21948
22011
|
const fee = rec.get("fee");
|
|
22012
|
+
const rawTaskId = rec.get("taskId");
|
|
22013
|
+
const taskId = typeof rawTaskId === "string" && rawTaskId !== "" ? rawTaskId : null;
|
|
22014
|
+
if (taskId === null) missingTaskId++;
|
|
21949
22015
|
const row = {
|
|
21950
|
-
taskId
|
|
22016
|
+
taskId,
|
|
22017
|
+
rowKey: rec.get("rowKey"),
|
|
21951
22018
|
name: rec.get("name") ?? "",
|
|
21952
22019
|
clientName: rec.get("clientName") ?? null,
|
|
21953
22020
|
propertyAddress: rec.get("propertyAddress") ?? null,
|
|
@@ -21960,7 +22027,7 @@ app47.get("/", requireAdminSession, async (c) => {
|
|
|
21960
22027
|
if (COMPLETED.has(status)) completed.push(row);
|
|
21961
22028
|
else if (!HIDDEN_FROM_OPEN.has(status)) open.push(row);
|
|
21962
22029
|
}
|
|
21963
|
-
console.log(`${TAG37} op=list account=${accountId} open=${open.length} completed=${completed.length}`);
|
|
22030
|
+
console.log(`${TAG37} op=list account=${accountId} open=${open.length} completed=${completed.length} missingTaskId=${missingTaskId}`);
|
|
21964
22031
|
return c.json({ open, completed });
|
|
21965
22032
|
} catch (err) {
|
|
21966
22033
|
console.error(`${TAG37} op=list error="${err instanceof Error ? err.message : String(err)}"`);
|
|
@@ -21986,7 +22053,11 @@ app48.post("/", requireAdminSession, async (c) => {
|
|
|
21986
22053
|
return c.json({ error: "invalid-json" }, 400);
|
|
21987
22054
|
}
|
|
21988
22055
|
const taskId = typeof body.taskId === "string" ? body.taskId : "";
|
|
21989
|
-
if (!taskId)
|
|
22056
|
+
if (!taskId) {
|
|
22057
|
+
const reason = body.taskId === null ? "null-taskId" : "missing-taskId";
|
|
22058
|
+
console.error(`${TAG38} op=timer-start rejected reason=${reason} account=${accountId}`);
|
|
22059
|
+
return c.json({ error: "taskId required" }, 400);
|
|
22060
|
+
}
|
|
21990
22061
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
21991
22062
|
const session = getSession();
|
|
21992
22063
|
try {
|
|
@@ -22043,7 +22114,11 @@ app49.post("/", requireAdminSession, async (c) => {
|
|
|
22043
22114
|
return c.json({ error: "invalid-json" }, 400);
|
|
22044
22115
|
}
|
|
22045
22116
|
const taskId = typeof body.taskId === "string" ? body.taskId : "";
|
|
22046
|
-
if (!taskId)
|
|
22117
|
+
if (!taskId) {
|
|
22118
|
+
const reason = body.taskId === null ? "null-taskId" : "missing-taskId";
|
|
22119
|
+
console.error(`${TAG39} op=timer-stop rejected reason=${reason} account=${accountId}`);
|
|
22120
|
+
return c.json({ error: "taskId required" }, 400);
|
|
22121
|
+
}
|
|
22047
22122
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
22048
22123
|
const session = getSession();
|
|
22049
22124
|
try {
|
|
@@ -22111,7 +22186,11 @@ app50.post("/", requireAdminSession, async (c) => {
|
|
|
22111
22186
|
return c.json({ error: "invalid-json" }, 400);
|
|
22112
22187
|
}
|
|
22113
22188
|
const taskId = typeof body.taskId === "string" ? body.taskId : "";
|
|
22114
|
-
if (!taskId)
|
|
22189
|
+
if (!taskId) {
|
|
22190
|
+
const reason = body.taskId === null ? "null-taskId" : "missing-taskId";
|
|
22191
|
+
console.error(`${TAG40} op=complete rejected reason=${reason} account=${accountId}`);
|
|
22192
|
+
return c.json({ error: "taskId required" }, 400);
|
|
22193
|
+
}
|
|
22115
22194
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
22116
22195
|
const session = getSession();
|
|
22117
22196
|
try {
|
|
@@ -22154,7 +22233,8 @@ app51.post("/", requireAdminSession, async (c) => {
|
|
|
22154
22233
|
}
|
|
22155
22234
|
const taskId = typeof body.taskId === "string" ? body.taskId : "";
|
|
22156
22235
|
if (!taskId) {
|
|
22157
|
-
|
|
22236
|
+
const reason = body.taskId === null ? "null-taskId" : "missing-taskId";
|
|
22237
|
+
console.error(`${TAG41} op=time-adjust rejected reason=${reason} account=${accountId}`);
|
|
22158
22238
|
return c.json({ error: "taskId required" }, 400);
|
|
22159
22239
|
}
|
|
22160
22240
|
const newSeconds = body.newSeconds;
|
|
@@ -22217,7 +22297,7 @@ app51.post("/", requireAdminSession, async (c) => {
|
|
|
22217
22297
|
var task_time_adjust_default = app51;
|
|
22218
22298
|
|
|
22219
22299
|
// server/routes/admin/activity.ts
|
|
22220
|
-
import { readdirSync as
|
|
22300
|
+
import { readdirSync as readdirSync24 } from "fs";
|
|
22221
22301
|
var app52 = new Hono();
|
|
22222
22302
|
var TAG42 = "[activity]";
|
|
22223
22303
|
function resolveHouseAccountId(accounts) {
|
|
@@ -22233,7 +22313,7 @@ function requestToken() {
|
|
|
22233
22313
|
var short = (id) => id ? id.slice(0, 8) : "unset";
|
|
22234
22314
|
function countAccountDirsOnDisk() {
|
|
22235
22315
|
try {
|
|
22236
|
-
return
|
|
22316
|
+
return readdirSync24(ACCOUNTS_DIR, { withFileTypes: true }).filter(
|
|
22237
22317
|
(e) => e.isDirectory() && !e.name.startsWith(".")
|
|
22238
22318
|
).length;
|
|
22239
22319
|
} catch {
|
|
@@ -22288,8 +22368,10 @@ app52.get("/", requireAdminSession, async (c) => {
|
|
|
22288
22368
|
const untaggedCount = rows.filter((r) => r.accountId === null).length;
|
|
22289
22369
|
const meteringFailed = rows.filter((r) => r.meteringError !== null).length;
|
|
22290
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;
|
|
22291
22373
|
console.log(
|
|
22292
|
-
`${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}`
|
|
22293
22375
|
);
|
|
22294
22376
|
console.log(
|
|
22295
22377
|
`${TAG42} op=response req=${req} rows=${rows.length} accounts=${valid.length} untagged=${untaggedCount} meteringFailed=${meteringFailed} ms=${Date.now() - start}`
|
|
@@ -22597,7 +22679,7 @@ app56.route("/request-magic-link", request_magic_link_default);
|
|
|
22597
22679
|
var access_default = app56;
|
|
22598
22680
|
|
|
22599
22681
|
// server/routes/sites.ts
|
|
22600
|
-
import { existsSync as
|
|
22682
|
+
import { existsSync as existsSync33, readFileSync as readFileSync36, realpathSync as realpathSync7, statSync as statSync14 } from "fs";
|
|
22601
22683
|
import { resolve as resolve28 } from "path";
|
|
22602
22684
|
var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
|
|
22603
22685
|
var MIME = {
|
|
@@ -22663,7 +22745,7 @@ app57.get("/:rel{.*}", (c) => {
|
|
|
22663
22745
|
}
|
|
22664
22746
|
let stat8;
|
|
22665
22747
|
try {
|
|
22666
|
-
stat8 =
|
|
22748
|
+
stat8 = existsSync33(filePath) ? statSync14(filePath) : null;
|
|
22667
22749
|
} catch {
|
|
22668
22750
|
stat8 = null;
|
|
22669
22751
|
}
|
|
@@ -22682,7 +22764,7 @@ app57.get("/:rel{.*}", (c) => {
|
|
|
22682
22764
|
console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
|
|
22683
22765
|
return c.text("Forbidden", 403);
|
|
22684
22766
|
}
|
|
22685
|
-
if (!
|
|
22767
|
+
if (!existsSync33(filePath)) {
|
|
22686
22768
|
console.error(`[sites] not-found path=${reqPath} status=404`);
|
|
22687
22769
|
return c.text("Not found", 404);
|
|
22688
22770
|
}
|
|
@@ -22813,8 +22895,8 @@ var VISITOR_COOKIE_NAME = "mxy_v";
|
|
|
22813
22895
|
var VISITOR_COOKIE_MAX_AGE_SECONDS = Math.floor(DEFAULT_TTL_MS / 1e3);
|
|
22814
22896
|
|
|
22815
22897
|
// app/lib/brand-config.ts
|
|
22816
|
-
import { existsSync as
|
|
22817
|
-
import { join as
|
|
22898
|
+
import { existsSync as existsSync34, readFileSync as readFileSync38 } from "fs";
|
|
22899
|
+
import { join as join38 } from "path";
|
|
22818
22900
|
var cached2 = null;
|
|
22819
22901
|
var cachedAttempted = false;
|
|
22820
22902
|
function readBrandConfig() {
|
|
@@ -22822,8 +22904,8 @@ function readBrandConfig() {
|
|
|
22822
22904
|
cachedAttempted = true;
|
|
22823
22905
|
const platformRoot5 = process.env.MAXY_PLATFORM_ROOT;
|
|
22824
22906
|
if (!platformRoot5) return null;
|
|
22825
|
-
const brandPath =
|
|
22826
|
-
if (!
|
|
22907
|
+
const brandPath = join38(platformRoot5, "config", "brand.json");
|
|
22908
|
+
if (!existsSync34(brandPath)) return null;
|
|
22827
22909
|
try {
|
|
22828
22910
|
cached2 = JSON.parse(readFileSync38(brandPath, "utf-8"));
|
|
22829
22911
|
return cached2;
|
|
@@ -23314,8 +23396,8 @@ var visitor_event_default = app60;
|
|
|
23314
23396
|
|
|
23315
23397
|
// server/routes/session.ts
|
|
23316
23398
|
import { resolve as resolve29 } from "path";
|
|
23317
|
-
import { existsSync as
|
|
23318
|
-
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;
|
|
23319
23401
|
function writeBrandingCache(accountId, agentSlug, branding) {
|
|
23320
23402
|
try {
|
|
23321
23403
|
const cacheDir = resolve29(MAXY_DIR, "branding-cache", accountId);
|
|
@@ -23330,7 +23412,7 @@ function parseVisitorCookie2(cookieHeader) {
|
|
|
23330
23412
|
const match = cookieHeader.match(/(?:^|;\s*)maxy_visitor=([^;]*)/);
|
|
23331
23413
|
if (!match) return null;
|
|
23332
23414
|
const value = decodeURIComponent(match[1]).trim();
|
|
23333
|
-
return
|
|
23415
|
+
return UUID_RE5.test(value) ? value : null;
|
|
23334
23416
|
}
|
|
23335
23417
|
function parseAccessSessionId2(cookieHeader) {
|
|
23336
23418
|
if (!cookieHeader) return null;
|
|
@@ -23398,7 +23480,7 @@ app61.post("/", async (c) => {
|
|
|
23398
23480
|
let agentConfig = null;
|
|
23399
23481
|
if (account) {
|
|
23400
23482
|
const agentDir = resolve29(account.accountDir, "agents", agentSlug);
|
|
23401
|
-
if (!
|
|
23483
|
+
if (!existsSync35(agentDir) || !existsSync35(resolve29(agentDir, "config.json"))) {
|
|
23402
23484
|
return c.json({ error: "Agent not found" }, 404);
|
|
23403
23485
|
}
|
|
23404
23486
|
agentConfig = resolveAgentConfig(account.accountDir, agentSlug);
|
|
@@ -23428,7 +23510,7 @@ app61.post("/", async (c) => {
|
|
|
23428
23510
|
);
|
|
23429
23511
|
}
|
|
23430
23512
|
}
|
|
23431
|
-
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)) {
|
|
23432
23514
|
if (visitorId) {
|
|
23433
23515
|
const recent = await findRecentConversation(visitorId, accountId, agentSlug).catch(() => null);
|
|
23434
23516
|
if (recent) {
|
|
@@ -23730,8 +23812,8 @@ function startTimeEntryCensus(openSession, opts = {}) {
|
|
|
23730
23812
|
}
|
|
23731
23813
|
|
|
23732
23814
|
// app/lib/ledger-census.ts
|
|
23733
|
-
import { readdirSync as
|
|
23734
|
-
import { join as
|
|
23815
|
+
import { readdirSync as readdirSync25, readFileSync as readFileSync39, statSync as statSync15 } from "fs";
|
|
23816
|
+
import { join as join39 } from "path";
|
|
23735
23817
|
|
|
23736
23818
|
// ../lib/ledger-core/dist/reconcile.js
|
|
23737
23819
|
var LEDGER_INDEX_NAMES = [
|
|
@@ -23779,15 +23861,15 @@ var DAY_MS = 864e5;
|
|
|
23779
23861
|
function countWriteRejects24h(logDir, now) {
|
|
23780
23862
|
let entries;
|
|
23781
23863
|
try {
|
|
23782
|
-
entries =
|
|
23864
|
+
entries = readdirSync25(logDir).filter((f) => f.startsWith("mcp-ledger-") && f.endsWith(".log"));
|
|
23783
23865
|
} catch {
|
|
23784
23866
|
return 0;
|
|
23785
23867
|
}
|
|
23786
23868
|
let total = 0;
|
|
23787
23869
|
for (const name of entries) {
|
|
23788
|
-
const path3 =
|
|
23870
|
+
const path3 = join39(logDir, name);
|
|
23789
23871
|
try {
|
|
23790
|
-
if (now -
|
|
23872
|
+
if (now - statSync15(path3).mtimeMs > DAY_MS) continue;
|
|
23791
23873
|
for (const line of readFileSync39(path3, "utf8").split("\n")) {
|
|
23792
23874
|
if (line.includes("[graph-write] reject")) total += 1;
|
|
23793
23875
|
}
|
|
@@ -24275,8 +24357,8 @@ async function migrateUploads(opts = {}) {
|
|
|
24275
24357
|
|
|
24276
24358
|
// app/lib/migrate-admin-webchat-sidecars.ts
|
|
24277
24359
|
import { readdir as readdir6, readFile as readFile6, rename as rename3, writeFile as writeFile4, unlink as unlink3 } from "fs/promises";
|
|
24278
|
-
import { existsSync as
|
|
24279
|
-
import { join as
|
|
24360
|
+
import { existsSync as existsSync36 } from "fs";
|
|
24361
|
+
import { join as join40 } from "path";
|
|
24280
24362
|
var ADMIN_ROLE2 = "admin";
|
|
24281
24363
|
var WEBCHAT_CHANNEL2 = "webchat";
|
|
24282
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;
|
|
@@ -24305,7 +24387,7 @@ async function writeRaw(path3, obj) {
|
|
|
24305
24387
|
await rename3(tmp, path3);
|
|
24306
24388
|
} catch (err) {
|
|
24307
24389
|
try {
|
|
24308
|
-
if (
|
|
24390
|
+
if (existsSync36(tmp)) await unlink3(tmp);
|
|
24309
24391
|
} catch {
|
|
24310
24392
|
}
|
|
24311
24393
|
throw err;
|
|
@@ -24321,7 +24403,7 @@ async function collectLiveSidecars(projectsRoot) {
|
|
|
24321
24403
|
}
|
|
24322
24404
|
for (const slug of slugs) {
|
|
24323
24405
|
if (!slug.isDirectory()) continue;
|
|
24324
|
-
const slugDir =
|
|
24406
|
+
const slugDir = join40(projectsRoot, slug.name);
|
|
24325
24407
|
let entries;
|
|
24326
24408
|
try {
|
|
24327
24409
|
entries = await readdir6(slugDir, { withFileTypes: true });
|
|
@@ -24330,9 +24412,9 @@ async function collectLiveSidecars(projectsRoot) {
|
|
|
24330
24412
|
}
|
|
24331
24413
|
for (const entry of entries) {
|
|
24332
24414
|
if (entry.isFile() && SESSION_META_RE.test(entry.name)) {
|
|
24333
|
-
out.push(
|
|
24415
|
+
out.push(join40(slugDir, entry.name));
|
|
24334
24416
|
} else if (entry.isDirectory() && entry.name === "subagents") {
|
|
24335
|
-
const subDir =
|
|
24417
|
+
const subDir = join40(slugDir, entry.name);
|
|
24336
24418
|
let subs;
|
|
24337
24419
|
try {
|
|
24338
24420
|
subs = await readdir6(subDir, { withFileTypes: true });
|
|
@@ -24340,7 +24422,7 @@ async function collectLiveSidecars(projectsRoot) {
|
|
|
24340
24422
|
continue;
|
|
24341
24423
|
}
|
|
24342
24424
|
for (const s of subs) {
|
|
24343
|
-
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));
|
|
24344
24426
|
}
|
|
24345
24427
|
}
|
|
24346
24428
|
}
|
|
@@ -24352,7 +24434,7 @@ function shortId(path3) {
|
|
|
24352
24434
|
return base.slice(0, 8);
|
|
24353
24435
|
}
|
|
24354
24436
|
async function migrateAdminWebchatSidecars(opts = {}) {
|
|
24355
|
-
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) ?? "";
|
|
24356
24438
|
const usersFile = opts.usersFile ?? USERS_FILE;
|
|
24357
24439
|
const accountId = opts.accountId ?? resolveAccount()?.accountId ?? null;
|
|
24358
24440
|
const resolveName = opts.resolveName ?? defaultResolveName;
|
|
@@ -26715,12 +26797,12 @@ function startTelegramNativeFileFollower(input) {
|
|
|
26715
26797
|
}
|
|
26716
26798
|
|
|
26717
26799
|
// server/telegram-descriptor.ts
|
|
26718
|
-
import { resolve as resolve34, join as
|
|
26800
|
+
import { resolve as resolve34, join as join41 } from "path";
|
|
26719
26801
|
function telegramGatewayUrl() {
|
|
26720
26802
|
return `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`;
|
|
26721
26803
|
}
|
|
26722
26804
|
function telegramServerPath() {
|
|
26723
|
-
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");
|
|
26724
26806
|
}
|
|
26725
26807
|
|
|
26726
26808
|
// app/lib/channel-pty-bridge/public-session-end-review.ts
|
|
@@ -27007,7 +27089,7 @@ function broadcastAdminShutdown(reason) {
|
|
|
27007
27089
|
|
|
27008
27090
|
// ../lib/entitlement/src/index.ts
|
|
27009
27091
|
import { createPublicKey, createHash as createHash6, verify as cryptoVerify } from "crypto";
|
|
27010
|
-
import { existsSync as
|
|
27092
|
+
import { existsSync as existsSync37, readFileSync as readFileSync40, statSync as statSync16 } from "fs";
|
|
27011
27093
|
import { resolve as resolve35 } from "path";
|
|
27012
27094
|
|
|
27013
27095
|
// ../lib/entitlement/src/canonicalize.ts
|
|
@@ -27056,10 +27138,10 @@ function resolveEntitlement(brand, account) {
|
|
|
27056
27138
|
return logResolved(implicitTrust(account), null);
|
|
27057
27139
|
}
|
|
27058
27140
|
const entitlementPath = resolve35(brand.configDir, "entitlement.json");
|
|
27059
|
-
if (!
|
|
27141
|
+
if (!existsSync37(entitlementPath)) {
|
|
27060
27142
|
return logResolved(anonymousFallback("missing"), { reason: "missing" });
|
|
27061
27143
|
}
|
|
27062
|
-
const stat8 =
|
|
27144
|
+
const stat8 = statSync16(entitlementPath);
|
|
27063
27145
|
const key = memoKey(stat8.mtimeMs, account);
|
|
27064
27146
|
if (memo && memo.key === key) {
|
|
27065
27147
|
return memo.result;
|
|
@@ -27247,12 +27329,12 @@ function clientFrom(c) {
|
|
|
27247
27329
|
}
|
|
27248
27330
|
installMediaDownloadGuard();
|
|
27249
27331
|
var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT || "";
|
|
27250
|
-
var BRAND_JSON_PATH = PLATFORM_ROOT8 ?
|
|
27332
|
+
var BRAND_JSON_PATH = PLATFORM_ROOT8 ? join42(PLATFORM_ROOT8, "config", "brand.json") : "";
|
|
27251
27333
|
var BRAND = { productName: "Maxy", hostname: "maxy", configDir: ".maxy", marketingUrl: "https://getmaxy.com" };
|
|
27252
|
-
if (BRAND_JSON_PATH && !
|
|
27334
|
+
if (BRAND_JSON_PATH && !existsSync38(BRAND_JSON_PATH)) {
|
|
27253
27335
|
console.error(`[brand] WARNING: brand.json not found at ${BRAND_JSON_PATH} \u2014 using Maxy defaults`);
|
|
27254
27336
|
}
|
|
27255
|
-
if (BRAND_JSON_PATH &&
|
|
27337
|
+
if (BRAND_JSON_PATH && existsSync38(BRAND_JSON_PATH)) {
|
|
27256
27338
|
try {
|
|
27257
27339
|
const parsed = JSON.parse(readFileSync41(BRAND_JSON_PATH, "utf-8"));
|
|
27258
27340
|
BRAND = { ...BRAND, ...parsed };
|
|
@@ -27286,10 +27368,10 @@ var brandLoginOpts = {
|
|
|
27286
27368
|
appleTouchIconPath: brandAppIcon512Path,
|
|
27287
27369
|
themeColor: BRAND.defaultColors?.primary
|
|
27288
27370
|
};
|
|
27289
|
-
var ALIAS_DOMAINS_PATH =
|
|
27371
|
+
var ALIAS_DOMAINS_PATH = join42(homedir4(), BRAND.configDir, "alias-domains.json");
|
|
27290
27372
|
function loadAliasDomains() {
|
|
27291
27373
|
try {
|
|
27292
|
-
if (!
|
|
27374
|
+
if (!existsSync38(ALIAS_DOMAINS_PATH)) return null;
|
|
27293
27375
|
const parsed = JSON.parse(readFileSync41(ALIAS_DOMAINS_PATH, "utf-8"));
|
|
27294
27376
|
if (!Array.isArray(parsed)) {
|
|
27295
27377
|
console.error("[alias-domains] malformed alias-domains.json \u2014 expected array");
|
|
@@ -27354,7 +27436,7 @@ async function recordPassiveDispatch(input) {
|
|
|
27354
27436
|
var waGateway = new WaGateway({
|
|
27355
27437
|
fetchStandingRules: fetchAccountStandingRules,
|
|
27356
27438
|
gatewayUrl: `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`,
|
|
27357
|
-
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"),
|
|
27358
27440
|
// Task 751 / 1390 — file delivery on the native channel. `maxyAccountId` (the
|
|
27359
27441
|
// path-validation scope) is the sender's effective SESSION account, resolved
|
|
27360
27442
|
// once at the inbound gate and threaded here via the gateway's per-sender doc
|
|
@@ -27369,7 +27451,7 @@ var waGateway = new WaGateway({
|
|
|
27369
27451
|
caption,
|
|
27370
27452
|
accountId,
|
|
27371
27453
|
maxyAccountId,
|
|
27372
|
-
platformRoot: resolve36(process.env.MAXY_PLATFORM_ROOT ??
|
|
27454
|
+
platformRoot: resolve36(process.env.MAXY_PLATFORM_ROOT ?? join42(__dirname, ".."))
|
|
27373
27455
|
});
|
|
27374
27456
|
return result.ok ? { ok: true, messageId: result.messageId } : { ok: false, error: result.error };
|
|
27375
27457
|
},
|
|
@@ -27473,7 +27555,7 @@ function runDuplicateSenderAudit() {
|
|
|
27473
27555
|
try {
|
|
27474
27556
|
const configDir2 = process.env.CLAUDE_CONFIG_DIR;
|
|
27475
27557
|
if (!configDir2) return;
|
|
27476
|
-
const projectsRoot =
|
|
27558
|
+
const projectsRoot = join42(configDir2, "projects");
|
|
27477
27559
|
const records = [];
|
|
27478
27560
|
for (const { path: jsonlPath, isSubagent, archived } of enumerateJsonls(projectsRoot)) {
|
|
27479
27561
|
if (isSubagent || archived) continue;
|
|
@@ -28025,7 +28107,7 @@ app63.get("/agent-assets/:slug/:filename", (c) => {
|
|
|
28025
28107
|
console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
|
|
28026
28108
|
return c.text("Forbidden", 403);
|
|
28027
28109
|
}
|
|
28028
|
-
if (!
|
|
28110
|
+
if (!existsSync38(filePath)) {
|
|
28029
28111
|
console.error(`[agent-assets] serve slug=${slug} file=${filename} status=404`);
|
|
28030
28112
|
return c.text("Not found", 404);
|
|
28031
28113
|
}
|
|
@@ -28055,7 +28137,7 @@ app63.get("/generated/:filename", (c) => {
|
|
|
28055
28137
|
console.error(`[generated] serve file=${filename} status=403`);
|
|
28056
28138
|
return c.text("Forbidden", 403);
|
|
28057
28139
|
}
|
|
28058
|
-
if (!
|
|
28140
|
+
if (!existsSync38(filePath)) {
|
|
28059
28141
|
console.error(`[generated] serve file=${filename} status=404`);
|
|
28060
28142
|
return c.text("Not found", 404);
|
|
28061
28143
|
}
|
|
@@ -28075,7 +28157,7 @@ app63.route("/v", visitor_consent_default);
|
|
|
28075
28157
|
var htmlCache = /* @__PURE__ */ new Map();
|
|
28076
28158
|
var brandLogoPath = "/brand/maxy-monochrome.png";
|
|
28077
28159
|
var brandIconPath = "/brand/maxy-monochrome.png";
|
|
28078
|
-
if (BRAND_JSON_PATH &&
|
|
28160
|
+
if (BRAND_JSON_PATH && existsSync38(BRAND_JSON_PATH)) {
|
|
28079
28161
|
try {
|
|
28080
28162
|
const fullBrand = JSON.parse(readFileSync41(BRAND_JSON_PATH, "utf-8"));
|
|
28081
28163
|
if (fullBrand.assets?.logo) brandLogoPath = `/brand/${fullBrand.assets.logo}`;
|
|
@@ -28104,7 +28186,7 @@ var brandScript = `<script>window.__BRAND__=${JSON.stringify({
|
|
|
28104
28186
|
var brandThemeColor = BRAND.defaultColors?.primary ?? "#000000";
|
|
28105
28187
|
var brandBackgroundColor = BRAND.defaultColors?.background ?? "#ffffff";
|
|
28106
28188
|
var brandAppIconsExist = [brandAppIcon192Path, brandAppIcon512Path, brandMaskableIconPath].every(
|
|
28107
|
-
(p) =>
|
|
28189
|
+
(p) => existsSync38(resolve36(process.cwd(), "public", p.replace(/^\//, "")))
|
|
28108
28190
|
);
|
|
28109
28191
|
var SW_SOURCE = (() => {
|
|
28110
28192
|
try {
|
|
@@ -28116,8 +28198,8 @@ var SW_SOURCE = (() => {
|
|
|
28116
28198
|
function readInstalledVersion() {
|
|
28117
28199
|
try {
|
|
28118
28200
|
if (!PLATFORM_ROOT8) return "unknown";
|
|
28119
|
-
const versionFile =
|
|
28120
|
-
if (!
|
|
28201
|
+
const versionFile = join42(PLATFORM_ROOT8, "config", `.${BRAND.hostname}-version`);
|
|
28202
|
+
if (!existsSync38(versionFile)) return "unknown";
|
|
28121
28203
|
const content = readFileSync41(versionFile, "utf-8").trim();
|
|
28122
28204
|
return content || "unknown";
|
|
28123
28205
|
} catch {
|
|
@@ -28176,12 +28258,12 @@ ${clientErrorReporterScript}
|
|
|
28176
28258
|
return html;
|
|
28177
28259
|
}
|
|
28178
28260
|
function loadBrandingCache(agentSlug) {
|
|
28179
|
-
const configDir2 =
|
|
28261
|
+
const configDir2 = join42(homedir4(), BRAND.configDir);
|
|
28180
28262
|
try {
|
|
28181
28263
|
const accountId = getDefaultAccountId();
|
|
28182
28264
|
if (!accountId) return null;
|
|
28183
|
-
const cachePath =
|
|
28184
|
-
if (!
|
|
28265
|
+
const cachePath = join42(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
|
|
28266
|
+
if (!existsSync38(cachePath)) return null;
|
|
28185
28267
|
return JSON.parse(readFileSync41(cachePath, "utf-8"));
|
|
28186
28268
|
} catch {
|
|
28187
28269
|
return null;
|
|
@@ -28414,11 +28496,11 @@ var hostname = process.env.HOSTNAME ?? "127.0.0.1";
|
|
|
28414
28496
|
var httpServer = serve({ fetch: app63.fetch, port, hostname });
|
|
28415
28497
|
console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
28416
28498
|
{
|
|
28417
|
-
const reconcilePlatformRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
28499
|
+
const reconcilePlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join42(__dirname, "..");
|
|
28418
28500
|
const reconcileScript = resolve36(reconcilePlatformRoot, "plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js");
|
|
28419
28501
|
const RECONCILE_INTERVAL_MS = 12e4;
|
|
28420
28502
|
const runReconcile = () => {
|
|
28421
|
-
if (!
|
|
28503
|
+
if (!existsSync38(reconcileScript)) return;
|
|
28422
28504
|
try {
|
|
28423
28505
|
const child = spawn3(process.execPath, [reconcileScript], {
|
|
28424
28506
|
env: { ...process.env, PLATFORM_ROOT: reconcilePlatformRoot },
|
|
@@ -28436,11 +28518,11 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
28436
28518
|
loop.unref();
|
|
28437
28519
|
}
|
|
28438
28520
|
{
|
|
28439
|
-
const outlookPlatformRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
28521
|
+
const outlookPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join42(__dirname, "..");
|
|
28440
28522
|
const outlookScript = resolve36(outlookPlatformRoot, "plugins/outlook/mcp/dist/scripts/complete-registration.js");
|
|
28441
28523
|
const OUTLOOK_COMPLETE_INTERVAL_MS = 3e4;
|
|
28442
28524
|
const runOutlookComplete = () => {
|
|
28443
|
-
if (!
|
|
28525
|
+
if (!existsSync38(outlookScript)) return;
|
|
28444
28526
|
try {
|
|
28445
28527
|
const child = spawn3(process.execPath, [outlookScript], {
|
|
28446
28528
|
env: { ...process.env, PLATFORM_ROOT: outlookPlatformRoot },
|
|
@@ -28458,20 +28540,20 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
28458
28540
|
outlookLoop.unref();
|
|
28459
28541
|
}
|
|
28460
28542
|
{
|
|
28461
|
-
const auditRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
28543
|
+
const auditRoot = process.env.MAXY_PLATFORM_ROOT ?? join42(__dirname, "..");
|
|
28462
28544
|
const strandedAccountsDir = resolve36(auditRoot, "..", "data/accounts");
|
|
28463
28545
|
const STRANDED_AUDIT_INTERVAL_MS = 3e5;
|
|
28464
28546
|
const STRANDED_AGE_MS = 16 * 6e4;
|
|
28465
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;
|
|
28466
28548
|
const runStrandedAudit = () => {
|
|
28467
28549
|
try {
|
|
28468
|
-
if (!
|
|
28550
|
+
if (!existsSync38(strandedAccountsDir)) return;
|
|
28469
28551
|
const now = Date.now();
|
|
28470
|
-
for (const name of
|
|
28552
|
+
for (const name of readdirSync26(strandedAccountsDir)) {
|
|
28471
28553
|
if (!STRANDED_UUID_RE.test(name)) continue;
|
|
28472
28554
|
const pendingPath2 = resolve36(strandedAccountsDir, name, "secrets/outlook/pending-devicecode.enc");
|
|
28473
|
-
if (!
|
|
28474
|
-
const ageMs = now -
|
|
28555
|
+
if (!existsSync38(pendingPath2)) continue;
|
|
28556
|
+
const ageMs = now - statSync17(pendingPath2).mtimeMs;
|
|
28475
28557
|
if (ageMs > STRANDED_AGE_MS) {
|
|
28476
28558
|
console.error(`[outlook-mcp] devicecode-stranded account=${name} ageSec=${Math.floor(ageMs / 1e3)}`);
|
|
28477
28559
|
}
|
|
@@ -28486,7 +28568,45 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
28486
28568
|
strandedLoop.unref();
|
|
28487
28569
|
}
|
|
28488
28570
|
{
|
|
28489
|
-
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, "..");
|
|
28490
28610
|
const STORAGE_AUDIT_INTERVAL_MS = 3e5;
|
|
28491
28611
|
const runStorageAuditSafe = () => {
|
|
28492
28612
|
runStorageAudit(auditPlatformRoot).catch(
|
|
@@ -28508,7 +28628,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
28508
28628
|
pagesAuditLoop.unref();
|
|
28509
28629
|
}
|
|
28510
28630
|
{
|
|
28511
|
-
const publishPlatformRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
28631
|
+
const publishPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join42(__dirname, "..");
|
|
28512
28632
|
const publishScript = resolve36(publishPlatformRoot, "plugins/scheduling/mcp/dist/scripts/publish-availability.js");
|
|
28513
28633
|
const PUBLISH_INTERVAL_MS = 3e5;
|
|
28514
28634
|
const currentAccount = () => {
|
|
@@ -28520,7 +28640,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
28520
28640
|
}
|
|
28521
28641
|
};
|
|
28522
28642
|
const spawnPublish = (account) => {
|
|
28523
|
-
if (!
|
|
28643
|
+
if (!existsSync38(publishScript)) return;
|
|
28524
28644
|
try {
|
|
28525
28645
|
const child = spawn3(process.execPath, [publishScript], {
|
|
28526
28646
|
env: {
|
|
@@ -28541,7 +28661,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
28541
28661
|
const availPath = resolve36(account.accountDir, "calendar-availability.json");
|
|
28542
28662
|
let hasBookingSite = false;
|
|
28543
28663
|
try {
|
|
28544
|
-
if (
|
|
28664
|
+
if (existsSync38(availPath)) {
|
|
28545
28665
|
const cfg = JSON.parse(readFileSync41(availPath, "utf-8"));
|
|
28546
28666
|
hasBookingSite = typeof cfg.bookingDbName === "string" && cfg.bookingDbName.length > 0;
|
|
28547
28667
|
}
|
|
@@ -28550,7 +28670,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
28550
28670
|
if (!hasBookingSite) return;
|
|
28551
28671
|
const statePath = resolve36(account.accountDir, "state", "booking-availability", "last-publish.json");
|
|
28552
28672
|
let lastSuccessAt = null;
|
|
28553
|
-
if (
|
|
28673
|
+
if (existsSync38(statePath)) {
|
|
28554
28674
|
try {
|
|
28555
28675
|
const rec = JSON.parse(readFileSync41(statePath, "utf-8"));
|
|
28556
28676
|
lastSuccessAt = rec.lastSuccessAt ?? null;
|
|
@@ -28577,12 +28697,12 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
28577
28697
|
startTimeEntryCensus(() => getSession());
|
|
28578
28698
|
startLedgerCensus(() => getSession());
|
|
28579
28699
|
{
|
|
28580
|
-
const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
28700
|
+
const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join42(__dirname, "..");
|
|
28581
28701
|
const auditScript = resolve36(auditPlatformRoot, "plugins/connector/mcp/dist/scripts/audit-connectors.js");
|
|
28582
28702
|
const auditLogDir = process.env.LOG_DIR ?? LOG_DIR;
|
|
28583
28703
|
const CONNECTOR_AUDIT_INTERVAL_MS = 3e5;
|
|
28584
28704
|
const runConnectorAudit = () => {
|
|
28585
|
-
if (!
|
|
28705
|
+
if (!existsSync38(auditScript)) return;
|
|
28586
28706
|
try {
|
|
28587
28707
|
const child = spawn3(process.execPath, [auditScript], {
|
|
28588
28708
|
env: { ...process.env, PLATFORM_ROOT: auditPlatformRoot, LOG_DIR: auditLogDir },
|
|
@@ -28693,7 +28813,7 @@ try {
|
|
|
28693
28813
|
var ADMINUSER_RECONCILE_INTERVAL_MS = 60 * 60 * 1e3;
|
|
28694
28814
|
async function runAdminUserReconcileTick() {
|
|
28695
28815
|
try {
|
|
28696
|
-
if (!
|
|
28816
|
+
if (!existsSync38(USERS_FILE)) {
|
|
28697
28817
|
console.error("[adminuser-self-heal] skip reason=no-users-file");
|
|
28698
28818
|
return;
|
|
28699
28819
|
}
|
|
@@ -28738,7 +28858,7 @@ var ingestAuditTimer = setInterval(runIngestAuditTick, INGEST_AUDIT_INTERVAL_MS)
|
|
|
28738
28858
|
if (typeof ingestAuditTimer.unref === "function") ingestAuditTimer.unref();
|
|
28739
28859
|
var USERS_RECONCILE_INTERVAL_MS = 60 * 60 * 1e3;
|
|
28740
28860
|
function countUsersRows() {
|
|
28741
|
-
if (!
|
|
28861
|
+
if (!existsSync38(USERS_FILE)) return 0;
|
|
28742
28862
|
const raw = readFileSync41(USERS_FILE, "utf-8").trim();
|
|
28743
28863
|
if (!raw) return 0;
|
|
28744
28864
|
const users = JSON.parse(raw);
|
|
@@ -28859,7 +28979,7 @@ if (bootAccountConfig?.whatsapp) {
|
|
|
28859
28979
|
}
|
|
28860
28980
|
init({
|
|
28861
28981
|
configDir: configDirForWhatsApp,
|
|
28862
|
-
platformRoot: resolve36(process.env.MAXY_PLATFORM_ROOT ??
|
|
28982
|
+
platformRoot: resolve36(process.env.MAXY_PLATFORM_ROOT ?? join42(__dirname, "..")),
|
|
28863
28983
|
accountConfig: bootAccountConfig,
|
|
28864
28984
|
onMessage: async (msg) => {
|
|
28865
28985
|
if (msg.isOwnerMirror) {
|