@rubytech/create-maxy-code 0.1.600 → 0.1.602
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__tests__/email-sampler-unit.test.js +31 -0
- package/dist/index.js +18 -2
- package/dist/port-resolution.js +24 -0
- package/package.json +1 -1
- package/payload/platform/plugins/admin/hooks/video-frames-inject.sh +141 -0
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +5 -1
- package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +10 -0
- package/payload/platform/plugins/docs/references/admin-ui.md +2 -0
- package/payload/platform/plugins/docs/references/telegram-guide.md +2 -0
- package/payload/platform/plugins/email/PLUGIN.md +7 -1
- package/payload/platform/plugins/email/mcp/dist/lib/credentials.d.ts +27 -0
- package/payload/platform/plugins/email/mcp/dist/lib/credentials.d.ts.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/lib/credentials.js +78 -0
- package/payload/platform/plugins/email/mcp/dist/lib/credentials.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/sampler/__tests__/sample-mailbox.test.d.ts +2 -0
- package/payload/platform/plugins/email/mcp/dist/sampler/__tests__/sample-mailbox.test.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/sampler/__tests__/sample-mailbox.test.js +96 -0
- package/payload/platform/plugins/email/mcp/dist/sampler/__tests__/sample-mailbox.test.js.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/sampler/main.d.ts +2 -0
- package/payload/platform/plugins/email/mcp/dist/sampler/main.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/sampler/main.js +75 -0
- package/payload/platform/plugins/email/mcp/dist/sampler/main.js.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/sampler/sample-mailbox.d.ts +48 -0
- package/payload/platform/plugins/email/mcp/dist/sampler/sample-mailbox.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/sampler/sample-mailbox.js +77 -0
- package/payload/platform/plugins/email/mcp/dist/sampler/sample-mailbox.js.map +1 -0
- package/payload/platform/plugins/scheduling/PLUGIN.md +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/gate-audits.test.js +67 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/gate-audits.test.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/gate.test.js +89 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/gate.test.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/outage-marker.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/outage-marker.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/outage-marker.test.js +160 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/outage-marker.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/routine-run.test.js +16 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/routine-run.test.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/gate.d.ts +31 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/gate.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/gate.js +42 -4
- package/payload/platform/plugins/scheduling/mcp/dist/lib/gate.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/outage-marker.d.ts +101 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/outage-marker.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/outage-marker.js +130 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/outage-marker.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/routine-run.d.ts +10 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/routine-run.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/routine-run.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/schedule-audit.d.ts +24 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/schedule-audit.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/schedule-audit.js +89 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/schedule-audit.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/agent-turn-dispatch.test.js +67 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/agent-turn-dispatch.test.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/gate-dispatch-wiring.test.js +31 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/gate-dispatch-wiring.test.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.d.ts +10 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.js +46 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js +72 -4
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/scheduling-gate.test.js +81 -4
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/scheduling-gate.test.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/scheduling-gate.d.ts +50 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/scheduling-gate.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/scheduling-gate.js +48 -7
- package/payload/platform/plugins/scheduling/mcp/dist/tools/scheduling-gate.js.map +1 -1
- package/payload/platform/plugins/telegram/PLUGIN.md +4 -0
- package/payload/platform/plugins/telegram/mcp/dist/__tests__/public-pin-registry.test.js +33 -1
- package/payload/platform/plugins/telegram/mcp/dist/__tests__/public-pin-registry.test.js.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/__tests__/public-pin.test.js +166 -1
- package/payload/platform/plugins/telegram/mcp/dist/__tests__/public-pin.test.js.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/index.js +39 -14
- package/payload/platform/plugins/telegram/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/lib/public-pin.d.ts +95 -0
- package/payload/platform/plugins/telegram/mcp/dist/lib/public-pin.d.ts.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/lib/public-pin.js +125 -0
- package/payload/platform/plugins/telegram/mcp/dist/lib/public-pin.js.map +1 -1
- package/payload/platform/scripts/logs-read.sh +18 -3
- package/payload/platform/services/telegram-channel/dist/notification.d.ts +6 -0
- package/payload/platform/services/telegram-channel/dist/notification.d.ts.map +1 -1
- package/payload/platform/services/telegram-channel/dist/notification.js +12 -5
- package/payload/platform/services/telegram-channel/dist/notification.js.map +1 -1
- package/payload/platform/services/whatsapp-channel/dist/notification.d.ts +5 -0
- package/payload/platform/services/whatsapp-channel/dist/notification.d.ts.map +1 -1
- package/payload/platform/services/whatsapp-channel/dist/notification.js +9 -3
- package/payload/platform/services/whatsapp-channel/dist/notification.js.map +1 -1
- package/payload/platform/templates/account-settings.json +6 -0
- package/payload/server/chunk-CYU75QAV.js +377 -0
- package/payload/server/{chunk-34FPJYHN.js → chunk-GI5AVCRG.js} +87 -146
- package/payload/server/chunk-KUVNCAE4.js +77 -0
- package/payload/server/{manager-7BXVB76I.js → manager-VDHT3YYI.js} +2 -1
- package/payload/server/maxy-edge.js +33 -1
- package/payload/server/public/activity.html +6 -6
- package/payload/server/public/agents.html +5 -5
- package/payload/server/public/assets/{AdminLoginScreens-B3W6J6Bl.js → AdminLoginScreens-CaQqLuxZ.js} +1 -1
- package/payload/server/public/assets/AdminLoginScreens-CaQqLuxZ.js.br +0 -0
- package/payload/server/public/assets/AdminLoginScreens-CaQqLuxZ.js.gz +0 -0
- package/payload/server/public/assets/{AdminShell-C3R-vMZ5.js → AdminShell-D8WTrqem.js} +1 -1
- package/payload/server/public/assets/AdminShell-D8WTrqem.js.br +0 -0
- package/payload/server/public/assets/AdminShell-D8WTrqem.js.gz +0 -0
- package/payload/server/public/assets/{activity-tzv68iBs.js → activity-B3fiJrC2.js} +1 -1
- package/payload/server/public/assets/activity-B3fiJrC2.js.br +0 -0
- package/payload/server/public/assets/activity-B3fiJrC2.js.gz +0 -0
- package/payload/server/public/assets/admin-ouF-DflP.js +1 -0
- package/payload/server/public/assets/admin-ouF-DflP.js.br +0 -0
- package/payload/server/public/assets/admin-ouF-DflP.js.gz +0 -0
- package/payload/server/public/assets/{agents-DUZfeY3X.js → agents-C8RSXHdh.js} +1 -1
- package/payload/server/public/assets/agents-C8RSXHdh.js.br +0 -0
- package/payload/server/public/assets/agents-C8RSXHdh.js.gz +0 -0
- package/payload/server/public/assets/{browser-DwLaXqjO.js → browser-Dbv6-Rag.js} +1 -1
- package/payload/server/public/assets/browser-Dbv6-Rag.js.br +0 -0
- package/payload/server/public/assets/browser-Dbv6-Rag.js.gz +0 -0
- package/payload/server/public/assets/{calendar-Cli8Qjl9.js → calendar-vJjtsH9n.js} +1 -1
- package/payload/server/public/assets/calendar-vJjtsH9n.js.br +0 -0
- package/payload/server/public/assets/calendar-vJjtsH9n.js.gz +0 -0
- package/payload/server/public/assets/chat-cqL4qPUy.js +1 -0
- package/payload/server/public/assets/chat-cqL4qPUy.js.br +1 -0
- package/payload/server/public/assets/chat-cqL4qPUy.js.gz +0 -0
- package/payload/server/public/assets/chevron-left-DB98DSG3.js +1 -0
- package/payload/server/public/assets/chevron-left-DB98DSG3.js.br +0 -0
- package/payload/server/public/assets/clock-4YwsYe4L.js +1 -0
- package/payload/server/public/assets/clock-4YwsYe4L.js.br +0 -0
- package/payload/server/public/assets/clock-4YwsYe4L.js.gz +0 -0
- package/payload/server/public/assets/{copy-yhhwfEbQ.js → copy-DyG7sC5o.js} +1 -1
- package/payload/server/public/assets/copy-DyG7sC5o.js.br +0 -0
- package/payload/server/public/assets/copy-DyG7sC5o.js.gz +0 -0
- package/payload/server/public/assets/data-BAzLtx9C.js +1 -0
- package/payload/server/public/assets/data-BAzLtx9C.js.br +0 -0
- package/payload/server/public/assets/data-BAzLtx9C.js.gz +0 -0
- package/payload/server/public/assets/{field-jg0YQNDy.js → field-Bx6pM-vq.js} +1 -1
- package/payload/server/public/assets/field-Bx6pM-vq.js.br +0 -0
- package/payload/server/public/assets/field-Bx6pM-vq.js.gz +0 -0
- package/payload/server/public/assets/{file-text-D0EdW7h4.js → file-text-CpHWsMGe.js} +1 -1
- package/payload/server/public/assets/file-text-CpHWsMGe.js.br +0 -0
- package/payload/server/public/assets/file-text-CpHWsMGe.js.gz +0 -0
- package/payload/server/public/assets/{graph--AUr4uBc.js → graph-DjOywuv_.js} +1 -1
- package/payload/server/public/assets/graph-DjOywuv_.js.br +0 -0
- package/payload/server/public/assets/graph-DjOywuv_.js.gz +0 -0
- package/payload/server/public/assets/{graph-labels-DM0CiAX1.js → graph-labels-CGWtqa-m.js} +1 -1
- package/payload/server/public/assets/graph-labels-CGWtqa-m.js.br +0 -0
- package/payload/server/public/assets/graph-labels-CGWtqa-m.js.gz +0 -0
- package/payload/server/public/assets/{jsx-runtime-lfcjzaWi.css → jsx-runtime-D75_aR1J.css} +1 -1
- package/payload/server/public/assets/jsx-runtime-D75_aR1J.css.br +0 -0
- package/payload/server/public/assets/{jsx-runtime-lfcjzaWi.css.gz → jsx-runtime-D75_aR1J.css.gz} +0 -0
- package/payload/server/public/assets/{operator-CNYKStFX.js → operator-_DN0RF1R.js} +1 -1
- package/payload/server/public/assets/operator-_DN0RF1R.js.br +0 -0
- package/payload/server/public/assets/operator-_DN0RF1R.js.gz +0 -0
- package/payload/server/public/assets/page-DI4qQIK0.js +1 -0
- package/payload/server/public/assets/page-DI4qQIK0.js.br +0 -0
- package/payload/server/public/assets/page-DI4qQIK0.js.gz +0 -0
- package/payload/server/public/assets/page-zCwgrs8m.js +32 -0
- package/payload/server/public/assets/page-zCwgrs8m.js.br +0 -0
- package/payload/server/public/assets/page-zCwgrs8m.js.gz +0 -0
- package/payload/server/public/assets/play-CHQ5a9yh.js +1 -0
- package/payload/server/public/assets/play-CHQ5a9yh.js.br +0 -0
- package/payload/server/public/assets/play-CHQ5a9yh.js.gz +0 -0
- package/payload/server/public/assets/{public-7gXDqCog.js → public-DDVWBNSH.js} +1 -1
- package/payload/server/public/assets/public-DDVWBNSH.js.br +0 -0
- package/payload/server/public/assets/public-DDVWBNSH.js.gz +0 -0
- package/payload/server/public/assets/{rotate-ccw-DhqNTPpo.js → rotate-ccw-xTwkf-m7.js} +1 -1
- package/payload/server/public/assets/rotate-ccw-xTwkf-m7.js.br +0 -0
- package/payload/server/public/assets/rotate-ccw-xTwkf-m7.js.gz +0 -0
- package/payload/server/public/assets/{routines-DN_yDtEj.js → routines-Bu5MdNmG.js} +1 -1
- package/payload/server/public/assets/routines-Bu5MdNmG.js.br +0 -0
- package/payload/server/public/assets/routines-Bu5MdNmG.js.gz +0 -0
- package/payload/server/public/assets/{skills-pb_3BdOl.js → skills-DRunh5vy.js} +1 -1
- package/payload/server/public/assets/skills-DRunh5vy.js.br +0 -0
- package/payload/server/public/assets/skills-DRunh5vy.js.gz +0 -0
- package/payload/server/public/assets/{tasks-BQm4boat.js → tasks-DI2fznvd.js} +1 -1
- package/payload/server/public/assets/tasks-DI2fznvd.js.br +0 -0
- package/payload/server/public/assets/tasks-DI2fznvd.js.gz +0 -0
- package/payload/server/public/assets/{triangle-alert-d7yjaIqv.js → triangle-alert-B6CHZeUf.js} +1 -1
- package/payload/server/public/assets/triangle-alert-B6CHZeUf.js.br +0 -0
- package/payload/server/public/assets/triangle-alert-B6CHZeUf.js.gz +0 -0
- package/payload/server/public/assets/{useCopyFeedback-CZ6Qhfkj.js → useCopyFeedback-6rU2IEPk.js} +1 -1
- package/payload/server/public/assets/useCopyFeedback-6rU2IEPk.js.br +2 -0
- package/payload/server/public/assets/useCopyFeedback-6rU2IEPk.js.gz +0 -0
- package/payload/server/public/assets/{useMediaQuery-R1smYLx4.js → useMediaQuery-D7A5Bzs3.js} +1 -1
- package/payload/server/public/assets/useMediaQuery-D7A5Bzs3.js.br +0 -0
- package/payload/server/public/assets/useMediaQuery-D7A5Bzs3.js.gz +0 -0
- package/payload/server/public/assets/useVoiceRecorder-CptrerVA.js +2 -0
- package/payload/server/public/assets/useVoiceRecorder-CptrerVA.js.br +0 -0
- package/payload/server/public/assets/useVoiceRecorder-CptrerVA.js.gz +0 -0
- package/payload/server/public/assets/{wrench-DL1pbaCs.js → wrench-DyX4C8aY.js} +1 -1
- package/payload/server/public/assets/wrench-DyX4C8aY.js.br +0 -0
- package/payload/server/public/assets/wrench-DyX4C8aY.js.gz +0 -0
- package/payload/server/public/browser.html +5 -5
- package/payload/server/public/calendar.html +8 -8
- package/payload/server/public/chat.html +14 -14
- package/payload/server/public/data.html +12 -12
- package/payload/server/public/field.html +3 -3
- package/payload/server/public/graph.html +10 -10
- package/payload/server/public/index.html +14 -14
- package/payload/server/public/operator.html +15 -15
- package/payload/server/public/public.html +14 -14
- package/payload/server/public/routines.html +8 -8
- package/payload/server/public/skills.html +6 -6
- package/payload/server/public/tasks.html +7 -7
- package/payload/server/server.js +634 -461
- package/payload/server/video-extract.js +36 -0
- package/payload/server/public/assets/AdminLoginScreens-B3W6J6Bl.js.br +0 -0
- package/payload/server/public/assets/AdminLoginScreens-B3W6J6Bl.js.gz +0 -0
- package/payload/server/public/assets/AdminShell-C3R-vMZ5.js.br +0 -0
- package/payload/server/public/assets/AdminShell-C3R-vMZ5.js.gz +0 -0
- package/payload/server/public/assets/activity-tzv68iBs.js.br +0 -0
- package/payload/server/public/assets/activity-tzv68iBs.js.gz +0 -0
- package/payload/server/public/assets/admin-CzW_9jm3.js +0 -1
- package/payload/server/public/assets/admin-CzW_9jm3.js.br +0 -0
- package/payload/server/public/assets/admin-CzW_9jm3.js.gz +0 -0
- package/payload/server/public/assets/agents-DUZfeY3X.js.br +0 -0
- package/payload/server/public/assets/agents-DUZfeY3X.js.gz +0 -0
- package/payload/server/public/assets/browser-DwLaXqjO.js.br +0 -0
- package/payload/server/public/assets/browser-DwLaXqjO.js.gz +0 -0
- package/payload/server/public/assets/calendar-Cli8Qjl9.js.br +0 -0
- package/payload/server/public/assets/calendar-Cli8Qjl9.js.gz +0 -0
- package/payload/server/public/assets/chat-ByAgBgm1.js +0 -1
- package/payload/server/public/assets/chat-ByAgBgm1.js.br +0 -1
- package/payload/server/public/assets/chat-ByAgBgm1.js.gz +0 -0
- package/payload/server/public/assets/chevron-left-BIYVnwvk.js +0 -1
- package/payload/server/public/assets/chevron-left-BIYVnwvk.js.br +0 -0
- package/payload/server/public/assets/clock-Dzy79hq3.js +0 -1
- package/payload/server/public/assets/clock-Dzy79hq3.js.br +0 -0
- package/payload/server/public/assets/clock-Dzy79hq3.js.gz +0 -0
- package/payload/server/public/assets/copy-yhhwfEbQ.js.br +0 -0
- package/payload/server/public/assets/copy-yhhwfEbQ.js.gz +0 -0
- package/payload/server/public/assets/data-CsMMki2A.js +0 -1
- package/payload/server/public/assets/data-CsMMki2A.js.br +0 -0
- package/payload/server/public/assets/data-CsMMki2A.js.gz +0 -0
- package/payload/server/public/assets/field-jg0YQNDy.js.br +0 -0
- package/payload/server/public/assets/field-jg0YQNDy.js.gz +0 -0
- package/payload/server/public/assets/file-text-D0EdW7h4.js.br +0 -0
- package/payload/server/public/assets/file-text-D0EdW7h4.js.gz +0 -0
- package/payload/server/public/assets/graph--AUr4uBc.js.br +0 -0
- package/payload/server/public/assets/graph--AUr4uBc.js.gz +0 -0
- package/payload/server/public/assets/graph-labels-DM0CiAX1.js.br +0 -0
- package/payload/server/public/assets/graph-labels-DM0CiAX1.js.gz +0 -0
- package/payload/server/public/assets/jsx-runtime-lfcjzaWi.css.br +0 -0
- package/payload/server/public/assets/operator-CNYKStFX.js.br +0 -0
- package/payload/server/public/assets/operator-CNYKStFX.js.gz +0 -0
- package/payload/server/public/assets/page-DSsEpl8J.js +0 -32
- package/payload/server/public/assets/page-DSsEpl8J.js.br +0 -0
- package/payload/server/public/assets/page-DSsEpl8J.js.gz +0 -0
- package/payload/server/public/assets/page-DjhmwxnY.js +0 -1
- package/payload/server/public/assets/page-DjhmwxnY.js.br +0 -0
- package/payload/server/public/assets/page-DjhmwxnY.js.gz +0 -0
- package/payload/server/public/assets/play-DhZlml5b.js +0 -1
- package/payload/server/public/assets/play-DhZlml5b.js.br +0 -0
- package/payload/server/public/assets/play-DhZlml5b.js.gz +0 -0
- package/payload/server/public/assets/public-7gXDqCog.js.br +0 -0
- package/payload/server/public/assets/public-7gXDqCog.js.gz +0 -0
- package/payload/server/public/assets/rotate-ccw-DhqNTPpo.js.br +0 -0
- package/payload/server/public/assets/rotate-ccw-DhqNTPpo.js.gz +0 -0
- package/payload/server/public/assets/routines-DN_yDtEj.js.br +0 -0
- package/payload/server/public/assets/routines-DN_yDtEj.js.gz +0 -0
- package/payload/server/public/assets/skills-pb_3BdOl.js.br +0 -0
- package/payload/server/public/assets/skills-pb_3BdOl.js.gz +0 -0
- package/payload/server/public/assets/tasks-BQm4boat.js.br +0 -0
- package/payload/server/public/assets/tasks-BQm4boat.js.gz +0 -0
- package/payload/server/public/assets/triangle-alert-d7yjaIqv.js.br +0 -0
- package/payload/server/public/assets/triangle-alert-d7yjaIqv.js.gz +0 -0
- package/payload/server/public/assets/useCopyFeedback-CZ6Qhfkj.js.br +0 -0
- package/payload/server/public/assets/useCopyFeedback-CZ6Qhfkj.js.gz +0 -0
- package/payload/server/public/assets/useMediaQuery-R1smYLx4.js.br +0 -0
- package/payload/server/public/assets/useMediaQuery-R1smYLx4.js.gz +0 -0
- package/payload/server/public/assets/useVoiceRecorder-DM1v6sRa.js +0 -2
- package/payload/server/public/assets/useVoiceRecorder-DM1v6sRa.js.br +0 -0
- package/payload/server/public/assets/useVoiceRecorder-DM1v6sRa.js.gz +0 -0
- package/payload/server/public/assets/wrench-DL1pbaCs.js.br +0 -0
- package/payload/server/public/assets/wrench-DL1pbaCs.js.gz +0 -0
- /package/payload/server/public/assets/{jsx-runtime-BtDK2X5t.js → jsx-runtime-B2Q1UOSJ.js} +0 -0
- /package/payload/server/public/assets/{jsx-runtime-BtDK2X5t.js.br → jsx-runtime-B2Q1UOSJ.js.br} +0 -0
- /package/payload/server/public/assets/{jsx-runtime-BtDK2X5t.js.gz → jsx-runtime-B2Q1UOSJ.js.gz} +0 -0
package/payload/server/server.js
CHANGED
|
@@ -71,6 +71,11 @@ import {
|
|
|
71
71
|
vncLog,
|
|
72
72
|
walkPremiumBundles
|
|
73
73
|
} from "./chunk-MNN2RWJR.js";
|
|
74
|
+
import {
|
|
75
|
+
audioExtension,
|
|
76
|
+
isAudioMime,
|
|
77
|
+
isVideoMime
|
|
78
|
+
} from "./chunk-KUVNCAE4.js";
|
|
74
79
|
import {
|
|
75
80
|
ACCOUNTS_ROOT,
|
|
76
81
|
DATA_ROOT,
|
|
@@ -210,13 +215,12 @@ import {
|
|
|
210
215
|
storeMediaBuffer,
|
|
211
216
|
storePublicAttachment,
|
|
212
217
|
toWhatsappJid,
|
|
213
|
-
transcribe,
|
|
214
218
|
validateAccountIdEnv,
|
|
215
219
|
validateFilePathInAccount,
|
|
216
220
|
waitForConnection,
|
|
217
221
|
warnNonUuidAccount,
|
|
218
222
|
writeChatMetadataMerged
|
|
219
|
-
} from "./chunk-
|
|
223
|
+
} from "./chunk-GI5AVCRG.js";
|
|
220
224
|
import {
|
|
221
225
|
ACCOUNTS_DIR,
|
|
222
226
|
AGENT_SLUG_PATTERN,
|
|
@@ -282,6 +286,10 @@ import {
|
|
|
282
286
|
verifyConversationOwnership,
|
|
283
287
|
writeAdminUserAndPerson
|
|
284
288
|
} from "./chunk-6AQYMT6C.js";
|
|
289
|
+
import {
|
|
290
|
+
extractVideo,
|
|
291
|
+
transcribe
|
|
292
|
+
} from "./chunk-CYU75QAV.js";
|
|
285
293
|
import {
|
|
286
294
|
D1_MAX_SQL_STATEMENT_BYTES,
|
|
287
295
|
D1_QUERY_MAX_BODY_BYTES,
|
|
@@ -4252,6 +4260,74 @@ var TELEGRAM_CARD_TOOLS = /* @__PURE__ */ new Set([
|
|
|
4252
4260
|
"mcp__telegram__telegram-card",
|
|
4253
4261
|
"mcp__plugin_telegram_telegram__telegram-card"
|
|
4254
4262
|
]);
|
|
4263
|
+
var TELEGRAM_MEDIA_SEND_TOOLS = /* @__PURE__ */ new Set([
|
|
4264
|
+
"mcp__telegram__telegram-media-send",
|
|
4265
|
+
"mcp__plugin_telegram_telegram__telegram-media-send"
|
|
4266
|
+
]);
|
|
4267
|
+
var TELEGRAM_ASK_TOOLS = /* @__PURE__ */ new Set([
|
|
4268
|
+
"mcp__telegram__telegram-ask",
|
|
4269
|
+
"mcp__plugin_telegram_telegram__telegram-ask"
|
|
4270
|
+
]);
|
|
4271
|
+
var TELEGRAM_API_TOOLS = /* @__PURE__ */ new Set([
|
|
4272
|
+
"mcp__telegram__telegram-api",
|
|
4273
|
+
"mcp__plugin_telegram_telegram__telegram-api"
|
|
4274
|
+
]);
|
|
4275
|
+
var TELEGRAM_API_TRANSMIT_METHODS = /* @__PURE__ */ new Set(["sendMessage", "editMessageText"]);
|
|
4276
|
+
var TELEGRAM_SEND_TOOLS = /* @__PURE__ */ new Set([
|
|
4277
|
+
...TELEGRAM_CARD_TOOLS,
|
|
4278
|
+
...TELEGRAM_MEDIA_SEND_TOOLS,
|
|
4279
|
+
...TELEGRAM_ASK_TOOLS,
|
|
4280
|
+
...TELEGRAM_API_TOOLS
|
|
4281
|
+
]);
|
|
4282
|
+
function chatIdOf(value) {
|
|
4283
|
+
if (typeof value === "string") return value;
|
|
4284
|
+
if (typeof value === "number" && Number.isFinite(value)) return String(value);
|
|
4285
|
+
return "";
|
|
4286
|
+
}
|
|
4287
|
+
function cardOutcome(text, isError) {
|
|
4288
|
+
const v = /card-result: outcome=(\w+)/.exec(text)?.[1];
|
|
4289
|
+
if (v === "edited" || v === "unchanged" || v === "sent") return v;
|
|
4290
|
+
if (v === "none") return "failed";
|
|
4291
|
+
return isError ? "failed" : "sent";
|
|
4292
|
+
}
|
|
4293
|
+
function pendingSendOf(name, input) {
|
|
4294
|
+
const i = input ?? {};
|
|
4295
|
+
if (TELEGRAM_CARD_TOOLS.has(name)) {
|
|
4296
|
+
return {
|
|
4297
|
+
kind: "telegram-card",
|
|
4298
|
+
text: typeof i.text === "string" ? i.text : "",
|
|
4299
|
+
buttons: parseCardButtonsFromInput(input),
|
|
4300
|
+
chatId: chatIdOf(i.chatId),
|
|
4301
|
+
ts: null
|
|
4302
|
+
};
|
|
4303
|
+
}
|
|
4304
|
+
if (TELEGRAM_MEDIA_SEND_TOOLS.has(name) || TELEGRAM_ASK_TOOLS.has(name)) {
|
|
4305
|
+
const kind = typeof i.kind === "string" ? i.kind : "";
|
|
4306
|
+
const text = TELEGRAM_MEDIA_SEND_TOOLS.has(name) ? typeof i.caption === "string" ? i.caption : "" : typeof i.question === "string" ? i.question : "";
|
|
4307
|
+
return {
|
|
4308
|
+
kind: "telegram-send",
|
|
4309
|
+
label: kind,
|
|
4310
|
+
text,
|
|
4311
|
+
chatId: chatIdOf(i.chatId),
|
|
4312
|
+
edit: kind.startsWith("edit") || kind.startsWith("stop"),
|
|
4313
|
+
ts: null
|
|
4314
|
+
};
|
|
4315
|
+
}
|
|
4316
|
+
if (TELEGRAM_API_TOOLS.has(name)) {
|
|
4317
|
+
const method = typeof i.method === "string" ? i.method : "";
|
|
4318
|
+
if (!TELEGRAM_API_TRANSMIT_METHODS.has(method)) return null;
|
|
4319
|
+
const params = i.params ?? {};
|
|
4320
|
+
return {
|
|
4321
|
+
kind: "telegram-send",
|
|
4322
|
+
label: method,
|
|
4323
|
+
text: typeof params.text === "string" ? params.text : "",
|
|
4324
|
+
chatId: chatIdOf(params.chat_id),
|
|
4325
|
+
edit: method === "editMessageText",
|
|
4326
|
+
ts: null
|
|
4327
|
+
};
|
|
4328
|
+
}
|
|
4329
|
+
return null;
|
|
4330
|
+
}
|
|
4255
4331
|
function parseCardButtonsFromInput(input) {
|
|
4256
4332
|
const rows = input?.buttons;
|
|
4257
4333
|
if (!Array.isArray(rows)) return [];
|
|
@@ -4396,7 +4472,29 @@ function erroredToolUseIds(lines) {
|
|
|
4396
4472
|
}
|
|
4397
4473
|
return ids;
|
|
4398
4474
|
}
|
|
4399
|
-
function
|
|
4475
|
+
function answeredToolUseIds(lines) {
|
|
4476
|
+
const ids = /* @__PURE__ */ new Set();
|
|
4477
|
+
for (const line of lines) {
|
|
4478
|
+
if (!line || line[0] !== "{" || !line.includes("tool_use_id")) continue;
|
|
4479
|
+
let row;
|
|
4480
|
+
try {
|
|
4481
|
+
const parsed = JSON.parse(line);
|
|
4482
|
+
if (!parsed || typeof parsed !== "object") continue;
|
|
4483
|
+
row = parsed;
|
|
4484
|
+
} catch {
|
|
4485
|
+
continue;
|
|
4486
|
+
}
|
|
4487
|
+
const content = row.message?.content;
|
|
4488
|
+
if (!Array.isArray(content)) continue;
|
|
4489
|
+
for (const block of content) {
|
|
4490
|
+
if (!block || typeof block !== "object") continue;
|
|
4491
|
+
const b = block;
|
|
4492
|
+
if (b.type === "tool_result" && typeof b.tool_use_id === "string") ids.add(b.tool_use_id);
|
|
4493
|
+
}
|
|
4494
|
+
}
|
|
4495
|
+
return ids;
|
|
4496
|
+
}
|
|
4497
|
+
function assistantTurns(content, ts, promoteFinal = false, erroredIds = /* @__PURE__ */ new Set(), uuid, answeredIds = /* @__PURE__ */ new Set(), pending = /* @__PURE__ */ new Map(), fullRead = true) {
|
|
4400
4498
|
if (!Array.isArray(content)) return [];
|
|
4401
4499
|
const out = [];
|
|
4402
4500
|
for (const block of content) {
|
|
@@ -4430,21 +4528,21 @@ function assistantTurns(content, ts, promoteFinal = false, erroredIds = /* @__PU
|
|
|
4430
4528
|
} else {
|
|
4431
4529
|
out.push({ kind: "agent-file", files, caption, ts });
|
|
4432
4530
|
}
|
|
4433
|
-
} else if (b.type === "tool_use" && typeof b.name === "string" &&
|
|
4434
|
-
const
|
|
4435
|
-
|
|
4436
|
-
|
|
4437
|
-
|
|
4438
|
-
|
|
4439
|
-
ts
|
|
4440
|
-
}
|
|
4531
|
+
} else if (b.type === "tool_use" && typeof b.name === "string" && TELEGRAM_SEND_TOOLS.has(b.name)) {
|
|
4532
|
+
const send = pendingSendOf(b.name, b.input);
|
|
4533
|
+
const id = typeof b.id === "string" ? b.id : null;
|
|
4534
|
+
if (send !== null && id !== null && (answeredIds.has(id) || !fullRead)) {
|
|
4535
|
+
pending.set(id, { ...send, ts });
|
|
4536
|
+
} else {
|
|
4537
|
+
out.push({ kind: "tool-call", name: b.name, input: b.input ?? null, ts });
|
|
4538
|
+
}
|
|
4441
4539
|
} else if (b.type === "tool_use" && typeof b.name === "string") {
|
|
4442
4540
|
out.push({ kind: "tool-call", name: b.name, input: b.input ?? null, ts });
|
|
4443
4541
|
}
|
|
4444
4542
|
}
|
|
4445
4543
|
return out;
|
|
4446
4544
|
}
|
|
4447
|
-
function toolResultTurns(content, ts) {
|
|
4545
|
+
function toolResultTurns(content, ts, pending = /* @__PURE__ */ new Map()) {
|
|
4448
4546
|
if (!Array.isArray(content)) return [];
|
|
4449
4547
|
const out = [];
|
|
4450
4548
|
for (const block of content) {
|
|
@@ -4455,6 +4553,15 @@ function toolResultTurns(content, ts) {
|
|
|
4455
4553
|
(c) => c && typeof c === "object" && typeof c.text === "string" ? c.text : ""
|
|
4456
4554
|
).join("") : "";
|
|
4457
4555
|
out.push({ kind: "tool-result", text, isError: b.is_error === true, ts });
|
|
4556
|
+
const id = b.tool_use_id;
|
|
4557
|
+
if (typeof id !== "string") continue;
|
|
4558
|
+
const send = pending.get(id);
|
|
4559
|
+
if (send === void 0) continue;
|
|
4560
|
+
pending.delete(id);
|
|
4561
|
+
const outcome = send.kind === "telegram-card" ? cardOutcome(text, b.is_error === true) : b.is_error === true ? "failed" : send.edit ? "edited" : "sent";
|
|
4562
|
+
out.push(
|
|
4563
|
+
send.kind === "telegram-card" ? { kind: "telegram-card", text: send.text, buttons: send.buttons, chatId: send.chatId, outcome, ts: send.ts } : { kind: "telegram-send", label: send.label, text: send.text, chatId: send.chatId, outcome, ts: send.ts }
|
|
4564
|
+
);
|
|
4458
4565
|
}
|
|
4459
4566
|
return out;
|
|
4460
4567
|
}
|
|
@@ -4479,9 +4586,11 @@ function renderOrSuppressChannelInbound(u, ts, out, queuedPendingSuppress, uuid,
|
|
|
4479
4586
|
out.push(operatorInboundTurn(u, ts, uuid, census));
|
|
4480
4587
|
}
|
|
4481
4588
|
}
|
|
4482
|
-
function parseTranscript(lines, queuedPendingSuppress = /* @__PURE__ */ new Map(), turnCtx = {}) {
|
|
4589
|
+
function parseTranscript(lines, queuedPendingSuppress = /* @__PURE__ */ new Map(), turnCtx = {}, fullRead = true) {
|
|
4483
4590
|
const out = [];
|
|
4591
|
+
const pendingSends = turnCtx.pendingTelegramSends ??= /* @__PURE__ */ new Map();
|
|
4484
4592
|
const erroredIds = erroredToolUseIds(lines);
|
|
4593
|
+
const answeredIds = lines.some((l) => l.includes("telegram-")) ? answeredToolUseIds(lines) : /* @__PURE__ */ new Set();
|
|
4485
4594
|
for (const line of lines) {
|
|
4486
4595
|
if (!line || line[0] !== "{") continue;
|
|
4487
4596
|
let row;
|
|
@@ -4505,7 +4614,7 @@ function parseTranscript(lines, queuedPendingSuppress = /* @__PURE__ */ new Map(
|
|
|
4505
4614
|
}
|
|
4506
4615
|
const isEnd = msg?.stop_reason === "end_turn";
|
|
4507
4616
|
const promoteFinal = isEnd && turnCtx.lastChannelSource !== void 0;
|
|
4508
|
-
out.push(...assistantTurns(msg?.content, ts, promoteFinal, erroredIds, asString(row.uuid) ?? void 0));
|
|
4617
|
+
out.push(...assistantTurns(msg?.content, ts, promoteFinal, erroredIds, asString(row.uuid) ?? void 0, answeredIds, pendingSends, fullRead));
|
|
4509
4618
|
continue;
|
|
4510
4619
|
}
|
|
4511
4620
|
if (row.type === "queue-operation" && row.operation === "enqueue") {
|
|
@@ -4538,7 +4647,7 @@ function parseTranscript(lines, queuedPendingSuppress = /* @__PURE__ */ new Map(
|
|
|
4538
4647
|
continue;
|
|
4539
4648
|
}
|
|
4540
4649
|
if (Array.isArray(msg.content)) {
|
|
4541
|
-
out.push(...toolResultTurns(msg.content, ts));
|
|
4650
|
+
out.push(...toolResultTurns(msg.content, ts, pendingSends));
|
|
4542
4651
|
continue;
|
|
4543
4652
|
}
|
|
4544
4653
|
const text = asString(msg.content);
|
|
@@ -5650,48 +5759,6 @@ function logPublicAddress(slug, verdict) {
|
|
|
5650
5759
|
import { writeFile, mkdtemp, rm } from "fs/promises";
|
|
5651
5760
|
import { tmpdir as tmpdir2 } from "os";
|
|
5652
5761
|
import { join as join7 } from "path";
|
|
5653
|
-
|
|
5654
|
-
// app/lib/stt/audio-mime.ts
|
|
5655
|
-
var AUDIO_MIME_TYPES = /* @__PURE__ */ new Set([
|
|
5656
|
-
"audio/ogg",
|
|
5657
|
-
"audio/opus",
|
|
5658
|
-
"audio/webm",
|
|
5659
|
-
"audio/mp4",
|
|
5660
|
-
"audio/x-m4a",
|
|
5661
|
-
"audio/mpeg",
|
|
5662
|
-
"audio/wav",
|
|
5663
|
-
"video/mp4"
|
|
5664
|
-
]);
|
|
5665
|
-
function normalizeMime(mimeType) {
|
|
5666
|
-
return mimeType.split(";")[0].trim().toLowerCase();
|
|
5667
|
-
}
|
|
5668
|
-
function isAudioMime(mimeType) {
|
|
5669
|
-
return AUDIO_MIME_TYPES.has(normalizeMime(mimeType));
|
|
5670
|
-
}
|
|
5671
|
-
function audioExtension(mimeType) {
|
|
5672
|
-
switch (normalizeMime(mimeType)) {
|
|
5673
|
-
case "audio/ogg":
|
|
5674
|
-
return ".ogg";
|
|
5675
|
-
case "audio/opus":
|
|
5676
|
-
return ".opus";
|
|
5677
|
-
case "audio/webm":
|
|
5678
|
-
return ".webm";
|
|
5679
|
-
case "audio/mp4":
|
|
5680
|
-
return ".m4a";
|
|
5681
|
-
case "audio/x-m4a":
|
|
5682
|
-
return ".m4a";
|
|
5683
|
-
case "audio/mpeg":
|
|
5684
|
-
return ".mp3";
|
|
5685
|
-
case "audio/wav":
|
|
5686
|
-
return ".wav";
|
|
5687
|
-
case "video/mp4":
|
|
5688
|
-
return ".mp4";
|
|
5689
|
-
default:
|
|
5690
|
-
return ".audio";
|
|
5691
|
-
}
|
|
5692
|
-
}
|
|
5693
|
-
|
|
5694
|
-
// app/lib/stt/voice-note.ts
|
|
5695
5762
|
var TAG4 = "[voice]";
|
|
5696
5763
|
async function transcribeVoiceNote(file, source) {
|
|
5697
5764
|
const startMs = Date.now();
|
|
@@ -7487,7 +7554,7 @@ async function defaultHttpGet(url) {
|
|
|
7487
7554
|
}
|
|
7488
7555
|
}
|
|
7489
7556
|
async function defaultResolve(accountId) {
|
|
7490
|
-
const { resolveSocket: resolveSocket2 } = await import("./manager-
|
|
7557
|
+
const { resolveSocket: resolveSocket2 } = await import("./manager-VDHT3YYI.js");
|
|
7491
7558
|
return resolveSocket2(accountId);
|
|
7492
7559
|
}
|
|
7493
7560
|
async function fetchAvatar(accountId, jid, deps = {}) {
|
|
@@ -15841,7 +15908,7 @@ data: ${JSON.stringify(obj)}
|
|
|
15841
15908
|
const { lines, nextOffset } = splitNewLines(buf, offset);
|
|
15842
15909
|
offset = nextOffset;
|
|
15843
15910
|
let n = 0;
|
|
15844
|
-
for (const turn of parseTranscript(lines, queuedPendingSuppress, turnCtx)) {
|
|
15911
|
+
for (const turn of parseTranscript(lines, queuedPendingSuppress, turnCtx, false)) {
|
|
15845
15912
|
send(controller, enrichAdminAttachments(enrichDownloads(turn, scratchpadRoot), sessionId), offset);
|
|
15846
15913
|
actx.lastParentTurns.push(turn);
|
|
15847
15914
|
if (turn.kind === "agent-error") {
|
|
@@ -16987,6 +17054,19 @@ async function authorizeAccountWrite(c, accountId) {
|
|
|
16987
17054
|
return { ok: true, via: "session" };
|
|
16988
17055
|
}
|
|
16989
17056
|
|
|
17057
|
+
// app/lib/video/webchat-video.ts
|
|
17058
|
+
var TAG26 = "[video]";
|
|
17059
|
+
async function extractWebchatVideo(file, extractImpl = extractVideo) {
|
|
17060
|
+
if (!isVideoMime(file.mimeType)) return void 0;
|
|
17061
|
+
try {
|
|
17062
|
+
return await extractImpl(file.storagePath, file.mimeType);
|
|
17063
|
+
} catch (err) {
|
|
17064
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
17065
|
+
console.error(`${TAG26} webchat extract failed error=${reason} path=${file.storagePath}`);
|
|
17066
|
+
return void 0;
|
|
17067
|
+
}
|
|
17068
|
+
}
|
|
17069
|
+
|
|
16990
17070
|
// ../lib/models/src/index.ts
|
|
16991
17071
|
var OPUS_MODEL = "claude-opus-5[1m]";
|
|
16992
17072
|
var SONNET_MODEL = "claude-sonnet-5";
|
|
@@ -17422,6 +17502,18 @@ async function reapplyLeversViaManager() {
|
|
|
17422
17502
|
}
|
|
17423
17503
|
var WEBCHAT_SEND_TURN_WINDOW_MS = Number(process.env.WEBCHAT_SEND_TURN_WINDOW_MS ?? String(15e3));
|
|
17424
17504
|
var sendSeq = 0;
|
|
17505
|
+
var transcribingKeys = /* @__PURE__ */ new Map();
|
|
17506
|
+
function markTranscribing(key2) {
|
|
17507
|
+
transcribingKeys.set(key2, (transcribingKeys.get(key2) ?? 0) + 1);
|
|
17508
|
+
}
|
|
17509
|
+
function clearTranscribing(key2) {
|
|
17510
|
+
const left = (transcribingKeys.get(key2) ?? 1) - 1;
|
|
17511
|
+
if (left > 0) transcribingKeys.set(key2, left);
|
|
17512
|
+
else transcribingKeys.delete(key2);
|
|
17513
|
+
}
|
|
17514
|
+
function isTranscribing(key2) {
|
|
17515
|
+
return (transcribingKeys.get(key2) ?? 0) > 0;
|
|
17516
|
+
}
|
|
17425
17517
|
function createWebchatRoutes(deps) {
|
|
17426
17518
|
const app81 = new Hono();
|
|
17427
17519
|
app81.post("/send", requireAdminSession, async (c) => {
|
|
@@ -17532,13 +17624,17 @@ function createWebchatRoutes(deps) {
|
|
|
17532
17624
|
deliveryKey = `session:${deliverySessionId}`;
|
|
17533
17625
|
deliveryAccountId = bootstrapAccountId;
|
|
17534
17626
|
}
|
|
17627
|
+
let audioFile;
|
|
17628
|
+
let kind = "files";
|
|
17629
|
+
const stored = [];
|
|
17630
|
+
const sendId = sendIdFromResolve ?? ++sendSeq;
|
|
17535
17631
|
if (isMultipart) {
|
|
17536
|
-
|
|
17632
|
+
kind = files.some((f) => isAudioMime(f.type)) ? "voice" : "files";
|
|
17537
17633
|
if (files.length > MAX_FILES_PER_MESSAGE) {
|
|
17538
17634
|
console.error(`[webchat:inbound] op=send-refused kind=${kind} reason=too-many-files count=${files.length}`);
|
|
17539
17635
|
return c.json({ error: `Maximum ${MAX_FILES_PER_MESSAGE} files per message.` }, 422);
|
|
17540
17636
|
}
|
|
17541
|
-
|
|
17637
|
+
audioFile = files.find((f) => isAudioMime(f.type));
|
|
17542
17638
|
const regularFiles = files.filter((f) => !isAudioMime(f.type));
|
|
17543
17639
|
for (const file of regularFiles) {
|
|
17544
17640
|
try {
|
|
@@ -17552,7 +17648,6 @@ function createWebchatRoutes(deps) {
|
|
|
17552
17648
|
return c.json({ error: detail }, 422);
|
|
17553
17649
|
}
|
|
17554
17650
|
}
|
|
17555
|
-
const stored = [];
|
|
17556
17651
|
if (audioFile) {
|
|
17557
17652
|
if (audioFile.size > MAX_FILE_SIZE_BYTES) {
|
|
17558
17653
|
console.error(`[webchat:inbound] op=send-refused kind=voice reason=oversize bytes=${audioFile.size}`);
|
|
@@ -17565,14 +17660,6 @@ function createWebchatRoutes(deps) {
|
|
|
17565
17660
|
console.error(`[webchat:inbound] op=send-refused kind=voice reason=audio-store-failed detail=${detail}`);
|
|
17566
17661
|
return c.json({ error: "failed to store voice recording" }, 500);
|
|
17567
17662
|
}
|
|
17568
|
-
const result = await transcribeVoiceNote(audioFile, "admin");
|
|
17569
|
-
if (result.ok) {
|
|
17570
|
-
text = text.length > 0 ? `${text}
|
|
17571
|
-
|
|
17572
|
-
${result.result.text}` : result.result.text;
|
|
17573
|
-
} else {
|
|
17574
|
-
console.error(`[webchat:inbound] op=stt-failed kind=voice detail=${result.error}`);
|
|
17575
|
-
}
|
|
17576
17663
|
}
|
|
17577
17664
|
try {
|
|
17578
17665
|
for (const file of regularFiles) {
|
|
@@ -17588,51 +17675,87 @@ ${result.result.text}` : result.result.text;
|
|
|
17588
17675
|
const ext = dot >= 0 ? s.filename.slice(dot).toLowerCase() : "";
|
|
17589
17676
|
console.log(`[attach-ingest] mime=${s.mimeType} ext=${ext} converted=${!!s.readableTextPath} path=${s.storagePath}`);
|
|
17590
17677
|
}
|
|
17591
|
-
if (stored.length
|
|
17592
|
-
const listing = stored.map((s) => `${s.filename} (${s.readableTextPath ?? s.storagePath})`).join(", ");
|
|
17593
|
-
const note = `[The operator uploaded ${stored.length} file(s): ${listing}]`;
|
|
17594
|
-
text = text.length > 0 ? `${text}
|
|
17595
|
-
|
|
17596
|
-
${note}` : note;
|
|
17597
|
-
}
|
|
17598
|
-
if (text.length === 0) {
|
|
17678
|
+
if (text.length === 0 && stored.length === 0) {
|
|
17599
17679
|
console.error(`[webchat:inbound] op=send-refused kind=${kind} reason=empty-text`);
|
|
17600
17680
|
return c.json({ error: "text required" }, 400);
|
|
17601
17681
|
}
|
|
17602
|
-
console.log(`[webchat:inbound] op=send-parsed kind=${kind} files=${stored.length} bytes=${Buffer.byteLength(text, "utf8")}`);
|
|
17603
|
-
}
|
|
17604
|
-
if (target !== void 0 && await managerActivity(deliverySessionId) === "busy") {
|
|
17605
|
-
console.log(`[webchat:inbound] op=queued-busy sessionId=${deliverySessionId.slice(0, 8)} key=${deliveryKey}`);
|
|
17606
17682
|
}
|
|
17607
|
-
const adminUserId = requesterUserId ?? void 0;
|
|
17608
|
-
const inboundStartedAt = Date.now();
|
|
17609
|
-
const sendId = sendIdFromResolve ?? ++sendSeq;
|
|
17610
|
-
const replyContext = resolveQuoted(deliverySessionId, quotedUuid, sendId);
|
|
17611
|
-
const inbound = await deps.handleInbound({
|
|
17612
|
-
role: "admin",
|
|
17613
|
-
accountId: deliveryAccountId,
|
|
17614
|
-
key: deliveryKey,
|
|
17615
|
-
text,
|
|
17616
|
-
sessionId: deliverySessionId,
|
|
17617
|
-
adminUserId,
|
|
17618
|
-
...replyContext ? { replyContext } : {}
|
|
17619
|
-
});
|
|
17620
|
-
const turnSessionId = deliverySessionId;
|
|
17621
17683
|
const keyDisplay2 = deliveryKey.slice(0, "session:".length + 8);
|
|
17622
|
-
const
|
|
17623
|
-
|
|
17624
|
-
|
|
17625
|
-
|
|
17626
|
-
|
|
17627
|
-
|
|
17628
|
-
|
|
17629
|
-
|
|
17630
|
-
|
|
17631
|
-
|
|
17632
|
-
|
|
17684
|
+
const completeSend = async () => {
|
|
17685
|
+
if (isMultipart) {
|
|
17686
|
+
if (audioFile) {
|
|
17687
|
+
const result = await transcribeVoiceNote(audioFile, "admin");
|
|
17688
|
+
if (result.ok) {
|
|
17689
|
+
text = text.length > 0 ? `${text}
|
|
17690
|
+
|
|
17691
|
+
${result.result.text}` : result.result.text;
|
|
17692
|
+
} else {
|
|
17693
|
+
console.error(`[webchat:inbound] op=stt-failed kind=voice detail=${result.error}`);
|
|
17694
|
+
}
|
|
17695
|
+
}
|
|
17696
|
+
if (stored.length > 0) {
|
|
17697
|
+
const listing = stored.map((s) => `${s.filename} (${s.readableTextPath ?? s.storagePath})`).join(", ");
|
|
17698
|
+
const note = `[The operator uploaded ${stored.length} file(s): ${listing}]`;
|
|
17699
|
+
text = text.length > 0 ? `${text}
|
|
17700
|
+
|
|
17701
|
+
${note}` : note;
|
|
17702
|
+
}
|
|
17703
|
+
for (const s of stored) {
|
|
17704
|
+
const timeline = await extractWebchatVideo(s);
|
|
17705
|
+
if (timeline) text = `${text}
|
|
17706
|
+
|
|
17707
|
+
${timeline}`;
|
|
17708
|
+
}
|
|
17709
|
+
console.log(`[webchat:inbound] op=send-parsed kind=${kind} files=${stored.length} bytes=${Buffer.byteLength(text, "utf8")}`);
|
|
17633
17710
|
}
|
|
17634
|
-
|
|
17635
|
-
|
|
17711
|
+
if (target !== void 0 && await managerActivity(deliverySessionId) === "busy") {
|
|
17712
|
+
console.log(`[webchat:inbound] op=queued-busy sessionId=${deliverySessionId.slice(0, 8)} key=${deliveryKey}`);
|
|
17713
|
+
}
|
|
17714
|
+
const adminUserId = requesterUserId ?? void 0;
|
|
17715
|
+
const inboundStartedAt = Date.now();
|
|
17716
|
+
const replyContext = resolveQuoted(deliverySessionId, quotedUuid, sendId);
|
|
17717
|
+
const inbound = await deps.handleInbound({
|
|
17718
|
+
role: "admin",
|
|
17719
|
+
accountId: deliveryAccountId,
|
|
17720
|
+
key: deliveryKey,
|
|
17721
|
+
text,
|
|
17722
|
+
sessionId: deliverySessionId,
|
|
17723
|
+
adminUserId,
|
|
17724
|
+
...replyContext ? { replyContext } : {}
|
|
17725
|
+
});
|
|
17726
|
+
const turnSessionId = deliverySessionId;
|
|
17727
|
+
const baseline = jsonlSizeBytes(locateSession(turnSessionId).projectDir, turnSessionId);
|
|
17728
|
+
console.error(
|
|
17729
|
+
`[webchat:inbound] op=send-accepted key=${keyDisplay2} sendId=${sendId} baselineBytes=${baseline ?? "absent"} acceptMs=${Date.now() - inboundStartedAt} spawn=${inbound.spawn !== null ? "triggered" : "none"}`
|
|
17730
|
+
);
|
|
17731
|
+
const turnTimer = setTimeout(() => {
|
|
17732
|
+
const now = jsonlSizeBytes(locateSession(turnSessionId).projectDir, turnSessionId);
|
|
17733
|
+
const grew = now !== null && (baseline === null || now > baseline);
|
|
17734
|
+
if (grew) {
|
|
17735
|
+
console.error(`[webchat:inbound] op=send-turned key=${keyDisplay2} sendId=${sendId} bytes=${now}`);
|
|
17736
|
+
} else {
|
|
17737
|
+
console.error(`[webchat:inbound] op=send-no-turn key=${keyDisplay2} sendId=${sendId} baselineBytes=${baseline ?? "absent"}`);
|
|
17738
|
+
}
|
|
17739
|
+
}, WEBCHAT_SEND_TURN_WINDOW_MS);
|
|
17740
|
+
if (turnTimer.unref) turnTimer.unref();
|
|
17741
|
+
};
|
|
17742
|
+
const deferred = audioFile !== void 0 || stored.some((s) => isVideoMime(s.mimeType));
|
|
17743
|
+
if (deferred) {
|
|
17744
|
+
markTranscribing(deliveryKey);
|
|
17745
|
+
notify("webchat-pointer", deliveryAccountId);
|
|
17746
|
+
const stagedBytes = stored.reduce((n, s) => n + s.sizeBytes, 0);
|
|
17747
|
+
console.log(`[webchat:inbound] op=send-staged kind=${kind} key=${keyDisplay2} bytes=${stagedBytes}`);
|
|
17748
|
+
void completeSend().catch((err) => {
|
|
17749
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
17750
|
+
console.error(`[webchat:inbound] op=send-continuation-failed key=${keyDisplay2} detail=${detail}`);
|
|
17751
|
+
deps.markDeliveryFailure?.(deliveryKey, `send-${sendId}`);
|
|
17752
|
+
}).finally(() => {
|
|
17753
|
+
clearTranscribing(deliveryKey);
|
|
17754
|
+
notify("webchat-pointer", deliveryAccountId);
|
|
17755
|
+
});
|
|
17756
|
+
return c.json({ ok: true, transcribing: true });
|
|
17757
|
+
}
|
|
17758
|
+
await completeSend();
|
|
17636
17759
|
return c.json({ ok: true });
|
|
17637
17760
|
});
|
|
17638
17761
|
app81.post("/interrupt", requireAdminSession, async (c) => {
|
|
@@ -17742,7 +17865,7 @@ ${note}` : note;
|
|
|
17742
17865
|
}
|
|
17743
17866
|
const known = resolvedProjectDir !== null || sessionSidecarExists(target);
|
|
17744
17867
|
const indicators2 = await fetchComposerIndicators(target);
|
|
17745
|
-
return c.json({ sessionId: target, projectDir: resolvedProjectDir, transcriptSessionId, channelBinding: conflictingBinding(channel), known, sizeBytes: jsonlSizeBytes(projectDir2, target), pendingPermissionPrompt: deps.pendingPromptFor?.(`session:${target}`) ?? null, deliveryFailure: deps.deliveryFailureFor?.(`session:${target}`) ?? null, ...indicators2, ...readLevers(scopeAccountId ? validateAccountId2(scopeAccountId) : null) });
|
|
17868
|
+
return c.json({ sessionId: target, projectDir: resolvedProjectDir, transcriptSessionId, channelBinding: conflictingBinding(channel), known, sizeBytes: jsonlSizeBytes(projectDir2, target), pendingPermissionPrompt: deps.pendingPromptFor?.(`session:${target}`) ?? null, deliveryFailure: deps.deliveryFailureFor?.(`session:${target}`) ?? null, transcribing: isTranscribing(`session:${target}`), ...indicators2, ...readLevers(scopeAccountId ? validateAccountId2(scopeAccountId) : null) });
|
|
17746
17869
|
}
|
|
17747
17870
|
const account = scopeAccountId ? validateAccountId2(scopeAccountId) : null;
|
|
17748
17871
|
const { sessionId, source } = resolveCanonical(accountId, account?.accountDir ?? null, requesterUserId, primaryUserId, scopeAccountId, multiAccount);
|
|
@@ -17770,7 +17893,7 @@ ${note}` : note;
|
|
|
17770
17893
|
}
|
|
17771
17894
|
}
|
|
17772
17895
|
const indicators = await fetchComposerIndicators(sessionId);
|
|
17773
|
-
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) });
|
|
17896
|
+
return c.json({ sessionId, projectDir, source, sizeBytes: jsonlSizeBytes(projectDir, sessionId), pendingPermissionPrompt: deps.pendingPromptFor?.(`session:${sessionId}`) ?? null, deliveryFailure: deps.deliveryFailureFor?.(`session:${sessionId}`) ?? null, transcribing: isTranscribing(`session:${sessionId}`), ...indicators, ...readLevers(account) });
|
|
17774
17897
|
});
|
|
17775
17898
|
app81.post("/permission-verdict", requireAdminSession, async (c) => {
|
|
17776
17899
|
const body = await c.req.json().catch(() => null);
|
|
@@ -18997,7 +19120,7 @@ function routeTelegramUpdate(input) {
|
|
|
18997
19120
|
// app/lib/telegram/inbound/media.ts
|
|
18998
19121
|
var import_dist5 = __toESM(require_dist4(), 1);
|
|
18999
19122
|
import { join as join37 } from "path";
|
|
19000
|
-
var
|
|
19123
|
+
var TAG27 = "[telegram-inbound]";
|
|
19001
19124
|
var TELEGRAM_MEDIA_DIR = "/tmp/maxy-media";
|
|
19002
19125
|
var DOWNLOAD_TIMEOUT_MS = 45e3;
|
|
19003
19126
|
async function downloadTelegramMedia(input) {
|
|
@@ -19046,7 +19169,7 @@ async function downloadTelegramMedia(input) {
|
|
|
19046
19169
|
result = { ...base, failure: err instanceof Error ? err.message : String(err) };
|
|
19047
19170
|
}
|
|
19048
19171
|
console.error(
|
|
19049
|
-
`${
|
|
19172
|
+
`${TAG27} op=media-download botId=${input.botId} type=${item.type} ok=${result.path ? "yes" : "no"} bytes=${bytes} path=${result.path ?? "-"} reason=${result.failure ?? "-"}`
|
|
19050
19173
|
);
|
|
19051
19174
|
out.push(result);
|
|
19052
19175
|
}
|
|
@@ -19056,7 +19179,7 @@ async function downloadTelegramMedia(input) {
|
|
|
19056
19179
|
// app/lib/telegram/inbound/servable.ts
|
|
19057
19180
|
import { readFile as readFile6 } from "fs/promises";
|
|
19058
19181
|
import { basename as basename12 } from "path";
|
|
19059
|
-
var
|
|
19182
|
+
var TAG28 = "[telegram-inbound]";
|
|
19060
19183
|
async function storeTelegramServable(input) {
|
|
19061
19184
|
const out = [];
|
|
19062
19185
|
for (const [index, item] of input.media.entries()) {
|
|
@@ -19070,12 +19193,12 @@ async function storeTelegramServable(input) {
|
|
|
19070
19193
|
}
|
|
19071
19194
|
out.push(attachmentId);
|
|
19072
19195
|
console.error(
|
|
19073
|
-
`${
|
|
19196
|
+
`${TAG28} op=servable-store ok=true type=${item.type} id=${attachmentId}`
|
|
19074
19197
|
);
|
|
19075
19198
|
} catch (err) {
|
|
19076
19199
|
const reason = err instanceof Error ? err.message : String(err);
|
|
19077
19200
|
console.error(
|
|
19078
|
-
`${
|
|
19201
|
+
`${TAG28} op=servable-store ok=false type=${item.type} id=${attachmentId} reason=${reason.slice(0, 100)}`
|
|
19079
19202
|
);
|
|
19080
19203
|
}
|
|
19081
19204
|
}
|
|
@@ -19083,7 +19206,7 @@ async function storeTelegramServable(input) {
|
|
|
19083
19206
|
}
|
|
19084
19207
|
|
|
19085
19208
|
// app/lib/telegram/inbound/transcribe.ts
|
|
19086
|
-
var
|
|
19209
|
+
var TAG29 = "[telegram-inbound]";
|
|
19087
19210
|
async function transcribeTelegramAudio(input) {
|
|
19088
19211
|
const doTranscribe = input.transcribeImpl ?? transcribe;
|
|
19089
19212
|
const out = [];
|
|
@@ -19095,7 +19218,7 @@ async function transcribeTelegramAudio(input) {
|
|
|
19095
19218
|
}
|
|
19096
19219
|
if (!m.path) {
|
|
19097
19220
|
console.error(
|
|
19098
|
-
`${
|
|
19221
|
+
`${TAG29} op=transcribe botId=${input.botId} ok=no chars=0 ms=0 reason=${m.failure ?? "no local file"}`
|
|
19099
19222
|
);
|
|
19100
19223
|
out.push(m);
|
|
19101
19224
|
continue;
|
|
@@ -19112,7 +19235,7 @@ async function transcribeTelegramAudio(input) {
|
|
|
19112
19235
|
reason = err instanceof Error ? err.message : String(err);
|
|
19113
19236
|
}
|
|
19114
19237
|
console.error(
|
|
19115
|
-
`${
|
|
19238
|
+
`${TAG29} op=transcribe botId=${input.botId} ok=${heard ? "yes" : "no"} chars=${heard?.length ?? 0} ms=${Date.now() - startedMs} reason=${reason}`
|
|
19116
19239
|
);
|
|
19117
19240
|
if (heard) {
|
|
19118
19241
|
transcripts.push(heard);
|
|
@@ -19129,6 +19252,33 @@ async function transcribeTelegramAudio(input) {
|
|
|
19129
19252
|
${body}` : body, media: out };
|
|
19130
19253
|
}
|
|
19131
19254
|
|
|
19255
|
+
// app/lib/telegram/inbound/video.ts
|
|
19256
|
+
var TAG30 = "[telegram-inbound]";
|
|
19257
|
+
async function extractTelegramVideo(input) {
|
|
19258
|
+
const doExtract = input.extractImpl ?? extractVideo;
|
|
19259
|
+
const out = [];
|
|
19260
|
+
for (const m of input.media) {
|
|
19261
|
+
if (m.type !== "video" || !m.path) {
|
|
19262
|
+
out.push(m);
|
|
19263
|
+
continue;
|
|
19264
|
+
}
|
|
19265
|
+
const startedMs = Date.now();
|
|
19266
|
+
let timeline;
|
|
19267
|
+
let reason = "-";
|
|
19268
|
+
try {
|
|
19269
|
+
timeline = await doExtract(m.path, m.mimetype ?? "");
|
|
19270
|
+
if (!timeline) reason = "no timeline returned";
|
|
19271
|
+
} catch (err) {
|
|
19272
|
+
reason = err instanceof Error ? err.message : String(err);
|
|
19273
|
+
}
|
|
19274
|
+
console.error(
|
|
19275
|
+
`${TAG30} op=video-extract botId=${input.botId} ok=${timeline ? "yes" : "no"} chars=${timeline?.length ?? 0} ms=${Date.now() - startedMs} reason=${reason}`
|
|
19276
|
+
);
|
|
19277
|
+
out.push(timeline ? { ...m, timeline } : m);
|
|
19278
|
+
}
|
|
19279
|
+
return { media: out };
|
|
19280
|
+
}
|
|
19281
|
+
|
|
19132
19282
|
// app/lib/telegram/gateway/telegram-inbound-census.ts
|
|
19133
19283
|
var ANSWER_THRESHOLD_MS = 3e4;
|
|
19134
19284
|
var GAP_NAME_LIMIT2 = 10;
|
|
@@ -19571,7 +19721,7 @@ async function visitStatusSet(p) {
|
|
|
19571
19721
|
}
|
|
19572
19722
|
|
|
19573
19723
|
// app/lib/telegram/dispatch/press.ts
|
|
19574
|
-
var
|
|
19724
|
+
var TAG31 = "[dispatch-tg]";
|
|
19575
19725
|
function logValue(v) {
|
|
19576
19726
|
return v.replace(/[\r\n]+/g, " ");
|
|
19577
19727
|
}
|
|
@@ -19632,12 +19782,12 @@ async function handleDispatchPress(p) {
|
|
|
19632
19782
|
status: ${status}`;
|
|
19633
19783
|
const done = await p.edit(p.token, p.chatId, p.messageId, text, toBotApiKeyboard(kb.rows));
|
|
19634
19784
|
p.emit(
|
|
19635
|
-
`${
|
|
19785
|
+
`${TAG31} op=card-redrawn visitId=${logVisitId} messageId=${p.messageId} buttons=${kb.rows.flat().length} drawnFor=${logValue(status)}` + (done.ok ? "" : ` editError="${logValue(done.error ?? "unknown")}"`)
|
|
19636
19786
|
);
|
|
19637
19787
|
};
|
|
19638
19788
|
if (visit.status !== parsed.drawnFor) {
|
|
19639
19789
|
p.emit(
|
|
19640
|
-
`${
|
|
19790
|
+
`${TAG31} op=callback-stale updateId=${u} visitId=${logVisitId} expected=${logDrawnFor} actual=${logValue(visit.status)}`
|
|
19641
19791
|
);
|
|
19642
19792
|
await redraw(visit.status);
|
|
19643
19793
|
return {
|
|
@@ -19664,7 +19814,7 @@ status: ${status}`;
|
|
|
19664
19814
|
return { kind: "refused", reason: out.reason, answer: out.message };
|
|
19665
19815
|
}
|
|
19666
19816
|
p.emit(
|
|
19667
|
-
`${
|
|
19817
|
+
`${TAG31} op=callback-applied updateId=${u} visitId=${logVisitId} from=${logValue(out.value.from)} to=${logValue(out.value.to)} tool=dispatch-visit-status-set ms=${Date.now() - startedAt}`
|
|
19668
19818
|
);
|
|
19669
19819
|
await redraw(out.value.to);
|
|
19670
19820
|
return {
|
|
@@ -19691,7 +19841,7 @@ async function bindChatToVisit(p) {
|
|
|
19691
19841
|
}
|
|
19692
19842
|
|
|
19693
19843
|
// app/lib/telegram/dispatch/location.ts
|
|
19694
|
-
var
|
|
19844
|
+
var TAG32 = "[dispatch-tg]";
|
|
19695
19845
|
async function handleDispatchLocation(p) {
|
|
19696
19846
|
const bound = await bindChatToVisit({
|
|
19697
19847
|
session: p.session,
|
|
@@ -19708,7 +19858,7 @@ async function handleDispatchLocation(p) {
|
|
|
19708
19858
|
at: { latitude: p.latitude, longitude: p.longitude }
|
|
19709
19859
|
});
|
|
19710
19860
|
p.emit(
|
|
19711
|
-
`${
|
|
19861
|
+
`${TAG32} op=location-update visitId=${bound.visit.visitId} workerId=${bound.worker.workerId} distanceM=${v.distanceM ?? "none"} inside=${v.inside} siteHasCoords=${v.siteHasCoords} radiusM=${v.radiusM ?? "none"}`
|
|
19712
19862
|
);
|
|
19713
19863
|
if (!v.siteHasCoords) return { kind: "no-coords" };
|
|
19714
19864
|
if (v.radiusM === null) return { kind: "no-radius" };
|
|
@@ -19726,12 +19876,12 @@ async function handleDispatchLocation(p) {
|
|
|
19726
19876
|
});
|
|
19727
19877
|
if (!rec.ok) {
|
|
19728
19878
|
p.emit(
|
|
19729
|
-
`${
|
|
19879
|
+
`${TAG32} op=geofence-refused visitId=${bound.visit.visitId} workerId=${bound.worker.workerId} distanceM=${v.distanceM} reason=${rec.reason}`
|
|
19730
19880
|
);
|
|
19731
19881
|
return { kind: "not-recorded" };
|
|
19732
19882
|
}
|
|
19733
19883
|
p.emit(
|
|
19734
|
-
`${
|
|
19884
|
+
`${TAG32} op=geofence-enter visitId=${bound.visit.visitId} observedAt=${observedAt} distanceM=${v.distanceM} pressedAt=${bound.visit.arrivedPressedAt ?? "none"}`
|
|
19735
19885
|
);
|
|
19736
19886
|
return { kind: "recorded" };
|
|
19737
19887
|
}
|
|
@@ -19763,7 +19913,7 @@ function readTgActivity(accountId) {
|
|
|
19763
19913
|
}
|
|
19764
19914
|
|
|
19765
19915
|
// app/lib/telegram/dispatch/media.ts
|
|
19766
|
-
var
|
|
19916
|
+
var TAG33 = "[dispatch-tg]";
|
|
19767
19917
|
async function handleDispatchMedia(p) {
|
|
19768
19918
|
const bound = await bindChatToVisit({
|
|
19769
19919
|
session: p.session,
|
|
@@ -19774,14 +19924,14 @@ async function handleDispatchMedia(p) {
|
|
|
19774
19924
|
if (bound.kind !== "bound") {
|
|
19775
19925
|
const tell = bound.kind === "no-open-visit" ? `You have no open ${p.cfg.vocabulary.visit}, so I have kept this in the chat. Open one and send it again.` : bound.kind === "many-open-visits" ? `You have ${bound.visits.length} open ${p.cfg.vocabulary.visit}s, so I have kept this in the chat rather than guessing. Open the one you mean in the job sheet and send it there.` : null;
|
|
19776
19926
|
p.emit(
|
|
19777
|
-
`${
|
|
19927
|
+
`${TAG33} op=unbound-inbound chatId=${p.telegramUserId} kind=${p.kind} reason=${bound.kind} told=${tell !== null}`
|
|
19778
19928
|
);
|
|
19779
19929
|
return { kind: "unattached", reason: bound.kind, tell };
|
|
19780
19930
|
}
|
|
19781
19931
|
const visitId = bound.visit.visitId;
|
|
19782
19932
|
if (p.kind === "voice") {
|
|
19783
19933
|
p.emit(
|
|
19784
|
-
`${
|
|
19934
|
+
`${TAG33} op=voice-received visitId=${visitId} durationS=${p.durationS ?? "none"} bytes=${p.bytes ?? "none"}`
|
|
19785
19935
|
);
|
|
19786
19936
|
noteVoiceReceived(p.accountId, visitId);
|
|
19787
19937
|
if (p.transcript === null || p.transcript.length === 0) {
|
|
@@ -19801,7 +19951,7 @@ async function handleDispatchMedia(p) {
|
|
|
19801
19951
|
note: p.transcript
|
|
19802
19952
|
});
|
|
19803
19953
|
p.emit(
|
|
19804
|
-
`${
|
|
19954
|
+
`${TAG33} op=voice-transcribed visitId=${visitId} chars=${p.transcript.length} ms=${Date.now() - startedAt}`
|
|
19805
19955
|
);
|
|
19806
19956
|
noteVoiceTranscribed(p.accountId, visitId);
|
|
19807
19957
|
return { kind: "note", visitId };
|
|
@@ -19821,14 +19971,14 @@ async function handleDispatchMedia(p) {
|
|
|
19821
19971
|
visitId,
|
|
19822
19972
|
mediaRef: p.path
|
|
19823
19973
|
});
|
|
19824
|
-
p.emit(`${
|
|
19974
|
+
p.emit(`${TAG33} op=media-attached visitId=${visitId} kind=${p.kind} path=${p.path}`);
|
|
19825
19975
|
return { kind: "media", visitId };
|
|
19826
19976
|
}
|
|
19827
19977
|
|
|
19828
19978
|
// app/lib/telegram/live-location.ts
|
|
19829
19979
|
import { existsSync as existsSync26, mkdirSync as mkdirSync6, readFileSync as readFileSync30, readdirSync as readdirSync20, statSync as statSync19, writeFileSync as writeFileSync13 } from "fs";
|
|
19830
19980
|
import { join as join38 } from "path";
|
|
19831
|
-
var
|
|
19981
|
+
var TAG34 = "[telegram-inbound]";
|
|
19832
19982
|
var LIVE_LOCATION_FILE = "telegram-live-location.json";
|
|
19833
19983
|
var LIVE_LOCATION_CENSUS_TAG = "[telegram-live-location-census]";
|
|
19834
19984
|
function liveLocationKey(botId, senderId) {
|
|
@@ -19864,12 +20014,12 @@ function writeLiveLocation(input) {
|
|
|
19864
20014
|
const livePeriodS = input.livePeriodS ?? stored[key2]?.livePeriodS ?? null;
|
|
19865
20015
|
if (livePeriodS === null) {
|
|
19866
20016
|
emit(
|
|
19867
|
-
`${
|
|
20017
|
+
`${TAG34} op=live-location op=skipped-write senderId=${senderId} botId=${botId} reason=no-live-period`
|
|
19868
20018
|
);
|
|
19869
20019
|
return { written: false, reason: "no-live-period" };
|
|
19870
20020
|
}
|
|
19871
20021
|
if (input.atS === null) {
|
|
19872
|
-
emit(`${
|
|
20022
|
+
emit(`${TAG34} op=live-location op=skipped-write senderId=${senderId} botId=${botId} reason=no-date`);
|
|
19873
20023
|
return { written: false, reason: "no-date" };
|
|
19874
20024
|
}
|
|
19875
20025
|
const next = {
|
|
@@ -19887,7 +20037,7 @@ function writeLiveLocation(input) {
|
|
|
19887
20037
|
mkdirSync6(accountDir, { recursive: true });
|
|
19888
20038
|
writeFileSync13(path, JSON.stringify(kept, null, 2) + "\n", "utf-8");
|
|
19889
20039
|
emit(
|
|
19890
|
-
`${
|
|
20040
|
+
`${TAG34} op=live-location op=updated senderId=${senderId} botId=${botId} ageMs=${now - next.at} livePeriodS=${livePeriodS}`
|
|
19891
20041
|
);
|
|
19892
20042
|
return { written: true };
|
|
19893
20043
|
}
|
|
@@ -19931,7 +20081,7 @@ function liveLocationCensusLine(accountsRoot, now) {
|
|
|
19931
20081
|
// app/lib/telegram/business-connection.ts
|
|
19932
20082
|
import { existsSync as existsSync27, mkdirSync as mkdirSync7, readFileSync as readFileSync31, writeFileSync as writeFileSync14 } from "fs";
|
|
19933
20083
|
import { join as join39 } from "path";
|
|
19934
|
-
var
|
|
20084
|
+
var TAG35 = "[telegram-inbound]";
|
|
19935
20085
|
var BUSINESS_CONNECTION_FILE = "telegram-business-connection.json";
|
|
19936
20086
|
function truncateConnectionId(id) {
|
|
19937
20087
|
return `${id.slice(0, 6)}\u2026`;
|
|
@@ -19964,7 +20114,7 @@ function writeBusinessConnection(input) {
|
|
|
19964
20114
|
const canReply = rights?.can_reply === true;
|
|
19965
20115
|
const say = (stored, reason) => {
|
|
19966
20116
|
emit(
|
|
19967
|
-
`${
|
|
20117
|
+
`${TAG35} op=business-connection botId=${botId} connectionId=${id === null ? "none" : truncateConnectionId(id)} userId=${userId ?? "none"} isEnabled=${isEnabled} canReply=${canReply} stored=${stored} reason=${reason}`
|
|
19968
20118
|
);
|
|
19969
20119
|
};
|
|
19970
20120
|
if (id === null) {
|
|
@@ -20043,7 +20193,7 @@ async function editTelegramMessage(botToken, chatId, messageId, text, keyboard)
|
|
|
20043
20193
|
}
|
|
20044
20194
|
|
|
20045
20195
|
// server/routes/telegram.ts
|
|
20046
|
-
var
|
|
20196
|
+
var TAG36 = "[telegram-inbound]";
|
|
20047
20197
|
var PROVISION_TAG = "[telegram-provision]";
|
|
20048
20198
|
function entryActive(entry3, accountDir, botId, noteSpecialist) {
|
|
20049
20199
|
if (entry3.role === "admin") return true;
|
|
@@ -20053,7 +20203,7 @@ function entryActive(entry3, accountDir, botId, noteSpecialist) {
|
|
|
20053
20203
|
noteSpecialist?.(rosterValid);
|
|
20054
20204
|
if (rosterValid) return true;
|
|
20055
20205
|
console.error(
|
|
20056
|
-
`${
|
|
20206
|
+
`${TAG36} op=specialist-refused botId=${botId} specialist=${logValue2(entry3.specialist)} reason=specialist-unknown`
|
|
20057
20207
|
);
|
|
20058
20208
|
return false;
|
|
20059
20209
|
}
|
|
@@ -20104,13 +20254,13 @@ function accountConfig(accountDir) {
|
|
|
20104
20254
|
function raiseChannelTurn(input) {
|
|
20105
20255
|
if (!input.active) {
|
|
20106
20256
|
console.error(
|
|
20107
|
-
`${
|
|
20257
|
+
`${TAG36} op=reject reason=agent-inactive botId=${input.botId} agent=${input.agentSlug}`
|
|
20108
20258
|
);
|
|
20109
20259
|
return;
|
|
20110
20260
|
}
|
|
20111
20261
|
const gateway = getTelegramGateway();
|
|
20112
20262
|
if (!gateway) {
|
|
20113
|
-
console.error(`${
|
|
20263
|
+
console.error(`${TAG36} op=reply-dropped botId=${input.botId} reason=gateway-not-ready`);
|
|
20114
20264
|
return;
|
|
20115
20265
|
}
|
|
20116
20266
|
const reply = async (replyText) => {
|
|
@@ -20131,8 +20281,8 @@ function raiseChannelTurn(input) {
|
|
|
20131
20281
|
origin: "agent",
|
|
20132
20282
|
createdAt: at
|
|
20133
20283
|
});
|
|
20134
|
-
console.error(`${
|
|
20135
|
-
} else console.error(`${
|
|
20284
|
+
console.error(`${TAG36} op=reply-sent botId=${input.botId} ok=true`);
|
|
20285
|
+
} else console.error(`${TAG36} op=reply-dropped botId=${input.botId} reason=${sent.error}`);
|
|
20136
20286
|
};
|
|
20137
20287
|
void gateway.handleInbound({
|
|
20138
20288
|
accountId: input.accountId,
|
|
@@ -20157,34 +20307,34 @@ var app11 = new Hono();
|
|
|
20157
20307
|
app11.post("/", async (c) => {
|
|
20158
20308
|
const botId = c.req.query("bot");
|
|
20159
20309
|
if (!botId) {
|
|
20160
|
-
console.error(`${
|
|
20310
|
+
console.error(`${TAG36} op=reject reason=missing-bot-param`);
|
|
20161
20311
|
return c.json({ ok: false }, 400);
|
|
20162
20312
|
}
|
|
20163
|
-
console.error(`${
|
|
20313
|
+
console.error(`${TAG36} op=received botId=${botId} path=/api/telegram/`);
|
|
20164
20314
|
const resolved = resolveBotEntry(listValidAccounts(), botId);
|
|
20165
20315
|
if (resolved.kind === "none") {
|
|
20166
|
-
console.error(`${
|
|
20316
|
+
console.error(`${TAG36} op=reject reason=unknown-bot botId=${botId}`);
|
|
20167
20317
|
return c.json({ ok: false }, 401);
|
|
20168
20318
|
}
|
|
20169
20319
|
if (resolved.kind === "duplicate") {
|
|
20170
|
-
console.error(`${
|
|
20320
|
+
console.error(`${TAG36} op=reject reason=duplicate-bot-id botId=${botId} accounts=${resolved.count}`);
|
|
20171
20321
|
return c.json({ ok: false }, 401);
|
|
20172
20322
|
}
|
|
20173
20323
|
const { accountId, accountDir, entry: entry3 } = resolved;
|
|
20174
20324
|
const agentSlug = entryAgentSlug(entry3);
|
|
20175
|
-
console.error(`${
|
|
20325
|
+
console.error(`${TAG36} op=entry botId=${botId} accountId=${accountId} role=${entry3.role} agent=${agentSlug}`);
|
|
20176
20326
|
const sp = secretPath(botId);
|
|
20177
20327
|
if (!existsSync28(sp)) {
|
|
20178
|
-
console.error(`${
|
|
20328
|
+
console.error(`${TAG36} op=secret botId=${botId} result=missing-file`);
|
|
20179
20329
|
return c.json({ ok: false }, 401);
|
|
20180
20330
|
}
|
|
20181
20331
|
const expected = readFileSync32(sp, "utf-8").trim();
|
|
20182
20332
|
const got = c.req.header("x-telegram-bot-api-secret-token") ?? "";
|
|
20183
20333
|
if (got !== expected) {
|
|
20184
|
-
console.error(`${
|
|
20334
|
+
console.error(`${TAG36} op=secret botId=${botId} result=mismatch`);
|
|
20185
20335
|
return c.json({ ok: false }, 401);
|
|
20186
20336
|
}
|
|
20187
|
-
console.error(`${
|
|
20337
|
+
console.error(`${TAG36} op=secret botId=${botId} result=ok`);
|
|
20188
20338
|
let update;
|
|
20189
20339
|
try {
|
|
20190
20340
|
update = await c.req.json();
|
|
@@ -20193,7 +20343,7 @@ app11.post("/", async (c) => {
|
|
|
20193
20343
|
}
|
|
20194
20344
|
const shape = describeTelegramUpdate(update);
|
|
20195
20345
|
console.error(
|
|
20196
|
-
`${
|
|
20346
|
+
`${TAG36} op=inbound-kind botId=${botId} update=${shape.envelope} content=${shape.content} chatType=${shape.chatType} isEdit=${shape.isEdit ? "yes" : "no"}`
|
|
20197
20347
|
);
|
|
20198
20348
|
if (update.business_connection) {
|
|
20199
20349
|
writeBusinessConnection({
|
|
@@ -20207,13 +20357,13 @@ app11.post("/", async (c) => {
|
|
|
20207
20357
|
if (shape.chatType === "group" || shape.chatType === "supergroup") {
|
|
20208
20358
|
const allowlisted = entry3.role === "public" && (entry3.groupPolicy ?? "disabled") === "allowlist" && shape.chatId !== null && (entry3.allowGroups ?? []).includes(shape.chatId);
|
|
20209
20359
|
console.error(
|
|
20210
|
-
`${
|
|
20360
|
+
`${TAG36} op=group-inbound botId=${botId} chatType=${shape.chatType} chatId=${shape.chatId ?? "none"} senderId=${shape.senderId ?? "none"} threadId=${shape.threadId ?? "none"} allowlisted=${allowlisted ? "yes" : "no"}`
|
|
20211
20361
|
);
|
|
20212
20362
|
}
|
|
20213
20363
|
if (shape.chatType === "channel") {
|
|
20214
20364
|
const allowlisted = entry3.role === "public" && (entry3.channelPolicy ?? "disabled") === "allowlist" && shape.chatId !== null && (entry3.allowChannels ?? []).includes(shape.chatId);
|
|
20215
20365
|
console.error(
|
|
20216
|
-
`${
|
|
20366
|
+
`${TAG36} op=channel-post botId=${botId} chatId=${shape.chatId ?? "none"} messageId=${shape.messageId ?? "none"} senderChat=${shape.senderChat ?? "none"} isEdit=${shape.isEdit ? "yes" : "no"} allowlisted=${allowlisted ? "yes" : "no"}`
|
|
20217
20367
|
);
|
|
20218
20368
|
}
|
|
20219
20369
|
const hostBots = update.managed_bot ? listBotEntries(accountConfig(accountDir).telegram) : [];
|
|
@@ -20234,56 +20384,56 @@ app11.post("/", async (c) => {
|
|
|
20234
20384
|
decision.kind === "managed-bot" && decision.authorised && decision.event === "created";
|
|
20235
20385
|
noteInboundKind(shape.primaryKind, raisesTurn, shape.envelope);
|
|
20236
20386
|
if (decision.kind === "ignore") {
|
|
20237
|
-
console.error(`${
|
|
20387
|
+
console.error(`${TAG36} op=ignore botId=${botId} reason=${decision.reason}`);
|
|
20238
20388
|
return c.json({ ok: true }, 200);
|
|
20239
20389
|
}
|
|
20240
20390
|
if (decision.kind === "denied") {
|
|
20241
20391
|
if (decision.reason === "admin-entry-no-groups" || decision.reason === "not-in-allowGroups" || decision.reason === "group-policy-disabled") {
|
|
20242
20392
|
console.error(
|
|
20243
|
-
`${
|
|
20393
|
+
`${TAG36} op=group-refused botId=${botId} chatId=${shape.chatId ?? "none"} reason=${decision.reason}`
|
|
20244
20394
|
);
|
|
20245
20395
|
}
|
|
20246
20396
|
if (decision.reason === "admin-entry-no-channels" || decision.reason === "specialist-entry-no-channels" || decision.reason === "unbound-entry-no-channels" || decision.reason === "not-in-allowChannels" || decision.reason === "channel-policy-disabled") {
|
|
20247
20397
|
console.error(
|
|
20248
|
-
`${
|
|
20398
|
+
`${TAG36} op=channel-refused botId=${botId} chatId=${shape.chatId ?? "none"} reason=${decision.reason}`
|
|
20249
20399
|
);
|
|
20250
20400
|
}
|
|
20251
|
-
console.error(`${
|
|
20401
|
+
console.error(`${TAG36} op=access botId=${botId} senderId=- allowed=false reason=${decision.reason}`);
|
|
20252
20402
|
if (entry3.role === "specialist") {
|
|
20253
20403
|
console.error(
|
|
20254
|
-
`${
|
|
20404
|
+
`${TAG36} op=specialist-refused botId=${botId} specialist=${logValue2(entry3.specialist)} reason=${decision.reason}`
|
|
20255
20405
|
);
|
|
20256
20406
|
}
|
|
20257
20407
|
return c.json({ ok: true }, 200);
|
|
20258
20408
|
}
|
|
20259
20409
|
if (!isBindableEntry(entry3)) {
|
|
20260
|
-
console.error(`${
|
|
20410
|
+
console.error(`${TAG36} op=ignore botId=${botId} reason=bot-unbound`);
|
|
20261
20411
|
return c.json({ ok: true }, 200);
|
|
20262
20412
|
}
|
|
20263
20413
|
if (decision.kind === "chat-member") {
|
|
20264
20414
|
console.error(
|
|
20265
|
-
`${
|
|
20415
|
+
`${TAG36} op=chat-member-group botId=${botId} chatId=${decision.chatId} userId=${decision.userId || "none"} status=${logValue2(decision.status)}`
|
|
20266
20416
|
);
|
|
20267
20417
|
return c.json({ ok: true }, 200);
|
|
20268
20418
|
}
|
|
20269
20419
|
if (decision.kind === "recorded") {
|
|
20270
20420
|
console.error(
|
|
20271
|
-
`${
|
|
20421
|
+
`${TAG36} op=recorded botId=${botId} envelope=${decision.envelope} chatId=${decision.chatId ?? "none"} messageId=${decision.messageId ?? "none"}`
|
|
20272
20422
|
);
|
|
20273
20423
|
return c.json({ ok: true }, 200);
|
|
20274
20424
|
}
|
|
20275
20425
|
if (decision.kind === "comment-root") {
|
|
20276
20426
|
console.error(
|
|
20277
|
-
`${
|
|
20427
|
+
`${TAG36} op=channel-comment-root botId=${botId} groupChatId=${decision.groupChatId} rootMessageId=${decision.rootMessageId} channelChatId=${decision.channelChatId}`
|
|
20278
20428
|
);
|
|
20279
20429
|
return c.json({ ok: true }, 200);
|
|
20280
20430
|
}
|
|
20281
20431
|
if (decision.kind === "callback") {
|
|
20282
20432
|
console.error(
|
|
20283
|
-
`${
|
|
20433
|
+
`${TAG36} op=callback-received botId=${botId} callbackId=${decision.callbackId} chatId=${decision.chatId} messageId=${decision.messageId ?? "none"} data=${decision.data === null ? "none" : logValue2(decision.data)}`
|
|
20284
20434
|
);
|
|
20285
20435
|
console.error(
|
|
20286
|
-
`${
|
|
20436
|
+
`${TAG36} op=callback-authorised botId=${botId} senderId=${decision.senderId} allowed=${decision.allowed} reason=${decision.reason}`
|
|
20287
20437
|
);
|
|
20288
20438
|
const cbSubject = telegramConversationSubject(decision.chatType, decision.chatId, decision.senderId);
|
|
20289
20439
|
if (decision.allowed) {
|
|
@@ -20296,7 +20446,7 @@ app11.post("/", async (c) => {
|
|
|
20296
20446
|
cbBody = label;
|
|
20297
20447
|
} else {
|
|
20298
20448
|
console.error(
|
|
20299
|
-
`${
|
|
20449
|
+
`${TAG36} op=button-label-miss botId=${botId} chatId=${decision.chatId} data=${logValue2(decision.data)}`
|
|
20300
20450
|
);
|
|
20301
20451
|
}
|
|
20302
20452
|
}
|
|
@@ -20357,11 +20507,11 @@ app11.post("/", async (c) => {
|
|
|
20357
20507
|
const answered4 = await answerTelegramCallback(entry3.token, decision.callbackId, answerText);
|
|
20358
20508
|
const outcome = !answered4.ok ? "error" : decision.allowed ? "stored" : "refused";
|
|
20359
20509
|
console.error(
|
|
20360
|
-
`${
|
|
20510
|
+
`${TAG36} op=callback-answered botId=${botId} callbackId=${decision.callbackId} ms=${Date.now() - answerStartedAt} outcome=${outcome}${answered4.error ? ` error=${logValue2(answered4.error)}` : ""}`
|
|
20361
20511
|
);
|
|
20362
20512
|
if (decision.allowed && parseDispatchCallback(decision.data) === null) {
|
|
20363
20513
|
const cbActive = entryActive(entry3, accountDir, botId);
|
|
20364
|
-
console.error(`${
|
|
20514
|
+
console.error(`${TAG36} op=agent botId=${botId} slug=${agentSlug} active=${cbActive}`);
|
|
20365
20515
|
raiseChannelTurn({
|
|
20366
20516
|
accountId,
|
|
20367
20517
|
accountDir,
|
|
@@ -20388,10 +20538,10 @@ app11.post("/", async (c) => {
|
|
|
20388
20538
|
if (decision.kind === "poll") {
|
|
20389
20539
|
const options = decision.optionIds.length > 0 ? decision.optionIds.join(",") : "retracted";
|
|
20390
20540
|
console.error(
|
|
20391
|
-
`${
|
|
20541
|
+
`${TAG36} op=poll-received botId=${botId} updateId=${decision.updateId ?? "none"} senderId=${decision.senderId} pollId=${logValue2(decision.pollId)} options=${options}`
|
|
20392
20542
|
);
|
|
20393
20543
|
console.error(
|
|
20394
|
-
`${
|
|
20544
|
+
`${TAG36} op=poll-authorised botId=${botId} senderId=${decision.senderId} allowed=${decision.allowed} reason=${decision.reason}`
|
|
20395
20545
|
);
|
|
20396
20546
|
if (!decision.allowed) return c.json({ ok: true }, 200);
|
|
20397
20547
|
const pollKey = telegramChannelKey(botId, decision.senderId);
|
|
@@ -20414,7 +20564,7 @@ app11.post("/", async (c) => {
|
|
|
20414
20564
|
createdAt: pollAt
|
|
20415
20565
|
});
|
|
20416
20566
|
const pollActive = entryActive(entry3, accountDir, botId);
|
|
20417
|
-
console.error(`${
|
|
20567
|
+
console.error(`${TAG36} op=agent botId=${botId} slug=${agentSlug} active=${pollActive}`);
|
|
20418
20568
|
raiseChannelTurn({
|
|
20419
20569
|
accountId,
|
|
20420
20570
|
accountDir,
|
|
@@ -20440,10 +20590,10 @@ app11.post("/", async (c) => {
|
|
|
20440
20590
|
const quotedBody = findInboundBody(accountId, rKey, decision.messageId);
|
|
20441
20591
|
const shown = decision.newReaction.length > 0 ? decision.newReaction.join(",") : "none";
|
|
20442
20592
|
console.error(
|
|
20443
|
-
`${
|
|
20593
|
+
`${TAG36} op=reaction-received botId=${botId} chatId=${decision.chatId} messageId=${decision.messageId} senderId=${decision.senderId} old=${decision.oldReaction.join(",") || "none"} new=${shown} targetHeld=${quotedBody === null ? "no" : "yes"}`
|
|
20444
20594
|
);
|
|
20445
20595
|
console.error(
|
|
20446
|
-
`${
|
|
20596
|
+
`${TAG36} op=reaction-authorised botId=${botId} senderId=${decision.senderId} allowed=${decision.allowed} reason=${decision.reason}`
|
|
20447
20597
|
);
|
|
20448
20598
|
if (!decision.allowed) return c.json({ ok: true }, 200);
|
|
20449
20599
|
const rScope = entry3.role === "admin" ? "admin" : "public";
|
|
@@ -20466,7 +20616,7 @@ app11.post("/", async (c) => {
|
|
|
20466
20616
|
createdAt: rAt
|
|
20467
20617
|
});
|
|
20468
20618
|
const rActive = entryActive(entry3, accountDir, botId);
|
|
20469
|
-
console.error(`${
|
|
20619
|
+
console.error(`${TAG36} op=agent botId=${botId} slug=${agentSlug} active=${rActive}`);
|
|
20470
20620
|
raiseChannelTurn({
|
|
20471
20621
|
accountId,
|
|
20472
20622
|
accountDir,
|
|
@@ -20490,25 +20640,25 @@ app11.post("/", async (c) => {
|
|
|
20490
20640
|
if (decision.kind === "checkout") {
|
|
20491
20641
|
if (decision.query === "pre-checkout") {
|
|
20492
20642
|
console.error(
|
|
20493
|
-
`${
|
|
20643
|
+
`${TAG36} op=precheckout-received botId=${botId} queryId=${decision.queryId} payload=${logValue2(decision.payload)} amount=${decision.amount ?? "none"} currency=${decision.currency ?? "none"}`
|
|
20494
20644
|
);
|
|
20495
20645
|
noteCheckoutArrived(botId, decision.queryId, Date.now());
|
|
20496
20646
|
} else {
|
|
20497
20647
|
console.error(
|
|
20498
|
-
`${
|
|
20648
|
+
`${TAG36} op=shipping-received botId=${botId} queryId=${decision.queryId} payload=${logValue2(decision.payload)}`
|
|
20499
20649
|
);
|
|
20500
20650
|
}
|
|
20501
20651
|
console.error(
|
|
20502
|
-
`${
|
|
20652
|
+
`${TAG36} op=checkout-ignored botId=${botId} senderId=${decision.senderId} queryId=${decision.queryId} query=${decision.query} allowed=${decision.allowed} reason=payments-removed`
|
|
20503
20653
|
);
|
|
20504
20654
|
return c.json({ ok: true }, 200);
|
|
20505
20655
|
}
|
|
20506
20656
|
if (decision.kind === "subscription") {
|
|
20507
20657
|
console.error(
|
|
20508
|
-
`${
|
|
20658
|
+
`${TAG36} op=subscription botId=${botId} userId=${decision.senderId} payload=${logValue2(decision.payload)} state=${decision.state}`
|
|
20509
20659
|
);
|
|
20510
20660
|
console.error(
|
|
20511
|
-
`${
|
|
20661
|
+
`${TAG36} op=subscription-authorised botId=${botId} senderId=${decision.senderId} allowed=${decision.allowed} reason=${decision.reason}`
|
|
20512
20662
|
);
|
|
20513
20663
|
if (!decision.allowed) return c.json({ ok: true }, 200);
|
|
20514
20664
|
const sKey = telegramChannelKey(botId, decision.senderId);
|
|
@@ -20531,7 +20681,7 @@ app11.post("/", async (c) => {
|
|
|
20531
20681
|
createdAt: sAt
|
|
20532
20682
|
});
|
|
20533
20683
|
const sActive = entryActive(entry3, accountDir, botId);
|
|
20534
|
-
console.error(`${
|
|
20684
|
+
console.error(`${TAG36} op=agent botId=${botId} slug=${agentSlug} active=${sActive}`);
|
|
20535
20685
|
raiseChannelTurn({
|
|
20536
20686
|
accountId,
|
|
20537
20687
|
accountDir,
|
|
@@ -20555,7 +20705,7 @@ app11.post("/", async (c) => {
|
|
|
20555
20705
|
if (!decision.isClosed) return c.json({ ok: true }, 200);
|
|
20556
20706
|
const where = findPollConversation(accountId, decision.pollId);
|
|
20557
20707
|
console.error(
|
|
20558
|
-
`${
|
|
20708
|
+
`${TAG36} op=poll-closed botId=${botId} pollId=${logValue2(decision.pollId)} options=${decision.options.length} totalVotes=${decision.totalVotes} targetHeld=${where === null ? "no" : "yes"}`
|
|
20559
20709
|
);
|
|
20560
20710
|
if (where === null) return c.json({ ok: true }, 200);
|
|
20561
20711
|
const plScope = entry3.role === "admin" ? "admin" : "public";
|
|
@@ -20578,7 +20728,7 @@ app11.post("/", async (c) => {
|
|
|
20578
20728
|
createdAt: plAt
|
|
20579
20729
|
});
|
|
20580
20730
|
const plActive = entryActive(entry3, accountDir, botId);
|
|
20581
|
-
console.error(`${
|
|
20731
|
+
console.error(`${TAG36} op=agent botId=${botId} slug=${agentSlug} active=${plActive}`);
|
|
20582
20732
|
raiseChannelTurn({
|
|
20583
20733
|
accountId,
|
|
20584
20734
|
accountDir,
|
|
@@ -20599,7 +20749,7 @@ app11.post("/", async (c) => {
|
|
|
20599
20749
|
}
|
|
20600
20750
|
if (decision.kind === "member") {
|
|
20601
20751
|
console.error(
|
|
20602
|
-
`${
|
|
20752
|
+
`${TAG36} op=chat-member botId=${botId} chatId=${decision.chatId} status=${decision.status}`
|
|
20603
20753
|
);
|
|
20604
20754
|
return c.json({ ok: true }, 200);
|
|
20605
20755
|
}
|
|
@@ -20607,13 +20757,13 @@ app11.post("/", async (c) => {
|
|
|
20607
20757
|
const { newBotId } = decision;
|
|
20608
20758
|
if (!decision.authorised) {
|
|
20609
20759
|
console.error(
|
|
20610
|
-
`${
|
|
20760
|
+
`${TAG36} op=managed-bot botId=${botId} event=${decision.event} newBotId=${newBotId} result=refused reason=public-entry-no-provision`
|
|
20611
20761
|
);
|
|
20612
20762
|
return c.json({ ok: true }, 200);
|
|
20613
20763
|
}
|
|
20614
20764
|
const { event } = decision;
|
|
20615
20765
|
console.error(
|
|
20616
|
-
`${
|
|
20766
|
+
`${TAG36} op=managed-bot botId=${botId} event=${event} newBotId=${newBotId} creator=${decision.creatorId ?? "none"}`
|
|
20617
20767
|
);
|
|
20618
20768
|
const fetched = await getManagedBotToken(entry3.token, Number(newBotId));
|
|
20619
20769
|
console.error(
|
|
@@ -20669,11 +20819,11 @@ app11.post("/", async (c) => {
|
|
|
20669
20819
|
const matched = bizStored !== null && bizStored.id === decision.businessConnectionId;
|
|
20670
20820
|
const bizNowS = Math.floor(Date.now() / 1e3);
|
|
20671
20821
|
console.error(
|
|
20672
|
-
`${
|
|
20822
|
+
`${TAG36} op=business-message botId=${botId} connectionId=${truncateConnectionId(decision.businessConnectionId)} chatId=${decision.chatId} senderId=${decision.senderId} messageId=${decision.messageId ?? "none"} kind=${shape.primaryKind} ageS=${decision.date === null ? "none" : bizNowS - decision.date} matched=${matched ? "yes" : "no"}`
|
|
20673
20823
|
);
|
|
20674
20824
|
if (!matched) {
|
|
20675
20825
|
console.error(
|
|
20676
|
-
`${
|
|
20826
|
+
`${TAG36} op=business-refused botId=${botId} connectionId=${truncateConnectionId(decision.businessConnectionId)} reason=${bizStored === null ? "no-record" : "mismatch"}`
|
|
20677
20827
|
);
|
|
20678
20828
|
return c.json({ ok: true }, 200);
|
|
20679
20829
|
}
|
|
@@ -20735,7 +20885,7 @@ app11.post("/", async (c) => {
|
|
|
20735
20885
|
}
|
|
20736
20886
|
const bizGateway = getTelegramGateway();
|
|
20737
20887
|
if (!bizGateway) {
|
|
20738
|
-
console.error(`${
|
|
20888
|
+
console.error(`${TAG36} op=reply-dropped botId=${botId} reason=gateway-not-ready`);
|
|
20739
20889
|
return c.json({ ok: true }, 200);
|
|
20740
20890
|
}
|
|
20741
20891
|
const bizConnectionId = bizStored.id;
|
|
@@ -20749,7 +20899,7 @@ app11.post("/", async (c) => {
|
|
|
20749
20899
|
);
|
|
20750
20900
|
if (!verdict.allowed) {
|
|
20751
20901
|
console.error(
|
|
20752
|
-
`${
|
|
20902
|
+
`${TAG36} op=reply-dropped botId=${botId} reason=business-window-${verdict.reason} detail="${logValue2(businessWindowRefusal(decision.chatId, verdict.ageS))}"`
|
|
20753
20903
|
);
|
|
20754
20904
|
return;
|
|
20755
20905
|
}
|
|
@@ -20776,8 +20926,8 @@ app11.post("/", async (c) => {
|
|
|
20776
20926
|
origin: "agent",
|
|
20777
20927
|
createdAt: outAt
|
|
20778
20928
|
});
|
|
20779
|
-
console.error(`${
|
|
20780
|
-
} else console.error(`${
|
|
20929
|
+
console.error(`${TAG36} op=reply-sent botId=${botId} ok=true`);
|
|
20930
|
+
} else console.error(`${TAG36} op=reply-dropped botId=${botId} reason=${sent.error}`);
|
|
20781
20931
|
};
|
|
20782
20932
|
void bizGateway.handleInbound({
|
|
20783
20933
|
accountId,
|
|
@@ -20808,7 +20958,7 @@ app11.post("/", async (c) => {
|
|
|
20808
20958
|
const delStored = readBusinessConnection(accountDir, botId);
|
|
20809
20959
|
if (delStored === null || delStored.id !== decision.businessConnectionId) {
|
|
20810
20960
|
console.error(
|
|
20811
|
-
`${
|
|
20961
|
+
`${TAG36} op=business-refused botId=${botId} connectionId=${truncateConnectionId(decision.businessConnectionId)} reason=${delStored === null ? "no-record" : "mismatch"}`
|
|
20812
20962
|
);
|
|
20813
20963
|
return c.json({ ok: true }, 200);
|
|
20814
20964
|
}
|
|
@@ -20825,12 +20975,12 @@ app11.post("/", async (c) => {
|
|
|
20825
20975
|
if (res.created) marked += 1;
|
|
20826
20976
|
}
|
|
20827
20977
|
console.error(
|
|
20828
|
-
`${
|
|
20978
|
+
`${TAG36} op=business-deleted botId=${botId} chatId=${decision.chatId} ids=${decision.messageIds.length} marked=${marked}`
|
|
20829
20979
|
);
|
|
20830
20980
|
return c.json({ ok: true }, 200);
|
|
20831
20981
|
}
|
|
20832
20982
|
const { senderId, chatId, text } = decision;
|
|
20833
|
-
console.error(`${
|
|
20983
|
+
console.error(`${TAG36} op=access botId=${botId} senderId=${senderId} allowed=true reason=${decision.reason}`);
|
|
20834
20984
|
const subject = telegramConversationSubject(decision.chatType, chatId, senderId);
|
|
20835
20985
|
const channelKey = telegramChannelKey(botId, subject);
|
|
20836
20986
|
const scope = entry3.role === "public" ? "public" : "admin";
|
|
@@ -20917,17 +21067,17 @@ app11.post("/", async (c) => {
|
|
|
20917
21067
|
const active = entryActive(entry3, accountDir, botId, (rosterValid) => {
|
|
20918
21068
|
if (entry3.role !== "specialist") return;
|
|
20919
21069
|
console.error(
|
|
20920
|
-
`${
|
|
21070
|
+
`${TAG36} op=specialist-inbound botId=${botId} specialist=${logValue2(entry3.specialist)} senderId=${senderId} sessionId=${sessionId} rosterValid=${rosterValid ? "yes" : "no"}`
|
|
20921
21071
|
);
|
|
20922
21072
|
});
|
|
20923
|
-
console.error(`${
|
|
21073
|
+
console.error(`${TAG36} op=agent botId=${botId} slug=${agentSlug} active=${active}`);
|
|
20924
21074
|
if (!active) {
|
|
20925
|
-
console.error(`${
|
|
21075
|
+
console.error(`${TAG36} op=reject reason=agent-inactive botId=${botId} agent=${agentSlug}`);
|
|
20926
21076
|
return c.json({ ok: true }, 200);
|
|
20927
21077
|
}
|
|
20928
21078
|
const gateway = getTelegramGateway();
|
|
20929
21079
|
if (!gateway) {
|
|
20930
|
-
console.error(`${
|
|
21080
|
+
console.error(`${TAG36} op=reply-dropped botId=${botId} reason=gateway-not-ready`);
|
|
20931
21081
|
return c.json({ ok: true }, 200);
|
|
20932
21082
|
}
|
|
20933
21083
|
const replyThreadId = decision.threadId ?? void 0;
|
|
@@ -20949,8 +21099,8 @@ app11.post("/", async (c) => {
|
|
|
20949
21099
|
origin: "agent",
|
|
20950
21100
|
createdAt: at
|
|
20951
21101
|
});
|
|
20952
|
-
console.error(`${
|
|
20953
|
-
} else console.error(`${
|
|
21102
|
+
console.error(`${TAG36} op=reply-sent botId=${botId} ok=true`);
|
|
21103
|
+
} else console.error(`${TAG36} op=reply-dropped botId=${botId} reason=${sent.error}`);
|
|
20954
21104
|
};
|
|
20955
21105
|
const media = await downloadTelegramMedia({ token: entry3.token, botId, items: decision.media });
|
|
20956
21106
|
if (media.length > 0) {
|
|
@@ -21010,7 +21160,7 @@ app11.post("/", async (c) => {
|
|
|
21010
21160
|
if (written.written && !decision.isEdit) noteShareStarted();
|
|
21011
21161
|
} catch (err) {
|
|
21012
21162
|
console.error(
|
|
21013
|
-
`${
|
|
21163
|
+
`${TAG36} op=live-location op=write-failed botId=${botId} senderId=${senderId} detail="${logValue2(err instanceof Error ? err.message : String(err))}"`
|
|
21014
21164
|
);
|
|
21015
21165
|
}
|
|
21016
21166
|
}
|
|
@@ -21022,6 +21172,8 @@ app11.post("/", async (c) => {
|
|
|
21022
21172
|
textIsPlaceholder: decision.textIsPlaceholder,
|
|
21023
21173
|
media
|
|
21024
21174
|
});
|
|
21175
|
+
const seen = await extractTelegramVideo({ botId, media: heard.media });
|
|
21176
|
+
heard.media = seen.media;
|
|
21025
21177
|
if (heard.text !== text) {
|
|
21026
21178
|
const patched = appendUpdate(accountId, channelKey, {
|
|
21027
21179
|
kind: "update",
|
|
@@ -21030,7 +21182,7 @@ app11.post("/", async (c) => {
|
|
|
21030
21182
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
21031
21183
|
});
|
|
21032
21184
|
console.error(
|
|
21033
|
-
`${
|
|
21185
|
+
`${TAG36} op=transcript-patch botId=${botId} target=${inboundMessageId} ok=${patched.created}`
|
|
21034
21186
|
);
|
|
21035
21187
|
}
|
|
21036
21188
|
{
|
|
@@ -21066,7 +21218,7 @@ app11.post("/", async (c) => {
|
|
|
21066
21218
|
}
|
|
21067
21219
|
if (decision.isEdit && decision.location) {
|
|
21068
21220
|
console.error(
|
|
21069
|
-
`${
|
|
21221
|
+
`${TAG36} op=live-location op=suppressed-turn botId=${botId} senderId=${senderId} reason=live-edit`
|
|
21070
21222
|
);
|
|
21071
21223
|
return;
|
|
21072
21224
|
}
|
|
@@ -21117,7 +21269,7 @@ function mountTelegramRoutes(app81, telegramRoutes) {
|
|
|
21117
21269
|
// server/routes/quickbooks.ts
|
|
21118
21270
|
import { join as join41 } from "path";
|
|
21119
21271
|
import { existsSync as existsSync29, readFileSync as readFileSync33, writeFileSync as writeFileSync15, mkdirSync as mkdirSync8, rmSync as rmSync4, renameSync as renameSync5 } from "fs";
|
|
21120
|
-
var
|
|
21272
|
+
var TAG37 = "[quickbooks]";
|
|
21121
21273
|
var INTUIT_TOKEN_URL = "https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer";
|
|
21122
21274
|
var STATE_RE = /^[A-Za-z0-9_-]+$/;
|
|
21123
21275
|
function pendingPath(accountDir, state) {
|
|
@@ -21130,14 +21282,14 @@ async function completeConsent(args) {
|
|
|
21130
21282
|
const { accountDir, code, realmId } = args;
|
|
21131
21283
|
const state = args.state;
|
|
21132
21284
|
if (!state || !STATE_RE.test(state) || !existsSync29(pendingPath(accountDir, state))) {
|
|
21133
|
-
console.error(`${
|
|
21285
|
+
console.error(`${TAG37} op=callback state=${state ?? ""} stateValid=false realmId=${realmId ?? ""}`);
|
|
21134
21286
|
return { ok: false, status: 400, message: "Invalid or unknown authorization state.", stateValid: false };
|
|
21135
21287
|
}
|
|
21136
21288
|
const claimFile = `${pendingPath(accountDir, state)}.claimed`;
|
|
21137
21289
|
try {
|
|
21138
21290
|
renameSync5(pendingPath(accountDir, state), claimFile);
|
|
21139
21291
|
} catch {
|
|
21140
|
-
console.error(`${
|
|
21292
|
+
console.error(`${TAG37} op=callback state=${state} stateValid=false realmId=${realmId ?? ""}`);
|
|
21141
21293
|
return { ok: false, status: 400, message: "Invalid or unknown authorization state.", stateValid: false };
|
|
21142
21294
|
}
|
|
21143
21295
|
try {
|
|
@@ -21145,14 +21297,14 @@ async function completeConsent(args) {
|
|
|
21145
21297
|
try {
|
|
21146
21298
|
pending = JSON.parse(readFileSync33(claimFile, "utf-8"));
|
|
21147
21299
|
} catch {
|
|
21148
|
-
console.error(`${
|
|
21300
|
+
console.error(`${TAG37} op=callback state=${state} stateValid=false realmId=${realmId ?? ""}`);
|
|
21149
21301
|
return { ok: false, status: 400, message: "Authorization state could not be read.", stateValid: false };
|
|
21150
21302
|
}
|
|
21151
21303
|
if (Date.now() > pending.expiresAt) {
|
|
21152
|
-
console.error(`${
|
|
21304
|
+
console.error(`${TAG37} op=callback state=${state} stateValid=false realmId=${realmId ?? ""}`);
|
|
21153
21305
|
return { ok: false, status: 400, message: "Authorization request expired. Generate a new consent link.", stateValid: false };
|
|
21154
21306
|
}
|
|
21155
|
-
console.error(`${
|
|
21307
|
+
console.error(`${TAG37} op=callback state=${state} stateValid=true realmId=${realmId ?? ""}`);
|
|
21156
21308
|
if (!code || !realmId) {
|
|
21157
21309
|
return { ok: false, status: 400, message: "Missing code or realmId in the callback.", stateValid: true };
|
|
21158
21310
|
}
|
|
@@ -21176,12 +21328,12 @@ async function completeConsent(args) {
|
|
|
21176
21328
|
});
|
|
21177
21329
|
const text = await res.text();
|
|
21178
21330
|
if (!res.ok) {
|
|
21179
|
-
console.error(`${
|
|
21331
|
+
console.error(`${TAG37} op=token-exchange realmId=${realmId} persisted=false`);
|
|
21180
21332
|
return { ok: false, status: 502, message: `Token exchange failed (${res.status}). Generate a new consent link to retry.`, stateValid: true };
|
|
21181
21333
|
}
|
|
21182
21334
|
const body = JSON.parse(text);
|
|
21183
21335
|
if (!body.refresh_token) {
|
|
21184
|
-
console.error(`${
|
|
21336
|
+
console.error(`${TAG37} op=token-exchange realmId=${realmId} persisted=false`);
|
|
21185
21337
|
return { ok: false, status: 502, message: "Token exchange returned no refresh token.", stateValid: true };
|
|
21186
21338
|
}
|
|
21187
21339
|
const now = Date.now();
|
|
@@ -21194,7 +21346,7 @@ async function completeConsent(args) {
|
|
|
21194
21346
|
mkdirSync8(join41(accountDir, "secrets"), { recursive: true });
|
|
21195
21347
|
writeFileSync15(storePath(accountDir), JSON.stringify(store2, null, 2), { mode: 384 });
|
|
21196
21348
|
const persisted = JSON.parse(readFileSync33(storePath(accountDir), "utf-8")).connections?.[realmId]?.refreshToken === body.refresh_token;
|
|
21197
|
-
console.error(`${
|
|
21349
|
+
console.error(`${TAG37} op=token-exchange realmId=${realmId} persisted=${persisted}`);
|
|
21198
21350
|
return { ok: persisted, status: persisted ? 200 : 500, message: persisted ? `Connected company ${realmId}.` : "Failed to persist the connection.", stateValid: true };
|
|
21199
21351
|
} finally {
|
|
21200
21352
|
rmSync4(claimFile, { force: true });
|
|
@@ -21207,7 +21359,7 @@ var app12 = new Hono();
|
|
|
21207
21359
|
app12.get("/callback", async (c) => {
|
|
21208
21360
|
const account = resolveAccount();
|
|
21209
21361
|
if (!account) {
|
|
21210
|
-
console.error(`${
|
|
21362
|
+
console.error(`${TAG37} op=callback stateValid=false realmId= reason=no-account`);
|
|
21211
21363
|
return c.html(page("QuickBooks", "This install has no account configured."), 500);
|
|
21212
21364
|
}
|
|
21213
21365
|
const result = await completeConsent({
|
|
@@ -22172,7 +22324,7 @@ function startDispatchFieldCensus(getSession3, intervalMs = FIFTEEN_MIN_MS) {
|
|
|
22172
22324
|
}
|
|
22173
22325
|
|
|
22174
22326
|
// server/routes/field.ts
|
|
22175
|
-
var
|
|
22327
|
+
var TAG38 = "[dispatch-field]";
|
|
22176
22328
|
var MAX_INITDATA_AGE_S = 3600;
|
|
22177
22329
|
var ZONE_FALLBACK2 = "UTC";
|
|
22178
22330
|
var SITE_HISTORY_LIMIT = 20;
|
|
@@ -22221,7 +22373,7 @@ function gate(c) {
|
|
|
22221
22373
|
Date.now()
|
|
22222
22374
|
);
|
|
22223
22375
|
console.log(
|
|
22224
|
-
`${
|
|
22376
|
+
`${TAG38} op=initdata-verify workerId=${auth.ok ? auth.worker.workerId : "none"} ok=${auth.ok} reason=${auth.ok ? "ok" : auth.reason} ageS=${auth.ageS}`
|
|
22225
22377
|
);
|
|
22226
22378
|
if (auth.ok) {
|
|
22227
22379
|
noteFieldContact(auth.accountId, auth.worker.workerId, Date.now());
|
|
@@ -22243,7 +22395,7 @@ async function loadSheet(auth, visitId) {
|
|
|
22243
22395
|
if (!visit) return { ok: false, status: 404, reason: "not-found" };
|
|
22244
22396
|
if (visit.workerId !== auth.worker.workerId) {
|
|
22245
22397
|
console.error(
|
|
22246
|
-
`${
|
|
22398
|
+
`${TAG38} op=visit-refused visitId=${visitId} workerId=${auth.worker.workerId} reason=not-assigned`
|
|
22247
22399
|
);
|
|
22248
22400
|
return { ok: false, status: 403, reason: "not-assigned" };
|
|
22249
22401
|
}
|
|
@@ -22264,7 +22416,7 @@ async function loadSheet(auth, visitId) {
|
|
|
22264
22416
|
}
|
|
22265
22417
|
function readFailed(reason, err, ctx) {
|
|
22266
22418
|
console.error(
|
|
22267
|
-
`${
|
|
22419
|
+
`${TAG38} op=read-failed ${ctx} error="${err instanceof Error ? err.message : String(err)}" reason=${reason}`
|
|
22268
22420
|
);
|
|
22269
22421
|
}
|
|
22270
22422
|
var app14 = new Hono();
|
|
@@ -22280,7 +22432,7 @@ app14.get("/session", async (c) => {
|
|
|
22280
22432
|
return c.json({ reason: "read-failed" }, 503);
|
|
22281
22433
|
}
|
|
22282
22434
|
console.log(
|
|
22283
|
-
`${
|
|
22435
|
+
`${TAG38} op=session-open workerId=${auth.worker.workerId} visits=${visits} source=network`
|
|
22284
22436
|
);
|
|
22285
22437
|
return c.json({
|
|
22286
22438
|
worker: { workerId: auth.worker.workerId, name: auth.worker.name },
|
|
@@ -22316,7 +22468,7 @@ app14.get("/visit/:visitId", async (c) => {
|
|
|
22316
22468
|
const loaded = await loadSheet(auth, visitId);
|
|
22317
22469
|
if (!loaded.ok) return c.json({ reason: loaded.reason }, loaded.status);
|
|
22318
22470
|
console.log(
|
|
22319
|
-
`${
|
|
22471
|
+
`${TAG38} op=sheet-open visitId=${visitId} workerId=${auth.worker.workerId} historyVisits=${loaded.history.length} source=network`
|
|
22320
22472
|
);
|
|
22321
22473
|
return c.json({
|
|
22322
22474
|
visit: loaded.visit,
|
|
@@ -22352,7 +22504,7 @@ app14.post("/visit/:visitId/record", async (c) => {
|
|
|
22352
22504
|
);
|
|
22353
22505
|
if (!out.ok) return c.json({ reason: out.reason, detail: out.message }, 400);
|
|
22354
22506
|
const kind = body.checklistItem !== void 0 ? "checklist" : body.partId !== void 0 ? "part" : body.signature !== void 0 ? "signature" : body.mediaRef !== void 0 ? "media" : "note";
|
|
22355
|
-
console.log(`${
|
|
22507
|
+
console.log(`${TAG38} op=edit-recorded visitId=${visitId} workerId=${auth.worker.workerId} kind=${kind}`);
|
|
22356
22508
|
return c.json(out.value);
|
|
22357
22509
|
});
|
|
22358
22510
|
app14.post("/visit/:visitId/status", async (c) => {
|
|
@@ -22379,7 +22531,7 @@ app14.post("/visit/:visitId/status", async (c) => {
|
|
|
22379
22531
|
const prefix = "missing-required-field:";
|
|
22380
22532
|
if (out.reason.startsWith(prefix)) {
|
|
22381
22533
|
const missing = out.reason.slice(prefix.length);
|
|
22382
|
-
console.error(`${
|
|
22534
|
+
console.error(`${TAG38} op=complete-refused visitId=${visitId} missing=${missing}`);
|
|
22383
22535
|
return c.json({ reason: "missing-required-field", missing, detail: out.message }, 409);
|
|
22384
22536
|
}
|
|
22385
22537
|
return c.json({ reason: out.reason, detail: out.message }, 409);
|
|
@@ -22391,7 +22543,7 @@ app14.post("/visit/:visitId/status", async (c) => {
|
|
|
22391
22543
|
Math.round((Date.parse(out.value.at) - Date.parse(dueToLeaveAt)) / 1e3)
|
|
22392
22544
|
);
|
|
22393
22545
|
console.log(
|
|
22394
|
-
`${
|
|
22546
|
+
`${TAG38} op=complete visitId=${visitId} checklist=${state.checklistDone}/${state.checklistTotal} notes=${state.notes} media=${state.media} parts=${state.parts} signatures=${state.signatures} lagS=${lagS}`
|
|
22395
22547
|
);
|
|
22396
22548
|
return c.json(out.value);
|
|
22397
22549
|
});
|
|
@@ -22400,10 +22552,10 @@ app14.post("/probe", async (c) => {
|
|
|
22400
22552
|
if (!auth.ok) return c.json({ reason: auth.reason }, auth.status);
|
|
22401
22553
|
const p = await c.req.json();
|
|
22402
22554
|
console.log(
|
|
22403
|
-
`${
|
|
22555
|
+
`${TAG38} op=storage-probe platform=${p.platform} indexedDB=${p.indexedDB} localStorage=${p.localStorage} cacheStorage=${p.cacheStorage} serviceWorker=${p.serviceWorker} persisted=${p.persisted} workerId=${auth.worker.workerId}`
|
|
22404
22556
|
);
|
|
22405
22557
|
console.log(
|
|
22406
|
-
`${
|
|
22558
|
+
`${TAG38} op=launch-params workerId=${auth.worker.workerId} keys=${(p.launchKeys ?? []).join(",") || "none"}`
|
|
22407
22559
|
);
|
|
22408
22560
|
const anyUsable = p.indexedDB || p.localStorage || p.cacheStorage;
|
|
22409
22561
|
noteFieldStorage(auth.accountId, auth.worker.workerId, anyUsable, Date.now());
|
|
@@ -22530,6 +22682,14 @@ app15.post("/", async (c) => {
|
|
|
22530
22682
|
// the standard fields.
|
|
22531
22683
|
"graph-fullscreen-not-covering",
|
|
22532
22684
|
"graph-fullscreen-canvas-mismatch",
|
|
22685
|
+
// Task 2439 — the admin composer's own send failure. The inline reporter in
|
|
22686
|
+
// server/index.ts hooks only `error` and `unhandledrejection`, so a caught
|
|
22687
|
+
// fetch rejection in send() reached no sink at all. Without this entry the
|
|
22688
|
+
// POST collapses to kind=unknown and the log loses the source, which is the
|
|
22689
|
+
// whole point of the report. Deliberately NOT in ERROR_KINDS: it fires at
|
|
22690
|
+
// most once per send press, so it cannot exhaust a budget, and leaving it in
|
|
22691
|
+
// the telemetry class keeps the protected error budget for uncaught errors.
|
|
22692
|
+
"webchat-send-failed",
|
|
22533
22693
|
"event"
|
|
22534
22694
|
]);
|
|
22535
22695
|
const kind = allowedKinds.has(kindRaw) ? kindRaw : "unknown";
|
|
@@ -25309,7 +25469,7 @@ function resolveTunnelUrl() {
|
|
|
25309
25469
|
if (!state) return null;
|
|
25310
25470
|
return `https://${hostname2}.${state.domain}`;
|
|
25311
25471
|
}
|
|
25312
|
-
var
|
|
25472
|
+
var TAG39 = "[claude-session-manager:wrapper]";
|
|
25313
25473
|
async function refuseIfClaudeAuthDead(c, route, sessionId) {
|
|
25314
25474
|
const auth = await ensureAuth();
|
|
25315
25475
|
if (auth.status !== "dead" && auth.status !== "missing") return null;
|
|
@@ -25327,12 +25487,12 @@ async function performSpawnWithInitialMessage(args) {
|
|
|
25327
25487
|
const aboutOwner = await resolveOwnerProfileBlock(args.senderId, args.userId);
|
|
25328
25488
|
const ownerMs = Date.now() - ownerStart;
|
|
25329
25489
|
const aboutOwnerStatus = aboutOwner == null ? "absent" : "ok" in aboutOwner && aboutOwner.ok === false ? `unresolved:${aboutOwner.reason}` : "ok";
|
|
25330
|
-
console.log(`${
|
|
25490
|
+
console.log(`${TAG39} about-owner-resolved status=${aboutOwnerStatus} ms=${ownerMs}`);
|
|
25331
25491
|
const dormantPlugins = computeDormantPlugins(args.senderId);
|
|
25332
25492
|
const activePlugins = computeActivePlugins(args.senderId);
|
|
25333
25493
|
const specialistDomains = computeSpecialistDomains(args.senderId);
|
|
25334
25494
|
const tunnelUrl = resolveTunnelUrl();
|
|
25335
|
-
console.log(`${
|
|
25495
|
+
console.log(`${TAG39} tunnel-url-resolved value=${tunnelUrl ?? "null"}`);
|
|
25336
25496
|
const upstreamPayload = JSON.stringify({
|
|
25337
25497
|
senderId: args.senderId,
|
|
25338
25498
|
// Task 205 — pass userId through to the manager so it lands as
|
|
@@ -25359,24 +25519,24 @@ async function performSpawnWithInitialMessage(args) {
|
|
|
25359
25519
|
// unshapely values.
|
|
25360
25520
|
conversationNodeId: args.conversationNodeId
|
|
25361
25521
|
});
|
|
25362
|
-
console.log(`${
|
|
25522
|
+
console.log(`${TAG39} forward-spawn-start managerBase=${managerBase("claude-session-manager:wrapper")} bytes=${upstreamPayload.length} hidden=${args.hidden} specialist=${args.specialist ?? "none"}`);
|
|
25363
25523
|
const forwardStart = Date.now();
|
|
25364
25524
|
const upstream = await fetch(`${managerBase("claude-session-manager:wrapper")}/public-spawn`, {
|
|
25365
25525
|
method: "POST",
|
|
25366
25526
|
headers: { "content-type": "application/json" },
|
|
25367
25527
|
body: upstreamPayload
|
|
25368
25528
|
}).catch((err) => {
|
|
25369
|
-
console.error(`${
|
|
25529
|
+
console.error(`${TAG39} fetch-failed op=spawn message=${err instanceof Error ? err.message : String(err)} ms=${Date.now() - forwardStart}`);
|
|
25370
25530
|
return null;
|
|
25371
25531
|
});
|
|
25372
25532
|
if (!upstream) return {
|
|
25373
25533
|
response: new Response(JSON.stringify({ error: "manager-unreachable" }), { status: 503, headers: { "content-type": "application/json" } }),
|
|
25374
25534
|
claudeSessionId: null
|
|
25375
25535
|
};
|
|
25376
|
-
console.log(`${
|
|
25536
|
+
console.log(`${TAG39} forward-spawn-done status=${upstream.status} ms=${Date.now() - forwardStart}`);
|
|
25377
25537
|
if (args.initialMessage) {
|
|
25378
25538
|
const inputBytes = Buffer.byteLength(args.initialMessage, "utf8");
|
|
25379
|
-
console.log(`${
|
|
25539
|
+
console.log(`${TAG39} initial-message-inlined bytes=${inputBytes}`);
|
|
25380
25540
|
}
|
|
25381
25541
|
const bodyText = await upstream.text().catch(() => "");
|
|
25382
25542
|
let claudeSessionId = null;
|
|
@@ -25411,7 +25571,7 @@ app24.post("/", async (c) => {
|
|
|
25411
25571
|
if (refusal) return refusal;
|
|
25412
25572
|
const senderId = getAccountIdForSession(cacheKey) ?? "";
|
|
25413
25573
|
if (!senderId) {
|
|
25414
|
-
console.error(`${
|
|
25574
|
+
console.error(`${TAG39} reject reason=no-account-id cacheKey-prefix=${cacheKey.slice(0, 8)}`);
|
|
25415
25575
|
return c.json({ error: "admin-account-not-resolved" }, 500);
|
|
25416
25576
|
}
|
|
25417
25577
|
const userId = getUserIdForSession(cacheKey) ?? void 0;
|
|
@@ -25420,7 +25580,7 @@ app24.post("/", async (c) => {
|
|
|
25420
25580
|
const permissionMode = typeof body.permissionMode === "string" ? body.permissionMode : void 0;
|
|
25421
25581
|
const specialist = typeof body.specialist === "string" && /^[A-Za-z0-9_-]{1,64}$/.test(body.specialist) ? body.specialist : void 0;
|
|
25422
25582
|
const model = typeof body.model === "string" && /^[A-Za-z0-9._-]{1,64}$/.test(body.model) ? body.model : void 0;
|
|
25423
|
-
console.log(`${
|
|
25583
|
+
console.log(`${TAG39} 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"}`);
|
|
25424
25584
|
const conversationNodeId = cacheKey ? getSessionIdForSession(cacheKey) : void 0;
|
|
25425
25585
|
const { response, claudeSessionId } = await performSpawnWithInitialMessage({
|
|
25426
25586
|
senderId,
|
|
@@ -25439,13 +25599,13 @@ app24.post("/", async (c) => {
|
|
|
25439
25599
|
claudeSessionId,
|
|
25440
25600
|
senderId
|
|
25441
25601
|
);
|
|
25442
|
-
console.log(`${
|
|
25602
|
+
console.log(`${TAG39} route-done surface=cookie status=${response.status} route-ms=${Date.now() - routeStart}`);
|
|
25443
25603
|
return response;
|
|
25444
25604
|
});
|
|
25445
25605
|
var claude_sessions_default = app24;
|
|
25446
25606
|
|
|
25447
25607
|
// server/routes/admin/log-ingest.ts
|
|
25448
|
-
var
|
|
25608
|
+
var TAG40 = "[log-ingest]";
|
|
25449
25609
|
var TAG_PATTERN = /^[A-Za-z0-9_:-]{1,32}$/;
|
|
25450
25610
|
var LEVELS = /* @__PURE__ */ new Set(["debug", "info", "warn", "error"]);
|
|
25451
25611
|
var MAX_LINE_BYTES = 4096;
|
|
@@ -25456,7 +25616,7 @@ function isLoopbackAddr2(addr) {
|
|
|
25456
25616
|
app25.post("/", async (c) => {
|
|
25457
25617
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
25458
25618
|
if (!isLoopbackAddr2(remoteAddr)) {
|
|
25459
|
-
console.error(`${
|
|
25619
|
+
console.error(`${TAG40} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
25460
25620
|
return c.json({ error: "log-ingest-loopback-only" }, 403);
|
|
25461
25621
|
}
|
|
25462
25622
|
const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
|
|
@@ -25465,7 +25625,7 @@ app25.post("/", async (c) => {
|
|
|
25465
25625
|
const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
|
|
25466
25626
|
const offender = tokens.find((t) => !isLoopbackAddr2(t));
|
|
25467
25627
|
if (offender !== void 0) {
|
|
25468
|
-
console.error(`${
|
|
25628
|
+
console.error(`${TAG40} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
|
|
25469
25629
|
return c.json({ error: "log-ingest-loopback-only" }, 403);
|
|
25470
25630
|
}
|
|
25471
25631
|
}
|
|
@@ -25500,7 +25660,7 @@ var log_ingest_default = app25;
|
|
|
25500
25660
|
|
|
25501
25661
|
// server/routes/admin/session-blocked.ts
|
|
25502
25662
|
import { join as join48 } from "path";
|
|
25503
|
-
var
|
|
25663
|
+
var TAG41 = "[blocked-tool-notify]";
|
|
25504
25664
|
function isLoopbackAddr3(addr) {
|
|
25505
25665
|
return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
|
|
25506
25666
|
}
|
|
@@ -25518,18 +25678,18 @@ Answer the permission card in the session's PTY or in Claude Desktop. Some check
|
|
|
25518
25678
|
async function sendWhatsApp(account, to, text) {
|
|
25519
25679
|
const res = resolveSocket(account.accountId);
|
|
25520
25680
|
if (!res.ok) {
|
|
25521
|
-
console.error(`${
|
|
25681
|
+
console.error(`${TAG41} op=socket-unavailable accountId=${account.accountId} reason=${res.reason}`);
|
|
25522
25682
|
return false;
|
|
25523
25683
|
}
|
|
25524
25684
|
const sent = await sendTextMessage(res.sock, to, text, { accountId: res.accountId });
|
|
25525
|
-
if (!sent.success) console.error(`${
|
|
25685
|
+
if (!sent.success) console.error(`${TAG41} op=send-failed to=${to} error=${sent.error ?? "unknown"}`);
|
|
25526
25686
|
return sent.success === true;
|
|
25527
25687
|
}
|
|
25528
25688
|
var app26 = new Hono();
|
|
25529
25689
|
app26.post("/", async (c) => {
|
|
25530
25690
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
25531
25691
|
if (!isLoopbackAddr3(remoteAddr)) {
|
|
25532
|
-
console.error(`${
|
|
25692
|
+
console.error(`${TAG41} op=reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
25533
25693
|
return c.json({ error: "session-blocked-loopback-only" }, 403);
|
|
25534
25694
|
}
|
|
25535
25695
|
let body = {};
|
|
@@ -25550,13 +25710,13 @@ app26.post("/", async (c) => {
|
|
|
25550
25710
|
const account = validateAccountId2(meta.accountId ?? "");
|
|
25551
25711
|
if (!account) {
|
|
25552
25712
|
console.error(
|
|
25553
|
-
`${
|
|
25713
|
+
`${TAG41} op=account-unresolved sessionId=${sessionId.slice(0, 8)} sidecarAccountId=${meta.accountId ?? "none"}`
|
|
25554
25714
|
);
|
|
25555
25715
|
return c.json({ delivered: false, channel: "none" }, 200);
|
|
25556
25716
|
}
|
|
25557
25717
|
if (meta.role === "admin" && meta.channel === "whatsapp" && meta.senderId) {
|
|
25558
25718
|
const delivered2 = await sendWhatsApp(account, meta.senderId, text);
|
|
25559
|
-
console.error(`${
|
|
25719
|
+
console.error(`${TAG41} op=notify sessionId=${sessionId.slice(0, 8)} channel=whatsapp delivered=${delivered2}`);
|
|
25560
25720
|
return c.json({ delivered: delivered2, channel: "whatsapp" }, 200);
|
|
25561
25721
|
}
|
|
25562
25722
|
if (meta.role === "admin" && meta.channel === "telegram" && meta.senderId) {
|
|
@@ -25566,11 +25726,11 @@ app26.post("/", async (c) => {
|
|
|
25566
25726
|
const chatId = Number(parsed.senderId);
|
|
25567
25727
|
if (resolved.kind === "one" && Number.isFinite(chatId)) {
|
|
25568
25728
|
const res = await sendTelegramText(resolved.entry.token, chatId, text);
|
|
25569
|
-
console.error(`${
|
|
25729
|
+
console.error(`${TAG41} op=notify sessionId=${sessionId.slice(0, 8)} channel=telegram delivered=${res.ok}`);
|
|
25570
25730
|
return c.json({ delivered: res.ok, channel: "telegram" }, 200);
|
|
25571
25731
|
}
|
|
25572
25732
|
console.error(
|
|
25573
|
-
`${
|
|
25733
|
+
`${TAG41} op=telegram-unresolved sessionId=${sessionId.slice(0, 8)} botId=${parsed.botId} kind=${resolved.kind}`
|
|
25574
25734
|
);
|
|
25575
25735
|
}
|
|
25576
25736
|
}
|
|
@@ -25580,7 +25740,7 @@ app26.post("/", async (c) => {
|
|
|
25580
25740
|
if (await sendWhatsApp(account, phone, text)) delivered = true;
|
|
25581
25741
|
}
|
|
25582
25742
|
console.error(
|
|
25583
|
-
`${
|
|
25743
|
+
`${TAG41} op=notify sessionId=${sessionId.slice(0, 8)} channel=house-admin phones=${phones.length} delivered=${delivered}`
|
|
25584
25744
|
);
|
|
25585
25745
|
return c.json({ delivered, channel: "house-admin" }, 200);
|
|
25586
25746
|
});
|
|
@@ -25613,18 +25773,18 @@ var ALLOWED_EVENTS = /* @__PURE__ */ new Set([
|
|
|
25613
25773
|
]);
|
|
25614
25774
|
var app27 = new Hono();
|
|
25615
25775
|
app27.post("/", async (c) => {
|
|
25616
|
-
const
|
|
25776
|
+
const TAG77 = "[admin:events]";
|
|
25617
25777
|
let body;
|
|
25618
25778
|
try {
|
|
25619
25779
|
body = await c.req.json();
|
|
25620
25780
|
} catch (err) {
|
|
25621
25781
|
const detail = err instanceof Error ? err.message : String(err);
|
|
25622
|
-
console.error(`${
|
|
25782
|
+
console.error(`${TAG77} reject reason=body-not-json detail=${detail}`);
|
|
25623
25783
|
return c.json({ ok: false, detail: "Request body was not valid JSON" }, 400);
|
|
25624
25784
|
}
|
|
25625
25785
|
const event = typeof body.event === "string" ? body.event : "";
|
|
25626
25786
|
if (!ALLOWED_EVENTS.has(event)) {
|
|
25627
|
-
console.error(`${
|
|
25787
|
+
console.error(`${TAG77} reject reason=event-not-allowed event=${JSON.stringify(event)}`);
|
|
25628
25788
|
return c.json({ ok: false, detail: `Event "${event}" is not allowed` }, 400);
|
|
25629
25789
|
}
|
|
25630
25790
|
const rawFields = body.fields && typeof body.fields === "object" ? body.fields : {};
|
|
@@ -31189,7 +31349,7 @@ function managerLogFollowUrl(sessionId, opts) {
|
|
|
31189
31349
|
}
|
|
31190
31350
|
|
|
31191
31351
|
// server/routes/admin/linkedin-ingest.ts
|
|
31192
|
-
var
|
|
31352
|
+
var TAG42 = "[linkedin-ingest-route]";
|
|
31193
31353
|
var UUID4 = /^[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}$/;
|
|
31194
31354
|
var ISO = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,3})?(?:Z|[+-]\d{2}:\d{2})$/;
|
|
31195
31355
|
var LINKEDIN_URL = /^https:\/\/www\.linkedin\.com\//;
|
|
@@ -31314,28 +31474,28 @@ app45.post("/", requireIngestToken, async (c) => {
|
|
|
31314
31474
|
try {
|
|
31315
31475
|
body = await c.req.json();
|
|
31316
31476
|
} catch {
|
|
31317
|
-
console.error(
|
|
31477
|
+
console.error(TAG42 + " rejected status=400 reason=schema:body-not-json");
|
|
31318
31478
|
return c.json({ ok: false, error: "schema", reason: "body-not-json" }, 400);
|
|
31319
31479
|
}
|
|
31320
31480
|
const v = validate2(body);
|
|
31321
31481
|
if (!v.ok) {
|
|
31322
|
-
console.error(
|
|
31482
|
+
console.error(TAG42 + " rejected status=" + v.status + " reason=" + v.reason + " missing=" + v.missing.join(","));
|
|
31323
31483
|
return c.json({ ok: false, error: v.error, reason: v.reason, missing: v.missing }, v.status);
|
|
31324
31484
|
}
|
|
31325
31485
|
const envelope = v.envelope;
|
|
31326
31486
|
const senderId = c.var.ingestAccountId ?? "";
|
|
31327
31487
|
if (!senderId) {
|
|
31328
|
-
console.error(
|
|
31488
|
+
console.error(TAG42 + " rejected status=500 reason=admin-account-not-resolved");
|
|
31329
31489
|
return c.json({ ok: false, error: "admin-account-not-resolved" }, 500);
|
|
31330
31490
|
}
|
|
31331
31491
|
const payloadBytes = JSON.stringify(envelope).length;
|
|
31332
31492
|
console.log(
|
|
31333
|
-
|
|
31493
|
+
TAG42 + " received kind=" + envelope.kind + " account=" + senderId.slice(0, 8) + " pageUrl=" + envelope.pageUrl + " dispatchId=" + envelope.dispatchId + " payloadBytes=" + payloadBytes
|
|
31334
31494
|
);
|
|
31335
31495
|
const initialMessage = buildInitialMessage(envelope);
|
|
31336
31496
|
const spawnStart = Date.now();
|
|
31337
31497
|
const sessionId = randomUUID9();
|
|
31338
|
-
console.log(
|
|
31498
|
+
console.log(TAG42 + " route target=rc-spawn dispatchId=" + envelope.dispatchId + " sessionId=" + sessionId.slice(0, 8));
|
|
31339
31499
|
const spawned = await managerRcSpawn({
|
|
31340
31500
|
sessionId,
|
|
31341
31501
|
initialMessage,
|
|
@@ -31348,12 +31508,12 @@ app45.post("/", requireIngestToken, async (c) => {
|
|
|
31348
31508
|
});
|
|
31349
31509
|
if ("error" in spawned) {
|
|
31350
31510
|
console.error(
|
|
31351
|
-
|
|
31511
|
+
TAG42 + " dispatch-failed dispatchId=" + envelope.dispatchId + " status=" + spawned.status + " ms=" + (Date.now() - spawnStart) + " message=" + spawned.error
|
|
31352
31512
|
);
|
|
31353
31513
|
return c.json({ ok: false, error: "dispatch-failed", upstreamStatus: spawned.status, detail: spawned.error }, 502);
|
|
31354
31514
|
}
|
|
31355
31515
|
console.log(
|
|
31356
|
-
|
|
31516
|
+
TAG42 + " dispatched dispatchId=" + envelope.dispatchId + " taskId=" + spawned.sessionId + " ms=" + (Date.now() - spawnStart)
|
|
31357
31517
|
);
|
|
31358
31518
|
return c.json({ ok: true, dispatchId: envelope.dispatchId, taskId: spawned.sessionId }, 202);
|
|
31359
31519
|
});
|
|
@@ -31361,7 +31521,7 @@ var linkedin_ingest_default = app45;
|
|
|
31361
31521
|
|
|
31362
31522
|
// server/routes/admin/post-turn-context.ts
|
|
31363
31523
|
import neo4j3 from "neo4j-driver";
|
|
31364
|
-
var
|
|
31524
|
+
var TAG43 = "[post-turn-context]";
|
|
31365
31525
|
var STRIPPED_PROPERTIES2 = /* @__PURE__ */ new Set([
|
|
31366
31526
|
"embedding",
|
|
31367
31527
|
"passwordHash",
|
|
@@ -31403,7 +31563,7 @@ var app46 = new Hono();
|
|
|
31403
31563
|
app46.get("/", async (c) => {
|
|
31404
31564
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
31405
31565
|
if (!isLoopbackAddr4(remoteAddr)) {
|
|
31406
|
-
console.error(`${
|
|
31566
|
+
console.error(`${TAG43} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
31407
31567
|
return c.json({ error: "post-turn-context-loopback-only" }, 403);
|
|
31408
31568
|
}
|
|
31409
31569
|
const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
|
|
@@ -31412,7 +31572,7 @@ app46.get("/", async (c) => {
|
|
|
31412
31572
|
const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
|
|
31413
31573
|
const offender = tokens.find((t) => !isLoopbackAddr4(t));
|
|
31414
31574
|
if (offender !== void 0) {
|
|
31415
|
-
console.error(`${
|
|
31575
|
+
console.error(`${TAG43} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
|
|
31416
31576
|
return c.json({ error: "post-turn-context-loopback-only" }, 403);
|
|
31417
31577
|
}
|
|
31418
31578
|
}
|
|
@@ -31444,7 +31604,7 @@ app46.get("/", async (c) => {
|
|
|
31444
31604
|
writes.sort((a, b) => a.sortKey.localeCompare(b.sortKey));
|
|
31445
31605
|
const total = Date.now() - started2;
|
|
31446
31606
|
console.log(
|
|
31447
|
-
`${
|
|
31607
|
+
`${TAG43} sessionId=${sessionId} accountId=${accountId} writes=${writes.length} ms=${total}`
|
|
31448
31608
|
);
|
|
31449
31609
|
return c.json({
|
|
31450
31610
|
writes: writes.map(({ elementId, labels, properties }) => ({ elementId, labels, properties }))
|
|
@@ -31453,7 +31613,7 @@ app46.get("/", async (c) => {
|
|
|
31453
31613
|
const elapsed = Date.now() - started2;
|
|
31454
31614
|
const message = err instanceof Error ? err.message : String(err);
|
|
31455
31615
|
console.error(
|
|
31456
|
-
`${
|
|
31616
|
+
`${TAG43} neo4j-unreachable sessionId=${sessionId} ms=${elapsed} err="${message}"`
|
|
31457
31617
|
);
|
|
31458
31618
|
return c.json({ error: `post-turn-context unavailable: ${message}` }, 503);
|
|
31459
31619
|
} finally {
|
|
@@ -31566,7 +31726,7 @@ function formatPreviousContext(writes) {
|
|
|
31566
31726
|
}
|
|
31567
31727
|
|
|
31568
31728
|
// server/routes/admin/public-session-context.ts
|
|
31569
|
-
var
|
|
31729
|
+
var TAG44 = "[public-session-context]";
|
|
31570
31730
|
function isLoopbackAddr5(addr) {
|
|
31571
31731
|
return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
|
|
31572
31732
|
}
|
|
@@ -31574,7 +31734,7 @@ var app47 = new Hono();
|
|
|
31574
31734
|
app47.get("/", async (c) => {
|
|
31575
31735
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
31576
31736
|
if (!isLoopbackAddr5(remoteAddr)) {
|
|
31577
|
-
console.error(`${
|
|
31737
|
+
console.error(`${TAG44} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
31578
31738
|
return c.json({ error: "public-session-context-loopback-only" }, 403);
|
|
31579
31739
|
}
|
|
31580
31740
|
const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
|
|
@@ -31583,7 +31743,7 @@ app47.get("/", async (c) => {
|
|
|
31583
31743
|
const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
|
|
31584
31744
|
const offender = tokens.find((t) => !isLoopbackAddr5(t));
|
|
31585
31745
|
if (offender !== void 0) {
|
|
31586
|
-
console.error(`${
|
|
31746
|
+
console.error(`${TAG44} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
|
|
31587
31747
|
return c.json({ error: "public-session-context-loopback-only" }, 403);
|
|
31588
31748
|
}
|
|
31589
31749
|
}
|
|
@@ -31597,14 +31757,14 @@ app47.get("/", async (c) => {
|
|
|
31597
31757
|
const writes = await fetchSliceWrites(session, sliceToken, accountId);
|
|
31598
31758
|
const total = Date.now() - started2;
|
|
31599
31759
|
console.log(
|
|
31600
|
-
`${
|
|
31760
|
+
`${TAG44} sliceToken=${sliceToken.slice(0, 8)} writes=${writes.length} ms=${total}`
|
|
31601
31761
|
);
|
|
31602
31762
|
return c.json({ writes });
|
|
31603
31763
|
} catch (err) {
|
|
31604
31764
|
const elapsed = Date.now() - started2;
|
|
31605
31765
|
const message = err instanceof Error ? err.message : String(err);
|
|
31606
31766
|
console.error(
|
|
31607
|
-
`${
|
|
31767
|
+
`${TAG44} neo4j-unreachable sliceToken=${sliceToken.slice(0, 8)} ms=${elapsed} err="${message}"`
|
|
31608
31768
|
);
|
|
31609
31769
|
return c.json({ error: `public-session-context unavailable: ${message}` }, 503);
|
|
31610
31770
|
} finally {
|
|
@@ -31623,7 +31783,7 @@ function getWebchatGateway() {
|
|
|
31623
31783
|
}
|
|
31624
31784
|
|
|
31625
31785
|
// server/routes/admin/public-session-exit.ts
|
|
31626
|
-
var
|
|
31786
|
+
var TAG45 = "[public-session-exit-route]";
|
|
31627
31787
|
function isLoopbackAddr6(addr) {
|
|
31628
31788
|
return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
|
|
31629
31789
|
}
|
|
@@ -31631,7 +31791,7 @@ var app48 = new Hono();
|
|
|
31631
31791
|
app48.post("/", async (c) => {
|
|
31632
31792
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
31633
31793
|
if (!isLoopbackAddr6(remoteAddr)) {
|
|
31634
|
-
console.error(`${
|
|
31794
|
+
console.error(`${TAG45} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
31635
31795
|
return c.json({ error: "public-session-exit-loopback-only" }, 403);
|
|
31636
31796
|
}
|
|
31637
31797
|
const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
|
|
@@ -31640,7 +31800,7 @@ app48.post("/", async (c) => {
|
|
|
31640
31800
|
const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
|
|
31641
31801
|
const offender = tokens.find((t) => !isLoopbackAddr6(t));
|
|
31642
31802
|
if (offender !== void 0) {
|
|
31643
|
-
console.error(`${
|
|
31803
|
+
console.error(`${TAG45} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
|
|
31644
31804
|
return c.json({ error: "public-session-exit-loopback-only" }, 403);
|
|
31645
31805
|
}
|
|
31646
31806
|
}
|
|
@@ -31654,7 +31814,7 @@ app48.post("/", async (c) => {
|
|
|
31654
31814
|
if (!sessionId) return c.json({ error: "sessionId required" }, 400);
|
|
31655
31815
|
const gateway = getWebchatGateway();
|
|
31656
31816
|
if (!gateway) {
|
|
31657
|
-
console.error(`${
|
|
31817
|
+
console.error(`${TAG45} reject reason=gateway-unset sessionId=${sessionId.slice(0, 8)}`);
|
|
31658
31818
|
return c.json({ error: "webchat-gateway-unset" }, 503);
|
|
31659
31819
|
}
|
|
31660
31820
|
gateway.handlePublicSessionExit(sessionId);
|
|
@@ -31663,7 +31823,7 @@ app48.post("/", async (c) => {
|
|
|
31663
31823
|
var public_session_exit_default = app48;
|
|
31664
31824
|
|
|
31665
31825
|
// server/routes/admin/access-session-evict.ts
|
|
31666
|
-
var
|
|
31826
|
+
var TAG46 = "[access-session-evict]";
|
|
31667
31827
|
function isLoopbackAddr7(addr) {
|
|
31668
31828
|
return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
|
|
31669
31829
|
}
|
|
@@ -31671,7 +31831,7 @@ var app49 = new Hono();
|
|
|
31671
31831
|
app49.post("/", async (c) => {
|
|
31672
31832
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
31673
31833
|
if (!isLoopbackAddr7(remoteAddr)) {
|
|
31674
|
-
console.error(`${
|
|
31834
|
+
console.error(`${TAG46} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
31675
31835
|
return c.json({ error: "access-session-evict-loopback-only" }, 403);
|
|
31676
31836
|
}
|
|
31677
31837
|
const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
|
|
@@ -31680,7 +31840,7 @@ app49.post("/", async (c) => {
|
|
|
31680
31840
|
const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
|
|
31681
31841
|
const offender = tokens.find((t) => !isLoopbackAddr7(t));
|
|
31682
31842
|
if (offender !== void 0) {
|
|
31683
|
-
console.error(`${
|
|
31843
|
+
console.error(`${TAG46} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
|
|
31684
31844
|
return c.json({ error: "access-session-evict-loopback-only" }, 403);
|
|
31685
31845
|
}
|
|
31686
31846
|
}
|
|
@@ -31693,13 +31853,13 @@ app49.post("/", async (c) => {
|
|
|
31693
31853
|
const grantId = typeof body.grantId === "string" ? body.grantId.trim() : "";
|
|
31694
31854
|
if (!grantId) return c.json({ error: "grantId required" }, 400);
|
|
31695
31855
|
const dropped = evictAccessSessionsByGrant(grantId);
|
|
31696
|
-
console.log(`${
|
|
31856
|
+
console.log(`${TAG46} grantId=${grantId} dropped=${dropped}`);
|
|
31697
31857
|
return c.json({ ok: true, dropped });
|
|
31698
31858
|
});
|
|
31699
31859
|
var access_session_evict_default = app49;
|
|
31700
31860
|
|
|
31701
31861
|
// server/routes/admin/enrol-person.ts
|
|
31702
|
-
var
|
|
31862
|
+
var TAG47 = "[enrol]";
|
|
31703
31863
|
function isLoopbackAddr8(addr) {
|
|
31704
31864
|
return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
|
|
31705
31865
|
}
|
|
@@ -31708,7 +31868,7 @@ var app50 = new Hono();
|
|
|
31708
31868
|
app50.post("/", async (c) => {
|
|
31709
31869
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
31710
31870
|
if (!isLoopbackAddr8(remoteAddr)) {
|
|
31711
|
-
console.error(`${
|
|
31871
|
+
console.error(`${TAG47} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
31712
31872
|
return c.json({ error: "enrol-person-loopback-only" }, 403);
|
|
31713
31873
|
}
|
|
31714
31874
|
const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
|
|
@@ -31717,7 +31877,7 @@ app50.post("/", async (c) => {
|
|
|
31717
31877
|
const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
|
|
31718
31878
|
const offender = tokens.find((t) => !isLoopbackAddr8(t));
|
|
31719
31879
|
if (offender !== void 0) {
|
|
31720
|
-
console.error(`${
|
|
31880
|
+
console.error(`${TAG47} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
|
|
31721
31881
|
return c.json({ error: "enrol-person-loopback-only" }, 403);
|
|
31722
31882
|
}
|
|
31723
31883
|
}
|
|
@@ -31742,7 +31902,7 @@ app50.post("/", async (c) => {
|
|
|
31742
31902
|
}
|
|
31743
31903
|
const accountId = process.env.ACCOUNT_ID ?? "";
|
|
31744
31904
|
if (!accountId) {
|
|
31745
|
-
console.error(`${
|
|
31905
|
+
console.error(`${TAG47} op=person result=no-account-id`);
|
|
31746
31906
|
return c.json({ error: "no-account-id" }, 500);
|
|
31747
31907
|
}
|
|
31748
31908
|
let personId;
|
|
@@ -31750,7 +31910,7 @@ app50.post("/", async (c) => {
|
|
|
31750
31910
|
personId = await enrolPerson({ accountId, phone, email, agentSlug });
|
|
31751
31911
|
} catch (err) {
|
|
31752
31912
|
console.error(
|
|
31753
|
-
`${
|
|
31913
|
+
`${TAG47} op=person result=write-failed agentSlug=${agentSlug} contact=${maskContact(email)} err="${err instanceof Error ? err.message : String(err)}"`
|
|
31754
31914
|
);
|
|
31755
31915
|
return c.json({ error: "enrol-failed" }, 500);
|
|
31756
31916
|
}
|
|
@@ -31760,11 +31920,11 @@ app50.post("/", async (c) => {
|
|
|
31760
31920
|
if (g) grant = { grantId: g.grantId, status: g.status, contactValue: g.contactValue };
|
|
31761
31921
|
} catch (err) {
|
|
31762
31922
|
console.error(
|
|
31763
|
-
`${
|
|
31923
|
+
`${TAG47} op=person result=grant-lookup-failed contact=${maskContact(email)} err="${err instanceof Error ? err.message : String(err)}"`
|
|
31764
31924
|
);
|
|
31765
31925
|
}
|
|
31766
31926
|
console.log(
|
|
31767
|
-
`${
|
|
31927
|
+
`${TAG47} op=person personId=${personId} account=${accountId} agentSlug=${agentSlug} contact=${maskContact(email)}`
|
|
31768
31928
|
);
|
|
31769
31929
|
return c.json({ personId, grant }, 200);
|
|
31770
31930
|
});
|
|
@@ -33832,7 +33992,7 @@ function toNum(v) {
|
|
|
33832
33992
|
}
|
|
33833
33993
|
|
|
33834
33994
|
// server/routes/admin/tasks-list.ts
|
|
33835
|
-
var
|
|
33995
|
+
var TAG48 = "[task-timer]";
|
|
33836
33996
|
var COMPLETED = /* @__PURE__ */ new Set(["completed"]);
|
|
33837
33997
|
var HIDDEN_FROM_OPEN = /* @__PURE__ */ new Set(["completed", "cancelled"]);
|
|
33838
33998
|
var app57 = new Hono();
|
|
@@ -33840,12 +34000,12 @@ app57.get("/", requireAdminSession, async (c) => {
|
|
|
33840
34000
|
const cacheKey = c.var.cacheKey;
|
|
33841
34001
|
const accountId = getAccountIdForSession(cacheKey);
|
|
33842
34002
|
if (!accountId) {
|
|
33843
|
-
console.error(`${
|
|
34003
|
+
console.error(`${TAG48} op=list auth-rejected reason="no account for session"`);
|
|
33844
34004
|
return c.json({ error: "Account not found for session" }, 401);
|
|
33845
34005
|
}
|
|
33846
34006
|
const cacheStart = Date.now();
|
|
33847
34007
|
const cached3 = await getOrCompute("tasks-list", accountId, () => computeTaskList(accountId));
|
|
33848
|
-
console.log(`${
|
|
34008
|
+
console.log(`${TAG48} op=list-cache cache=${cached3.state} account=${accountId} ms=${Date.now() - cacheStart}`);
|
|
33849
34009
|
if (cached3.value === null) {
|
|
33850
34010
|
return c.json({ error: "tasks-list-failed" }, 500);
|
|
33851
34011
|
}
|
|
@@ -33946,13 +34106,13 @@ async function computeTaskList(accountId) {
|
|
|
33946
34106
|
orphans = orphanResult.records.length > 0 ? toNum(orphanResult.records[0].get("orphans")) : 0;
|
|
33947
34107
|
} catch (err) {
|
|
33948
34108
|
console.error(
|
|
33949
|
-
`${
|
|
34109
|
+
`${TAG48} op=session-orphans-census-failed account=${accountId} error="${err instanceof Error ? err.message : String(err)}"`
|
|
33950
34110
|
);
|
|
33951
34111
|
orphans = -1;
|
|
33952
34112
|
}
|
|
33953
34113
|
if (orphans > 0) {
|
|
33954
34114
|
console.error(
|
|
33955
|
-
`${
|
|
34115
|
+
`${TAG48} op=session-orphans account=${accountId} orphans=${orphans} detail="task marked for a session spawn that never linked; the spawned session is unreachable from its row"`
|
|
33956
34116
|
);
|
|
33957
34117
|
}
|
|
33958
34118
|
let orphanEntries = 0;
|
|
@@ -33971,14 +34131,14 @@ async function computeTaskList(accountId) {
|
|
|
33971
34131
|
orphanAdjustments = orphanTime.records.length > 0 ? toNum(orphanTime.records[0].get("orphanAdjustments")) : 0;
|
|
33972
34132
|
} catch (err) {
|
|
33973
34133
|
console.error(
|
|
33974
|
-
`${
|
|
34134
|
+
`${TAG48} op=orphan-time-records-census-failed account=${accountId} error="${err instanceof Error ? err.message : String(err)}"`
|
|
33975
34135
|
);
|
|
33976
34136
|
orphanEntries = -1;
|
|
33977
34137
|
orphanAdjustments = -1;
|
|
33978
34138
|
}
|
|
33979
34139
|
if (orphanEntries > 0 || orphanAdjustments > 0) {
|
|
33980
34140
|
console.error(
|
|
33981
|
-
`${
|
|
34141
|
+
`${TAG48} op=orphan-time-records account=${accountId} orphanEntries=${orphanEntries} orphanAdjustments=${orphanAdjustments} detail="time records whose task no longer exists; something removed the task without its records"`
|
|
33982
34142
|
);
|
|
33983
34143
|
}
|
|
33984
34144
|
const linkedIds = [...open3, ...completed].map((r) => r.sessionId).filter((s) => s !== null);
|
|
@@ -33991,7 +34151,7 @@ async function computeTaskList(accountId) {
|
|
|
33991
34151
|
const walk = enumerateJsonlsWithSkips(join60(cfg, "projects"));
|
|
33992
34152
|
if (walk.skipped > 0) {
|
|
33993
34153
|
console.error(
|
|
33994
|
-
`${
|
|
34154
|
+
`${TAG48} op=session-dangling-census-incomplete account=${accountId} skipped=${walk.skipped} detail="a slug the walk could not read contributes no session ids, so its links cannot be judged"`
|
|
33995
34155
|
);
|
|
33996
34156
|
dangling = null;
|
|
33997
34157
|
} else {
|
|
@@ -34000,28 +34160,28 @@ async function computeTaskList(accountId) {
|
|
|
34000
34160
|
}
|
|
34001
34161
|
} catch (err) {
|
|
34002
34162
|
console.error(
|
|
34003
|
-
`${
|
|
34163
|
+
`${TAG48} op=session-dangling-census-failed account=${accountId} error="${err instanceof Error ? err.message : String(err)}"`
|
|
34004
34164
|
);
|
|
34005
34165
|
dangling = null;
|
|
34006
34166
|
}
|
|
34007
34167
|
}
|
|
34008
34168
|
if (dangling !== null && dangling > 0) {
|
|
34009
34169
|
console.error(
|
|
34010
|
-
`${
|
|
34170
|
+
`${TAG48} op=session-dangling account=${accountId} dangling=${dangling} linked=${linkedIds.length} detail="a task links a session with no JSONL on disk; clicking it will not resume"`
|
|
34011
34171
|
);
|
|
34012
34172
|
}
|
|
34013
34173
|
const returned = result.records.length;
|
|
34014
34174
|
if (returned < graphTotal) {
|
|
34015
34175
|
console.error(
|
|
34016
|
-
`${
|
|
34176
|
+
`${TAG48} op=list row-count-shortfall account=${accountId} returned=${returned} graphTotal=${graphTotal} missing=${graphTotal - returned}`
|
|
34017
34177
|
);
|
|
34018
34178
|
}
|
|
34019
34179
|
console.log(
|
|
34020
|
-
`${
|
|
34180
|
+
`${TAG48} op=list account=${accountId} returned=${returned} graphTotal=${graphTotal} open=${open3.length} completed=${completed.length} missingTaskId=${missingTaskId} missingCreatedAt=${missingCreatedAt} assigned=${assigned} sessionLinked=${sessionLinked} sessionOrphans=${orphans < 0 ? "n/a" : orphans} sessionDangling=${dangling === null ? "n/a" : dangling}`
|
|
34021
34181
|
);
|
|
34022
34182
|
return { open: open3, completed };
|
|
34023
34183
|
} catch (err) {
|
|
34024
|
-
console.error(`${
|
|
34184
|
+
console.error(`${TAG48} op=list error="${err instanceof Error ? err.message : String(err)}"`);
|
|
34025
34185
|
return null;
|
|
34026
34186
|
} finally {
|
|
34027
34187
|
await session.close();
|
|
@@ -34031,7 +34191,7 @@ var tasks_list_default = app57;
|
|
|
34031
34191
|
|
|
34032
34192
|
// server/routes/admin/task-timer-start.ts
|
|
34033
34193
|
import { randomUUID as randomUUID11 } from "crypto";
|
|
34034
|
-
var
|
|
34194
|
+
var TAG49 = "[task-timer]";
|
|
34035
34195
|
var app58 = new Hono();
|
|
34036
34196
|
app58.post("/", requireAdminSession, async (c) => {
|
|
34037
34197
|
const cacheKey = c.var.cacheKey;
|
|
@@ -34046,7 +34206,7 @@ app58.post("/", requireAdminSession, async (c) => {
|
|
|
34046
34206
|
const taskId = typeof body.taskId === "string" ? body.taskId : "";
|
|
34047
34207
|
if (!taskId) {
|
|
34048
34208
|
const reason = body.taskId === null ? "null-taskId" : "missing-taskId";
|
|
34049
|
-
console.error(`${
|
|
34209
|
+
console.error(`${TAG49} op=timer-start rejected reason=${reason} account=${accountId}`);
|
|
34050
34210
|
return c.json({ error: "taskId required" }, 400);
|
|
34051
34211
|
}
|
|
34052
34212
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -34057,7 +34217,7 @@ app58.post("/", requireAdminSession, async (c) => {
|
|
|
34057
34217
|
{ taskId, accountId }
|
|
34058
34218
|
);
|
|
34059
34219
|
if (target.records.length === 0) {
|
|
34060
|
-
console.error(`${
|
|
34220
|
+
console.error(`${TAG49} op=start taskId=${taskId} accountId=${accountId} result=task-not-found`);
|
|
34061
34221
|
return c.json({ error: "task-not-found" }, 404);
|
|
34062
34222
|
}
|
|
34063
34223
|
const open3 = await session.run(
|
|
@@ -34069,7 +34229,7 @@ app58.post("/", requireAdminSession, async (c) => {
|
|
|
34069
34229
|
const priorEntryId = open3.records[0]?.get("entryId");
|
|
34070
34230
|
const priorStartedAt = open3.records[0]?.get("startedAt");
|
|
34071
34231
|
if (priorEntryId) {
|
|
34072
|
-
console.log(`${
|
|
34232
|
+
console.log(`${TAG49} op=start taskId=${taskId} accountId=${accountId} result=already-running`);
|
|
34073
34233
|
invalidate("tasks-list", accountId);
|
|
34074
34234
|
return c.json({ ok: true, running: true, entryId: priorEntryId, startedAt: priorStartedAt });
|
|
34075
34235
|
}
|
|
@@ -34080,11 +34240,11 @@ app58.post("/", requireAdminSession, async (c) => {
|
|
|
34080
34240
|
CREATE (te)-[:LOGGED_AGAINST]->(t)`,
|
|
34081
34241
|
{ taskId, accountId, entryId, now }
|
|
34082
34242
|
);
|
|
34083
|
-
console.log(`${
|
|
34243
|
+
console.log(`${TAG49} op=opened taskId=${taskId} entryId=${entryId} startedAt=${now}`);
|
|
34084
34244
|
invalidate("tasks-list", accountId);
|
|
34085
34245
|
return c.json({ ok: true, running: true, entryId, startedAt: now });
|
|
34086
34246
|
} catch (err) {
|
|
34087
|
-
console.error(`${
|
|
34247
|
+
console.error(`${TAG49} op=start error="${err instanceof Error ? err.message : String(err)}"`);
|
|
34088
34248
|
return c.json({ error: "task-timer-start-failed" }, 500);
|
|
34089
34249
|
} finally {
|
|
34090
34250
|
await session.close();
|
|
@@ -34094,7 +34254,7 @@ var task_timer_start_default = app58;
|
|
|
34094
34254
|
|
|
34095
34255
|
// server/routes/admin/task-timer-stop.ts
|
|
34096
34256
|
import neo4j5 from "neo4j-driver";
|
|
34097
|
-
var
|
|
34257
|
+
var TAG50 = "[task-timer]";
|
|
34098
34258
|
var app59 = new Hono();
|
|
34099
34259
|
app59.post("/", requireAdminSession, async (c) => {
|
|
34100
34260
|
const cacheKey = c.var.cacheKey;
|
|
@@ -34109,7 +34269,7 @@ app59.post("/", requireAdminSession, async (c) => {
|
|
|
34109
34269
|
const taskId = typeof body.taskId === "string" ? body.taskId : "";
|
|
34110
34270
|
if (!taskId) {
|
|
34111
34271
|
const reason = body.taskId === null ? "null-taskId" : "missing-taskId";
|
|
34112
|
-
console.error(`${
|
|
34272
|
+
console.error(`${TAG50} op=timer-stop rejected reason=${reason} account=${accountId}`);
|
|
34113
34273
|
return c.json({ error: "taskId required" }, 400);
|
|
34114
34274
|
}
|
|
34115
34275
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -34130,7 +34290,7 @@ app59.post("/", requireAdminSession, async (c) => {
|
|
|
34130
34290
|
{ taskId, accountId }
|
|
34131
34291
|
);
|
|
34132
34292
|
const secondsLogged2 = toNum(cur.records[0]?.get("secondsLogged"));
|
|
34133
|
-
console.log(`${
|
|
34293
|
+
console.log(`${TAG50} op=stop taskId=${taskId} entryId=none seconds=0 totalAfter=${secondsLogged2}`);
|
|
34134
34294
|
invalidate("tasks-list", accountId);
|
|
34135
34295
|
return c.json({ ok: true, running: false, seconds: 0, secondsLogged: secondsLogged2 });
|
|
34136
34296
|
}
|
|
@@ -34154,12 +34314,12 @@ app59.post("/", requireAdminSession, async (c) => {
|
|
|
34154
34314
|
const sumEntries = toNum(verify.records[0]?.get("sumEntries"));
|
|
34155
34315
|
const sumAdjustments = toNum(verify.records[0]?.get("sumAdjustments"));
|
|
34156
34316
|
const secondsLogged = toNum(verify.records[0]?.get("secondsLogged"));
|
|
34157
|
-
console.log(`${
|
|
34158
|
-
console.log(`${
|
|
34317
|
+
console.log(`${TAG50} op=stop taskId=${taskId} entryId=${entryId} seconds=${seconds} totalAfter=${secondsLogged}`);
|
|
34318
|
+
console.log(`${TAG50} op=persisted taskId=${taskId} entryId=${entryId} sumEntries=${sumEntries} sumAdjustments=${sumAdjustments} secondsLogged=${secondsLogged}`);
|
|
34159
34319
|
invalidate("tasks-list", accountId);
|
|
34160
34320
|
return c.json({ ok: true, running: false, seconds, secondsLogged });
|
|
34161
34321
|
} catch (err) {
|
|
34162
|
-
console.error(`${
|
|
34322
|
+
console.error(`${TAG50} op=stop error="${err instanceof Error ? err.message : String(err)}"`);
|
|
34163
34323
|
return c.json({ error: "task-timer-stop-failed" }, 500);
|
|
34164
34324
|
} finally {
|
|
34165
34325
|
await session.close();
|
|
@@ -34168,7 +34328,7 @@ app59.post("/", requireAdminSession, async (c) => {
|
|
|
34168
34328
|
var task_timer_stop_default = app59;
|
|
34169
34329
|
|
|
34170
34330
|
// server/routes/admin/task-complete.ts
|
|
34171
|
-
var
|
|
34331
|
+
var TAG51 = "[task-timer]";
|
|
34172
34332
|
var app60 = new Hono();
|
|
34173
34333
|
app60.post("/", requireAdminSession, async (c) => {
|
|
34174
34334
|
const cacheKey = c.var.cacheKey;
|
|
@@ -34183,7 +34343,7 @@ app60.post("/", requireAdminSession, async (c) => {
|
|
|
34183
34343
|
const taskId = typeof body.taskId === "string" ? body.taskId : "";
|
|
34184
34344
|
if (!taskId) {
|
|
34185
34345
|
const reason = body.taskId === null ? "null-taskId" : "missing-taskId";
|
|
34186
|
-
console.error(`${
|
|
34346
|
+
console.error(`${TAG51} op=complete rejected reason=${reason} account=${accountId}`);
|
|
34187
34347
|
return c.json({ error: "taskId required" }, 400);
|
|
34188
34348
|
}
|
|
34189
34349
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -34199,11 +34359,11 @@ app60.post("/", requireAdminSession, async (c) => {
|
|
|
34199
34359
|
return c.json({ error: "task-not-found" }, 404);
|
|
34200
34360
|
}
|
|
34201
34361
|
const secondsLogged = toNum(result.records[0].get("secondsLogged"));
|
|
34202
|
-
console.log(`${
|
|
34362
|
+
console.log(`${TAG51} op=complete taskId=${taskId} status=completed secondsLogged=${secondsLogged}`);
|
|
34203
34363
|
invalidate("tasks-list", accountId);
|
|
34204
34364
|
return c.json({ ok: true, status: "completed", secondsLogged });
|
|
34205
34365
|
} catch (err) {
|
|
34206
|
-
console.error(`${
|
|
34366
|
+
console.error(`${TAG51} op=complete error="${err instanceof Error ? err.message : String(err)}"`);
|
|
34207
34367
|
return c.json({ error: "task-complete-failed" }, 500);
|
|
34208
34368
|
} finally {
|
|
34209
34369
|
await session.close();
|
|
@@ -34214,7 +34374,7 @@ var task_complete_default = app60;
|
|
|
34214
34374
|
// server/routes/admin/task-time-adjust.ts
|
|
34215
34375
|
import { randomUUID as randomUUID12 } from "crypto";
|
|
34216
34376
|
import neo4j6 from "neo4j-driver";
|
|
34217
|
-
var
|
|
34377
|
+
var TAG52 = "[task-time-adjust]";
|
|
34218
34378
|
var app61 = new Hono();
|
|
34219
34379
|
app61.post("/", requireAdminSession, async (c) => {
|
|
34220
34380
|
const cacheKey = c.var.cacheKey;
|
|
@@ -34224,23 +34384,23 @@ app61.post("/", requireAdminSession, async (c) => {
|
|
|
34224
34384
|
try {
|
|
34225
34385
|
body = await c.req.json();
|
|
34226
34386
|
} catch {
|
|
34227
|
-
console.error(`${
|
|
34387
|
+
console.error(`${TAG52} op=reject reason=bad-json`);
|
|
34228
34388
|
return c.json({ error: "invalid-json" }, 400);
|
|
34229
34389
|
}
|
|
34230
34390
|
const taskId = typeof body.taskId === "string" ? body.taskId : "";
|
|
34231
34391
|
if (!taskId) {
|
|
34232
34392
|
const reason = body.taskId === null ? "null-taskId" : "missing-taskId";
|
|
34233
|
-
console.error(`${
|
|
34393
|
+
console.error(`${TAG52} op=time-adjust rejected reason=${reason} account=${accountId}`);
|
|
34234
34394
|
return c.json({ error: "taskId required" }, 400);
|
|
34235
34395
|
}
|
|
34236
34396
|
const newSeconds = body.newSeconds;
|
|
34237
34397
|
if (typeof newSeconds !== "number" || !Number.isInteger(newSeconds) || newSeconds < 0) {
|
|
34238
|
-
console.error(`${
|
|
34398
|
+
console.error(`${TAG52} op=reject reason=invalid-seconds taskId=${taskId} accountId=${accountId}`);
|
|
34239
34399
|
return c.json({ error: "newSeconds must be a non-negative integer" }, 400);
|
|
34240
34400
|
}
|
|
34241
34401
|
const adjustmentId = randomUUID12();
|
|
34242
34402
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
34243
|
-
console.log(`${
|
|
34403
|
+
console.log(`${TAG52} op=request adjustmentId=${adjustmentId} taskId=${taskId} accountId=${accountId} newSeconds=${newSeconds}`);
|
|
34244
34404
|
const session = getSession();
|
|
34245
34405
|
try {
|
|
34246
34406
|
const guard = await session.run(
|
|
@@ -34250,12 +34410,12 @@ app61.post("/", requireAdminSession, async (c) => {
|
|
|
34250
34410
|
{ taskId, accountId }
|
|
34251
34411
|
);
|
|
34252
34412
|
if (guard.records.length === 0) {
|
|
34253
|
-
console.error(`${
|
|
34413
|
+
console.error(`${TAG52} op=reject reason=no-task adjustmentId=${adjustmentId} taskId=${taskId} accountId=${accountId}`);
|
|
34254
34414
|
return c.json({ error: "task-not-found" }, 404);
|
|
34255
34415
|
}
|
|
34256
34416
|
const openCount = toNum(guard.records[0].get("openCount"));
|
|
34257
34417
|
if (openCount > 0) {
|
|
34258
|
-
console.error(`${
|
|
34418
|
+
console.error(`${TAG52} op=reject reason=running adjustmentId=${adjustmentId} taskId=${taskId} accountId=${accountId}`);
|
|
34259
34419
|
return c.json({ error: "task-timer-running" }, 409);
|
|
34260
34420
|
}
|
|
34261
34421
|
const previousSeconds = toNum(guard.records[0].get("previousSeconds"));
|
|
@@ -34281,11 +34441,11 @@ app61.post("/", requireAdminSession, async (c) => {
|
|
|
34281
34441
|
}
|
|
34282
34442
|
);
|
|
34283
34443
|
const secondsLoggedAfter = toNum(write.records[0]?.get("secondsLoggedAfter"));
|
|
34284
|
-
console.log(`${
|
|
34444
|
+
console.log(`${TAG52} op=persisted adjustmentId=${adjustmentId} previousSeconds=${previousSeconds} newSeconds=${newSeconds} delta=${delta} secondsLoggedAfter=${secondsLoggedAfter}`);
|
|
34285
34445
|
invalidate("tasks-list", accountId);
|
|
34286
34446
|
return c.json({ ok: true, secondsLogged: secondsLoggedAfter });
|
|
34287
34447
|
} catch (err) {
|
|
34288
|
-
console.error(`${
|
|
34448
|
+
console.error(`${TAG52} op=error adjustmentId=${adjustmentId} taskId=${taskId} error="${err instanceof Error ? err.message : String(err)}"`);
|
|
34289
34449
|
return c.json({ error: "task-time-adjust-failed" }, 500);
|
|
34290
34450
|
} finally {
|
|
34291
34451
|
await session.close();
|
|
@@ -34295,7 +34455,7 @@ var task_time_adjust_default = app61;
|
|
|
34295
34455
|
|
|
34296
34456
|
// server/routes/admin/task-delete.ts
|
|
34297
34457
|
import { randomUUID as randomUUID13 } from "crypto";
|
|
34298
|
-
var
|
|
34458
|
+
var TAG53 = "[task-delete]";
|
|
34299
34459
|
var app62 = new Hono();
|
|
34300
34460
|
app62.post("/", requireAdminSession, async (c) => {
|
|
34301
34461
|
const cacheKey = c.var.cacheKey;
|
|
@@ -34305,18 +34465,18 @@ app62.post("/", requireAdminSession, async (c) => {
|
|
|
34305
34465
|
try {
|
|
34306
34466
|
body = await c.req.json();
|
|
34307
34467
|
} catch {
|
|
34308
|
-
console.error(`${
|
|
34468
|
+
console.error(`${TAG53} op=reject reason=bad-json`);
|
|
34309
34469
|
return c.json({ error: "invalid-json" }, 400);
|
|
34310
34470
|
}
|
|
34311
34471
|
const deletionId = randomUUID13();
|
|
34312
34472
|
const taskId = typeof body.taskId === "string" ? body.taskId : "";
|
|
34313
34473
|
if (!taskId) {
|
|
34314
34474
|
const reason = body.taskId === null ? "null-taskId" : "missing-taskId";
|
|
34315
|
-
console.error(`${
|
|
34475
|
+
console.error(`${TAG53} op=reject reason=${reason} deletionId=${deletionId} accountId=${accountId}`);
|
|
34316
34476
|
return c.json({ error: "taskId required" }, 400);
|
|
34317
34477
|
}
|
|
34318
34478
|
console.log(
|
|
34319
|
-
`${
|
|
34479
|
+
`${TAG53} op=request deletionId=${deletionId} taskId=${taskId} accountId=${accountId} confirmed=${body.confirmed === true}`
|
|
34320
34480
|
);
|
|
34321
34481
|
const session = getSession();
|
|
34322
34482
|
try {
|
|
@@ -34332,18 +34492,18 @@ app62.post("/", requireAdminSession, async (c) => {
|
|
|
34332
34492
|
{ taskId, accountId }
|
|
34333
34493
|
);
|
|
34334
34494
|
if (guard.records.length === 0) {
|
|
34335
|
-
console.error(`${
|
|
34495
|
+
console.error(`${TAG53} op=reject reason=no-task deletionId=${deletionId} taskId=${taskId} accountId=${accountId}`);
|
|
34336
34496
|
return c.json({ error: "task-not-found" }, 404);
|
|
34337
34497
|
}
|
|
34338
34498
|
const timeEntries = toNum(guard.records[0].get("timeEntries"));
|
|
34339
34499
|
const openCount = toNum(guard.records[0].get("openCount"));
|
|
34340
34500
|
const adjustments = toNum(guard.records[0].get("adjustments"));
|
|
34341
34501
|
console.log(
|
|
34342
|
-
`${
|
|
34502
|
+
`${TAG53} op=guard deletionId=${deletionId} taskId=${taskId} openCount=${openCount} timeEntries=${timeEntries} adjustments=${adjustments}`
|
|
34343
34503
|
);
|
|
34344
34504
|
if (openCount > 0) {
|
|
34345
34505
|
console.error(
|
|
34346
|
-
`${
|
|
34506
|
+
`${TAG53} op=reject reason=running deletionId=${deletionId} taskId=${taskId} openCount=${openCount}`
|
|
34347
34507
|
);
|
|
34348
34508
|
return c.json({ error: "task-timer-running" }, 409);
|
|
34349
34509
|
}
|
|
@@ -34379,18 +34539,18 @@ app62.post("/", requireAdminSession, async (c) => {
|
|
|
34379
34539
|
const adjustmentsLeft = toNum(after.records[0]?.get("adjustmentsLeft"));
|
|
34380
34540
|
const remaining = taskLeft + entriesLeft + adjustmentsLeft;
|
|
34381
34541
|
console.log(
|
|
34382
|
-
`${
|
|
34542
|
+
`${TAG53} op=persisted deletionId=${deletionId} taskId=${taskId} tasksDeleted=${tasksDeleted} timeEntriesDeleted=${timeEntriesDeleted} adjustmentsDeleted=${adjustmentsDeleted} remaining=${remaining}`
|
|
34383
34543
|
);
|
|
34384
34544
|
if (remaining > 0) {
|
|
34385
34545
|
console.error(
|
|
34386
|
-
`${
|
|
34546
|
+
`${TAG53} op=incomplete deletionId=${deletionId} taskId=${taskId} taskLeft=${taskLeft} entriesLeft=${entriesLeft} adjustmentsLeft=${adjustmentsLeft} detail="the delete returned but rows for this taskId survive"`
|
|
34387
34547
|
);
|
|
34388
34548
|
}
|
|
34389
34549
|
invalidate("tasks-list", accountId);
|
|
34390
34550
|
return c.json({ ok: true, tasksDeleted, timeEntriesDeleted, adjustmentsDeleted, remaining });
|
|
34391
34551
|
} catch (err) {
|
|
34392
34552
|
console.error(
|
|
34393
|
-
`${
|
|
34553
|
+
`${TAG53} op=error deletionId=${deletionId} taskId=${taskId} error="${err instanceof Error ? err.message : String(err)}"`
|
|
34394
34554
|
);
|
|
34395
34555
|
return c.json({ error: "task-delete-failed" }, 500);
|
|
34396
34556
|
} finally {
|
|
@@ -34484,7 +34644,7 @@ async function resolveAssignableAdmins(accountId, accountsDir = ACCOUNTS_DIR) {
|
|
|
34484
34644
|
}
|
|
34485
34645
|
|
|
34486
34646
|
// server/routes/admin/task-assign.ts
|
|
34487
|
-
var
|
|
34647
|
+
var TAG54 = "[task-assign]";
|
|
34488
34648
|
var app63 = new Hono();
|
|
34489
34649
|
app63.post("/", requireAdminSession, async (c) => {
|
|
34490
34650
|
const cacheKey = c.var.cacheKey;
|
|
@@ -34499,7 +34659,7 @@ app63.post("/", requireAdminSession, async (c) => {
|
|
|
34499
34659
|
const taskId = typeof body.taskId === "string" ? body.taskId : "";
|
|
34500
34660
|
if (!taskId) {
|
|
34501
34661
|
const reason = body.taskId === null ? "null-taskId" : "missing-taskId";
|
|
34502
|
-
console.error(`${
|
|
34662
|
+
console.error(`${TAG54} op=assign rejected reason=${reason} account=${accountId}`);
|
|
34503
34663
|
return c.json({ error: "taskId required" }, 400);
|
|
34504
34664
|
}
|
|
34505
34665
|
const rawAssignee = body.assigneeUserId;
|
|
@@ -34511,7 +34671,7 @@ app63.post("/", requireAdminSession, async (c) => {
|
|
|
34511
34671
|
const { ids } = await resolveAllowedAssigneeIds(accountId);
|
|
34512
34672
|
if (!ids.has(assigneeUserId)) {
|
|
34513
34673
|
console.error(
|
|
34514
|
-
`${
|
|
34674
|
+
`${TAG54} op=assign taskId=${taskId.slice(0, 8)} assigneeUserId=${assigneeUserId.slice(0, 8)} assigned=false source=route reason=not-in-roster`
|
|
34515
34675
|
);
|
|
34516
34676
|
return c.json({ error: "assignee-not-in-roster" }, 403);
|
|
34517
34677
|
}
|
|
@@ -34533,7 +34693,7 @@ app63.post("/", requireAdminSession, async (c) => {
|
|
|
34533
34693
|
`MATCH (t:Task {taskId: $taskId, accountId: $accountId}) SET t.updatedAt = $now`,
|
|
34534
34694
|
{ taskId, accountId, now }
|
|
34535
34695
|
);
|
|
34536
|
-
console.log(`${
|
|
34696
|
+
console.log(`${TAG54} op=assign taskId=${taskId.slice(0, 8)} assigneeUserId=none assigned=false source=route`);
|
|
34537
34697
|
invalidate("tasks-list", accountId);
|
|
34538
34698
|
return c.json({ ok: true, assigneeUserId: null, assigneeName: null });
|
|
34539
34699
|
}
|
|
@@ -34549,7 +34709,7 @@ app63.post("/", requireAdminSession, async (c) => {
|
|
|
34549
34709
|
);
|
|
34550
34710
|
if (set.records.length === 0) {
|
|
34551
34711
|
console.error(
|
|
34552
|
-
`${
|
|
34712
|
+
`${TAG54} op=assign taskId=${taskId.slice(0, 8)} assigneeUserId=${assigneeUserId.slice(0, 8)} assigned=false source=route reason=no-adminuser-node`
|
|
34553
34713
|
);
|
|
34554
34714
|
return c.json({ error: "assignee-no-admin-node" }, 409);
|
|
34555
34715
|
}
|
|
@@ -34557,12 +34717,12 @@ app63.post("/", requireAdminSession, async (c) => {
|
|
|
34557
34717
|
const family = set.records[0].get("familyName") ?? null;
|
|
34558
34718
|
const assigneeName = given && given.trim().length > 0 ? family && family.trim().length > 0 ? `${given.trim()} ${family.trim()}` : given.trim() : null;
|
|
34559
34719
|
console.log(
|
|
34560
|
-
`${
|
|
34720
|
+
`${TAG54} op=assign taskId=${taskId.slice(0, 8)} assigneeUserId=${assigneeUserId.slice(0, 8)} assigned=true source=route`
|
|
34561
34721
|
);
|
|
34562
34722
|
invalidate("tasks-list", accountId);
|
|
34563
34723
|
return c.json({ ok: true, assigneeUserId, assigneeName });
|
|
34564
34724
|
} catch (err) {
|
|
34565
|
-
console.error(`${
|
|
34725
|
+
console.error(`${TAG54} op=assign error="${err instanceof Error ? err.message : String(err)}"`);
|
|
34566
34726
|
return c.json({ error: "task-assign-failed" }, 500);
|
|
34567
34727
|
} finally {
|
|
34568
34728
|
await session.close();
|
|
@@ -34571,13 +34731,13 @@ app63.post("/", requireAdminSession, async (c) => {
|
|
|
34571
34731
|
var task_assign_default = app63;
|
|
34572
34732
|
|
|
34573
34733
|
// server/routes/admin/task-session-open.ts
|
|
34574
|
-
var
|
|
34734
|
+
var TAG55 = "[task-session]";
|
|
34575
34735
|
var app64 = new Hono();
|
|
34576
34736
|
app64.post("/", requireAdminSession, async (c) => {
|
|
34577
34737
|
const cacheKey = c.var.cacheKey;
|
|
34578
34738
|
const accountId = getAccountIdForSession(cacheKey);
|
|
34579
34739
|
if (!accountId) {
|
|
34580
|
-
console.error(`${
|
|
34740
|
+
console.error(`${TAG55} op=request auth-rejected reason="no account for session"`);
|
|
34581
34741
|
return c.json({ error: "Account not found for session" }, 401);
|
|
34582
34742
|
}
|
|
34583
34743
|
let body;
|
|
@@ -34589,7 +34749,7 @@ app64.post("/", requireAdminSession, async (c) => {
|
|
|
34589
34749
|
const taskId = typeof body.taskId === "string" ? body.taskId : "";
|
|
34590
34750
|
if (!taskId) {
|
|
34591
34751
|
const reason = body.taskId === null ? "null-taskId" : "missing-taskId";
|
|
34592
|
-
console.error(`${
|
|
34752
|
+
console.error(`${TAG55} op=request rejected reason=${reason} account=${accountId}`);
|
|
34593
34753
|
return c.json({ error: "taskId required" }, 400);
|
|
34594
34754
|
}
|
|
34595
34755
|
const session = getSession();
|
|
@@ -34603,14 +34763,14 @@ app64.post("/", requireAdminSession, async (c) => {
|
|
|
34603
34763
|
{ taskId, accountId }
|
|
34604
34764
|
);
|
|
34605
34765
|
if (found.records.length === 0) {
|
|
34606
|
-
console.error(`${
|
|
34766
|
+
console.error(`${TAG55} op=request taskId=${taskId} account=${accountId} result=task-not-found`);
|
|
34607
34767
|
return c.json({ error: "task-not-found" }, 404);
|
|
34608
34768
|
}
|
|
34609
34769
|
const title = found.records[0].get("name") ?? "";
|
|
34610
34770
|
const sessionId = found.records[0].get("sessionId") ?? null;
|
|
34611
34771
|
const description = found.records[0].get("description") ?? "";
|
|
34612
34772
|
const notes = found.records[0].get("notes") ?? "";
|
|
34613
|
-
console.log(`${
|
|
34773
|
+
console.log(`${TAG55} op=request taskId=${taskId} account=${accountId} linked=${sessionId ?? "none"}`);
|
|
34614
34774
|
if (sessionId !== null) return c.json({ sessionId, title, description, notes });
|
|
34615
34775
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
34616
34776
|
const stamped = await session.run(
|
|
@@ -34620,10 +34780,10 @@ app64.post("/", requireAdminSession, async (c) => {
|
|
|
34620
34780
|
{ taskId, accountId, now }
|
|
34621
34781
|
);
|
|
34622
34782
|
const at = stamped.records[0]?.get("at") ?? void 0;
|
|
34623
|
-
console.log(`${
|
|
34783
|
+
console.log(`${TAG55} op=marker taskId=${taskId} stamped=${at !== void 0}`);
|
|
34624
34784
|
return c.json({ sessionId: null, title, description, notes });
|
|
34625
34785
|
} catch (err) {
|
|
34626
|
-
console.error(`${
|
|
34786
|
+
console.error(`${TAG55} op=request taskId=${taskId} error="${err instanceof Error ? err.message : String(err)}"`);
|
|
34627
34787
|
return c.json({ error: "task-session-open-failed" }, 500);
|
|
34628
34788
|
} finally {
|
|
34629
34789
|
await session.close();
|
|
@@ -34632,13 +34792,13 @@ app64.post("/", requireAdminSession, async (c) => {
|
|
|
34632
34792
|
var task_session_open_default = app64;
|
|
34633
34793
|
|
|
34634
34794
|
// server/routes/admin/task-session-link.ts
|
|
34635
|
-
var
|
|
34795
|
+
var TAG56 = "[task-session]";
|
|
34636
34796
|
var app65 = new Hono();
|
|
34637
34797
|
app65.post("/", requireAdminSession, async (c) => {
|
|
34638
34798
|
const cacheKey = c.var.cacheKey;
|
|
34639
34799
|
const accountId = getAccountIdForSession(cacheKey);
|
|
34640
34800
|
if (!accountId) {
|
|
34641
|
-
console.error(`${
|
|
34801
|
+
console.error(`${TAG56} op=link auth-rejected reason="no account for session"`);
|
|
34642
34802
|
return c.json({ error: "Account not found for session" }, 401);
|
|
34643
34803
|
}
|
|
34644
34804
|
let body;
|
|
@@ -34650,12 +34810,12 @@ app65.post("/", requireAdminSession, async (c) => {
|
|
|
34650
34810
|
const taskId = typeof body.taskId === "string" ? body.taskId : "";
|
|
34651
34811
|
if (!taskId) {
|
|
34652
34812
|
const reason = body.taskId === null ? "null-taskId" : "missing-taskId";
|
|
34653
|
-
console.error(`${
|
|
34813
|
+
console.error(`${TAG56} op=link rejected reason=${reason} account=${accountId}`);
|
|
34654
34814
|
return c.json({ error: "taskId required" }, 400);
|
|
34655
34815
|
}
|
|
34656
34816
|
const sessionId = typeof body.sessionId === "string" && body.sessionId.length > 0 ? body.sessionId : "";
|
|
34657
34817
|
if (!sessionId) {
|
|
34658
|
-
console.error(`${
|
|
34818
|
+
console.error(`${TAG56} op=link rejected reason=missing-sessionId taskId=${taskId} account=${accountId}`);
|
|
34659
34819
|
return c.json({ error: "sessionId required" }, 400);
|
|
34660
34820
|
}
|
|
34661
34821
|
const session = getSession();
|
|
@@ -34669,13 +34829,13 @@ app65.post("/", requireAdminSession, async (c) => {
|
|
|
34669
34829
|
{ taskId, accountId, sessionId }
|
|
34670
34830
|
);
|
|
34671
34831
|
if (state.records.length === 0) {
|
|
34672
|
-
console.error(`${
|
|
34832
|
+
console.error(`${TAG56} op=link taskId=${taskId} account=${accountId} result=task-not-found`);
|
|
34673
34833
|
return c.json({ error: "task-not-found" }, 404);
|
|
34674
34834
|
}
|
|
34675
34835
|
const conversationExists = state.records[0].get("conversationExists") === true;
|
|
34676
34836
|
const priorSessionIds = (state.records[0].get("priorSessionIds") ?? []).filter((s) => typeof s === "string");
|
|
34677
34837
|
if (!conversationExists) {
|
|
34678
|
-
console.error(`${
|
|
34838
|
+
console.error(`${TAG56} op=link-failed taskId=${taskId} sessionId=${sessionId} reason=conversation-absent`);
|
|
34679
34839
|
return c.json({ linked: false, created: false, repointedFrom: null });
|
|
34680
34840
|
}
|
|
34681
34841
|
const stale = priorSessionIds.filter((s) => s !== sessionId);
|
|
@@ -34701,18 +34861,18 @@ app65.post("/", requireAdminSession, async (c) => {
|
|
|
34701
34861
|
const repointedFrom = stale.length > 0 ? stale[0] : null;
|
|
34702
34862
|
if (!linked) {
|
|
34703
34863
|
console.error(
|
|
34704
|
-
`${
|
|
34864
|
+
`${TAG56} op=link-failed taskId=${taskId} sessionId=${sessionId} reason=edge-absent-after-merge linkedTo=${linkedTo ?? "none"}`
|
|
34705
34865
|
);
|
|
34706
34866
|
return c.json({ linked: false, created: false, repointedFrom });
|
|
34707
34867
|
}
|
|
34708
34868
|
console.log(
|
|
34709
|
-
`${
|
|
34869
|
+
`${TAG56} op=link taskId=${taskId} sessionId=${sessionId} created=${created} repointedFrom=${repointedFrom ?? "none"}`
|
|
34710
34870
|
);
|
|
34711
34871
|
invalidate("tasks-list", accountId);
|
|
34712
34872
|
return c.json({ linked: true, created, repointedFrom });
|
|
34713
34873
|
} catch (err) {
|
|
34714
34874
|
console.error(
|
|
34715
|
-
`${
|
|
34875
|
+
`${TAG56} op=link-failed taskId=${taskId} sessionId=${sessionId} reason="${err instanceof Error ? err.message : String(err)}"`
|
|
34716
34876
|
);
|
|
34717
34877
|
return c.json({ error: "task-session-link-failed" }, 500);
|
|
34718
34878
|
} finally {
|
|
@@ -34722,21 +34882,21 @@ app65.post("/", requireAdminSession, async (c) => {
|
|
|
34722
34882
|
var task_session_link_default = app65;
|
|
34723
34883
|
|
|
34724
34884
|
// server/routes/admin/admin-users-list.ts
|
|
34725
|
-
var
|
|
34885
|
+
var TAG57 = "[admin-users]";
|
|
34726
34886
|
var app66 = new Hono();
|
|
34727
34887
|
app66.get("/", requireAdminSession, async (c) => {
|
|
34728
34888
|
const cacheKey = c.var.cacheKey;
|
|
34729
34889
|
const accountId = getAccountIdForSession(cacheKey);
|
|
34730
34890
|
if (!accountId) {
|
|
34731
|
-
console.error(`${
|
|
34891
|
+
console.error(`${TAG57} op=list auth-rejected reason="no account for session"`);
|
|
34732
34892
|
return c.json({ error: "Account not found for session" }, 401);
|
|
34733
34893
|
}
|
|
34734
34894
|
try {
|
|
34735
34895
|
const users = await resolveAssignableAdmins(accountId);
|
|
34736
|
-
console.log(`${
|
|
34896
|
+
console.log(`${TAG57} op=list account=${accountId} count=${users.length}`);
|
|
34737
34897
|
return c.json({ ok: true, users });
|
|
34738
34898
|
} catch (err) {
|
|
34739
|
-
console.error(`${
|
|
34899
|
+
console.error(`${TAG57} op=list error="${err instanceof Error ? err.message : String(err)}"`);
|
|
34740
34900
|
return c.json({ error: "admin-users-list-failed" }, 500);
|
|
34741
34901
|
}
|
|
34742
34902
|
});
|
|
@@ -34744,7 +34904,7 @@ var admin_users_list_default = app66;
|
|
|
34744
34904
|
|
|
34745
34905
|
// server/routes/admin/dispatch-destinations.ts
|
|
34746
34906
|
import { resolve as resolve43 } from "path";
|
|
34747
|
-
var
|
|
34907
|
+
var TAG58 = "[admin:routines]";
|
|
34748
34908
|
function scopeFor(d, houseDir, houseAccountId) {
|
|
34749
34909
|
if (d.channel !== "whatsapp") return null;
|
|
34750
34910
|
if (d.label === "Account manager") return boundSubAccountFor(houseDir, d.destination);
|
|
@@ -34762,7 +34922,7 @@ var app67 = new Hono();
|
|
|
34762
34922
|
app67.get("/", requireAdminSession, async (c) => {
|
|
34763
34923
|
const accountId = getAccountIdForSession(c.var.cacheKey);
|
|
34764
34924
|
if (!accountId) {
|
|
34765
|
-
console.error(`${
|
|
34925
|
+
console.error(`${TAG58} op=destinations auth-rejected reason="no account for session"`);
|
|
34766
34926
|
return c.json({ error: "Account not found for session" }, 401);
|
|
34767
34927
|
}
|
|
34768
34928
|
let houseAccountId = null;
|
|
@@ -34770,7 +34930,7 @@ app67.get("/", requireAdminSession, async (c) => {
|
|
|
34770
34930
|
houseAccountId = resolveHouseOrSoleAccountId(ACCOUNTS_DIR);
|
|
34771
34931
|
} catch (err) {
|
|
34772
34932
|
const message = err instanceof Error ? err.message : String(err);
|
|
34773
|
-
console.error(`${
|
|
34933
|
+
console.error(`${TAG58} op=destinations account=${accountId.slice(0, 8)} outcome=house-unresolved reason="${message}"`);
|
|
34774
34934
|
}
|
|
34775
34935
|
const destinations = listDispatchDestinations({ accountsDir: ACCOUNTS_DIR, houseAccountId, accountId });
|
|
34776
34936
|
const houseDir = houseAccountId === null ? null : resolve43(ACCOUNTS_DIR, houseAccountId);
|
|
@@ -34821,7 +34981,7 @@ app67.get("/", requireAdminSession, async (c) => {
|
|
|
34821
34981
|
const scopes = [...byScope.keys()];
|
|
34822
34982
|
const nameScope = scopes.length === 0 ? "none" : scopes.every((s) => s === houseAccountId) ? "house" : scopes.some((s) => s === houseAccountId) ? "mixed" : "account";
|
|
34823
34983
|
console.log(
|
|
34824
|
-
`${
|
|
34984
|
+
`${TAG58} op=destinations account=${accountId.slice(0, 8)} count=${destinations.length} named=${named} unnamed=${destinations.length - named} nameScope=${nameScope}` + (houseAccountId === null ? " outcome=house-unresolved" : "") + (namesUnresolved === null ? "" : ` outcome=names-unresolved reason="${namesUnresolved}"`)
|
|
34825
34985
|
);
|
|
34826
34986
|
return c.json({ destinations });
|
|
34827
34987
|
});
|
|
@@ -34830,7 +34990,7 @@ var dispatch_destinations_default = app67;
|
|
|
34830
34990
|
// server/routes/admin/activity.ts
|
|
34831
34991
|
import { readdirSync as readdirSync30 } from "fs";
|
|
34832
34992
|
var app68 = new Hono();
|
|
34833
|
-
var
|
|
34993
|
+
var TAG59 = "[activity]";
|
|
34834
34994
|
function resolveHouseAccountId2(accounts) {
|
|
34835
34995
|
const houses = accounts.filter((a) => a.config.role === "house");
|
|
34836
34996
|
if (houses.length === 1) return { accountId: houses[0].accountId, reason: "house" };
|
|
@@ -34859,19 +35019,19 @@ app68.get("/", requireAdminSession, async (c) => {
|
|
|
34859
35019
|
const house = resolveHouseAccountId2(valid);
|
|
34860
35020
|
const isHouse = caller2 !== null && house.accountId !== null && caller2 === house.accountId;
|
|
34861
35021
|
console.log(
|
|
34862
|
-
`${
|
|
35022
|
+
`${TAG59} op=request req=${req} caller=${short(caller2)} house=${isHouse} houseVia=${house.reason}`
|
|
34863
35023
|
);
|
|
34864
35024
|
if (!isHouse) {
|
|
34865
35025
|
const reason = house.accountId === null ? house.reason : "not-house";
|
|
34866
35026
|
console.error(
|
|
34867
|
-
`${
|
|
35027
|
+
`${TAG59} op=gate req=${req} decision=deny reason=${reason} caller=${short(caller2)} houseAcct=${short(house.accountId)} accounts=${valid.length}`
|
|
34868
35028
|
);
|
|
34869
35029
|
return c.json({ error: "house-only" }, 403);
|
|
34870
35030
|
}
|
|
34871
|
-
console.log(`${
|
|
35031
|
+
console.log(`${TAG59} op=gate req=${req} decision=allow caller=${short(caller2)} via=${house.reason}`);
|
|
34872
35032
|
const onDisk = countAccountDirsOnDisk();
|
|
34873
35033
|
console.log(
|
|
34874
|
-
`${
|
|
35034
|
+
`${TAG59} op=accounts req=${req} onDisk=${onDisk ?? "unknown"} valid=${valid.length} ids=${valid.map((a) => short(a.accountId)).join(",")}`
|
|
34875
35035
|
);
|
|
34876
35036
|
const start = Date.now();
|
|
34877
35037
|
let res;
|
|
@@ -34887,17 +35047,17 @@ app68.get("/", requireAdminSession, async (c) => {
|
|
|
34887
35047
|
});
|
|
34888
35048
|
} catch (err) {
|
|
34889
35049
|
console.error(
|
|
34890
|
-
`${
|
|
35050
|
+
`${TAG59} op=manager-fail req=${req} reason=unreachable err=${err instanceof Error ? err.message : String(err)}`
|
|
34891
35051
|
);
|
|
34892
35052
|
return c.json({ error: "manager-unreachable" }, 502);
|
|
34893
35053
|
}
|
|
34894
35054
|
if (res.status !== 200) {
|
|
34895
|
-
console.error(`${
|
|
35055
|
+
console.error(`${TAG59} op=manager-fail req=${req} reason=status status=${res.status}`);
|
|
34896
35056
|
return c.json({ error: `manager-status-${res.status}` }, 502);
|
|
34897
35057
|
}
|
|
34898
35058
|
const body = await res.json().catch(() => null);
|
|
34899
35059
|
if (!body || !Array.isArray(body.rows)) {
|
|
34900
|
-
console.error(`${
|
|
35060
|
+
console.error(`${TAG59} op=manager-fail req=${req} reason=bad-json`);
|
|
34901
35061
|
return c.json({ error: "manager-bad-json" }, 502);
|
|
34902
35062
|
}
|
|
34903
35063
|
const rows = body.rows;
|
|
@@ -34908,10 +35068,10 @@ app68.get("/", requireAdminSession, async (c) => {
|
|
|
34908
35068
|
const ageNull = rows.filter((r) => r.ageMs === null).length;
|
|
34909
35069
|
const sidecarNull = rows.filter((r) => r.sidecarMissing).length;
|
|
34910
35070
|
console.log(
|
|
34911
|
-
`${
|
|
35071
|
+
`${TAG59} op=census req=${req} ageMs=${censusAgeMs ?? "none"} live=${census?.live ?? "none"} cpuNull=${census?.cpuNull ?? "none"} rows=${rows.length} ageNull=${ageNull} sidecarNull=${sidecarNull}`
|
|
34912
35072
|
);
|
|
34913
35073
|
console.log(
|
|
34914
|
-
`${
|
|
35074
|
+
`${TAG59} op=response req=${req} rows=${rows.length} accounts=${valid.length} untagged=${untaggedCount} meteringFailed=${meteringFailed} ms=${Date.now() - start}`
|
|
34915
35075
|
);
|
|
34916
35076
|
const names = {};
|
|
34917
35077
|
await Promise.all(
|
|
@@ -34930,7 +35090,7 @@ app68.get("/", requireAdminSession, async (c) => {
|
|
|
34930
35090
|
return acc;
|
|
34931
35091
|
}, {});
|
|
34932
35092
|
console.log(
|
|
34933
|
-
`${
|
|
35093
|
+
`${TAG59} op=loops req=${req} armed=${armed2} rendered=${loopRows.length} procPct=${cpu.processPct?.toFixed(1) ?? "null"} attributedPct=${cpu.attributedPct?.toFixed(1) ?? "null"} ` + Object.entries(byState).map(([s, n]) => `${s}=${n}`).join(" ")
|
|
34934
35094
|
);
|
|
34935
35095
|
return c.json({
|
|
34936
35096
|
rows,
|
|
@@ -35021,7 +35181,7 @@ app69.route("/activity", activity_default);
|
|
|
35021
35181
|
var admin_default = app69;
|
|
35022
35182
|
|
|
35023
35183
|
// server/routes/access/verify-token.ts
|
|
35024
|
-
var
|
|
35184
|
+
var TAG60 = "[access-verify]";
|
|
35025
35185
|
var MINT_TAG = "[access-session-mint]";
|
|
35026
35186
|
var COOKIE_NAME = "__access_session";
|
|
35027
35187
|
var app70 = new Hono();
|
|
@@ -35040,39 +35200,39 @@ app70.post("/", async (c) => {
|
|
|
35040
35200
|
}
|
|
35041
35201
|
const rateMsg = checkAccessRateLimit(ip, agentSlug);
|
|
35042
35202
|
if (rateMsg) {
|
|
35043
|
-
console.error(`${
|
|
35203
|
+
console.error(`${TAG60} grantId=- agentSlug=${agentSlug} result=rate-limited ip=${ip}`);
|
|
35044
35204
|
return c.json({ error: rateMsg }, 429);
|
|
35045
35205
|
}
|
|
35046
35206
|
const grant = await findGrantByMagicToken(token);
|
|
35047
35207
|
if (!grant) {
|
|
35048
35208
|
recordAccessFailedAttempt(ip, agentSlug);
|
|
35049
|
-
console.error(`${
|
|
35209
|
+
console.error(`${TAG60} grantId=- agentSlug=${agentSlug} result=notfound ip=${ip}`);
|
|
35050
35210
|
return c.json({ error: "invalid-or-expired-link" }, 401);
|
|
35051
35211
|
}
|
|
35052
35212
|
if (grant.agentSlug !== agentSlug) {
|
|
35053
35213
|
recordAccessFailedAttempt(ip, agentSlug);
|
|
35054
35214
|
console.error(
|
|
35055
|
-
`${
|
|
35215
|
+
`${TAG60} grantId=${grant.grantId} agentSlug=${agentSlug} result=agent-mismatch grantAgent=${grant.agentSlug} ip=${ip}`
|
|
35056
35216
|
);
|
|
35057
35217
|
return c.json({ error: "invalid-or-expired-link" }, 401);
|
|
35058
35218
|
}
|
|
35059
35219
|
if (grant.status === "expired" || grant.status === "revoked") {
|
|
35060
35220
|
recordAccessFailedAttempt(ip, agentSlug);
|
|
35061
35221
|
console.error(
|
|
35062
|
-
`${
|
|
35222
|
+
`${TAG60} grantId=${grant.grantId} agentSlug=${agentSlug} result=expired status=${grant.status} ip=${ip}`
|
|
35063
35223
|
);
|
|
35064
35224
|
return c.json({ error: "access-no-longer-valid" }, 401);
|
|
35065
35225
|
}
|
|
35066
35226
|
if (grant.expiresAt !== null && grant.expiresAt < Date.now()) {
|
|
35067
35227
|
recordAccessFailedAttempt(ip, agentSlug);
|
|
35068
35228
|
console.error(
|
|
35069
|
-
`${
|
|
35229
|
+
`${TAG60} grantId=${grant.grantId} agentSlug=${agentSlug} result=expired reason=expiresAt-past ip=${ip}`
|
|
35070
35230
|
);
|
|
35071
35231
|
return c.json({ error: "access-no-longer-valid" }, 401);
|
|
35072
35232
|
}
|
|
35073
35233
|
if (!grant.sliceToken) {
|
|
35074
35234
|
console.error(
|
|
35075
|
-
`${
|
|
35235
|
+
`${TAG60} grantId=${grant.grantId} agentSlug=${agentSlug} result=no-slice-token reason=schema-violation`
|
|
35076
35236
|
);
|
|
35077
35237
|
return c.json({ error: "grant-misconfigured" }, 500);
|
|
35078
35238
|
}
|
|
@@ -35088,12 +35248,12 @@ app70.post("/", async (c) => {
|
|
|
35088
35248
|
await consumeMagicTokenAndActivate(grant.grantId);
|
|
35089
35249
|
} catch (err) {
|
|
35090
35250
|
console.error(
|
|
35091
|
-
`${
|
|
35251
|
+
`${TAG60} grantId=${grant.grantId} agentSlug=${agentSlug} result=consume-failed err="${err instanceof Error ? err.message : String(err)}"`
|
|
35092
35252
|
);
|
|
35093
35253
|
return c.json({ error: "verification-failed" }, 500);
|
|
35094
35254
|
}
|
|
35095
35255
|
clearAccessRateLimit(ip, agentSlug);
|
|
35096
|
-
console.log(`${
|
|
35256
|
+
console.log(`${TAG60} grantId=${grant.grantId} agentSlug=${agentSlug} result=ok ip=${ip}`);
|
|
35097
35257
|
console.log(
|
|
35098
35258
|
`${MINT_TAG} grantId=${grant.grantId} sliceToken=${grant.sliceToken.slice(0, 8)} agentSlug=${agentSlug} personId=${grant.personId ?? "none"}`
|
|
35099
35259
|
);
|
|
@@ -35169,7 +35329,7 @@ async function sendMagicLinkEmail(payload) {
|
|
|
35169
35329
|
}
|
|
35170
35330
|
|
|
35171
35331
|
// server/routes/access/request-magic-link.ts
|
|
35172
|
-
var
|
|
35332
|
+
var TAG61 = "[access-request-link]";
|
|
35173
35333
|
var app71 = new Hono();
|
|
35174
35334
|
var VISITOR_MESSAGE = "If that email is on the invite list, a fresh link is on the way.";
|
|
35175
35335
|
app71.post("/", async (c) => {
|
|
@@ -35186,18 +35346,18 @@ app71.post("/", async (c) => {
|
|
|
35186
35346
|
}
|
|
35187
35347
|
const rateMsg = checkRequestLinkRateLimit(contactValue);
|
|
35188
35348
|
if (rateMsg) {
|
|
35189
|
-
console.error(`${
|
|
35349
|
+
console.error(`${TAG61} contactValue=${maskContact(contactValue)} result=rate-limited`);
|
|
35190
35350
|
return c.json({ error: rateMsg }, 429);
|
|
35191
35351
|
}
|
|
35192
35352
|
recordRequestLinkAttempt(contactValue);
|
|
35193
35353
|
const accountId = process.env.ACCOUNT_ID ?? "";
|
|
35194
35354
|
if (!accountId) {
|
|
35195
|
-
console.error(`${
|
|
35355
|
+
console.error(`${TAG61} contactValue=${maskContact(contactValue)} result=no-account-id`);
|
|
35196
35356
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
35197
35357
|
}
|
|
35198
35358
|
const grant = await findActiveGrantByContact(contactValue, agentSlug, accountId);
|
|
35199
35359
|
if (!grant) {
|
|
35200
|
-
console.log(`${
|
|
35360
|
+
console.log(`${TAG61} contactValue=${maskContact(contactValue)} result=notfound`);
|
|
35201
35361
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
35202
35362
|
}
|
|
35203
35363
|
let token;
|
|
@@ -35205,7 +35365,7 @@ app71.post("/", async (c) => {
|
|
|
35205
35365
|
token = await generateNewMagicToken(grant.grantId);
|
|
35206
35366
|
} catch (err) {
|
|
35207
35367
|
console.error(
|
|
35208
|
-
`${
|
|
35368
|
+
`${TAG61} contactValue=${maskContact(contactValue)} result=mint-failed err="${err instanceof Error ? err.message : String(err)}"`
|
|
35209
35369
|
);
|
|
35210
35370
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
35211
35371
|
}
|
|
@@ -35237,12 +35397,12 @@ app71.post("/", async (c) => {
|
|
|
35237
35397
|
});
|
|
35238
35398
|
if (!sendResult.ok) {
|
|
35239
35399
|
console.error(
|
|
35240
|
-
`${
|
|
35400
|
+
`${TAG61} contactValue=${maskContact(contactValue)} result=send-failed err="${sendResult.error}"`
|
|
35241
35401
|
);
|
|
35242
35402
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
35243
35403
|
}
|
|
35244
35404
|
console.log(
|
|
35245
|
-
`${
|
|
35405
|
+
`${TAG61} contactValue=${maskContact(contactValue)} result=ok messageId=${sendResult.messageId}`
|
|
35246
35406
|
);
|
|
35247
35407
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
35248
35408
|
});
|
|
@@ -36252,7 +36412,7 @@ import { stat as stat8, readFile as readFile12, realpath } from "fs/promises";
|
|
|
36252
36412
|
import { join as join62, resolve as resolve47, sep as sep11 } from "path";
|
|
36253
36413
|
import { Readable as Readable3 } from "stream";
|
|
36254
36414
|
var app79 = new Hono();
|
|
36255
|
-
var
|
|
36415
|
+
var TAG62 = "[portal-fetch]";
|
|
36256
36416
|
async function verifySignature(secret, accountId, relPath, expiresAtMs, signature, nowMs) {
|
|
36257
36417
|
if (!secret || !signature) return false;
|
|
36258
36418
|
if (!Number.isFinite(expiresAtMs) || expiresAtMs <= nowMs) return false;
|
|
@@ -36307,14 +36467,14 @@ async function readAccountSecret(accountId) {
|
|
|
36307
36467
|
try {
|
|
36308
36468
|
text = await readFile12(path, "utf8");
|
|
36309
36469
|
} catch {
|
|
36310
|
-
console.error(`${
|
|
36470
|
+
console.error(`${TAG62} op=no-secret account="${accountId}" path="${path}"`);
|
|
36311
36471
|
return "";
|
|
36312
36472
|
}
|
|
36313
36473
|
for (const line of text.split("\n")) {
|
|
36314
36474
|
const m = line.match(/^PORTAL_FETCH_SECRET=(.*)$/);
|
|
36315
36475
|
if (m) return m[1].trim();
|
|
36316
36476
|
}
|
|
36317
|
-
console.error(`${
|
|
36477
|
+
console.error(`${TAG62} op=no-secret account="${accountId}" reason=key-absent path="${path}"`);
|
|
36318
36478
|
return "";
|
|
36319
36479
|
}
|
|
36320
36480
|
function isValidAccountId2(value) {
|
|
@@ -36374,16 +36534,16 @@ async function handle(c, headOnly) {
|
|
|
36374
36534
|
const sig = c.req.query("sig") ?? "";
|
|
36375
36535
|
const owner = c.req.query("owner") ?? "";
|
|
36376
36536
|
console.log(
|
|
36377
|
-
`${
|
|
36537
|
+
`${TAG62} op=request account=${q(accountId)} path=${q(relPath)} owner=${q(owner)} head=${headOnly}`
|
|
36378
36538
|
);
|
|
36379
36539
|
if (!isValidAccountId2(accountId)) {
|
|
36380
|
-
console.error(`${
|
|
36540
|
+
console.error(`${TAG62} op=denied account=${q(accountId)} reason=account-id`);
|
|
36381
36541
|
return c.json({ ok: false, error: "denied" }, 401);
|
|
36382
36542
|
}
|
|
36383
36543
|
const secret = await readAccountSecret(accountId);
|
|
36384
36544
|
const verified = owner ? await verifyOwnUploadSignature(secret, accountId, owner, relPath, exp, sig, Date.now()) : await verifySignature(secret, accountId, relPath, exp, sig, Date.now());
|
|
36385
36545
|
if (!verified) {
|
|
36386
|
-
console.error(`${
|
|
36546
|
+
console.error(`${TAG62} op=denied account=${q(accountId)} reason=secret`);
|
|
36387
36547
|
return c.json({ ok: false, error: "denied" }, 401);
|
|
36388
36548
|
}
|
|
36389
36549
|
const target = await resolveFetchTarget(
|
|
@@ -36393,14 +36553,14 @@ async function handle(c, headOnly) {
|
|
|
36393
36553
|
);
|
|
36394
36554
|
if (!target.ok) {
|
|
36395
36555
|
const op = target.reason === "enoent" ? "miss" : "denied";
|
|
36396
|
-
console.error(`${
|
|
36556
|
+
console.error(`${TAG62} op=${op} account=${accountId} reason=${target.reason}`);
|
|
36397
36557
|
return c.json({ ok: false, error: "not found" }, 404);
|
|
36398
36558
|
}
|
|
36399
36559
|
if (headOnly) {
|
|
36400
|
-
console.log(`${
|
|
36560
|
+
console.log(`${TAG62} op=served account=${accountId} bytes=${target.sizeBytes} head=true`);
|
|
36401
36561
|
return c.body(null, 200);
|
|
36402
36562
|
}
|
|
36403
|
-
console.log(`${
|
|
36563
|
+
console.log(`${TAG62} op=served account=${accountId} bytes=${target.sizeBytes}`);
|
|
36404
36564
|
return new Response(Readable3.toWeb(createReadStream3(target.absolute)), {
|
|
36405
36565
|
status: 200,
|
|
36406
36566
|
headers: {
|
|
@@ -36419,7 +36579,7 @@ app79.on("HEAD", "/fetch", (c) => handle(c, true));
|
|
|
36419
36579
|
var portal_fetch_default = app79;
|
|
36420
36580
|
|
|
36421
36581
|
// app/lib/timeentry-census.ts
|
|
36422
|
-
var
|
|
36582
|
+
var TAG63 = "[timeentry-census]";
|
|
36423
36583
|
function reconcileTimeEntries(rows, now, horizonMs) {
|
|
36424
36584
|
const openEntries = rows.openEntries.length;
|
|
36425
36585
|
let oldestOpenAgeMs = 0;
|
|
@@ -36459,12 +36619,12 @@ async function runTimeEntryCensusOnce(session, now, horizonMs) {
|
|
|
36459
36619
|
sumAdjustments: toNum(r.get("sumAdjustments"))
|
|
36460
36620
|
}));
|
|
36461
36621
|
const finding = reconcileTimeEntries({ openEntries, taskSums }, now, horizonMs);
|
|
36462
|
-
const line = `${
|
|
36622
|
+
const line = `${TAG63} openEntries=${finding.openEntries} oldestOpenAgeMin=${finding.oldestOpenAgeMin} maxOpenPerAccount=${finding.maxOpenPerAccount} driftTasks=${finding.driftTasks}`;
|
|
36463
36623
|
if (finding.alarm) console.error(`${line} alarm=true`);
|
|
36464
36624
|
else console.log(line);
|
|
36465
36625
|
return finding;
|
|
36466
36626
|
} catch (err) {
|
|
36467
|
-
console.error(`${
|
|
36627
|
+
console.error(`${TAG63} error="${err instanceof Error ? err.message : String(err)}"`);
|
|
36468
36628
|
return null;
|
|
36469
36629
|
}
|
|
36470
36630
|
}
|
|
@@ -36478,13 +36638,13 @@ function startTimeEntryCensus(openSession, opts = {}) {
|
|
|
36478
36638
|
try {
|
|
36479
36639
|
session = openSession();
|
|
36480
36640
|
} catch (err) {
|
|
36481
|
-
console.error(`${
|
|
36641
|
+
console.error(`${TAG63} open-session-failed error="${err instanceof Error ? err.message : String(err)}"`);
|
|
36482
36642
|
return;
|
|
36483
36643
|
}
|
|
36484
36644
|
try {
|
|
36485
36645
|
await runTimeEntryCensusOnce(session, Date.now(), horizonMs);
|
|
36486
36646
|
} catch (err) {
|
|
36487
|
-
console.error(`${
|
|
36647
|
+
console.error(`${TAG63} tick-failed error="${err instanceof Error ? err.message : String(err)}"`);
|
|
36488
36648
|
} finally {
|
|
36489
36649
|
try {
|
|
36490
36650
|
await session.close();
|
|
@@ -36545,7 +36705,7 @@ function formatCensusLine(f) {
|
|
|
36545
36705
|
}
|
|
36546
36706
|
|
|
36547
36707
|
// app/lib/ledger-census.ts
|
|
36548
|
-
var
|
|
36708
|
+
var TAG64 = "[ledger-census]";
|
|
36549
36709
|
var DAY_MS = 864e5;
|
|
36550
36710
|
function countWriteRejects24h(logDir, now) {
|
|
36551
36711
|
let entries2;
|
|
@@ -36621,7 +36781,7 @@ async function runLedgerCensusOnce(session, now) {
|
|
|
36621
36781
|
else console.log(line);
|
|
36622
36782
|
return finding;
|
|
36623
36783
|
} catch (err) {
|
|
36624
|
-
console.error(`${
|
|
36784
|
+
console.error(`${TAG64} error="${err instanceof Error ? err.message : String(err)}"`);
|
|
36625
36785
|
return null;
|
|
36626
36786
|
}
|
|
36627
36787
|
}
|
|
@@ -36634,7 +36794,7 @@ function startLedgerCensus(openSession, opts = {}) {
|
|
|
36634
36794
|
session = openSession();
|
|
36635
36795
|
} catch (err) {
|
|
36636
36796
|
console.error(
|
|
36637
|
-
`${
|
|
36797
|
+
`${TAG64} open-session-failed error="${err instanceof Error ? err.message : String(err)}"`
|
|
36638
36798
|
);
|
|
36639
36799
|
return;
|
|
36640
36800
|
}
|
|
@@ -36642,7 +36802,7 @@ function startLedgerCensus(openSession, opts = {}) {
|
|
|
36642
36802
|
await runLedgerCensusOnce(session, Date.now());
|
|
36643
36803
|
} catch (err) {
|
|
36644
36804
|
console.error(
|
|
36645
|
-
`${
|
|
36805
|
+
`${TAG64} tick-failed error="${err instanceof Error ? err.message : String(err)}"`
|
|
36646
36806
|
);
|
|
36647
36807
|
} finally {
|
|
36648
36808
|
try {
|
|
@@ -36987,7 +37147,7 @@ function startDispatchTgCensus(getSession3, intervalMs = FIFTEEN_MIN_MS3) {
|
|
|
36987
37147
|
}
|
|
36988
37148
|
|
|
36989
37149
|
// app/lib/conversation-audit.ts
|
|
36990
|
-
var
|
|
37150
|
+
var TAG65 = "[conversation-audit]";
|
|
36991
37151
|
async function runConversationAudit() {
|
|
36992
37152
|
const session = getSession();
|
|
36993
37153
|
try {
|
|
@@ -37024,12 +37184,12 @@ async function runConversationAudit() {
|
|
|
37024
37184
|
multiAnchored: Number(multiRec?.get("multiAnchored") ?? 0)
|
|
37025
37185
|
};
|
|
37026
37186
|
console.error(
|
|
37027
|
-
`${
|
|
37187
|
+
`${TAG65} channel=whatsapp total=${result.total} senders=${result.senders} multiAnchored=${result.multiAnchored} unreconciled=${result.unreconciled} unpairable=${result.unpairable}`
|
|
37028
37188
|
);
|
|
37029
37189
|
return result;
|
|
37030
37190
|
} catch (err) {
|
|
37031
37191
|
const reason = err instanceof Error ? `${err.name}:${err.message.slice(0, 200)}` : String(err).slice(0, 200);
|
|
37032
|
-
console.error(`${
|
|
37192
|
+
console.error(`${TAG65} op=failed reason=${reason}`);
|
|
37033
37193
|
return null;
|
|
37034
37194
|
} finally {
|
|
37035
37195
|
await session.close();
|
|
@@ -37157,7 +37317,7 @@ function startGraphHealthTimer() {
|
|
|
37157
37317
|
import { existsSync as existsSync54, statSync as statSync29, readdirSync as readdirSync32 } from "fs";
|
|
37158
37318
|
import { join as join65 } from "path";
|
|
37159
37319
|
var import_dist16 = __toESM(require_dist(), 1);
|
|
37160
|
-
var
|
|
37320
|
+
var TAG66 = "[shared-census]";
|
|
37161
37321
|
var WIRED_SURFACES = 3;
|
|
37162
37322
|
function countFiles(dir) {
|
|
37163
37323
|
let n = 0;
|
|
@@ -37185,8 +37345,8 @@ function runSharedFolderCensus(dataRoot = DATA_ROOT) {
|
|
|
37185
37345
|
}
|
|
37186
37346
|
}
|
|
37187
37347
|
const files = isDir ? countFiles(root) : 0;
|
|
37188
|
-
console.error(`${
|
|
37189
|
-
console.error(`${
|
|
37348
|
+
console.error(`${TAG66} op=root exists=${exists} isDir=${isDir} files=${files}`);
|
|
37349
|
+
console.error(`${TAG66} op=wiring surfaces=${WIRED_SURFACES}/3`);
|
|
37190
37350
|
return `shared root ${exists ? "present" : "ABSENT"}, ${files} file(s)`;
|
|
37191
37351
|
}
|
|
37192
37352
|
function startSharedFolderCensus() {
|
|
@@ -37202,7 +37362,7 @@ function startSharedFolderCensus() {
|
|
|
37202
37362
|
import { readdirSync as readdirSync33, readFileSync as readFileSync57 } from "fs";
|
|
37203
37363
|
import { homedir as homedir4 } from "os";
|
|
37204
37364
|
import { join as join66 } from "path";
|
|
37205
|
-
var
|
|
37365
|
+
var TAG67 = "[claude-auth]";
|
|
37206
37366
|
function refreshTokenLength(raw) {
|
|
37207
37367
|
let data;
|
|
37208
37368
|
try {
|
|
@@ -37246,7 +37406,7 @@ function runCredRefreshCensus(home = homedir4()) {
|
|
|
37246
37406
|
const blank = rows.filter(isBlank).length;
|
|
37247
37407
|
const detail = rows.map((r) => `${r.brand}:${r.refreshTokenLen === null ? "unreadable" : r.refreshTokenLen}`).join(",");
|
|
37248
37408
|
console.log(
|
|
37249
|
-
`${
|
|
37409
|
+
`${TAG67} op=cred-refresh-census result=${censusResult(rows)} brands=${rows.length} blank=${blank} detail=${detail}`
|
|
37250
37410
|
);
|
|
37251
37411
|
return `${rows.length} brand(s), ${blank} blank`;
|
|
37252
37412
|
}
|
|
@@ -39745,6 +39905,16 @@ var WebchatGateway = class _WebchatGateway {
|
|
|
39745
39905
|
clearDeliveryFailure(key2) {
|
|
39746
39906
|
this.deliveryFailures.delete(key2);
|
|
39747
39907
|
}
|
|
39908
|
+
/** Task 2439 — mark a key undelivered from OUTSIDE the drain path. Every other
|
|
39909
|
+
* writer above fires because a message the hub already holds could not be
|
|
39910
|
+
* delivered. The send route's deferred continuation is the one case where no
|
|
39911
|
+
* message ever reached the hub: it dies before handleInbound runs, so nothing
|
|
39912
|
+
* is queued, nothing can go stale, and no drain can fail. Without this the
|
|
39913
|
+
* client's pending window (Task 2465 reads exactly this marker) never gets a
|
|
39914
|
+
* verdict and the composer stays disabled until the page is reloaded. */
|
|
39915
|
+
markDeliveryFailure(key2, messageId) {
|
|
39916
|
+
this.deliveryFailures.set(key2, { messageId, at: Date.now() });
|
|
39917
|
+
}
|
|
39748
39918
|
/** Task 2465 — record which session a conversation key's child is running.
|
|
39749
39919
|
* Public so the audit below can be driven directly in tests without standing
|
|
39750
39920
|
* up the channel-server HTTP surface; production writes come from runSpawn and
|
|
@@ -40437,14 +40607,14 @@ function makeFileDelivery(opts) {
|
|
|
40437
40607
|
}
|
|
40438
40608
|
|
|
40439
40609
|
// app/lib/webchat/file-delivery.ts
|
|
40440
|
-
var
|
|
40610
|
+
var TAG68 = "[webchat-adaptor]";
|
|
40441
40611
|
function platformRoot2() {
|
|
40442
40612
|
return process.env.MAXY_PLATFORM_ROOT || "";
|
|
40443
40613
|
}
|
|
40444
40614
|
function makeWebchatSendFile(entry3) {
|
|
40445
40615
|
return async (filePath) => {
|
|
40446
40616
|
if (!entry3.accountId) {
|
|
40447
|
-
console.error(`${
|
|
40617
|
+
console.error(`${TAG68} file-delivery reject reason=no-account sender=${entry3.senderId}`);
|
|
40448
40618
|
return { ok: false, error: "no-account" };
|
|
40449
40619
|
}
|
|
40450
40620
|
const accountDir = resolve50(platformRoot2(), "..", "data/accounts", entry3.accountId);
|
|
@@ -40452,14 +40622,14 @@ function makeWebchatSendFile(entry3) {
|
|
|
40452
40622
|
const resolved = realpathSync9(filePath);
|
|
40453
40623
|
const accountResolved = realpathSync9(accountDir);
|
|
40454
40624
|
if (!resolved.startsWith(accountResolved + "/")) {
|
|
40455
|
-
console.error(`${
|
|
40625
|
+
console.error(`${TAG68} file-delivery reject reason=outside_account_directory sender=${entry3.senderId}`);
|
|
40456
40626
|
return { ok: false, error: "outside-account" };
|
|
40457
40627
|
}
|
|
40458
40628
|
return { ok: true };
|
|
40459
40629
|
} catch (err) {
|
|
40460
40630
|
const code = err.code;
|
|
40461
40631
|
console.error(
|
|
40462
|
-
`${
|
|
40632
|
+
`${TAG68} file-delivery reject reason=${code === "ENOENT" ? "not-found" : "path-error"} sender=${entry3.senderId}`
|
|
40463
40633
|
);
|
|
40464
40634
|
return { ok: false, error: code === "ENOENT" ? "not-found" : "path-error" };
|
|
40465
40635
|
}
|
|
@@ -40468,7 +40638,7 @@ function makeWebchatSendFile(entry3) {
|
|
|
40468
40638
|
function makeWebchatFileDelivery(entry3) {
|
|
40469
40639
|
return makeFileDelivery({
|
|
40470
40640
|
entry: entry3,
|
|
40471
|
-
tag:
|
|
40641
|
+
tag: TAG68,
|
|
40472
40642
|
channel: "webchat",
|
|
40473
40643
|
sendFile: makeWebchatSendFile(entry3),
|
|
40474
40644
|
deferUntilVerdict: true
|
|
@@ -40547,7 +40717,7 @@ function buildPublicWebchatSpawnRequest(input) {
|
|
|
40547
40717
|
}
|
|
40548
40718
|
|
|
40549
40719
|
// app/lib/whatsapp/inbound/file-delivery-bridge.ts
|
|
40550
|
-
var
|
|
40720
|
+
var TAG69 = "[whatsapp-adaptor]";
|
|
40551
40721
|
var SEND_USER_FILE2 = "SendUserFile";
|
|
40552
40722
|
var WHATSAPP_SEND_DOCUMENT = "whatsapp-send-document";
|
|
40553
40723
|
function platformRoot3() {
|
|
@@ -40565,7 +40735,7 @@ function makeWhatsAppSendFile(entry3, maxyAccountId) {
|
|
|
40565
40735
|
});
|
|
40566
40736
|
if (result.ok) return { ok: true };
|
|
40567
40737
|
console.error(
|
|
40568
|
-
`${
|
|
40738
|
+
`${TAG69} file-delivery reject reason=send-failed sender=${entry3.senderId} status=${result.status} message=${result.error}`
|
|
40569
40739
|
);
|
|
40570
40740
|
return { ok: false, error: result.error };
|
|
40571
40741
|
};
|
|
@@ -40573,7 +40743,7 @@ function makeWhatsAppSendFile(entry3, maxyAccountId) {
|
|
|
40573
40743
|
function makeWhatsAppFileDelivery(entry3, maxyAccountId) {
|
|
40574
40744
|
const shared = makeFileDelivery({
|
|
40575
40745
|
entry: entry3,
|
|
40576
|
-
tag:
|
|
40746
|
+
tag: TAG69,
|
|
40577
40747
|
channel: "whatsapp",
|
|
40578
40748
|
sendFile: makeWhatsAppSendFile(entry3, maxyAccountId)
|
|
40579
40749
|
});
|
|
@@ -40608,7 +40778,7 @@ function makeWhatsAppFileDelivery(entry3, maxyAccountId) {
|
|
|
40608
40778
|
if (!delivered) {
|
|
40609
40779
|
const fileField = call2.filePath !== void 0 ? ` file=${call2.filePath}` : "";
|
|
40610
40780
|
console.error(
|
|
40611
|
-
`${
|
|
40781
|
+
`${TAG69} file-delivery-unreconciled sender=${entry3.senderId} sessionId=${sid} tool=${WHATSAPP_SEND_DOCUMENT}${fileField}`
|
|
40612
40782
|
);
|
|
40613
40783
|
}
|
|
40614
40784
|
}
|
|
@@ -40774,7 +40944,7 @@ function whatsappDoorLabel(doorId) {
|
|
|
40774
40944
|
}
|
|
40775
40945
|
|
|
40776
40946
|
// app/lib/channel-delivery/refusal-notice.ts
|
|
40777
|
-
var
|
|
40947
|
+
var TAG70 = "[channel-delivery]";
|
|
40778
40948
|
var notified = /* @__PURE__ */ new Set();
|
|
40779
40949
|
function refusalNoticeText(reason) {
|
|
40780
40950
|
return reason === "claude-auth-dead" ? "Your message arrived but no assistant could be started: the Claude sign-in on this install is not active. An operator has to sign in again; send this again once they have." : `Your message arrived but no assistant could be started (${reason}). Nothing was lost; try again shortly.`;
|
|
@@ -40783,19 +40953,19 @@ async function sendRefusalNotice(input) {
|
|
|
40783
40953
|
if (notified.has(input.doorId)) return;
|
|
40784
40954
|
const fields = `channel=${input.channel} sender=${input.sender} reason=${input.reason}`;
|
|
40785
40955
|
if (!input.send) {
|
|
40786
|
-
console.error(`${
|
|
40956
|
+
console.error(`${TAG70} op=refusal-notice-failed ${fields} error=no-target`);
|
|
40787
40957
|
return;
|
|
40788
40958
|
}
|
|
40789
40959
|
try {
|
|
40790
40960
|
await input.send(guardOutbound(input.sender, refusalNoticeText(input.reason)));
|
|
40791
40961
|
} catch (e) {
|
|
40792
40962
|
console.error(
|
|
40793
|
-
`${
|
|
40963
|
+
`${TAG70} op=refusal-notice-failed ${fields} error=${e instanceof Error ? e.message : String(e)}`
|
|
40794
40964
|
);
|
|
40795
40965
|
return;
|
|
40796
40966
|
}
|
|
40797
40967
|
notified.add(input.doorId);
|
|
40798
|
-
console.error(`${
|
|
40968
|
+
console.error(`${TAG70} op=refusal-notice ${fields} status=${input.status}`);
|
|
40799
40969
|
}
|
|
40800
40970
|
function clearRefusalNotice(doorId) {
|
|
40801
40971
|
notified.delete(doorId);
|
|
@@ -41455,10 +41625,10 @@ function buildTelegramSpawnRequest(input) {
|
|
|
41455
41625
|
}
|
|
41456
41626
|
|
|
41457
41627
|
// server/telegram-ensure-session.ts
|
|
41458
|
-
var
|
|
41628
|
+
var TAG71 = "[telegram-inbound]";
|
|
41459
41629
|
function reportReused(botId, channelKey, result) {
|
|
41460
41630
|
if (!result.reused) return;
|
|
41461
|
-
console.error(`${
|
|
41631
|
+
console.error(`${TAG71} op=spawn-reused botId=${botId} key=${channelKey} sessionId=${result.sessionId}`);
|
|
41462
41632
|
}
|
|
41463
41633
|
function buildTelegramEnsureSession(deps) {
|
|
41464
41634
|
return async (input) => {
|
|
@@ -41522,10 +41692,10 @@ function buildTelegramEnsureSession(deps) {
|
|
|
41522
41692
|
return;
|
|
41523
41693
|
}
|
|
41524
41694
|
console.error(
|
|
41525
|
-
`${
|
|
41695
|
+
`${TAG71} op=telegram-spawn-door botId=${input.botId} role=specialist door=rc specialist=${input.specialist}`
|
|
41526
41696
|
);
|
|
41527
41697
|
console.error(
|
|
41528
|
-
`${
|
|
41698
|
+
`${TAG71} op=spawn botId=${input.botId} sessionId=${req.sessionId} targetAccountId=${input.accountId} role=specialist specialist=${input.specialist}`
|
|
41529
41699
|
);
|
|
41530
41700
|
reportReused(input.botId, req.channelKey, result2);
|
|
41531
41701
|
noteSpawnOk2(input.botId);
|
|
@@ -41560,10 +41730,10 @@ function buildTelegramEnsureSession(deps) {
|
|
|
41560
41730
|
return;
|
|
41561
41731
|
}
|
|
41562
41732
|
console.error(
|
|
41563
|
-
`${
|
|
41733
|
+
`${TAG71} op=telegram-spawn-door botId=${input.botId} role=public door=rc agent=${input.agentSlug}`
|
|
41564
41734
|
);
|
|
41565
41735
|
console.error(
|
|
41566
|
-
`${
|
|
41736
|
+
`${TAG71} op=spawn botId=${input.botId} sessionId=${result2.sessionId} targetAccountId=${input.accountId} role=public`
|
|
41567
41737
|
);
|
|
41568
41738
|
reportReused(input.botId, req.channelKey, result2);
|
|
41569
41739
|
noteSpawnOk2(input.botId);
|
|
@@ -41587,7 +41757,7 @@ function buildTelegramEnsureSession(deps) {
|
|
|
41587
41757
|
return;
|
|
41588
41758
|
}
|
|
41589
41759
|
console.error(
|
|
41590
|
-
`${
|
|
41760
|
+
`${TAG71} op=spawn botId=${input.botId} sessionId=${req.sessionId} targetAccountId=${input.accountId} role=admin`
|
|
41591
41761
|
);
|
|
41592
41762
|
reportReused(input.botId, req.channelKey, result);
|
|
41593
41763
|
noteSpawnOk2(input.botId);
|
|
@@ -41606,7 +41776,7 @@ function buildTelegramEnsureSession(deps) {
|
|
|
41606
41776
|
import { realpathSync as realpathSync10 } from "fs";
|
|
41607
41777
|
import { readFile as readFile15, stat as stat10 } from "fs/promises";
|
|
41608
41778
|
import { resolve as resolve51, basename as basename18 } from "path";
|
|
41609
|
-
var
|
|
41779
|
+
var TAG72 = "[telegram:outbound]";
|
|
41610
41780
|
var TELEGRAM_DOCUMENT_MAX_BYTES = 50 * 1024 * 1024;
|
|
41611
41781
|
async function sendTelegramDocument(input) {
|
|
41612
41782
|
const { botToken, chatId, filePath, caption, maxyAccountId, platformRoot: platformRoot5 } = input;
|
|
@@ -41623,10 +41793,10 @@ async function sendTelegramDocument(input) {
|
|
|
41623
41793
|
} catch (err) {
|
|
41624
41794
|
const code = err.code;
|
|
41625
41795
|
if (code === "ENOENT") {
|
|
41626
|
-
console.error(`${
|
|
41796
|
+
console.error(`${TAG72} document ENOENT scope=account-dir accountDir=${accountDir} maxyAccountId=${maxyAccountId}`);
|
|
41627
41797
|
return { ok: false, status: 500, error: `Account directory not resolvable for ${maxyAccountId}` };
|
|
41628
41798
|
}
|
|
41629
|
-
console.error(`${
|
|
41799
|
+
console.error(`${TAG72} document path error scope=account-dir maxyAccountId=${maxyAccountId}: ${String(err)}`);
|
|
41630
41800
|
return { ok: false, status: 500, error: String(err) };
|
|
41631
41801
|
}
|
|
41632
41802
|
let resolvedPath;
|
|
@@ -41635,14 +41805,14 @@ async function sendTelegramDocument(input) {
|
|
|
41635
41805
|
} catch (err) {
|
|
41636
41806
|
const code = err.code;
|
|
41637
41807
|
if (code === "ENOENT") {
|
|
41638
|
-
console.error(`${
|
|
41808
|
+
console.error(`${TAG72} document ENOENT scope=file path=${filePath} maxyAccountId=${maxyAccountId}`);
|
|
41639
41809
|
return { ok: false, status: 404, error: `File not found: ${filePath}` };
|
|
41640
41810
|
}
|
|
41641
|
-
console.error(`${
|
|
41811
|
+
console.error(`${TAG72} document path error scope=file maxyAccountId=${maxyAccountId}: ${String(err)}`);
|
|
41642
41812
|
return { ok: false, status: 500, error: String(err) };
|
|
41643
41813
|
}
|
|
41644
41814
|
if (!resolvedPath.startsWith(accountResolved + "/")) {
|
|
41645
|
-
console.error(`${
|
|
41815
|
+
console.error(`${TAG72} document REJECTED reason=outside_account_directory maxyAccountId=${maxyAccountId}`);
|
|
41646
41816
|
return { ok: false, status: 403, error: "Access denied: file is outside the account directory" };
|
|
41647
41817
|
}
|
|
41648
41818
|
const fileStat = await stat10(resolvedPath);
|
|
@@ -41675,24 +41845,24 @@ async function sendTelegramDocument(input) {
|
|
|
41675
41845
|
error = e instanceof Error ? e.message : String(e);
|
|
41676
41846
|
}
|
|
41677
41847
|
console.error(
|
|
41678
|
-
`${
|
|
41848
|
+
`${TAG72} sent document to=${chatId} file=${filename} bytes=${fileStat.size} ok=${ok2}` + (messageId !== void 0 ? ` id=${messageId}` : "")
|
|
41679
41849
|
);
|
|
41680
41850
|
return ok2 ? { ok: true, messageId } : { ok: false, status: 500, error };
|
|
41681
41851
|
}
|
|
41682
41852
|
|
|
41683
41853
|
// app/lib/telegram/outbound/file-delivery.ts
|
|
41684
|
-
var
|
|
41854
|
+
var TAG73 = "[telegram:outbound]";
|
|
41685
41855
|
function platformRoot4() {
|
|
41686
41856
|
return process.env.MAXY_PLATFORM_ROOT || "";
|
|
41687
41857
|
}
|
|
41688
41858
|
function makeTelegramSendFile(entry3, botToken) {
|
|
41689
41859
|
return async (filePath, caption) => {
|
|
41690
41860
|
if (!botToken) {
|
|
41691
|
-
console.error(`${
|
|
41861
|
+
console.error(`${TAG73} file-delivery reject reason=no-bot-token sender=${entry3.senderId} role=${entry3.role}`);
|
|
41692
41862
|
return { ok: false, error: "no-bot-token" };
|
|
41693
41863
|
}
|
|
41694
41864
|
if (entry3.replyTarget == null) {
|
|
41695
|
-
console.error(`${
|
|
41865
|
+
console.error(`${TAG73} file-delivery reject reason=no-reply-target sender=${entry3.senderId} role=${entry3.role}`);
|
|
41696
41866
|
return { ok: false, error: "no-reply-target" };
|
|
41697
41867
|
}
|
|
41698
41868
|
const result = await sendTelegramDocument({
|
|
@@ -41709,7 +41879,7 @@ function makeTelegramSendFile(entry3, botToken) {
|
|
|
41709
41879
|
function makeTelegramFileDelivery(entry3, botToken) {
|
|
41710
41880
|
return makeFileDelivery({
|
|
41711
41881
|
entry: entry3,
|
|
41712
|
-
tag:
|
|
41882
|
+
tag: TAG73,
|
|
41713
41883
|
channel: "telegram",
|
|
41714
41884
|
sendFile: makeTelegramSendFile(entry3, botToken)
|
|
41715
41885
|
});
|
|
@@ -42120,7 +42290,7 @@ function adminFanTargets(p) {
|
|
|
42120
42290
|
|
|
42121
42291
|
// app/lib/channel-pty-bridge/public-session-end-review.ts
|
|
42122
42292
|
import { randomUUID as randomUUID14 } from "crypto";
|
|
42123
|
-
var
|
|
42293
|
+
var TAG74 = "[public-session-review]";
|
|
42124
42294
|
var CONSUMED_CAP = 500;
|
|
42125
42295
|
var consumed = /* @__PURE__ */ new Set();
|
|
42126
42296
|
function consumeOnce(sessionId) {
|
|
@@ -42147,7 +42317,7 @@ async function fetchJsonl(sessionId) {
|
|
|
42147
42317
|
return await res.text();
|
|
42148
42318
|
} catch (err) {
|
|
42149
42319
|
console.error(
|
|
42150
|
-
`${
|
|
42320
|
+
`${TAG74} jsonl-fetch-failed sessionId=${sessionId} err="${err instanceof Error ? err.message : String(err)}"`
|
|
42151
42321
|
);
|
|
42152
42322
|
return null;
|
|
42153
42323
|
}
|
|
@@ -42171,7 +42341,7 @@ async function fetchPriorWrites(sliceToken, accountId) {
|
|
|
42171
42341
|
const res = await fetch(url);
|
|
42172
42342
|
if (!res.ok) {
|
|
42173
42343
|
console.error(
|
|
42174
|
-
`${
|
|
42344
|
+
`${TAG74} prior-writes-fetch-failed sliceToken=${sliceToken.slice(0, 8)} status=${res.status}`
|
|
42175
42345
|
);
|
|
42176
42346
|
return [];
|
|
42177
42347
|
}
|
|
@@ -42179,7 +42349,7 @@ async function fetchPriorWrites(sliceToken, accountId) {
|
|
|
42179
42349
|
return Array.isArray(body.writes) ? body.writes : [];
|
|
42180
42350
|
} catch (err) {
|
|
42181
42351
|
console.error(
|
|
42182
|
-
`${
|
|
42352
|
+
`${TAG74} prior-writes-fetch-threw sliceToken=${sliceToken.slice(0, 8)} err="${err instanceof Error ? err.message : String(err)}"`
|
|
42183
42353
|
);
|
|
42184
42354
|
return [];
|
|
42185
42355
|
}
|
|
@@ -42208,7 +42378,7 @@ function composeInitialMessage(input) {
|
|
|
42208
42378
|
}
|
|
42209
42379
|
async function dispatchReviewer(input, initialMessage) {
|
|
42210
42380
|
const sessionId = randomUUID14();
|
|
42211
|
-
console.log(`${
|
|
42381
|
+
console.log(`${TAG74} route target=rc-spawn sessionId=${sessionId.slice(0, 8)} sourceSession=${input.sessionId.slice(0, 8)}`);
|
|
42212
42382
|
const spawned = await managerRcSpawn({
|
|
42213
42383
|
sessionId,
|
|
42214
42384
|
initialMessage,
|
|
@@ -42232,21 +42402,21 @@ async function firePublicSessionEndReview(input) {
|
|
|
42232
42402
|
const dispatchedAt = Date.now();
|
|
42233
42403
|
if (consumed.has(input.sessionId)) {
|
|
42234
42404
|
console.log(
|
|
42235
|
-
`${
|
|
42405
|
+
`${TAG74} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-already-reviewed`
|
|
42236
42406
|
);
|
|
42237
42407
|
return;
|
|
42238
42408
|
}
|
|
42239
42409
|
const jsonl = await fetchJsonl(input.sessionId);
|
|
42240
42410
|
if (!jsonl) {
|
|
42241
42411
|
console.log(
|
|
42242
|
-
`${
|
|
42412
|
+
`${TAG74} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-jsonl-missing`
|
|
42243
42413
|
);
|
|
42244
42414
|
return;
|
|
42245
42415
|
}
|
|
42246
42416
|
const operatorTurns = countOperatorTurns(jsonl);
|
|
42247
42417
|
if (operatorTurns === 0) {
|
|
42248
42418
|
console.log(
|
|
42249
|
-
`${
|
|
42419
|
+
`${TAG74} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-no-turns`
|
|
42250
42420
|
);
|
|
42251
42421
|
return;
|
|
42252
42422
|
}
|
|
@@ -42260,19 +42430,19 @@ async function firePublicSessionEndReview(input) {
|
|
|
42260
42430
|
});
|
|
42261
42431
|
if (!consumeOnce(input.sessionId)) {
|
|
42262
42432
|
console.log(
|
|
42263
|
-
`${
|
|
42433
|
+
`${TAG74} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-already-reviewed`
|
|
42264
42434
|
);
|
|
42265
42435
|
return;
|
|
42266
42436
|
}
|
|
42267
42437
|
const dispatched = await dispatchReviewer(input, initialMessage);
|
|
42268
42438
|
if (!dispatched.ok) {
|
|
42269
42439
|
console.error(
|
|
42270
|
-
`${
|
|
42440
|
+
`${TAG74} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-spawn-failed reason=${dispatched.reason}`
|
|
42271
42441
|
);
|
|
42272
42442
|
return;
|
|
42273
42443
|
}
|
|
42274
42444
|
console.log(
|
|
42275
|
-
`${
|
|
42445
|
+
`${TAG74} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=dispatched managerSessionId=${dispatched.managerSessionId} operatorTurns=${operatorTurns} priorWrites=${priorWrites.length} ms=${Date.now() - dispatchedAt}`
|
|
42276
42446
|
);
|
|
42277
42447
|
}
|
|
42278
42448
|
|
|
@@ -42541,10 +42711,10 @@ function* walkTelegramSidecars() {
|
|
|
42541
42711
|
}
|
|
42542
42712
|
|
|
42543
42713
|
// server/telegram-group-census.ts
|
|
42544
|
-
var
|
|
42714
|
+
var TAG75 = "[telegram-audit]";
|
|
42545
42715
|
var PRESENT_STATUSES = /* @__PURE__ */ new Set(["member", "administrator", "creator"]);
|
|
42546
42716
|
function buildGroupCensusLine(c) {
|
|
42547
|
-
return `${
|
|
42717
|
+
return `${TAG75} op=group-census bots=${c.bots} groups=${c.groups} present=${c.present} absent=${c.absent} privacyOff=${c.privacyOff}`;
|
|
42548
42718
|
}
|
|
42549
42719
|
async function runTelegramGroupCensus(accounts, deps) {
|
|
42550
42720
|
const counts = { bots: 0, groups: 0, present: 0, absent: 0, privacyOff: 0 };
|
|
@@ -42575,10 +42745,10 @@ async function runTelegramGroupCensus(accounts, deps) {
|
|
|
42575
42745
|
}
|
|
42576
42746
|
|
|
42577
42747
|
// server/telegram-channel-census.ts
|
|
42578
|
-
var
|
|
42748
|
+
var TAG76 = "[telegram-audit]";
|
|
42579
42749
|
var ADMIN_STATUSES = /* @__PURE__ */ new Set(["administrator", "creator"]);
|
|
42580
42750
|
function buildChannelCensusLine(c) {
|
|
42581
|
-
return `${
|
|
42751
|
+
return `${TAG76} op=channel-census bots=${c.bots} channels=${c.channels} admin=${c.admin} notAdmin=${c.notAdmin} noPostRight=${c.noPostRight}`;
|
|
42582
42752
|
}
|
|
42583
42753
|
async function runTelegramChannelCensus(accounts, deps) {
|
|
42584
42754
|
const counts = { bots: 0, channels: 0, admin: 0, notAdmin: 0, noPostRight: 0 };
|
|
@@ -44204,6 +44374,9 @@ app80.route("/api/webchat", createWebchatRoutes({
|
|
|
44204
44374
|
// Task 940 — the permission relay's pointer read + verdict write.
|
|
44205
44375
|
pendingPromptFor: (key2) => webchatGateway.pendingPromptFor(key2),
|
|
44206
44376
|
deliveryFailureFor: (key2) => webchatGateway.deliveryFailureFor(key2),
|
|
44377
|
+
// Task 2439 — the deferred send continuation's only way to report that a
|
|
44378
|
+
// staged upload will never produce a turn.
|
|
44379
|
+
markDeliveryFailure: (key2, messageId) => webchatGateway.markDeliveryFailure(key2, messageId),
|
|
44207
44380
|
resolvePermissionVerdict: (key2, requestId, behavior) => webchatGateway.resolvePermissionVerdict(key2, requestId, behavior)
|
|
44208
44381
|
}));
|
|
44209
44382
|
app80.route("/api/webchat/greeting", webchat_greeting_default);
|