@rubytech/create-maxy-code 0.1.474 → 0.1.476
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/payload/platform/lib/storage-broker/dist/cf-exec.d.ts.map +1 -1
- package/payload/platform/lib/storage-broker/dist/cf-exec.js +3 -2
- package/payload/platform/lib/storage-broker/dist/cf-exec.js.map +1 -1
- package/payload/platform/lib/storage-broker/src/cf-exec.ts +3 -2
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +18 -9
- package/payload/platform/plugins/cloudflare/skills/calendar-site/template/schema.sql +13 -3
- package/payload/platform/plugins/docs/references/calendar-booking.md +2 -2
- package/payload/platform/plugins/docs/references/google-guide.md +15 -6
- package/payload/platform/plugins/google/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/google/PLUGIN.md +60 -12
- package/payload/platform/plugins/google/mcp/dist/__tests__/account-audit.test.d.ts +2 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/account-audit.test.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/account-audit.test.js +229 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/account-audit.test.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/account-register.test.js +9 -9
- package/payload/platform/plugins/google/mcp/dist/__tests__/account-register.test.js.map +1 -1
- package/payload/platform/plugins/google/mcp/dist/__tests__/consent-url-redirect.test.d.ts +2 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/consent-url-redirect.test.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/consent-url-redirect.test.js +17 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/consent-url-redirect.test.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/loopback-listener.test.d.ts +2 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/loopback-listener.test.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/loopback-listener.test.js +146 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/loopback-listener.test.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/pending-redirect.test.d.ts +2 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/pending-redirect.test.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/pending-redirect.test.js +19 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/pending-redirect.test.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/register-redirect-chain.test.d.ts +2 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/register-redirect-chain.test.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/register-redirect-chain.test.js +41 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/register-redirect-chain.test.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/auth/account-audit.d.ts +44 -0
- package/payload/platform/plugins/google/mcp/dist/auth/account-audit.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/auth/account-audit.js +112 -0
- package/payload/platform/plugins/google/mcp/dist/auth/account-audit.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/auth/loopback-listener.d.ts +17 -0
- package/payload/platform/plugins/google/mcp/dist/auth/loopback-listener.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/auth/loopback-listener.js +143 -0
- package/payload/platform/plugins/google/mcp/dist/auth/loopback-listener.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/auth/pending-store.d.ts +9 -0
- package/payload/platform/plugins/google/mcp/dist/auth/pending-store.d.ts.map +1 -1
- package/payload/platform/plugins/google/mcp/dist/auth/pending-store.js.map +1 -1
- package/payload/platform/plugins/google/mcp/dist/index.js +73 -5
- package/payload/platform/plugins/google/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/google/mcp/dist/scripts/account-audit.d.ts +2 -0
- package/payload/platform/plugins/google/mcp/dist/scripts/account-audit.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/scripts/account-audit.js +37 -0
- package/payload/platform/plugins/google/mcp/dist/scripts/account-audit.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/tools/account-register.d.ts +20 -4
- package/payload/platform/plugins/google/mcp/dist/tools/account-register.d.ts.map +1 -1
- package/payload/platform/plugins/google/mcp/dist/tools/account-register.js +19 -9
- package/payload/platform/plugins/google/mcp/dist/tools/account-register.js.map +1 -1
- package/payload/platform/plugins/google/references/auth.md +93 -14
- package/payload/platform/plugins/scheduling/PLUGIN.md +2 -2
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/booking-reconcile.test.js +158 -23
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/booking-reconcile.test.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/booking-schema-migration.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/booking-schema-migration.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/booking-schema-migration.test.js +200 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/booking-schema-migration.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/connector-sync-provision.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/connector-sync-provision.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/connector-sync-provision.test.js +309 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/connector-sync-provision.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/d1-command.test.js +219 -19
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/d1-command.test.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/booking-reconcile.d.ts +94 -11
- package/payload/platform/plugins/scheduling/mcp/dist/lib/booking-reconcile.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/booking-reconcile.js +106 -22
- package/payload/platform/plugins/scheduling/mcp/dist/lib/booking-reconcile.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/connector-sync-provision.d.ts +109 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/connector-sync-provision.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/connector-sync-provision.js +213 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/connector-sync-provision.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/d1-command.d.ts +80 -8
- package/payload/platform/plugins/scheduling/mcp/dist/lib/d1-command.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/d1-command.js +202 -8
- package/payload/platform/plugins/scheduling/mcp/dist/lib/d1-command.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/reconcile-bookings.d.ts +6 -4
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/reconcile-bookings.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js +334 -142
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js.map +1 -1
- 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/{chunk-Y6V45R6M.js → chunk-LBCMFD4O.js} +173 -29
- package/payload/server/maxy-edge.js +1 -1
- package/payload/server/public/activity.html +6 -6
- package/payload/server/public/assets/{AdminLoginScreens-B44KbEuC.js → AdminLoginScreens-DximwPlS.js} +1 -1
- package/payload/server/public/assets/{AdminShell-BjxV2qkb.js → AdminShell-BehbH-Oa.js} +1 -1
- package/payload/server/public/assets/{Checkbox-DSeZNGNA.js → Checkbox-DM-eHqOS.js} +1 -1
- package/payload/server/public/assets/activity-hDwUeQd6.js +1 -0
- package/payload/server/public/assets/{admin-B4LpTCur.js → admin-CAkDnGdk.js} +1 -1
- package/payload/server/public/assets/{browser-CEFvaWwI.js → browser-DXl8hOoi.js} +1 -1
- package/payload/server/public/assets/{calendar-B3zo6V34.js → calendar-DP6hn4-6.js} +1 -1
- package/payload/server/public/assets/chat-DhOfVGYM.js +1 -0
- package/payload/server/public/assets/chevron-left-DYNBoLii.js +1 -0
- package/payload/server/public/assets/data-bq8fTo_s.js +1 -0
- package/payload/server/public/assets/{graph-RaOrnSf2.js → graph-CHcYoEJ5.js} +1 -1
- package/payload/server/public/assets/{graph-labels-GlTEIYJj.js → graph-labels-CZykslZM.js} +1 -1
- package/payload/server/public/assets/{maximize-2-CHDa8p5h.js → maximize-2-31AZEcMS.js} +1 -1
- package/payload/server/public/assets/{operator-DtqHY4jV.js → operator-BGGpdsO_.js} +1 -1
- package/payload/server/public/assets/{page-CkhFj8GQ.js → page-BloC6ygA.js} +1 -1
- package/payload/server/public/assets/{page-DxnWgPtd.js → page-DOeiiqbR.js} +1 -1
- package/payload/server/public/assets/{public-D5TUfQ3I.js → public-CGgO6IZv.js} +1 -1
- package/payload/server/public/assets/{rotate-ccw-BJjVAQQY.js → rotate-ccw-BlAi6iFg.js} +1 -1
- package/payload/server/public/assets/{tasks-CM9pYYG1.js → tasks-C1giFRRL.js} +1 -1
- package/payload/server/public/assets/{time-entry-format-C5RYEYjM.js → time-entry-format-CiUUQdq7.js} +1 -1
- package/payload/server/public/assets/{triangle-alert-DLfIsuo_.js → triangle-alert-CVqKuLoa.js} +1 -1
- package/payload/server/public/assets/{useCopyFeedback-7yKeiAzV.js → useCopyFeedback-ksyUe_g1.js} +1 -1
- package/payload/server/public/assets/{useSelectionMode-CWlh6AEq.js → useSelectionMode-BPrBkdTd.js} +1 -1
- package/payload/server/public/assets/{useSubAccountSwitcher-B2n9QPVI.css → useSubAccountSwitcher-K4kYeN6i.css} +1 -1
- package/payload/server/public/assets/{useVoiceRecorder-j3ZArZ2H.js → useVoiceRecorder-CTXP8oTW.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 +547 -423
- package/payload/server/public/assets/activity-CdipMTDp.js +0 -1
- package/payload/server/public/assets/chat-5tJdo9i_.js +0 -1
- package/payload/server/public/assets/chevron-left-BJllrPBj.js +0 -1
- package/payload/server/public/assets/data-Du79EgR-.js +0 -1
- /package/payload/server/public/assets/{useSubAccountSwitcher-CBlKgwms.js → useSubAccountSwitcher-DzgzTRRn.js} +0 -0
package/payload/server/server.js
CHANGED
|
@@ -28,6 +28,7 @@ import {
|
|
|
28
28
|
VNC_DISPLAY,
|
|
29
29
|
WEBSOCKIFY_PORT,
|
|
30
30
|
accessPasswordCollides,
|
|
31
|
+
armedCount,
|
|
31
32
|
autoDeliverPremiumPlugins,
|
|
32
33
|
canAccessAdmin,
|
|
33
34
|
checkRateLimit,
|
|
@@ -71,6 +72,7 @@ import {
|
|
|
71
72
|
isValidAccountId,
|
|
72
73
|
linkConversationTranscript,
|
|
73
74
|
listAdminSessions,
|
|
75
|
+
listLoops,
|
|
74
76
|
listValidAccounts,
|
|
75
77
|
loadAdminUserName,
|
|
76
78
|
loadPersonNameByElementId,
|
|
@@ -81,6 +83,7 @@ import {
|
|
|
81
83
|
projectAgent,
|
|
82
84
|
reconcileEnabledPluginsForAccounts,
|
|
83
85
|
recordFailedAttempt,
|
|
86
|
+
registerLoop,
|
|
84
87
|
registerSession,
|
|
85
88
|
renameConversation,
|
|
86
89
|
renderLoginPage,
|
|
@@ -112,7 +115,7 @@ import {
|
|
|
112
115
|
vncLog,
|
|
113
116
|
walkPremiumBundles,
|
|
114
117
|
writeAdminUserAndPerson
|
|
115
|
-
} from "./chunk-
|
|
118
|
+
} from "./chunk-LBCMFD4O.js";
|
|
116
119
|
import {
|
|
117
120
|
D1_MAX_SQL_STATEMENT_BYTES,
|
|
118
121
|
D1_QUERY_MAX_BODY_BYTES,
|
|
@@ -1534,10 +1537,10 @@ var serveStatic = (options = { root: "" }) => {
|
|
|
1534
1537
|
};
|
|
1535
1538
|
|
|
1536
1539
|
// server/index.ts
|
|
1537
|
-
import { readFileSync as readFileSync41, existsSync as
|
|
1540
|
+
import { readFileSync as readFileSync41, existsSync as existsSync38, watchFile, readdirSync as readdirSync26, statSync as statSync17 } from "fs";
|
|
1538
1541
|
import { spawn as spawn3 } from "child_process";
|
|
1539
1542
|
import { createHash as createHash7 } from "crypto";
|
|
1540
|
-
import { resolve as resolve36, join as
|
|
1543
|
+
import { resolve as resolve36, join as join42, basename as basename12 } from "path";
|
|
1541
1544
|
import { homedir as homedir4 } from "os";
|
|
1542
1545
|
import { monitorEventLoopDelay } from "perf_hooks";
|
|
1543
1546
|
|
|
@@ -2391,12 +2394,12 @@ function startAuthHealthHeartbeat(intervalMs = 5 * 60 * 1e3) {
|
|
|
2391
2394
|
ticking = false;
|
|
2392
2395
|
}
|
|
2393
2396
|
};
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2397
|
+
return registerLoop({
|
|
2398
|
+
name: "auth-health",
|
|
2399
|
+
intervalMs,
|
|
2400
|
+
firstRunDelayMs: 0,
|
|
2401
|
+
run: tick
|
|
2402
|
+
});
|
|
2400
2403
|
}
|
|
2401
2404
|
async function ensureAuth() {
|
|
2402
2405
|
const health = assessAuthHealth();
|
|
@@ -2809,12 +2812,12 @@ function createBaileysLogger(bindings = {}, authDir) {
|
|
|
2809
2812
|
var credsSaveQueue = Promise.resolve();
|
|
2810
2813
|
async function drainCredsSaveQueue(timeoutMs = 5e3) {
|
|
2811
2814
|
console.error(`${TAG6} draining credential save queue\u2026`);
|
|
2812
|
-
const
|
|
2815
|
+
const timer = new Promise(
|
|
2813
2816
|
(resolve37) => setTimeout(() => resolve37("timeout"), timeoutMs)
|
|
2814
2817
|
);
|
|
2815
2818
|
const result = await Promise.race([
|
|
2816
2819
|
credsSaveQueue.then(() => "drained"),
|
|
2817
|
-
|
|
2820
|
+
timer
|
|
2818
2821
|
]);
|
|
2819
2822
|
if (result === "timeout") {
|
|
2820
2823
|
console.error(`${TAG6} credential save queue drain timed out after ${timeoutMs}ms`);
|
|
@@ -3100,19 +3103,19 @@ function isTimeoutError(err) {
|
|
|
3100
3103
|
}
|
|
3101
3104
|
function withTimeout(label, promise, timeoutMs) {
|
|
3102
3105
|
return new Promise((resolve37, reject) => {
|
|
3103
|
-
const
|
|
3106
|
+
const timer = setTimeout(() => {
|
|
3104
3107
|
const err = new Error(`${label} timed out after ${timeoutMs}ms`);
|
|
3105
3108
|
err.__maxyTimeout = true;
|
|
3106
3109
|
reject(err);
|
|
3107
3110
|
}, timeoutMs);
|
|
3108
|
-
|
|
3111
|
+
timer.unref?.();
|
|
3109
3112
|
promise.then(
|
|
3110
3113
|
(value) => {
|
|
3111
|
-
clearTimeout(
|
|
3114
|
+
clearTimeout(timer);
|
|
3112
3115
|
resolve37(value);
|
|
3113
3116
|
},
|
|
3114
3117
|
(err) => {
|
|
3115
|
-
clearTimeout(
|
|
3118
|
+
clearTimeout(timer);
|
|
3116
3119
|
reject(err);
|
|
3117
3120
|
}
|
|
3118
3121
|
);
|
|
@@ -5197,10 +5200,10 @@ function createInboundDebouncer(opts) {
|
|
|
5197
5200
|
flushKey(key).catch(onError);
|
|
5198
5201
|
}, debounceMs);
|
|
5199
5202
|
} else {
|
|
5200
|
-
const
|
|
5203
|
+
const timer = setTimeout(() => {
|
|
5201
5204
|
flushKey(key).catch(onError);
|
|
5202
5205
|
}, debounceMs);
|
|
5203
|
-
pending.set(key, { entries: [msg], timer
|
|
5206
|
+
pending.set(key, { entries: [msg], timer });
|
|
5204
5207
|
}
|
|
5205
5208
|
}
|
|
5206
5209
|
function registerPending(key, promise) {
|
|
@@ -5855,9 +5858,9 @@ async function connectWithReconnect(conn) {
|
|
|
5855
5858
|
`${TAG17} reconnecting account=${conn.accountId} in ${delay}ms (attempt ${decision.nextAttempts}/${maxAttempts})`
|
|
5856
5859
|
);
|
|
5857
5860
|
await new Promise((resolve37) => {
|
|
5858
|
-
const
|
|
5861
|
+
const timer = setTimeout(resolve37, delay);
|
|
5859
5862
|
conn.abortController.signal.addEventListener("abort", () => {
|
|
5860
|
-
clearTimeout(
|
|
5863
|
+
clearTimeout(timer);
|
|
5861
5864
|
resolve37();
|
|
5862
5865
|
}, { once: true });
|
|
5863
5866
|
});
|
|
@@ -9687,46 +9690,74 @@ async function runPagesAudit(root) {
|
|
|
9687
9690
|
}
|
|
9688
9691
|
}
|
|
9689
9692
|
|
|
9693
|
+
// server/google-pending-audit.ts
|
|
9694
|
+
import { existsSync as existsSync10, readdirSync as readdirSync9, statSync as statSync4 } from "fs";
|
|
9695
|
+
import { join as join14 } from "path";
|
|
9696
|
+
var GOOGLE_PENDING_LIFETIME_SEC = 600;
|
|
9697
|
+
var UUID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
9698
|
+
function runGooglePendingAudit(accountsDir, nowMs, emit, readMtimeMs = (path3) => statSync4(path3).mtimeMs) {
|
|
9699
|
+
let scanned = 0;
|
|
9700
|
+
let stranded = 0;
|
|
9701
|
+
if (existsSync10(accountsDir)) {
|
|
9702
|
+
for (const accountId of readdirSync9(accountsDir)) {
|
|
9703
|
+
if (!UUID_RE2.test(accountId)) continue;
|
|
9704
|
+
const pendingPath2 = join14(accountsDir, accountId, "secrets", "google", "pending-oauth.enc");
|
|
9705
|
+
try {
|
|
9706
|
+
if (!existsSync10(pendingPath2)) continue;
|
|
9707
|
+
const ageSec = Math.max(0, Math.floor((nowMs - readMtimeMs(pendingPath2)) / 1e3));
|
|
9708
|
+
scanned += 1;
|
|
9709
|
+
if (ageSec >= GOOGLE_PENDING_LIFETIME_SEC) {
|
|
9710
|
+
stranded += 1;
|
|
9711
|
+
emit(`[google-oauth] op=pending-stranded account=${accountId} ageSec=${ageSec}`);
|
|
9712
|
+
}
|
|
9713
|
+
} catch {
|
|
9714
|
+
}
|
|
9715
|
+
}
|
|
9716
|
+
}
|
|
9717
|
+
emit(`[google-oauth] op=pending-audit scanned=${scanned} stranded=${stranded}`);
|
|
9718
|
+
return { scanned, stranded };
|
|
9719
|
+
}
|
|
9720
|
+
|
|
9690
9721
|
// server/routes/whatsapp-reader.ts
|
|
9691
|
-
import { readFileSync as readFileSync19, watch, statSync as
|
|
9692
|
-
import { basename as basename4, dirname as dirname5, isAbsolute, join as
|
|
9722
|
+
import { readFileSync as readFileSync19, watch, statSync as statSync7, openSync, readSync, closeSync, existsSync as existsSync13, readdirSync as readdirSync14, realpathSync as realpathSync5 } from "fs";
|
|
9723
|
+
import { basename as basename4, dirname as dirname5, isAbsolute, join as join19, relative as relative2, resolve as resolve13, sep as sep3 } from "path";
|
|
9693
9724
|
|
|
9694
9725
|
// server/routes/admin/sidebar-sessions.ts
|
|
9695
|
-
import { readdirSync as
|
|
9696
|
-
import { dirname as dirname4, join as
|
|
9726
|
+
import { readdirSync as readdirSync12, readFileSync as readFileSync17, statSync as statSync6 } from "fs";
|
|
9727
|
+
import { dirname as dirname4, join as join17, resolve as resolve12 } from "path";
|
|
9697
9728
|
|
|
9698
9729
|
// ../services/claude-session-manager/src/jsonl-path.ts
|
|
9699
|
-
import { existsSync as
|
|
9730
|
+
import { existsSync as existsSync11, readdirSync as readdirSync10 } from "fs";
|
|
9700
9731
|
import { homedir } from "os";
|
|
9701
|
-
import { join as
|
|
9732
|
+
import { join as join15 } from "path";
|
|
9702
9733
|
function findExistingJsonlForSessionId(claudeConfigDir2, sessionId) {
|
|
9703
|
-
const projectsRoot =
|
|
9704
|
-
if (!
|
|
9734
|
+
const projectsRoot = join15(claudeConfigDir2, "projects");
|
|
9735
|
+
if (!existsSync11(projectsRoot)) return null;
|
|
9705
9736
|
let slugs;
|
|
9706
9737
|
try {
|
|
9707
|
-
slugs =
|
|
9738
|
+
slugs = readdirSync10(projectsRoot, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
9708
9739
|
} catch {
|
|
9709
9740
|
return null;
|
|
9710
9741
|
}
|
|
9711
9742
|
const basename13 = `${sessionId}.jsonl`;
|
|
9712
9743
|
for (const slug of slugs) {
|
|
9713
|
-
const live =
|
|
9714
|
-
if (
|
|
9715
|
-
const archived =
|
|
9716
|
-
if (
|
|
9744
|
+
const live = join15(projectsRoot, slug, basename13);
|
|
9745
|
+
if (existsSync11(live)) return live;
|
|
9746
|
+
const archived = join15(projectsRoot, slug, "archive", basename13);
|
|
9747
|
+
if (existsSync11(archived)) return archived;
|
|
9717
9748
|
}
|
|
9718
9749
|
return null;
|
|
9719
9750
|
}
|
|
9720
9751
|
|
|
9721
9752
|
// app/lib/admin-identity/pin-validator.ts
|
|
9722
9753
|
import { createHash as createHash3 } from "crypto";
|
|
9723
|
-
import { existsSync as
|
|
9724
|
-
import { join as
|
|
9754
|
+
import { existsSync as existsSync12, readFileSync as readFileSync16, readdirSync as readdirSync11, statSync as statSync5 } from "fs";
|
|
9755
|
+
import { join as join16 } from "path";
|
|
9725
9756
|
function hashPin(pin) {
|
|
9726
9757
|
return createHash3("sha256").update(pin).digest("hex");
|
|
9727
9758
|
}
|
|
9728
9759
|
function readUsersFile(usersFilePath) {
|
|
9729
|
-
if (!
|
|
9760
|
+
if (!existsSync12(usersFilePath)) return null;
|
|
9730
9761
|
const raw = readFileSync16(usersFilePath, "utf-8").trim();
|
|
9731
9762
|
if (!raw) return [];
|
|
9732
9763
|
return JSON.parse(raw);
|
|
@@ -9846,16 +9877,16 @@ function enumerateJsonls(projectsRoot) {
|
|
|
9846
9877
|
const out = [];
|
|
9847
9878
|
let slugs;
|
|
9848
9879
|
try {
|
|
9849
|
-
slugs =
|
|
9880
|
+
slugs = readdirSync12(projectsRoot, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
9850
9881
|
} catch (err) {
|
|
9851
9882
|
if (err.code === "ENOENT") return out;
|
|
9852
9883
|
throw err;
|
|
9853
9884
|
}
|
|
9854
9885
|
for (const slug of slugs) {
|
|
9855
|
-
const slugDir =
|
|
9886
|
+
const slugDir = join17(projectsRoot, slug);
|
|
9856
9887
|
let entries;
|
|
9857
9888
|
try {
|
|
9858
|
-
entries =
|
|
9889
|
+
entries = readdirSync12(slugDir, { withFileTypes: true });
|
|
9859
9890
|
} catch (err) {
|
|
9860
9891
|
const code = err.code ?? "unknown";
|
|
9861
9892
|
console.error(`[admin-sessions-list] slug-skipped slug=${slug} code=${code}`);
|
|
@@ -9863,12 +9894,12 @@ function enumerateJsonls(projectsRoot) {
|
|
|
9863
9894
|
}
|
|
9864
9895
|
for (const entry of entries) {
|
|
9865
9896
|
if (entry.isFile() && SESSION_ID_RE.test(entry.name)) {
|
|
9866
|
-
out.push({ path:
|
|
9897
|
+
out.push({ path: join17(slugDir, entry.name), isSubagent: false, archived: false });
|
|
9867
9898
|
} else if (entry.isDirectory() && entry.name === "subagents") {
|
|
9868
|
-
const subDir =
|
|
9899
|
+
const subDir = join17(slugDir, entry.name);
|
|
9869
9900
|
let subEntries;
|
|
9870
9901
|
try {
|
|
9871
|
-
subEntries =
|
|
9902
|
+
subEntries = readdirSync12(subDir, { withFileTypes: true });
|
|
9872
9903
|
} catch (err) {
|
|
9873
9904
|
const code = err.code ?? "unknown";
|
|
9874
9905
|
console.error(`[admin-sessions-list] subagents-skipped slug=${slug} code=${code}`);
|
|
@@ -9876,14 +9907,14 @@ function enumerateJsonls(projectsRoot) {
|
|
|
9876
9907
|
}
|
|
9877
9908
|
for (const sub of subEntries) {
|
|
9878
9909
|
if (sub.isFile() && SESSION_ID_RE.test(sub.name)) {
|
|
9879
|
-
out.push({ path:
|
|
9910
|
+
out.push({ path: join17(subDir, sub.name), isSubagent: true, archived: false });
|
|
9880
9911
|
}
|
|
9881
9912
|
}
|
|
9882
9913
|
} else if (entry.isDirectory() && entry.name === "archive") {
|
|
9883
|
-
const archiveDir =
|
|
9914
|
+
const archiveDir = join17(slugDir, entry.name);
|
|
9884
9915
|
let archiveEntries;
|
|
9885
9916
|
try {
|
|
9886
|
-
archiveEntries =
|
|
9917
|
+
archiveEntries = readdirSync12(archiveDir, { withFileTypes: true });
|
|
9887
9918
|
} catch (err) {
|
|
9888
9919
|
const code = err.code ?? "unknown";
|
|
9889
9920
|
console.error(`[admin-sessions-list] archive-skipped slug=${slug} code=${code}`);
|
|
@@ -9891,7 +9922,7 @@ function enumerateJsonls(projectsRoot) {
|
|
|
9891
9922
|
}
|
|
9892
9923
|
for (const arc of archiveEntries) {
|
|
9893
9924
|
if (arc.isFile() && SESSION_ID_RE.test(arc.name)) {
|
|
9894
|
-
out.push({ path:
|
|
9925
|
+
out.push({ path: join17(archiveDir, arc.name), isSubagent: false, archived: true });
|
|
9895
9926
|
}
|
|
9896
9927
|
}
|
|
9897
9928
|
}
|
|
@@ -9924,7 +9955,7 @@ async function fetchLiveSessions() {
|
|
|
9924
9955
|
function loadUserTitles(accountDir) {
|
|
9925
9956
|
const out = /* @__PURE__ */ new Map();
|
|
9926
9957
|
if (!accountDir) return out;
|
|
9927
|
-
const path3 =
|
|
9958
|
+
const path3 = join17(accountDir, "session-titles.json");
|
|
9928
9959
|
let raw;
|
|
9929
9960
|
try {
|
|
9930
9961
|
raw = readFileSync17(path3, "utf8");
|
|
@@ -10051,7 +10082,7 @@ app4.get("/", requireAdminSession, async (c) => {
|
|
|
10051
10082
|
console.error("[admin-sessions-list] CLAUDE_CONFIG_DIR not set; returning empty list");
|
|
10052
10083
|
return c.json({ sessions: [], accountId: scopeAccountId });
|
|
10053
10084
|
}
|
|
10054
|
-
const projectsRoot =
|
|
10085
|
+
const projectsRoot = join17(configDir2, "projects");
|
|
10055
10086
|
const jsonls = enumerateJsonls(projectsRoot);
|
|
10056
10087
|
const liveSessions = await fetchLiveSessions();
|
|
10057
10088
|
const accountDir = scopeAccountId ? resolve12(ACCOUNTS_DIR, scopeAccountId) : null;
|
|
@@ -10096,7 +10127,7 @@ app4.get("/", requireAdminSession, async (c) => {
|
|
|
10096
10127
|
let mtimeMs;
|
|
10097
10128
|
try {
|
|
10098
10129
|
body = readFileSync17(path3, "utf8");
|
|
10099
|
-
mtimeMs =
|
|
10130
|
+
mtimeMs = statSync6(path3).mtimeMs;
|
|
10100
10131
|
} catch {
|
|
10101
10132
|
continue;
|
|
10102
10133
|
}
|
|
@@ -10104,7 +10135,7 @@ app4.get("/", requireAdminSession, async (c) => {
|
|
|
10104
10135
|
const pid = live ? liveSessions.get(sessionId) ?? null : null;
|
|
10105
10136
|
const resolved = resolveTitle(body, sessionId, userTitles);
|
|
10106
10137
|
titleSourceCounts[resolved.source] += 1;
|
|
10107
|
-
const metaPath =
|
|
10138
|
+
const metaPath = join17(projectDir, `${sessionId}.meta.json`);
|
|
10108
10139
|
const { bridgeIds, role, channel: sidecarChannel, senderId, personId, adminUserId, accountId: rowAccountId } = readSidecarMeta(metaPath);
|
|
10109
10140
|
if (multiAccount) {
|
|
10110
10141
|
if (rowAccountId === null) untaggedCount += 1;
|
|
@@ -10417,9 +10448,9 @@ function isModelGated(turns) {
|
|
|
10417
10448
|
return turns.some((t) => t.kind === "agent-error" && t.code === "model_unavailable");
|
|
10418
10449
|
}
|
|
10419
10450
|
function renderOrSuppressChannelInbound(u, ts, out, queuedPendingSuppress) {
|
|
10420
|
-
const
|
|
10421
|
-
if (
|
|
10422
|
-
queuedPendingSuppress.set(u.text,
|
|
10451
|
+
const armed2 = queuedPendingSuppress.get(u.text) ?? 0;
|
|
10452
|
+
if (armed2 > 0) {
|
|
10453
|
+
queuedPendingSuppress.set(u.text, armed2 - 1);
|
|
10423
10454
|
} else {
|
|
10424
10455
|
out.push(operatorInboundTurn(u, ts));
|
|
10425
10456
|
}
|
|
@@ -10517,8 +10548,8 @@ function parseTranscript(lines, queuedPendingSuppress = /* @__PURE__ */ new Map(
|
|
|
10517
10548
|
}
|
|
10518
10549
|
|
|
10519
10550
|
// app/lib/whatsapp-reader/enrich-attachments.ts
|
|
10520
|
-
import { readFileSync as readFileSync18, readdirSync as
|
|
10521
|
-
import { join as
|
|
10551
|
+
import { readFileSync as readFileSync18, readdirSync as readdirSync13 } from "fs";
|
|
10552
|
+
import { join as join18 } from "path";
|
|
10522
10553
|
var ADMIN_UPLOAD_PATH = /\/uploads\/(?!public\/)([0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12})\//gi;
|
|
10523
10554
|
function adminAttachmentIds(text) {
|
|
10524
10555
|
const ids = [];
|
|
@@ -10531,7 +10562,7 @@ function adminAttachmentIds(text) {
|
|
|
10531
10562
|
function adminAttachmentsFromText(text, uploadsBase) {
|
|
10532
10563
|
const out = [];
|
|
10533
10564
|
for (const id of adminAttachmentIds(text)) {
|
|
10534
|
-
const meta = readAttachmentMeta(
|
|
10565
|
+
const meta = readAttachmentMeta(join18(uploadsBase, id));
|
|
10535
10566
|
if (meta) out.push(meta);
|
|
10536
10567
|
}
|
|
10537
10568
|
return out;
|
|
@@ -10539,7 +10570,7 @@ function adminAttachmentsFromText(text, uploadsBase) {
|
|
|
10539
10570
|
function readSidecar(dir, attachmentId) {
|
|
10540
10571
|
let parsed;
|
|
10541
10572
|
try {
|
|
10542
|
-
parsed = JSON.parse(readFileSync18(
|
|
10573
|
+
parsed = JSON.parse(readFileSync18(join18(dir, `${attachmentId}.meta.json`), "utf8"));
|
|
10543
10574
|
} catch {
|
|
10544
10575
|
return null;
|
|
10545
10576
|
}
|
|
@@ -10562,13 +10593,13 @@ function readAttachmentMeta(dir) {
|
|
|
10562
10593
|
function listSessionAttachmentsInDir(dir) {
|
|
10563
10594
|
let entries;
|
|
10564
10595
|
try {
|
|
10565
|
-
entries =
|
|
10596
|
+
entries = readdirSync13(dir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
10566
10597
|
} catch {
|
|
10567
10598
|
return [];
|
|
10568
10599
|
}
|
|
10569
10600
|
const sidecars = [];
|
|
10570
10601
|
for (const name of entries) {
|
|
10571
|
-
const sidecar = readSidecar(
|
|
10602
|
+
const sidecar = readSidecar(join18(dir, name), name);
|
|
10572
10603
|
if (sidecar) sidecars.push(sidecar);
|
|
10573
10604
|
}
|
|
10574
10605
|
sidecars.sort((a, b) => a.storedAt.localeCompare(b.storedAt));
|
|
@@ -10628,8 +10659,8 @@ function pickActivity(entries, grown, nowMs, concurrencyWindowMs) {
|
|
|
10628
10659
|
|
|
10629
10660
|
// server/routes/stream-lifecycle.ts
|
|
10630
10661
|
var GAUGE_INTERVAL_MS = 6e4;
|
|
10631
|
-
function isArmed(
|
|
10632
|
-
return
|
|
10662
|
+
function isArmed(timer) {
|
|
10663
|
+
return timer._destroyed !== true;
|
|
10633
10664
|
}
|
|
10634
10665
|
var Registration = class {
|
|
10635
10666
|
constructor(connId, channel, startedAt) {
|
|
@@ -10639,9 +10670,9 @@ var Registration = class {
|
|
|
10639
10670
|
}
|
|
10640
10671
|
timers = [];
|
|
10641
10672
|
closed = false;
|
|
10642
|
-
arm(
|
|
10643
|
-
this.timers.push(
|
|
10644
|
-
return
|
|
10673
|
+
arm(timer) {
|
|
10674
|
+
this.timers.push(timer);
|
|
10675
|
+
return timer;
|
|
10645
10676
|
}
|
|
10646
10677
|
teardown(reason) {
|
|
10647
10678
|
if (this.closed) return false;
|
|
@@ -10675,11 +10706,11 @@ function emitGauge() {
|
|
|
10675
10706
|
counts[reg.channel]++;
|
|
10676
10707
|
oldestMs = Math.max(oldestMs, now - reg.startedAt);
|
|
10677
10708
|
}
|
|
10678
|
-
const
|
|
10709
|
+
const armed2 = counts.reader + counts.store;
|
|
10679
10710
|
console.log(
|
|
10680
|
-
`[wa-stream] op=gauge armed=${
|
|
10711
|
+
`[wa-stream] op=gauge armed=${armed2} reader=${counts.reader} store=${counts.store} oldestSec=${Math.floor(oldestMs / 1e3)} stale=${stale}`
|
|
10681
10712
|
);
|
|
10682
|
-
if (
|
|
10713
|
+
if (armed2 === 0) stopGauge();
|
|
10683
10714
|
}
|
|
10684
10715
|
function startGauge() {
|
|
10685
10716
|
if (gaugeTimer) return;
|
|
@@ -10728,14 +10759,14 @@ app5.get("/conversations", requireAdminSession, async (c) => {
|
|
|
10728
10759
|
}
|
|
10729
10760
|
const cfg = claudeConfigDir();
|
|
10730
10761
|
if (!cfg) return c.json({ conversations: [] });
|
|
10731
|
-
const projectsRoot =
|
|
10762
|
+
const projectsRoot = join19(cfg, "projects");
|
|
10732
10763
|
const userTitles = loadUserTitles(ACCOUNTS_DIR ?? null);
|
|
10733
10764
|
const rows = [];
|
|
10734
10765
|
let sessionRowsExcludedUntagged = 0;
|
|
10735
10766
|
for (const { path: path3 } of enumerateJsonls(projectsRoot)) {
|
|
10736
10767
|
const sessionId = basename4(path3).replace(/\.jsonl$/, "");
|
|
10737
10768
|
const projectDir = dirname5(path3);
|
|
10738
|
-
const meta = readSidecarMeta(
|
|
10769
|
+
const meta = readSidecarMeta(join19(projectDir, `${sessionId}.meta.json`));
|
|
10739
10770
|
if (!isReaderChannelSession(meta.role, meta.channel)) continue;
|
|
10740
10771
|
if (multiAccount) {
|
|
10741
10772
|
if (meta.accountId === null) sessionRowsExcludedUntagged += 1;
|
|
@@ -10827,7 +10858,7 @@ app5.get("/conversations", requireAdminSession, async (c) => {
|
|
|
10827
10858
|
return c.json({ conversations: [...sessionConversations, ...allStoreRows] });
|
|
10828
10859
|
});
|
|
10829
10860
|
function readFrom(path3, from) {
|
|
10830
|
-
const end =
|
|
10861
|
+
const end = statSync7(path3).size;
|
|
10831
10862
|
if (end <= from) return { buf: Buffer.alloc(0), end: from };
|
|
10832
10863
|
const fd = openSync(path3, "r");
|
|
10833
10864
|
try {
|
|
@@ -10912,7 +10943,7 @@ function openTaskKey(turns) {
|
|
|
10912
10943
|
}
|
|
10913
10944
|
function readSubagentMeta(dir, hex) {
|
|
10914
10945
|
try {
|
|
10915
|
-
const m = JSON.parse(readFileSync19(
|
|
10946
|
+
const m = JSON.parse(readFileSync19(join19(dir, `agent-${hex}.meta.json`), "utf8"));
|
|
10916
10947
|
if (typeof m.agentType === "string" && typeof m.description === "string" && typeof m.toolUseId === "string") {
|
|
10917
10948
|
return { agentType: m.agentType, description: m.description, toolUseId: m.toolUseId };
|
|
10918
10949
|
}
|
|
@@ -10935,7 +10966,7 @@ function runActivityTick(c) {
|
|
|
10935
10966
|
c.parentGrewThisTick = false;
|
|
10936
10967
|
let names = [];
|
|
10937
10968
|
try {
|
|
10938
|
-
names =
|
|
10969
|
+
names = readdirSync14(c.subagentsDir).filter((n) => AGENT_JSONL_RE.test(n));
|
|
10939
10970
|
} catch {
|
|
10940
10971
|
}
|
|
10941
10972
|
const entries = [];
|
|
@@ -10944,7 +10975,7 @@ function runActivityTick(c) {
|
|
|
10944
10975
|
let size = 0;
|
|
10945
10976
|
let mtimeMs = 0;
|
|
10946
10977
|
try {
|
|
10947
|
-
const st =
|
|
10978
|
+
const st = statSync7(join19(c.subagentsDir, name));
|
|
10948
10979
|
size = st.size;
|
|
10949
10980
|
mtimeMs = st.mtimeMs;
|
|
10950
10981
|
} catch {
|
|
@@ -10989,11 +11020,11 @@ app5.get("/stream", requireAdminSession, (c) => {
|
|
|
10989
11020
|
const sessionId = c.req.query("sessionId") ?? "";
|
|
10990
11021
|
const projectDir = c.req.query("projectDir") ?? "";
|
|
10991
11022
|
const cfg = claudeConfigDir();
|
|
10992
|
-
const projectsRoot = cfg ? resolve13(
|
|
11023
|
+
const projectsRoot = cfg ? resolve13(join19(cfg, "projects")) : null;
|
|
10993
11024
|
if (!cfg || !projectsRoot || !SESSION_ID_RE2.test(sessionId)) {
|
|
10994
11025
|
return c.json({ error: "bad session reference" }, 400);
|
|
10995
11026
|
}
|
|
10996
|
-
const jsonlPath = resolve13(
|
|
11027
|
+
const jsonlPath = resolve13(join19(projectDir, `${sessionId}.jsonl`));
|
|
10997
11028
|
if (!jsonlPath.startsWith(projectsRoot + sep3)) {
|
|
10998
11029
|
return c.json({ error: "bad session reference" }, 400);
|
|
10999
11030
|
}
|
|
@@ -11012,7 +11043,7 @@ data: ${JSON.stringify(turn)}
|
|
|
11012
11043
|
start(controller) {
|
|
11013
11044
|
const fileEnd0 = (() => {
|
|
11014
11045
|
try {
|
|
11015
|
-
return
|
|
11046
|
+
return statSync7(jsonlPath).size;
|
|
11016
11047
|
} catch {
|
|
11017
11048
|
return 0;
|
|
11018
11049
|
}
|
|
@@ -11020,9 +11051,9 @@ data: ${JSON.stringify(turn)}
|
|
|
11020
11051
|
let offset = resumeOffset(lastEventId, fileEnd0);
|
|
11021
11052
|
console.log(`[wa-stream] op=open conn=${connId} sessionId=${sessionId} channel=reader resume=${offset}`);
|
|
11022
11053
|
const sessionKey = c.req.query("session_key") ?? "";
|
|
11023
|
-
const subagentsDir = resolve13(
|
|
11054
|
+
const subagentsDir = resolve13(join19(projectDir, sessionId, "subagents"));
|
|
11024
11055
|
console.log(
|
|
11025
|
-
`[webchat-activity] op=watch-subagents key=${sessionKey} dir=${subagentsDir} exists=${
|
|
11056
|
+
`[webchat-activity] op=watch-subagents key=${sessionKey} dir=${subagentsDir} exists=${existsSync13(subagentsDir)}`
|
|
11026
11057
|
);
|
|
11027
11058
|
const actx = makeActivityCtx({
|
|
11028
11059
|
subagentsDir,
|
|
@@ -11136,10 +11167,10 @@ app5.get("/directives", requireAdminSession, (c) => {
|
|
|
11136
11167
|
const sessionId = c.req.query("sessionId") ?? "";
|
|
11137
11168
|
if (!SESSION_ID_RE2.test(sessionId)) return c.json({ error: "bad session reference" }, 400);
|
|
11138
11169
|
const dir = directiveStoreDir(sessionId);
|
|
11139
|
-
if (!dir || !
|
|
11170
|
+
if (!dir || !existsSync13(dir)) return c.json({ entries: [] });
|
|
11140
11171
|
let names;
|
|
11141
11172
|
try {
|
|
11142
|
-
names =
|
|
11173
|
+
names = readdirSync14(dir).filter((n) => DIRECTIVE_NAME_RE.test(n));
|
|
11143
11174
|
} catch {
|
|
11144
11175
|
return c.json({ entries: [] });
|
|
11145
11176
|
}
|
|
@@ -11149,7 +11180,7 @@ app5.get("/directives", requireAdminSession, (c) => {
|
|
|
11149
11180
|
const pid = Number(pidPart);
|
|
11150
11181
|
let len = 0;
|
|
11151
11182
|
try {
|
|
11152
|
-
len =
|
|
11183
|
+
len = statSync7(join19(dir, name)).size;
|
|
11153
11184
|
} catch {
|
|
11154
11185
|
}
|
|
11155
11186
|
return { name, secs, pid, ts: Number.isFinite(secs) ? new Date(secs * 1e3).toISOString() : null, len };
|
|
@@ -11164,7 +11195,7 @@ app5.get("/directive", requireAdminSession, (c) => {
|
|
|
11164
11195
|
}
|
|
11165
11196
|
const dir = directiveStoreDir(sessionId);
|
|
11166
11197
|
if (!dir) return c.json({ error: "no account" }, 404);
|
|
11167
|
-
const path3 = resolve13(
|
|
11198
|
+
const path3 = resolve13(join19(dir, name));
|
|
11168
11199
|
if (!path3.startsWith(dir + sep3)) return c.json({ error: "bad reference" }, 400);
|
|
11169
11200
|
let body;
|
|
11170
11201
|
try {
|
|
@@ -11222,7 +11253,7 @@ app5.get("/store-stream", requireAdminSession, (c) => {
|
|
|
11222
11253
|
console.log(`[wa-reader] op=store-quote msgId=${r.msgKeyId} quoted=${!!q}`);
|
|
11223
11254
|
}
|
|
11224
11255
|
if (r.attachmentId) {
|
|
11225
|
-
const meta = readAttachmentMeta(
|
|
11256
|
+
const meta = readAttachmentMeta(join19(uploadsBase, r.attachmentId));
|
|
11226
11257
|
if (meta) return { ...turn, attachments: [meta] };
|
|
11227
11258
|
}
|
|
11228
11259
|
return turn;
|
|
@@ -11255,7 +11286,7 @@ data: ${JSON.stringify(payload)}
|
|
|
11255
11286
|
};
|
|
11256
11287
|
const fileEnd0 = (() => {
|
|
11257
11288
|
try {
|
|
11258
|
-
return
|
|
11289
|
+
return statSync7(file).size;
|
|
11259
11290
|
} catch {
|
|
11260
11291
|
return 0;
|
|
11261
11292
|
}
|
|
@@ -11473,7 +11504,7 @@ app5.post("/reply", requireAdminSession, async (c) => {
|
|
|
11473
11504
|
const absolute = resolved.absolute;
|
|
11474
11505
|
let size = -1;
|
|
11475
11506
|
try {
|
|
11476
|
-
const st =
|
|
11507
|
+
const st = statSync7(absolute);
|
|
11477
11508
|
size = st.isFile() ? st.size : -1;
|
|
11478
11509
|
} catch {
|
|
11479
11510
|
size = -1;
|
|
@@ -11597,8 +11628,8 @@ app5.post("/reply", requireAdminSession, async (c) => {
|
|
|
11597
11628
|
var whatsapp_reader_default = app5;
|
|
11598
11629
|
|
|
11599
11630
|
// server/routes/public-reader.ts
|
|
11600
|
-
import { statSync as
|
|
11601
|
-
import { basename as basename5, dirname as dirname6, join as
|
|
11631
|
+
import { statSync as statSync8, openSync as openSync2, readSync as readSync2, closeSync as closeSync2, watch as watch2, readFileSync as readFileSync20, readdirSync as readdirSync15 } from "fs";
|
|
11632
|
+
import { basename as basename5, dirname as dirname6, join as join20, resolve as resolve14, sep as sep4 } from "path";
|
|
11602
11633
|
|
|
11603
11634
|
// app/lib/whatsapp-reader/delivered-kinds.ts
|
|
11604
11635
|
var PUBLIC_DELIVERED_KINDS = /* @__PURE__ */ new Set([
|
|
@@ -11672,10 +11703,10 @@ function enumeratePublicRows() {
|
|
|
11672
11703
|
const cfg = claudeConfigDir();
|
|
11673
11704
|
if (!cfg) return [];
|
|
11674
11705
|
const rows = [];
|
|
11675
|
-
for (const { path: path3 } of enumerateJsonls(
|
|
11706
|
+
for (const { path: path3 } of enumerateJsonls(join20(cfg, "projects"))) {
|
|
11676
11707
|
const sessionId = basename5(path3).replace(/\.jsonl$/, "");
|
|
11677
11708
|
const projectDir = dirname6(path3);
|
|
11678
|
-
const meta = readSidecarMeta(
|
|
11709
|
+
const meta = readSidecarMeta(join20(projectDir, `${sessionId}.meta.json`));
|
|
11679
11710
|
rows.push({
|
|
11680
11711
|
sessionId,
|
|
11681
11712
|
projectDir,
|
|
@@ -11731,7 +11762,7 @@ function enrichPublicAttachments(turns, sessionAttachments, cursor) {
|
|
|
11731
11762
|
}
|
|
11732
11763
|
}
|
|
11733
11764
|
function readFrom2(path3, from) {
|
|
11734
|
-
const end =
|
|
11765
|
+
const end = statSync8(path3).size;
|
|
11735
11766
|
if (end <= from) return { buf: Buffer.alloc(0), end: from };
|
|
11736
11767
|
const fd = openSync2(path3, "r");
|
|
11737
11768
|
try {
|
|
@@ -11751,15 +11782,15 @@ app6.get("/stream", (c) => {
|
|
|
11751
11782
|
const sessionId = c.req.query("sessionId") ?? "";
|
|
11752
11783
|
const projectDir = c.req.query("projectDir") ?? "";
|
|
11753
11784
|
const cfg = claudeConfigDir();
|
|
11754
|
-
const projectsRoot = cfg ? resolve14(
|
|
11785
|
+
const projectsRoot = cfg ? resolve14(join20(cfg, "projects")) : null;
|
|
11755
11786
|
if (!cfg || !projectsRoot || !SESSION_ID_RE2.test(sessionId)) {
|
|
11756
11787
|
return c.json({ error: "bad session reference" }, 400);
|
|
11757
11788
|
}
|
|
11758
|
-
const jsonlPath = resolve14(
|
|
11789
|
+
const jsonlPath = resolve14(join20(projectDir, `${sessionId}.jsonl`));
|
|
11759
11790
|
if (!jsonlPath.startsWith(projectsRoot + sep4)) {
|
|
11760
11791
|
return c.json({ error: "bad session reference" }, 400);
|
|
11761
11792
|
}
|
|
11762
|
-
const meta = readSidecarMeta(
|
|
11793
|
+
const meta = readSidecarMeta(join20(projectDir, `${sessionId}.meta.json`));
|
|
11763
11794
|
const isPublicWebchat = meta.role === "public" && meta.channel === "webchat";
|
|
11764
11795
|
const owns = visitor.kind === "person" ? meta.personId === visitor.personId : meta.personId === null && meta.visitorId === visitor.visitorId;
|
|
11765
11796
|
if (!(isPublicWebchat && owns)) {
|
|
@@ -11872,7 +11903,7 @@ app6.get("/attachment/:attachmentId", (c) => {
|
|
|
11872
11903
|
let dataFile;
|
|
11873
11904
|
let buffer;
|
|
11874
11905
|
try {
|
|
11875
|
-
dataFile =
|
|
11906
|
+
dataFile = readdirSync15(dir).find((f) => !f.endsWith(".meta.json") && !f.endsWith(EXTRACTED_TEXT_SUFFIX));
|
|
11876
11907
|
if (!dataFile) throw new Error("no data file");
|
|
11877
11908
|
buffer = readFileSync20(resolve14(dir, dataFile));
|
|
11878
11909
|
} catch {
|
|
@@ -11896,16 +11927,16 @@ var public_reader_default = app6;
|
|
|
11896
11927
|
|
|
11897
11928
|
// server/routes/webchat.ts
|
|
11898
11929
|
import { basename as basename6, dirname as dirname7 } from "path";
|
|
11899
|
-
import { join as
|
|
11900
|
-
import { existsSync as
|
|
11930
|
+
import { join as join23 } from "path";
|
|
11931
|
+
import { existsSync as existsSync15, readdirSync as readdirSync17, readFileSync as readFileSync23, renameSync as renameSync4, statSync as statSync9, writeFileSync as writeFileSync8 } from "fs";
|
|
11901
11932
|
|
|
11902
11933
|
// server/canonical-webchat-override.ts
|
|
11903
11934
|
import { readFileSync as readFileSync21, writeFileSync as writeFileSync6, renameSync as renameSync2 } from "fs";
|
|
11904
|
-
import { join as
|
|
11935
|
+
import { join as join21 } from "path";
|
|
11905
11936
|
var FILE = "canonical-webchat-session.json";
|
|
11906
11937
|
var UUID = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
|
|
11907
11938
|
function canonicalOverridePath(accountDir) {
|
|
11908
|
-
return
|
|
11939
|
+
return join21(accountDir, FILE);
|
|
11909
11940
|
}
|
|
11910
11941
|
function readRaw(accountDir) {
|
|
11911
11942
|
try {
|
|
@@ -11984,8 +12015,8 @@ function isNewSessionEffortLevel(value) {
|
|
|
11984
12015
|
}
|
|
11985
12016
|
|
|
11986
12017
|
// ../services/claude-session-manager/src/sidecar-store.ts
|
|
11987
|
-
import { existsSync as
|
|
11988
|
-
import { join as
|
|
12018
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync4, readdirSync as readdirSync16, readFileSync as readFileSync22, renameSync as renameSync3, unlinkSync as unlinkSync2, writeFileSync as writeFileSync7 } from "fs";
|
|
12019
|
+
import { join as join22 } from "path";
|
|
11989
12020
|
function escapeRegExp(s) {
|
|
11990
12021
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
11991
12022
|
}
|
|
@@ -11993,7 +12024,7 @@ function createSidecarStore(config) {
|
|
|
11993
12024
|
const { suffix, validate: validate2 } = config;
|
|
11994
12025
|
const suffixRe = new RegExp(`${escapeRegExp(suffix)}$`);
|
|
11995
12026
|
function pathFor(sessionsDir, id) {
|
|
11996
|
-
return
|
|
12027
|
+
return join22(sessionsDir, `${id}${suffix}`);
|
|
11997
12028
|
}
|
|
11998
12029
|
function write(sessionsDir, id, record) {
|
|
11999
12030
|
mkdirSync4(sessionsDir, { recursive: true });
|
|
@@ -12005,7 +12036,7 @@ function createSidecarStore(config) {
|
|
|
12005
12036
|
return { ok: true };
|
|
12006
12037
|
} catch (error) {
|
|
12007
12038
|
try {
|
|
12008
|
-
if (
|
|
12039
|
+
if (existsSync14(tmp)) unlinkSync2(tmp);
|
|
12009
12040
|
} catch {
|
|
12010
12041
|
}
|
|
12011
12042
|
return { ok: false, error };
|
|
@@ -12030,14 +12061,14 @@ function createSidecarStore(config) {
|
|
|
12030
12061
|
function readAll(sessionsDir, onSkip) {
|
|
12031
12062
|
let names;
|
|
12032
12063
|
try {
|
|
12033
|
-
names =
|
|
12064
|
+
names = readdirSync16(sessionsDir, { withFileTypes: true }).filter((entry) => entry.isFile()).map((entry) => entry.name);
|
|
12034
12065
|
} catch {
|
|
12035
12066
|
return [];
|
|
12036
12067
|
}
|
|
12037
12068
|
const out = [];
|
|
12038
12069
|
for (const name of names) {
|
|
12039
12070
|
if (!suffixRe.test(name)) continue;
|
|
12040
|
-
const path3 =
|
|
12071
|
+
const path3 = join22(sessionsDir, name);
|
|
12041
12072
|
let raw;
|
|
12042
12073
|
try {
|
|
12043
12074
|
raw = readFileSync22(path3, "utf8");
|
|
@@ -12061,7 +12092,7 @@ function createSidecarStore(config) {
|
|
|
12061
12092
|
function clear(sessionsDir, id) {
|
|
12062
12093
|
const path3 = pathFor(sessionsDir, id);
|
|
12063
12094
|
try {
|
|
12064
|
-
if (
|
|
12095
|
+
if (existsSync14(path3)) {
|
|
12065
12096
|
unlinkSync2(path3);
|
|
12066
12097
|
return { ok: true, removed: true };
|
|
12067
12098
|
}
|
|
@@ -12114,22 +12145,22 @@ var UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9
|
|
|
12114
12145
|
function locateSession(sessionId) {
|
|
12115
12146
|
const dir = findSessionProjectDir(sessionId);
|
|
12116
12147
|
if (!dir) return { projectDir: null, channel: null, accountId: null };
|
|
12117
|
-
const meta = readSidecarMeta(
|
|
12148
|
+
const meta = readSidecarMeta(join23(dir, `${sessionId}.meta.json`));
|
|
12118
12149
|
return { projectDir: dir, channel: meta.channel, accountId: meta.accountId };
|
|
12119
12150
|
}
|
|
12120
12151
|
function locateSidecar(sessionId) {
|
|
12121
12152
|
const cfg = claudeConfigDir();
|
|
12122
12153
|
if (!cfg) return null;
|
|
12123
|
-
const projectsRoot =
|
|
12154
|
+
const projectsRoot = join23(cfg, "projects");
|
|
12124
12155
|
let slugs;
|
|
12125
12156
|
try {
|
|
12126
|
-
slugs =
|
|
12157
|
+
slugs = readdirSync17(projectsRoot, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
12127
12158
|
} catch {
|
|
12128
12159
|
return null;
|
|
12129
12160
|
}
|
|
12130
12161
|
for (const slug of slugs) {
|
|
12131
|
-
const metaPath =
|
|
12132
|
-
if (
|
|
12162
|
+
const metaPath = join23(projectsRoot, slug, `${sessionId}.meta.json`);
|
|
12163
|
+
if (existsSync15(metaPath)) {
|
|
12133
12164
|
const meta = readSidecarMeta(metaPath);
|
|
12134
12165
|
return { channel: meta.channel, adminUserId: meta.adminUserId, accountId: meta.accountId };
|
|
12135
12166
|
}
|
|
@@ -12141,7 +12172,7 @@ function readTargetOwner(sessionId) {
|
|
|
12141
12172
|
if (sidecar !== null) return { found: true, owner: sidecar.adminUserId };
|
|
12142
12173
|
const { projectDir } = locateSession(sessionId);
|
|
12143
12174
|
if (projectDir !== null) {
|
|
12144
|
-
return { found: true, owner: readSidecarMeta(
|
|
12175
|
+
return { found: true, owner: readSidecarMeta(join23(projectDir, `${sessionId}.meta.json`)).adminUserId };
|
|
12145
12176
|
}
|
|
12146
12177
|
return { found: false, owner: null };
|
|
12147
12178
|
}
|
|
@@ -12155,7 +12186,7 @@ function sessionSidecarExists(sessionId) {
|
|
|
12155
12186
|
function jsonlSizeBytes(projectDir, sessionId) {
|
|
12156
12187
|
if (projectDir === null) return null;
|
|
12157
12188
|
try {
|
|
12158
|
-
return
|
|
12189
|
+
return statSync9(join23(projectDir, `${sessionId}.jsonl`)).size;
|
|
12159
12190
|
} catch {
|
|
12160
12191
|
return null;
|
|
12161
12192
|
}
|
|
@@ -12291,15 +12322,15 @@ function latestAdminWebchatSessionId(requesterUserId, primaryUserId, scopeAccoun
|
|
|
12291
12322
|
const cfg = claudeConfigDir();
|
|
12292
12323
|
if (!cfg) return null;
|
|
12293
12324
|
let best = null;
|
|
12294
|
-
for (const { path: path3, isSubagent, archived } of enumerateJsonls(
|
|
12325
|
+
for (const { path: path3, isSubagent, archived } of enumerateJsonls(join23(cfg, "projects"))) {
|
|
12295
12326
|
if (isSubagent || archived) continue;
|
|
12296
12327
|
const id = basename6(path3).slice(0, -".jsonl".length);
|
|
12297
|
-
const meta = readSidecarMeta(
|
|
12328
|
+
const meta = readSidecarMeta(join23(dirname7(path3), `${id}.meta.json`));
|
|
12298
12329
|
if (meta.role !== "admin" || meta.channel !== "webchat") continue;
|
|
12299
12330
|
if (multiAccount && meta.accountId !== scopeAccountId) continue;
|
|
12300
12331
|
let mtimeMs;
|
|
12301
12332
|
try {
|
|
12302
|
-
mtimeMs =
|
|
12333
|
+
mtimeMs = statSync9(path3).mtimeMs;
|
|
12303
12334
|
} catch {
|
|
12304
12335
|
continue;
|
|
12305
12336
|
}
|
|
@@ -12616,7 +12647,7 @@ ${note}` : note;
|
|
|
12616
12647
|
console.error(`[webchat:settings] op=${op} outcome=refused value=${value} reason=account-unresolved`);
|
|
12617
12648
|
return c.json({ error: "account unresolved" }, 503);
|
|
12618
12649
|
}
|
|
12619
|
-
const accountJsonPath =
|
|
12650
|
+
const accountJsonPath = join23(account.accountDir, "account.json");
|
|
12620
12651
|
try {
|
|
12621
12652
|
const parsed = JSON.parse(readFileSync23(accountJsonPath, "utf8"));
|
|
12622
12653
|
if (op === "model") parsed.adminModel = value;
|
|
@@ -12664,7 +12695,7 @@ ${note}` : note;
|
|
|
12664
12695
|
const cfg2 = claudeConfigDir();
|
|
12665
12696
|
if (cfg2) {
|
|
12666
12697
|
const source2 = resolveBridgeSource(
|
|
12667
|
-
|
|
12698
|
+
join23(cfg2, "sessions"),
|
|
12668
12699
|
target,
|
|
12669
12700
|
(id) => locateSession(id).projectDir !== null
|
|
12670
12701
|
);
|
|
@@ -12696,7 +12727,7 @@ ${note}` : note;
|
|
|
12696
12727
|
const cfg = claudeConfigDir();
|
|
12697
12728
|
let projectDir = null;
|
|
12698
12729
|
if (cfg) {
|
|
12699
|
-
for (const { path: path3 } of enumerateJsonls(
|
|
12730
|
+
for (const { path: path3 } of enumerateJsonls(join23(cfg, "projects"))) {
|
|
12700
12731
|
if (basename6(path3) === `${sessionId}.jsonl`) {
|
|
12701
12732
|
projectDir = dirname7(path3);
|
|
12702
12733
|
break;
|
|
@@ -12704,7 +12735,7 @@ ${note}` : note;
|
|
|
12704
12735
|
}
|
|
12705
12736
|
}
|
|
12706
12737
|
if (source === "latest" && requesterUserId !== null) {
|
|
12707
|
-
const owner = readSidecarMeta(
|
|
12738
|
+
const owner = readSidecarMeta(join23(projectDir ?? "", `${sessionId}.meta.json`)).adminUserId;
|
|
12708
12739
|
if (owner !== null && owner !== requesterUserId && requesterUserId !== primaryUserId) {
|
|
12709
12740
|
console.error(`[webchat:inbound] op=session-resolve-foreign key=${sessionId.slice(0, 8)} owner=${owner.slice(0, 8)} requester=${requesterUserId.slice(0, 8)}`);
|
|
12710
12741
|
}
|
|
@@ -12736,8 +12767,8 @@ ${note}` : note;
|
|
|
12736
12767
|
import { resolve as resolve15 } from "path";
|
|
12737
12768
|
|
|
12738
12769
|
// app/lib/claude-agent/specialist-roster.ts
|
|
12739
|
-
import { existsSync as
|
|
12740
|
-
import { join as
|
|
12770
|
+
import { existsSync as existsSync16, readFileSync as readFileSync24, readdirSync as readdirSync18 } from "fs";
|
|
12771
|
+
import { join as join24 } from "path";
|
|
12741
12772
|
function field(fm, name) {
|
|
12742
12773
|
const m = fm.match(new RegExp(`^${name}:\\s*(.*?)\\r?$`, "m"));
|
|
12743
12774
|
if (!m) return null;
|
|
@@ -12748,15 +12779,15 @@ function field(fm, name) {
|
|
|
12748
12779
|
return value || null;
|
|
12749
12780
|
}
|
|
12750
12781
|
function readSpecialistRoster(specialistsDir) {
|
|
12751
|
-
if (!
|
|
12752
|
-
const entries =
|
|
12782
|
+
if (!existsSync16(specialistsDir)) return { specialists: [], skipped: [] };
|
|
12783
|
+
const entries = readdirSync18(specialistsDir);
|
|
12753
12784
|
const specialists = [];
|
|
12754
12785
|
const skipped = [];
|
|
12755
12786
|
for (const file of entries.sort()) {
|
|
12756
12787
|
if (!file.endsWith(".md")) continue;
|
|
12757
12788
|
let raw;
|
|
12758
12789
|
try {
|
|
12759
|
-
raw = readFileSync24(
|
|
12790
|
+
raw = readFileSync24(join24(specialistsDir, file), "utf-8");
|
|
12760
12791
|
} catch (err) {
|
|
12761
12792
|
skipped.push({ file, reason: err instanceof Error ? err.message : String(err) });
|
|
12762
12793
|
continue;
|
|
@@ -12873,8 +12904,8 @@ var webchat_greeting_default = app7;
|
|
|
12873
12904
|
|
|
12874
12905
|
// server/routes/telegram.ts
|
|
12875
12906
|
import { homedir as homedir2 } from "os";
|
|
12876
|
-
import { resolve as resolve16, join as
|
|
12877
|
-
import { existsSync as
|
|
12907
|
+
import { resolve as resolve16, join as join25 } from "path";
|
|
12908
|
+
import { existsSync as existsSync17, readFileSync as readFileSync25 } from "fs";
|
|
12878
12909
|
|
|
12879
12910
|
// app/lib/telegram/gateway/instance.ts
|
|
12880
12911
|
var instance = null;
|
|
@@ -12933,8 +12964,8 @@ function routeTelegramUpdate(input) {
|
|
|
12933
12964
|
var TAG27 = "[telegram-inbound]";
|
|
12934
12965
|
function configDirName() {
|
|
12935
12966
|
const platformRoot5 = process.env.MAXY_PLATFORM_ROOT ?? resolve16(process.cwd(), "..");
|
|
12936
|
-
const brandPath =
|
|
12937
|
-
if (
|
|
12967
|
+
const brandPath = join25(platformRoot5, "config", "brand.json");
|
|
12968
|
+
if (existsSync17(brandPath)) {
|
|
12938
12969
|
try {
|
|
12939
12970
|
return JSON.parse(readFileSync25(brandPath, "utf-8")).configDir ?? ".maxy";
|
|
12940
12971
|
} catch {
|
|
@@ -12955,7 +12986,7 @@ app8.post("/", async (c) => {
|
|
|
12955
12986
|
return c.json({ ok: false }, 400);
|
|
12956
12987
|
}
|
|
12957
12988
|
const sp = secretPath(botType);
|
|
12958
|
-
if (!
|
|
12989
|
+
if (!existsSync17(sp)) {
|
|
12959
12990
|
console.error(`${TAG27} op=reject reason=no-secret-file botType=${botType}`);
|
|
12960
12991
|
return c.json({ ok: false }, 401);
|
|
12961
12992
|
}
|
|
@@ -13022,21 +13053,21 @@ app8.post("/", async (c) => {
|
|
|
13022
13053
|
var telegram_default = app8;
|
|
13023
13054
|
|
|
13024
13055
|
// server/routes/quickbooks.ts
|
|
13025
|
-
import { join as
|
|
13026
|
-
import { existsSync as
|
|
13056
|
+
import { join as join26 } from "path";
|
|
13057
|
+
import { existsSync as existsSync18, readFileSync as readFileSync26, writeFileSync as writeFileSync9, mkdirSync as mkdirSync5, rmSync, renameSync as renameSync5 } from "fs";
|
|
13027
13058
|
var TAG28 = "[quickbooks]";
|
|
13028
13059
|
var INTUIT_TOKEN_URL = "https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer";
|
|
13029
13060
|
var STATE_RE = /^[A-Za-z0-9_-]+$/;
|
|
13030
13061
|
function pendingPath(accountDir, state) {
|
|
13031
|
-
return
|
|
13062
|
+
return join26(accountDir, "secrets", "quickbooks-pending", `${state}.json`);
|
|
13032
13063
|
}
|
|
13033
13064
|
function storePath(accountDir) {
|
|
13034
|
-
return
|
|
13065
|
+
return join26(accountDir, "secrets", "quickbooks.json");
|
|
13035
13066
|
}
|
|
13036
13067
|
async function completeConsent(args) {
|
|
13037
13068
|
const { accountDir, code, realmId } = args;
|
|
13038
13069
|
const state = args.state;
|
|
13039
|
-
if (!state || !STATE_RE.test(state) || !
|
|
13070
|
+
if (!state || !STATE_RE.test(state) || !existsSync18(pendingPath(accountDir, state))) {
|
|
13040
13071
|
console.error(`${TAG28} op=callback state=${state ?? ""} stateValid=false realmId=${realmId ?? ""}`);
|
|
13041
13072
|
return { ok: false, status: 400, message: "Invalid or unknown authorization state.", stateValid: false };
|
|
13042
13073
|
}
|
|
@@ -13063,7 +13094,7 @@ async function completeConsent(args) {
|
|
|
13063
13094
|
if (!code || !realmId) {
|
|
13064
13095
|
return { ok: false, status: 400, message: "Missing code or realmId in the callback.", stateValid: true };
|
|
13065
13096
|
}
|
|
13066
|
-
if (!
|
|
13097
|
+
if (!existsSync18(storePath(accountDir))) {
|
|
13067
13098
|
return { ok: false, status: 500, message: "No QuickBooks credentials are stored for this account.", stateValid: true };
|
|
13068
13099
|
}
|
|
13069
13100
|
const store2 = JSON.parse(readFileSync26(storePath(accountDir), "utf-8"));
|
|
@@ -13098,7 +13129,7 @@ async function completeConsent(args) {
|
|
|
13098
13129
|
refreshTokenExpiry: now + (body.x_refresh_token_expires_in ?? 864e4) * 1e3,
|
|
13099
13130
|
lastRefresh: now
|
|
13100
13131
|
};
|
|
13101
|
-
mkdirSync5(
|
|
13132
|
+
mkdirSync5(join26(accountDir, "secrets"), { recursive: true });
|
|
13102
13133
|
writeFileSync9(storePath(accountDir), JSON.stringify(store2, null, 2), { mode: 384 });
|
|
13103
13134
|
const persisted = JSON.parse(readFileSync26(storePath(accountDir), "utf-8")).connections?.[realmId]?.refreshToken === body.refresh_token;
|
|
13104
13135
|
console.error(`${TAG28} op=token-exchange realmId=${realmId} persisted=${persisted}`);
|
|
@@ -13131,7 +13162,7 @@ var quickbooks_default = app9;
|
|
|
13131
13162
|
|
|
13132
13163
|
// server/routes/onboarding.ts
|
|
13133
13164
|
import { spawn, spawnSync as spawnSync2, execFileSync as execFileSync3 } from "child_process";
|
|
13134
|
-
import { openSync as openSync3, closeSync as closeSync3, writeFileSync as writeFileSync11, writeSync, existsSync as
|
|
13165
|
+
import { openSync as openSync3, closeSync as closeSync3, writeFileSync as writeFileSync11, writeSync, existsSync as existsSync20, readFileSync as readFileSync28, unlinkSync as unlinkSync3, renameSync as renameSync7 } from "fs";
|
|
13135
13166
|
import { createHash as createHash4, randomUUID as randomUUID8 } from "crypto";
|
|
13136
13167
|
|
|
13137
13168
|
// app/lib/claude-spawn-env.ts
|
|
@@ -13140,7 +13171,7 @@ function claudeBin() {
|
|
|
13140
13171
|
}
|
|
13141
13172
|
|
|
13142
13173
|
// server/routes/onboarding.ts
|
|
13143
|
-
import { dirname as dirname9, join as
|
|
13174
|
+
import { dirname as dirname9, join as join28 } from "path";
|
|
13144
13175
|
|
|
13145
13176
|
// app/lib/claude-keychain.ts
|
|
13146
13177
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
@@ -13269,8 +13300,8 @@ function readHostCredsBlob(service) {
|
|
|
13269
13300
|
}
|
|
13270
13301
|
|
|
13271
13302
|
// ../lib/admins-write/src/index.ts
|
|
13272
|
-
import { existsSync as
|
|
13273
|
-
import { dirname as dirname8, join as
|
|
13303
|
+
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";
|
|
13304
|
+
import { dirname as dirname8, join as join27 } from "path";
|
|
13274
13305
|
function id8(value) {
|
|
13275
13306
|
return value.slice(0, 8);
|
|
13276
13307
|
}
|
|
@@ -13311,7 +13342,7 @@ function writeAdminEntry(input) {
|
|
|
13311
13342
|
const result = { usersJsonResult: "noop", accountJsonResult: "noop" };
|
|
13312
13343
|
try {
|
|
13313
13344
|
let users = [];
|
|
13314
|
-
if (
|
|
13345
|
+
if (existsSync19(input.usersFile)) {
|
|
13315
13346
|
const raw = readFileSync27(input.usersFile, "utf-8").trim();
|
|
13316
13347
|
if (raw) {
|
|
13317
13348
|
const parsed = JSON.parse(raw);
|
|
@@ -13343,8 +13374,8 @@ function writeAdminEntry(input) {
|
|
|
13343
13374
|
return result;
|
|
13344
13375
|
}
|
|
13345
13376
|
try {
|
|
13346
|
-
const accountJsonPath =
|
|
13347
|
-
if (!
|
|
13377
|
+
const accountJsonPath = join27(input.accountDir, "account.json");
|
|
13378
|
+
if (!existsSync19(accountJsonPath)) {
|
|
13348
13379
|
throw new Error(`account.json not found at ${accountJsonPath}`);
|
|
13349
13380
|
}
|
|
13350
13381
|
const config = JSON.parse(readFileSync27(accountJsonPath, "utf-8"));
|
|
@@ -13367,7 +13398,7 @@ function writeAdminEntry(input) {
|
|
|
13367
13398
|
function computeAdminStoreDivergence(input) {
|
|
13368
13399
|
const result = { divergences: 0, accountWithoutUsers: [], usersWithoutAccount: [], errors: [] };
|
|
13369
13400
|
const usersUserIds = /* @__PURE__ */ new Set();
|
|
13370
|
-
if (
|
|
13401
|
+
if (existsSync19(input.usersFile)) {
|
|
13371
13402
|
try {
|
|
13372
13403
|
const raw = readFileSync27(input.usersFile, "utf-8").trim();
|
|
13373
13404
|
if (raw) {
|
|
@@ -13381,24 +13412,24 @@ function computeAdminStoreDivergence(input) {
|
|
|
13381
13412
|
}
|
|
13382
13413
|
}
|
|
13383
13414
|
const accountUserIds = /* @__PURE__ */ new Set();
|
|
13384
|
-
if (
|
|
13415
|
+
if (existsSync19(input.accountsDir)) {
|
|
13385
13416
|
let entries;
|
|
13386
13417
|
try {
|
|
13387
|
-
entries =
|
|
13418
|
+
entries = readdirSync19(input.accountsDir);
|
|
13388
13419
|
} catch (err) {
|
|
13389
13420
|
result.errors.push({ source: input.accountsDir, detail: err instanceof Error ? err.message : String(err) });
|
|
13390
13421
|
return result;
|
|
13391
13422
|
}
|
|
13392
13423
|
for (const entry of entries) {
|
|
13393
13424
|
if (entry.startsWith(".")) continue;
|
|
13394
|
-
const accountDir =
|
|
13425
|
+
const accountDir = join27(input.accountsDir, entry);
|
|
13395
13426
|
try {
|
|
13396
|
-
if (!
|
|
13427
|
+
if (!statSync10(accountDir).isDirectory()) continue;
|
|
13397
13428
|
} catch {
|
|
13398
13429
|
continue;
|
|
13399
13430
|
}
|
|
13400
|
-
const accountJsonPath =
|
|
13401
|
-
if (!
|
|
13431
|
+
const accountJsonPath = join27(accountDir, "account.json");
|
|
13432
|
+
if (!existsSync19(accountJsonPath)) continue;
|
|
13402
13433
|
let admins = [];
|
|
13403
13434
|
try {
|
|
13404
13435
|
const config = JSON.parse(readFileSync27(accountJsonPath, "utf-8"));
|
|
@@ -13449,7 +13480,7 @@ function hashPin2(pin) {
|
|
|
13449
13480
|
return createHash4("sha256").update(pin).digest("hex");
|
|
13450
13481
|
}
|
|
13451
13482
|
function readUsersFile2() {
|
|
13452
|
-
if (!
|
|
13483
|
+
if (!existsSync20(USERS_FILE)) return null;
|
|
13453
13484
|
const raw = readFileSync28(USERS_FILE, "utf-8").trim();
|
|
13454
13485
|
if (!raw) return [];
|
|
13455
13486
|
return JSON.parse(raw);
|
|
@@ -13509,7 +13540,7 @@ app10.post("/claude-auth", async (c) => {
|
|
|
13509
13540
|
} catch (err) {
|
|
13510
13541
|
logoutError = err instanceof Error ? err.message : String(err);
|
|
13511
13542
|
}
|
|
13512
|
-
const credentialsPresent =
|
|
13543
|
+
const credentialsPresent = existsSync20(CLAUDE_CREDENTIALS_FILE);
|
|
13513
13544
|
const ranMs = Date.now() - start;
|
|
13514
13545
|
console.log(`[onboarding] op=claude-logout credentialsPresent=${credentialsPresent} ranMs=${ranMs} logoutError=${logoutError ? JSON.stringify(logoutError.slice(0, 120)) : "none"}`);
|
|
13515
13546
|
return c.json({ logged_out: !credentialsPresent });
|
|
@@ -13575,7 +13606,7 @@ app10.post("/claude-auth", async (c) => {
|
|
|
13575
13606
|
});
|
|
13576
13607
|
persistKeychainService(
|
|
13577
13608
|
writebackResult,
|
|
13578
|
-
(service) => writeFileSync11(
|
|
13609
|
+
(service) => writeFileSync11(join28(dirname9(CLAUDE_CREDENTIALS_FILE), ".keychain-service"), service, { mode: 384 }),
|
|
13579
13610
|
(line) => console.log(line)
|
|
13580
13611
|
);
|
|
13581
13612
|
if (darwinAuthChild === claudeProc2) darwinAuthChild = null;
|
|
@@ -13658,7 +13689,7 @@ app10.post("/set-pin", async (c) => {
|
|
|
13658
13689
|
console.log(`[set-pin] wrote users.json + account.json admins: userId=${userId.slice(0, 8)}\u2026 role=owner`);
|
|
13659
13690
|
if (process.platform === "linux") {
|
|
13660
13691
|
let installOwner = null;
|
|
13661
|
-
if (
|
|
13692
|
+
if (existsSync20(INSTALL_OWNER_FILE)) {
|
|
13662
13693
|
try {
|
|
13663
13694
|
const raw = readFileSync28(INSTALL_OWNER_FILE, "utf-8").trim();
|
|
13664
13695
|
if (raw.length > 0) installOwner = raw;
|
|
@@ -13806,7 +13837,7 @@ app10.put("/set-pin", requireAdminSession, async (c) => {
|
|
|
13806
13837
|
console.log(`[set-pin] changed PIN in place: userId=${sessionUserId.slice(0, 8)}\u2026`);
|
|
13807
13838
|
if (process.platform === "linux") {
|
|
13808
13839
|
let installOwner = null;
|
|
13809
|
-
if (
|
|
13840
|
+
if (existsSync20(INSTALL_OWNER_FILE)) {
|
|
13810
13841
|
try {
|
|
13811
13842
|
const raw = readFileSync28(INSTALL_OWNER_FILE, "utf-8").trim();
|
|
13812
13843
|
if (raw.length > 0) installOwner = raw;
|
|
@@ -13840,9 +13871,9 @@ ${body.newPin}
|
|
|
13840
13871
|
var onboarding_default = app10;
|
|
13841
13872
|
|
|
13842
13873
|
// server/routes/client-error.ts
|
|
13843
|
-
import { appendFileSync as appendFileSync4, existsSync as
|
|
13844
|
-
import { join as
|
|
13845
|
-
var CLIENT_ERRORS_LOG =
|
|
13874
|
+
import { appendFileSync as appendFileSync4, existsSync as existsSync21, renameSync as renameSync8, statSync as statSync11 } from "fs";
|
|
13875
|
+
import { join as join29 } from "path";
|
|
13876
|
+
var CLIENT_ERRORS_LOG = join29(LOG_DIR, "client-errors.log");
|
|
13846
13877
|
var MAX_LOG_SIZE = 10 * 1024 * 1024;
|
|
13847
13878
|
var MAX_BODY_SIZE = 8 * 1024;
|
|
13848
13879
|
var MAX_STACK_LEN = 2e3;
|
|
@@ -13890,8 +13921,8 @@ function stackHead(stack) {
|
|
|
13890
13921
|
}
|
|
13891
13922
|
function rotateIfNeeded() {
|
|
13892
13923
|
try {
|
|
13893
|
-
if (!
|
|
13894
|
-
const stats =
|
|
13924
|
+
if (!existsSync21(CLIENT_ERRORS_LOG)) return;
|
|
13925
|
+
const stats = statSync11(CLIENT_ERRORS_LOG);
|
|
13895
13926
|
if (stats.size < MAX_LOG_SIZE) return;
|
|
13896
13927
|
renameSync8(CLIENT_ERRORS_LOG, CLIENT_ERRORS_LOG + ".1");
|
|
13897
13928
|
} catch (err) {
|
|
@@ -14217,18 +14248,18 @@ app13.get("/", requireAdminSession, async (c) => {
|
|
|
14217
14248
|
var accounts_default = app13;
|
|
14218
14249
|
|
|
14219
14250
|
// server/routes/admin/logs.ts
|
|
14220
|
-
import { existsSync as
|
|
14251
|
+
import { existsSync as existsSync23, readdirSync as readdirSync20, readFileSync as readFileSync29, statSync as statSync12 } from "fs";
|
|
14221
14252
|
import { resolve as resolve17, basename as basename7 } from "path";
|
|
14222
14253
|
|
|
14223
14254
|
// app/lib/logs-read-resolve.ts
|
|
14224
|
-
import { existsSync as
|
|
14225
|
-
import { join as
|
|
14255
|
+
import { existsSync as existsSync22 } from "fs";
|
|
14256
|
+
import { join as join30 } from "path";
|
|
14226
14257
|
function resolveSessionLogPaths(filename, logDirs) {
|
|
14227
14258
|
const tried = [filename];
|
|
14228
14259
|
const hits = [];
|
|
14229
14260
|
for (const dir of logDirs) {
|
|
14230
|
-
const fullPath =
|
|
14231
|
-
if (
|
|
14261
|
+
const fullPath = join30(dir, filename);
|
|
14262
|
+
if (existsSync22(fullPath)) {
|
|
14232
14263
|
hits.push({ path: fullPath, dir });
|
|
14233
14264
|
}
|
|
14234
14265
|
}
|
|
@@ -14257,7 +14288,7 @@ app14.get("/", async (c) => {
|
|
|
14257
14288
|
searched.push(filePath);
|
|
14258
14289
|
try {
|
|
14259
14290
|
const buffer = readFileSync29(filePath);
|
|
14260
|
-
const onDiskBytes =
|
|
14291
|
+
const onDiskBytes = statSync12(filePath).size;
|
|
14261
14292
|
const headers = {
|
|
14262
14293
|
"Content-Type": "text/plain; charset=utf-8",
|
|
14263
14294
|
"Content-Length": String(buffer.byteLength)
|
|
@@ -14322,7 +14353,7 @@ app14.get("/", async (c) => {
|
|
|
14322
14353
|
try {
|
|
14323
14354
|
const filename = basename7(hit.path);
|
|
14324
14355
|
const buffer = readFileSync29(hit.path);
|
|
14325
|
-
const onDiskBytes =
|
|
14356
|
+
const onDiskBytes = statSync12(hit.path).size;
|
|
14326
14357
|
const headers = {
|
|
14327
14358
|
"Content-Type": "text/plain; charset=utf-8",
|
|
14328
14359
|
"Content-Length": String(buffer.byteLength)
|
|
@@ -14356,16 +14387,16 @@ app14.get("/", async (c) => {
|
|
|
14356
14387
|
const seen = /* @__PURE__ */ new Set();
|
|
14357
14388
|
const logs = {};
|
|
14358
14389
|
for (const dir of logDirs) {
|
|
14359
|
-
if (!
|
|
14390
|
+
if (!existsSync23(dir)) continue;
|
|
14360
14391
|
let files;
|
|
14361
14392
|
try {
|
|
14362
|
-
files =
|
|
14393
|
+
files = readdirSync20(dir).filter((f) => f.endsWith(".log"));
|
|
14363
14394
|
} catch (err) {
|
|
14364
14395
|
const reason = err instanceof Error ? err.message : String(err);
|
|
14365
14396
|
console.warn(`[admin/logs] readdir-fail dir=${dir} reason=${reason}`);
|
|
14366
14397
|
continue;
|
|
14367
14398
|
}
|
|
14368
|
-
files.filter((f) => !seen.has(f)).map((f) => ({ name: f, mtime:
|
|
14399
|
+
files.filter((f) => !seen.has(f)).map((f) => ({ name: f, mtime: statSync12(resolve17(dir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime).forEach(({ name }) => {
|
|
14369
14400
|
seen.add(name);
|
|
14370
14401
|
try {
|
|
14371
14402
|
const content = readFileSync29(resolve17(dir, name));
|
|
@@ -14408,7 +14439,7 @@ var claude_info_default = app15;
|
|
|
14408
14439
|
|
|
14409
14440
|
// server/routes/admin/attachment.ts
|
|
14410
14441
|
import { readFile as readFile2, readdir } from "fs/promises";
|
|
14411
|
-
import { existsSync as
|
|
14442
|
+
import { existsSync as existsSync24 } from "fs";
|
|
14412
14443
|
import { resolve as resolve18 } from "path";
|
|
14413
14444
|
var app16 = new Hono();
|
|
14414
14445
|
var ATTACHMENT_ID_RE3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
|
|
@@ -14431,12 +14462,12 @@ app16.get("/:attachmentId", requireAdminSession, async (c) => {
|
|
|
14431
14462
|
}
|
|
14432
14463
|
let accountId = pinnedAccountId;
|
|
14433
14464
|
let dir = uploadsDirFor2(accountId, attachmentId);
|
|
14434
|
-
let found =
|
|
14465
|
+
let found = existsSync24(dir);
|
|
14435
14466
|
if (!found) {
|
|
14436
14467
|
for (const candidate of listValidAccounts()) {
|
|
14437
14468
|
if (candidate.accountId === pinnedAccountId) continue;
|
|
14438
14469
|
const candidateDir = uploadsDirFor2(candidate.accountId, attachmentId);
|
|
14439
|
-
if (
|
|
14470
|
+
if (existsSync24(candidateDir)) {
|
|
14440
14471
|
accountId = candidate.accountId;
|
|
14441
14472
|
dir = candidateDir;
|
|
14442
14473
|
found = true;
|
|
@@ -14451,7 +14482,7 @@ app16.get("/:attachmentId", requireAdminSession, async (c) => {
|
|
|
14451
14482
|
return new Response("Not found", { status: 404 });
|
|
14452
14483
|
}
|
|
14453
14484
|
const metaPath = resolve18(dir, `${attachmentId}.meta.json`);
|
|
14454
|
-
if (!
|
|
14485
|
+
if (!existsSync24(metaPath)) {
|
|
14455
14486
|
return new Response("Not found", { status: 404 });
|
|
14456
14487
|
}
|
|
14457
14488
|
let meta;
|
|
@@ -14485,21 +14516,21 @@ var attachment_default = app16;
|
|
|
14485
14516
|
|
|
14486
14517
|
// server/routes/admin/agents.ts
|
|
14487
14518
|
import { resolve as resolve19 } from "path";
|
|
14488
|
-
import { readdirSync as
|
|
14519
|
+
import { readdirSync as readdirSync21, readFileSync as readFileSync30, existsSync as existsSync25, rmSync as rmSync2 } from "fs";
|
|
14489
14520
|
var app17 = new Hono();
|
|
14490
14521
|
app17.get("/", (c) => {
|
|
14491
14522
|
const account = resolveAccount();
|
|
14492
14523
|
if (!account) return c.json({ agents: [] });
|
|
14493
14524
|
const agentsDir = resolve19(account.accountDir, "agents");
|
|
14494
|
-
if (!
|
|
14525
|
+
if (!existsSync25(agentsDir)) return c.json({ agents: [] });
|
|
14495
14526
|
const agents = [];
|
|
14496
14527
|
try {
|
|
14497
|
-
const entries =
|
|
14528
|
+
const entries = readdirSync21(agentsDir, { withFileTypes: true });
|
|
14498
14529
|
for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
14499
14530
|
if (!entry.isDirectory()) continue;
|
|
14500
14531
|
if (entry.name === "admin") continue;
|
|
14501
14532
|
const configPath2 = resolve19(agentsDir, entry.name, "config.json");
|
|
14502
|
-
if (!
|
|
14533
|
+
if (!existsSync25(configPath2)) continue;
|
|
14503
14534
|
try {
|
|
14504
14535
|
const config = JSON.parse(readFileSync30(configPath2, "utf-8"));
|
|
14505
14536
|
agents.push({
|
|
@@ -14528,7 +14559,7 @@ app17.delete("/:slug", async (c) => {
|
|
|
14528
14559
|
return c.json({ error: "Invalid agent slug" }, 400);
|
|
14529
14560
|
}
|
|
14530
14561
|
const agentDir = resolve19(account.accountDir, "agents", slug);
|
|
14531
|
-
if (!
|
|
14562
|
+
if (!existsSync25(agentDir)) {
|
|
14532
14563
|
return c.json({ error: "Agent not found" }, 404);
|
|
14533
14564
|
}
|
|
14534
14565
|
try {
|
|
@@ -14558,7 +14589,7 @@ app17.post("/:slug/project", async (c) => {
|
|
|
14558
14589
|
return c.json({ error: "Invalid agent slug" }, 400);
|
|
14559
14590
|
}
|
|
14560
14591
|
const agentDir = resolve19(account.accountDir, "agents", slug);
|
|
14561
|
-
if (!
|
|
14592
|
+
if (!existsSync25(agentDir)) {
|
|
14562
14593
|
return c.json({ error: "Agent not found on disk" }, 404);
|
|
14563
14594
|
}
|
|
14564
14595
|
try {
|
|
@@ -14574,7 +14605,7 @@ var agents_default = app17;
|
|
|
14574
14605
|
// server/routes/admin/sessions.ts
|
|
14575
14606
|
import crypto2 from "crypto";
|
|
14576
14607
|
import { resolve as resolvePath } from "path";
|
|
14577
|
-
import { existsSync as
|
|
14608
|
+
import { existsSync as existsSync26, mkdirSync as mkdirSync7, createWriteStream } from "fs";
|
|
14578
14609
|
|
|
14579
14610
|
// ../lib/admin-conversation-purge/src/index.ts
|
|
14580
14611
|
async function purgeAdminConversationJsonls(args) {
|
|
@@ -14734,7 +14765,7 @@ function validateAndShapeAttachments(raws, conversationAccountId, sessionId, mes
|
|
|
14734
14765
|
let reason = null;
|
|
14735
14766
|
if (!a.attachmentId || !a.filename || !a.mimeType || !a.storagePath) reason = "schema-fail";
|
|
14736
14767
|
else if (a.accountId !== conversationAccountId) reason = "account-mismatch";
|
|
14737
|
-
else if (!
|
|
14768
|
+
else if (!existsSync26(a.storagePath)) reason = "missing-file";
|
|
14738
14769
|
if (reason) {
|
|
14739
14770
|
invalid++;
|
|
14740
14771
|
try {
|
|
@@ -15260,8 +15291,8 @@ app18.put("/:id/label", requireAdminSession, async (c) => {
|
|
|
15260
15291
|
var sessions_default = app18;
|
|
15261
15292
|
|
|
15262
15293
|
// app/lib/claude-agent/spawn-context.ts
|
|
15263
|
-
import { existsSync as
|
|
15264
|
-
import { dirname as dirname10, resolve as resolve20, join as
|
|
15294
|
+
import { existsSync as existsSync27, readFileSync as readFileSync31, readdirSync as readdirSync22, statSync as statSync13 } from "fs";
|
|
15295
|
+
import { dirname as dirname10, resolve as resolve20, join as join31 } from "path";
|
|
15265
15296
|
async function resolveOwnerProfileBlock(accountId, userId) {
|
|
15266
15297
|
if (!userId) return { ok: false, reason: "missing-user-id" };
|
|
15267
15298
|
try {
|
|
@@ -15302,12 +15333,12 @@ function frontmatterField(manifest, field2) {
|
|
|
15302
15333
|
function extractPluginToolDescriptions(pluginDir) {
|
|
15303
15334
|
const out = /* @__PURE__ */ new Map();
|
|
15304
15335
|
const candidates = [
|
|
15305
|
-
|
|
15306
|
-
|
|
15336
|
+
join31(pluginDir, "mcp/dist/index.js"),
|
|
15337
|
+
join31(pluginDir, "mcp/src/index.ts")
|
|
15307
15338
|
];
|
|
15308
15339
|
let raw = null;
|
|
15309
15340
|
for (const path3 of candidates) {
|
|
15310
|
-
if (!
|
|
15341
|
+
if (!existsSync27(path3)) continue;
|
|
15311
15342
|
try {
|
|
15312
15343
|
raw = readFileSync31(path3, "utf-8");
|
|
15313
15344
|
break;
|
|
@@ -15359,25 +15390,25 @@ function parseSkillPathsFromFrontmatter(fm) {
|
|
|
15359
15390
|
function listPluginDirs() {
|
|
15360
15391
|
const out = /* @__PURE__ */ new Map();
|
|
15361
15392
|
const platformPlugins = resolve20(PLATFORM_ROOT, "plugins");
|
|
15362
|
-
if (
|
|
15363
|
-
for (const name of
|
|
15364
|
-
const dir =
|
|
15393
|
+
if (existsSync27(platformPlugins)) {
|
|
15394
|
+
for (const name of readdirSync22(platformPlugins)) {
|
|
15395
|
+
const dir = join31(platformPlugins, name);
|
|
15365
15396
|
try {
|
|
15366
|
-
if (
|
|
15397
|
+
if (statSync13(dir).isDirectory()) out.set(name, dir);
|
|
15367
15398
|
} catch {
|
|
15368
15399
|
}
|
|
15369
15400
|
}
|
|
15370
15401
|
}
|
|
15371
15402
|
const premiumRoot = resolve20(dirname10(PLATFORM_ROOT), "premium-plugins");
|
|
15372
|
-
if (
|
|
15373
|
-
for (const bundle of
|
|
15374
|
-
const bundlePlugins =
|
|
15375
|
-
if (!
|
|
15403
|
+
if (existsSync27(premiumRoot)) {
|
|
15404
|
+
for (const bundle of readdirSync22(premiumRoot)) {
|
|
15405
|
+
const bundlePlugins = join31(premiumRoot, bundle, "plugins");
|
|
15406
|
+
if (!existsSync27(bundlePlugins)) continue;
|
|
15376
15407
|
try {
|
|
15377
|
-
for (const name of
|
|
15378
|
-
const dir =
|
|
15408
|
+
for (const name of readdirSync22(bundlePlugins)) {
|
|
15409
|
+
const dir = join31(bundlePlugins, name);
|
|
15379
15410
|
try {
|
|
15380
|
-
if (
|
|
15411
|
+
if (statSync13(dir).isDirectory()) out.set(name, dir);
|
|
15381
15412
|
} catch {
|
|
15382
15413
|
}
|
|
15383
15414
|
}
|
|
@@ -15389,7 +15420,7 @@ function listPluginDirs() {
|
|
|
15389
15420
|
}
|
|
15390
15421
|
function readEnabledPlugins(accountId) {
|
|
15391
15422
|
const accountFile = resolve20(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
|
|
15392
|
-
if (!
|
|
15423
|
+
if (!existsSync27(accountFile)) return /* @__PURE__ */ new Set();
|
|
15393
15424
|
try {
|
|
15394
15425
|
const parsed = JSON.parse(readFileSync31(accountFile, "utf-8"));
|
|
15395
15426
|
return new Set(
|
|
@@ -15400,7 +15431,7 @@ function readEnabledPlugins(accountId) {
|
|
|
15400
15431
|
}
|
|
15401
15432
|
}
|
|
15402
15433
|
function readFrontmatter(path3) {
|
|
15403
|
-
if (!
|
|
15434
|
+
if (!existsSync27(path3)) return null;
|
|
15404
15435
|
let raw;
|
|
15405
15436
|
try {
|
|
15406
15437
|
raw = readFileSync31(path3, "utf-8");
|
|
@@ -15418,7 +15449,7 @@ function computeActivePlugins(accountId) {
|
|
|
15418
15449
|
for (const name of Array.from(enabled).sort()) {
|
|
15419
15450
|
const dir = pluginDirs.get(name);
|
|
15420
15451
|
if (!dir) continue;
|
|
15421
|
-
const fm = readFrontmatter(
|
|
15452
|
+
const fm = readFrontmatter(join31(dir, "PLUGIN.md"));
|
|
15422
15453
|
if (!fm) continue;
|
|
15423
15454
|
const description = frontmatterField(`---
|
|
15424
15455
|
${fm}
|
|
@@ -15435,7 +15466,7 @@ ${fm}
|
|
|
15435
15466
|
`plugin-manifest-tool-coverage plugin=${name} tools=${tools.length} with-desc=${withDesc}`
|
|
15436
15467
|
);
|
|
15437
15468
|
if (toolNames.length > 0 && descMap.size === 0) {
|
|
15438
|
-
const hasSource =
|
|
15469
|
+
const hasSource = existsSync27(join31(dir, "mcp/dist/index.js")) || existsSync27(join31(dir, "mcp/src/index.ts"));
|
|
15439
15470
|
if (hasSource) {
|
|
15440
15471
|
console.warn(
|
|
15441
15472
|
`[spawn-context] WARN plugin=${name} mcp source present but tool-description regex matched zero entries \u2014 SDK upgrade may have changed the registration shape`
|
|
@@ -15445,7 +15476,7 @@ ${fm}
|
|
|
15445
15476
|
const skillPaths = parseSkillPathsFromFrontmatter(fm);
|
|
15446
15477
|
const skills = [];
|
|
15447
15478
|
for (const relPath of skillPaths) {
|
|
15448
|
-
const skillPath =
|
|
15479
|
+
const skillPath = join31(dir, relPath);
|
|
15449
15480
|
const skillFm = readFrontmatter(skillPath);
|
|
15450
15481
|
if (!skillFm) continue;
|
|
15451
15482
|
const skillName = frontmatterField(`---
|
|
@@ -15462,10 +15493,10 @@ ${skillFm}
|
|
|
15462
15493
|
}
|
|
15463
15494
|
function computeSpecialistDomains(accountId) {
|
|
15464
15495
|
const specialistsDir = resolve20(PLATFORM_ROOT, "..", "data/accounts", accountId, "specialists", "agents");
|
|
15465
|
-
if (!
|
|
15496
|
+
if (!existsSync27(specialistsDir)) return [];
|
|
15466
15497
|
let entries;
|
|
15467
15498
|
try {
|
|
15468
|
-
entries =
|
|
15499
|
+
entries = readdirSync22(specialistsDir);
|
|
15469
15500
|
} catch {
|
|
15470
15501
|
return [];
|
|
15471
15502
|
}
|
|
@@ -15489,7 +15520,7 @@ function computeSpecialistDomains(accountId) {
|
|
|
15489
15520
|
const out = [];
|
|
15490
15521
|
for (const file of entries.sort()) {
|
|
15491
15522
|
if (!file.endsWith(".md")) continue;
|
|
15492
|
-
const fm = readFrontmatter(
|
|
15523
|
+
const fm = readFrontmatter(join31(specialistsDir, file));
|
|
15493
15524
|
if (!fm) continue;
|
|
15494
15525
|
const wrapped = `---
|
|
15495
15526
|
${fm}
|
|
@@ -15508,7 +15539,7 @@ ${fm}
|
|
|
15508
15539
|
}
|
|
15509
15540
|
function computeDormantPlugins(accountId) {
|
|
15510
15541
|
const accountFile = resolve20(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
|
|
15511
|
-
if (!
|
|
15542
|
+
if (!existsSync27(accountFile)) return [];
|
|
15512
15543
|
let enabled;
|
|
15513
15544
|
try {
|
|
15514
15545
|
const raw = readFileSync31(accountFile, "utf-8");
|
|
@@ -15523,10 +15554,10 @@ function computeDormantPlugins(accountId) {
|
|
|
15523
15554
|
return [];
|
|
15524
15555
|
}
|
|
15525
15556
|
const pluginsDir = resolve20(PLATFORM_ROOT, "plugins");
|
|
15526
|
-
if (!
|
|
15557
|
+
if (!existsSync27(pluginsDir)) return [];
|
|
15527
15558
|
let entries;
|
|
15528
15559
|
try {
|
|
15529
|
-
entries =
|
|
15560
|
+
entries = readdirSync22(pluginsDir);
|
|
15530
15561
|
} catch {
|
|
15531
15562
|
return [];
|
|
15532
15563
|
}
|
|
@@ -15534,7 +15565,7 @@ function computeDormantPlugins(accountId) {
|
|
|
15534
15565
|
for (const name of entries) {
|
|
15535
15566
|
if (enabled.has(name)) continue;
|
|
15536
15567
|
const manifestPath = resolve20(pluginsDir, name, "PLUGIN.md");
|
|
15537
|
-
if (!
|
|
15568
|
+
if (!existsSync27(manifestPath)) continue;
|
|
15538
15569
|
let manifest;
|
|
15539
15570
|
try {
|
|
15540
15571
|
manifest = readFileSync31(manifestPath, "utf-8");
|
|
@@ -15551,11 +15582,11 @@ function computeDormantPlugins(accountId) {
|
|
|
15551
15582
|
}
|
|
15552
15583
|
|
|
15553
15584
|
// server/routes/admin/claude-sessions.ts
|
|
15554
|
-
import { existsSync as
|
|
15585
|
+
import { existsSync as existsSync28, readFileSync as readFileSync32 } from "fs";
|
|
15555
15586
|
import { resolve as resolve21 } from "path";
|
|
15556
15587
|
function readTunnelState(brandConfigDir) {
|
|
15557
15588
|
const statePath = `${process.env.HOME ?? ""}/${brandConfigDir}/cloudflared/tunnel.state`;
|
|
15558
|
-
if (!
|
|
15589
|
+
if (!existsSync28(statePath)) return null;
|
|
15559
15590
|
try {
|
|
15560
15591
|
const parsed = JSON.parse(readFileSync32(statePath, "utf-8"));
|
|
15561
15592
|
const tunnelId = typeof parsed.tunnelId === "string" ? parsed.tunnelId : null;
|
|
@@ -15813,11 +15844,11 @@ app21.post("/", async (c) => {
|
|
|
15813
15844
|
var events_default = app21;
|
|
15814
15845
|
|
|
15815
15846
|
// server/routes/admin/files.ts
|
|
15816
|
-
import { createReadStream as createReadStream2, createWriteStream as createWriteStream2, existsSync as
|
|
15847
|
+
import { createReadStream as createReadStream2, createWriteStream as createWriteStream2, existsSync as existsSync29 } from "fs";
|
|
15817
15848
|
import { readdir as readdir3, readFile as readFile4, stat as stat4, mkdir as mkdir3, unlink as unlink2, rename, rmdir } from "fs/promises";
|
|
15818
15849
|
import { realpathSync as realpathSync6 } from "fs";
|
|
15819
15850
|
import { randomUUID as randomUUID10 } from "crypto";
|
|
15820
|
-
import { basename as basename9, dirname as dirname11, join as
|
|
15851
|
+
import { basename as basename9, dirname as dirname11, join as join33, relative as relative4, resolve as resolve23, sep as sep6 } from "path";
|
|
15821
15852
|
import { Readable as Readable2 } from "stream";
|
|
15822
15853
|
|
|
15823
15854
|
// ../lib/graph-trash/src/index.ts
|
|
@@ -16054,7 +16085,7 @@ async function restoreNode(params) {
|
|
|
16054
16085
|
}
|
|
16055
16086
|
|
|
16056
16087
|
// app/lib/file-delete-cascade.ts
|
|
16057
|
-
var
|
|
16088
|
+
var UUID_RE3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
16058
16089
|
function parseAttachmentPath(relPath) {
|
|
16059
16090
|
const segments = relPath.split("/").filter(Boolean);
|
|
16060
16091
|
if (segments.length !== 5) return null;
|
|
@@ -16062,7 +16093,7 @@ function parseAttachmentPath(relPath) {
|
|
|
16062
16093
|
const accountId = segments[1];
|
|
16063
16094
|
const attachmentId = segments[3];
|
|
16064
16095
|
const filename = segments[4];
|
|
16065
|
-
if (!
|
|
16096
|
+
if (!UUID_RE3.test(accountId) || !UUID_RE3.test(attachmentId)) return null;
|
|
16066
16097
|
const dot = filename.lastIndexOf(".");
|
|
16067
16098
|
if (dot === -1) return null;
|
|
16068
16099
|
const stem = filename.slice(0, dot);
|
|
@@ -16135,7 +16166,7 @@ async function cascadeDeleteDocument(params) {
|
|
|
16135
16166
|
|
|
16136
16167
|
// app/lib/file-index.ts
|
|
16137
16168
|
import * as fsp from "fs/promises";
|
|
16138
|
-
import { resolve as resolve22, relative as relative3, join as
|
|
16169
|
+
import { resolve as resolve22, relative as relative3, join as join32, basename as basename8, extname as extname2, sep as sep5 } from "path";
|
|
16139
16170
|
import { tmpdir as tmpdir2 } from "os";
|
|
16140
16171
|
import { execFile as execFile2 } from "child_process";
|
|
16141
16172
|
import { promisify as promisify2 } from "util";
|
|
@@ -16217,7 +16248,7 @@ async function extractPdf(absolute) {
|
|
|
16217
16248
|
return stdout.trim();
|
|
16218
16249
|
}
|
|
16219
16250
|
async function ocrPdf(absolute) {
|
|
16220
|
-
const outPdf =
|
|
16251
|
+
const outPdf = join32(tmpdir2(), `file-index-ocr-${process.pid}-${Date.now()}.pdf`);
|
|
16221
16252
|
try {
|
|
16222
16253
|
await execFileAsync2(
|
|
16223
16254
|
"ocrmypdf",
|
|
@@ -16279,7 +16310,7 @@ async function readDisplayName(absolute) {
|
|
|
16279
16310
|
const stem = dot === -1 ? base : base.slice(0, dot);
|
|
16280
16311
|
if (base === `${stem}.meta.json`) return null;
|
|
16281
16312
|
try {
|
|
16282
|
-
const raw = await fsp.readFile(
|
|
16313
|
+
const raw = await fsp.readFile(join32(dir, `${stem}.meta.json`), "utf-8");
|
|
16283
16314
|
const meta = JSON.parse(raw);
|
|
16284
16315
|
const dn = meta.displayName ?? meta.filename;
|
|
16285
16316
|
return typeof dn === "string" && dn.length > 0 ? dn : null;
|
|
@@ -16300,7 +16331,7 @@ async function walkSubtree(root, dataRoot, out) {
|
|
|
16300
16331
|
for (const entry of entries) {
|
|
16301
16332
|
if (entry.isSymbolicLink()) continue;
|
|
16302
16333
|
if (entry.isDirectory() && entry.name === ".uploads-tmp") continue;
|
|
16303
|
-
const abs =
|
|
16334
|
+
const abs = join32(root, entry.name);
|
|
16304
16335
|
if (entry.isDirectory()) {
|
|
16305
16336
|
const sub = await walkSubtree(abs, dataRoot, out);
|
|
16306
16337
|
if (!sub.clean) clean = false;
|
|
@@ -16653,10 +16684,10 @@ function buildZip(entries) {
|
|
|
16653
16684
|
|
|
16654
16685
|
// server/routes/admin/files.ts
|
|
16655
16686
|
var UPLOAD_TMP_DIR = ".uploads-tmp";
|
|
16656
|
-
var
|
|
16687
|
+
var UUID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
16657
16688
|
async function readMeta(absDir, baseName) {
|
|
16658
16689
|
try {
|
|
16659
|
-
const raw = await readFile4(
|
|
16690
|
+
const raw = await readFile4(join33(absDir, `${baseName}.meta.json`), "utf8");
|
|
16660
16691
|
const parsed = JSON.parse(raw);
|
|
16661
16692
|
if (typeof parsed?.filename === "string") {
|
|
16662
16693
|
return { filename: parsed.filename, mimeType: typeof parsed.mimeType === "string" ? parsed.mimeType : void 0 };
|
|
@@ -16675,7 +16706,7 @@ async function readAccountNames() {
|
|
|
16675
16706
|
return map;
|
|
16676
16707
|
}
|
|
16677
16708
|
for (const name of names) {
|
|
16678
|
-
if (!
|
|
16709
|
+
if (!UUID_RE4.test(name)) continue;
|
|
16679
16710
|
const configPath2 = resolve23(accountsDir, name, "account.json");
|
|
16680
16711
|
try {
|
|
16681
16712
|
const raw = await readFile4(configPath2, "utf8");
|
|
@@ -16710,8 +16741,8 @@ async function servableFilesIn(dirAbs, uuid) {
|
|
|
16710
16741
|
return out;
|
|
16711
16742
|
}
|
|
16712
16743
|
async function enrich(absolute, entry, accountNames) {
|
|
16713
|
-
if (entry.kind === "directory" &&
|
|
16714
|
-
const dirAbs =
|
|
16744
|
+
if (entry.kind === "directory" && UUID_RE4.test(entry.name)) {
|
|
16745
|
+
const dirAbs = join33(absolute, entry.name);
|
|
16715
16746
|
const meta = await readMeta(dirAbs, entry.name);
|
|
16716
16747
|
if (meta?.filename) {
|
|
16717
16748
|
const servable = await servableFilesIn(dirAbs, entry.name);
|
|
@@ -16720,7 +16751,7 @@ async function enrich(absolute, entry, accountNames) {
|
|
|
16720
16751
|
let size = null;
|
|
16721
16752
|
let modifiedAt = entry.modifiedAt;
|
|
16722
16753
|
try {
|
|
16723
|
-
const st = await stat4(
|
|
16754
|
+
const st = await stat4(join33(dirAbs, innerName));
|
|
16724
16755
|
size = st.size;
|
|
16725
16756
|
modifiedAt = st.mtime.toISOString();
|
|
16726
16757
|
} catch {
|
|
@@ -16745,7 +16776,7 @@ async function enrich(absolute, entry, accountNames) {
|
|
|
16745
16776
|
if (entry.kind === "file") {
|
|
16746
16777
|
const dot = entry.name.lastIndexOf(".");
|
|
16747
16778
|
const base = dot === -1 ? entry.name : entry.name.slice(0, dot);
|
|
16748
|
-
if (
|
|
16779
|
+
if (UUID_RE4.test(base)) {
|
|
16749
16780
|
const meta = await readMeta(absolute, base);
|
|
16750
16781
|
if (meta?.filename) {
|
|
16751
16782
|
entry.displayName = meta.filename;
|
|
@@ -16758,7 +16789,7 @@ async function enrich(absolute, entry, accountNames) {
|
|
|
16758
16789
|
function buildDisplayPath(relPath, accountNames) {
|
|
16759
16790
|
if (relPath === "." || relPath === "") return [];
|
|
16760
16791
|
return relPath.split("/").filter(Boolean).map((seg) => {
|
|
16761
|
-
const dn =
|
|
16792
|
+
const dn = UUID_RE4.test(seg) ? accountNames.get(seg) : void 0;
|
|
16762
16793
|
return dn ? { name: seg, displayName: dn } : { name: seg };
|
|
16763
16794
|
});
|
|
16764
16795
|
}
|
|
@@ -16808,11 +16839,11 @@ function isProtectedFromRename(relPath) {
|
|
|
16808
16839
|
if (segments.length === 3 && segments[0] === "accounts" && segments[2] === "uploads") {
|
|
16809
16840
|
return true;
|
|
16810
16841
|
}
|
|
16811
|
-
if (segments.length === 4 && segments[0] === "accounts" && segments[2] === "uploads" &&
|
|
16842
|
+
if (segments.length === 4 && segments[0] === "accounts" && segments[2] === "uploads" && UUID_RE4.test(segments[3])) {
|
|
16812
16843
|
return true;
|
|
16813
16844
|
}
|
|
16814
16845
|
if (parseAttachmentPath(relPath) !== null) return true;
|
|
16815
|
-
if (
|
|
16846
|
+
if (UUID_RE4.test(base.replace(/\.meta\.json$/, "")) && base.endsWith(".meta.json")) {
|
|
16816
16847
|
return true;
|
|
16817
16848
|
}
|
|
16818
16849
|
return false;
|
|
@@ -16886,16 +16917,16 @@ app22.get("/", requireAdminSession, async (c) => {
|
|
|
16886
16917
|
const isAccountParent = segs.length === 1 && segs[0] === "accounts";
|
|
16887
16918
|
const entries = [];
|
|
16888
16919
|
for (const name of names) {
|
|
16889
|
-
if (
|
|
16920
|
+
if (UUID_RE4.test(name.replace(/\.meta\.json$/, "")) && name.endsWith(".meta.json")) {
|
|
16890
16921
|
continue;
|
|
16891
16922
|
}
|
|
16892
|
-
if (isAccountParent &&
|
|
16923
|
+
if (isAccountParent && UUID_RE4.test(name) && name !== accountId) {
|
|
16893
16924
|
continue;
|
|
16894
16925
|
}
|
|
16895
16926
|
const childRel = relPath === "" || relPath === "." ? name : `${relPath}/${name}`;
|
|
16896
16927
|
const protectedEntry = isProtectedFromDeletion(childRel).protected;
|
|
16897
16928
|
try {
|
|
16898
|
-
const entryPath =
|
|
16929
|
+
const entryPath = join33(absolute, name);
|
|
16899
16930
|
const s = await stat4(entryPath);
|
|
16900
16931
|
entries.push({
|
|
16901
16932
|
name,
|
|
@@ -16958,7 +16989,7 @@ app22.get("/download", requireAdminSession, async (c) => {
|
|
|
16958
16989
|
console.error(`[data] op=scratchpad-no-session sessionId="${sessionId.slice(0, 8)}\u2026"`);
|
|
16959
16990
|
return c.json({ error: "Not found" }, 404);
|
|
16960
16991
|
}
|
|
16961
|
-
const meta = readSidecarMeta(
|
|
16992
|
+
const meta = readSidecarMeta(join33(projectDir, `${sessionId}.meta.json`));
|
|
16962
16993
|
if (!meta.accountId || meta.accountId !== accountId) {
|
|
16963
16994
|
console.error(`[data] account-scope-blocked root="scratchpad" sessionId="${sessionId.slice(0, 8)}\u2026" account=${accountId.slice(0, 8)}\u2026`);
|
|
16964
16995
|
return c.json({ error: "Not found" }, 404);
|
|
@@ -17053,7 +17084,7 @@ async function* walkRegularFiles(dirAbsolute) {
|
|
|
17053
17084
|
const dirents = await readdir3(dirAbsolute, { withFileTypes: true });
|
|
17054
17085
|
for (const d of dirents) {
|
|
17055
17086
|
if (d.isSymbolicLink()) continue;
|
|
17056
|
-
const child =
|
|
17087
|
+
const child = join33(dirAbsolute, d.name);
|
|
17057
17088
|
if (d.isDirectory()) {
|
|
17058
17089
|
yield* walkRegularFiles(child);
|
|
17059
17090
|
continue;
|
|
@@ -17163,7 +17194,7 @@ async function resolveUploadTarget(c, accountId, uid) {
|
|
|
17163
17194
|
const base = resolveOwnAccountWrite(rawDir, accountId, "POST /api/admin/files/upload");
|
|
17164
17195
|
if (!base.ok) return { ok: false, status: base.status, error: base.error };
|
|
17165
17196
|
const relDir = relpath ? dirname11(relpath) : ".";
|
|
17166
|
-
const destRel = relDir === "." ? base.relative :
|
|
17197
|
+
const destRel = relDir === "." ? base.relative : join33(base.relative, relDir);
|
|
17167
17198
|
if (crossesForeignAccountPartition(destRel, accountId)) {
|
|
17168
17199
|
console.error(`[data] account-scope-blocked endpoint="POST /api/admin/files/upload" path="${destRel}" account=${accountId.slice(0, 8)}\u2026`);
|
|
17169
17200
|
return { ok: false, status: 404, error: "Not found" };
|
|
@@ -17237,7 +17268,7 @@ app22.post("/upload", requireAdminSession, async (c) => {
|
|
|
17237
17268
|
});
|
|
17238
17269
|
await unlink2(tmpPath).catch(() => {
|
|
17239
17270
|
});
|
|
17240
|
-
const tempRemoved = !
|
|
17271
|
+
const tempRemoved = !existsSync29(tmpPath);
|
|
17241
17272
|
console.error(`[data-upload] op=cleanup uid=${uid} tempRemoved=${tempRemoved}`);
|
|
17242
17273
|
};
|
|
17243
17274
|
const reader = body.getReader();
|
|
@@ -17311,7 +17342,7 @@ async function discardChunkUpload(uploadId, state) {
|
|
|
17311
17342
|
});
|
|
17312
17343
|
await unlink2(state.tmpPath).catch(() => {
|
|
17313
17344
|
});
|
|
17314
|
-
const tempRemoved = !
|
|
17345
|
+
const tempRemoved = !existsSync29(state.tmpPath);
|
|
17315
17346
|
console.error(`[data-upload] op=cleanup uid=${uploadId} tempRemoved=${tempRemoved}`);
|
|
17316
17347
|
}
|
|
17317
17348
|
async function writeChunkBody(body, out, alreadyReceived, ceiling) {
|
|
@@ -17540,8 +17571,8 @@ app22.delete("/", requireAdminSession, async (c) => {
|
|
|
17540
17571
|
const dot = base.lastIndexOf(".");
|
|
17541
17572
|
const stem = dot === -1 ? base : base.slice(0, dot);
|
|
17542
17573
|
const containerDir = dirname11(absolute);
|
|
17543
|
-
const sidecarPath =
|
|
17544
|
-
const isAttachmentContainer =
|
|
17574
|
+
const sidecarPath = UUID_RE4.test(stem) && base !== `${stem}.meta.json` ? join33(containerDir, `${stem}.meta.json`) : null;
|
|
17575
|
+
const isAttachmentContainer = UUID_RE4.test(stem) && basename9(containerDir) === stem;
|
|
17545
17576
|
await unlink2(absolute);
|
|
17546
17577
|
if (sidecarPath) {
|
|
17547
17578
|
try {
|
|
@@ -17550,7 +17581,7 @@ app22.delete("/", requireAdminSession, async (c) => {
|
|
|
17550
17581
|
}
|
|
17551
17582
|
}
|
|
17552
17583
|
if (isAttachmentContainer) {
|
|
17553
|
-
await unlink2(
|
|
17584
|
+
await unlink2(join33(containerDir, `${stem}${EXTRACTED_TEXT_SUFFIX}`)).catch(() => {
|
|
17554
17585
|
});
|
|
17555
17586
|
await rmdir(containerDir).catch(() => {
|
|
17556
17587
|
});
|
|
@@ -18654,8 +18685,8 @@ function isHiddenByDefault(label) {
|
|
|
18654
18685
|
}
|
|
18655
18686
|
|
|
18656
18687
|
// server/lib/top-level-labels.ts
|
|
18657
|
-
import { readdirSync as
|
|
18658
|
-
import { join as
|
|
18688
|
+
import { readdirSync as readdirSync23, readFileSync as readFileSync33 } from "fs";
|
|
18689
|
+
import { join as join34, resolve as resolve24 } from "path";
|
|
18659
18690
|
var STATIC_TOP_LEVEL_LABELS = Object.freeze(
|
|
18660
18691
|
/* @__PURE__ */ new Set([
|
|
18661
18692
|
// Base-schema infra (schema-base.md has no top-level section).
|
|
@@ -18748,7 +18779,7 @@ function parseTopLevelLabels(content) {
|
|
|
18748
18779
|
}
|
|
18749
18780
|
function resolveReferencesDir() {
|
|
18750
18781
|
if (process.env.MAXY_PLATFORM_ROOT) {
|
|
18751
|
-
return
|
|
18782
|
+
return join34(process.env.MAXY_PLATFORM_ROOT, "plugins", "memory", "references");
|
|
18752
18783
|
}
|
|
18753
18784
|
return resolve24(import.meta.dirname, "../../../plugins/memory/references");
|
|
18754
18785
|
}
|
|
@@ -18756,9 +18787,9 @@ function parseTableTopLevelLabels(referencesDir) {
|
|
|
18756
18787
|
const labels = /* @__PURE__ */ new Set();
|
|
18757
18788
|
const contributingFiles = [];
|
|
18758
18789
|
try {
|
|
18759
|
-
const fileNames =
|
|
18790
|
+
const fileNames = readdirSync23(referencesDir).filter((f) => f.startsWith("schema-") && f.endsWith(".md")).sort();
|
|
18760
18791
|
for (const fileName of fileNames) {
|
|
18761
|
-
const content = readFileSync33(
|
|
18792
|
+
const content = readFileSync33(join34(referencesDir, fileName), "utf-8");
|
|
18762
18793
|
const parsed = parseTopLevelLabels(content);
|
|
18763
18794
|
if (parsed.length > 0) contributingFiles.push(fileName);
|
|
18764
18795
|
for (const label of parsed) labels.add(label);
|
|
@@ -19912,7 +19943,7 @@ var graph_default_view_default = app28;
|
|
|
19912
19943
|
// server/routes/admin/sidebar-artefacts.ts
|
|
19913
19944
|
import { readdir as readdir4, stat as stat5 } from "fs/promises";
|
|
19914
19945
|
import { resolve as resolve25, relative as relative5, isAbsolute as isAbsolute2, sep as sep7, basename as basename10 } from "path";
|
|
19915
|
-
import { existsSync as
|
|
19946
|
+
import { existsSync as existsSync30 } from "fs";
|
|
19916
19947
|
var LIMIT = 50;
|
|
19917
19948
|
var ADMIN_AGENT_FILES = ["IDENTITY.md", "SOUL.md", "KNOWLEDGE.md"];
|
|
19918
19949
|
function toDataRootRelPath(absPath) {
|
|
@@ -20019,7 +20050,7 @@ async function fetchAgentTemplateRows(accountDir) {
|
|
|
20019
20050
|
async function unionSpecialistFilenames(overrideDir, bundledDir) {
|
|
20020
20051
|
const names = /* @__PURE__ */ new Set();
|
|
20021
20052
|
for (const dir of [overrideDir, bundledDir]) {
|
|
20022
|
-
if (!
|
|
20053
|
+
if (!existsSync30(dir)) continue;
|
|
20023
20054
|
try {
|
|
20024
20055
|
const entries = await readdir4(dir);
|
|
20025
20056
|
for (const entry of entries) {
|
|
@@ -20034,7 +20065,7 @@ async function unionSpecialistFilenames(overrideDir, bundledDir) {
|
|
|
20034
20065
|
}
|
|
20035
20066
|
async function readAgentTemplateRow(inp) {
|
|
20036
20067
|
let chosenPath = null;
|
|
20037
|
-
if (
|
|
20068
|
+
if (existsSync30(inp.overridePath)) {
|
|
20038
20069
|
try {
|
|
20039
20070
|
validateFilePathInAccount(inp.overridePath, inp.overrideRoot);
|
|
20040
20071
|
chosenPath = inp.overridePath;
|
|
@@ -20045,7 +20076,7 @@ async function readAgentTemplateRow(inp) {
|
|
|
20045
20076
|
);
|
|
20046
20077
|
return null;
|
|
20047
20078
|
}
|
|
20048
|
-
} else if (
|
|
20079
|
+
} else if (existsSync30(inp.bundledPath)) {
|
|
20049
20080
|
if (!isWithin(inp.bundledPath, inp.bundledRoot)) {
|
|
20050
20081
|
console.error(
|
|
20051
20082
|
`[admin/sidebar-artefacts] agent-template-read-failed agent=${inp.displayName} kind=${inp.logName} error="bundled path outside PLATFORM_ROOT"`
|
|
@@ -20647,12 +20678,12 @@ app37.get("/", async (c) => {
|
|
|
20647
20678
|
var system_stats_default = app37;
|
|
20648
20679
|
|
|
20649
20680
|
// server/routes/admin/health.ts
|
|
20650
|
-
import { existsSync as
|
|
20651
|
-
import { resolve as resolve26, join as
|
|
20681
|
+
import { existsSync as existsSync31, readFileSync as readFileSync34 } from "fs";
|
|
20682
|
+
import { resolve as resolve26, join as join35 } from "path";
|
|
20652
20683
|
var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve26(process.cwd(), "..");
|
|
20653
20684
|
var brandHostname = "maxy";
|
|
20654
|
-
var brandJsonPath =
|
|
20655
|
-
if (
|
|
20685
|
+
var brandJsonPath = join35(PLATFORM_ROOT6, "config", "brand.json");
|
|
20686
|
+
if (existsSync31(brandJsonPath)) {
|
|
20656
20687
|
try {
|
|
20657
20688
|
const brand = JSON.parse(readFileSync34(brandJsonPath, "utf-8"));
|
|
20658
20689
|
if (brand.hostname) brandHostname = brand.hostname;
|
|
@@ -20663,7 +20694,7 @@ var VERSION_FILE = resolve26(PLATFORM_ROOT6, `config/.${brandHostname}-version`)
|
|
|
20663
20694
|
var PROCESS_STARTED_AT = (/* @__PURE__ */ new Date()).toISOString();
|
|
20664
20695
|
var PROBE_TIMEOUT_MS = 1e3;
|
|
20665
20696
|
function readVersion() {
|
|
20666
|
-
if (!
|
|
20697
|
+
if (!existsSync31(VERSION_FILE)) return "unknown";
|
|
20667
20698
|
return readFileSync34(VERSION_FILE, "utf-8").trim() || "unknown";
|
|
20668
20699
|
}
|
|
20669
20700
|
async function probeConversationDb() {
|
|
@@ -20673,18 +20704,18 @@ async function probeConversationDb() {
|
|
|
20673
20704
|
} catch (err) {
|
|
20674
20705
|
return { state: "error", reason: err instanceof Error ? err.message : String(err) };
|
|
20675
20706
|
}
|
|
20676
|
-
let
|
|
20707
|
+
let timer;
|
|
20677
20708
|
try {
|
|
20678
20709
|
const probe = session.run("RETURN 1");
|
|
20679
20710
|
const timeout = new Promise((_, reject) => {
|
|
20680
|
-
|
|
20711
|
+
timer = setTimeout(() => reject(new Error("timeout")), PROBE_TIMEOUT_MS);
|
|
20681
20712
|
});
|
|
20682
20713
|
await Promise.race([probe, timeout]);
|
|
20683
20714
|
return { state: "ok" };
|
|
20684
20715
|
} catch (err) {
|
|
20685
20716
|
return { state: "error", reason: err instanceof Error ? err.message : String(err) };
|
|
20686
20717
|
} finally {
|
|
20687
|
-
if (
|
|
20718
|
+
if (timer) clearTimeout(timer);
|
|
20688
20719
|
session.close().catch(() => {
|
|
20689
20720
|
});
|
|
20690
20721
|
}
|
|
@@ -21440,8 +21471,8 @@ app45.post("/launch", requireAdminSession, async (c) => {
|
|
|
21440
21471
|
var browser_default = app45;
|
|
21441
21472
|
|
|
21442
21473
|
// server/routes/admin/calendar.ts
|
|
21443
|
-
import { existsSync as
|
|
21444
|
-
import { join as
|
|
21474
|
+
import { existsSync as existsSync32 } from "fs";
|
|
21475
|
+
import { join as join37 } from "path";
|
|
21445
21476
|
|
|
21446
21477
|
// server/lib/calendar-ics.ts
|
|
21447
21478
|
var CRLF = "\r\n";
|
|
@@ -21541,7 +21572,7 @@ function countVEvents(ics) {
|
|
|
21541
21572
|
|
|
21542
21573
|
// server/lib/calendar-availability.ts
|
|
21543
21574
|
import { readFileSync as readFileSync35 } from "fs";
|
|
21544
|
-
import { join as
|
|
21575
|
+
import { join as join36 } from "path";
|
|
21545
21576
|
var AVAILABILITY_FILENAME = "calendar-availability.json";
|
|
21546
21577
|
var REQUIRED_KEYS = [
|
|
21547
21578
|
"timezone",
|
|
@@ -21550,7 +21581,7 @@ var REQUIRED_KEYS = [
|
|
|
21550
21581
|
"weekly"
|
|
21551
21582
|
];
|
|
21552
21583
|
function readAvailabilityConfig(accountDir) {
|
|
21553
|
-
const path3 =
|
|
21584
|
+
const path3 = join36(accountDir, AVAILABILITY_FILENAME);
|
|
21554
21585
|
let raw;
|
|
21555
21586
|
try {
|
|
21556
21587
|
raw = readFileSync35(path3, "utf-8");
|
|
@@ -21912,7 +21943,7 @@ app46.get("/booking-link", requireAdminSession, (c) => {
|
|
|
21912
21943
|
console.error('[calendar] op=booking-link-fail err="no account configured"');
|
|
21913
21944
|
return c.json({ bookingDomain: null });
|
|
21914
21945
|
}
|
|
21915
|
-
if (!
|
|
21946
|
+
if (!existsSync32(join37(account.accountDir, AVAILABILITY_FILENAME))) {
|
|
21916
21947
|
console.log("[calendar] op=booking-link bookingDomain=none source=availability-config");
|
|
21917
21948
|
return c.json({ bookingDomain: null });
|
|
21918
21949
|
}
|
|
@@ -22269,7 +22300,7 @@ app51.post("/", requireAdminSession, async (c) => {
|
|
|
22269
22300
|
var task_time_adjust_default = app51;
|
|
22270
22301
|
|
|
22271
22302
|
// server/routes/admin/activity.ts
|
|
22272
|
-
import { readdirSync as
|
|
22303
|
+
import { readdirSync as readdirSync24 } from "fs";
|
|
22273
22304
|
var app52 = new Hono();
|
|
22274
22305
|
var TAG42 = "[activity]";
|
|
22275
22306
|
function resolveHouseAccountId(accounts) {
|
|
@@ -22285,7 +22316,7 @@ function requestToken() {
|
|
|
22285
22316
|
var short = (id) => id ? id.slice(0, 8) : "unset";
|
|
22286
22317
|
function countAccountDirsOnDisk() {
|
|
22287
22318
|
try {
|
|
22288
|
-
return
|
|
22319
|
+
return readdirSync24(ACCOUNTS_DIR, { withFileTypes: true }).filter(
|
|
22289
22320
|
(e) => e.isDirectory() && !e.name.startsWith(".")
|
|
22290
22321
|
).length;
|
|
22291
22322
|
} catch {
|
|
@@ -22340,8 +22371,10 @@ app52.get("/", requireAdminSession, async (c) => {
|
|
|
22340
22371
|
const untaggedCount = rows.filter((r) => r.accountId === null).length;
|
|
22341
22372
|
const meteringFailed = rows.filter((r) => r.meteringError !== null).length;
|
|
22342
22373
|
const censusAgeMs = census ? Date.now() - census.sampleAtMs : null;
|
|
22374
|
+
const ageNull = rows.filter((r) => r.ageMs === null).length;
|
|
22375
|
+
const sidecarNull = rows.filter((r) => r.sidecarMissing).length;
|
|
22343
22376
|
console.log(
|
|
22344
|
-
`${TAG42} op=census req=${req} ageMs=${censusAgeMs ?? "none"} live=${census?.live ?? "none"} cpuNull=${census?.cpuNull ?? "none"}`
|
|
22377
|
+
`${TAG42} op=census req=${req} ageMs=${censusAgeMs ?? "none"} live=${census?.live ?? "none"} cpuNull=${census?.cpuNull ?? "none"} rows=${rows.length} ageNull=${ageNull} sidecarNull=${sidecarNull}`
|
|
22345
22378
|
);
|
|
22346
22379
|
console.log(
|
|
22347
22380
|
`${TAG42} op=response req=${req} rows=${rows.length} accounts=${valid.length} untagged=${untaggedCount} meteringFailed=${meteringFailed} ms=${Date.now() - start}`
|
|
@@ -22353,10 +22386,20 @@ app52.get("/", requireAdminSession, async (c) => {
|
|
|
22353
22386
|
if (name) names[a.accountId] = name;
|
|
22354
22387
|
})
|
|
22355
22388
|
);
|
|
22389
|
+
const loopRows = listLoops();
|
|
22390
|
+
const armed2 = armedCount();
|
|
22391
|
+
const byState = loopRows.reduce((acc, r) => {
|
|
22392
|
+
acc[r.state] = (acc[r.state] ?? 0) + 1;
|
|
22393
|
+
return acc;
|
|
22394
|
+
}, {});
|
|
22395
|
+
console.log(
|
|
22396
|
+
`${TAG42} op=loops req=${req} armed=${armed2} rendered=${loopRows.length} ` + Object.entries(byState).map(([s, n]) => `${s}=${n}`).join(" ")
|
|
22397
|
+
);
|
|
22356
22398
|
return c.json({
|
|
22357
22399
|
rows,
|
|
22358
22400
|
census,
|
|
22359
22401
|
censusAgeMs,
|
|
22402
|
+
loops: { armed: armed2, rows: loopRows },
|
|
22360
22403
|
accounts: {
|
|
22361
22404
|
onDisk,
|
|
22362
22405
|
valid: valid.length,
|
|
@@ -22649,7 +22692,7 @@ app56.route("/request-magic-link", request_magic_link_default);
|
|
|
22649
22692
|
var access_default = app56;
|
|
22650
22693
|
|
|
22651
22694
|
// server/routes/sites.ts
|
|
22652
|
-
import { existsSync as
|
|
22695
|
+
import { existsSync as existsSync33, readFileSync as readFileSync36, realpathSync as realpathSync7, statSync as statSync14 } from "fs";
|
|
22653
22696
|
import { resolve as resolve28 } from "path";
|
|
22654
22697
|
var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
|
|
22655
22698
|
var MIME = {
|
|
@@ -22715,7 +22758,7 @@ app57.get("/:rel{.*}", (c) => {
|
|
|
22715
22758
|
}
|
|
22716
22759
|
let stat8;
|
|
22717
22760
|
try {
|
|
22718
|
-
stat8 =
|
|
22761
|
+
stat8 = existsSync33(filePath) ? statSync14(filePath) : null;
|
|
22719
22762
|
} catch {
|
|
22720
22763
|
stat8 = null;
|
|
22721
22764
|
}
|
|
@@ -22734,7 +22777,7 @@ app57.get("/:rel{.*}", (c) => {
|
|
|
22734
22777
|
console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
|
|
22735
22778
|
return c.text("Forbidden", 403);
|
|
22736
22779
|
}
|
|
22737
|
-
if (!
|
|
22780
|
+
if (!existsSync33(filePath)) {
|
|
22738
22781
|
console.error(`[sites] not-found path=${reqPath} status=404`);
|
|
22739
22782
|
return c.text("Not found", 404);
|
|
22740
22783
|
}
|
|
@@ -22865,8 +22908,8 @@ var VISITOR_COOKIE_NAME = "mxy_v";
|
|
|
22865
22908
|
var VISITOR_COOKIE_MAX_AGE_SECONDS = Math.floor(DEFAULT_TTL_MS / 1e3);
|
|
22866
22909
|
|
|
22867
22910
|
// app/lib/brand-config.ts
|
|
22868
|
-
import { existsSync as
|
|
22869
|
-
import { join as
|
|
22911
|
+
import { existsSync as existsSync34, readFileSync as readFileSync38 } from "fs";
|
|
22912
|
+
import { join as join38 } from "path";
|
|
22870
22913
|
var cached2 = null;
|
|
22871
22914
|
var cachedAttempted = false;
|
|
22872
22915
|
function readBrandConfig() {
|
|
@@ -22874,8 +22917,8 @@ function readBrandConfig() {
|
|
|
22874
22917
|
cachedAttempted = true;
|
|
22875
22918
|
const platformRoot5 = process.env.MAXY_PLATFORM_ROOT;
|
|
22876
22919
|
if (!platformRoot5) return null;
|
|
22877
|
-
const brandPath =
|
|
22878
|
-
if (!
|
|
22920
|
+
const brandPath = join38(platformRoot5, "config", "brand.json");
|
|
22921
|
+
if (!existsSync34(brandPath)) return null;
|
|
22879
22922
|
try {
|
|
22880
22923
|
cached2 = JSON.parse(readFileSync38(brandPath, "utf-8"));
|
|
22881
22924
|
return cached2;
|
|
@@ -23366,8 +23409,8 @@ var visitor_event_default = app60;
|
|
|
23366
23409
|
|
|
23367
23410
|
// server/routes/session.ts
|
|
23368
23411
|
import { resolve as resolve29 } from "path";
|
|
23369
|
-
import { existsSync as
|
|
23370
|
-
var
|
|
23412
|
+
import { existsSync as existsSync35, writeFileSync as writeFileSync13, mkdirSync as mkdirSync9 } from "fs";
|
|
23413
|
+
var UUID_RE5 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
23371
23414
|
function writeBrandingCache(accountId, agentSlug, branding) {
|
|
23372
23415
|
try {
|
|
23373
23416
|
const cacheDir = resolve29(MAXY_DIR, "branding-cache", accountId);
|
|
@@ -23382,7 +23425,7 @@ function parseVisitorCookie2(cookieHeader) {
|
|
|
23382
23425
|
const match = cookieHeader.match(/(?:^|;\s*)maxy_visitor=([^;]*)/);
|
|
23383
23426
|
if (!match) return null;
|
|
23384
23427
|
const value = decodeURIComponent(match[1]).trim();
|
|
23385
|
-
return
|
|
23428
|
+
return UUID_RE5.test(value) ? value : null;
|
|
23386
23429
|
}
|
|
23387
23430
|
function parseAccessSessionId2(cookieHeader) {
|
|
23388
23431
|
if (!cookieHeader) return null;
|
|
@@ -23450,7 +23493,7 @@ app61.post("/", async (c) => {
|
|
|
23450
23493
|
let agentConfig = null;
|
|
23451
23494
|
if (account) {
|
|
23452
23495
|
const agentDir = resolve29(account.accountDir, "agents", agentSlug);
|
|
23453
|
-
if (!
|
|
23496
|
+
if (!existsSync35(agentDir) || !existsSync35(resolve29(agentDir, "config.json"))) {
|
|
23454
23497
|
return c.json({ error: "Agent not found" }, 404);
|
|
23455
23498
|
}
|
|
23456
23499
|
agentConfig = resolveAgentConfig(account.accountDir, agentSlug);
|
|
@@ -23480,7 +23523,7 @@ app61.post("/", async (c) => {
|
|
|
23480
23523
|
);
|
|
23481
23524
|
}
|
|
23482
23525
|
}
|
|
23483
|
-
if (body.session_key && typeof body.session_key === "string" &&
|
|
23526
|
+
if (body.session_key && typeof body.session_key === "string" && UUID_RE5.test(body.session_key)) {
|
|
23484
23527
|
if (visitorId) {
|
|
23485
23528
|
const recent = await findRecentConversation(visitorId, accountId, agentSlug).catch(() => null);
|
|
23486
23529
|
if (recent) {
|
|
@@ -23771,19 +23814,17 @@ function startTimeEntryCensus(openSession, opts = {}) {
|
|
|
23771
23814
|
}
|
|
23772
23815
|
}
|
|
23773
23816
|
};
|
|
23774
|
-
|
|
23775
|
-
|
|
23776
|
-
|
|
23777
|
-
|
|
23778
|
-
|
|
23779
|
-
|
|
23780
|
-
}
|
|
23781
|
-
return () => clearInterval(id);
|
|
23817
|
+
return registerLoop({
|
|
23818
|
+
name: "timeentry-census",
|
|
23819
|
+
intervalMs,
|
|
23820
|
+
firstRunDelayMs: 0,
|
|
23821
|
+
run: tick
|
|
23822
|
+
});
|
|
23782
23823
|
}
|
|
23783
23824
|
|
|
23784
23825
|
// app/lib/ledger-census.ts
|
|
23785
|
-
import { readdirSync as
|
|
23786
|
-
import { join as
|
|
23826
|
+
import { readdirSync as readdirSync25, readFileSync as readFileSync39, statSync as statSync15 } from "fs";
|
|
23827
|
+
import { join as join39 } from "path";
|
|
23787
23828
|
|
|
23788
23829
|
// ../lib/ledger-core/dist/reconcile.js
|
|
23789
23830
|
var LEDGER_INDEX_NAMES = [
|
|
@@ -23831,15 +23872,15 @@ var DAY_MS = 864e5;
|
|
|
23831
23872
|
function countWriteRejects24h(logDir, now) {
|
|
23832
23873
|
let entries;
|
|
23833
23874
|
try {
|
|
23834
|
-
entries =
|
|
23875
|
+
entries = readdirSync25(logDir).filter((f) => f.startsWith("mcp-ledger-") && f.endsWith(".log"));
|
|
23835
23876
|
} catch {
|
|
23836
23877
|
return 0;
|
|
23837
23878
|
}
|
|
23838
23879
|
let total = 0;
|
|
23839
23880
|
for (const name of entries) {
|
|
23840
|
-
const path3 =
|
|
23881
|
+
const path3 = join39(logDir, name);
|
|
23841
23882
|
try {
|
|
23842
|
-
if (now -
|
|
23883
|
+
if (now - statSync15(path3).mtimeMs > DAY_MS) continue;
|
|
23843
23884
|
for (const line of readFileSync39(path3, "utf8").split("\n")) {
|
|
23844
23885
|
if (line.includes("[graph-write] reject")) total += 1;
|
|
23845
23886
|
}
|
|
@@ -23932,15 +23973,12 @@ function startLedgerCensus(openSession, opts = {}) {
|
|
|
23932
23973
|
}
|
|
23933
23974
|
}
|
|
23934
23975
|
};
|
|
23935
|
-
|
|
23936
|
-
|
|
23937
|
-
|
|
23938
|
-
|
|
23939
|
-
|
|
23940
|
-
|
|
23941
|
-
id.unref();
|
|
23942
|
-
}
|
|
23943
|
-
return () => clearInterval(id);
|
|
23976
|
+
return registerLoop({
|
|
23977
|
+
name: "ledger-census",
|
|
23978
|
+
intervalMs,
|
|
23979
|
+
firstRunDelayMs: 0,
|
|
23980
|
+
run: tick
|
|
23981
|
+
});
|
|
23944
23982
|
}
|
|
23945
23983
|
|
|
23946
23984
|
// app/lib/conversation-audit.ts
|
|
@@ -23992,7 +24030,7 @@ function renderLabelTop(rows) {
|
|
|
23992
24030
|
return `${labels}:${c}`;
|
|
23993
24031
|
}).join(",");
|
|
23994
24032
|
}
|
|
23995
|
-
var
|
|
24033
|
+
var armed = false;
|
|
23996
24034
|
async function runGraphHealthTick() {
|
|
23997
24035
|
const session = getSession();
|
|
23998
24036
|
try {
|
|
@@ -24087,16 +24125,16 @@ async function verifyUserProfileConstraint() {
|
|
|
24087
24125
|
}
|
|
24088
24126
|
}
|
|
24089
24127
|
function startGraphHealthTimer() {
|
|
24090
|
-
if (
|
|
24128
|
+
if (armed) return;
|
|
24091
24129
|
verifyUserProfileConstraint().catch(() => {
|
|
24092
24130
|
});
|
|
24093
|
-
|
|
24131
|
+
registerLoop({
|
|
24132
|
+
name: "graph-health",
|
|
24133
|
+
intervalMs: HOUR_MS,
|
|
24134
|
+
firstRunDelayMs: 0,
|
|
24135
|
+
run: () => runGraphHealthTick()
|
|
24094
24136
|
});
|
|
24095
|
-
|
|
24096
|
-
runGraphHealthTick().catch(() => {
|
|
24097
|
-
});
|
|
24098
|
-
}, HOUR_MS);
|
|
24099
|
-
if (typeof timer.unref === "function") timer.unref();
|
|
24137
|
+
armed = true;
|
|
24100
24138
|
}
|
|
24101
24139
|
|
|
24102
24140
|
// app/lib/file-watcher.ts
|
|
@@ -24327,8 +24365,8 @@ async function migrateUploads(opts = {}) {
|
|
|
24327
24365
|
|
|
24328
24366
|
// app/lib/migrate-admin-webchat-sidecars.ts
|
|
24329
24367
|
import { readdir as readdir6, readFile as readFile6, rename as rename3, writeFile as writeFile4, unlink as unlink3 } from "fs/promises";
|
|
24330
|
-
import { existsSync as
|
|
24331
|
-
import { join as
|
|
24368
|
+
import { existsSync as existsSync36 } from "fs";
|
|
24369
|
+
import { join as join40 } from "path";
|
|
24332
24370
|
var ADMIN_ROLE2 = "admin";
|
|
24333
24371
|
var WEBCHAT_CHANNEL2 = "webchat";
|
|
24334
24372
|
var SESSION_META_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\.meta\.json$/i;
|
|
@@ -24357,7 +24395,7 @@ async function writeRaw(path3, obj) {
|
|
|
24357
24395
|
await rename3(tmp, path3);
|
|
24358
24396
|
} catch (err) {
|
|
24359
24397
|
try {
|
|
24360
|
-
if (
|
|
24398
|
+
if (existsSync36(tmp)) await unlink3(tmp);
|
|
24361
24399
|
} catch {
|
|
24362
24400
|
}
|
|
24363
24401
|
throw err;
|
|
@@ -24373,7 +24411,7 @@ async function collectLiveSidecars(projectsRoot) {
|
|
|
24373
24411
|
}
|
|
24374
24412
|
for (const slug of slugs) {
|
|
24375
24413
|
if (!slug.isDirectory()) continue;
|
|
24376
|
-
const slugDir =
|
|
24414
|
+
const slugDir = join40(projectsRoot, slug.name);
|
|
24377
24415
|
let entries;
|
|
24378
24416
|
try {
|
|
24379
24417
|
entries = await readdir6(slugDir, { withFileTypes: true });
|
|
@@ -24382,9 +24420,9 @@ async function collectLiveSidecars(projectsRoot) {
|
|
|
24382
24420
|
}
|
|
24383
24421
|
for (const entry of entries) {
|
|
24384
24422
|
if (entry.isFile() && SESSION_META_RE.test(entry.name)) {
|
|
24385
|
-
out.push(
|
|
24423
|
+
out.push(join40(slugDir, entry.name));
|
|
24386
24424
|
} else if (entry.isDirectory() && entry.name === "subagents") {
|
|
24387
|
-
const subDir =
|
|
24425
|
+
const subDir = join40(slugDir, entry.name);
|
|
24388
24426
|
let subs;
|
|
24389
24427
|
try {
|
|
24390
24428
|
subs = await readdir6(subDir, { withFileTypes: true });
|
|
@@ -24392,7 +24430,7 @@ async function collectLiveSidecars(projectsRoot) {
|
|
|
24392
24430
|
continue;
|
|
24393
24431
|
}
|
|
24394
24432
|
for (const s of subs) {
|
|
24395
|
-
if (s.isFile() && SESSION_META_RE.test(s.name)) out.push(
|
|
24433
|
+
if (s.isFile() && SESSION_META_RE.test(s.name)) out.push(join40(subDir, s.name));
|
|
24396
24434
|
}
|
|
24397
24435
|
}
|
|
24398
24436
|
}
|
|
@@ -24404,7 +24442,7 @@ function shortId(path3) {
|
|
|
24404
24442
|
return base.slice(0, 8);
|
|
24405
24443
|
}
|
|
24406
24444
|
async function migrateAdminWebchatSidecars(opts = {}) {
|
|
24407
|
-
const projectsRoot = opts.projectsRoot ?? (process.env.CLAUDE_CONFIG_DIR ?
|
|
24445
|
+
const projectsRoot = opts.projectsRoot ?? (process.env.CLAUDE_CONFIG_DIR ? join40(process.env.CLAUDE_CONFIG_DIR, "projects") : null) ?? "";
|
|
24408
24446
|
const usersFile = opts.usersFile ?? USERS_FILE;
|
|
24409
24447
|
const accountId = opts.accountId ?? resolveAccount()?.accountId ?? null;
|
|
24410
24448
|
const resolveName = opts.resolveName ?? defaultResolveName;
|
|
@@ -25416,13 +25454,13 @@ var WebchatGateway = class _WebchatGateway {
|
|
|
25416
25454
|
* response, preserving the pre-756 POST→single-blob browser contract. */
|
|
25417
25455
|
awaitReply(key, timeoutMs) {
|
|
25418
25456
|
return new Promise((resolve37) => {
|
|
25419
|
-
const
|
|
25457
|
+
const timer = setTimeout(() => {
|
|
25420
25458
|
this.replyAwaiters.delete(key);
|
|
25421
25459
|
resolve37({ timeout: true });
|
|
25422
25460
|
}, timeoutMs);
|
|
25423
|
-
if (
|
|
25461
|
+
if (timer.unref) timer.unref();
|
|
25424
25462
|
this.replyAwaiters.set(key, (r) => {
|
|
25425
|
-
clearTimeout(
|
|
25463
|
+
clearTimeout(timer);
|
|
25426
25464
|
this.replyAwaiters.delete(key);
|
|
25427
25465
|
resolve37(r);
|
|
25428
25466
|
});
|
|
@@ -25437,16 +25475,16 @@ var WebchatGateway = class _WebchatGateway {
|
|
|
25437
25475
|
const k = _WebchatGateway.promptKey(p.key, p.requestId);
|
|
25438
25476
|
return new Promise((resolve37) => {
|
|
25439
25477
|
this.pendingPrompts.get(k)?.resolve({ timeout: true });
|
|
25440
|
-
const
|
|
25478
|
+
const timer = setTimeout(() => {
|
|
25441
25479
|
this.pendingPrompts.delete(k);
|
|
25442
25480
|
resolve37({ timeout: true });
|
|
25443
25481
|
}, timeoutMs);
|
|
25444
|
-
if (
|
|
25482
|
+
if (timer.unref) timer.unref();
|
|
25445
25483
|
this.pendingPrompts.set(k, {
|
|
25446
25484
|
...p,
|
|
25447
25485
|
at: Date.now(),
|
|
25448
25486
|
resolve: (r) => {
|
|
25449
|
-
clearTimeout(
|
|
25487
|
+
clearTimeout(timer);
|
|
25450
25488
|
this.pendingPrompts.delete(k);
|
|
25451
25489
|
resolve37(r);
|
|
25452
25490
|
}
|
|
@@ -26767,12 +26805,12 @@ function startTelegramNativeFileFollower(input) {
|
|
|
26767
26805
|
}
|
|
26768
26806
|
|
|
26769
26807
|
// server/telegram-descriptor.ts
|
|
26770
|
-
import { resolve as resolve34, join as
|
|
26808
|
+
import { resolve as resolve34, join as join41 } from "path";
|
|
26771
26809
|
function telegramGatewayUrl() {
|
|
26772
26810
|
return `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`;
|
|
26773
26811
|
}
|
|
26774
26812
|
function telegramServerPath() {
|
|
26775
|
-
return process.env.MAXY_TELEGRAM_CHANNEL_SERVER_PATH ?? resolve34(process.env.MAXY_PLATFORM_ROOT ??
|
|
26813
|
+
return process.env.MAXY_TELEGRAM_CHANNEL_SERVER_PATH ?? resolve34(process.env.MAXY_PLATFORM_ROOT ?? join41(__dirname, ".."), "services/telegram-channel/dist/server.js");
|
|
26776
26814
|
}
|
|
26777
26815
|
|
|
26778
26816
|
// app/lib/channel-pty-bridge/public-session-end-review.ts
|
|
@@ -27059,7 +27097,7 @@ function broadcastAdminShutdown(reason) {
|
|
|
27059
27097
|
|
|
27060
27098
|
// ../lib/entitlement/src/index.ts
|
|
27061
27099
|
import { createPublicKey, createHash as createHash6, verify as cryptoVerify } from "crypto";
|
|
27062
|
-
import { existsSync as
|
|
27100
|
+
import { existsSync as existsSync37, readFileSync as readFileSync40, statSync as statSync16 } from "fs";
|
|
27063
27101
|
import { resolve as resolve35 } from "path";
|
|
27064
27102
|
|
|
27065
27103
|
// ../lib/entitlement/src/canonicalize.ts
|
|
@@ -27108,10 +27146,10 @@ function resolveEntitlement(brand, account) {
|
|
|
27108
27146
|
return logResolved(implicitTrust(account), null);
|
|
27109
27147
|
}
|
|
27110
27148
|
const entitlementPath = resolve35(brand.configDir, "entitlement.json");
|
|
27111
|
-
if (!
|
|
27149
|
+
if (!existsSync37(entitlementPath)) {
|
|
27112
27150
|
return logResolved(anonymousFallback("missing"), { reason: "missing" });
|
|
27113
27151
|
}
|
|
27114
|
-
const stat8 =
|
|
27152
|
+
const stat8 = statSync16(entitlementPath);
|
|
27115
27153
|
const key = memoKey(stat8.mtimeMs, account);
|
|
27116
27154
|
if (memo && memo.key === key) {
|
|
27117
27155
|
return memo.result;
|
|
@@ -27299,12 +27337,12 @@ function clientFrom(c) {
|
|
|
27299
27337
|
}
|
|
27300
27338
|
installMediaDownloadGuard();
|
|
27301
27339
|
var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT || "";
|
|
27302
|
-
var BRAND_JSON_PATH = PLATFORM_ROOT8 ?
|
|
27340
|
+
var BRAND_JSON_PATH = PLATFORM_ROOT8 ? join42(PLATFORM_ROOT8, "config", "brand.json") : "";
|
|
27303
27341
|
var BRAND = { productName: "Maxy", hostname: "maxy", configDir: ".maxy", marketingUrl: "https://getmaxy.com" };
|
|
27304
|
-
if (BRAND_JSON_PATH && !
|
|
27342
|
+
if (BRAND_JSON_PATH && !existsSync38(BRAND_JSON_PATH)) {
|
|
27305
27343
|
console.error(`[brand] WARNING: brand.json not found at ${BRAND_JSON_PATH} \u2014 using Maxy defaults`);
|
|
27306
27344
|
}
|
|
27307
|
-
if (BRAND_JSON_PATH &&
|
|
27345
|
+
if (BRAND_JSON_PATH && existsSync38(BRAND_JSON_PATH)) {
|
|
27308
27346
|
try {
|
|
27309
27347
|
const parsed = JSON.parse(readFileSync41(BRAND_JSON_PATH, "utf-8"));
|
|
27310
27348
|
BRAND = { ...BRAND, ...parsed };
|
|
@@ -27338,10 +27376,10 @@ var brandLoginOpts = {
|
|
|
27338
27376
|
appleTouchIconPath: brandAppIcon512Path,
|
|
27339
27377
|
themeColor: BRAND.defaultColors?.primary
|
|
27340
27378
|
};
|
|
27341
|
-
var ALIAS_DOMAINS_PATH =
|
|
27379
|
+
var ALIAS_DOMAINS_PATH = join42(homedir4(), BRAND.configDir, "alias-domains.json");
|
|
27342
27380
|
function loadAliasDomains() {
|
|
27343
27381
|
try {
|
|
27344
|
-
if (!
|
|
27382
|
+
if (!existsSync38(ALIAS_DOMAINS_PATH)) return null;
|
|
27345
27383
|
const parsed = JSON.parse(readFileSync41(ALIAS_DOMAINS_PATH, "utf-8"));
|
|
27346
27384
|
if (!Array.isArray(parsed)) {
|
|
27347
27385
|
console.error("[alias-domains] malformed alias-domains.json \u2014 expected array");
|
|
@@ -27406,7 +27444,7 @@ async function recordPassiveDispatch(input) {
|
|
|
27406
27444
|
var waGateway = new WaGateway({
|
|
27407
27445
|
fetchStandingRules: fetchAccountStandingRules,
|
|
27408
27446
|
gatewayUrl: `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`,
|
|
27409
|
-
serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve36(process.env.MAXY_PLATFORM_ROOT ??
|
|
27447
|
+
serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve36(process.env.MAXY_PLATFORM_ROOT ?? join42(__dirname, ".."), "services/whatsapp-channel/dist/server.js"),
|
|
27410
27448
|
// Task 751 / 1390 — file delivery on the native channel. `maxyAccountId` (the
|
|
27411
27449
|
// path-validation scope) is the sender's effective SESSION account, resolved
|
|
27412
27450
|
// once at the inbound gate and threaded here via the gateway's per-sender doc
|
|
@@ -27421,7 +27459,7 @@ var waGateway = new WaGateway({
|
|
|
27421
27459
|
caption,
|
|
27422
27460
|
accountId,
|
|
27423
27461
|
maxyAccountId,
|
|
27424
|
-
platformRoot: resolve36(process.env.MAXY_PLATFORM_ROOT ??
|
|
27462
|
+
platformRoot: resolve36(process.env.MAXY_PLATFORM_ROOT ?? join42(__dirname, ".."))
|
|
27425
27463
|
});
|
|
27426
27464
|
return result.ok ? { ok: true, messageId: result.messageId } : { ok: false, error: result.error };
|
|
27427
27465
|
},
|
|
@@ -27525,7 +27563,7 @@ function runDuplicateSenderAudit() {
|
|
|
27525
27563
|
try {
|
|
27526
27564
|
const configDir2 = process.env.CLAUDE_CONFIG_DIR;
|
|
27527
27565
|
if (!configDir2) return;
|
|
27528
|
-
const projectsRoot =
|
|
27566
|
+
const projectsRoot = join42(configDir2, "projects");
|
|
27529
27567
|
const records = [];
|
|
27530
27568
|
for (const { path: jsonlPath, isSubagent, archived } of enumerateJsonls(projectsRoot)) {
|
|
27531
27569
|
if (isSubagent || archived) continue;
|
|
@@ -27539,8 +27577,12 @@ function runDuplicateSenderAudit() {
|
|
|
27539
27577
|
console.error(`[whatsapp-native] op=duplicate-sender-audit-error error=${err instanceof Error ? err.message : String(err)}`);
|
|
27540
27578
|
}
|
|
27541
27579
|
}
|
|
27542
|
-
|
|
27543
|
-
|
|
27580
|
+
registerLoop({
|
|
27581
|
+
name: "whatsapp-duplicate-sender-audit",
|
|
27582
|
+
intervalMs: 15 * 6e4,
|
|
27583
|
+
firstRunDelayMs: 0,
|
|
27584
|
+
run: runDuplicateSenderAudit
|
|
27585
|
+
});
|
|
27544
27586
|
var webchatGateway = new WebchatGateway({
|
|
27545
27587
|
fetchStandingRules: fetchAccountStandingRules,
|
|
27546
27588
|
gatewayUrl: webchatGatewayUrl(),
|
|
@@ -28077,7 +28119,7 @@ app63.get("/agent-assets/:slug/:filename", (c) => {
|
|
|
28077
28119
|
console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
|
|
28078
28120
|
return c.text("Forbidden", 403);
|
|
28079
28121
|
}
|
|
28080
|
-
if (!
|
|
28122
|
+
if (!existsSync38(filePath)) {
|
|
28081
28123
|
console.error(`[agent-assets] serve slug=${slug} file=${filename} status=404`);
|
|
28082
28124
|
return c.text("Not found", 404);
|
|
28083
28125
|
}
|
|
@@ -28107,7 +28149,7 @@ app63.get("/generated/:filename", (c) => {
|
|
|
28107
28149
|
console.error(`[generated] serve file=${filename} status=403`);
|
|
28108
28150
|
return c.text("Forbidden", 403);
|
|
28109
28151
|
}
|
|
28110
|
-
if (!
|
|
28152
|
+
if (!existsSync38(filePath)) {
|
|
28111
28153
|
console.error(`[generated] serve file=${filename} status=404`);
|
|
28112
28154
|
return c.text("Not found", 404);
|
|
28113
28155
|
}
|
|
@@ -28127,7 +28169,7 @@ app63.route("/v", visitor_consent_default);
|
|
|
28127
28169
|
var htmlCache = /* @__PURE__ */ new Map();
|
|
28128
28170
|
var brandLogoPath = "/brand/maxy-monochrome.png";
|
|
28129
28171
|
var brandIconPath = "/brand/maxy-monochrome.png";
|
|
28130
|
-
if (BRAND_JSON_PATH &&
|
|
28172
|
+
if (BRAND_JSON_PATH && existsSync38(BRAND_JSON_PATH)) {
|
|
28131
28173
|
try {
|
|
28132
28174
|
const fullBrand = JSON.parse(readFileSync41(BRAND_JSON_PATH, "utf-8"));
|
|
28133
28175
|
if (fullBrand.assets?.logo) brandLogoPath = `/brand/${fullBrand.assets.logo}`;
|
|
@@ -28156,7 +28198,7 @@ var brandScript = `<script>window.__BRAND__=${JSON.stringify({
|
|
|
28156
28198
|
var brandThemeColor = BRAND.defaultColors?.primary ?? "#000000";
|
|
28157
28199
|
var brandBackgroundColor = BRAND.defaultColors?.background ?? "#ffffff";
|
|
28158
28200
|
var brandAppIconsExist = [brandAppIcon192Path, brandAppIcon512Path, brandMaskableIconPath].every(
|
|
28159
|
-
(p) =>
|
|
28201
|
+
(p) => existsSync38(resolve36(process.cwd(), "public", p.replace(/^\//, "")))
|
|
28160
28202
|
);
|
|
28161
28203
|
var SW_SOURCE = (() => {
|
|
28162
28204
|
try {
|
|
@@ -28168,8 +28210,8 @@ var SW_SOURCE = (() => {
|
|
|
28168
28210
|
function readInstalledVersion() {
|
|
28169
28211
|
try {
|
|
28170
28212
|
if (!PLATFORM_ROOT8) return "unknown";
|
|
28171
|
-
const versionFile =
|
|
28172
|
-
if (!
|
|
28213
|
+
const versionFile = join42(PLATFORM_ROOT8, "config", `.${BRAND.hostname}-version`);
|
|
28214
|
+
if (!existsSync38(versionFile)) return "unknown";
|
|
28173
28215
|
const content = readFileSync41(versionFile, "utf-8").trim();
|
|
28174
28216
|
return content || "unknown";
|
|
28175
28217
|
} catch {
|
|
@@ -28228,12 +28270,12 @@ ${clientErrorReporterScript}
|
|
|
28228
28270
|
return html;
|
|
28229
28271
|
}
|
|
28230
28272
|
function loadBrandingCache(agentSlug) {
|
|
28231
|
-
const configDir2 =
|
|
28273
|
+
const configDir2 = join42(homedir4(), BRAND.configDir);
|
|
28232
28274
|
try {
|
|
28233
28275
|
const accountId = getDefaultAccountId();
|
|
28234
28276
|
if (!accountId) return null;
|
|
28235
|
-
const cachePath =
|
|
28236
|
-
if (!
|
|
28277
|
+
const cachePath = join42(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
|
|
28278
|
+
if (!existsSync38(cachePath)) return null;
|
|
28237
28279
|
return JSON.parse(readFileSync41(cachePath, "utf-8"));
|
|
28238
28280
|
} catch {
|
|
28239
28281
|
return null;
|
|
@@ -28466,11 +28508,11 @@ var hostname = process.env.HOSTNAME ?? "127.0.0.1";
|
|
|
28466
28508
|
var httpServer = serve({ fetch: app63.fetch, port, hostname });
|
|
28467
28509
|
console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
28468
28510
|
{
|
|
28469
|
-
const reconcilePlatformRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
28511
|
+
const reconcilePlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join42(__dirname, "..");
|
|
28470
28512
|
const reconcileScript = resolve36(reconcilePlatformRoot, "plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js");
|
|
28471
28513
|
const RECONCILE_INTERVAL_MS = 12e4;
|
|
28472
28514
|
const runReconcile = () => {
|
|
28473
|
-
if (!
|
|
28515
|
+
if (!existsSync38(reconcileScript)) return;
|
|
28474
28516
|
try {
|
|
28475
28517
|
const child = spawn3(process.execPath, [reconcileScript], {
|
|
28476
28518
|
env: { ...process.env, PLATFORM_ROOT: reconcilePlatformRoot },
|
|
@@ -28482,17 +28524,20 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
28482
28524
|
console.error(`[calendar-reconcile] spawn-failed err="${err.message}"`);
|
|
28483
28525
|
}
|
|
28484
28526
|
};
|
|
28485
|
-
|
|
28486
|
-
|
|
28487
|
-
|
|
28488
|
-
|
|
28527
|
+
registerLoop({
|
|
28528
|
+
name: "calendar-reconcile",
|
|
28529
|
+
intervalMs: RECONCILE_INTERVAL_MS,
|
|
28530
|
+
firstRunDelayMs: 15e3,
|
|
28531
|
+
detached: true,
|
|
28532
|
+
run: runReconcile
|
|
28533
|
+
});
|
|
28489
28534
|
}
|
|
28490
28535
|
{
|
|
28491
|
-
const outlookPlatformRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
28536
|
+
const outlookPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join42(__dirname, "..");
|
|
28492
28537
|
const outlookScript = resolve36(outlookPlatformRoot, "plugins/outlook/mcp/dist/scripts/complete-registration.js");
|
|
28493
28538
|
const OUTLOOK_COMPLETE_INTERVAL_MS = 3e4;
|
|
28494
28539
|
const runOutlookComplete = () => {
|
|
28495
|
-
if (!
|
|
28540
|
+
if (!existsSync38(outlookScript)) return;
|
|
28496
28541
|
try {
|
|
28497
28542
|
const child = spawn3(process.execPath, [outlookScript], {
|
|
28498
28543
|
env: { ...process.env, PLATFORM_ROOT: outlookPlatformRoot },
|
|
@@ -28504,26 +28549,29 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
28504
28549
|
console.error(`[outlook-complete] spawn-failed err="${err.message}"`);
|
|
28505
28550
|
}
|
|
28506
28551
|
};
|
|
28507
|
-
|
|
28508
|
-
|
|
28509
|
-
|
|
28510
|
-
|
|
28552
|
+
registerLoop({
|
|
28553
|
+
name: "outlook-devicecode-complete",
|
|
28554
|
+
intervalMs: OUTLOOK_COMPLETE_INTERVAL_MS,
|
|
28555
|
+
firstRunDelayMs: 18e3,
|
|
28556
|
+
detached: true,
|
|
28557
|
+
run: runOutlookComplete
|
|
28558
|
+
});
|
|
28511
28559
|
}
|
|
28512
28560
|
{
|
|
28513
|
-
const auditRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
28561
|
+
const auditRoot = process.env.MAXY_PLATFORM_ROOT ?? join42(__dirname, "..");
|
|
28514
28562
|
const strandedAccountsDir = resolve36(auditRoot, "..", "data/accounts");
|
|
28515
28563
|
const STRANDED_AUDIT_INTERVAL_MS = 3e5;
|
|
28516
28564
|
const STRANDED_AGE_MS = 16 * 6e4;
|
|
28517
28565
|
const STRANDED_UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
28518
28566
|
const runStrandedAudit = () => {
|
|
28519
28567
|
try {
|
|
28520
|
-
if (!
|
|
28568
|
+
if (!existsSync38(strandedAccountsDir)) return;
|
|
28521
28569
|
const now = Date.now();
|
|
28522
|
-
for (const name of
|
|
28570
|
+
for (const name of readdirSync26(strandedAccountsDir)) {
|
|
28523
28571
|
if (!STRANDED_UUID_RE.test(name)) continue;
|
|
28524
28572
|
const pendingPath2 = resolve36(strandedAccountsDir, name, "secrets/outlook/pending-devicecode.enc");
|
|
28525
|
-
if (!
|
|
28526
|
-
const ageMs = now -
|
|
28573
|
+
if (!existsSync38(pendingPath2)) continue;
|
|
28574
|
+
const ageMs = now - statSync17(pendingPath2).mtimeMs;
|
|
28527
28575
|
if (ageMs > STRANDED_AGE_MS) {
|
|
28528
28576
|
console.error(`[outlook-mcp] devicecode-stranded account=${name} ageSec=${Math.floor(ageMs / 1e3)}`);
|
|
28529
28577
|
}
|
|
@@ -28532,35 +28580,82 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
28532
28580
|
console.error(`[outlook-mcp] devicecode-stranded-audit error="${err.message}"`);
|
|
28533
28581
|
}
|
|
28534
28582
|
};
|
|
28535
|
-
|
|
28536
|
-
|
|
28537
|
-
|
|
28538
|
-
|
|
28583
|
+
registerLoop({
|
|
28584
|
+
name: "outlook-stranded-audit",
|
|
28585
|
+
intervalMs: STRANDED_AUDIT_INTERVAL_MS,
|
|
28586
|
+
firstRunDelayMs: 25e3,
|
|
28587
|
+
run: runStrandedAudit
|
|
28588
|
+
});
|
|
28539
28589
|
}
|
|
28540
28590
|
{
|
|
28541
|
-
const
|
|
28542
|
-
const
|
|
28543
|
-
const
|
|
28544
|
-
|
|
28545
|
-
|
|
28546
|
-
|
|
28591
|
+
const googleRoot = process.env.MAXY_PLATFORM_ROOT ?? join42(__dirname, "..");
|
|
28592
|
+
const googleAccountsDir = resolve36(googleRoot, "..", "data/accounts");
|
|
28593
|
+
const GOOGLE_PENDING_AUDIT_INTERVAL_MS = 3e5;
|
|
28594
|
+
const runGooglePendingAuditSafe = () => {
|
|
28595
|
+
try {
|
|
28596
|
+
runGooglePendingAudit(googleAccountsDir, Date.now(), (line) => console.error(line));
|
|
28597
|
+
} catch (err) {
|
|
28598
|
+
console.error(`[google-oauth] op=pending-audit-error error="${err.message}"`);
|
|
28599
|
+
}
|
|
28547
28600
|
};
|
|
28548
|
-
|
|
28549
|
-
|
|
28550
|
-
|
|
28551
|
-
|
|
28552
|
-
|
|
28553
|
-
|
|
28554
|
-
|
|
28555
|
-
|
|
28601
|
+
registerLoop({
|
|
28602
|
+
name: "google-pending-audit",
|
|
28603
|
+
intervalMs: GOOGLE_PENDING_AUDIT_INTERVAL_MS,
|
|
28604
|
+
firstRunDelayMs: 27e3,
|
|
28605
|
+
run: runGooglePendingAuditSafe
|
|
28606
|
+
});
|
|
28607
|
+
const googleAuditScript = resolve36(googleRoot, "plugins/google/mcp/dist/scripts/account-audit.js");
|
|
28608
|
+
const GOOGLE_ACCOUNT_AUDIT_INTERVAL_MS = 36e5;
|
|
28609
|
+
const runGoogleAccountAudit = () => {
|
|
28610
|
+
if (!existsSync38(googleAuditScript)) return;
|
|
28611
|
+
try {
|
|
28612
|
+
const child = spawn3(process.execPath, [googleAuditScript], {
|
|
28613
|
+
env: { ...process.env, PLATFORM_ROOT: googleRoot },
|
|
28614
|
+
stdio: "inherit"
|
|
28615
|
+
});
|
|
28616
|
+
child.unref();
|
|
28617
|
+
child.on(
|
|
28618
|
+
"error",
|
|
28619
|
+
(err) => console.error(`[google-account-audit] op=spawn-failed error="${err.message}"`)
|
|
28620
|
+
);
|
|
28621
|
+
} catch (err) {
|
|
28622
|
+
console.error(`[google-account-audit] op=spawn-failed error="${err.message}"`);
|
|
28623
|
+
}
|
|
28556
28624
|
};
|
|
28557
|
-
|
|
28558
|
-
|
|
28559
|
-
|
|
28560
|
-
|
|
28625
|
+
registerLoop({
|
|
28626
|
+
name: "google-account-audit",
|
|
28627
|
+
intervalMs: GOOGLE_ACCOUNT_AUDIT_INTERVAL_MS,
|
|
28628
|
+
firstRunDelayMs: 45e3,
|
|
28629
|
+
detached: true,
|
|
28630
|
+
run: runGoogleAccountAudit
|
|
28631
|
+
});
|
|
28561
28632
|
}
|
|
28562
28633
|
{
|
|
28563
|
-
const
|
|
28634
|
+
const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join42(__dirname, "..");
|
|
28635
|
+
const STORAGE_AUDIT_INTERVAL_MS = 3e5;
|
|
28636
|
+
const runStorageAuditSafe = () => runStorageAudit(auditPlatformRoot).catch((err) => {
|
|
28637
|
+
console.error(`[storage-audit] error="${err.message}"`);
|
|
28638
|
+
throw err;
|
|
28639
|
+
});
|
|
28640
|
+
registerLoop({
|
|
28641
|
+
name: "storage-audit",
|
|
28642
|
+
intervalMs: STORAGE_AUDIT_INTERVAL_MS,
|
|
28643
|
+
firstRunDelayMs: 2e4,
|
|
28644
|
+
run: runStorageAuditSafe
|
|
28645
|
+
});
|
|
28646
|
+
const runPagesAuditSafe = () => runPagesAudit(auditPlatformRoot).catch((err) => {
|
|
28647
|
+
console.error(`[pages-audit] error="${err.message}"`);
|
|
28648
|
+
throw err;
|
|
28649
|
+
});
|
|
28650
|
+
registerLoop({
|
|
28651
|
+
name: "pages-audit",
|
|
28652
|
+
intervalMs: STORAGE_AUDIT_INTERVAL_MS,
|
|
28653
|
+
firstRunDelayMs: 35e3,
|
|
28654
|
+
run: runPagesAuditSafe
|
|
28655
|
+
});
|
|
28656
|
+
}
|
|
28657
|
+
{
|
|
28658
|
+
const publishPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join42(__dirname, "..");
|
|
28564
28659
|
const publishScript = resolve36(publishPlatformRoot, "plugins/scheduling/mcp/dist/scripts/publish-availability.js");
|
|
28565
28660
|
const PUBLISH_INTERVAL_MS = 3e5;
|
|
28566
28661
|
const currentAccount = () => {
|
|
@@ -28572,7 +28667,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
28572
28667
|
}
|
|
28573
28668
|
};
|
|
28574
28669
|
const spawnPublish = (account) => {
|
|
28575
|
-
if (!
|
|
28670
|
+
if (!existsSync38(publishScript)) return;
|
|
28576
28671
|
try {
|
|
28577
28672
|
const child = spawn3(process.execPath, [publishScript], {
|
|
28578
28673
|
env: {
|
|
@@ -28593,7 +28688,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
28593
28688
|
const availPath = resolve36(account.accountDir, "calendar-availability.json");
|
|
28594
28689
|
let hasBookingSite = false;
|
|
28595
28690
|
try {
|
|
28596
|
-
if (
|
|
28691
|
+
if (existsSync38(availPath)) {
|
|
28597
28692
|
const cfg = JSON.parse(readFileSync41(availPath, "utf-8"));
|
|
28598
28693
|
hasBookingSite = typeof cfg.bookingDbName === "string" && cfg.bookingDbName.length > 0;
|
|
28599
28694
|
}
|
|
@@ -28602,7 +28697,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
28602
28697
|
if (!hasBookingSite) return;
|
|
28603
28698
|
const statePath = resolve36(account.accountDir, "state", "booking-availability", "last-publish.json");
|
|
28604
28699
|
let lastSuccessAt = null;
|
|
28605
|
-
if (
|
|
28700
|
+
if (existsSync38(statePath)) {
|
|
28606
28701
|
try {
|
|
28607
28702
|
const rec = JSON.parse(readFileSync41(statePath, "utf-8"));
|
|
28608
28703
|
lastSuccessAt = rec.lastSuccessAt ?? null;
|
|
@@ -28621,20 +28716,23 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
28621
28716
|
spawnPublish(account);
|
|
28622
28717
|
auditSnapshotAge(account);
|
|
28623
28718
|
};
|
|
28624
|
-
|
|
28625
|
-
|
|
28626
|
-
|
|
28627
|
-
|
|
28719
|
+
registerLoop({
|
|
28720
|
+
name: "calendar-availability-publish",
|
|
28721
|
+
intervalMs: PUBLISH_INTERVAL_MS,
|
|
28722
|
+
firstRunDelayMs: 2e4,
|
|
28723
|
+
detached: true,
|
|
28724
|
+
run: publishTick
|
|
28725
|
+
});
|
|
28628
28726
|
}
|
|
28629
28727
|
startTimeEntryCensus(() => getSession());
|
|
28630
28728
|
startLedgerCensus(() => getSession());
|
|
28631
28729
|
{
|
|
28632
|
-
const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
28730
|
+
const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join42(__dirname, "..");
|
|
28633
28731
|
const auditScript = resolve36(auditPlatformRoot, "plugins/connector/mcp/dist/scripts/audit-connectors.js");
|
|
28634
28732
|
const auditLogDir = process.env.LOG_DIR ?? LOG_DIR;
|
|
28635
28733
|
const CONNECTOR_AUDIT_INTERVAL_MS = 3e5;
|
|
28636
28734
|
const runConnectorAudit = () => {
|
|
28637
|
-
if (!
|
|
28735
|
+
if (!existsSync38(auditScript)) return;
|
|
28638
28736
|
try {
|
|
28639
28737
|
const child = spawn3(process.execPath, [auditScript], {
|
|
28640
28738
|
env: { ...process.env, PLATFORM_ROOT: auditPlatformRoot, LOG_DIR: auditLogDir },
|
|
@@ -28646,10 +28744,13 @@ startLedgerCensus(() => getSession());
|
|
|
28646
28744
|
console.error(`[connector-audit] spawn-failed err="${err.message}"`);
|
|
28647
28745
|
}
|
|
28648
28746
|
};
|
|
28649
|
-
|
|
28650
|
-
|
|
28651
|
-
|
|
28652
|
-
|
|
28747
|
+
registerLoop({
|
|
28748
|
+
name: "connector-audit",
|
|
28749
|
+
intervalMs: CONNECTOR_AUDIT_INTERVAL_MS,
|
|
28750
|
+
firstRunDelayMs: 3e4,
|
|
28751
|
+
detached: true,
|
|
28752
|
+
run: runConnectorAudit
|
|
28753
|
+
});
|
|
28653
28754
|
}
|
|
28654
28755
|
{
|
|
28655
28756
|
const census = pwaCensus({
|
|
@@ -28672,15 +28773,19 @@ startAuthHealthHeartbeat();
|
|
|
28672
28773
|
loopHist.enable();
|
|
28673
28774
|
const LOG_THRESHOLD_MS = 1e3;
|
|
28674
28775
|
const WINDOW_MS2 = 3e4;
|
|
28675
|
-
|
|
28676
|
-
|
|
28677
|
-
|
|
28678
|
-
|
|
28679
|
-
|
|
28680
|
-
|
|
28776
|
+
registerLoop({
|
|
28777
|
+
name: "event-loop-lag",
|
|
28778
|
+
intervalMs: WINDOW_MS2,
|
|
28779
|
+
run: () => {
|
|
28780
|
+
const maxMs = loopHist.max / 1e6;
|
|
28781
|
+
const p99Ms = loopHist.percentile(99) / 1e6;
|
|
28782
|
+
loopHist.reset();
|
|
28783
|
+
if (maxMs >= LOG_THRESHOLD_MS) {
|
|
28784
|
+
console.error(`[event-loop] lag p99=${Math.round(p99Ms)} max=${Math.round(maxMs)} window=${WINDOW_MS2 / 1e3}s`);
|
|
28785
|
+
}
|
|
28786
|
+
return `p99 ${Math.round(p99Ms)}ms, max ${Math.round(maxMs)}ms`;
|
|
28681
28787
|
}
|
|
28682
|
-
}
|
|
28683
|
-
lagTimer.unref();
|
|
28788
|
+
});
|
|
28684
28789
|
}
|
|
28685
28790
|
var SUBAPP_MANIFEST = [
|
|
28686
28791
|
{ prefix: "/api/health", file: "server/routes/health.ts", subapp: health_default },
|
|
@@ -28745,7 +28850,7 @@ try {
|
|
|
28745
28850
|
var ADMINUSER_RECONCILE_INTERVAL_MS = 60 * 60 * 1e3;
|
|
28746
28851
|
async function runAdminUserReconcileTick() {
|
|
28747
28852
|
try {
|
|
28748
|
-
if (!
|
|
28853
|
+
if (!existsSync38(USERS_FILE)) {
|
|
28749
28854
|
console.error("[adminuser-self-heal] skip reason=no-users-file");
|
|
28750
28855
|
return;
|
|
28751
28856
|
}
|
|
@@ -28772,11 +28877,14 @@ async function runAdminUserReconcileTick() {
|
|
|
28772
28877
|
console.error(`[adminuser-self-heal] rejected: ${err instanceof Error ? err.message : String(err)}`);
|
|
28773
28878
|
}
|
|
28774
28879
|
}
|
|
28775
|
-
|
|
28776
|
-
|
|
28777
|
-
|
|
28778
|
-
|
|
28779
|
-
|
|
28880
|
+
registerLoop({
|
|
28881
|
+
name: "adminuser-reconcile",
|
|
28882
|
+
intervalMs: ADMINUSER_RECONCILE_INTERVAL_MS,
|
|
28883
|
+
firstRunDelayMs: 0,
|
|
28884
|
+
// Returned, not void-called: the registry awaits it, so the recorded
|
|
28885
|
+
// duration and outcome describe the tick rather than the call that started it.
|
|
28886
|
+
run: () => runAdminUserReconcileTick()
|
|
28887
|
+
});
|
|
28780
28888
|
var INGEST_AUDIT_INTERVAL_MS = 15 * 60 * 1e3;
|
|
28781
28889
|
var runIngestAuditTick = () => {
|
|
28782
28890
|
try {
|
|
@@ -28785,12 +28893,15 @@ var runIngestAuditTick = () => {
|
|
|
28785
28893
|
console.error(`[wa-ingest-audit] rejected: ${err instanceof Error ? err.message : String(err)}`);
|
|
28786
28894
|
}
|
|
28787
28895
|
};
|
|
28788
|
-
|
|
28789
|
-
|
|
28790
|
-
|
|
28896
|
+
registerLoop({
|
|
28897
|
+
name: "wa-ingest-audit",
|
|
28898
|
+
intervalMs: INGEST_AUDIT_INTERVAL_MS,
|
|
28899
|
+
firstRunDelayMs: 0,
|
|
28900
|
+
run: runIngestAuditTick
|
|
28901
|
+
});
|
|
28791
28902
|
var USERS_RECONCILE_INTERVAL_MS = 60 * 60 * 1e3;
|
|
28792
28903
|
function countUsersRows() {
|
|
28793
|
-
if (!
|
|
28904
|
+
if (!existsSync38(USERS_FILE)) return 0;
|
|
28794
28905
|
const raw = readFileSync41(USERS_FILE, "utf-8").trim();
|
|
28795
28906
|
if (!raw) return 0;
|
|
28796
28907
|
const users = JSON.parse(raw);
|
|
@@ -28814,9 +28925,12 @@ function runUsersReconcileTick() {
|
|
|
28814
28925
|
console.error(`[users-reconcile] op=error detail=${err instanceof Error ? err.message : String(err)}`);
|
|
28815
28926
|
}
|
|
28816
28927
|
}
|
|
28817
|
-
|
|
28818
|
-
|
|
28819
|
-
|
|
28928
|
+
registerLoop({
|
|
28929
|
+
name: "users-reconcile",
|
|
28930
|
+
intervalMs: USERS_RECONCILE_INTERVAL_MS,
|
|
28931
|
+
firstRunDelayMs: 0,
|
|
28932
|
+
run: runUsersReconcileTick
|
|
28933
|
+
});
|
|
28820
28934
|
startGraphHealthTimer();
|
|
28821
28935
|
void migrateUploads().catch((err) => console.error(`[uploads-migrate] failed err="${err instanceof Error ? err.message : String(err)}"`)).finally(() => {
|
|
28822
28936
|
void startFileWatcher().catch((err) => {
|
|
@@ -28825,9 +28939,19 @@ void migrateUploads().catch((err) => console.error(`[uploads-migrate] failed err
|
|
|
28825
28939
|
});
|
|
28826
28940
|
void sweepStaleUploadTemps().catch((err) => console.error(`[data-upload] op=sweep-failed err="${err instanceof Error ? err.message : String(err)}"`));
|
|
28827
28941
|
var CHUNK_IDLE_TTL_MS = 30 * 60 * 1e3;
|
|
28828
|
-
|
|
28829
|
-
|
|
28830
|
-
|
|
28942
|
+
registerLoop({
|
|
28943
|
+
name: "upload-chunk-evict",
|
|
28944
|
+
intervalMs: 10 * 60 * 1e3,
|
|
28945
|
+
// The domain-tagged line is kept and the rejection rethrown: existing
|
|
28946
|
+
// `[data-upload]` greps keep working AND the registry records the failure,
|
|
28947
|
+
// rather than swallowing it and reporting the run as healthy.
|
|
28948
|
+
run: () => evictStaleChunkUploads(CHUNK_IDLE_TTL_MS).then((evicted) => `evicted ${evicted}`).catch((err) => {
|
|
28949
|
+
console.error(
|
|
28950
|
+
`[data-upload] op=evict-failed err="${err instanceof Error ? err.message : String(err)}"`
|
|
28951
|
+
);
|
|
28952
|
+
throw err;
|
|
28953
|
+
})
|
|
28954
|
+
});
|
|
28831
28955
|
void migrateAdminWebchatSidecars().catch((err) => console.error(`[sidecar-backfill] failed err="${err instanceof Error ? err.message : String(err)}"`));
|
|
28832
28956
|
try {
|
|
28833
28957
|
const accounts = enumerateValidAccountIds(getAccountsDirFromEnv());
|
|
@@ -28911,7 +29035,7 @@ if (bootAccountConfig?.whatsapp) {
|
|
|
28911
29035
|
}
|
|
28912
29036
|
init({
|
|
28913
29037
|
configDir: configDirForWhatsApp,
|
|
28914
|
-
platformRoot: resolve36(process.env.MAXY_PLATFORM_ROOT ??
|
|
29038
|
+
platformRoot: resolve36(process.env.MAXY_PLATFORM_ROOT ?? join42(__dirname, "..")),
|
|
28915
29039
|
accountConfig: bootAccountConfig,
|
|
28916
29040
|
onMessage: async (msg) => {
|
|
28917
29041
|
if (msg.isOwnerMirror) {
|