@rubytech/create-maxy-code 0.1.460 → 0.1.462
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__tests__/cron-heartbeat-registration.test.js +57 -28
- package/dist/__tests__/launchd-plist.test.js +26 -0
- package/dist/cron-registration.js +30 -8
- package/dist/index.js +50 -9
- package/dist/launchd-plist.js +1 -1
- package/dist/uninstall.js +9 -3
- package/package.json +1 -1
- package/payload/platform/lib/graph-mcp/dist/index.d.ts +2 -1
- package/payload/platform/lib/graph-mcp/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/graph-mcp/dist/index.js +14 -22
- package/payload/platform/lib/graph-mcp/dist/index.js.map +1 -1
- package/payload/platform/lib/graph-mcp/src/index.ts +15 -22
- package/payload/platform/lib/mcp-spawn-tee/dist/index.d.ts +8 -7
- package/payload/platform/lib/mcp-spawn-tee/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/mcp-spawn-tee/dist/index.js +19 -19
- package/payload/platform/lib/mcp-spawn-tee/dist/index.js.map +1 -1
- package/payload/platform/lib/mcp-spawn-tee/src/__tests__/spawn-tee.test.ts +34 -5
- package/payload/platform/lib/mcp-spawn-tee/src/index.ts +22 -19
- package/payload/platform/lib/mcp-stderr-tee/dist/index.d.ts +35 -17
- package/payload/platform/lib/mcp-stderr-tee/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/mcp-stderr-tee/dist/index.js +41 -48
- package/payload/platform/lib/mcp-stderr-tee/dist/index.js.map +1 -1
- package/payload/platform/lib/mcp-stderr-tee/src/index.ts +42 -51
- package/payload/platform/lib/storage-broker/dist/__tests__/audit.test.js +27 -0
- package/payload/platform/lib/storage-broker/dist/__tests__/audit.test.js.map +1 -1
- package/payload/platform/lib/storage-broker/dist/__tests__/cf-exec.test.js +49 -0
- package/payload/platform/lib/storage-broker/dist/__tests__/cf-exec.test.js.map +1 -1
- package/payload/platform/lib/storage-broker/dist/audit.d.ts +11 -0
- package/payload/platform/lib/storage-broker/dist/audit.d.ts.map +1 -1
- package/payload/platform/lib/storage-broker/dist/audit.js +16 -0
- package/payload/platform/lib/storage-broker/dist/audit.js.map +1 -1
- package/payload/platform/lib/storage-broker/dist/cf-exec.d.ts +18 -0
- package/payload/platform/lib/storage-broker/dist/cf-exec.d.ts.map +1 -1
- package/payload/platform/lib/storage-broker/dist/cf-exec.js +77 -0
- package/payload/platform/lib/storage-broker/dist/cf-exec.js.map +1 -1
- package/payload/platform/lib/storage-broker/dist/house-scoped-token.js +3 -0
- package/payload/platform/lib/storage-broker/dist/house-scoped-token.js.map +1 -1
- package/payload/platform/lib/storage-broker/dist/registry.d.ts +1 -1
- package/payload/platform/lib/storage-broker/dist/registry.d.ts.map +1 -1
- package/payload/platform/lib/storage-broker/dist/registry.js.map +1 -1
- package/payload/platform/lib/storage-broker/src/__tests__/audit.test.ts +32 -1
- package/payload/platform/lib/storage-broker/src/__tests__/cf-exec.test.ts +61 -0
- package/payload/platform/lib/storage-broker/src/audit.ts +45 -0
- package/payload/platform/lib/storage-broker/src/cf-exec.ts +91 -0
- package/payload/platform/lib/storage-broker/src/house-scoped-token.ts +3 -0
- package/payload/platform/lib/storage-broker/src/registry.ts +5 -1
- package/payload/platform/plugins/admin/lib/mcp-spawn-tee/index.js +19 -19
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +22 -11
- package/payload/platform/plugins/aeo/lib/mcp-spawn-tee/index.js +19 -19
- package/payload/platform/plugins/browser/lib/mcp-spawn-tee/index.js +19 -19
- package/payload/platform/plugins/cloudflare/PLUGIN.md +1 -1
- package/payload/platform/plugins/cloudflare/bin/portal-enrol.mjs +96 -0
- package/payload/platform/plugins/cloudflare/mcp/__tests__/auth-route.test.ts +54 -40
- package/payload/platform/plugins/cloudflare/mcp/__tests__/passcode.test.ts +169 -39
- package/payload/platform/plugins/cloudflare/mcp/__tests__/portal-enrol.test.ts +207 -0
- package/payload/platform/plugins/cloudflare/mcp/dist/index.js +5 -5
- package/payload/platform/plugins/cloudflare/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/cloudflare/mcp/package.json +1 -1
- package/payload/platform/plugins/cloudflare/references/hosting-sites.md +2 -0
- package/payload/platform/plugins/cloudflare/skills/calendar-site/SKILL.md +1 -1
- package/payload/platform/plugins/cloudflare/skills/data-portal/SKILL.md +21 -19
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/functions/api/_lib/passcode.mjs +193 -0
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/functions/api/auth.ts +18 -12
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/schema.sql +14 -5
- package/payload/platform/plugins/cloudflare/skills/site-deploy/SKILL.md +2 -0
- package/payload/platform/plugins/connector/lib/mcp-spawn-tee/index.js +19 -19
- package/payload/platform/plugins/contacts/lib/mcp-spawn-tee/index.js +19 -19
- package/payload/platform/plugins/docs/references/admin-session.md +3 -3
- package/payload/platform/plugins/docs/references/cloudflare.md +2 -0
- package/payload/platform/plugins/docs/references/outlook-guide.md +11 -4
- package/payload/platform/plugins/docs/references/plugins-guide.md +8 -6
- package/payload/platform/plugins/email/lib/mcp-spawn-tee/index.js +19 -19
- package/payload/platform/plugins/filesystem/lib/mcp-spawn-tee/index.js +19 -19
- package/payload/platform/plugins/graph-viewer/lib/mcp-spawn-tee/index.js +19 -19
- package/payload/platform/plugins/memory/PLUGIN.md +1 -1
- package/payload/platform/plugins/memory/lib/mcp-spawn-tee/index.js +19 -19
- package/payload/platform/plugins/memory/mcp/dist/lib/log-ingest.js +2 -2
- package/payload/platform/plugins/memory/mcp/dist/lib/log-ingest.js.map +1 -1
- package/payload/platform/plugins/outlook/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/outlook/PLUGIN.md +2 -2
- package/payload/platform/plugins/outlook/lib/mcp-spawn-tee/index.js +19 -19
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-threaded.test.d.ts +2 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-threaded.test.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-threaded.test.js +238 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-threaded.test.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/index.js +9 -5
- package/payload/platform/plugins/outlook/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/tools/draft.d.ts +58 -9
- package/payload/platform/plugins/outlook/mcp/dist/tools/draft.d.ts.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/tools/draft.js +113 -19
- package/payload/platform/plugins/outlook/mcp/dist/tools/draft.js.map +1 -1
- package/payload/platform/plugins/outlook/skills/outlook/SKILL.md +5 -2
- package/payload/platform/plugins/quickbooks/lib/mcp-spawn-tee/index.js +19 -19
- package/payload/platform/plugins/replicate/lib/mcp-spawn-tee/index.js +19 -19
- package/payload/platform/plugins/scheduling/lib/mcp-spawn-tee/index.js +19 -19
- package/payload/platform/plugins/storage-broker/PLUGIN.md +9 -1
- package/payload/platform/plugins/storage-broker/lib/mcp-spawn-tee/index.js +19 -19
- package/payload/platform/plugins/storage-broker/mcp/dist/confine-path.d.ts.map +1 -1
- package/payload/platform/plugins/storage-broker/mcp/dist/confine-path.js +16 -5
- package/payload/platform/plugins/storage-broker/mcp/dist/confine-path.js.map +1 -1
- package/payload/platform/plugins/storage-broker/mcp/dist/index.js +49 -0
- package/payload/platform/plugins/storage-broker/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/telegram/lib/mcp-spawn-tee/index.js +19 -19
- package/payload/platform/plugins/url-get/lib/mcp-spawn-tee/index.js +19 -19
- package/payload/platform/plugins/voice-mirror/PLUGIN.md +1 -1
- package/payload/platform/plugins/voice-mirror/lib/mcp-spawn-tee/index.js +19 -19
- package/payload/platform/plugins/voice-mirror/mcp/dist/tools/voice-distil-profile.d.ts.map +1 -1
- package/payload/platform/plugins/voice-mirror/mcp/dist/tools/voice-distil-profile.js +98 -9
- package/payload/platform/plugins/voice-mirror/mcp/dist/tools/voice-distil-profile.js.map +1 -1
- package/payload/platform/plugins/voice-mirror/mcp/dist/tools/voice-retrieve-conditioning.d.ts.map +1 -1
- package/payload/platform/plugins/voice-mirror/mcp/dist/tools/voice-retrieve-conditioning.js +54 -21
- package/payload/platform/plugins/voice-mirror/mcp/dist/tools/voice-retrieve-conditioning.js.map +1 -1
- package/payload/platform/plugins/voice-mirror/mcp/scripts/smoke.mjs +110 -0
- package/payload/platform/plugins/voice-mirror/skills/voice-mirror/SKILL.md +6 -3
- package/payload/platform/plugins/web-designer/PLUGIN.md +1 -1
- package/payload/platform/plugins/web-designer/commands/website.md +6 -0
- package/payload/platform/plugins/web-designer/skills/web-design/references/deploy.md +12 -0
- package/payload/platform/plugins/whatsapp/lib/mcp-spawn-tee/index.js +19 -19
- package/payload/platform/plugins/work/lib/mcp-spawn-tee/index.js +19 -19
- package/payload/platform/plugins/workflows/lib/mcp-spawn-tee/index.js +19 -19
- package/payload/platform/scripts/__tests__/logs-rotate.test.sh +260 -0
- package/payload/platform/scripts/__tests__/resume-tunnel.test.sh +79 -0
- package/payload/platform/scripts/logs-read.sh +31 -0
- package/payload/platform/scripts/logs-rotate.sh +207 -0
- package/payload/platform/scripts/resume-tunnel.sh +27 -0
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +2 -0
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.js +41 -5
- package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/index.d.ts +1 -0
- package/payload/platform/services/claude-session-manager/dist/index.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/index.js +22 -0
- package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/install-start-counter.d.ts +2 -0
- package/payload/platform/services/claude-session-manager/dist/install-start-counter.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/install-start-counter.js +12 -0
- package/payload/platform/services/claude-session-manager/dist/install-start-counter.js.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/pty-census.d.ts +122 -9
- package/payload/platform/services/claude-session-manager/dist/pty-census.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-census.js +214 -29
- package/payload/platform/services/claude-session-manager/dist/pty-census.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +39 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts +5 -3
- package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/rc-daemon.js +13 -1
- package/payload/platform/services/claude-session-manager/dist/rc-daemon.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/session-memory-cap.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/session-memory-cap.js +4 -2
- package/payload/platform/services/claude-session-manager/dist/session-memory-cap.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/slice-memory-policy.d.ts +150 -0
- package/payload/platform/services/claude-session-manager/dist/slice-memory-policy.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/slice-memory-policy.js +333 -0
- package/payload/platform/services/claude-session-manager/dist/slice-memory-policy.js.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/start-counter.d.ts +10 -0
- package/payload/platform/services/claude-session-manager/dist/start-counter.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/start-counter.js +55 -0
- package/payload/platform/services/claude-session-manager/dist/start-counter.js.map +1 -0
- package/payload/server/{chunk-JXWFVE5X.js → chunk-BBSPFN45.js} +65 -0
- package/payload/server/public/assets/{AdminLoginScreens-BFbpkEUS.js → AdminLoginScreens-Bed8SDxY.js} +1 -1
- package/payload/server/public/assets/{AdminShell-CdOGObaZ.js → AdminShell-BLh9O6dn.js} +1 -1
- package/payload/server/public/assets/{Checkbox-RFD_F0c0.js → Checkbox-BC_KSbpS.js} +1 -1
- package/payload/server/public/assets/{admin-CYGdL-1O.js → admin-DfWgJVI3.js} +1 -1
- package/payload/server/public/assets/{browser-DVfa_plj.js → browser-C0vkv-hH.js} +1 -1
- package/payload/server/public/assets/{calendar-JC_Dxa4n.js → calendar-_pfHw0Hp.js} +1 -1
- package/payload/server/public/assets/chat-CufidiBQ.js +1 -0
- package/payload/server/public/assets/chevron-left-BnpVBu51.js +1 -0
- package/payload/server/public/assets/data-CR-fbPWr.js +1 -0
- package/payload/server/public/assets/{graph-hBUrRSkr.js → graph-BZiudUGr.js} +1 -1
- package/payload/server/public/assets/{graph-labels-CHh6zs8t.js → graph-labels-BzmmJwCR.js} +1 -1
- package/payload/server/public/assets/{maximize-2-DjxE4rm9.js → maximize-2-Bhdsv0U-.js} +1 -1
- package/payload/server/public/assets/{operator-BqU9SQuu.js → operator-Cj0B_usT.js} +1 -1
- package/payload/server/public/assets/page-84Fdwiu_.js +32 -0
- package/payload/server/public/assets/{page-DiQhU6lD.js → page-8AB3jUa_.js} +1 -1
- package/payload/server/public/assets/{public-Cu_eALgY.js → public-BkNW9e9T.js} +1 -1
- package/payload/server/public/assets/{rotate-ccw-F9DsSTSJ.js → rotate-ccw-D_5cETGt.js} +1 -1
- package/payload/server/public/assets/{tasks-CE-D0f50.js → tasks-EyKLXINi.js} +1 -1
- package/payload/server/public/assets/{time-entry-format-D2rsWhov.js → time-entry-format-DAwmmR3i.js} +1 -1
- package/payload/server/public/assets/{useCopyFeedback-QxOmoobV.js → useCopyFeedback-rOWd_lzl.js} +1 -1
- package/payload/server/public/assets/{useSelectionMode-RIzNqFjV.js → useSelectionMode-DDmLmPph.js} +1 -1
- package/payload/server/public/assets/{useSubAccountSwitcher-BW_fK1Nt.css → useSubAccountSwitcher-pu0jjLCz.css} +1 -1
- package/payload/server/public/assets/{useVoiceRecorder-WrWurSYI.js → useVoiceRecorder-azG8zSUI.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 +10 -10
- package/payload/server/public/graph.html +11 -11
- package/payload/server/public/index.html +13 -13
- 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 +581 -209
- package/payload/server/{src-4F37OHLK.js → src-YLGAZY36.js} +5 -1
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/functions/api/_lib/passcode.ts +0 -73
- package/payload/server/public/assets/chat-Yf8Nkop8.js +0 -1
- package/payload/server/public/assets/chevron-left-CAiAUBxO.js +0 -1
- package/payload/server/public/assets/data-hqdYXaEn.js +0 -1
- package/payload/server/public/assets/page-B4c4_4HP.js +0 -32
- /package/payload/server/public/assets/{useSubAccountSwitcher-wo_qGW-I.js → useSubAccountSwitcher-CU-lOxTd.js} +0 -0
package/payload/server/server.js
CHANGED
|
@@ -122,10 +122,11 @@ import {
|
|
|
122
122
|
authorizeAccess,
|
|
123
123
|
listResources,
|
|
124
124
|
makeHouseCfExec,
|
|
125
|
+
makeHousePagesExec,
|
|
125
126
|
registerResource,
|
|
126
127
|
resolveOwner,
|
|
127
128
|
tooLargeMessage
|
|
128
|
-
} from "./chunk-
|
|
129
|
+
} from "./chunk-BBSPFN45.js";
|
|
129
130
|
import {
|
|
130
131
|
__commonJS,
|
|
131
132
|
__toESM
|
|
@@ -1535,7 +1536,7 @@ var serveStatic = (options = { root: "" }) => {
|
|
|
1535
1536
|
import { readFileSync as readFileSync38, existsSync as existsSync36, watchFile, readdirSync as readdirSync21, statSync as statSync14 } from "fs";
|
|
1536
1537
|
import { spawn as spawn3 } from "child_process";
|
|
1537
1538
|
import { createHash as createHash7 } from "crypto";
|
|
1538
|
-
import { resolve as
|
|
1539
|
+
import { resolve as resolve36, join as join38, basename as basename12 } from "path";
|
|
1539
1540
|
import { homedir as homedir4 } from "os";
|
|
1540
1541
|
import { monitorEventLoopDelay } from "perf_hooks";
|
|
1541
1542
|
|
|
@@ -2248,7 +2249,7 @@ var credsSaveQueue = Promise.resolve();
|
|
|
2248
2249
|
async function drainCredsSaveQueue(timeoutMs = 5e3) {
|
|
2249
2250
|
console.error(`${TAG2} draining credential save queue\u2026`);
|
|
2250
2251
|
const timer2 = new Promise(
|
|
2251
|
-
(
|
|
2252
|
+
(resolve37) => setTimeout(() => resolve37("timeout"), timeoutMs)
|
|
2252
2253
|
);
|
|
2253
2254
|
const result = await Promise.race([
|
|
2254
2255
|
credsSaveQueue.then(() => "drained"),
|
|
@@ -2411,11 +2412,11 @@ async function createWaSocket(opts) {
|
|
|
2411
2412
|
return sock;
|
|
2412
2413
|
}
|
|
2413
2414
|
async function waitForConnection(sock) {
|
|
2414
|
-
return new Promise((
|
|
2415
|
+
return new Promise((resolve37, reject) => {
|
|
2415
2416
|
const handler = (update) => {
|
|
2416
2417
|
if (update.connection === "open") {
|
|
2417
2418
|
sock.ev.off("connection.update", handler);
|
|
2418
|
-
|
|
2419
|
+
resolve37();
|
|
2419
2420
|
}
|
|
2420
2421
|
if (update.connection === "close") {
|
|
2421
2422
|
sock.ev.off("connection.update", handler);
|
|
@@ -2520,7 +2521,7 @@ import { inspect as inspect2 } from "util";
|
|
|
2520
2521
|
|
|
2521
2522
|
// app/lib/whatsapp/with-timeout.ts
|
|
2522
2523
|
function withTimeout(label, promise, timeoutMs) {
|
|
2523
|
-
return new Promise((
|
|
2524
|
+
return new Promise((resolve37, reject) => {
|
|
2524
2525
|
const timer2 = setTimeout(() => {
|
|
2525
2526
|
reject(new Error(`${label} timed out after ${timeoutMs}ms`));
|
|
2526
2527
|
}, timeoutMs);
|
|
@@ -2528,7 +2529,7 @@ function withTimeout(label, promise, timeoutMs) {
|
|
|
2528
2529
|
promise.then(
|
|
2529
2530
|
(value) => {
|
|
2530
2531
|
clearTimeout(timer2);
|
|
2531
|
-
|
|
2532
|
+
resolve37(value);
|
|
2532
2533
|
},
|
|
2533
2534
|
(err) => {
|
|
2534
2535
|
clearTimeout(timer2);
|
|
@@ -3779,8 +3780,8 @@ async function persistWhatsAppMessage(input) {
|
|
|
3779
3780
|
const { givenName, familyName } = splitName(input.pushName);
|
|
3780
3781
|
const prev = sessionWriteLocks.get(input.cacheKey);
|
|
3781
3782
|
let release;
|
|
3782
|
-
const mine = new Promise((
|
|
3783
|
-
release =
|
|
3783
|
+
const mine = new Promise((resolve37) => {
|
|
3784
|
+
release = resolve37;
|
|
3784
3785
|
});
|
|
3785
3786
|
const chained = (prev ?? Promise.resolve()).then(() => mine);
|
|
3786
3787
|
sessionWriteLocks.set(input.cacheKey, chained);
|
|
@@ -5484,11 +5485,11 @@ async function connectWithReconnect(conn) {
|
|
|
5484
5485
|
console.error(
|
|
5485
5486
|
`${TAG13} reconnecting account=${conn.accountId} in ${delay}ms (attempt ${decision.nextAttempts}/${maxAttempts})`
|
|
5486
5487
|
);
|
|
5487
|
-
await new Promise((
|
|
5488
|
-
const timer2 = setTimeout(
|
|
5488
|
+
await new Promise((resolve37) => {
|
|
5489
|
+
const timer2 = setTimeout(resolve37, delay);
|
|
5489
5490
|
conn.abortController.signal.addEventListener("abort", () => {
|
|
5490
5491
|
clearTimeout(timer2);
|
|
5491
|
-
|
|
5492
|
+
resolve37();
|
|
5492
5493
|
}, { once: true });
|
|
5493
5494
|
});
|
|
5494
5495
|
}
|
|
@@ -5496,16 +5497,16 @@ async function connectWithReconnect(conn) {
|
|
|
5496
5497
|
}
|
|
5497
5498
|
}
|
|
5498
5499
|
function waitForDisconnectEvent(conn) {
|
|
5499
|
-
return new Promise((
|
|
5500
|
+
return new Promise((resolve37) => {
|
|
5500
5501
|
if (!conn.sock) {
|
|
5501
|
-
|
|
5502
|
+
resolve37();
|
|
5502
5503
|
return;
|
|
5503
5504
|
}
|
|
5504
5505
|
const sock = conn.sock;
|
|
5505
5506
|
const handler = (update) => {
|
|
5506
5507
|
if (update.connection === "close") {
|
|
5507
5508
|
sock.ev.off("connection.update", handler);
|
|
5508
|
-
|
|
5509
|
+
resolve37();
|
|
5509
5510
|
}
|
|
5510
5511
|
};
|
|
5511
5512
|
sock.ev.on("connection.update", handler);
|
|
@@ -5873,8 +5874,8 @@ async function handleInboundMessage(conn, msg) {
|
|
|
5873
5874
|
const conversationKey = isGroup ? remoteJid : senderPhone;
|
|
5874
5875
|
const debounceKey = `${conn.accountId}:${conversationKey}:${senderPhone}`;
|
|
5875
5876
|
let resolvePending;
|
|
5876
|
-
const sttPending = new Promise((
|
|
5877
|
-
resolvePending =
|
|
5877
|
+
const sttPending = new Promise((resolve37) => {
|
|
5878
|
+
resolvePending = resolve37;
|
|
5878
5879
|
});
|
|
5879
5880
|
if (conn.debouncer) conn.debouncer.registerPending(debounceKey, sttPending);
|
|
5880
5881
|
try {
|
|
@@ -6302,20 +6303,20 @@ function buildX11Env(chromiumWrapperPath, transport = "vnc") {
|
|
|
6302
6303
|
|
|
6303
6304
|
// server/routes/health.ts
|
|
6304
6305
|
function checkPort(port2, timeoutMs = 500) {
|
|
6305
|
-
return new Promise((
|
|
6306
|
+
return new Promise((resolve37) => {
|
|
6306
6307
|
const socket = createConnection2(port2, "127.0.0.1");
|
|
6307
6308
|
socket.setTimeout(timeoutMs);
|
|
6308
6309
|
socket.once("connect", () => {
|
|
6309
6310
|
socket.destroy();
|
|
6310
|
-
|
|
6311
|
+
resolve37(true);
|
|
6311
6312
|
});
|
|
6312
6313
|
socket.once("error", () => {
|
|
6313
6314
|
socket.destroy();
|
|
6314
|
-
|
|
6315
|
+
resolve37(false);
|
|
6315
6316
|
});
|
|
6316
6317
|
socket.once("timeout", () => {
|
|
6317
6318
|
socket.destroy();
|
|
6318
|
-
|
|
6319
|
+
resolve37(false);
|
|
6319
6320
|
});
|
|
6320
6321
|
});
|
|
6321
6322
|
}
|
|
@@ -6780,7 +6781,7 @@ ${result.result.text}` : result.result.text;
|
|
|
6780
6781
|
spawnedAt: /* @__PURE__ */ new Date()
|
|
6781
6782
|
});
|
|
6782
6783
|
const replyP = deps.awaitReply(session_key, webchatTurnTimeoutMs());
|
|
6783
|
-
await deps.handleInbound({
|
|
6784
|
+
const { spawn: spawn4 } = await deps.handleInbound({
|
|
6784
6785
|
role: "public",
|
|
6785
6786
|
accountId: account.accountId,
|
|
6786
6787
|
key: session_key,
|
|
@@ -6793,6 +6794,7 @@ ${result.result.text}` : result.result.text;
|
|
|
6793
6794
|
name: publicTitle
|
|
6794
6795
|
}
|
|
6795
6796
|
});
|
|
6797
|
+
if (spawn4) await spawn4;
|
|
6796
6798
|
const reply = await replyP;
|
|
6797
6799
|
if ("timeout" in reply) {
|
|
6798
6800
|
controller.enqueue(
|
|
@@ -7592,8 +7594,8 @@ async function startLogin(opts) {
|
|
|
7592
7594
|
await clearAuth(authDir);
|
|
7593
7595
|
let resolveCode = null;
|
|
7594
7596
|
let rejectCode = null;
|
|
7595
|
-
const codePromise = new Promise((
|
|
7596
|
-
resolveCode =
|
|
7597
|
+
const codePromise = new Promise((resolve37, reject) => {
|
|
7598
|
+
resolveCode = resolve37;
|
|
7597
7599
|
rejectCode = reject;
|
|
7598
7600
|
});
|
|
7599
7601
|
const codeTimer = setTimeout(
|
|
@@ -7765,14 +7767,14 @@ function routeDocumentOutboundAt(to, filePath) {
|
|
|
7765
7767
|
return lastRouteDocumentOutboundAt.get(routeKey(to, filePath));
|
|
7766
7768
|
}
|
|
7767
7769
|
async function sendWhatsAppDocument(input) {
|
|
7768
|
-
const { to, filePath, caption, accountId, maxyAccountId, platformRoot:
|
|
7770
|
+
const { to, filePath, caption, accountId, maxyAccountId, platformRoot: platformRoot5 } = input;
|
|
7769
7771
|
if (!to || !filePath) {
|
|
7770
7772
|
return { ok: false, status: 400, error: "Missing required fields: to, filePath" };
|
|
7771
7773
|
}
|
|
7772
|
-
if (!maxyAccountId || !
|
|
7774
|
+
if (!maxyAccountId || !platformRoot5) {
|
|
7773
7775
|
return { ok: false, status: 400, error: "Cannot validate file path: missing account or platform context" };
|
|
7774
7776
|
}
|
|
7775
|
-
const accountDir = resolve9(
|
|
7777
|
+
const accountDir = resolve9(platformRoot5, "..", "data/accounts", maxyAccountId);
|
|
7776
7778
|
let resolvedPath;
|
|
7777
7779
|
try {
|
|
7778
7780
|
resolvedPath = realpathSync3(filePath);
|
|
@@ -8733,7 +8735,8 @@ var bodyLimit = (options) => {
|
|
|
8733
8735
|
|
|
8734
8736
|
// server/routes/storage-broker.ts
|
|
8735
8737
|
import { join as join11, resolve as resolve11 } from "path";
|
|
8736
|
-
import { readdirSync as readdirSync6, readFileSync as readFileSync13, existsSync as existsSync8 } from "fs";
|
|
8738
|
+
import { readdirSync as readdirSync6, readFileSync as readFileSync13, existsSync as existsSync8, realpathSync as realpathSync4 } from "fs";
|
|
8739
|
+
import { randomUUID as randomUUID7 } from "crypto";
|
|
8737
8740
|
var app3 = new Hono();
|
|
8738
8741
|
function platformRoot() {
|
|
8739
8742
|
return process.env.MAXY_PLATFORM_ROOT ?? process.env.PLATFORM_ROOT ?? join11(__dirname, "..", "..");
|
|
@@ -8792,6 +8795,125 @@ var d1QueryBodyLimit = bodyLimit({
|
|
|
8792
8795
|
);
|
|
8793
8796
|
}
|
|
8794
8797
|
});
|
|
8798
|
+
var pagesDeployBodyLimit = bodyLimit({
|
|
8799
|
+
maxSize: STORAGE_RESOURCE_NAME_MAX_BODY_BYTES,
|
|
8800
|
+
onError: (c) => {
|
|
8801
|
+
log("write", "pages", caller(c) ?? "none", "*", null, "deny", "publish-body-too-large");
|
|
8802
|
+
return c.json(
|
|
8803
|
+
{
|
|
8804
|
+
error: `request body exceeds the ${(STORAGE_RESOURCE_NAME_MAX_BODY_BYTES / 1024).toFixed(
|
|
8805
|
+
1
|
|
8806
|
+
)} KiB (${STORAGE_RESOURCE_NAME_MAX_BODY_BYTES} bytes) limit for a Pages publish, which carries only a project name, a site folder name and an optional branch.`
|
|
8807
|
+
},
|
|
8808
|
+
413
|
|
8809
|
+
);
|
|
8810
|
+
}
|
|
8811
|
+
});
|
|
8812
|
+
function resolveSiteDir(account, site) {
|
|
8813
|
+
if (!site || site === "." || site === "..") return null;
|
|
8814
|
+
if (site.includes("/") || site.includes("\\") || site.includes("\0")) return null;
|
|
8815
|
+
const accountsDir = resolve11(platformRoot(), "..", "data", "accounts");
|
|
8816
|
+
const base = resolve11(accountsDir, account, "sites");
|
|
8817
|
+
const dir = resolve11(base, site);
|
|
8818
|
+
if (dir !== base && !dir.startsWith(base + "/")) return null;
|
|
8819
|
+
try {
|
|
8820
|
+
const realBase = realpathSync4(base);
|
|
8821
|
+
const realDir = realpathSync4(dir);
|
|
8822
|
+
if (!realDir.startsWith(realBase + "/")) return null;
|
|
8823
|
+
return realDir;
|
|
8824
|
+
} catch {
|
|
8825
|
+
return null;
|
|
8826
|
+
}
|
|
8827
|
+
}
|
|
8828
|
+
async function verifyDeployed(url) {
|
|
8829
|
+
try {
|
|
8830
|
+
const res = await fetch(`${url}?cb=${Date.now()}`, { method: "GET", redirect: "follow" });
|
|
8831
|
+
return res.status;
|
|
8832
|
+
} catch {
|
|
8833
|
+
return null;
|
|
8834
|
+
}
|
|
8835
|
+
}
|
|
8836
|
+
app3.post("/pages/deploy", pagesDeployBodyLimit, async (c) => {
|
|
8837
|
+
const pub = randomUUID7().slice(0, 8);
|
|
8838
|
+
const account = caller(c);
|
|
8839
|
+
if (!account) {
|
|
8840
|
+
log("write", "pages", "none", "*", null, "deny", "no-caller");
|
|
8841
|
+
return c.json({ error: "no-caller" }, 403);
|
|
8842
|
+
}
|
|
8843
|
+
const parsed = await readJsonBody(c);
|
|
8844
|
+
if (!parsed.ok) return parsed.res;
|
|
8845
|
+
const { project, site, branch } = parsed.body;
|
|
8846
|
+
if (!project || typeof project !== "string") return c.json({ error: "project-required" }, 400);
|
|
8847
|
+
if (!site || typeof site !== "string") return c.json({ error: "site-required" }, 400);
|
|
8848
|
+
if (branch !== void 0 && typeof branch !== "string") return c.json({ error: "branch-invalid" }, 400);
|
|
8849
|
+
console.error(
|
|
8850
|
+
`[pages-broker] op=request pub=${pub} caller=${account} project=${project} site=${site} branch=${branch ?? "default"}`
|
|
8851
|
+
);
|
|
8852
|
+
const dir = resolveSiteDir(account, site);
|
|
8853
|
+
if (dir === null) {
|
|
8854
|
+
console.error(`[pages-broker] op=path pub=${pub} site=${site} inside=false`);
|
|
8855
|
+
log("write", "pages", account, String(site), null, "deny", "invalid-site");
|
|
8856
|
+
return c.json({ error: "invalid-site" }, 400);
|
|
8857
|
+
}
|
|
8858
|
+
console.error(`[pages-broker] op=path pub=${pub} resolved=${dir} inside=true`);
|
|
8859
|
+
const session = getSession();
|
|
8860
|
+
try {
|
|
8861
|
+
const owner = await resolveOwner(session, "pages", project);
|
|
8862
|
+
const decision = authorizeAccess({ caller: account, owner, action: "write" });
|
|
8863
|
+
console.error(
|
|
8864
|
+
`[pages-broker] op=authorize pub=${pub} caller=${account} owner=${owner ?? "none"} decision=${decision.allow ? "allow" : "deny"} reason=${decision.reason}`
|
|
8865
|
+
);
|
|
8866
|
+
log("write", "pages", account, project, owner, decision.allow ? "allow" : "deny", decision.allow ? void 0 : decision.reason);
|
|
8867
|
+
if (!decision.allow) return c.json({ error: decision.reason }, 403);
|
|
8868
|
+
const started = Date.now();
|
|
8869
|
+
const { url } = await (await makeHousePagesExec(platformRoot())).pagesDeploy(dir, project, branch);
|
|
8870
|
+
console.error(`[pages-broker] op=deploy pub=${pub} ranMs=${Date.now() - started} url=${url}`);
|
|
8871
|
+
const httpStatus = await verifyDeployed(url);
|
|
8872
|
+
const verified = httpStatus === 200;
|
|
8873
|
+
console.error(
|
|
8874
|
+
`[pages-broker] op=complete pub=${pub} httpStatus=${httpStatus ?? "unreachable"} verified=${verified}`
|
|
8875
|
+
);
|
|
8876
|
+
if (!verified) {
|
|
8877
|
+
return c.json({ error: "deploy-unverified", url, httpStatus }, 502);
|
|
8878
|
+
}
|
|
8879
|
+
return c.json({ url });
|
|
8880
|
+
} catch (err) {
|
|
8881
|
+
console.error(`[pages-broker] op=exit pub=${pub} result=error detail="${String(err)}"`);
|
|
8882
|
+
return c.json({ error: String(err) }, 500);
|
|
8883
|
+
} finally {
|
|
8884
|
+
await session.close();
|
|
8885
|
+
}
|
|
8886
|
+
});
|
|
8887
|
+
app3.post("/pages/adopt", nameBodyLimit("pages"), async (c) => {
|
|
8888
|
+
const houseAdminScope = c.req.header("x-maxy-house-admin-scope")?.trim() || null;
|
|
8889
|
+
const account = caller(c);
|
|
8890
|
+
if (!houseAdminScope) {
|
|
8891
|
+
log("write", "pages", account ?? "none", "*", null, "deny", "not-house-admin");
|
|
8892
|
+
return c.json({ error: "not-house-admin" }, 403);
|
|
8893
|
+
}
|
|
8894
|
+
const parsed = await readJsonBody(c);
|
|
8895
|
+
if (!parsed.ok) return parsed.res;
|
|
8896
|
+
const { project, account: target } = parsed.body;
|
|
8897
|
+
if (!project || typeof project !== "string") return c.json({ error: "project-required" }, 400);
|
|
8898
|
+
if (!target || typeof target !== "string") return c.json({ error: "account-required" }, 400);
|
|
8899
|
+
const session = getSession();
|
|
8900
|
+
try {
|
|
8901
|
+
const owner = await resolveOwner(session, "pages", project);
|
|
8902
|
+
if (owner !== null && owner !== target) {
|
|
8903
|
+
log("write", "pages", target, project, owner, "deny", "already-owned");
|
|
8904
|
+
return c.json({ error: "already-owned", owner }, 409);
|
|
8905
|
+
}
|
|
8906
|
+
if (owner === null) {
|
|
8907
|
+
await registerResource(session, { accountId: target, kind: "pages", name: project, cfResourceId: project });
|
|
8908
|
+
}
|
|
8909
|
+
log("write", "pages", target, project, target, "allow");
|
|
8910
|
+
return c.json({ project, account: target });
|
|
8911
|
+
} catch (err) {
|
|
8912
|
+
return c.json({ error: String(err) }, 500);
|
|
8913
|
+
} finally {
|
|
8914
|
+
await session.close();
|
|
8915
|
+
}
|
|
8916
|
+
});
|
|
8795
8917
|
app3.get("/d1/list", async (c) => {
|
|
8796
8918
|
const account = caller(c);
|
|
8797
8919
|
if (!account) return c.json({ error: "no-caller" }, 403);
|
|
@@ -9061,7 +9183,7 @@ app3.post("/r2/object/delete", envelopeBodyLimit("write"), async (c) => {
|
|
|
9061
9183
|
});
|
|
9062
9184
|
var storage_broker_default = app3;
|
|
9063
9185
|
async function runStorageAudit(root) {
|
|
9064
|
-
const { reconcileStorage } = await import("./src-
|
|
9186
|
+
const { reconcileStorage } = await import("./src-YLGAZY36.js");
|
|
9065
9187
|
const session = getSession();
|
|
9066
9188
|
try {
|
|
9067
9189
|
const cf = await makeHouseCfExec(root);
|
|
@@ -9093,9 +9215,31 @@ async function runStorageAudit(root) {
|
|
|
9093
9215
|
await session.close();
|
|
9094
9216
|
}
|
|
9095
9217
|
}
|
|
9218
|
+
async function runPagesAudit(root) {
|
|
9219
|
+
const { reconcilePages } = await import("./src-YLGAZY36.js");
|
|
9220
|
+
const session = getSession();
|
|
9221
|
+
try {
|
|
9222
|
+
const cf = await makeHousePagesExec(root);
|
|
9223
|
+
const r = await reconcilePages({
|
|
9224
|
+
cfProjects: async () => (await cf.pagesProjectList()).map((p) => p.name),
|
|
9225
|
+
registeredProjects: async () => {
|
|
9226
|
+
const res = await session.run(
|
|
9227
|
+
"MATCH (r:StorageResource {kind: $kind}) RETURN r.name AS name",
|
|
9228
|
+
{ kind: "pages" }
|
|
9229
|
+
);
|
|
9230
|
+
return res.records.map((rec) => rec.get("name"));
|
|
9231
|
+
}
|
|
9232
|
+
});
|
|
9233
|
+
console.error(
|
|
9234
|
+
`[pages-audit] projects=${r.projects} registered=${r.registered} orphan=${r.orphans.length} phantom=${r.phantoms.length}` + r.orphans.map((n) => ` orphan:${n}`).join("") + r.phantoms.map((n) => ` phantom:${n}`).join("")
|
|
9235
|
+
);
|
|
9236
|
+
} finally {
|
|
9237
|
+
await session.close();
|
|
9238
|
+
}
|
|
9239
|
+
}
|
|
9096
9240
|
|
|
9097
9241
|
// server/routes/whatsapp-reader.ts
|
|
9098
|
-
import { readFileSync as readFileSync17, watch, statSync as statSync5, openSync, readSync, closeSync, existsSync as existsSync11, readdirSync as readdirSync11, realpathSync as
|
|
9242
|
+
import { readFileSync as readFileSync17, watch, statSync as statSync5, openSync, readSync, closeSync, existsSync as existsSync11, readdirSync as readdirSync11, realpathSync as realpathSync5 } from "fs";
|
|
9099
9243
|
import { basename as basename4, dirname as dirname5, isAbsolute, join as join16, relative as relative2, resolve as resolve13, sep as sep3 } from "path";
|
|
9100
9244
|
|
|
9101
9245
|
// server/routes/admin/sidebar-sessions.ts
|
|
@@ -9727,7 +9871,31 @@ function joinTextBlocks(content) {
|
|
|
9727
9871
|
}
|
|
9728
9872
|
return parts.join("");
|
|
9729
9873
|
}
|
|
9730
|
-
function
|
|
9874
|
+
function erroredToolUseIds(lines) {
|
|
9875
|
+
const ids = /* @__PURE__ */ new Set();
|
|
9876
|
+
for (const line of lines) {
|
|
9877
|
+
if (!line || line[0] !== "{" || !line.includes("is_error")) continue;
|
|
9878
|
+
let row;
|
|
9879
|
+
try {
|
|
9880
|
+
const parsed = JSON.parse(line);
|
|
9881
|
+
if (!parsed || typeof parsed !== "object") continue;
|
|
9882
|
+
row = parsed;
|
|
9883
|
+
} catch {
|
|
9884
|
+
continue;
|
|
9885
|
+
}
|
|
9886
|
+
const content = row.message?.content;
|
|
9887
|
+
if (!Array.isArray(content)) continue;
|
|
9888
|
+
for (const block of content) {
|
|
9889
|
+
if (!block || typeof block !== "object") continue;
|
|
9890
|
+
const b = block;
|
|
9891
|
+
if (b.type === "tool_result" && b.is_error === true && typeof b.tool_use_id === "string") {
|
|
9892
|
+
ids.add(b.tool_use_id);
|
|
9893
|
+
}
|
|
9894
|
+
}
|
|
9895
|
+
}
|
|
9896
|
+
return ids;
|
|
9897
|
+
}
|
|
9898
|
+
function assistantTurns(content, ts, promoteFinal = false, erroredIds = /* @__PURE__ */ new Set()) {
|
|
9731
9899
|
if (!Array.isArray(content)) return [];
|
|
9732
9900
|
const out = [];
|
|
9733
9901
|
for (const block of content) {
|
|
@@ -9747,7 +9915,12 @@ function assistantTurns(content, ts, promoteFinal = false) {
|
|
|
9747
9915
|
const input = b.input ?? {};
|
|
9748
9916
|
const files = Array.isArray(input.files) ? input.files.filter((f) => typeof f === "string") : [];
|
|
9749
9917
|
const caption = typeof input.caption === "string" ? input.caption : null;
|
|
9750
|
-
|
|
9918
|
+
const refused = typeof b.id === "string" && erroredIds.has(b.id);
|
|
9919
|
+
if (files.length === 0 || refused) {
|
|
9920
|
+
out.push({ kind: "tool-call", name: SEND_USER_FILE_TOOL, input: b.input ?? null, ts });
|
|
9921
|
+
} else {
|
|
9922
|
+
out.push({ kind: "agent-file", files, caption, ts });
|
|
9923
|
+
}
|
|
9751
9924
|
} else if (b.type === "tool_use" && typeof b.name === "string") {
|
|
9752
9925
|
out.push({ kind: "tool-call", name: b.name, input: b.input ?? null, ts });
|
|
9753
9926
|
}
|
|
@@ -9787,6 +9960,7 @@ function renderOrSuppressChannelInbound(u, ts, out, queuedPendingSuppress) {
|
|
|
9787
9960
|
}
|
|
9788
9961
|
function parseTranscript(lines, queuedPendingSuppress = /* @__PURE__ */ new Map(), turnCtx = {}) {
|
|
9789
9962
|
const out = [];
|
|
9963
|
+
const erroredIds = erroredToolUseIds(lines);
|
|
9790
9964
|
for (const line of lines) {
|
|
9791
9965
|
if (!line || line[0] !== "{") continue;
|
|
9792
9966
|
let row;
|
|
@@ -9811,7 +9985,7 @@ function parseTranscript(lines, queuedPendingSuppress = /* @__PURE__ */ new Map(
|
|
|
9811
9985
|
if (hasWebchatReply(msg?.content)) turnCtx.repliedThisTurn = true;
|
|
9812
9986
|
const isEnd = msg?.stop_reason === "end_turn";
|
|
9813
9987
|
const promoteFinal = isEnd && turnCtx.lastChannelSource === "webchat" && !turnCtx.repliedThisTurn;
|
|
9814
|
-
out.push(...assistantTurns(msg?.content, ts, promoteFinal));
|
|
9988
|
+
out.push(...assistantTurns(msg?.content, ts, promoteFinal, erroredIds));
|
|
9815
9989
|
continue;
|
|
9816
9990
|
}
|
|
9817
9991
|
if (row.type === "queue-operation" && row.operation === "enqueue") {
|
|
@@ -10208,7 +10382,7 @@ function enrichDownloads(turn, scratchpadRoot) {
|
|
|
10208
10382
|
if (turn.kind !== "agent-file") return turn;
|
|
10209
10383
|
let scratchpadReal = null;
|
|
10210
10384
|
try {
|
|
10211
|
-
scratchpadReal =
|
|
10385
|
+
scratchpadReal = realpathSync5(scratchpadRoot);
|
|
10212
10386
|
} catch {
|
|
10213
10387
|
scratchpadReal = null;
|
|
10214
10388
|
}
|
|
@@ -10219,7 +10393,7 @@ function enrichDownloads(turn, scratchpadRoot) {
|
|
|
10219
10393
|
}
|
|
10220
10394
|
if (scratchpadReal) {
|
|
10221
10395
|
try {
|
|
10222
|
-
const fileReal =
|
|
10396
|
+
const fileReal = realpathSync5(f);
|
|
10223
10397
|
if (fileReal === scratchpadReal || fileReal.startsWith(scratchpadReal + sep3)) {
|
|
10224
10398
|
return { root: "scratchpad", path: relative2(scratchpadReal, fileReal) };
|
|
10225
10399
|
}
|
|
@@ -11881,7 +12055,7 @@ ${note}` : note;
|
|
|
11881
12055
|
console.error(`[webchat:inbound] op=send-refused kind=${kind} reason=empty-text`);
|
|
11882
12056
|
return c.json({ error: "text required" }, 400);
|
|
11883
12057
|
}
|
|
11884
|
-
console.log(`[webchat:inbound] op=send-
|
|
12058
|
+
console.log(`[webchat:inbound] op=send-parsed kind=${kind} files=${stored.length} bytes=${Buffer.byteLength(text, "utf8")}`);
|
|
11885
12059
|
}
|
|
11886
12060
|
let deliveredIntId = null;
|
|
11887
12061
|
if (deliverySessionId !== void 0 && await managerActivity(deliverySessionId) === "busy") {
|
|
@@ -11893,11 +12067,8 @@ ${note}` : note;
|
|
|
11893
12067
|
deliveredIntId = outcome.intId;
|
|
11894
12068
|
}
|
|
11895
12069
|
const adminUserId = requesterUserId ?? void 0;
|
|
11896
|
-
|
|
11897
|
-
|
|
11898
|
-
} else {
|
|
11899
|
-
await deps.handleInbound({ role: "admin", accountId: bootstrapAccountId, key: deliveryKey, text, adminUserId });
|
|
11900
|
-
}
|
|
12070
|
+
const inboundStartedAt = Date.now();
|
|
12071
|
+
const inbound = deliverySessionId !== void 0 ? await deps.handleInbound({ role: "admin", accountId: deliveryAccountId, key: deliveryKey, text, sessionId: deliverySessionId, adminUserId }) : await deps.handleInbound({ role: "admin", accountId: bootstrapAccountId, key: deliveryKey, text, adminUserId });
|
|
11901
12072
|
if (deliveredIntId !== null) {
|
|
11902
12073
|
console.log(`[webchat-interrupt] op=delivered intId=${deliveredIntId} sessionId=${deliverySessionId.slice(0, 8)}`);
|
|
11903
12074
|
}
|
|
@@ -11914,7 +12085,9 @@ ${note}` : note;
|
|
|
11914
12085
|
}
|
|
11915
12086
|
const keyDisplay2 = deliveryKey.startsWith("session:") ? deliveryKey.slice(0, "session:".length + 8) : WEBCHAT_ADMIN_KEY;
|
|
11916
12087
|
const baseline = jsonlSizeBytes(locateSession(turnSessionId).projectDir, turnSessionId);
|
|
11917
|
-
console.error(
|
|
12088
|
+
console.error(
|
|
12089
|
+
`[webchat:inbound] op=send-accepted key=${keyDisplay2} sendId=${sendId} baselineBytes=${baseline ?? "absent"} acceptMs=${Date.now() - inboundStartedAt} spawn=${inbound.spawn !== null ? "triggered" : "none"}`
|
|
12090
|
+
);
|
|
11918
12091
|
const turnTimer = setTimeout(() => {
|
|
11919
12092
|
const now = jsonlSizeBytes(locateSession(turnSessionId).projectDir, turnSessionId);
|
|
11920
12093
|
const grew = now !== null && (baseline === null || now > baseline);
|
|
@@ -12293,8 +12466,8 @@ function routeTelegramUpdate(input) {
|
|
|
12293
12466
|
// server/routes/telegram.ts
|
|
12294
12467
|
var TAG23 = "[telegram-inbound]";
|
|
12295
12468
|
function configDirName() {
|
|
12296
|
-
const
|
|
12297
|
-
const brandPath = join22(
|
|
12469
|
+
const platformRoot5 = process.env.MAXY_PLATFORM_ROOT ?? resolve16(process.cwd(), "..");
|
|
12470
|
+
const brandPath = join22(platformRoot5, "config", "brand.json");
|
|
12298
12471
|
if (existsSync15(brandPath)) {
|
|
12299
12472
|
try {
|
|
12300
12473
|
return JSON.parse(readFileSync23(brandPath, "utf-8")).configDir ?? ".maxy";
|
|
@@ -12493,7 +12666,7 @@ var quickbooks_default = app9;
|
|
|
12493
12666
|
// server/routes/onboarding.ts
|
|
12494
12667
|
import { spawn, spawnSync as spawnSync2, execFileSync as execFileSync3 } from "child_process";
|
|
12495
12668
|
import { openSync as openSync3, closeSync as closeSync3, writeFileSync as writeFileSync10, writeSync, existsSync as existsSync18, readFileSync as readFileSync26, unlinkSync as unlinkSync3, renameSync as renameSync7 } from "fs";
|
|
12496
|
-
import { createHash as createHash4, randomUUID as
|
|
12669
|
+
import { createHash as createHash4, randomUUID as randomUUID8 } from "crypto";
|
|
12497
12670
|
|
|
12498
12671
|
// app/lib/claude-spawn-env.ts
|
|
12499
12672
|
function claudeBin() {
|
|
@@ -12989,7 +13162,7 @@ app10.post("/set-pin", async (c) => {
|
|
|
12989
13162
|
const hash = hashPin2(body.pin);
|
|
12990
13163
|
const account = resolveAccount();
|
|
12991
13164
|
const existingOwnerUserId = account?.config.admins?.find((a) => a.role === "owner")?.userId;
|
|
12992
|
-
const userId = existingOwnerUserId ??
|
|
13165
|
+
const userId = existingOwnerUserId ?? randomUUID8();
|
|
12993
13166
|
if (existingOwnerUserId) {
|
|
12994
13167
|
console.log(`[set-pin] reusing existing owner userId=${userId.slice(0, 8)}\u2026 (change-PIN preserves identity)`);
|
|
12995
13168
|
} else {
|
|
@@ -13381,7 +13554,7 @@ app11.post("/", async (c) => {
|
|
|
13381
13554
|
var client_error_default = app11;
|
|
13382
13555
|
|
|
13383
13556
|
// server/routes/admin/session.ts
|
|
13384
|
-
import { randomUUID as
|
|
13557
|
+
import { randomUUID as randomUUID9 } from "crypto";
|
|
13385
13558
|
async function resolveUserIdentity(accountId, userId) {
|
|
13386
13559
|
const result = await loadAdminUserName(userId);
|
|
13387
13560
|
if (result.source === "neo4j") {
|
|
@@ -13395,7 +13568,7 @@ async function resolveUserIdentity(accountId, userId) {
|
|
|
13395
13568
|
async function createAdminSession(accountId, thinkingView, userId, userName, role, avatar) {
|
|
13396
13569
|
const account = resolveAccount();
|
|
13397
13570
|
const effectiveThinkingView = thinkingView ?? account?.config.thinkingView ?? "default";
|
|
13398
|
-
const signedSessionToken =
|
|
13571
|
+
const signedSessionToken = randomUUID9();
|
|
13399
13572
|
const cacheKey = fingerprintSessionKey(signedSessionToken);
|
|
13400
13573
|
registerSession(cacheKey, "admin", accountId, void 0, userId, userName ?? void 0, role);
|
|
13401
13574
|
if (userId) setWantsPriorConversation(cacheKey);
|
|
@@ -13437,15 +13610,15 @@ function operatorRoleFor(config, userId) {
|
|
|
13437
13610
|
async function buildAccountOptionList(accounts, userId) {
|
|
13438
13611
|
const houseAccount = accounts.find((a) => a.config.role === "house");
|
|
13439
13612
|
console.log(`[admin-accounts] op=list count=${accounts.length} house=${houseAccount?.accountId ?? "none"}`);
|
|
13440
|
-
const
|
|
13613
|
+
const resolve37 = async (a) => {
|
|
13441
13614
|
const businessName = await fetchAccountName(a.accountId) || void 0;
|
|
13442
13615
|
return { accountId: a.accountId, businessName, role: operatorRoleFor(a.config, userId), isHouse: a.config.role === "house" };
|
|
13443
13616
|
};
|
|
13444
13617
|
const houseOptions = await Promise.all(
|
|
13445
|
-
accounts.filter((a) => a.config.role === "house").map(
|
|
13618
|
+
accounts.filter((a) => a.config.role === "house").map(resolve37)
|
|
13446
13619
|
);
|
|
13447
13620
|
const nonHouseOptions = await Promise.all(
|
|
13448
|
-
accounts.filter((a) => a.config.role !== "house").map(
|
|
13621
|
+
accounts.filter((a) => a.config.role !== "house").map(resolve37)
|
|
13449
13622
|
);
|
|
13450
13623
|
const sortKey = (o) => (o.businessName || o.accountId).toLowerCase();
|
|
13451
13624
|
nonHouseOptions.sort((x, y) => {
|
|
@@ -14929,10 +15102,10 @@ function readTunnelState(brandConfigDir) {
|
|
|
14929
15102
|
}
|
|
14930
15103
|
}
|
|
14931
15104
|
function resolveTunnelUrl() {
|
|
14932
|
-
const
|
|
15105
|
+
const platformRoot5 = process.env.MAXY_PLATFORM_ROOT ?? process.env.PLATFORM_ROOT ?? resolve21(process.cwd(), "..");
|
|
14933
15106
|
let brand;
|
|
14934
15107
|
try {
|
|
14935
|
-
brand = JSON.parse(readFileSync30(resolve21(
|
|
15108
|
+
brand = JSON.parse(readFileSync30(resolve21(platformRoot5, "config", "brand.json"), "utf-8"));
|
|
14936
15109
|
} catch {
|
|
14937
15110
|
return null;
|
|
14938
15111
|
}
|
|
@@ -15141,18 +15314,18 @@ var ALLOWED_EVENTS = /* @__PURE__ */ new Set([
|
|
|
15141
15314
|
]);
|
|
15142
15315
|
var app21 = new Hono();
|
|
15143
15316
|
app21.post("/", async (c) => {
|
|
15144
|
-
const
|
|
15317
|
+
const TAG46 = "[admin:events]";
|
|
15145
15318
|
let body;
|
|
15146
15319
|
try {
|
|
15147
15320
|
body = await c.req.json();
|
|
15148
15321
|
} catch (err) {
|
|
15149
15322
|
const detail = err instanceof Error ? err.message : String(err);
|
|
15150
|
-
console.error(`${
|
|
15323
|
+
console.error(`${TAG46} reject reason=body-not-json detail=${detail}`);
|
|
15151
15324
|
return c.json({ ok: false, detail: "Request body was not valid JSON" }, 400);
|
|
15152
15325
|
}
|
|
15153
15326
|
const event = typeof body.event === "string" ? body.event : "";
|
|
15154
15327
|
if (!ALLOWED_EVENTS.has(event)) {
|
|
15155
|
-
console.error(`${
|
|
15328
|
+
console.error(`${TAG46} reject reason=event-not-allowed event=${JSON.stringify(event)}`);
|
|
15156
15329
|
return c.json({ ok: false, detail: `Event "${event}" is not allowed` }, 400);
|
|
15157
15330
|
}
|
|
15158
15331
|
const rawFields = body.fields && typeof body.fields === "object" ? body.fields : {};
|
|
@@ -15176,8 +15349,8 @@ var events_default = app21;
|
|
|
15176
15349
|
// server/routes/admin/files.ts
|
|
15177
15350
|
import { createReadStream as createReadStream2, createWriteStream as createWriteStream2, existsSync as existsSync27 } from "fs";
|
|
15178
15351
|
import { readdir as readdir3, readFile as readFile4, stat as stat4, mkdir as mkdir3, unlink as unlink2, rename, rmdir } from "fs/promises";
|
|
15179
|
-
import { realpathSync as
|
|
15180
|
-
import { randomUUID as
|
|
15352
|
+
import { realpathSync as realpathSync6 } from "fs";
|
|
15353
|
+
import { randomUUID as randomUUID10 } from "crypto";
|
|
15181
15354
|
import { basename as basename9, dirname as dirname11, join as join30, relative as relative4, resolve as resolve23, sep as sep6 } from "path";
|
|
15182
15355
|
import { Readable as Readable2 } from "stream";
|
|
15183
15356
|
|
|
@@ -16542,8 +16715,8 @@ async function resolveUploadTarget(c, accountId, uid) {
|
|
|
16542
16715
|
const info = await stat4(destDir).catch(() => null);
|
|
16543
16716
|
if (!info || !info.isDirectory()) return { ok: false, status: 400, error: "Upload destination is not a directory" };
|
|
16544
16717
|
}
|
|
16545
|
-
const dataRootReal =
|
|
16546
|
-
const destDirReal =
|
|
16718
|
+
const dataRootReal = realpathSync6(DATA_ROOT);
|
|
16719
|
+
const destDirReal = realpathSync6(destDir);
|
|
16547
16720
|
if (destDirReal !== dataRootReal && !destDirReal.startsWith(dataRootReal + sep6)) {
|
|
16548
16721
|
console.error(`[data-upload] op=path-traversal-blocked uid=${uid} requested="${destRel}" resolved="${destDirReal}"`);
|
|
16549
16722
|
return { ok: false, status: 403, error: "Upload destination escapes DATA_ROOT" };
|
|
@@ -16569,7 +16742,7 @@ app22.post("/upload", requireAdminSession, async (c) => {
|
|
|
16569
16742
|
if (c.req.query("uploadId") !== void 0) {
|
|
16570
16743
|
return handleChunkUpload(c, accountId);
|
|
16571
16744
|
}
|
|
16572
|
-
const uid = `${Date.now()}-${
|
|
16745
|
+
const uid = `${Date.now()}-${randomUUID10().slice(0, 8)}`;
|
|
16573
16746
|
const declaredBytes = c.req.header("content-length") ?? "unknown";
|
|
16574
16747
|
const target = await resolveUploadTarget(c, accountId, uid);
|
|
16575
16748
|
if (!target.ok) return c.json({ error: target.error }, target.status);
|
|
@@ -19644,9 +19817,9 @@ app34.get("/", requireAdminSession, async (c) => {
|
|
|
19644
19817
|
var session_usage_default = app34;
|
|
19645
19818
|
|
|
19646
19819
|
// server/routes/admin/session-rc-spawn.ts
|
|
19647
|
-
import { randomUUID as
|
|
19820
|
+
import { randomUUID as randomUUID11 } from "crypto";
|
|
19648
19821
|
var ACCOUNT_UUID_RE3 = /^[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}$/;
|
|
19649
|
-
function resolveSpawnPlan(host, operatorDomains, body, mintId =
|
|
19822
|
+
function resolveSpawnPlan(host, operatorDomains, body, mintId = randomUUID11, adminUserId, authenticatedName, callerAccountId) {
|
|
19650
19823
|
const operator = isOperatorHost(host, operatorDomains);
|
|
19651
19824
|
const resumeId = typeof body.sessionId === "string" && body.sessionId.length > 0 ? body.sessionId : void 0;
|
|
19652
19825
|
const name = typeof body.name === "string" && body.name.length > 0 ? body.name : void 0;
|
|
@@ -19701,8 +19874,8 @@ app35.post("/", requireAdminSession, async (c) => {
|
|
|
19701
19874
|
const adminUserId = cacheKey ? getUserIdForSession(cacheKey) : void 0;
|
|
19702
19875
|
const accountId = cacheKey ? getAccountIdForSession(cacheKey) : void 0;
|
|
19703
19876
|
const authenticatedName = accountId ? await resolveAuthenticatedName(accountId, adminUserId) : void 0;
|
|
19704
|
-
const plan = resolveSpawnPlan(host, getOperatorDomains(), body,
|
|
19705
|
-
const spawnReqId =
|
|
19877
|
+
const plan = resolveSpawnPlan(host, getOperatorDomains(), body, randomUUID11, adminUserId, authenticatedName, accountId);
|
|
19878
|
+
const spawnReqId = randomUUID11();
|
|
19706
19879
|
console.log(
|
|
19707
19880
|
`[chat-spawn] op=request spawnReqId=${spawnReqId} origin=${plan.origin} kind=${plan.kind} sessionId=${plan.kind === "new" ? "new" : plan.sessionId}`
|
|
19708
19881
|
);
|
|
@@ -19774,8 +19947,8 @@ app35.post("/", requireAdminSession, async (c) => {
|
|
|
19774
19947
|
var session_rc_spawn_default = app35;
|
|
19775
19948
|
|
|
19776
19949
|
// server/routes/admin/session-reseat.ts
|
|
19777
|
-
import { randomUUID as
|
|
19778
|
-
function resolveReseatPlan(body, mintId =
|
|
19950
|
+
import { randomUUID as randomUUID12 } from "crypto";
|
|
19951
|
+
function resolveReseatPlan(body, mintId = randomUUID12, adminUserId, authenticatedName) {
|
|
19779
19952
|
const sessionId = mintId();
|
|
19780
19953
|
const key = `session:${sessionId}`;
|
|
19781
19954
|
const payload = {
|
|
@@ -19829,11 +20002,11 @@ app36.post("/", requireAdminSession, async (c) => {
|
|
|
19829
20002
|
const authenticatedName = accountId ? await resolveAuthenticatedName(accountId, adminUserId) : void 0;
|
|
19830
20003
|
const plan = resolveReseatPlan(
|
|
19831
20004
|
{ fromSessionId, model, ...permissionMode ? { permissionMode } : {}, ...effort ? { effort } : {} },
|
|
19832
|
-
|
|
20005
|
+
randomUUID12,
|
|
19833
20006
|
adminUserId,
|
|
19834
20007
|
authenticatedName
|
|
19835
20008
|
);
|
|
19836
|
-
const reseatReqId =
|
|
20009
|
+
const reseatReqId = randomUUID12();
|
|
19837
20010
|
console.log(`[chat-reseat] op=request reseatReqId=${reseatReqId} from=${fromSessionId} to-model=${model} to-mode=${permissionMode ?? "none"} to-effort=${effort ?? "none"} new=${plan.sessionId}`);
|
|
19838
20011
|
let res;
|
|
19839
20012
|
try {
|
|
@@ -20076,7 +20249,7 @@ app38.get("/", async (c) => {
|
|
|
20076
20249
|
var health_default2 = app38;
|
|
20077
20250
|
|
|
20078
20251
|
// server/routes/admin/linkedin-ingest.ts
|
|
20079
|
-
import { randomUUID as
|
|
20252
|
+
import { randomUUID as randomUUID13 } from "crypto";
|
|
20080
20253
|
|
|
20081
20254
|
// app/lib/channel-pty-bridge/manager-client.ts
|
|
20082
20255
|
function managerBase2() {
|
|
@@ -20329,7 +20502,7 @@ app39.post("/", requireAdminSession, async (c) => {
|
|
|
20329
20502
|
);
|
|
20330
20503
|
const initialMessage = buildInitialMessage(envelope);
|
|
20331
20504
|
const spawnStart = Date.now();
|
|
20332
|
-
const sessionId =
|
|
20505
|
+
const sessionId = randomUUID13();
|
|
20333
20506
|
console.log(TAG27 + " route target=rc-spawn dispatchId=" + envelope.dispatchId + " sessionId=" + sessionId.slice(0, 8));
|
|
20334
20507
|
const spawned = await managerRcSpawn({
|
|
20335
20508
|
sessionId,
|
|
@@ -21367,7 +21540,7 @@ app47.get("/", requireAdminSession, async (c) => {
|
|
|
21367
21540
|
var tasks_list_default = app47;
|
|
21368
21541
|
|
|
21369
21542
|
// server/routes/admin/task-timer-start.ts
|
|
21370
|
-
import { randomUUID as
|
|
21543
|
+
import { randomUUID as randomUUID14 } from "crypto";
|
|
21371
21544
|
var TAG34 = "[task-timer]";
|
|
21372
21545
|
var app48 = new Hono();
|
|
21373
21546
|
app48.post("/", requireAdminSession, async (c) => {
|
|
@@ -21405,7 +21578,7 @@ app48.post("/", requireAdminSession, async (c) => {
|
|
|
21405
21578
|
console.log(`${TAG34} op=start taskId=${taskId} accountId=${accountId} result=already-running`);
|
|
21406
21579
|
return c.json({ ok: true, running: true, entryId: priorEntryId, startedAt: priorStartedAt });
|
|
21407
21580
|
}
|
|
21408
|
-
const entryId =
|
|
21581
|
+
const entryId = randomUUID14();
|
|
21409
21582
|
await session.run(
|
|
21410
21583
|
`MATCH (t:Task {taskId: $taskId, accountId: $accountId})
|
|
21411
21584
|
CREATE (te:TimeEntry {entryId: $entryId, taskId: $taskId, accountId: $accountId, startedAt: $now, endedAt: null})
|
|
@@ -21532,7 +21705,7 @@ app50.post("/", requireAdminSession, async (c) => {
|
|
|
21532
21705
|
var task_complete_default = app50;
|
|
21533
21706
|
|
|
21534
21707
|
// server/routes/admin/task-time-adjust.ts
|
|
21535
|
-
import { randomUUID as
|
|
21708
|
+
import { randomUUID as randomUUID15 } from "crypto";
|
|
21536
21709
|
import neo4j6 from "neo4j-driver";
|
|
21537
21710
|
var TAG37 = "[task-time-adjust]";
|
|
21538
21711
|
var app51 = new Hono();
|
|
@@ -21557,7 +21730,7 @@ app51.post("/", requireAdminSession, async (c) => {
|
|
|
21557
21730
|
console.error(`${TAG37} op=reject reason=invalid-seconds taskId=${taskId} accountId=${accountId}`);
|
|
21558
21731
|
return c.json({ error: "newSeconds must be a non-negative integer" }, 400);
|
|
21559
21732
|
}
|
|
21560
|
-
const adjustmentId =
|
|
21733
|
+
const adjustmentId = randomUUID15();
|
|
21561
21734
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
21562
21735
|
console.log(`${TAG37} op=request adjustmentId=${adjustmentId} taskId=${taskId} accountId=${accountId} newSeconds=${newSeconds}`);
|
|
21563
21736
|
const session = getSession();
|
|
@@ -21891,7 +22064,7 @@ app55.route("/request-magic-link", request_magic_link_default);
|
|
|
21891
22064
|
var access_default = app55;
|
|
21892
22065
|
|
|
21893
22066
|
// server/routes/sites.ts
|
|
21894
|
-
import { existsSync as existsSync31, readFileSync as readFileSync34, realpathSync as
|
|
22067
|
+
import { existsSync as existsSync31, readFileSync as readFileSync34, realpathSync as realpathSync7, statSync as statSync12 } from "fs";
|
|
21895
22068
|
import { resolve as resolve28 } from "path";
|
|
21896
22069
|
var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
|
|
21897
22070
|
var MIME = {
|
|
@@ -21983,8 +22156,8 @@ app56.get("/:rel{.*}", (c) => {
|
|
|
21983
22156
|
let realPath;
|
|
21984
22157
|
let realRoot;
|
|
21985
22158
|
try {
|
|
21986
|
-
realPath =
|
|
21987
|
-
realRoot =
|
|
22159
|
+
realPath = realpathSync7(filePath);
|
|
22160
|
+
realRoot = realpathSync7(rootDir);
|
|
21988
22161
|
} catch {
|
|
21989
22162
|
console.error(`[sites] not-found path=${reqPath} status=404`);
|
|
21990
22163
|
return c.text("Not found", 404);
|
|
@@ -22114,9 +22287,9 @@ var cachedAttempted = false;
|
|
|
22114
22287
|
function readBrandConfig() {
|
|
22115
22288
|
if (cachedAttempted) return cached2;
|
|
22116
22289
|
cachedAttempted = true;
|
|
22117
|
-
const
|
|
22118
|
-
if (!
|
|
22119
|
-
const brandPath = join35(
|
|
22290
|
+
const platformRoot5 = process.env.MAXY_PLATFORM_ROOT;
|
|
22291
|
+
if (!platformRoot5) return null;
|
|
22292
|
+
const brandPath = join35(platformRoot5, "config", "brand.json");
|
|
22120
22293
|
if (!existsSync32(brandPath)) return null;
|
|
22121
22294
|
try {
|
|
22122
22295
|
cached2 = JSON.parse(readFileSync36(brandPath, "utf-8"));
|
|
@@ -24453,16 +24626,16 @@ var WebchatGateway = class _WebchatGateway {
|
|
|
24453
24626
|
* The public /api/chat route awaits this to return the reply on the same SSE
|
|
24454
24627
|
* response, preserving the pre-756 POST→single-blob browser contract. */
|
|
24455
24628
|
awaitReply(key, timeoutMs) {
|
|
24456
|
-
return new Promise((
|
|
24629
|
+
return new Promise((resolve37) => {
|
|
24457
24630
|
const timer2 = setTimeout(() => {
|
|
24458
24631
|
this.replyAwaiters.delete(key);
|
|
24459
|
-
|
|
24632
|
+
resolve37({ timeout: true });
|
|
24460
24633
|
}, timeoutMs);
|
|
24461
24634
|
if (timer2.unref) timer2.unref();
|
|
24462
24635
|
this.replyAwaiters.set(key, (r) => {
|
|
24463
24636
|
clearTimeout(timer2);
|
|
24464
24637
|
this.replyAwaiters.delete(key);
|
|
24465
|
-
|
|
24638
|
+
resolve37(r);
|
|
24466
24639
|
});
|
|
24467
24640
|
});
|
|
24468
24641
|
}
|
|
@@ -24473,11 +24646,11 @@ var WebchatGateway = class _WebchatGateway {
|
|
|
24473
24646
|
* terminal dialog stays answerable). */
|
|
24474
24647
|
awaitPermissionVerdict(p, timeoutMs) {
|
|
24475
24648
|
const k = _WebchatGateway.promptKey(p.key, p.requestId);
|
|
24476
|
-
return new Promise((
|
|
24649
|
+
return new Promise((resolve37) => {
|
|
24477
24650
|
this.pendingPrompts.get(k)?.resolve({ timeout: true });
|
|
24478
24651
|
const timer2 = setTimeout(() => {
|
|
24479
24652
|
this.pendingPrompts.delete(k);
|
|
24480
|
-
|
|
24653
|
+
resolve37({ timeout: true });
|
|
24481
24654
|
}, timeoutMs);
|
|
24482
24655
|
if (timer2.unref) timer2.unref();
|
|
24483
24656
|
this.pendingPrompts.set(k, {
|
|
@@ -24486,7 +24659,7 @@ var WebchatGateway = class _WebchatGateway {
|
|
|
24486
24659
|
resolve: (r) => {
|
|
24487
24660
|
clearTimeout(timer2);
|
|
24488
24661
|
this.pendingPrompts.delete(k);
|
|
24489
|
-
|
|
24662
|
+
resolve37(r);
|
|
24490
24663
|
}
|
|
24491
24664
|
});
|
|
24492
24665
|
console.error(`[webchat:perm] op=open key=${keyDisplay(p.key)} id=${p.requestId} tool=${p.toolName}`);
|
|
@@ -24727,7 +24900,9 @@ var WebchatGateway = class _WebchatGateway {
|
|
|
24727
24900
|
this.recovering = false;
|
|
24728
24901
|
}
|
|
24729
24902
|
}
|
|
24730
|
-
/** Handle one inbound webchat message (browser POST → here).
|
|
24903
|
+
/** Handle one inbound webchat message (browser POST → here). Resolves when
|
|
24904
|
+
* the hub holds the message; the cold-start spawn is returned as a handle
|
|
24905
|
+
* (Task 1715 — see WebchatInboundResult). */
|
|
24731
24906
|
async handleInbound(input) {
|
|
24732
24907
|
const bytes = Buffer.byteLength(input.text, "utf8");
|
|
24733
24908
|
const hadSubscriber = this.hub.hasSubscriber(input.key);
|
|
@@ -24761,63 +24936,60 @@ var WebchatGateway = class _WebchatGateway {
|
|
|
24761
24936
|
}
|
|
24762
24937
|
const existing = this.publicSessions.get(input.key);
|
|
24763
24938
|
if (existing) existing.lastActivityAt = Date.now();
|
|
24939
|
+
let spawn4 = null;
|
|
24764
24940
|
if (!hadSubscriber && !this.spawning.has(input.key)) {
|
|
24765
24941
|
this.spawning.add(input.key);
|
|
24766
24942
|
console.error(`[webchat:inbound] op=spawn-trigger key=${input.key} role=${input.role}`);
|
|
24767
|
-
|
|
24768
|
-
|
|
24943
|
+
spawn4 = this.runSpawn(input);
|
|
24944
|
+
spawn4.catch(() => {
|
|
24945
|
+
});
|
|
24946
|
+
}
|
|
24947
|
+
return { spawn: spawn4 };
|
|
24948
|
+
}
|
|
24949
|
+
/** Task 1715 — the cold-start spawn, run off the accept's path. Rejects on a
|
|
24950
|
+
* failed spawn so the public caller's SSE still errors; logs op=spawn-failed
|
|
24951
|
+
* first, because on the admin path the 200 has already been returned and this
|
|
24952
|
+
* line is the only attribution the failure gets. */
|
|
24953
|
+
async runSpawn(input) {
|
|
24954
|
+
const startedAt = Date.now();
|
|
24955
|
+
try {
|
|
24956
|
+
const spawned = await this.deps.ensureChannelSession({
|
|
24957
|
+
accountId: input.accountId,
|
|
24958
|
+
key: input.key,
|
|
24959
|
+
role: input.role,
|
|
24960
|
+
gatewayUrl: this.deps.gatewayUrl,
|
|
24961
|
+
serverPath: this.deps.serverPath,
|
|
24962
|
+
// Task 800 — only present on a session-targeted launch, so the
|
|
24963
|
+
// default-path call shape stays byte-identical.
|
|
24964
|
+
...input.sessionId !== void 0 ? { sessionId: input.sessionId } : {},
|
|
24965
|
+
// The authenticated admin's userId on an admin bootstrap inbound; the
|
|
24966
|
+
// default-path call shape stays byte-identical when absent.
|
|
24967
|
+
...input.adminUserId !== void 0 ? { adminUserId: input.adminUserId } : {},
|
|
24968
|
+
// Task 756 — public spawn params on a role:'public' inbound.
|
|
24969
|
+
...input.public !== void 0 ? { public: input.public } : {}
|
|
24970
|
+
});
|
|
24971
|
+
if (input.role === "public" && input.public && spawned && "sessionId" in spawned) {
|
|
24972
|
+
this.publicSessions.set(input.key, {
|
|
24973
|
+
sessionId: spawned.sessionId,
|
|
24769
24974
|
accountId: input.accountId,
|
|
24770
|
-
|
|
24771
|
-
|
|
24772
|
-
|
|
24773
|
-
|
|
24774
|
-
// Task 800 — only present on a session-targeted launch, so the
|
|
24775
|
-
// default-path call shape stays byte-identical.
|
|
24776
|
-
...input.sessionId !== void 0 ? { sessionId: input.sessionId } : {},
|
|
24777
|
-
// The authenticated admin's userId on an admin bootstrap inbound; the
|
|
24778
|
-
// default-path call shape stays byte-identical when absent.
|
|
24779
|
-
...input.adminUserId !== void 0 ? { adminUserId: input.adminUserId } : {},
|
|
24780
|
-
// Task 756 — public spawn params on a role:'public' inbound.
|
|
24781
|
-
...input.public !== void 0 ? { public: input.public } : {}
|
|
24975
|
+
agentSlug: input.public.agentSlug,
|
|
24976
|
+
sliceToken: input.public.sliceToken,
|
|
24977
|
+
personId: input.public.personId,
|
|
24978
|
+
lastActivityAt: Date.now()
|
|
24782
24979
|
});
|
|
24783
|
-
if (input.role === "public" && input.public && spawned && "sessionId" in spawned) {
|
|
24784
|
-
this.publicSessions.set(input.key, {
|
|
24785
|
-
sessionId: spawned.sessionId,
|
|
24786
|
-
accountId: input.accountId,
|
|
24787
|
-
agentSlug: input.public.agentSlug,
|
|
24788
|
-
sliceToken: input.public.sliceToken,
|
|
24789
|
-
personId: input.public.personId,
|
|
24790
|
-
lastActivityAt: Date.now()
|
|
24791
|
-
});
|
|
24792
|
-
}
|
|
24793
|
-
} finally {
|
|
24794
|
-
this.spawning.delete(input.key);
|
|
24795
24980
|
}
|
|
24981
|
+
} catch (err) {
|
|
24982
|
+
const reason = (err instanceof Error ? err.message : String(err)).replace(/\s+/g, " ");
|
|
24983
|
+
console.error(
|
|
24984
|
+
`[webchat:inbound] op=spawn-failed key=${keyDisplay(input.key)} role=${input.role} ms=${Date.now() - startedAt} reason=${reason}`
|
|
24985
|
+
);
|
|
24986
|
+
throw err;
|
|
24987
|
+
} finally {
|
|
24988
|
+
this.spawning.delete(input.key);
|
|
24796
24989
|
}
|
|
24797
24990
|
}
|
|
24798
24991
|
};
|
|
24799
24992
|
|
|
24800
|
-
// app/lib/webchat/gateway/public-spawn-request.ts
|
|
24801
|
-
function buildPublicWebchatSpawnRequest(input) {
|
|
24802
|
-
const { agentSlug, sliceToken, personId, visitorId, name } = input.public;
|
|
24803
|
-
return {
|
|
24804
|
-
senderId: input.key,
|
|
24805
|
-
role: "public",
|
|
24806
|
-
channel: "webchat",
|
|
24807
|
-
accountId: input.accountId,
|
|
24808
|
-
agentSlug,
|
|
24809
|
-
model: SONNET_MODEL,
|
|
24810
|
-
// sliceToken/personId are present only for a gated visitor; open-mode
|
|
24811
|
-
// public agents carry neither (mirrors the bridge's open-mode key).
|
|
24812
|
-
...sliceToken ? { sliceToken } : {},
|
|
24813
|
-
...personId ? { personId } : {},
|
|
24814
|
-
...visitorId ? { visitorId } : {},
|
|
24815
|
-
...input.previousContext ? { previousContext: input.previousContext } : {},
|
|
24816
|
-
name,
|
|
24817
|
-
webchatChannel: { key: input.key, gatewayUrl: input.gatewayUrl, serverPath: input.serverPath }
|
|
24818
|
-
};
|
|
24819
|
-
}
|
|
24820
|
-
|
|
24821
24993
|
// app/lib/channel-pty-bridge/follower.ts
|
|
24822
24994
|
function followerPendingMaxMs() {
|
|
24823
24995
|
return Number(process.env.CHANNEL_PTY_FOLLOWER_PENDING_MAX_MS ?? String(3e5));
|
|
@@ -24825,6 +24997,13 @@ function followerPendingMaxMs() {
|
|
|
24825
24997
|
function followerRetryMs() {
|
|
24826
24998
|
return Number(process.env.CHANNEL_PTY_FOLLOWER_RETRY_MS ?? String(1e3));
|
|
24827
24999
|
}
|
|
25000
|
+
function toolResultText(content) {
|
|
25001
|
+
if (typeof content === "string") return content;
|
|
25002
|
+
if (!Array.isArray(content)) return "";
|
|
25003
|
+
return content.map(
|
|
25004
|
+
(b) => b && typeof b === "object" && typeof b.text === "string" ? b.text : ""
|
|
25005
|
+
).join("");
|
|
25006
|
+
}
|
|
24828
25007
|
function startFollower(opts) {
|
|
24829
25008
|
const abort = new AbortController();
|
|
24830
25009
|
const { entry, tag } = opts;
|
|
@@ -24867,6 +25046,8 @@ function startFollower(opts) {
|
|
|
24867
25046
|
const decoder = new TextDecoder("utf8");
|
|
24868
25047
|
let buffered = "";
|
|
24869
25048
|
const fileDelivery = opts.fileDelivery ?? null;
|
|
25049
|
+
const captureVerdicts = typeof fileDelivery?.onFileToolResult === "function";
|
|
25050
|
+
const awaitingVerdict = /* @__PURE__ */ new Set();
|
|
24870
25051
|
let firedFileTools = [];
|
|
24871
25052
|
let suppressing = opts.suppressResumeReplay === true;
|
|
24872
25053
|
let discardedTurns = 0;
|
|
@@ -24900,6 +25081,28 @@ function startFollower(opts) {
|
|
|
24900
25081
|
continue;
|
|
24901
25082
|
}
|
|
24902
25083
|
if (event.type === "user") {
|
|
25084
|
+
if (captureVerdicts && awaitingVerdict.size > 0 && !suppressing) {
|
|
25085
|
+
const umsg = event.message;
|
|
25086
|
+
if (umsg && Array.isArray(umsg.content)) {
|
|
25087
|
+
for (const block of umsg.content) {
|
|
25088
|
+
if (block?.type !== "tool_result") continue;
|
|
25089
|
+
const id = block.tool_use_id;
|
|
25090
|
+
if (typeof id !== "string" || !awaitingVerdict.has(id)) continue;
|
|
25091
|
+
awaitingVerdict.delete(id);
|
|
25092
|
+
try {
|
|
25093
|
+
await fileDelivery.onFileToolResult({
|
|
25094
|
+
toolUseId: id,
|
|
25095
|
+
isError: block.is_error === true,
|
|
25096
|
+
text: toolResultText(block.content)
|
|
25097
|
+
});
|
|
25098
|
+
} catch (err) {
|
|
25099
|
+
console.error(
|
|
25100
|
+
`${tag} file-delivery-error sessionId=${sid} phase=tool-result message=${err instanceof Error ? err.message : String(err)}`
|
|
25101
|
+
);
|
|
25102
|
+
}
|
|
25103
|
+
}
|
|
25104
|
+
}
|
|
25105
|
+
}
|
|
24903
25106
|
entry.pendingTurnText = "";
|
|
24904
25107
|
firedFileTools = [];
|
|
24905
25108
|
continue;
|
|
@@ -24921,8 +25124,10 @@ function startFollower(opts) {
|
|
|
24921
25124
|
continue;
|
|
24922
25125
|
}
|
|
24923
25126
|
firedFileTools.push(block.name);
|
|
25127
|
+
const toolUseId = typeof block.id === "string" ? block.id : "";
|
|
25128
|
+
if (captureVerdicts && toolUseId) awaitingVerdict.add(toolUseId);
|
|
24924
25129
|
try {
|
|
24925
|
-
await fileDelivery.onFileToolUse({ toolName: block.name, input: block.input });
|
|
25130
|
+
await fileDelivery.onFileToolUse({ toolName: block.name, toolUseId, input: block.input });
|
|
24926
25131
|
} catch (err) {
|
|
24927
25132
|
console.error(
|
|
24928
25133
|
`${tag} file-delivery-error sessionId=${sid} tool=${block.name} message=${err instanceof Error ? err.message : String(err)}`
|
|
@@ -24944,9 +25149,10 @@ function startFollower(opts) {
|
|
|
24944
25149
|
if (flush.trim()) {
|
|
24945
25150
|
await fanOut(entry.subscribers, flush, opts.onError, tag);
|
|
24946
25151
|
}
|
|
24947
|
-
if (fileDelivery && firedFileTools.length > 0) {
|
|
25152
|
+
if (fileDelivery && (firedFileTools.length > 0 || captureVerdicts)) {
|
|
24948
25153
|
const fired = firedFileTools;
|
|
24949
25154
|
firedFileTools = [];
|
|
25155
|
+
awaitingVerdict.clear();
|
|
24950
25156
|
try {
|
|
24951
25157
|
fileDelivery.onTurnEnd(fired);
|
|
24952
25158
|
} catch (err) {
|
|
@@ -24984,28 +25190,55 @@ async function fanOut(subscribers, text, onError, tag) {
|
|
|
24984
25190
|
);
|
|
24985
25191
|
}
|
|
24986
25192
|
|
|
25193
|
+
// app/lib/webchat/file-delivery.ts
|
|
25194
|
+
import { realpathSync as realpathSync8 } from "fs";
|
|
25195
|
+
import { resolve as resolve32 } from "path";
|
|
25196
|
+
|
|
24987
25197
|
// app/lib/channel-pty-bridge/file-delivery.ts
|
|
24988
25198
|
var SEND_USER_FILE = "SendUserFile";
|
|
24989
25199
|
function makeFileDelivery(opts) {
|
|
24990
|
-
const { entry, tag, channel, sendFile } = opts;
|
|
25200
|
+
const { entry, tag, channel, sendFile, deferUntilVerdict = false } = opts;
|
|
24991
25201
|
let failedFiles = [];
|
|
24992
25202
|
let attempts = 0;
|
|
24993
|
-
|
|
25203
|
+
const pending = /* @__PURE__ */ new Map();
|
|
25204
|
+
function parseInput(input) {
|
|
25205
|
+
const i = input ?? {};
|
|
25206
|
+
return {
|
|
25207
|
+
// A non-array `files` yields zero files. This is the observed refused-call
|
|
25208
|
+
// shape: with the tool absent from the enabled set its schema is absent
|
|
25209
|
+
// from the request, so the model emits a JSON-encoded string. Never parse
|
|
25210
|
+
// it back — the harness refused the call.
|
|
25211
|
+
files: Array.isArray(i.files) ? i.files.filter((f) => typeof f === "string") : [],
|
|
25212
|
+
caption: typeof i.caption === "string" ? i.caption : void 0
|
|
25213
|
+
};
|
|
25214
|
+
}
|
|
25215
|
+
async function forward(call) {
|
|
25216
|
+
for (let i = 0; i < call.files.length; i++) {
|
|
25217
|
+
attempts++;
|
|
25218
|
+
const result = await sendFile(call.files[i], i === 0 ? call.caption : void 0);
|
|
25219
|
+
const name = call.files[i].split("/").pop() ?? call.files[i];
|
|
25220
|
+
console.error(`${tag} op=file-forward channel=${channel} file=${name} outcome=${result.ok ? "ok" : "fail"}`);
|
|
25221
|
+
if (!result.ok) failedFiles.push(call.files[i]);
|
|
25222
|
+
}
|
|
25223
|
+
}
|
|
25224
|
+
function unreconciledCall(reason, files, detail) {
|
|
25225
|
+
const d = detail ? ` detail="${detail.replace(/\s+/g, " ").slice(0, 120)}"` : "";
|
|
25226
|
+
console.error(
|
|
25227
|
+
`${tag} file-delivery-unreconciled sender=${entry.senderId} sessionId=${entry.sessionId.slice(0, 8)} tool=${SEND_USER_FILE} reason=${reason} files=${files}${d}`
|
|
25228
|
+
);
|
|
25229
|
+
}
|
|
25230
|
+
const handler = {
|
|
24994
25231
|
isFileDeliveryTool(toolName) {
|
|
24995
25232
|
return toolName === SEND_USER_FILE;
|
|
24996
25233
|
},
|
|
24997
25234
|
async onFileToolUse(use) {
|
|
24998
25235
|
if (use.toolName !== SEND_USER_FILE) return;
|
|
24999
|
-
const
|
|
25000
|
-
|
|
25001
|
-
|
|
25002
|
-
|
|
25003
|
-
attempts++;
|
|
25004
|
-
const result = await sendFile(files[i], i === 0 ? caption : void 0);
|
|
25005
|
-
const name = files[i].split("/").pop() ?? files[i];
|
|
25006
|
-
console.error(`${tag} op=file-forward channel=${channel} file=${name} outcome=${result.ok ? "ok" : "fail"}`);
|
|
25007
|
-
if (!result.ok) failedFiles.push(files[i]);
|
|
25236
|
+
const call = parseInput(use.input);
|
|
25237
|
+
if (deferUntilVerdict) {
|
|
25238
|
+
pending.set(use.toolUseId, call);
|
|
25239
|
+
return;
|
|
25008
25240
|
}
|
|
25241
|
+
await forward(call);
|
|
25009
25242
|
},
|
|
25010
25243
|
onTurnEnd(firedTools) {
|
|
25011
25244
|
const failed = failedFiles;
|
|
@@ -25018,6 +25251,11 @@ function makeFileDelivery(opts) {
|
|
|
25018
25251
|
`${tag} file-delivery-unreconciled sender=${entry.senderId} sessionId=${sid} tool=${SEND_USER_FILE} file=${file}`
|
|
25019
25252
|
);
|
|
25020
25253
|
}
|
|
25254
|
+
if (deferUntilVerdict) {
|
|
25255
|
+
for (const call of pending.values()) unreconciledCall("no-verdict", call.files.length);
|
|
25256
|
+
pending.clear();
|
|
25257
|
+
return;
|
|
25258
|
+
}
|
|
25021
25259
|
if (firedTools.includes(SEND_USER_FILE) && tried === 0) {
|
|
25022
25260
|
console.error(
|
|
25023
25261
|
`${tag} file-delivery-unreconciled sender=${entry.senderId} sessionId=${sid} tool=${SEND_USER_FILE}`
|
|
@@ -25025,13 +25263,123 @@ function makeFileDelivery(opts) {
|
|
|
25025
25263
|
}
|
|
25026
25264
|
}
|
|
25027
25265
|
};
|
|
25266
|
+
if (deferUntilVerdict) {
|
|
25267
|
+
handler.onFileToolResult = async (result) => {
|
|
25268
|
+
const call = pending.get(result.toolUseId);
|
|
25269
|
+
if (!call) return;
|
|
25270
|
+
pending.delete(result.toolUseId);
|
|
25271
|
+
if (result.isError) {
|
|
25272
|
+
unreconciledCall("harness-refused", call.files.length, result.text);
|
|
25273
|
+
return;
|
|
25274
|
+
}
|
|
25275
|
+
if (call.files.length === 0) {
|
|
25276
|
+
unreconciledCall("no-files", 0);
|
|
25277
|
+
return;
|
|
25278
|
+
}
|
|
25279
|
+
await forward(call);
|
|
25280
|
+
};
|
|
25281
|
+
}
|
|
25282
|
+
return handler;
|
|
25283
|
+
}
|
|
25284
|
+
|
|
25285
|
+
// app/lib/webchat/file-delivery.ts
|
|
25286
|
+
var TAG41 = "[webchat-adaptor]";
|
|
25287
|
+
function platformRoot2() {
|
|
25288
|
+
return process.env.MAXY_PLATFORM_ROOT || "";
|
|
25289
|
+
}
|
|
25290
|
+
function makeWebchatSendFile(entry) {
|
|
25291
|
+
return async (filePath) => {
|
|
25292
|
+
if (!entry.accountId) {
|
|
25293
|
+
console.error(`${TAG41} file-delivery reject reason=no-account sender=${entry.senderId}`);
|
|
25294
|
+
return { ok: false, error: "no-account" };
|
|
25295
|
+
}
|
|
25296
|
+
const accountDir = resolve32(platformRoot2(), "..", "data/accounts", entry.accountId);
|
|
25297
|
+
try {
|
|
25298
|
+
const resolved = realpathSync8(filePath);
|
|
25299
|
+
const accountResolved = realpathSync8(accountDir);
|
|
25300
|
+
if (!resolved.startsWith(accountResolved + "/")) {
|
|
25301
|
+
console.error(`${TAG41} file-delivery reject reason=outside_account_directory sender=${entry.senderId}`);
|
|
25302
|
+
return { ok: false, error: "outside-account" };
|
|
25303
|
+
}
|
|
25304
|
+
return { ok: true };
|
|
25305
|
+
} catch (err) {
|
|
25306
|
+
const code = err.code;
|
|
25307
|
+
console.error(
|
|
25308
|
+
`${TAG41} file-delivery reject reason=${code === "ENOENT" ? "not-found" : "path-error"} sender=${entry.senderId}`
|
|
25309
|
+
);
|
|
25310
|
+
return { ok: false, error: code === "ENOENT" ? "not-found" : "path-error" };
|
|
25311
|
+
}
|
|
25312
|
+
};
|
|
25313
|
+
}
|
|
25314
|
+
function makeWebchatFileDelivery(entry) {
|
|
25315
|
+
return makeFileDelivery({
|
|
25316
|
+
entry,
|
|
25317
|
+
tag: TAG41,
|
|
25318
|
+
channel: "webchat",
|
|
25319
|
+
sendFile: makeWebchatSendFile(entry),
|
|
25320
|
+
deferUntilVerdict: true
|
|
25321
|
+
});
|
|
25322
|
+
}
|
|
25323
|
+
|
|
25324
|
+
// app/lib/webchat/gateway/native-file-follower.ts
|
|
25325
|
+
function startWebchatNativeFileFollower(input) {
|
|
25326
|
+
const entry = {
|
|
25327
|
+
sessionId: input.sessionId,
|
|
25328
|
+
role: "admin",
|
|
25329
|
+
channel: "webchat",
|
|
25330
|
+
accountId: input.accountId,
|
|
25331
|
+
senderId: input.key,
|
|
25332
|
+
agentSlug: "admin",
|
|
25333
|
+
lastInboundAt: Date.now(),
|
|
25334
|
+
writeChain: Promise.resolve(),
|
|
25335
|
+
subscribers: /* @__PURE__ */ new Set(),
|
|
25336
|
+
pendingTurnText: "",
|
|
25337
|
+
followerAbort: null,
|
|
25338
|
+
followerRunning: false,
|
|
25339
|
+
sliceToken: "",
|
|
25340
|
+
personId: null,
|
|
25341
|
+
name: null,
|
|
25342
|
+
// Webchat renders from the transcript; there is no separate reply target.
|
|
25343
|
+
replyTarget: null
|
|
25344
|
+
};
|
|
25345
|
+
return startFollower({
|
|
25346
|
+
entry,
|
|
25347
|
+
tag: "[webchat-adaptor]",
|
|
25348
|
+
fileDelivery: makeWebchatFileDelivery(entry),
|
|
25349
|
+
// A resumed session's JSONL already holds prior SendUserFile tool_uses;
|
|
25350
|
+
// suppress replay so historical calls are not re-reconciled on attach.
|
|
25351
|
+
suppressResumeReplay: true,
|
|
25352
|
+
onClose: input.onClose ?? (() => {
|
|
25353
|
+
})
|
|
25354
|
+
});
|
|
25355
|
+
}
|
|
25356
|
+
|
|
25357
|
+
// app/lib/webchat/gateway/public-spawn-request.ts
|
|
25358
|
+
function buildPublicWebchatSpawnRequest(input) {
|
|
25359
|
+
const { agentSlug, sliceToken, personId, visitorId, name } = input.public;
|
|
25360
|
+
return {
|
|
25361
|
+
senderId: input.key,
|
|
25362
|
+
role: "public",
|
|
25363
|
+
channel: "webchat",
|
|
25364
|
+
accountId: input.accountId,
|
|
25365
|
+
agentSlug,
|
|
25366
|
+
model: SONNET_MODEL,
|
|
25367
|
+
// sliceToken/personId are present only for a gated visitor; open-mode
|
|
25368
|
+
// public agents carry neither (mirrors the bridge's open-mode key).
|
|
25369
|
+
...sliceToken ? { sliceToken } : {},
|
|
25370
|
+
...personId ? { personId } : {},
|
|
25371
|
+
...visitorId ? { visitorId } : {},
|
|
25372
|
+
...input.previousContext ? { previousContext: input.previousContext } : {},
|
|
25373
|
+
name,
|
|
25374
|
+
webchatChannel: { key: input.key, gatewayUrl: input.gatewayUrl, serverPath: input.serverPath }
|
|
25375
|
+
};
|
|
25028
25376
|
}
|
|
25029
25377
|
|
|
25030
25378
|
// app/lib/whatsapp/inbound/file-delivery-bridge.ts
|
|
25031
|
-
var
|
|
25379
|
+
var TAG42 = "[whatsapp-adaptor]";
|
|
25032
25380
|
var SEND_USER_FILE2 = "SendUserFile";
|
|
25033
25381
|
var WHATSAPP_SEND_DOCUMENT = "whatsapp-send-document";
|
|
25034
|
-
function
|
|
25382
|
+
function platformRoot3() {
|
|
25035
25383
|
return process.env.MAXY_PLATFORM_ROOT || "";
|
|
25036
25384
|
}
|
|
25037
25385
|
function makeWhatsAppSendFile(entry, maxyAccountId) {
|
|
@@ -25042,11 +25390,11 @@ function makeWhatsAppSendFile(entry, maxyAccountId) {
|
|
|
25042
25390
|
caption,
|
|
25043
25391
|
accountId: entry.accountId,
|
|
25044
25392
|
maxyAccountId,
|
|
25045
|
-
platformRoot:
|
|
25393
|
+
platformRoot: platformRoot3()
|
|
25046
25394
|
});
|
|
25047
25395
|
if (result.ok) return { ok: true };
|
|
25048
25396
|
console.error(
|
|
25049
|
-
`${
|
|
25397
|
+
`${TAG42} file-delivery reject reason=send-failed sender=${entry.senderId} status=${result.status} message=${result.error}`
|
|
25050
25398
|
);
|
|
25051
25399
|
return { ok: false, error: result.error };
|
|
25052
25400
|
};
|
|
@@ -25054,7 +25402,7 @@ function makeWhatsAppSendFile(entry, maxyAccountId) {
|
|
|
25054
25402
|
function makeWhatsAppFileDelivery(entry, maxyAccountId) {
|
|
25055
25403
|
const shared = makeFileDelivery({
|
|
25056
25404
|
entry,
|
|
25057
|
-
tag:
|
|
25405
|
+
tag: TAG42,
|
|
25058
25406
|
channel: "whatsapp",
|
|
25059
25407
|
sendFile: makeWhatsAppSendFile(entry, maxyAccountId)
|
|
25060
25408
|
});
|
|
@@ -25089,7 +25437,7 @@ function makeWhatsAppFileDelivery(entry, maxyAccountId) {
|
|
|
25089
25437
|
if (!delivered) {
|
|
25090
25438
|
const fileField = call.filePath !== void 0 ? ` file=${call.filePath}` : "";
|
|
25091
25439
|
console.error(
|
|
25092
|
-
`${
|
|
25440
|
+
`${TAG42} file-delivery-unreconciled sender=${entry.senderId} sessionId=${sid} tool=${WHATSAPP_SEND_DOCUMENT}${fileField}`
|
|
25093
25441
|
);
|
|
25094
25442
|
}
|
|
25095
25443
|
}
|
|
@@ -25480,35 +25828,35 @@ function buildTelegramSpawnRequest(input) {
|
|
|
25480
25828
|
}
|
|
25481
25829
|
|
|
25482
25830
|
// app/lib/telegram/outbound/send-document.ts
|
|
25483
|
-
import { realpathSync as
|
|
25831
|
+
import { realpathSync as realpathSync9 } from "fs";
|
|
25484
25832
|
import { readFile as readFile7, stat as stat7 } from "fs/promises";
|
|
25485
|
-
import { resolve as
|
|
25486
|
-
var
|
|
25833
|
+
import { resolve as resolve33, basename as basename11 } from "path";
|
|
25834
|
+
var TAG43 = "[telegram:outbound]";
|
|
25487
25835
|
var TELEGRAM_DOCUMENT_MAX_BYTES = 50 * 1024 * 1024;
|
|
25488
25836
|
async function sendTelegramDocument(input) {
|
|
25489
|
-
const { botToken, chatId, filePath, caption, maxyAccountId, platformRoot:
|
|
25837
|
+
const { botToken, chatId, filePath, caption, maxyAccountId, platformRoot: platformRoot5 } = input;
|
|
25490
25838
|
if (!botToken || !filePath) {
|
|
25491
25839
|
return { ok: false, status: 400, error: "Missing required fields: botToken, filePath" };
|
|
25492
25840
|
}
|
|
25493
|
-
if (!maxyAccountId || !
|
|
25841
|
+
if (!maxyAccountId || !platformRoot5) {
|
|
25494
25842
|
return { ok: false, status: 400, error: "Cannot validate file path: missing account or platform context" };
|
|
25495
25843
|
}
|
|
25496
|
-
const accountDir =
|
|
25844
|
+
const accountDir = resolve33(platformRoot5, "..", "data/accounts", maxyAccountId);
|
|
25497
25845
|
let resolvedPath;
|
|
25498
25846
|
try {
|
|
25499
|
-
resolvedPath =
|
|
25500
|
-
const accountResolved =
|
|
25847
|
+
resolvedPath = realpathSync9(filePath);
|
|
25848
|
+
const accountResolved = realpathSync9(accountDir);
|
|
25501
25849
|
if (!resolvedPath.startsWith(accountResolved + "/")) {
|
|
25502
|
-
console.error(`${
|
|
25850
|
+
console.error(`${TAG43} document REJECTED reason=outside_account_directory maxyAccountId=${maxyAccountId}`);
|
|
25503
25851
|
return { ok: false, status: 403, error: "Access denied: file is outside the account directory" };
|
|
25504
25852
|
}
|
|
25505
25853
|
} catch (err) {
|
|
25506
25854
|
const code = err.code;
|
|
25507
25855
|
if (code === "ENOENT") {
|
|
25508
|
-
console.error(`${
|
|
25856
|
+
console.error(`${TAG43} document ENOENT path=${filePath}`);
|
|
25509
25857
|
return { ok: false, status: 404, error: `File not found: ${filePath}` };
|
|
25510
25858
|
}
|
|
25511
|
-
console.error(`${
|
|
25859
|
+
console.error(`${TAG43} document path error: ${String(err)}`);
|
|
25512
25860
|
return { ok: false, status: 500, error: String(err) };
|
|
25513
25861
|
}
|
|
25514
25862
|
const fileStat = await stat7(resolvedPath);
|
|
@@ -25541,14 +25889,14 @@ async function sendTelegramDocument(input) {
|
|
|
25541
25889
|
error = e instanceof Error ? e.message : String(e);
|
|
25542
25890
|
}
|
|
25543
25891
|
console.error(
|
|
25544
|
-
`${
|
|
25892
|
+
`${TAG43} sent document to=${chatId} file=${filename} bytes=${fileStat.size} ok=${ok}` + (messageId !== void 0 ? ` id=${messageId}` : "")
|
|
25545
25893
|
);
|
|
25546
25894
|
return ok ? { ok: true, messageId } : { ok: false, status: 500, error };
|
|
25547
25895
|
}
|
|
25548
25896
|
|
|
25549
25897
|
// app/lib/telegram/outbound/file-delivery.ts
|
|
25550
|
-
var
|
|
25551
|
-
function
|
|
25898
|
+
var TAG44 = "[telegram:outbound]";
|
|
25899
|
+
function platformRoot4() {
|
|
25552
25900
|
return process.env.MAXY_PLATFORM_ROOT || "";
|
|
25553
25901
|
}
|
|
25554
25902
|
function makeTelegramSendFile(entry) {
|
|
@@ -25559,11 +25907,11 @@ function makeTelegramSendFile(entry) {
|
|
|
25559
25907
|
botToken = (entry.role === "admin" ? tg?.adminBotToken : tg?.publicBotToken) ?? null;
|
|
25560
25908
|
}
|
|
25561
25909
|
if (!botToken) {
|
|
25562
|
-
console.error(`${
|
|
25910
|
+
console.error(`${TAG44} file-delivery reject reason=no-bot-token sender=${entry.senderId} role=${entry.role}`);
|
|
25563
25911
|
return { ok: false, error: "no-bot-token" };
|
|
25564
25912
|
}
|
|
25565
25913
|
if (entry.replyTarget == null) {
|
|
25566
|
-
console.error(`${
|
|
25914
|
+
console.error(`${TAG44} file-delivery reject reason=no-reply-target sender=${entry.senderId} role=${entry.role}`);
|
|
25567
25915
|
return { ok: false, error: "no-reply-target" };
|
|
25568
25916
|
}
|
|
25569
25917
|
const result = await sendTelegramDocument({
|
|
@@ -25572,7 +25920,7 @@ function makeTelegramSendFile(entry) {
|
|
|
25572
25920
|
filePath,
|
|
25573
25921
|
caption,
|
|
25574
25922
|
maxyAccountId: entry.accountId,
|
|
25575
|
-
platformRoot:
|
|
25923
|
+
platformRoot: platformRoot4()
|
|
25576
25924
|
});
|
|
25577
25925
|
return result.ok ? { ok: true } : { ok: false, error: result.error };
|
|
25578
25926
|
};
|
|
@@ -25580,7 +25928,7 @@ function makeTelegramSendFile(entry) {
|
|
|
25580
25928
|
function makeTelegramFileDelivery(entry) {
|
|
25581
25929
|
return makeFileDelivery({
|
|
25582
25930
|
entry,
|
|
25583
|
-
tag:
|
|
25931
|
+
tag: TAG44,
|
|
25584
25932
|
channel: "telegram",
|
|
25585
25933
|
sendFile: makeTelegramSendFile(entry)
|
|
25586
25934
|
});
|
|
@@ -25620,17 +25968,17 @@ function startTelegramNativeFileFollower(input) {
|
|
|
25620
25968
|
}
|
|
25621
25969
|
|
|
25622
25970
|
// server/telegram-descriptor.ts
|
|
25623
|
-
import { resolve as
|
|
25971
|
+
import { resolve as resolve34, join as join37 } from "path";
|
|
25624
25972
|
function telegramGatewayUrl() {
|
|
25625
25973
|
return `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`;
|
|
25626
25974
|
}
|
|
25627
25975
|
function telegramServerPath() {
|
|
25628
|
-
return process.env.MAXY_TELEGRAM_CHANNEL_SERVER_PATH ??
|
|
25976
|
+
return process.env.MAXY_TELEGRAM_CHANNEL_SERVER_PATH ?? resolve34(process.env.MAXY_PLATFORM_ROOT ?? join37(__dirname, ".."), "services/telegram-channel/dist/server.js");
|
|
25629
25977
|
}
|
|
25630
25978
|
|
|
25631
25979
|
// app/lib/channel-pty-bridge/public-session-end-review.ts
|
|
25632
|
-
import { randomUUID as
|
|
25633
|
-
var
|
|
25980
|
+
import { randomUUID as randomUUID16 } from "crypto";
|
|
25981
|
+
var TAG45 = "[public-session-review]";
|
|
25634
25982
|
var CONSUMED_CAP = 500;
|
|
25635
25983
|
var consumed = /* @__PURE__ */ new Set();
|
|
25636
25984
|
function consumeOnce(sessionId) {
|
|
@@ -25657,7 +26005,7 @@ async function fetchJsonl(sessionId) {
|
|
|
25657
26005
|
return await res.text();
|
|
25658
26006
|
} catch (err) {
|
|
25659
26007
|
console.error(
|
|
25660
|
-
`${
|
|
26008
|
+
`${TAG45} jsonl-fetch-failed sessionId=${sessionId} err="${err instanceof Error ? err.message : String(err)}"`
|
|
25661
26009
|
);
|
|
25662
26010
|
return null;
|
|
25663
26011
|
}
|
|
@@ -25681,7 +26029,7 @@ async function fetchPriorWrites(sliceToken, accountId) {
|
|
|
25681
26029
|
const res = await fetch(url);
|
|
25682
26030
|
if (!res.ok) {
|
|
25683
26031
|
console.error(
|
|
25684
|
-
`${
|
|
26032
|
+
`${TAG45} prior-writes-fetch-failed sliceToken=${sliceToken.slice(0, 8)} status=${res.status}`
|
|
25685
26033
|
);
|
|
25686
26034
|
return [];
|
|
25687
26035
|
}
|
|
@@ -25689,7 +26037,7 @@ async function fetchPriorWrites(sliceToken, accountId) {
|
|
|
25689
26037
|
return Array.isArray(body.writes) ? body.writes : [];
|
|
25690
26038
|
} catch (err) {
|
|
25691
26039
|
console.error(
|
|
25692
|
-
`${
|
|
26040
|
+
`${TAG45} prior-writes-fetch-threw sliceToken=${sliceToken.slice(0, 8)} err="${err instanceof Error ? err.message : String(err)}"`
|
|
25693
26041
|
);
|
|
25694
26042
|
return [];
|
|
25695
26043
|
}
|
|
@@ -25717,8 +26065,8 @@ function composeInitialMessage(input) {
|
|
|
25717
26065
|
].join("\n");
|
|
25718
26066
|
}
|
|
25719
26067
|
async function dispatchReviewer(input, initialMessage) {
|
|
25720
|
-
const sessionId =
|
|
25721
|
-
console.log(`${
|
|
26068
|
+
const sessionId = randomUUID16();
|
|
26069
|
+
console.log(`${TAG45} route target=rc-spawn sessionId=${sessionId.slice(0, 8)} sourceSession=${input.sessionId.slice(0, 8)}`);
|
|
25722
26070
|
const spawned = await managerRcSpawn({
|
|
25723
26071
|
sessionId,
|
|
25724
26072
|
initialMessage,
|
|
@@ -25738,21 +26086,21 @@ async function firePublicSessionEndReview(input) {
|
|
|
25738
26086
|
const dispatchedAt = Date.now();
|
|
25739
26087
|
if (consumed.has(input.sessionId)) {
|
|
25740
26088
|
console.log(
|
|
25741
|
-
`${
|
|
26089
|
+
`${TAG45} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-already-reviewed`
|
|
25742
26090
|
);
|
|
25743
26091
|
return;
|
|
25744
26092
|
}
|
|
25745
26093
|
const jsonl = await fetchJsonl(input.sessionId);
|
|
25746
26094
|
if (!jsonl) {
|
|
25747
26095
|
console.log(
|
|
25748
|
-
`${
|
|
26096
|
+
`${TAG45} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-jsonl-missing`
|
|
25749
26097
|
);
|
|
25750
26098
|
return;
|
|
25751
26099
|
}
|
|
25752
26100
|
const operatorTurns = countOperatorTurns(jsonl);
|
|
25753
26101
|
if (operatorTurns === 0) {
|
|
25754
26102
|
console.log(
|
|
25755
|
-
`${
|
|
26103
|
+
`${TAG45} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-no-turns`
|
|
25756
26104
|
);
|
|
25757
26105
|
return;
|
|
25758
26106
|
}
|
|
@@ -25766,19 +26114,19 @@ async function firePublicSessionEndReview(input) {
|
|
|
25766
26114
|
});
|
|
25767
26115
|
if (!consumeOnce(input.sessionId)) {
|
|
25768
26116
|
console.log(
|
|
25769
|
-
`${
|
|
26117
|
+
`${TAG45} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-already-reviewed`
|
|
25770
26118
|
);
|
|
25771
26119
|
return;
|
|
25772
26120
|
}
|
|
25773
26121
|
const dispatched = await dispatchReviewer(input, initialMessage);
|
|
25774
26122
|
if (!dispatched.ok) {
|
|
25775
26123
|
console.error(
|
|
25776
|
-
`${
|
|
26124
|
+
`${TAG45} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-spawn-failed reason=${dispatched.reason}`
|
|
25777
26125
|
);
|
|
25778
26126
|
return;
|
|
25779
26127
|
}
|
|
25780
26128
|
console.log(
|
|
25781
|
-
`${
|
|
26129
|
+
`${TAG45} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=dispatched managerSessionId=${dispatched.managerSessionId} operatorTurns=${operatorTurns} priorWrites=${priorWrites.length} ms=${Date.now() - dispatchedAt}`
|
|
25782
26130
|
);
|
|
25783
26131
|
}
|
|
25784
26132
|
|
|
@@ -25888,7 +26236,7 @@ function broadcastAdminShutdown(reason) {
|
|
|
25888
26236
|
// ../lib/entitlement/src/index.ts
|
|
25889
26237
|
import { createPublicKey, createHash as createHash6, verify as cryptoVerify } from "crypto";
|
|
25890
26238
|
import { existsSync as existsSync35, readFileSync as readFileSync37, statSync as statSync13 } from "fs";
|
|
25891
|
-
import { resolve as
|
|
26239
|
+
import { resolve as resolve35 } from "path";
|
|
25892
26240
|
|
|
25893
26241
|
// ../lib/entitlement/src/canonicalize.ts
|
|
25894
26242
|
function canonicalize(value) {
|
|
@@ -25923,7 +26271,7 @@ var PUBKEY_SHA256 = "8eee6bcb33545fd13b16d3199a5735ca5db5062834c7b49dfe4f23801d9
|
|
|
25923
26271
|
var GRACE_DAYS = 7;
|
|
25924
26272
|
var GRACE_MS = GRACE_DAYS * 24 * 60 * 60 * 1e3;
|
|
25925
26273
|
function pubkeyPath(brand) {
|
|
25926
|
-
return
|
|
26274
|
+
return resolve35(brand.platformRoot, "lib", "entitlement", "rubytech-pubkey.pem");
|
|
25927
26275
|
}
|
|
25928
26276
|
var memo = null;
|
|
25929
26277
|
function memoKey(mtimeMs, account) {
|
|
@@ -25935,7 +26283,7 @@ function resolveEntitlement(brand, account) {
|
|
|
25935
26283
|
if (brand.commercialMode !== true) {
|
|
25936
26284
|
return logResolved(implicitTrust(account), null);
|
|
25937
26285
|
}
|
|
25938
|
-
const entitlementPath =
|
|
26286
|
+
const entitlementPath = resolve35(brand.configDir, "entitlement.json");
|
|
25939
26287
|
if (!existsSync35(entitlementPath)) {
|
|
25940
26288
|
return logResolved(anonymousFallback("missing"), { reason: "missing" });
|
|
25941
26289
|
}
|
|
@@ -26195,6 +26543,7 @@ function isPublicHost(host) {
|
|
|
26195
26543
|
}
|
|
26196
26544
|
var app62 = new Hono();
|
|
26197
26545
|
var nativeFileFollowers = /* @__PURE__ */ new Map();
|
|
26546
|
+
var webchatFileFollowers = /* @__PURE__ */ new Map();
|
|
26198
26547
|
async function fetchAccountStandingRules(accountId) {
|
|
26199
26548
|
const session = getSession();
|
|
26200
26549
|
try {
|
|
@@ -26232,7 +26581,7 @@ async function recordPassiveDispatch(input) {
|
|
|
26232
26581
|
var waGateway = new WaGateway({
|
|
26233
26582
|
fetchStandingRules: fetchAccountStandingRules,
|
|
26234
26583
|
gatewayUrl: `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`,
|
|
26235
|
-
serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ??
|
|
26584
|
+
serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve36(process.env.MAXY_PLATFORM_ROOT ?? join38(__dirname, ".."), "services/whatsapp-channel/dist/server.js"),
|
|
26236
26585
|
// Task 751 / 1390 — file delivery on the native channel. `maxyAccountId` (the
|
|
26237
26586
|
// path-validation scope) is the sender's effective SESSION account, resolved
|
|
26238
26587
|
// once at the inbound gate and threaded here via the gateway's per-sender doc
|
|
@@ -26247,7 +26596,7 @@ var waGateway = new WaGateway({
|
|
|
26247
26596
|
caption,
|
|
26248
26597
|
accountId,
|
|
26249
26598
|
maxyAccountId,
|
|
26250
|
-
platformRoot:
|
|
26599
|
+
platformRoot: resolve36(process.env.MAXY_PLATFORM_ROOT ?? join38(__dirname, ".."))
|
|
26251
26600
|
});
|
|
26252
26601
|
return result.ok ? { ok: true, messageId: result.messageId } : { ok: false, error: result.error };
|
|
26253
26602
|
},
|
|
@@ -26405,6 +26754,20 @@ var webchatGateway = new WebchatGateway({
|
|
|
26405
26754
|
console.error(`[webchat:inbound] op=spawn-failed key=${key} error=${result.error} status=${result.status}`);
|
|
26406
26755
|
return;
|
|
26407
26756
|
}
|
|
26757
|
+
const priorWebchatFollower = webchatFileFollowers.get(key);
|
|
26758
|
+
if (priorWebchatFollower) priorWebchatFollower.abort();
|
|
26759
|
+
let wac;
|
|
26760
|
+
wac = startWebchatNativeFileFollower({
|
|
26761
|
+
sessionId: result.sessionId,
|
|
26762
|
+
key,
|
|
26763
|
+
// The session's own resolved account (house or sub-account) — the
|
|
26764
|
+
// file-path validation scope, exactly as passed to the spawn above.
|
|
26765
|
+
accountId,
|
|
26766
|
+
onClose: () => {
|
|
26767
|
+
if (webchatFileFollowers.get(key) === wac) webchatFileFollowers.delete(key);
|
|
26768
|
+
}
|
|
26769
|
+
});
|
|
26770
|
+
webchatFileFollowers.set(key, wac);
|
|
26408
26771
|
return { sessionId: result.sessionId };
|
|
26409
26772
|
},
|
|
26410
26773
|
// Task-962 — the recovery pass asks the manager to respawn a wedged already-
|
|
@@ -26866,8 +27229,8 @@ app62.get("/agent-assets/:slug/:filename", (c) => {
|
|
|
26866
27229
|
console.error(`[agent-assets] no-account slug=${slug} file=${filename}`);
|
|
26867
27230
|
return c.text("Not found", 404);
|
|
26868
27231
|
}
|
|
26869
|
-
const filePath =
|
|
26870
|
-
const expectedDir =
|
|
27232
|
+
const filePath = resolve36(account.accountDir, "agents", slug, "assets", filename);
|
|
27233
|
+
const expectedDir = resolve36(account.accountDir, "agents", slug, "assets");
|
|
26871
27234
|
if (!filePath.startsWith(expectedDir + "/")) {
|
|
26872
27235
|
console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
|
|
26873
27236
|
return c.text("Forbidden", 403);
|
|
@@ -26896,8 +27259,8 @@ app62.get("/generated/:filename", (c) => {
|
|
|
26896
27259
|
console.error(`[generated] serve file=${filename} status=404`);
|
|
26897
27260
|
return c.text("Not found", 404);
|
|
26898
27261
|
}
|
|
26899
|
-
const filePath =
|
|
26900
|
-
const expectedDir =
|
|
27262
|
+
const filePath = resolve36(account.accountDir, "generated", filename);
|
|
27263
|
+
const expectedDir = resolve36(account.accountDir, "generated");
|
|
26901
27264
|
if (!filePath.startsWith(expectedDir + "/")) {
|
|
26902
27265
|
console.error(`[generated] serve file=${filename} status=403`);
|
|
26903
27266
|
return c.text("Forbidden", 403);
|
|
@@ -26951,11 +27314,11 @@ var brandScript = `<script>window.__BRAND__=${JSON.stringify({
|
|
|
26951
27314
|
var brandThemeColor = BRAND.defaultColors?.primary ?? "#000000";
|
|
26952
27315
|
var brandBackgroundColor = BRAND.defaultColors?.background ?? "#ffffff";
|
|
26953
27316
|
var brandAppIconsExist = [brandAppIcon192Path, brandAppIcon512Path, brandMaskableIconPath].every(
|
|
26954
|
-
(p) => existsSync36(
|
|
27317
|
+
(p) => existsSync36(resolve36(process.cwd(), "public", p.replace(/^\//, "")))
|
|
26955
27318
|
);
|
|
26956
27319
|
var SW_SOURCE = (() => {
|
|
26957
27320
|
try {
|
|
26958
|
-
return readFileSync38(
|
|
27321
|
+
return readFileSync38(resolve36(process.cwd(), "public", "sw.js"), "utf-8");
|
|
26959
27322
|
} catch {
|
|
26960
27323
|
return null;
|
|
26961
27324
|
}
|
|
@@ -27006,7 +27369,7 @@ var clientErrorReporterScript = `<script>
|
|
|
27006
27369
|
function cachedHtml(file) {
|
|
27007
27370
|
let html = htmlCache.get(file);
|
|
27008
27371
|
if (!html) {
|
|
27009
|
-
html = readFileSync38(
|
|
27372
|
+
html = readFileSync38(resolve36(process.cwd(), "public", file), "utf-8");
|
|
27010
27373
|
const productNameEsc = escapeHtml(BRAND.productName);
|
|
27011
27374
|
html = html.replace(/<title>([^<]*)<\/title>/, (_match, inner) => `<title>${escapeHtml(inner).replace(/Maxy/g, productNameEsc)}</title>`);
|
|
27012
27375
|
html = html.replace('href="/favicon.ico"', `href="${escapeHtml(brandFaviconPath)}"`);
|
|
@@ -27124,7 +27487,7 @@ app62.use("/vnc-popout.html", logViewerFetch);
|
|
|
27124
27487
|
app62.get("/vnc-popout.html", (c) => {
|
|
27125
27488
|
let html = htmlCache.get("vnc-popout.html");
|
|
27126
27489
|
if (!html) {
|
|
27127
|
-
html = readFileSync38(
|
|
27490
|
+
html = readFileSync38(resolve36(process.cwd(), "public", "vnc-popout.html"), "utf-8");
|
|
27128
27491
|
const name = escapeHtml(BRAND.productName);
|
|
27129
27492
|
html = html.replace("<title>Browser \u2014 Maxy</title>", `<title>${name}</title>`);
|
|
27130
27493
|
html = html.replace("</head>", ` ${brandScript}
|
|
@@ -27257,7 +27620,7 @@ var httpServer = serve({ fetch: app62.fetch, port, hostname });
|
|
|
27257
27620
|
console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
27258
27621
|
{
|
|
27259
27622
|
const reconcilePlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join38(__dirname, "..");
|
|
27260
|
-
const reconcileScript =
|
|
27623
|
+
const reconcileScript = resolve36(reconcilePlatformRoot, "plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js");
|
|
27261
27624
|
const RECONCILE_INTERVAL_MS = 12e4;
|
|
27262
27625
|
const runReconcile = () => {
|
|
27263
27626
|
if (!existsSync36(reconcileScript)) return;
|
|
@@ -27279,7 +27642,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
27279
27642
|
}
|
|
27280
27643
|
{
|
|
27281
27644
|
const outlookPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join38(__dirname, "..");
|
|
27282
|
-
const outlookScript =
|
|
27645
|
+
const outlookScript = resolve36(outlookPlatformRoot, "plugins/outlook/mcp/dist/scripts/complete-registration.js");
|
|
27283
27646
|
const OUTLOOK_COMPLETE_INTERVAL_MS = 3e4;
|
|
27284
27647
|
const runOutlookComplete = () => {
|
|
27285
27648
|
if (!existsSync36(outlookScript)) return;
|
|
@@ -27301,7 +27664,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
27301
27664
|
}
|
|
27302
27665
|
{
|
|
27303
27666
|
const auditRoot = process.env.MAXY_PLATFORM_ROOT ?? join38(__dirname, "..");
|
|
27304
|
-
const strandedAccountsDir =
|
|
27667
|
+
const strandedAccountsDir = resolve36(auditRoot, "..", "data/accounts");
|
|
27305
27668
|
const STRANDED_AUDIT_INTERVAL_MS = 3e5;
|
|
27306
27669
|
const STRANDED_AGE_MS = 16 * 6e4;
|
|
27307
27670
|
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;
|
|
@@ -27311,7 +27674,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
27311
27674
|
const now = Date.now();
|
|
27312
27675
|
for (const name of readdirSync21(strandedAccountsDir)) {
|
|
27313
27676
|
if (!STRANDED_UUID_RE.test(name)) continue;
|
|
27314
|
-
const pendingPath2 =
|
|
27677
|
+
const pendingPath2 = resolve36(strandedAccountsDir, name, "secrets/outlook/pending-devicecode.enc");
|
|
27315
27678
|
if (!existsSync36(pendingPath2)) continue;
|
|
27316
27679
|
const ageMs = now - statSync14(pendingPath2).mtimeMs;
|
|
27317
27680
|
if (ageMs > STRANDED_AGE_MS) {
|
|
@@ -27339,10 +27702,19 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
27339
27702
|
auditFirst.unref();
|
|
27340
27703
|
const auditLoop = setInterval(runStorageAuditSafe, STORAGE_AUDIT_INTERVAL_MS);
|
|
27341
27704
|
auditLoop.unref();
|
|
27705
|
+
const runPagesAuditSafe = () => {
|
|
27706
|
+
runPagesAudit(auditPlatformRoot).catch(
|
|
27707
|
+
(err) => console.error(`[pages-audit] error="${err.message}"`)
|
|
27708
|
+
);
|
|
27709
|
+
};
|
|
27710
|
+
const pagesAuditFirst = setTimeout(runPagesAuditSafe, 35e3);
|
|
27711
|
+
pagesAuditFirst.unref();
|
|
27712
|
+
const pagesAuditLoop = setInterval(runPagesAuditSafe, STORAGE_AUDIT_INTERVAL_MS);
|
|
27713
|
+
pagesAuditLoop.unref();
|
|
27342
27714
|
}
|
|
27343
27715
|
{
|
|
27344
27716
|
const publishPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join38(__dirname, "..");
|
|
27345
|
-
const publishScript =
|
|
27717
|
+
const publishScript = resolve36(publishPlatformRoot, "plugins/scheduling/mcp/dist/scripts/publish-availability.js");
|
|
27346
27718
|
const PUBLISH_INTERVAL_MS = 3e5;
|
|
27347
27719
|
const currentAccount = () => {
|
|
27348
27720
|
try {
|
|
@@ -27371,7 +27743,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
27371
27743
|
}
|
|
27372
27744
|
};
|
|
27373
27745
|
const auditSnapshotAge = (account) => {
|
|
27374
|
-
const availPath =
|
|
27746
|
+
const availPath = resolve36(account.accountDir, "calendar-availability.json");
|
|
27375
27747
|
let hasBookingSite = false;
|
|
27376
27748
|
try {
|
|
27377
27749
|
if (existsSync36(availPath)) {
|
|
@@ -27381,7 +27753,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
27381
27753
|
} catch {
|
|
27382
27754
|
}
|
|
27383
27755
|
if (!hasBookingSite) return;
|
|
27384
|
-
const statePath =
|
|
27756
|
+
const statePath = resolve36(account.accountDir, "state", "booking-availability", "last-publish.json");
|
|
27385
27757
|
let lastSuccessAt = null;
|
|
27386
27758
|
if (existsSync36(statePath)) {
|
|
27387
27759
|
try {
|
|
@@ -27410,7 +27782,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
27410
27782
|
startTimeEntryCensus(() => getSession());
|
|
27411
27783
|
{
|
|
27412
27784
|
const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join38(__dirname, "..");
|
|
27413
|
-
const auditScript =
|
|
27785
|
+
const auditScript = resolve36(auditPlatformRoot, "plugins/connector/mcp/dist/scripts/audit-connectors.js");
|
|
27414
27786
|
const auditLogDir = process.env.LOG_DIR ?? LOG_DIR;
|
|
27415
27787
|
const CONNECTOR_AUDIT_INTERVAL_MS = 3e5;
|
|
27416
27788
|
const runConnectorAudit = () => {
|
|
@@ -27679,7 +28051,7 @@ if (bootAccountConfig?.whatsapp) {
|
|
|
27679
28051
|
}
|
|
27680
28052
|
init({
|
|
27681
28053
|
configDir: configDirForWhatsApp,
|
|
27682
|
-
platformRoot:
|
|
28054
|
+
platformRoot: resolve36(process.env.MAXY_PLATFORM_ROOT ?? join38(__dirname, "..")),
|
|
27683
28055
|
accountConfig: bootAccountConfig,
|
|
27684
28056
|
onMessage: async (msg) => {
|
|
27685
28057
|
if (msg.isOwnerMirror) {
|