@rubytech/create-maxy-code 0.1.469 → 0.1.471
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +40 -0
- package/package.json +1 -1
- package/payload/platform/config/brand.json +2 -1
- package/payload/platform/docs/superpowers/plans/2026-07-18-graph-native-ledger.md +807 -0
- package/payload/platform/docs/superpowers/specs/2026-07-18-graph-native-ledger-design.md +241 -0
- package/payload/platform/lib/ledger-core/dist/ageing.d.ts +14 -0
- package/payload/platform/lib/ledger-core/dist/ageing.d.ts.map +1 -0
- package/payload/platform/lib/ledger-core/dist/ageing.js +38 -0
- package/payload/platform/lib/ledger-core/dist/ageing.js.map +1 -0
- package/payload/platform/lib/ledger-core/dist/balance.d.ts +25 -0
- package/payload/platform/lib/ledger-core/dist/balance.d.ts.map +1 -0
- package/payload/platform/lib/ledger-core/dist/balance.js +38 -0
- package/payload/platform/lib/ledger-core/dist/balance.js.map +1 -0
- package/payload/platform/lib/ledger-core/dist/index.d.ts +5 -0
- package/payload/platform/lib/ledger-core/dist/index.d.ts.map +1 -0
- package/payload/platform/lib/ledger-core/dist/index.js +5 -0
- package/payload/platform/lib/ledger-core/dist/index.js.map +1 -0
- package/payload/platform/lib/ledger-core/dist/money.d.ts +12 -0
- package/payload/platform/lib/ledger-core/dist/money.d.ts.map +1 -0
- package/payload/platform/lib/ledger-core/dist/money.js +16 -0
- package/payload/platform/lib/ledger-core/dist/money.js.map +1 -0
- package/payload/platform/lib/ledger-core/dist/reconcile.d.ts +51 -0
- package/payload/platform/lib/ledger-core/dist/reconcile.d.ts.map +1 -0
- package/payload/platform/lib/ledger-core/dist/reconcile.js +77 -0
- package/payload/platform/lib/ledger-core/dist/reconcile.js.map +1 -0
- package/payload/platform/lib/ledger-core/package.json +16 -0
- package/payload/platform/lib/ledger-core/src/__tests__/ageing.test.ts +42 -0
- package/payload/platform/lib/ledger-core/src/__tests__/balance.test.ts +48 -0
- package/payload/platform/lib/ledger-core/src/__tests__/reconcile.test.ts +87 -0
- package/payload/platform/lib/ledger-core/src/ageing.ts +51 -0
- package/payload/platform/lib/ledger-core/src/balance.ts +52 -0
- package/payload/platform/lib/ledger-core/src/index.ts +4 -0
- package/payload/platform/lib/ledger-core/src/money.ts +17 -0
- package/payload/platform/lib/ledger-core/src/reconcile.ts +109 -0
- package/payload/platform/lib/ledger-core/tsconfig.json +6 -0
- package/payload/platform/neo4j/schema.cypher +16 -0
- package/payload/platform/package.json +2 -2
- package/payload/platform/plugins/.claude-plugin/marketplace.json +10 -0
- package/payload/platform/plugins/admin/hooks/lib/maxy-mcp-plugins.txt +2 -0
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +171 -2
- package/payload/platform/plugins/cloudflare/bin/__tests__/portal-brand-css.test.sh +139 -0
- package/payload/platform/plugins/cloudflare/bin/portal-brand-css.mjs +128 -0
- package/payload/platform/plugins/cloudflare/mcp/__tests__/portal-enrol.test.ts +1 -1
- package/payload/platform/plugins/cloudflare/mcp/__tests__/skill-contract.test.ts +25 -0
- package/payload/platform/plugins/cloudflare/mcp/__tests__/template-config.test.ts +55 -3
- package/payload/platform/plugins/cloudflare/skills/data-portal/SKILL.md +38 -3
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/{public/portal.css → portal.css} +13 -2
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/wrangler.toml +1 -1
- package/payload/platform/plugins/docs/references/admin-ui.md +48 -0
- package/payload/platform/plugins/docs/references/google-guide.md +68 -0
- package/payload/platform/plugins/docs/references/internals.md +1 -1
- package/payload/platform/plugins/docs/references/ledger.md +43 -0
- package/payload/platform/plugins/email/PLUGIN.md +4 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/display-truncation.test.d.ts +2 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/display-truncation.test.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/display-truncation.test.js +196 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/display-truncation.test.js.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/source-fetch-efficiency.test.js +10 -8
- package/payload/platform/plugins/email/mcp/dist/__tests__/source-fetch-efficiency.test.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/__tests__/truncation-tool-output.test.d.ts +2 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/truncation-tool-output.test.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/truncation-tool-output.test.js +110 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/truncation-tool-output.test.js.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/lib/imap.d.ts +22 -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 +90 -36
- package/payload/platform/plugins/email/mcp/dist/lib/imap.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-read.d.ts.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-read.js +6 -2
- package/payload/platform/plugins/email/mcp/dist/tools/email-read.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-search.d.ts.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-search.js +6 -2
- package/payload/platform/plugins/email/mcp/dist/tools/email-search.js.map +1 -1
- package/payload/platform/plugins/email/skills/email-ingest/SKILL.md +4 -0
- package/payload/platform/plugins/google/.claude-plugin/plugin.json +21 -0
- package/payload/platform/plugins/google/PLUGIN.md +104 -0
- package/payload/platform/plugins/google/lib/mcp-spawn-tee/index.js +193 -0
- package/payload/platform/plugins/google/lib/mcp-spawn-tee/package.json +3 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/account-register.test.d.ts +2 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/account-register.test.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/account-register.test.js +60 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/account-register.test.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/calendar-tools.test.d.ts +2 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/calendar-tools.test.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/calendar-tools.test.js +48 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/calendar-tools.test.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/google-client.test.d.ts +2 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/google-client.test.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/google-client.test.js +25 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/google-client.test.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/index-registration.test.d.ts +2 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/index-registration.test.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/index-registration.test.js +40 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/index-registration.test.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/pending-store.test.d.ts +2 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/pending-store.test.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/pending-store.test.js +35 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/pending-store.test.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/token-store.test.d.ts +2 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/token-store.test.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/token-store.test.js +85 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/token-store.test.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/auth/pending-store.d.ts +25 -0
- package/payload/platform/plugins/google/mcp/dist/auth/pending-store.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/auth/pending-store.js +87 -0
- package/payload/platform/plugins/google/mcp/dist/auth/pending-store.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/auth/token-store.d.ts +46 -0
- package/payload/platform/plugins/google/mcp/dist/auth/token-store.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/auth/token-store.js +138 -0
- package/payload/platform/plugins/google/mcp/dist/auth/token-store.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/index.d.ts +25 -0
- package/payload/platform/plugins/google/mcp/dist/index.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/index.js +300 -0
- package/payload/platform/plugins/google/mcp/dist/index.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/lib/google-client.d.ts +28 -0
- package/payload/platform/plugins/google/mcp/dist/lib/google-client.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/lib/google-client.js +102 -0
- package/payload/platform/plugins/google/mcp/dist/lib/google-client.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/lib/log.d.ts +3 -0
- package/payload/platform/plugins/google/mcp/dist/lib/log.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/lib/log.js +16 -0
- package/payload/platform/plugins/google/mcp/dist/lib/log.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/tools/account-info.d.ts +12 -0
- package/payload/platform/plugins/google/mcp/dist/tools/account-info.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/tools/account-info.js +23 -0
- package/payload/platform/plugins/google/mcp/dist/tools/account-info.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/tools/account-list.d.ts +12 -0
- package/payload/platform/plugins/google/mcp/dist/tools/account-list.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/tools/account-list.js +9 -0
- package/payload/platform/plugins/google/mcp/dist/tools/account-list.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/tools/account-register.d.ts +42 -0
- package/payload/platform/plugins/google/mcp/dist/tools/account-register.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/tools/account-register.js +102 -0
- package/payload/platform/plugins/google/mcp/dist/tools/account-register.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-cancel.d.ts +10 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-cancel.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-cancel.js +9 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-cancel.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-create.d.ts +20 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-create.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-create.js +25 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-create.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-event.d.ts +6 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-event.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-event.js +7 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-event.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-freebusy.d.ts +14 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-freebusy.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-freebusy.js +16 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-freebusy.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-list.d.ts +44 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-list.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-list.js +36 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-list.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-respond.d.ts +16 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-respond.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-respond.js +29 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-respond.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-update.d.ts +16 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-update.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-update.js +32 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-update.js.map +1 -0
- package/payload/platform/plugins/google/mcp/package.json +20 -0
- package/payload/platform/plugins/google/references/auth.md +35 -0
- package/payload/platform/plugins/ledger/.claude-plugin/plugin.json +21 -0
- package/payload/platform/plugins/ledger/PLUGIN.md +82 -0
- package/payload/platform/plugins/ledger/lib/mcp-spawn-tee/index.js +193 -0
- package/payload/platform/plugins/ledger/lib/mcp-spawn-tee/package.json +3 -0
- package/payload/platform/plugins/ledger/mcp/dist/index.d.ts +2 -0
- package/payload/platform/plugins/ledger/mcp/dist/index.d.ts.map +1 -0
- package/payload/platform/plugins/ledger/mcp/dist/index.js +168 -0
- package/payload/platform/plugins/ledger/mcp/dist/index.js.map +1 -0
- package/payload/platform/plugins/ledger/mcp/dist/lib/ids.d.ts +4 -0
- package/payload/platform/plugins/ledger/mcp/dist/lib/ids.d.ts.map +1 -0
- package/payload/platform/plugins/ledger/mcp/dist/lib/ids.js +0 -0
- package/payload/platform/plugins/ledger/mcp/dist/lib/ids.js.map +1 -0
- package/payload/platform/plugins/ledger/mcp/dist/lib/neo4j.d.ts +5 -0
- package/payload/platform/plugins/ledger/mcp/dist/lib/neo4j.d.ts.map +1 -0
- package/payload/platform/plugins/ledger/mcp/dist/lib/neo4j.js +40 -0
- package/payload/platform/plugins/ledger/mcp/dist/lib/neo4j.js.map +1 -0
- package/payload/platform/plugins/ledger/mcp/dist/lib/read.d.ts +29 -0
- package/payload/platform/plugins/ledger/mcp/dist/lib/read.d.ts.map +1 -0
- package/payload/platform/plugins/ledger/mcp/dist/lib/read.js +138 -0
- package/payload/platform/plugins/ledger/mcp/dist/lib/read.js.map +1 -0
- package/payload/platform/plugins/ledger/mcp/dist/lib/types.d.ts +47 -0
- package/payload/platform/plugins/ledger/mcp/dist/lib/types.d.ts.map +1 -0
- package/payload/platform/plugins/ledger/mcp/dist/lib/types.js +14 -0
- package/payload/platform/plugins/ledger/mcp/dist/lib/types.js.map +1 -0
- package/payload/platform/plugins/ledger/mcp/dist/tools/balance.d.ts +18 -0
- package/payload/platform/plugins/ledger/mcp/dist/tools/balance.d.ts.map +1 -0
- package/payload/platform/plugins/ledger/mcp/dist/tools/balance.js +23 -0
- package/payload/platform/plugins/ledger/mcp/dist/tools/balance.js.map +1 -0
- package/payload/platform/plugins/ledger/mcp/dist/tools/cash-record.d.ts +26 -0
- package/payload/platform/plugins/ledger/mcp/dist/tools/cash-record.d.ts.map +1 -0
- package/payload/platform/plugins/ledger/mcp/dist/tools/cash-record.js +33 -0
- package/payload/platform/plugins/ledger/mcp/dist/tools/cash-record.js.map +1 -0
- package/payload/platform/plugins/ledger/mcp/dist/tools/invoice-record.d.ts +27 -0
- package/payload/platform/plugins/ledger/mcp/dist/tools/invoice-record.d.ts.map +1 -0
- package/payload/platform/plugins/ledger/mcp/dist/tools/invoice-record.js +40 -0
- package/payload/platform/plugins/ledger/mcp/dist/tools/invoice-record.js.map +1 -0
- package/payload/platform/plugins/ledger/mcp/dist/tools/payment-record.d.ts +46 -0
- package/payload/platform/plugins/ledger/mcp/dist/tools/payment-record.d.ts.map +1 -0
- package/payload/platform/plugins/ledger/mcp/dist/tools/payment-record.js +68 -0
- package/payload/platform/plugins/ledger/mcp/dist/tools/payment-record.js.map +1 -0
- package/payload/platform/plugins/ledger/mcp/dist/tools/reconcile.d.ts +20 -0
- package/payload/platform/plugins/ledger/mcp/dist/tools/reconcile.d.ts.map +1 -0
- package/payload/platform/plugins/ledger/mcp/dist/tools/reconcile.js +30 -0
- package/payload/platform/plugins/ledger/mcp/dist/tools/reconcile.js.map +1 -0
- package/payload/platform/plugins/ledger/mcp/dist/tools/statement.d.ts +26 -0
- package/payload/platform/plugins/ledger/mcp/dist/tools/statement.d.ts.map +1 -0
- package/payload/platform/plugins/ledger/mcp/dist/tools/statement.js +35 -0
- package/payload/platform/plugins/ledger/mcp/dist/tools/statement.js.map +1 -0
- package/payload/platform/plugins/ledger/mcp/package.json +21 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/ledger-vertical-coverage.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/ledger-vertical-coverage.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/ledger-vertical-coverage.test.js +81 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/ledger-vertical-coverage.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/schema-loader.d.ts +9 -7
- package/payload/platform/plugins/memory/mcp/dist/lib/schema-loader.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/schema-loader.js +10 -8
- package/payload/platform/plugins/memory/mcp/dist/lib/schema-loader.js.map +1 -1
- package/payload/platform/plugins/memory/references/schema-base.md +22 -0
- package/payload/platform/plugins/memory/references/schema-construction.md +0 -18
- package/payload/platform/plugins/scheduling/PLUGIN.md +20 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/meeting-write.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/meeting-write.js +11 -2
- package/payload/platform/plugins/scheduling/mcp/dist/lib/meeting-write.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.js +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.js.map +1 -1
- package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-create.js +3 -3
- package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-create.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/activity-rows.d.ts +138 -0
- package/payload/platform/services/claude-session-manager/dist/activity-rows.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/activity-rows.js +268 -0
- package/payload/platform/services/claude-session-manager/dist/activity-rows.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 +20 -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 +6 -0
- 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 +42 -0
- package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/index.js +10 -1
- package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-census.d.ts +80 -6
- package/payload/platform/services/claude-session-manager/dist/pty-census.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-census.js +96 -20
- package/payload/platform/services/claude-session-manager/dist/pty-census.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/slice-memory-policy.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/slice-memory-policy.js +5 -1
- package/payload/platform/services/claude-session-manager/dist/slice-memory-policy.js.map +1 -1
- package/payload/platform/templates/specialists/agents/database-operator.md +1 -1
- package/payload/platform/templates/specialists/agents/personal-assistant.md +1 -1
- package/payload/platform/templates/specialists/agents/project-manager.md +1 -1
- package/payload/server/{chunk-POBXIHOF.js → chunk-BSTIQX52.js} +59 -1
- package/payload/server/maxy-edge.js +1 -1
- package/payload/server/public/activity.html +17 -0
- package/payload/server/public/assets/AdminLoginScreens-Rf94VD9w.js +1 -0
- package/payload/server/public/assets/AdminShell-CyGKg7MG.js +2 -0
- package/payload/server/public/assets/Checkbox-B0jmI2y2.js +1 -0
- package/payload/server/public/assets/HeaderMenu-BnTYGNaB.js +9 -0
- package/payload/server/public/assets/{useSubAccountSwitcher-pu0jjLCz.css → HeaderMenu-DtIEBHOU.css} +1 -1
- package/payload/server/public/assets/activity-BOBTWFr-.js +1 -0
- package/payload/server/public/assets/admin-HDLzwbLl.js +1 -0
- package/payload/server/public/assets/{arc-qKfXIt8v.js → arc-CFMJyMm-.js} +1 -1
- package/payload/server/public/assets/architecture-YZFGNWBL-Cypt5qHL.js +1 -0
- package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-DkVrGn7G.js → architectureDiagram-Q4EWVU46-CmOpXLsH.js} +1 -1
- package/payload/server/public/assets/{blockDiagram-DXYQGD6D-DqavswGH.js → blockDiagram-DXYQGD6D-CmS8f9YF.js} +1 -1
- package/payload/server/public/assets/browser-D4_XLSSm.js +1 -0
- package/payload/server/public/assets/{c4Diagram-AHTNJAMY-B7fyKiXe.js → c4Diagram-AHTNJAMY-BXIjMl6A.js} +1 -1
- package/payload/server/public/assets/calendar-s5V_gbI7.js +1 -0
- package/payload/server/public/assets/channel-DhrFAm7m.js +1 -0
- package/payload/server/public/assets/chat-40WyKzGb.js +1 -0
- package/payload/server/public/assets/chevron-left-C35qGP5f.js +1 -0
- package/payload/server/public/assets/{chunk-2KRD3SAO-DsgMtGkv.js → chunk-2KRD3SAO-D4fktAwW.js} +1 -1
- package/payload/server/public/assets/{chunk-336JU56O-CkdISfNt.js → chunk-336JU56O-C2MKnRTj.js} +2 -2
- package/payload/server/public/assets/chunk-426QAEUC-BhU7-TyS.js +1 -0
- package/payload/server/public/assets/{chunk-4BX2VUAB-CYpiF2bl.js → chunk-4BX2VUAB-C13Wz3zS.js} +1 -1
- package/payload/server/public/assets/{chunk-4TB4RGXK-CWyc_F7v.js → chunk-4TB4RGXK-CalYahTR.js} +1 -1
- package/payload/server/public/assets/{chunk-55IACEB6-BbzKMw2Z.js → chunk-55IACEB6-TmOKdy8a.js} +1 -1
- package/payload/server/public/assets/{chunk-5FUZZQ4R-u19Nai9e.js → chunk-5FUZZQ4R-C-i0BVag.js} +1 -1
- package/payload/server/public/assets/{chunk-5PVQY5BW-Ba8by6Uy.js → chunk-5PVQY5BW-D6bJMLnf.js} +1 -1
- package/payload/server/public/assets/{chunk-67CJDMHE-BwUuxtyb.js → chunk-67CJDMHE-Cif9Uu5C.js} +1 -1
- package/payload/server/public/assets/{chunk-7N4EOEYR-BRH9iM9L.js → chunk-7N4EOEYR-WjTHCXnd.js} +1 -1
- package/payload/server/public/assets/{chunk-AA7GKIK3-BGoztgLL.js → chunk-AA7GKIK3-CwCfdQmb.js} +1 -1
- package/payload/server/public/assets/{chunk-BSJP7CBP-C5GDAZTl.js → chunk-BSJP7CBP-9A67yXwT.js} +1 -1
- package/payload/server/public/assets/{chunk-CIAEETIT-ChY32VPS.js → chunk-CIAEETIT-DPMiWSBi.js} +1 -1
- package/payload/server/public/assets/{chunk-EDXVE4YY-CPSD3p6p.js → chunk-EDXVE4YY-B9PBdwiT.js} +1 -1
- package/payload/server/public/assets/{chunk-ENJZ2VHE-D1oL-iUr.js → chunk-ENJZ2VHE-CM5OqcQ5.js} +1 -1
- package/payload/server/public/assets/{chunk-FMBD7UC4-CPvYEr54.js → chunk-FMBD7UC4-Bmt_ZRlV.js} +1 -1
- package/payload/server/public/assets/{chunk-FOC6F5B3-9Yyj7Vbz.js → chunk-FOC6F5B3-DfGJGxpX.js} +1 -1
- package/payload/server/public/assets/{chunk-ICPOFSXX-BaYgh8FR.js → chunk-ICPOFSXX-D6M89DA0.js} +2 -2
- package/payload/server/public/assets/{chunk-K5T4RW27-5ucpeRvm.js → chunk-K5T4RW27-DMpoaqw2.js} +1 -1
- package/payload/server/public/assets/{chunk-KGLVRYIC-DW-FHk7T.js → chunk-KGLVRYIC-DYUFgri2.js} +1 -1
- package/payload/server/public/assets/{chunk-LIHQZDEY-CGGVfAyG.js → chunk-LIHQZDEY-x3LmeKmx.js} +1 -1
- package/payload/server/public/assets/{chunk-ORNJ4GCN-Bv8EUa5d.js → chunk-ORNJ4GCN-BeuNAWkW.js} +1 -1
- package/payload/server/public/assets/{chunk-OYMX7WX6-C1mXJnyw.js → chunk-OYMX7WX6-Bv6gisQ6.js} +1 -1
- package/payload/server/public/assets/chunk-QZHKN3VN-7_kS3RBy.js +1 -0
- package/payload/server/public/assets/{chunk-U2HBQHQK-PwSQz6EP.js → chunk-U2HBQHQK-C2iT9Av2.js} +1 -1
- package/payload/server/public/assets/{chunk-X2U36JSP--NPHTBlU.js → chunk-X2U36JSP-Bd6bv87A.js} +1 -1
- package/payload/server/public/assets/{chunk-XPW4576I-Bbc7Da32.js → chunk-XPW4576I-ByFnN4JO.js} +1 -1
- package/payload/server/public/assets/{chunk-YZCP3GAM-D-9v8e--.js → chunk-YZCP3GAM-Bt8I6ZDb.js} +1 -1
- package/payload/server/public/assets/{chunk-ZZ45TVLE-CMPg670Q.js → chunk-ZZ45TVLE-DBMPgZ_A.js} +1 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-BrWqm88p.js +1 -0
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-D0wzG5Fd.js +1 -0
- package/payload/server/public/assets/clone-DQA-nNrl.js +1 -0
- package/payload/server/public/assets/{cose-bilkent-S5V4N54A-NVSb1Bhy.js → cose-bilkent-S5V4N54A-DgLEaApT.js} +1 -1
- package/payload/server/public/assets/{dagre-KV5264BT-V2Ai1DFl.js → dagre-KV5264BT-kWVPgmmL.js} +1 -1
- package/payload/server/public/assets/{dagre-QfLcO-1j.js → dagre-mSazqXgG.js} +1 -1
- package/payload/server/public/assets/data-Bq0vU3qJ.js +1 -0
- package/payload/server/public/assets/{diagram-5BDNPKRD-Caw21693.js → diagram-5BDNPKRD-BHe_omJD.js} +1 -1
- package/payload/server/public/assets/{diagram-G4DWMVQ6-CgwVkT2q.js → diagram-G4DWMVQ6-fUFsmM3x.js} +1 -1
- package/payload/server/public/assets/{diagram-MMDJMWI5-DFUrLZhs.js → diagram-MMDJMWI5-DmujPLlM.js} +1 -1
- package/payload/server/public/assets/{diagram-TYMM5635-CEEiEuZJ.js → diagram-TYMM5635-B7Aoas89.js} +1 -1
- package/payload/server/public/assets/{dist-Cvgxm7qv.js → dist-C9D_xz81.js} +1 -1
- package/payload/server/public/assets/{erDiagram-SMLLAGMA-CG10NrT3.js → erDiagram-SMLLAGMA-6hS1rGiO.js} +1 -1
- package/payload/server/public/assets/{flatten-DAO0sfCM.js → flatten-BXzaHgtL.js} +1 -1
- package/payload/server/public/assets/{flowDiagram-DWJPFMVM-BqkV9Okv.js → flowDiagram-DWJPFMVM-Bqhr_r5b.js} +1 -1
- package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-DRiCDQF6.js → ganttDiagram-T4ZO3ILL-B8kjyN4o.js} +1 -1
- package/payload/server/public/assets/gitGraph-7Q5UKJZL-C_-XjxLd.js +1 -0
- package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-BZV2voyy.js → gitGraphDiagram-UUTBAWPF--TTRq4ir.js} +1 -1
- package/payload/server/public/assets/{graph-BZiudUGr.js → graph-C252ZHjp.js} +3 -3
- package/payload/server/public/assets/graph-labels-DzPbbhLc.js +1 -0
- package/payload/server/public/assets/{graphlib-DGPThX8M.js → graphlib-CWkjawc5.js} +1 -1
- package/payload/server/public/assets/info-OMHHGYJF-BH8yDCfL.js +1 -0
- package/payload/server/public/assets/infoDiagram-42DDH7IO-D8U4M0pK.js +2 -0
- package/payload/server/public/assets/{isEmpty-Cb_U81C6.js → isEmpty-uB1dEu_Z.js} +1 -1
- package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-BKsAxSvp.js → ishikawaDiagram-UXIWVN3A-CR8B7VzM.js} +1 -1
- package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-CmliuOd-.js → journeyDiagram-VCZTEJTY-45lWAvtq.js} +1 -1
- package/payload/server/public/assets/{kanban-definition-6JOO6SKY-DAlElMb-.js → kanban-definition-6JOO6SKY-DkrPXLVb.js} +1 -1
- package/payload/server/public/assets/{line-DKZqLKAC.js → line-Db0H446a.js} +1 -1
- package/payload/server/public/assets/{linear-CbSGdh1x.js → linear-X3O7lwK3.js} +1 -1
- package/payload/server/public/assets/maximize-2-CEbXFpQT.js +1 -0
- package/payload/server/public/assets/{mermaid-parser.core-DFvbao9C.js → mermaid-parser.core-CixBHOya.js} +2 -2
- package/payload/server/public/assets/{mermaid.core-C0vEBxDm.js → mermaid.core-BGQq98L7.js} +3 -3
- package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-CShASUKd.js → mindmap-definition-QFDTVHPH-v9cJl1mj.js} +1 -1
- package/payload/server/public/assets/operator-zKk4HMdX.js +1 -0
- package/payload/server/public/assets/{ordinal-H0tVmBDP.js → ordinal-CZY9laxg.js} +1 -1
- package/payload/server/public/assets/packet-4T2RLAQJ-Bajcns4r.js +1 -0
- package/payload/server/public/assets/page-BrmN_vzV.js +1 -0
- package/payload/server/public/assets/page-Cts-ESBe.js +32 -0
- package/payload/server/public/assets/{pdf-render-jAQU0nXt.js → pdf-render-7HZBTZ0_.js} +1 -1
- package/payload/server/public/assets/pie-ZZUOXDRM-D7hjM5w1.js +1 -0
- package/payload/server/public/assets/{pieDiagram-DEJITSTG-CBZHpDAJ.js → pieDiagram-DEJITSTG-DQ0b6edX.js} +1 -1
- package/payload/server/public/assets/public-BItzHBc0.js +1 -0
- package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-n3bB3K91.js → quadrantDiagram-34T5L4WZ-B64mj7Ei.js} +1 -1
- package/payload/server/public/assets/radar-PYXPWWZC-B46d5x7a.js +1 -0
- package/payload/server/public/assets/{reduce-DAvwat-a.js → reduce-BGQzAenn.js} +1 -1
- package/payload/server/public/assets/{requirementDiagram-MS252O5E-DiDvQK3c.js → requirementDiagram-MS252O5E-CE2JIEWo.js} +1 -1
- package/payload/server/public/assets/rotate-ccw-B0EYGhGx.js +1 -0
- package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-DWDQQZmd.js → sankeyDiagram-XADWPNL6-Cmt5cfCz.js} +1 -1
- package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-DmAqRlBT.js → sequenceDiagram-FGHM5R23-B5vVn_sw.js} +1 -1
- package/payload/server/public/assets/{src-DV4LKv2E.js → src-BTKk8KAG.js} +1 -1
- package/payload/server/public/assets/{stateDiagram-FHFEXIEX-D4R-n6bZ.js → stateDiagram-FHFEXIEX-DiUEJ-RZ.js} +1 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-DIm3XuAD.js +1 -0
- package/payload/server/public/assets/tasks-ClE8-be8.js +1 -0
- package/payload/server/public/assets/time-entry-format-BwjGLnXu.js +1 -0
- package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-CjiHGP4l.js → timeline-definition-GMOUNBTQ-C9jprDVw.js} +1 -1
- package/payload/server/public/assets/treeView-SZITEDCU-3XQh5xQ1.js +1 -0
- package/payload/server/public/assets/treemap-W4RFUUIX-DwR-_l5z.js +1 -0
- package/payload/server/public/assets/triangle-alert-DejWYn1x.js +1 -0
- package/payload/server/public/assets/useCopyFeedback-CpSgOavK.js +1 -0
- package/payload/server/public/assets/useSelectionMode-ZQZQUgze.js +1 -0
- package/payload/server/public/assets/useSubAccountSwitcher-DuRLvCfO.js +1 -0
- package/payload/server/public/assets/useVoiceRecorder-BTYYeUJW.js +2 -0
- package/payload/server/public/assets/{vennDiagram-DHZGUBPP-CBdDQ7c-.js → vennDiagram-DHZGUBPP-DWqQJ9X0.js} +1 -1
- package/payload/server/public/assets/wardley-RL74JXVD-DZp9oCGv.js +1 -0
- package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-BlIQPKLb.js → wardleyDiagram-NUSXRM2D-Dg6c2Voh.js} +1 -1
- package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-CslKgh9B.js → xychartDiagram-5P7HB3ND-EhN-zeDj.js} +1 -1
- package/payload/server/public/browser.html +7 -6
- package/payload/server/public/calendar.html +8 -7
- package/payload/server/public/chat.html +15 -14
- package/payload/server/public/data.html +14 -12
- package/payload/server/public/graph.html +13 -12
- package/payload/server/public/index.html +17 -15
- package/payload/server/public/operator.html +17 -16
- package/payload/server/public/public.html +15 -14
- package/payload/server/public/tasks.html +7 -6
- package/payload/server/server.js +1064 -536
- package/payload/server/public/assets/AdminLoginScreens-Bed8SDxY.js +0 -1
- package/payload/server/public/assets/AdminShell-BLh9O6dn.js +0 -2
- package/payload/server/public/assets/Checkbox-BC_KSbpS.js +0 -1
- package/payload/server/public/assets/admin-DfWgJVI3.js +0 -1
- package/payload/server/public/assets/architecture-YZFGNWBL-FPHT7s-C.js +0 -1
- package/payload/server/public/assets/browser-C0vkv-hH.js +0 -1
- package/payload/server/public/assets/calendar-_pfHw0Hp.js +0 -1
- package/payload/server/public/assets/channel-j70eMvcL.js +0 -1
- package/payload/server/public/assets/chat-DYT5H81o.js +0 -1
- package/payload/server/public/assets/chevron-left-BnpVBu51.js +0 -1
- package/payload/server/public/assets/chunk-426QAEUC-D-NcAlTW.js +0 -1
- package/payload/server/public/assets/chunk-QZHKN3VN-CAwbQBtf.js +0 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-Ct6Rn0vt.js +0 -1
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-B_2XCIFv.js +0 -1
- package/payload/server/public/assets/clone-DjPWA_NH.js +0 -1
- package/payload/server/public/assets/data-CR-fbPWr.js +0 -1
- package/payload/server/public/assets/gitGraph-7Q5UKJZL-B8Hx7f-D.js +0 -1
- package/payload/server/public/assets/graph-labels-BzmmJwCR.js +0 -1
- package/payload/server/public/assets/info-OMHHGYJF-BicCJTqU.js +0 -1
- package/payload/server/public/assets/infoDiagram-42DDH7IO-tf-8rOez.js +0 -2
- package/payload/server/public/assets/maximize-2-Bhdsv0U-.js +0 -1
- package/payload/server/public/assets/operator-gm2eP4r6.js +0 -1
- package/payload/server/public/assets/packet-4T2RLAQJ-Ckn_5hq0.js +0 -1
- package/payload/server/public/assets/page-8AB3jUa_.js +0 -1
- package/payload/server/public/assets/page-BoPorLg-.js +0 -32
- package/payload/server/public/assets/pie-ZZUOXDRM-DzlGQW3J.js +0 -1
- package/payload/server/public/assets/public-DqJk6qgW.js +0 -1
- package/payload/server/public/assets/radar-PYXPWWZC-BHo2YD8b.js +0 -1
- package/payload/server/public/assets/rotate-ccw-D_5cETGt.js +0 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-BcFRbGRu.js +0 -1
- package/payload/server/public/assets/tasks-EyKLXINi.js +0 -1
- package/payload/server/public/assets/time-entry-format-DAwmmR3i.js +0 -1
- package/payload/server/public/assets/treeView-SZITEDCU-BtRr5vXp.js +0 -1
- package/payload/server/public/assets/treemap-W4RFUUIX-D8p0sbyo.js +0 -1
- package/payload/server/public/assets/useCopyFeedback-rOWd_lzl.js +0 -1
- package/payload/server/public/assets/useSelectionMode-DDmLmPph.js +0 -1
- package/payload/server/public/assets/useSubAccountSwitcher-CU-lOxTd.js +0 -9
- package/payload/server/public/assets/useVoiceRecorder-azG8zSUI.js +0 -2
- package/payload/server/public/assets/wardley-RL74JXVD-DgMn-9ZJ.js +0 -1
- /package/payload/platform/plugins/cloudflare/skills/data-portal/{template/schema.sql → schema.sql} +0 -0
- /package/payload/platform/plugins/cloudflare/skills/data-portal/template/{public/index.html → index.html} +0 -0
- /package/payload/platform/plugins/cloudflare/skills/data-portal/template/{public/portal.js → portal.js} +0 -0
- /package/payload/server/public/assets/{_baseFor-D3BqAOBr.js → _baseFor-CMWvz0uA.js} +0 -0
- /package/payload/server/public/assets/{array-iYP9fzJp.js → array-Cny_NT6T.js} +0 -0
- /package/payload/server/public/assets/{chunk-Ck5AOu5v.js → chunk-TPjIAO9U.js} +0 -0
- /package/payload/server/public/assets/{cytoscape.esm-BQSBzPsB.js → cytoscape.esm-De0CCmB2.js} +0 -0
- /package/payload/server/public/assets/{defaultLocale-BrdA1gDi.js → defaultLocale-BahRht8U.js} +0 -0
- /package/payload/server/public/assets/{init-Bx0S6pkp.js → init-DoIvjoJ_.js} +0 -0
- /package/payload/server/public/assets/{katex-BsiH_a6d.js → katex-Bfn1OZEl.js} +0 -0
- /package/payload/server/public/assets/{path-BLSgTy3w.js → path-CTezU8L5.js} +0 -0
- /package/payload/server/public/assets/{preload-helper-ClBMtM1g.js → preload-helper-CT1Z6Pdu.js} +0 -0
- /package/payload/server/public/assets/{rough.esm-BMOtDaaS.js → rough.esm-BJo4pvXu.js} +0 -0
package/payload/server/server.js
CHANGED
|
@@ -42,6 +42,7 @@ import {
|
|
|
42
42
|
embed,
|
|
43
43
|
emitMissingOnResolve,
|
|
44
44
|
ensureConversation,
|
|
45
|
+
ensureSessionConversation,
|
|
45
46
|
fetchAccountName,
|
|
46
47
|
fetchBranding,
|
|
47
48
|
findMissingPlugins,
|
|
@@ -111,7 +112,7 @@ import {
|
|
|
111
112
|
vncLog,
|
|
112
113
|
walkPremiumBundles,
|
|
113
114
|
writeAdminUserAndPerson
|
|
114
|
-
} from "./chunk-
|
|
115
|
+
} from "./chunk-BSTIQX52.js";
|
|
115
116
|
import {
|
|
116
117
|
D1_MAX_SQL_STATEMENT_BYTES,
|
|
117
118
|
D1_QUERY_MAX_BODY_BYTES,
|
|
@@ -1533,10 +1534,10 @@ var serveStatic = (options = { root: "" }) => {
|
|
|
1533
1534
|
};
|
|
1534
1535
|
|
|
1535
1536
|
// server/index.ts
|
|
1536
|
-
import { readFileSync as
|
|
1537
|
+
import { readFileSync as readFileSync39, existsSync as existsSync37, watchFile, readdirSync as readdirSync23, statSync as statSync14 } from "fs";
|
|
1537
1538
|
import { spawn as spawn3 } from "child_process";
|
|
1538
1539
|
import { createHash as createHash7 } from "crypto";
|
|
1539
|
-
import { resolve as resolve36, join as
|
|
1540
|
+
import { resolve as resolve36, join as join39, basename as basename12 } from "path";
|
|
1540
1541
|
import { homedir as homedir4 } from "os";
|
|
1541
1542
|
import { monitorEventLoopDelay } from "perf_hooks";
|
|
1542
1543
|
|
|
@@ -6675,8 +6676,8 @@ function webchatTurnTimeoutMs() {
|
|
|
6675
6676
|
return Number(process.env.WEBCHAT_TURN_TIMEOUT_MS ?? String(2 * 6e4));
|
|
6676
6677
|
}
|
|
6677
6678
|
function createChatRoutes(deps) {
|
|
6678
|
-
const
|
|
6679
|
-
|
|
6679
|
+
const app64 = new Hono();
|
|
6680
|
+
app64.post("/", async (c) => {
|
|
6680
6681
|
console.log(`[chat-route] entered route=public method=POST`);
|
|
6681
6682
|
const contentType = c.req.header("content-type") ?? "";
|
|
6682
6683
|
const account = resolveAccount();
|
|
@@ -6940,7 +6941,7 @@ ${result.result.text}` : result.result.text;
|
|
|
6940
6941
|
}
|
|
6941
6942
|
});
|
|
6942
6943
|
});
|
|
6943
|
-
return
|
|
6944
|
+
return app64;
|
|
6944
6945
|
}
|
|
6945
6946
|
|
|
6946
6947
|
// app/lib/channel-pty-bridge/admin-session-id.ts
|
|
@@ -6974,8 +6975,8 @@ function isLoopbackAddr(addr) {
|
|
|
6974
6975
|
return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
|
|
6975
6976
|
}
|
|
6976
6977
|
function createScheduleInjectRoutes(deps) {
|
|
6977
|
-
const
|
|
6978
|
-
|
|
6978
|
+
const app64 = new Hono();
|
|
6979
|
+
app64.post("/", async (c) => {
|
|
6979
6980
|
const env = c.env;
|
|
6980
6981
|
const remoteAddr = env?.incoming?.socket?.remoteAddress ?? "";
|
|
6981
6982
|
if (!isLoopbackAddr(remoteAddr)) {
|
|
@@ -7076,11 +7077,11 @@ function createScheduleInjectRoutes(deps) {
|
|
|
7076
7077
|
console.error(`${TAG17} op=inject-spawn eventId=${eventId} sessionId=${sessionId} result=ok status=-`);
|
|
7077
7078
|
return c.json({ ok: true }, 200);
|
|
7078
7079
|
});
|
|
7079
|
-
return
|
|
7080
|
+
return app64;
|
|
7080
7081
|
}
|
|
7081
7082
|
|
|
7082
7083
|
// server/index.ts
|
|
7083
|
-
var
|
|
7084
|
+
var import_dist10 = __toESM(require_dist(), 1);
|
|
7084
7085
|
|
|
7085
7086
|
// app/lib/whatsapp/socket-resolution-error.ts
|
|
7086
7087
|
function formatPresentKeys(presentKeys) {
|
|
@@ -12012,8 +12013,8 @@ async function reapplyLeversViaManager() {
|
|
|
12012
12013
|
var WEBCHAT_SEND_TURN_WINDOW_MS = Number(process.env.WEBCHAT_SEND_TURN_WINDOW_MS ?? String(15e3));
|
|
12013
12014
|
var sendSeq = 0;
|
|
12014
12015
|
function createWebchatRoutes(deps) {
|
|
12015
|
-
const
|
|
12016
|
-
|
|
12016
|
+
const app64 = new Hono();
|
|
12017
|
+
app64.post("/send", requireAdminSession, async (c) => {
|
|
12017
12018
|
let accountId;
|
|
12018
12019
|
try {
|
|
12019
12020
|
accountId = resolvePlatformAccountId();
|
|
@@ -12225,7 +12226,7 @@ ${note}` : note;
|
|
|
12225
12226
|
if (turnTimer.unref) turnTimer.unref();
|
|
12226
12227
|
return c.json({ ok: true });
|
|
12227
12228
|
});
|
|
12228
|
-
|
|
12229
|
+
app64.post("/interrupt", requireAdminSession, async (c) => {
|
|
12229
12230
|
const cacheKey = c.get("cacheKey");
|
|
12230
12231
|
const requesterUserId = (cacheKey ? getUserIdForSession(cacheKey) : void 0) ?? null;
|
|
12231
12232
|
const primaryUserId = resolvePrimaryAdminUserId();
|
|
@@ -12253,7 +12254,7 @@ ${note}` : note;
|
|
|
12253
12254
|
}
|
|
12254
12255
|
return c.json({ ok: true, stopped: outcome.stopped, intId: outcome.intId, deadChild: outcome.deadChild }, 200);
|
|
12255
12256
|
});
|
|
12256
|
-
|
|
12257
|
+
app64.post("/settings", requireAdminSession, async (c) => {
|
|
12257
12258
|
const body = await c.req.json().catch(() => null);
|
|
12258
12259
|
const op = body?.op;
|
|
12259
12260
|
const value = body?.value;
|
|
@@ -12293,7 +12294,7 @@ ${note}` : note;
|
|
|
12293
12294
|
console.log(`[webchat:settings] op=${op} outcome=accepted value=${value} settingsApplied=${settingsApplied}`);
|
|
12294
12295
|
return c.json({ ok: true, settingsApplied });
|
|
12295
12296
|
});
|
|
12296
|
-
|
|
12297
|
+
app64.get("/session", requireAdminSession, async (c) => {
|
|
12297
12298
|
let accountId;
|
|
12298
12299
|
try {
|
|
12299
12300
|
accountId = resolvePlatformAccountId();
|
|
@@ -12371,7 +12372,7 @@ ${note}` : note;
|
|
|
12371
12372
|
const indicators = await fetchComposerIndicators(sessionId);
|
|
12372
12373
|
return c.json({ sessionId, projectDir, source, sizeBytes: jsonlSizeBytes(projectDir, sessionId), pendingPermissionPrompt: deps.pendingPromptFor?.(`session:${sessionId}`) ?? null, deliveryFailure: deps.deliveryFailureFor?.(`session:${sessionId}`) ?? null, ...indicators, ...readLevers(account) });
|
|
12373
12374
|
});
|
|
12374
|
-
|
|
12375
|
+
app64.post("/permission-verdict", requireAdminSession, async (c) => {
|
|
12375
12376
|
const body = await c.req.json().catch(() => null);
|
|
12376
12377
|
const sessionId = body?.sessionId;
|
|
12377
12378
|
const requestId = body?.request_id;
|
|
@@ -12388,7 +12389,7 @@ ${note}` : note;
|
|
|
12388
12389
|
const ok = deps.resolvePermissionVerdict?.(`session:${sessionId}`, requestId, behavior) ?? false;
|
|
12389
12390
|
return c.json({ ok });
|
|
12390
12391
|
});
|
|
12391
|
-
return
|
|
12392
|
+
return app64;
|
|
12392
12393
|
}
|
|
12393
12394
|
|
|
12394
12395
|
// server/routes/webchat-greeting.ts
|
|
@@ -12788,9 +12789,249 @@ app9.get("/callback", async (c) => {
|
|
|
12788
12789
|
});
|
|
12789
12790
|
var quickbooks_default = app9;
|
|
12790
12791
|
|
|
12792
|
+
// server/routes/google-oauth.ts
|
|
12793
|
+
import { createCipheriv, createDecipheriv, randomBytes } from "crypto";
|
|
12794
|
+
import { chmodSync, existsSync as existsSync17, mkdirSync as mkdirSync5, readdirSync as readdirSync16, readFileSync as readFileSync25, renameSync as renameSync6, rmSync as rmSync2, writeFileSync as writeFileSync9 } from "fs";
|
|
12795
|
+
import { join as join24 } from "path";
|
|
12796
|
+
var TAG26 = "[google-oauth]";
|
|
12797
|
+
var TOKEN_URL = "https://oauth2.googleapis.com/token";
|
|
12798
|
+
var PRIMARY_CALENDAR_URL = "https://www.googleapis.com/calendar/v3/calendars/primary";
|
|
12799
|
+
var PENDING_LIFETIME_MS = 6e5;
|
|
12800
|
+
function sanitizeAccountKey(key) {
|
|
12801
|
+
const safe = key.replace(/[^A-Za-z0-9._-]/g, "_");
|
|
12802
|
+
return safe === "." || safe === ".." ? `_${safe}` : safe;
|
|
12803
|
+
}
|
|
12804
|
+
function secretsDir(accountsDir, accountId) {
|
|
12805
|
+
return join24(accountsDir, sanitizeAccountKey(accountId), "secrets", "google");
|
|
12806
|
+
}
|
|
12807
|
+
function esc(s) {
|
|
12808
|
+
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
12809
|
+
}
|
|
12810
|
+
function refreshTokenBelongsToAccount(accountsDir, accountId, refreshToken) {
|
|
12811
|
+
const dir = join24(secretsDir(accountsDir, accountId), "accounts");
|
|
12812
|
+
if (!existsSync17(dir)) return false;
|
|
12813
|
+
let key;
|
|
12814
|
+
try {
|
|
12815
|
+
key = loadKey(accountsDir, accountId);
|
|
12816
|
+
} catch {
|
|
12817
|
+
return false;
|
|
12818
|
+
}
|
|
12819
|
+
for (const entry of readdirSync16(dir)) {
|
|
12820
|
+
const path3 = join24(dir, entry, "tokens.enc");
|
|
12821
|
+
if (!existsSync17(path3)) continue;
|
|
12822
|
+
try {
|
|
12823
|
+
const blob = JSON.parse(decrypt(key, readFileSync25(path3, "utf-8").trim()));
|
|
12824
|
+
if (blob.refreshToken && blob.refreshToken === refreshToken) return true;
|
|
12825
|
+
} catch {
|
|
12826
|
+
}
|
|
12827
|
+
}
|
|
12828
|
+
return false;
|
|
12829
|
+
}
|
|
12830
|
+
function loadKey(accountsDir, accountId) {
|
|
12831
|
+
const dir = secretsDir(accountsDir, accountId);
|
|
12832
|
+
const keyPath = join24(dir, ".key");
|
|
12833
|
+
mkdirSync5(dir, { recursive: true, mode: 448 });
|
|
12834
|
+
if (existsSync17(keyPath)) return Buffer.from(readFileSync25(keyPath, "utf-8").trim(), "base64");
|
|
12835
|
+
const k = randomBytes(32);
|
|
12836
|
+
writeFileSync9(keyPath, k.toString("base64"), { mode: 384 });
|
|
12837
|
+
chmodSync(keyPath, 384);
|
|
12838
|
+
return k;
|
|
12839
|
+
}
|
|
12840
|
+
function decrypt(key, raw) {
|
|
12841
|
+
const [ivHex, payload] = raw.split(":");
|
|
12842
|
+
const d = createDecipheriv("aes-256-cbc", key, Buffer.from(ivHex, "hex"));
|
|
12843
|
+
return d.update(payload, "hex", "utf8") + d.final("utf8");
|
|
12844
|
+
}
|
|
12845
|
+
function encrypt(key, plain) {
|
|
12846
|
+
const iv = randomBytes(16);
|
|
12847
|
+
const c = createCipheriv("aes-256-cbc", key, iv);
|
|
12848
|
+
return `${iv.toString("hex")}:${c.update(plain, "utf8", "hex") + c.final("hex")}`;
|
|
12849
|
+
}
|
|
12850
|
+
function atomicWrite(path3, contents) {
|
|
12851
|
+
const temp = `${path3}.${process.pid}.${randomBytes(6).toString("hex")}.tmp`;
|
|
12852
|
+
try {
|
|
12853
|
+
writeFileSync9(temp, contents, { mode: 384 });
|
|
12854
|
+
chmodSync(temp, 384);
|
|
12855
|
+
renameSync6(temp, path3);
|
|
12856
|
+
} catch (err) {
|
|
12857
|
+
try {
|
|
12858
|
+
rmSync2(temp, { force: true });
|
|
12859
|
+
} catch {
|
|
12860
|
+
}
|
|
12861
|
+
throw err;
|
|
12862
|
+
}
|
|
12863
|
+
}
|
|
12864
|
+
function readPending(accountsDir, accountId) {
|
|
12865
|
+
const path3 = join24(secretsDir(accountsDir, accountId), "pending-oauth.enc");
|
|
12866
|
+
if (!existsSync17(path3)) return null;
|
|
12867
|
+
const raw = readFileSync25(path3, "utf-8").trim();
|
|
12868
|
+
if (!raw) return null;
|
|
12869
|
+
try {
|
|
12870
|
+
return JSON.parse(decrypt(loadKey(accountsDir, accountId), raw));
|
|
12871
|
+
} catch {
|
|
12872
|
+
return null;
|
|
12873
|
+
}
|
|
12874
|
+
}
|
|
12875
|
+
function clearPending(accountsDir, accountId) {
|
|
12876
|
+
const path3 = join24(secretsDir(accountsDir, accountId), "pending-oauth.enc");
|
|
12877
|
+
if (existsSync17(path3)) rmSync2(path3, { force: true });
|
|
12878
|
+
}
|
|
12879
|
+
function writeTokens(accountsDir, accountId, email, tok) {
|
|
12880
|
+
const key = loadKey(accountsDir, accountId);
|
|
12881
|
+
const dir = join24(secretsDir(accountsDir, accountId), "accounts", sanitizeAccountKey(email));
|
|
12882
|
+
mkdirSync5(dir, { recursive: true, mode: 448 });
|
|
12883
|
+
const now = Date.now();
|
|
12884
|
+
const blob = {
|
|
12885
|
+
accessToken: tok.accessToken,
|
|
12886
|
+
refreshToken: tok.refreshToken,
|
|
12887
|
+
accessTokenExpiry: now + tok.expiresInSeconds * 1e3,
|
|
12888
|
+
lastRefresh: now,
|
|
12889
|
+
email,
|
|
12890
|
+
scopes: tok.scopes
|
|
12891
|
+
};
|
|
12892
|
+
atomicWrite(join24(dir, "tokens.enc"), encrypt(key, JSON.stringify(blob)));
|
|
12893
|
+
}
|
|
12894
|
+
function readHouseGoogleCreds(platformRoot5) {
|
|
12895
|
+
const path3 = join24(platformRoot5, "config", "google-house.env");
|
|
12896
|
+
if (!existsSync17(path3)) return null;
|
|
12897
|
+
const env = {};
|
|
12898
|
+
for (const line of readFileSync25(path3, "utf-8").split(/\r?\n/)) {
|
|
12899
|
+
const m = line.match(/^([A-Z0-9_]+)=(.*)$/);
|
|
12900
|
+
if (m) env[m[1]] = m[2].trim();
|
|
12901
|
+
}
|
|
12902
|
+
if (!env.GOOGLE_CLIENT_ID || !env.GOOGLE_CLIENT_SECRET) return null;
|
|
12903
|
+
return { clientId: env.GOOGLE_CLIENT_ID, clientSecret: env.GOOGLE_CLIENT_SECRET };
|
|
12904
|
+
}
|
|
12905
|
+
function page2(title, body) {
|
|
12906
|
+
return `<!doctype html><meta name="viewport" content="width=device-width,initial-scale=1"><title>${title}</title><div style="font:16px/1.5 system-ui;margin:3rem auto;max-width:30rem;padding:0 1rem"><h1 style="font-size:1.3rem">${title}</h1><p>${body}</p></div>`;
|
|
12907
|
+
}
|
|
12908
|
+
function createGoogleOAuthRoutes(platformRoot5, accountsDir) {
|
|
12909
|
+
const routes = new Hono();
|
|
12910
|
+
routes.get("/oauth/callback", async (c) => {
|
|
12911
|
+
const code = c.req.query("code");
|
|
12912
|
+
const state = c.req.query("state");
|
|
12913
|
+
const accountId = c.req.query("account");
|
|
12914
|
+
if (!code || !state || !accountId) {
|
|
12915
|
+
console.error(`${TAG26} op=callback outcome=error error=missing-params`);
|
|
12916
|
+
return c.html(page2("Missing parameters", "Return to your chat and start again."), 400);
|
|
12917
|
+
}
|
|
12918
|
+
const held = readPending(accountsDir, accountId);
|
|
12919
|
+
const stateMatch = held !== null && held.state === state;
|
|
12920
|
+
console.error(`${TAG26} op=callback reg=${state} account=${accountId} state-match=${stateMatch}`);
|
|
12921
|
+
if (!held || !stateMatch) {
|
|
12922
|
+
return c.html(page2("This link has expired", "Return to your chat and start again."), 400);
|
|
12923
|
+
}
|
|
12924
|
+
const ageMs = Date.now() - held.createdAt;
|
|
12925
|
+
if (ageMs > PENDING_LIFETIME_MS) {
|
|
12926
|
+
console.error(`${TAG26} op=callback reg=${state} outcome=error error=pending-expired ageMs=${ageMs}`);
|
|
12927
|
+
clearPending(accountsDir, accountId);
|
|
12928
|
+
return c.html(page2("This link has expired", "Return to your chat and start again."), 400);
|
|
12929
|
+
}
|
|
12930
|
+
const failed = (title, body, status) => {
|
|
12931
|
+
clearPending(accountsDir, accountId);
|
|
12932
|
+
return c.html(page2(title, body), status);
|
|
12933
|
+
};
|
|
12934
|
+
const creds = readHouseGoogleCreds(platformRoot5);
|
|
12935
|
+
if (!creds) {
|
|
12936
|
+
console.error(`${TAG26} op=token-exchange reg=${state} outcome=error error=house-env-missing`);
|
|
12937
|
+
return failed("Not configured", "This install has no Google credentials yet.", 500);
|
|
12938
|
+
}
|
|
12939
|
+
const publicBase = (process.env.GOOGLE_PUBLIC_BASE ?? "").replace(/\/+$/, "");
|
|
12940
|
+
if (!publicBase) {
|
|
12941
|
+
console.error(`${TAG26} op=callback reg=${state} outcome=error error=public-base-unset`);
|
|
12942
|
+
return failed("Not configured", "This install has no public base configured.", 500);
|
|
12943
|
+
}
|
|
12944
|
+
const redirectUri = `${publicBase}/api/google/oauth/callback?account=${encodeURIComponent(accountId)}`;
|
|
12945
|
+
try {
|
|
12946
|
+
const res = await fetch(TOKEN_URL, {
|
|
12947
|
+
method: "POST",
|
|
12948
|
+
headers: { "content-type": "application/x-www-form-urlencoded" },
|
|
12949
|
+
body: new URLSearchParams({
|
|
12950
|
+
code,
|
|
12951
|
+
client_id: creds.clientId,
|
|
12952
|
+
client_secret: creds.clientSecret,
|
|
12953
|
+
redirect_uri: redirectUri,
|
|
12954
|
+
grant_type: "authorization_code",
|
|
12955
|
+
code_verifier: held.verifier
|
|
12956
|
+
})
|
|
12957
|
+
});
|
|
12958
|
+
const text = await res.text();
|
|
12959
|
+
if (!res.ok) {
|
|
12960
|
+
console.error(`${TAG26} op=token-exchange reg=${state} outcome=error status=${res.status} body=${text.slice(0, 300)}`);
|
|
12961
|
+
return failed("Could not connect", `Google refused the exchange (${res.status}).`, 502);
|
|
12962
|
+
}
|
|
12963
|
+
console.error(`${TAG26} op=token-exchange reg=${state} outcome=ok`);
|
|
12964
|
+
const tok = JSON.parse(text);
|
|
12965
|
+
const calRes = await fetch(PRIMARY_CALENDAR_URL, {
|
|
12966
|
+
headers: { authorization: `Bearer ${tok.access_token}` }
|
|
12967
|
+
});
|
|
12968
|
+
const calText = await calRes.text();
|
|
12969
|
+
if (!calRes.ok) {
|
|
12970
|
+
console.error(`${TAG26} op=identity reg=${state} outcome=error status=${calRes.status} body=${calText.slice(0, 300)}`);
|
|
12971
|
+
return failed("Could not connect", "Connected, but the calendar identity could not be read.", 502);
|
|
12972
|
+
}
|
|
12973
|
+
const email = JSON.parse(calText).id;
|
|
12974
|
+
console.error(`${TAG26} op=identity reg=${state} email=${email}`);
|
|
12975
|
+
writeTokens(accountsDir, accountId, email, {
|
|
12976
|
+
accessToken: tok.access_token,
|
|
12977
|
+
refreshToken: tok.refresh_token ?? null,
|
|
12978
|
+
expiresInSeconds: tok.expires_in,
|
|
12979
|
+
scopes: tok.scope ? tok.scope.split(" ") : []
|
|
12980
|
+
});
|
|
12981
|
+
console.error(
|
|
12982
|
+
`${TAG26} op=tokens-write reg=${state} account=${accountId} refreshIssued=${tok.refresh_token ? "true" : "false"}`
|
|
12983
|
+
);
|
|
12984
|
+
clearPending(accountsDir, accountId);
|
|
12985
|
+
console.error(`${TAG26} op=pending-clear reg=${state} verified=${readPending(accountsDir, accountId) === null}`);
|
|
12986
|
+
console.error(`${TAG26} op=registered reg=${state} account=${accountId} email=${email}`);
|
|
12987
|
+
return c.html(
|
|
12988
|
+
page2(
|
|
12989
|
+
"Calendar connected",
|
|
12990
|
+
`${esc(email)} is connected to this account. You can close this page and return to your chat.`
|
|
12991
|
+
)
|
|
12992
|
+
);
|
|
12993
|
+
} catch (err) {
|
|
12994
|
+
const msg = err.message;
|
|
12995
|
+
console.error(`${TAG26} op=token-exchange reg=${state} outcome=error error=${msg}`);
|
|
12996
|
+
return failed("Could not connect", "Something went wrong. Return to your chat and try again.", 502);
|
|
12997
|
+
}
|
|
12998
|
+
});
|
|
12999
|
+
routes.post("/oauth/refresh", async (c) => {
|
|
13000
|
+
const body = await c.req.json().catch(() => ({}));
|
|
13001
|
+
const { accountId, refreshToken } = body;
|
|
13002
|
+
if (!accountId || !refreshToken) {
|
|
13003
|
+
return c.json({ error: "accountId and refreshToken are required" }, 400);
|
|
13004
|
+
}
|
|
13005
|
+
if (!refreshTokenBelongsToAccount(accountsDir, accountId, refreshToken)) {
|
|
13006
|
+
console.error(`${TAG26} op=refresh account=${accountId} outcome=denied reason=token-not-held`);
|
|
13007
|
+
return c.json({ error: "refresh token is not held by this account" }, 403);
|
|
13008
|
+
}
|
|
13009
|
+
const creds = readHouseGoogleCreds(platformRoot5);
|
|
13010
|
+
if (!creds) return c.json({ error: "google-house.env is absent or incomplete" }, 500);
|
|
13011
|
+
const res = await fetch(TOKEN_URL, {
|
|
13012
|
+
method: "POST",
|
|
13013
|
+
headers: { "content-type": "application/x-www-form-urlencoded" },
|
|
13014
|
+
body: new URLSearchParams({
|
|
13015
|
+
client_id: creds.clientId,
|
|
13016
|
+
client_secret: creds.clientSecret,
|
|
13017
|
+
refresh_token: refreshToken,
|
|
13018
|
+
grant_type: "refresh_token"
|
|
13019
|
+
})
|
|
13020
|
+
});
|
|
13021
|
+
const text = await res.text();
|
|
13022
|
+
if (!res.ok) {
|
|
13023
|
+
console.error(`${TAG26} op=refresh account=${accountId} outcome=error status=${res.status} body=${text.slice(0, 300)}`);
|
|
13024
|
+
return c.json({ error: text.slice(0, 300) }, 502);
|
|
13025
|
+
}
|
|
13026
|
+
console.error(`${TAG26} op=refresh account=${accountId} outcome=ok`);
|
|
13027
|
+
return c.json(JSON.parse(text));
|
|
13028
|
+
});
|
|
13029
|
+
return routes;
|
|
13030
|
+
}
|
|
13031
|
+
|
|
12791
13032
|
// server/routes/onboarding.ts
|
|
12792
13033
|
import { spawn, spawnSync as spawnSync2, execFileSync as execFileSync3 } from "child_process";
|
|
12793
|
-
import { openSync as openSync3, closeSync as closeSync3, writeFileSync as
|
|
13034
|
+
import { openSync as openSync3, closeSync as closeSync3, writeFileSync as writeFileSync11, writeSync, existsSync as existsSync19, readFileSync as readFileSync27, unlinkSync as unlinkSync3, renameSync as renameSync8 } from "fs";
|
|
12794
13035
|
import { createHash as createHash4, randomUUID as randomUUID8 } from "crypto";
|
|
12795
13036
|
|
|
12796
13037
|
// app/lib/claude-spawn-env.ts
|
|
@@ -12799,7 +13040,7 @@ function claudeBin() {
|
|
|
12799
13040
|
}
|
|
12800
13041
|
|
|
12801
13042
|
// server/routes/onboarding.ts
|
|
12802
|
-
import { dirname as dirname9, join as
|
|
13043
|
+
import { dirname as dirname9, join as join26 } from "path";
|
|
12803
13044
|
|
|
12804
13045
|
// app/lib/claude-keychain.ts
|
|
12805
13046
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
@@ -12928,8 +13169,8 @@ function readHostCredsBlob(service) {
|
|
|
12928
13169
|
}
|
|
12929
13170
|
|
|
12930
13171
|
// ../lib/admins-write/src/index.ts
|
|
12931
|
-
import { existsSync as
|
|
12932
|
-
import { dirname as dirname8, join as
|
|
13172
|
+
import { existsSync as existsSync18, readFileSync as readFileSync26, writeFileSync as writeFileSync10, renameSync as renameSync7, mkdirSync as mkdirSync6, readdirSync as readdirSync17, statSync as statSync8, appendFileSync as appendFileSync2 } from "fs";
|
|
13173
|
+
import { dirname as dirname8, join as join25 } from "path";
|
|
12933
13174
|
function id8(value) {
|
|
12934
13175
|
return value.slice(0, 8);
|
|
12935
13176
|
}
|
|
@@ -12943,7 +13184,7 @@ function appendUsersAuditLine(audit, fields) {
|
|
|
12943
13184
|
const line = `[users-audit] action=${fields.action} actor=${actor}${targetFields}${sess} field=${fields.field} rowsBefore=${fields.rowsBefore} rowsAfter=${fields.rowsAfter} ts=${(/* @__PURE__ */ new Date()).toISOString()}
|
|
12944
13185
|
`;
|
|
12945
13186
|
try {
|
|
12946
|
-
|
|
13187
|
+
mkdirSync6(dirname8(audit.logFile), { recursive: true, mode: 448 });
|
|
12947
13188
|
appendFileSync2(audit.logFile, line, { mode: 384 });
|
|
12948
13189
|
} catch (err) {
|
|
12949
13190
|
console.error(
|
|
@@ -12961,17 +13202,17 @@ function logLine(input, result) {
|
|
|
12961
13202
|
);
|
|
12962
13203
|
}
|
|
12963
13204
|
function writeFileAtomic(filePath, contents, mode) {
|
|
12964
|
-
|
|
13205
|
+
mkdirSync6(dirname8(filePath), { recursive: true });
|
|
12965
13206
|
const tempPath = `${filePath}.tmp-${process.pid}-${Date.now()}`;
|
|
12966
|
-
|
|
12967
|
-
|
|
13207
|
+
writeFileSync10(tempPath, contents, mode !== void 0 ? { mode } : void 0);
|
|
13208
|
+
renameSync7(tempPath, filePath);
|
|
12968
13209
|
}
|
|
12969
13210
|
function writeAdminEntry(input) {
|
|
12970
13211
|
const result = { usersJsonResult: "noop", accountJsonResult: "noop" };
|
|
12971
13212
|
try {
|
|
12972
13213
|
let users = [];
|
|
12973
|
-
if (
|
|
12974
|
-
const raw =
|
|
13214
|
+
if (existsSync18(input.usersFile)) {
|
|
13215
|
+
const raw = readFileSync26(input.usersFile, "utf-8").trim();
|
|
12975
13216
|
if (raw) {
|
|
12976
13217
|
const parsed = JSON.parse(raw);
|
|
12977
13218
|
if (!Array.isArray(parsed)) {
|
|
@@ -13002,11 +13243,11 @@ function writeAdminEntry(input) {
|
|
|
13002
13243
|
return result;
|
|
13003
13244
|
}
|
|
13004
13245
|
try {
|
|
13005
|
-
const accountJsonPath =
|
|
13006
|
-
if (!
|
|
13246
|
+
const accountJsonPath = join25(input.accountDir, "account.json");
|
|
13247
|
+
if (!existsSync18(accountJsonPath)) {
|
|
13007
13248
|
throw new Error(`account.json not found at ${accountJsonPath}`);
|
|
13008
13249
|
}
|
|
13009
|
-
const config = JSON.parse(
|
|
13250
|
+
const config = JSON.parse(readFileSync26(accountJsonPath, "utf-8"));
|
|
13010
13251
|
const admins = config.admins ?? [];
|
|
13011
13252
|
if (admins.some((a) => a.userId === input.userId)) {
|
|
13012
13253
|
result.accountJsonResult = "noop";
|
|
@@ -13026,9 +13267,9 @@ function writeAdminEntry(input) {
|
|
|
13026
13267
|
function computeAdminStoreDivergence(input) {
|
|
13027
13268
|
const result = { divergences: 0, accountWithoutUsers: [], usersWithoutAccount: [], errors: [] };
|
|
13028
13269
|
const usersUserIds = /* @__PURE__ */ new Set();
|
|
13029
|
-
if (
|
|
13270
|
+
if (existsSync18(input.usersFile)) {
|
|
13030
13271
|
try {
|
|
13031
|
-
const raw =
|
|
13272
|
+
const raw = readFileSync26(input.usersFile, "utf-8").trim();
|
|
13032
13273
|
if (raw) {
|
|
13033
13274
|
const users = JSON.parse(raw);
|
|
13034
13275
|
for (const u of users) {
|
|
@@ -13040,27 +13281,27 @@ function computeAdminStoreDivergence(input) {
|
|
|
13040
13281
|
}
|
|
13041
13282
|
}
|
|
13042
13283
|
const accountUserIds = /* @__PURE__ */ new Set();
|
|
13043
|
-
if (
|
|
13284
|
+
if (existsSync18(input.accountsDir)) {
|
|
13044
13285
|
let entries;
|
|
13045
13286
|
try {
|
|
13046
|
-
entries =
|
|
13287
|
+
entries = readdirSync17(input.accountsDir);
|
|
13047
13288
|
} catch (err) {
|
|
13048
13289
|
result.errors.push({ source: input.accountsDir, detail: err instanceof Error ? err.message : String(err) });
|
|
13049
13290
|
return result;
|
|
13050
13291
|
}
|
|
13051
13292
|
for (const entry of entries) {
|
|
13052
13293
|
if (entry.startsWith(".")) continue;
|
|
13053
|
-
const accountDir =
|
|
13294
|
+
const accountDir = join25(input.accountsDir, entry);
|
|
13054
13295
|
try {
|
|
13055
13296
|
if (!statSync8(accountDir).isDirectory()) continue;
|
|
13056
13297
|
} catch {
|
|
13057
13298
|
continue;
|
|
13058
13299
|
}
|
|
13059
|
-
const accountJsonPath =
|
|
13060
|
-
if (!
|
|
13300
|
+
const accountJsonPath = join25(accountDir, "account.json");
|
|
13301
|
+
if (!existsSync18(accountJsonPath)) continue;
|
|
13061
13302
|
let admins = [];
|
|
13062
13303
|
try {
|
|
13063
|
-
const config = JSON.parse(
|
|
13304
|
+
const config = JSON.parse(readFileSync26(accountJsonPath, "utf-8"));
|
|
13064
13305
|
admins = config.admins ?? [];
|
|
13065
13306
|
} catch (err) {
|
|
13066
13307
|
result.errors.push({ source: accountJsonPath, detail: err instanceof Error ? err.message : String(err) });
|
|
@@ -13108,8 +13349,8 @@ function hashPin2(pin) {
|
|
|
13108
13349
|
return createHash4("sha256").update(pin).digest("hex");
|
|
13109
13350
|
}
|
|
13110
13351
|
function readUsersFile2() {
|
|
13111
|
-
if (!
|
|
13112
|
-
const raw =
|
|
13352
|
+
if (!existsSync19(USERS_FILE)) return null;
|
|
13353
|
+
const raw = readFileSync27(USERS_FILE, "utf-8").trim();
|
|
13113
13354
|
if (!raw) return [];
|
|
13114
13355
|
return JSON.parse(raw);
|
|
13115
13356
|
}
|
|
@@ -13168,7 +13409,7 @@ app10.post("/claude-auth", async (c) => {
|
|
|
13168
13409
|
} catch (err) {
|
|
13169
13410
|
logoutError = err instanceof Error ? err.message : String(err);
|
|
13170
13411
|
}
|
|
13171
|
-
const credentialsPresent =
|
|
13412
|
+
const credentialsPresent = existsSync19(CLAUDE_CREDENTIALS_FILE);
|
|
13172
13413
|
const ranMs = Date.now() - start;
|
|
13173
13414
|
console.log(`[onboarding] op=claude-logout credentialsPresent=${credentialsPresent} ranMs=${ranMs} logoutError=${logoutError ? JSON.stringify(logoutError.slice(0, 120)) : "none"}`);
|
|
13174
13415
|
return c.json({ logged_out: !credentialsPresent });
|
|
@@ -13202,7 +13443,7 @@ app10.post("/claude-auth", async (c) => {
|
|
|
13202
13443
|
return c.json({ launched: cdpReady });
|
|
13203
13444
|
}
|
|
13204
13445
|
ensureLogDir();
|
|
13205
|
-
|
|
13446
|
+
writeFileSync11(logPath("claude-auth"), "");
|
|
13206
13447
|
const claudeAuthLogFd = openSync3(logPath("claude-auth"), "a");
|
|
13207
13448
|
const onClaudeOutput = (chunk) => writeSync(claudeAuthLogFd, chunk);
|
|
13208
13449
|
if (process.platform === "darwin") {
|
|
@@ -13227,14 +13468,14 @@ app10.post("/claude-auth", async (c) => {
|
|
|
13227
13468
|
readBlob: readHostCredsBlob,
|
|
13228
13469
|
writeFile: (blob) => {
|
|
13229
13470
|
const tmp = `${CLAUDE_CREDENTIALS_FILE}.${process.pid}.tmp`;
|
|
13230
|
-
|
|
13231
|
-
|
|
13471
|
+
writeFileSync11(tmp, blob, { mode: 384 });
|
|
13472
|
+
renameSync8(tmp, CLAUDE_CREDENTIALS_FILE);
|
|
13232
13473
|
},
|
|
13233
13474
|
log: (line) => console.log(line)
|
|
13234
13475
|
});
|
|
13235
13476
|
persistKeychainService(
|
|
13236
13477
|
writebackResult,
|
|
13237
|
-
(service) =>
|
|
13478
|
+
(service) => writeFileSync11(join26(dirname9(CLAUDE_CREDENTIALS_FILE), ".keychain-service"), service, { mode: 384 }),
|
|
13238
13479
|
(line) => console.log(line)
|
|
13239
13480
|
);
|
|
13240
13481
|
if (darwinAuthChild === claudeProc2) darwinAuthChild = null;
|
|
@@ -13317,9 +13558,9 @@ app10.post("/set-pin", async (c) => {
|
|
|
13317
13558
|
console.log(`[set-pin] wrote users.json + account.json admins: userId=${userId.slice(0, 8)}\u2026 role=owner`);
|
|
13318
13559
|
if (process.platform === "linux") {
|
|
13319
13560
|
let installOwner = null;
|
|
13320
|
-
if (
|
|
13561
|
+
if (existsSync19(INSTALL_OWNER_FILE)) {
|
|
13321
13562
|
try {
|
|
13322
|
-
const raw =
|
|
13563
|
+
const raw = readFileSync27(INSTALL_OWNER_FILE, "utf-8").trim();
|
|
13323
13564
|
if (raw.length > 0) installOwner = raw;
|
|
13324
13565
|
} catch (err) {
|
|
13325
13566
|
console.error(`[set-pin] install-owner-read-failed path=${INSTALL_OWNER_FILE} error=${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -13400,7 +13641,7 @@ app10.delete("/set-pin", requireAdminSession, async (c) => {
|
|
|
13400
13641
|
unlinkSync3(USERS_FILE);
|
|
13401
13642
|
console.log(`[set-pin] cleared users.json (last entry removed): userId=${sessionUserId.slice(0, 8)}\u2026`);
|
|
13402
13643
|
} else {
|
|
13403
|
-
|
|
13644
|
+
writeFileSync11(USERS_FILE, JSON.stringify(remaining), { mode: 384 });
|
|
13404
13645
|
console.log(`[set-pin] removed entry from users.json: userId=${sessionUserId.slice(0, 8)}\u2026 remaining=${remaining.length}`);
|
|
13405
13646
|
}
|
|
13406
13647
|
logUsersAudit(
|
|
@@ -13465,9 +13706,9 @@ app10.put("/set-pin", requireAdminSession, async (c) => {
|
|
|
13465
13706
|
console.log(`[set-pin] changed PIN in place: userId=${sessionUserId.slice(0, 8)}\u2026`);
|
|
13466
13707
|
if (process.platform === "linux") {
|
|
13467
13708
|
let installOwner = null;
|
|
13468
|
-
if (
|
|
13709
|
+
if (existsSync19(INSTALL_OWNER_FILE)) {
|
|
13469
13710
|
try {
|
|
13470
|
-
const raw =
|
|
13711
|
+
const raw = readFileSync27(INSTALL_OWNER_FILE, "utf-8").trim();
|
|
13471
13712
|
if (raw.length > 0) installOwner = raw;
|
|
13472
13713
|
} catch (err) {
|
|
13473
13714
|
console.error(`[set-pin] install-owner-read-failed path=${INSTALL_OWNER_FILE} error=${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -13499,9 +13740,9 @@ ${body.newPin}
|
|
|
13499
13740
|
var onboarding_default = app10;
|
|
13500
13741
|
|
|
13501
13742
|
// server/routes/client-error.ts
|
|
13502
|
-
import { appendFileSync as appendFileSync3, existsSync as
|
|
13503
|
-
import { join as
|
|
13504
|
-
var CLIENT_ERRORS_LOG =
|
|
13743
|
+
import { appendFileSync as appendFileSync3, existsSync as existsSync20, renameSync as renameSync9, statSync as statSync9 } from "fs";
|
|
13744
|
+
import { join as join27 } from "path";
|
|
13745
|
+
var CLIENT_ERRORS_LOG = join27(LOG_DIR, "client-errors.log");
|
|
13505
13746
|
var MAX_LOG_SIZE = 10 * 1024 * 1024;
|
|
13506
13747
|
var MAX_BODY_SIZE = 8 * 1024;
|
|
13507
13748
|
var MAX_STACK_LEN = 2e3;
|
|
@@ -13549,10 +13790,10 @@ function stackHead(stack) {
|
|
|
13549
13790
|
}
|
|
13550
13791
|
function rotateIfNeeded() {
|
|
13551
13792
|
try {
|
|
13552
|
-
if (!
|
|
13793
|
+
if (!existsSync20(CLIENT_ERRORS_LOG)) return;
|
|
13553
13794
|
const stats = statSync9(CLIENT_ERRORS_LOG);
|
|
13554
13795
|
if (stats.size < MAX_LOG_SIZE) return;
|
|
13555
|
-
|
|
13796
|
+
renameSync9(CLIENT_ERRORS_LOG, CLIENT_ERRORS_LOG + ".1");
|
|
13556
13797
|
} catch (err) {
|
|
13557
13798
|
console.error(`[client-error] log rotation failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
13558
13799
|
}
|
|
@@ -13876,18 +14117,18 @@ app13.get("/", requireAdminSession, async (c) => {
|
|
|
13876
14117
|
var accounts_default = app13;
|
|
13877
14118
|
|
|
13878
14119
|
// server/routes/admin/logs.ts
|
|
13879
|
-
import { existsSync as
|
|
14120
|
+
import { existsSync as existsSync22, readdirSync as readdirSync18, readFileSync as readFileSync28, statSync as statSync10 } from "fs";
|
|
13880
14121
|
import { resolve as resolve17, basename as basename7 } from "path";
|
|
13881
14122
|
|
|
13882
14123
|
// app/lib/logs-read-resolve.ts
|
|
13883
|
-
import { existsSync as
|
|
13884
|
-
import { join as
|
|
14124
|
+
import { existsSync as existsSync21 } from "fs";
|
|
14125
|
+
import { join as join28 } from "path";
|
|
13885
14126
|
function resolveSessionLogPaths(filename, logDirs) {
|
|
13886
14127
|
const tried = [filename];
|
|
13887
14128
|
const hits = [];
|
|
13888
14129
|
for (const dir of logDirs) {
|
|
13889
|
-
const fullPath =
|
|
13890
|
-
if (
|
|
14130
|
+
const fullPath = join28(dir, filename);
|
|
14131
|
+
if (existsSync21(fullPath)) {
|
|
13891
14132
|
hits.push({ path: fullPath, dir });
|
|
13892
14133
|
}
|
|
13893
14134
|
}
|
|
@@ -13915,7 +14156,7 @@ app14.get("/", async (c) => {
|
|
|
13915
14156
|
const filePath = resolve17(dir, safe);
|
|
13916
14157
|
searched.push(filePath);
|
|
13917
14158
|
try {
|
|
13918
|
-
const buffer =
|
|
14159
|
+
const buffer = readFileSync28(filePath);
|
|
13919
14160
|
const onDiskBytes = statSync10(filePath).size;
|
|
13920
14161
|
const headers = {
|
|
13921
14162
|
"Content-Type": "text/plain; charset=utf-8",
|
|
@@ -13980,7 +14221,7 @@ app14.get("/", async (c) => {
|
|
|
13980
14221
|
console.info(`[admin/logs] resolved cacheKey=${cacheKeySlice} sessionId=${sessionIdSlice} via=${primaryId === cacheKey ? "cacheKey" : primaryId === sessionKeyFromConv ? "reverse-lookup" : "sessionId-fallback"}`);
|
|
13981
14222
|
try {
|
|
13982
14223
|
const filename = basename7(hit.path);
|
|
13983
|
-
const buffer =
|
|
14224
|
+
const buffer = readFileSync28(hit.path);
|
|
13984
14225
|
const onDiskBytes = statSync10(hit.path).size;
|
|
13985
14226
|
const headers = {
|
|
13986
14227
|
"Content-Type": "text/plain; charset=utf-8",
|
|
@@ -14015,10 +14256,10 @@ app14.get("/", async (c) => {
|
|
|
14015
14256
|
const seen = /* @__PURE__ */ new Set();
|
|
14016
14257
|
const logs = {};
|
|
14017
14258
|
for (const dir of logDirs) {
|
|
14018
|
-
if (!
|
|
14259
|
+
if (!existsSync22(dir)) continue;
|
|
14019
14260
|
let files;
|
|
14020
14261
|
try {
|
|
14021
|
-
files =
|
|
14262
|
+
files = readdirSync18(dir).filter((f) => f.endsWith(".log"));
|
|
14022
14263
|
} catch (err) {
|
|
14023
14264
|
const reason = err instanceof Error ? err.message : String(err);
|
|
14024
14265
|
console.warn(`[admin/logs] readdir-fail dir=${dir} reason=${reason}`);
|
|
@@ -14027,7 +14268,7 @@ app14.get("/", async (c) => {
|
|
|
14027
14268
|
files.filter((f) => !seen.has(f)).map((f) => ({ name: f, mtime: statSync10(resolve17(dir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime).forEach(({ name }) => {
|
|
14028
14269
|
seen.add(name);
|
|
14029
14270
|
try {
|
|
14030
|
-
const content =
|
|
14271
|
+
const content = readFileSync28(resolve17(dir, name));
|
|
14031
14272
|
const tail = content.length > TAIL_BYTES ? content.subarray(content.length - TAIL_BYTES).toString("utf-8") : content.toString("utf-8");
|
|
14032
14273
|
logs[name] = tail.trim() || "(empty)";
|
|
14033
14274
|
} catch (err) {
|
|
@@ -14067,7 +14308,7 @@ var claude_info_default = app15;
|
|
|
14067
14308
|
|
|
14068
14309
|
// server/routes/admin/attachment.ts
|
|
14069
14310
|
import { readFile as readFile2, readdir } from "fs/promises";
|
|
14070
|
-
import { existsSync as
|
|
14311
|
+
import { existsSync as existsSync23 } from "fs";
|
|
14071
14312
|
import { resolve as resolve18 } from "path";
|
|
14072
14313
|
var app16 = new Hono();
|
|
14073
14314
|
var ATTACHMENT_ID_RE3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
|
|
@@ -14090,12 +14331,12 @@ app16.get("/:attachmentId", requireAdminSession, async (c) => {
|
|
|
14090
14331
|
}
|
|
14091
14332
|
let accountId = pinnedAccountId;
|
|
14092
14333
|
let dir = uploadsDirFor2(accountId, attachmentId);
|
|
14093
|
-
let found =
|
|
14334
|
+
let found = existsSync23(dir);
|
|
14094
14335
|
if (!found) {
|
|
14095
14336
|
for (const candidate of listValidAccounts()) {
|
|
14096
14337
|
if (candidate.accountId === pinnedAccountId) continue;
|
|
14097
14338
|
const candidateDir = uploadsDirFor2(candidate.accountId, attachmentId);
|
|
14098
|
-
if (
|
|
14339
|
+
if (existsSync23(candidateDir)) {
|
|
14099
14340
|
accountId = candidate.accountId;
|
|
14100
14341
|
dir = candidateDir;
|
|
14101
14342
|
found = true;
|
|
@@ -14110,7 +14351,7 @@ app16.get("/:attachmentId", requireAdminSession, async (c) => {
|
|
|
14110
14351
|
return new Response("Not found", { status: 404 });
|
|
14111
14352
|
}
|
|
14112
14353
|
const metaPath = resolve18(dir, `${attachmentId}.meta.json`);
|
|
14113
|
-
if (!
|
|
14354
|
+
if (!existsSync23(metaPath)) {
|
|
14114
14355
|
return new Response("Not found", { status: 404 });
|
|
14115
14356
|
}
|
|
14116
14357
|
let meta;
|
|
@@ -14144,23 +14385,23 @@ var attachment_default = app16;
|
|
|
14144
14385
|
|
|
14145
14386
|
// server/routes/admin/agents.ts
|
|
14146
14387
|
import { resolve as resolve19 } from "path";
|
|
14147
|
-
import { readdirSync as
|
|
14388
|
+
import { readdirSync as readdirSync19, readFileSync as readFileSync29, existsSync as existsSync24, rmSync as rmSync3 } from "fs";
|
|
14148
14389
|
var app17 = new Hono();
|
|
14149
14390
|
app17.get("/", (c) => {
|
|
14150
14391
|
const account = resolveAccount();
|
|
14151
14392
|
if (!account) return c.json({ agents: [] });
|
|
14152
14393
|
const agentsDir = resolve19(account.accountDir, "agents");
|
|
14153
|
-
if (!
|
|
14394
|
+
if (!existsSync24(agentsDir)) return c.json({ agents: [] });
|
|
14154
14395
|
const agents = [];
|
|
14155
14396
|
try {
|
|
14156
|
-
const entries =
|
|
14397
|
+
const entries = readdirSync19(agentsDir, { withFileTypes: true });
|
|
14157
14398
|
for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
14158
14399
|
if (!entry.isDirectory()) continue;
|
|
14159
14400
|
if (entry.name === "admin") continue;
|
|
14160
14401
|
const configPath2 = resolve19(agentsDir, entry.name, "config.json");
|
|
14161
|
-
if (!
|
|
14402
|
+
if (!existsSync24(configPath2)) continue;
|
|
14162
14403
|
try {
|
|
14163
|
-
const config = JSON.parse(
|
|
14404
|
+
const config = JSON.parse(readFileSync29(configPath2, "utf-8"));
|
|
14164
14405
|
agents.push({
|
|
14165
14406
|
slug: entry.name,
|
|
14166
14407
|
displayName: config.displayName ?? entry.name,
|
|
@@ -14187,7 +14428,7 @@ app17.delete("/:slug", async (c) => {
|
|
|
14187
14428
|
return c.json({ error: "Invalid agent slug" }, 400);
|
|
14188
14429
|
}
|
|
14189
14430
|
const agentDir = resolve19(account.accountDir, "agents", slug);
|
|
14190
|
-
if (!
|
|
14431
|
+
if (!existsSync24(agentDir)) {
|
|
14191
14432
|
return c.json({ error: "Agent not found" }, 404);
|
|
14192
14433
|
}
|
|
14193
14434
|
try {
|
|
@@ -14198,7 +14439,7 @@ app17.delete("/:slug", async (c) => {
|
|
|
14198
14439
|
return c.json({ error: `Graph cleanup failed: ${msg}` }, 500);
|
|
14199
14440
|
}
|
|
14200
14441
|
try {
|
|
14201
|
-
|
|
14442
|
+
rmSync3(agentDir, { recursive: true, force: true });
|
|
14202
14443
|
console.log(`[admin/agents] deleted agent "${slug}"`);
|
|
14203
14444
|
return c.json({ ok: true });
|
|
14204
14445
|
} catch (err) {
|
|
@@ -14217,7 +14458,7 @@ app17.post("/:slug/project", async (c) => {
|
|
|
14217
14458
|
return c.json({ error: "Invalid agent slug" }, 400);
|
|
14218
14459
|
}
|
|
14219
14460
|
const agentDir = resolve19(account.accountDir, "agents", slug);
|
|
14220
|
-
if (!
|
|
14461
|
+
if (!existsSync24(agentDir)) {
|
|
14221
14462
|
return c.json({ error: "Agent not found on disk" }, 404);
|
|
14222
14463
|
}
|
|
14223
14464
|
try {
|
|
@@ -14233,7 +14474,7 @@ var agents_default = app17;
|
|
|
14233
14474
|
// server/routes/admin/sessions.ts
|
|
14234
14475
|
import crypto2 from "crypto";
|
|
14235
14476
|
import { resolve as resolvePath } from "path";
|
|
14236
|
-
import { existsSync as
|
|
14477
|
+
import { existsSync as existsSync25, mkdirSync as mkdirSync7, createWriteStream } from "fs";
|
|
14237
14478
|
|
|
14238
14479
|
// ../lib/admin-conversation-purge/src/index.ts
|
|
14239
14480
|
async function purgeAdminConversationJsonls(args) {
|
|
@@ -14380,7 +14621,7 @@ var pickComponentBytes = (..._args) => null;
|
|
|
14380
14621
|
function openResumeStreamLog(accountId, sessionId) {
|
|
14381
14622
|
const dir = resolvePath(ACCOUNTS_DIR, accountId, "resume-logs");
|
|
14382
14623
|
try {
|
|
14383
|
-
|
|
14624
|
+
mkdirSync7(dir, { recursive: true });
|
|
14384
14625
|
} catch {
|
|
14385
14626
|
}
|
|
14386
14627
|
return createWriteStream(resolvePath(dir, `${sessionId}.log`), { flags: "a" });
|
|
@@ -14393,7 +14634,7 @@ function validateAndShapeAttachments(raws, conversationAccountId, sessionId, mes
|
|
|
14393
14634
|
let reason = null;
|
|
14394
14635
|
if (!a.attachmentId || !a.filename || !a.mimeType || !a.storagePath) reason = "schema-fail";
|
|
14395
14636
|
else if (a.accountId !== conversationAccountId) reason = "account-mismatch";
|
|
14396
|
-
else if (!
|
|
14637
|
+
else if (!existsSync25(a.storagePath)) reason = "missing-file";
|
|
14397
14638
|
if (reason) {
|
|
14398
14639
|
invalid++;
|
|
14399
14640
|
try {
|
|
@@ -14919,8 +15160,8 @@ app18.put("/:id/label", requireAdminSession, async (c) => {
|
|
|
14919
15160
|
var sessions_default = app18;
|
|
14920
15161
|
|
|
14921
15162
|
// app/lib/claude-agent/spawn-context.ts
|
|
14922
|
-
import { existsSync as
|
|
14923
|
-
import { dirname as dirname10, resolve as resolve20, join as
|
|
15163
|
+
import { existsSync as existsSync26, readFileSync as readFileSync30, readdirSync as readdirSync20, statSync as statSync11 } from "fs";
|
|
15164
|
+
import { dirname as dirname10, resolve as resolve20, join as join29 } from "path";
|
|
14924
15165
|
async function resolveOwnerProfileBlock(accountId, userId) {
|
|
14925
15166
|
if (!userId) return { ok: false, reason: "missing-user-id" };
|
|
14926
15167
|
try {
|
|
@@ -14961,14 +15202,14 @@ function frontmatterField(manifest, field2) {
|
|
|
14961
15202
|
function extractPluginToolDescriptions(pluginDir) {
|
|
14962
15203
|
const out = /* @__PURE__ */ new Map();
|
|
14963
15204
|
const candidates = [
|
|
14964
|
-
|
|
14965
|
-
|
|
15205
|
+
join29(pluginDir, "mcp/dist/index.js"),
|
|
15206
|
+
join29(pluginDir, "mcp/src/index.ts")
|
|
14966
15207
|
];
|
|
14967
15208
|
let raw = null;
|
|
14968
15209
|
for (const path3 of candidates) {
|
|
14969
|
-
if (!
|
|
15210
|
+
if (!existsSync26(path3)) continue;
|
|
14970
15211
|
try {
|
|
14971
|
-
raw =
|
|
15212
|
+
raw = readFileSync30(path3, "utf-8");
|
|
14972
15213
|
break;
|
|
14973
15214
|
} catch {
|
|
14974
15215
|
}
|
|
@@ -15018,9 +15259,9 @@ function parseSkillPathsFromFrontmatter(fm) {
|
|
|
15018
15259
|
function listPluginDirs() {
|
|
15019
15260
|
const out = /* @__PURE__ */ new Map();
|
|
15020
15261
|
const platformPlugins = resolve20(PLATFORM_ROOT, "plugins");
|
|
15021
|
-
if (
|
|
15022
|
-
for (const name of
|
|
15023
|
-
const dir =
|
|
15262
|
+
if (existsSync26(platformPlugins)) {
|
|
15263
|
+
for (const name of readdirSync20(platformPlugins)) {
|
|
15264
|
+
const dir = join29(platformPlugins, name);
|
|
15024
15265
|
try {
|
|
15025
15266
|
if (statSync11(dir).isDirectory()) out.set(name, dir);
|
|
15026
15267
|
} catch {
|
|
@@ -15028,13 +15269,13 @@ function listPluginDirs() {
|
|
|
15028
15269
|
}
|
|
15029
15270
|
}
|
|
15030
15271
|
const premiumRoot = resolve20(dirname10(PLATFORM_ROOT), "premium-plugins");
|
|
15031
|
-
if (
|
|
15032
|
-
for (const bundle of
|
|
15033
|
-
const bundlePlugins =
|
|
15034
|
-
if (!
|
|
15272
|
+
if (existsSync26(premiumRoot)) {
|
|
15273
|
+
for (const bundle of readdirSync20(premiumRoot)) {
|
|
15274
|
+
const bundlePlugins = join29(premiumRoot, bundle, "plugins");
|
|
15275
|
+
if (!existsSync26(bundlePlugins)) continue;
|
|
15035
15276
|
try {
|
|
15036
|
-
for (const name of
|
|
15037
|
-
const dir =
|
|
15277
|
+
for (const name of readdirSync20(bundlePlugins)) {
|
|
15278
|
+
const dir = join29(bundlePlugins, name);
|
|
15038
15279
|
try {
|
|
15039
15280
|
if (statSync11(dir).isDirectory()) out.set(name, dir);
|
|
15040
15281
|
} catch {
|
|
@@ -15048,9 +15289,9 @@ function listPluginDirs() {
|
|
|
15048
15289
|
}
|
|
15049
15290
|
function readEnabledPlugins(accountId) {
|
|
15050
15291
|
const accountFile = resolve20(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
|
|
15051
|
-
if (!
|
|
15292
|
+
if (!existsSync26(accountFile)) return /* @__PURE__ */ new Set();
|
|
15052
15293
|
try {
|
|
15053
|
-
const parsed = JSON.parse(
|
|
15294
|
+
const parsed = JSON.parse(readFileSync30(accountFile, "utf-8"));
|
|
15054
15295
|
return new Set(
|
|
15055
15296
|
Array.isArray(parsed.enabledPlugins) ? parsed.enabledPlugins.filter((p) => typeof p === "string") : []
|
|
15056
15297
|
);
|
|
@@ -15059,10 +15300,10 @@ function readEnabledPlugins(accountId) {
|
|
|
15059
15300
|
}
|
|
15060
15301
|
}
|
|
15061
15302
|
function readFrontmatter(path3) {
|
|
15062
|
-
if (!
|
|
15303
|
+
if (!existsSync26(path3)) return null;
|
|
15063
15304
|
let raw;
|
|
15064
15305
|
try {
|
|
15065
|
-
raw =
|
|
15306
|
+
raw = readFileSync30(path3, "utf-8");
|
|
15066
15307
|
} catch {
|
|
15067
15308
|
return null;
|
|
15068
15309
|
}
|
|
@@ -15077,7 +15318,7 @@ function computeActivePlugins(accountId) {
|
|
|
15077
15318
|
for (const name of Array.from(enabled).sort()) {
|
|
15078
15319
|
const dir = pluginDirs.get(name);
|
|
15079
15320
|
if (!dir) continue;
|
|
15080
|
-
const fm = readFrontmatter(
|
|
15321
|
+
const fm = readFrontmatter(join29(dir, "PLUGIN.md"));
|
|
15081
15322
|
if (!fm) continue;
|
|
15082
15323
|
const description = frontmatterField(`---
|
|
15083
15324
|
${fm}
|
|
@@ -15094,7 +15335,7 @@ ${fm}
|
|
|
15094
15335
|
`plugin-manifest-tool-coverage plugin=${name} tools=${tools.length} with-desc=${withDesc}`
|
|
15095
15336
|
);
|
|
15096
15337
|
if (toolNames.length > 0 && descMap.size === 0) {
|
|
15097
|
-
const hasSource =
|
|
15338
|
+
const hasSource = existsSync26(join29(dir, "mcp/dist/index.js")) || existsSync26(join29(dir, "mcp/src/index.ts"));
|
|
15098
15339
|
if (hasSource) {
|
|
15099
15340
|
console.warn(
|
|
15100
15341
|
`[spawn-context] WARN plugin=${name} mcp source present but tool-description regex matched zero entries \u2014 SDK upgrade may have changed the registration shape`
|
|
@@ -15104,7 +15345,7 @@ ${fm}
|
|
|
15104
15345
|
const skillPaths = parseSkillPathsFromFrontmatter(fm);
|
|
15105
15346
|
const skills = [];
|
|
15106
15347
|
for (const relPath of skillPaths) {
|
|
15107
|
-
const skillPath =
|
|
15348
|
+
const skillPath = join29(dir, relPath);
|
|
15108
15349
|
const skillFm = readFrontmatter(skillPath);
|
|
15109
15350
|
if (!skillFm) continue;
|
|
15110
15351
|
const skillName = frontmatterField(`---
|
|
@@ -15121,10 +15362,10 @@ ${skillFm}
|
|
|
15121
15362
|
}
|
|
15122
15363
|
function computeSpecialistDomains(accountId) {
|
|
15123
15364
|
const specialistsDir = resolve20(PLATFORM_ROOT, "..", "data/accounts", accountId, "specialists", "agents");
|
|
15124
|
-
if (!
|
|
15365
|
+
if (!existsSync26(specialistsDir)) return [];
|
|
15125
15366
|
let entries;
|
|
15126
15367
|
try {
|
|
15127
|
-
entries =
|
|
15368
|
+
entries = readdirSync20(specialistsDir);
|
|
15128
15369
|
} catch {
|
|
15129
15370
|
return [];
|
|
15130
15371
|
}
|
|
@@ -15148,7 +15389,7 @@ function computeSpecialistDomains(accountId) {
|
|
|
15148
15389
|
const out = [];
|
|
15149
15390
|
for (const file of entries.sort()) {
|
|
15150
15391
|
if (!file.endsWith(".md")) continue;
|
|
15151
|
-
const fm = readFrontmatter(
|
|
15392
|
+
const fm = readFrontmatter(join29(specialistsDir, file));
|
|
15152
15393
|
if (!fm) continue;
|
|
15153
15394
|
const wrapped = `---
|
|
15154
15395
|
${fm}
|
|
@@ -15167,10 +15408,10 @@ ${fm}
|
|
|
15167
15408
|
}
|
|
15168
15409
|
function computeDormantPlugins(accountId) {
|
|
15169
15410
|
const accountFile = resolve20(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
|
|
15170
|
-
if (!
|
|
15411
|
+
if (!existsSync26(accountFile)) return [];
|
|
15171
15412
|
let enabled;
|
|
15172
15413
|
try {
|
|
15173
|
-
const raw =
|
|
15414
|
+
const raw = readFileSync30(accountFile, "utf-8");
|
|
15174
15415
|
const parsed = JSON.parse(raw);
|
|
15175
15416
|
enabled = new Set(
|
|
15176
15417
|
Array.isArray(parsed.enabledPlugins) ? parsed.enabledPlugins.filter((p) => typeof p === "string") : []
|
|
@@ -15182,10 +15423,10 @@ function computeDormantPlugins(accountId) {
|
|
|
15182
15423
|
return [];
|
|
15183
15424
|
}
|
|
15184
15425
|
const pluginsDir = resolve20(PLATFORM_ROOT, "plugins");
|
|
15185
|
-
if (!
|
|
15426
|
+
if (!existsSync26(pluginsDir)) return [];
|
|
15186
15427
|
let entries;
|
|
15187
15428
|
try {
|
|
15188
|
-
entries =
|
|
15429
|
+
entries = readdirSync20(pluginsDir);
|
|
15189
15430
|
} catch {
|
|
15190
15431
|
return [];
|
|
15191
15432
|
}
|
|
@@ -15193,10 +15434,10 @@ function computeDormantPlugins(accountId) {
|
|
|
15193
15434
|
for (const name of entries) {
|
|
15194
15435
|
if (enabled.has(name)) continue;
|
|
15195
15436
|
const manifestPath = resolve20(pluginsDir, name, "PLUGIN.md");
|
|
15196
|
-
if (!
|
|
15437
|
+
if (!existsSync26(manifestPath)) continue;
|
|
15197
15438
|
let manifest;
|
|
15198
15439
|
try {
|
|
15199
|
-
manifest =
|
|
15440
|
+
manifest = readFileSync30(manifestPath, "utf-8");
|
|
15200
15441
|
} catch {
|
|
15201
15442
|
continue;
|
|
15202
15443
|
}
|
|
@@ -15210,13 +15451,13 @@ function computeDormantPlugins(accountId) {
|
|
|
15210
15451
|
}
|
|
15211
15452
|
|
|
15212
15453
|
// server/routes/admin/claude-sessions.ts
|
|
15213
|
-
import { existsSync as
|
|
15454
|
+
import { existsSync as existsSync27, readFileSync as readFileSync31 } from "fs";
|
|
15214
15455
|
import { resolve as resolve21 } from "path";
|
|
15215
15456
|
function readTunnelState(brandConfigDir) {
|
|
15216
15457
|
const statePath = `${process.env.HOME ?? ""}/${brandConfigDir}/cloudflared/tunnel.state`;
|
|
15217
|
-
if (!
|
|
15458
|
+
if (!existsSync27(statePath)) return null;
|
|
15218
15459
|
try {
|
|
15219
|
-
const parsed = JSON.parse(
|
|
15460
|
+
const parsed = JSON.parse(readFileSync31(statePath, "utf-8"));
|
|
15220
15461
|
const tunnelId = typeof parsed.tunnelId === "string" ? parsed.tunnelId : null;
|
|
15221
15462
|
const tunnelName = typeof parsed.tunnelName === "string" ? parsed.tunnelName : null;
|
|
15222
15463
|
const domain = typeof parsed.domain === "string" ? parsed.domain : null;
|
|
@@ -15230,7 +15471,7 @@ function resolveTunnelUrl() {
|
|
|
15230
15471
|
const platformRoot5 = process.env.MAXY_PLATFORM_ROOT ?? process.env.PLATFORM_ROOT ?? resolve21(process.cwd(), "..");
|
|
15231
15472
|
let brand;
|
|
15232
15473
|
try {
|
|
15233
|
-
brand = JSON.parse(
|
|
15474
|
+
brand = JSON.parse(readFileSync31(resolve21(platformRoot5, "config", "brand.json"), "utf-8"));
|
|
15234
15475
|
} catch {
|
|
15235
15476
|
return null;
|
|
15236
15477
|
}
|
|
@@ -15241,7 +15482,7 @@ function resolveTunnelUrl() {
|
|
|
15241
15482
|
if (!state) return null;
|
|
15242
15483
|
return `https://${hostname2}.${state.domain}`;
|
|
15243
15484
|
}
|
|
15244
|
-
var
|
|
15485
|
+
var TAG27 = "[claude-session-manager:wrapper]";
|
|
15245
15486
|
async function refuseIfClaudeAuthDead(c, route, sessionId) {
|
|
15246
15487
|
const auth = await ensureAuth();
|
|
15247
15488
|
if (auth.status !== "dead" && auth.status !== "missing") return null;
|
|
@@ -15259,12 +15500,12 @@ async function performSpawnWithInitialMessage(args) {
|
|
|
15259
15500
|
const aboutOwner = await resolveOwnerProfileBlock(args.senderId, args.userId);
|
|
15260
15501
|
const ownerMs = Date.now() - ownerStart;
|
|
15261
15502
|
const aboutOwnerStatus = aboutOwner == null ? "absent" : "ok" in aboutOwner && aboutOwner.ok === false ? `unresolved:${aboutOwner.reason}` : "ok";
|
|
15262
|
-
console.log(`${
|
|
15503
|
+
console.log(`${TAG27} about-owner-resolved status=${aboutOwnerStatus} ms=${ownerMs}`);
|
|
15263
15504
|
const dormantPlugins = computeDormantPlugins(args.senderId);
|
|
15264
15505
|
const activePlugins = computeActivePlugins(args.senderId);
|
|
15265
15506
|
const specialistDomains = computeSpecialistDomains(args.senderId);
|
|
15266
15507
|
const tunnelUrl = resolveTunnelUrl();
|
|
15267
|
-
console.log(`${
|
|
15508
|
+
console.log(`${TAG27} tunnel-url-resolved value=${tunnelUrl ?? "null"}`);
|
|
15268
15509
|
const upstreamPayload = JSON.stringify({
|
|
15269
15510
|
senderId: args.senderId,
|
|
15270
15511
|
// Task 205 — pass userId through to the manager so it lands as
|
|
@@ -15291,24 +15532,24 @@ async function performSpawnWithInitialMessage(args) {
|
|
|
15291
15532
|
// unshapely values.
|
|
15292
15533
|
conversationNodeId: args.conversationNodeId
|
|
15293
15534
|
});
|
|
15294
|
-
console.log(`${
|
|
15535
|
+
console.log(`${TAG27} forward-spawn-start managerBase=${managerBase("claude-session-manager:wrapper")} bytes=${upstreamPayload.length} hidden=${args.hidden} specialist=${args.specialist ?? "none"}`);
|
|
15295
15536
|
const forwardStart = Date.now();
|
|
15296
15537
|
const upstream = await fetch(`${managerBase("claude-session-manager:wrapper")}/public-spawn`, {
|
|
15297
15538
|
method: "POST",
|
|
15298
15539
|
headers: { "content-type": "application/json" },
|
|
15299
15540
|
body: upstreamPayload
|
|
15300
15541
|
}).catch((err) => {
|
|
15301
|
-
console.error(`${
|
|
15542
|
+
console.error(`${TAG27} fetch-failed op=spawn message=${err instanceof Error ? err.message : String(err)} ms=${Date.now() - forwardStart}`);
|
|
15302
15543
|
return null;
|
|
15303
15544
|
});
|
|
15304
15545
|
if (!upstream) return {
|
|
15305
15546
|
response: new Response(JSON.stringify({ error: "manager-unreachable" }), { status: 503, headers: { "content-type": "application/json" } }),
|
|
15306
15547
|
claudeSessionId: null
|
|
15307
15548
|
};
|
|
15308
|
-
console.log(`${
|
|
15549
|
+
console.log(`${TAG27} forward-spawn-done status=${upstream.status} ms=${Date.now() - forwardStart}`);
|
|
15309
15550
|
if (args.initialMessage) {
|
|
15310
15551
|
const inputBytes = Buffer.byteLength(args.initialMessage, "utf8");
|
|
15311
|
-
console.log(`${
|
|
15552
|
+
console.log(`${TAG27} initial-message-inlined bytes=${inputBytes}`);
|
|
15312
15553
|
}
|
|
15313
15554
|
const bodyText = await upstream.text().catch(() => "");
|
|
15314
15555
|
let claudeSessionId = null;
|
|
@@ -15343,7 +15584,7 @@ app19.post("/", async (c) => {
|
|
|
15343
15584
|
if (refusal) return refusal;
|
|
15344
15585
|
const senderId = getAccountIdForSession(cacheKey) ?? "";
|
|
15345
15586
|
if (!senderId) {
|
|
15346
|
-
console.error(`${
|
|
15587
|
+
console.error(`${TAG27} reject reason=no-account-id cacheKey-prefix=${cacheKey.slice(0, 8)}`);
|
|
15347
15588
|
return c.json({ error: "admin-account-not-resolved" }, 500);
|
|
15348
15589
|
}
|
|
15349
15590
|
const userId = getUserIdForSession(cacheKey) ?? void 0;
|
|
@@ -15352,7 +15593,7 @@ app19.post("/", async (c) => {
|
|
|
15352
15593
|
const permissionMode = typeof body.permissionMode === "string" ? body.permissionMode : void 0;
|
|
15353
15594
|
const specialist = typeof body.specialist === "string" && /^[A-Za-z0-9_-]{1,64}$/.test(body.specialist) ? body.specialist : void 0;
|
|
15354
15595
|
const model = typeof body.model === "string" && /^[A-Za-z0-9._-]{1,64}$/.test(body.model) ? body.model : void 0;
|
|
15355
|
-
console.log(`${
|
|
15596
|
+
console.log(`${TAG27} spawn-request-in surface=cookie accountId=${senderId.slice(0, 8)} userId=${userId ? userId.slice(0, 8) : "absent"} channel=${channel} permissionMode=${permissionMode ?? "default"} specialist=${specialist ?? "none"} model=${model ?? "default"} initialMessage=${initialMessage ? "yes" : "no"}`);
|
|
15356
15597
|
const conversationNodeId = cacheKey ? getSessionIdForSession(cacheKey) : void 0;
|
|
15357
15598
|
const { response, claudeSessionId } = await performSpawnWithInitialMessage({
|
|
15358
15599
|
senderId,
|
|
@@ -15371,13 +15612,13 @@ app19.post("/", async (c) => {
|
|
|
15371
15612
|
claudeSessionId,
|
|
15372
15613
|
senderId
|
|
15373
15614
|
);
|
|
15374
|
-
console.log(`${
|
|
15615
|
+
console.log(`${TAG27} route-done surface=cookie status=${response.status} route-ms=${Date.now() - routeStart}`);
|
|
15375
15616
|
return response;
|
|
15376
15617
|
});
|
|
15377
15618
|
var claude_sessions_default = app19;
|
|
15378
15619
|
|
|
15379
15620
|
// server/routes/admin/log-ingest.ts
|
|
15380
|
-
var
|
|
15621
|
+
var TAG28 = "[log-ingest]";
|
|
15381
15622
|
var TAG_PATTERN = /^[A-Za-z0-9_:-]{1,32}$/;
|
|
15382
15623
|
var LEVELS = /* @__PURE__ */ new Set(["debug", "info", "warn", "error"]);
|
|
15383
15624
|
var MAX_LINE_BYTES = 4096;
|
|
@@ -15388,7 +15629,7 @@ function isLoopbackAddr2(addr) {
|
|
|
15388
15629
|
app20.post("/", async (c) => {
|
|
15389
15630
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
15390
15631
|
if (!isLoopbackAddr2(remoteAddr)) {
|
|
15391
|
-
console.error(`${
|
|
15632
|
+
console.error(`${TAG28} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
15392
15633
|
return c.json({ error: "log-ingest-loopback-only" }, 403);
|
|
15393
15634
|
}
|
|
15394
15635
|
const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
|
|
@@ -15397,7 +15638,7 @@ app20.post("/", async (c) => {
|
|
|
15397
15638
|
const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
|
|
15398
15639
|
const offender = tokens.find((t) => !isLoopbackAddr2(t));
|
|
15399
15640
|
if (offender !== void 0) {
|
|
15400
|
-
console.error(`${
|
|
15641
|
+
console.error(`${TAG28} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
|
|
15401
15642
|
return c.json({ error: "log-ingest-loopback-only" }, 403);
|
|
15402
15643
|
}
|
|
15403
15644
|
}
|
|
@@ -15439,18 +15680,18 @@ var ALLOWED_EVENTS = /* @__PURE__ */ new Set([
|
|
|
15439
15680
|
]);
|
|
15440
15681
|
var app21 = new Hono();
|
|
15441
15682
|
app21.post("/", async (c) => {
|
|
15442
|
-
const
|
|
15683
|
+
const TAG51 = "[admin:events]";
|
|
15443
15684
|
let body;
|
|
15444
15685
|
try {
|
|
15445
15686
|
body = await c.req.json();
|
|
15446
15687
|
} catch (err) {
|
|
15447
15688
|
const detail = err instanceof Error ? err.message : String(err);
|
|
15448
|
-
console.error(`${
|
|
15689
|
+
console.error(`${TAG51} reject reason=body-not-json detail=${detail}`);
|
|
15449
15690
|
return c.json({ ok: false, detail: "Request body was not valid JSON" }, 400);
|
|
15450
15691
|
}
|
|
15451
15692
|
const event = typeof body.event === "string" ? body.event : "";
|
|
15452
15693
|
if (!ALLOWED_EVENTS.has(event)) {
|
|
15453
|
-
console.error(`${
|
|
15694
|
+
console.error(`${TAG51} reject reason=event-not-allowed event=${JSON.stringify(event)}`);
|
|
15454
15695
|
return c.json({ ok: false, detail: `Event "${event}" is not allowed` }, 400);
|
|
15455
15696
|
}
|
|
15456
15697
|
const rawFields = body.fields && typeof body.fields === "object" ? body.fields : {};
|
|
@@ -15472,11 +15713,11 @@ app21.post("/", async (c) => {
|
|
|
15472
15713
|
var events_default = app21;
|
|
15473
15714
|
|
|
15474
15715
|
// server/routes/admin/files.ts
|
|
15475
|
-
import { createReadStream as createReadStream2, createWriteStream as createWriteStream2, existsSync as
|
|
15716
|
+
import { createReadStream as createReadStream2, createWriteStream as createWriteStream2, existsSync as existsSync28 } from "fs";
|
|
15476
15717
|
import { readdir as readdir3, readFile as readFile4, stat as stat4, mkdir as mkdir3, unlink as unlink2, rename, rmdir } from "fs/promises";
|
|
15477
15718
|
import { realpathSync as realpathSync6 } from "fs";
|
|
15478
15719
|
import { randomUUID as randomUUID10 } from "crypto";
|
|
15479
|
-
import { basename as basename9, dirname as dirname11, join as
|
|
15720
|
+
import { basename as basename9, dirname as dirname11, join as join31, relative as relative4, resolve as resolve23, sep as sep6 } from "path";
|
|
15480
15721
|
import { Readable as Readable2 } from "stream";
|
|
15481
15722
|
|
|
15482
15723
|
// ../lib/graph-trash/src/index.ts
|
|
@@ -15794,7 +16035,7 @@ async function cascadeDeleteDocument(params) {
|
|
|
15794
16035
|
|
|
15795
16036
|
// app/lib/file-index.ts
|
|
15796
16037
|
import * as fsp from "fs/promises";
|
|
15797
|
-
import { resolve as resolve22, relative as relative3, join as
|
|
16038
|
+
import { resolve as resolve22, relative as relative3, join as join30, basename as basename8, extname as extname2, sep as sep5 } from "path";
|
|
15798
16039
|
import { tmpdir as tmpdir2 } from "os";
|
|
15799
16040
|
import { execFile as execFile2 } from "child_process";
|
|
15800
16041
|
import { promisify as promisify2 } from "util";
|
|
@@ -15876,7 +16117,7 @@ async function extractPdf(absolute) {
|
|
|
15876
16117
|
return stdout.trim();
|
|
15877
16118
|
}
|
|
15878
16119
|
async function ocrPdf(absolute) {
|
|
15879
|
-
const outPdf =
|
|
16120
|
+
const outPdf = join30(tmpdir2(), `file-index-ocr-${process.pid}-${Date.now()}.pdf`);
|
|
15880
16121
|
try {
|
|
15881
16122
|
await execFileAsync2(
|
|
15882
16123
|
"ocrmypdf",
|
|
@@ -15938,7 +16179,7 @@ async function readDisplayName(absolute) {
|
|
|
15938
16179
|
const stem = dot === -1 ? base : base.slice(0, dot);
|
|
15939
16180
|
if (base === `${stem}.meta.json`) return null;
|
|
15940
16181
|
try {
|
|
15941
|
-
const raw = await fsp.readFile(
|
|
16182
|
+
const raw = await fsp.readFile(join30(dir, `${stem}.meta.json`), "utf-8");
|
|
15942
16183
|
const meta = JSON.parse(raw);
|
|
15943
16184
|
const dn = meta.displayName ?? meta.filename;
|
|
15944
16185
|
return typeof dn === "string" && dn.length > 0 ? dn : null;
|
|
@@ -15959,7 +16200,7 @@ async function walkSubtree(root, dataRoot, out) {
|
|
|
15959
16200
|
for (const entry of entries) {
|
|
15960
16201
|
if (entry.isSymbolicLink()) continue;
|
|
15961
16202
|
if (entry.isDirectory() && entry.name === ".uploads-tmp") continue;
|
|
15962
|
-
const abs =
|
|
16203
|
+
const abs = join30(root, entry.name);
|
|
15963
16204
|
if (entry.isDirectory()) {
|
|
15964
16205
|
const sub = await walkSubtree(abs, dataRoot, out);
|
|
15965
16206
|
if (!sub.clean) clean = false;
|
|
@@ -16315,7 +16556,7 @@ var UPLOAD_TMP_DIR = ".uploads-tmp";
|
|
|
16315
16556
|
var UUID_RE3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
16316
16557
|
async function readMeta(absDir, baseName) {
|
|
16317
16558
|
try {
|
|
16318
|
-
const raw = await readFile4(
|
|
16559
|
+
const raw = await readFile4(join31(absDir, `${baseName}.meta.json`), "utf8");
|
|
16319
16560
|
const parsed = JSON.parse(raw);
|
|
16320
16561
|
if (typeof parsed?.filename === "string") {
|
|
16321
16562
|
return { filename: parsed.filename, mimeType: typeof parsed.mimeType === "string" ? parsed.mimeType : void 0 };
|
|
@@ -16370,7 +16611,7 @@ async function servableFilesIn(dirAbs, uuid) {
|
|
|
16370
16611
|
}
|
|
16371
16612
|
async function enrich(absolute, entry, accountNames) {
|
|
16372
16613
|
if (entry.kind === "directory" && UUID_RE3.test(entry.name)) {
|
|
16373
|
-
const dirAbs =
|
|
16614
|
+
const dirAbs = join31(absolute, entry.name);
|
|
16374
16615
|
const meta = await readMeta(dirAbs, entry.name);
|
|
16375
16616
|
if (meta?.filename) {
|
|
16376
16617
|
const servable = await servableFilesIn(dirAbs, entry.name);
|
|
@@ -16379,7 +16620,7 @@ async function enrich(absolute, entry, accountNames) {
|
|
|
16379
16620
|
let size = null;
|
|
16380
16621
|
let modifiedAt = entry.modifiedAt;
|
|
16381
16622
|
try {
|
|
16382
|
-
const st = await stat4(
|
|
16623
|
+
const st = await stat4(join31(dirAbs, innerName));
|
|
16383
16624
|
size = st.size;
|
|
16384
16625
|
modifiedAt = st.mtime.toISOString();
|
|
16385
16626
|
} catch {
|
|
@@ -16554,7 +16795,7 @@ app22.get("/", requireAdminSession, async (c) => {
|
|
|
16554
16795
|
const childRel = relPath === "" || relPath === "." ? name : `${relPath}/${name}`;
|
|
16555
16796
|
const protectedEntry = isProtectedFromDeletion(childRel).protected;
|
|
16556
16797
|
try {
|
|
16557
|
-
const entryPath =
|
|
16798
|
+
const entryPath = join31(absolute, name);
|
|
16558
16799
|
const s = await stat4(entryPath);
|
|
16559
16800
|
entries.push({
|
|
16560
16801
|
name,
|
|
@@ -16617,7 +16858,7 @@ app22.get("/download", requireAdminSession, async (c) => {
|
|
|
16617
16858
|
console.error(`[data] op=scratchpad-no-session sessionId="${sessionId.slice(0, 8)}\u2026"`);
|
|
16618
16859
|
return c.json({ error: "Not found" }, 404);
|
|
16619
16860
|
}
|
|
16620
|
-
const meta = readSidecarMeta(
|
|
16861
|
+
const meta = readSidecarMeta(join31(projectDir, `${sessionId}.meta.json`));
|
|
16621
16862
|
if (!meta.accountId || meta.accountId !== accountId) {
|
|
16622
16863
|
console.error(`[data] account-scope-blocked root="scratchpad" sessionId="${sessionId.slice(0, 8)}\u2026" account=${accountId.slice(0, 8)}\u2026`);
|
|
16623
16864
|
return c.json({ error: "Not found" }, 404);
|
|
@@ -16712,7 +16953,7 @@ async function* walkRegularFiles(dirAbsolute) {
|
|
|
16712
16953
|
const dirents = await readdir3(dirAbsolute, { withFileTypes: true });
|
|
16713
16954
|
for (const d of dirents) {
|
|
16714
16955
|
if (d.isSymbolicLink()) continue;
|
|
16715
|
-
const child =
|
|
16956
|
+
const child = join31(dirAbsolute, d.name);
|
|
16716
16957
|
if (d.isDirectory()) {
|
|
16717
16958
|
yield* walkRegularFiles(child);
|
|
16718
16959
|
continue;
|
|
@@ -16822,7 +17063,7 @@ async function resolveUploadTarget(c, accountId, uid) {
|
|
|
16822
17063
|
const base = resolveOwnAccountWrite(rawDir, accountId, "POST /api/admin/files/upload");
|
|
16823
17064
|
if (!base.ok) return { ok: false, status: base.status, error: base.error };
|
|
16824
17065
|
const relDir = relpath ? dirname11(relpath) : ".";
|
|
16825
|
-
const destRel = relDir === "." ? base.relative :
|
|
17066
|
+
const destRel = relDir === "." ? base.relative : join31(base.relative, relDir);
|
|
16826
17067
|
if (crossesForeignAccountPartition(destRel, accountId)) {
|
|
16827
17068
|
console.error(`[data] account-scope-blocked endpoint="POST /api/admin/files/upload" path="${destRel}" account=${accountId.slice(0, 8)}\u2026`);
|
|
16828
17069
|
return { ok: false, status: 404, error: "Not found" };
|
|
@@ -16896,7 +17137,7 @@ app22.post("/upload", requireAdminSession, async (c) => {
|
|
|
16896
17137
|
});
|
|
16897
17138
|
await unlink2(tmpPath).catch(() => {
|
|
16898
17139
|
});
|
|
16899
|
-
const tempRemoved = !
|
|
17140
|
+
const tempRemoved = !existsSync28(tmpPath);
|
|
16900
17141
|
console.error(`[data-upload] op=cleanup uid=${uid} tempRemoved=${tempRemoved}`);
|
|
16901
17142
|
};
|
|
16902
17143
|
const reader = body.getReader();
|
|
@@ -16970,7 +17211,7 @@ async function discardChunkUpload(uploadId, state) {
|
|
|
16970
17211
|
});
|
|
16971
17212
|
await unlink2(state.tmpPath).catch(() => {
|
|
16972
17213
|
});
|
|
16973
|
-
const tempRemoved = !
|
|
17214
|
+
const tempRemoved = !existsSync28(state.tmpPath);
|
|
16974
17215
|
console.error(`[data-upload] op=cleanup uid=${uploadId} tempRemoved=${tempRemoved}`);
|
|
16975
17216
|
}
|
|
16976
17217
|
async function writeChunkBody(body, out, alreadyReceived, ceiling) {
|
|
@@ -17199,7 +17440,7 @@ app22.delete("/", requireAdminSession, async (c) => {
|
|
|
17199
17440
|
const dot = base.lastIndexOf(".");
|
|
17200
17441
|
const stem = dot === -1 ? base : base.slice(0, dot);
|
|
17201
17442
|
const containerDir = dirname11(absolute);
|
|
17202
|
-
const sidecarPath = UUID_RE3.test(stem) && base !== `${stem}.meta.json` ?
|
|
17443
|
+
const sidecarPath = UUID_RE3.test(stem) && base !== `${stem}.meta.json` ? join31(containerDir, `${stem}.meta.json`) : null;
|
|
17203
17444
|
const isAttachmentContainer = UUID_RE3.test(stem) && basename9(containerDir) === stem;
|
|
17204
17445
|
await unlink2(absolute);
|
|
17205
17446
|
if (sidecarPath) {
|
|
@@ -17209,7 +17450,7 @@ app22.delete("/", requireAdminSession, async (c) => {
|
|
|
17209
17450
|
}
|
|
17210
17451
|
}
|
|
17211
17452
|
if (isAttachmentContainer) {
|
|
17212
|
-
await unlink2(
|
|
17453
|
+
await unlink2(join31(containerDir, `${stem}${EXTRACTED_TEXT_SUFFIX}`)).catch(() => {
|
|
17213
17454
|
});
|
|
17214
17455
|
await rmdir(containerDir).catch(() => {
|
|
17215
17456
|
});
|
|
@@ -18313,8 +18554,8 @@ function isHiddenByDefault(label) {
|
|
|
18313
18554
|
}
|
|
18314
18555
|
|
|
18315
18556
|
// server/lib/top-level-labels.ts
|
|
18316
|
-
import { readdirSync as
|
|
18317
|
-
import { join as
|
|
18557
|
+
import { readdirSync as readdirSync21, readFileSync as readFileSync32 } from "fs";
|
|
18558
|
+
import { join as join32, resolve as resolve24 } from "path";
|
|
18318
18559
|
var STATIC_TOP_LEVEL_LABELS = Object.freeze(
|
|
18319
18560
|
/* @__PURE__ */ new Set([
|
|
18320
18561
|
// Base-schema infra (schema-base.md has no top-level section).
|
|
@@ -18407,7 +18648,7 @@ function parseTopLevelLabels(content) {
|
|
|
18407
18648
|
}
|
|
18408
18649
|
function resolveReferencesDir() {
|
|
18409
18650
|
if (process.env.MAXY_PLATFORM_ROOT) {
|
|
18410
|
-
return
|
|
18651
|
+
return join32(process.env.MAXY_PLATFORM_ROOT, "plugins", "memory", "references");
|
|
18411
18652
|
}
|
|
18412
18653
|
return resolve24(import.meta.dirname, "../../../plugins/memory/references");
|
|
18413
18654
|
}
|
|
@@ -18415,9 +18656,9 @@ function parseTableTopLevelLabels(referencesDir) {
|
|
|
18415
18656
|
const labels = /* @__PURE__ */ new Set();
|
|
18416
18657
|
const contributingFiles = [];
|
|
18417
18658
|
try {
|
|
18418
|
-
const fileNames =
|
|
18659
|
+
const fileNames = readdirSync21(referencesDir).filter((f) => f.startsWith("schema-") && f.endsWith(".md")).sort();
|
|
18419
18660
|
for (const fileName of fileNames) {
|
|
18420
|
-
const content =
|
|
18661
|
+
const content = readFileSync32(join32(referencesDir, fileName), "utf-8");
|
|
18421
18662
|
const parsed = parseTopLevelLabels(content);
|
|
18422
18663
|
if (parsed.length > 0) contributingFiles.push(fileName);
|
|
18423
18664
|
for (const label of parsed) labels.add(label);
|
|
@@ -19571,7 +19812,7 @@ var graph_default_view_default = app28;
|
|
|
19571
19812
|
// server/routes/admin/sidebar-artefacts.ts
|
|
19572
19813
|
import { readdir as readdir4, stat as stat5 } from "fs/promises";
|
|
19573
19814
|
import { resolve as resolve25, relative as relative5, isAbsolute as isAbsolute2, sep as sep7, basename as basename10 } from "path";
|
|
19574
|
-
import { existsSync as
|
|
19815
|
+
import { existsSync as existsSync29 } from "fs";
|
|
19575
19816
|
var LIMIT = 50;
|
|
19576
19817
|
var ADMIN_AGENT_FILES = ["IDENTITY.md", "SOUL.md", "KNOWLEDGE.md"];
|
|
19577
19818
|
function toDataRootRelPath(absPath) {
|
|
@@ -19678,7 +19919,7 @@ async function fetchAgentTemplateRows(accountDir) {
|
|
|
19678
19919
|
async function unionSpecialistFilenames(overrideDir, bundledDir) {
|
|
19679
19920
|
const names = /* @__PURE__ */ new Set();
|
|
19680
19921
|
for (const dir of [overrideDir, bundledDir]) {
|
|
19681
|
-
if (!
|
|
19922
|
+
if (!existsSync29(dir)) continue;
|
|
19682
19923
|
try {
|
|
19683
19924
|
const entries = await readdir4(dir);
|
|
19684
19925
|
for (const entry of entries) {
|
|
@@ -19693,7 +19934,7 @@ async function unionSpecialistFilenames(overrideDir, bundledDir) {
|
|
|
19693
19934
|
}
|
|
19694
19935
|
async function readAgentTemplateRow(inp) {
|
|
19695
19936
|
let chosenPath = null;
|
|
19696
|
-
if (
|
|
19937
|
+
if (existsSync29(inp.overridePath)) {
|
|
19697
19938
|
try {
|
|
19698
19939
|
validateFilePathInAccount(inp.overridePath, inp.overrideRoot);
|
|
19699
19940
|
chosenPath = inp.overridePath;
|
|
@@ -19704,7 +19945,7 @@ async function readAgentTemplateRow(inp) {
|
|
|
19704
19945
|
);
|
|
19705
19946
|
return null;
|
|
19706
19947
|
}
|
|
19707
|
-
} else if (
|
|
19948
|
+
} else if (existsSync29(inp.bundledPath)) {
|
|
19708
19949
|
if (!isWithin(inp.bundledPath, inp.bundledRoot)) {
|
|
19709
19950
|
console.error(
|
|
19710
19951
|
`[admin/sidebar-artefacts] agent-template-read-failed agent=${inp.displayName} kind=${inp.logName} error="bundled path outside PLATFORM_ROOT"`
|
|
@@ -20306,14 +20547,14 @@ app37.get("/", async (c) => {
|
|
|
20306
20547
|
var system_stats_default = app37;
|
|
20307
20548
|
|
|
20308
20549
|
// server/routes/admin/health.ts
|
|
20309
|
-
import { existsSync as
|
|
20310
|
-
import { resolve as resolve26, join as
|
|
20550
|
+
import { existsSync as existsSync30, readFileSync as readFileSync33 } from "fs";
|
|
20551
|
+
import { resolve as resolve26, join as join33 } from "path";
|
|
20311
20552
|
var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve26(process.cwd(), "..");
|
|
20312
20553
|
var brandHostname = "maxy";
|
|
20313
|
-
var brandJsonPath =
|
|
20314
|
-
if (
|
|
20554
|
+
var brandJsonPath = join33(PLATFORM_ROOT6, "config", "brand.json");
|
|
20555
|
+
if (existsSync30(brandJsonPath)) {
|
|
20315
20556
|
try {
|
|
20316
|
-
const brand = JSON.parse(
|
|
20557
|
+
const brand = JSON.parse(readFileSync33(brandJsonPath, "utf-8"));
|
|
20317
20558
|
if (brand.hostname) brandHostname = brand.hostname;
|
|
20318
20559
|
} catch {
|
|
20319
20560
|
}
|
|
@@ -20322,8 +20563,8 @@ var VERSION_FILE = resolve26(PLATFORM_ROOT6, `config/.${brandHostname}-version`)
|
|
|
20322
20563
|
var PROCESS_STARTED_AT = (/* @__PURE__ */ new Date()).toISOString();
|
|
20323
20564
|
var PROBE_TIMEOUT_MS = 1e3;
|
|
20324
20565
|
function readVersion() {
|
|
20325
|
-
if (!
|
|
20326
|
-
return
|
|
20566
|
+
if (!existsSync30(VERSION_FILE)) return "unknown";
|
|
20567
|
+
return readFileSync33(VERSION_FILE, "utf-8").trim() || "unknown";
|
|
20327
20568
|
}
|
|
20328
20569
|
async function probeConversationDb() {
|
|
20329
20570
|
let session;
|
|
@@ -20502,7 +20743,7 @@ function managerLogFollowUrl(sessionId, opts) {
|
|
|
20502
20743
|
}
|
|
20503
20744
|
|
|
20504
20745
|
// server/routes/admin/linkedin-ingest.ts
|
|
20505
|
-
var
|
|
20746
|
+
var TAG29 = "[linkedin-ingest-route]";
|
|
20506
20747
|
var UUID2 = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
|
|
20507
20748
|
var ISO = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,3})?(?:Z|[+-]\d{2}:\d{2})$/;
|
|
20508
20749
|
var LINKEDIN_URL = /^https:\/\/www\.linkedin\.com\//;
|
|
@@ -20606,29 +20847,29 @@ app39.post("/", requireAdminSession, async (c) => {
|
|
|
20606
20847
|
try {
|
|
20607
20848
|
body = await c.req.json();
|
|
20608
20849
|
} catch {
|
|
20609
|
-
console.error(
|
|
20850
|
+
console.error(TAG29 + " rejected status=400 reason=schema:body-not-json");
|
|
20610
20851
|
return c.json({ ok: false, error: "schema", reason: "body-not-json" }, 400);
|
|
20611
20852
|
}
|
|
20612
20853
|
const v = validate(body);
|
|
20613
20854
|
if (!v.ok) {
|
|
20614
|
-
console.error(
|
|
20855
|
+
console.error(TAG29 + " rejected status=" + v.status + " reason=" + v.reason + " missing=" + v.missing.join(","));
|
|
20615
20856
|
return c.json({ ok: false, error: v.error, reason: v.reason, missing: v.missing }, v.status);
|
|
20616
20857
|
}
|
|
20617
20858
|
const envelope = v.envelope;
|
|
20618
20859
|
const cacheKey = c.var.cacheKey ?? "";
|
|
20619
20860
|
const senderId = getAccountIdForSession(cacheKey) ?? "";
|
|
20620
20861
|
if (!senderId) {
|
|
20621
|
-
console.error(
|
|
20862
|
+
console.error(TAG29 + " rejected status=500 reason=admin-account-not-resolved");
|
|
20622
20863
|
return c.json({ ok: false, error: "admin-account-not-resolved" }, 500);
|
|
20623
20864
|
}
|
|
20624
20865
|
const payloadBytes = JSON.stringify(envelope).length;
|
|
20625
20866
|
console.log(
|
|
20626
|
-
|
|
20867
|
+
TAG29 + " received kind=" + envelope.kind + " account=" + senderId.slice(0, 8) + " pageUrl=" + envelope.pageUrl + " dispatchId=" + envelope.dispatchId + " payloadBytes=" + payloadBytes
|
|
20627
20868
|
);
|
|
20628
20869
|
const initialMessage = buildInitialMessage(envelope);
|
|
20629
20870
|
const spawnStart = Date.now();
|
|
20630
20871
|
const sessionId = randomUUID13();
|
|
20631
|
-
console.log(
|
|
20872
|
+
console.log(TAG29 + " route target=rc-spawn dispatchId=" + envelope.dispatchId + " sessionId=" + sessionId.slice(0, 8));
|
|
20632
20873
|
const spawned = await managerRcSpawn({
|
|
20633
20874
|
sessionId,
|
|
20634
20875
|
initialMessage,
|
|
@@ -20637,12 +20878,12 @@ app39.post("/", requireAdminSession, async (c) => {
|
|
|
20637
20878
|
});
|
|
20638
20879
|
if ("error" in spawned) {
|
|
20639
20880
|
console.error(
|
|
20640
|
-
|
|
20881
|
+
TAG29 + " dispatch-failed dispatchId=" + envelope.dispatchId + " status=" + spawned.status + " ms=" + (Date.now() - spawnStart) + " message=" + spawned.error
|
|
20641
20882
|
);
|
|
20642
20883
|
return c.json({ ok: false, error: "dispatch-failed", upstreamStatus: spawned.status, detail: spawned.error }, 502);
|
|
20643
20884
|
}
|
|
20644
20885
|
console.log(
|
|
20645
|
-
|
|
20886
|
+
TAG29 + " dispatched dispatchId=" + envelope.dispatchId + " taskId=" + spawned.sessionId + " ms=" + (Date.now() - spawnStart)
|
|
20646
20887
|
);
|
|
20647
20888
|
return c.json({ ok: true, dispatchId: envelope.dispatchId, taskId: spawned.sessionId }, 202);
|
|
20648
20889
|
});
|
|
@@ -20650,7 +20891,7 @@ var linkedin_ingest_default = app39;
|
|
|
20650
20891
|
|
|
20651
20892
|
// server/routes/admin/post-turn-context.ts
|
|
20652
20893
|
import neo4j3 from "neo4j-driver";
|
|
20653
|
-
var
|
|
20894
|
+
var TAG30 = "[post-turn-context]";
|
|
20654
20895
|
var STRIPPED_PROPERTIES2 = /* @__PURE__ */ new Set([
|
|
20655
20896
|
"embedding",
|
|
20656
20897
|
"passwordHash",
|
|
@@ -20692,7 +20933,7 @@ var app40 = new Hono();
|
|
|
20692
20933
|
app40.get("/", async (c) => {
|
|
20693
20934
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
20694
20935
|
if (!isLoopbackAddr3(remoteAddr)) {
|
|
20695
|
-
console.error(`${
|
|
20936
|
+
console.error(`${TAG30} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
20696
20937
|
return c.json({ error: "post-turn-context-loopback-only" }, 403);
|
|
20697
20938
|
}
|
|
20698
20939
|
const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
|
|
@@ -20701,7 +20942,7 @@ app40.get("/", async (c) => {
|
|
|
20701
20942
|
const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
|
|
20702
20943
|
const offender = tokens.find((t) => !isLoopbackAddr3(t));
|
|
20703
20944
|
if (offender !== void 0) {
|
|
20704
|
-
console.error(`${
|
|
20945
|
+
console.error(`${TAG30} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
|
|
20705
20946
|
return c.json({ error: "post-turn-context-loopback-only" }, 403);
|
|
20706
20947
|
}
|
|
20707
20948
|
}
|
|
@@ -20733,7 +20974,7 @@ app40.get("/", async (c) => {
|
|
|
20733
20974
|
writes.sort((a, b) => a.sortKey.localeCompare(b.sortKey));
|
|
20734
20975
|
const total = Date.now() - started;
|
|
20735
20976
|
console.log(
|
|
20736
|
-
`${
|
|
20977
|
+
`${TAG30} sessionId=${sessionId} accountId=${accountId} writes=${writes.length} ms=${total}`
|
|
20737
20978
|
);
|
|
20738
20979
|
return c.json({
|
|
20739
20980
|
writes: writes.map(({ elementId, labels, properties }) => ({ elementId, labels, properties }))
|
|
@@ -20742,7 +20983,7 @@ app40.get("/", async (c) => {
|
|
|
20742
20983
|
const elapsed = Date.now() - started;
|
|
20743
20984
|
const message = err instanceof Error ? err.message : String(err);
|
|
20744
20985
|
console.error(
|
|
20745
|
-
`${
|
|
20986
|
+
`${TAG30} neo4j-unreachable sessionId=${sessionId} ms=${elapsed} err="${message}"`
|
|
20746
20987
|
);
|
|
20747
20988
|
return c.json({ error: `post-turn-context unavailable: ${message}` }, 503);
|
|
20748
20989
|
} finally {
|
|
@@ -20855,7 +21096,7 @@ function formatPreviousContext(writes) {
|
|
|
20855
21096
|
}
|
|
20856
21097
|
|
|
20857
21098
|
// server/routes/admin/public-session-context.ts
|
|
20858
|
-
var
|
|
21099
|
+
var TAG31 = "[public-session-context]";
|
|
20859
21100
|
function isLoopbackAddr4(addr) {
|
|
20860
21101
|
return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
|
|
20861
21102
|
}
|
|
@@ -20863,7 +21104,7 @@ var app41 = new Hono();
|
|
|
20863
21104
|
app41.get("/", async (c) => {
|
|
20864
21105
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
20865
21106
|
if (!isLoopbackAddr4(remoteAddr)) {
|
|
20866
|
-
console.error(`${
|
|
21107
|
+
console.error(`${TAG31} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
20867
21108
|
return c.json({ error: "public-session-context-loopback-only" }, 403);
|
|
20868
21109
|
}
|
|
20869
21110
|
const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
|
|
@@ -20872,7 +21113,7 @@ app41.get("/", async (c) => {
|
|
|
20872
21113
|
const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
|
|
20873
21114
|
const offender = tokens.find((t) => !isLoopbackAddr4(t));
|
|
20874
21115
|
if (offender !== void 0) {
|
|
20875
|
-
console.error(`${
|
|
21116
|
+
console.error(`${TAG31} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
|
|
20876
21117
|
return c.json({ error: "public-session-context-loopback-only" }, 403);
|
|
20877
21118
|
}
|
|
20878
21119
|
}
|
|
@@ -20886,14 +21127,14 @@ app41.get("/", async (c) => {
|
|
|
20886
21127
|
const writes = await fetchSliceWrites(session, sliceToken, accountId);
|
|
20887
21128
|
const total = Date.now() - started;
|
|
20888
21129
|
console.log(
|
|
20889
|
-
`${
|
|
21130
|
+
`${TAG31} sliceToken=${sliceToken.slice(0, 8)} writes=${writes.length} ms=${total}`
|
|
20890
21131
|
);
|
|
20891
21132
|
return c.json({ writes });
|
|
20892
21133
|
} catch (err) {
|
|
20893
21134
|
const elapsed = Date.now() - started;
|
|
20894
21135
|
const message = err instanceof Error ? err.message : String(err);
|
|
20895
21136
|
console.error(
|
|
20896
|
-
`${
|
|
21137
|
+
`${TAG31} neo4j-unreachable sliceToken=${sliceToken.slice(0, 8)} ms=${elapsed} err="${message}"`
|
|
20897
21138
|
);
|
|
20898
21139
|
return c.json({ error: `public-session-context unavailable: ${message}` }, 503);
|
|
20899
21140
|
} finally {
|
|
@@ -20912,7 +21153,7 @@ function getWebchatGateway() {
|
|
|
20912
21153
|
}
|
|
20913
21154
|
|
|
20914
21155
|
// server/routes/admin/public-session-exit.ts
|
|
20915
|
-
var
|
|
21156
|
+
var TAG32 = "[public-session-exit-route]";
|
|
20916
21157
|
function isLoopbackAddr5(addr) {
|
|
20917
21158
|
return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
|
|
20918
21159
|
}
|
|
@@ -20920,7 +21161,7 @@ var app42 = new Hono();
|
|
|
20920
21161
|
app42.post("/", async (c) => {
|
|
20921
21162
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
20922
21163
|
if (!isLoopbackAddr5(remoteAddr)) {
|
|
20923
|
-
console.error(`${
|
|
21164
|
+
console.error(`${TAG32} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
20924
21165
|
return c.json({ error: "public-session-exit-loopback-only" }, 403);
|
|
20925
21166
|
}
|
|
20926
21167
|
const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
|
|
@@ -20929,7 +21170,7 @@ app42.post("/", async (c) => {
|
|
|
20929
21170
|
const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
|
|
20930
21171
|
const offender = tokens.find((t) => !isLoopbackAddr5(t));
|
|
20931
21172
|
if (offender !== void 0) {
|
|
20932
|
-
console.error(`${
|
|
21173
|
+
console.error(`${TAG32} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
|
|
20933
21174
|
return c.json({ error: "public-session-exit-loopback-only" }, 403);
|
|
20934
21175
|
}
|
|
20935
21176
|
}
|
|
@@ -20943,7 +21184,7 @@ app42.post("/", async (c) => {
|
|
|
20943
21184
|
if (!sessionId) return c.json({ error: "sessionId required" }, 400);
|
|
20944
21185
|
const gateway = getWebchatGateway();
|
|
20945
21186
|
if (!gateway) {
|
|
20946
|
-
console.error(`${
|
|
21187
|
+
console.error(`${TAG32} reject reason=gateway-unset sessionId=${sessionId.slice(0, 8)}`);
|
|
20947
21188
|
return c.json({ error: "webchat-gateway-unset" }, 503);
|
|
20948
21189
|
}
|
|
20949
21190
|
gateway.handlePublicSessionExit(sessionId);
|
|
@@ -20952,7 +21193,7 @@ app42.post("/", async (c) => {
|
|
|
20952
21193
|
var public_session_exit_default = app42;
|
|
20953
21194
|
|
|
20954
21195
|
// server/routes/admin/access-session-evict.ts
|
|
20955
|
-
var
|
|
21196
|
+
var TAG33 = "[access-session-evict]";
|
|
20956
21197
|
function isLoopbackAddr6(addr) {
|
|
20957
21198
|
return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
|
|
20958
21199
|
}
|
|
@@ -20960,7 +21201,7 @@ var app43 = new Hono();
|
|
|
20960
21201
|
app43.post("/", async (c) => {
|
|
20961
21202
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
20962
21203
|
if (!isLoopbackAddr6(remoteAddr)) {
|
|
20963
|
-
console.error(`${
|
|
21204
|
+
console.error(`${TAG33} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
20964
21205
|
return c.json({ error: "access-session-evict-loopback-only" }, 403);
|
|
20965
21206
|
}
|
|
20966
21207
|
const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
|
|
@@ -20969,7 +21210,7 @@ app43.post("/", async (c) => {
|
|
|
20969
21210
|
const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
|
|
20970
21211
|
const offender = tokens.find((t) => !isLoopbackAddr6(t));
|
|
20971
21212
|
if (offender !== void 0) {
|
|
20972
|
-
console.error(`${
|
|
21213
|
+
console.error(`${TAG33} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
|
|
20973
21214
|
return c.json({ error: "access-session-evict-loopback-only" }, 403);
|
|
20974
21215
|
}
|
|
20975
21216
|
}
|
|
@@ -20982,13 +21223,13 @@ app43.post("/", async (c) => {
|
|
|
20982
21223
|
const grantId = typeof body.grantId === "string" ? body.grantId.trim() : "";
|
|
20983
21224
|
if (!grantId) return c.json({ error: "grantId required" }, 400);
|
|
20984
21225
|
const dropped = evictAccessSessionsByGrant(grantId);
|
|
20985
|
-
console.log(`${
|
|
21226
|
+
console.log(`${TAG33} grantId=${grantId} dropped=${dropped}`);
|
|
20986
21227
|
return c.json({ ok: true, dropped });
|
|
20987
21228
|
});
|
|
20988
21229
|
var access_session_evict_default = app43;
|
|
20989
21230
|
|
|
20990
21231
|
// server/routes/admin/enrol-person.ts
|
|
20991
|
-
var
|
|
21232
|
+
var TAG34 = "[enrol]";
|
|
20992
21233
|
function isLoopbackAddr7(addr) {
|
|
20993
21234
|
return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
|
|
20994
21235
|
}
|
|
@@ -20997,7 +21238,7 @@ var app44 = new Hono();
|
|
|
20997
21238
|
app44.post("/", async (c) => {
|
|
20998
21239
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
20999
21240
|
if (!isLoopbackAddr7(remoteAddr)) {
|
|
21000
|
-
console.error(`${
|
|
21241
|
+
console.error(`${TAG34} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
21001
21242
|
return c.json({ error: "enrol-person-loopback-only" }, 403);
|
|
21002
21243
|
}
|
|
21003
21244
|
const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
|
|
@@ -21006,7 +21247,7 @@ app44.post("/", async (c) => {
|
|
|
21006
21247
|
const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
|
|
21007
21248
|
const offender = tokens.find((t) => !isLoopbackAddr7(t));
|
|
21008
21249
|
if (offender !== void 0) {
|
|
21009
|
-
console.error(`${
|
|
21250
|
+
console.error(`${TAG34} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
|
|
21010
21251
|
return c.json({ error: "enrol-person-loopback-only" }, 403);
|
|
21011
21252
|
}
|
|
21012
21253
|
}
|
|
@@ -21031,7 +21272,7 @@ app44.post("/", async (c) => {
|
|
|
21031
21272
|
}
|
|
21032
21273
|
const accountId = process.env.ACCOUNT_ID ?? "";
|
|
21033
21274
|
if (!accountId) {
|
|
21034
|
-
console.error(`${
|
|
21275
|
+
console.error(`${TAG34} op=person result=no-account-id`);
|
|
21035
21276
|
return c.json({ error: "no-account-id" }, 500);
|
|
21036
21277
|
}
|
|
21037
21278
|
let personId;
|
|
@@ -21039,7 +21280,7 @@ app44.post("/", async (c) => {
|
|
|
21039
21280
|
personId = await enrolPerson({ accountId, phone, email, agentSlug });
|
|
21040
21281
|
} catch (err) {
|
|
21041
21282
|
console.error(
|
|
21042
|
-
`${
|
|
21283
|
+
`${TAG34} op=person result=write-failed agentSlug=${agentSlug} contact=${maskContact(email)} err="${err instanceof Error ? err.message : String(err)}"`
|
|
21043
21284
|
);
|
|
21044
21285
|
return c.json({ error: "enrol-failed" }, 500);
|
|
21045
21286
|
}
|
|
@@ -21049,11 +21290,11 @@ app44.post("/", async (c) => {
|
|
|
21049
21290
|
if (g) grant = { grantId: g.grantId, status: g.status, contactValue: g.contactValue };
|
|
21050
21291
|
} catch (err) {
|
|
21051
21292
|
console.error(
|
|
21052
|
-
`${
|
|
21293
|
+
`${TAG34} op=person result=grant-lookup-failed contact=${maskContact(email)} err="${err instanceof Error ? err.message : String(err)}"`
|
|
21053
21294
|
);
|
|
21054
21295
|
}
|
|
21055
21296
|
console.log(
|
|
21056
|
-
`${
|
|
21297
|
+
`${TAG34} op=person personId=${personId} account=${accountId} agentSlug=${agentSlug} contact=${maskContact(email)}`
|
|
21057
21298
|
);
|
|
21058
21299
|
return c.json({ personId, grant }, 200);
|
|
21059
21300
|
});
|
|
@@ -21099,8 +21340,8 @@ app45.post("/launch", requireAdminSession, async (c) => {
|
|
|
21099
21340
|
var browser_default = app45;
|
|
21100
21341
|
|
|
21101
21342
|
// server/routes/admin/calendar.ts
|
|
21102
|
-
import { existsSync as
|
|
21103
|
-
import { join as
|
|
21343
|
+
import { existsSync as existsSync31 } from "fs";
|
|
21344
|
+
import { join as join35 } from "path";
|
|
21104
21345
|
|
|
21105
21346
|
// server/lib/calendar-ics.ts
|
|
21106
21347
|
var CRLF = "\r\n";
|
|
@@ -21199,8 +21440,8 @@ function countVEvents(ics) {
|
|
|
21199
21440
|
}
|
|
21200
21441
|
|
|
21201
21442
|
// server/lib/calendar-availability.ts
|
|
21202
|
-
import { readFileSync as
|
|
21203
|
-
import { join as
|
|
21443
|
+
import { readFileSync as readFileSync34 } from "fs";
|
|
21444
|
+
import { join as join34 } from "path";
|
|
21204
21445
|
var AVAILABILITY_FILENAME = "calendar-availability.json";
|
|
21205
21446
|
var REQUIRED_KEYS = [
|
|
21206
21447
|
"timezone",
|
|
@@ -21209,10 +21450,10 @@ var REQUIRED_KEYS = [
|
|
|
21209
21450
|
"weekly"
|
|
21210
21451
|
];
|
|
21211
21452
|
function readAvailabilityConfig(accountDir) {
|
|
21212
|
-
const path3 =
|
|
21453
|
+
const path3 = join34(accountDir, AVAILABILITY_FILENAME);
|
|
21213
21454
|
let raw;
|
|
21214
21455
|
try {
|
|
21215
|
-
raw =
|
|
21456
|
+
raw = readFileSync34(path3, "utf-8");
|
|
21216
21457
|
} catch {
|
|
21217
21458
|
throw new Error(`availability not configured: ${path3} not found`);
|
|
21218
21459
|
}
|
|
@@ -21571,7 +21812,7 @@ app46.get("/booking-link", requireAdminSession, (c) => {
|
|
|
21571
21812
|
console.error('[calendar] op=booking-link-fail err="no account configured"');
|
|
21572
21813
|
return c.json({ bookingDomain: null });
|
|
21573
21814
|
}
|
|
21574
|
-
if (!
|
|
21815
|
+
if (!existsSync31(join35(account.accountDir, AVAILABILITY_FILENAME))) {
|
|
21575
21816
|
console.log("[calendar] op=booking-link bookingDomain=none source=availability-config");
|
|
21576
21817
|
return c.json({ bookingDomain: null });
|
|
21577
21818
|
}
|
|
@@ -21607,7 +21848,7 @@ function toNum(v) {
|
|
|
21607
21848
|
}
|
|
21608
21849
|
|
|
21609
21850
|
// server/routes/admin/tasks-list.ts
|
|
21610
|
-
var
|
|
21851
|
+
var TAG35 = "[task-timer]";
|
|
21611
21852
|
var COMPLETED = /* @__PURE__ */ new Set(["completed"]);
|
|
21612
21853
|
var HIDDEN_FROM_OPEN = /* @__PURE__ */ new Set(["completed", "cancelled"]);
|
|
21613
21854
|
var app47 = new Hono();
|
|
@@ -21615,7 +21856,7 @@ app47.get("/", requireAdminSession, async (c) => {
|
|
|
21615
21856
|
const cacheKey = c.var.cacheKey;
|
|
21616
21857
|
const accountId = getAccountIdForSession(cacheKey);
|
|
21617
21858
|
if (!accountId) {
|
|
21618
|
-
console.error(`${
|
|
21859
|
+
console.error(`${TAG35} op=list auth-rejected reason="no account for session"`);
|
|
21619
21860
|
return c.json({ error: "Account not found for session" }, 401);
|
|
21620
21861
|
}
|
|
21621
21862
|
const session = getSession();
|
|
@@ -21653,10 +21894,10 @@ app47.get("/", requireAdminSession, async (c) => {
|
|
|
21653
21894
|
if (COMPLETED.has(status)) completed.push(row);
|
|
21654
21895
|
else if (!HIDDEN_FROM_OPEN.has(status)) open.push(row);
|
|
21655
21896
|
}
|
|
21656
|
-
console.log(`${
|
|
21897
|
+
console.log(`${TAG35} op=list account=${accountId} open=${open.length} completed=${completed.length}`);
|
|
21657
21898
|
return c.json({ open, completed });
|
|
21658
21899
|
} catch (err) {
|
|
21659
|
-
console.error(`${
|
|
21900
|
+
console.error(`${TAG35} op=list error="${err instanceof Error ? err.message : String(err)}"`);
|
|
21660
21901
|
return c.json({ error: "tasks-list-failed" }, 500);
|
|
21661
21902
|
} finally {
|
|
21662
21903
|
await session.close();
|
|
@@ -21666,7 +21907,7 @@ var tasks_list_default = app47;
|
|
|
21666
21907
|
|
|
21667
21908
|
// server/routes/admin/task-timer-start.ts
|
|
21668
21909
|
import { randomUUID as randomUUID14 } from "crypto";
|
|
21669
|
-
var
|
|
21910
|
+
var TAG36 = "[task-timer]";
|
|
21670
21911
|
var app48 = new Hono();
|
|
21671
21912
|
app48.post("/", requireAdminSession, async (c) => {
|
|
21672
21913
|
const cacheKey = c.var.cacheKey;
|
|
@@ -21688,7 +21929,7 @@ app48.post("/", requireAdminSession, async (c) => {
|
|
|
21688
21929
|
{ taskId, accountId }
|
|
21689
21930
|
);
|
|
21690
21931
|
if (target.records.length === 0) {
|
|
21691
|
-
console.error(`${
|
|
21932
|
+
console.error(`${TAG36} op=start taskId=${taskId} accountId=${accountId} result=task-not-found`);
|
|
21692
21933
|
return c.json({ error: "task-not-found" }, 404);
|
|
21693
21934
|
}
|
|
21694
21935
|
const open = await session.run(
|
|
@@ -21700,7 +21941,7 @@ app48.post("/", requireAdminSession, async (c) => {
|
|
|
21700
21941
|
const priorEntryId = open.records[0]?.get("entryId");
|
|
21701
21942
|
const priorStartedAt = open.records[0]?.get("startedAt");
|
|
21702
21943
|
if (priorEntryId) {
|
|
21703
|
-
console.log(`${
|
|
21944
|
+
console.log(`${TAG36} op=start taskId=${taskId} accountId=${accountId} result=already-running`);
|
|
21704
21945
|
return c.json({ ok: true, running: true, entryId: priorEntryId, startedAt: priorStartedAt });
|
|
21705
21946
|
}
|
|
21706
21947
|
const entryId = randomUUID14();
|
|
@@ -21710,10 +21951,10 @@ app48.post("/", requireAdminSession, async (c) => {
|
|
|
21710
21951
|
CREATE (te)-[:LOGGED_AGAINST]->(t)`,
|
|
21711
21952
|
{ taskId, accountId, entryId, now }
|
|
21712
21953
|
);
|
|
21713
|
-
console.log(`${
|
|
21954
|
+
console.log(`${TAG36} op=opened taskId=${taskId} entryId=${entryId} startedAt=${now}`);
|
|
21714
21955
|
return c.json({ ok: true, running: true, entryId, startedAt: now });
|
|
21715
21956
|
} catch (err) {
|
|
21716
|
-
console.error(`${
|
|
21957
|
+
console.error(`${TAG36} op=start error="${err instanceof Error ? err.message : String(err)}"`);
|
|
21717
21958
|
return c.json({ error: "task-timer-start-failed" }, 500);
|
|
21718
21959
|
} finally {
|
|
21719
21960
|
await session.close();
|
|
@@ -21723,7 +21964,7 @@ var task_timer_start_default = app48;
|
|
|
21723
21964
|
|
|
21724
21965
|
// server/routes/admin/task-timer-stop.ts
|
|
21725
21966
|
import neo4j5 from "neo4j-driver";
|
|
21726
|
-
var
|
|
21967
|
+
var TAG37 = "[task-timer]";
|
|
21727
21968
|
var app49 = new Hono();
|
|
21728
21969
|
app49.post("/", requireAdminSession, async (c) => {
|
|
21729
21970
|
const cacheKey = c.var.cacheKey;
|
|
@@ -21755,7 +21996,7 @@ app49.post("/", requireAdminSession, async (c) => {
|
|
|
21755
21996
|
{ taskId, accountId }
|
|
21756
21997
|
);
|
|
21757
21998
|
const secondsLogged2 = toNum(cur.records[0]?.get("secondsLogged"));
|
|
21758
|
-
console.log(`${
|
|
21999
|
+
console.log(`${TAG37} op=stop taskId=${taskId} entryId=none seconds=0 totalAfter=${secondsLogged2}`);
|
|
21759
22000
|
return c.json({ ok: true, running: false, seconds: 0, secondsLogged: secondsLogged2 });
|
|
21760
22001
|
}
|
|
21761
22002
|
const seconds = secondsBetween(startedAt, now);
|
|
@@ -21778,11 +22019,11 @@ app49.post("/", requireAdminSession, async (c) => {
|
|
|
21778
22019
|
const sumEntries = toNum(verify.records[0]?.get("sumEntries"));
|
|
21779
22020
|
const sumAdjustments = toNum(verify.records[0]?.get("sumAdjustments"));
|
|
21780
22021
|
const secondsLogged = toNum(verify.records[0]?.get("secondsLogged"));
|
|
21781
|
-
console.log(`${
|
|
21782
|
-
console.log(`${
|
|
22022
|
+
console.log(`${TAG37} op=stop taskId=${taskId} entryId=${entryId} seconds=${seconds} totalAfter=${secondsLogged}`);
|
|
22023
|
+
console.log(`${TAG37} op=persisted taskId=${taskId} entryId=${entryId} sumEntries=${sumEntries} sumAdjustments=${sumAdjustments} secondsLogged=${secondsLogged}`);
|
|
21783
22024
|
return c.json({ ok: true, running: false, seconds, secondsLogged });
|
|
21784
22025
|
} catch (err) {
|
|
21785
|
-
console.error(`${
|
|
22026
|
+
console.error(`${TAG37} op=stop error="${err instanceof Error ? err.message : String(err)}"`);
|
|
21786
22027
|
return c.json({ error: "task-timer-stop-failed" }, 500);
|
|
21787
22028
|
} finally {
|
|
21788
22029
|
await session.close();
|
|
@@ -21791,7 +22032,7 @@ app49.post("/", requireAdminSession, async (c) => {
|
|
|
21791
22032
|
var task_timer_stop_default = app49;
|
|
21792
22033
|
|
|
21793
22034
|
// server/routes/admin/task-complete.ts
|
|
21794
|
-
var
|
|
22035
|
+
var TAG38 = "[task-timer]";
|
|
21795
22036
|
var app50 = new Hono();
|
|
21796
22037
|
app50.post("/", requireAdminSession, async (c) => {
|
|
21797
22038
|
const cacheKey = c.var.cacheKey;
|
|
@@ -21818,10 +22059,10 @@ app50.post("/", requireAdminSession, async (c) => {
|
|
|
21818
22059
|
return c.json({ error: "task-not-found" }, 404);
|
|
21819
22060
|
}
|
|
21820
22061
|
const secondsLogged = toNum(result.records[0].get("secondsLogged"));
|
|
21821
|
-
console.log(`${
|
|
22062
|
+
console.log(`${TAG38} op=complete taskId=${taskId} status=completed secondsLogged=${secondsLogged}`);
|
|
21822
22063
|
return c.json({ ok: true, status: "completed", secondsLogged });
|
|
21823
22064
|
} catch (err) {
|
|
21824
|
-
console.error(`${
|
|
22065
|
+
console.error(`${TAG38} op=complete error="${err instanceof Error ? err.message : String(err)}"`);
|
|
21825
22066
|
return c.json({ error: "task-complete-failed" }, 500);
|
|
21826
22067
|
} finally {
|
|
21827
22068
|
await session.close();
|
|
@@ -21832,7 +22073,7 @@ var task_complete_default = app50;
|
|
|
21832
22073
|
// server/routes/admin/task-time-adjust.ts
|
|
21833
22074
|
import { randomUUID as randomUUID15 } from "crypto";
|
|
21834
22075
|
import neo4j6 from "neo4j-driver";
|
|
21835
|
-
var
|
|
22076
|
+
var TAG39 = "[task-time-adjust]";
|
|
21836
22077
|
var app51 = new Hono();
|
|
21837
22078
|
app51.post("/", requireAdminSession, async (c) => {
|
|
21838
22079
|
const cacheKey = c.var.cacheKey;
|
|
@@ -21842,22 +22083,22 @@ app51.post("/", requireAdminSession, async (c) => {
|
|
|
21842
22083
|
try {
|
|
21843
22084
|
body = await c.req.json();
|
|
21844
22085
|
} catch {
|
|
21845
|
-
console.error(`${
|
|
22086
|
+
console.error(`${TAG39} op=reject reason=bad-json`);
|
|
21846
22087
|
return c.json({ error: "invalid-json" }, 400);
|
|
21847
22088
|
}
|
|
21848
22089
|
const taskId = typeof body.taskId === "string" ? body.taskId : "";
|
|
21849
22090
|
if (!taskId) {
|
|
21850
|
-
console.error(`${
|
|
22091
|
+
console.error(`${TAG39} op=reject reason=no-task`);
|
|
21851
22092
|
return c.json({ error: "taskId required" }, 400);
|
|
21852
22093
|
}
|
|
21853
22094
|
const newSeconds = body.newSeconds;
|
|
21854
22095
|
if (typeof newSeconds !== "number" || !Number.isInteger(newSeconds) || newSeconds < 0) {
|
|
21855
|
-
console.error(`${
|
|
22096
|
+
console.error(`${TAG39} op=reject reason=invalid-seconds taskId=${taskId} accountId=${accountId}`);
|
|
21856
22097
|
return c.json({ error: "newSeconds must be a non-negative integer" }, 400);
|
|
21857
22098
|
}
|
|
21858
22099
|
const adjustmentId = randomUUID15();
|
|
21859
22100
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
21860
|
-
console.log(`${
|
|
22101
|
+
console.log(`${TAG39} op=request adjustmentId=${adjustmentId} taskId=${taskId} accountId=${accountId} newSeconds=${newSeconds}`);
|
|
21861
22102
|
const session = getSession();
|
|
21862
22103
|
try {
|
|
21863
22104
|
const guard = await session.run(
|
|
@@ -21867,12 +22108,12 @@ app51.post("/", requireAdminSession, async (c) => {
|
|
|
21867
22108
|
{ taskId, accountId }
|
|
21868
22109
|
);
|
|
21869
22110
|
if (guard.records.length === 0) {
|
|
21870
|
-
console.error(`${
|
|
22111
|
+
console.error(`${TAG39} op=reject reason=no-task adjustmentId=${adjustmentId} taskId=${taskId} accountId=${accountId}`);
|
|
21871
22112
|
return c.json({ error: "task-not-found" }, 404);
|
|
21872
22113
|
}
|
|
21873
22114
|
const openCount = toNum(guard.records[0].get("openCount"));
|
|
21874
22115
|
if (openCount > 0) {
|
|
21875
|
-
console.error(`${
|
|
22116
|
+
console.error(`${TAG39} op=reject reason=running adjustmentId=${adjustmentId} taskId=${taskId} accountId=${accountId}`);
|
|
21876
22117
|
return c.json({ error: "task-timer-running" }, 409);
|
|
21877
22118
|
}
|
|
21878
22119
|
const previousSeconds = toNum(guard.records[0].get("previousSeconds"));
|
|
@@ -21898,10 +22139,10 @@ app51.post("/", requireAdminSession, async (c) => {
|
|
|
21898
22139
|
}
|
|
21899
22140
|
);
|
|
21900
22141
|
const secondsLoggedAfter = toNum(write.records[0]?.get("secondsLoggedAfter"));
|
|
21901
|
-
console.log(`${
|
|
22142
|
+
console.log(`${TAG39} op=persisted adjustmentId=${adjustmentId} previousSeconds=${previousSeconds} newSeconds=${newSeconds} delta=${delta} secondsLoggedAfter=${secondsLoggedAfter}`);
|
|
21902
22143
|
return c.json({ ok: true, secondsLogged: secondsLoggedAfter });
|
|
21903
22144
|
} catch (err) {
|
|
21904
|
-
console.error(`${
|
|
22145
|
+
console.error(`${TAG39} op=error adjustmentId=${adjustmentId} taskId=${taskId} error="${err instanceof Error ? err.message : String(err)}"`);
|
|
21905
22146
|
return c.json({ error: "task-time-adjust-failed" }, 500);
|
|
21906
22147
|
} finally {
|
|
21907
22148
|
await session.close();
|
|
@@ -21909,57 +22150,150 @@ app51.post("/", requireAdminSession, async (c) => {
|
|
|
21909
22150
|
});
|
|
21910
22151
|
var task_time_adjust_default = app51;
|
|
21911
22152
|
|
|
21912
|
-
// server/routes/admin/
|
|
22153
|
+
// server/routes/admin/activity.ts
|
|
22154
|
+
import { readdirSync as readdirSync22 } from "fs";
|
|
21913
22155
|
var app52 = new Hono();
|
|
21914
|
-
|
|
21915
|
-
|
|
21916
|
-
|
|
21917
|
-
|
|
21918
|
-
|
|
21919
|
-
|
|
21920
|
-
|
|
21921
|
-
|
|
21922
|
-
|
|
21923
|
-
|
|
21924
|
-
|
|
21925
|
-
|
|
21926
|
-
|
|
21927
|
-
|
|
21928
|
-
|
|
21929
|
-
|
|
21930
|
-
|
|
21931
|
-
|
|
21932
|
-
|
|
21933
|
-
|
|
21934
|
-
|
|
21935
|
-
app52.
|
|
21936
|
-
|
|
21937
|
-
|
|
21938
|
-
|
|
21939
|
-
|
|
21940
|
-
|
|
21941
|
-
|
|
21942
|
-
|
|
21943
|
-
|
|
21944
|
-
|
|
21945
|
-
|
|
21946
|
-
|
|
21947
|
-
|
|
21948
|
-
|
|
21949
|
-
|
|
21950
|
-
|
|
21951
|
-
|
|
21952
|
-
|
|
21953
|
-
|
|
21954
|
-
|
|
21955
|
-
|
|
22156
|
+
var TAG40 = "[activity]";
|
|
22157
|
+
function resolveHouseAccountId(accounts) {
|
|
22158
|
+
const houses = accounts.filter((a) => a.config.role === "house");
|
|
22159
|
+
if (houses.length === 1) return { accountId: houses[0].accountId, reason: "house" };
|
|
22160
|
+
if (houses.length > 1) return { accountId: null, reason: "multiple-houses" };
|
|
22161
|
+
if (accounts.length === 1) return { accountId: accounts[0].accountId, reason: "sole-account" };
|
|
22162
|
+
return { accountId: null, reason: "no-house" };
|
|
22163
|
+
}
|
|
22164
|
+
function requestToken() {
|
|
22165
|
+
return Math.random().toString(16).slice(2, 10);
|
|
22166
|
+
}
|
|
22167
|
+
var short = (id) => id ? id.slice(0, 8) : "unset";
|
|
22168
|
+
function countAccountDirsOnDisk() {
|
|
22169
|
+
try {
|
|
22170
|
+
return readdirSync22(ACCOUNTS_DIR, { withFileTypes: true }).filter(
|
|
22171
|
+
(e) => e.isDirectory() && !e.name.startsWith(".")
|
|
22172
|
+
).length;
|
|
22173
|
+
} catch {
|
|
22174
|
+
return null;
|
|
22175
|
+
}
|
|
22176
|
+
}
|
|
22177
|
+
app52.get("/", requireAdminSession, async (c) => {
|
|
22178
|
+
const req = requestToken();
|
|
22179
|
+
const cacheKey = c.var.cacheKey;
|
|
22180
|
+
const caller2 = getAccountIdForSession(cacheKey) ?? null;
|
|
22181
|
+
const valid = listValidAccounts();
|
|
22182
|
+
const house = resolveHouseAccountId(valid);
|
|
22183
|
+
const isHouse = caller2 !== null && house.accountId !== null && caller2 === house.accountId;
|
|
22184
|
+
console.log(
|
|
22185
|
+
`${TAG40} op=request req=${req} caller=${short(caller2)} house=${isHouse} houseVia=${house.reason}`
|
|
22186
|
+
);
|
|
22187
|
+
if (!isHouse) {
|
|
22188
|
+
const reason = house.accountId === null ? house.reason : "not-house";
|
|
22189
|
+
console.error(
|
|
22190
|
+
`${TAG40} op=gate req=${req} decision=deny reason=${reason} caller=${short(caller2)} houseAcct=${short(house.accountId)} accounts=${valid.length}`
|
|
22191
|
+
);
|
|
22192
|
+
return c.json({ error: "house-only" }, 403);
|
|
22193
|
+
}
|
|
22194
|
+
console.log(`${TAG40} op=gate req=${req} decision=allow caller=${short(caller2)} via=${house.reason}`);
|
|
22195
|
+
const onDisk = countAccountDirsOnDisk();
|
|
22196
|
+
console.log(
|
|
22197
|
+
`${TAG40} op=accounts req=${req} onDisk=${onDisk ?? "unknown"} valid=${valid.length} ids=${valid.map((a) => short(a.accountId)).join(",")}`
|
|
22198
|
+
);
|
|
22199
|
+
const start = Date.now();
|
|
22200
|
+
let res;
|
|
22201
|
+
try {
|
|
22202
|
+
res = await fetch(`${managerBase("activity:wrapper")}/activity`, {
|
|
22203
|
+
signal: AbortSignal.timeout(3e4)
|
|
22204
|
+
});
|
|
22205
|
+
} catch (err) {
|
|
22206
|
+
console.error(
|
|
22207
|
+
`${TAG40} op=manager-fail req=${req} reason=unreachable err=${err instanceof Error ? err.message : String(err)}`
|
|
22208
|
+
);
|
|
22209
|
+
return c.json({ error: "manager-unreachable" }, 502);
|
|
22210
|
+
}
|
|
22211
|
+
if (res.status !== 200) {
|
|
22212
|
+
console.error(`${TAG40} op=manager-fail req=${req} reason=status status=${res.status}`);
|
|
22213
|
+
return c.json({ error: `manager-status-${res.status}` }, 502);
|
|
22214
|
+
}
|
|
22215
|
+
const body = await res.json().catch(() => null);
|
|
22216
|
+
if (!body || !Array.isArray(body.rows)) {
|
|
22217
|
+
console.error(`${TAG40} op=manager-fail req=${req} reason=bad-json`);
|
|
22218
|
+
return c.json({ error: "manager-bad-json" }, 502);
|
|
22219
|
+
}
|
|
22220
|
+
const rows = body.rows;
|
|
22221
|
+
const census = body.census ?? null;
|
|
22222
|
+
const untaggedCount = rows.filter((r) => r.accountId === null).length;
|
|
22223
|
+
const meteringFailed = rows.filter((r) => r.meteringError !== null).length;
|
|
22224
|
+
const censusAgeMs = census ? Date.now() - census.sampleAtMs : null;
|
|
22225
|
+
console.log(
|
|
22226
|
+
`${TAG40} op=census req=${req} ageMs=${censusAgeMs ?? "none"} live=${census?.live ?? "none"} cpuNull=${census?.cpuNull ?? "none"}`
|
|
22227
|
+
);
|
|
22228
|
+
console.log(
|
|
22229
|
+
`${TAG40} op=response req=${req} rows=${rows.length} accounts=${valid.length} untagged=${untaggedCount} meteringFailed=${meteringFailed} ms=${Date.now() - start}`
|
|
22230
|
+
);
|
|
22231
|
+
return c.json({
|
|
22232
|
+
rows,
|
|
22233
|
+
census,
|
|
22234
|
+
censusAgeMs,
|
|
22235
|
+
accounts: {
|
|
22236
|
+
onDisk,
|
|
22237
|
+
valid: valid.length,
|
|
22238
|
+
ids: valid.map((a) => a.accountId),
|
|
22239
|
+
untaggedCount
|
|
22240
|
+
}
|
|
22241
|
+
});
|
|
22242
|
+
});
|
|
22243
|
+
var activity_default = app52;
|
|
22244
|
+
|
|
22245
|
+
// server/routes/admin/index.ts
|
|
22246
|
+
var app53 = new Hono();
|
|
22247
|
+
app53.route("/session", session_default);
|
|
22248
|
+
app53.route("/accounts", accounts_default);
|
|
22249
|
+
app53.route("/logs", logs_default);
|
|
22250
|
+
app53.route("/claude-info", claude_info_default);
|
|
22251
|
+
app53.route("/attachment", attachment_default);
|
|
22252
|
+
app53.route("/agents", agents_default);
|
|
22253
|
+
app53.route("/sessions", sessions_default);
|
|
22254
|
+
app53.route("/claude-sessions", claude_sessions_default);
|
|
22255
|
+
app53.route("/log-ingest", log_ingest_default);
|
|
22256
|
+
app53.route("/events", events_default);
|
|
22257
|
+
app53.route("/files", files_default);
|
|
22258
|
+
app53.route("/graph-search", graph_search_default);
|
|
22259
|
+
app53.route("/graph-subgraph", graph_subgraph_default);
|
|
22260
|
+
app53.route("/graph-delete", graph_delete_default);
|
|
22261
|
+
app53.route("/graph-restore", graph_restore_default);
|
|
22262
|
+
app53.route("/graph-labels-in-graph", graph_labels_in_graph_default);
|
|
22263
|
+
app53.route("/graph-default-view", graph_default_view_default);
|
|
22264
|
+
app53.route("/sidebar-artefacts", sidebar_artefacts_default);
|
|
22265
|
+
app53.route("/sidebar-sessions", sidebar_sessions_default);
|
|
22266
|
+
app53.route("/session-delete", session_delete_default);
|
|
22267
|
+
app53.route("/session-stop", session_stop_default);
|
|
22268
|
+
app53.route("/session-archive", session_archive_default);
|
|
22269
|
+
app53.route("/session-rename", session_rename_default);
|
|
22270
|
+
app53.route("/session-usage", session_usage_default);
|
|
22271
|
+
app53.route("/browser", browser_default);
|
|
22272
|
+
app53.route("/session-rc-spawn", session_rc_spawn_default);
|
|
22273
|
+
app53.route("/session-reseat", session_reseat_default);
|
|
22274
|
+
app53.route("/system-stats", system_stats_default);
|
|
22275
|
+
app53.route("/health-brand", health_default2);
|
|
22276
|
+
app53.route("/linkedin-ingest", linkedin_ingest_default);
|
|
22277
|
+
app53.route("/post-turn-context", post_turn_context_default);
|
|
22278
|
+
app53.route("/public-session-context", public_session_context_default);
|
|
22279
|
+
app53.route("/public-session-exit", public_session_exit_default);
|
|
22280
|
+
app53.route("/access-session-evict", access_session_evict_default);
|
|
22281
|
+
app53.route("/enrol-person", enrol_person_default);
|
|
22282
|
+
app53.route("/calendar", calendar_default);
|
|
22283
|
+
app53.route("/tasks-list", tasks_list_default);
|
|
22284
|
+
app53.route("/task-timer-start", task_timer_start_default);
|
|
22285
|
+
app53.route("/task-timer-stop", task_timer_stop_default);
|
|
22286
|
+
app53.route("/task-complete", task_complete_default);
|
|
22287
|
+
app53.route("/task-time-adjust", task_time_adjust_default);
|
|
22288
|
+
app53.route("/activity", activity_default);
|
|
22289
|
+
var admin_default = app53;
|
|
21956
22290
|
|
|
21957
22291
|
// server/routes/access/verify-token.ts
|
|
21958
|
-
var
|
|
22292
|
+
var TAG41 = "[access-verify]";
|
|
21959
22293
|
var MINT_TAG = "[access-session-mint]";
|
|
21960
22294
|
var COOKIE_NAME = "__access_session";
|
|
21961
|
-
var
|
|
21962
|
-
|
|
22295
|
+
var app54 = new Hono();
|
|
22296
|
+
app54.post("/", async (c) => {
|
|
21963
22297
|
const ip = c.var.clientIp || "unknown";
|
|
21964
22298
|
let body;
|
|
21965
22299
|
try {
|
|
@@ -21974,39 +22308,39 @@ app53.post("/", async (c) => {
|
|
|
21974
22308
|
}
|
|
21975
22309
|
const rateMsg = checkAccessRateLimit(ip, agentSlug);
|
|
21976
22310
|
if (rateMsg) {
|
|
21977
|
-
console.error(`${
|
|
22311
|
+
console.error(`${TAG41} grantId=- agentSlug=${agentSlug} result=rate-limited ip=${ip}`);
|
|
21978
22312
|
return c.json({ error: rateMsg }, 429);
|
|
21979
22313
|
}
|
|
21980
22314
|
const grant = await findGrantByMagicToken(token);
|
|
21981
22315
|
if (!grant) {
|
|
21982
22316
|
recordAccessFailedAttempt(ip, agentSlug);
|
|
21983
|
-
console.error(`${
|
|
22317
|
+
console.error(`${TAG41} grantId=- agentSlug=${agentSlug} result=notfound ip=${ip}`);
|
|
21984
22318
|
return c.json({ error: "invalid-or-expired-link" }, 401);
|
|
21985
22319
|
}
|
|
21986
22320
|
if (grant.agentSlug !== agentSlug) {
|
|
21987
22321
|
recordAccessFailedAttempt(ip, agentSlug);
|
|
21988
22322
|
console.error(
|
|
21989
|
-
`${
|
|
22323
|
+
`${TAG41} grantId=${grant.grantId} agentSlug=${agentSlug} result=agent-mismatch grantAgent=${grant.agentSlug} ip=${ip}`
|
|
21990
22324
|
);
|
|
21991
22325
|
return c.json({ error: "invalid-or-expired-link" }, 401);
|
|
21992
22326
|
}
|
|
21993
22327
|
if (grant.status === "expired" || grant.status === "revoked") {
|
|
21994
22328
|
recordAccessFailedAttempt(ip, agentSlug);
|
|
21995
22329
|
console.error(
|
|
21996
|
-
`${
|
|
22330
|
+
`${TAG41} grantId=${grant.grantId} agentSlug=${agentSlug} result=expired status=${grant.status} ip=${ip}`
|
|
21997
22331
|
);
|
|
21998
22332
|
return c.json({ error: "access-no-longer-valid" }, 401);
|
|
21999
22333
|
}
|
|
22000
22334
|
if (grant.expiresAt !== null && grant.expiresAt < Date.now()) {
|
|
22001
22335
|
recordAccessFailedAttempt(ip, agentSlug);
|
|
22002
22336
|
console.error(
|
|
22003
|
-
`${
|
|
22337
|
+
`${TAG41} grantId=${grant.grantId} agentSlug=${agentSlug} result=expired reason=expiresAt-past ip=${ip}`
|
|
22004
22338
|
);
|
|
22005
22339
|
return c.json({ error: "access-no-longer-valid" }, 401);
|
|
22006
22340
|
}
|
|
22007
22341
|
if (!grant.sliceToken) {
|
|
22008
22342
|
console.error(
|
|
22009
|
-
`${
|
|
22343
|
+
`${TAG41} grantId=${grant.grantId} agentSlug=${agentSlug} result=no-slice-token reason=schema-violation`
|
|
22010
22344
|
);
|
|
22011
22345
|
return c.json({ error: "grant-misconfigured" }, 500);
|
|
22012
22346
|
}
|
|
@@ -22022,12 +22356,12 @@ app53.post("/", async (c) => {
|
|
|
22022
22356
|
await consumeMagicTokenAndActivate(grant.grantId);
|
|
22023
22357
|
} catch (err) {
|
|
22024
22358
|
console.error(
|
|
22025
|
-
`${
|
|
22359
|
+
`${TAG41} grantId=${grant.grantId} agentSlug=${agentSlug} result=consume-failed err="${err instanceof Error ? err.message : String(err)}"`
|
|
22026
22360
|
);
|
|
22027
22361
|
return c.json({ error: "verification-failed" }, 500);
|
|
22028
22362
|
}
|
|
22029
22363
|
clearAccessRateLimit(ip, agentSlug);
|
|
22030
|
-
console.log(`${
|
|
22364
|
+
console.log(`${TAG41} grantId=${grant.grantId} agentSlug=${agentSlug} result=ok ip=${ip}`);
|
|
22031
22365
|
console.log(
|
|
22032
22366
|
`${MINT_TAG} grantId=${grant.grantId} sliceToken=${grant.sliceToken.slice(0, 8)} agentSlug=${agentSlug} personId=${grant.personId ?? "none"}`
|
|
22033
22367
|
);
|
|
@@ -22041,7 +22375,7 @@ app53.post("/", async (c) => {
|
|
|
22041
22375
|
displayName: grant.displayName
|
|
22042
22376
|
});
|
|
22043
22377
|
});
|
|
22044
|
-
var verify_token_default =
|
|
22378
|
+
var verify_token_default = app54;
|
|
22045
22379
|
|
|
22046
22380
|
// app/lib/access-email.ts
|
|
22047
22381
|
import { spawn as spawn2 } from "child_process";
|
|
@@ -22103,10 +22437,10 @@ async function sendMagicLinkEmail(payload) {
|
|
|
22103
22437
|
}
|
|
22104
22438
|
|
|
22105
22439
|
// server/routes/access/request-magic-link.ts
|
|
22106
|
-
var
|
|
22107
|
-
var
|
|
22440
|
+
var TAG42 = "[access-request-link]";
|
|
22441
|
+
var app55 = new Hono();
|
|
22108
22442
|
var VISITOR_MESSAGE = "If that email is on the invite list, a fresh link is on the way.";
|
|
22109
|
-
|
|
22443
|
+
app55.post("/", async (c) => {
|
|
22110
22444
|
let body;
|
|
22111
22445
|
try {
|
|
22112
22446
|
body = await c.req.json();
|
|
@@ -22120,18 +22454,18 @@ app54.post("/", async (c) => {
|
|
|
22120
22454
|
}
|
|
22121
22455
|
const rateMsg = checkRequestLinkRateLimit(contactValue);
|
|
22122
22456
|
if (rateMsg) {
|
|
22123
|
-
console.error(`${
|
|
22457
|
+
console.error(`${TAG42} contactValue=${maskContact(contactValue)} result=rate-limited`);
|
|
22124
22458
|
return c.json({ error: rateMsg }, 429);
|
|
22125
22459
|
}
|
|
22126
22460
|
recordRequestLinkAttempt(contactValue);
|
|
22127
22461
|
const accountId = process.env.ACCOUNT_ID ?? "";
|
|
22128
22462
|
if (!accountId) {
|
|
22129
|
-
console.error(`${
|
|
22463
|
+
console.error(`${TAG42} contactValue=${maskContact(contactValue)} result=no-account-id`);
|
|
22130
22464
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
22131
22465
|
}
|
|
22132
22466
|
const grant = await findActiveGrantByContact(contactValue, agentSlug, accountId);
|
|
22133
22467
|
if (!grant) {
|
|
22134
|
-
console.log(`${
|
|
22468
|
+
console.log(`${TAG42} contactValue=${maskContact(contactValue)} result=notfound`);
|
|
22135
22469
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
22136
22470
|
}
|
|
22137
22471
|
let token;
|
|
@@ -22139,7 +22473,7 @@ app54.post("/", async (c) => {
|
|
|
22139
22473
|
token = await generateNewMagicToken(grant.grantId);
|
|
22140
22474
|
} catch (err) {
|
|
22141
22475
|
console.error(
|
|
22142
|
-
`${
|
|
22476
|
+
`${TAG42} contactValue=${maskContact(contactValue)} result=mint-failed err="${err instanceof Error ? err.message : String(err)}"`
|
|
22143
22477
|
);
|
|
22144
22478
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
22145
22479
|
}
|
|
@@ -22171,25 +22505,25 @@ app54.post("/", async (c) => {
|
|
|
22171
22505
|
});
|
|
22172
22506
|
if (!sendResult.ok) {
|
|
22173
22507
|
console.error(
|
|
22174
|
-
`${
|
|
22508
|
+
`${TAG42} contactValue=${maskContact(contactValue)} result=send-failed err="${sendResult.error}"`
|
|
22175
22509
|
);
|
|
22176
22510
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
22177
22511
|
}
|
|
22178
22512
|
console.log(
|
|
22179
|
-
`${
|
|
22513
|
+
`${TAG42} contactValue=${maskContact(contactValue)} result=ok messageId=${sendResult.messageId}`
|
|
22180
22514
|
);
|
|
22181
22515
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
22182
22516
|
});
|
|
22183
|
-
var request_magic_link_default =
|
|
22517
|
+
var request_magic_link_default = app55;
|
|
22184
22518
|
|
|
22185
22519
|
// server/routes/access/index.ts
|
|
22186
|
-
var
|
|
22187
|
-
|
|
22188
|
-
|
|
22189
|
-
var access_default =
|
|
22520
|
+
var app56 = new Hono();
|
|
22521
|
+
app56.route("/verify-token", verify_token_default);
|
|
22522
|
+
app56.route("/request-magic-link", request_magic_link_default);
|
|
22523
|
+
var access_default = app56;
|
|
22190
22524
|
|
|
22191
22525
|
// server/routes/sites.ts
|
|
22192
|
-
import { existsSync as
|
|
22526
|
+
import { existsSync as existsSync32, readFileSync as readFileSync35, realpathSync as realpathSync7, statSync as statSync12 } from "fs";
|
|
22193
22527
|
import { resolve as resolve28 } from "path";
|
|
22194
22528
|
var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
|
|
22195
22529
|
var MIME = {
|
|
@@ -22221,8 +22555,8 @@ function getExt(p) {
|
|
|
22221
22555
|
if (idx < p.lastIndexOf("/")) return "";
|
|
22222
22556
|
return p.slice(idx).toLowerCase();
|
|
22223
22557
|
}
|
|
22224
|
-
var
|
|
22225
|
-
|
|
22558
|
+
var app57 = new Hono();
|
|
22559
|
+
app57.get("/:rel{.*}", (c) => {
|
|
22226
22560
|
const reqPath = c.req.path;
|
|
22227
22561
|
const rawRel = c.req.param("rel") ?? "";
|
|
22228
22562
|
const trimmed = rawRel.replace(/^\/+/, "").replace(/\/+$/, "");
|
|
@@ -22255,7 +22589,7 @@ app56.get("/:rel{.*}", (c) => {
|
|
|
22255
22589
|
}
|
|
22256
22590
|
let stat8;
|
|
22257
22591
|
try {
|
|
22258
|
-
stat8 =
|
|
22592
|
+
stat8 = existsSync32(filePath) ? statSync12(filePath) : null;
|
|
22259
22593
|
} catch {
|
|
22260
22594
|
stat8 = null;
|
|
22261
22595
|
}
|
|
@@ -22274,7 +22608,7 @@ app56.get("/:rel{.*}", (c) => {
|
|
|
22274
22608
|
console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
|
|
22275
22609
|
return c.text("Forbidden", 403);
|
|
22276
22610
|
}
|
|
22277
|
-
if (!
|
|
22611
|
+
if (!existsSync32(filePath)) {
|
|
22278
22612
|
console.error(`[sites] not-found path=${reqPath} status=404`);
|
|
22279
22613
|
return c.text("Not found", 404);
|
|
22280
22614
|
}
|
|
@@ -22293,7 +22627,7 @@ app56.get("/:rel{.*}", (c) => {
|
|
|
22293
22627
|
}
|
|
22294
22628
|
let body;
|
|
22295
22629
|
try {
|
|
22296
|
-
body =
|
|
22630
|
+
body = readFileSync35(realPath);
|
|
22297
22631
|
} catch (err) {
|
|
22298
22632
|
const code = err?.code;
|
|
22299
22633
|
if (code === "EISDIR") {
|
|
@@ -22325,11 +22659,11 @@ app56.get("/:rel{.*}", (c) => {
|
|
|
22325
22659
|
"X-Content-Type-Options": "nosniff"
|
|
22326
22660
|
});
|
|
22327
22661
|
});
|
|
22328
|
-
var sites_default =
|
|
22662
|
+
var sites_default = app57;
|
|
22329
22663
|
|
|
22330
22664
|
// app/lib/visitor-token.ts
|
|
22331
|
-
import { createHmac, randomBytes, timingSafeEqual } from "crypto";
|
|
22332
|
-
import { mkdirSync as
|
|
22665
|
+
import { createHmac, randomBytes as randomBytes2, timingSafeEqual } from "crypto";
|
|
22666
|
+
import { mkdirSync as mkdirSync8, readFileSync as readFileSync36, writeFileSync as writeFileSync12 } from "fs";
|
|
22333
22667
|
import { dirname as dirname12 } from "path";
|
|
22334
22668
|
var TOKEN_PREFIX = "v1.";
|
|
22335
22669
|
var SECRET_BYTES = 32;
|
|
@@ -22338,21 +22672,21 @@ var cachedSecret = null;
|
|
|
22338
22672
|
function getSecret() {
|
|
22339
22673
|
if (cachedSecret) return cachedSecret;
|
|
22340
22674
|
try {
|
|
22341
|
-
const hex2 =
|
|
22675
|
+
const hex2 = readFileSync36(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
|
|
22342
22676
|
if (hex2.length === SECRET_BYTES * 2) {
|
|
22343
22677
|
cachedSecret = Buffer.from(hex2, "hex");
|
|
22344
22678
|
return cachedSecret;
|
|
22345
22679
|
}
|
|
22346
22680
|
} catch {
|
|
22347
22681
|
}
|
|
22348
|
-
const fresh =
|
|
22682
|
+
const fresh = randomBytes2(SECRET_BYTES).toString("hex");
|
|
22349
22683
|
try {
|
|
22350
|
-
|
|
22351
|
-
|
|
22684
|
+
mkdirSync8(dirname12(VISITOR_TOKEN_SECRET_FILE), { recursive: true, mode: 448 });
|
|
22685
|
+
writeFileSync12(VISITOR_TOKEN_SECRET_FILE, fresh, { mode: 384, flag: "wx" });
|
|
22352
22686
|
console.log(`[visitor-token] secret minted path=${VISITOR_TOKEN_SECRET_FILE}`);
|
|
22353
22687
|
} catch {
|
|
22354
22688
|
}
|
|
22355
|
-
const hex =
|
|
22689
|
+
const hex = readFileSync36(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
|
|
22356
22690
|
cachedSecret = Buffer.from(hex, "hex");
|
|
22357
22691
|
return cachedSecret;
|
|
22358
22692
|
}
|
|
@@ -22405,8 +22739,8 @@ var VISITOR_COOKIE_NAME = "mxy_v";
|
|
|
22405
22739
|
var VISITOR_COOKIE_MAX_AGE_SECONDS = Math.floor(DEFAULT_TTL_MS / 1e3);
|
|
22406
22740
|
|
|
22407
22741
|
// app/lib/brand-config.ts
|
|
22408
|
-
import { existsSync as
|
|
22409
|
-
import { join as
|
|
22742
|
+
import { existsSync as existsSync33, readFileSync as readFileSync37 } from "fs";
|
|
22743
|
+
import { join as join36 } from "path";
|
|
22410
22744
|
var cached2 = null;
|
|
22411
22745
|
var cachedAttempted = false;
|
|
22412
22746
|
function readBrandConfig() {
|
|
@@ -22414,10 +22748,10 @@ function readBrandConfig() {
|
|
|
22414
22748
|
cachedAttempted = true;
|
|
22415
22749
|
const platformRoot5 = process.env.MAXY_PLATFORM_ROOT;
|
|
22416
22750
|
if (!platformRoot5) return null;
|
|
22417
|
-
const brandPath =
|
|
22418
|
-
if (!
|
|
22751
|
+
const brandPath = join36(platformRoot5, "config", "brand.json");
|
|
22752
|
+
if (!existsSync33(brandPath)) return null;
|
|
22419
22753
|
try {
|
|
22420
|
-
cached2 = JSON.parse(
|
|
22754
|
+
cached2 = JSON.parse(readFileSync37(brandPath, "utf-8"));
|
|
22421
22755
|
return cached2;
|
|
22422
22756
|
} catch {
|
|
22423
22757
|
return null;
|
|
@@ -22425,7 +22759,7 @@ function readBrandConfig() {
|
|
|
22425
22759
|
}
|
|
22426
22760
|
|
|
22427
22761
|
// server/routes/visitor-consent.ts
|
|
22428
|
-
var
|
|
22762
|
+
var app58 = new Hono();
|
|
22429
22763
|
var CONSENT_COOKIE_NAME = "mxy_consent";
|
|
22430
22764
|
var CONSENT_COOKIE_MAX_AGE_SECONDS = 60 * 60 * 24 * 365;
|
|
22431
22765
|
var DEFAULT_CONSENT_COPY = {
|
|
@@ -22470,17 +22804,17 @@ function siteSlugFromReferer(referer) {
|
|
|
22470
22804
|
return "";
|
|
22471
22805
|
}
|
|
22472
22806
|
}
|
|
22473
|
-
|
|
22807
|
+
app58.options("/consent", (c) => {
|
|
22474
22808
|
const origin = getOrigin(c);
|
|
22475
22809
|
setCorsHeaders(c, origin);
|
|
22476
22810
|
return c.body(null, 204);
|
|
22477
22811
|
});
|
|
22478
|
-
|
|
22812
|
+
app58.options("/brand-config", (c) => {
|
|
22479
22813
|
const origin = getOrigin(c);
|
|
22480
22814
|
setCorsHeaders(c, origin);
|
|
22481
22815
|
return c.body(null, 204);
|
|
22482
22816
|
});
|
|
22483
|
-
|
|
22817
|
+
app58.post("/consent", async (c) => {
|
|
22484
22818
|
const origin = getOrigin(c);
|
|
22485
22819
|
setCorsHeaders(c, origin);
|
|
22486
22820
|
let raw;
|
|
@@ -22520,7 +22854,7 @@ app57.post("/consent", async (c) => {
|
|
|
22520
22854
|
console.log(`[consent] ${parsed.decision} site=${site} brand=${brandName} tokenBound=${tokenBound}`);
|
|
22521
22855
|
return c.body(null, 204);
|
|
22522
22856
|
});
|
|
22523
|
-
|
|
22857
|
+
app58.get("/brand-config", (c) => {
|
|
22524
22858
|
const origin = getOrigin(c);
|
|
22525
22859
|
setCorsHeaders(c, origin);
|
|
22526
22860
|
const brand = readBrandConfig();
|
|
@@ -22530,7 +22864,7 @@ app57.get("/brand-config", (c) => {
|
|
|
22530
22864
|
c.header("Cache-Control", "public, max-age=300");
|
|
22531
22865
|
return c.json({ consent: { copy, palette } });
|
|
22532
22866
|
});
|
|
22533
|
-
var visitor_consent_default =
|
|
22867
|
+
var visitor_consent_default = app58;
|
|
22534
22868
|
|
|
22535
22869
|
// server/routes/listings.ts
|
|
22536
22870
|
function getCookie(headerValue, name) {
|
|
@@ -22557,8 +22891,8 @@ function appendConsentParams(pageUrl, token) {
|
|
|
22557
22891
|
}
|
|
22558
22892
|
var SAFE_SLUG_RE = /^[a-z0-9](?:[a-z0-9-]{0,118}[a-z0-9])?$/;
|
|
22559
22893
|
var CHAT_SESSION_KEY_RE = /^[A-Za-z0-9][A-Za-z0-9_-]{7,127}$/;
|
|
22560
|
-
var
|
|
22561
|
-
|
|
22894
|
+
var app59 = new Hono();
|
|
22895
|
+
app59.get("/:slug/click", async (c) => {
|
|
22562
22896
|
const slug = c.req.param("slug") ?? "";
|
|
22563
22897
|
const rawSession = c.req.query("session") ?? "";
|
|
22564
22898
|
const sessionKey = CHAT_SESSION_KEY_RE.test(rawSession) ? rawSession : "invalid";
|
|
@@ -22622,10 +22956,10 @@ app58.get("/:slug/click", async (c) => {
|
|
|
22622
22956
|
console.log(`[property-card-click] sessionKey=${sessionKey} listingSlug=${slug} consent=${consentCookie ?? "absent"} ts=${(/* @__PURE__ */ new Date()).toISOString()}`);
|
|
22623
22957
|
return c.redirect(redirectUrl, 302);
|
|
22624
22958
|
});
|
|
22625
|
-
var listings_default =
|
|
22959
|
+
var listings_default = app59;
|
|
22626
22960
|
|
|
22627
22961
|
// server/routes/visitor-event.ts
|
|
22628
|
-
var
|
|
22962
|
+
var app60 = new Hono();
|
|
22629
22963
|
var BOT_UA_RE = /\b(bot|crawl|spider|slurp|headlesschrome|phantomjs|googlebot|bingbot|yandex|baiduspider|ahrefsbot|semrushbot|mj12bot|dotbot|petalbot)\b/i;
|
|
22630
22964
|
var buckets = /* @__PURE__ */ new Map();
|
|
22631
22965
|
var RATE_LIMIT = 60;
|
|
@@ -22692,12 +23026,12 @@ function originAllowed(origin, allowlist) {
|
|
|
22692
23026
|
return false;
|
|
22693
23027
|
}
|
|
22694
23028
|
}
|
|
22695
|
-
|
|
23029
|
+
app60.options("/event", (c) => {
|
|
22696
23030
|
const origin = getOrigin2(c);
|
|
22697
23031
|
setCorsHeaders2(c, origin);
|
|
22698
23032
|
return c.body(null, 204);
|
|
22699
23033
|
});
|
|
22700
|
-
|
|
23034
|
+
app60.post("/event", async (c) => {
|
|
22701
23035
|
const origin = getOrigin2(c);
|
|
22702
23036
|
setCorsHeaders2(c, origin);
|
|
22703
23037
|
const ua = c.req.header("user-agent") ?? "";
|
|
@@ -22902,17 +23236,17 @@ async function writeEvent(opts) {
|
|
|
22902
23236
|
);
|
|
22903
23237
|
}
|
|
22904
23238
|
}
|
|
22905
|
-
var visitor_event_default =
|
|
23239
|
+
var visitor_event_default = app60;
|
|
22906
23240
|
|
|
22907
23241
|
// server/routes/session.ts
|
|
22908
23242
|
import { resolve as resolve29 } from "path";
|
|
22909
|
-
import { existsSync as
|
|
23243
|
+
import { existsSync as existsSync34, writeFileSync as writeFileSync13, mkdirSync as mkdirSync9 } from "fs";
|
|
22910
23244
|
var UUID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
22911
23245
|
function writeBrandingCache(accountId, agentSlug, branding) {
|
|
22912
23246
|
try {
|
|
22913
23247
|
const cacheDir = resolve29(MAXY_DIR, "branding-cache", accountId);
|
|
22914
|
-
|
|
22915
|
-
|
|
23248
|
+
mkdirSync9(cacheDir, { recursive: true });
|
|
23249
|
+
writeFileSync13(resolve29(cacheDir, `${agentSlug}.json`), JSON.stringify(branding), "utf-8");
|
|
22916
23250
|
} catch (err) {
|
|
22917
23251
|
console.error(`[branding] cache write failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
22918
23252
|
}
|
|
@@ -22948,8 +23282,8 @@ function withVisitorCookie(response, visitorId) {
|
|
|
22948
23282
|
headers
|
|
22949
23283
|
});
|
|
22950
23284
|
}
|
|
22951
|
-
var
|
|
22952
|
-
|
|
23285
|
+
var app61 = new Hono();
|
|
23286
|
+
app61.post("/", async (c) => {
|
|
22953
23287
|
let body;
|
|
22954
23288
|
try {
|
|
22955
23289
|
body = await c.req.json();
|
|
@@ -22990,7 +23324,7 @@ app60.post("/", async (c) => {
|
|
|
22990
23324
|
let agentConfig = null;
|
|
22991
23325
|
if (account) {
|
|
22992
23326
|
const agentDir = resolve29(account.accountDir, "agents", agentSlug);
|
|
22993
|
-
if (!
|
|
23327
|
+
if (!existsSync34(agentDir) || !existsSync34(resolve29(agentDir, "config.json"))) {
|
|
22994
23328
|
return c.json({ error: "Agent not found" }, 404);
|
|
22995
23329
|
}
|
|
22996
23330
|
agentConfig = resolveAgentConfig(account.accountDir, agentSlug);
|
|
@@ -23096,7 +23430,7 @@ app60.post("/", async (c) => {
|
|
|
23096
23430
|
newVisitorId
|
|
23097
23431
|
);
|
|
23098
23432
|
});
|
|
23099
|
-
var session_default2 =
|
|
23433
|
+
var session_default2 = app61;
|
|
23100
23434
|
|
|
23101
23435
|
// server/lib/calendar-slots.ts
|
|
23102
23436
|
var WEEKDAYS = ["sun", "mon", "tue", "wed", "thu", "fri", "sat"];
|
|
@@ -23179,17 +23513,17 @@ function computeOpenSlots(config, busy, fromISO, toISO) {
|
|
|
23179
23513
|
}
|
|
23180
23514
|
|
|
23181
23515
|
// server/routes/calendar-public.ts
|
|
23182
|
-
var
|
|
23516
|
+
var app62 = new Hono();
|
|
23183
23517
|
function setCors(c) {
|
|
23184
23518
|
c.header("Access-Control-Allow-Origin", "*");
|
|
23185
23519
|
c.header("Access-Control-Allow-Methods", "GET, OPTIONS");
|
|
23186
23520
|
c.header("Access-Control-Allow-Headers", "content-type");
|
|
23187
23521
|
}
|
|
23188
|
-
|
|
23522
|
+
app62.options("/free-busy", (c) => {
|
|
23189
23523
|
setCors(c);
|
|
23190
23524
|
return c.body(null, 204);
|
|
23191
23525
|
});
|
|
23192
|
-
|
|
23526
|
+
app62.get("/free-busy", async (c) => {
|
|
23193
23527
|
setCors(c);
|
|
23194
23528
|
const from = c.req.query("from");
|
|
23195
23529
|
const to = c.req.query("to");
|
|
@@ -23235,10 +23569,10 @@ app61.get("/free-busy", async (c) => {
|
|
|
23235
23569
|
await session.close();
|
|
23236
23570
|
}
|
|
23237
23571
|
});
|
|
23238
|
-
var calendar_public_default =
|
|
23572
|
+
var calendar_public_default = app62;
|
|
23239
23573
|
|
|
23240
23574
|
// app/lib/timeentry-census.ts
|
|
23241
|
-
var
|
|
23575
|
+
var TAG43 = "[timeentry-census]";
|
|
23242
23576
|
function reconcileTimeEntries(rows, now, horizonMs) {
|
|
23243
23577
|
const openEntries = rows.openEntries.length;
|
|
23244
23578
|
let oldestOpenAgeMs = 0;
|
|
@@ -23278,12 +23612,12 @@ async function runTimeEntryCensusOnce(session, now, horizonMs) {
|
|
|
23278
23612
|
sumAdjustments: toNum(r.get("sumAdjustments"))
|
|
23279
23613
|
}));
|
|
23280
23614
|
const finding = reconcileTimeEntries({ openEntries, taskSums }, now, horizonMs);
|
|
23281
|
-
const line = `${
|
|
23615
|
+
const line = `${TAG43} openEntries=${finding.openEntries} oldestOpenAgeMin=${finding.oldestOpenAgeMin} maxOpenPerAccount=${finding.maxOpenPerAccount} driftTasks=${finding.driftTasks}`;
|
|
23282
23616
|
if (finding.alarm) console.error(`${line} alarm=true`);
|
|
23283
23617
|
else console.log(line);
|
|
23284
23618
|
return finding;
|
|
23285
23619
|
} catch (err) {
|
|
23286
|
-
console.error(`${
|
|
23620
|
+
console.error(`${TAG43} error="${err instanceof Error ? err.message : String(err)}"`);
|
|
23287
23621
|
return null;
|
|
23288
23622
|
}
|
|
23289
23623
|
}
|
|
@@ -23297,13 +23631,13 @@ function startTimeEntryCensus(openSession, opts = {}) {
|
|
|
23297
23631
|
try {
|
|
23298
23632
|
session = openSession();
|
|
23299
23633
|
} catch (err) {
|
|
23300
|
-
console.error(`${
|
|
23634
|
+
console.error(`${TAG43} open-session-failed error="${err instanceof Error ? err.message : String(err)}"`);
|
|
23301
23635
|
return;
|
|
23302
23636
|
}
|
|
23303
23637
|
try {
|
|
23304
23638
|
await runTimeEntryCensusOnce(session, Date.now(), horizonMs);
|
|
23305
23639
|
} catch (err) {
|
|
23306
|
-
console.error(`${
|
|
23640
|
+
console.error(`${TAG43} tick-failed error="${err instanceof Error ? err.message : String(err)}"`);
|
|
23307
23641
|
} finally {
|
|
23308
23642
|
try {
|
|
23309
23643
|
await session.close();
|
|
@@ -23321,8 +23655,181 @@ function startTimeEntryCensus(openSession, opts = {}) {
|
|
|
23321
23655
|
return () => clearInterval(id);
|
|
23322
23656
|
}
|
|
23323
23657
|
|
|
23658
|
+
// ../lib/ledger-core/dist/reconcile.js
|
|
23659
|
+
var LEDGER_INDEX_NAMES = [
|
|
23660
|
+
"invoice_account_confirmation_unique",
|
|
23661
|
+
"cash_entry_account_entryid_unique",
|
|
23662
|
+
"cash_entry_account",
|
|
23663
|
+
"invoice_line_account",
|
|
23664
|
+
"invoice_payment_account",
|
|
23665
|
+
"credit_account"
|
|
23666
|
+
];
|
|
23667
|
+
function countSuspectDuplicates(keys) {
|
|
23668
|
+
const groups = /* @__PURE__ */ new Map();
|
|
23669
|
+
for (const k of keys) {
|
|
23670
|
+
const composite = `${k.invoiceId}|${k.amount}|${k.date}`;
|
|
23671
|
+
const ids = groups.get(composite) ?? /* @__PURE__ */ new Set();
|
|
23672
|
+
ids.add(k.paymentId);
|
|
23673
|
+
groups.set(composite, ids);
|
|
23674
|
+
}
|
|
23675
|
+
let total = 0;
|
|
23676
|
+
for (const ids of groups.values())
|
|
23677
|
+
total += Math.max(0, ids.size - 1);
|
|
23678
|
+
return total;
|
|
23679
|
+
}
|
|
23680
|
+
function reconcileLedger(rows, _now) {
|
|
23681
|
+
const suspectDuplicates = countSuspectDuplicates(rows.paymentKeys);
|
|
23682
|
+
const alarm = rows.orphanPayments > 0 || rows.storedBalanceProps > 0 || suspectDuplicates > 0 || rows.declaredNotLive.length > 0;
|
|
23683
|
+
return {
|
|
23684
|
+
invoices: rows.invoices,
|
|
23685
|
+
payments: rows.payments,
|
|
23686
|
+
orphanPayments: rows.orphanPayments,
|
|
23687
|
+
storedBalanceProps: rows.storedBalanceProps,
|
|
23688
|
+
suspectDuplicates,
|
|
23689
|
+
declaredNotLive: rows.declaredNotLive,
|
|
23690
|
+
alarm
|
|
23691
|
+
};
|
|
23692
|
+
}
|
|
23693
|
+
function formatCensusLine(f) {
|
|
23694
|
+
return `[ledger-census] invoices=${f.invoices} payments=${f.payments} orphanPayments=${f.orphanPayments} storedBalanceProps=${f.storedBalanceProps} suspectDuplicates=${f.suspectDuplicates} declaredNotLive=${f.declaredNotLive.length === 0 ? "none" : f.declaredNotLive.join(",")}`;
|
|
23695
|
+
}
|
|
23696
|
+
|
|
23697
|
+
// app/lib/ledger-census.ts
|
|
23698
|
+
var TAG44 = "[ledger-census]";
|
|
23699
|
+
function toNum2(v) {
|
|
23700
|
+
if (typeof v === "number") return v;
|
|
23701
|
+
if (v && typeof v === "object" && "toNumber" in v) {
|
|
23702
|
+
return v.toNumber();
|
|
23703
|
+
}
|
|
23704
|
+
return 0;
|
|
23705
|
+
}
|
|
23706
|
+
async function runLedgerCensusOnce(session, now) {
|
|
23707
|
+
try {
|
|
23708
|
+
const counts = await session.run(
|
|
23709
|
+
`MATCH (i:Invoice|InboundInvoice) WITH count(i) AS invoices
|
|
23710
|
+
OPTIONAL MATCH (p:InvoicePayment)
|
|
23711
|
+
RETURN invoices, count(p) AS payments`
|
|
23712
|
+
);
|
|
23713
|
+
const orphans = await session.run(
|
|
23714
|
+
`MATCH (p:InvoicePayment)
|
|
23715
|
+
WHERE NOT ( (:Invoice|InboundInvoice)-[:HAS_PAYMENT]->(p) )
|
|
23716
|
+
RETURN count(p) AS orphanPayments`
|
|
23717
|
+
);
|
|
23718
|
+
const stored = await session.run(
|
|
23719
|
+
`MATCH (i:Invoice|InboundInvoice)
|
|
23720
|
+
WHERE i.outstanding IS NOT NULL OR i.balance IS NOT NULL OR i.amountPaid IS NOT NULL
|
|
23721
|
+
RETURN count(i) AS storedBalanceProps`
|
|
23722
|
+
);
|
|
23723
|
+
const keys = await session.run(
|
|
23724
|
+
`MATCH (i:Invoice|InboundInvoice)-[:HAS_PAYMENT]->(p:InvoicePayment)
|
|
23725
|
+
RETURN i.confirmationNumber AS invoiceId, p.paymentId AS paymentId,
|
|
23726
|
+
p.amount AS amount, p.date AS date`
|
|
23727
|
+
);
|
|
23728
|
+
const indexes = await session.run(`SHOW INDEXES YIELD name RETURN collect(name) AS names`);
|
|
23729
|
+
const live = new Set(indexes.records[0]?.get("names") ?? []);
|
|
23730
|
+
const finding = reconcileLedger(
|
|
23731
|
+
{
|
|
23732
|
+
invoices: toNum2(counts.records[0]?.get("invoices")),
|
|
23733
|
+
payments: toNum2(counts.records[0]?.get("payments")),
|
|
23734
|
+
orphanPayments: toNum2(orphans.records[0]?.get("orphanPayments")),
|
|
23735
|
+
storedBalanceProps: toNum2(stored.records[0]?.get("storedBalanceProps")),
|
|
23736
|
+
paymentKeys: keys.records.map((r) => ({
|
|
23737
|
+
invoiceId: r.get("invoiceId") ?? "",
|
|
23738
|
+
paymentId: r.get("paymentId") ?? "",
|
|
23739
|
+
amount: toNum2(r.get("amount")),
|
|
23740
|
+
date: r.get("date") ?? ""
|
|
23741
|
+
})),
|
|
23742
|
+
declaredNotLive: LEDGER_INDEX_NAMES.filter((n) => !live.has(n))
|
|
23743
|
+
},
|
|
23744
|
+
now
|
|
23745
|
+
);
|
|
23746
|
+
const line = formatCensusLine(finding);
|
|
23747
|
+
if (finding.alarm) console.error(`${line} alarm=true`);
|
|
23748
|
+
else console.log(line);
|
|
23749
|
+
return finding;
|
|
23750
|
+
} catch (err) {
|
|
23751
|
+
console.error(`${TAG44} error="${err instanceof Error ? err.message : String(err)}"`);
|
|
23752
|
+
return null;
|
|
23753
|
+
}
|
|
23754
|
+
}
|
|
23755
|
+
var DEFAULT_INTERVAL_MS2 = 15 * 60 * 1e3;
|
|
23756
|
+
function startLedgerCensus(openSession, opts = {}) {
|
|
23757
|
+
const intervalMs = opts.intervalMs ?? DEFAULT_INTERVAL_MS2;
|
|
23758
|
+
const tick = async () => {
|
|
23759
|
+
let session;
|
|
23760
|
+
try {
|
|
23761
|
+
session = openSession();
|
|
23762
|
+
} catch (err) {
|
|
23763
|
+
console.error(
|
|
23764
|
+
`${TAG44} open-session-failed error="${err instanceof Error ? err.message : String(err)}"`
|
|
23765
|
+
);
|
|
23766
|
+
return;
|
|
23767
|
+
}
|
|
23768
|
+
try {
|
|
23769
|
+
await runLedgerCensusOnce(session, Date.now());
|
|
23770
|
+
} catch (err) {
|
|
23771
|
+
console.error(
|
|
23772
|
+
`${TAG44} tick-failed error="${err instanceof Error ? err.message : String(err)}"`
|
|
23773
|
+
);
|
|
23774
|
+
} finally {
|
|
23775
|
+
try {
|
|
23776
|
+
await session.close();
|
|
23777
|
+
} catch {
|
|
23778
|
+
}
|
|
23779
|
+
}
|
|
23780
|
+
};
|
|
23781
|
+
void tick();
|
|
23782
|
+
const id = setInterval(() => {
|
|
23783
|
+
void tick();
|
|
23784
|
+
}, intervalMs);
|
|
23785
|
+
if (typeof id.unref === "function") {
|
|
23786
|
+
;
|
|
23787
|
+
id.unref();
|
|
23788
|
+
}
|
|
23789
|
+
return () => clearInterval(id);
|
|
23790
|
+
}
|
|
23791
|
+
|
|
23792
|
+
// app/lib/conversation-audit.ts
|
|
23793
|
+
var TAG45 = "[conversation-audit]";
|
|
23794
|
+
async function runConversationAudit() {
|
|
23795
|
+
const session = getSession();
|
|
23796
|
+
try {
|
|
23797
|
+
const res = await session.run(
|
|
23798
|
+
`MATCH (a:Conversation {channel: 'whatsapp'})
|
|
23799
|
+
WHERE a.channelAddress =~ '[0-9]+'
|
|
23800
|
+
WITH collect(a.channelAddress) AS anchored
|
|
23801
|
+
MATCH (c:Conversation {channel: 'whatsapp'})
|
|
23802
|
+
WITH anchored,
|
|
23803
|
+
count(*) AS total,
|
|
23804
|
+
sum(CASE WHEN c.channelAddress = 'default' THEN 1 ELSE 0 END) AS unpairable,
|
|
23805
|
+
collect(CASE WHEN c.channelAddress =~ 'default:[0-9]+'
|
|
23806
|
+
THEN substring(c.channelAddress, 8) END) AS forensic
|
|
23807
|
+
RETURN total,
|
|
23808
|
+
unpairable,
|
|
23809
|
+
size([p IN forensic WHERE p IS NOT NULL AND NOT p IN anchored]) AS unreconciled`,
|
|
23810
|
+
{}
|
|
23811
|
+
);
|
|
23812
|
+
const rec = res.records[0];
|
|
23813
|
+
const result = {
|
|
23814
|
+
total: Number(rec?.get("total") ?? 0),
|
|
23815
|
+
unreconciled: Number(rec?.get("unreconciled") ?? 0),
|
|
23816
|
+
unpairable: Number(rec?.get("unpairable") ?? 0)
|
|
23817
|
+
};
|
|
23818
|
+
console.error(
|
|
23819
|
+
`${TAG45} channel=whatsapp total=${result.total} unreconciled=${result.unreconciled} unpairable=${result.unpairable}`
|
|
23820
|
+
);
|
|
23821
|
+
return result;
|
|
23822
|
+
} catch (err) {
|
|
23823
|
+
const reason = err instanceof Error ? `${err.name}:${err.message.slice(0, 200)}` : String(err).slice(0, 200);
|
|
23824
|
+
console.error(`${TAG45} op=failed reason=${reason}`);
|
|
23825
|
+
return null;
|
|
23826
|
+
} finally {
|
|
23827
|
+
await session.close();
|
|
23828
|
+
}
|
|
23829
|
+
}
|
|
23830
|
+
|
|
23324
23831
|
// app/lib/graph-health.ts
|
|
23325
|
-
var
|
|
23832
|
+
var import_dist5 = __toESM(require_dist4(), 1);
|
|
23326
23833
|
var HOUR_MS = 60 * 60 * 1e3;
|
|
23327
23834
|
function renderLabelTop(rows) {
|
|
23328
23835
|
return rows.map((b) => {
|
|
@@ -23367,7 +23874,7 @@ async function runGraphHealthTick() {
|
|
|
23367
23874
|
console.error(
|
|
23368
23875
|
`[graph-health] userprofile-multi accounts=${upAccounts} top=${upTop.length > 0 ? upTop.join(",") : "none"}`
|
|
23369
23876
|
);
|
|
23370
|
-
const indexed = [...
|
|
23877
|
+
const indexed = [...import_dist5.VECTOR_INDEXED_LABELS];
|
|
23371
23878
|
const embCount = await session.run(
|
|
23372
23879
|
`MATCH (n) WHERE n.embedding IS NULL AND any(l IN labels(n) WHERE l IN $indexed)
|
|
23373
23880
|
RETURN count(n) AS total`,
|
|
@@ -23666,8 +24173,8 @@ async function migrateUploads(opts = {}) {
|
|
|
23666
24173
|
|
|
23667
24174
|
// app/lib/migrate-admin-webchat-sidecars.ts
|
|
23668
24175
|
import { readdir as readdir6, readFile as readFile6, rename as rename3, writeFile as writeFile4, unlink as unlink3 } from "fs/promises";
|
|
23669
|
-
import { existsSync as
|
|
23670
|
-
import { join as
|
|
24176
|
+
import { existsSync as existsSync35 } from "fs";
|
|
24177
|
+
import { join as join37 } from "path";
|
|
23671
24178
|
var ADMIN_ROLE2 = "admin";
|
|
23672
24179
|
var WEBCHAT_CHANNEL2 = "webchat";
|
|
23673
24180
|
var SESSION_META_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\.meta\.json$/i;
|
|
@@ -23696,7 +24203,7 @@ async function writeRaw(path3, obj) {
|
|
|
23696
24203
|
await rename3(tmp, path3);
|
|
23697
24204
|
} catch (err) {
|
|
23698
24205
|
try {
|
|
23699
|
-
if (
|
|
24206
|
+
if (existsSync35(tmp)) await unlink3(tmp);
|
|
23700
24207
|
} catch {
|
|
23701
24208
|
}
|
|
23702
24209
|
throw err;
|
|
@@ -23712,7 +24219,7 @@ async function collectLiveSidecars(projectsRoot) {
|
|
|
23712
24219
|
}
|
|
23713
24220
|
for (const slug of slugs) {
|
|
23714
24221
|
if (!slug.isDirectory()) continue;
|
|
23715
|
-
const slugDir =
|
|
24222
|
+
const slugDir = join37(projectsRoot, slug.name);
|
|
23716
24223
|
let entries;
|
|
23717
24224
|
try {
|
|
23718
24225
|
entries = await readdir6(slugDir, { withFileTypes: true });
|
|
@@ -23721,9 +24228,9 @@ async function collectLiveSidecars(projectsRoot) {
|
|
|
23721
24228
|
}
|
|
23722
24229
|
for (const entry of entries) {
|
|
23723
24230
|
if (entry.isFile() && SESSION_META_RE.test(entry.name)) {
|
|
23724
|
-
out.push(
|
|
24231
|
+
out.push(join37(slugDir, entry.name));
|
|
23725
24232
|
} else if (entry.isDirectory() && entry.name === "subagents") {
|
|
23726
|
-
const subDir =
|
|
24233
|
+
const subDir = join37(slugDir, entry.name);
|
|
23727
24234
|
let subs;
|
|
23728
24235
|
try {
|
|
23729
24236
|
subs = await readdir6(subDir, { withFileTypes: true });
|
|
@@ -23731,7 +24238,7 @@ async function collectLiveSidecars(projectsRoot) {
|
|
|
23731
24238
|
continue;
|
|
23732
24239
|
}
|
|
23733
24240
|
for (const s of subs) {
|
|
23734
|
-
if (s.isFile() && SESSION_META_RE.test(s.name)) out.push(
|
|
24241
|
+
if (s.isFile() && SESSION_META_RE.test(s.name)) out.push(join37(subDir, s.name));
|
|
23735
24242
|
}
|
|
23736
24243
|
}
|
|
23737
24244
|
}
|
|
@@ -23743,7 +24250,7 @@ function shortId(path3) {
|
|
|
23743
24250
|
return base.slice(0, 8);
|
|
23744
24251
|
}
|
|
23745
24252
|
async function migrateAdminWebchatSidecars(opts = {}) {
|
|
23746
|
-
const projectsRoot = opts.projectsRoot ?? (process.env.CLAUDE_CONFIG_DIR ?
|
|
24253
|
+
const projectsRoot = opts.projectsRoot ?? (process.env.CLAUDE_CONFIG_DIR ? join37(process.env.CLAUDE_CONFIG_DIR, "projects") : null) ?? "";
|
|
23747
24254
|
const usersFile = opts.usersFile ?? USERS_FILE;
|
|
23748
24255
|
const accountId = opts.accountId ?? resolveAccount()?.accountId ?? null;
|
|
23749
24256
|
const resolveName = opts.resolveName ?? defaultResolveName;
|
|
@@ -23935,7 +24442,7 @@ var InboundHub = class {
|
|
|
23935
24442
|
};
|
|
23936
24443
|
|
|
23937
24444
|
// app/lib/whatsapp/gateway/wa-gateway.ts
|
|
23938
|
-
var
|
|
24445
|
+
var import_dist6 = __toESM(require_dist(), 1);
|
|
23939
24446
|
|
|
23940
24447
|
// node_modules/hono/dist/utils/stream.js
|
|
23941
24448
|
var StreamingApi = class {
|
|
@@ -24088,8 +24595,8 @@ var streamSSE = (c, cb, onError) => {
|
|
|
24088
24595
|
|
|
24089
24596
|
// app/lib/whatsapp/gateway/routes.ts
|
|
24090
24597
|
function createWaChannelRoutes(deps) {
|
|
24091
|
-
const
|
|
24092
|
-
|
|
24598
|
+
const app64 = new Hono();
|
|
24599
|
+
app64.get("/wa-channel/inbound", (c) => {
|
|
24093
24600
|
const senderId = c.req.query("senderId");
|
|
24094
24601
|
if (!senderId) return c.json({ error: "senderId required" }, 400);
|
|
24095
24602
|
return streamSSE(c, async (stream2) => {
|
|
@@ -24107,7 +24614,7 @@ function createWaChannelRoutes(deps) {
|
|
|
24107
24614
|
}
|
|
24108
24615
|
});
|
|
24109
24616
|
});
|
|
24110
|
-
|
|
24617
|
+
app64.post("/wa-channel/reply", async (c) => {
|
|
24111
24618
|
const body = await c.req.json().catch(() => null);
|
|
24112
24619
|
const senderId = body?.senderId;
|
|
24113
24620
|
const text = body?.text;
|
|
@@ -24128,7 +24635,7 @@ function createWaChannelRoutes(deps) {
|
|
|
24128
24635
|
console.error(`[whatsapp-native] op=reply-dispatch senderId=${senderId} bytes=${bytes}`);
|
|
24129
24636
|
return c.json({ ok: true });
|
|
24130
24637
|
});
|
|
24131
|
-
|
|
24638
|
+
app64.post("/wa-channel/reply-document", async (c) => {
|
|
24132
24639
|
const body = await c.req.json().catch(() => null);
|
|
24133
24640
|
const senderId = body?.senderId;
|
|
24134
24641
|
const files = body?.files;
|
|
@@ -24167,7 +24674,7 @@ function createWaChannelRoutes(deps) {
|
|
|
24167
24674
|
}
|
|
24168
24675
|
return c.json({ ok: true, results });
|
|
24169
24676
|
});
|
|
24170
|
-
|
|
24677
|
+
app64.post("/wa-channel/ready", async (c) => {
|
|
24171
24678
|
const body = await c.req.json().catch(() => null);
|
|
24172
24679
|
const senderId = body?.senderId;
|
|
24173
24680
|
if (typeof senderId !== "string") {
|
|
@@ -24176,7 +24683,7 @@ function createWaChannelRoutes(deps) {
|
|
|
24176
24683
|
deps.onReady?.(senderId);
|
|
24177
24684
|
return c.json({ ok: true });
|
|
24178
24685
|
});
|
|
24179
|
-
|
|
24686
|
+
app64.post("/wa-channel/received", async (c) => {
|
|
24180
24687
|
const body = await c.req.json().catch(() => null);
|
|
24181
24688
|
const senderId = body?.senderId;
|
|
24182
24689
|
const waMessageId = body?.waMessageId;
|
|
@@ -24186,7 +24693,7 @@ function createWaChannelRoutes(deps) {
|
|
|
24186
24693
|
deps.onReceived?.(senderId, waMessageId);
|
|
24187
24694
|
return c.json({ ok: true });
|
|
24188
24695
|
});
|
|
24189
|
-
|
|
24696
|
+
app64.post("/wa-channel/turn-end", async (c) => {
|
|
24190
24697
|
const body = await c.req.json().catch(() => null);
|
|
24191
24698
|
const senderId = body?.senderId;
|
|
24192
24699
|
const sessionId = body?.sessionId;
|
|
@@ -24219,7 +24726,7 @@ function createWaChannelRoutes(deps) {
|
|
|
24219
24726
|
console.error(`[whatsapp-native] op=turn-end sessionId=${sid} replied=no delivered=none`);
|
|
24220
24727
|
return c.json({ ok: true, delivered: "none" });
|
|
24221
24728
|
});
|
|
24222
|
-
return
|
|
24729
|
+
return app64;
|
|
24223
24730
|
}
|
|
24224
24731
|
|
|
24225
24732
|
// app/lib/whatsapp/gateway/wa-gateway.ts
|
|
@@ -24321,7 +24828,7 @@ var WaGateway = class {
|
|
|
24321
24828
|
const injected = res.block ? (res.block.match(/^- /gm) ?? []).length : 0;
|
|
24322
24829
|
const owner8 = res.ownerUserId ? res.ownerUserId.slice(0, 8) : "-";
|
|
24323
24830
|
console.error(
|
|
24324
|
-
`[preference-inject] op=inject channel=wa accountId=${input.effectiveAccountId} injected=${injected} owner=${owner8} source=${res.source} capped=${injected >=
|
|
24831
|
+
`[preference-inject] op=inject channel=wa accountId=${input.effectiveAccountId} injected=${injected} owner=${owner8} source=${res.source} capped=${injected >= import_dist6.INJECTION_RULE_CAP}`
|
|
24325
24832
|
);
|
|
24326
24833
|
}
|
|
24327
24834
|
this.hub.deliver(
|
|
@@ -24594,12 +25101,12 @@ var InboundHub2 = class {
|
|
|
24594
25101
|
};
|
|
24595
25102
|
|
|
24596
25103
|
// app/lib/webchat/gateway/webchat-gateway.ts
|
|
24597
|
-
var
|
|
25104
|
+
var import_dist7 = __toESM(require_dist(), 1);
|
|
24598
25105
|
|
|
24599
25106
|
// app/lib/webchat/gateway/routes.ts
|
|
24600
25107
|
function createWebchatChannelRoutes(deps) {
|
|
24601
|
-
const
|
|
24602
|
-
|
|
25108
|
+
const app64 = new Hono();
|
|
25109
|
+
app64.get("/webchat-channel/inbound", (c) => {
|
|
24603
25110
|
const key = c.req.query("key");
|
|
24604
25111
|
if (!key) return c.json({ error: "key required" }, 400);
|
|
24605
25112
|
return streamSSE(c, async (stream2) => {
|
|
@@ -24617,7 +25124,7 @@ function createWebchatChannelRoutes(deps) {
|
|
|
24617
25124
|
}
|
|
24618
25125
|
});
|
|
24619
25126
|
});
|
|
24620
|
-
|
|
25127
|
+
app64.post("/webchat-channel/reply", async (c) => {
|
|
24621
25128
|
const body = await c.req.json().catch(() => null);
|
|
24622
25129
|
const key = body?.key;
|
|
24623
25130
|
const text = body?.text;
|
|
@@ -24627,7 +25134,7 @@ function createWebchatChannelRoutes(deps) {
|
|
|
24627
25134
|
deps.onReply?.(key, text);
|
|
24628
25135
|
return c.json({ ok: true });
|
|
24629
25136
|
});
|
|
24630
|
-
|
|
25137
|
+
app64.post("/webchat-channel/connector-auth", async (c) => {
|
|
24631
25138
|
const body = await c.req.json().catch(() => null);
|
|
24632
25139
|
const key = body?.key;
|
|
24633
25140
|
const sessionId = body?.sessionId;
|
|
@@ -24640,7 +25147,7 @@ function createWebchatChannelRoutes(deps) {
|
|
|
24640
25147
|
const result = await deps.onConnectorAuth({ key, sessionId, name, completed });
|
|
24641
25148
|
return c.json(result);
|
|
24642
25149
|
});
|
|
24643
|
-
|
|
25150
|
+
app64.post("/webchat-channel/ready", async (c) => {
|
|
24644
25151
|
const body = await c.req.json().catch(() => null);
|
|
24645
25152
|
const key = body?.key;
|
|
24646
25153
|
if (typeof key !== "string") {
|
|
@@ -24649,7 +25156,7 @@ function createWebchatChannelRoutes(deps) {
|
|
|
24649
25156
|
deps.onReady?.(key);
|
|
24650
25157
|
return c.json({ ok: true });
|
|
24651
25158
|
});
|
|
24652
|
-
|
|
25159
|
+
app64.post("/webchat-channel/permission-request", async (c) => {
|
|
24653
25160
|
const body = await c.req.json().catch(() => null);
|
|
24654
25161
|
const key = body?.key;
|
|
24655
25162
|
const requestId = body?.request_id;
|
|
@@ -24663,7 +25170,7 @@ function createWebchatChannelRoutes(deps) {
|
|
|
24663
25170
|
const verdict = await deps.awaitPermissionVerdict({ key, requestId, toolName, description, inputPreview });
|
|
24664
25171
|
return c.json(verdict);
|
|
24665
25172
|
});
|
|
24666
|
-
|
|
25173
|
+
app64.post("/webchat-channel/received", async (c) => {
|
|
24667
25174
|
const body = await c.req.json().catch(() => null);
|
|
24668
25175
|
const key = body?.key;
|
|
24669
25176
|
const messageId = body?.messageId;
|
|
@@ -24673,7 +25180,7 @@ function createWebchatChannelRoutes(deps) {
|
|
|
24673
25180
|
deps.onReceived?.(key, messageId);
|
|
24674
25181
|
return c.json({ ok: true });
|
|
24675
25182
|
});
|
|
24676
|
-
|
|
25183
|
+
app64.post("/webchat-channel/turn-end", async (c) => {
|
|
24677
25184
|
const body = await c.req.json().catch(() => null);
|
|
24678
25185
|
const key = body?.key;
|
|
24679
25186
|
const sessionId = body?.sessionId;
|
|
@@ -24696,7 +25203,7 @@ function createWebchatChannelRoutes(deps) {
|
|
|
24696
25203
|
console.error(`[webchat-native] op=turn-end channel=webchat key=${k} sessionId=${sid} replied=no delivered=none`);
|
|
24697
25204
|
return c.json({ ok: true, delivered: "none" });
|
|
24698
25205
|
});
|
|
24699
|
-
return
|
|
25206
|
+
return app64;
|
|
24700
25207
|
}
|
|
24701
25208
|
|
|
24702
25209
|
// app/lib/webchat/gateway/webchat-gateway.ts
|
|
@@ -25042,7 +25549,7 @@ var WebchatGateway = class _WebchatGateway {
|
|
|
25042
25549
|
const injected = res.block ? (res.block.match(/^- /gm) ?? []).length : 0;
|
|
25043
25550
|
const owner8 = res.ownerUserId ? res.ownerUserId.slice(0, 8) : "-";
|
|
25044
25551
|
console.error(
|
|
25045
|
-
`[preference-inject] op=inject channel=web accountId=${input.accountId} injected=${injected} owner=${owner8} source=${res.source} capped=${injected >=
|
|
25552
|
+
`[preference-inject] op=inject channel=web accountId=${input.accountId} injected=${injected} owner=${owner8} source=${res.source} capped=${injected >= import_dist7.INJECTION_RULE_CAP}`
|
|
25046
25553
|
);
|
|
25047
25554
|
}
|
|
25048
25555
|
this.hub.deliver(
|
|
@@ -25411,14 +25918,14 @@ function makeFileDelivery(opts) {
|
|
|
25411
25918
|
}
|
|
25412
25919
|
|
|
25413
25920
|
// app/lib/webchat/file-delivery.ts
|
|
25414
|
-
var
|
|
25921
|
+
var TAG46 = "[webchat-adaptor]";
|
|
25415
25922
|
function platformRoot2() {
|
|
25416
25923
|
return process.env.MAXY_PLATFORM_ROOT || "";
|
|
25417
25924
|
}
|
|
25418
25925
|
function makeWebchatSendFile(entry) {
|
|
25419
25926
|
return async (filePath) => {
|
|
25420
25927
|
if (!entry.accountId) {
|
|
25421
|
-
console.error(`${
|
|
25928
|
+
console.error(`${TAG46} file-delivery reject reason=no-account sender=${entry.senderId}`);
|
|
25422
25929
|
return { ok: false, error: "no-account" };
|
|
25423
25930
|
}
|
|
25424
25931
|
const accountDir = resolve32(platformRoot2(), "..", "data/accounts", entry.accountId);
|
|
@@ -25426,14 +25933,14 @@ function makeWebchatSendFile(entry) {
|
|
|
25426
25933
|
const resolved = realpathSync8(filePath);
|
|
25427
25934
|
const accountResolved = realpathSync8(accountDir);
|
|
25428
25935
|
if (!resolved.startsWith(accountResolved + "/")) {
|
|
25429
|
-
console.error(`${
|
|
25936
|
+
console.error(`${TAG46} file-delivery reject reason=outside_account_directory sender=${entry.senderId}`);
|
|
25430
25937
|
return { ok: false, error: "outside-account" };
|
|
25431
25938
|
}
|
|
25432
25939
|
return { ok: true };
|
|
25433
25940
|
} catch (err) {
|
|
25434
25941
|
const code = err.code;
|
|
25435
25942
|
console.error(
|
|
25436
|
-
`${
|
|
25943
|
+
`${TAG46} file-delivery reject reason=${code === "ENOENT" ? "not-found" : "path-error"} sender=${entry.senderId}`
|
|
25437
25944
|
);
|
|
25438
25945
|
return { ok: false, error: code === "ENOENT" ? "not-found" : "path-error" };
|
|
25439
25946
|
}
|
|
@@ -25442,7 +25949,7 @@ function makeWebchatSendFile(entry) {
|
|
|
25442
25949
|
function makeWebchatFileDelivery(entry) {
|
|
25443
25950
|
return makeFileDelivery({
|
|
25444
25951
|
entry,
|
|
25445
|
-
tag:
|
|
25952
|
+
tag: TAG46,
|
|
25446
25953
|
channel: "webchat",
|
|
25447
25954
|
sendFile: makeWebchatSendFile(entry),
|
|
25448
25955
|
deferUntilVerdict: true
|
|
@@ -25504,7 +26011,7 @@ function buildPublicWebchatSpawnRequest(input) {
|
|
|
25504
26011
|
}
|
|
25505
26012
|
|
|
25506
26013
|
// app/lib/whatsapp/inbound/file-delivery-bridge.ts
|
|
25507
|
-
var
|
|
26014
|
+
var TAG47 = "[whatsapp-adaptor]";
|
|
25508
26015
|
var SEND_USER_FILE2 = "SendUserFile";
|
|
25509
26016
|
var WHATSAPP_SEND_DOCUMENT = "whatsapp-send-document";
|
|
25510
26017
|
function platformRoot3() {
|
|
@@ -25522,7 +26029,7 @@ function makeWhatsAppSendFile(entry, maxyAccountId) {
|
|
|
25522
26029
|
});
|
|
25523
26030
|
if (result.ok) return { ok: true };
|
|
25524
26031
|
console.error(
|
|
25525
|
-
`${
|
|
26032
|
+
`${TAG47} file-delivery reject reason=send-failed sender=${entry.senderId} status=${result.status} message=${result.error}`
|
|
25526
26033
|
);
|
|
25527
26034
|
return { ok: false, error: result.error };
|
|
25528
26035
|
};
|
|
@@ -25530,7 +26037,7 @@ function makeWhatsAppSendFile(entry, maxyAccountId) {
|
|
|
25530
26037
|
function makeWhatsAppFileDelivery(entry, maxyAccountId) {
|
|
25531
26038
|
const shared = makeFileDelivery({
|
|
25532
26039
|
entry,
|
|
25533
|
-
tag:
|
|
26040
|
+
tag: TAG47,
|
|
25534
26041
|
channel: "whatsapp",
|
|
25535
26042
|
sendFile: makeWhatsAppSendFile(entry, maxyAccountId)
|
|
25536
26043
|
});
|
|
@@ -25565,7 +26072,7 @@ function makeWhatsAppFileDelivery(entry, maxyAccountId) {
|
|
|
25565
26072
|
if (!delivered) {
|
|
25566
26073
|
const fileField = call.filePath !== void 0 ? ` file=${call.filePath}` : "";
|
|
25567
26074
|
console.error(
|
|
25568
|
-
`${
|
|
26075
|
+
`${TAG47} file-delivery-unreconciled sender=${entry.senderId} sessionId=${sid} tool=${WHATSAPP_SEND_DOCUMENT}${fileField}`
|
|
25569
26076
|
);
|
|
25570
26077
|
}
|
|
25571
26078
|
}
|
|
@@ -25747,12 +26254,12 @@ var InboundHub3 = class {
|
|
|
25747
26254
|
};
|
|
25748
26255
|
|
|
25749
26256
|
// app/lib/telegram/gateway/telegram-gateway.ts
|
|
25750
|
-
var
|
|
26257
|
+
var import_dist8 = __toESM(require_dist(), 1);
|
|
25751
26258
|
|
|
25752
26259
|
// app/lib/telegram/gateway/routes.ts
|
|
25753
26260
|
function createTelegramChannelRoutes(deps) {
|
|
25754
|
-
const
|
|
25755
|
-
|
|
26261
|
+
const app64 = new Hono();
|
|
26262
|
+
app64.get("/tg-channel/inbound", (c) => {
|
|
25756
26263
|
const key = c.req.query("key");
|
|
25757
26264
|
if (!key) return c.json({ error: "key required" }, 400);
|
|
25758
26265
|
return streamSSE(c, async (stream2) => {
|
|
@@ -25770,7 +26277,7 @@ function createTelegramChannelRoutes(deps) {
|
|
|
25770
26277
|
}
|
|
25771
26278
|
});
|
|
25772
26279
|
});
|
|
25773
|
-
|
|
26280
|
+
app64.post("/tg-channel/reply", async (c) => {
|
|
25774
26281
|
const body = await c.req.json().catch(() => null);
|
|
25775
26282
|
const key = body?.key;
|
|
25776
26283
|
const text = body?.text;
|
|
@@ -25786,7 +26293,7 @@ function createTelegramChannelRoutes(deps) {
|
|
|
25786
26293
|
console.error(`[telegram-native] op=reply key=${key} bytes=${Buffer.byteLength(text, "utf8")}`);
|
|
25787
26294
|
return c.json({ ok: true });
|
|
25788
26295
|
});
|
|
25789
|
-
|
|
26296
|
+
app64.post("/tg-channel/ready", async (c) => {
|
|
25790
26297
|
const body = await c.req.json().catch(() => null);
|
|
25791
26298
|
const key = body?.key;
|
|
25792
26299
|
if (typeof key !== "string") {
|
|
@@ -25795,7 +26302,7 @@ function createTelegramChannelRoutes(deps) {
|
|
|
25795
26302
|
deps.onReady?.(key);
|
|
25796
26303
|
return c.json({ ok: true });
|
|
25797
26304
|
});
|
|
25798
|
-
|
|
26305
|
+
app64.post("/tg-channel/received", async (c) => {
|
|
25799
26306
|
const body = await c.req.json().catch(() => null);
|
|
25800
26307
|
const key = body?.key;
|
|
25801
26308
|
const messageId = body?.messageId;
|
|
@@ -25805,7 +26312,7 @@ function createTelegramChannelRoutes(deps) {
|
|
|
25805
26312
|
deps.onReceived?.(key, messageId);
|
|
25806
26313
|
return c.json({ ok: true });
|
|
25807
26314
|
});
|
|
25808
|
-
|
|
26315
|
+
app64.post("/tg-channel/turn-end", async (c) => {
|
|
25809
26316
|
const body = await c.req.json().catch(() => null);
|
|
25810
26317
|
const key = body?.key;
|
|
25811
26318
|
const sessionId = body?.sessionId;
|
|
@@ -25838,7 +26345,7 @@ function createTelegramChannelRoutes(deps) {
|
|
|
25838
26345
|
console.error(`[telegram-native] op=turn-end key=${key} sessionId=${sid} replied=no delivered=none`);
|
|
25839
26346
|
return c.json({ ok: true, delivered: "none" });
|
|
25840
26347
|
});
|
|
25841
|
-
return
|
|
26348
|
+
return app64;
|
|
25842
26349
|
}
|
|
25843
26350
|
|
|
25844
26351
|
// app/lib/telegram/gateway/telegram-gateway.ts
|
|
@@ -25903,7 +26410,7 @@ var TelegramGateway = class {
|
|
|
25903
26410
|
const injected = res.block ? (res.block.match(/^- /gm) ?? []).length : 0;
|
|
25904
26411
|
const owner8 = res.ownerUserId ? res.ownerUserId.slice(0, 8) : "-";
|
|
25905
26412
|
console.error(
|
|
25906
|
-
`[preference-inject] op=inject channel=tg accountId=${input.accountId} injected=${injected} owner=${owner8} source=${res.source} capped=${injected >=
|
|
26413
|
+
`[preference-inject] op=inject channel=tg accountId=${input.accountId} injected=${injected} owner=${owner8} source=${res.source} capped=${injected >= import_dist8.INJECTION_RULE_CAP}`
|
|
25907
26414
|
);
|
|
25908
26415
|
}
|
|
25909
26416
|
this.hub.deliver(
|
|
@@ -25969,7 +26476,7 @@ function buildTelegramSpawnRequest(input) {
|
|
|
25969
26476
|
import { realpathSync as realpathSync9 } from "fs";
|
|
25970
26477
|
import { readFile as readFile7, stat as stat7 } from "fs/promises";
|
|
25971
26478
|
import { resolve as resolve33, basename as basename11 } from "path";
|
|
25972
|
-
var
|
|
26479
|
+
var TAG48 = "[telegram:outbound]";
|
|
25973
26480
|
var TELEGRAM_DOCUMENT_MAX_BYTES = 50 * 1024 * 1024;
|
|
25974
26481
|
async function sendTelegramDocument(input) {
|
|
25975
26482
|
const { botToken, chatId, filePath, caption, maxyAccountId, platformRoot: platformRoot5 } = input;
|
|
@@ -25985,16 +26492,16 @@ async function sendTelegramDocument(input) {
|
|
|
25985
26492
|
resolvedPath = realpathSync9(filePath);
|
|
25986
26493
|
const accountResolved = realpathSync9(accountDir);
|
|
25987
26494
|
if (!resolvedPath.startsWith(accountResolved + "/")) {
|
|
25988
|
-
console.error(`${
|
|
26495
|
+
console.error(`${TAG48} document REJECTED reason=outside_account_directory maxyAccountId=${maxyAccountId}`);
|
|
25989
26496
|
return { ok: false, status: 403, error: "Access denied: file is outside the account directory" };
|
|
25990
26497
|
}
|
|
25991
26498
|
} catch (err) {
|
|
25992
26499
|
const code = err.code;
|
|
25993
26500
|
if (code === "ENOENT") {
|
|
25994
|
-
console.error(`${
|
|
26501
|
+
console.error(`${TAG48} document ENOENT path=${filePath}`);
|
|
25995
26502
|
return { ok: false, status: 404, error: `File not found: ${filePath}` };
|
|
25996
26503
|
}
|
|
25997
|
-
console.error(`${
|
|
26504
|
+
console.error(`${TAG48} document path error: ${String(err)}`);
|
|
25998
26505
|
return { ok: false, status: 500, error: String(err) };
|
|
25999
26506
|
}
|
|
26000
26507
|
const fileStat = await stat7(resolvedPath);
|
|
@@ -26027,13 +26534,13 @@ async function sendTelegramDocument(input) {
|
|
|
26027
26534
|
error = e instanceof Error ? e.message : String(e);
|
|
26028
26535
|
}
|
|
26029
26536
|
console.error(
|
|
26030
|
-
`${
|
|
26537
|
+
`${TAG48} sent document to=${chatId} file=${filename} bytes=${fileStat.size} ok=${ok}` + (messageId !== void 0 ? ` id=${messageId}` : "")
|
|
26031
26538
|
);
|
|
26032
26539
|
return ok ? { ok: true, messageId } : { ok: false, status: 500, error };
|
|
26033
26540
|
}
|
|
26034
26541
|
|
|
26035
26542
|
// app/lib/telegram/outbound/file-delivery.ts
|
|
26036
|
-
var
|
|
26543
|
+
var TAG49 = "[telegram:outbound]";
|
|
26037
26544
|
function platformRoot4() {
|
|
26038
26545
|
return process.env.MAXY_PLATFORM_ROOT || "";
|
|
26039
26546
|
}
|
|
@@ -26045,11 +26552,11 @@ function makeTelegramSendFile(entry) {
|
|
|
26045
26552
|
botToken = (entry.role === "admin" ? tg?.adminBotToken : tg?.publicBotToken) ?? null;
|
|
26046
26553
|
}
|
|
26047
26554
|
if (!botToken) {
|
|
26048
|
-
console.error(`${
|
|
26555
|
+
console.error(`${TAG49} file-delivery reject reason=no-bot-token sender=${entry.senderId} role=${entry.role}`);
|
|
26049
26556
|
return { ok: false, error: "no-bot-token" };
|
|
26050
26557
|
}
|
|
26051
26558
|
if (entry.replyTarget == null) {
|
|
26052
|
-
console.error(`${
|
|
26559
|
+
console.error(`${TAG49} file-delivery reject reason=no-reply-target sender=${entry.senderId} role=${entry.role}`);
|
|
26053
26560
|
return { ok: false, error: "no-reply-target" };
|
|
26054
26561
|
}
|
|
26055
26562
|
const result = await sendTelegramDocument({
|
|
@@ -26066,7 +26573,7 @@ function makeTelegramSendFile(entry) {
|
|
|
26066
26573
|
function makeTelegramFileDelivery(entry) {
|
|
26067
26574
|
return makeFileDelivery({
|
|
26068
26575
|
entry,
|
|
26069
|
-
tag:
|
|
26576
|
+
tag: TAG49,
|
|
26070
26577
|
channel: "telegram",
|
|
26071
26578
|
sendFile: makeTelegramSendFile(entry)
|
|
26072
26579
|
});
|
|
@@ -26106,17 +26613,17 @@ function startTelegramNativeFileFollower(input) {
|
|
|
26106
26613
|
}
|
|
26107
26614
|
|
|
26108
26615
|
// server/telegram-descriptor.ts
|
|
26109
|
-
import { resolve as resolve34, join as
|
|
26616
|
+
import { resolve as resolve34, join as join38 } from "path";
|
|
26110
26617
|
function telegramGatewayUrl() {
|
|
26111
26618
|
return `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`;
|
|
26112
26619
|
}
|
|
26113
26620
|
function telegramServerPath() {
|
|
26114
|
-
return process.env.MAXY_TELEGRAM_CHANNEL_SERVER_PATH ?? resolve34(process.env.MAXY_PLATFORM_ROOT ??
|
|
26621
|
+
return process.env.MAXY_TELEGRAM_CHANNEL_SERVER_PATH ?? resolve34(process.env.MAXY_PLATFORM_ROOT ?? join38(__dirname, ".."), "services/telegram-channel/dist/server.js");
|
|
26115
26622
|
}
|
|
26116
26623
|
|
|
26117
26624
|
// app/lib/channel-pty-bridge/public-session-end-review.ts
|
|
26118
26625
|
import { randomUUID as randomUUID16 } from "crypto";
|
|
26119
|
-
var
|
|
26626
|
+
var TAG50 = "[public-session-review]";
|
|
26120
26627
|
var CONSUMED_CAP = 500;
|
|
26121
26628
|
var consumed = /* @__PURE__ */ new Set();
|
|
26122
26629
|
function consumeOnce(sessionId) {
|
|
@@ -26143,7 +26650,7 @@ async function fetchJsonl(sessionId) {
|
|
|
26143
26650
|
return await res.text();
|
|
26144
26651
|
} catch (err) {
|
|
26145
26652
|
console.error(
|
|
26146
|
-
`${
|
|
26653
|
+
`${TAG50} jsonl-fetch-failed sessionId=${sessionId} err="${err instanceof Error ? err.message : String(err)}"`
|
|
26147
26654
|
);
|
|
26148
26655
|
return null;
|
|
26149
26656
|
}
|
|
@@ -26167,7 +26674,7 @@ async function fetchPriorWrites(sliceToken, accountId) {
|
|
|
26167
26674
|
const res = await fetch(url);
|
|
26168
26675
|
if (!res.ok) {
|
|
26169
26676
|
console.error(
|
|
26170
|
-
`${
|
|
26677
|
+
`${TAG50} prior-writes-fetch-failed sliceToken=${sliceToken.slice(0, 8)} status=${res.status}`
|
|
26171
26678
|
);
|
|
26172
26679
|
return [];
|
|
26173
26680
|
}
|
|
@@ -26175,7 +26682,7 @@ async function fetchPriorWrites(sliceToken, accountId) {
|
|
|
26175
26682
|
return Array.isArray(body.writes) ? body.writes : [];
|
|
26176
26683
|
} catch (err) {
|
|
26177
26684
|
console.error(
|
|
26178
|
-
`${
|
|
26685
|
+
`${TAG50} prior-writes-fetch-threw sliceToken=${sliceToken.slice(0, 8)} err="${err instanceof Error ? err.message : String(err)}"`
|
|
26179
26686
|
);
|
|
26180
26687
|
return [];
|
|
26181
26688
|
}
|
|
@@ -26204,7 +26711,7 @@ function composeInitialMessage(input) {
|
|
|
26204
26711
|
}
|
|
26205
26712
|
async function dispatchReviewer(input, initialMessage) {
|
|
26206
26713
|
const sessionId = randomUUID16();
|
|
26207
|
-
console.log(`${
|
|
26714
|
+
console.log(`${TAG50} route target=rc-spawn sessionId=${sessionId.slice(0, 8)} sourceSession=${input.sessionId.slice(0, 8)}`);
|
|
26208
26715
|
const spawned = await managerRcSpawn({
|
|
26209
26716
|
sessionId,
|
|
26210
26717
|
initialMessage,
|
|
@@ -26224,21 +26731,21 @@ async function firePublicSessionEndReview(input) {
|
|
|
26224
26731
|
const dispatchedAt = Date.now();
|
|
26225
26732
|
if (consumed.has(input.sessionId)) {
|
|
26226
26733
|
console.log(
|
|
26227
|
-
`${
|
|
26734
|
+
`${TAG50} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-already-reviewed`
|
|
26228
26735
|
);
|
|
26229
26736
|
return;
|
|
26230
26737
|
}
|
|
26231
26738
|
const jsonl = await fetchJsonl(input.sessionId);
|
|
26232
26739
|
if (!jsonl) {
|
|
26233
26740
|
console.log(
|
|
26234
|
-
`${
|
|
26741
|
+
`${TAG50} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-jsonl-missing`
|
|
26235
26742
|
);
|
|
26236
26743
|
return;
|
|
26237
26744
|
}
|
|
26238
26745
|
const operatorTurns = countOperatorTurns(jsonl);
|
|
26239
26746
|
if (operatorTurns === 0) {
|
|
26240
26747
|
console.log(
|
|
26241
|
-
`${
|
|
26748
|
+
`${TAG50} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-no-turns`
|
|
26242
26749
|
);
|
|
26243
26750
|
return;
|
|
26244
26751
|
}
|
|
@@ -26252,28 +26759,28 @@ async function firePublicSessionEndReview(input) {
|
|
|
26252
26759
|
});
|
|
26253
26760
|
if (!consumeOnce(input.sessionId)) {
|
|
26254
26761
|
console.log(
|
|
26255
|
-
`${
|
|
26762
|
+
`${TAG50} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-already-reviewed`
|
|
26256
26763
|
);
|
|
26257
26764
|
return;
|
|
26258
26765
|
}
|
|
26259
26766
|
const dispatched = await dispatchReviewer(input, initialMessage);
|
|
26260
26767
|
if (!dispatched.ok) {
|
|
26261
26768
|
console.error(
|
|
26262
|
-
`${
|
|
26769
|
+
`${TAG50} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-spawn-failed reason=${dispatched.reason}`
|
|
26263
26770
|
);
|
|
26264
26771
|
return;
|
|
26265
26772
|
}
|
|
26266
26773
|
console.log(
|
|
26267
|
-
`${
|
|
26774
|
+
`${TAG50} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=dispatched managerSessionId=${dispatched.managerSessionId} operatorTurns=${operatorTurns} priorWrites=${priorWrites.length} ms=${Date.now() - dispatchedAt}`
|
|
26268
26775
|
);
|
|
26269
26776
|
}
|
|
26270
26777
|
|
|
26271
26778
|
// app/lib/whatsapp/inbound/resolve-client-graph-owner.ts
|
|
26272
|
-
var
|
|
26779
|
+
var import_dist9 = __toESM(require_dist(), 1);
|
|
26273
26780
|
async function resolveClientOwnerUserId(accountId, deps = {}) {
|
|
26274
26781
|
const listAccounts = deps.listAccounts ?? listValidAccounts;
|
|
26275
26782
|
const getSession4 = deps.getSession ?? getSession;
|
|
26276
|
-
const resolveOwner2 = deps.resolveOwner ??
|
|
26783
|
+
const resolveOwner2 = deps.resolveOwner ?? import_dist9.resolveOwnerUserId;
|
|
26277
26784
|
const role = listAccounts().find((a) => a.accountId === accountId)?.config.role;
|
|
26278
26785
|
if (role !== "client") return null;
|
|
26279
26786
|
const session = getSession4();
|
|
@@ -26398,7 +26905,7 @@ function broadcastAdminShutdown(reason) {
|
|
|
26398
26905
|
|
|
26399
26906
|
// ../lib/entitlement/src/index.ts
|
|
26400
26907
|
import { createPublicKey, createHash as createHash6, verify as cryptoVerify } from "crypto";
|
|
26401
|
-
import { existsSync as
|
|
26908
|
+
import { existsSync as existsSync36, readFileSync as readFileSync38, statSync as statSync13 } from "fs";
|
|
26402
26909
|
import { resolve as resolve35 } from "path";
|
|
26403
26910
|
|
|
26404
26911
|
// ../lib/entitlement/src/canonicalize.ts
|
|
@@ -26447,7 +26954,7 @@ function resolveEntitlement(brand, account) {
|
|
|
26447
26954
|
return logResolved(implicitTrust(account), null);
|
|
26448
26955
|
}
|
|
26449
26956
|
const entitlementPath = resolve35(brand.configDir, "entitlement.json");
|
|
26450
|
-
if (!
|
|
26957
|
+
if (!existsSync36(entitlementPath)) {
|
|
26451
26958
|
return logResolved(anonymousFallback("missing"), { reason: "missing" });
|
|
26452
26959
|
}
|
|
26453
26960
|
const stat8 = statSync13(entitlementPath);
|
|
@@ -26462,7 +26969,7 @@ function resolveEntitlement(brand, account) {
|
|
|
26462
26969
|
function verifyAndResolve(brand, entitlementPath, account) {
|
|
26463
26970
|
let pubkeyPem;
|
|
26464
26971
|
try {
|
|
26465
|
-
pubkeyPem =
|
|
26972
|
+
pubkeyPem = readFileSync38(pubkeyPath(brand), "utf-8");
|
|
26466
26973
|
} catch (err) {
|
|
26467
26974
|
return logResolved(anonymousFallback("pubkey-missing"), {
|
|
26468
26975
|
reason: "pubkey-missing"
|
|
@@ -26476,7 +26983,7 @@ function verifyAndResolve(brand, entitlementPath, account) {
|
|
|
26476
26983
|
}
|
|
26477
26984
|
let envelope;
|
|
26478
26985
|
try {
|
|
26479
|
-
envelope = JSON.parse(
|
|
26986
|
+
envelope = JSON.parse(readFileSync38(entitlementPath, "utf-8"));
|
|
26480
26987
|
} catch {
|
|
26481
26988
|
return logResolved(anonymousFallback("malformed"), { reason: "malformed" });
|
|
26482
26989
|
}
|
|
@@ -26637,14 +27144,14 @@ function clientFrom(c) {
|
|
|
26637
27144
|
);
|
|
26638
27145
|
}
|
|
26639
27146
|
var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT || "";
|
|
26640
|
-
var BRAND_JSON_PATH = PLATFORM_ROOT8 ?
|
|
27147
|
+
var BRAND_JSON_PATH = PLATFORM_ROOT8 ? join39(PLATFORM_ROOT8, "config", "brand.json") : "";
|
|
26641
27148
|
var BRAND = { productName: "Maxy", hostname: "maxy", configDir: ".maxy", marketingUrl: "https://getmaxy.com" };
|
|
26642
|
-
if (BRAND_JSON_PATH && !
|
|
27149
|
+
if (BRAND_JSON_PATH && !existsSync37(BRAND_JSON_PATH)) {
|
|
26643
27150
|
console.error(`[brand] WARNING: brand.json not found at ${BRAND_JSON_PATH} \u2014 using Maxy defaults`);
|
|
26644
27151
|
}
|
|
26645
|
-
if (BRAND_JSON_PATH &&
|
|
27152
|
+
if (BRAND_JSON_PATH && existsSync37(BRAND_JSON_PATH)) {
|
|
26646
27153
|
try {
|
|
26647
|
-
const parsed = JSON.parse(
|
|
27154
|
+
const parsed = JSON.parse(readFileSync39(BRAND_JSON_PATH, "utf-8"));
|
|
26648
27155
|
BRAND = { ...BRAND, ...parsed };
|
|
26649
27156
|
} catch (err) {
|
|
26650
27157
|
console.error(`[brand] Failed to parse brand.json: ${err.message}`);
|
|
@@ -26676,11 +27183,11 @@ var brandLoginOpts = {
|
|
|
26676
27183
|
appleTouchIconPath: brandAppIcon512Path,
|
|
26677
27184
|
themeColor: BRAND.defaultColors?.primary
|
|
26678
27185
|
};
|
|
26679
|
-
var ALIAS_DOMAINS_PATH =
|
|
27186
|
+
var ALIAS_DOMAINS_PATH = join39(homedir4(), BRAND.configDir, "alias-domains.json");
|
|
26680
27187
|
function loadAliasDomains() {
|
|
26681
27188
|
try {
|
|
26682
|
-
if (!
|
|
26683
|
-
const parsed = JSON.parse(
|
|
27189
|
+
if (!existsSync37(ALIAS_DOMAINS_PATH)) return null;
|
|
27190
|
+
const parsed = JSON.parse(readFileSync39(ALIAS_DOMAINS_PATH, "utf-8"));
|
|
26684
27191
|
if (!Array.isArray(parsed)) {
|
|
26685
27192
|
console.error("[alias-domains] malformed alias-domains.json \u2014 expected array");
|
|
26686
27193
|
return null;
|
|
@@ -26704,14 +27211,14 @@ watchFile(ALIAS_DOMAINS_PATH, { interval: 2e3 }, () => {
|
|
|
26704
27211
|
function isPublicHost(host) {
|
|
26705
27212
|
return host.startsWith("public.") || aliasDomains.has(host);
|
|
26706
27213
|
}
|
|
26707
|
-
var
|
|
27214
|
+
var app63 = new Hono();
|
|
26708
27215
|
var nativeFileFollowers = /* @__PURE__ */ new Map();
|
|
26709
27216
|
var webchatFileFollowers = /* @__PURE__ */ new Map();
|
|
26710
27217
|
async function fetchAccountStandingRules(accountId) {
|
|
26711
27218
|
const session = getSession();
|
|
26712
27219
|
try {
|
|
26713
|
-
const res = await (0,
|
|
26714
|
-
return { block: (0,
|
|
27220
|
+
const res = await (0, import_dist10.resolveActiveRules)(session, accountId);
|
|
27221
|
+
return { block: (0, import_dist10.formatStandingRulesBlock)(res.rules), ownerUserId: res.ownerUserId, source: res.source };
|
|
26715
27222
|
} catch (err) {
|
|
26716
27223
|
console.error(
|
|
26717
27224
|
`[preference-inject] op=fetch-failed accountId=${accountId} error=${err instanceof Error ? err.message : String(err)}`
|
|
@@ -26744,7 +27251,7 @@ async function recordPassiveDispatch(input) {
|
|
|
26744
27251
|
var waGateway = new WaGateway({
|
|
26745
27252
|
fetchStandingRules: fetchAccountStandingRules,
|
|
26746
27253
|
gatewayUrl: `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`,
|
|
26747
|
-
serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve36(process.env.MAXY_PLATFORM_ROOT ??
|
|
27254
|
+
serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve36(process.env.MAXY_PLATFORM_ROOT ?? join39(__dirname, ".."), "services/whatsapp-channel/dist/server.js"),
|
|
26748
27255
|
// Task 751 / 1390 — file delivery on the native channel. `maxyAccountId` (the
|
|
26749
27256
|
// path-validation scope) is the sender's effective SESSION account, resolved
|
|
26750
27257
|
// once at the inbound gate and threaded here via the gateway's per-sender doc
|
|
@@ -26759,7 +27266,7 @@ var waGateway = new WaGateway({
|
|
|
26759
27266
|
caption,
|
|
26760
27267
|
accountId,
|
|
26761
27268
|
maxyAccountId,
|
|
26762
|
-
platformRoot: resolve36(process.env.MAXY_PLATFORM_ROOT ??
|
|
27269
|
+
platformRoot: resolve36(process.env.MAXY_PLATFORM_ROOT ?? join39(__dirname, ".."))
|
|
26763
27270
|
});
|
|
26764
27271
|
return result.ok ? { ok: true, messageId: result.messageId } : { ok: false, error: result.error };
|
|
26765
27272
|
},
|
|
@@ -26812,6 +27319,13 @@ var waGateway = new WaGateway({
|
|
|
26812
27319
|
console.error(`[whatsapp-native] op=account-manager-route senderId=${senderId} managesAccount=${managesAccount} effectiveAccount=${effectiveAccountId} source=gate`);
|
|
26813
27320
|
}
|
|
26814
27321
|
const req = buildWaSpawnRequest({ accountId: effectiveAccountId, senderId, role, personId, gatewayUrl, serverPath });
|
|
27322
|
+
await ensureSessionConversation({
|
|
27323
|
+
accountId: effectiveAccountId,
|
|
27324
|
+
sessionId: req.sessionId,
|
|
27325
|
+
channel: "whatsapp",
|
|
27326
|
+
channelAddress: senderId,
|
|
27327
|
+
agentType: role === "admin" ? "admin" : "public"
|
|
27328
|
+
});
|
|
26815
27329
|
let userId = role === "admin" ? resolveAdminUserId({ accountId: effectiveAccountId, senderPhone: senderId }) ?? (ownerSelfPhone ? resolveOwnerUserId(effectiveAccountId) ?? void 0 : void 0) : void 0;
|
|
26816
27330
|
let graphOwnerResolved = false;
|
|
26817
27331
|
if (role === "admin" && userId === void 0) {
|
|
@@ -26850,13 +27364,13 @@ var waGateway = new WaGateway({
|
|
|
26850
27364
|
nativeFileFollowers.set(senderId, ac);
|
|
26851
27365
|
}
|
|
26852
27366
|
});
|
|
26853
|
-
|
|
27367
|
+
app63.route("/", waGateway.routes());
|
|
26854
27368
|
waGateway.startSweeper();
|
|
26855
27369
|
function runDuplicateSenderAudit() {
|
|
26856
27370
|
try {
|
|
26857
27371
|
const configDir2 = process.env.CLAUDE_CONFIG_DIR;
|
|
26858
27372
|
if (!configDir2) return;
|
|
26859
|
-
const projectsRoot =
|
|
27373
|
+
const projectsRoot = join39(configDir2, "projects");
|
|
26860
27374
|
const records = [];
|
|
26861
27375
|
for (const { path: jsonlPath, isSubagent, archived } of enumerateJsonls(projectsRoot)) {
|
|
26862
27376
|
if (isSubagent || archived) continue;
|
|
@@ -26968,7 +27482,7 @@ var webchatGateway = new WebchatGateway({
|
|
|
26968
27482
|
firePublicSessionEndReview: (input) => firePublicSessionEndReview(input)
|
|
26969
27483
|
});
|
|
26970
27484
|
setWebchatGateway(webchatGateway);
|
|
26971
|
-
|
|
27485
|
+
app63.route("/", webchatGateway.routes());
|
|
26972
27486
|
webchatGateway.startSweeper();
|
|
26973
27487
|
webchatGateway.startPublicReaper();
|
|
26974
27488
|
var telegramFileFollowers = /* @__PURE__ */ new Map();
|
|
@@ -27002,7 +27516,7 @@ var telegramGateway = new TelegramGateway({
|
|
|
27002
27516
|
}
|
|
27003
27517
|
});
|
|
27004
27518
|
setTelegramGateway(telegramGateway);
|
|
27005
|
-
|
|
27519
|
+
app63.route("/", telegramGateway.routes());
|
|
27006
27520
|
telegramGateway.startSweeper();
|
|
27007
27521
|
var chatRoutes = createChatRoutes({
|
|
27008
27522
|
handleInbound: (input) => webchatGateway.handleInbound(input),
|
|
@@ -27036,19 +27550,19 @@ var scheduleInjectRoutes = createScheduleInjectRoutes({
|
|
|
27036
27550
|
return managed.account;
|
|
27037
27551
|
}
|
|
27038
27552
|
});
|
|
27039
|
-
|
|
27040
|
-
|
|
27553
|
+
app63.route("/api/channel/schedule-inject", scheduleInjectRoutes);
|
|
27554
|
+
app63.use("*", clientIpMiddleware);
|
|
27041
27555
|
function allowsSameOriginFraming(path3) {
|
|
27042
27556
|
return path3 === "/vnc-viewer.html" || path3.startsWith("/api/admin/attachment/") || path3.startsWith("/api/public-reader/attachment/") || path3 === "/api/admin/files/download";
|
|
27043
27557
|
}
|
|
27044
|
-
|
|
27558
|
+
app63.use("*", async (c, next) => {
|
|
27045
27559
|
await next();
|
|
27046
27560
|
c.header("X-Content-Type-Options", "nosniff");
|
|
27047
27561
|
c.header("Referrer-Policy", "strict-origin-when-cross-origin");
|
|
27048
27562
|
c.header("X-Frame-Options", allowsSameOriginFraming(c.req.path) ? "SAMEORIGIN" : "DENY");
|
|
27049
27563
|
});
|
|
27050
27564
|
var HTTP_LOG_PATHS = /* @__PURE__ */ new Set(["/vnc-viewer.html", "/vnc-popout.html"]);
|
|
27051
|
-
|
|
27565
|
+
app63.use("*", async (c, next) => {
|
|
27052
27566
|
if (!HTTP_LOG_PATHS.has(c.req.path)) {
|
|
27053
27567
|
await next();
|
|
27054
27568
|
return;
|
|
@@ -27066,7 +27580,7 @@ app62.use("*", async (c, next) => {
|
|
|
27066
27580
|
});
|
|
27067
27581
|
}
|
|
27068
27582
|
});
|
|
27069
|
-
|
|
27583
|
+
app63.use("*", async (c, next) => {
|
|
27070
27584
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
27071
27585
|
if (isOperatorHost(host, getOperatorDomains()) || !isPublicHost(host)) {
|
|
27072
27586
|
await next();
|
|
@@ -27104,7 +27618,7 @@ function resolveRemoteAuthOpts(c) {
|
|
|
27104
27618
|
return { ...brandLoginOpts, origin };
|
|
27105
27619
|
}
|
|
27106
27620
|
var MAX_LOGIN_BODY = 8 * 1024;
|
|
27107
|
-
|
|
27621
|
+
app63.post("/__remote-auth/login", async (c) => {
|
|
27108
27622
|
const client = clientFrom(c);
|
|
27109
27623
|
const clientIp = client.ip || "unknown";
|
|
27110
27624
|
if (!requestIsTlsTerminated(c)) {
|
|
@@ -27149,7 +27663,7 @@ app62.post("/__remote-auth/login", async (c) => {
|
|
|
27149
27663
|
}
|
|
27150
27664
|
});
|
|
27151
27665
|
});
|
|
27152
|
-
|
|
27666
|
+
app63.get("/__remote-auth/logout", (c) => {
|
|
27153
27667
|
const client = clientFrom(c);
|
|
27154
27668
|
const clientIp = client.ip || "unknown";
|
|
27155
27669
|
console.error(`[remote-auth] logout ip=${clientIp}`);
|
|
@@ -27162,7 +27676,7 @@ app62.get("/__remote-auth/logout", (c) => {
|
|
|
27162
27676
|
}
|
|
27163
27677
|
});
|
|
27164
27678
|
});
|
|
27165
|
-
|
|
27679
|
+
app63.post("/__remote-auth/change-password", async (c) => {
|
|
27166
27680
|
const client = clientFrom(c);
|
|
27167
27681
|
const clientIp = client.ip || "unknown";
|
|
27168
27682
|
const rateLimited = checkRateLimit(client);
|
|
@@ -27221,13 +27735,13 @@ app62.post("/__remote-auth/change-password", async (c) => {
|
|
|
27221
27735
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(c), mode: "change", changeError: "Failed to save password", redirect }), 200);
|
|
27222
27736
|
}
|
|
27223
27737
|
});
|
|
27224
|
-
|
|
27738
|
+
app63.get("/__remote-auth/setup", (c) => {
|
|
27225
27739
|
if (isRemoteAuthConfigured()) {
|
|
27226
27740
|
return c.redirect("/");
|
|
27227
27741
|
}
|
|
27228
27742
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(c), mode: "setup" }), 200);
|
|
27229
27743
|
});
|
|
27230
|
-
|
|
27744
|
+
app63.post("/__remote-auth/set-initial-password", async (c) => {
|
|
27231
27745
|
if (isRemoteAuthConfigured()) {
|
|
27232
27746
|
return c.redirect("/");
|
|
27233
27747
|
}
|
|
@@ -27265,10 +27779,10 @@ app62.post("/__remote-auth/set-initial-password", async (c) => {
|
|
|
27265
27779
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(c), mode: "setup", setupError: "Failed to save password. Please try again." }), 200);
|
|
27266
27780
|
}
|
|
27267
27781
|
});
|
|
27268
|
-
|
|
27782
|
+
app63.get("/api/remote-auth/status", (c) => {
|
|
27269
27783
|
return c.json({ configured: isRemoteAuthConfigured() });
|
|
27270
27784
|
});
|
|
27271
|
-
|
|
27785
|
+
app63.post("/api/remote-auth/set-password", async (c) => {
|
|
27272
27786
|
let body;
|
|
27273
27787
|
try {
|
|
27274
27788
|
body = await c.req.json();
|
|
@@ -27307,10 +27821,10 @@ app62.post("/api/remote-auth/set-password", async (c) => {
|
|
|
27307
27821
|
return c.json({ error: "Failed to save password" }, 500);
|
|
27308
27822
|
}
|
|
27309
27823
|
});
|
|
27310
|
-
|
|
27824
|
+
app63.route("/api/_client-error", client_error_default);
|
|
27311
27825
|
console.log("[client-error-route] mounted");
|
|
27312
27826
|
var PWA_PUBLIC_PATHS = /* @__PURE__ */ new Set(["/sw.js", ...PWA_SURFACES.map((s) => s.manifestPath)]);
|
|
27313
|
-
|
|
27827
|
+
app63.use("*", async (c, next) => {
|
|
27314
27828
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
27315
27829
|
const path3 = c.req.path;
|
|
27316
27830
|
if (path3 === "/favicon.ico" || path3.startsWith("/assets/") || path3.startsWith("/brand/") || // Public free/busy is read by the booking page (a separate Cloudflare Pages
|
|
@@ -27354,27 +27868,34 @@ app62.use("*", async (c, next) => {
|
|
|
27354
27868
|
}
|
|
27355
27869
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(c), redirect: path3 }), 200);
|
|
27356
27870
|
});
|
|
27357
|
-
|
|
27358
|
-
|
|
27359
|
-
|
|
27360
|
-
|
|
27361
|
-
|
|
27362
|
-
|
|
27363
|
-
|
|
27871
|
+
app63.route("/api/health", health_default);
|
|
27872
|
+
app63.route("/api/chat", chatRoutes);
|
|
27873
|
+
app63.route("/api/whatsapp", whatsapp_default);
|
|
27874
|
+
app63.route("/api/storage", storage_broker_default);
|
|
27875
|
+
app63.route("/api/whatsapp-reader", whatsapp_reader_default);
|
|
27876
|
+
app63.route("/api/public-reader", public_reader_default);
|
|
27877
|
+
app63.route("/api/webchat", createWebchatRoutes({
|
|
27364
27878
|
handleInbound: (input) => webchatGateway.handleInbound(input),
|
|
27365
27879
|
// Task 940 — the permission relay's pointer read + verdict write.
|
|
27366
27880
|
pendingPromptFor: (key) => webchatGateway.pendingPromptFor(key),
|
|
27367
27881
|
deliveryFailureFor: (key) => webchatGateway.deliveryFailureFor(key),
|
|
27368
27882
|
resolvePermissionVerdict: (key, requestId, behavior) => webchatGateway.resolvePermissionVerdict(key, requestId, behavior)
|
|
27369
27883
|
}));
|
|
27370
|
-
|
|
27371
|
-
|
|
27372
|
-
|
|
27373
|
-
|
|
27374
|
-
|
|
27375
|
-
|
|
27376
|
-
|
|
27377
|
-
|
|
27884
|
+
app63.route("/api/webchat/greeting", webchat_greeting_default);
|
|
27885
|
+
app63.route("/api/telegram", telegram_default);
|
|
27886
|
+
app63.route("/api/quickbooks", quickbooks_default);
|
|
27887
|
+
app63.route(
|
|
27888
|
+
"/api/google",
|
|
27889
|
+
createGoogleOAuthRoutes(
|
|
27890
|
+
resolve36(process.env.MAXY_PLATFORM_ROOT ?? join39(__dirname, "..")),
|
|
27891
|
+
resolve36(process.env.MAXY_PLATFORM_ROOT ?? join39(__dirname, ".."), "..", "data/accounts")
|
|
27892
|
+
)
|
|
27893
|
+
);
|
|
27894
|
+
app63.route("/api/onboarding", onboarding_default);
|
|
27895
|
+
app63.route("/api/admin", admin_default);
|
|
27896
|
+
app63.route("/api/access", access_default);
|
|
27897
|
+
app63.route("/api/session", session_default2);
|
|
27898
|
+
app63.route("/api/calendar", calendar_public_default);
|
|
27378
27899
|
var SAFE_SLUG_RE2 = /^[a-z][a-z0-9-]{2,49}$/;
|
|
27379
27900
|
var SAFE_FILENAME_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
|
|
27380
27901
|
var IMAGE_MIME = {
|
|
@@ -27386,7 +27907,7 @@ var IMAGE_MIME = {
|
|
|
27386
27907
|
".svg": "image/svg+xml",
|
|
27387
27908
|
".ico": "image/x-icon"
|
|
27388
27909
|
};
|
|
27389
|
-
|
|
27910
|
+
app63.get("/agent-assets/:slug/:filename", (c) => {
|
|
27390
27911
|
const slug = c.req.param("slug");
|
|
27391
27912
|
const filename = c.req.param("filename");
|
|
27392
27913
|
if (!SAFE_SLUG_RE2.test(slug)) {
|
|
@@ -27408,20 +27929,20 @@ app62.get("/agent-assets/:slug/:filename", (c) => {
|
|
|
27408
27929
|
console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
|
|
27409
27930
|
return c.text("Forbidden", 403);
|
|
27410
27931
|
}
|
|
27411
|
-
if (!
|
|
27932
|
+
if (!existsSync37(filePath)) {
|
|
27412
27933
|
console.error(`[agent-assets] serve slug=${slug} file=${filename} status=404`);
|
|
27413
27934
|
return c.text("Not found", 404);
|
|
27414
27935
|
}
|
|
27415
27936
|
const ext = "." + filename.split(".").pop()?.toLowerCase();
|
|
27416
27937
|
const contentType = IMAGE_MIME[ext] || "application/octet-stream";
|
|
27417
27938
|
console.log(`[agent-assets] serve slug=${slug} file=${filename} status=200`);
|
|
27418
|
-
const body =
|
|
27939
|
+
const body = readFileSync39(filePath);
|
|
27419
27940
|
return c.body(body, 200, {
|
|
27420
27941
|
"Content-Type": contentType,
|
|
27421
27942
|
"Cache-Control": "public, max-age=3600"
|
|
27422
27943
|
});
|
|
27423
27944
|
});
|
|
27424
|
-
|
|
27945
|
+
app63.get("/generated/:filename", (c) => {
|
|
27425
27946
|
const filename = c.req.param("filename");
|
|
27426
27947
|
if (!SAFE_FILENAME_RE.test(filename) || filename.includes("..")) {
|
|
27427
27948
|
console.error(`[generated] serve file=${filename} status=403`);
|
|
@@ -27438,29 +27959,29 @@ app62.get("/generated/:filename", (c) => {
|
|
|
27438
27959
|
console.error(`[generated] serve file=${filename} status=403`);
|
|
27439
27960
|
return c.text("Forbidden", 403);
|
|
27440
27961
|
}
|
|
27441
|
-
if (!
|
|
27962
|
+
if (!existsSync37(filePath)) {
|
|
27442
27963
|
console.error(`[generated] serve file=${filename} status=404`);
|
|
27443
27964
|
return c.text("Not found", 404);
|
|
27444
27965
|
}
|
|
27445
27966
|
const ext = "." + filename.split(".").pop()?.toLowerCase();
|
|
27446
27967
|
const contentType = IMAGE_MIME[ext] || "application/octet-stream";
|
|
27447
27968
|
console.log(`[generated] serve file=${filename} status=200`);
|
|
27448
|
-
const body =
|
|
27969
|
+
const body = readFileSync39(filePath);
|
|
27449
27970
|
return c.body(body, 200, {
|
|
27450
27971
|
"Content-Type": contentType,
|
|
27451
27972
|
"Cache-Control": "public, max-age=86400"
|
|
27452
27973
|
});
|
|
27453
27974
|
});
|
|
27454
|
-
|
|
27455
|
-
|
|
27456
|
-
|
|
27457
|
-
|
|
27975
|
+
app63.route("/sites", sites_default);
|
|
27976
|
+
app63.route("/listings", listings_default);
|
|
27977
|
+
app63.route("/v", visitor_event_default);
|
|
27978
|
+
app63.route("/v", visitor_consent_default);
|
|
27458
27979
|
var htmlCache = /* @__PURE__ */ new Map();
|
|
27459
27980
|
var brandLogoPath = "/brand/maxy-monochrome.png";
|
|
27460
27981
|
var brandIconPath = "/brand/maxy-monochrome.png";
|
|
27461
|
-
if (BRAND_JSON_PATH &&
|
|
27982
|
+
if (BRAND_JSON_PATH && existsSync37(BRAND_JSON_PATH)) {
|
|
27462
27983
|
try {
|
|
27463
|
-
const fullBrand = JSON.parse(
|
|
27984
|
+
const fullBrand = JSON.parse(readFileSync39(BRAND_JSON_PATH, "utf-8"));
|
|
27464
27985
|
if (fullBrand.assets?.logo) brandLogoPath = `/brand/${fullBrand.assets.logo}`;
|
|
27465
27986
|
brandIconPath = fullBrand.assets?.icon ? `/brand/${fullBrand.assets.icon}` : brandLogoPath;
|
|
27466
27987
|
} catch {
|
|
@@ -27487,11 +28008,11 @@ var brandScript = `<script>window.__BRAND__=${JSON.stringify({
|
|
|
27487
28008
|
var brandThemeColor = BRAND.defaultColors?.primary ?? "#000000";
|
|
27488
28009
|
var brandBackgroundColor = BRAND.defaultColors?.background ?? "#ffffff";
|
|
27489
28010
|
var brandAppIconsExist = [brandAppIcon192Path, brandAppIcon512Path, brandMaskableIconPath].every(
|
|
27490
|
-
(p) =>
|
|
28011
|
+
(p) => existsSync37(resolve36(process.cwd(), "public", p.replace(/^\//, "")))
|
|
27491
28012
|
);
|
|
27492
28013
|
var SW_SOURCE = (() => {
|
|
27493
28014
|
try {
|
|
27494
|
-
return
|
|
28015
|
+
return readFileSync39(resolve36(process.cwd(), "public", "sw.js"), "utf-8");
|
|
27495
28016
|
} catch {
|
|
27496
28017
|
return null;
|
|
27497
28018
|
}
|
|
@@ -27499,9 +28020,9 @@ var SW_SOURCE = (() => {
|
|
|
27499
28020
|
function readInstalledVersion() {
|
|
27500
28021
|
try {
|
|
27501
28022
|
if (!PLATFORM_ROOT8) return "unknown";
|
|
27502
|
-
const versionFile =
|
|
27503
|
-
if (!
|
|
27504
|
-
const content =
|
|
28023
|
+
const versionFile = join39(PLATFORM_ROOT8, "config", `.${BRAND.hostname}-version`);
|
|
28024
|
+
if (!existsSync37(versionFile)) return "unknown";
|
|
28025
|
+
const content = readFileSync39(versionFile, "utf-8").trim();
|
|
27505
28026
|
return content || "unknown";
|
|
27506
28027
|
} catch {
|
|
27507
28028
|
return "unknown";
|
|
@@ -27542,7 +28063,7 @@ var clientErrorReporterScript = `<script>
|
|
|
27542
28063
|
function cachedHtml(file) {
|
|
27543
28064
|
let html = htmlCache.get(file);
|
|
27544
28065
|
if (!html) {
|
|
27545
|
-
html =
|
|
28066
|
+
html = readFileSync39(resolve36(process.cwd(), "public", file), "utf-8");
|
|
27546
28067
|
const productNameEsc = escapeHtml(BRAND.productName);
|
|
27547
28068
|
html = html.replace(/<title>([^<]*)<\/title>/, (_match, inner) => `<title>${escapeHtml(inner).replace(/Maxy/g, productNameEsc)}</title>`);
|
|
27548
28069
|
html = html.replace('href="/favicon.ico"', `href="${escapeHtml(brandFaviconPath)}"`);
|
|
@@ -27559,13 +28080,13 @@ ${clientErrorReporterScript}
|
|
|
27559
28080
|
return html;
|
|
27560
28081
|
}
|
|
27561
28082
|
function loadBrandingCache(agentSlug) {
|
|
27562
|
-
const configDir2 =
|
|
28083
|
+
const configDir2 = join39(homedir4(), BRAND.configDir);
|
|
27563
28084
|
try {
|
|
27564
28085
|
const accountId = getDefaultAccountId();
|
|
27565
28086
|
if (!accountId) return null;
|
|
27566
|
-
const cachePath =
|
|
27567
|
-
if (!
|
|
27568
|
-
return JSON.parse(
|
|
28087
|
+
const cachePath = join39(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
|
|
28088
|
+
if (!existsSync37(cachePath)) return null;
|
|
28089
|
+
return JSON.parse(readFileSync39(cachePath, "utf-8"));
|
|
27569
28090
|
} catch {
|
|
27570
28091
|
return null;
|
|
27571
28092
|
}
|
|
@@ -27609,7 +28130,7 @@ function brandedPublicHtml(agentSlug) {
|
|
|
27609
28130
|
function agentUnavailableHtml() {
|
|
27610
28131
|
return `<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>${escapeHtml(BRAND.productName)}</title></head><body style="font-family:system-ui,sans-serif;max-width:32rem;margin:4rem auto;padding:0 1.5rem;color:#222"><h1 style="font-size:1.25rem">Agent unavailable</h1><p>This agent isn't available right now. If you reached this page from a saved link, the agent may have been turned off.</p></body></html>`;
|
|
27611
28132
|
}
|
|
27612
|
-
|
|
28133
|
+
app63.get("/", (c) => {
|
|
27613
28134
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
27614
28135
|
const klass = classifyHost(host, getOperatorDomains(), isPublicHost);
|
|
27615
28136
|
if (klass === "operator") {
|
|
@@ -27631,12 +28152,12 @@ app62.get("/", (c) => {
|
|
|
27631
28152
|
console.log(`[host-class] host=${host} class=admin served=index.html`);
|
|
27632
28153
|
return c.html(cachedHtml("index.html"));
|
|
27633
28154
|
});
|
|
27634
|
-
|
|
28155
|
+
app63.get("/public", (c) => {
|
|
27635
28156
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
27636
28157
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
27637
28158
|
return c.html(cachedHtml("public.html"));
|
|
27638
28159
|
});
|
|
27639
|
-
|
|
28160
|
+
app63.get("/public-chat", (c) => {
|
|
27640
28161
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
27641
28162
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
27642
28163
|
return c.html(cachedHtml("public.html"));
|
|
@@ -27655,12 +28176,12 @@ async function logViewerFetch(c, next) {
|
|
|
27655
28176
|
duration_ms: Date.now() - start
|
|
27656
28177
|
});
|
|
27657
28178
|
}
|
|
27658
|
-
|
|
27659
|
-
|
|
27660
|
-
|
|
28179
|
+
app63.use("/vnc-viewer.html", logViewerFetch);
|
|
28180
|
+
app63.use("/vnc-popout.html", logViewerFetch);
|
|
28181
|
+
app63.get("/vnc-popout.html", (c) => {
|
|
27661
28182
|
let html = htmlCache.get("vnc-popout.html");
|
|
27662
28183
|
if (!html) {
|
|
27663
|
-
html =
|
|
28184
|
+
html = readFileSync39(resolve36(process.cwd(), "public", "vnc-popout.html"), "utf-8");
|
|
27664
28185
|
const name = escapeHtml(BRAND.productName);
|
|
27665
28186
|
html = html.replace("<title>Browser \u2014 Maxy</title>", `<title>${name}</title>`);
|
|
27666
28187
|
html = html.replace("</head>", ` ${brandScript}
|
|
@@ -27670,7 +28191,7 @@ app62.get("/vnc-popout.html", (c) => {
|
|
|
27670
28191
|
}
|
|
27671
28192
|
return c.html(html);
|
|
27672
28193
|
});
|
|
27673
|
-
|
|
28194
|
+
app63.post("/api/vnc/client-event", async (c) => {
|
|
27674
28195
|
let body;
|
|
27675
28196
|
try {
|
|
27676
28197
|
body = await c.req.json();
|
|
@@ -27691,11 +28212,11 @@ app62.post("/api/vnc/client-event", async (c) => {
|
|
|
27691
28212
|
});
|
|
27692
28213
|
return c.json({ ok: true });
|
|
27693
28214
|
});
|
|
27694
|
-
|
|
28215
|
+
app63.get("/g/:slug", (c) => {
|
|
27695
28216
|
return c.html(brandedPublicHtml(resolveDefaultSlug() ?? void 0));
|
|
27696
28217
|
});
|
|
27697
28218
|
for (const pwa of PWA_SURFACES) {
|
|
27698
|
-
|
|
28219
|
+
app63.get(pwa.manifestPath, (c) => {
|
|
27699
28220
|
const manifest = buildManifest(pwa, {
|
|
27700
28221
|
productName: BRAND.productName,
|
|
27701
28222
|
appIcon192: brandAppIcon192Path,
|
|
@@ -27711,7 +28232,7 @@ for (const pwa of PWA_SURFACES) {
|
|
|
27711
28232
|
return c.body(JSON.stringify(manifest));
|
|
27712
28233
|
});
|
|
27713
28234
|
}
|
|
27714
|
-
|
|
28235
|
+
app63.get("/sw.js", (c) => {
|
|
27715
28236
|
if (SW_SOURCE == null) {
|
|
27716
28237
|
console.error("[pwa] op=sw status=500 reason=sw-source-missing");
|
|
27717
28238
|
return c.text("Service worker unavailable", 500);
|
|
@@ -27720,12 +28241,12 @@ app62.get("/sw.js", (c) => {
|
|
|
27720
28241
|
console.log(`[pwa] op=sw status=200 ct=${SW_CONTENT_TYPE}`);
|
|
27721
28242
|
return c.body(SW_SOURCE);
|
|
27722
28243
|
});
|
|
27723
|
-
|
|
28244
|
+
app63.get("/graph", (c) => {
|
|
27724
28245
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
27725
28246
|
if (isPublicHost(host) || isOperatorHost(host, getOperatorDomains())) return c.text("Not found", 404);
|
|
27726
28247
|
return c.html(cachedHtml("graph.html"));
|
|
27727
28248
|
});
|
|
27728
|
-
|
|
28249
|
+
app63.get("/chat", (c) => {
|
|
27729
28250
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
27730
28251
|
if (isOperatorHost(host, getOperatorDomains())) {
|
|
27731
28252
|
console.log(`[host-class] host=${host} class=operator served=operator.html`);
|
|
@@ -27734,27 +28255,32 @@ app62.get("/chat", (c) => {
|
|
|
27734
28255
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
27735
28256
|
return c.html(cachedHtml("chat.html"));
|
|
27736
28257
|
});
|
|
27737
|
-
|
|
28258
|
+
app63.get("/data", (c) => {
|
|
27738
28259
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
27739
28260
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
27740
28261
|
return c.html(cachedHtml("data.html"));
|
|
27741
28262
|
});
|
|
27742
|
-
|
|
28263
|
+
app63.get("/tasks", (c) => {
|
|
27743
28264
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
27744
28265
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
27745
28266
|
return c.html(cachedHtml("tasks.html"));
|
|
27746
28267
|
});
|
|
27747
|
-
|
|
28268
|
+
app63.get("/activity", (c) => {
|
|
28269
|
+
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
28270
|
+
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
28271
|
+
return c.html(cachedHtml("activity.html"));
|
|
28272
|
+
});
|
|
28273
|
+
app63.get("/calendar", (c) => {
|
|
27748
28274
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
27749
28275
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
27750
28276
|
return c.html(cachedHtml("calendar.html"));
|
|
27751
28277
|
});
|
|
27752
|
-
|
|
28278
|
+
app63.get("/browser", (c) => {
|
|
27753
28279
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
27754
28280
|
if (isPublicHost(host) || isOperatorHost(host, getOperatorDomains())) return c.text("Not found", 404);
|
|
27755
28281
|
return c.html(cachedHtml("browser.html"));
|
|
27756
28282
|
});
|
|
27757
|
-
|
|
28283
|
+
app63.get("/:slug", async (c, next) => {
|
|
27758
28284
|
const slug = c.req.param("slug");
|
|
27759
28285
|
if (AGENT_SLUG_PATTERN.test(`/${slug}`)) {
|
|
27760
28286
|
const account = resolveAccount();
|
|
@@ -27769,13 +28295,13 @@ app62.get("/:slug", async (c, next) => {
|
|
|
27769
28295
|
await next();
|
|
27770
28296
|
});
|
|
27771
28297
|
if (brandFaviconPath !== "/favicon.ico") {
|
|
27772
|
-
|
|
28298
|
+
app63.get("/favicon.ico", (c) => {
|
|
27773
28299
|
c.header("Cache-Control", "public, max-age=300");
|
|
27774
28300
|
return c.redirect(brandFaviconPath, 302);
|
|
27775
28301
|
});
|
|
27776
28302
|
}
|
|
27777
|
-
|
|
27778
|
-
|
|
28303
|
+
app63.use("/*", serveStatic({ root: "./public" }));
|
|
28304
|
+
app63.all("*", (c) => {
|
|
27779
28305
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
27780
28306
|
const path3 = c.req.path;
|
|
27781
28307
|
if (isPublicHost(host)) {
|
|
@@ -27789,14 +28315,14 @@ app62.all("*", (c) => {
|
|
|
27789
28315
|
});
|
|
27790
28316
|
var port = requirePortEnv("MAXY_UI_INTERNAL_PORT", { tag: "ui-server" });
|
|
27791
28317
|
var hostname = process.env.HOSTNAME ?? "127.0.0.1";
|
|
27792
|
-
var httpServer = serve({ fetch:
|
|
28318
|
+
var httpServer = serve({ fetch: app63.fetch, port, hostname });
|
|
27793
28319
|
console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
27794
28320
|
{
|
|
27795
|
-
const reconcilePlatformRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
28321
|
+
const reconcilePlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join39(__dirname, "..");
|
|
27796
28322
|
const reconcileScript = resolve36(reconcilePlatformRoot, "plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js");
|
|
27797
28323
|
const RECONCILE_INTERVAL_MS = 12e4;
|
|
27798
28324
|
const runReconcile = () => {
|
|
27799
|
-
if (!
|
|
28325
|
+
if (!existsSync37(reconcileScript)) return;
|
|
27800
28326
|
try {
|
|
27801
28327
|
const child = spawn3(process.execPath, [reconcileScript], {
|
|
27802
28328
|
env: { ...process.env, PLATFORM_ROOT: reconcilePlatformRoot },
|
|
@@ -27814,11 +28340,11 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
27814
28340
|
loop.unref();
|
|
27815
28341
|
}
|
|
27816
28342
|
{
|
|
27817
|
-
const outlookPlatformRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
28343
|
+
const outlookPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join39(__dirname, "..");
|
|
27818
28344
|
const outlookScript = resolve36(outlookPlatformRoot, "plugins/outlook/mcp/dist/scripts/complete-registration.js");
|
|
27819
28345
|
const OUTLOOK_COMPLETE_INTERVAL_MS = 3e4;
|
|
27820
28346
|
const runOutlookComplete = () => {
|
|
27821
|
-
if (!
|
|
28347
|
+
if (!existsSync37(outlookScript)) return;
|
|
27822
28348
|
try {
|
|
27823
28349
|
const child = spawn3(process.execPath, [outlookScript], {
|
|
27824
28350
|
env: { ...process.env, PLATFORM_ROOT: outlookPlatformRoot },
|
|
@@ -27836,19 +28362,19 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
27836
28362
|
outlookLoop.unref();
|
|
27837
28363
|
}
|
|
27838
28364
|
{
|
|
27839
|
-
const auditRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
28365
|
+
const auditRoot = process.env.MAXY_PLATFORM_ROOT ?? join39(__dirname, "..");
|
|
27840
28366
|
const strandedAccountsDir = resolve36(auditRoot, "..", "data/accounts");
|
|
27841
28367
|
const STRANDED_AUDIT_INTERVAL_MS = 3e5;
|
|
27842
28368
|
const STRANDED_AGE_MS = 16 * 6e4;
|
|
27843
28369
|
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;
|
|
27844
28370
|
const runStrandedAudit = () => {
|
|
27845
28371
|
try {
|
|
27846
|
-
if (!
|
|
28372
|
+
if (!existsSync37(strandedAccountsDir)) return;
|
|
27847
28373
|
const now = Date.now();
|
|
27848
|
-
for (const name of
|
|
28374
|
+
for (const name of readdirSync23(strandedAccountsDir)) {
|
|
27849
28375
|
if (!STRANDED_UUID_RE.test(name)) continue;
|
|
27850
28376
|
const pendingPath2 = resolve36(strandedAccountsDir, name, "secrets/outlook/pending-devicecode.enc");
|
|
27851
|
-
if (!
|
|
28377
|
+
if (!existsSync37(pendingPath2)) continue;
|
|
27852
28378
|
const ageMs = now - statSync14(pendingPath2).mtimeMs;
|
|
27853
28379
|
if (ageMs > STRANDED_AGE_MS) {
|
|
27854
28380
|
console.error(`[outlook-mcp] devicecode-stranded account=${name} ageSec=${Math.floor(ageMs / 1e3)}`);
|
|
@@ -27864,7 +28390,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
27864
28390
|
strandedLoop.unref();
|
|
27865
28391
|
}
|
|
27866
28392
|
{
|
|
27867
|
-
const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
28393
|
+
const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join39(__dirname, "..");
|
|
27868
28394
|
const STORAGE_AUDIT_INTERVAL_MS = 3e5;
|
|
27869
28395
|
const runStorageAuditSafe = () => {
|
|
27870
28396
|
runStorageAudit(auditPlatformRoot).catch(
|
|
@@ -27886,7 +28412,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
27886
28412
|
pagesAuditLoop.unref();
|
|
27887
28413
|
}
|
|
27888
28414
|
{
|
|
27889
|
-
const publishPlatformRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
28415
|
+
const publishPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join39(__dirname, "..");
|
|
27890
28416
|
const publishScript = resolve36(publishPlatformRoot, "plugins/scheduling/mcp/dist/scripts/publish-availability.js");
|
|
27891
28417
|
const PUBLISH_INTERVAL_MS = 3e5;
|
|
27892
28418
|
const currentAccount = () => {
|
|
@@ -27898,7 +28424,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
27898
28424
|
}
|
|
27899
28425
|
};
|
|
27900
28426
|
const spawnPublish = (account) => {
|
|
27901
|
-
if (!
|
|
28427
|
+
if (!existsSync37(publishScript)) return;
|
|
27902
28428
|
try {
|
|
27903
28429
|
const child = spawn3(process.execPath, [publishScript], {
|
|
27904
28430
|
env: {
|
|
@@ -27919,8 +28445,8 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
27919
28445
|
const availPath = resolve36(account.accountDir, "calendar-availability.json");
|
|
27920
28446
|
let hasBookingSite = false;
|
|
27921
28447
|
try {
|
|
27922
|
-
if (
|
|
27923
|
-
const cfg = JSON.parse(
|
|
28448
|
+
if (existsSync37(availPath)) {
|
|
28449
|
+
const cfg = JSON.parse(readFileSync39(availPath, "utf-8"));
|
|
27924
28450
|
hasBookingSite = typeof cfg.bookingDbName === "string" && cfg.bookingDbName.length > 0;
|
|
27925
28451
|
}
|
|
27926
28452
|
} catch {
|
|
@@ -27928,9 +28454,9 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
27928
28454
|
if (!hasBookingSite) return;
|
|
27929
28455
|
const statePath = resolve36(account.accountDir, "state", "booking-availability", "last-publish.json");
|
|
27930
28456
|
let lastSuccessAt = null;
|
|
27931
|
-
if (
|
|
28457
|
+
if (existsSync37(statePath)) {
|
|
27932
28458
|
try {
|
|
27933
|
-
const rec = JSON.parse(
|
|
28459
|
+
const rec = JSON.parse(readFileSync39(statePath, "utf-8"));
|
|
27934
28460
|
lastSuccessAt = rec.lastSuccessAt ?? null;
|
|
27935
28461
|
} catch {
|
|
27936
28462
|
console.error(`[calendar-availability] op=audit accountId=${account.accountId} snapshotAgeMs=na reason=bad-state-file`);
|
|
@@ -27953,13 +28479,14 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
27953
28479
|
publishLoop.unref();
|
|
27954
28480
|
}
|
|
27955
28481
|
startTimeEntryCensus(() => getSession());
|
|
28482
|
+
startLedgerCensus(() => getSession());
|
|
27956
28483
|
{
|
|
27957
|
-
const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
28484
|
+
const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join39(__dirname, "..");
|
|
27958
28485
|
const auditScript = resolve36(auditPlatformRoot, "plugins/connector/mcp/dist/scripts/audit-connectors.js");
|
|
27959
28486
|
const auditLogDir = process.env.LOG_DIR ?? LOG_DIR;
|
|
27960
28487
|
const CONNECTOR_AUDIT_INTERVAL_MS = 3e5;
|
|
27961
28488
|
const runConnectorAudit = () => {
|
|
27962
|
-
if (!
|
|
28489
|
+
if (!existsSync37(auditScript)) return;
|
|
27963
28490
|
try {
|
|
27964
28491
|
const child = spawn3(process.execPath, [auditScript], {
|
|
27965
28492
|
env: { ...process.env, PLATFORM_ROOT: auditPlatformRoot, LOG_DIR: auditLogDir },
|
|
@@ -28030,7 +28557,7 @@ for (const m of SUBAPP_MANIFEST) {
|
|
|
28030
28557
|
}
|
|
28031
28558
|
try {
|
|
28032
28559
|
const registered = [];
|
|
28033
|
-
for (const r of
|
|
28560
|
+
for (const r of app63.routes ?? []) {
|
|
28034
28561
|
if (typeof r.path !== "string" || r.path.includes(":") || r.path.includes("*")) continue;
|
|
28035
28562
|
if (AGENT_SLUG_PATTERN.test(r.path)) {
|
|
28036
28563
|
registered.push({ method: (r.method ?? "ALL").toUpperCase(), path: r.path });
|
|
@@ -28070,11 +28597,11 @@ try {
|
|
|
28070
28597
|
var ADMINUSER_RECONCILE_INTERVAL_MS = 60 * 60 * 1e3;
|
|
28071
28598
|
async function runAdminUserReconcileTick() {
|
|
28072
28599
|
try {
|
|
28073
|
-
if (!
|
|
28600
|
+
if (!existsSync37(USERS_FILE)) {
|
|
28074
28601
|
console.error("[adminuser-self-heal] skip reason=no-users-file");
|
|
28075
28602
|
return;
|
|
28076
28603
|
}
|
|
28077
|
-
const usersRaw =
|
|
28604
|
+
const usersRaw = readFileSync39(USERS_FILE, "utf-8").trim();
|
|
28078
28605
|
if (!usersRaw) {
|
|
28079
28606
|
console.error("[adminuser-self-heal] skip reason=empty-users-file");
|
|
28080
28607
|
return;
|
|
@@ -28092,6 +28619,7 @@ async function runAdminUserReconcileTick() {
|
|
|
28092
28619
|
}
|
|
28093
28620
|
await runAdminUserSelfHeal({ userId, accountId: account.accountId });
|
|
28094
28621
|
await runUserProfileReconcile();
|
|
28622
|
+
await runConversationAudit();
|
|
28095
28623
|
} catch (err) {
|
|
28096
28624
|
console.error(`[adminuser-self-heal] rejected: ${err instanceof Error ? err.message : String(err)}`);
|
|
28097
28625
|
}
|
|
@@ -28103,8 +28631,8 @@ var adminUserReconcileTimer = setInterval(() => {
|
|
|
28103
28631
|
if (typeof adminUserReconcileTimer.unref === "function") adminUserReconcileTimer.unref();
|
|
28104
28632
|
var USERS_RECONCILE_INTERVAL_MS = 60 * 60 * 1e3;
|
|
28105
28633
|
function countUsersRows() {
|
|
28106
|
-
if (!
|
|
28107
|
-
const raw =
|
|
28634
|
+
if (!existsSync37(USERS_FILE)) return 0;
|
|
28635
|
+
const raw = readFileSync39(USERS_FILE, "utf-8").trim();
|
|
28108
28636
|
if (!raw) return 0;
|
|
28109
28637
|
const users = JSON.parse(raw);
|
|
28110
28638
|
return users.filter((u) => typeof u.userId === "string").length;
|
|
@@ -28224,7 +28752,7 @@ if (bootAccountConfig?.whatsapp) {
|
|
|
28224
28752
|
}
|
|
28225
28753
|
init({
|
|
28226
28754
|
configDir: configDirForWhatsApp,
|
|
28227
|
-
platformRoot: resolve36(process.env.MAXY_PLATFORM_ROOT ??
|
|
28755
|
+
platformRoot: resolve36(process.env.MAXY_PLATFORM_ROOT ?? join39(__dirname, "..")),
|
|
28228
28756
|
accountConfig: bootAccountConfig,
|
|
28229
28757
|
onMessage: async (msg) => {
|
|
28230
28758
|
if (msg.isOwnerMirror) {
|