@rubytech/create-maxy-code 0.1.442 → 0.1.443
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__tests__/converge-client-admins.test.js +50 -0
- package/dist/converge-client-admins.js +67 -0
- package/dist/index.js +8 -0
- package/package.json +1 -1
- package/payload/platform/docs/superpowers/plans/2026-07-13-account-schema-ontology-projection.md +547 -0
- package/payload/platform/docs/superpowers/plans/2026-07-14-graph-top-level-labels-ontology-single-source.md +458 -0
- package/payload/platform/docs/superpowers/specs/2026-07-13-account-schema-ontology-projection-design.md +178 -0
- package/payload/platform/docs/superpowers/specs/2026-07-14-graph-top-level-labels-ontology-single-source-design.md +119 -0
- package/payload/platform/plugins/admin/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/admin/PLUGIN.md +7 -1
- package/payload/platform/plugins/admin/hooks/__tests__/fs-schema-guard.test.sh +19 -2
- package/payload/platform/plugins/admin/mcp/dist/index.js +126 -1
- package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/admin/mcp/dist/tools/account-lifecycle.d.ts +30 -0
- package/payload/platform/plugins/admin/mcp/dist/tools/account-lifecycle.d.ts.map +1 -1
- package/payload/platform/plugins/admin/mcp/dist/tools/account-lifecycle.js +78 -0
- package/payload/platform/plugins/admin/mcp/dist/tools/account-lifecycle.js.map +1 -1
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +2 -2
- package/payload/platform/plugins/docs/references/admin-ui.md +1 -1
- package/payload/platform/plugins/memory/PLUGIN.md +2 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/resolve-active-vertical.test.js +12 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/resolve-active-vertical.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/resolve-active-vertical.d.ts +9 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/resolve-active-vertical.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/resolve-active-vertical.js +19 -2
- package/payload/platform/plugins/memory/mcp/dist/lib/resolve-active-vertical.js.map +1 -1
- package/payload/platform/plugins/memory/references/schema-estate-agent.md +8 -3
- package/payload/platform/scripts/__tests__/account-schema-owned-dirs.test.sh +58 -0
- package/payload/platform/scripts/__tests__/provision-role-stamp.test.sh +6 -0
- package/payload/platform/scripts/lib/account-schema-owned-dirs.py +143 -10
- package/payload/platform/scripts/lib/provision-account-dir.sh +5 -0
- package/payload/platform/scripts/name-glsmith-owner.sh +239 -0
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +2 -0
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
- package/payload/server/server.js +341 -169
- package/payload/platform/plugins/memory/references/schema-trades.md +0 -34
package/payload/server/server.js
CHANGED
|
@@ -1413,10 +1413,10 @@ var serveStatic = (options = { root: "" }) => {
|
|
|
1413
1413
|
};
|
|
1414
1414
|
|
|
1415
1415
|
// server/index.ts
|
|
1416
|
-
import { readFileSync as
|
|
1416
|
+
import { readFileSync as readFileSync37, existsSync as existsSync35, watchFile } from "fs";
|
|
1417
1417
|
import { spawn as spawn3 } from "child_process";
|
|
1418
1418
|
import { createHash as createHash7 } from "crypto";
|
|
1419
|
-
import { resolve as
|
|
1419
|
+
import { resolve as resolve34, join as join37, basename as basename12 } from "path";
|
|
1420
1420
|
import { homedir as homedir4 } from "os";
|
|
1421
1421
|
import { monitorEventLoopDelay } from "perf_hooks";
|
|
1422
1422
|
|
|
@@ -2129,7 +2129,7 @@ var credsSaveQueue = Promise.resolve();
|
|
|
2129
2129
|
async function drainCredsSaveQueue(timeoutMs = 5e3) {
|
|
2130
2130
|
console.error(`${TAG2} draining credential save queue\u2026`);
|
|
2131
2131
|
const timer2 = new Promise(
|
|
2132
|
-
(
|
|
2132
|
+
(resolve35) => setTimeout(() => resolve35("timeout"), timeoutMs)
|
|
2133
2133
|
);
|
|
2134
2134
|
const result = await Promise.race([
|
|
2135
2135
|
credsSaveQueue.then(() => "drained"),
|
|
@@ -2292,11 +2292,11 @@ async function createWaSocket(opts) {
|
|
|
2292
2292
|
return sock;
|
|
2293
2293
|
}
|
|
2294
2294
|
async function waitForConnection(sock) {
|
|
2295
|
-
return new Promise((
|
|
2295
|
+
return new Promise((resolve35, reject) => {
|
|
2296
2296
|
const handler = (update) => {
|
|
2297
2297
|
if (update.connection === "open") {
|
|
2298
2298
|
sock.ev.off("connection.update", handler);
|
|
2299
|
-
|
|
2299
|
+
resolve35();
|
|
2300
2300
|
}
|
|
2301
2301
|
if (update.connection === "close") {
|
|
2302
2302
|
sock.ev.off("connection.update", handler);
|
|
@@ -2401,7 +2401,7 @@ import { inspect as inspect2 } from "util";
|
|
|
2401
2401
|
|
|
2402
2402
|
// app/lib/whatsapp/with-timeout.ts
|
|
2403
2403
|
function withTimeout(label, promise, timeoutMs) {
|
|
2404
|
-
return new Promise((
|
|
2404
|
+
return new Promise((resolve35, reject) => {
|
|
2405
2405
|
const timer2 = setTimeout(() => {
|
|
2406
2406
|
reject(new Error(`${label} timed out after ${timeoutMs}ms`));
|
|
2407
2407
|
}, timeoutMs);
|
|
@@ -2409,7 +2409,7 @@ function withTimeout(label, promise, timeoutMs) {
|
|
|
2409
2409
|
promise.then(
|
|
2410
2410
|
(value) => {
|
|
2411
2411
|
clearTimeout(timer2);
|
|
2412
|
-
|
|
2412
|
+
resolve35(value);
|
|
2413
2413
|
},
|
|
2414
2414
|
(err) => {
|
|
2415
2415
|
clearTimeout(timer2);
|
|
@@ -3489,10 +3489,10 @@ function readConversationSummaries(platformAccountId) {
|
|
|
3489
3489
|
} catch {
|
|
3490
3490
|
continue;
|
|
3491
3491
|
}
|
|
3492
|
-
const
|
|
3493
|
-
if (
|
|
3492
|
+
const cached3 = summaryCache.get(file);
|
|
3493
|
+
if (cached3 && cached3.size === size && cached3.mtimeMs === mtimeMs) {
|
|
3494
3494
|
cacheHits++;
|
|
3495
|
-
out.set(remoteJid,
|
|
3495
|
+
out.set(remoteJid, cached3.summary);
|
|
3496
3496
|
continue;
|
|
3497
3497
|
}
|
|
3498
3498
|
let summary;
|
|
@@ -3556,8 +3556,8 @@ async function persistWhatsAppMessage(input) {
|
|
|
3556
3556
|
const { givenName, familyName } = splitName(input.pushName);
|
|
3557
3557
|
const prev = sessionWriteLocks.get(input.cacheKey);
|
|
3558
3558
|
let release;
|
|
3559
|
-
const mine = new Promise((
|
|
3560
|
-
release =
|
|
3559
|
+
const mine = new Promise((resolve35) => {
|
|
3560
|
+
release = resolve35;
|
|
3561
3561
|
});
|
|
3562
3562
|
const chained = (prev ?? Promise.resolve()).then(() => mine);
|
|
3563
3563
|
sessionWriteLocks.set(input.cacheKey, chained);
|
|
@@ -3700,8 +3700,8 @@ import { resolve as resolve3 } from "path";
|
|
|
3700
3700
|
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
3701
3701
|
var cache = /* @__PURE__ */ new Map();
|
|
3702
3702
|
function enumerateValidAccountIds(accountsDir) {
|
|
3703
|
-
const
|
|
3704
|
-
if (
|
|
3703
|
+
const cached3 = cache.get(accountsDir);
|
|
3704
|
+
if (cached3 !== void 0) return cached3;
|
|
3705
3705
|
let names;
|
|
3706
3706
|
try {
|
|
3707
3707
|
names = readdirSync2(accountsDir);
|
|
@@ -5259,11 +5259,11 @@ async function connectWithReconnect(conn) {
|
|
|
5259
5259
|
console.error(
|
|
5260
5260
|
`${TAG13} reconnecting account=${conn.accountId} in ${delay}ms (attempt ${decision.nextAttempts}/${maxAttempts})`
|
|
5261
5261
|
);
|
|
5262
|
-
await new Promise((
|
|
5263
|
-
const timer2 = setTimeout(
|
|
5262
|
+
await new Promise((resolve35) => {
|
|
5263
|
+
const timer2 = setTimeout(resolve35, delay);
|
|
5264
5264
|
conn.abortController.signal.addEventListener("abort", () => {
|
|
5265
5265
|
clearTimeout(timer2);
|
|
5266
|
-
|
|
5266
|
+
resolve35();
|
|
5267
5267
|
}, { once: true });
|
|
5268
5268
|
});
|
|
5269
5269
|
}
|
|
@@ -5271,16 +5271,16 @@ async function connectWithReconnect(conn) {
|
|
|
5271
5271
|
}
|
|
5272
5272
|
}
|
|
5273
5273
|
function waitForDisconnectEvent(conn) {
|
|
5274
|
-
return new Promise((
|
|
5274
|
+
return new Promise((resolve35) => {
|
|
5275
5275
|
if (!conn.sock) {
|
|
5276
|
-
|
|
5276
|
+
resolve35();
|
|
5277
5277
|
return;
|
|
5278
5278
|
}
|
|
5279
5279
|
const sock = conn.sock;
|
|
5280
5280
|
const handler = (update) => {
|
|
5281
5281
|
if (update.connection === "close") {
|
|
5282
5282
|
sock.ev.off("connection.update", handler);
|
|
5283
|
-
|
|
5283
|
+
resolve35();
|
|
5284
5284
|
}
|
|
5285
5285
|
};
|
|
5286
5286
|
sock.ev.on("connection.update", handler);
|
|
@@ -5602,8 +5602,8 @@ async function handleInboundMessage(conn, msg) {
|
|
|
5602
5602
|
const conversationKey = isGroup ? remoteJid : senderPhone;
|
|
5603
5603
|
const debounceKey = `${conn.accountId}:${conversationKey}:${senderPhone}`;
|
|
5604
5604
|
let resolvePending;
|
|
5605
|
-
const sttPending = new Promise((
|
|
5606
|
-
resolvePending =
|
|
5605
|
+
const sttPending = new Promise((resolve35) => {
|
|
5606
|
+
resolvePending = resolve35;
|
|
5607
5607
|
});
|
|
5608
5608
|
if (conn.debouncer) conn.debouncer.registerPending(debounceKey, sttPending);
|
|
5609
5609
|
try {
|
|
@@ -6031,20 +6031,20 @@ function buildX11Env(chromiumWrapperPath, transport = "vnc") {
|
|
|
6031
6031
|
|
|
6032
6032
|
// server/routes/health.ts
|
|
6033
6033
|
function checkPort(port2, timeoutMs = 500) {
|
|
6034
|
-
return new Promise((
|
|
6034
|
+
return new Promise((resolve35) => {
|
|
6035
6035
|
const socket = createConnection2(port2, "127.0.0.1");
|
|
6036
6036
|
socket.setTimeout(timeoutMs);
|
|
6037
6037
|
socket.once("connect", () => {
|
|
6038
6038
|
socket.destroy();
|
|
6039
|
-
|
|
6039
|
+
resolve35(true);
|
|
6040
6040
|
});
|
|
6041
6041
|
socket.once("error", () => {
|
|
6042
6042
|
socket.destroy();
|
|
6043
|
-
|
|
6043
|
+
resolve35(false);
|
|
6044
6044
|
});
|
|
6045
6045
|
socket.once("timeout", () => {
|
|
6046
6046
|
socket.destroy();
|
|
6047
|
-
|
|
6047
|
+
resolve35(false);
|
|
6048
6048
|
});
|
|
6049
6049
|
});
|
|
6050
6050
|
}
|
|
@@ -7321,8 +7321,8 @@ async function startLogin(opts) {
|
|
|
7321
7321
|
await clearAuth(authDir);
|
|
7322
7322
|
let resolveCode = null;
|
|
7323
7323
|
let rejectCode = null;
|
|
7324
|
-
const codePromise = new Promise((
|
|
7325
|
-
resolveCode =
|
|
7324
|
+
const codePromise = new Promise((resolve35, reject) => {
|
|
7325
|
+
resolveCode = resolve35;
|
|
7326
7326
|
rejectCode = reject;
|
|
7327
7327
|
});
|
|
7328
7328
|
const codeTimer = setTimeout(
|
|
@@ -9210,6 +9210,24 @@ function splitNewLines(buf, baseOffset) {
|
|
|
9210
9210
|
};
|
|
9211
9211
|
}
|
|
9212
9212
|
|
|
9213
|
+
// app/lib/whatsapp-reader/authorize-reply-file-ref.ts
|
|
9214
|
+
var ACCOUNT_UUID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
9215
|
+
function accountPartitionOwner(relative7) {
|
|
9216
|
+
const segs = relative7.split("/").filter(Boolean);
|
|
9217
|
+
if (segs.length < 2 || segs[0] !== "accounts") return null;
|
|
9218
|
+
return ACCOUNT_UUID_RE2.test(segs[1]) ? segs[1] : null;
|
|
9219
|
+
}
|
|
9220
|
+
function authorizeReplyFileRef(input) {
|
|
9221
|
+
const { relative: relative7, sendAccountId, sessionAccountId } = input;
|
|
9222
|
+
const segs = relative7.split("/").filter(Boolean);
|
|
9223
|
+
const inAccounts = segs.length >= 2 && segs[0] === "accounts";
|
|
9224
|
+
if (inAccounts && segs[1] === sendAccountId) return { allow: true, via: "own" };
|
|
9225
|
+
if (inAccounts && sessionAccountId && segs[1] === sessionAccountId) return { allow: true, via: "session" };
|
|
9226
|
+
if (accountPartitionOwner(relative7)) return { allow: false, reason: "cross-account" };
|
|
9227
|
+
if (segs[0] === "public" || inAccounts && segs[1] === "public") return { allow: false, reason: "public" };
|
|
9228
|
+
return { allow: false, reason: "foreign" };
|
|
9229
|
+
}
|
|
9230
|
+
|
|
9213
9231
|
// server/routes/admin/manager-client.ts
|
|
9214
9232
|
var SESSION_ID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
9215
9233
|
function isSessionId(value) {
|
|
@@ -9244,6 +9262,11 @@ function isMimeAdmitted(mimeType, supportedSet) {
|
|
|
9244
9262
|
|
|
9245
9263
|
// server/routes/whatsapp-reader.ts
|
|
9246
9264
|
var app4 = new Hono();
|
|
9265
|
+
var DENY_COPY = {
|
|
9266
|
+
"cross-account": "This file belongs to another account. Open that account to send it.",
|
|
9267
|
+
public: "This file cannot be sent to a WhatsApp contact.",
|
|
9268
|
+
foreign: "This file cannot be sent to a WhatsApp contact."
|
|
9269
|
+
};
|
|
9247
9270
|
app4.get("/conversations", requireAdminSession, async (c) => {
|
|
9248
9271
|
const cacheKey = c.var.cacheKey;
|
|
9249
9272
|
const scopeAccountId = getAccountIdForSession(cacheKey) ?? null;
|
|
@@ -9891,7 +9914,9 @@ app4.post("/reply", requireAdminSession, async (c) => {
|
|
|
9891
9914
|
return c.json({ error: "invalid accountId" }, 400);
|
|
9892
9915
|
}
|
|
9893
9916
|
const validAccount = isValidAccountId(accountId);
|
|
9894
|
-
|
|
9917
|
+
const cacheKey = c.var.cacheKey;
|
|
9918
|
+
const sessionAccountId = getAccountIdForSession(cacheKey) ?? null;
|
|
9919
|
+
console.log(`${MANUAL_TAG} op=scope sendId=${sendId} accountId=${accountId} validAccount=${validAccount} sessionAccount=${sessionAccountId ?? "null"} src=session`);
|
|
9895
9920
|
if (!validAccount) {
|
|
9896
9921
|
exit("rejected");
|
|
9897
9922
|
return c.json({ error: "unknown account" }, 400);
|
|
@@ -9929,26 +9954,37 @@ app4.post("/reply", requireAdminSession, async (c) => {
|
|
|
9929
9954
|
}
|
|
9930
9955
|
}
|
|
9931
9956
|
const resolvedRefs = [];
|
|
9957
|
+
const acct8 = accountId.slice(0, 8);
|
|
9958
|
+
const sess8 = sessionAccountId ? sessionAccountId.slice(0, 8) : "";
|
|
9932
9959
|
for (const ref of fileRefs) {
|
|
9933
9960
|
const resolved = resolveDataPath(ref);
|
|
9934
|
-
|
|
9935
|
-
|
|
9961
|
+
if (!resolved.ok) {
|
|
9962
|
+
console.log(`${MANUAL_TAG} op=reply-file-ref sendId=${sendId} path=${ref} owner= sendAccount=${acct8} sessionAccount=${sess8} via=deny reason=unresolved ok=false`);
|
|
9963
|
+
exit("rejected");
|
|
9964
|
+
return c.json({ error: `device file not found: ${ref}`, reason: "file-ref-unresolved" }, 404);
|
|
9965
|
+
}
|
|
9966
|
+
const owner = accountPartitionOwner(resolved.relative);
|
|
9967
|
+
const owner8 = owner ? owner.slice(0, 8) : "";
|
|
9968
|
+
const decision = authorizeReplyFileRef({ relative: resolved.relative, sendAccountId: accountId, sessionAccountId });
|
|
9969
|
+
if (!decision.allow) {
|
|
9970
|
+
console.log(`${MANUAL_TAG} op=reply-file-ref sendId=${sendId} path=${ref} owner=${owner8} sendAccount=${acct8} sessionAccount=${sess8} via=deny reason=${decision.reason} ok=false`);
|
|
9971
|
+
exit("rejected");
|
|
9972
|
+
return c.json({ error: DENY_COPY[decision.reason], reason: `file-ref-${decision.reason}` }, 403);
|
|
9973
|
+
}
|
|
9974
|
+
const absolute = resolved.absolute;
|
|
9936
9975
|
let size = -1;
|
|
9937
|
-
|
|
9938
|
-
|
|
9939
|
-
|
|
9940
|
-
|
|
9941
|
-
|
|
9942
|
-
} catch {
|
|
9943
|
-
size = -1;
|
|
9944
|
-
}
|
|
9976
|
+
try {
|
|
9977
|
+
const st = statSync5(absolute);
|
|
9978
|
+
size = st.isFile() ? st.size : -1;
|
|
9979
|
+
} catch {
|
|
9980
|
+
size = -1;
|
|
9945
9981
|
}
|
|
9946
|
-
|
|
9947
|
-
|
|
9948
|
-
if (!ok) {
|
|
9982
|
+
if (size < 0) {
|
|
9983
|
+
console.log(`${MANUAL_TAG} op=reply-file-ref sendId=${sendId} path=${ref} owner=${owner8} sendAccount=${acct8} sessionAccount=${sess8} via=${decision.via} reason=missing ok=false`);
|
|
9949
9984
|
exit("rejected");
|
|
9950
9985
|
return c.json({ error: `device file not found: ${ref}`, reason: "file-ref-unresolved" }, 404);
|
|
9951
9986
|
}
|
|
9987
|
+
console.log(`${MANUAL_TAG} op=reply-file-ref sendId=${sendId} path=${ref} owner=${owner8} sendAccount=${acct8} sessionAccount=${sess8} via=${decision.via} reason=none ok=true`);
|
|
9952
9988
|
if (size > MAX_FILE_BYTES) {
|
|
9953
9989
|
exit("rejected");
|
|
9954
9990
|
return c.json({ error: `"${basename4(absolute)}" exceeds the 50 MB limit` }, 400);
|
|
@@ -17099,6 +17135,142 @@ function isHiddenByDefault(label) {
|
|
|
17099
17135
|
return HIDDEN_BY_DEFAULT_LABELS.has(label);
|
|
17100
17136
|
}
|
|
17101
17137
|
|
|
17138
|
+
// server/lib/top-level-labels.ts
|
|
17139
|
+
import { readdirSync as readdirSync19, readFileSync as readFileSync30 } from "fs";
|
|
17140
|
+
import { join as join30, resolve as resolve23 } from "path";
|
|
17141
|
+
var STATIC_TOP_LEVEL_LABELS = Object.freeze(
|
|
17142
|
+
/* @__PURE__ */ new Set([
|
|
17143
|
+
// Base-schema infra (schema-base.md has no top-level section).
|
|
17144
|
+
"LocalBusiness",
|
|
17145
|
+
"Service",
|
|
17146
|
+
"PriceSpecification",
|
|
17147
|
+
"OpeningHoursSpecification",
|
|
17148
|
+
"Organization",
|
|
17149
|
+
"Person",
|
|
17150
|
+
"UserProfile",
|
|
17151
|
+
"Preference",
|
|
17152
|
+
"AdminUser",
|
|
17153
|
+
"AccessGrant",
|
|
17154
|
+
"KnowledgeDocument",
|
|
17155
|
+
"DigitalDocument",
|
|
17156
|
+
"CreativeWork",
|
|
17157
|
+
"Question",
|
|
17158
|
+
"FAQPage",
|
|
17159
|
+
"DefinedTerm",
|
|
17160
|
+
"Review",
|
|
17161
|
+
"ImageObject",
|
|
17162
|
+
"Invoice",
|
|
17163
|
+
"Task",
|
|
17164
|
+
"Project",
|
|
17165
|
+
"Event",
|
|
17166
|
+
"Workflow",
|
|
17167
|
+
"Email",
|
|
17168
|
+
"EmailAccount",
|
|
17169
|
+
"Agent",
|
|
17170
|
+
// Knowledge-work vertical: schema-knowledge-work.md has no top-level
|
|
17171
|
+
// section yet.
|
|
17172
|
+
"Objective",
|
|
17173
|
+
"KeyResult",
|
|
17174
|
+
"Decision",
|
|
17175
|
+
"Risk",
|
|
17176
|
+
"Source",
|
|
17177
|
+
"Finding",
|
|
17178
|
+
"Hypothesis"
|
|
17179
|
+
])
|
|
17180
|
+
);
|
|
17181
|
+
function splitPipeRow(row) {
|
|
17182
|
+
let trimmed = row.trim();
|
|
17183
|
+
if (trimmed.startsWith("|")) trimmed = trimmed.slice(1);
|
|
17184
|
+
if (trimmed.endsWith("|")) trimmed = trimmed.slice(0, -1);
|
|
17185
|
+
const cells = [];
|
|
17186
|
+
let inBacktick = false;
|
|
17187
|
+
let start = 0;
|
|
17188
|
+
for (let i = 0; i < trimmed.length; i++) {
|
|
17189
|
+
const ch = trimmed[i];
|
|
17190
|
+
if (ch === "`") inBacktick = !inBacktick;
|
|
17191
|
+
else if (ch === "|" && !inBacktick) {
|
|
17192
|
+
cells.push(trimmed.slice(start, i).trim());
|
|
17193
|
+
start = i + 1;
|
|
17194
|
+
}
|
|
17195
|
+
}
|
|
17196
|
+
cells.push(trimmed.slice(start).trim());
|
|
17197
|
+
return cells;
|
|
17198
|
+
}
|
|
17199
|
+
var stripBackticks = (s) => s.replace(/`/g, "").trim();
|
|
17200
|
+
function parseTopLevelLabels(content) {
|
|
17201
|
+
const lines = content.split(/\r?\n/);
|
|
17202
|
+
let i = 0;
|
|
17203
|
+
while (i < lines.length) {
|
|
17204
|
+
if (lines[i].toLowerCase().startsWith("## top-level node types")) break;
|
|
17205
|
+
i++;
|
|
17206
|
+
}
|
|
17207
|
+
if (i >= lines.length) return [];
|
|
17208
|
+
i++;
|
|
17209
|
+
for (; i < lines.length - 1; i++) {
|
|
17210
|
+
const line = lines[i];
|
|
17211
|
+
if (line.startsWith("## ")) return [];
|
|
17212
|
+
if (!line.includes("|")) continue;
|
|
17213
|
+
const sep9 = lines[i + 1];
|
|
17214
|
+
if (!/^\s*\|?[\s:|-]+\|?\s*$/.test(sep9) || !sep9.includes("-")) continue;
|
|
17215
|
+
const headers = splitPipeRow(line).map((h) => stripBackticks(h).toLowerCase());
|
|
17216
|
+
const labelCol = headers.findIndex((h) => h === "neo4j label");
|
|
17217
|
+
if (labelCol === -1) return [];
|
|
17218
|
+
const out = [];
|
|
17219
|
+
let j = i + 2;
|
|
17220
|
+
for (; j < lines.length; j++) {
|
|
17221
|
+
const row = lines[j];
|
|
17222
|
+
if (!row.trim() || !row.includes("|")) break;
|
|
17223
|
+
const cells = splitPipeRow(row);
|
|
17224
|
+
const label = stripBackticks(cells[labelCol] ?? "");
|
|
17225
|
+
if (label) out.push(label);
|
|
17226
|
+
}
|
|
17227
|
+
return out;
|
|
17228
|
+
}
|
|
17229
|
+
return [];
|
|
17230
|
+
}
|
|
17231
|
+
function resolveReferencesDir() {
|
|
17232
|
+
if (process.env.MAXY_PLATFORM_ROOT) {
|
|
17233
|
+
return join30(process.env.MAXY_PLATFORM_ROOT, "plugins", "memory", "references");
|
|
17234
|
+
}
|
|
17235
|
+
return resolve23(import.meta.dirname, "../../../plugins/memory/references");
|
|
17236
|
+
}
|
|
17237
|
+
function parseTableTopLevelLabels(referencesDir) {
|
|
17238
|
+
const labels = /* @__PURE__ */ new Set();
|
|
17239
|
+
const contributingFiles = [];
|
|
17240
|
+
try {
|
|
17241
|
+
const fileNames = readdirSync19(referencesDir).filter((f) => f.startsWith("schema-") && f.endsWith(".md")).sort();
|
|
17242
|
+
for (const fileName of fileNames) {
|
|
17243
|
+
const content = readFileSync30(join30(referencesDir, fileName), "utf-8");
|
|
17244
|
+
const parsed = parseTopLevelLabels(content);
|
|
17245
|
+
if (parsed.length > 0) contributingFiles.push(fileName);
|
|
17246
|
+
for (const label of parsed) labels.add(label);
|
|
17247
|
+
}
|
|
17248
|
+
} catch (err) {
|
|
17249
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
17250
|
+
process.stderr.write(
|
|
17251
|
+
`[graph-page] op=top-level-labels source=ontology status=error dir=${referencesDir} reason="${message}"
|
|
17252
|
+
`
|
|
17253
|
+
);
|
|
17254
|
+
throw err;
|
|
17255
|
+
}
|
|
17256
|
+
return { labels, contributingFiles };
|
|
17257
|
+
}
|
|
17258
|
+
var cached = null;
|
|
17259
|
+
function getTopLevelLabelAllowlist(opts = {}) {
|
|
17260
|
+
if (!opts.referencesDir && cached) return cached;
|
|
17261
|
+
const referencesDir = opts.referencesDir ?? resolveReferencesDir();
|
|
17262
|
+
const { labels: derived, contributingFiles } = parseTableTopLevelLabels(referencesDir);
|
|
17263
|
+
const derivedCount = derived.size;
|
|
17264
|
+
for (const label of STATIC_TOP_LEVEL_LABELS) derived.add(label);
|
|
17265
|
+
const result = Object.freeze(derived);
|
|
17266
|
+
process.stderr.write(
|
|
17267
|
+
`[graph-page] op=top-level-labels source=ontology count=${derived.size} files=${contributingFiles.join("|") || "none"} derived=${derivedCount} static=${STATIC_TOP_LEVEL_LABELS.size}
|
|
17268
|
+
`
|
|
17269
|
+
);
|
|
17270
|
+
if (!opts.referencesDir) cached = result;
|
|
17271
|
+
return result;
|
|
17272
|
+
}
|
|
17273
|
+
|
|
17102
17274
|
// server/routes/admin/graph-subgraph.ts
|
|
17103
17275
|
var CEILING = 2e3;
|
|
17104
17276
|
var TOP_LEVEL_LIMIT = 1e3;
|
|
@@ -17220,7 +17392,7 @@ async function handleDefault(c, accountId) {
|
|
|
17220
17392
|
}
|
|
17221
17393
|
async function handleDefaultTopLevel(c, accountId, flags) {
|
|
17222
17394
|
const { includeTrashed, includeAgentActions } = flags;
|
|
17223
|
-
const labels = [...
|
|
17395
|
+
const labels = [...getTopLevelLabelAllowlist()].filter((l) => !HIDDEN_BY_DEFAULT_LABELS.has(l));
|
|
17224
17396
|
const agentActionLabels = [...AGENT_ACTION_LABELS];
|
|
17225
17397
|
const started = Date.now();
|
|
17226
17398
|
const session = getSession();
|
|
@@ -18031,7 +18203,7 @@ app26.get("/", requireAdminSession, async (c) => {
|
|
|
18031
18203
|
const started = Date.now();
|
|
18032
18204
|
const session = getSession();
|
|
18033
18205
|
try {
|
|
18034
|
-
const allowedSet = new Set(
|
|
18206
|
+
const allowedSet = new Set(getTopLevelLabelAllowlist());
|
|
18035
18207
|
if (includeAgentActions) {
|
|
18036
18208
|
for (const label of AGENT_ACTION_LABELS) allowedSet.add(label);
|
|
18037
18209
|
}
|
|
@@ -18193,12 +18365,12 @@ function validateBody(body) {
|
|
|
18193
18365
|
if (typeof lbl !== "string") {
|
|
18194
18366
|
return { ok: false, code: "shape", reason: "labels must be an array of strings" };
|
|
18195
18367
|
}
|
|
18196
|
-
if (!
|
|
18368
|
+
if (!getTopLevelLabelAllowlist().has(lbl)) {
|
|
18197
18369
|
return {
|
|
18198
18370
|
ok: false,
|
|
18199
18371
|
code: "not-eligible-chip",
|
|
18200
18372
|
label: lbl,
|
|
18201
|
-
reason: `label "${lbl}" is not eligible for default view \u2014 outside the chip allowlist
|
|
18373
|
+
reason: `label "${lbl}" is not eligible for default view \u2014 outside the chip allowlist`
|
|
18202
18374
|
};
|
|
18203
18375
|
}
|
|
18204
18376
|
seen.add(lbl);
|
|
@@ -18221,7 +18393,7 @@ var graph_default_view_default = app27;
|
|
|
18221
18393
|
|
|
18222
18394
|
// server/routes/admin/sidebar-artefacts.ts
|
|
18223
18395
|
import { readdir as readdir4, stat as stat5 } from "fs/promises";
|
|
18224
|
-
import { resolve as
|
|
18396
|
+
import { resolve as resolve24, relative as relative5, isAbsolute as isAbsolute2, sep as sep7, basename as basename10 } from "path";
|
|
18225
18397
|
import { existsSync as existsSync27 } from "fs";
|
|
18226
18398
|
var LIMIT = 50;
|
|
18227
18399
|
var ADMIN_AGENT_FILES = ["IDENTITY.md", "SOUL.md", "KNOWLEDGE.md"];
|
|
@@ -18241,7 +18413,7 @@ app28.get("/", requireAdminSession, async (c) => {
|
|
|
18241
18413
|
if (accountFiles === null) {
|
|
18242
18414
|
return c.json({ error: "Failed to load artefacts" }, 500);
|
|
18243
18415
|
}
|
|
18244
|
-
const accountDir =
|
|
18416
|
+
const accountDir = resolve24(ACCOUNTS_DIR, accountId);
|
|
18245
18417
|
const agents = await fetchAgentTemplateRows(accountDir);
|
|
18246
18418
|
const artefacts = [...accountFiles, ...agents].sort(
|
|
18247
18419
|
(a, b) => (b.updatedAt ?? "").localeCompare(a.updatedAt ?? "")
|
|
@@ -18293,8 +18465,8 @@ async function fetchAccountFileArtefacts(accountId) {
|
|
|
18293
18465
|
async function fetchAgentTemplateRows(accountDir) {
|
|
18294
18466
|
const rows = [];
|
|
18295
18467
|
for (const filename of ADMIN_AGENT_FILES) {
|
|
18296
|
-
const overridePath =
|
|
18297
|
-
const bundledPath =
|
|
18468
|
+
const overridePath = resolve24(accountDir, "agents", "admin", filename);
|
|
18469
|
+
const bundledPath = resolve24(PLATFORM_ROOT, "templates", "agents", "admin", filename);
|
|
18298
18470
|
const labelStem = filename.replace(/\.md$/, "");
|
|
18299
18471
|
const row = await readAgentTemplateRow({
|
|
18300
18472
|
id: `agent-template:admin:${filename}`,
|
|
@@ -18307,12 +18479,12 @@ async function fetchAgentTemplateRows(accountDir) {
|
|
|
18307
18479
|
});
|
|
18308
18480
|
if (row) rows.push(row);
|
|
18309
18481
|
}
|
|
18310
|
-
const overrideDir =
|
|
18311
|
-
const bundledDir =
|
|
18482
|
+
const overrideDir = resolve24(accountDir, "specialists", "agents");
|
|
18483
|
+
const bundledDir = resolve24(PLATFORM_ROOT, "templates", "specialists", "agents");
|
|
18312
18484
|
const specialistNames = await unionSpecialistFilenames(overrideDir, bundledDir);
|
|
18313
18485
|
for (const filename of specialistNames) {
|
|
18314
|
-
const overridePath =
|
|
18315
|
-
const bundledPath =
|
|
18486
|
+
const overridePath = resolve24(overrideDir, filename);
|
|
18487
|
+
const bundledPath = resolve24(bundledDir, filename);
|
|
18316
18488
|
const row = await readAgentTemplateRow({
|
|
18317
18489
|
id: `agent-template:specialist:${filename}`,
|
|
18318
18490
|
displayName: filename.replace(/\.md$/, ""),
|
|
@@ -18594,7 +18766,7 @@ var session_usage_default = app33;
|
|
|
18594
18766
|
|
|
18595
18767
|
// server/routes/admin/session-rc-spawn.ts
|
|
18596
18768
|
import { randomUUID as randomUUID10 } from "crypto";
|
|
18597
|
-
var
|
|
18769
|
+
var ACCOUNT_UUID_RE3 = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
|
|
18598
18770
|
function resolveSpawnPlan(host, operatorDomains, body, mintId = randomUUID10, adminUserId, authenticatedName, callerAccountId) {
|
|
18599
18771
|
const operator = isOperatorHost(host, operatorDomains);
|
|
18600
18772
|
const resumeId = typeof body.sessionId === "string" && body.sessionId.length > 0 ? body.sessionId : void 0;
|
|
@@ -18605,8 +18777,8 @@ function resolveSpawnPlan(host, operatorDomains, body, mintId = randomUUID10, ad
|
|
|
18605
18777
|
const pickedModel = kind === "new" && typeof body.model === "string" && isSelectableModel(body.model) ? body.model : null;
|
|
18606
18778
|
const pickedEffort = kind === "new" && typeof body.effort === "string" && isNewSessionEffortLevel(body.effort) ? body.effort : null;
|
|
18607
18779
|
const paramsSource = pickedModel !== null && pickedEffort !== null ? "picker" : "default";
|
|
18608
|
-
const callerTargetAccountId = typeof callerAccountId === "string" &&
|
|
18609
|
-
const bodyTargetAccountId = typeof body.targetAccountId === "string" &&
|
|
18780
|
+
const callerTargetAccountId = typeof callerAccountId === "string" && ACCOUNT_UUID_RE3.test(callerAccountId) ? callerAccountId : void 0;
|
|
18781
|
+
const bodyTargetAccountId = typeof body.targetAccountId === "string" && ACCOUNT_UUID_RE3.test(body.targetAccountId) ? body.targetAccountId : void 0;
|
|
18610
18782
|
const targetAccountId = kind === "new" ? callerTargetAccountId : bodyTargetAccountId;
|
|
18611
18783
|
const payload = {};
|
|
18612
18784
|
let sessionId;
|
|
@@ -18957,24 +19129,24 @@ app36.get("/", async (c) => {
|
|
|
18957
19129
|
var system_stats_default = app36;
|
|
18958
19130
|
|
|
18959
19131
|
// server/routes/admin/health.ts
|
|
18960
|
-
import { existsSync as existsSync28, readFileSync as
|
|
18961
|
-
import { resolve as
|
|
18962
|
-
var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ??
|
|
19132
|
+
import { existsSync as existsSync28, readFileSync as readFileSync31 } from "fs";
|
|
19133
|
+
import { resolve as resolve25, join as join31 } from "path";
|
|
19134
|
+
var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve25(process.cwd(), "..");
|
|
18963
19135
|
var brandHostname = "maxy";
|
|
18964
|
-
var brandJsonPath =
|
|
19136
|
+
var brandJsonPath = join31(PLATFORM_ROOT6, "config", "brand.json");
|
|
18965
19137
|
if (existsSync28(brandJsonPath)) {
|
|
18966
19138
|
try {
|
|
18967
|
-
const brand = JSON.parse(
|
|
19139
|
+
const brand = JSON.parse(readFileSync31(brandJsonPath, "utf-8"));
|
|
18968
19140
|
if (brand.hostname) brandHostname = brand.hostname;
|
|
18969
19141
|
} catch {
|
|
18970
19142
|
}
|
|
18971
19143
|
}
|
|
18972
|
-
var VERSION_FILE =
|
|
19144
|
+
var VERSION_FILE = resolve25(PLATFORM_ROOT6, `config/.${brandHostname}-version`);
|
|
18973
19145
|
var PROCESS_STARTED_AT = (/* @__PURE__ */ new Date()).toISOString();
|
|
18974
19146
|
var PROBE_TIMEOUT_MS = 1e3;
|
|
18975
19147
|
function readVersion() {
|
|
18976
19148
|
if (!existsSync28(VERSION_FILE)) return "unknown";
|
|
18977
|
-
return
|
|
19149
|
+
return readFileSync31(VERSION_FILE, "utf-8").trim() || "unknown";
|
|
18978
19150
|
}
|
|
18979
19151
|
async function probeConversationDb() {
|
|
18980
19152
|
let session;
|
|
@@ -19751,7 +19923,7 @@ var browser_default = app44;
|
|
|
19751
19923
|
|
|
19752
19924
|
// server/routes/admin/calendar.ts
|
|
19753
19925
|
import { existsSync as existsSync29 } from "fs";
|
|
19754
|
-
import { join as
|
|
19926
|
+
import { join as join33 } from "path";
|
|
19755
19927
|
|
|
19756
19928
|
// server/lib/calendar-ics.ts
|
|
19757
19929
|
var CRLF = "\r\n";
|
|
@@ -19850,8 +20022,8 @@ function countVEvents(ics) {
|
|
|
19850
20022
|
}
|
|
19851
20023
|
|
|
19852
20024
|
// server/lib/calendar-availability.ts
|
|
19853
|
-
import { readFileSync as
|
|
19854
|
-
import { join as
|
|
20025
|
+
import { readFileSync as readFileSync32 } from "fs";
|
|
20026
|
+
import { join as join32 } from "path";
|
|
19855
20027
|
var AVAILABILITY_FILENAME = "calendar-availability.json";
|
|
19856
20028
|
var REQUIRED_KEYS = [
|
|
19857
20029
|
"timezone",
|
|
@@ -19860,10 +20032,10 @@ var REQUIRED_KEYS = [
|
|
|
19860
20032
|
"weekly"
|
|
19861
20033
|
];
|
|
19862
20034
|
function readAvailabilityConfig(accountDir) {
|
|
19863
|
-
const path2 =
|
|
20035
|
+
const path2 = join32(accountDir, AVAILABILITY_FILENAME);
|
|
19864
20036
|
let raw;
|
|
19865
20037
|
try {
|
|
19866
|
-
raw =
|
|
20038
|
+
raw = readFileSync32(path2, "utf-8");
|
|
19867
20039
|
} catch {
|
|
19868
20040
|
throw new Error(`availability not configured: ${path2} not found`);
|
|
19869
20041
|
}
|
|
@@ -20222,7 +20394,7 @@ app45.get("/booking-link", requireAdminSession, (c) => {
|
|
|
20222
20394
|
console.error('[calendar] op=booking-link-fail err="no account configured"');
|
|
20223
20395
|
return c.json({ bookingDomain: null });
|
|
20224
20396
|
}
|
|
20225
|
-
if (!existsSync29(
|
|
20397
|
+
if (!existsSync29(join33(account.accountDir, AVAILABILITY_FILENAME))) {
|
|
20226
20398
|
console.log("[calendar] op=booking-link bookingDomain=none source=availability-config");
|
|
20227
20399
|
return c.json({ bookingDomain: null });
|
|
20228
20400
|
}
|
|
@@ -20696,9 +20868,9 @@ var verify_token_default = app52;
|
|
|
20696
20868
|
|
|
20697
20869
|
// app/lib/access-email.ts
|
|
20698
20870
|
import { spawn as spawn2 } from "child_process";
|
|
20699
|
-
import { resolve as
|
|
20700
|
-
var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT ??
|
|
20701
|
-
var SEND_SCRIPT =
|
|
20871
|
+
import { resolve as resolve26 } from "path";
|
|
20872
|
+
var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT ?? resolve26(process.cwd(), "..");
|
|
20873
|
+
var SEND_SCRIPT = resolve26(
|
|
20702
20874
|
PLATFORM_ROOT7,
|
|
20703
20875
|
"plugins",
|
|
20704
20876
|
"email",
|
|
@@ -20840,8 +21012,8 @@ app54.route("/request-magic-link", request_magic_link_default);
|
|
|
20840
21012
|
var access_default = app54;
|
|
20841
21013
|
|
|
20842
21014
|
// server/routes/sites.ts
|
|
20843
|
-
import { existsSync as existsSync30, readFileSync as
|
|
20844
|
-
import { resolve as
|
|
21015
|
+
import { existsSync as existsSync30, readFileSync as readFileSync33, realpathSync as realpathSync6, statSync as statSync12 } from "fs";
|
|
21016
|
+
import { resolve as resolve27 } from "path";
|
|
20845
21017
|
var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
|
|
20846
21018
|
var MIME = {
|
|
20847
21019
|
".html": "text/html; charset=utf-8",
|
|
@@ -20898,8 +21070,8 @@ app55.get("/:rel{.*}", (c) => {
|
|
|
20898
21070
|
}
|
|
20899
21071
|
segments.push(seg);
|
|
20900
21072
|
}
|
|
20901
|
-
const rootDir =
|
|
20902
|
-
let filePath = segments.length === 0 ? rootDir :
|
|
21073
|
+
const rootDir = resolve27(account.accountDir, "sites");
|
|
21074
|
+
let filePath = segments.length === 0 ? rootDir : resolve27(rootDir, ...segments);
|
|
20903
21075
|
if (filePath !== rootDir && !filePath.startsWith(rootDir + "/")) {
|
|
20904
21076
|
console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
|
|
20905
21077
|
return c.text("Forbidden", 403);
|
|
@@ -20919,7 +21091,7 @@ app55.get("/:rel{.*}", (c) => {
|
|
|
20919
21091
|
return c.redirect(target, 301);
|
|
20920
21092
|
}
|
|
20921
21093
|
if (stat8?.isDirectory()) {
|
|
20922
|
-
filePath =
|
|
21094
|
+
filePath = resolve27(filePath, "index.html");
|
|
20923
21095
|
}
|
|
20924
21096
|
if (!filePath.startsWith(rootDir + "/")) {
|
|
20925
21097
|
console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
|
|
@@ -20944,7 +21116,7 @@ app55.get("/:rel{.*}", (c) => {
|
|
|
20944
21116
|
}
|
|
20945
21117
|
let body;
|
|
20946
21118
|
try {
|
|
20947
|
-
body =
|
|
21119
|
+
body = readFileSync33(realPath);
|
|
20948
21120
|
} catch (err) {
|
|
20949
21121
|
const code = err?.code;
|
|
20950
21122
|
if (code === "EISDIR") {
|
|
@@ -20980,7 +21152,7 @@ var sites_default = app55;
|
|
|
20980
21152
|
|
|
20981
21153
|
// app/lib/visitor-token.ts
|
|
20982
21154
|
import { createHmac, randomBytes, timingSafeEqual } from "crypto";
|
|
20983
|
-
import { mkdirSync as mkdirSync7, readFileSync as
|
|
21155
|
+
import { mkdirSync as mkdirSync7, readFileSync as readFileSync34, writeFileSync as writeFileSync11 } from "fs";
|
|
20984
21156
|
import { dirname as dirname11 } from "path";
|
|
20985
21157
|
var TOKEN_PREFIX = "v1.";
|
|
20986
21158
|
var SECRET_BYTES = 32;
|
|
@@ -20989,7 +21161,7 @@ var cachedSecret = null;
|
|
|
20989
21161
|
function getSecret() {
|
|
20990
21162
|
if (cachedSecret) return cachedSecret;
|
|
20991
21163
|
try {
|
|
20992
|
-
const hex2 =
|
|
21164
|
+
const hex2 = readFileSync34(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
|
|
20993
21165
|
if (hex2.length === SECRET_BYTES * 2) {
|
|
20994
21166
|
cachedSecret = Buffer.from(hex2, "hex");
|
|
20995
21167
|
return cachedSecret;
|
|
@@ -21003,7 +21175,7 @@ function getSecret() {
|
|
|
21003
21175
|
console.log(`[visitor-token] secret minted path=${VISITOR_TOKEN_SECRET_FILE}`);
|
|
21004
21176
|
} catch {
|
|
21005
21177
|
}
|
|
21006
|
-
const hex =
|
|
21178
|
+
const hex = readFileSync34(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
|
|
21007
21179
|
cachedSecret = Buffer.from(hex, "hex");
|
|
21008
21180
|
return cachedSecret;
|
|
21009
21181
|
}
|
|
@@ -21056,20 +21228,20 @@ var VISITOR_COOKIE_NAME = "mxy_v";
|
|
|
21056
21228
|
var VISITOR_COOKIE_MAX_AGE_SECONDS = Math.floor(DEFAULT_TTL_MS / 1e3);
|
|
21057
21229
|
|
|
21058
21230
|
// app/lib/brand-config.ts
|
|
21059
|
-
import { existsSync as existsSync31, readFileSync as
|
|
21060
|
-
import { join as
|
|
21061
|
-
var
|
|
21231
|
+
import { existsSync as existsSync31, readFileSync as readFileSync35 } from "fs";
|
|
21232
|
+
import { join as join34 } from "path";
|
|
21233
|
+
var cached2 = null;
|
|
21062
21234
|
var cachedAttempted = false;
|
|
21063
21235
|
function readBrandConfig() {
|
|
21064
|
-
if (cachedAttempted) return
|
|
21236
|
+
if (cachedAttempted) return cached2;
|
|
21065
21237
|
cachedAttempted = true;
|
|
21066
21238
|
const platformRoot3 = process.env.MAXY_PLATFORM_ROOT;
|
|
21067
21239
|
if (!platformRoot3) return null;
|
|
21068
|
-
const brandPath =
|
|
21240
|
+
const brandPath = join34(platformRoot3, "config", "brand.json");
|
|
21069
21241
|
if (!existsSync31(brandPath)) return null;
|
|
21070
21242
|
try {
|
|
21071
|
-
|
|
21072
|
-
return
|
|
21243
|
+
cached2 = JSON.parse(readFileSync35(brandPath, "utf-8"));
|
|
21244
|
+
return cached2;
|
|
21073
21245
|
} catch {
|
|
21074
21246
|
return null;
|
|
21075
21247
|
}
|
|
@@ -21556,14 +21728,14 @@ async function writeEvent(opts) {
|
|
|
21556
21728
|
var visitor_event_default = app58;
|
|
21557
21729
|
|
|
21558
21730
|
// server/routes/session.ts
|
|
21559
|
-
import { resolve as
|
|
21731
|
+
import { resolve as resolve28 } from "path";
|
|
21560
21732
|
import { existsSync as existsSync32, writeFileSync as writeFileSync12, mkdirSync as mkdirSync8 } from "fs";
|
|
21561
21733
|
var UUID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
21562
21734
|
function writeBrandingCache(accountId, agentSlug, branding) {
|
|
21563
21735
|
try {
|
|
21564
|
-
const cacheDir =
|
|
21736
|
+
const cacheDir = resolve28(MAXY_DIR, "branding-cache", accountId);
|
|
21565
21737
|
mkdirSync8(cacheDir, { recursive: true });
|
|
21566
|
-
writeFileSync12(
|
|
21738
|
+
writeFileSync12(resolve28(cacheDir, `${agentSlug}.json`), JSON.stringify(branding), "utf-8");
|
|
21567
21739
|
} catch (err) {
|
|
21568
21740
|
console.error(`[branding] cache write failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
21569
21741
|
}
|
|
@@ -21640,8 +21812,8 @@ app59.post("/", async (c) => {
|
|
|
21640
21812
|
}
|
|
21641
21813
|
let agentConfig = null;
|
|
21642
21814
|
if (account) {
|
|
21643
|
-
const agentDir =
|
|
21644
|
-
if (!existsSync32(agentDir) || !existsSync32(
|
|
21815
|
+
const agentDir = resolve28(account.accountDir, "agents", agentSlug);
|
|
21816
|
+
if (!existsSync32(agentDir) || !existsSync32(resolve28(agentDir, "config.json"))) {
|
|
21645
21817
|
return c.json({ error: "Agent not found" }, 404);
|
|
21646
21818
|
}
|
|
21647
21819
|
agentConfig = resolveAgentConfig(account.accountDir, agentSlug);
|
|
@@ -22087,8 +22259,8 @@ function startGraphHealthTimer() {
|
|
|
22087
22259
|
|
|
22088
22260
|
// app/lib/file-watcher.ts
|
|
22089
22261
|
import * as fsp2 from "fs/promises";
|
|
22090
|
-
import { resolve as
|
|
22091
|
-
var
|
|
22262
|
+
import { resolve as resolve29, sep as sep8 } from "path";
|
|
22263
|
+
var ACCOUNT_UUID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
22092
22264
|
var DEFAULT_COALESCE_MS = 500;
|
|
22093
22265
|
var ROOTS = ["accounts"];
|
|
22094
22266
|
function _routeEvent(rootName, filename) {
|
|
@@ -22096,7 +22268,7 @@ function _routeEvent(rootName, filename) {
|
|
|
22096
22268
|
const segs = filename.split(sep8).filter(Boolean);
|
|
22097
22269
|
if (segs.length < 2) return null;
|
|
22098
22270
|
const accountId = segs[0];
|
|
22099
|
-
if (!
|
|
22271
|
+
if (!ACCOUNT_UUID_RE4.test(accountId)) return null;
|
|
22100
22272
|
return { accountId, relativePath: `${rootName}/${segs.join("/")}` };
|
|
22101
22273
|
}
|
|
22102
22274
|
async function startFileWatcher(opts = {}) {
|
|
@@ -22106,7 +22278,7 @@ async function startFileWatcher(opts = {}) {
|
|
|
22106
22278
|
const dropFn = opts.drop ?? dropFileIndex;
|
|
22107
22279
|
for (const r of ROOTS) {
|
|
22108
22280
|
try {
|
|
22109
|
-
await fsp2.mkdir(
|
|
22281
|
+
await fsp2.mkdir(resolve29(dataRoot, r), { recursive: true });
|
|
22110
22282
|
} catch (err) {
|
|
22111
22283
|
console.error(
|
|
22112
22284
|
`[file-watcher] start-failed root="${r}" err="${err.message}" \u2014 index will be maintained by the 5-min reconcile backstop only`
|
|
@@ -22127,7 +22299,7 @@ async function startFileWatcher(opts = {}) {
|
|
|
22127
22299
|
timers.set(relativePath, t);
|
|
22128
22300
|
}
|
|
22129
22301
|
async function runHook(relativePath, accountId) {
|
|
22130
|
-
const absolute =
|
|
22302
|
+
const absolute = resolve29(dataRoot, relativePath);
|
|
22131
22303
|
let exists = false;
|
|
22132
22304
|
try {
|
|
22133
22305
|
const st = await fsp2.stat(absolute);
|
|
@@ -22151,7 +22323,7 @@ async function startFileWatcher(opts = {}) {
|
|
|
22151
22323
|
}
|
|
22152
22324
|
}
|
|
22153
22325
|
async function watchRoot(rootName) {
|
|
22154
|
-
const absRoot =
|
|
22326
|
+
const absRoot = resolve29(dataRoot, rootName);
|
|
22155
22327
|
try {
|
|
22156
22328
|
const iter = fsp2.watch(absRoot, { recursive: true, signal: controller.signal });
|
|
22157
22329
|
for await (const event of iter) {
|
|
@@ -22190,8 +22362,8 @@ async function startFileWatcher(opts = {}) {
|
|
|
22190
22362
|
|
|
22191
22363
|
// app/lib/migrate-uploads.ts
|
|
22192
22364
|
import { mkdir as mkdir5, readdir as readdir5, rename as rename2, rm as rm3 } from "fs/promises";
|
|
22193
|
-
import { dirname as dirname12, relative as relative6, resolve as
|
|
22194
|
-
var
|
|
22365
|
+
import { dirname as dirname12, relative as relative6, resolve as resolve30 } from "path";
|
|
22366
|
+
var ACCOUNT_UUID_RE5 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
22195
22367
|
async function walkFiles(dir) {
|
|
22196
22368
|
const out = [];
|
|
22197
22369
|
let entries;
|
|
@@ -22201,7 +22373,7 @@ async function walkFiles(dir) {
|
|
|
22201
22373
|
return out;
|
|
22202
22374
|
}
|
|
22203
22375
|
for (const e of entries) {
|
|
22204
|
-
const abs =
|
|
22376
|
+
const abs = resolve30(dir, e.name);
|
|
22205
22377
|
if (e.isDirectory()) {
|
|
22206
22378
|
out.push(...await walkFiles(abs));
|
|
22207
22379
|
} else if (e.isFile()) {
|
|
@@ -22221,7 +22393,7 @@ async function relocateTree(srcDir, destDir, dataRoot, accountId, session) {
|
|
|
22221
22393
|
let moved = 0;
|
|
22222
22394
|
for (const oldAbs of files) {
|
|
22223
22395
|
const suffix = relative6(srcDir, oldAbs);
|
|
22224
|
-
const newAbs =
|
|
22396
|
+
const newAbs = resolve30(destDir, suffix);
|
|
22225
22397
|
await mkdir5(dirname12(newAbs), { recursive: true });
|
|
22226
22398
|
await rename2(oldAbs, newAbs);
|
|
22227
22399
|
moved++;
|
|
@@ -22248,7 +22420,7 @@ async function relocateTree(srcDir, destDir, dataRoot, accountId, session) {
|
|
|
22248
22420
|
}
|
|
22249
22421
|
async function migrateUploads(opts = {}) {
|
|
22250
22422
|
const dataRoot = opts.dataRoot ?? DATA_ROOT;
|
|
22251
|
-
const oldRoot =
|
|
22423
|
+
const oldRoot = resolve30(dataRoot, "uploads");
|
|
22252
22424
|
let topEntries;
|
|
22253
22425
|
try {
|
|
22254
22426
|
topEntries = await readdir5(oldRoot, { withFileTypes: true });
|
|
@@ -22267,10 +22439,10 @@ async function migrateUploads(opts = {}) {
|
|
|
22267
22439
|
try {
|
|
22268
22440
|
for (const entry of topEntries) {
|
|
22269
22441
|
const name = entry.name;
|
|
22270
|
-
if (
|
|
22442
|
+
if (ACCOUNT_UUID_RE5.test(name)) {
|
|
22271
22443
|
moved += await relocateTree(
|
|
22272
|
-
|
|
22273
|
-
|
|
22444
|
+
resolve30(oldRoot, name),
|
|
22445
|
+
resolve30(dataRoot, "accounts", name, "uploads"),
|
|
22274
22446
|
dataRoot,
|
|
22275
22447
|
name,
|
|
22276
22448
|
session
|
|
@@ -22282,8 +22454,8 @@ async function migrateUploads(opts = {}) {
|
|
|
22282
22454
|
continue;
|
|
22283
22455
|
}
|
|
22284
22456
|
moved += await relocateTree(
|
|
22285
|
-
|
|
22286
|
-
|
|
22457
|
+
resolve30(oldRoot, "public"),
|
|
22458
|
+
resolve30(dataRoot, "accounts", installAccountId, "uploads", "public"),
|
|
22287
22459
|
dataRoot,
|
|
22288
22460
|
null,
|
|
22289
22461
|
// public uploads carry no graph nodes
|
|
@@ -22314,7 +22486,7 @@ async function migrateUploads(opts = {}) {
|
|
|
22314
22486
|
// app/lib/migrate-admin-webchat-sidecars.ts
|
|
22315
22487
|
import { readdir as readdir6, readFile as readFile6, rename as rename3, writeFile as writeFile4, unlink as unlink3 } from "fs/promises";
|
|
22316
22488
|
import { existsSync as existsSync33 } from "fs";
|
|
22317
|
-
import { join as
|
|
22489
|
+
import { join as join35 } from "path";
|
|
22318
22490
|
var ADMIN_ROLE2 = "admin";
|
|
22319
22491
|
var WEBCHAT_CHANNEL2 = "webchat";
|
|
22320
22492
|
var SESSION_META_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\.meta\.json$/i;
|
|
@@ -22359,7 +22531,7 @@ async function collectLiveSidecars(projectsRoot) {
|
|
|
22359
22531
|
}
|
|
22360
22532
|
for (const slug of slugs) {
|
|
22361
22533
|
if (!slug.isDirectory()) continue;
|
|
22362
|
-
const slugDir =
|
|
22534
|
+
const slugDir = join35(projectsRoot, slug.name);
|
|
22363
22535
|
let entries;
|
|
22364
22536
|
try {
|
|
22365
22537
|
entries = await readdir6(slugDir, { withFileTypes: true });
|
|
@@ -22368,9 +22540,9 @@ async function collectLiveSidecars(projectsRoot) {
|
|
|
22368
22540
|
}
|
|
22369
22541
|
for (const entry of entries) {
|
|
22370
22542
|
if (entry.isFile() && SESSION_META_RE.test(entry.name)) {
|
|
22371
|
-
out.push(
|
|
22543
|
+
out.push(join35(slugDir, entry.name));
|
|
22372
22544
|
} else if (entry.isDirectory() && entry.name === "subagents") {
|
|
22373
|
-
const subDir =
|
|
22545
|
+
const subDir = join35(slugDir, entry.name);
|
|
22374
22546
|
let subs;
|
|
22375
22547
|
try {
|
|
22376
22548
|
subs = await readdir6(subDir, { withFileTypes: true });
|
|
@@ -22378,7 +22550,7 @@ async function collectLiveSidecars(projectsRoot) {
|
|
|
22378
22550
|
continue;
|
|
22379
22551
|
}
|
|
22380
22552
|
for (const s of subs) {
|
|
22381
|
-
if (s.isFile() && SESSION_META_RE.test(s.name)) out.push(
|
|
22553
|
+
if (s.isFile() && SESSION_META_RE.test(s.name)) out.push(join35(subDir, s.name));
|
|
22382
22554
|
}
|
|
22383
22555
|
}
|
|
22384
22556
|
}
|
|
@@ -22390,7 +22562,7 @@ function shortId(path2) {
|
|
|
22390
22562
|
return base.slice(0, 8);
|
|
22391
22563
|
}
|
|
22392
22564
|
async function migrateAdminWebchatSidecars(opts = {}) {
|
|
22393
|
-
const projectsRoot = opts.projectsRoot ?? (process.env.CLAUDE_CONFIG_DIR ?
|
|
22565
|
+
const projectsRoot = opts.projectsRoot ?? (process.env.CLAUDE_CONFIG_DIR ? join35(process.env.CLAUDE_CONFIG_DIR, "projects") : null) ?? "";
|
|
22394
22566
|
const usersFile = opts.usersFile ?? USERS_FILE;
|
|
22395
22567
|
const accountId = opts.accountId ?? resolveAccount()?.accountId ?? null;
|
|
22396
22568
|
const resolveName = opts.resolveName ?? defaultResolveName;
|
|
@@ -23369,16 +23541,16 @@ var WebchatGateway = class _WebchatGateway {
|
|
|
23369
23541
|
* The public /api/chat route awaits this to return the reply on the same SSE
|
|
23370
23542
|
* response, preserving the pre-756 POST→single-blob browser contract. */
|
|
23371
23543
|
awaitReply(key, timeoutMs) {
|
|
23372
|
-
return new Promise((
|
|
23544
|
+
return new Promise((resolve35) => {
|
|
23373
23545
|
const timer2 = setTimeout(() => {
|
|
23374
23546
|
this.replyAwaiters.delete(key);
|
|
23375
|
-
|
|
23547
|
+
resolve35({ timeout: true });
|
|
23376
23548
|
}, timeoutMs);
|
|
23377
23549
|
if (timer2.unref) timer2.unref();
|
|
23378
23550
|
this.replyAwaiters.set(key, (r) => {
|
|
23379
23551
|
clearTimeout(timer2);
|
|
23380
23552
|
this.replyAwaiters.delete(key);
|
|
23381
|
-
|
|
23553
|
+
resolve35(r);
|
|
23382
23554
|
});
|
|
23383
23555
|
});
|
|
23384
23556
|
}
|
|
@@ -23389,11 +23561,11 @@ var WebchatGateway = class _WebchatGateway {
|
|
|
23389
23561
|
* terminal dialog stays answerable). */
|
|
23390
23562
|
awaitPermissionVerdict(p, timeoutMs) {
|
|
23391
23563
|
const k = _WebchatGateway.promptKey(p.key, p.requestId);
|
|
23392
|
-
return new Promise((
|
|
23564
|
+
return new Promise((resolve35) => {
|
|
23393
23565
|
this.pendingPrompts.get(k)?.resolve({ timeout: true });
|
|
23394
23566
|
const timer2 = setTimeout(() => {
|
|
23395
23567
|
this.pendingPrompts.delete(k);
|
|
23396
|
-
|
|
23568
|
+
resolve35({ timeout: true });
|
|
23397
23569
|
}, timeoutMs);
|
|
23398
23570
|
if (timer2.unref) timer2.unref();
|
|
23399
23571
|
this.pendingPrompts.set(k, {
|
|
@@ -23402,7 +23574,7 @@ var WebchatGateway = class _WebchatGateway {
|
|
|
23402
23574
|
resolve: (r) => {
|
|
23403
23575
|
clearTimeout(timer2);
|
|
23404
23576
|
this.pendingPrompts.delete(k);
|
|
23405
|
-
|
|
23577
|
+
resolve35(r);
|
|
23406
23578
|
}
|
|
23407
23579
|
});
|
|
23408
23580
|
console.error(`[webchat:perm] op=open key=${keyDisplay(p.key)} id=${p.requestId} tool=${p.toolName}`);
|
|
@@ -24398,7 +24570,7 @@ function buildTelegramSpawnRequest(input) {
|
|
|
24398
24570
|
// app/lib/telegram/outbound/send-document.ts
|
|
24399
24571
|
import { realpathSync as realpathSync7 } from "fs";
|
|
24400
24572
|
import { readFile as readFile7, stat as stat7 } from "fs/promises";
|
|
24401
|
-
import { resolve as
|
|
24573
|
+
import { resolve as resolve31, basename as basename11 } from "path";
|
|
24402
24574
|
var TAG42 = "[telegram:outbound]";
|
|
24403
24575
|
var TELEGRAM_DOCUMENT_MAX_BYTES = 50 * 1024 * 1024;
|
|
24404
24576
|
async function sendTelegramDocument(input) {
|
|
@@ -24409,7 +24581,7 @@ async function sendTelegramDocument(input) {
|
|
|
24409
24581
|
if (!maxyAccountId || !platformRoot3) {
|
|
24410
24582
|
return { ok: false, status: 400, error: "Cannot validate file path: missing account or platform context" };
|
|
24411
24583
|
}
|
|
24412
|
-
const accountDir =
|
|
24584
|
+
const accountDir = resolve31(platformRoot3, "..", "data/accounts", maxyAccountId);
|
|
24413
24585
|
let resolvedPath;
|
|
24414
24586
|
try {
|
|
24415
24587
|
resolvedPath = realpathSync7(filePath);
|
|
@@ -24536,12 +24708,12 @@ function startTelegramNativeFileFollower(input) {
|
|
|
24536
24708
|
}
|
|
24537
24709
|
|
|
24538
24710
|
// server/telegram-descriptor.ts
|
|
24539
|
-
import { resolve as
|
|
24711
|
+
import { resolve as resolve32, join as join36 } from "path";
|
|
24540
24712
|
function telegramGatewayUrl() {
|
|
24541
24713
|
return `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`;
|
|
24542
24714
|
}
|
|
24543
24715
|
function telegramServerPath() {
|
|
24544
|
-
return process.env.MAXY_TELEGRAM_CHANNEL_SERVER_PATH ??
|
|
24716
|
+
return process.env.MAXY_TELEGRAM_CHANNEL_SERVER_PATH ?? resolve32(process.env.MAXY_PLATFORM_ROOT ?? join36(__dirname, ".."), "services/telegram-channel/dist/server.js");
|
|
24545
24717
|
}
|
|
24546
24718
|
|
|
24547
24719
|
// app/lib/channel-pty-bridge/public-session-end-review.ts
|
|
@@ -24803,8 +24975,8 @@ function broadcastAdminShutdown(reason) {
|
|
|
24803
24975
|
|
|
24804
24976
|
// ../lib/entitlement/src/index.ts
|
|
24805
24977
|
import { createPublicKey, createHash as createHash6, verify as cryptoVerify } from "crypto";
|
|
24806
|
-
import { existsSync as existsSync34, readFileSync as
|
|
24807
|
-
import { resolve as
|
|
24978
|
+
import { existsSync as existsSync34, readFileSync as readFileSync36, statSync as statSync13 } from "fs";
|
|
24979
|
+
import { resolve as resolve33 } from "path";
|
|
24808
24980
|
|
|
24809
24981
|
// ../lib/entitlement/src/canonicalize.ts
|
|
24810
24982
|
function canonicalize(value) {
|
|
@@ -24839,7 +25011,7 @@ var PUBKEY_SHA256 = "8eee6bcb33545fd13b16d3199a5735ca5db5062834c7b49dfe4f23801d9
|
|
|
24839
25011
|
var GRACE_DAYS = 7;
|
|
24840
25012
|
var GRACE_MS = GRACE_DAYS * 24 * 60 * 60 * 1e3;
|
|
24841
25013
|
function pubkeyPath(brand) {
|
|
24842
|
-
return
|
|
25014
|
+
return resolve33(brand.platformRoot, "lib", "entitlement", "rubytech-pubkey.pem");
|
|
24843
25015
|
}
|
|
24844
25016
|
var memo = null;
|
|
24845
25017
|
function memoKey(mtimeMs, account) {
|
|
@@ -24851,7 +25023,7 @@ function resolveEntitlement(brand, account) {
|
|
|
24851
25023
|
if (brand.commercialMode !== true) {
|
|
24852
25024
|
return logResolved(implicitTrust(account), null);
|
|
24853
25025
|
}
|
|
24854
|
-
const entitlementPath =
|
|
25026
|
+
const entitlementPath = resolve33(brand.configDir, "entitlement.json");
|
|
24855
25027
|
if (!existsSync34(entitlementPath)) {
|
|
24856
25028
|
return logResolved(anonymousFallback("missing"), { reason: "missing" });
|
|
24857
25029
|
}
|
|
@@ -24867,7 +25039,7 @@ function resolveEntitlement(brand, account) {
|
|
|
24867
25039
|
function verifyAndResolve(brand, entitlementPath, account) {
|
|
24868
25040
|
let pubkeyPem;
|
|
24869
25041
|
try {
|
|
24870
|
-
pubkeyPem =
|
|
25042
|
+
pubkeyPem = readFileSync36(pubkeyPath(brand), "utf-8");
|
|
24871
25043
|
} catch (err) {
|
|
24872
25044
|
return logResolved(anonymousFallback("pubkey-missing"), {
|
|
24873
25045
|
reason: "pubkey-missing"
|
|
@@ -24881,7 +25053,7 @@ function verifyAndResolve(brand, entitlementPath, account) {
|
|
|
24881
25053
|
}
|
|
24882
25054
|
let envelope;
|
|
24883
25055
|
try {
|
|
24884
|
-
envelope = JSON.parse(
|
|
25056
|
+
envelope = JSON.parse(readFileSync36(entitlementPath, "utf-8"));
|
|
24885
25057
|
} catch {
|
|
24886
25058
|
return logResolved(anonymousFallback("malformed"), { reason: "malformed" });
|
|
24887
25059
|
}
|
|
@@ -25042,14 +25214,14 @@ function clientFrom(c) {
|
|
|
25042
25214
|
);
|
|
25043
25215
|
}
|
|
25044
25216
|
var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT || "";
|
|
25045
|
-
var BRAND_JSON_PATH = PLATFORM_ROOT8 ?
|
|
25217
|
+
var BRAND_JSON_PATH = PLATFORM_ROOT8 ? join37(PLATFORM_ROOT8, "config", "brand.json") : "";
|
|
25046
25218
|
var BRAND = { productName: "Maxy", hostname: "maxy", configDir: ".maxy", marketingUrl: "https://getmaxy.com" };
|
|
25047
25219
|
if (BRAND_JSON_PATH && !existsSync35(BRAND_JSON_PATH)) {
|
|
25048
25220
|
console.error(`[brand] WARNING: brand.json not found at ${BRAND_JSON_PATH} \u2014 using Maxy defaults`);
|
|
25049
25221
|
}
|
|
25050
25222
|
if (BRAND_JSON_PATH && existsSync35(BRAND_JSON_PATH)) {
|
|
25051
25223
|
try {
|
|
25052
|
-
const parsed = JSON.parse(
|
|
25224
|
+
const parsed = JSON.parse(readFileSync37(BRAND_JSON_PATH, "utf-8"));
|
|
25053
25225
|
BRAND = { ...BRAND, ...parsed };
|
|
25054
25226
|
} catch (err) {
|
|
25055
25227
|
console.error(`[brand] Failed to parse brand.json: ${err.message}`);
|
|
@@ -25081,11 +25253,11 @@ var brandLoginOpts = {
|
|
|
25081
25253
|
appleTouchIconPath: brandAppIcon512Path,
|
|
25082
25254
|
themeColor: BRAND.defaultColors?.primary
|
|
25083
25255
|
};
|
|
25084
|
-
var ALIAS_DOMAINS_PATH =
|
|
25256
|
+
var ALIAS_DOMAINS_PATH = join37(homedir4(), BRAND.configDir, "alias-domains.json");
|
|
25085
25257
|
function loadAliasDomains() {
|
|
25086
25258
|
try {
|
|
25087
25259
|
if (!existsSync35(ALIAS_DOMAINS_PATH)) return null;
|
|
25088
|
-
const parsed = JSON.parse(
|
|
25260
|
+
const parsed = JSON.parse(readFileSync37(ALIAS_DOMAINS_PATH, "utf-8"));
|
|
25089
25261
|
if (!Array.isArray(parsed)) {
|
|
25090
25262
|
console.error("[alias-domains] malformed alias-domains.json \u2014 expected array");
|
|
25091
25263
|
return null;
|
|
@@ -25148,7 +25320,7 @@ async function recordPassiveDispatch(input) {
|
|
|
25148
25320
|
var waGateway = new WaGateway({
|
|
25149
25321
|
fetchStandingRules: fetchAccountStandingRules,
|
|
25150
25322
|
gatewayUrl: `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`,
|
|
25151
|
-
serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ??
|
|
25323
|
+
serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve34(process.env.MAXY_PLATFORM_ROOT ?? join37(__dirname, ".."), "services/whatsapp-channel/dist/server.js"),
|
|
25152
25324
|
// Task 751 / 1390 — file delivery on the native channel. `maxyAccountId` (the
|
|
25153
25325
|
// path-validation scope) is the sender's effective SESSION account, resolved
|
|
25154
25326
|
// once at the inbound gate and threaded here via the gateway's per-sender doc
|
|
@@ -25163,7 +25335,7 @@ var waGateway = new WaGateway({
|
|
|
25163
25335
|
caption,
|
|
25164
25336
|
accountId,
|
|
25165
25337
|
maxyAccountId,
|
|
25166
|
-
platformRoot:
|
|
25338
|
+
platformRoot: resolve34(process.env.MAXY_PLATFORM_ROOT ?? join37(__dirname, ".."))
|
|
25167
25339
|
});
|
|
25168
25340
|
return result.ok ? { ok: true, messageId: result.messageId } : { ok: false, error: result.error };
|
|
25169
25341
|
},
|
|
@@ -25761,8 +25933,8 @@ app61.get("/agent-assets/:slug/:filename", (c) => {
|
|
|
25761
25933
|
console.error(`[agent-assets] no-account slug=${slug} file=${filename}`);
|
|
25762
25934
|
return c.text("Not found", 404);
|
|
25763
25935
|
}
|
|
25764
|
-
const filePath =
|
|
25765
|
-
const expectedDir =
|
|
25936
|
+
const filePath = resolve34(account.accountDir, "agents", slug, "assets", filename);
|
|
25937
|
+
const expectedDir = resolve34(account.accountDir, "agents", slug, "assets");
|
|
25766
25938
|
if (!filePath.startsWith(expectedDir + "/")) {
|
|
25767
25939
|
console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
|
|
25768
25940
|
return c.text("Forbidden", 403);
|
|
@@ -25774,7 +25946,7 @@ app61.get("/agent-assets/:slug/:filename", (c) => {
|
|
|
25774
25946
|
const ext = "." + filename.split(".").pop()?.toLowerCase();
|
|
25775
25947
|
const contentType = IMAGE_MIME[ext] || "application/octet-stream";
|
|
25776
25948
|
console.log(`[agent-assets] serve slug=${slug} file=${filename} status=200`);
|
|
25777
|
-
const body =
|
|
25949
|
+
const body = readFileSync37(filePath);
|
|
25778
25950
|
return c.body(body, 200, {
|
|
25779
25951
|
"Content-Type": contentType,
|
|
25780
25952
|
"Cache-Control": "public, max-age=3600"
|
|
@@ -25791,8 +25963,8 @@ app61.get("/generated/:filename", (c) => {
|
|
|
25791
25963
|
console.error(`[generated] serve file=${filename} status=404`);
|
|
25792
25964
|
return c.text("Not found", 404);
|
|
25793
25965
|
}
|
|
25794
|
-
const filePath =
|
|
25795
|
-
const expectedDir =
|
|
25966
|
+
const filePath = resolve34(account.accountDir, "generated", filename);
|
|
25967
|
+
const expectedDir = resolve34(account.accountDir, "generated");
|
|
25796
25968
|
if (!filePath.startsWith(expectedDir + "/")) {
|
|
25797
25969
|
console.error(`[generated] serve file=${filename} status=403`);
|
|
25798
25970
|
return c.text("Forbidden", 403);
|
|
@@ -25804,7 +25976,7 @@ app61.get("/generated/:filename", (c) => {
|
|
|
25804
25976
|
const ext = "." + filename.split(".").pop()?.toLowerCase();
|
|
25805
25977
|
const contentType = IMAGE_MIME[ext] || "application/octet-stream";
|
|
25806
25978
|
console.log(`[generated] serve file=${filename} status=200`);
|
|
25807
|
-
const body =
|
|
25979
|
+
const body = readFileSync37(filePath);
|
|
25808
25980
|
return c.body(body, 200, {
|
|
25809
25981
|
"Content-Type": contentType,
|
|
25810
25982
|
"Cache-Control": "public, max-age=86400"
|
|
@@ -25819,7 +25991,7 @@ var brandLogoPath = "/brand/maxy-monochrome.png";
|
|
|
25819
25991
|
var brandIconPath = "/brand/maxy-monochrome.png";
|
|
25820
25992
|
if (BRAND_JSON_PATH && existsSync35(BRAND_JSON_PATH)) {
|
|
25821
25993
|
try {
|
|
25822
|
-
const fullBrand = JSON.parse(
|
|
25994
|
+
const fullBrand = JSON.parse(readFileSync37(BRAND_JSON_PATH, "utf-8"));
|
|
25823
25995
|
if (fullBrand.assets?.logo) brandLogoPath = `/brand/${fullBrand.assets.logo}`;
|
|
25824
25996
|
brandIconPath = fullBrand.assets?.icon ? `/brand/${fullBrand.assets.icon}` : brandLogoPath;
|
|
25825
25997
|
} catch {
|
|
@@ -25846,11 +26018,11 @@ var brandScript = `<script>window.__BRAND__=${JSON.stringify({
|
|
|
25846
26018
|
var brandThemeColor = BRAND.defaultColors?.primary ?? "#000000";
|
|
25847
26019
|
var brandBackgroundColor = BRAND.defaultColors?.background ?? "#ffffff";
|
|
25848
26020
|
var brandAppIconsExist = [brandAppIcon192Path, brandAppIcon512Path, brandMaskableIconPath].every(
|
|
25849
|
-
(p) => existsSync35(
|
|
26021
|
+
(p) => existsSync35(resolve34(process.cwd(), "public", p.replace(/^\//, "")))
|
|
25850
26022
|
);
|
|
25851
26023
|
var SW_SOURCE = (() => {
|
|
25852
26024
|
try {
|
|
25853
|
-
return
|
|
26025
|
+
return readFileSync37(resolve34(process.cwd(), "public", "sw.js"), "utf-8");
|
|
25854
26026
|
} catch {
|
|
25855
26027
|
return null;
|
|
25856
26028
|
}
|
|
@@ -25858,9 +26030,9 @@ var SW_SOURCE = (() => {
|
|
|
25858
26030
|
function readInstalledVersion() {
|
|
25859
26031
|
try {
|
|
25860
26032
|
if (!PLATFORM_ROOT8) return "unknown";
|
|
25861
|
-
const versionFile =
|
|
26033
|
+
const versionFile = join37(PLATFORM_ROOT8, "config", `.${BRAND.hostname}-version`);
|
|
25862
26034
|
if (!existsSync35(versionFile)) return "unknown";
|
|
25863
|
-
const content =
|
|
26035
|
+
const content = readFileSync37(versionFile, "utf-8").trim();
|
|
25864
26036
|
return content || "unknown";
|
|
25865
26037
|
} catch {
|
|
25866
26038
|
return "unknown";
|
|
@@ -25901,7 +26073,7 @@ var clientErrorReporterScript = `<script>
|
|
|
25901
26073
|
function cachedHtml(file) {
|
|
25902
26074
|
let html = htmlCache.get(file);
|
|
25903
26075
|
if (!html) {
|
|
25904
|
-
html =
|
|
26076
|
+
html = readFileSync37(resolve34(process.cwd(), "public", file), "utf-8");
|
|
25905
26077
|
const productNameEsc = escapeHtml(BRAND.productName);
|
|
25906
26078
|
html = html.replace(/<title>([^<]*)<\/title>/, (_match, inner) => `<title>${escapeHtml(inner).replace(/Maxy/g, productNameEsc)}</title>`);
|
|
25907
26079
|
html = html.replace('href="/favicon.ico"', `href="${escapeHtml(brandFaviconPath)}"`);
|
|
@@ -25918,13 +26090,13 @@ ${clientErrorReporterScript}
|
|
|
25918
26090
|
return html;
|
|
25919
26091
|
}
|
|
25920
26092
|
function loadBrandingCache(agentSlug) {
|
|
25921
|
-
const configDir2 =
|
|
26093
|
+
const configDir2 = join37(homedir4(), BRAND.configDir);
|
|
25922
26094
|
try {
|
|
25923
26095
|
const accountId = getDefaultAccountId();
|
|
25924
26096
|
if (!accountId) return null;
|
|
25925
|
-
const cachePath =
|
|
26097
|
+
const cachePath = join37(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
|
|
25926
26098
|
if (!existsSync35(cachePath)) return null;
|
|
25927
|
-
return JSON.parse(
|
|
26099
|
+
return JSON.parse(readFileSync37(cachePath, "utf-8"));
|
|
25928
26100
|
} catch {
|
|
25929
26101
|
return null;
|
|
25930
26102
|
}
|
|
@@ -25941,11 +26113,11 @@ var brandedHtmlCache = /* @__PURE__ */ new Map();
|
|
|
25941
26113
|
function brandedPublicHtml(agentSlug) {
|
|
25942
26114
|
const baseHtml = cachedHtml("public.html");
|
|
25943
26115
|
if (!agentSlug) return baseHtml;
|
|
25944
|
-
const
|
|
26116
|
+
const cached3 = brandedHtmlCache.get(agentSlug);
|
|
25945
26117
|
const branding = loadBrandingCache(agentSlug);
|
|
25946
26118
|
if (!branding) return baseHtml;
|
|
25947
26119
|
const brandHash = JSON.stringify(branding).length;
|
|
25948
|
-
if (
|
|
26120
|
+
if (cached3 && cached3.mtime === brandHash) return cached3.html;
|
|
25949
26121
|
const title = escapeHtml(branding.name);
|
|
25950
26122
|
const description = branding.tagline ? escapeHtml(branding.tagline) : "";
|
|
25951
26123
|
const themeColor = branding.primaryColor || "";
|
|
@@ -26019,7 +26191,7 @@ app61.use("/vnc-popout.html", logViewerFetch);
|
|
|
26019
26191
|
app61.get("/vnc-popout.html", (c) => {
|
|
26020
26192
|
let html = htmlCache.get("vnc-popout.html");
|
|
26021
26193
|
if (!html) {
|
|
26022
|
-
html =
|
|
26194
|
+
html = readFileSync37(resolve34(process.cwd(), "public", "vnc-popout.html"), "utf-8");
|
|
26023
26195
|
const name = escapeHtml(BRAND.productName);
|
|
26024
26196
|
html = html.replace("<title>Browser \u2014 Maxy</title>", `<title>${name}</title>`);
|
|
26025
26197
|
html = html.replace("</head>", ` ${brandScript}
|
|
@@ -26151,8 +26323,8 @@ var hostname = process.env.HOSTNAME ?? "127.0.0.1";
|
|
|
26151
26323
|
var httpServer = serve({ fetch: app61.fetch, port, hostname });
|
|
26152
26324
|
console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
26153
26325
|
{
|
|
26154
|
-
const reconcilePlatformRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
26155
|
-
const reconcileScript =
|
|
26326
|
+
const reconcilePlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join37(__dirname, "..");
|
|
26327
|
+
const reconcileScript = resolve34(reconcilePlatformRoot, "plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js");
|
|
26156
26328
|
const RECONCILE_INTERVAL_MS = 12e4;
|
|
26157
26329
|
const runReconcile = () => {
|
|
26158
26330
|
if (!existsSync35(reconcileScript)) return;
|
|
@@ -26173,8 +26345,8 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
26173
26345
|
loop.unref();
|
|
26174
26346
|
}
|
|
26175
26347
|
{
|
|
26176
|
-
const publishPlatformRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
26177
|
-
const publishScript =
|
|
26348
|
+
const publishPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join37(__dirname, "..");
|
|
26349
|
+
const publishScript = resolve34(publishPlatformRoot, "plugins/scheduling/mcp/dist/scripts/publish-availability.js");
|
|
26178
26350
|
const PUBLISH_INTERVAL_MS = 3e5;
|
|
26179
26351
|
const currentAccount = () => {
|
|
26180
26352
|
try {
|
|
@@ -26203,21 +26375,21 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
26203
26375
|
}
|
|
26204
26376
|
};
|
|
26205
26377
|
const auditSnapshotAge = (account) => {
|
|
26206
|
-
const availPath =
|
|
26378
|
+
const availPath = resolve34(account.accountDir, "calendar-availability.json");
|
|
26207
26379
|
let hasBookingSite = false;
|
|
26208
26380
|
try {
|
|
26209
26381
|
if (existsSync35(availPath)) {
|
|
26210
|
-
const cfg = JSON.parse(
|
|
26382
|
+
const cfg = JSON.parse(readFileSync37(availPath, "utf-8"));
|
|
26211
26383
|
hasBookingSite = typeof cfg.bookingDbName === "string" && cfg.bookingDbName.length > 0;
|
|
26212
26384
|
}
|
|
26213
26385
|
} catch {
|
|
26214
26386
|
}
|
|
26215
26387
|
if (!hasBookingSite) return;
|
|
26216
|
-
const statePath =
|
|
26388
|
+
const statePath = resolve34(account.accountDir, "state", "booking-availability", "last-publish.json");
|
|
26217
26389
|
let lastSuccessAt = null;
|
|
26218
26390
|
if (existsSync35(statePath)) {
|
|
26219
26391
|
try {
|
|
26220
|
-
const rec = JSON.parse(
|
|
26392
|
+
const rec = JSON.parse(readFileSync37(statePath, "utf-8"));
|
|
26221
26393
|
lastSuccessAt = rec.lastSuccessAt ?? null;
|
|
26222
26394
|
} catch {
|
|
26223
26395
|
console.error(`[calendar-availability] op=audit accountId=${account.accountId} snapshotAgeMs=na reason=bad-state-file`);
|
|
@@ -26241,8 +26413,8 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
26241
26413
|
}
|
|
26242
26414
|
startTimeEntryCensus(() => getSession());
|
|
26243
26415
|
{
|
|
26244
|
-
const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
26245
|
-
const auditScript =
|
|
26416
|
+
const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join37(__dirname, "..");
|
|
26417
|
+
const auditScript = resolve34(auditPlatformRoot, "plugins/connector/mcp/dist/scripts/audit-connectors.js");
|
|
26246
26418
|
const auditLogDir = process.env.LOG_DIR ?? LOG_DIR;
|
|
26247
26419
|
const CONNECTOR_AUDIT_INTERVAL_MS = 3e5;
|
|
26248
26420
|
const runConnectorAudit = () => {
|
|
@@ -26360,7 +26532,7 @@ async function runAdminUserReconcileTick() {
|
|
|
26360
26532
|
console.error("[adminuser-self-heal] skip reason=no-users-file");
|
|
26361
26533
|
return;
|
|
26362
26534
|
}
|
|
26363
|
-
const usersRaw =
|
|
26535
|
+
const usersRaw = readFileSync37(USERS_FILE, "utf-8").trim();
|
|
26364
26536
|
if (!usersRaw) {
|
|
26365
26537
|
console.error("[adminuser-self-heal] skip reason=empty-users-file");
|
|
26366
26538
|
return;
|
|
@@ -26390,7 +26562,7 @@ if (typeof adminUserReconcileTimer.unref === "function") adminUserReconcileTimer
|
|
|
26390
26562
|
var USERS_RECONCILE_INTERVAL_MS = 60 * 60 * 1e3;
|
|
26391
26563
|
function countUsersRows() {
|
|
26392
26564
|
if (!existsSync35(USERS_FILE)) return 0;
|
|
26393
|
-
const raw =
|
|
26565
|
+
const raw = readFileSync37(USERS_FILE, "utf-8").trim();
|
|
26394
26566
|
if (!raw) return 0;
|
|
26395
26567
|
const users = JSON.parse(raw);
|
|
26396
26568
|
return users.filter((u) => typeof u.userId === "string").length;
|
|
@@ -26510,7 +26682,7 @@ if (bootAccountConfig?.whatsapp) {
|
|
|
26510
26682
|
}
|
|
26511
26683
|
init({
|
|
26512
26684
|
configDir: configDirForWhatsApp,
|
|
26513
|
-
platformRoot:
|
|
26685
|
+
platformRoot: resolve34(process.env.MAXY_PLATFORM_ROOT ?? join37(__dirname, "..")),
|
|
26514
26686
|
accountConfig: bootAccountConfig,
|
|
26515
26687
|
onMessage: async (msg) => {
|
|
26516
26688
|
if (msg.isOwnerMirror) {
|