@rubytech/create-maxy 1.0.808 → 1.0.809
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/payload/platform/plugins/memory/mcp/dist/index.js +86 -0
- package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/whatsapp-export-insight-pass.d.ts +23 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/whatsapp-export-insight-pass.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/whatsapp-export-insight-pass.js +401 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/whatsapp-export-insight-pass.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/whatsapp-export-preview.d.ts +28 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/whatsapp-export-preview.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/whatsapp-export-preview.js +34 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/whatsapp-export-preview.js.map +1 -0
- package/payload/platform/plugins/memory/references/schema-base.md +12 -0
- package/payload/platform/plugins/whatsapp/PLUGIN.md +3 -1
- package/payload/platform/plugins/whatsapp-import/bin/ingest.mjs +225 -346
- package/payload/platform/plugins/whatsapp-import/bin/whatsapp-ingest.sh +28 -10
- package/payload/platform/plugins/whatsapp-import/lib/dist/derive-keys.d.ts +21 -0
- package/payload/platform/plugins/whatsapp-import/lib/dist/derive-keys.d.ts.map +1 -0
- package/payload/platform/plugins/whatsapp-import/lib/dist/derive-keys.js +41 -0
- package/payload/platform/plugins/whatsapp-import/lib/dist/derive-keys.js.map +1 -0
- package/payload/platform/plugins/whatsapp-import/lib/dist/filter.d.ts +29 -0
- package/payload/platform/plugins/whatsapp-import/lib/dist/filter.d.ts.map +1 -0
- package/payload/platform/plugins/whatsapp-import/lib/dist/filter.js +123 -0
- package/payload/platform/plugins/whatsapp-import/lib/dist/filter.js.map +1 -0
- package/payload/platform/plugins/whatsapp-import/lib/dist/index.d.ts +4 -0
- package/payload/platform/plugins/whatsapp-import/lib/dist/index.d.ts.map +1 -1
- package/payload/platform/plugins/whatsapp-import/lib/dist/index.js +9 -1
- package/payload/platform/plugins/whatsapp-import/lib/dist/index.js.map +1 -1
- package/payload/platform/plugins/whatsapp-import/lib/src/__tests__/filter-gate.test.ts +170 -0
- package/payload/platform/plugins/whatsapp-import/lib/src/__tests__/ingest-idempotence.test.ts +141 -0
- package/payload/platform/plugins/whatsapp-import/lib/src/derive-keys.ts +59 -0
- package/payload/platform/plugins/whatsapp-import/lib/src/filter.ts +136 -0
- package/payload/platform/plugins/whatsapp-import/lib/src/index.ts +12 -0
- package/payload/platform/plugins/whatsapp-import/skills/whatsapp-import/SKILL.md +80 -25
- package/payload/platform/plugins/whatsapp-import/skills/whatsapp-import-enrich/SKILL.md +22 -3
- package/payload/platform/templates/specialists/agents/database-operator.md +9 -4
- package/payload/server/public/assets/admin-Bwrd2DBq.js +352 -0
- package/payload/server/public/index.html +1 -1
- package/payload/server/server.js +271 -188
- package/payload/server/public/assets/admin-MxaCgGHZ.js +0 -352
package/payload/server/server.js
CHANGED
|
@@ -619,15 +619,15 @@ var serveStatic = (options = { root: "" }) => {
|
|
|
619
619
|
};
|
|
620
620
|
|
|
621
621
|
// server/index.ts
|
|
622
|
-
import { readFileSync as
|
|
623
|
-
import { resolve as
|
|
622
|
+
import { readFileSync as readFileSync19, existsSync as existsSync25, watchFile } from "fs";
|
|
623
|
+
import { resolve as resolve25, join as join11, basename as basename7 } from "path";
|
|
624
624
|
import { homedir as homedir2 } from "os";
|
|
625
625
|
|
|
626
626
|
// app/lib/agent-slug-pattern.ts
|
|
627
627
|
var AGENT_SLUG_PATTERN = /^\/([a-z][a-z0-9-]{2,49})$/;
|
|
628
628
|
|
|
629
629
|
// server/routes/health.ts
|
|
630
|
-
import { existsSync as existsSync6, readFileSync as
|
|
630
|
+
import { existsSync as existsSync6, readFileSync as readFileSync6 } from "fs";
|
|
631
631
|
import { createConnection } from "net";
|
|
632
632
|
|
|
633
633
|
// app/lib/network.ts
|
|
@@ -2836,7 +2836,7 @@ var credsSaveQueue = Promise.resolve();
|
|
|
2836
2836
|
async function drainCredsSaveQueue(timeoutMs = 5e3) {
|
|
2837
2837
|
console.error(`${TAG3} draining credential save queue\u2026`);
|
|
2838
2838
|
const timer2 = new Promise(
|
|
2839
|
-
(
|
|
2839
|
+
(resolve26) => setTimeout(() => resolve26("timeout"), timeoutMs)
|
|
2840
2840
|
);
|
|
2841
2841
|
const result = await Promise.race([
|
|
2842
2842
|
credsSaveQueue.then(() => "drained"),
|
|
@@ -2964,11 +2964,11 @@ async function createWaSocket(opts) {
|
|
|
2964
2964
|
return sock;
|
|
2965
2965
|
}
|
|
2966
2966
|
async function waitForConnection(sock) {
|
|
2967
|
-
return new Promise((
|
|
2967
|
+
return new Promise((resolve26, reject) => {
|
|
2968
2968
|
const handler = (update) => {
|
|
2969
2969
|
if (update.connection === "open") {
|
|
2970
2970
|
sock.ev.off("connection.update", handler);
|
|
2971
|
-
|
|
2971
|
+
resolve26();
|
|
2972
2972
|
}
|
|
2973
2973
|
if (update.connection === "close") {
|
|
2974
2974
|
sock.ev.off("connection.update", handler);
|
|
@@ -3082,14 +3082,14 @@ ${inspected}`;
|
|
|
3082
3082
|
return inspect2(err, INSPECT_OPTS2);
|
|
3083
3083
|
}
|
|
3084
3084
|
function withTimeout(label, promise, timeoutMs) {
|
|
3085
|
-
return new Promise((
|
|
3085
|
+
return new Promise((resolve26, reject) => {
|
|
3086
3086
|
const timer2 = setTimeout(() => {
|
|
3087
3087
|
reject(new Error(`${label} timed out after ${timeoutMs}ms`));
|
|
3088
3088
|
}, timeoutMs);
|
|
3089
3089
|
promise.then(
|
|
3090
3090
|
(value) => {
|
|
3091
3091
|
clearTimeout(timer2);
|
|
3092
|
-
|
|
3092
|
+
resolve26(value);
|
|
3093
3093
|
},
|
|
3094
3094
|
(err) => {
|
|
3095
3095
|
clearTimeout(timer2);
|
|
@@ -3610,8 +3610,8 @@ async function persistWhatsAppMessage(input) {
|
|
|
3610
3610
|
const { givenName, familyName } = splitName(input.pushName);
|
|
3611
3611
|
const prev = sessionWriteLocks.get(input.sessionKey);
|
|
3612
3612
|
let release;
|
|
3613
|
-
const mine = new Promise((
|
|
3614
|
-
release =
|
|
3613
|
+
const mine = new Promise((resolve26) => {
|
|
3614
|
+
release = resolve26;
|
|
3615
3615
|
});
|
|
3616
3616
|
const chained = (prev ?? Promise.resolve()).then(() => mine);
|
|
3617
3617
|
sessionWriteLocks.set(input.sessionKey, chained);
|
|
@@ -3629,7 +3629,7 @@ async function persistWhatsAppMessage(input) {
|
|
|
3629
3629
|
existingM IS NOT NULL AS messageExisted
|
|
3630
3630
|
MERGE (s:Person {telephone: $senderTelephone})
|
|
3631
3631
|
ON CREATE SET
|
|
3632
|
-
s.accountId = $
|
|
3632
|
+
s.accountId = $platformAccountId,
|
|
3633
3633
|
s.givenName = $givenName,
|
|
3634
3634
|
s.familyName = $familyName,
|
|
3635
3635
|
s.source = 'whatsapp-live',
|
|
@@ -3641,7 +3641,7 @@ async function persistWhatsAppMessage(input) {
|
|
|
3641
3641
|
MERGE (m:Message {messageId: $messageId})
|
|
3642
3642
|
ON CREATE SET
|
|
3643
3643
|
m:WhatsAppMessage,
|
|
3644
|
-
m.accountId = $
|
|
3644
|
+
m.accountId = $platformAccountId,
|
|
3645
3645
|
m.conversationId = c.conversationId,
|
|
3646
3646
|
m.source = 'whatsapp',
|
|
3647
3647
|
m.createdByAgent = 'whatsapp-live',
|
|
@@ -3687,7 +3687,7 @@ async function persistWhatsAppMessage(input) {
|
|
|
3687
3687
|
const params = {
|
|
3688
3688
|
sessionKey: input.sessionKey,
|
|
3689
3689
|
messageId,
|
|
3690
|
-
|
|
3690
|
+
platformAccountId: input.platformAccountId,
|
|
3691
3691
|
senderTelephone,
|
|
3692
3692
|
senderName: input.pushName ?? null,
|
|
3693
3693
|
givenName,
|
|
@@ -3704,7 +3704,7 @@ async function persistWhatsAppMessage(input) {
|
|
|
3704
3704
|
const result = await session.run(cypher, params);
|
|
3705
3705
|
const ms = Date.now() - t0;
|
|
3706
3706
|
if (result.records.length === 0) {
|
|
3707
|
-
console.error(`${TAG7} skip reason=conversation-not-found accountId=${input.
|
|
3707
|
+
console.error(`${TAG7} skip reason=conversation-not-found accountId=${input.platformAccountId} sessionKey=${input.sessionKey} messageId=${messageId}`);
|
|
3708
3708
|
return null;
|
|
3709
3709
|
}
|
|
3710
3710
|
const rec = result.records[0];
|
|
@@ -3725,14 +3725,14 @@ async function persistWhatsAppMessage(input) {
|
|
|
3725
3725
|
console.error(`${TAG7} next-skip reason=no-prior msgId=${messageId}`);
|
|
3726
3726
|
}
|
|
3727
3727
|
console.error(
|
|
3728
|
-
`${TAG7} write messageId=${messageId} sessionKey=${input.sessionKey} fromMe=${input.fromMe} dateSent=${dateSentIso} bodyBytes=${Buffer.byteLength(input.body, "utf8")} ms=${ms}`
|
|
3728
|
+
`${TAG7} write messageId=${messageId} accountId=${input.platformAccountId} sessionKey=${input.sessionKey} fromMe=${input.fromMe} dateSent=${dateSentIso} bodyBytes=${Buffer.byteLength(input.body, "utf8")} ms=${ms}`
|
|
3729
3729
|
);
|
|
3730
3730
|
return { messageId, created: true, senderElementId };
|
|
3731
3731
|
} catch (err) {
|
|
3732
3732
|
const ms = Date.now() - t0;
|
|
3733
3733
|
const reason = sanitizeReason(err);
|
|
3734
3734
|
console.error(
|
|
3735
|
-
`${TAG7} FAIL accountId=${input.accountId} remoteJid=${input.remoteJid} msgKey=${input.msgKeyId} reason=${reason} ms=${ms}`
|
|
3735
|
+
`${TAG7} FAIL accountId=${input.platformAccountId} waname=${input.accountId} remoteJid=${input.remoteJid} msgKey=${input.msgKeyId} reason=${reason} ms=${ms}`
|
|
3736
3736
|
);
|
|
3737
3737
|
return null;
|
|
3738
3738
|
} finally {
|
|
@@ -3770,7 +3770,7 @@ async function ensureWhatsAppConversation(input) {
|
|
|
3770
3770
|
const t0 = Date.now();
|
|
3771
3771
|
try {
|
|
3772
3772
|
const result = await ensureConversation(
|
|
3773
|
-
input.
|
|
3773
|
+
input.platformAccountId,
|
|
3774
3774
|
input.agentType,
|
|
3775
3775
|
input.sessionKey
|
|
3776
3776
|
);
|
|
@@ -3795,6 +3795,52 @@ async function ensureWhatsAppConversation(input) {
|
|
|
3795
3795
|
}
|
|
3796
3796
|
}
|
|
3797
3797
|
|
|
3798
|
+
// app/lib/whatsapp/platform-account-id.ts
|
|
3799
|
+
import { readdirSync as readdirSync2, readFileSync as readFileSync5 } from "fs";
|
|
3800
|
+
import { resolve as resolve6 } from "path";
|
|
3801
|
+
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
3802
|
+
var cached = null;
|
|
3803
|
+
var cachedAccountsDir = null;
|
|
3804
|
+
function resolvePlatformAccountId(accountsDir = ACCOUNTS_DIR) {
|
|
3805
|
+
if (cached !== null && cachedAccountsDir === accountsDir) return cached;
|
|
3806
|
+
const valid = enumerateValidAccountIds(accountsDir);
|
|
3807
|
+
if (valid.length === 0) {
|
|
3808
|
+
throw new Error(
|
|
3809
|
+
`[whatsapp-persist] resolvePlatformAccountId: no platform account found under ${accountsDir} \u2014 corrupt install? Cannot stamp n.accountId without a valid UUID.`
|
|
3810
|
+
);
|
|
3811
|
+
}
|
|
3812
|
+
if (valid.length > 1) {
|
|
3813
|
+
throw new Error(
|
|
3814
|
+
`[whatsapp-persist] resolvePlatformAccountId: multiple platform accounts found under ${accountsDir} (${valid.join(", ")}) \u2014 Phase 0 invariant requires exactly one. Loud-fail rather than picking one silently.`
|
|
3815
|
+
);
|
|
3816
|
+
}
|
|
3817
|
+
cached = valid[0];
|
|
3818
|
+
cachedAccountsDir = accountsDir;
|
|
3819
|
+
return cached;
|
|
3820
|
+
}
|
|
3821
|
+
function enumerateValidAccountIds(accountsDir) {
|
|
3822
|
+
let names;
|
|
3823
|
+
try {
|
|
3824
|
+
names = readdirSync2(accountsDir);
|
|
3825
|
+
} catch (err) {
|
|
3826
|
+
if (err.code === "ENOENT") return [];
|
|
3827
|
+
throw err;
|
|
3828
|
+
}
|
|
3829
|
+
const valid = [];
|
|
3830
|
+
for (const name of names) {
|
|
3831
|
+
if (!UUID_RE.test(name)) continue;
|
|
3832
|
+
const configPath2 = resolve6(accountsDir, name, "account.json");
|
|
3833
|
+
try {
|
|
3834
|
+
JSON.parse(readFileSync5(configPath2, "utf-8"));
|
|
3835
|
+
valid.push(name);
|
|
3836
|
+
} catch (err) {
|
|
3837
|
+
const code = err.code;
|
|
3838
|
+
if (code === "ENOENT") continue;
|
|
3839
|
+
}
|
|
3840
|
+
}
|
|
3841
|
+
return valid;
|
|
3842
|
+
}
|
|
3843
|
+
|
|
3798
3844
|
// app/lib/whatsapp/inbound/media.ts
|
|
3799
3845
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
3800
3846
|
import { writeFile, mkdir } from "fs/promises";
|
|
@@ -4273,9 +4319,23 @@ async function startConnection(accountId) {
|
|
|
4273
4319
|
console.error(`${TAG13} no credentials for account=${accountId}`);
|
|
4274
4320
|
return;
|
|
4275
4321
|
}
|
|
4322
|
+
let platformAccountId;
|
|
4323
|
+
try {
|
|
4324
|
+
platformAccountId = resolvePlatformAccountId();
|
|
4325
|
+
console.error(
|
|
4326
|
+
`[whatsapp-persist] resolved-account-id waname=${accountId} uuid=${platformAccountId}`
|
|
4327
|
+
);
|
|
4328
|
+
} catch (err) {
|
|
4329
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
4330
|
+
console.error(
|
|
4331
|
+
`[whatsapp-persist] resolved-account-id FAIL waname=${accountId} reason=${reason}`
|
|
4332
|
+
);
|
|
4333
|
+
throw err;
|
|
4334
|
+
}
|
|
4276
4335
|
await stopConnection(accountId);
|
|
4277
4336
|
const conn = {
|
|
4278
4337
|
accountId,
|
|
4338
|
+
platformAccountId,
|
|
4279
4339
|
accountName: whatsAppConfig.accounts?.[accountId]?.name,
|
|
4280
4340
|
authDir,
|
|
4281
4341
|
sock: null,
|
|
@@ -4330,11 +4390,25 @@ function getSocket(accountId) {
|
|
|
4330
4390
|
}
|
|
4331
4391
|
async function registerLoginSocket(accountId, sock, authDir) {
|
|
4332
4392
|
if (!configDir) throw new Error("WhatsApp manager not initialized");
|
|
4393
|
+
let platformAccountId;
|
|
4394
|
+
try {
|
|
4395
|
+
platformAccountId = resolvePlatformAccountId();
|
|
4396
|
+
console.error(
|
|
4397
|
+
`[whatsapp-persist] resolved-account-id waname=${accountId} uuid=${platformAccountId}`
|
|
4398
|
+
);
|
|
4399
|
+
} catch (err) {
|
|
4400
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
4401
|
+
console.error(
|
|
4402
|
+
`[whatsapp-persist] resolved-account-id FAIL waname=${accountId} reason=${reason}`
|
|
4403
|
+
);
|
|
4404
|
+
throw err;
|
|
4405
|
+
}
|
|
4333
4406
|
await stopConnection(accountId);
|
|
4334
4407
|
const selfId = readSelfId(authDir);
|
|
4335
4408
|
const lidMapping = sock.signalRepository?.lidMapping ?? null;
|
|
4336
4409
|
const conn = {
|
|
4337
4410
|
accountId,
|
|
4411
|
+
platformAccountId,
|
|
4338
4412
|
accountName: whatsAppConfig.accounts?.[accountId]?.name,
|
|
4339
4413
|
authDir,
|
|
4340
4414
|
sock,
|
|
@@ -4500,11 +4574,11 @@ async function connectWithReconnect(conn) {
|
|
|
4500
4574
|
console.error(
|
|
4501
4575
|
`${TAG13} reconnecting account=${conn.accountId} in ${delay}ms (attempt ${decision.nextAttempts}/${maxAttempts})`
|
|
4502
4576
|
);
|
|
4503
|
-
await new Promise((
|
|
4504
|
-
const timer2 = setTimeout(
|
|
4577
|
+
await new Promise((resolve26) => {
|
|
4578
|
+
const timer2 = setTimeout(resolve26, delay);
|
|
4505
4579
|
conn.abortController.signal.addEventListener("abort", () => {
|
|
4506
4580
|
clearTimeout(timer2);
|
|
4507
|
-
|
|
4581
|
+
resolve26();
|
|
4508
4582
|
}, { once: true });
|
|
4509
4583
|
});
|
|
4510
4584
|
}
|
|
@@ -4512,16 +4586,16 @@ async function connectWithReconnect(conn) {
|
|
|
4512
4586
|
}
|
|
4513
4587
|
}
|
|
4514
4588
|
function waitForDisconnectEvent(conn) {
|
|
4515
|
-
return new Promise((
|
|
4589
|
+
return new Promise((resolve26) => {
|
|
4516
4590
|
if (!conn.sock) {
|
|
4517
|
-
|
|
4591
|
+
resolve26();
|
|
4518
4592
|
return;
|
|
4519
4593
|
}
|
|
4520
4594
|
const sock = conn.sock;
|
|
4521
4595
|
const handler = (update) => {
|
|
4522
4596
|
if (update.connection === "close") {
|
|
4523
4597
|
sock.ev.off("connection.update", handler);
|
|
4524
|
-
|
|
4598
|
+
resolve26();
|
|
4525
4599
|
}
|
|
4526
4600
|
};
|
|
4527
4601
|
sock.ev.on("connection.update", handler);
|
|
@@ -4542,8 +4616,8 @@ function watchForDisconnect(conn) {
|
|
|
4542
4616
|
});
|
|
4543
4617
|
}
|
|
4544
4618
|
async function getGroupMeta(conn, jid) {
|
|
4545
|
-
const
|
|
4546
|
-
if (
|
|
4619
|
+
const cached2 = conn.groupMetaCache.get(jid);
|
|
4620
|
+
if (cached2 && cached2.expires > Date.now()) return cached2;
|
|
4547
4621
|
if (!conn.sock) return null;
|
|
4548
4622
|
console.error(`${TAG13} group metadata cache miss for ${jid}, fetching from Baileys account=${conn.accountId}`);
|
|
4549
4623
|
try {
|
|
@@ -4655,6 +4729,7 @@ function monitorInbound(conn) {
|
|
|
4655
4729
|
if (msg.key.id) {
|
|
4656
4730
|
const merged = await ensureWhatsAppConversation({
|
|
4657
4731
|
accountId: conn.accountId,
|
|
4732
|
+
platformAccountId: conn.platformAccountId,
|
|
4658
4733
|
sessionKey,
|
|
4659
4734
|
agentType: sessionKeyAgentType,
|
|
4660
4735
|
groupJid: isGroup ? remoteJid : void 0
|
|
@@ -4662,6 +4737,7 @@ function monitorInbound(conn) {
|
|
|
4662
4737
|
if (merged) {
|
|
4663
4738
|
await persistWhatsAppMessage({
|
|
4664
4739
|
accountId: conn.accountId,
|
|
4740
|
+
platformAccountId: conn.platformAccountId,
|
|
4665
4741
|
remoteJid,
|
|
4666
4742
|
sessionKey,
|
|
4667
4743
|
msgKeyId: msg.key.id,
|
|
@@ -4780,8 +4856,8 @@ async function handleInboundMessage(conn, msg) {
|
|
|
4780
4856
|
const conversationKey = isGroup ? remoteJid : senderPhone;
|
|
4781
4857
|
const debounceKey = `${conn.accountId}:${conversationKey}:${senderPhone}`;
|
|
4782
4858
|
let resolvePending;
|
|
4783
|
-
const sttPending = new Promise((
|
|
4784
|
-
resolvePending =
|
|
4859
|
+
const sttPending = new Promise((resolve26) => {
|
|
4860
|
+
resolvePending = resolve26;
|
|
4785
4861
|
});
|
|
4786
4862
|
if (conn.debouncer) conn.debouncer.registerPending(debounceKey, sttPending);
|
|
4787
4863
|
try {
|
|
@@ -4894,20 +4970,20 @@ async function probeApiKey() {
|
|
|
4894
4970
|
return result.status;
|
|
4895
4971
|
}
|
|
4896
4972
|
function checkPort(port2, timeoutMs = 500) {
|
|
4897
|
-
return new Promise((
|
|
4973
|
+
return new Promise((resolve26) => {
|
|
4898
4974
|
const socket = createConnection(port2, "127.0.0.1");
|
|
4899
4975
|
socket.setTimeout(timeoutMs);
|
|
4900
4976
|
socket.once("connect", () => {
|
|
4901
4977
|
socket.destroy();
|
|
4902
|
-
|
|
4978
|
+
resolve26(true);
|
|
4903
4979
|
});
|
|
4904
4980
|
socket.once("error", () => {
|
|
4905
4981
|
socket.destroy();
|
|
4906
|
-
|
|
4982
|
+
resolve26(false);
|
|
4907
4983
|
});
|
|
4908
4984
|
socket.once("timeout", () => {
|
|
4909
4985
|
socket.destroy();
|
|
4910
|
-
|
|
4986
|
+
resolve26(false);
|
|
4911
4987
|
});
|
|
4912
4988
|
});
|
|
4913
4989
|
}
|
|
@@ -4917,7 +4993,7 @@ app.get("/", async (c) => {
|
|
|
4917
4993
|
let pinConfigured = false;
|
|
4918
4994
|
try {
|
|
4919
4995
|
if (existsSync6(USERS_FILE)) {
|
|
4920
|
-
const raw =
|
|
4996
|
+
const raw = readFileSync6(USERS_FILE, "utf-8").trim();
|
|
4921
4997
|
if (raw) {
|
|
4922
4998
|
const users = JSON.parse(raw);
|
|
4923
4999
|
pinConfigured = Array.isArray(users) && users.length > 0;
|
|
@@ -5002,14 +5078,14 @@ app.get("/", async (c) => {
|
|
|
5002
5078
|
var health_default = app;
|
|
5003
5079
|
|
|
5004
5080
|
// server/routes/session.ts
|
|
5005
|
-
import { resolve as
|
|
5081
|
+
import { resolve as resolve7 } from "path";
|
|
5006
5082
|
import { existsSync as existsSync7, writeFileSync as writeFileSync5, mkdirSync as mkdirSync4 } from "fs";
|
|
5007
|
-
var
|
|
5083
|
+
var UUID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
5008
5084
|
function writeBrandingCache(accountId, agentSlug, branding) {
|
|
5009
5085
|
try {
|
|
5010
|
-
const cacheDir =
|
|
5086
|
+
const cacheDir = resolve7(MAXY_DIR, "branding-cache", accountId);
|
|
5011
5087
|
mkdirSync4(cacheDir, { recursive: true });
|
|
5012
|
-
writeFileSync5(
|
|
5088
|
+
writeFileSync5(resolve7(cacheDir, `${agentSlug}.json`), JSON.stringify(branding), "utf-8");
|
|
5013
5089
|
} catch (err) {
|
|
5014
5090
|
console.error(`[branding] cache write failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
5015
5091
|
}
|
|
@@ -5019,7 +5095,7 @@ function parseVisitorCookie(cookieHeader) {
|
|
|
5019
5095
|
const match = cookieHeader.match(/(?:^|;\s*)maxy_visitor=([^;]*)/);
|
|
5020
5096
|
if (!match) return null;
|
|
5021
5097
|
const value = decodeURIComponent(match[1]).trim();
|
|
5022
|
-
return
|
|
5098
|
+
return UUID_RE2.test(value) ? value : null;
|
|
5023
5099
|
}
|
|
5024
5100
|
function withVisitorCookie(response, visitorId) {
|
|
5025
5101
|
if (!visitorId) return response;
|
|
@@ -5079,8 +5155,8 @@ app2.post("/", async (c) => {
|
|
|
5079
5155
|
}
|
|
5080
5156
|
let agentConfig = null;
|
|
5081
5157
|
if (account) {
|
|
5082
|
-
const agentDir =
|
|
5083
|
-
const agentConfigPath =
|
|
5158
|
+
const agentDir = resolve7(account.accountDir, "agents", agentSlug);
|
|
5159
|
+
const agentConfigPath = resolve7(agentDir, "config.json");
|
|
5084
5160
|
if (!existsSync7(agentDir) || !existsSync7(agentConfigPath)) {
|
|
5085
5161
|
return c.json({ error: "Agent not found" }, 404);
|
|
5086
5162
|
}
|
|
@@ -5334,9 +5410,9 @@ ${raw}`;
|
|
|
5334
5410
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
5335
5411
|
import { mkdir as mkdir2, readFile, stat as stat2, writeFile as writeFile2 } from "fs/promises";
|
|
5336
5412
|
import { realpathSync } from "fs";
|
|
5337
|
-
import { resolve as
|
|
5338
|
-
var PLATFORM_ROOT2 = process.env.MAXY_PLATFORM_ROOT ??
|
|
5339
|
-
var ATTACHMENTS_ROOT =
|
|
5413
|
+
import { resolve as resolve8, extname, basename as basename3 } from "path";
|
|
5414
|
+
var PLATFORM_ROOT2 = process.env.MAXY_PLATFORM_ROOT ?? resolve8(process.cwd(), "../platform");
|
|
5415
|
+
var ATTACHMENTS_ROOT = resolve8(PLATFORM_ROOT2, "..", "data/uploads");
|
|
5340
5416
|
var SUPPORTED_MIME_TYPES = /* @__PURE__ */ new Set([
|
|
5341
5417
|
"image/jpeg",
|
|
5342
5418
|
"image/png",
|
|
@@ -5363,11 +5439,11 @@ function assertSupportedMime(mimeType) {
|
|
|
5363
5439
|
}
|
|
5364
5440
|
async function writeAttachment(scope, filename, mimeType, sizeBytes, buffer) {
|
|
5365
5441
|
const attachmentId = randomUUID4();
|
|
5366
|
-
const dir =
|
|
5442
|
+
const dir = resolve8(ATTACHMENTS_ROOT, scope, attachmentId);
|
|
5367
5443
|
await mkdir2(dir, { recursive: true });
|
|
5368
5444
|
const ext = extname(filename) || "";
|
|
5369
|
-
const storagePath =
|
|
5370
|
-
const metaPath =
|
|
5445
|
+
const storagePath = resolve8(dir, `${attachmentId}${ext}`);
|
|
5446
|
+
const metaPath = resolve8(dir, `${attachmentId}.meta.json`);
|
|
5371
5447
|
const meta = {
|
|
5372
5448
|
attachmentId,
|
|
5373
5449
|
scope,
|
|
@@ -6045,16 +6121,16 @@ var group_default = app4;
|
|
|
6045
6121
|
|
|
6046
6122
|
// app/lib/access-gate.ts
|
|
6047
6123
|
import neo4j from "neo4j-driver";
|
|
6048
|
-
import { readFileSync as
|
|
6049
|
-
import { resolve as
|
|
6124
|
+
import { readFileSync as readFileSync7 } from "fs";
|
|
6125
|
+
import { resolve as resolve9 } from "path";
|
|
6050
6126
|
import { randomUUID as randomUUID5, randomInt } from "crypto";
|
|
6051
|
-
var PLATFORM_ROOT3 = process.env.MAXY_PLATFORM_ROOT ??
|
|
6127
|
+
var PLATFORM_ROOT3 = process.env.MAXY_PLATFORM_ROOT ?? resolve9(process.cwd(), "..");
|
|
6052
6128
|
var driver = null;
|
|
6053
6129
|
function readPassword() {
|
|
6054
6130
|
if (process.env.NEO4J_PASSWORD) return process.env.NEO4J_PASSWORD;
|
|
6055
|
-
const passwordFile =
|
|
6131
|
+
const passwordFile = resolve9(PLATFORM_ROOT3, "config/.neo4j-password");
|
|
6056
6132
|
try {
|
|
6057
|
-
return
|
|
6133
|
+
return readFileSync7(passwordFile, "utf-8").trim();
|
|
6058
6134
|
} catch {
|
|
6059
6135
|
throw new Error(
|
|
6060
6136
|
`Neo4j password not found. Expected at ${passwordFile} or in NEO4J_PASSWORD env var.`
|
|
@@ -6365,19 +6441,19 @@ async function findActiveGrantByContact(contactValue, agentSlug, accountId) {
|
|
|
6365
6441
|
}
|
|
6366
6442
|
|
|
6367
6443
|
// app/lib/brevo-sms.ts
|
|
6368
|
-
import { readFileSync as
|
|
6444
|
+
import { readFileSync as readFileSync8, writeFileSync as writeFileSync6, mkdirSync as mkdirSync5, existsSync as existsSync8, chmodSync } from "fs";
|
|
6369
6445
|
import { dirname as dirname4 } from "path";
|
|
6370
|
-
import { resolve as
|
|
6371
|
-
var BREVO_API_KEY_FILE =
|
|
6446
|
+
import { resolve as resolve10 } from "path";
|
|
6447
|
+
var BREVO_API_KEY_FILE = resolve10(MAXY_DIR, ".brevo-api-key");
|
|
6372
6448
|
var BREVO_API_URL = "https://api.brevo.com/v3/transactionalSMS/sms";
|
|
6373
6449
|
var BREVO_TIMEOUT_MS = 1e4;
|
|
6374
6450
|
var BREVO_SENDER = "Maxy";
|
|
6375
6451
|
var platformRoot = process.env.MAXY_PLATFORM_ROOT;
|
|
6376
6452
|
if (platformRoot) {
|
|
6377
6453
|
try {
|
|
6378
|
-
const brandPath =
|
|
6454
|
+
const brandPath = resolve10(platformRoot, "config", "brand.json");
|
|
6379
6455
|
if (existsSync8(brandPath)) {
|
|
6380
|
-
const brand = JSON.parse(
|
|
6456
|
+
const brand = JSON.parse(readFileSync8(brandPath, "utf-8"));
|
|
6381
6457
|
if (brand.productName) BREVO_SENDER = brand.productName;
|
|
6382
6458
|
}
|
|
6383
6459
|
} catch {
|
|
@@ -6385,7 +6461,7 @@ if (platformRoot) {
|
|
|
6385
6461
|
}
|
|
6386
6462
|
function readBrevoApiKey() {
|
|
6387
6463
|
try {
|
|
6388
|
-
const key =
|
|
6464
|
+
const key = readFileSync8(BREVO_API_KEY_FILE, "utf-8").trim();
|
|
6389
6465
|
if (!key) {
|
|
6390
6466
|
throw new Error(`Brevo API key file is empty: ${BREVO_API_KEY_FILE}`);
|
|
6391
6467
|
}
|
|
@@ -6816,7 +6892,7 @@ app5.post("/send-otp", async (c) => {
|
|
|
6816
6892
|
var access_default = app5;
|
|
6817
6893
|
|
|
6818
6894
|
// server/routes/telegram.ts
|
|
6819
|
-
import { existsSync as existsSync9, readFileSync as
|
|
6895
|
+
import { existsSync as existsSync9, readFileSync as readFileSync9 } from "fs";
|
|
6820
6896
|
import { timingSafeEqual } from "crypto";
|
|
6821
6897
|
|
|
6822
6898
|
// app/lib/telegram/access-control.ts
|
|
@@ -6854,7 +6930,7 @@ function getWebhookSecret(botType) {
|
|
|
6854
6930
|
const filePath = botType === "admin" ? TELEGRAM_ADMIN_WEBHOOK_SECRET_FILE : TELEGRAM_WEBHOOK_SECRET_FILE;
|
|
6855
6931
|
try {
|
|
6856
6932
|
if (!existsSync9(filePath)) return null;
|
|
6857
|
-
const secret =
|
|
6933
|
+
const secret = readFileSync9(filePath, "utf-8").trim();
|
|
6858
6934
|
return secret || null;
|
|
6859
6935
|
} catch {
|
|
6860
6936
|
return null;
|
|
@@ -7012,9 +7088,9 @@ app6.post("/webhook", async (c) => {
|
|
|
7012
7088
|
var telegram_default = app6;
|
|
7013
7089
|
|
|
7014
7090
|
// server/routes/whatsapp.ts
|
|
7015
|
-
import { join as join6, resolve as
|
|
7091
|
+
import { join as join6, resolve as resolve11, basename as basename4 } from "path";
|
|
7016
7092
|
import { readFile as readFile2, stat as stat3 } from "fs/promises";
|
|
7017
|
-
import { realpathSync as realpathSync2, readdirSync as
|
|
7093
|
+
import { realpathSync as realpathSync2, readdirSync as readdirSync3, readFileSync as readFileSync10, existsSync as existsSync10 } from "fs";
|
|
7018
7094
|
|
|
7019
7095
|
// app/lib/whatsapp/login.ts
|
|
7020
7096
|
import { randomUUID as randomUUID6 } from "crypto";
|
|
@@ -7120,8 +7196,8 @@ async function startLogin(opts) {
|
|
|
7120
7196
|
resetActiveLogin(accountId);
|
|
7121
7197
|
let resolveQr = null;
|
|
7122
7198
|
let rejectQr = null;
|
|
7123
|
-
const qrPromise = new Promise((
|
|
7124
|
-
resolveQr =
|
|
7199
|
+
const qrPromise = new Promise((resolve26, reject) => {
|
|
7200
|
+
resolveQr = resolve26;
|
|
7125
7201
|
rejectQr = reject;
|
|
7126
7202
|
});
|
|
7127
7203
|
const qrTimer = setTimeout(
|
|
@@ -7515,17 +7591,17 @@ app7.post("/config", async (c) => {
|
|
|
7515
7591
|
return c.json(result, result.ok ? 200 : 400);
|
|
7516
7592
|
}
|
|
7517
7593
|
case "list-public-agents": {
|
|
7518
|
-
const agentsDir =
|
|
7594
|
+
const agentsDir = resolve11(account.accountDir, "agents");
|
|
7519
7595
|
const agents = [];
|
|
7520
7596
|
if (existsSync10(agentsDir)) {
|
|
7521
7597
|
try {
|
|
7522
|
-
const entries =
|
|
7598
|
+
const entries = readdirSync3(agentsDir, { withFileTypes: true });
|
|
7523
7599
|
for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
7524
7600
|
if (!entry.isDirectory() || entry.name === "admin") continue;
|
|
7525
|
-
const configPath2 =
|
|
7601
|
+
const configPath2 = resolve11(agentsDir, entry.name, "config.json");
|
|
7526
7602
|
if (!existsSync10(configPath2)) continue;
|
|
7527
7603
|
try {
|
|
7528
|
-
const config = JSON.parse(
|
|
7604
|
+
const config = JSON.parse(readFileSync10(configPath2, "utf-8"));
|
|
7529
7605
|
agents.push({ slug: entry.name, displayName: config.displayName ?? entry.name });
|
|
7530
7606
|
} catch {
|
|
7531
7607
|
console.error(`${TAG18} config action=list-public-agents error="failed to parse config.json for agent ${entry.name}" \u2014 skipping`);
|
|
@@ -7600,7 +7676,7 @@ app7.post("/send-document", async (c) => {
|
|
|
7600
7676
|
if (!maxyAccountId || !PLATFORM_ROOT4) {
|
|
7601
7677
|
return c.json({ error: "Cannot validate file path: missing account or platform context" }, 400);
|
|
7602
7678
|
}
|
|
7603
|
-
const accountDir =
|
|
7679
|
+
const accountDir = resolve11(PLATFORM_ROOT4, "..", "data/accounts", maxyAccountId);
|
|
7604
7680
|
let resolvedPath;
|
|
7605
7681
|
try {
|
|
7606
7682
|
resolvedPath = realpathSync2(filePath);
|
|
@@ -7737,8 +7813,8 @@ var whatsapp_default = app7;
|
|
|
7737
7813
|
|
|
7738
7814
|
// server/routes/onboarding.ts
|
|
7739
7815
|
import { spawn, execFileSync } from "child_process";
|
|
7740
|
-
import { openSync as openSync2, closeSync as closeSync2, writeFileSync as writeFileSync7, writeSync, existsSync as existsSync11, mkdirSync as mkdirSync6, readFileSync as
|
|
7741
|
-
import { resolve as
|
|
7816
|
+
import { openSync as openSync2, closeSync as closeSync2, writeFileSync as writeFileSync7, writeSync, existsSync as existsSync11, mkdirSync as mkdirSync6, readFileSync as readFileSync11, unlinkSync } from "fs";
|
|
7817
|
+
import { resolve as resolve12, dirname as dirname5 } from "path";
|
|
7742
7818
|
import { createHash, randomUUID as randomUUID7 } from "crypto";
|
|
7743
7819
|
var PLATFORM_ROOT5 = process.env.MAXY_PLATFORM_ROOT || "";
|
|
7744
7820
|
function hashPin(pin) {
|
|
@@ -7746,7 +7822,7 @@ function hashPin(pin) {
|
|
|
7746
7822
|
}
|
|
7747
7823
|
function readUsersFile() {
|
|
7748
7824
|
if (!existsSync11(USERS_FILE)) return null;
|
|
7749
|
-
const raw =
|
|
7825
|
+
const raw = readFileSync11(USERS_FILE, "utf-8").trim();
|
|
7750
7826
|
if (!raw) return [];
|
|
7751
7827
|
return JSON.parse(raw);
|
|
7752
7828
|
}
|
|
@@ -7867,7 +7943,7 @@ app8.post("/set-pin", async (c) => {
|
|
|
7867
7943
|
console.log(`[set-pin] wrote users.json: userId=${userId.slice(0, 8)}\u2026 hash=${hash.slice(0, 8)}\u2026`);
|
|
7868
7944
|
if (account) {
|
|
7869
7945
|
try {
|
|
7870
|
-
const config = JSON.parse(
|
|
7946
|
+
const config = JSON.parse(readFileSync11(`${account.accountDir}/account.json`, "utf-8"));
|
|
7871
7947
|
if (!config.admins) config.admins = [];
|
|
7872
7948
|
if (!config.admins.some((a) => a.userId === userId)) {
|
|
7873
7949
|
config.admins.push({ userId, role: "owner" });
|
|
@@ -7943,16 +8019,16 @@ app8.post("/skip", async (c) => {
|
|
|
7943
8019
|
}
|
|
7944
8020
|
const { accountId, accountDir } = account;
|
|
7945
8021
|
let agentName = "Maxy";
|
|
7946
|
-
const brandPath = PLATFORM_ROOT5 ?
|
|
8022
|
+
const brandPath = PLATFORM_ROOT5 ? resolve12(PLATFORM_ROOT5, "config", "brand.json") : "";
|
|
7947
8023
|
if (brandPath && existsSync11(brandPath)) {
|
|
7948
8024
|
try {
|
|
7949
|
-
const brand = JSON.parse(
|
|
8025
|
+
const brand = JSON.parse(readFileSync11(brandPath, "utf-8"));
|
|
7950
8026
|
if (brand.productName) agentName = brand.productName;
|
|
7951
8027
|
} catch (err) {
|
|
7952
8028
|
console.error(`[onboarding-skip] brand.json read failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
7953
8029
|
}
|
|
7954
8030
|
}
|
|
7955
|
-
const soulPath =
|
|
8031
|
+
const soulPath = resolve12(accountDir, "agents", "admin", "SOUL.md");
|
|
7956
8032
|
try {
|
|
7957
8033
|
mkdirSync6(dirname5(soulPath), { recursive: true });
|
|
7958
8034
|
writeFileSync7(soulPath, `You are ${agentName}, an AI operations manager.
|
|
@@ -8115,9 +8191,16 @@ app9.post("/", async (c) => {
|
|
|
8115
8191
|
const safe = typeof v === "string" ? truncate(v, 200) : typeof v === "number" || typeof v === "boolean" ? String(v) : JSON.stringify(v).slice(0, 200);
|
|
8116
8192
|
return `${k}=${safe}`;
|
|
8117
8193
|
}).join(" ");
|
|
8118
|
-
|
|
8119
|
-
|
|
8120
|
-
|
|
8194
|
+
const TAGGED_PREFIX_SOURCES = /* @__PURE__ */ new Set(["admin-chat-relay-poll"]);
|
|
8195
|
+
if (TAGGED_PREFIX_SOURCES.has(source)) {
|
|
8196
|
+
console.log(
|
|
8197
|
+
`[${source}] ts=${ts} ip=${ip} version=${version || "unknown"}${extra ? " " + extra : ""}`
|
|
8198
|
+
);
|
|
8199
|
+
} else {
|
|
8200
|
+
console.log(
|
|
8201
|
+
`[client-event] ts=${ts} ip=${ip} source=${source} version=${version || "unknown"}${extra ? " " + extra : ""}`
|
|
8202
|
+
);
|
|
8203
|
+
}
|
|
8121
8204
|
} else {
|
|
8122
8205
|
console.error(
|
|
8123
8206
|
`[client-error] ts=${ts} ip=${ip} kind=${kind} url=${JSON.stringify(url)} version=${version || "unknown"} ua=${JSON.stringify(ua)} msg=${JSON.stringify(msg)} stack-head=${JSON.stringify(head)} file-line-col=${JSON.stringify(fileLineCol)}`
|
|
@@ -8151,7 +8234,7 @@ app9.post("/", async (c) => {
|
|
|
8151
8234
|
var client_error_default = app9;
|
|
8152
8235
|
|
|
8153
8236
|
// server/routes/admin/session.ts
|
|
8154
|
-
import { readFileSync as
|
|
8237
|
+
import { readFileSync as readFileSync12, writeFileSync as writeFileSync8, existsSync as existsSync13 } from "fs";
|
|
8155
8238
|
import { createHash as createHash2 } from "crypto";
|
|
8156
8239
|
var deprecationLogged = /* @__PURE__ */ new Set();
|
|
8157
8240
|
function hashPin2(pin) {
|
|
@@ -8159,7 +8242,7 @@ function hashPin2(pin) {
|
|
|
8159
8242
|
}
|
|
8160
8243
|
function readUsersFile2() {
|
|
8161
8244
|
if (!existsSync13(USERS_FILE)) return null;
|
|
8162
|
-
const raw =
|
|
8245
|
+
const raw = readFileSync12(USERS_FILE, "utf-8").trim();
|
|
8163
8246
|
if (!raw) return [];
|
|
8164
8247
|
return JSON.parse(raw);
|
|
8165
8248
|
}
|
|
@@ -8333,7 +8416,7 @@ app10.post("/", async (c) => {
|
|
|
8333
8416
|
var session_default2 = app10;
|
|
8334
8417
|
|
|
8335
8418
|
// server/routes/admin/chat.ts
|
|
8336
|
-
import { resolve as
|
|
8419
|
+
import { resolve as resolve13 } from "path";
|
|
8337
8420
|
import { appendFileSync as appendFileSync4 } from "fs";
|
|
8338
8421
|
|
|
8339
8422
|
// app/lib/script-stream-tailer.ts
|
|
@@ -8788,7 +8871,7 @@ app11.post("/", requireAdminSession, async (c) => {
|
|
|
8788
8871
|
function resolveTeeStreamLogPath() {
|
|
8789
8872
|
const liveConvId = getConversationIdForSession(session_key);
|
|
8790
8873
|
const key = liveConvId ?? preflushStreamLogKey(session_key);
|
|
8791
|
-
return
|
|
8874
|
+
return resolve13(account.accountDir, "logs", `claude-agent-stream-${key}.log`);
|
|
8792
8875
|
}
|
|
8793
8876
|
try {
|
|
8794
8877
|
appendFileSync4(resolveTeeStreamLogPath(), `[${(/* @__PURE__ */ new Date()).toISOString()}] [chat-route-version=task606-tee-path-resolve] sessionKey=${session_key.slice(0, 12)}\u2026
|
|
@@ -8890,7 +8973,7 @@ app11.post("/", requireAdminSession, async (c) => {
|
|
|
8890
8973
|
try {
|
|
8891
8974
|
registerAdminSSE(sseEntry);
|
|
8892
8975
|
if (sseConvId) {
|
|
8893
|
-
const streamLogPath =
|
|
8976
|
+
const streamLogPath = resolve13(account.accountDir, "logs", `claude-agent-stream-${sseConvId}.log`);
|
|
8894
8977
|
tailer = startScriptStreamTailer({
|
|
8895
8978
|
path: streamLogPath,
|
|
8896
8979
|
onEvent: (event) => {
|
|
@@ -9019,8 +9102,8 @@ app12.post("/", requireAdminSession, async (c) => {
|
|
|
9019
9102
|
var compact_default = app12;
|
|
9020
9103
|
|
|
9021
9104
|
// server/routes/admin/logs.ts
|
|
9022
|
-
import { existsSync as existsSync15, readdirSync as
|
|
9023
|
-
import { resolve as
|
|
9105
|
+
import { existsSync as existsSync15, readdirSync as readdirSync4, readFileSync as readFileSync13, statSync as statSync7 } from "fs";
|
|
9106
|
+
import { resolve as resolve14, basename as basename5 } from "path";
|
|
9024
9107
|
|
|
9025
9108
|
// app/lib/logs-read-resolve.ts
|
|
9026
9109
|
import { existsSync as existsSync14 } from "fs";
|
|
@@ -9064,7 +9147,7 @@ app13.get("/", async (c) => {
|
|
|
9064
9147
|
const sessionKeyParam = c.req.query("sessionKey");
|
|
9065
9148
|
const download = c.req.query("download") === "1";
|
|
9066
9149
|
const account = resolveAccount();
|
|
9067
|
-
const accountLogDir2 = account ?
|
|
9150
|
+
const accountLogDir2 = account ? resolve14(account.accountDir, "logs") : null;
|
|
9068
9151
|
const logDirs = [];
|
|
9069
9152
|
if (accountLogDir2) logDirs.push(accountLogDir2);
|
|
9070
9153
|
logDirs.push(LOG_DIR);
|
|
@@ -9072,10 +9155,10 @@ app13.get("/", async (c) => {
|
|
|
9072
9155
|
const safe = basename5(fileParam);
|
|
9073
9156
|
const searched = [];
|
|
9074
9157
|
for (const dir of logDirs) {
|
|
9075
|
-
const filePath =
|
|
9158
|
+
const filePath = resolve14(dir, safe);
|
|
9076
9159
|
searched.push(filePath);
|
|
9077
9160
|
try {
|
|
9078
|
-
const buffer =
|
|
9161
|
+
const buffer = readFileSync13(filePath);
|
|
9079
9162
|
const onDiskBytes = statSync7(filePath).size;
|
|
9080
9163
|
const headers = {
|
|
9081
9164
|
"Content-Type": "text/plain; charset=utf-8",
|
|
@@ -9150,7 +9233,7 @@ app13.get("/", async (c) => {
|
|
|
9150
9233
|
try {
|
|
9151
9234
|
const filename = basename5(hit.path);
|
|
9152
9235
|
if (stalePreflushCount > 0 && !download) {
|
|
9153
|
-
const content =
|
|
9236
|
+
const content = readFileSync13(hit.path, "utf-8");
|
|
9154
9237
|
return c.json({
|
|
9155
9238
|
log: content,
|
|
9156
9239
|
filename,
|
|
@@ -9158,7 +9241,7 @@ app13.get("/", async (c) => {
|
|
|
9158
9241
|
warnings: stalePreflushPaths.map((path2) => ({ kind: "stale-preflush", path: path2 }))
|
|
9159
9242
|
});
|
|
9160
9243
|
}
|
|
9161
|
-
const buffer =
|
|
9244
|
+
const buffer = readFileSync13(hit.path);
|
|
9162
9245
|
const onDiskBytes = statSync7(hit.path).size;
|
|
9163
9246
|
const headers = {
|
|
9164
9247
|
"Content-Type": "text/plain; charset=utf-8",
|
|
@@ -9195,16 +9278,16 @@ app13.get("/", async (c) => {
|
|
|
9195
9278
|
if (!existsSync15(dir)) continue;
|
|
9196
9279
|
let files;
|
|
9197
9280
|
try {
|
|
9198
|
-
files =
|
|
9281
|
+
files = readdirSync4(dir).filter((f) => f.endsWith(".log"));
|
|
9199
9282
|
} catch (err) {
|
|
9200
9283
|
const reason = err instanceof Error ? err.message : String(err);
|
|
9201
9284
|
console.warn(`[admin/logs] readdir-fail dir=${dir} reason=${reason}`);
|
|
9202
9285
|
continue;
|
|
9203
9286
|
}
|
|
9204
|
-
files.filter((f) => !seen.has(f)).map((f) => ({ name: f, mtime: statSync7(
|
|
9287
|
+
files.filter((f) => !seen.has(f)).map((f) => ({ name: f, mtime: statSync7(resolve14(dir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime).forEach(({ name }) => {
|
|
9205
9288
|
seen.add(name);
|
|
9206
9289
|
try {
|
|
9207
|
-
const content =
|
|
9290
|
+
const content = readFileSync13(resolve14(dir, name));
|
|
9208
9291
|
const tail = content.length > TAIL_BYTES ? content.subarray(content.length - TAIL_BYTES).toString("utf-8") : content.toString("utf-8");
|
|
9209
9292
|
logs[name] = tail.trim() || "(empty)";
|
|
9210
9293
|
} catch (err) {
|
|
@@ -9244,7 +9327,7 @@ var claude_info_default = app14;
|
|
|
9244
9327
|
// server/routes/admin/attachment.ts
|
|
9245
9328
|
import { readFile as readFile3, readdir } from "fs/promises";
|
|
9246
9329
|
import { existsSync as existsSync16 } from "fs";
|
|
9247
|
-
import { resolve as
|
|
9330
|
+
import { resolve as resolve15 } from "path";
|
|
9248
9331
|
var app15 = new Hono();
|
|
9249
9332
|
app15.get("/:attachmentId", requireAdminSession, async (c) => {
|
|
9250
9333
|
const attachmentId = c.req.param("attachmentId");
|
|
@@ -9256,11 +9339,11 @@ app15.get("/:attachmentId", requireAdminSession, async (c) => {
|
|
|
9256
9339
|
if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/.test(attachmentId)) {
|
|
9257
9340
|
return new Response("Not found", { status: 404 });
|
|
9258
9341
|
}
|
|
9259
|
-
const dir =
|
|
9342
|
+
const dir = resolve15(ATTACHMENTS_ROOT, accountId, attachmentId);
|
|
9260
9343
|
if (!existsSync16(dir)) {
|
|
9261
9344
|
return new Response("Not found", { status: 404 });
|
|
9262
9345
|
}
|
|
9263
|
-
const metaPath =
|
|
9346
|
+
const metaPath = resolve15(dir, `${attachmentId}.meta.json`);
|
|
9264
9347
|
if (!existsSync16(metaPath)) {
|
|
9265
9348
|
return new Response("Not found", { status: 404 });
|
|
9266
9349
|
}
|
|
@@ -9275,7 +9358,7 @@ app15.get("/:attachmentId", requireAdminSession, async (c) => {
|
|
|
9275
9358
|
if (!dataFile) {
|
|
9276
9359
|
return new Response("Not found", { status: 404 });
|
|
9277
9360
|
}
|
|
9278
|
-
const filePath =
|
|
9361
|
+
const filePath = resolve15(dir, dataFile);
|
|
9279
9362
|
const buffer = await readFile3(filePath);
|
|
9280
9363
|
return new Response(new Uint8Array(buffer), {
|
|
9281
9364
|
headers: {
|
|
@@ -9288,24 +9371,24 @@ app15.get("/:attachmentId", requireAdminSession, async (c) => {
|
|
|
9288
9371
|
var attachment_default = app15;
|
|
9289
9372
|
|
|
9290
9373
|
// server/routes/admin/agents.ts
|
|
9291
|
-
import { resolve as
|
|
9292
|
-
import { readdirSync as
|
|
9374
|
+
import { resolve as resolve16 } from "path";
|
|
9375
|
+
import { readdirSync as readdirSync5, readFileSync as readFileSync14, existsSync as existsSync17, rmSync } from "fs";
|
|
9293
9376
|
var app16 = new Hono();
|
|
9294
9377
|
app16.get("/", (c) => {
|
|
9295
9378
|
const account = resolveAccount();
|
|
9296
9379
|
if (!account) return c.json({ agents: [] });
|
|
9297
|
-
const agentsDir =
|
|
9380
|
+
const agentsDir = resolve16(account.accountDir, "agents");
|
|
9298
9381
|
if (!existsSync17(agentsDir)) return c.json({ agents: [] });
|
|
9299
9382
|
const agents = [];
|
|
9300
9383
|
try {
|
|
9301
|
-
const entries =
|
|
9384
|
+
const entries = readdirSync5(agentsDir, { withFileTypes: true });
|
|
9302
9385
|
for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
9303
9386
|
if (!entry.isDirectory()) continue;
|
|
9304
9387
|
if (entry.name === "admin") continue;
|
|
9305
|
-
const configPath2 =
|
|
9388
|
+
const configPath2 = resolve16(agentsDir, entry.name, "config.json");
|
|
9306
9389
|
if (!existsSync17(configPath2)) continue;
|
|
9307
9390
|
try {
|
|
9308
|
-
const config = JSON.parse(
|
|
9391
|
+
const config = JSON.parse(readFileSync14(configPath2, "utf-8"));
|
|
9309
9392
|
agents.push({
|
|
9310
9393
|
slug: entry.name,
|
|
9311
9394
|
displayName: config.displayName ?? entry.name,
|
|
@@ -9331,7 +9414,7 @@ app16.delete("/:slug", async (c) => {
|
|
|
9331
9414
|
if (slug.includes("/") || slug.includes("..") || slug.includes("\\")) {
|
|
9332
9415
|
return c.json({ error: "Invalid agent slug" }, 400);
|
|
9333
9416
|
}
|
|
9334
|
-
const agentDir =
|
|
9417
|
+
const agentDir = resolve16(account.accountDir, "agents", slug);
|
|
9335
9418
|
if (!existsSync17(agentDir)) {
|
|
9336
9419
|
return c.json({ error: "Agent not found" }, 404);
|
|
9337
9420
|
}
|
|
@@ -9361,7 +9444,7 @@ app16.post("/:slug/project", async (c) => {
|
|
|
9361
9444
|
if (slug.includes("/") || slug.includes("..") || slug.includes("\\")) {
|
|
9362
9445
|
return c.json({ error: "Invalid agent slug" }, 400);
|
|
9363
9446
|
}
|
|
9364
|
-
const agentDir =
|
|
9447
|
+
const agentDir = resolve16(account.accountDir, "agents", slug);
|
|
9365
9448
|
if (!existsSync17(agentDir)) {
|
|
9366
9449
|
return c.json({ error: "Agent not found on disk" }, 404);
|
|
9367
9450
|
}
|
|
@@ -9918,8 +10001,8 @@ var events_default = app20;
|
|
|
9918
10001
|
|
|
9919
10002
|
// server/routes/admin/cloudflare.ts
|
|
9920
10003
|
import { homedir } from "os";
|
|
9921
|
-
import { resolve as
|
|
9922
|
-
import { readFileSync as
|
|
10004
|
+
import { resolve as resolve18 } from "path";
|
|
10005
|
+
import { readFileSync as readFileSync17 } from "fs";
|
|
9923
10006
|
|
|
9924
10007
|
// app/lib/dns-label.ts
|
|
9925
10008
|
var VALID_LABEL = /^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$/;
|
|
@@ -9935,14 +10018,14 @@ function isValidDomain(value) {
|
|
|
9935
10018
|
}
|
|
9936
10019
|
|
|
9937
10020
|
// app/lib/alias-domains.ts
|
|
9938
|
-
import { existsSync as existsSync19, mkdirSync as mkdirSync8, readFileSync as
|
|
10021
|
+
import { existsSync as existsSync19, mkdirSync as mkdirSync8, readFileSync as readFileSync15, writeFileSync as writeFileSync9 } from "fs";
|
|
9939
10022
|
import { dirname as dirname7 } from "path";
|
|
9940
|
-
import { resolve as
|
|
9941
|
-
var ALIAS_DOMAINS_PATH =
|
|
10023
|
+
import { resolve as resolve17 } from "path";
|
|
10024
|
+
var ALIAS_DOMAINS_PATH = resolve17(MAXY_DIR, "alias-domains.json");
|
|
9942
10025
|
function readExisting() {
|
|
9943
10026
|
if (!existsSync19(ALIAS_DOMAINS_PATH)) return /* @__PURE__ */ new Set();
|
|
9944
10027
|
try {
|
|
9945
|
-
const parsed = JSON.parse(
|
|
10028
|
+
const parsed = JSON.parse(readFileSync15(ALIAS_DOMAINS_PATH, "utf-8"));
|
|
9946
10029
|
if (!Array.isArray(parsed)) return /* @__PURE__ */ new Set();
|
|
9947
10030
|
return new Set(parsed.filter((h) => typeof h === "string"));
|
|
9948
10031
|
} catch {
|
|
@@ -9961,8 +10044,8 @@ function addAliasDomain(hostname2) {
|
|
|
9961
10044
|
import {
|
|
9962
10045
|
existsSync as existsSync20,
|
|
9963
10046
|
mkdirSync as mkdirSync9,
|
|
9964
|
-
readdirSync as
|
|
9965
|
-
readFileSync as
|
|
10047
|
+
readdirSync as readdirSync6,
|
|
10048
|
+
readFileSync as readFileSync16,
|
|
9966
10049
|
unlinkSync as unlinkSync2,
|
|
9967
10050
|
writeFileSync as writeFileSync10
|
|
9968
10051
|
} from "fs";
|
|
@@ -10008,7 +10091,7 @@ function consumeActionCompletionRelays(accountDir) {
|
|
|
10008
10091
|
if (!existsSync20(dir)) return [];
|
|
10009
10092
|
let entries;
|
|
10010
10093
|
try {
|
|
10011
|
-
entries =
|
|
10094
|
+
entries = readdirSync6(dir);
|
|
10012
10095
|
} catch (e) {
|
|
10013
10096
|
console.error(
|
|
10014
10097
|
`${TAG19} phase=readdir-failed dir=${dir} error=${e instanceof Error ? e.message : String(e)}`
|
|
@@ -10021,7 +10104,7 @@ function consumeActionCompletionRelays(accountDir) {
|
|
|
10021
10104
|
const filePath = join9(dir, name);
|
|
10022
10105
|
let raw;
|
|
10023
10106
|
try {
|
|
10024
|
-
raw =
|
|
10107
|
+
raw = readFileSync16(filePath, "utf-8");
|
|
10025
10108
|
} catch (e) {
|
|
10026
10109
|
console.error(
|
|
10027
10110
|
`${TAG19} phase=read-failed file=${name} error=${e instanceof Error ? e.message : String(e)}`
|
|
@@ -10078,10 +10161,10 @@ import { existsSync as existsSyncFs, readFileSync as readFileSyncFs } from "fs";
|
|
|
10078
10161
|
var SETUP_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
10079
10162
|
var DOMAINS_TIMEOUT_MS = 40 * 1e3;
|
|
10080
10163
|
function loadBrandInfo() {
|
|
10081
|
-
const platformRoot2 = process.env.MAXY_PLATFORM_ROOT ??
|
|
10082
|
-
const brandPath =
|
|
10164
|
+
const platformRoot2 = process.env.MAXY_PLATFORM_ROOT ?? resolve18(process.cwd(), "..");
|
|
10165
|
+
const brandPath = resolve18(platformRoot2, "config", "brand.json");
|
|
10083
10166
|
try {
|
|
10084
|
-
const parsed = JSON.parse(
|
|
10167
|
+
const parsed = JSON.parse(readFileSync17(brandPath, "utf-8"));
|
|
10085
10168
|
const hostname2 = typeof parsed.hostname === "string" && parsed.hostname ? parsed.hostname : "maxy";
|
|
10086
10169
|
const configDir2 = typeof parsed.configDir === "string" && parsed.configDir ? parsed.configDir : ".maxy";
|
|
10087
10170
|
return { hostname: hostname2, configDir: configDir2 };
|
|
@@ -10184,7 +10267,7 @@ app21.get("/domains", requireAdminSession, async (c) => {
|
|
|
10184
10267
|
streamLogPath = streamLogPathFor(accountId, correlationId).streamLogPath;
|
|
10185
10268
|
log(`phase=stream-log-resolved path=${streamLogPath}`);
|
|
10186
10269
|
const brand = loadBrandInfo();
|
|
10187
|
-
const scriptPath =
|
|
10270
|
+
const scriptPath = resolve18(homedir(), "list-cf-domains.sh");
|
|
10188
10271
|
const result = await runFormSpawn({
|
|
10189
10272
|
scriptPath,
|
|
10190
10273
|
args: [brand.hostname],
|
|
@@ -10449,17 +10532,17 @@ var cloudflare_default = app21;
|
|
|
10449
10532
|
import { createReadStream as createReadStream3 } from "fs";
|
|
10450
10533
|
import { readdir as readdir2, readFile as readFile4, stat as stat4, mkdir as mkdir3, writeFile as writeFile4, unlink as unlink2 } from "fs/promises";
|
|
10451
10534
|
import { realpathSync as realpathSync4 } from "fs";
|
|
10452
|
-
import { basename as basename6, dirname as dirname8, join as join10, resolve as
|
|
10535
|
+
import { basename as basename6, dirname as dirname8, join as join10, resolve as resolve20, sep as sep2 } from "path";
|
|
10453
10536
|
import { Readable as Readable2 } from "stream";
|
|
10454
10537
|
|
|
10455
10538
|
// app/lib/data-path.ts
|
|
10456
10539
|
import { realpathSync as realpathSync3 } from "fs";
|
|
10457
|
-
import { resolve as
|
|
10458
|
-
var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ??
|
|
10459
|
-
var DATA_ROOT =
|
|
10540
|
+
import { resolve as resolve19, normalize, sep, relative } from "path";
|
|
10541
|
+
var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve19(process.cwd(), "../platform");
|
|
10542
|
+
var DATA_ROOT = resolve19(PLATFORM_ROOT6, "..", "data");
|
|
10460
10543
|
function resolveDataPath(raw) {
|
|
10461
10544
|
const cleaned = normalize("/" + (raw ?? "").replace(/\\/g, "/")).replace(/^\/+/, "");
|
|
10462
|
-
const absolute =
|
|
10545
|
+
const absolute = resolve19(DATA_ROOT, cleaned);
|
|
10463
10546
|
let dataRootReal;
|
|
10464
10547
|
try {
|
|
10465
10548
|
dataRootReal = realpathSync3(DATA_ROOT);
|
|
@@ -10724,7 +10807,7 @@ async function restoreNode(params) {
|
|
|
10724
10807
|
}
|
|
10725
10808
|
|
|
10726
10809
|
// app/lib/file-delete-cascade.ts
|
|
10727
|
-
var
|
|
10810
|
+
var UUID_RE3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
10728
10811
|
function parseAttachmentPath(relPath2) {
|
|
10729
10812
|
const segments = relPath2.split("/").filter(Boolean);
|
|
10730
10813
|
if (segments.length !== 4) return null;
|
|
@@ -10732,7 +10815,7 @@ function parseAttachmentPath(relPath2) {
|
|
|
10732
10815
|
const accountId = segments[1];
|
|
10733
10816
|
const attachmentId = segments[2];
|
|
10734
10817
|
const filename = segments[3];
|
|
10735
|
-
if (!
|
|
10818
|
+
if (!UUID_RE3.test(accountId) || !UUID_RE3.test(attachmentId)) return null;
|
|
10736
10819
|
const dot = filename.lastIndexOf(".");
|
|
10737
10820
|
if (dot === -1) return null;
|
|
10738
10821
|
const stem = filename.slice(0, dot);
|
|
@@ -10804,7 +10887,7 @@ async function cascadeDeleteDocument(params) {
|
|
|
10804
10887
|
}
|
|
10805
10888
|
|
|
10806
10889
|
// server/routes/admin/files.ts
|
|
10807
|
-
var
|
|
10890
|
+
var UUID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
10808
10891
|
async function readMeta(absDir, baseName) {
|
|
10809
10892
|
try {
|
|
10810
10893
|
const raw = await readFile4(join10(absDir, `${baseName}.meta.json`), "utf8");
|
|
@@ -10818,7 +10901,7 @@ async function readMeta(absDir, baseName) {
|
|
|
10818
10901
|
}
|
|
10819
10902
|
async function readAccountNames() {
|
|
10820
10903
|
const map = /* @__PURE__ */ new Map();
|
|
10821
|
-
const accountsDir =
|
|
10904
|
+
const accountsDir = resolve20(DATA_ROOT, "accounts");
|
|
10822
10905
|
let names;
|
|
10823
10906
|
try {
|
|
10824
10907
|
names = await readdir2(accountsDir);
|
|
@@ -10826,8 +10909,8 @@ async function readAccountNames() {
|
|
|
10826
10909
|
return map;
|
|
10827
10910
|
}
|
|
10828
10911
|
for (const name of names) {
|
|
10829
|
-
if (!
|
|
10830
|
-
const configPath2 =
|
|
10912
|
+
if (!UUID_RE4.test(name)) continue;
|
|
10913
|
+
const configPath2 = resolve20(accountsDir, name, "account.json");
|
|
10831
10914
|
try {
|
|
10832
10915
|
const raw = await readFile4(configPath2, "utf8");
|
|
10833
10916
|
const parsed = JSON.parse(raw);
|
|
@@ -10844,7 +10927,7 @@ async function readAccountNames() {
|
|
|
10844
10927
|
return map;
|
|
10845
10928
|
}
|
|
10846
10929
|
async function enrich(absolute, entry, accountNames) {
|
|
10847
|
-
if (entry.kind === "directory" &&
|
|
10930
|
+
if (entry.kind === "directory" && UUID_RE4.test(entry.name)) {
|
|
10848
10931
|
const meta = await readMeta(join10(absolute, entry.name), entry.name);
|
|
10849
10932
|
if (meta?.filename) {
|
|
10850
10933
|
entry.displayName = meta.filename;
|
|
@@ -10860,7 +10943,7 @@ async function enrich(absolute, entry, accountNames) {
|
|
|
10860
10943
|
if (entry.kind === "file") {
|
|
10861
10944
|
const dot = entry.name.lastIndexOf(".");
|
|
10862
10945
|
const base = dot === -1 ? entry.name : entry.name.slice(0, dot);
|
|
10863
|
-
if (
|
|
10946
|
+
if (UUID_RE4.test(base)) {
|
|
10864
10947
|
const meta = await readMeta(absolute, base);
|
|
10865
10948
|
if (meta?.filename) {
|
|
10866
10949
|
entry.displayName = meta.filename;
|
|
@@ -10872,7 +10955,7 @@ async function enrich(absolute, entry, accountNames) {
|
|
|
10872
10955
|
function buildDisplayPath(relPath2, accountNames) {
|
|
10873
10956
|
if (relPath2 === "." || relPath2 === "") return [];
|
|
10874
10957
|
return relPath2.split("/").filter(Boolean).map((seg) => {
|
|
10875
|
-
const dn =
|
|
10958
|
+
const dn = UUID_RE4.test(seg) ? accountNames.get(seg) : void 0;
|
|
10876
10959
|
return dn ? { name: seg, displayName: dn } : { name: seg };
|
|
10877
10960
|
});
|
|
10878
10961
|
}
|
|
@@ -10900,7 +10983,7 @@ app22.get("/", requireAdminSession, async (c) => {
|
|
|
10900
10983
|
const names = await readdir2(absolute);
|
|
10901
10984
|
const entries = [];
|
|
10902
10985
|
for (const name of names) {
|
|
10903
|
-
if (
|
|
10986
|
+
if (UUID_RE4.test(name.replace(/\.meta\.json$/, "")) && name.endsWith(".meta.json")) {
|
|
10904
10987
|
continue;
|
|
10905
10988
|
}
|
|
10906
10989
|
try {
|
|
@@ -11018,8 +11101,8 @@ app22.post("/upload", requireAdminSession, async (c) => {
|
|
|
11018
11101
|
}
|
|
11019
11102
|
const safeName = basename6(file.name).replace(/[\0/\\]/g, "_");
|
|
11020
11103
|
const finalName = `${Date.now()}-${safeName}`;
|
|
11021
|
-
const destDir =
|
|
11022
|
-
const destPath =
|
|
11104
|
+
const destDir = resolve20(DATA_ROOT, "uploads", accountId);
|
|
11105
|
+
const destPath = resolve20(destDir, finalName);
|
|
11023
11106
|
try {
|
|
11024
11107
|
await mkdir3(destDir, { recursive: true });
|
|
11025
11108
|
const dataRootReal = realpathSync4(DATA_ROOT);
|
|
@@ -11077,7 +11160,7 @@ app22.delete("/", requireAdminSession, async (c) => {
|
|
|
11077
11160
|
}
|
|
11078
11161
|
const dot = base.lastIndexOf(".");
|
|
11079
11162
|
const stem = dot === -1 ? base : base.slice(0, dot);
|
|
11080
|
-
const sidecarPath =
|
|
11163
|
+
const sidecarPath = UUID_RE4.test(stem) && base !== `${stem}.meta.json` ? join10(dirname8(absolute), `${stem}.meta.json`) : null;
|
|
11081
11164
|
await unlink2(absolute);
|
|
11082
11165
|
if (sidecarPath) {
|
|
11083
11166
|
try {
|
|
@@ -12534,7 +12617,7 @@ var adherence_default = app30;
|
|
|
12534
12617
|
// server/routes/admin/sidebar-artefacts.ts
|
|
12535
12618
|
import neo4j3 from "neo4j-driver";
|
|
12536
12619
|
import { readFile as readFile5, readdir as readdir3, stat as stat5 } from "fs/promises";
|
|
12537
|
-
import { resolve as
|
|
12620
|
+
import { resolve as resolve21, relative as relative2, isAbsolute } from "path";
|
|
12538
12621
|
import { existsSync as existsSync21 } from "fs";
|
|
12539
12622
|
var LIMIT = 50;
|
|
12540
12623
|
var TEXT_MIME_PREFIXES = ["text/", "application/json", "application/markdown"];
|
|
@@ -12551,7 +12634,7 @@ app31.get("/", requireAdminSession, async (c) => {
|
|
|
12551
12634
|
if (docs === null) {
|
|
12552
12635
|
return c.json({ error: "Failed to load artefacts" }, 500);
|
|
12553
12636
|
}
|
|
12554
|
-
const accountDir =
|
|
12637
|
+
const accountDir = resolve21(ACCOUNTS_DIR, accountId);
|
|
12555
12638
|
const agents = await fetchAgentTemplateRows(accountDir);
|
|
12556
12639
|
const artefacts = [...docs, ...agents].sort(
|
|
12557
12640
|
(a, b) => (b.updatedAt ?? "").localeCompare(a.updatedAt ?? "")
|
|
@@ -12614,8 +12697,8 @@ async function readArtefactContent(accountId, attachmentId, mimeType, displayNam
|
|
|
12614
12697
|
logSkip(displayName, "non-text-mime", mimeType);
|
|
12615
12698
|
return { content: "", skipReason: "non-text-mime" };
|
|
12616
12699
|
}
|
|
12617
|
-
const accountDir =
|
|
12618
|
-
const dir =
|
|
12700
|
+
const accountDir = resolve21(ATTACHMENTS_ROOT, accountId);
|
|
12701
|
+
const dir = resolve21(accountDir, attachmentId);
|
|
12619
12702
|
try {
|
|
12620
12703
|
validateFilePathInAccount(dir, accountDir);
|
|
12621
12704
|
} catch {
|
|
@@ -12629,7 +12712,7 @@ async function readArtefactContent(accountId, attachmentId, mimeType, displayNam
|
|
|
12629
12712
|
logSkip(displayName, "missing-on-disk", mimeType);
|
|
12630
12713
|
return { content: "", skipReason: "missing-on-disk" };
|
|
12631
12714
|
}
|
|
12632
|
-
return { content: await readFile5(
|
|
12715
|
+
return { content: await readFile5(resolve21(dir, dataFile), "utf-8"), skipReason: null };
|
|
12633
12716
|
} catch (err) {
|
|
12634
12717
|
const message = err instanceof Error ? err.message : String(err);
|
|
12635
12718
|
console.error(`[admin/sidebar-artefacts] read-failed attachmentId=${attachmentId.slice(0, 8)} error="${message}"`);
|
|
@@ -12645,8 +12728,8 @@ function logSkip(name, reason, mimeType) {
|
|
|
12645
12728
|
async function fetchAgentTemplateRows(accountDir) {
|
|
12646
12729
|
const rows = [];
|
|
12647
12730
|
for (const filename of ADMIN_AGENT_FILES) {
|
|
12648
|
-
const overridePath =
|
|
12649
|
-
const bundledPath =
|
|
12731
|
+
const overridePath = resolve21(accountDir, "agents", "admin", filename);
|
|
12732
|
+
const bundledPath = resolve21(PLATFORM_ROOT, "templates", "agents", "admin", filename);
|
|
12650
12733
|
const labelStem = filename.replace(/\.md$/, "");
|
|
12651
12734
|
const row = await readAgentTemplateRow({
|
|
12652
12735
|
id: `agent-template:admin:${filename}`,
|
|
@@ -12660,12 +12743,12 @@ async function fetchAgentTemplateRows(accountDir) {
|
|
|
12660
12743
|
});
|
|
12661
12744
|
if (row) rows.push(row);
|
|
12662
12745
|
}
|
|
12663
|
-
const overrideDir =
|
|
12664
|
-
const bundledDir =
|
|
12746
|
+
const overrideDir = resolve21(accountDir, "specialists", "agents");
|
|
12747
|
+
const bundledDir = resolve21(PLATFORM_ROOT, "templates", "specialists", "agents");
|
|
12665
12748
|
const specialistNames = await unionSpecialistFilenames(overrideDir, bundledDir);
|
|
12666
12749
|
for (const filename of specialistNames) {
|
|
12667
|
-
const overridePath =
|
|
12668
|
-
const bundledPath =
|
|
12750
|
+
const overridePath = resolve21(overrideDir, filename);
|
|
12751
|
+
const bundledPath = resolve21(bundledDir, filename);
|
|
12669
12752
|
const row = await readAgentTemplateRow({
|
|
12670
12753
|
id: `agent-template:specialist:${filename}`,
|
|
12671
12754
|
displayName: filename.replace(/\.md$/, ""),
|
|
@@ -12750,10 +12833,10 @@ var sidebar_artefacts_default = app31;
|
|
|
12750
12833
|
|
|
12751
12834
|
// server/routes/admin/sidebar-artefact-save.ts
|
|
12752
12835
|
import { mkdir as mkdir4, readdir as readdir4, stat as stat6, writeFile as writeFile5 } from "fs/promises";
|
|
12753
|
-
import { resolve as
|
|
12836
|
+
import { resolve as resolve22 } from "path";
|
|
12754
12837
|
import { existsSync as existsSync22 } from "fs";
|
|
12755
12838
|
var ADMIN_AGENT_FILES2 = /* @__PURE__ */ new Set(["IDENTITY.md", "SOUL.md", "KNOWLEDGE.md"]);
|
|
12756
|
-
var
|
|
12839
|
+
var UUID_RE5 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
|
|
12757
12840
|
var app32 = new Hono();
|
|
12758
12841
|
app32.post("/", requireAdminSession, async (c) => {
|
|
12759
12842
|
const sessionKey = c.var.sessionKey;
|
|
@@ -12763,7 +12846,7 @@ app32.post("/", requireAdminSession, async (c) => {
|
|
|
12763
12846
|
if (!body || typeof body.id !== "string" || typeof body.content !== "string") {
|
|
12764
12847
|
return c.json({ error: "id and content required" }, 400);
|
|
12765
12848
|
}
|
|
12766
|
-
const accountDir =
|
|
12849
|
+
const accountDir = resolve22(ACCOUNTS_DIR, accountId);
|
|
12767
12850
|
const resolved = await resolveSavePath(body.id, accountId, accountDir);
|
|
12768
12851
|
if (resolved.kind === "reject") {
|
|
12769
12852
|
console.error(
|
|
@@ -12804,22 +12887,22 @@ async function resolveSavePath(id, accountId, accountDir) {
|
|
|
12804
12887
|
if (role !== "admin" || !ADMIN_AGENT_FILES2.has(filename)) {
|
|
12805
12888
|
return { kind: "reject", status: 400, reason: "invalid-id" };
|
|
12806
12889
|
}
|
|
12807
|
-
const parent =
|
|
12890
|
+
const parent = resolve22(accountDir, "agents", "admin");
|
|
12808
12891
|
await mkdir4(parent, { recursive: true });
|
|
12809
12892
|
try {
|
|
12810
12893
|
validateFilePathInAccount(parent, accountDir);
|
|
12811
12894
|
} catch {
|
|
12812
12895
|
return { kind: "reject", status: 400, reason: "containment-rejected" };
|
|
12813
12896
|
}
|
|
12814
|
-
return { kind: "admin-template", path:
|
|
12897
|
+
return { kind: "admin-template", path: resolve22(parent, filename) };
|
|
12815
12898
|
}
|
|
12816
|
-
if (
|
|
12817
|
-
const dir =
|
|
12899
|
+
if (UUID_RE5.test(id)) {
|
|
12900
|
+
const dir = resolve22(ATTACHMENTS_ROOT, accountId, id);
|
|
12818
12901
|
if (!existsSync22(dir)) {
|
|
12819
12902
|
return { kind: "reject", status: 400, reason: "not-found" };
|
|
12820
12903
|
}
|
|
12821
12904
|
try {
|
|
12822
|
-
validateFilePathInAccount(dir,
|
|
12905
|
+
validateFilePathInAccount(dir, resolve22(ATTACHMENTS_ROOT, accountId));
|
|
12823
12906
|
} catch {
|
|
12824
12907
|
return { kind: "reject", status: 400, reason: "containment-rejected" };
|
|
12825
12908
|
}
|
|
@@ -12828,7 +12911,7 @@ async function resolveSavePath(id, accountId, accountDir) {
|
|
|
12828
12911
|
if (!dataFile) {
|
|
12829
12912
|
return { kind: "reject", status: 400, reason: "not-found" };
|
|
12830
12913
|
}
|
|
12831
|
-
return { kind: "knowledge-doc", path:
|
|
12914
|
+
return { kind: "knowledge-doc", path: resolve22(dir, dataFile) };
|
|
12832
12915
|
}
|
|
12833
12916
|
return { kind: "reject", status: 400, reason: "invalid-id" };
|
|
12834
12917
|
}
|
|
@@ -12840,26 +12923,26 @@ var sidebar_artefact_save_default = app32;
|
|
|
12840
12923
|
// server/routes/admin/sidebar-artefact-content.ts
|
|
12841
12924
|
import { readFile as readFile6, readdir as readdir5 } from "fs/promises";
|
|
12842
12925
|
import { existsSync as existsSync23 } from "fs";
|
|
12843
|
-
import { resolve as
|
|
12844
|
-
var
|
|
12926
|
+
import { resolve as resolve23 } from "path";
|
|
12927
|
+
var UUID_RE6 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
|
|
12845
12928
|
var app33 = new Hono();
|
|
12846
12929
|
app33.get("/", requireAdminSession, async (c) => {
|
|
12847
12930
|
const sessionKey = c.var.sessionKey;
|
|
12848
12931
|
const accountId = getAccountIdForSession(sessionKey);
|
|
12849
12932
|
if (!accountId) return new Response("Unauthorized", { status: 401 });
|
|
12850
12933
|
const id = c.req.query("id") ?? "";
|
|
12851
|
-
if (!
|
|
12934
|
+
if (!UUID_RE6.test(id)) {
|
|
12852
12935
|
console.error(`[admin/sidebar-artefact-content] not-found id=${id.slice(0, 8)}`);
|
|
12853
12936
|
return new Response("Not found", { status: 404 });
|
|
12854
12937
|
}
|
|
12855
|
-
const dir =
|
|
12938
|
+
const dir = resolve23(ATTACHMENTS_ROOT, accountId, id);
|
|
12856
12939
|
if (!existsSync23(dir)) {
|
|
12857
12940
|
console.error(`[admin/sidebar-artefact-content] not-found id=${id.slice(0, 8)}`);
|
|
12858
12941
|
return new Response("Not found", { status: 404 });
|
|
12859
12942
|
}
|
|
12860
12943
|
let meta;
|
|
12861
12944
|
try {
|
|
12862
|
-
meta = JSON.parse(await readFile6(
|
|
12945
|
+
meta = JSON.parse(await readFile6(resolve23(dir, `${id}.meta.json`), "utf-8"));
|
|
12863
12946
|
} catch {
|
|
12864
12947
|
console.error(`[admin/sidebar-artefact-content] not-found id=${id.slice(0, 8)}`);
|
|
12865
12948
|
return new Response("Not found", { status: 404 });
|
|
@@ -12871,7 +12954,7 @@ app33.get("/", requireAdminSession, async (c) => {
|
|
|
12871
12954
|
return new Response("Not found", { status: 404 });
|
|
12872
12955
|
}
|
|
12873
12956
|
const start = Date.now();
|
|
12874
|
-
const buffer = await readFile6(
|
|
12957
|
+
const buffer = await readFile6(resolve23(dir, dataFile));
|
|
12875
12958
|
const ms = Date.now() - start;
|
|
12876
12959
|
console.log(
|
|
12877
12960
|
`[admin/sidebar-artefact-content] account=${accountId} id=${id.slice(0, 8)} mime=${meta.mimeType} bytes=${buffer.length} ms=${ms}`
|
|
@@ -12915,8 +12998,8 @@ app34.route("/sidebar-artefact-content", sidebar_artefact_content_default);
|
|
|
12915
12998
|
var admin_default = app34;
|
|
12916
12999
|
|
|
12917
13000
|
// server/routes/sites.ts
|
|
12918
|
-
import { existsSync as existsSync24, readFileSync as
|
|
12919
|
-
import { resolve as
|
|
13001
|
+
import { existsSync as existsSync24, readFileSync as readFileSync18, realpathSync as realpathSync5, statSync as statSync8 } from "fs";
|
|
13002
|
+
import { resolve as resolve24 } from "path";
|
|
12920
13003
|
var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
|
|
12921
13004
|
var MIME = {
|
|
12922
13005
|
".html": "text/html; charset=utf-8",
|
|
@@ -12974,8 +13057,8 @@ app35.get("/:rel{.*}", (c) => {
|
|
|
12974
13057
|
}
|
|
12975
13058
|
segments.push(seg);
|
|
12976
13059
|
}
|
|
12977
|
-
const rootDir =
|
|
12978
|
-
let filePath = segments.length === 0 ? rootDir :
|
|
13060
|
+
const rootDir = resolve24(account.accountDir, "sites");
|
|
13061
|
+
let filePath = segments.length === 0 ? rootDir : resolve24(rootDir, ...segments);
|
|
12979
13062
|
if (filePath !== rootDir && !filePath.startsWith(rootDir + "/")) {
|
|
12980
13063
|
console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
|
|
12981
13064
|
return c.text("Forbidden", 403);
|
|
@@ -12987,9 +13070,9 @@ app35.get("/:rel{.*}", (c) => {
|
|
|
12987
13070
|
stat7 = null;
|
|
12988
13071
|
}
|
|
12989
13072
|
if (stat7?.isDirectory()) {
|
|
12990
|
-
filePath =
|
|
13073
|
+
filePath = resolve24(filePath, "index.html");
|
|
12991
13074
|
} else if (stat7 === null && isDirRequest) {
|
|
12992
|
-
filePath =
|
|
13075
|
+
filePath = resolve24(filePath, "index.html");
|
|
12993
13076
|
}
|
|
12994
13077
|
if (!filePath.startsWith(rootDir + "/")) {
|
|
12995
13078
|
console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
|
|
@@ -13014,7 +13097,7 @@ app35.get("/:rel{.*}", (c) => {
|
|
|
13014
13097
|
}
|
|
13015
13098
|
let body;
|
|
13016
13099
|
try {
|
|
13017
|
-
body =
|
|
13100
|
+
body = readFileSync18(realPath);
|
|
13018
13101
|
} catch (err) {
|
|
13019
13102
|
const code = err?.code;
|
|
13020
13103
|
if (code === "EISDIR") {
|
|
@@ -13153,7 +13236,7 @@ if (BRAND_JSON_PATH && !existsSync25(BRAND_JSON_PATH)) {
|
|
|
13153
13236
|
}
|
|
13154
13237
|
if (BRAND_JSON_PATH && existsSync25(BRAND_JSON_PATH)) {
|
|
13155
13238
|
try {
|
|
13156
|
-
const parsed = JSON.parse(
|
|
13239
|
+
const parsed = JSON.parse(readFileSync19(BRAND_JSON_PATH, "utf-8"));
|
|
13157
13240
|
BRAND = { ...BRAND, ...parsed };
|
|
13158
13241
|
} catch (err) {
|
|
13159
13242
|
console.error(`[brand] Failed to parse brand.json: ${err.message}`);
|
|
@@ -13176,7 +13259,7 @@ var ALIAS_DOMAINS_PATH2 = join11(homedir2(), BRAND.configDir, "alias-domains.jso
|
|
|
13176
13259
|
function loadAliasDomains() {
|
|
13177
13260
|
try {
|
|
13178
13261
|
if (!existsSync25(ALIAS_DOMAINS_PATH2)) return null;
|
|
13179
|
-
const parsed = JSON.parse(
|
|
13262
|
+
const parsed = JSON.parse(readFileSync19(ALIAS_DOMAINS_PATH2, "utf-8"));
|
|
13180
13263
|
if (!Array.isArray(parsed)) {
|
|
13181
13264
|
console.error("[alias-domains] malformed alias-domains.json \u2014 expected array");
|
|
13182
13265
|
return null;
|
|
@@ -13516,8 +13599,8 @@ app36.get("/agent-assets/:slug/:filename", (c) => {
|
|
|
13516
13599
|
console.error(`[agent-assets] no-account slug=${slug} file=${filename}`);
|
|
13517
13600
|
return c.text("Not found", 404);
|
|
13518
13601
|
}
|
|
13519
|
-
const filePath =
|
|
13520
|
-
const expectedDir =
|
|
13602
|
+
const filePath = resolve25(account.accountDir, "agents", slug, "assets", filename);
|
|
13603
|
+
const expectedDir = resolve25(account.accountDir, "agents", slug, "assets");
|
|
13521
13604
|
if (!filePath.startsWith(expectedDir + "/")) {
|
|
13522
13605
|
console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
|
|
13523
13606
|
return c.text("Forbidden", 403);
|
|
@@ -13529,7 +13612,7 @@ app36.get("/agent-assets/:slug/:filename", (c) => {
|
|
|
13529
13612
|
const ext = "." + filename.split(".").pop()?.toLowerCase();
|
|
13530
13613
|
const contentType = IMAGE_MIME[ext] || "application/octet-stream";
|
|
13531
13614
|
console.log(`[agent-assets] serve slug=${slug} file=${filename} status=200`);
|
|
13532
|
-
const body =
|
|
13615
|
+
const body = readFileSync19(filePath);
|
|
13533
13616
|
return c.body(body, 200, {
|
|
13534
13617
|
"Content-Type": contentType,
|
|
13535
13618
|
"Cache-Control": "public, max-age=3600"
|
|
@@ -13546,8 +13629,8 @@ app36.get("/generated/:filename", (c) => {
|
|
|
13546
13629
|
console.error(`[generated] serve file=${filename} status=404`);
|
|
13547
13630
|
return c.text("Not found", 404);
|
|
13548
13631
|
}
|
|
13549
|
-
const filePath =
|
|
13550
|
-
const expectedDir =
|
|
13632
|
+
const filePath = resolve25(account.accountDir, "generated", filename);
|
|
13633
|
+
const expectedDir = resolve25(account.accountDir, "generated");
|
|
13551
13634
|
if (!filePath.startsWith(expectedDir + "/")) {
|
|
13552
13635
|
console.error(`[generated] serve file=${filename} status=403`);
|
|
13553
13636
|
return c.text("Forbidden", 403);
|
|
@@ -13559,7 +13642,7 @@ app36.get("/generated/:filename", (c) => {
|
|
|
13559
13642
|
const ext = "." + filename.split(".").pop()?.toLowerCase();
|
|
13560
13643
|
const contentType = IMAGE_MIME[ext] || "application/octet-stream";
|
|
13561
13644
|
console.log(`[generated] serve file=${filename} status=200`);
|
|
13562
|
-
const body =
|
|
13645
|
+
const body = readFileSync19(filePath);
|
|
13563
13646
|
return c.body(body, 200, {
|
|
13564
13647
|
"Content-Type": contentType,
|
|
13565
13648
|
"Cache-Control": "public, max-age=86400"
|
|
@@ -13571,7 +13654,7 @@ var brandLogoPath = "/brand/maxy-monochrome.png";
|
|
|
13571
13654
|
var brandIconPath = "/brand/maxy-monochrome.png";
|
|
13572
13655
|
if (BRAND_JSON_PATH && existsSync25(BRAND_JSON_PATH)) {
|
|
13573
13656
|
try {
|
|
13574
|
-
const fullBrand = JSON.parse(
|
|
13657
|
+
const fullBrand = JSON.parse(readFileSync19(BRAND_JSON_PATH, "utf-8"));
|
|
13575
13658
|
if (fullBrand.assets?.logo) brandLogoPath = `/brand/${fullBrand.assets.logo}`;
|
|
13576
13659
|
brandIconPath = fullBrand.assets?.icon ? `/brand/${fullBrand.assets.icon}` : brandLogoPath;
|
|
13577
13660
|
} catch {
|
|
@@ -13590,7 +13673,7 @@ function readInstalledVersion() {
|
|
|
13590
13673
|
if (!PLATFORM_ROOT7) return "unknown";
|
|
13591
13674
|
const versionFile = join11(PLATFORM_ROOT7, "config", `.${BRAND.hostname}-version`);
|
|
13592
13675
|
if (!existsSync25(versionFile)) return "unknown";
|
|
13593
|
-
const content =
|
|
13676
|
+
const content = readFileSync19(versionFile, "utf-8").trim();
|
|
13594
13677
|
return content || "unknown";
|
|
13595
13678
|
} catch {
|
|
13596
13679
|
return "unknown";
|
|
@@ -13631,7 +13714,7 @@ var clientErrorReporterScript = `<script>
|
|
|
13631
13714
|
function cachedHtml(file) {
|
|
13632
13715
|
let html = htmlCache.get(file);
|
|
13633
13716
|
if (!html) {
|
|
13634
|
-
html =
|
|
13717
|
+
html = readFileSync19(resolve25(process.cwd(), "public", file), "utf-8");
|
|
13635
13718
|
const productNameEsc = escapeHtml(BRAND.productName);
|
|
13636
13719
|
html = html.replace(/<title>([^<]*)<\/title>/, (_match, inner) => `<title>${escapeHtml(inner).replace(/Maxy/g, productNameEsc)}</title>`);
|
|
13637
13720
|
html = html.replace('href="/favicon.ico"', `href="${escapeHtml(brandFaviconPath)}"`);
|
|
@@ -13651,12 +13734,12 @@ function loadBrandingCache(agentSlug) {
|
|
|
13651
13734
|
try {
|
|
13652
13735
|
const accountJsonPath = join11(configDir2, "account.json");
|
|
13653
13736
|
if (!existsSync25(accountJsonPath)) return null;
|
|
13654
|
-
const account = JSON.parse(
|
|
13737
|
+
const account = JSON.parse(readFileSync19(accountJsonPath, "utf-8"));
|
|
13655
13738
|
const accountId = account.accountId;
|
|
13656
13739
|
if (!accountId) return null;
|
|
13657
13740
|
const cachePath = join11(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
|
|
13658
13741
|
if (!existsSync25(cachePath)) return null;
|
|
13659
|
-
return JSON.parse(
|
|
13742
|
+
return JSON.parse(readFileSync19(cachePath, "utf-8"));
|
|
13660
13743
|
} catch {
|
|
13661
13744
|
return null;
|
|
13662
13745
|
}
|
|
@@ -13666,7 +13749,7 @@ function resolveDefaultSlug() {
|
|
|
13666
13749
|
const configDir2 = join11(homedir2(), BRAND.configDir);
|
|
13667
13750
|
const accountJsonPath = join11(configDir2, "account.json");
|
|
13668
13751
|
if (!existsSync25(accountJsonPath)) return null;
|
|
13669
|
-
const account = JSON.parse(
|
|
13752
|
+
const account = JSON.parse(readFileSync19(accountJsonPath, "utf-8"));
|
|
13670
13753
|
return account.defaultAgent || null;
|
|
13671
13754
|
} catch {
|
|
13672
13755
|
return null;
|
|
@@ -13675,11 +13758,11 @@ function resolveDefaultSlug() {
|
|
|
13675
13758
|
function brandedPublicHtml(agentSlug) {
|
|
13676
13759
|
const baseHtml = cachedHtml("public.html");
|
|
13677
13760
|
if (!agentSlug) return baseHtml;
|
|
13678
|
-
const
|
|
13761
|
+
const cached2 = brandedHtmlCache.get(agentSlug);
|
|
13679
13762
|
const branding = loadBrandingCache(agentSlug);
|
|
13680
13763
|
if (!branding) return baseHtml;
|
|
13681
13764
|
const brandHash = JSON.stringify(branding).length;
|
|
13682
|
-
if (
|
|
13765
|
+
if (cached2 && cached2.mtime === brandHash) return cached2.html;
|
|
13683
13766
|
const title = escapeHtml(branding.name);
|
|
13684
13767
|
const description = branding.tagline ? escapeHtml(branding.tagline) : "";
|
|
13685
13768
|
const themeColor = branding.primaryColor || "";
|
|
@@ -13739,7 +13822,7 @@ app36.use("/vnc-popout.html", logViewerFetch);
|
|
|
13739
13822
|
app36.get("/vnc-popout.html", (c) => {
|
|
13740
13823
|
let html = htmlCache.get("vnc-popout.html");
|
|
13741
13824
|
if (!html) {
|
|
13742
|
-
html =
|
|
13825
|
+
html = readFileSync19(resolve25(process.cwd(), "public", "vnc-popout.html"), "utf-8");
|
|
13743
13826
|
const name = escapeHtml(BRAND.productName);
|
|
13744
13827
|
html = html.replace("<title>Browser \u2014 Maxy</title>", `<title>${name}</title>`);
|
|
13745
13828
|
html = html.replace("</head>", ` ${brandScript}
|
|
@@ -13830,7 +13913,7 @@ try {
|
|
|
13830
13913
|
try {
|
|
13831
13914
|
let userId = "";
|
|
13832
13915
|
if (existsSync25(USERS_FILE)) {
|
|
13833
|
-
const users = JSON.parse(
|
|
13916
|
+
const users = JSON.parse(readFileSync19(USERS_FILE, "utf-8").trim() || "[]");
|
|
13834
13917
|
userId = users[0]?.userId ?? "";
|
|
13835
13918
|
}
|
|
13836
13919
|
await backfillNullUserIdConversations(userId);
|
|
@@ -13939,7 +14022,7 @@ if (bootAccountConfig?.whatsapp) {
|
|
|
13939
14022
|
}
|
|
13940
14023
|
init({
|
|
13941
14024
|
configDir: configDirForWhatsApp,
|
|
13942
|
-
platformRoot:
|
|
14025
|
+
platformRoot: resolve25(process.env.MAXY_PLATFORM_ROOT ?? join11(__dirname, "..")),
|
|
13943
14026
|
accountConfig: bootAccountConfig,
|
|
13944
14027
|
onMessage: async (msg) => {
|
|
13945
14028
|
try {
|