@rubytech/create-maxy-code 0.1.485 → 0.1.487
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/docs/superpowers/plans/2026-07-21-graph-caption-resolver.md +124 -0
- package/payload/platform/docs/superpowers/plans/2026-07-21-task-1877-bash-schema-enforcement.md +107 -0
- package/payload/platform/docs/superpowers/plans/2026-07-21-task-1887-reconcile-allowed-top-level.md +205 -0
- package/payload/platform/lib/graph-style/dist/index.d.ts +4 -1
- package/payload/platform/lib/graph-style/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/graph-style/dist/index.js +109 -1
- package/payload/platform/lib/graph-style/dist/index.js.map +1 -1
- package/payload/platform/lib/graph-style/src/__tests__/caption-coverage.test.ts +117 -0
- package/payload/platform/lib/graph-style/src/index.ts +81 -1
- package/payload/platform/plugins/admin/hooks/__tests__/fs-schema-guard-bash.test.sh +159 -0
- package/payload/platform/plugins/admin/hooks/__tests__/fs-schema-guard.test.sh +18 -6
- package/payload/platform/plugins/admin/hooks/fs-schema-guard-bash-post.sh +141 -0
- package/payload/platform/plugins/admin/hooks/fs-schema-guard-bash-pre.sh +66 -0
- package/payload/platform/plugins/admin/hooks/fs-schema-guard.sh +33 -1
- package/payload/platform/plugins/admin/skills/professional-document/SKILL.md +3 -3
- package/payload/platform/plugins/cloudflare/PLUGIN.md +5 -3
- package/payload/platform/plugins/cloudflare/bin/portal-enrol.mjs +23 -2
- package/payload/platform/plugins/cloudflare/bin/portal-index-push.mjs +30 -8
- package/payload/platform/plugins/cloudflare/bin/schema-exposed-dirs.mjs +22 -2
- package/payload/platform/plugins/cloudflare/mcp/__tests__/authorize.test.ts +2 -2
- package/payload/platform/plugins/cloudflare/mcp/__tests__/portal-directory-listing.test.ts +49 -2
- package/payload/platform/plugins/cloudflare/mcp/__tests__/portal-enrol.test.ts +57 -3
- package/payload/platform/plugins/cloudflare/mcp/__tests__/portal-index-push.test.ts +23 -0
- package/payload/platform/plugins/cloudflare/mcp/__tests__/portal-indexed-download.test.ts +44 -2
- package/payload/platform/plugins/cloudflare/mcp/__tests__/portal-session-grant.test.ts +67 -0
- package/payload/platform/plugins/cloudflare/mcp/__tests__/schema-exposed-dirs.test.ts +43 -0
- package/payload/platform/plugins/cloudflare/skills/data-portal/SKILL.md +54 -5
- package/payload/platform/plugins/cloudflare/skills/data-portal/schema.sql +10 -1
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/functions/api/_lib/session.ts +19 -5
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/functions/api/download.ts +19 -2
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/functions/api/files.ts +8 -2
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/index.html +28 -5
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/portal.css +195 -6
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/portal.js +193 -10
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/wrangler.toml +4 -3
- package/payload/platform/plugins/email/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/email/PLUGIN.md +5 -1
- package/payload/platform/plugins/email/mcp/dist/__tests__/attachment-select.test.d.ts +2 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/attachment-select.test.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/attachment-select.test.js +50 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/attachment-select.test.js.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/attachment-text.test.d.ts +2 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/attachment-text.test.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/attachment-text.test.js +51 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/attachment-text.test.js.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/email-fetch-attachment.test.d.ts +2 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/email-fetch-attachment.test.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/email-fetch-attachment.test.js +89 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/email-fetch-attachment.test.js.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/index.js +28 -0
- package/payload/platform/plugins/email/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/lib/attachment-text.d.ts +22 -0
- package/payload/platform/plugins/email/mcp/dist/lib/attachment-text.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/lib/attachment-text.js +55 -0
- package/payload/platform/plugins/email/mcp/dist/lib/attachment-text.js.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/lib/imap.d.ts +32 -0
- package/payload/platform/plugins/email/mcp/dist/lib/imap.d.ts.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/lib/imap.js +75 -1
- package/payload/platform/plugins/email/mcp/dist/lib/imap.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-fetch-attachment.d.ts +19 -0
- package/payload/platform/plugins/email/mcp/dist/tools/email-fetch-attachment.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/tools/email-fetch-attachment.js +49 -0
- package/payload/platform/plugins/email/mcp/dist/tools/email-fetch-attachment.js.map +1 -0
- package/payload/platform/plugins/email/references/email-reference.md +7 -1
- package/payload/platform/plugins/memory/references/schema-construction.md +18 -12
- package/payload/platform/plugins/memory/references/schema-estate-agent.md +11 -6
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/free-busy-url.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/free-busy-url.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/free-busy-url.test.js +12 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/free-busy-url.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/free-busy-url.d.ts +8 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/free-busy-url.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/free-busy-url.js +12 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/free-busy-url.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/publish-availability.js +12 -2
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/publish-availability.js.map +1 -1
- package/payload/platform/scripts/__tests__/account-schema-owned-dirs.test.sh +75 -6
- package/payload/platform/scripts/lib/account-schema-owned-dirs.py +111 -22
- package/payload/platform/scripts/lib/provision-account-dir.sh +8 -1
- package/payload/platform/services/claude-session-manager/dist/account-dir-schema-reconcile.d.ts +39 -0
- package/payload/platform/services/claude-session-manager/dist/account-dir-schema-reconcile.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/account-dir-schema-reconcile.js +315 -0
- package/payload/platform/services/claude-session-manager/dist/account-dir-schema-reconcile.js.map +1 -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 +1 -0
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/index.js +15 -0
- package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/system-prompt.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/system-prompt.js +4 -0
- package/payload/platform/services/claude-session-manager/dist/system-prompt.js.map +1 -1
- package/payload/platform/templates/account-schema/SCHEMA.md +17 -0
- package/payload/platform/templates/specialists/agents/personal-assistant.md +1 -1
- package/payload/server/{chunk-XGNRSM57.js → chunk-HN4HFTXE.js} +6 -0
- package/payload/server/maxy-edge.js +1 -1
- package/payload/server/public/assets/{admin-rScqRq-R.js → admin-BoVCP4Mw.js} +1 -1
- package/payload/server/public/assets/{data-TOWuhMFb.js → data-CtOxa94P.js} +1 -1
- package/payload/server/public/assets/{graph-labels-Axa04w8A.js → graph-labels-C8-sIKuv.js} +1 -1
- package/payload/server/public/assets/{graph-BEGs_P2m.js → graph-mJ9ky5dc.js} +1 -1
- package/payload/server/public/assets/{page-6CZ8R57f.js → page-Cv0qUwMG.js} +1 -1
- package/payload/server/public/data.html +3 -3
- package/payload/server/public/graph.html +2 -2
- package/payload/server/public/index.html +3 -3
- package/payload/server/server.js +231 -103
package/payload/server/server.js
CHANGED
|
@@ -117,7 +117,7 @@ import {
|
|
|
117
117
|
vncLog,
|
|
118
118
|
walkPremiumBundles,
|
|
119
119
|
writeAdminUserAndPerson
|
|
120
|
-
} from "./chunk-
|
|
120
|
+
} from "./chunk-HN4HFTXE.js";
|
|
121
121
|
import {
|
|
122
122
|
D1_MAX_SQL_STATEMENT_BYTES,
|
|
123
123
|
D1_QUERY_MAX_BODY_BYTES,
|
|
@@ -798,6 +798,21 @@ var require_dist3 = __commonJS({
|
|
|
798
798
|
return null;
|
|
799
799
|
return m[1];
|
|
800
800
|
}
|
|
801
|
+
function estateAddress(props) {
|
|
802
|
+
const address = typeof props.address === "string" ? props.address : "";
|
|
803
|
+
const slug = typeof props.slug === "string" ? props.slug : "";
|
|
804
|
+
return address.length > 0 ? address : slug;
|
|
805
|
+
}
|
|
806
|
+
function estateListingName(props) {
|
|
807
|
+
const displayName = typeof props.displayName === "string" ? props.displayName : "";
|
|
808
|
+
const slug = typeof props.slug === "string" ? props.slug : "";
|
|
809
|
+
return displayName.length > 0 ? displayName : slug;
|
|
810
|
+
}
|
|
811
|
+
function offerCaption(props) {
|
|
812
|
+
const status = typeof props.status === "string" ? props.status : "";
|
|
813
|
+
const price = typeof props.price === "number" ? `\xA3${props.price}` : typeof props.price === "string" && props.price.length > 0 ? `\xA3${props.price}` : "";
|
|
814
|
+
return [status, price].filter((s) => s.length > 0).join(" ");
|
|
815
|
+
}
|
|
801
816
|
function pickShortLabel(node) {
|
|
802
817
|
const props = node.properties;
|
|
803
818
|
const primaryLabel2 = node.labels[0];
|
|
@@ -870,6 +885,40 @@ var require_dist3 = __commonJS({
|
|
|
870
885
|
if (ts)
|
|
871
886
|
return `${roleShort} ${ts}`;
|
|
872
887
|
}
|
|
888
|
+
} else if (primaryLabel2 === "Property") {
|
|
889
|
+
const v = estateAddress(props);
|
|
890
|
+
if (v.length > 0)
|
|
891
|
+
return v.length > 24 ? v.slice(0, 24) + "\u2026" : v;
|
|
892
|
+
} else if (primaryLabel2 === "Listing") {
|
|
893
|
+
const v = estateListingName(props);
|
|
894
|
+
if (v.length > 0)
|
|
895
|
+
return v.length > 24 ? v.slice(0, 24) + "\u2026" : v;
|
|
896
|
+
} else if (primaryLabel2 === "Viewing") {
|
|
897
|
+
const v = typeof props.date === "string" ? props.date : "";
|
|
898
|
+
if (v.length > 0)
|
|
899
|
+
return v.length > 24 ? v.slice(0, 24) + "\u2026" : v;
|
|
900
|
+
} else if (primaryLabel2 === "Offer") {
|
|
901
|
+
const v = offerCaption(props);
|
|
902
|
+
if (v.length > 0)
|
|
903
|
+
return v.length > 24 ? v.slice(0, 24) + "\u2026" : v;
|
|
904
|
+
} else if (primaryLabel2 === "Visit") {
|
|
905
|
+
const purpose = typeof props.purpose === "string" ? props.purpose : "";
|
|
906
|
+
const status = typeof props.status === "string" ? props.status : "";
|
|
907
|
+
const v = purpose.length > 0 ? purpose : status;
|
|
908
|
+
if (v.length > 0)
|
|
909
|
+
return v.length > 24 ? v.slice(0, 24) + "\u2026" : v;
|
|
910
|
+
} else if (primaryLabel2 === "PurchaseOrder") {
|
|
911
|
+
const v = typeof props.poNumber === "string" ? props.poNumber : "";
|
|
912
|
+
if (v.length > 0)
|
|
913
|
+
return v.length > 24 ? v.slice(0, 24) + "\u2026" : v;
|
|
914
|
+
} else if (primaryLabel2 === "Invoice") {
|
|
915
|
+
const v = typeof props.confirmationNumber === "string" ? props.confirmationNumber : "";
|
|
916
|
+
if (v.length > 0)
|
|
917
|
+
return v.length > 24 ? v.slice(0, 24) + "\u2026" : v;
|
|
918
|
+
} else if (primaryLabel2 === "Risk" || primaryLabel2 === "Finding" || primaryLabel2 === "Hypothesis") {
|
|
919
|
+
const v = typeof props.statement === "string" ? props.statement : "";
|
|
920
|
+
if (v.length > 0)
|
|
921
|
+
return v.length > 24 ? v.slice(0, 24) + "\u2026" : v;
|
|
873
922
|
}
|
|
874
923
|
for (const k of ["name", "title", "summary", "givenName", "subject", "text"]) {
|
|
875
924
|
const v = props[k];
|
|
@@ -938,6 +987,40 @@ var require_dist3 = __commonJS({
|
|
|
938
987
|
const desc = typeof props.description === "string" ? props.description : "";
|
|
939
988
|
if (desc.length > 0)
|
|
940
989
|
return desc;
|
|
990
|
+
} else if (primaryLabel2 === "Property") {
|
|
991
|
+
const v = estateAddress(props);
|
|
992
|
+
if (v.length > 0)
|
|
993
|
+
return v;
|
|
994
|
+
} else if (primaryLabel2 === "Listing") {
|
|
995
|
+
const v = estateListingName(props);
|
|
996
|
+
if (v.length > 0)
|
|
997
|
+
return v;
|
|
998
|
+
} else if (primaryLabel2 === "Viewing") {
|
|
999
|
+
const v = typeof props.date === "string" ? props.date : "";
|
|
1000
|
+
if (v.length > 0)
|
|
1001
|
+
return v;
|
|
1002
|
+
} else if (primaryLabel2 === "Offer") {
|
|
1003
|
+
const v = offerCaption(props);
|
|
1004
|
+
if (v.length > 0)
|
|
1005
|
+
return v;
|
|
1006
|
+
} else if (primaryLabel2 === "Visit") {
|
|
1007
|
+
const purpose = typeof props.purpose === "string" ? props.purpose : "";
|
|
1008
|
+
const status = typeof props.status === "string" ? props.status : "";
|
|
1009
|
+
const v = purpose.length > 0 ? purpose : status;
|
|
1010
|
+
if (v.length > 0)
|
|
1011
|
+
return v;
|
|
1012
|
+
} else if (primaryLabel2 === "PurchaseOrder") {
|
|
1013
|
+
const v = typeof props.poNumber === "string" ? props.poNumber : "";
|
|
1014
|
+
if (v.length > 0)
|
|
1015
|
+
return v;
|
|
1016
|
+
} else if (primaryLabel2 === "Invoice") {
|
|
1017
|
+
const v = typeof props.confirmationNumber === "string" ? props.confirmationNumber : "";
|
|
1018
|
+
if (v.length > 0)
|
|
1019
|
+
return v;
|
|
1020
|
+
} else if (primaryLabel2 === "Risk" || primaryLabel2 === "Finding" || primaryLabel2 === "Hypothesis") {
|
|
1021
|
+
const v = typeof props.statement === "string" ? props.statement : "";
|
|
1022
|
+
if (v.length > 0)
|
|
1023
|
+
return v;
|
|
941
1024
|
}
|
|
942
1025
|
for (const k of ["name", "title", "summary", "givenName", "subject", "text"]) {
|
|
943
1026
|
const v = props[k];
|
|
@@ -1560,10 +1643,10 @@ var serveStatic = (options = { root: "" }) => {
|
|
|
1560
1643
|
};
|
|
1561
1644
|
|
|
1562
1645
|
// server/index.ts
|
|
1563
|
-
import { readFileSync as
|
|
1646
|
+
import { readFileSync as readFileSync43, existsSync as existsSync39, watchFile, readdirSync as readdirSync26, statSync as statSync17 } from "fs";
|
|
1564
1647
|
import { spawn as spawn3 } from "child_process";
|
|
1565
1648
|
import { createHash as createHash7 } from "crypto";
|
|
1566
|
-
import { resolve as
|
|
1649
|
+
import { resolve as resolve39, join as join45, basename as basename12 } from "path";
|
|
1567
1650
|
import { homedir as homedir4 } from "os";
|
|
1568
1651
|
import { monitorEventLoopDelay } from "perf_hooks";
|
|
1569
1652
|
|
|
@@ -2837,7 +2920,7 @@ var credsSaveQueue = Promise.resolve();
|
|
|
2837
2920
|
async function drainCredsSaveQueue(timeoutMs = 5e3) {
|
|
2838
2921
|
console.error(`${TAG6} draining credential save queue\u2026`);
|
|
2839
2922
|
const timer = new Promise(
|
|
2840
|
-
(
|
|
2923
|
+
(resolve40) => setTimeout(() => resolve40("timeout"), timeoutMs)
|
|
2841
2924
|
);
|
|
2842
2925
|
const result = await Promise.race([
|
|
2843
2926
|
credsSaveQueue.then(() => "drained"),
|
|
@@ -3014,11 +3097,11 @@ async function createWaSocket(opts) {
|
|
|
3014
3097
|
return sock;
|
|
3015
3098
|
}
|
|
3016
3099
|
async function waitForConnection(sock) {
|
|
3017
|
-
return new Promise((
|
|
3100
|
+
return new Promise((resolve40, reject) => {
|
|
3018
3101
|
const handler = (update) => {
|
|
3019
3102
|
if (update.connection === "open") {
|
|
3020
3103
|
sock.ev.off("connection.update", handler);
|
|
3021
|
-
|
|
3104
|
+
resolve40();
|
|
3022
3105
|
}
|
|
3023
3106
|
if (update.connection === "close") {
|
|
3024
3107
|
sock.ev.off("connection.update", handler);
|
|
@@ -3126,7 +3209,7 @@ function isTimeoutError(err) {
|
|
|
3126
3209
|
return Boolean(err?.__maxyTimeout);
|
|
3127
3210
|
}
|
|
3128
3211
|
function withTimeout(label, promise, timeoutMs) {
|
|
3129
|
-
return new Promise((
|
|
3212
|
+
return new Promise((resolve40, reject) => {
|
|
3130
3213
|
const timer = setTimeout(() => {
|
|
3131
3214
|
const err = new Error(`${label} timed out after ${timeoutMs}ms`);
|
|
3132
3215
|
err.__maxyTimeout = true;
|
|
@@ -3136,7 +3219,7 @@ function withTimeout(label, promise, timeoutMs) {
|
|
|
3136
3219
|
promise.then(
|
|
3137
3220
|
(value) => {
|
|
3138
3221
|
clearTimeout(timer);
|
|
3139
|
-
|
|
3222
|
+
resolve40(value);
|
|
3140
3223
|
},
|
|
3141
3224
|
(err) => {
|
|
3142
3225
|
clearTimeout(timer);
|
|
@@ -4195,8 +4278,8 @@ async function persistWhatsAppMessage(input) {
|
|
|
4195
4278
|
const { givenName, familyName } = splitName(input.pushName);
|
|
4196
4279
|
const prev = sessionWriteLocks.get(input.cacheKey);
|
|
4197
4280
|
let release;
|
|
4198
|
-
const mine = new Promise((
|
|
4199
|
-
release =
|
|
4281
|
+
const mine = new Promise((resolve40) => {
|
|
4282
|
+
release = resolve40;
|
|
4200
4283
|
});
|
|
4201
4284
|
const chained = (prev ?? Promise.resolve()).then(() => mine);
|
|
4202
4285
|
sessionWriteLocks.set(input.cacheKey, chained);
|
|
@@ -5933,11 +6016,11 @@ async function connectWithReconnect(conn) {
|
|
|
5933
6016
|
console.error(
|
|
5934
6017
|
`${TAG17} reconnecting account=${conn.accountId} in ${delay}ms (attempt ${decision.nextAttempts}/${maxAttempts})`
|
|
5935
6018
|
);
|
|
5936
|
-
await new Promise((
|
|
5937
|
-
const timer = setTimeout(
|
|
6019
|
+
await new Promise((resolve40) => {
|
|
6020
|
+
const timer = setTimeout(resolve40, delay);
|
|
5938
6021
|
conn.abortController.signal.addEventListener("abort", () => {
|
|
5939
6022
|
clearTimeout(timer);
|
|
5940
|
-
|
|
6023
|
+
resolve40();
|
|
5941
6024
|
}, { once: true });
|
|
5942
6025
|
});
|
|
5943
6026
|
}
|
|
@@ -5945,16 +6028,16 @@ async function connectWithReconnect(conn) {
|
|
|
5945
6028
|
}
|
|
5946
6029
|
}
|
|
5947
6030
|
function waitForDisconnectEvent(conn) {
|
|
5948
|
-
return new Promise((
|
|
6031
|
+
return new Promise((resolve40) => {
|
|
5949
6032
|
if (!conn.sock) {
|
|
5950
|
-
|
|
6033
|
+
resolve40();
|
|
5951
6034
|
return;
|
|
5952
6035
|
}
|
|
5953
6036
|
const sock = conn.sock;
|
|
5954
6037
|
const handler = (update) => {
|
|
5955
6038
|
if (update.connection === "close") {
|
|
5956
6039
|
sock.ev.off("connection.update", handler);
|
|
5957
|
-
|
|
6040
|
+
resolve40();
|
|
5958
6041
|
}
|
|
5959
6042
|
};
|
|
5960
6043
|
sock.ev.on("connection.update", handler);
|
|
@@ -6428,8 +6511,8 @@ async function handleInboundMessage(conn, msg) {
|
|
|
6428
6511
|
const conversationKey = isGroup ? remoteJid : senderPhone;
|
|
6429
6512
|
const debounceKey = `${conn.accountId}:${conversationKey}:${senderPhone}`;
|
|
6430
6513
|
let resolvePending;
|
|
6431
|
-
const sttPending = new Promise((
|
|
6432
|
-
resolvePending =
|
|
6514
|
+
const sttPending = new Promise((resolve40) => {
|
|
6515
|
+
resolvePending = resolve40;
|
|
6433
6516
|
});
|
|
6434
6517
|
if (conn.debouncer) conn.debouncer.registerPending(debounceKey, sttPending);
|
|
6435
6518
|
try {
|
|
@@ -6818,20 +6901,20 @@ function buildX11Env(chromiumWrapperPath, transport = "vnc") {
|
|
|
6818
6901
|
|
|
6819
6902
|
// server/routes/health.ts
|
|
6820
6903
|
function checkPort(port2, timeoutMs = 500) {
|
|
6821
|
-
return new Promise((
|
|
6904
|
+
return new Promise((resolve40) => {
|
|
6822
6905
|
const socket = createConnection2(port2, "127.0.0.1");
|
|
6823
6906
|
socket.setTimeout(timeoutMs);
|
|
6824
6907
|
socket.once("connect", () => {
|
|
6825
6908
|
socket.destroy();
|
|
6826
|
-
|
|
6909
|
+
resolve40(true);
|
|
6827
6910
|
});
|
|
6828
6911
|
socket.once("error", () => {
|
|
6829
6912
|
socket.destroy();
|
|
6830
|
-
|
|
6913
|
+
resolve40(false);
|
|
6831
6914
|
});
|
|
6832
6915
|
socket.once("timeout", () => {
|
|
6833
6916
|
socket.destroy();
|
|
6834
|
-
|
|
6917
|
+
resolve40(false);
|
|
6835
6918
|
});
|
|
6836
6919
|
});
|
|
6837
6920
|
}
|
|
@@ -8162,8 +8245,8 @@ async function startLogin(opts) {
|
|
|
8162
8245
|
await clearAuth(authDir);
|
|
8163
8246
|
let resolveCode = null;
|
|
8164
8247
|
let rejectCode = null;
|
|
8165
|
-
const codePromise = new Promise((
|
|
8166
|
-
resolveCode =
|
|
8248
|
+
const codePromise = new Promise((resolve40, reject) => {
|
|
8249
|
+
resolveCode = resolve40;
|
|
8167
8250
|
rejectCode = reject;
|
|
8168
8251
|
});
|
|
8169
8252
|
const codeTimer = setTimeout(
|
|
@@ -14598,15 +14681,15 @@ function operatorRoleFor(config, userId) {
|
|
|
14598
14681
|
async function buildAccountOptionList(accounts, userId) {
|
|
14599
14682
|
const houseAccount = accounts.find((a) => a.config.role === "house");
|
|
14600
14683
|
console.log(`[admin-accounts] op=list count=${accounts.length} house=${houseAccount?.accountId ?? "none"}`);
|
|
14601
|
-
const
|
|
14684
|
+
const resolve40 = async (a) => {
|
|
14602
14685
|
const businessName = await fetchAccountName(a.accountId) || void 0;
|
|
14603
14686
|
return { accountId: a.accountId, businessName, role: operatorRoleFor(a.config, userId), isHouse: a.config.role === "house" };
|
|
14604
14687
|
};
|
|
14605
14688
|
const houseOptions = await Promise.all(
|
|
14606
|
-
accounts.filter((a) => a.config.role === "house").map(
|
|
14689
|
+
accounts.filter((a) => a.config.role === "house").map(resolve40)
|
|
14607
14690
|
);
|
|
14608
14691
|
const nonHouseOptions = await Promise.all(
|
|
14609
|
-
accounts.filter((a) => a.config.role !== "house").map(
|
|
14692
|
+
accounts.filter((a) => a.config.role !== "house").map(resolve40)
|
|
14610
14693
|
);
|
|
14611
14694
|
const sortKey = (o) => (o.businessName || o.accountId).toLowerCase();
|
|
14612
14695
|
nonHouseOptions.sort((x, y) => {
|
|
@@ -24411,7 +24494,17 @@ app62.get("/free-busy", async (c) => {
|
|
|
24411
24494
|
if (Number.isNaN(Date.parse(from)) || Number.isNaN(Date.parse(to))) {
|
|
24412
24495
|
return c.json({ error: "from and to must be parseable ISO timestamps" }, 400);
|
|
24413
24496
|
}
|
|
24414
|
-
const
|
|
24497
|
+
const accountParam = c.req.query("account");
|
|
24498
|
+
let account;
|
|
24499
|
+
if (accountParam) {
|
|
24500
|
+
account = listValidAccounts().find((a) => a.accountId === accountParam) ?? null;
|
|
24501
|
+
if (!account) {
|
|
24502
|
+
console.error(`[calendar] op=free-busy-unknown-account account="${accountParam}"`);
|
|
24503
|
+
return c.json({ error: "Availability not configured" }, 404);
|
|
24504
|
+
}
|
|
24505
|
+
} else {
|
|
24506
|
+
account = resolveAccount();
|
|
24507
|
+
}
|
|
24415
24508
|
if (!account) return c.json({ error: "No account configured" }, 500);
|
|
24416
24509
|
let config;
|
|
24417
24510
|
try {
|
|
@@ -24463,6 +24556,8 @@ var ONT_END = "<!-- ontology-buckets:end -->";
|
|
|
24463
24556
|
var OWNED_START = "<!-- plugin-owned-dirs:start -->";
|
|
24464
24557
|
var OWNED_END = "<!-- plugin-owned-dirs:end -->";
|
|
24465
24558
|
var ALWAYS_EXPOSED = "output";
|
|
24559
|
+
var SYSTEM_DIRS = /* @__PURE__ */ new Set(["agents", "secrets", "specialists", "state", "memory", "cache", "logs", "tmp"]);
|
|
24560
|
+
var SAFE_FOLDER = /^[A-Za-z0-9_-]+$/;
|
|
24466
24561
|
var DOMAIN_LINE = /^- `([^`/]+)\/` - one folder per /;
|
|
24467
24562
|
var OWNED_LINE = /^- `([^`/]+)\/` — /;
|
|
24468
24563
|
function region(text, start, end) {
|
|
@@ -24482,7 +24577,7 @@ function allowedBlockOrNull(text) {
|
|
|
24482
24577
|
}
|
|
24483
24578
|
return null;
|
|
24484
24579
|
}
|
|
24485
|
-
function resolveExposedDirs(schemaText) {
|
|
24580
|
+
function resolveExposedDirs(schemaText, exposeFolders = []) {
|
|
24486
24581
|
const empty = {
|
|
24487
24582
|
schemaPresent: false,
|
|
24488
24583
|
allowed: (
|
|
@@ -24524,7 +24619,11 @@ function resolveExposedDirs(schemaText) {
|
|
|
24524
24619
|
const pluginOwned = dirsIn(owned, OWNED_LINE);
|
|
24525
24620
|
const collisions = domainBuckets.filter((d) => pluginOwned.includes(d));
|
|
24526
24621
|
const candidates = [ALWAYS_EXPOSED, ...domainBuckets.filter((d) => !collisions.includes(d))];
|
|
24527
|
-
const
|
|
24622
|
+
const ontologyExposed = [...new Set(candidates)].filter((d) => allowed.includes(d));
|
|
24623
|
+
const extras = (Array.isArray(exposeFolders) ? exposeFolders : []).filter(
|
|
24624
|
+
(f) => typeof f === "string" && SAFE_FOLDER.test(f) && !SYSTEM_DIRS.has(f)
|
|
24625
|
+
);
|
|
24626
|
+
const exposed = [.../* @__PURE__ */ new Set([...ontologyExposed, ...extras])].sort();
|
|
24528
24627
|
return { schemaPresent: true, allowed, domainBuckets, pluginOwned, collisions, exposed };
|
|
24529
24628
|
}
|
|
24530
24629
|
|
|
@@ -24573,6 +24672,14 @@ async function readAccountSecret(accountId) {
|
|
|
24573
24672
|
function isValidAccountId2(value) {
|
|
24574
24673
|
return /^[A-Za-z0-9-]+$/.test(value);
|
|
24575
24674
|
}
|
|
24675
|
+
async function readExposeFolders(accountDir) {
|
|
24676
|
+
try {
|
|
24677
|
+
const cfg = JSON.parse(await readFile6(join42(accountDir, "data-portal.json"), "utf8"));
|
|
24678
|
+
return Array.isArray(cfg?.exposeFolders) ? cfg.exposeFolders.filter((f) => typeof f === "string") : [];
|
|
24679
|
+
} catch {
|
|
24680
|
+
return [];
|
|
24681
|
+
}
|
|
24682
|
+
}
|
|
24576
24683
|
async function resolveFetchTarget(accountDir, relPath) {
|
|
24577
24684
|
let schemaText = null;
|
|
24578
24685
|
try {
|
|
@@ -24580,7 +24687,8 @@ async function resolveFetchTarget(accountDir, relPath) {
|
|
|
24580
24687
|
} catch {
|
|
24581
24688
|
schemaText = null;
|
|
24582
24689
|
}
|
|
24583
|
-
const
|
|
24690
|
+
const exposeFolders = await readExposeFolders(accountDir);
|
|
24691
|
+
const { exposed } = resolveExposedDirs(schemaText, exposeFolders);
|
|
24584
24692
|
if (exposed.length === 0) return { ok: false, reason: "not-exposed" };
|
|
24585
24693
|
const lexical = resolve32(accountDir, relPath);
|
|
24586
24694
|
let root;
|
|
@@ -26401,16 +26509,16 @@ var WebchatGateway = class _WebchatGateway {
|
|
|
26401
26509
|
* The public /api/chat route awaits this to return the reply on the same SSE
|
|
26402
26510
|
* response, preserving the pre-756 POST→single-blob browser contract. */
|
|
26403
26511
|
awaitReply(key, timeoutMs) {
|
|
26404
|
-
return new Promise((
|
|
26512
|
+
return new Promise((resolve40) => {
|
|
26405
26513
|
const timer = setTimeout(() => {
|
|
26406
26514
|
this.replyAwaiters.delete(key);
|
|
26407
|
-
|
|
26515
|
+
resolve40({ timeout: true });
|
|
26408
26516
|
}, timeoutMs);
|
|
26409
26517
|
if (timer.unref) timer.unref();
|
|
26410
26518
|
this.replyAwaiters.set(key, (r) => {
|
|
26411
26519
|
clearTimeout(timer);
|
|
26412
26520
|
this.replyAwaiters.delete(key);
|
|
26413
|
-
|
|
26521
|
+
resolve40(r);
|
|
26414
26522
|
});
|
|
26415
26523
|
});
|
|
26416
26524
|
}
|
|
@@ -26421,11 +26529,11 @@ var WebchatGateway = class _WebchatGateway {
|
|
|
26421
26529
|
* terminal dialog stays answerable). */
|
|
26422
26530
|
awaitPermissionVerdict(p, timeoutMs) {
|
|
26423
26531
|
const k = _WebchatGateway.promptKey(p.key, p.requestId);
|
|
26424
|
-
return new Promise((
|
|
26532
|
+
return new Promise((resolve40) => {
|
|
26425
26533
|
this.pendingPrompts.get(k)?.resolve({ timeout: true });
|
|
26426
26534
|
const timer = setTimeout(() => {
|
|
26427
26535
|
this.pendingPrompts.delete(k);
|
|
26428
|
-
|
|
26536
|
+
resolve40({ timeout: true });
|
|
26429
26537
|
}, timeoutMs);
|
|
26430
26538
|
if (timer.unref) timer.unref();
|
|
26431
26539
|
this.pendingPrompts.set(k, {
|
|
@@ -26434,7 +26542,7 @@ var WebchatGateway = class _WebchatGateway {
|
|
|
26434
26542
|
resolve: (r) => {
|
|
26435
26543
|
clearTimeout(timer);
|
|
26436
26544
|
this.pendingPrompts.delete(k);
|
|
26437
|
-
|
|
26545
|
+
resolve40(r);
|
|
26438
26546
|
}
|
|
26439
26547
|
});
|
|
26440
26548
|
console.error(`[webchat:perm] op=open key=${keyDisplay(p.key)} id=${p.requestId} tool=${p.toolName}`);
|
|
@@ -28058,6 +28166,22 @@ function warnOnChannelAdminBindingDrift() {
|
|
|
28058
28166
|
}
|
|
28059
28167
|
}
|
|
28060
28168
|
|
|
28169
|
+
// server/lib/booking-site-accounts.ts
|
|
28170
|
+
import { existsSync as existsSync37, readFileSync as readFileSync41 } from "fs";
|
|
28171
|
+
import { resolve as resolve37 } from "path";
|
|
28172
|
+
function listBookingSiteAccounts(accounts) {
|
|
28173
|
+
return accounts.filter((a) => {
|
|
28174
|
+
const availPath = resolve37(a.accountDir, "calendar-availability.json");
|
|
28175
|
+
if (!existsSync37(availPath)) return false;
|
|
28176
|
+
try {
|
|
28177
|
+
const cfg = JSON.parse(readFileSync41(availPath, "utf-8"));
|
|
28178
|
+
return typeof cfg.bookingDbName === "string" && cfg.bookingDbName.length > 0;
|
|
28179
|
+
} catch {
|
|
28180
|
+
return false;
|
|
28181
|
+
}
|
|
28182
|
+
});
|
|
28183
|
+
}
|
|
28184
|
+
|
|
28061
28185
|
// app/lib/admin-sse-registry.ts
|
|
28062
28186
|
var activeAdminSSEControllers = /* @__PURE__ */ new Set();
|
|
28063
28187
|
function broadcastAdminShutdown(reason) {
|
|
@@ -28088,8 +28212,8 @@ function broadcastAdminShutdown(reason) {
|
|
|
28088
28212
|
|
|
28089
28213
|
// ../lib/entitlement/src/index.ts
|
|
28090
28214
|
import { createPublicKey, createHash as createHash6, verify as cryptoVerify } from "crypto";
|
|
28091
|
-
import { existsSync as
|
|
28092
|
-
import { resolve as
|
|
28215
|
+
import { existsSync as existsSync38, readFileSync as readFileSync42, statSync as statSync16 } from "fs";
|
|
28216
|
+
import { resolve as resolve38 } from "path";
|
|
28093
28217
|
|
|
28094
28218
|
// ../lib/entitlement/src/canonicalize.ts
|
|
28095
28219
|
function canonicalize(value) {
|
|
@@ -28124,7 +28248,7 @@ var PUBKEY_SHA256 = "8eee6bcb33545fd13b16d3199a5735ca5db5062834c7b49dfe4f23801d9
|
|
|
28124
28248
|
var GRACE_DAYS = 7;
|
|
28125
28249
|
var GRACE_MS = GRACE_DAYS * 24 * 60 * 60 * 1e3;
|
|
28126
28250
|
function pubkeyPath(brand) {
|
|
28127
|
-
return
|
|
28251
|
+
return resolve38(brand.platformRoot, "lib", "entitlement", "rubytech-pubkey.pem");
|
|
28128
28252
|
}
|
|
28129
28253
|
var memo = null;
|
|
28130
28254
|
function memoKey(mtimeMs, account) {
|
|
@@ -28136,8 +28260,8 @@ function resolveEntitlement(brand, account) {
|
|
|
28136
28260
|
if (brand.commercialMode !== true) {
|
|
28137
28261
|
return logResolved(implicitTrust(account), null);
|
|
28138
28262
|
}
|
|
28139
|
-
const entitlementPath =
|
|
28140
|
-
if (!
|
|
28263
|
+
const entitlementPath = resolve38(brand.configDir, "entitlement.json");
|
|
28264
|
+
if (!existsSync38(entitlementPath)) {
|
|
28141
28265
|
return logResolved(anonymousFallback("missing"), { reason: "missing" });
|
|
28142
28266
|
}
|
|
28143
28267
|
const stat9 = statSync16(entitlementPath);
|
|
@@ -28152,7 +28276,7 @@ function resolveEntitlement(brand, account) {
|
|
|
28152
28276
|
function verifyAndResolve(brand, entitlementPath, account) {
|
|
28153
28277
|
let pubkeyPem;
|
|
28154
28278
|
try {
|
|
28155
|
-
pubkeyPem =
|
|
28279
|
+
pubkeyPem = readFileSync42(pubkeyPath(brand), "utf-8");
|
|
28156
28280
|
} catch (err) {
|
|
28157
28281
|
return logResolved(anonymousFallback("pubkey-missing"), {
|
|
28158
28282
|
reason: "pubkey-missing"
|
|
@@ -28166,7 +28290,7 @@ function verifyAndResolve(brand, entitlementPath, account) {
|
|
|
28166
28290
|
}
|
|
28167
28291
|
let envelope;
|
|
28168
28292
|
try {
|
|
28169
|
-
envelope = JSON.parse(
|
|
28293
|
+
envelope = JSON.parse(readFileSync42(entitlementPath, "utf-8"));
|
|
28170
28294
|
} catch {
|
|
28171
28295
|
return logResolved(anonymousFallback("malformed"), { reason: "malformed" });
|
|
28172
28296
|
}
|
|
@@ -28330,12 +28454,12 @@ installMediaDownloadGuard();
|
|
|
28330
28454
|
var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT || "";
|
|
28331
28455
|
var BRAND_JSON_PATH = PLATFORM_ROOT8 ? join45(PLATFORM_ROOT8, "config", "brand.json") : "";
|
|
28332
28456
|
var BRAND = { productName: "Maxy", hostname: "maxy", configDir: ".maxy", marketingUrl: "https://getmaxy.com" };
|
|
28333
|
-
if (BRAND_JSON_PATH && !
|
|
28457
|
+
if (BRAND_JSON_PATH && !existsSync39(BRAND_JSON_PATH)) {
|
|
28334
28458
|
console.error(`[brand] WARNING: brand.json not found at ${BRAND_JSON_PATH} \u2014 using Maxy defaults`);
|
|
28335
28459
|
}
|
|
28336
|
-
if (BRAND_JSON_PATH &&
|
|
28460
|
+
if (BRAND_JSON_PATH && existsSync39(BRAND_JSON_PATH)) {
|
|
28337
28461
|
try {
|
|
28338
|
-
const parsed = JSON.parse(
|
|
28462
|
+
const parsed = JSON.parse(readFileSync43(BRAND_JSON_PATH, "utf-8"));
|
|
28339
28463
|
BRAND = { ...BRAND, ...parsed };
|
|
28340
28464
|
} catch (err) {
|
|
28341
28465
|
console.error(`[brand] Failed to parse brand.json: ${err.message}`);
|
|
@@ -28370,8 +28494,8 @@ var brandLoginOpts = {
|
|
|
28370
28494
|
var ALIAS_DOMAINS_PATH = join45(homedir4(), BRAND.configDir, "alias-domains.json");
|
|
28371
28495
|
function loadAliasDomains() {
|
|
28372
28496
|
try {
|
|
28373
|
-
if (!
|
|
28374
|
-
const parsed = JSON.parse(
|
|
28497
|
+
if (!existsSync39(ALIAS_DOMAINS_PATH)) return null;
|
|
28498
|
+
const parsed = JSON.parse(readFileSync43(ALIAS_DOMAINS_PATH, "utf-8"));
|
|
28375
28499
|
if (!Array.isArray(parsed)) {
|
|
28376
28500
|
console.error("[alias-domains] malformed alias-domains.json \u2014 expected array");
|
|
28377
28501
|
return null;
|
|
@@ -28444,7 +28568,7 @@ var waGateway = new WaGateway({
|
|
|
28444
28568
|
fetchStandingRules: fetchAccountStandingRules,
|
|
28445
28569
|
resolveSessionOverride: (accountId, senderId) => resolveChannelOverride(accountId, "whatsapp", senderId),
|
|
28446
28570
|
gatewayUrl: `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`,
|
|
28447
|
-
serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ??
|
|
28571
|
+
serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve39(process.env.MAXY_PLATFORM_ROOT ?? join45(__dirname, ".."), "services/whatsapp-channel/dist/server.js"),
|
|
28448
28572
|
// Task 751 / 1390 — file delivery on the native channel. `maxyAccountId` (the
|
|
28449
28573
|
// path-validation scope) is the sender's effective SESSION account, resolved
|
|
28450
28574
|
// once at the inbound gate and threaded here via the gateway's per-sender doc
|
|
@@ -28459,7 +28583,7 @@ var waGateway = new WaGateway({
|
|
|
28459
28583
|
caption,
|
|
28460
28584
|
accountId,
|
|
28461
28585
|
maxyAccountId,
|
|
28462
|
-
platformRoot:
|
|
28586
|
+
platformRoot: resolve39(process.env.MAXY_PLATFORM_ROOT ?? join45(__dirname, ".."))
|
|
28463
28587
|
});
|
|
28464
28588
|
return result.ok ? { ok: true, messageId: result.messageId } : { ok: false, error: result.error };
|
|
28465
28589
|
},
|
|
@@ -29135,20 +29259,20 @@ app64.get("/agent-assets/:slug/:filename", (c) => {
|
|
|
29135
29259
|
console.error(`[agent-assets] no-account slug=${slug} file=${filename}`);
|
|
29136
29260
|
return c.text("Not found", 404);
|
|
29137
29261
|
}
|
|
29138
|
-
const filePath =
|
|
29139
|
-
const expectedDir =
|
|
29262
|
+
const filePath = resolve39(account.accountDir, "agents", slug, "assets", filename);
|
|
29263
|
+
const expectedDir = resolve39(account.accountDir, "agents", slug, "assets");
|
|
29140
29264
|
if (!filePath.startsWith(expectedDir + "/")) {
|
|
29141
29265
|
console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
|
|
29142
29266
|
return c.text("Forbidden", 403);
|
|
29143
29267
|
}
|
|
29144
|
-
if (!
|
|
29268
|
+
if (!existsSync39(filePath)) {
|
|
29145
29269
|
console.error(`[agent-assets] serve slug=${slug} file=${filename} status=404`);
|
|
29146
29270
|
return c.text("Not found", 404);
|
|
29147
29271
|
}
|
|
29148
29272
|
const ext = "." + filename.split(".").pop()?.toLowerCase();
|
|
29149
29273
|
const contentType = IMAGE_MIME[ext] || "application/octet-stream";
|
|
29150
29274
|
console.log(`[agent-assets] serve slug=${slug} file=${filename} status=200`);
|
|
29151
|
-
const body =
|
|
29275
|
+
const body = readFileSync43(filePath);
|
|
29152
29276
|
return c.body(body, 200, {
|
|
29153
29277
|
"Content-Type": contentType,
|
|
29154
29278
|
"Cache-Control": "public, max-age=3600"
|
|
@@ -29165,20 +29289,20 @@ app64.get("/generated/:filename", (c) => {
|
|
|
29165
29289
|
console.error(`[generated] serve file=${filename} status=404`);
|
|
29166
29290
|
return c.text("Not found", 404);
|
|
29167
29291
|
}
|
|
29168
|
-
const filePath =
|
|
29169
|
-
const expectedDir =
|
|
29292
|
+
const filePath = resolve39(account.accountDir, "generated", filename);
|
|
29293
|
+
const expectedDir = resolve39(account.accountDir, "generated");
|
|
29170
29294
|
if (!filePath.startsWith(expectedDir + "/")) {
|
|
29171
29295
|
console.error(`[generated] serve file=${filename} status=403`);
|
|
29172
29296
|
return c.text("Forbidden", 403);
|
|
29173
29297
|
}
|
|
29174
|
-
if (!
|
|
29298
|
+
if (!existsSync39(filePath)) {
|
|
29175
29299
|
console.error(`[generated] serve file=${filename} status=404`);
|
|
29176
29300
|
return c.text("Not found", 404);
|
|
29177
29301
|
}
|
|
29178
29302
|
const ext = "." + filename.split(".").pop()?.toLowerCase();
|
|
29179
29303
|
const contentType = IMAGE_MIME[ext] || "application/octet-stream";
|
|
29180
29304
|
console.log(`[generated] serve file=${filename} status=200`);
|
|
29181
|
-
const body =
|
|
29305
|
+
const body = readFileSync43(filePath);
|
|
29182
29306
|
return c.body(body, 200, {
|
|
29183
29307
|
"Content-Type": contentType,
|
|
29184
29308
|
"Cache-Control": "public, max-age=86400"
|
|
@@ -29191,9 +29315,9 @@ app64.route("/v", visitor_consent_default);
|
|
|
29191
29315
|
var htmlCache = /* @__PURE__ */ new Map();
|
|
29192
29316
|
var brandLogoPath = "/brand/maxy-monochrome.png";
|
|
29193
29317
|
var brandIconPath = "/brand/maxy-monochrome.png";
|
|
29194
|
-
if (BRAND_JSON_PATH &&
|
|
29318
|
+
if (BRAND_JSON_PATH && existsSync39(BRAND_JSON_PATH)) {
|
|
29195
29319
|
try {
|
|
29196
|
-
const fullBrand = JSON.parse(
|
|
29320
|
+
const fullBrand = JSON.parse(readFileSync43(BRAND_JSON_PATH, "utf-8"));
|
|
29197
29321
|
if (fullBrand.assets?.logo) brandLogoPath = `/brand/${fullBrand.assets.logo}`;
|
|
29198
29322
|
brandIconPath = fullBrand.assets?.icon ? `/brand/${fullBrand.assets.icon}` : brandLogoPath;
|
|
29199
29323
|
} catch {
|
|
@@ -29220,11 +29344,11 @@ var brandScript = `<script>window.__BRAND__=${JSON.stringify({
|
|
|
29220
29344
|
var brandThemeColor = BRAND.defaultColors?.primary ?? "#000000";
|
|
29221
29345
|
var brandBackgroundColor = BRAND.defaultColors?.background ?? "#ffffff";
|
|
29222
29346
|
var brandAppIconsExist = [brandAppIcon192Path, brandAppIcon512Path, brandMaskableIconPath].every(
|
|
29223
|
-
(p) =>
|
|
29347
|
+
(p) => existsSync39(resolve39(process.cwd(), "public", p.replace(/^\//, "")))
|
|
29224
29348
|
);
|
|
29225
29349
|
var SW_SOURCE = (() => {
|
|
29226
29350
|
try {
|
|
29227
|
-
return
|
|
29351
|
+
return readFileSync43(resolve39(process.cwd(), "public", "sw.js"), "utf-8");
|
|
29228
29352
|
} catch {
|
|
29229
29353
|
return null;
|
|
29230
29354
|
}
|
|
@@ -29233,8 +29357,8 @@ function readInstalledVersion() {
|
|
|
29233
29357
|
try {
|
|
29234
29358
|
if (!PLATFORM_ROOT8) return "unknown";
|
|
29235
29359
|
const versionFile = join45(PLATFORM_ROOT8, "config", `.${BRAND.hostname}-version`);
|
|
29236
|
-
if (!
|
|
29237
|
-
const content =
|
|
29360
|
+
if (!existsSync39(versionFile)) return "unknown";
|
|
29361
|
+
const content = readFileSync43(versionFile, "utf-8").trim();
|
|
29238
29362
|
return content || "unknown";
|
|
29239
29363
|
} catch {
|
|
29240
29364
|
return "unknown";
|
|
@@ -29275,7 +29399,7 @@ var clientErrorReporterScript = `<script>
|
|
|
29275
29399
|
function cachedHtml(file) {
|
|
29276
29400
|
let html = htmlCache.get(file);
|
|
29277
29401
|
if (!html) {
|
|
29278
|
-
html =
|
|
29402
|
+
html = readFileSync43(resolve39(process.cwd(), "public", file), "utf-8");
|
|
29279
29403
|
const productNameEsc = escapeHtml(BRAND.productName);
|
|
29280
29404
|
html = html.replace(/<title>([^<]*)<\/title>/, (_match, inner) => `<title>${escapeHtml(inner).replace(/Maxy/g, productNameEsc)}</title>`);
|
|
29281
29405
|
html = html.replace('href="/favicon.ico"', `href="${escapeHtml(brandFaviconPath)}"`);
|
|
@@ -29297,8 +29421,8 @@ function loadBrandingCache(agentSlug) {
|
|
|
29297
29421
|
const accountId = getDefaultAccountId();
|
|
29298
29422
|
if (!accountId) return null;
|
|
29299
29423
|
const cachePath = join45(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
|
|
29300
|
-
if (!
|
|
29301
|
-
return JSON.parse(
|
|
29424
|
+
if (!existsSync39(cachePath)) return null;
|
|
29425
|
+
return JSON.parse(readFileSync43(cachePath, "utf-8"));
|
|
29302
29426
|
} catch {
|
|
29303
29427
|
return null;
|
|
29304
29428
|
}
|
|
@@ -29393,7 +29517,7 @@ app64.use("/vnc-popout.html", logViewerFetch);
|
|
|
29393
29517
|
app64.get("/vnc-popout.html", (c) => {
|
|
29394
29518
|
let html = htmlCache.get("vnc-popout.html");
|
|
29395
29519
|
if (!html) {
|
|
29396
|
-
html =
|
|
29520
|
+
html = readFileSync43(resolve39(process.cwd(), "public", "vnc-popout.html"), "utf-8");
|
|
29397
29521
|
const name = escapeHtml(BRAND.productName);
|
|
29398
29522
|
html = html.replace("<title>Browser \u2014 Maxy</title>", `<title>${name}</title>`);
|
|
29399
29523
|
html = html.replace("</head>", ` ${brandScript}
|
|
@@ -29531,10 +29655,10 @@ var httpServer = serve({ fetch: app64.fetch, port, hostname });
|
|
|
29531
29655
|
console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
29532
29656
|
{
|
|
29533
29657
|
const reconcilePlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join45(__dirname, "..");
|
|
29534
|
-
const reconcileScript =
|
|
29658
|
+
const reconcileScript = resolve39(reconcilePlatformRoot, "plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js");
|
|
29535
29659
|
const RECONCILE_INTERVAL_MS = 12e4;
|
|
29536
29660
|
const runReconcile = (ctx) => {
|
|
29537
|
-
if (!
|
|
29661
|
+
if (!existsSync39(reconcileScript)) return;
|
|
29538
29662
|
try {
|
|
29539
29663
|
const child = spawn3(process.execPath, [reconcileScript], {
|
|
29540
29664
|
env: { ...process.env, PLATFORM_ROOT: reconcilePlatformRoot },
|
|
@@ -29557,10 +29681,10 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
29557
29681
|
}
|
|
29558
29682
|
{
|
|
29559
29683
|
const outlookPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join45(__dirname, "..");
|
|
29560
|
-
const outlookScript =
|
|
29684
|
+
const outlookScript = resolve39(outlookPlatformRoot, "plugins/outlook/mcp/dist/scripts/complete-registration.js");
|
|
29561
29685
|
const OUTLOOK_COMPLETE_INTERVAL_MS = 3e4;
|
|
29562
29686
|
const runOutlookComplete = (ctx) => {
|
|
29563
|
-
if (!
|
|
29687
|
+
if (!existsSync39(outlookScript)) return;
|
|
29564
29688
|
try {
|
|
29565
29689
|
const child = spawn3(process.execPath, [outlookScript], {
|
|
29566
29690
|
env: { ...process.env, PLATFORM_ROOT: outlookPlatformRoot },
|
|
@@ -29583,18 +29707,18 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
29583
29707
|
}
|
|
29584
29708
|
{
|
|
29585
29709
|
const auditRoot = process.env.MAXY_PLATFORM_ROOT ?? join45(__dirname, "..");
|
|
29586
|
-
const strandedAccountsDir =
|
|
29710
|
+
const strandedAccountsDir = resolve39(auditRoot, "..", "data/accounts");
|
|
29587
29711
|
const STRANDED_AUDIT_INTERVAL_MS = 3e5;
|
|
29588
29712
|
const STRANDED_AGE_MS = 16 * 6e4;
|
|
29589
29713
|
const STRANDED_UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
29590
29714
|
const runStrandedAudit = () => {
|
|
29591
29715
|
try {
|
|
29592
|
-
if (!
|
|
29716
|
+
if (!existsSync39(strandedAccountsDir)) return;
|
|
29593
29717
|
const now = Date.now();
|
|
29594
29718
|
for (const name of readdirSync26(strandedAccountsDir)) {
|
|
29595
29719
|
if (!STRANDED_UUID_RE.test(name)) continue;
|
|
29596
|
-
const pendingPath2 =
|
|
29597
|
-
if (!
|
|
29720
|
+
const pendingPath2 = resolve39(strandedAccountsDir, name, "secrets/outlook/pending-devicecode.enc");
|
|
29721
|
+
if (!existsSync39(pendingPath2)) continue;
|
|
29598
29722
|
const ageMs = now - statSync17(pendingPath2).mtimeMs;
|
|
29599
29723
|
if (ageMs > STRANDED_AGE_MS) {
|
|
29600
29724
|
console.error(`[outlook-mcp] devicecode-stranded account=${name} ageSec=${Math.floor(ageMs / 1e3)}`);
|
|
@@ -29613,7 +29737,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
29613
29737
|
}
|
|
29614
29738
|
{
|
|
29615
29739
|
const googleRoot = process.env.MAXY_PLATFORM_ROOT ?? join45(__dirname, "..");
|
|
29616
|
-
const googleAccountsDir =
|
|
29740
|
+
const googleAccountsDir = resolve39(googleRoot, "..", "data/accounts");
|
|
29617
29741
|
const GOOGLE_PENDING_AUDIT_INTERVAL_MS = 3e5;
|
|
29618
29742
|
const runGooglePendingAuditSafe = () => {
|
|
29619
29743
|
try {
|
|
@@ -29628,10 +29752,10 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
29628
29752
|
firstRunDelayMs: 27e3,
|
|
29629
29753
|
run: runGooglePendingAuditSafe
|
|
29630
29754
|
});
|
|
29631
|
-
const googleAuditScript =
|
|
29755
|
+
const googleAuditScript = resolve39(googleRoot, "plugins/google/mcp/dist/scripts/account-audit.js");
|
|
29632
29756
|
const GOOGLE_ACCOUNT_AUDIT_INTERVAL_MS = 36e5;
|
|
29633
29757
|
const runGoogleAccountAudit = (ctx) => {
|
|
29634
|
-
if (!
|
|
29758
|
+
if (!existsSync39(googleAuditScript)) return;
|
|
29635
29759
|
try {
|
|
29636
29760
|
const child = spawn3(process.execPath, [googleAuditScript], {
|
|
29637
29761
|
env: { ...process.env, PLATFORM_ROOT: googleRoot },
|
|
@@ -29691,18 +29815,18 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
29691
29815
|
}
|
|
29692
29816
|
{
|
|
29693
29817
|
const publishPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join45(__dirname, "..");
|
|
29694
|
-
const publishScript =
|
|
29818
|
+
const publishScript = resolve39(publishPlatformRoot, "plugins/scheduling/mcp/dist/scripts/publish-availability.js");
|
|
29695
29819
|
const PUBLISH_INTERVAL_MS = 3e5;
|
|
29696
|
-
const
|
|
29820
|
+
const bookingAccounts = () => {
|
|
29697
29821
|
try {
|
|
29698
|
-
return
|
|
29822
|
+
return listBookingSiteAccounts(listValidAccounts());
|
|
29699
29823
|
} catch (err) {
|
|
29700
|
-
console.error(`[calendar-availability] op=publish result=error reason=
|
|
29701
|
-
return
|
|
29824
|
+
console.error(`[calendar-availability] op=publish result=error reason=enumerate-failed err="${err.message}"`);
|
|
29825
|
+
return [];
|
|
29702
29826
|
}
|
|
29703
29827
|
};
|
|
29704
29828
|
const spawnPublish = (account, ctx) => {
|
|
29705
|
-
if (!
|
|
29829
|
+
if (!existsSync39(publishScript)) return;
|
|
29706
29830
|
try {
|
|
29707
29831
|
const child = spawn3(process.execPath, [publishScript], {
|
|
29708
29832
|
env: {
|
|
@@ -29721,21 +29845,21 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
29721
29845
|
}
|
|
29722
29846
|
};
|
|
29723
29847
|
const auditSnapshotAge = (account) => {
|
|
29724
|
-
const availPath =
|
|
29848
|
+
const availPath = resolve39(account.accountDir, "calendar-availability.json");
|
|
29725
29849
|
let hasBookingSite = false;
|
|
29726
29850
|
try {
|
|
29727
|
-
if (
|
|
29728
|
-
const cfg = JSON.parse(
|
|
29851
|
+
if (existsSync39(availPath)) {
|
|
29852
|
+
const cfg = JSON.parse(readFileSync43(availPath, "utf-8"));
|
|
29729
29853
|
hasBookingSite = typeof cfg.bookingDbName === "string" && cfg.bookingDbName.length > 0;
|
|
29730
29854
|
}
|
|
29731
29855
|
} catch {
|
|
29732
29856
|
}
|
|
29733
29857
|
if (!hasBookingSite) return;
|
|
29734
|
-
const statePath =
|
|
29858
|
+
const statePath = resolve39(account.accountDir, "state", "booking-availability", "last-publish.json");
|
|
29735
29859
|
let lastSuccessAt = null;
|
|
29736
|
-
if (
|
|
29860
|
+
if (existsSync39(statePath)) {
|
|
29737
29861
|
try {
|
|
29738
|
-
const rec = JSON.parse(
|
|
29862
|
+
const rec = JSON.parse(readFileSync43(statePath, "utf-8"));
|
|
29739
29863
|
lastSuccessAt = rec.lastSuccessAt ?? null;
|
|
29740
29864
|
} catch {
|
|
29741
29865
|
console.error(`[calendar-availability] op=audit accountId=${account.accountId} snapshotAgeMs=na reason=bad-state-file`);
|
|
@@ -29747,10 +29871,14 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
29747
29871
|
console.error(`[calendar-availability] op=audit accountId=${account.accountId} snapshotAgeMs=${ageMs ?? "na"}`);
|
|
29748
29872
|
};
|
|
29749
29873
|
const publishTick = (ctx) => {
|
|
29750
|
-
const account
|
|
29751
|
-
|
|
29752
|
-
|
|
29753
|
-
|
|
29874
|
+
for (const account of bookingAccounts()) {
|
|
29875
|
+
try {
|
|
29876
|
+
spawnPublish(account, ctx);
|
|
29877
|
+
auditSnapshotAge(account);
|
|
29878
|
+
} catch (err) {
|
|
29879
|
+
console.error(`[calendar-availability] op=publish accountId=${account.accountId} result=error reason=tick-failed err="${err.message}"`);
|
|
29880
|
+
}
|
|
29881
|
+
}
|
|
29754
29882
|
};
|
|
29755
29883
|
registerLoop({
|
|
29756
29884
|
name: "calendar-availability-publish",
|
|
@@ -29764,11 +29892,11 @@ startTimeEntryCensus(() => getSession());
|
|
|
29764
29892
|
startLedgerCensus(() => getSession());
|
|
29765
29893
|
{
|
|
29766
29894
|
const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join45(__dirname, "..");
|
|
29767
|
-
const auditScript =
|
|
29895
|
+
const auditScript = resolve39(auditPlatformRoot, "plugins/connector/mcp/dist/scripts/audit-connectors.js");
|
|
29768
29896
|
const auditLogDir = process.env.LOG_DIR ?? LOG_DIR;
|
|
29769
29897
|
const CONNECTOR_AUDIT_INTERVAL_MS = 3e5;
|
|
29770
29898
|
const runConnectorAudit = (ctx) => {
|
|
29771
|
-
if (!
|
|
29899
|
+
if (!existsSync39(auditScript)) return;
|
|
29772
29900
|
try {
|
|
29773
29901
|
const child = spawn3(process.execPath, [auditScript], {
|
|
29774
29902
|
env: { ...process.env, PLATFORM_ROOT: auditPlatformRoot, LOG_DIR: auditLogDir },
|
|
@@ -29888,11 +30016,11 @@ try {
|
|
|
29888
30016
|
var ADMINUSER_RECONCILE_INTERVAL_MS = 60 * 60 * 1e3;
|
|
29889
30017
|
async function runAdminUserReconcileTick() {
|
|
29890
30018
|
try {
|
|
29891
|
-
if (!
|
|
30019
|
+
if (!existsSync39(USERS_FILE)) {
|
|
29892
30020
|
console.error("[adminuser-self-heal] skip reason=no-users-file");
|
|
29893
30021
|
return;
|
|
29894
30022
|
}
|
|
29895
|
-
const usersRaw =
|
|
30023
|
+
const usersRaw = readFileSync43(USERS_FILE, "utf-8").trim();
|
|
29896
30024
|
if (!usersRaw) {
|
|
29897
30025
|
console.error("[adminuser-self-heal] skip reason=empty-users-file");
|
|
29898
30026
|
return;
|
|
@@ -29939,8 +30067,8 @@ registerLoop({
|
|
|
29939
30067
|
});
|
|
29940
30068
|
var USERS_RECONCILE_INTERVAL_MS = 60 * 60 * 1e3;
|
|
29941
30069
|
function countUsersRows() {
|
|
29942
|
-
if (!
|
|
29943
|
-
const raw =
|
|
30070
|
+
if (!existsSync39(USERS_FILE)) return 0;
|
|
30071
|
+
const raw = readFileSync43(USERS_FILE, "utf-8").trim();
|
|
29944
30072
|
if (!raw) return 0;
|
|
29945
30073
|
const users = JSON.parse(raw);
|
|
29946
30074
|
return users.filter((u) => typeof u.userId === "string").length;
|
|
@@ -30073,7 +30201,7 @@ if (bootAccountConfig?.whatsapp) {
|
|
|
30073
30201
|
}
|
|
30074
30202
|
init({
|
|
30075
30203
|
configDir: configDirForWhatsApp,
|
|
30076
|
-
platformRoot:
|
|
30204
|
+
platformRoot: resolve39(process.env.MAXY_PLATFORM_ROOT ?? join45(__dirname, "..")),
|
|
30077
30205
|
accountConfig: bootAccountConfig,
|
|
30078
30206
|
onMessage: async (msg) => {
|
|
30079
30207
|
if (isObserveAccount(msg.accountId)) {
|