@rubytech/create-maxy-code 0.1.476 → 0.1.478
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-20-task-1704-data-portal-standing-audit.md +673 -0
- package/payload/platform/docs/superpowers/specs/2026-07-20-task-1704-data-portal-standing-audit-design.md +177 -0
- package/payload/platform/docs/superpowers/specs/2026-07-20-task-1820-cpu-triage-admin-tools-design.md +97 -0
- package/payload/platform/lib/storage-broker/dist/__tests__/audit.test.js +44 -0
- package/payload/platform/lib/storage-broker/dist/__tests__/audit.test.js.map +1 -1
- package/payload/platform/lib/storage-broker/dist/audit.d.ts +56 -0
- package/payload/platform/lib/storage-broker/dist/audit.d.ts.map +1 -1
- package/payload/platform/lib/storage-broker/dist/audit.js +34 -0
- package/payload/platform/lib/storage-broker/dist/audit.js.map +1 -1
- package/payload/platform/lib/storage-broker/src/__tests__/audit.test.ts +70 -1
- package/payload/platform/lib/storage-broker/src/audit.ts +111 -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/mcp/dist/index.js +72 -0
- package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/admin/mcp/dist/tools/cpu-triage.d.ts +94 -0
- package/payload/platform/plugins/admin/mcp/dist/tools/cpu-triage.d.ts.map +1 -0
- package/payload/platform/plugins/admin/mcp/dist/tools/cpu-triage.js +229 -0
- package/payload/platform/plugins/admin/mcp/dist/tools/cpu-triage.js.map +1 -0
- 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/email/PLUGIN.md +2 -1
- package/payload/platform/plugins/email/mcp/dist/__tests__/confirm-sent-copy.test.d.ts +2 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/confirm-sent-copy.test.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/confirm-sent-copy.test.js +92 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/confirm-sent-copy.test.js.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/email-draft-send.test.js +112 -12
- package/payload/platform/plugins/email/mcp/dist/__tests__/email-draft-send.test.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/__tests__/email-send-sent-copy.test.d.ts +2 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/email-send-sent-copy.test.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/email-send-sent-copy.test.js +54 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/email-send-sent-copy.test.js.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/imap-drafts.test.js +170 -1
- package/payload/platform/plugins/email/mcp/dist/__tests__/imap-drafts.test.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/__tests__/sent-copy-note.test.d.ts +2 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/sent-copy-note.test.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/sent-copy-note.test.js +86 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/sent-copy-note.test.js.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/sent-copy-sweep.test.d.ts +2 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/sent-copy-sweep.test.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/sent-copy-sweep.test.js +164 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/sent-copy-sweep.test.js.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/sent-ledger.test.d.ts +2 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/sent-ledger.test.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/sent-ledger.test.js +82 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/sent-ledger.test.js.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/lib/imap.d.ts +95 -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 +223 -0
- package/payload/platform/plugins/email/mcp/dist/lib/imap.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/lib/sent-copy-note.d.ts +18 -0
- package/payload/platform/plugins/email/mcp/dist/lib/sent-copy-note.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/lib/sent-copy-note.js +59 -0
- package/payload/platform/plugins/email/mcp/dist/lib/sent-copy-note.js.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/lib/sent-copy-sweep.d.ts +48 -0
- package/payload/platform/plugins/email/mcp/dist/lib/sent-copy-sweep.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/lib/sent-copy-sweep.js +79 -0
- package/payload/platform/plugins/email/mcp/dist/lib/sent-copy-sweep.js.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/lib/sent-ledger.d.ts +44 -0
- package/payload/platform/plugins/email/mcp/dist/lib/sent-ledger.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/lib/sent-ledger.js +63 -0
- package/payload/platform/plugins/email/mcp/dist/lib/sent-ledger.js.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/scripts/sent-copy-sweep.d.ts +2 -0
- package/payload/platform/plugins/email/mcp/dist/scripts/sent-copy-sweep.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/scripts/sent-copy-sweep.js +55 -0
- package/payload/platform/plugins/email/mcp/dist/scripts/sent-copy-sweep.js.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/tools/email-draft-send.d.ts.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-draft-send.js +64 -13
- package/payload/platform/plugins/email/mcp/dist/tools/email-draft-send.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-reply.d.ts.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-reply.js +11 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-reply.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-send.d.ts.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-send.js +16 -3
- package/payload/platform/plugins/email/mcp/dist/tools/email-send.js.map +1 -1
- package/payload/platform/plugins/email/references/email-reference.md +36 -0
- package/payload/platform/plugins/scheduling/mcp/dist/__tests__/sent-sweep-throttle.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/__tests__/sent-sweep-throttle.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/__tests__/sent-sweep-throttle.test.js +18 -0
- package/payload/platform/plugins/scheduling/mcp/dist/__tests__/sent-sweep-throttle.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/booking-block-sqlite.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/booking-block-sqlite.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/booking-block-sqlite.test.js +150 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/booking-block-sqlite.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/booking-block.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/booking-block.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/booking-block.test.js +248 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/booking-block.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/booking-reconcile.d.ts +90 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/booking-reconcile.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/booking-reconcile.js +105 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/booking-reconcile.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/sent-sweep-throttle.d.ts +13 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/sent-sweep-throttle.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/sent-sweep-throttle.js +10 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/sent-sweep-throttle.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js +53 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js +88 -10
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js.map +1 -1
- package/payload/platform/scripts/cpu-triage-run.sh +117 -0
- package/payload/platform/scripts/cpu-triage.sh +332 -0
- package/payload/platform/services/claude-session-manager/dist/activity-range.d.ts +40 -0
- package/payload/platform/services/claude-session-manager/dist/activity-range.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/activity-range.js +68 -0
- package/payload/platform/services/claude-session-manager/dist/activity-range.js.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/activity-rows.d.ts +40 -8
- package/payload/platform/services/claude-session-manager/dist/activity-rows.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/activity-rows.js +74 -7
- package/payload/platform/services/claude-session-manager/dist/activity-rows.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +2 -0
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.js +9 -0
- package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
- package/payload/server/{chunk-56WJMBQQ.js → chunk-3XLLTG6R.js} +14 -0
- package/payload/server/{chunk-LBCMFD4O.js → chunk-XGNRSM57.js} +129 -37
- package/payload/server/maxy-edge.js +1 -1
- package/payload/server/public/activity.html +6 -6
- package/payload/server/public/assets/{AdminLoginScreens-DximwPlS.js → AdminLoginScreens-DR5eLF-a.js} +1 -1
- package/payload/server/public/assets/AdminShell-D9zaUxPd.js +2 -0
- package/payload/server/public/assets/{Checkbox-DM-eHqOS.js → Checkbox-DcbbAIe5.js} +1 -1
- package/payload/server/public/assets/activity-C9P5NjEZ.js +1 -0
- package/payload/server/public/assets/{admin-CAkDnGdk.js → admin-D2KLZnQW.js} +1 -1
- package/payload/server/public/assets/{browser-DXl8hOoi.js → browser-CDWqEiCD.js} +1 -1
- package/payload/server/public/assets/{calendar-DP6hn4-6.js → calendar-BG7fOpbB.js} +1 -1
- package/payload/server/public/assets/chat-RyH-WYQC.js +1 -0
- package/payload/server/public/assets/chevron-left-DmXCr6nB.js +1 -0
- package/payload/server/public/assets/data-BaY_LkLR.js +1 -0
- package/payload/server/public/assets/{graph-CHcYoEJ5.js → graph-DRloNic4.js} +1 -1
- package/payload/server/public/assets/{graph-labels-CZykslZM.js → graph-labels-DD-GqS4v.js} +1 -1
- package/payload/server/public/assets/{maximize-2-31AZEcMS.js → maximize-2-CzDaBugs.js} +1 -1
- package/payload/server/public/assets/{operator-BGGpdsO_.js → operator-BZeeyait.js} +1 -1
- package/payload/server/public/assets/{page-BloC6ygA.js → page-B0obcg3b.js} +1 -1
- package/payload/server/public/assets/{page-DOeiiqbR.js → page-ef-6rRPL.js} +1 -1
- package/payload/server/public/assets/{public-CGgO6IZv.js → public-9D3MMOkC.js} +1 -1
- package/payload/server/public/assets/{rotate-ccw-BlAi6iFg.js → rotate-ccw-DXEKUhXP.js} +1 -1
- package/payload/server/public/assets/tasks-BB0L7e5a.js +1 -0
- package/payload/server/public/assets/{time-entry-format-CiUUQdq7.js → time-entry-format-CsYAjplS.js} +1 -1
- package/payload/server/public/assets/{triangle-alert-CVqKuLoa.js → triangle-alert-0lSBIUg-.js} +1 -1
- package/payload/server/public/assets/{useCopyFeedback-ksyUe_g1.js → useCopyFeedback-jTBQ2h0V.js} +1 -1
- package/payload/server/public/assets/{useSelectionMode-BPrBkdTd.js → useSelectionMode-BooArySZ.js} +1 -1
- package/payload/server/public/assets/useSubAccountSwitcher-D9knHOKq.css +1 -0
- package/payload/server/public/assets/{useVoiceRecorder-CTXP8oTW.js → useVoiceRecorder-PUT8q_sm.js} +1 -1
- package/payload/server/public/browser.html +5 -5
- package/payload/server/public/calendar.html +6 -6
- package/payload/server/public/chat.html +12 -12
- package/payload/server/public/data.html +11 -11
- package/payload/server/public/graph.html +11 -11
- package/payload/server/public/index.html +14 -14
- package/payload/server/public/operator.html +14 -14
- package/payload/server/public/public.html +12 -12
- package/payload/server/public/tasks.html +5 -5
- package/payload/server/server.js +325 -77
- package/payload/server/{src-JYPKMWJR.js → src-XQ63FPRE.js} +3 -1
- package/payload/server/public/assets/AdminShell-BehbH-Oa.js +0 -2
- package/payload/server/public/assets/activity-hDwUeQd6.js +0 -1
- package/payload/server/public/assets/chat-DhOfVGYM.js +0 -1
- package/payload/server/public/assets/chevron-left-DYNBoLii.js +0 -1
- package/payload/server/public/assets/data-bq8fTo_s.js +0 -1
- package/payload/server/public/assets/tasks-C1giFRRL.js +0 -1
- package/payload/server/public/assets/useSubAccountSwitcher-K4kYeN6i.css +0 -1
- /package/payload/server/public/assets/{useSubAccountSwitcher-DzgzTRRn.js → useSubAccountSwitcher-BZnzc5C3.js} +0 -0
package/payload/server/server.js
CHANGED
|
@@ -97,6 +97,8 @@ import {
|
|
|
97
97
|
runAdminUserSelfHeal,
|
|
98
98
|
runUserProfileReconcile,
|
|
99
99
|
safeJson,
|
|
100
|
+
sampleCpu,
|
|
101
|
+
sampleProcessCpu,
|
|
100
102
|
sanitizeClientCorrId,
|
|
101
103
|
serve,
|
|
102
104
|
setAccessPassword,
|
|
@@ -115,7 +117,7 @@ import {
|
|
|
115
117
|
vncLog,
|
|
116
118
|
walkPremiumBundles,
|
|
117
119
|
writeAdminUserAndPerson
|
|
118
|
-
} from "./chunk-
|
|
120
|
+
} from "./chunk-XGNRSM57.js";
|
|
119
121
|
import {
|
|
120
122
|
D1_MAX_SQL_STATEMENT_BYTES,
|
|
121
123
|
D1_QUERY_MAX_BODY_BYTES,
|
|
@@ -127,10 +129,11 @@ import {
|
|
|
127
129
|
listResources,
|
|
128
130
|
makeHouseCfExec,
|
|
129
131
|
makeHousePagesExec,
|
|
132
|
+
reconcileDataPortal,
|
|
130
133
|
registerResource,
|
|
131
134
|
resolveOwner,
|
|
132
135
|
tooLargeMessage
|
|
133
|
-
} from "./chunk-
|
|
136
|
+
} from "./chunk-3XLLTG6R.js";
|
|
134
137
|
import {
|
|
135
138
|
__commonJS,
|
|
136
139
|
__toESM
|
|
@@ -9635,59 +9638,148 @@ app3.post("/r2/object/delete", envelopeBodyLimit("write"), async (c) => {
|
|
|
9635
9638
|
});
|
|
9636
9639
|
var storage_broker_default = app3;
|
|
9637
9640
|
async function runStorageAudit(root) {
|
|
9638
|
-
const { reconcileStorage } = await import("./src-
|
|
9639
|
-
const
|
|
9640
|
-
|
|
9641
|
-
|
|
9642
|
-
|
|
9643
|
-
|
|
9644
|
-
|
|
9645
|
-
|
|
9646
|
-
|
|
9641
|
+
const { reconcileStorage } = await import("./src-XQ63FPRE.js");
|
|
9642
|
+
const cf = await makeHouseCfExec(root);
|
|
9643
|
+
const accountsDir = resolve11(root, "..", "data", "accounts");
|
|
9644
|
+
const strays = (await reconcileStorage({
|
|
9645
|
+
cfD1: async () => (await cf.d1List()).map((d) => d.name),
|
|
9646
|
+
cfR2: async () => (await cf.r2List()).map((b) => b.name),
|
|
9647
|
+
// Its own session per invocation, never one captured from the enclosing
|
|
9648
|
+
// scope. reconcileStorage issues the "d1" and "r2" reads through the same
|
|
9649
|
+
// Promise.all, and a Neo4j session admits one query at a time — sharing one
|
|
9650
|
+
// made the second reject, which left this audit reporting nothing for 802
|
|
9651
|
+
// consecutive ticks on maxy-code and 295 on sitedesk-code. Sessions come
|
|
9652
|
+
// from the driver pool, so one per read is cheap; the alternative,
|
|
9653
|
+
// serialising the library's fan-out, would bend it around this caller.
|
|
9654
|
+
registeredNames: async (kind) => {
|
|
9655
|
+
const session = getSession();
|
|
9656
|
+
try {
|
|
9647
9657
|
const res = await session.run(
|
|
9648
9658
|
"MATCH (r:StorageResource {kind: $kind}) RETURN r.name AS name",
|
|
9649
9659
|
{ kind }
|
|
9650
9660
|
);
|
|
9651
9661
|
return res.records.map((rec) => rec.get("name"));
|
|
9652
|
-
}
|
|
9653
|
-
|
|
9654
|
-
if (!existsSync9(accountsDir)) return [];
|
|
9655
|
-
const files = [];
|
|
9656
|
-
for (const accountId of readdirSync8(accountsDir)) {
|
|
9657
|
-
const p = join13(accountsDir, accountId, "secrets", "cloudflare.env");
|
|
9658
|
-
if (existsSync9(p)) files.push({ accountId, path: p, contents: readFileSync15(p, "utf8") });
|
|
9659
|
-
}
|
|
9660
|
-
return files;
|
|
9662
|
+
} finally {
|
|
9663
|
+
await session.close();
|
|
9661
9664
|
}
|
|
9662
|
-
}
|
|
9663
|
-
|
|
9664
|
-
|
|
9665
|
-
|
|
9666
|
-
|
|
9667
|
-
|
|
9668
|
-
|
|
9665
|
+
},
|
|
9666
|
+
accountSecretsFiles: async () => {
|
|
9667
|
+
if (!existsSync9(accountsDir)) return [];
|
|
9668
|
+
const files = [];
|
|
9669
|
+
for (const accountId of readdirSync8(accountsDir)) {
|
|
9670
|
+
const p = join13(accountsDir, accountId, "secrets", "cloudflare.env");
|
|
9671
|
+
if (existsSync9(p)) files.push({ accountId, path: p, contents: readFileSync15(p, "utf8") });
|
|
9672
|
+
}
|
|
9673
|
+
return files;
|
|
9674
|
+
}
|
|
9675
|
+
})).strays;
|
|
9676
|
+
console.error(
|
|
9677
|
+
`[storage-audit] strays=${strays.length}${strays.map((s) => ` ${s.kind}:${s.detail}`).join("")}`
|
|
9678
|
+
);
|
|
9669
9679
|
}
|
|
9670
9680
|
async function runPagesAudit(root) {
|
|
9671
|
-
const { reconcilePages } = await import("./src-
|
|
9672
|
-
const
|
|
9673
|
-
|
|
9674
|
-
|
|
9675
|
-
|
|
9676
|
-
|
|
9677
|
-
|
|
9681
|
+
const { reconcilePages } = await import("./src-XQ63FPRE.js");
|
|
9682
|
+
const cf = await makeHousePagesExec(root);
|
|
9683
|
+
const r = await reconcilePages({
|
|
9684
|
+
cfProjects: async () => (await cf.pagesProjectList()).map((p) => p.name),
|
|
9685
|
+
// Its own session per invocation, same rule as runStorageAudit above and
|
|
9686
|
+
// for the same reason. This previously held one session opened in the
|
|
9687
|
+
// enclosing scope, which was safe only because reconcilePages issues
|
|
9688
|
+
// exactly one registry query — a property of the library, not of this
|
|
9689
|
+
// caller. A second read added there would have reproduced 1813 here
|
|
9690
|
+
// verbatim. The old shape also held that session open across
|
|
9691
|
+
// makeHousePagesExec's network I/O, which is a pooled connection parked
|
|
9692
|
+
// for the length of a Cloudflare round trip.
|
|
9693
|
+
registeredProjects: async () => {
|
|
9694
|
+
const session = getSession();
|
|
9695
|
+
try {
|
|
9678
9696
|
const res = await session.run(
|
|
9679
9697
|
"MATCH (r:StorageResource {kind: $kind}) RETURN r.name AS name",
|
|
9680
9698
|
{ kind: "pages" }
|
|
9681
9699
|
);
|
|
9682
9700
|
return res.records.map((rec) => rec.get("name"));
|
|
9701
|
+
} finally {
|
|
9702
|
+
await session.close();
|
|
9683
9703
|
}
|
|
9684
|
-
}
|
|
9704
|
+
}
|
|
9705
|
+
});
|
|
9706
|
+
console.error(
|
|
9707
|
+
`[pages-audit] projects=${r.projects} registered=${r.registered} orphan=${r.orphans.length} phantom=${r.phantoms.length}` + r.orphans.map((n) => ` orphan:${n}`).join("") + r.phantoms.map((n) => ` phantom:${n}`).join("")
|
|
9708
|
+
);
|
|
9709
|
+
}
|
|
9710
|
+
function parseManifestRows(raw) {
|
|
9711
|
+
const envelope = Array.isArray(raw) ? raw[0] : null;
|
|
9712
|
+
const results = envelope?.results;
|
|
9713
|
+
if (!Array.isArray(results)) {
|
|
9714
|
+
throw new Error(`unexpected d1 payload: envelope carries no results array`);
|
|
9715
|
+
}
|
|
9716
|
+
return results.map((r, i) => {
|
|
9717
|
+
const row = r;
|
|
9718
|
+
const bad = ["objectKey", "ingested", "uploadedAt"].find(
|
|
9719
|
+
(f) => f === "ingested" ? typeof row[f] !== "number" : typeof row[f] !== "string"
|
|
9720
|
+
);
|
|
9721
|
+
if (bad) throw new Error(`unexpected d1 row: index=${i} field=${bad} type=${typeof row[bad]}`);
|
|
9722
|
+
return { objectKey: row.objectKey, ingested: row.ingested, uploadedAt: row.uploadedAt };
|
|
9723
|
+
});
|
|
9724
|
+
}
|
|
9725
|
+
function auditErrorText(message) {
|
|
9726
|
+
return message.split("\n")[0].replaceAll('"', "'").slice(0, 160);
|
|
9727
|
+
}
|
|
9728
|
+
function discoverPortalAccounts(accountsDir) {
|
|
9729
|
+
if (!existsSync9(accountsDir)) return [];
|
|
9730
|
+
const found = [];
|
|
9731
|
+
for (const accountId of readdirSync8(accountsDir)) {
|
|
9732
|
+
const configPath2 = join13(accountsDir, accountId, "data-portal.json");
|
|
9733
|
+
if (!existsSync9(configPath2)) continue;
|
|
9734
|
+
try {
|
|
9735
|
+
const cfg = JSON.parse(readFileSync15(configPath2, "utf-8"));
|
|
9736
|
+
if (typeof cfg.portalDbName === "string" && cfg.portalDbName.length > 0 && typeof cfg.bucketName === "string" && cfg.bucketName.length > 0) {
|
|
9737
|
+
found.push({ accountId, portalDbName: cfg.portalDbName, bucketName: cfg.bucketName });
|
|
9738
|
+
}
|
|
9739
|
+
} catch {
|
|
9740
|
+
}
|
|
9741
|
+
}
|
|
9742
|
+
return found;
|
|
9743
|
+
}
|
|
9744
|
+
async function runDataPortalAudit(root) {
|
|
9745
|
+
const portals = discoverPortalAccounts(resolve11(root, "..", "data", "accounts"));
|
|
9746
|
+
if (portals.length === 0) return "portals=0 degraded=0";
|
|
9747
|
+
const cf = await makeHouseCfExec(root);
|
|
9748
|
+
let degraded = 0;
|
|
9749
|
+
for (const portal of portals) {
|
|
9750
|
+
let rows = null;
|
|
9751
|
+
let d1Error = null;
|
|
9752
|
+
try {
|
|
9753
|
+
rows = parseManifestRows(
|
|
9754
|
+
await cf.d1Query(
|
|
9755
|
+
portal.portalDbName,
|
|
9756
|
+
"SELECT objectKey, ingested, uploadedAt FROM manifest"
|
|
9757
|
+
)
|
|
9758
|
+
);
|
|
9759
|
+
} catch (err) {
|
|
9760
|
+
d1Error = err.message;
|
|
9761
|
+
}
|
|
9762
|
+
let objects = null;
|
|
9763
|
+
let r2Error = null;
|
|
9764
|
+
try {
|
|
9765
|
+
objects = await cf.r2ObjectList(portal.bucketName);
|
|
9766
|
+
} catch (err) {
|
|
9767
|
+
r2Error = err.message;
|
|
9768
|
+
}
|
|
9769
|
+
const nowMs = Date.now();
|
|
9770
|
+
const reconciled = rows !== null && objects !== null ? reconcileDataPortal(objects, rows, nowMs) : null;
|
|
9771
|
+
const ageHrs = rows === null ? null : reconcileDataPortal([], rows, nowMs).oldestUningestedHrs;
|
|
9772
|
+
const degradation = [d1Error !== null ? "d1" : null, r2Error !== null ? "r2" : null].filter(Boolean).join("+");
|
|
9773
|
+
if (degradation) degraded += 1;
|
|
9774
|
+
const reasons = [
|
|
9775
|
+
d1Error !== null ? `d1:${auditErrorText(d1Error)}` : null,
|
|
9776
|
+
r2Error !== null ? `r2:${auditErrorText(r2Error)}` : null
|
|
9777
|
+
].filter(Boolean).join(" | ");
|
|
9685
9778
|
console.error(
|
|
9686
|
-
`[
|
|
9779
|
+
`[data-portal-audit] account=${portal.accountId} objects=${objects?.length ?? "na"} rows=${rows?.length ?? "na"} orphanObjects=${reconciled?.orphanObjects.length ?? "na"} phantomRows=${reconciled?.phantomRows.length ?? "na"} oldestUningestedHrs=${ageHrs?.toFixed(1) ?? "na"}` + (degradation ? ` degraded=${degradation} err="${reasons}"` : "")
|
|
9687
9780
|
);
|
|
9688
|
-
} finally {
|
|
9689
|
-
await session.close();
|
|
9690
9781
|
}
|
|
9782
|
+
return `portals=${portals.length} degraded=${degraded}`;
|
|
9691
9783
|
}
|
|
9692
9784
|
|
|
9693
9785
|
// server/google-pending-audit.ts
|
|
@@ -13905,12 +13997,21 @@ function checkRateLimit2(ip, cls) {
|
|
|
13905
13997
|
}
|
|
13906
13998
|
return { allow: true, blocked: 0, shouldLog: false };
|
|
13907
13999
|
}
|
|
13908
|
-
|
|
13909
|
-
|
|
13910
|
-
|
|
13911
|
-
|
|
14000
|
+
registerLoop({
|
|
14001
|
+
name: "client-error-rate-cleanup",
|
|
14002
|
+
intervalMs: WINDOW_MS,
|
|
14003
|
+
run: () => {
|
|
14004
|
+
const now = Date.now();
|
|
14005
|
+
let purged = 0;
|
|
14006
|
+
for (const [key, rec] of rateHits) {
|
|
14007
|
+
if (now - rec.windowStart >= WINDOW_MS * 2) {
|
|
14008
|
+
rateHits.delete(key);
|
|
14009
|
+
purged += 1;
|
|
14010
|
+
}
|
|
14011
|
+
}
|
|
14012
|
+
return `purged ${purged}, ${rateHits.size} live`;
|
|
13912
14013
|
}
|
|
13913
|
-
}
|
|
14014
|
+
});
|
|
13914
14015
|
function truncate(value, max) {
|
|
13915
14016
|
if (typeof value !== "string") return "";
|
|
13916
14017
|
return value.length > max ? value.slice(0, max) + "\u2026" : value;
|
|
@@ -21998,16 +22099,32 @@ app47.get("/", requireAdminSession, async (c) => {
|
|
|
21998
22099
|
WHERE te.endedAt IS NULL
|
|
21999
22100
|
WITH t, te ORDER BY te.startedAt
|
|
22000
22101
|
WITH t, head(collect(te)) AS openTe
|
|
22102
|
+
// OPTIONAL is load-bearing. Unassigned is the common state, so a plain
|
|
22103
|
+
// MATCH would silently drop most of the list with nothing looking wrong.
|
|
22104
|
+
OPTIONAL MATCH (t)-[:ASSIGNED_TO]->(a:AdminUser)
|
|
22105
|
+
// head(collect(...)) for the same reason the TimeEntry match above uses
|
|
22106
|
+
// it: a second ASSIGNED_TO edge would fan the row out, duplicating
|
|
22107
|
+
// rowKey and double-counting the assignee.
|
|
22108
|
+
WITH t, openTe, head(collect(a)) AS assignee
|
|
22001
22109
|
RETURN t.taskId AS taskId, elementId(t) AS rowKey, t.name AS name, t.clientName AS clientName,
|
|
22002
22110
|
t.propertyAddress AS propertyAddress, t.fee AS fee, t.status AS status,
|
|
22003
22111
|
coalesce(t.secondsLogged, 0) AS secondsLogged,
|
|
22004
|
-
openTe.startedAt AS runningStartedAt
|
|
22112
|
+
openTe.startedAt AS runningStartedAt,
|
|
22113
|
+
t.createdAt AS createdAt,
|
|
22114
|
+
assignee.userId AS assigneeUserId, assignee.name AS assigneeName
|
|
22005
22115
|
ORDER BY t.createdAt DESC`,
|
|
22006
22116
|
{ accountId }
|
|
22007
22117
|
);
|
|
22118
|
+
const totalResult = await session.run(
|
|
22119
|
+
`MATCH (t:Task {accountId: $accountId}) RETURN count(t) AS total`,
|
|
22120
|
+
{ accountId }
|
|
22121
|
+
);
|
|
22122
|
+
const graphTotal = totalResult.records.length > 0 ? toNum(totalResult.records[0].get("total")) : 0;
|
|
22008
22123
|
const open = [];
|
|
22009
22124
|
const completed = [];
|
|
22010
22125
|
let missingTaskId = 0;
|
|
22126
|
+
let missingCreatedAt = 0;
|
|
22127
|
+
let assigned = 0;
|
|
22011
22128
|
for (const rec of result.records) {
|
|
22012
22129
|
const status = rec.get("status") ?? "pending";
|
|
22013
22130
|
const runningStartedAt = rec.get("runningStartedAt") ?? null;
|
|
@@ -22015,6 +22132,10 @@ app47.get("/", requireAdminSession, async (c) => {
|
|
|
22015
22132
|
const rawTaskId = rec.get("taskId");
|
|
22016
22133
|
const taskId = typeof rawTaskId === "string" && rawTaskId !== "" ? rawTaskId : null;
|
|
22017
22134
|
if (taskId === null) missingTaskId++;
|
|
22135
|
+
const createdAt = rec.get("createdAt") ?? null;
|
|
22136
|
+
if (createdAt === null) missingCreatedAt++;
|
|
22137
|
+
const assigneeUserId = rec.get("assigneeUserId") ?? null;
|
|
22138
|
+
if (assigneeUserId !== null) assigned++;
|
|
22018
22139
|
const row = {
|
|
22019
22140
|
taskId,
|
|
22020
22141
|
rowKey: rec.get("rowKey"),
|
|
@@ -22025,12 +22146,23 @@ app47.get("/", requireAdminSession, async (c) => {
|
|
|
22025
22146
|
status,
|
|
22026
22147
|
secondsLogged: toNum(rec.get("secondsLogged")),
|
|
22027
22148
|
running: runningStartedAt !== null,
|
|
22028
|
-
runningStartedAt
|
|
22149
|
+
runningStartedAt,
|
|
22150
|
+
createdAt,
|
|
22151
|
+
assigneeUserId,
|
|
22152
|
+
assigneeName: rec.get("assigneeName") ?? null
|
|
22029
22153
|
};
|
|
22030
22154
|
if (COMPLETED.has(status)) completed.push(row);
|
|
22031
22155
|
else if (!HIDDEN_FROM_OPEN.has(status)) open.push(row);
|
|
22032
22156
|
}
|
|
22033
|
-
|
|
22157
|
+
const returned = result.records.length;
|
|
22158
|
+
if (returned < graphTotal) {
|
|
22159
|
+
console.error(
|
|
22160
|
+
`${TAG37} op=list row-count-shortfall account=${accountId} returned=${returned} graphTotal=${graphTotal} missing=${graphTotal - returned}`
|
|
22161
|
+
);
|
|
22162
|
+
}
|
|
22163
|
+
console.log(
|
|
22164
|
+
`${TAG37} op=list account=${accountId} returned=${returned} graphTotal=${graphTotal} open=${open.length} completed=${completed.length} missingTaskId=${missingTaskId} missingCreatedAt=${missingCreatedAt} assigned=${assigned}`
|
|
22165
|
+
);
|
|
22034
22166
|
return c.json({ open, completed });
|
|
22035
22167
|
} catch (err) {
|
|
22036
22168
|
console.error(`${TAG37} op=list error="${err instanceof Error ? err.message : String(err)}"`);
|
|
@@ -22348,7 +22480,13 @@ app52.get("/", requireAdminSession, async (c) => {
|
|
|
22348
22480
|
const start = Date.now();
|
|
22349
22481
|
let res;
|
|
22350
22482
|
try {
|
|
22351
|
-
|
|
22483
|
+
const qs = new URLSearchParams();
|
|
22484
|
+
const from = c.req.query("from");
|
|
22485
|
+
const to = c.req.query("to");
|
|
22486
|
+
if (from) qs.set("from", from);
|
|
22487
|
+
if (to) qs.set("to", to);
|
|
22488
|
+
const suffix = qs.size > 0 ? `?${qs.toString()}` : "";
|
|
22489
|
+
res = await fetch(`${managerBase("activity:wrapper")}/activity${suffix}`, {
|
|
22352
22490
|
signal: AbortSignal.timeout(3e4)
|
|
22353
22491
|
});
|
|
22354
22492
|
} catch (err) {
|
|
@@ -22386,6 +22524,9 @@ app52.get("/", requireAdminSession, async (c) => {
|
|
|
22386
22524
|
if (name) names[a.accountId] = name;
|
|
22387
22525
|
})
|
|
22388
22526
|
);
|
|
22527
|
+
const sampledAt = Date.now();
|
|
22528
|
+
sampleCpu(sampledAt);
|
|
22529
|
+
const cpu = sampleProcessCpu(sampledAt);
|
|
22389
22530
|
const loopRows = listLoops();
|
|
22390
22531
|
const armed2 = armedCount();
|
|
22391
22532
|
const byState = loopRows.reduce((acc, r) => {
|
|
@@ -22393,13 +22534,27 @@ app52.get("/", requireAdminSession, async (c) => {
|
|
|
22393
22534
|
return acc;
|
|
22394
22535
|
}, {});
|
|
22395
22536
|
console.log(
|
|
22396
|
-
`${TAG42} op=loops req=${req} armed=${armed2} rendered=${loopRows.length} ` + Object.entries(byState).map(([s, n]) => `${s}=${n}`).join(" ")
|
|
22537
|
+
`${TAG42} op=loops req=${req} armed=${armed2} rendered=${loopRows.length} procPct=${cpu.processPct?.toFixed(1) ?? "null"} attributedPct=${cpu.attributedPct?.toFixed(1) ?? "null"} ` + Object.entries(byState).map(([s, n]) => `${s}=${n}`).join(" ")
|
|
22397
22538
|
);
|
|
22398
22539
|
return c.json({
|
|
22399
22540
|
rows,
|
|
22400
22541
|
census,
|
|
22401
22542
|
censusAgeMs,
|
|
22402
|
-
|
|
22543
|
+
// `satisfies` and not a bare literal (Task 1825). LoopsPayload is what the
|
|
22544
|
+
// activity page destructures; without the check, a key renamed or dropped
|
|
22545
|
+
// here still compiles and the page reads undefined, which its own
|
|
22546
|
+
// vocabulary renders as a dash meaning "not measured". The check runs both
|
|
22547
|
+
// ways: a key the page does not know about fails as an excess property.
|
|
22548
|
+
loops: {
|
|
22549
|
+
armed: armed2,
|
|
22550
|
+
rows: loopRows,
|
|
22551
|
+
// The server's own CPU beside what the registry can explain. The GAP is
|
|
22552
|
+
// the point: loops summing to 2% against a process at 60% says the cost
|
|
22553
|
+
// is somewhere else, which small numbers alone would never tell you.
|
|
22554
|
+
processPct: cpu.processPct,
|
|
22555
|
+
attributedPct: cpu.attributedPct,
|
|
22556
|
+
unattributedPct: cpu.unattributedPct
|
|
22557
|
+
},
|
|
22403
22558
|
accounts: {
|
|
22404
22559
|
onDisk,
|
|
22405
22560
|
valid: valid.length,
|
|
@@ -23143,12 +23298,21 @@ function rateLimit(ip, now = Date.now()) {
|
|
|
23143
23298
|
if (b.count > RATE_LIMIT) return { ok: false, resetIn: b.resetAt - now };
|
|
23144
23299
|
return { ok: true, resetIn: b.resetAt - now };
|
|
23145
23300
|
}
|
|
23146
|
-
|
|
23147
|
-
|
|
23148
|
-
|
|
23149
|
-
|
|
23301
|
+
registerLoop({
|
|
23302
|
+
name: "visitor-event-rate-cleanup",
|
|
23303
|
+
intervalMs: 5 * RATE_WINDOW_MS,
|
|
23304
|
+
run: () => {
|
|
23305
|
+
const now = Date.now();
|
|
23306
|
+
let purged = 0;
|
|
23307
|
+
for (const [ip, b] of buckets) {
|
|
23308
|
+
if (now >= b.resetAt) {
|
|
23309
|
+
buckets.delete(ip);
|
|
23310
|
+
purged += 1;
|
|
23311
|
+
}
|
|
23312
|
+
}
|
|
23313
|
+
return `purged ${purged}, ${buckets.size} live`;
|
|
23150
23314
|
}
|
|
23151
|
-
}
|
|
23315
|
+
});
|
|
23152
23316
|
var VALID_TYPES = /* @__PURE__ */ new Set(["pageview", "click", "scroll", "dwell"]);
|
|
23153
23317
|
var ID_RE = /^[A-Za-z0-9_-]{6,128}$/;
|
|
23154
23318
|
function parseEvent(body) {
|
|
@@ -24976,10 +25140,28 @@ var WaGateway = class {
|
|
|
24976
25140
|
}
|
|
24977
25141
|
return events;
|
|
24978
25142
|
}
|
|
24979
|
-
/**
|
|
24980
|
-
*
|
|
25143
|
+
/** Arm the periodic reconciliation sweep in the long-lived UI process.
|
|
25144
|
+
*
|
|
25145
|
+
* Task 1814 — armed through the registry, so it appears on /activity. This
|
|
25146
|
+
* gateway is constructed once at module scope in server/index.ts and reached
|
|
25147
|
+
* everywhere else through the singleton accessor in ./instance, so the sweep
|
|
25148
|
+
* is per-install, not per-instance. Returns the registry's disarm function
|
|
25149
|
+
* rather than the interval handle; no caller reads it.
|
|
25150
|
+
*
|
|
25151
|
+
* Two semantics move with it. The timer is now unref'd, where the bare
|
|
25152
|
+
* setInterval was not: a loop is a passenger of the process, never what
|
|
25153
|
+
* keeps it alive. And a throwing sweep is recorded as lastError instead of
|
|
25154
|
+
* surfacing as an uncaught timer exception, so a sweep that fails every
|
|
25155
|
+
* tick now reads as a failing row on /activity rather than a crash. */
|
|
24981
25156
|
startSweeper(intervalMs = SWEEP_INTERVAL_MS) {
|
|
24982
|
-
return
|
|
25157
|
+
return registerLoop({
|
|
25158
|
+
name: "whatsapp-native-sweep",
|
|
25159
|
+
intervalMs,
|
|
25160
|
+
run: () => {
|
|
25161
|
+
const events = this.reconcile(Date.now());
|
|
25162
|
+
return events.length > 0 ? `${events.length} terminal events` : void 0;
|
|
25163
|
+
}
|
|
25164
|
+
});
|
|
24983
25165
|
}
|
|
24984
25166
|
/** Handle one inbound admin WhatsApp message. */
|
|
24985
25167
|
async handleInbound(input) {
|
|
@@ -25552,11 +25734,22 @@ var WebchatGateway = class _WebchatGateway {
|
|
|
25552
25734
|
void this.deps.deleteSession?.(rec.sessionId);
|
|
25553
25735
|
}
|
|
25554
25736
|
}
|
|
25555
|
-
/**
|
|
25737
|
+
/** Arm the periodic public idle reaper in the long-lived UI process.
|
|
25738
|
+
*
|
|
25739
|
+
* Task 1814 — armed through the registry, so it appears on /activity. Like
|
|
25740
|
+
* the sweeper below, this is per-install: one gateway per server, reached
|
|
25741
|
+
* through the singleton accessor in ./instance. Returns the registry's
|
|
25742
|
+
* disarm function rather than the interval handle; no caller reads it.
|
|
25743
|
+
*
|
|
25744
|
+
* This one already unref'd its handle, so only the error semantics move: a
|
|
25745
|
+
* throwing reap is recorded as lastError rather than surfacing as an
|
|
25746
|
+
* uncaught timer exception. */
|
|
25556
25747
|
startPublicReaper(intervalMs = 6e4) {
|
|
25557
|
-
|
|
25558
|
-
|
|
25559
|
-
|
|
25748
|
+
return registerLoop({
|
|
25749
|
+
name: "webchat-public-reaper",
|
|
25750
|
+
intervalMs,
|
|
25751
|
+
run: () => this.reapPublic(Date.now())
|
|
25752
|
+
});
|
|
25560
25753
|
}
|
|
25561
25754
|
/** A gated public PTY exited explicitly on the manager side (operator stop,
|
|
25562
25755
|
* claude crash, manager DELETE), not via the idle reaper. The manager POSTs
|
|
@@ -25638,15 +25831,36 @@ var WebchatGateway = class _WebchatGateway {
|
|
|
25638
25831
|
}
|
|
25639
25832
|
return events;
|
|
25640
25833
|
}
|
|
25641
|
-
/**
|
|
25834
|
+
/** Arm the periodic reconciliation sweep in the long-lived UI process. Each
|
|
25642
25835
|
* tick runs the sync sweep (drain-/inbound-undelivered) AND the async
|
|
25643
|
-
* recovery pass for queued-no-subscriber messages (Task-962).
|
|
25836
|
+
* recovery pass for queued-no-subscriber messages (Task-962).
|
|
25837
|
+
*
|
|
25838
|
+
* Task 1814 — armed through the registry, so it appears on /activity. This
|
|
25839
|
+
* gateway is constructed once at module scope in server/index.ts and reached
|
|
25840
|
+
* everywhere else through the singleton accessor in ./instance, so the sweep
|
|
25841
|
+
* is per-install, not per-instance. Returns the registry's disarm function
|
|
25842
|
+
* rather than the interval handle; no caller reads it.
|
|
25843
|
+
*
|
|
25844
|
+
* Two semantics move with it. The timer is now unref'd, where the bare
|
|
25845
|
+
* setInterval was not: a loop is a passenger of the process, never what
|
|
25846
|
+
* keeps it alive. And a throwing sweep is recorded as lastError instead of
|
|
25847
|
+
* surfacing as an uncaught timer exception, so a sweep that fails every
|
|
25848
|
+
* tick now reads as a failing row on /activity rather than a crash.
|
|
25849
|
+
*
|
|
25850
|
+
* recoverStalled stays fire-and-forget, exactly as it was: run() returns the
|
|
25851
|
+
* sync note, so the registry's duration covers the sweep and not the
|
|
25852
|
+
* recovery pass. */
|
|
25644
25853
|
startSweeper(intervalMs = SWEEP_INTERVAL_MS2) {
|
|
25645
|
-
return
|
|
25646
|
-
|
|
25647
|
-
|
|
25648
|
-
|
|
25649
|
-
|
|
25854
|
+
return registerLoop({
|
|
25855
|
+
name: "webchat-inbound-sweep",
|
|
25856
|
+
intervalMs,
|
|
25857
|
+
run: () => {
|
|
25858
|
+
const now = Date.now();
|
|
25859
|
+
const events = this.reconcile(now);
|
|
25860
|
+
void this.recoverStalled(now);
|
|
25861
|
+
return events.length > 0 ? `${events.length} terminal events` : void 0;
|
|
25862
|
+
}
|
|
25863
|
+
});
|
|
25650
25864
|
}
|
|
25651
25865
|
/** Task-962 — the per-session delivery-failure marker for the /session pointer.
|
|
25652
25866
|
* Non-null only when redelivery was exhausted for `key`; cleared on the next
|
|
@@ -26584,9 +26798,28 @@ var TelegramGateway = class {
|
|
|
26584
26798
|
}
|
|
26585
26799
|
return events;
|
|
26586
26800
|
}
|
|
26587
|
-
/**
|
|
26801
|
+
/** Arm the periodic reconciliation sweep in the long-lived UI process.
|
|
26802
|
+
*
|
|
26803
|
+
* Task 1814 — armed through the registry, so it appears on /activity. This
|
|
26804
|
+
* gateway is constructed once at module scope in server/index.ts and reached
|
|
26805
|
+
* everywhere else through the singleton accessor in ./instance, so the sweep
|
|
26806
|
+
* is per-install, not per-instance. Returns the registry's disarm function
|
|
26807
|
+
* rather than the interval handle; no caller reads it.
|
|
26808
|
+
*
|
|
26809
|
+
* Two semantics move with it. The timer is now unref'd, where the bare
|
|
26810
|
+
* setInterval was not: a loop is a passenger of the process, never what
|
|
26811
|
+
* keeps it alive. And a throwing sweep is recorded as lastError instead of
|
|
26812
|
+
* surfacing as an uncaught timer exception, so a sweep that fails every
|
|
26813
|
+
* tick now reads as a failing row on /activity rather than a crash. */
|
|
26588
26814
|
startSweeper(intervalMs = SWEEP_INTERVAL_MS3) {
|
|
26589
|
-
return
|
|
26815
|
+
return registerLoop({
|
|
26816
|
+
name: "telegram-native-sweep",
|
|
26817
|
+
intervalMs,
|
|
26818
|
+
run: () => {
|
|
26819
|
+
const events = this.reconcile(Date.now());
|
|
26820
|
+
return events.length > 0 ? `${events.length} terminal events` : void 0;
|
|
26821
|
+
}
|
|
26822
|
+
});
|
|
26590
26823
|
}
|
|
26591
26824
|
/** Handle one inbound telegram message. */
|
|
26592
26825
|
async handleInbound(input) {
|
|
@@ -28511,7 +28744,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
28511
28744
|
const reconcilePlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join42(__dirname, "..");
|
|
28512
28745
|
const reconcileScript = resolve36(reconcilePlatformRoot, "plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js");
|
|
28513
28746
|
const RECONCILE_INTERVAL_MS = 12e4;
|
|
28514
|
-
const runReconcile = () => {
|
|
28747
|
+
const runReconcile = (ctx) => {
|
|
28515
28748
|
if (!existsSync38(reconcileScript)) return;
|
|
28516
28749
|
try {
|
|
28517
28750
|
const child = spawn3(process.execPath, [reconcileScript], {
|
|
@@ -28519,6 +28752,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
28519
28752
|
stdio: "inherit"
|
|
28520
28753
|
});
|
|
28521
28754
|
child.unref();
|
|
28755
|
+
ctx.child(child.pid);
|
|
28522
28756
|
child.on("error", (err) => console.error(`[calendar-reconcile] spawn-failed err="${err.message}"`));
|
|
28523
28757
|
} catch (err) {
|
|
28524
28758
|
console.error(`[calendar-reconcile] spawn-failed err="${err.message}"`);
|
|
@@ -28536,7 +28770,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
28536
28770
|
const outlookPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join42(__dirname, "..");
|
|
28537
28771
|
const outlookScript = resolve36(outlookPlatformRoot, "plugins/outlook/mcp/dist/scripts/complete-registration.js");
|
|
28538
28772
|
const OUTLOOK_COMPLETE_INTERVAL_MS = 3e4;
|
|
28539
|
-
const runOutlookComplete = () => {
|
|
28773
|
+
const runOutlookComplete = (ctx) => {
|
|
28540
28774
|
if (!existsSync38(outlookScript)) return;
|
|
28541
28775
|
try {
|
|
28542
28776
|
const child = spawn3(process.execPath, [outlookScript], {
|
|
@@ -28544,6 +28778,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
28544
28778
|
stdio: "inherit"
|
|
28545
28779
|
});
|
|
28546
28780
|
child.unref();
|
|
28781
|
+
ctx.child(child.pid);
|
|
28547
28782
|
child.on("error", (err) => console.error(`[outlook-complete] spawn-failed err="${err.message}"`));
|
|
28548
28783
|
} catch (err) {
|
|
28549
28784
|
console.error(`[outlook-complete] spawn-failed err="${err.message}"`);
|
|
@@ -28606,7 +28841,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
28606
28841
|
});
|
|
28607
28842
|
const googleAuditScript = resolve36(googleRoot, "plugins/google/mcp/dist/scripts/account-audit.js");
|
|
28608
28843
|
const GOOGLE_ACCOUNT_AUDIT_INTERVAL_MS = 36e5;
|
|
28609
|
-
const runGoogleAccountAudit = () => {
|
|
28844
|
+
const runGoogleAccountAudit = (ctx) => {
|
|
28610
28845
|
if (!existsSync38(googleAuditScript)) return;
|
|
28611
28846
|
try {
|
|
28612
28847
|
const child = spawn3(process.execPath, [googleAuditScript], {
|
|
@@ -28614,6 +28849,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
28614
28849
|
stdio: "inherit"
|
|
28615
28850
|
});
|
|
28616
28851
|
child.unref();
|
|
28852
|
+
ctx.child(child.pid);
|
|
28617
28853
|
child.on(
|
|
28618
28854
|
"error",
|
|
28619
28855
|
(err) => console.error(`[google-account-audit] op=spawn-failed error="${err.message}"`)
|
|
@@ -28653,6 +28889,16 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
28653
28889
|
firstRunDelayMs: 35e3,
|
|
28654
28890
|
run: runPagesAuditSafe
|
|
28655
28891
|
});
|
|
28892
|
+
const runDataPortalAuditSafe = () => runDataPortalAudit(auditPlatformRoot).catch((err) => {
|
|
28893
|
+
console.error(`[data-portal-audit] error="${err.message}"`);
|
|
28894
|
+
throw err;
|
|
28895
|
+
});
|
|
28896
|
+
registerLoop({
|
|
28897
|
+
name: "data-portal-audit",
|
|
28898
|
+
intervalMs: STORAGE_AUDIT_INTERVAL_MS,
|
|
28899
|
+
firstRunDelayMs: 5e4,
|
|
28900
|
+
run: runDataPortalAuditSafe
|
|
28901
|
+
});
|
|
28656
28902
|
}
|
|
28657
28903
|
{
|
|
28658
28904
|
const publishPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join42(__dirname, "..");
|
|
@@ -28666,7 +28912,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
28666
28912
|
return null;
|
|
28667
28913
|
}
|
|
28668
28914
|
};
|
|
28669
|
-
const spawnPublish = (account) => {
|
|
28915
|
+
const spawnPublish = (account, ctx) => {
|
|
28670
28916
|
if (!existsSync38(publishScript)) return;
|
|
28671
28917
|
try {
|
|
28672
28918
|
const child = spawn3(process.execPath, [publishScript], {
|
|
@@ -28679,6 +28925,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
28679
28925
|
stdio: "inherit"
|
|
28680
28926
|
});
|
|
28681
28927
|
child.unref();
|
|
28928
|
+
ctx.child(child.pid);
|
|
28682
28929
|
child.on("error", (err) => console.error(`[calendar-availability] op=publish result=error reason=spawn-failed err="${err.message}"`));
|
|
28683
28930
|
} catch (err) {
|
|
28684
28931
|
console.error(`[calendar-availability] op=publish result=error reason=spawn-failed err="${err.message}"`);
|
|
@@ -28710,10 +28957,10 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
28710
28957
|
const ageMs = Number.isNaN(parsed) ? null : Date.now() - parsed;
|
|
28711
28958
|
console.error(`[calendar-availability] op=audit accountId=${account.accountId} snapshotAgeMs=${ageMs ?? "na"}`);
|
|
28712
28959
|
};
|
|
28713
|
-
const publishTick = () => {
|
|
28960
|
+
const publishTick = (ctx) => {
|
|
28714
28961
|
const account = currentAccount();
|
|
28715
28962
|
if (!account) return;
|
|
28716
|
-
spawnPublish(account);
|
|
28963
|
+
spawnPublish(account, ctx);
|
|
28717
28964
|
auditSnapshotAge(account);
|
|
28718
28965
|
};
|
|
28719
28966
|
registerLoop({
|
|
@@ -28731,7 +28978,7 @@ startLedgerCensus(() => getSession());
|
|
|
28731
28978
|
const auditScript = resolve36(auditPlatformRoot, "plugins/connector/mcp/dist/scripts/audit-connectors.js");
|
|
28732
28979
|
const auditLogDir = process.env.LOG_DIR ?? LOG_DIR;
|
|
28733
28980
|
const CONNECTOR_AUDIT_INTERVAL_MS = 3e5;
|
|
28734
|
-
const runConnectorAudit = () => {
|
|
28981
|
+
const runConnectorAudit = (ctx) => {
|
|
28735
28982
|
if (!existsSync38(auditScript)) return;
|
|
28736
28983
|
try {
|
|
28737
28984
|
const child = spawn3(process.execPath, [auditScript], {
|
|
@@ -28739,6 +28986,7 @@ startLedgerCensus(() => getSession());
|
|
|
28739
28986
|
stdio: "inherit"
|
|
28740
28987
|
});
|
|
28741
28988
|
child.unref();
|
|
28989
|
+
ctx.child(child.pid);
|
|
28742
28990
|
child.on("error", (err) => console.error(`[connector-audit] spawn-failed err="${err.message}"`));
|
|
28743
28991
|
} catch (err) {
|
|
28744
28992
|
console.error(`[connector-audit] spawn-failed err="${err.message}"`);
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
makeHouseCfExec,
|
|
15
15
|
makeHousePagesExec,
|
|
16
16
|
readHouseCredential,
|
|
17
|
+
reconcileDataPortal,
|
|
17
18
|
reconcilePages,
|
|
18
19
|
reconcileStorage,
|
|
19
20
|
registerResource,
|
|
@@ -22,7 +23,7 @@ import {
|
|
|
22
23
|
stripAccountWideTokens,
|
|
23
24
|
tooLargeMessage,
|
|
24
25
|
validateMapping
|
|
25
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-3XLLTG6R.js";
|
|
26
27
|
import "./chunk-PFF6I7KP.js";
|
|
27
28
|
export {
|
|
28
29
|
D1_MAX_SQL_STATEMENT_BYTES,
|
|
@@ -39,6 +40,7 @@ export {
|
|
|
39
40
|
makeHouseCfExec,
|
|
40
41
|
makeHousePagesExec,
|
|
41
42
|
readHouseCredential,
|
|
43
|
+
reconcileDataPortal,
|
|
42
44
|
reconcilePages,
|
|
43
45
|
reconcileStorage,
|
|
44
46
|
registerResource,
|