@rubytech/create-maxy-code 0.1.34 → 0.1.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +4 -1
- package/payload/platform/plugins/docs/references/platform.md +3 -1
- package/payload/platform/services/claude-session-manager/dist/config.d.ts +0 -5
- package/payload/platform/services/claude-session-manager/dist/config.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/config.js +16 -6
- package/payload/platform/services/claude-session-manager/dist/config.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.d.ts +0 -5
- 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 +98 -131
- package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/index.js +0 -1
- package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/jsonl-observer.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/jsonl-observer.js +38 -9
- package/payload/platform/services/claude-session-manager/dist/jsonl-observer.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts +14 -61
- 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 +109 -104
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/session-store.d.ts +30 -36
- package/payload/platform/services/claude-session-manager/dist/session-store.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/session-store.js +65 -58
- package/payload/platform/services/claude-session-manager/dist/session-store.js.map +1 -1
- package/payload/platform/templates/agents/admin/IDENTITY.md +5 -5
- package/payload/server/public/assets/{Checkbox-C6zXApx_.js → Checkbox-C_5g1tvd.js} +1 -1
- package/payload/server/public/assets/{admin-CF2ZQvXu.js → admin-CMhAQf3x.js} +24 -24
- package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-BYXgFii5.js → architectureDiagram-Q4EWVU46-PATAR9cB.js} +1 -1
- package/payload/server/public/assets/{blockDiagram-DXYQGD6D-GIQ0eO13.js → blockDiagram-DXYQGD6D-BTtUDSn8.js} +1 -1
- package/payload/server/public/assets/{brand-DdhkC994.css → brand--hRSJcTa.css} +1 -1
- package/payload/server/public/assets/{c4Diagram-AHTNJAMY-BmyWfG-l.js → c4Diagram-AHTNJAMY-DagJLqud.js} +1 -1
- package/payload/server/public/assets/channel-ad6bhEyF.js +1 -0
- package/payload/server/public/assets/{chunk-336JU56O-DcWl0MQo.js → chunk-336JU56O-r_17ZSte.js} +2 -2
- package/payload/server/public/assets/{chunk-426QAEUC-BIW6kq6y.js → chunk-426QAEUC-BeZHE5Od.js} +1 -1
- package/payload/server/public/assets/{chunk-4TB4RGXK-CdoHpV4X.js → chunk-4TB4RGXK-BOKuzFDs.js} +1 -1
- package/payload/server/public/assets/{chunk-5FUZZQ4R-bn_a4sfU.js → chunk-5FUZZQ4R-CFPql_Mb.js} +1 -1
- package/payload/server/public/assets/{chunk-5PVQY5BW-C_Rq8j_M.js → chunk-5PVQY5BW-B-ooj0Oj.js} +1 -1
- package/payload/server/public/assets/{chunk-EDXVE4YY-CWQvoVKV.js → chunk-EDXVE4YY-pfgSmAaU.js} +1 -1
- package/payload/server/public/assets/{chunk-ENJZ2VHE-DBHn1kSk.js → chunk-ENJZ2VHE-Czo3wSBG.js} +1 -1
- package/payload/server/public/assets/{chunk-ICPOFSXX-SW2Qx11O.js → chunk-ICPOFSXX-B0Kq8LNp.js} +1 -1
- package/payload/server/public/assets/{chunk-OYMX7WX6-BvIG7tVW.js → chunk-OYMX7WX6-BM97IkL3.js} +1 -1
- package/payload/server/public/assets/{chunk-U2HBQHQK-BiBUb0cF.js → chunk-U2HBQHQK-Qu1CuohC.js} +1 -1
- package/payload/server/public/assets/{chunk-X2U36JSP-Y0MKZCCh.js → chunk-X2U36JSP-uDlh8MVE.js} +1 -1
- package/payload/server/public/assets/{chunk-YZCP3GAM-DKPh06GH.js → chunk-YZCP3GAM-DUlG-OZ5.js} +1 -1
- package/payload/server/public/assets/{chunk-ZZ45TVLE-C2WNo-fK.js → chunk-ZZ45TVLE-BABivBFM.js} +1 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-D9Gycby2.js +1 -0
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-sUgm3wmz.js +1 -0
- package/payload/server/public/assets/clone-CZxh5VW0.js +1 -0
- package/payload/server/public/assets/{dagre-CrK8E9ee.js → dagre-BLaP4HDY.js} +1 -1
- package/payload/server/public/assets/{dagre-KV5264BT-_o6uXcH8.js → dagre-KV5264BT-CVL1mRVD.js} +1 -1
- package/payload/server/public/assets/data-DarDs6k1.js +1 -0
- package/payload/server/public/assets/{device-url-actions-BcHerWqJ.js → device-url-actions-Dmhh-Azv.js} +1 -1
- package/payload/server/public/assets/{diagram-5BDNPKRD-FFP9DKhc.js → diagram-5BDNPKRD-Db75sppc.js} +1 -1
- package/payload/server/public/assets/{diagram-G4DWMVQ6-DpwD1jBP.js → diagram-G4DWMVQ6-Cj8Nvgev.js} +1 -1
- package/payload/server/public/assets/{diagram-MMDJMWI5-C3K5agdK.js → diagram-MMDJMWI5-BGXJmtU0.js} +1 -1
- package/payload/server/public/assets/{diagram-TYMM5635-CbeDipbC.js → diagram-TYMM5635-FALU804i.js} +1 -1
- package/payload/server/public/assets/{erDiagram-SMLLAGMA-XBIFndNy.js → erDiagram-SMLLAGMA-Dny5IMgt.js} +1 -1
- package/payload/server/public/assets/{flowDiagram-DWJPFMVM-BvEgySyn.js → flowDiagram-DWJPFMVM-CvKuRNSd.js} +1 -1
- package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-D7gIRKJf.js → ganttDiagram-T4ZO3ILL-CMMNRVGJ.js} +1 -1
- package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-vJu_hcri.js → gitGraphDiagram-UUTBAWPF-GNp7o9CH.js} +1 -1
- package/payload/server/public/assets/graph-CG9KcTMy.js +1 -0
- package/payload/server/public/assets/graph-labels-DnFPoPy9.js +1 -0
- package/payload/server/public/assets/{graphlib-Dp0mN6JW.js → graphlib-Bbf4iSQ9.js} +1 -1
- package/payload/server/public/assets/{infoDiagram-42DDH7IO-g4Dlc5Cr.js → infoDiagram-42DDH7IO-CKnsQ4zf.js} +1 -1
- package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-D_45LXOe.js → ishikawaDiagram-UXIWVN3A-7iiLy5h7.js} +1 -1
- package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-CggbHl6N.js → journeyDiagram-VCZTEJTY-BqbrYu64.js} +1 -1
- package/payload/server/public/assets/{kanban-definition-6JOO6SKY-CysAe-Ab.js → kanban-definition-6JOO6SKY-B4xrW1HU.js} +1 -1
- package/payload/server/public/assets/{line-BAxq_DSY.js → line-VuY4jgLe.js} +1 -1
- package/payload/server/public/assets/{mermaid-parser.core-DbFuvkjL.js → mermaid-parser.core-BaqOkGpC.js} +1 -1
- package/payload/server/public/assets/{mermaid.core-CehvJn5b.js → mermaid.core-CCQHCJiH.js} +3 -3
- package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-DbPbBJ9h.js → mindmap-definition-QFDTVHPH-CD7_gX12.js} +1 -1
- package/payload/server/public/assets/page-BbunxlG3.js +1 -0
- package/payload/server/public/assets/{page-Co7KCRV8.js → page-CDFsJW62.js} +1 -1
- package/payload/server/public/assets/{pieDiagram-DEJITSTG-cagLL9ng.js → pieDiagram-DEJITSTG-DYv6IDvS.js} +1 -1
- package/payload/server/public/assets/{public-B6TEcDLx.js → public-vZ5OE_BJ.js} +3 -3
- package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-Keaa1jDh.js → quadrantDiagram-34T5L4WZ-Djjgb1kX.js} +1 -1
- package/payload/server/public/assets/{requirementDiagram-MS252O5E-BcYRyn5z.js → requirementDiagram-MS252O5E-D1jpw_fu.js} +1 -1
- package/payload/server/public/assets/{sankeyDiagram-XADWPNL6--fKoG9NR.js → sankeyDiagram-XADWPNL6-CiWmspyf.js} +1 -1
- package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-lKG36-Di.js → sequenceDiagram-FGHM5R23-B1GXIeQe.js} +1 -1
- package/payload/server/public/assets/{stateDiagram-FHFEXIEX-BuVsrlig.js → stateDiagram-FHFEXIEX-DX7QZrhc.js} +1 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-CekuC-ks.js +1 -0
- package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-D6X6uq17.js → timeline-definition-GMOUNBTQ-BxiwnKFu.js} +1 -1
- package/payload/server/public/assets/{vennDiagram-DHZGUBPP-BgvcfRVf.js → vennDiagram-DHZGUBPP-RxZA_K0W.js} +1 -1
- package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-Cpd1xsrt.js → wardleyDiagram-NUSXRM2D-b2tVWjtB.js} +1 -1
- package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-CDF5ZVFv.js → xychartDiagram-5P7HB3ND-D55tkJH1.js} +1 -1
- package/payload/server/public/data.html +5 -5
- package/payload/server/public/graph.html +6 -6
- package/payload/server/public/index.html +8 -8
- package/payload/server/public/public.html +5 -5
- package/payload/server/server.js +149 -129
- package/payload/docs/desktop-code-controls.md +0 -63
- package/payload/server/public/assets/channel-C76knBRO.js +0 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-Bohexn7P.js +0 -1
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-DVsmsAu7.js +0 -1
- package/payload/server/public/assets/clone-DUrXF4sO.js +0 -1
- package/payload/server/public/assets/data-j1WNhF8t.js +0 -1
- package/payload/server/public/assets/graph-C_f_9L_7.js +0 -1
- package/payload/server/public/assets/graph-labels-BSQJHlgf.js +0 -1
- package/payload/server/public/assets/page-B0BPrSE3.js +0 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-DSt88_xL.js +0 -1
- /package/payload/server/public/assets/{brand-B-bNrpwc.js → brand-B62OQoRC.js} +0 -0
package/payload/server/server.js
CHANGED
|
@@ -595,8 +595,8 @@ var serveStatic = (options = { root: "" }) => {
|
|
|
595
595
|
};
|
|
596
596
|
|
|
597
597
|
// server/index.ts
|
|
598
|
-
import { readFileSync as
|
|
599
|
-
import { resolve as
|
|
598
|
+
import { readFileSync as readFileSync20, existsSync as existsSync22, watchFile } from "fs";
|
|
599
|
+
import { resolve as resolve23, join as join12, basename as basename5 } from "path";
|
|
600
600
|
import { homedir as homedir4 } from "os";
|
|
601
601
|
|
|
602
602
|
// app/lib/agent-slug-pattern.ts
|
|
@@ -1416,7 +1416,7 @@ var credsSaveQueue = Promise.resolve();
|
|
|
1416
1416
|
async function drainCredsSaveQueue(timeoutMs = 5e3) {
|
|
1417
1417
|
console.error(`${TAG3} draining credential save queue\u2026`);
|
|
1418
1418
|
const timer2 = new Promise(
|
|
1419
|
-
(
|
|
1419
|
+
(resolve24) => setTimeout(() => resolve24("timeout"), timeoutMs)
|
|
1420
1420
|
);
|
|
1421
1421
|
const result = await Promise.race([
|
|
1422
1422
|
credsSaveQueue.then(() => "drained"),
|
|
@@ -1544,11 +1544,11 @@ async function createWaSocket(opts) {
|
|
|
1544
1544
|
return sock;
|
|
1545
1545
|
}
|
|
1546
1546
|
async function waitForConnection(sock) {
|
|
1547
|
-
return new Promise((
|
|
1547
|
+
return new Promise((resolve24, reject) => {
|
|
1548
1548
|
const handler = (update) => {
|
|
1549
1549
|
if (update.connection === "open") {
|
|
1550
1550
|
sock.ev.off("connection.update", handler);
|
|
1551
|
-
|
|
1551
|
+
resolve24();
|
|
1552
1552
|
}
|
|
1553
1553
|
if (update.connection === "close") {
|
|
1554
1554
|
sock.ev.off("connection.update", handler);
|
|
@@ -1662,14 +1662,14 @@ ${inspected}`;
|
|
|
1662
1662
|
return inspect2(err, INSPECT_OPTS2);
|
|
1663
1663
|
}
|
|
1664
1664
|
function withTimeout(label, promise, timeoutMs) {
|
|
1665
|
-
return new Promise((
|
|
1665
|
+
return new Promise((resolve24, reject) => {
|
|
1666
1666
|
const timer2 = setTimeout(() => {
|
|
1667
1667
|
reject(new Error(`${label} timed out after ${timeoutMs}ms`));
|
|
1668
1668
|
}, timeoutMs);
|
|
1669
1669
|
promise.then(
|
|
1670
1670
|
(value) => {
|
|
1671
1671
|
clearTimeout(timer2);
|
|
1672
|
-
|
|
1672
|
+
resolve24(value);
|
|
1673
1673
|
},
|
|
1674
1674
|
(err) => {
|
|
1675
1675
|
clearTimeout(timer2);
|
|
@@ -2204,8 +2204,8 @@ async function persistWhatsAppMessage(input) {
|
|
|
2204
2204
|
const { givenName, familyName } = splitName(input.pushName);
|
|
2205
2205
|
const prev = sessionWriteLocks.get(input.cacheKey);
|
|
2206
2206
|
let release;
|
|
2207
|
-
const mine = new Promise((
|
|
2208
|
-
release =
|
|
2207
|
+
const mine = new Promise((resolve24) => {
|
|
2208
|
+
release = resolve24;
|
|
2209
2209
|
});
|
|
2210
2210
|
const chained = (prev ?? Promise.resolve()).then(() => mine);
|
|
2211
2211
|
sessionWriteLocks.set(input.cacheKey, chained);
|
|
@@ -3242,11 +3242,11 @@ async function connectWithReconnect(conn) {
|
|
|
3242
3242
|
console.error(
|
|
3243
3243
|
`${TAG13} reconnecting account=${conn.accountId} in ${delay}ms (attempt ${decision.nextAttempts}/${maxAttempts})`
|
|
3244
3244
|
);
|
|
3245
|
-
await new Promise((
|
|
3246
|
-
const timer2 = setTimeout(
|
|
3245
|
+
await new Promise((resolve24) => {
|
|
3246
|
+
const timer2 = setTimeout(resolve24, delay);
|
|
3247
3247
|
conn.abortController.signal.addEventListener("abort", () => {
|
|
3248
3248
|
clearTimeout(timer2);
|
|
3249
|
-
|
|
3249
|
+
resolve24();
|
|
3250
3250
|
}, { once: true });
|
|
3251
3251
|
});
|
|
3252
3252
|
}
|
|
@@ -3254,16 +3254,16 @@ async function connectWithReconnect(conn) {
|
|
|
3254
3254
|
}
|
|
3255
3255
|
}
|
|
3256
3256
|
function waitForDisconnectEvent(conn) {
|
|
3257
|
-
return new Promise((
|
|
3257
|
+
return new Promise((resolve24) => {
|
|
3258
3258
|
if (!conn.sock) {
|
|
3259
|
-
|
|
3259
|
+
resolve24();
|
|
3260
3260
|
return;
|
|
3261
3261
|
}
|
|
3262
3262
|
const sock = conn.sock;
|
|
3263
3263
|
const handler = (update) => {
|
|
3264
3264
|
if (update.connection === "close") {
|
|
3265
3265
|
sock.ev.off("connection.update", handler);
|
|
3266
|
-
|
|
3266
|
+
resolve24();
|
|
3267
3267
|
}
|
|
3268
3268
|
};
|
|
3269
3269
|
sock.ev.on("connection.update", handler);
|
|
@@ -3525,8 +3525,8 @@ async function handleInboundMessage(conn, msg) {
|
|
|
3525
3525
|
const conversationKey = isGroup ? remoteJid : senderPhone;
|
|
3526
3526
|
const debounceKey = `${conn.accountId}:${conversationKey}:${senderPhone}`;
|
|
3527
3527
|
let resolvePending;
|
|
3528
|
-
const sttPending = new Promise((
|
|
3529
|
-
resolvePending =
|
|
3528
|
+
const sttPending = new Promise((resolve24) => {
|
|
3529
|
+
resolvePending = resolve24;
|
|
3530
3530
|
});
|
|
3531
3531
|
if (conn.debouncer) conn.debouncer.registerPending(debounceKey, sttPending);
|
|
3532
3532
|
try {
|
|
@@ -3930,20 +3930,20 @@ function buildX11Env(chromiumWrapperPath, transport = "vnc") {
|
|
|
3930
3930
|
|
|
3931
3931
|
// server/routes/health.ts
|
|
3932
3932
|
function checkPort(port2, timeoutMs = 500) {
|
|
3933
|
-
return new Promise((
|
|
3933
|
+
return new Promise((resolve24) => {
|
|
3934
3934
|
const socket = createConnection2(port2, "127.0.0.1");
|
|
3935
3935
|
socket.setTimeout(timeoutMs);
|
|
3936
3936
|
socket.once("connect", () => {
|
|
3937
3937
|
socket.destroy();
|
|
3938
|
-
|
|
3938
|
+
resolve24(true);
|
|
3939
3939
|
});
|
|
3940
3940
|
socket.once("error", () => {
|
|
3941
3941
|
socket.destroy();
|
|
3942
|
-
|
|
3942
|
+
resolve24(false);
|
|
3943
3943
|
});
|
|
3944
3944
|
socket.once("timeout", () => {
|
|
3945
3945
|
socket.destroy();
|
|
3946
|
-
|
|
3946
|
+
resolve24(false);
|
|
3947
3947
|
});
|
|
3948
3948
|
});
|
|
3949
3949
|
}
|
|
@@ -5019,12 +5019,12 @@ async function dispatchOnce(input) {
|
|
|
5019
5019
|
});
|
|
5020
5020
|
if (!entry) return { error: "spawn-failed" };
|
|
5021
5021
|
entry.lastInboundAt = Date.now();
|
|
5022
|
-
let
|
|
5022
|
+
let resolve24;
|
|
5023
5023
|
const turnPromise = new Promise((r) => {
|
|
5024
|
-
|
|
5024
|
+
resolve24 = r;
|
|
5025
5025
|
});
|
|
5026
5026
|
const listener = (text) => {
|
|
5027
|
-
|
|
5027
|
+
resolve24(text);
|
|
5028
5028
|
};
|
|
5029
5029
|
entry.subscribers.add(listener);
|
|
5030
5030
|
const writeOk = await writeInput(entry, input.text);
|
|
@@ -5387,8 +5387,8 @@ async function startLogin(opts) {
|
|
|
5387
5387
|
resetActiveLogin(accountId);
|
|
5388
5388
|
let resolveQr = null;
|
|
5389
5389
|
let rejectQr = null;
|
|
5390
|
-
const qrPromise = new Promise((
|
|
5391
|
-
resolveQr =
|
|
5390
|
+
const qrPromise = new Promise((resolve24, reject) => {
|
|
5391
|
+
resolveQr = resolve24;
|
|
5392
5392
|
rejectQr = reject;
|
|
5393
5393
|
});
|
|
5394
5394
|
const qrTimer = setTimeout(
|
|
@@ -7957,6 +7957,23 @@ function computeDormantPlugins(accountId) {
|
|
|
7957
7957
|
}
|
|
7958
7958
|
|
|
7959
7959
|
// server/routes/admin/claude-sessions.ts
|
|
7960
|
+
import { readFileSync as readFileSync14 } from "fs";
|
|
7961
|
+
import { resolve as resolve12 } from "path";
|
|
7962
|
+
function resolveTunnelUrl() {
|
|
7963
|
+
const platformRoot = process.env.MAXY_PLATFORM_ROOT ?? process.env.PLATFORM_ROOT ?? resolve12(process.cwd(), "..");
|
|
7964
|
+
let brand;
|
|
7965
|
+
try {
|
|
7966
|
+
brand = JSON.parse(readFileSync14(resolve12(platformRoot, "config", "brand.json"), "utf-8"));
|
|
7967
|
+
} catch {
|
|
7968
|
+
return null;
|
|
7969
|
+
}
|
|
7970
|
+
const hostname2 = typeof brand.hostname === "string" && brand.hostname ? brand.hostname : null;
|
|
7971
|
+
const configDir2 = typeof brand.configDir === "string" && brand.configDir ? brand.configDir : null;
|
|
7972
|
+
if (!hostname2 || !configDir2) return null;
|
|
7973
|
+
const state = readTunnelState(configDir2);
|
|
7974
|
+
if (!state) return null;
|
|
7975
|
+
return `https://${hostname2}.${state.domain}`;
|
|
7976
|
+
}
|
|
7960
7977
|
var TAG18 = "[claude-session-manager:wrapper]";
|
|
7961
7978
|
function managerBase2() {
|
|
7962
7979
|
const port2 = Number(process.env.CLAUDE_SESSION_MANAGER_PORT ?? "19400");
|
|
@@ -7965,10 +7982,11 @@ function managerBase2() {
|
|
|
7965
7982
|
var app15 = new Hono();
|
|
7966
7983
|
app15.use("*", requireAdminSession);
|
|
7967
7984
|
app15.post("/", async (c) => {
|
|
7985
|
+
const routeStart = Date.now();
|
|
7968
7986
|
const cacheKey = c.get("cacheKey") ?? "";
|
|
7969
7987
|
const senderId = getAccountIdForSession(cacheKey) ?? "";
|
|
7970
7988
|
if (!senderId) {
|
|
7971
|
-
console.error(`${TAG18} reject reason=no-account-id`);
|
|
7989
|
+
console.error(`${TAG18} reject reason=no-account-id cacheKey-prefix=${cacheKey.slice(0, 8)}`);
|
|
7972
7990
|
return c.json({ error: "admin-account-not-resolved" }, 500);
|
|
7973
7991
|
}
|
|
7974
7992
|
const userId = getUserIdForSession(cacheKey);
|
|
@@ -7980,24 +7998,38 @@ app15.post("/", async (c) => {
|
|
|
7980
7998
|
const channel = typeof body.channel === "string" ? body.channel : "browser";
|
|
7981
7999
|
const initialMessage = typeof body.initialMessage === "string" && body.initialMessage.trim() ? body.initialMessage : null;
|
|
7982
8000
|
const permissionMode = typeof body.permissionMode === "string" ? body.permissionMode : void 0;
|
|
8001
|
+
console.log(`${TAG18} spawn-request-in cacheKey-prefix=${cacheKey.slice(0, 8)} senderId=${senderId.slice(0, 8)} userId=${userId ? userId.slice(0, 8) : "absent"} channel=${channel} permissionMode=${permissionMode ?? "default"} initialMessage=${initialMessage ? "yes" : "no"}`);
|
|
8002
|
+
const ownerStart = Date.now();
|
|
7983
8003
|
const aboutOwner = await resolveOwnerProfileBlock(senderId, userId);
|
|
8004
|
+
const ownerMs = Date.now() - ownerStart;
|
|
8005
|
+
const aboutOwnerStatus = aboutOwner == null ? "absent" : "ok" in aboutOwner && aboutOwner.ok === false ? `unresolved:${aboutOwner.reason}` : "ok";
|
|
8006
|
+
console.log(`${TAG18} about-owner-resolved status=${aboutOwnerStatus} ms=${ownerMs}`);
|
|
8007
|
+
const dormantStart = Date.now();
|
|
7984
8008
|
const dormantPlugins = computeDormantPlugins(senderId);
|
|
8009
|
+
console.log(`${TAG18} dormant-plugins-computed count=${Array.isArray(dormantPlugins) ? dormantPlugins.length : 0} ms=${Date.now() - dormantStart}`);
|
|
8010
|
+
const tunnelUrl = resolveTunnelUrl();
|
|
8011
|
+
console.log(`${TAG18} tunnel-url-resolved value=${tunnelUrl ?? "null"}`);
|
|
8012
|
+
const forwardStart = Date.now();
|
|
8013
|
+
const upstreamPayload = JSON.stringify({
|
|
8014
|
+
senderId,
|
|
8015
|
+
role: "admin",
|
|
8016
|
+
channel,
|
|
8017
|
+
permissionMode,
|
|
8018
|
+
aboutOwner,
|
|
8019
|
+
dormantPlugins,
|
|
8020
|
+
tunnelUrl
|
|
8021
|
+
});
|
|
8022
|
+
console.log(`${TAG18} forward-spawn-start managerBase=${managerBase2()} bytes=${upstreamPayload.length}`);
|
|
7985
8023
|
const upstream = await fetch(`${managerBase2()}/spawn`, {
|
|
7986
8024
|
method: "POST",
|
|
7987
8025
|
headers: { "content-type": "application/json" },
|
|
7988
|
-
body:
|
|
7989
|
-
senderId,
|
|
7990
|
-
role: "admin",
|
|
7991
|
-
channel,
|
|
7992
|
-
permissionMode,
|
|
7993
|
-
aboutOwner,
|
|
7994
|
-
dormantPlugins
|
|
7995
|
-
})
|
|
8026
|
+
body: upstreamPayload
|
|
7996
8027
|
}).catch((err) => {
|
|
7997
|
-
console.error(`${TAG18} fetch-failed op=spawn message=${err instanceof Error ? err.message : String(err)}`);
|
|
8028
|
+
console.error(`${TAG18} fetch-failed op=spawn message=${err instanceof Error ? err.message : String(err)} ms=${Date.now() - forwardStart}`);
|
|
7998
8029
|
return null;
|
|
7999
8030
|
});
|
|
8000
8031
|
if (!upstream) return c.json({ error: "manager-unreachable" }, 503);
|
|
8032
|
+
console.log(`${TAG18} forward-spawn-done status=${upstream.status} ms=${Date.now() - forwardStart} route-ms=${Date.now() - routeStart}`);
|
|
8001
8033
|
let spawnedSessionId = null;
|
|
8002
8034
|
if (upstream.ok && initialMessage) {
|
|
8003
8035
|
const buffered = await upstream.clone().json().catch(() => null);
|
|
@@ -8046,6 +8078,7 @@ app15.post("/resume", async (c) => {
|
|
|
8046
8078
|
const channel = typeof body.channel === "string" ? body.channel : "browser";
|
|
8047
8079
|
const aboutOwner = await resolveOwnerProfileBlock(senderId, userId);
|
|
8048
8080
|
const dormantPlugins = computeDormantPlugins(senderId);
|
|
8081
|
+
const tunnelUrl = resolveTunnelUrl();
|
|
8049
8082
|
const upstream = await fetch(`${managerBase2()}/resume`, {
|
|
8050
8083
|
method: "POST",
|
|
8051
8084
|
headers: { "content-type": "application/json" },
|
|
@@ -8055,7 +8088,8 @@ app15.post("/resume", async (c) => {
|
|
|
8055
8088
|
channel,
|
|
8056
8089
|
claudeSessionId: body.claudeSessionId,
|
|
8057
8090
|
aboutOwner,
|
|
8058
|
-
dormantPlugins
|
|
8091
|
+
dormantPlugins,
|
|
8092
|
+
tunnelUrl
|
|
8059
8093
|
})
|
|
8060
8094
|
}).catch((err) => {
|
|
8061
8095
|
console.error(`${TAG18} fetch-failed op=resume message=${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -8392,8 +8426,8 @@ var events_default = app19;
|
|
|
8392
8426
|
|
|
8393
8427
|
// server/routes/admin/cloudflare.ts
|
|
8394
8428
|
import { homedir as homedir3 } from "os";
|
|
8395
|
-
import { resolve as
|
|
8396
|
-
import { readFileSync as
|
|
8429
|
+
import { resolve as resolve14 } from "path";
|
|
8430
|
+
import { readFileSync as readFileSync16 } from "fs";
|
|
8397
8431
|
|
|
8398
8432
|
// app/lib/dns-label.ts
|
|
8399
8433
|
var VALID_LABEL = /^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$/;
|
|
@@ -8409,14 +8443,14 @@ function isValidDomain(value) {
|
|
|
8409
8443
|
}
|
|
8410
8444
|
|
|
8411
8445
|
// app/lib/alias-domains.ts
|
|
8412
|
-
import { existsSync as existsSync15, mkdirSync as mkdirSync4, readFileSync as
|
|
8446
|
+
import { existsSync as existsSync15, mkdirSync as mkdirSync4, readFileSync as readFileSync15, writeFileSync as writeFileSync8 } from "fs";
|
|
8413
8447
|
import { dirname as dirname2 } from "path";
|
|
8414
|
-
import { resolve as
|
|
8415
|
-
var ALIAS_DOMAINS_PATH =
|
|
8448
|
+
import { resolve as resolve13 } from "path";
|
|
8449
|
+
var ALIAS_DOMAINS_PATH = resolve13(MAXY_DIR, "alias-domains.json");
|
|
8416
8450
|
function readExisting() {
|
|
8417
8451
|
if (!existsSync15(ALIAS_DOMAINS_PATH)) return /* @__PURE__ */ new Set();
|
|
8418
8452
|
try {
|
|
8419
|
-
const parsed = JSON.parse(
|
|
8453
|
+
const parsed = JSON.parse(readFileSync15(ALIAS_DOMAINS_PATH, "utf-8"));
|
|
8420
8454
|
if (!Array.isArray(parsed)) return /* @__PURE__ */ new Set();
|
|
8421
8455
|
return new Set(parsed.filter((h) => typeof h === "string"));
|
|
8422
8456
|
} catch {
|
|
@@ -8683,7 +8717,7 @@ var CLOUDFLARE_SETUP_FORM_SCHEMA = {
|
|
|
8683
8717
|
|
|
8684
8718
|
// server/routes/admin/cloudflare.ts
|
|
8685
8719
|
function cloudflareStreamLogPath(accountId, correlationId) {
|
|
8686
|
-
return
|
|
8720
|
+
return resolve14(ACCOUNTS_DIR, accountId, "cloudflare-stream-logs", `${correlationId}.log`);
|
|
8687
8721
|
}
|
|
8688
8722
|
var SETUP_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
8689
8723
|
var DOMAINS_TIMEOUT_MS = 40 * 1e3;
|
|
@@ -8713,10 +8747,10 @@ function readDiscoveryResults(accountId) {
|
|
|
8713
8747
|
return { tunnels: entry.tunnels, domains: entry.domains };
|
|
8714
8748
|
}
|
|
8715
8749
|
function loadBrandInfo() {
|
|
8716
|
-
const platformRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
8717
|
-
const brandPath =
|
|
8750
|
+
const platformRoot = process.env.MAXY_PLATFORM_ROOT ?? resolve14(process.cwd(), "..");
|
|
8751
|
+
const brandPath = resolve14(platformRoot, "config", "brand.json");
|
|
8718
8752
|
try {
|
|
8719
|
-
const parsed = JSON.parse(
|
|
8753
|
+
const parsed = JSON.parse(readFileSync16(brandPath, "utf-8"));
|
|
8720
8754
|
const hostname2 = typeof parsed.hostname === "string" && parsed.hostname ? parsed.hostname : "maxy";
|
|
8721
8755
|
const configDir2 = typeof parsed.configDir === "string" && parsed.configDir ? parsed.configDir : ".maxy";
|
|
8722
8756
|
return { hostname: hostname2, configDir: configDir2 };
|
|
@@ -8844,7 +8878,7 @@ app20.get("/domains", requireAdminSession, async (c) => {
|
|
|
8844
8878
|
streamLogPath = cloudflareStreamLogPath(accountId, correlationId);
|
|
8845
8879
|
log(`phase=stream-log-resolved path=${streamLogPath}`);
|
|
8846
8880
|
const brand = loadBrandInfo();
|
|
8847
|
-
const scriptPath =
|
|
8881
|
+
const scriptPath = resolve14(homedir3(), "list-cf-domains.sh");
|
|
8848
8882
|
const result = await runFormSpawn({
|
|
8849
8883
|
scriptPath,
|
|
8850
8884
|
args: [brand.hostname],
|
|
@@ -8935,7 +8969,7 @@ app20.get("/tunnels", requireAdminSession, async (c) => {
|
|
|
8935
8969
|
if (!accountId) return err("session", "No account bound to session \u2014 refresh chat.");
|
|
8936
8970
|
if (!correlationId) return err("session", "No active conversation for session \u2014 refresh chat.");
|
|
8937
8971
|
streamLogPath = cloudflareStreamLogPath(accountId, correlationId);
|
|
8938
|
-
const certPath =
|
|
8972
|
+
const certPath = resolve14(homedir3(), brand.configDir, "cloudflared", "cert.pem");
|
|
8939
8973
|
const { existsSync: existsSync23 } = await import("fs");
|
|
8940
8974
|
if (!existsSync23(certPath)) {
|
|
8941
8975
|
return err("cert", `Cloudflare origin certificate is not on disk yet (${certPath}). Complete the Cloudflare login first by submitting the form once \u2014 the OAuth flow writes cert.pem.`);
|
|
@@ -9261,17 +9295,17 @@ var cloudflare_default = app20;
|
|
|
9261
9295
|
import { createReadStream as createReadStream3 } from "fs";
|
|
9262
9296
|
import { readdir as readdir2, readFile as readFile4, stat as stat4, mkdir as mkdir3, writeFile as writeFile4, unlink as unlink2 } from "fs/promises";
|
|
9263
9297
|
import { realpathSync as realpathSync4 } from "fs";
|
|
9264
|
-
import { basename as basename4, dirname as dirname4, join as join10, resolve as
|
|
9298
|
+
import { basename as basename4, dirname as dirname4, join as join10, resolve as resolve16, sep as sep3 } from "path";
|
|
9265
9299
|
import { Readable as Readable2 } from "stream";
|
|
9266
9300
|
|
|
9267
9301
|
// app/lib/data-path.ts
|
|
9268
9302
|
import { realpathSync as realpathSync3 } from "fs";
|
|
9269
|
-
import { resolve as
|
|
9270
|
-
var PLATFORM_ROOT5 = process.env.MAXY_PLATFORM_ROOT ??
|
|
9271
|
-
var DATA_ROOT =
|
|
9303
|
+
import { resolve as resolve15, normalize, sep as sep2, relative } from "path";
|
|
9304
|
+
var PLATFORM_ROOT5 = process.env.MAXY_PLATFORM_ROOT ?? resolve15(process.cwd(), "../platform");
|
|
9305
|
+
var DATA_ROOT = resolve15(PLATFORM_ROOT5, "..", "data");
|
|
9272
9306
|
function resolveDataPath(raw) {
|
|
9273
9307
|
const cleaned = normalize("/" + (raw ?? "").replace(/\\/g, "/")).replace(/^\/+/, "");
|
|
9274
|
-
const absolute =
|
|
9308
|
+
const absolute = resolve15(DATA_ROOT, cleaned);
|
|
9275
9309
|
let dataRootReal;
|
|
9276
9310
|
try {
|
|
9277
9311
|
dataRootReal = realpathSync3(DATA_ROOT);
|
|
@@ -9629,7 +9663,7 @@ async function readMeta(absDir, baseName) {
|
|
|
9629
9663
|
}
|
|
9630
9664
|
async function readAccountNames() {
|
|
9631
9665
|
const map = /* @__PURE__ */ new Map();
|
|
9632
|
-
const accountsDir =
|
|
9666
|
+
const accountsDir = resolve16(DATA_ROOT, "accounts");
|
|
9633
9667
|
let names;
|
|
9634
9668
|
try {
|
|
9635
9669
|
names = await readdir2(accountsDir);
|
|
@@ -9638,7 +9672,7 @@ async function readAccountNames() {
|
|
|
9638
9672
|
}
|
|
9639
9673
|
for (const name of names) {
|
|
9640
9674
|
if (!UUID_RE4.test(name)) continue;
|
|
9641
|
-
const configPath2 =
|
|
9675
|
+
const configPath2 = resolve16(accountsDir, name, "account.json");
|
|
9642
9676
|
try {
|
|
9643
9677
|
const raw = await readFile4(configPath2, "utf8");
|
|
9644
9678
|
const parsed = JSON.parse(raw);
|
|
@@ -9829,8 +9863,8 @@ app21.post("/upload", requireAdminSession, async (c) => {
|
|
|
9829
9863
|
}
|
|
9830
9864
|
const safeName = basename4(file.name).replace(/[\0/\\]/g, "_");
|
|
9831
9865
|
const finalName = `${Date.now()}-${safeName}`;
|
|
9832
|
-
const destDir =
|
|
9833
|
-
const destPath =
|
|
9866
|
+
const destDir = resolve16(DATA_ROOT, "uploads", accountId);
|
|
9867
|
+
const destPath = resolve16(destDir, finalName);
|
|
9834
9868
|
try {
|
|
9835
9869
|
await mkdir3(destDir, { recursive: true });
|
|
9836
9870
|
const dataRootReal = realpathSync4(DATA_ROOT);
|
|
@@ -11549,7 +11583,7 @@ var file_attach_default = app28;
|
|
|
11549
11583
|
// server/routes/admin/sidebar-artefacts.ts
|
|
11550
11584
|
import neo4j2 from "neo4j-driver";
|
|
11551
11585
|
import { readFile as readFile5, readdir as readdir3, stat as stat5 } from "fs/promises";
|
|
11552
|
-
import { resolve as
|
|
11586
|
+
import { resolve as resolve17, relative as relative2, isAbsolute } from "path";
|
|
11553
11587
|
import { existsSync as existsSync16 } from "fs";
|
|
11554
11588
|
var LIMIT = 50;
|
|
11555
11589
|
var TEXT_MIME_PREFIXES = ["text/", "application/json", "application/markdown"];
|
|
@@ -11566,7 +11600,7 @@ app29.get("/", requireAdminSession, async (c) => {
|
|
|
11566
11600
|
if (docs === null) {
|
|
11567
11601
|
return c.json({ error: "Failed to load artefacts" }, 500);
|
|
11568
11602
|
}
|
|
11569
|
-
const accountDir =
|
|
11603
|
+
const accountDir = resolve17(ACCOUNTS_DIR, accountId);
|
|
11570
11604
|
const agents = await fetchAgentTemplateRows(accountDir);
|
|
11571
11605
|
const artefacts = [...docs, ...agents].sort(
|
|
11572
11606
|
(a, b) => (b.updatedAt ?? "").localeCompare(a.updatedAt ?? "")
|
|
@@ -11629,8 +11663,8 @@ async function readArtefactContent(accountId, attachmentId, mimeType, displayNam
|
|
|
11629
11663
|
logSkip(displayName, "non-text-mime", mimeType);
|
|
11630
11664
|
return { content: "", skipReason: "non-text-mime" };
|
|
11631
11665
|
}
|
|
11632
|
-
const accountDir =
|
|
11633
|
-
const dir =
|
|
11666
|
+
const accountDir = resolve17(ATTACHMENTS_ROOT, accountId);
|
|
11667
|
+
const dir = resolve17(accountDir, attachmentId);
|
|
11634
11668
|
try {
|
|
11635
11669
|
validateFilePathInAccount(dir, accountDir);
|
|
11636
11670
|
} catch {
|
|
@@ -11644,7 +11678,7 @@ async function readArtefactContent(accountId, attachmentId, mimeType, displayNam
|
|
|
11644
11678
|
logSkip(displayName, "missing-on-disk", mimeType);
|
|
11645
11679
|
return { content: "", skipReason: "missing-on-disk" };
|
|
11646
11680
|
}
|
|
11647
|
-
return { content: await readFile5(
|
|
11681
|
+
return { content: await readFile5(resolve17(dir, dataFile), "utf-8"), skipReason: null };
|
|
11648
11682
|
} catch (err) {
|
|
11649
11683
|
const message = err instanceof Error ? err.message : String(err);
|
|
11650
11684
|
console.error(`[admin/sidebar-artefacts] read-failed attachmentId=${attachmentId.slice(0, 8)} error="${message}"`);
|
|
@@ -11660,8 +11694,8 @@ function logSkip(name, reason, mimeType) {
|
|
|
11660
11694
|
async function fetchAgentTemplateRows(accountDir) {
|
|
11661
11695
|
const rows = [];
|
|
11662
11696
|
for (const filename of ADMIN_AGENT_FILES) {
|
|
11663
|
-
const overridePath =
|
|
11664
|
-
const bundledPath =
|
|
11697
|
+
const overridePath = resolve17(accountDir, "agents", "admin", filename);
|
|
11698
|
+
const bundledPath = resolve17(PLATFORM_ROOT, "templates", "agents", "admin", filename);
|
|
11665
11699
|
const labelStem = filename.replace(/\.md$/, "");
|
|
11666
11700
|
const row = await readAgentTemplateRow({
|
|
11667
11701
|
id: `agent-template:admin:${filename}`,
|
|
@@ -11675,12 +11709,12 @@ async function fetchAgentTemplateRows(accountDir) {
|
|
|
11675
11709
|
});
|
|
11676
11710
|
if (row) rows.push(row);
|
|
11677
11711
|
}
|
|
11678
|
-
const overrideDir =
|
|
11679
|
-
const bundledDir =
|
|
11712
|
+
const overrideDir = resolve17(accountDir, "specialists", "agents");
|
|
11713
|
+
const bundledDir = resolve17(PLATFORM_ROOT, "templates", "specialists", "agents");
|
|
11680
11714
|
const specialistNames = await unionSpecialistFilenames(overrideDir, bundledDir);
|
|
11681
11715
|
for (const filename of specialistNames) {
|
|
11682
|
-
const overridePath =
|
|
11683
|
-
const bundledPath =
|
|
11716
|
+
const overridePath = resolve17(overrideDir, filename);
|
|
11717
|
+
const bundledPath = resolve17(bundledDir, filename);
|
|
11684
11718
|
const row = await readAgentTemplateRow({
|
|
11685
11719
|
id: `agent-template:specialist:${filename}`,
|
|
11686
11720
|
displayName: filename.replace(/\.md$/, ""),
|
|
@@ -11765,7 +11799,7 @@ var sidebar_artefacts_default = app29;
|
|
|
11765
11799
|
|
|
11766
11800
|
// server/routes/admin/sidebar-artefact-save.ts
|
|
11767
11801
|
import { mkdir as mkdir4, readdir as readdir4, stat as stat6, writeFile as writeFile5 } from "fs/promises";
|
|
11768
|
-
import { resolve as
|
|
11802
|
+
import { resolve as resolve18 } from "path";
|
|
11769
11803
|
import { existsSync as existsSync17 } from "fs";
|
|
11770
11804
|
var ADMIN_AGENT_FILES2 = /* @__PURE__ */ new Set(["IDENTITY.md", "SOUL.md", "KNOWLEDGE.md"]);
|
|
11771
11805
|
var UUID_RE5 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
|
|
@@ -11778,7 +11812,7 @@ app30.post("/", requireAdminSession, async (c) => {
|
|
|
11778
11812
|
if (!body || typeof body.id !== "string" || typeof body.content !== "string") {
|
|
11779
11813
|
return c.json({ error: "id and content required" }, 400);
|
|
11780
11814
|
}
|
|
11781
|
-
const accountDir =
|
|
11815
|
+
const accountDir = resolve18(ACCOUNTS_DIR, accountId);
|
|
11782
11816
|
const resolved = await resolveSavePath(body.id, accountId, accountDir);
|
|
11783
11817
|
if (resolved.kind === "heal-race") {
|
|
11784
11818
|
c.header("Retry-After", "2");
|
|
@@ -11823,17 +11857,17 @@ async function resolveSavePath(id, accountId, accountDir) {
|
|
|
11823
11857
|
if (role !== "admin" || !ADMIN_AGENT_FILES2.has(filename)) {
|
|
11824
11858
|
return { kind: "reject", status: 400, reason: "invalid-id" };
|
|
11825
11859
|
}
|
|
11826
|
-
const parent =
|
|
11860
|
+
const parent = resolve18(accountDir, "agents", "admin");
|
|
11827
11861
|
await mkdir4(parent, { recursive: true });
|
|
11828
11862
|
try {
|
|
11829
11863
|
validateFilePathInAccount(parent, accountDir);
|
|
11830
11864
|
} catch {
|
|
11831
11865
|
return { kind: "reject", status: 400, reason: "containment-rejected" };
|
|
11832
11866
|
}
|
|
11833
|
-
return { kind: "admin-template", path:
|
|
11867
|
+
return { kind: "admin-template", path: resolve18(parent, filename) };
|
|
11834
11868
|
}
|
|
11835
11869
|
if (UUID_RE5.test(id)) {
|
|
11836
|
-
const dir =
|
|
11870
|
+
const dir = resolve18(ATTACHMENTS_ROOT, accountId, id);
|
|
11837
11871
|
if (!existsSync17(dir)) {
|
|
11838
11872
|
const attShort = id.slice(0, 8);
|
|
11839
11873
|
if (isHealPending(accountId, id)) {
|
|
@@ -11866,7 +11900,7 @@ async function resolveSavePath(id, accountId, accountDir) {
|
|
|
11866
11900
|
}
|
|
11867
11901
|
}
|
|
11868
11902
|
try {
|
|
11869
|
-
validateFilePathInAccount(dir,
|
|
11903
|
+
validateFilePathInAccount(dir, resolve18(ATTACHMENTS_ROOT, accountId));
|
|
11870
11904
|
} catch {
|
|
11871
11905
|
return { kind: "reject", status: 400, reason: "containment-rejected" };
|
|
11872
11906
|
}
|
|
@@ -11875,7 +11909,7 @@ async function resolveSavePath(id, accountId, accountDir) {
|
|
|
11875
11909
|
if (!dataFile) {
|
|
11876
11910
|
return { kind: "reject", status: 400, reason: "not-found" };
|
|
11877
11911
|
}
|
|
11878
|
-
return { kind: "knowledge-doc", path:
|
|
11912
|
+
return { kind: "knowledge-doc", path: resolve18(dir, dataFile) };
|
|
11879
11913
|
}
|
|
11880
11914
|
return { kind: "reject", status: 400, reason: "invalid-id" };
|
|
11881
11915
|
}
|
|
@@ -11887,7 +11921,7 @@ var sidebar_artefact_save_default = app30;
|
|
|
11887
11921
|
// server/routes/admin/sidebar-artefact-content.ts
|
|
11888
11922
|
import { readFile as readFile6, readdir as readdir5 } from "fs/promises";
|
|
11889
11923
|
import { existsSync as existsSync18 } from "fs";
|
|
11890
|
-
import { resolve as
|
|
11924
|
+
import { resolve as resolve19 } from "path";
|
|
11891
11925
|
var UUID_RE6 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
|
|
11892
11926
|
var app31 = new Hono();
|
|
11893
11927
|
app31.get("/", requireAdminSession, async (c) => {
|
|
@@ -11899,14 +11933,14 @@ app31.get("/", requireAdminSession, async (c) => {
|
|
|
11899
11933
|
console.error(`[admin/sidebar-artefact-content] not-found id=${id.slice(0, 8)}`);
|
|
11900
11934
|
return new Response("Not found", { status: 404 });
|
|
11901
11935
|
}
|
|
11902
|
-
const dir =
|
|
11936
|
+
const dir = resolve19(ATTACHMENTS_ROOT, accountId, id);
|
|
11903
11937
|
if (!existsSync18(dir)) {
|
|
11904
11938
|
console.error(`[admin/sidebar-artefact-content] not-found id=${id.slice(0, 8)}`);
|
|
11905
11939
|
return new Response("Not found", { status: 404 });
|
|
11906
11940
|
}
|
|
11907
11941
|
let meta;
|
|
11908
11942
|
try {
|
|
11909
|
-
meta = JSON.parse(await readFile6(
|
|
11943
|
+
meta = JSON.parse(await readFile6(resolve19(dir, `${id}.meta.json`), "utf-8"));
|
|
11910
11944
|
} catch {
|
|
11911
11945
|
console.error(`[admin/sidebar-artefact-content] not-found id=${id.slice(0, 8)}`);
|
|
11912
11946
|
return new Response("Not found", { status: 404 });
|
|
@@ -11918,7 +11952,7 @@ app31.get("/", requireAdminSession, async (c) => {
|
|
|
11918
11952
|
return new Response("Not found", { status: 404 });
|
|
11919
11953
|
}
|
|
11920
11954
|
const start = Date.now();
|
|
11921
|
-
const buffer = await readFile6(
|
|
11955
|
+
const buffer = await readFile6(resolve19(dir, dataFile));
|
|
11922
11956
|
const ms = Date.now() - start;
|
|
11923
11957
|
console.log(
|
|
11924
11958
|
`[admin/sidebar-artefact-content] account=${accountId} id=${id.slice(0, 8)} mime=${meta.mimeType} bytes=${buffer.length} ms=${ms}`
|
|
@@ -11934,24 +11968,24 @@ app31.get("/", requireAdminSession, async (c) => {
|
|
|
11934
11968
|
var sidebar_artefact_content_default = app31;
|
|
11935
11969
|
|
|
11936
11970
|
// server/routes/admin/health.ts
|
|
11937
|
-
import { existsSync as existsSync19, readFileSync as
|
|
11938
|
-
import { resolve as
|
|
11939
|
-
var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ??
|
|
11971
|
+
import { existsSync as existsSync19, readFileSync as readFileSync17 } from "fs";
|
|
11972
|
+
import { resolve as resolve20, join as join11 } from "path";
|
|
11973
|
+
var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve20(process.cwd(), "..");
|
|
11940
11974
|
var brandHostname = "maxy";
|
|
11941
11975
|
var brandJsonPath = join11(PLATFORM_ROOT6, "config", "brand.json");
|
|
11942
11976
|
if (existsSync19(brandJsonPath)) {
|
|
11943
11977
|
try {
|
|
11944
|
-
const brand = JSON.parse(
|
|
11978
|
+
const brand = JSON.parse(readFileSync17(brandJsonPath, "utf-8"));
|
|
11945
11979
|
if (brand.hostname) brandHostname = brand.hostname;
|
|
11946
11980
|
} catch {
|
|
11947
11981
|
}
|
|
11948
11982
|
}
|
|
11949
|
-
var VERSION_FILE =
|
|
11983
|
+
var VERSION_FILE = resolve20(PLATFORM_ROOT6, `config/.${brandHostname}-version`);
|
|
11950
11984
|
var PROCESS_STARTED_AT = (/* @__PURE__ */ new Date()).toISOString();
|
|
11951
11985
|
var PROBE_TIMEOUT_MS = 1e3;
|
|
11952
11986
|
function readVersion() {
|
|
11953
11987
|
if (!existsSync19(VERSION_FILE)) return "unknown";
|
|
11954
|
-
return
|
|
11988
|
+
return readFileSync17(VERSION_FILE, "utf-8").trim() || "unknown";
|
|
11955
11989
|
}
|
|
11956
11990
|
async function probeConversationDb() {
|
|
11957
11991
|
let session;
|
|
@@ -12033,8 +12067,8 @@ app33.route("/health-brand", health_default2);
|
|
|
12033
12067
|
var admin_default = app33;
|
|
12034
12068
|
|
|
12035
12069
|
// server/routes/sites.ts
|
|
12036
|
-
import { existsSync as existsSync20, readFileSync as
|
|
12037
|
-
import { resolve as
|
|
12070
|
+
import { existsSync as existsSync20, readFileSync as readFileSync18, realpathSync as realpathSync5, statSync as statSync7 } from "fs";
|
|
12071
|
+
import { resolve as resolve21 } from "path";
|
|
12038
12072
|
var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
|
|
12039
12073
|
var MIME = {
|
|
12040
12074
|
".html": "text/html; charset=utf-8",
|
|
@@ -12091,8 +12125,8 @@ app34.get("/:rel{.*}", (c) => {
|
|
|
12091
12125
|
}
|
|
12092
12126
|
segments.push(seg);
|
|
12093
12127
|
}
|
|
12094
|
-
const rootDir =
|
|
12095
|
-
let filePath = segments.length === 0 ? rootDir :
|
|
12128
|
+
const rootDir = resolve21(account.accountDir, "sites");
|
|
12129
|
+
let filePath = segments.length === 0 ? rootDir : resolve21(rootDir, ...segments);
|
|
12096
12130
|
if (filePath !== rootDir && !filePath.startsWith(rootDir + "/")) {
|
|
12097
12131
|
console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
|
|
12098
12132
|
return c.text("Forbidden", 403);
|
|
@@ -12112,7 +12146,7 @@ app34.get("/:rel{.*}", (c) => {
|
|
|
12112
12146
|
return c.redirect(target, 301);
|
|
12113
12147
|
}
|
|
12114
12148
|
if (stat7?.isDirectory()) {
|
|
12115
|
-
filePath =
|
|
12149
|
+
filePath = resolve21(filePath, "index.html");
|
|
12116
12150
|
}
|
|
12117
12151
|
if (!filePath.startsWith(rootDir + "/")) {
|
|
12118
12152
|
console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
|
|
@@ -12137,7 +12171,7 @@ app34.get("/:rel{.*}", (c) => {
|
|
|
12137
12171
|
}
|
|
12138
12172
|
let body;
|
|
12139
12173
|
try {
|
|
12140
|
-
body =
|
|
12174
|
+
body = readFileSync18(realPath);
|
|
12141
12175
|
} catch (err) {
|
|
12142
12176
|
const code = err?.code;
|
|
12143
12177
|
if (code === "EISDIR") {
|
|
@@ -12283,8 +12317,8 @@ function startReaper2() {
|
|
|
12283
12317
|
|
|
12284
12318
|
// ../lib/entitlement/src/index.ts
|
|
12285
12319
|
import { createPublicKey, createHash as createHash3, verify as cryptoVerify } from "crypto";
|
|
12286
|
-
import { existsSync as existsSync21, readFileSync as
|
|
12287
|
-
import { resolve as
|
|
12320
|
+
import { existsSync as existsSync21, readFileSync as readFileSync19, statSync as statSync8 } from "fs";
|
|
12321
|
+
import { resolve as resolve22 } from "path";
|
|
12288
12322
|
|
|
12289
12323
|
// ../lib/entitlement/src/canonicalize.ts
|
|
12290
12324
|
function canonicalize(value) {
|
|
@@ -12319,7 +12353,7 @@ var PUBKEY_SHA256 = "8eee6bcb33545fd13b16d3199a5735ca5db5062834c7b49dfe4f23801d9
|
|
|
12319
12353
|
var GRACE_DAYS = 7;
|
|
12320
12354
|
var GRACE_MS = GRACE_DAYS * 24 * 60 * 60 * 1e3;
|
|
12321
12355
|
function pubkeyPath(brand) {
|
|
12322
|
-
return
|
|
12356
|
+
return resolve22(brand.platformRoot, "lib", "entitlement", "rubytech-pubkey.pem");
|
|
12323
12357
|
}
|
|
12324
12358
|
var memo = null;
|
|
12325
12359
|
function memoKey(mtimeMs, account) {
|
|
@@ -12331,7 +12365,7 @@ function resolveEntitlement(brand, account) {
|
|
|
12331
12365
|
if (brand.commercialMode !== true) {
|
|
12332
12366
|
return logResolved(implicitTrust(account), null);
|
|
12333
12367
|
}
|
|
12334
|
-
const entitlementPath =
|
|
12368
|
+
const entitlementPath = resolve22(brand.configDir, "entitlement.json");
|
|
12335
12369
|
if (!existsSync21(entitlementPath)) {
|
|
12336
12370
|
return logResolved(anonymousFallback("missing"), { reason: "missing" });
|
|
12337
12371
|
}
|
|
@@ -12347,7 +12381,7 @@ function resolveEntitlement(brand, account) {
|
|
|
12347
12381
|
function verifyAndResolve(brand, entitlementPath, account) {
|
|
12348
12382
|
let pubkeyPem;
|
|
12349
12383
|
try {
|
|
12350
|
-
pubkeyPem =
|
|
12384
|
+
pubkeyPem = readFileSync19(pubkeyPath(brand), "utf-8");
|
|
12351
12385
|
} catch (err) {
|
|
12352
12386
|
return logResolved(anonymousFallback("pubkey-missing"), {
|
|
12353
12387
|
reason: "pubkey-missing"
|
|
@@ -12361,7 +12395,7 @@ function verifyAndResolve(brand, entitlementPath, account) {
|
|
|
12361
12395
|
}
|
|
12362
12396
|
let envelope;
|
|
12363
12397
|
try {
|
|
12364
|
-
envelope = JSON.parse(
|
|
12398
|
+
envelope = JSON.parse(readFileSync19(entitlementPath, "utf-8"));
|
|
12365
12399
|
} catch {
|
|
12366
12400
|
return logResolved(anonymousFallback("malformed"), { reason: "malformed" });
|
|
12367
12401
|
}
|
|
@@ -12529,7 +12563,7 @@ if (BRAND_JSON_PATH && !existsSync22(BRAND_JSON_PATH)) {
|
|
|
12529
12563
|
}
|
|
12530
12564
|
if (BRAND_JSON_PATH && existsSync22(BRAND_JSON_PATH)) {
|
|
12531
12565
|
try {
|
|
12532
|
-
const parsed = JSON.parse(
|
|
12566
|
+
const parsed = JSON.parse(readFileSync20(BRAND_JSON_PATH, "utf-8"));
|
|
12533
12567
|
BRAND = { ...BRAND, ...parsed };
|
|
12534
12568
|
} catch (err) {
|
|
12535
12569
|
console.error(`[brand] Failed to parse brand.json: ${err.message}`);
|
|
@@ -12552,7 +12586,7 @@ var ALIAS_DOMAINS_PATH2 = join12(homedir4(), BRAND.configDir, "alias-domains.jso
|
|
|
12552
12586
|
function loadAliasDomains() {
|
|
12553
12587
|
try {
|
|
12554
12588
|
if (!existsSync22(ALIAS_DOMAINS_PATH2)) return null;
|
|
12555
|
-
const parsed = JSON.parse(
|
|
12589
|
+
const parsed = JSON.parse(readFileSync20(ALIAS_DOMAINS_PATH2, "utf-8"));
|
|
12556
12590
|
if (!Array.isArray(parsed)) {
|
|
12557
12591
|
console.error("[alias-domains] malformed alias-domains.json \u2014 expected array");
|
|
12558
12592
|
return null;
|
|
@@ -12922,8 +12956,8 @@ app35.get("/agent-assets/:slug/:filename", (c) => {
|
|
|
12922
12956
|
console.error(`[agent-assets] no-account slug=${slug} file=${filename}`);
|
|
12923
12957
|
return c.text("Not found", 404);
|
|
12924
12958
|
}
|
|
12925
|
-
const filePath =
|
|
12926
|
-
const expectedDir =
|
|
12959
|
+
const filePath = resolve23(account.accountDir, "agents", slug, "assets", filename);
|
|
12960
|
+
const expectedDir = resolve23(account.accountDir, "agents", slug, "assets");
|
|
12927
12961
|
if (!filePath.startsWith(expectedDir + "/")) {
|
|
12928
12962
|
console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
|
|
12929
12963
|
return c.text("Forbidden", 403);
|
|
@@ -12935,7 +12969,7 @@ app35.get("/agent-assets/:slug/:filename", (c) => {
|
|
|
12935
12969
|
const ext = "." + filename.split(".").pop()?.toLowerCase();
|
|
12936
12970
|
const contentType = IMAGE_MIME[ext] || "application/octet-stream";
|
|
12937
12971
|
console.log(`[agent-assets] serve slug=${slug} file=${filename} status=200`);
|
|
12938
|
-
const body =
|
|
12972
|
+
const body = readFileSync20(filePath);
|
|
12939
12973
|
return c.body(body, 200, {
|
|
12940
12974
|
"Content-Type": contentType,
|
|
12941
12975
|
"Cache-Control": "public, max-age=3600"
|
|
@@ -12952,8 +12986,8 @@ app35.get("/generated/:filename", (c) => {
|
|
|
12952
12986
|
console.error(`[generated] serve file=${filename} status=404`);
|
|
12953
12987
|
return c.text("Not found", 404);
|
|
12954
12988
|
}
|
|
12955
|
-
const filePath =
|
|
12956
|
-
const expectedDir =
|
|
12989
|
+
const filePath = resolve23(account.accountDir, "generated", filename);
|
|
12990
|
+
const expectedDir = resolve23(account.accountDir, "generated");
|
|
12957
12991
|
if (!filePath.startsWith(expectedDir + "/")) {
|
|
12958
12992
|
console.error(`[generated] serve file=${filename} status=403`);
|
|
12959
12993
|
return c.text("Forbidden", 403);
|
|
@@ -12965,7 +12999,7 @@ app35.get("/generated/:filename", (c) => {
|
|
|
12965
12999
|
const ext = "." + filename.split(".").pop()?.toLowerCase();
|
|
12966
13000
|
const contentType = IMAGE_MIME[ext] || "application/octet-stream";
|
|
12967
13001
|
console.log(`[generated] serve file=${filename} status=200`);
|
|
12968
|
-
const body =
|
|
13002
|
+
const body = readFileSync20(filePath);
|
|
12969
13003
|
return c.body(body, 200, {
|
|
12970
13004
|
"Content-Type": contentType,
|
|
12971
13005
|
"Cache-Control": "public, max-age=86400"
|
|
@@ -12977,7 +13011,7 @@ var brandLogoPath = "/brand/maxy-monochrome.png";
|
|
|
12977
13011
|
var brandIconPath = "/brand/maxy-monochrome.png";
|
|
12978
13012
|
if (BRAND_JSON_PATH && existsSync22(BRAND_JSON_PATH)) {
|
|
12979
13013
|
try {
|
|
12980
|
-
const fullBrand = JSON.parse(
|
|
13014
|
+
const fullBrand = JSON.parse(readFileSync20(BRAND_JSON_PATH, "utf-8"));
|
|
12981
13015
|
if (fullBrand.assets?.logo) brandLogoPath = `/brand/${fullBrand.assets.logo}`;
|
|
12982
13016
|
brandIconPath = fullBrand.assets?.icon ? `/brand/${fullBrand.assets.icon}` : brandLogoPath;
|
|
12983
13017
|
} catch {
|
|
@@ -12996,7 +13030,7 @@ function readInstalledVersion() {
|
|
|
12996
13030
|
if (!PLATFORM_ROOT7) return "unknown";
|
|
12997
13031
|
const versionFile = join12(PLATFORM_ROOT7, "config", `.${BRAND.hostname}-version`);
|
|
12998
13032
|
if (!existsSync22(versionFile)) return "unknown";
|
|
12999
|
-
const content =
|
|
13033
|
+
const content = readFileSync20(versionFile, "utf-8").trim();
|
|
13000
13034
|
return content || "unknown";
|
|
13001
13035
|
} catch {
|
|
13002
13036
|
return "unknown";
|
|
@@ -13037,7 +13071,7 @@ var clientErrorReporterScript = `<script>
|
|
|
13037
13071
|
function cachedHtml(file) {
|
|
13038
13072
|
let html = htmlCache.get(file);
|
|
13039
13073
|
if (!html) {
|
|
13040
|
-
html =
|
|
13074
|
+
html = readFileSync20(resolve23(process.cwd(), "public", file), "utf-8");
|
|
13041
13075
|
const productNameEsc = escapeHtml(BRAND.productName);
|
|
13042
13076
|
html = html.replace(/<title>([^<]*)<\/title>/, (_match, inner) => `<title>${escapeHtml(inner).replace(/Maxy/g, productNameEsc)}</title>`);
|
|
13043
13077
|
html = html.replace('href="/favicon.ico"', `href="${escapeHtml(brandFaviconPath)}"`);
|
|
@@ -13057,12 +13091,12 @@ function loadBrandingCache(agentSlug) {
|
|
|
13057
13091
|
try {
|
|
13058
13092
|
const accountJsonPath = join12(configDir2, "account.json");
|
|
13059
13093
|
if (!existsSync22(accountJsonPath)) return null;
|
|
13060
|
-
const account = JSON.parse(
|
|
13094
|
+
const account = JSON.parse(readFileSync20(accountJsonPath, "utf-8"));
|
|
13061
13095
|
const accountId = account.accountId;
|
|
13062
13096
|
if (!accountId) return null;
|
|
13063
13097
|
const cachePath = join12(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
|
|
13064
13098
|
if (!existsSync22(cachePath)) return null;
|
|
13065
|
-
return JSON.parse(
|
|
13099
|
+
return JSON.parse(readFileSync20(cachePath, "utf-8"));
|
|
13066
13100
|
} catch {
|
|
13067
13101
|
return null;
|
|
13068
13102
|
}
|
|
@@ -13072,7 +13106,7 @@ function resolveDefaultSlug() {
|
|
|
13072
13106
|
const configDir2 = join12(homedir4(), BRAND.configDir);
|
|
13073
13107
|
const accountJsonPath = join12(configDir2, "account.json");
|
|
13074
13108
|
if (!existsSync22(accountJsonPath)) return null;
|
|
13075
|
-
const account = JSON.parse(
|
|
13109
|
+
const account = JSON.parse(readFileSync20(accountJsonPath, "utf-8"));
|
|
13076
13110
|
return account.defaultAgent || null;
|
|
13077
13111
|
} catch {
|
|
13078
13112
|
return null;
|
|
@@ -13145,7 +13179,7 @@ app35.use("/vnc-popout.html", logViewerFetch);
|
|
|
13145
13179
|
app35.get("/vnc-popout.html", (c) => {
|
|
13146
13180
|
let html = htmlCache.get("vnc-popout.html");
|
|
13147
13181
|
if (!html) {
|
|
13148
|
-
html =
|
|
13182
|
+
html = readFileSync20(resolve23(process.cwd(), "public", "vnc-popout.html"), "utf-8");
|
|
13149
13183
|
const name = escapeHtml(BRAND.productName);
|
|
13150
13184
|
html = html.replace("<title>Browser \u2014 Maxy</title>", `<title>${name}</title>`);
|
|
13151
13185
|
html = html.replace("</head>", ` ${brandScript}
|
|
@@ -13194,20 +13228,6 @@ app35.get("/data", (c) => {
|
|
|
13194
13228
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
13195
13229
|
return c.html(cachedHtml("data.html"));
|
|
13196
13230
|
});
|
|
13197
|
-
app35.get("/docs/desktop-code-controls", (c) => {
|
|
13198
|
-
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
13199
|
-
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
13200
|
-
const docsPath = PLATFORM_ROOT7 ? resolve22(PLATFORM_ROOT7, "..", "docs", "desktop-code-controls.md") : resolve22(process.cwd(), "docs", "desktop-code-controls.md");
|
|
13201
|
-
if (!existsSync22(docsPath)) {
|
|
13202
|
-
console.error(`[docs] desktop-code-controls.md missing at ${docsPath}`);
|
|
13203
|
-
return c.text(`docs/desktop-code-controls.md not found at ${docsPath}`, 404);
|
|
13204
|
-
}
|
|
13205
|
-
const md = readFileSync19(docsPath, "utf-8");
|
|
13206
|
-
const escaped = md.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
13207
|
-
return c.html(
|
|
13208
|
-
`<!doctype html><meta charset="utf-8"><title>Desktop Code-tab controls</title><style>body{font:14px/1.55 -apple-system,system-ui,sans-serif;max-width:760px;margin:2rem auto;padding:0 1rem;color:#111}pre{white-space:pre-wrap;font:inherit}</style><pre>${escaped}</pre>`
|
|
13209
|
-
);
|
|
13210
|
-
});
|
|
13211
13231
|
app35.get("/:slug", async (c, next) => {
|
|
13212
13232
|
const slug = c.req.param("slug");
|
|
13213
13233
|
if (AGENT_SLUG_PATTERN.test(`/${slug}`)) {
|
|
@@ -13266,7 +13286,7 @@ try {
|
|
|
13266
13286
|
(async () => {
|
|
13267
13287
|
try {
|
|
13268
13288
|
if (!existsSync22(USERS_FILE)) return;
|
|
13269
|
-
const usersRaw =
|
|
13289
|
+
const usersRaw = readFileSync20(USERS_FILE, "utf-8").trim();
|
|
13270
13290
|
if (!usersRaw) return;
|
|
13271
13291
|
const users = JSON.parse(usersRaw);
|
|
13272
13292
|
const userId = users[0]?.userId;
|
|
@@ -13392,7 +13412,7 @@ if (bootAccountConfig?.whatsapp) {
|
|
|
13392
13412
|
}
|
|
13393
13413
|
init({
|
|
13394
13414
|
configDir: configDirForWhatsApp,
|
|
13395
|
-
platformRoot:
|
|
13415
|
+
platformRoot: resolve23(process.env.MAXY_PLATFORM_ROOT ?? join12(__dirname, "..")),
|
|
13396
13416
|
accountConfig: bootAccountConfig,
|
|
13397
13417
|
onMessage: async (msg) => {
|
|
13398
13418
|
if (process.env.WHATSAPP_PTY_BRIDGE_ENABLED === "true" && msg.text && !msg.isOwnerMirror) {
|