@rubytech/create-sitedesk-code 0.1.608 → 0.1.609
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/payload/platform/lib/graph-write/dist/__tests__/account-id-gate.test.js +86 -0
- package/payload/platform/lib/graph-write/dist/__tests__/account-id-gate.test.js.map +1 -1
- package/payload/platform/lib/graph-write/dist/index.d.ts +30 -9
- package/payload/platform/lib/graph-write/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/graph-write/dist/index.js +22 -2
- package/payload/platform/lib/graph-write/dist/index.js.map +1 -1
- package/payload/platform/lib/graph-write/src/__tests__/account-id-gate.test.ts +99 -1
- package/payload/platform/lib/graph-write/src/index.ts +47 -12
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +45 -1
- package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +8 -0
- package/payload/platform/plugins/docs/references/telegram-guide.md +44 -0
- package/payload/platform/plugins/memory/mcp/dist/index.js +65 -0
- package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/xacct-counters.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/xacct-counters.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/xacct-counters.test.js +169 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/xacct-counters.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/xacct-counters.d.ts +63 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/xacct-counters.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/xacct-counters.js +114 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/xacct-counters.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-write-cross-account.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-write-cross-account.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-write-cross-account.test.js +123 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-write-cross-account.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/xacct-write-gate.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/xacct-write-gate.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/xacct-write-gate.test.js +110 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/xacct-write-gate.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js +7 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/vitest.config.ts +2 -0
- package/payload/platform/services/claude-session-manager/dist/claude-trust-preflight.d.ts +43 -0
- package/payload/platform/services/claude-session-manager/dist/claude-trust-preflight.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/claude-trust-preflight.js +88 -0
- package/payload/platform/services/claude-session-manager/dist/claude-trust-preflight.js.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.js +125 -4
- package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/index.js +26 -1
- package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/jsonl-path.d.ts +1 -1
- package/payload/platform/services/claude-session-manager/dist/jsonl-path.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/jsonl-path.js +26 -0
- package/payload/platform/services/claude-session-manager/dist/jsonl-path.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/recover-account.d.ts +54 -0
- package/payload/platform/services/claude-session-manager/dist/recover-account.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/recover-account.js +141 -0
- package/payload/platform/services/claude-session-manager/dist/recover-account.js.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/session-account-census.d.ts +30 -0
- package/payload/platform/services/claude-session-manager/dist/session-account-census.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/session-account-census.js +96 -0
- package/payload/platform/services/claude-session-manager/dist/session-account-census.js.map +1 -0
- package/payload/platform/services/telegram-channel/dist/instructions.d.ts +9 -0
- package/payload/platform/services/telegram-channel/dist/instructions.d.ts.map +1 -1
- package/payload/platform/services/telegram-channel/dist/instructions.js +15 -0
- package/payload/platform/services/telegram-channel/dist/instructions.js.map +1 -1
- package/payload/platform/services/telegram-channel/dist/notification.d.ts +6 -4
- package/payload/platform/services/telegram-channel/dist/notification.d.ts.map +1 -1
- package/payload/platform/services/telegram-channel/dist/notification.js +15 -1
- package/payload/platform/services/telegram-channel/dist/notification.js.map +1 -1
- package/payload/server/{chunk-GI5AVCRG.js → chunk-DRDU74ZM.js} +1 -1
- package/payload/server/{chunk-MNN2RWJR.js → chunk-IOPUA7QV.js} +1 -1
- package/payload/server/{chunk-6AQYMT6C.js → chunk-T6NXRWMG.js} +43 -8
- package/payload/server/{manager-VDHT3YYI.js → manager-O5L2SKW7.js} +2 -2
- package/payload/server/maxy-edge.js +2 -2
- package/payload/server/public/activity.html +6 -6
- package/payload/server/public/agents.html +5 -5
- package/payload/server/public/assets/{AdminLoginScreens-DuQ3ax5U.js → AdminLoginScreens-BBKEIEjY.js} +1 -1
- package/payload/server/public/assets/AdminLoginScreens-BBKEIEjY.js.br +0 -0
- package/payload/server/public/assets/AdminLoginScreens-BBKEIEjY.js.gz +0 -0
- package/payload/server/public/assets/{AdminShell-1HyATV_t.js → AdminShell-CrCdEMNW.js} +1 -1
- package/payload/server/public/assets/AdminShell-CrCdEMNW.js.br +0 -0
- package/payload/server/public/assets/AdminShell-CrCdEMNW.js.gz +0 -0
- package/payload/server/public/assets/{activity-C2qWlcJ5.js → activity-CbR3vaq1.js} +1 -1
- package/payload/server/public/assets/activity-CbR3vaq1.js.br +0 -0
- package/payload/server/public/assets/activity-CbR3vaq1.js.gz +0 -0
- package/payload/server/public/assets/{admin-DqpfY8-t.js → admin-D8qKnmhE.js} +1 -1
- package/payload/server/public/assets/admin-D8qKnmhE.js.br +0 -0
- package/payload/server/public/assets/admin-D8qKnmhE.js.gz +0 -0
- package/payload/server/public/assets/{agents-DoGVAjIT.js → agents-8gAQjRqI.js} +1 -1
- package/payload/server/public/assets/agents-8gAQjRqI.js.br +0 -0
- package/payload/server/public/assets/agents-8gAQjRqI.js.gz +0 -0
- package/payload/server/public/assets/{browser-DjqS897k.js → browser-jAje5ILy.js} +1 -1
- package/payload/server/public/assets/browser-jAje5ILy.js.br +0 -0
- package/payload/server/public/assets/browser-jAje5ILy.js.gz +0 -0
- package/payload/server/public/assets/{calendar-DJeOm0WS.js → calendar-xEmCJif9.js} +1 -1
- package/payload/server/public/assets/calendar-xEmCJif9.js.br +0 -0
- package/payload/server/public/assets/calendar-xEmCJif9.js.gz +0 -0
- package/payload/server/public/assets/chat-Ct5RDmv6.js +1 -0
- package/payload/server/public/assets/chat-Ct5RDmv6.js.br +0 -0
- package/payload/server/public/assets/chat-Ct5RDmv6.js.gz +0 -0
- package/payload/server/public/assets/{chevron-left-D9z1aK3p.js → chevron-left-DV8gIVC9.js} +1 -1
- package/payload/server/public/assets/chevron-left-DV8gIVC9.js.br +0 -0
- package/payload/server/public/assets/clock-PnR4Tlg9.js +1 -0
- package/payload/server/public/assets/clock-PnR4Tlg9.js.br +0 -0
- package/payload/server/public/assets/{copy-p9ZM9fnn.js → copy-b6MpzRz9.js} +1 -1
- package/payload/server/public/assets/copy-b6MpzRz9.js.br +0 -0
- package/payload/server/public/assets/copy-b6MpzRz9.js.gz +0 -0
- package/payload/server/public/assets/data-BxFc9wPl.js +1 -0
- package/payload/server/public/assets/data-BxFc9wPl.js.br +2 -0
- package/payload/server/public/assets/data-BxFc9wPl.js.gz +0 -0
- package/payload/server/public/assets/{field-WRk67lvr.js → field-CiIsn-47.js} +1 -1
- package/payload/server/public/assets/field-CiIsn-47.js.br +0 -0
- package/payload/server/public/assets/field-CiIsn-47.js.gz +0 -0
- package/payload/server/public/assets/{file-text-BJDCb334.js → file-text-Cy-IjCf8.js} +1 -1
- package/payload/server/public/assets/file-text-Cy-IjCf8.js.br +0 -0
- package/payload/server/public/assets/file-text-Cy-IjCf8.js.gz +0 -0
- package/payload/server/public/assets/{graph-CAU2xh2Z.js → graph-BdC2IGOT.js} +1 -1
- package/payload/server/public/assets/graph-BdC2IGOT.js.br +0 -0
- package/payload/server/public/assets/graph-BdC2IGOT.js.gz +0 -0
- package/payload/server/public/assets/{graph-labels-CEDmX7qW.js → graph-labels-3bstML8n.js} +1 -1
- package/payload/server/public/assets/graph-labels-3bstML8n.js.br +0 -0
- package/payload/server/public/assets/graph-labels-3bstML8n.js.gz +0 -0
- package/payload/server/public/assets/{jsx-runtime-hPFGo4rC.css → jsx-runtime-JxxB_2S6.css} +1 -1
- package/payload/server/public/assets/jsx-runtime-JxxB_2S6.css.br +0 -0
- package/payload/server/public/assets/{jsx-runtime-hPFGo4rC.css.gz → jsx-runtime-JxxB_2S6.css.gz} +0 -0
- package/payload/server/public/assets/{operator-1WFztEQA.js → operator-D7L2SA16.js} +1 -1
- package/payload/server/public/assets/operator-D7L2SA16.js.br +0 -0
- package/payload/server/public/assets/operator-D7L2SA16.js.gz +0 -0
- package/payload/server/public/assets/{page-B72XigcU.js → page-DspGbDgK.js} +1 -1
- package/payload/server/public/assets/page-DspGbDgK.js.br +0 -0
- package/payload/server/public/assets/page-DspGbDgK.js.gz +0 -0
- package/payload/server/public/assets/{page-nT8l_cX1.js → page-ObXxk8ol.js} +1 -1
- package/payload/server/public/assets/page-ObXxk8ol.js.br +0 -0
- package/payload/server/public/assets/page-ObXxk8ol.js.gz +0 -0
- package/payload/server/public/assets/play-BL4ztD3m.js +1 -0
- package/payload/server/public/assets/play-BL4ztD3m.js.br +0 -0
- package/payload/server/public/assets/play-BL4ztD3m.js.gz +0 -0
- package/payload/server/public/assets/{public-DAea6w7w.js → public-CEXKl8wg.js} +1 -1
- package/payload/server/public/assets/public-CEXKl8wg.js.br +0 -0
- package/payload/server/public/assets/public-CEXKl8wg.js.gz +0 -0
- package/payload/server/public/assets/{rotate-ccw-CqlRlGsY.js → rotate-ccw-ckXDebK2.js} +1 -1
- package/payload/server/public/assets/rotate-ccw-ckXDebK2.js.br +0 -0
- package/payload/server/public/assets/rotate-ccw-ckXDebK2.js.gz +0 -0
- package/payload/server/public/assets/{routines-vy5xsyqx.js → routines-Dwc2meN2.js} +1 -1
- package/payload/server/public/assets/routines-Dwc2meN2.js.br +0 -0
- package/payload/server/public/assets/routines-Dwc2meN2.js.gz +0 -0
- package/payload/server/public/assets/{skills-X7FTilVy.js → skills-DdHKHl4Z.js} +1 -1
- package/payload/server/public/assets/skills-DdHKHl4Z.js.br +0 -0
- package/payload/server/public/assets/skills-DdHKHl4Z.js.gz +0 -0
- package/payload/server/public/assets/{tasks-BXx_jk_p.js → tasks-C_yWRvOG.js} +1 -1
- package/payload/server/public/assets/tasks-C_yWRvOG.js.br +0 -0
- package/payload/server/public/assets/tasks-C_yWRvOG.js.gz +0 -0
- package/payload/server/public/assets/{triangle-alert-CuWcGaRo.js → triangle-alert-C-7A00P0.js} +1 -1
- package/payload/server/public/assets/triangle-alert-C-7A00P0.js.br +0 -0
- package/payload/server/public/assets/triangle-alert-C-7A00P0.js.gz +0 -0
- package/payload/server/public/assets/{useCopyFeedback-DLSKs6r2.js → useCopyFeedback-CWvSi-Qe.js} +1 -1
- package/payload/server/public/assets/useCopyFeedback-CWvSi-Qe.js.br +2 -0
- package/payload/server/public/assets/useCopyFeedback-CWvSi-Qe.js.gz +0 -0
- package/payload/server/public/assets/{useMediaQuery-C_1CV_iW.js → useMediaQuery-CLVRXJMp.js} +1 -1
- package/payload/server/public/assets/useMediaQuery-CLVRXJMp.js.br +0 -0
- package/payload/server/public/assets/useMediaQuery-CLVRXJMp.js.gz +0 -0
- package/payload/server/public/assets/{useVoiceRecorder-DBzM_HIx.js → useVoiceRecorder-BbJad9CQ.js} +1 -1
- package/payload/server/public/assets/useVoiceRecorder-BbJad9CQ.js.br +0 -0
- package/payload/server/public/assets/useVoiceRecorder-BbJad9CQ.js.gz +0 -0
- package/payload/server/public/assets/{wrench-nDMQ6x-6.js → wrench-Cl6TUm2T.js} +1 -1
- package/payload/server/public/assets/wrench-Cl6TUm2T.js.br +0 -0
- package/payload/server/public/assets/wrench-Cl6TUm2T.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 +16 -16
- 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 +511 -283
- package/payload/server/public/assets/AdminLoginScreens-DuQ3ax5U.js.br +0 -0
- package/payload/server/public/assets/AdminLoginScreens-DuQ3ax5U.js.gz +0 -0
- package/payload/server/public/assets/AdminShell-1HyATV_t.js.br +0 -0
- package/payload/server/public/assets/AdminShell-1HyATV_t.js.gz +0 -0
- package/payload/server/public/assets/activity-C2qWlcJ5.js.br +0 -0
- package/payload/server/public/assets/activity-C2qWlcJ5.js.gz +0 -0
- package/payload/server/public/assets/admin-DqpfY8-t.js.br +0 -0
- package/payload/server/public/assets/admin-DqpfY8-t.js.gz +0 -0
- package/payload/server/public/assets/agents-DoGVAjIT.js.br +0 -0
- package/payload/server/public/assets/agents-DoGVAjIT.js.gz +0 -0
- package/payload/server/public/assets/browser-DjqS897k.js.br +0 -0
- package/payload/server/public/assets/browser-DjqS897k.js.gz +0 -0
- package/payload/server/public/assets/calendar-DJeOm0WS.js.br +0 -0
- package/payload/server/public/assets/calendar-DJeOm0WS.js.gz +0 -0
- package/payload/server/public/assets/chat-BrRE0Dck.js +0 -1
- package/payload/server/public/assets/chat-BrRE0Dck.js.br +0 -0
- package/payload/server/public/assets/chat-BrRE0Dck.js.gz +0 -0
- package/payload/server/public/assets/chevron-left-D9z1aK3p.js.br +0 -0
- package/payload/server/public/assets/clock-BqHWMICF.js +0 -1
- package/payload/server/public/assets/clock-BqHWMICF.js.br +0 -0
- package/payload/server/public/assets/clock-BqHWMICF.js.gz +0 -0
- package/payload/server/public/assets/copy-p9ZM9fnn.js.br +0 -0
- package/payload/server/public/assets/copy-p9ZM9fnn.js.gz +0 -0
- package/payload/server/public/assets/data-CPsqW0qW.js +0 -1
- package/payload/server/public/assets/data-CPsqW0qW.js.br +0 -0
- package/payload/server/public/assets/data-CPsqW0qW.js.gz +0 -0
- package/payload/server/public/assets/field-WRk67lvr.js.br +0 -0
- package/payload/server/public/assets/field-WRk67lvr.js.gz +0 -0
- package/payload/server/public/assets/file-text-BJDCb334.js.br +0 -0
- package/payload/server/public/assets/file-text-BJDCb334.js.gz +0 -0
- package/payload/server/public/assets/graph-CAU2xh2Z.js.br +0 -0
- package/payload/server/public/assets/graph-CAU2xh2Z.js.gz +0 -0
- package/payload/server/public/assets/graph-labels-CEDmX7qW.js.br +0 -0
- package/payload/server/public/assets/graph-labels-CEDmX7qW.js.gz +0 -0
- package/payload/server/public/assets/jsx-runtime-hPFGo4rC.css.br +0 -0
- package/payload/server/public/assets/operator-1WFztEQA.js.br +0 -0
- package/payload/server/public/assets/operator-1WFztEQA.js.gz +0 -0
- package/payload/server/public/assets/page-B72XigcU.js.br +0 -0
- package/payload/server/public/assets/page-B72XigcU.js.gz +0 -0
- package/payload/server/public/assets/page-nT8l_cX1.js.br +0 -0
- package/payload/server/public/assets/page-nT8l_cX1.js.gz +0 -0
- package/payload/server/public/assets/play-CYqOCqm6.js +0 -1
- package/payload/server/public/assets/play-CYqOCqm6.js.br +0 -0
- package/payload/server/public/assets/play-CYqOCqm6.js.gz +0 -0
- package/payload/server/public/assets/public-DAea6w7w.js.br +0 -0
- package/payload/server/public/assets/public-DAea6w7w.js.gz +0 -0
- package/payload/server/public/assets/rotate-ccw-CqlRlGsY.js.br +0 -0
- package/payload/server/public/assets/rotate-ccw-CqlRlGsY.js.gz +0 -0
- package/payload/server/public/assets/routines-vy5xsyqx.js.br +0 -0
- package/payload/server/public/assets/routines-vy5xsyqx.js.gz +0 -0
- package/payload/server/public/assets/skills-X7FTilVy.js.br +0 -0
- package/payload/server/public/assets/skills-X7FTilVy.js.gz +0 -0
- package/payload/server/public/assets/tasks-BXx_jk_p.js.br +0 -0
- package/payload/server/public/assets/tasks-BXx_jk_p.js.gz +0 -0
- package/payload/server/public/assets/triangle-alert-CuWcGaRo.js.br +0 -0
- package/payload/server/public/assets/triangle-alert-CuWcGaRo.js.gz +0 -0
- package/payload/server/public/assets/useCopyFeedback-DLSKs6r2.js.br +0 -0
- package/payload/server/public/assets/useCopyFeedback-DLSKs6r2.js.gz +0 -0
- package/payload/server/public/assets/useMediaQuery-C_1CV_iW.js.br +0 -0
- package/payload/server/public/assets/useMediaQuery-C_1CV_iW.js.gz +0 -0
- package/payload/server/public/assets/useVoiceRecorder-DBzM_HIx.js.br +0 -0
- package/payload/server/public/assets/useVoiceRecorder-DBzM_HIx.js.gz +0 -0
- package/payload/server/public/assets/wrench-nDMQ6x-6.js.br +0 -0
- package/payload/server/public/assets/wrench-nDMQ6x-6.js.gz +0 -0
- /package/payload/server/public/assets/{jsx-runtime-CvVXOszc.js → jsx-runtime-BCAZhYqz.js} +0 -0
- /package/payload/server/public/assets/{jsx-runtime-CvVXOszc.js.br → jsx-runtime-BCAZhYqz.js.br} +0 -0
- /package/payload/server/public/assets/{jsx-runtime-CvVXOszc.js.gz → jsx-runtime-BCAZhYqz.js.gz} +0 -0
package/payload/server/server.js
CHANGED
|
@@ -70,7 +70,7 @@ import {
|
|
|
70
70
|
verifyRemotePassword,
|
|
71
71
|
vncLog,
|
|
72
72
|
walkPremiumBundles
|
|
73
|
-
} from "./chunk-
|
|
73
|
+
} from "./chunk-IOPUA7QV.js";
|
|
74
74
|
import {
|
|
75
75
|
audioExtension,
|
|
76
76
|
isAudioMime,
|
|
@@ -220,7 +220,7 @@ import {
|
|
|
220
220
|
waitForConnection,
|
|
221
221
|
warnNonUuidAccount,
|
|
222
222
|
writeChatMetadataMerged
|
|
223
|
-
} from "./chunk-
|
|
223
|
+
} from "./chunk-DRDU74ZM.js";
|
|
224
224
|
import {
|
|
225
225
|
ACCOUNTS_DIR,
|
|
226
226
|
AGENT_SLUG_PATTERN,
|
|
@@ -243,6 +243,7 @@ import {
|
|
|
243
243
|
VNC_DISPLAY,
|
|
244
244
|
WEBSOCKIFY_PORT,
|
|
245
245
|
armedCount,
|
|
246
|
+
censusAccountDirs,
|
|
246
247
|
createNewAdminConversation,
|
|
247
248
|
deleteAgentProjection,
|
|
248
249
|
deleteConversation,
|
|
@@ -285,7 +286,7 @@ import {
|
|
|
285
286
|
verifyAndGetConversationUpdatedAt,
|
|
286
287
|
verifyConversationOwnership,
|
|
287
288
|
writeAdminUserAndPerson
|
|
288
|
-
} from "./chunk-
|
|
289
|
+
} from "./chunk-T6NXRWMG.js";
|
|
289
290
|
import {
|
|
290
291
|
extractVideo,
|
|
291
292
|
transcribe
|
|
@@ -361,15 +362,15 @@ var require_dist2 = __commonJS({
|
|
|
361
362
|
return out;
|
|
362
363
|
}
|
|
363
364
|
function scanStore(storeDir) {
|
|
364
|
-
const
|
|
365
|
+
const newest2 = /* @__PURE__ */ new Map();
|
|
365
366
|
let storeRows = 0;
|
|
366
367
|
if (!storeDir || !(0, node_fs_1.existsSync)(storeDir))
|
|
367
|
-
return { newest, storeRows };
|
|
368
|
+
return { newest: newest2, storeRows };
|
|
368
369
|
let entries2;
|
|
369
370
|
try {
|
|
370
371
|
entries2 = (0, node_fs_1.readdirSync)(storeDir);
|
|
371
372
|
} catch {
|
|
372
|
-
return { newest, storeRows };
|
|
373
|
+
return { newest: newest2, storeRows };
|
|
373
374
|
}
|
|
374
375
|
for (const entry3 of entries2) {
|
|
375
376
|
if (!entry3.endsWith(".jsonl"))
|
|
@@ -401,10 +402,10 @@ var require_dist2 = __commonJS({
|
|
|
401
402
|
if (chatId !== senderId)
|
|
402
403
|
continue;
|
|
403
404
|
const key2 = `${botId}:${senderId}`;
|
|
404
|
-
const prev =
|
|
405
|
+
const prev = newest2.get(key2);
|
|
405
406
|
if (prev !== void 0 && prev.dateSent.localeCompare(dateSent) >= 0)
|
|
406
407
|
continue;
|
|
407
|
-
|
|
408
|
+
newest2.set(key2, {
|
|
408
409
|
chatId,
|
|
409
410
|
senderId,
|
|
410
411
|
senderName: typeof row.senderName === "string" ? row.senderName : null,
|
|
@@ -412,16 +413,16 @@ var require_dist2 = __commonJS({
|
|
|
412
413
|
});
|
|
413
414
|
}
|
|
414
415
|
}
|
|
415
|
-
return { newest, storeRows };
|
|
416
|
+
return { newest: newest2, storeRows };
|
|
416
417
|
}
|
|
417
418
|
function collectTelegramReach2(input) {
|
|
418
|
-
const { newest, storeRows } = scanStore(input.storeDir);
|
|
419
|
+
const { newest: newest2, storeRows } = scanStore(input.storeDir);
|
|
419
420
|
const bots = input.bots.map((bot) => {
|
|
420
421
|
const adminUsers = bot.adminUsers ?? [];
|
|
421
422
|
const adminSet = new Set(adminUsers.map((u) => String(u)));
|
|
422
423
|
const chats = [];
|
|
423
424
|
const seen = /* @__PURE__ */ new Set();
|
|
424
|
-
for (const [key2, row] of
|
|
425
|
+
for (const [key2, row] of newest2) {
|
|
425
426
|
if (key2.slice(0, key2.indexOf(":")) !== bot.id)
|
|
426
427
|
continue;
|
|
427
428
|
seen.add(row.senderId);
|
|
@@ -2923,7 +2924,8 @@ var require_dist10 = __commonJS({
|
|
|
2923
2924
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports2, p)) __createBinding(exports2, m, p);
|
|
2924
2925
|
};
|
|
2925
2926
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
2926
|
-
exports.DOCUMENT_ARCHIVE_LABELS = exports.VECTOR_INDEXED_LABELS = exports.PROVENANCE_SOURCE_LABELS = exports.ACTION_PROVENANCE_LABELS = void 0;
|
|
2927
|
+
exports.INVALID_ACCOUNT_ID_REASON = exports.DOCUMENT_ARCHIVE_LABELS = exports.VECTOR_INDEXED_LABELS = exports.PROVENANCE_SOURCE_LABELS = exports.ACTION_PROVENANCE_LABELS = void 0;
|
|
2928
|
+
exports.isInvalidAccountIdError = isInvalidAccountIdError;
|
|
2927
2929
|
exports.stampCreatedBy = stampCreatedBy;
|
|
2928
2930
|
exports.writeNodeWithEdges = writeNodeWithEdges;
|
|
2929
2931
|
__exportStar(require_audit(), exports);
|
|
@@ -3027,6 +3029,15 @@ var require_dist10 = __commonJS({
|
|
|
3027
3029
|
function findProvenanceCandidates(relationships) {
|
|
3028
3030
|
return relationships.filter((r) => r.type === "PRODUCED" && r.direction === "incoming");
|
|
3029
3031
|
}
|
|
3032
|
+
exports.INVALID_ACCOUNT_ID_REASON = "invalid-account-id";
|
|
3033
|
+
function invalidAccountIdError(slice) {
|
|
3034
|
+
const err = new Error(`Write doctrine violated: ${exports.INVALID_ACCOUNT_ID_REASON} (${slice}) \u2014 accountId must equal the account this write is authorised for: \`expectedAccountId\` when the caller resolves authority per call, otherwise the ACCOUNT_ID set by the spawning process. See .docs/neo4j.md "Account isolation invariant".`);
|
|
3035
|
+
err.reason = exports.INVALID_ACCOUNT_ID_REASON;
|
|
3036
|
+
return err;
|
|
3037
|
+
}
|
|
3038
|
+
function isInvalidAccountIdError(err) {
|
|
3039
|
+
return err instanceof Error && err.reason === exports.INVALID_ACCOUNT_ID_REASON;
|
|
3040
|
+
}
|
|
3030
3041
|
var MERGE_CREATE_ONLY_PROPS = /* @__PURE__ */ new Set([
|
|
3031
3042
|
"createdAt",
|
|
3032
3043
|
"createdByAgent",
|
|
@@ -3055,7 +3066,7 @@ var require_dist10 = __commonJS({
|
|
|
3055
3066
|
const slice = typeof accountId === "string" ? accountId.slice(0, 8) : "missing";
|
|
3056
3067
|
process.stderr.write(`[graph-write] reject reason=invalid-account-id accountId=${slice} writer=${agentLabel}
|
|
3057
3068
|
`);
|
|
3058
|
-
throw
|
|
3069
|
+
throw invalidAccountIdError(slice);
|
|
3059
3070
|
}
|
|
3060
3071
|
}
|
|
3061
3072
|
const reviewDigestActionTool = typeof props.actionTool === "string" && props.actionTool === "review-digest-compose";
|
|
@@ -3459,15 +3470,15 @@ function readRows(accountId, channelKey) {
|
|
|
3459
3470
|
}
|
|
3460
3471
|
}
|
|
3461
3472
|
function newestInboundTelegramDate(accountId, channelKey) {
|
|
3462
|
-
let
|
|
3473
|
+
let newest2 = null;
|
|
3463
3474
|
for (const row of readRows(accountId, channelKey)) {
|
|
3464
3475
|
if (isUpdateRecord(row)) continue;
|
|
3465
3476
|
if (row.fromMe) continue;
|
|
3466
3477
|
const d = row.telegramDate;
|
|
3467
3478
|
if (typeof d !== "number" || !Number.isFinite(d)) continue;
|
|
3468
|
-
if (
|
|
3479
|
+
if (newest2 === null || d > newest2) newest2 = d;
|
|
3469
3480
|
}
|
|
3470
|
-
return
|
|
3481
|
+
return newest2;
|
|
3471
3482
|
}
|
|
3472
3483
|
function readConversation2(accountId, channelKey) {
|
|
3473
3484
|
if (!(0, import_dist2.isStorableChannelKey)(channelKey)) return [];
|
|
@@ -3516,9 +3527,9 @@ function findPollConversation(accountId, pollId) {
|
|
|
3516
3527
|
}
|
|
3517
3528
|
var summaryCache = /* @__PURE__ */ new Map();
|
|
3518
3529
|
function summariseRecords(rows) {
|
|
3519
|
-
const
|
|
3520
|
-
if (
|
|
3521
|
-
const sorted =
|
|
3530
|
+
const records5 = messageRows(rows);
|
|
3531
|
+
if (records5.length === 0) return null;
|
|
3532
|
+
const sorted = records5.slice().sort(byDateSentAsc);
|
|
3522
3533
|
return { first: sorted[0], last: sorted[sorted.length - 1] };
|
|
3523
3534
|
}
|
|
3524
3535
|
function readConversationSummaries2(accountId) {
|
|
@@ -4078,9 +4089,9 @@ var idCache = /* @__PURE__ */ new Map();
|
|
|
4078
4089
|
function persistedMsgKeyIds() {
|
|
4079
4090
|
const ids = /* @__PURE__ */ new Set();
|
|
4080
4091
|
for (const accountId of listStoredAccountIds()) {
|
|
4081
|
-
for (const [remoteJid,
|
|
4092
|
+
for (const [remoteJid, records5] of readAllConversationsCached(accountId)) {
|
|
4082
4093
|
void remoteJid;
|
|
4083
|
-
for (const id of
|
|
4094
|
+
for (const id of records5) ids.add(id);
|
|
4084
4095
|
}
|
|
4085
4096
|
}
|
|
4086
4097
|
return ids;
|
|
@@ -4579,9 +4590,9 @@ function isModelGated(turns) {
|
|
|
4579
4590
|
return turns.some((t) => t.kind === "agent-error" && t.code === "model_unavailable");
|
|
4580
4591
|
}
|
|
4581
4592
|
function renderOrSuppressChannelInbound(u, ts, out, queuedPendingSuppress, uuid, census) {
|
|
4582
|
-
const
|
|
4583
|
-
if (
|
|
4584
|
-
queuedPendingSuppress.set(u.text,
|
|
4593
|
+
const armed3 = queuedPendingSuppress.get(u.text) ?? 0;
|
|
4594
|
+
if (armed3 > 0) {
|
|
4595
|
+
queuedPendingSuppress.set(u.text, armed3 - 1);
|
|
4585
4596
|
} else {
|
|
4586
4597
|
out.push(operatorInboundTurn(u, ts, uuid, census));
|
|
4587
4598
|
}
|
|
@@ -7948,7 +7959,7 @@ async function defaultHttpGet(url) {
|
|
|
7948
7959
|
}
|
|
7949
7960
|
}
|
|
7950
7961
|
async function defaultResolve(accountId) {
|
|
7951
|
-
const { resolveSocket: resolveSocket2 } = await import("./manager-
|
|
7962
|
+
const { resolveSocket: resolveSocket2 } = await import("./manager-O5L2SKW7.js");
|
|
7952
7963
|
return resolveSocket2(accountId);
|
|
7953
7964
|
}
|
|
7954
7965
|
async function fetchAvatar(accountId, jid, deps = {}) {
|
|
@@ -7999,15 +8010,15 @@ var CENSUS_TAG = "[wa-avatar-census]";
|
|
|
7999
8010
|
var AVATAR_STORE_MAX_BYTES = 16 * 1024 * 1024;
|
|
8000
8011
|
function liveJidsForAccount(accountId) {
|
|
8001
8012
|
const live = /* @__PURE__ */ new Set();
|
|
8002
|
-
for (const [remoteJid,
|
|
8003
|
-
for (const jid of avatarJidsForConversation(remoteJid,
|
|
8013
|
+
for (const [remoteJid, records5] of readAllConversations(accountId)) {
|
|
8014
|
+
for (const jid of avatarJidsForConversation(remoteJid, records5)) live.add(jid);
|
|
8004
8015
|
}
|
|
8005
8016
|
return live;
|
|
8006
8017
|
}
|
|
8007
|
-
function avatarJidsForConversation(remoteJid,
|
|
8018
|
+
function avatarJidsForConversation(remoteJid, records5) {
|
|
8008
8019
|
const jids = /* @__PURE__ */ new Set([remoteJid]);
|
|
8009
8020
|
if (!isGroupJid(remoteJid)) return jids;
|
|
8010
|
-
for (const r of
|
|
8021
|
+
for (const r of records5) {
|
|
8011
8022
|
if (r.fromMe) continue;
|
|
8012
8023
|
if (r.senderJid && isUserJid(r.senderJid)) jids.add(r.senderJid);
|
|
8013
8024
|
}
|
|
@@ -8142,10 +8153,10 @@ function auditGroupOutbound() {
|
|
|
8142
8153
|
let unstamped = 0;
|
|
8143
8154
|
const offenders = [];
|
|
8144
8155
|
for (const accountId of listStoredAccountIds()) {
|
|
8145
|
-
for (const [remoteJid,
|
|
8156
|
+
for (const [remoteJid, records5] of readAllConversations(accountId)) {
|
|
8146
8157
|
if (!isGroupJid(remoteJid)) continue;
|
|
8147
8158
|
convos++;
|
|
8148
|
-
for (const r of
|
|
8159
|
+
for (const r of records5) {
|
|
8149
8160
|
if (!r.fromMe) continue;
|
|
8150
8161
|
outbound++;
|
|
8151
8162
|
if (r.origin === "operator-manual") operator++;
|
|
@@ -14686,11 +14697,11 @@ function emitGauge() {
|
|
|
14686
14697
|
counts[reg.channel]++;
|
|
14687
14698
|
oldestMs = Math.max(oldestMs, now - reg.startedAt);
|
|
14688
14699
|
}
|
|
14689
|
-
const
|
|
14700
|
+
const armed3 = counts.reader + counts.store;
|
|
14690
14701
|
console.log(
|
|
14691
|
-
`[wa-stream] op=gauge armed=${
|
|
14702
|
+
`[wa-stream] op=gauge armed=${armed3} reader=${counts.reader} store=${counts.store} oldestSec=${Math.floor(oldestMs / 1e3)} stale=${stale}`
|
|
14692
14703
|
);
|
|
14693
|
-
if (
|
|
14704
|
+
if (armed3 === 0) stopGauge();
|
|
14694
14705
|
}
|
|
14695
14706
|
function startGauge() {
|
|
14696
14707
|
if (gaugeTimer) return;
|
|
@@ -14857,8 +14868,8 @@ function resolveReplyAppendAccount(args) {
|
|
|
14857
14868
|
if (args.isGroup) return args.sendAccountId;
|
|
14858
14869
|
return args.resolve(args.sendAccountId, args.counterpartyPhone) || args.sendAccountId;
|
|
14859
14870
|
}
|
|
14860
|
-
function warmConversationAvatars(accountId, remoteJid,
|
|
14861
|
-
const jids = avatarJidsForConversation(remoteJid,
|
|
14871
|
+
function warmConversationAvatars(accountId, remoteJid, records5) {
|
|
14872
|
+
const jids = avatarJidsForConversation(remoteJid, records5);
|
|
14862
14873
|
console.log(`[wa-avatar] op=request account=${accountId.slice(0, 8)} convo=${remoteJid.slice(0, 12)} jids=${jids.size} reason=reader-open`);
|
|
14863
14874
|
for (const jid of jids) {
|
|
14864
14875
|
void fetchAvatar(accountId, jid).catch((e) => {
|
|
@@ -14930,7 +14941,7 @@ app5.get("/store-backfill", requireAdminSession, (c) => {
|
|
|
14930
14941
|
return c.json({ turns: [], from: 0, reachedStart: true });
|
|
14931
14942
|
}
|
|
14932
14943
|
const { from, aligned } = backfillRangeStart(file, to, TAIL_WINDOW_BYTES);
|
|
14933
|
-
const
|
|
14944
|
+
const records5 = [];
|
|
14934
14945
|
const reactionRecords = [];
|
|
14935
14946
|
let reactionScanBytes = 0;
|
|
14936
14947
|
try {
|
|
@@ -14944,7 +14955,7 @@ app5.get("/store-backfill", requireAdminSession, (c) => {
|
|
|
14944
14955
|
reactionRecords.push(parsed);
|
|
14945
14956
|
continue;
|
|
14946
14957
|
}
|
|
14947
|
-
|
|
14958
|
+
records5.push(parsed);
|
|
14948
14959
|
} catch {
|
|
14949
14960
|
}
|
|
14950
14961
|
}
|
|
@@ -14963,11 +14974,11 @@ app5.get("/store-backfill", requireAdminSession, (c) => {
|
|
|
14963
14974
|
console.error(`[wa-reader] op=store-backfill remoteJid=${remoteJid} from=${from} to=${to} outcome=read-failed`);
|
|
14964
14975
|
return c.json({ error: "read-failed" }, 500);
|
|
14965
14976
|
}
|
|
14966
|
-
|
|
14977
|
+
records5.sort((a, b) => a.dateSent.localeCompare(b.dateSent));
|
|
14967
14978
|
const byMsgKeyId = /* @__PURE__ */ new Map();
|
|
14968
|
-
for (const m of
|
|
14979
|
+
for (const m of records5) byMsgKeyId.set(m.msgKeyId, m);
|
|
14969
14980
|
const wanted = /* @__PURE__ */ new Set();
|
|
14970
|
-
for (const m of
|
|
14981
|
+
for (const m of records5) {
|
|
14971
14982
|
if (m.quotedId && !byMsgKeyId.has(m.quotedId)) wanted.add(m.quotedId);
|
|
14972
14983
|
}
|
|
14973
14984
|
const q2 = resolveQuoteTargets(file, from, wanted);
|
|
@@ -14983,7 +14994,7 @@ app5.get("/store-backfill", requireAdminSession, (c) => {
|
|
|
14983
14994
|
const uploadsBase = resolve18(DATA_ROOT, "accounts", accountId, "uploads");
|
|
14984
14995
|
const toTurn2 = makeToTurn({ byMsgKeyId, uploadsBase });
|
|
14985
14996
|
const fold = foldReactions(reactionRecords);
|
|
14986
|
-
const turns =
|
|
14997
|
+
const turns = records5.map((m) => toTurn2(m, fold.get(m.msgKeyId)));
|
|
14987
14998
|
const reachedStart = from === 0;
|
|
14988
14999
|
noteBackfill(remoteJid.slice(0, 12));
|
|
14989
15000
|
console.log(
|
|
@@ -15060,7 +15071,7 @@ data: ${JSON.stringify({ from: alignedFrom, fileEnd: fileEnd0 })}
|
|
|
15060
15071
|
|
|
15061
15072
|
`)
|
|
15062
15073
|
);
|
|
15063
|
-
const
|
|
15074
|
+
const records5 = [];
|
|
15064
15075
|
try {
|
|
15065
15076
|
const { buf, end } = readFrom(file, alignedFrom);
|
|
15066
15077
|
offset = end;
|
|
@@ -15072,18 +15083,18 @@ data: ${JSON.stringify({ from: alignedFrom, fileEnd: fileEnd0 })}
|
|
|
15072
15083
|
reactionRecords.push(parsed);
|
|
15073
15084
|
continue;
|
|
15074
15085
|
}
|
|
15075
|
-
|
|
15086
|
+
records5.push(parsed);
|
|
15076
15087
|
} catch {
|
|
15077
15088
|
}
|
|
15078
15089
|
}
|
|
15079
15090
|
} catch {
|
|
15080
15091
|
offset = fileEnd0;
|
|
15081
15092
|
}
|
|
15082
|
-
|
|
15083
|
-
const scope =
|
|
15084
|
-
for (const m of
|
|
15093
|
+
records5.sort((a, b) => a.dateSent.localeCompare(b.dateSent));
|
|
15094
|
+
const scope = records5.length ? records5[records5.length - 1].scope : "none";
|
|
15095
|
+
for (const m of records5) byMsgKeyId.set(m.msgKeyId, m);
|
|
15085
15096
|
const wantedQuotes = /* @__PURE__ */ new Set();
|
|
15086
|
-
for (const m of
|
|
15097
|
+
for (const m of records5) {
|
|
15087
15098
|
if (m.quotedId && !byMsgKeyId.has(m.quotedId)) wantedQuotes.add(m.quotedId);
|
|
15088
15099
|
}
|
|
15089
15100
|
const q2 = resolveQuoteTargets(file, alignedFrom, wantedQuotes);
|
|
@@ -15097,14 +15108,14 @@ data: ${JSON.stringify({ from: alignedFrom, fileEnd: fileEnd0 })}
|
|
|
15097
15108
|
});
|
|
15098
15109
|
}
|
|
15099
15110
|
const backlogFold = foldReactions(reactionRecords);
|
|
15100
|
-
for (const m of
|
|
15111
|
+
for (const m of records5) send(toTurn2(m, backlogFold.get(m.msgKeyId)), offset);
|
|
15101
15112
|
console.log(
|
|
15102
|
-
`[wa-reader] op=open remoteJid=${remoteJid} scope=${scope} messages=${
|
|
15113
|
+
`[wa-reader] op=open remoteJid=${remoteJid} scope=${scope} messages=${records5.length} source=store`
|
|
15103
15114
|
);
|
|
15104
15115
|
console.log(
|
|
15105
|
-
`[wa-reader] op=store-window remoteJid=${remoteJid} fileBytes=${fileEnd0} budget=${TAIL_WINDOW_BYTES} rawFrom=${rawFrom} alignedFrom=${alignedFrom} aligned=${aligned} source=${alignedFrom > 0 ? "windowed" : "full"} messages=${
|
|
15116
|
+
`[wa-reader] op=store-window remoteJid=${remoteJid} fileBytes=${fileEnd0} budget=${TAIL_WINDOW_BYTES} rawFrom=${rawFrom} alignedFrom=${alignedFrom} aligned=${aligned} source=${alignedFrom > 0 ? "windowed" : "full"} messages=${records5.length} quoteWanted=${wantedQuotes.size} quoteResolved=${q2.found.size} quoteMissing=${wantedQuotes.size - q2.found.size} quoteScanBytes=${q2.scannedBytes} quoteCapped=${q2.capped}`
|
|
15106
15117
|
);
|
|
15107
|
-
warmConversationAvatars(accountId, remoteJid,
|
|
15118
|
+
warmConversationAvatars(accountId, remoteJid, records5);
|
|
15108
15119
|
} else {
|
|
15109
15120
|
reactionRecords.push(...readReactions(accountId, remoteJid));
|
|
15110
15121
|
}
|
|
@@ -15421,7 +15432,7 @@ var whatsapp_reader_default = app5;
|
|
|
15421
15432
|
|
|
15422
15433
|
// server/routes/telegram-reader.ts
|
|
15423
15434
|
import { statSync as statSync14, watch as watch3 } from "fs";
|
|
15424
|
-
import { join as
|
|
15435
|
+
import { join as join28, resolve as resolve19 } from "path";
|
|
15425
15436
|
|
|
15426
15437
|
// app/lib/telegram/outbound/get-chat.ts
|
|
15427
15438
|
async function getTelegramChat(botToken, chatId) {
|
|
@@ -15439,6 +15450,164 @@ async function getTelegramChat(botToken, chatId) {
|
|
|
15439
15450
|
}
|
|
15440
15451
|
}
|
|
15441
15452
|
|
|
15453
|
+
// app/lib/telegram/manual-send-census.ts
|
|
15454
|
+
var RECORD_THRESHOLD_MS = 3e4;
|
|
15455
|
+
var SUPPRESSION_THRESHOLD_MS = 6e5;
|
|
15456
|
+
var WINDOW_MS3 = 36e5;
|
|
15457
|
+
var records3 = [];
|
|
15458
|
+
function prune2(now) {
|
|
15459
|
+
records3 = records3.filter((r) => now - r.at <= WINDOW_MS3);
|
|
15460
|
+
}
|
|
15461
|
+
function newest(key2) {
|
|
15462
|
+
for (let i = records3.length - 1; i >= 0; i--) if (records3[i].key === key2) return records3[i];
|
|
15463
|
+
return void 0;
|
|
15464
|
+
}
|
|
15465
|
+
function noteManualSent(key2, now) {
|
|
15466
|
+
records3.push({ key: key2, at: now, recorded: false, skipped: null, suppressed: false });
|
|
15467
|
+
}
|
|
15468
|
+
function noteManualRecorded(key2, _now) {
|
|
15469
|
+
const r = newest(key2);
|
|
15470
|
+
if (r) r.recorded = true;
|
|
15471
|
+
}
|
|
15472
|
+
function noteManualSkipped(key2, reason, _now) {
|
|
15473
|
+
const r = newest(key2);
|
|
15474
|
+
if (r) r.skipped = reason;
|
|
15475
|
+
}
|
|
15476
|
+
function noteManualSuppressed(key2, _now) {
|
|
15477
|
+
const r = records3.find((x) => x.key === key2 && x.recorded && !x.suppressed);
|
|
15478
|
+
if (r) r.suppressed = true;
|
|
15479
|
+
}
|
|
15480
|
+
function readManualSendCensus(now) {
|
|
15481
|
+
prune2(now);
|
|
15482
|
+
let recorded = 0;
|
|
15483
|
+
let suppressed = 0;
|
|
15484
|
+
let unrecorded = 0;
|
|
15485
|
+
let skipped = 0;
|
|
15486
|
+
let leaked = 0;
|
|
15487
|
+
for (const r of records3) {
|
|
15488
|
+
if (r.recorded) recorded += 1;
|
|
15489
|
+
else if (r.skipped !== null) skipped += 1;
|
|
15490
|
+
else if (now - r.at > RECORD_THRESHOLD_MS) unrecorded += 1;
|
|
15491
|
+
if (r.suppressed) suppressed += 1;
|
|
15492
|
+
else if (r.recorded && now - r.at > SUPPRESSION_THRESHOLD_MS) leaked += 1;
|
|
15493
|
+
}
|
|
15494
|
+
return { sent: records3.length, recorded, suppressed, unrecorded, skipped, leaked };
|
|
15495
|
+
}
|
|
15496
|
+
function buildManualSendCensusLine(c) {
|
|
15497
|
+
return `[telegram-manual-census] sent=${c.sent} recorded=${c.recorded} suppressed=${c.suppressed} unrecorded=${c.unrecorded} skipped=${c.skipped} leaked=${c.leaked} window=60m`;
|
|
15498
|
+
}
|
|
15499
|
+
function runTelegramManualSendCensus(now) {
|
|
15500
|
+
console.error(buildManualSendCensusLine(readManualSendCensus(now)));
|
|
15501
|
+
}
|
|
15502
|
+
|
|
15503
|
+
// app/lib/telegram/manual-send-context.ts
|
|
15504
|
+
async function recordManualSendContext(input, deps) {
|
|
15505
|
+
const refuse2 = (reason) => {
|
|
15506
|
+
noteManualSkipped(input.channelKey, reason, deps.now());
|
|
15507
|
+
return { recorded: false, reason };
|
|
15508
|
+
};
|
|
15509
|
+
if (input.entry.role !== "public") return refuse2("not-public-bot");
|
|
15510
|
+
if (!deps.entryActive(input.entry, input.accountDir, input.botId)) return refuse2("agent-inactive");
|
|
15511
|
+
const businessKey = telegramBusinessChannelKey(input.botId, String(input.chatId));
|
|
15512
|
+
if (deps.newestInboundTelegramDate(input.accountId, businessKey) !== null) {
|
|
15513
|
+
return refuse2("business-chat");
|
|
15514
|
+
}
|
|
15515
|
+
if (deps.findSessionProjectDir(input.sessionId) === null) return refuse2("no-transcript");
|
|
15516
|
+
try {
|
|
15517
|
+
await deps.handleInbound({
|
|
15518
|
+
accountId: input.accountId,
|
|
15519
|
+
accountDir: input.accountDir,
|
|
15520
|
+
botId: input.botId,
|
|
15521
|
+
botToken: input.entry.token,
|
|
15522
|
+
agentSlug: input.entry.agent,
|
|
15523
|
+
senderId: input.senderId,
|
|
15524
|
+
// The route admits only a private chat, where the conversation's subject IS
|
|
15525
|
+
// the sender. Passed explicitly so the gateway's key and its session id are
|
|
15526
|
+
// derived from the same value the store row already carries.
|
|
15527
|
+
conversationSubject: input.senderId,
|
|
15528
|
+
businessChatId: null,
|
|
15529
|
+
role: "public",
|
|
15530
|
+
personId: null,
|
|
15531
|
+
specialist: null,
|
|
15532
|
+
chatId: String(input.chatId),
|
|
15533
|
+
text: input.text,
|
|
15534
|
+
// No file by construction: this is text the operator typed into the send
|
|
15535
|
+
// box.
|
|
15536
|
+
media: [],
|
|
15537
|
+
source: "operator-sent",
|
|
15538
|
+
// The webhook's own closure, rebuilt with the same parameters. The gateway
|
|
15539
|
+
// stores it as this key's live delivery target, so a closure that differed
|
|
15540
|
+
// would re-route every LATER answer on this conversation through it.
|
|
15541
|
+
reply: deps.buildReply({
|
|
15542
|
+
accountId: input.accountId,
|
|
15543
|
+
sessionId: input.sessionId,
|
|
15544
|
+
channelKey: input.channelKey,
|
|
15545
|
+
chatId: input.chatId,
|
|
15546
|
+
senderId: input.senderId,
|
|
15547
|
+
botToken: input.entry.token
|
|
15548
|
+
})
|
|
15549
|
+
});
|
|
15550
|
+
} catch (err) {
|
|
15551
|
+
return refuse2(`inject-error:${err instanceof Error ? err.message : String(err)}`);
|
|
15552
|
+
}
|
|
15553
|
+
return { recorded: true, reason: "-" };
|
|
15554
|
+
}
|
|
15555
|
+
|
|
15556
|
+
// app/lib/claude-agent/specialist-roster.ts
|
|
15557
|
+
import { existsSync as existsSync19, readFileSync as readFileSync22, readdirSync as readdirSync14 } from "fs";
|
|
15558
|
+
import { join as join27 } from "path";
|
|
15559
|
+
function listSpecialistCardNames(specialistsDir) {
|
|
15560
|
+
if (!existsSync19(specialistsDir)) return [];
|
|
15561
|
+
return readdirSync14(specialistsDir).filter((f) => f.endsWith(".md")).map((f) => f.slice(0, -3)).sort();
|
|
15562
|
+
}
|
|
15563
|
+
function field(fm, name) {
|
|
15564
|
+
const m = fm.match(new RegExp(`^${name}:\\s*(.*?)\\r?$`, "m"));
|
|
15565
|
+
if (!m) return null;
|
|
15566
|
+
let value = m[1].trim();
|
|
15567
|
+
if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
|
|
15568
|
+
value = value.slice(1, -1);
|
|
15569
|
+
}
|
|
15570
|
+
return value || null;
|
|
15571
|
+
}
|
|
15572
|
+
function readSpecialistRoster(specialistsDir) {
|
|
15573
|
+
if (!existsSync19(specialistsDir)) return { specialists: [], skipped: [] };
|
|
15574
|
+
const entries2 = readdirSync14(specialistsDir);
|
|
15575
|
+
const specialists = [];
|
|
15576
|
+
const skipped = [];
|
|
15577
|
+
for (const file of entries2.sort()) {
|
|
15578
|
+
if (!file.endsWith(".md")) continue;
|
|
15579
|
+
let raw;
|
|
15580
|
+
try {
|
|
15581
|
+
raw = readFileSync22(join27(specialistsDir, file), "utf-8");
|
|
15582
|
+
} catch (err) {
|
|
15583
|
+
skipped.push({ file, reason: err instanceof Error ? err.message : String(err) });
|
|
15584
|
+
continue;
|
|
15585
|
+
}
|
|
15586
|
+
const fm = raw.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
15587
|
+
if (!fm) {
|
|
15588
|
+
skipped.push({ file, reason: "no-frontmatter" });
|
|
15589
|
+
continue;
|
|
15590
|
+
}
|
|
15591
|
+
const name = field(fm[1], "name");
|
|
15592
|
+
if (!name) {
|
|
15593
|
+
skipped.push({ file, reason: "missing-name" });
|
|
15594
|
+
continue;
|
|
15595
|
+
}
|
|
15596
|
+
const summary = field(fm[1], "summary") ?? field(fm[1], "description") ?? "";
|
|
15597
|
+
specialists.push({ name, summary });
|
|
15598
|
+
}
|
|
15599
|
+
return { specialists, skipped };
|
|
15600
|
+
}
|
|
15601
|
+
|
|
15602
|
+
// app/lib/telegram/gateway/instance.ts
|
|
15603
|
+
var instance = null;
|
|
15604
|
+
function setTelegramGateway(gw) {
|
|
15605
|
+
instance = gw;
|
|
15606
|
+
}
|
|
15607
|
+
function getTelegramGateway() {
|
|
15608
|
+
return instance;
|
|
15609
|
+
}
|
|
15610
|
+
|
|
15442
15611
|
// server/routes/telegram-reader.ts
|
|
15443
15612
|
var TAG27 = "[telegram-reader]";
|
|
15444
15613
|
var app6 = new Hono();
|
|
@@ -15454,7 +15623,7 @@ function foldPatches(rows, uploadsBase) {
|
|
|
15454
15623
|
for (const id of row.attachmentIds) {
|
|
15455
15624
|
if (already.has(id)) continue;
|
|
15456
15625
|
already.add(id);
|
|
15457
|
-
const meta = readAttachmentMeta(
|
|
15626
|
+
const meta = readAttachmentMeta(join28(uploadsBase, id));
|
|
15458
15627
|
if (meta) metas.push(meta);
|
|
15459
15628
|
}
|
|
15460
15629
|
seen.set(row.targetMessageId, already);
|
|
@@ -15576,13 +15745,13 @@ app6.get("/store-backfill", requireAdminSession, (c) => {
|
|
|
15576
15745
|
patchScanBytes = Math.max(0, buf.length - pageEnd);
|
|
15577
15746
|
} catch {
|
|
15578
15747
|
}
|
|
15579
|
-
const
|
|
15748
|
+
const records5 = messagesIn(pageRows);
|
|
15580
15749
|
const patches = foldPatches(patchRows, uploadsBaseFor(v.accountId));
|
|
15581
15750
|
console.log(
|
|
15582
|
-
`${TAG27} op=backfill channelKey=${v.channelKey} from=${from} to=${to} turns=${
|
|
15751
|
+
`${TAG27} op=backfill channelKey=${v.channelKey} from=${from} to=${to} turns=${records5.length} patched=${patches.size} patchScanBytes=${patchScanBytes} done=${from === 0}`
|
|
15583
15752
|
);
|
|
15584
15753
|
return c.json({
|
|
15585
|
-
turns:
|
|
15754
|
+
turns: records5.map((r) => toTurn(r, patches.get(r.messageId))),
|
|
15586
15755
|
from,
|
|
15587
15756
|
done: from === 0
|
|
15588
15757
|
});
|
|
@@ -15635,11 +15804,11 @@ data: ${JSON.stringify({ from: alignedFrom, fileEnd: fileEnd0 })}
|
|
|
15635
15804
|
} catch {
|
|
15636
15805
|
offset = fileEnd0;
|
|
15637
15806
|
}
|
|
15638
|
-
const
|
|
15807
|
+
const records5 = messagesIn(rows);
|
|
15639
15808
|
const patches = foldPatches(rows, uploadsBase);
|
|
15640
|
-
for (const r of
|
|
15809
|
+
for (const r of records5) send(toTurn(r, patches.get(r.messageId)), offset);
|
|
15641
15810
|
console.log(
|
|
15642
|
-
`${TAG27} op=open channelKey=${channelKey} messages=${
|
|
15811
|
+
`${TAG27} op=open channelKey=${channelKey} messages=${records5.length} fileBytes=${fileEnd0} alignedFrom=${alignedFrom} aligned=${aligned} source=${alignedFrom > 0 ? "windowed" : "full"}`
|
|
15643
15812
|
);
|
|
15644
15813
|
}
|
|
15645
15814
|
const drain = () => {
|
|
@@ -15719,6 +15888,43 @@ data: ${JSON.stringify({
|
|
|
15719
15888
|
});
|
|
15720
15889
|
});
|
|
15721
15890
|
var MANUAL_TAG2 = "[telegram-manual]";
|
|
15891
|
+
function manualSendContextDeps() {
|
|
15892
|
+
return {
|
|
15893
|
+
// The same definition the webhook applies, from the same module: an agent the
|
|
15894
|
+
// operator switched off must not be resurrected by a manual send.
|
|
15895
|
+
entryActive: (entry3, accountDir, botId) => entryActive(entry3, accountDir, botId, {
|
|
15896
|
+
isActiveAgentSlug,
|
|
15897
|
+
specialistCards: (dir) => listSpecialistCardNames(dir),
|
|
15898
|
+
log: (line) => console.error(line)
|
|
15899
|
+
}),
|
|
15900
|
+
newestInboundTelegramDate,
|
|
15901
|
+
findSessionProjectDir,
|
|
15902
|
+
handleInbound: async (inbound) => {
|
|
15903
|
+
const gateway = getTelegramGateway();
|
|
15904
|
+
if (!gateway) throw new Error("gateway-not-ready");
|
|
15905
|
+
await gateway.handleInbound(inbound);
|
|
15906
|
+
},
|
|
15907
|
+
// One builder, shared with the webhook and the inject door, so no two doors
|
|
15908
|
+
// can disagree about which conversation an answer's row files under.
|
|
15909
|
+
buildReply: ({ accountId, sessionId, channelKey, chatId, senderId, botToken }) => buildTelegramReplyClosure({
|
|
15910
|
+
accountId,
|
|
15911
|
+
channelKey,
|
|
15912
|
+
sessionId,
|
|
15913
|
+
senderId,
|
|
15914
|
+
chatId,
|
|
15915
|
+
// The hook refuses every non-public entry above, so this is the only
|
|
15916
|
+
// scope reachable here.
|
|
15917
|
+
scope: "public",
|
|
15918
|
+
botToken,
|
|
15919
|
+
send: sendTelegramText,
|
|
15920
|
+
append: appendMessage2,
|
|
15921
|
+
log: (line) => console.error(line),
|
|
15922
|
+
now: () => /* @__PURE__ */ new Date()
|
|
15923
|
+
}),
|
|
15924
|
+
log: (line) => console.error(line),
|
|
15925
|
+
now: () => Date.now()
|
|
15926
|
+
};
|
|
15927
|
+
}
|
|
15722
15928
|
app6.post("/send", requireAdminSession, async (c) => {
|
|
15723
15929
|
const sendId = process.hrtime.bigint().toString(36).slice(-8);
|
|
15724
15930
|
const t0 = Date.now();
|
|
@@ -15816,6 +16022,25 @@ app6.post("/send", requireAdminSession, async (c) => {
|
|
|
15816
16022
|
console.error(
|
|
15817
16023
|
`${MANUAL_TAG2} op=recorded sendId=${sendId} records=${after.length} reread=${reread}`
|
|
15818
16024
|
);
|
|
16025
|
+
const contextSessionId = telegramAdminSessionId(resolution.accountId, parsed.senderId, parsed.botId);
|
|
16026
|
+
noteManualSent(channelKey, Date.now());
|
|
16027
|
+
const ctx = await recordManualSendContext(
|
|
16028
|
+
{
|
|
16029
|
+
accountId: resolution.accountId,
|
|
16030
|
+
accountDir: resolution.accountDir,
|
|
16031
|
+
entry: resolution.entry,
|
|
16032
|
+
botId: parsed.botId,
|
|
16033
|
+
senderId: parsed.senderId,
|
|
16034
|
+
chatId,
|
|
16035
|
+
channelKey,
|
|
16036
|
+
text,
|
|
16037
|
+
sessionId: contextSessionId
|
|
16038
|
+
},
|
|
16039
|
+
manualSendContextDeps()
|
|
16040
|
+
);
|
|
16041
|
+
console.error(
|
|
16042
|
+
`${MANUAL_TAG2} op=context-recorded sendId=${sendId} chatId=${chatId} sessionId=${contextSessionId} suppressed=${ctx.recorded ? "yes" : "no"} reason=${ctx.reason}`
|
|
16043
|
+
);
|
|
15819
16044
|
exit("delivered");
|
|
15820
16045
|
return c.json({ ok: true, recorded: reread }, 200);
|
|
15821
16046
|
});
|
|
@@ -15838,10 +16063,10 @@ function collectTelegramStoreCensus() {
|
|
|
15838
16063
|
const summaries = readConversationSummaries2(accountId);
|
|
15839
16064
|
for (const channelKey of summaries.keys()) {
|
|
15840
16065
|
out.conversations += 1;
|
|
15841
|
-
const
|
|
15842
|
-
if (
|
|
15843
|
-
out.records +=
|
|
15844
|
-
for (const r of
|
|
16066
|
+
const records5 = readConversation2(accountId, channelKey);
|
|
16067
|
+
if (records5.length > 0) out.served += 1;
|
|
16068
|
+
out.records += records5.length;
|
|
16069
|
+
for (const r of records5) {
|
|
15845
16070
|
if (r.origin === "inbound") out.inbound += 1;
|
|
15846
16071
|
else if (r.origin === "agent") out.agent += 1;
|
|
15847
16072
|
else if (r.origin === "operator-manual") out.operatorManual += 1;
|
|
@@ -15860,8 +16085,8 @@ function runTelegramStoreCensus() {
|
|
|
15860
16085
|
|
|
15861
16086
|
// app/lib/telegram/reach-census.ts
|
|
15862
16087
|
var import_dist4 = __toESM(require_dist2(), 1);
|
|
15863
|
-
import { existsSync as
|
|
15864
|
-
import { join as
|
|
16088
|
+
import { existsSync as existsSync20 } from "fs";
|
|
16089
|
+
import { join as join29 } from "path";
|
|
15865
16090
|
function collectTelegramReachCensus(accounts) {
|
|
15866
16091
|
const out = {
|
|
15867
16092
|
accounts: accounts.length,
|
|
@@ -15871,7 +16096,7 @@ function collectTelegramReachCensus(accounts) {
|
|
|
15871
16096
|
};
|
|
15872
16097
|
for (const account of accounts) {
|
|
15873
16098
|
const reach = (0, import_dist4.collectTelegramReach)({
|
|
15874
|
-
storeDir:
|
|
16099
|
+
storeDir: join29(STORE_ROOT2(), account.accountId),
|
|
15875
16100
|
bots: account.bots
|
|
15876
16101
|
});
|
|
15877
16102
|
for (const bot of reach.bots) {
|
|
@@ -15887,7 +16112,7 @@ function runTelegramReachCensus(accounts) {
|
|
|
15887
16112
|
const c = collectTelegramReachCensus(accounts);
|
|
15888
16113
|
const root = STORE_ROOT2();
|
|
15889
16114
|
console.error(
|
|
15890
|
-
`[telegram-reach-census] accounts=${c.accounts} bots=${c.bots} chatsKnown=${c.chatsKnown} botsWithNoChats=${c.botsWithNoChats} storeRoot=${root} exists=${
|
|
16115
|
+
`[telegram-reach-census] accounts=${c.accounts} bots=${c.bots} chatsKnown=${c.chatsKnown} botsWithNoChats=${c.botsWithNoChats} storeRoot=${root} exists=${existsSync20(root)}`
|
|
15891
16116
|
);
|
|
15892
16117
|
return c;
|
|
15893
16118
|
}
|
|
@@ -15925,7 +16150,7 @@ function runTelegramCheckoutCensus(bots, now) {
|
|
|
15925
16150
|
}
|
|
15926
16151
|
|
|
15927
16152
|
// app/lib/telegram/media-census.ts
|
|
15928
|
-
import { join as
|
|
16153
|
+
import { join as join30, resolve as resolve20 } from "path";
|
|
15929
16154
|
function idsByTarget(rows) {
|
|
15930
16155
|
const out = /* @__PURE__ */ new Map();
|
|
15931
16156
|
for (const row of rows) {
|
|
@@ -16006,8 +16231,8 @@ function readWaOperatorTurns() {
|
|
|
16006
16231
|
}
|
|
16007
16232
|
|
|
16008
16233
|
// server/routes/session-reader.ts
|
|
16009
|
-
import { readFileSync as
|
|
16010
|
-
import { isAbsolute as isAbsolute2, join as
|
|
16234
|
+
import { readFileSync as readFileSync23, watch as watch4, statSync as statSync15, existsSync as existsSync21, readdirSync as readdirSync15, realpathSync as realpathSync5 } from "fs";
|
|
16235
|
+
import { isAbsolute as isAbsolute2, join as join31, relative as relative3, resolve as resolve21, sep as sep5 } from "path";
|
|
16011
16236
|
|
|
16012
16237
|
// server/routes/admin/manager-client.ts
|
|
16013
16238
|
var SESSION_ID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
@@ -16023,10 +16248,10 @@ function managerBase(tag) {
|
|
|
16023
16248
|
function pickActivity(entries2, grown, nowMs, concurrencyWindowMs) {
|
|
16024
16249
|
const candidates = entries2.filter((e) => grown.has(e.hex));
|
|
16025
16250
|
if (candidates.length === 0) return null;
|
|
16026
|
-
let
|
|
16027
|
-
for (const e of candidates) if (e.mtimeMs >
|
|
16251
|
+
let newest2 = candidates[0];
|
|
16252
|
+
for (const e of candidates) if (e.mtimeMs > newest2.mtimeMs) newest2 = e;
|
|
16028
16253
|
const count = candidates.filter((e) => nowMs - e.mtimeMs < concurrencyWindowMs).length;
|
|
16029
|
-
return { hex:
|
|
16254
|
+
return { hex: newest2.hex, lastEmitAt: newest2.mtimeMs, count };
|
|
16030
16255
|
}
|
|
16031
16256
|
|
|
16032
16257
|
// server/routes/session-reader.ts
|
|
@@ -16112,7 +16337,7 @@ function openTaskKey(turns) {
|
|
|
16112
16337
|
}
|
|
16113
16338
|
function readSubagentMeta(dir, hex) {
|
|
16114
16339
|
try {
|
|
16115
|
-
const m = JSON.parse(
|
|
16340
|
+
const m = JSON.parse(readFileSync23(join31(dir, `agent-${hex}.meta.json`), "utf8"));
|
|
16116
16341
|
if (typeof m.agentType === "string" && typeof m.description === "string" && typeof m.toolUseId === "string") {
|
|
16117
16342
|
return { agentType: m.agentType, description: m.description, toolUseId: m.toolUseId };
|
|
16118
16343
|
}
|
|
@@ -16135,7 +16360,7 @@ function runActivityTick(c) {
|
|
|
16135
16360
|
c.parentGrewThisTick = false;
|
|
16136
16361
|
let names = [];
|
|
16137
16362
|
try {
|
|
16138
|
-
names =
|
|
16363
|
+
names = readdirSync15(c.subagentsDir).filter((n) => AGENT_JSONL_RE.test(n));
|
|
16139
16364
|
} catch {
|
|
16140
16365
|
}
|
|
16141
16366
|
const entries2 = [];
|
|
@@ -16144,7 +16369,7 @@ function runActivityTick(c) {
|
|
|
16144
16369
|
let size = 0;
|
|
16145
16370
|
let mtimeMs = 0;
|
|
16146
16371
|
try {
|
|
16147
|
-
const st = statSync15(
|
|
16372
|
+
const st = statSync15(join31(c.subagentsDir, name));
|
|
16148
16373
|
size = st.size;
|
|
16149
16374
|
mtimeMs = st.mtimeMs;
|
|
16150
16375
|
} catch {
|
|
@@ -16189,11 +16414,11 @@ app7.get("/stream", requireAdminSession, (c) => {
|
|
|
16189
16414
|
const sessionId = c.req.query("sessionId") ?? "";
|
|
16190
16415
|
const projectDir = c.req.query("projectDir") ?? "";
|
|
16191
16416
|
const cfg = claudeConfigDir();
|
|
16192
|
-
const projectsRoot = cfg ? resolve21(
|
|
16417
|
+
const projectsRoot = cfg ? resolve21(join31(cfg, "projects")) : null;
|
|
16193
16418
|
if (!cfg || !projectsRoot || !SESSION_ID_RE2.test(sessionId)) {
|
|
16194
16419
|
return c.json({ error: "bad session reference" }, 400);
|
|
16195
16420
|
}
|
|
16196
|
-
const jsonlPath = resolve21(
|
|
16421
|
+
const jsonlPath = resolve21(join31(projectDir, `${sessionId}.jsonl`));
|
|
16197
16422
|
if (!jsonlPath.startsWith(projectsRoot + sep5)) {
|
|
16198
16423
|
return c.json({ error: "bad session reference" }, 400);
|
|
16199
16424
|
}
|
|
@@ -16221,9 +16446,9 @@ data: ${JSON.stringify(turn)}
|
|
|
16221
16446
|
let offset = resumeOffset(lastEventId, fileEnd0);
|
|
16222
16447
|
console.log(`[wa-stream] op=open conn=${connId} sessionId=${sessionId} channel=reader resume=${offset}`);
|
|
16223
16448
|
const sessionKey = c.req.query("session_key") ?? "";
|
|
16224
|
-
const subagentsDir = resolve21(
|
|
16449
|
+
const subagentsDir = resolve21(join31(projectDir, sessionId, "subagents"));
|
|
16225
16450
|
console.log(
|
|
16226
|
-
`[webchat-activity] op=watch-subagents key=${sessionKey} dir=${subagentsDir} exists=${
|
|
16451
|
+
`[webchat-activity] op=watch-subagents key=${sessionKey} dir=${subagentsDir} exists=${existsSync21(subagentsDir)}`
|
|
16227
16452
|
);
|
|
16228
16453
|
const actx = makeActivityCtx({
|
|
16229
16454
|
subagentsDir,
|
|
@@ -16374,11 +16599,11 @@ app7.get("/backfill", requireAdminSession, (c) => {
|
|
|
16374
16599
|
const beforeRaw = c.req.query("before") ?? "";
|
|
16375
16600
|
const before = Number(beforeRaw);
|
|
16376
16601
|
const cfg = claudeConfigDir();
|
|
16377
|
-
const projectsRoot = cfg ? resolve21(
|
|
16602
|
+
const projectsRoot = cfg ? resolve21(join31(cfg, "projects")) : null;
|
|
16378
16603
|
if (!cfg || !projectsRoot || !SESSION_ID_RE2.test(sessionId) || beforeRaw === "" || !Number.isFinite(before) || before < 0) {
|
|
16379
16604
|
return c.json({ error: "bad session reference" }, 400);
|
|
16380
16605
|
}
|
|
16381
|
-
const jsonlPath = resolve21(
|
|
16606
|
+
const jsonlPath = resolve21(join31(projectDir, `${sessionId}.jsonl`));
|
|
16382
16607
|
if (!jsonlPath.startsWith(projectsRoot + sep5)) {
|
|
16383
16608
|
return c.json({ error: "bad session reference" }, 400);
|
|
16384
16609
|
}
|
|
@@ -16430,10 +16655,10 @@ app7.get("/directives", requireAdminSession, (c) => {
|
|
|
16430
16655
|
const sessionId = c.req.query("sessionId") ?? "";
|
|
16431
16656
|
if (!SESSION_ID_RE2.test(sessionId)) return c.json({ error: "bad session reference" }, 400);
|
|
16432
16657
|
const dir = directiveStoreDir(sessionId);
|
|
16433
|
-
if (!dir || !
|
|
16658
|
+
if (!dir || !existsSync21(dir)) return c.json({ entries: [] });
|
|
16434
16659
|
let names;
|
|
16435
16660
|
try {
|
|
16436
|
-
names =
|
|
16661
|
+
names = readdirSync15(dir).filter((n) => DIRECTIVE_NAME_RE.test(n));
|
|
16437
16662
|
} catch {
|
|
16438
16663
|
return c.json({ entries: [] });
|
|
16439
16664
|
}
|
|
@@ -16443,7 +16668,7 @@ app7.get("/directives", requireAdminSession, (c) => {
|
|
|
16443
16668
|
const pid = Number(pidPart);
|
|
16444
16669
|
let len = 0;
|
|
16445
16670
|
try {
|
|
16446
|
-
len = statSync15(
|
|
16671
|
+
len = statSync15(join31(dir, name)).size;
|
|
16447
16672
|
} catch {
|
|
16448
16673
|
}
|
|
16449
16674
|
return { name, secs, pid, ts: Number.isFinite(secs) ? new Date(secs * 1e3).toISOString() : null, len };
|
|
@@ -16458,11 +16683,11 @@ app7.get("/directive", requireAdminSession, (c) => {
|
|
|
16458
16683
|
}
|
|
16459
16684
|
const dir = directiveStoreDir(sessionId);
|
|
16460
16685
|
if (!dir) return c.json({ error: "no account" }, 404);
|
|
16461
|
-
const path = resolve21(
|
|
16686
|
+
const path = resolve21(join31(dir, name));
|
|
16462
16687
|
if (!path.startsWith(dir + sep5)) return c.json({ error: "bad reference" }, 400);
|
|
16463
16688
|
let body;
|
|
16464
16689
|
try {
|
|
16465
|
-
body =
|
|
16690
|
+
body = readFileSync23(path, "utf8");
|
|
16466
16691
|
} catch {
|
|
16467
16692
|
return c.json({ error: "not found" }, 404);
|
|
16468
16693
|
}
|
|
@@ -16471,8 +16696,8 @@ app7.get("/directive", requireAdminSession, (c) => {
|
|
|
16471
16696
|
var session_reader_default = app7;
|
|
16472
16697
|
|
|
16473
16698
|
// server/routes/operator-conversations.ts
|
|
16474
|
-
import { readFileSync as
|
|
16475
|
-
import { basename as basename9, dirname as dirname9, join as
|
|
16699
|
+
import { readFileSync as readFileSync24 } from "fs";
|
|
16700
|
+
import { basename as basename9, dirname as dirname9, join as join32 } from "path";
|
|
16476
16701
|
|
|
16477
16702
|
// app/lib/reader/operator-conversations.ts
|
|
16478
16703
|
function operatorConvName(row) {
|
|
@@ -16560,7 +16785,7 @@ app8.get("/conversations", requireAdminSession, async (c) => {
|
|
|
16560
16785
|
}
|
|
16561
16786
|
const cfg = claudeConfigDir();
|
|
16562
16787
|
if (!cfg) return c.json({ conversations: [] });
|
|
16563
|
-
const projectsRoot =
|
|
16788
|
+
const projectsRoot = join32(cfg, "projects");
|
|
16564
16789
|
const userTitles = loadUserTitles(ACCOUNTS_DIR ?? null);
|
|
16565
16790
|
const rows = [];
|
|
16566
16791
|
let sessionRowsExcludedUntagged = 0;
|
|
@@ -16578,7 +16803,7 @@ app8.get("/conversations", requireAdminSession, async (c) => {
|
|
|
16578
16803
|
enumeratedCount += 1;
|
|
16579
16804
|
const sessionId = basename9(path).replace(/\.jsonl$/, "");
|
|
16580
16805
|
const projectDir = dirname9(path);
|
|
16581
|
-
const meta = readSidecarMeta(
|
|
16806
|
+
const meta = readSidecarMeta(join32(projectDir, `${sessionId}.meta.json`));
|
|
16582
16807
|
if (!isReaderChannelSession(meta.role, meta.channel)) continue;
|
|
16583
16808
|
if (multiAccount) {
|
|
16584
16809
|
if (meta.accountId === null) {
|
|
@@ -16590,7 +16815,7 @@ app8.get("/conversations", requireAdminSession, async (c) => {
|
|
|
16590
16815
|
let body = "";
|
|
16591
16816
|
let bodyRead = false;
|
|
16592
16817
|
try {
|
|
16593
|
-
body =
|
|
16818
|
+
body = readFileSync24(path, "utf8");
|
|
16594
16819
|
bodyRead = true;
|
|
16595
16820
|
bodyReadCount += 1;
|
|
16596
16821
|
} catch (err) {
|
|
@@ -16766,7 +16991,7 @@ app8.get("/conversations-all", requireAdminSession, async (c) => {
|
|
|
16766
16991
|
const { value, state } = await getOrCompute("conversations-all", houseId, async () => {
|
|
16767
16992
|
const cfg = claudeConfigDir();
|
|
16768
16993
|
if (!cfg) return { conversations: [] };
|
|
16769
|
-
const projectsRoot =
|
|
16994
|
+
const projectsRoot = join32(cfg, "projects");
|
|
16770
16995
|
const userTitles = loadUserTitles(ACCOUNTS_DIR ?? null);
|
|
16771
16996
|
const validAccounts = listValidAccounts();
|
|
16772
16997
|
const validIds = new Set(validAccounts.map((a) => a.accountId));
|
|
@@ -16786,7 +17011,7 @@ app8.get("/conversations-all", requireAdminSession, async (c) => {
|
|
|
16786
17011
|
enumeratedCount += 1;
|
|
16787
17012
|
const sessionId = basename9(path).replace(/\.jsonl$/, "");
|
|
16788
17013
|
const projectDir = dirname9(path);
|
|
16789
|
-
const meta = readSidecarMeta(
|
|
17014
|
+
const meta = readSidecarMeta(join32(projectDir, `${sessionId}.meta.json`));
|
|
16790
17015
|
if (!isReaderChannelSession(meta.role, meta.channel)) continue;
|
|
16791
17016
|
if (meta.accountId === null) {
|
|
16792
17017
|
untaggedCount += 1;
|
|
@@ -16797,7 +17022,7 @@ app8.get("/conversations-all", requireAdminSession, async (c) => {
|
|
|
16797
17022
|
let body = "";
|
|
16798
17023
|
let bodyRead = false;
|
|
16799
17024
|
try {
|
|
16800
|
-
body =
|
|
17025
|
+
body = readFileSync24(path, "utf8");
|
|
16801
17026
|
bodyRead = true;
|
|
16802
17027
|
bodyReadCount += 1;
|
|
16803
17028
|
} catch (err) {
|
|
@@ -16922,8 +17147,8 @@ app8.get("/conversations-all", requireAdminSession, async (c) => {
|
|
|
16922
17147
|
var operator_conversations_default = app8;
|
|
16923
17148
|
|
|
16924
17149
|
// server/routes/public-reader.ts
|
|
16925
|
-
import { statSync as statSync17, watch as watch6, readFileSync as
|
|
16926
|
-
import { basename as basename10, dirname as dirname10, join as
|
|
17150
|
+
import { statSync as statSync17, watch as watch6, readFileSync as readFileSync25, readdirSync as readdirSync17 } from "fs";
|
|
17151
|
+
import { basename as basename10, dirname as dirname10, join as join33, resolve as resolve23, sep as sep7 } from "path";
|
|
16927
17152
|
|
|
16928
17153
|
// app/lib/reader/delivered-kinds.ts
|
|
16929
17154
|
var PUBLIC_DELIVERED_KINDS = /* @__PURE__ */ new Set([
|
|
@@ -17012,10 +17237,10 @@ function enumeratePublicRows() {
|
|
|
17012
17237
|
const cfg = claudeConfigDir();
|
|
17013
17238
|
if (!cfg) return [];
|
|
17014
17239
|
const rows = [];
|
|
17015
|
-
for (const { path } of enumerateJsonls(
|
|
17240
|
+
for (const { path } of enumerateJsonls(join33(cfg, "projects"))) {
|
|
17016
17241
|
const sessionId = basename10(path).replace(/\.jsonl$/, "");
|
|
17017
17242
|
const projectDir = dirname10(path);
|
|
17018
|
-
const meta = readSidecarMeta(
|
|
17243
|
+
const meta = readSidecarMeta(join33(projectDir, `${sessionId}.meta.json`));
|
|
17019
17244
|
rows.push({
|
|
17020
17245
|
sessionId,
|
|
17021
17246
|
projectDir,
|
|
@@ -17082,15 +17307,15 @@ app9.get("/backfill", (c) => {
|
|
|
17082
17307
|
const beforeRaw = c.req.query("before") ?? "";
|
|
17083
17308
|
const before = Number(beforeRaw);
|
|
17084
17309
|
const cfg = claudeConfigDir();
|
|
17085
|
-
const projectsRoot = cfg ? resolve23(
|
|
17310
|
+
const projectsRoot = cfg ? resolve23(join33(cfg, "projects")) : null;
|
|
17086
17311
|
if (!cfg || !projectsRoot || !SESSION_ID_RE2.test(sessionId) || beforeRaw === "" || !Number.isFinite(before) || before < 0) {
|
|
17087
17312
|
return c.json({ error: "bad session reference" }, 400);
|
|
17088
17313
|
}
|
|
17089
|
-
const jsonlPath = resolve23(
|
|
17314
|
+
const jsonlPath = resolve23(join33(projectDir, `${sessionId}.jsonl`));
|
|
17090
17315
|
if (!jsonlPath.startsWith(projectsRoot + sep7)) {
|
|
17091
17316
|
return c.json({ error: "bad session reference" }, 400);
|
|
17092
17317
|
}
|
|
17093
|
-
const meta = readSidecarMeta(
|
|
17318
|
+
const meta = readSidecarMeta(join33(projectDir, `${sessionId}.meta.json`));
|
|
17094
17319
|
const isPublicWebchat = meta.role === "public" && meta.channel === "webchat";
|
|
17095
17320
|
const owns = visitor.kind === "person" ? meta.personId === visitor.personId : meta.personId === null && meta.visitorId === visitor.visitorId;
|
|
17096
17321
|
if (!(isPublicWebchat && owns)) {
|
|
@@ -17149,15 +17374,15 @@ app9.get("/stream", (c) => {
|
|
|
17149
17374
|
const sessionId = c.req.query("sessionId") ?? "";
|
|
17150
17375
|
const projectDir = c.req.query("projectDir") ?? "";
|
|
17151
17376
|
const cfg = claudeConfigDir();
|
|
17152
|
-
const projectsRoot = cfg ? resolve23(
|
|
17377
|
+
const projectsRoot = cfg ? resolve23(join33(cfg, "projects")) : null;
|
|
17153
17378
|
if (!cfg || !projectsRoot || !SESSION_ID_RE2.test(sessionId)) {
|
|
17154
17379
|
return c.json({ error: "bad session reference" }, 400);
|
|
17155
17380
|
}
|
|
17156
|
-
const jsonlPath = resolve23(
|
|
17381
|
+
const jsonlPath = resolve23(join33(projectDir, `${sessionId}.jsonl`));
|
|
17157
17382
|
if (!jsonlPath.startsWith(projectsRoot + sep7)) {
|
|
17158
17383
|
return c.json({ error: "bad session reference" }, 400);
|
|
17159
17384
|
}
|
|
17160
|
-
const meta = readSidecarMeta(
|
|
17385
|
+
const meta = readSidecarMeta(join33(projectDir, `${sessionId}.meta.json`));
|
|
17161
17386
|
const isPublicWebchat = meta.role === "public" && meta.channel === "webchat";
|
|
17162
17387
|
const owns = visitor.kind === "person" ? meta.personId === visitor.personId : meta.personId === null && meta.visitorId === visitor.visitorId;
|
|
17163
17388
|
if (!(isPublicWebchat && owns)) {
|
|
@@ -17301,9 +17526,9 @@ app9.get("/attachment/:attachmentId", (c) => {
|
|
|
17301
17526
|
let dataFile;
|
|
17302
17527
|
let buffer;
|
|
17303
17528
|
try {
|
|
17304
|
-
dataFile =
|
|
17529
|
+
dataFile = readdirSync17(dir).find((f) => !f.endsWith(".meta.json") && !f.endsWith(EXTRACTED_TEXT_SUFFIX));
|
|
17305
17530
|
if (!dataFile) throw new Error("no data file");
|
|
17306
|
-
buffer =
|
|
17531
|
+
buffer = readFileSync25(resolve23(dir, dataFile));
|
|
17307
17532
|
} catch {
|
|
17308
17533
|
console.error(`${ATT_TAG} op=denied session=${ses} att=${at} reason=not-found`);
|
|
17309
17534
|
return new Response("Not found", { status: 404 });
|
|
@@ -17325,20 +17550,20 @@ var public_reader_default = app9;
|
|
|
17325
17550
|
|
|
17326
17551
|
// server/routes/webchat.ts
|
|
17327
17552
|
import { basename as basename11, dirname as dirname11 } from "path";
|
|
17328
|
-
import { join as
|
|
17329
|
-
import { existsSync as
|
|
17553
|
+
import { join as join36 } from "path";
|
|
17554
|
+
import { existsSync as existsSync24, readdirSync as readdirSync19, readFileSync as readFileSync28, renameSync as renameSync4, statSync as statSync18, writeFileSync as writeFileSync11 } from "fs";
|
|
17330
17555
|
|
|
17331
17556
|
// server/canonical-webchat-override.ts
|
|
17332
|
-
import { readFileSync as
|
|
17333
|
-
import { join as
|
|
17557
|
+
import { readFileSync as readFileSync26, writeFileSync as writeFileSync9, renameSync as renameSync2 } from "fs";
|
|
17558
|
+
import { join as join34 } from "path";
|
|
17334
17559
|
var FILE = "canonical-webchat-session.json";
|
|
17335
17560
|
var UUID2 = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
|
|
17336
17561
|
function canonicalOverridePath(accountDir) {
|
|
17337
|
-
return
|
|
17562
|
+
return join34(accountDir, FILE);
|
|
17338
17563
|
}
|
|
17339
17564
|
function readRaw(accountDir) {
|
|
17340
17565
|
try {
|
|
17341
|
-
return JSON.parse(
|
|
17566
|
+
return JSON.parse(readFileSync26(canonicalOverridePath(accountDir), "utf8"));
|
|
17342
17567
|
} catch {
|
|
17343
17568
|
return null;
|
|
17344
17569
|
}
|
|
@@ -17451,8 +17676,8 @@ function isNewSessionEffortLevel(value) {
|
|
|
17451
17676
|
}
|
|
17452
17677
|
|
|
17453
17678
|
// ../services/claude-session-manager/src/sidecar-store.ts
|
|
17454
|
-
import { existsSync as
|
|
17455
|
-
import { join as
|
|
17679
|
+
import { existsSync as existsSync23, mkdirSync as mkdirSync4, readdirSync as readdirSync18, readFileSync as readFileSync27, renameSync as renameSync3, unlinkSync as unlinkSync2, writeFileSync as writeFileSync10 } from "fs";
|
|
17680
|
+
import { join as join35 } from "path";
|
|
17456
17681
|
function escapeRegExp(s) {
|
|
17457
17682
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
17458
17683
|
}
|
|
@@ -17460,7 +17685,7 @@ function createSidecarStore(config) {
|
|
|
17460
17685
|
const { suffix, validate: validate3 } = config;
|
|
17461
17686
|
const suffixRe = new RegExp(`${escapeRegExp(suffix)}$`);
|
|
17462
17687
|
function pathFor(sessionsDir, id) {
|
|
17463
|
-
return
|
|
17688
|
+
return join35(sessionsDir, `${id}${suffix}`);
|
|
17464
17689
|
}
|
|
17465
17690
|
function write(sessionsDir, id, record) {
|
|
17466
17691
|
mkdirSync4(sessionsDir, { recursive: true });
|
|
@@ -17472,7 +17697,7 @@ function createSidecarStore(config) {
|
|
|
17472
17697
|
return { ok: true };
|
|
17473
17698
|
} catch (error) {
|
|
17474
17699
|
try {
|
|
17475
|
-
if (
|
|
17700
|
+
if (existsSync23(tmp)) unlinkSync2(tmp);
|
|
17476
17701
|
} catch {
|
|
17477
17702
|
}
|
|
17478
17703
|
return { ok: false, error };
|
|
@@ -17481,7 +17706,7 @@ function createSidecarStore(config) {
|
|
|
17481
17706
|
function readFileAt(path) {
|
|
17482
17707
|
let raw;
|
|
17483
17708
|
try {
|
|
17484
|
-
raw =
|
|
17709
|
+
raw = readFileSync27(path, "utf8");
|
|
17485
17710
|
} catch {
|
|
17486
17711
|
return null;
|
|
17487
17712
|
}
|
|
@@ -17497,17 +17722,17 @@ function createSidecarStore(config) {
|
|
|
17497
17722
|
function readAll3(sessionsDir, onSkip) {
|
|
17498
17723
|
let names;
|
|
17499
17724
|
try {
|
|
17500
|
-
names =
|
|
17725
|
+
names = readdirSync18(sessionsDir, { withFileTypes: true }).filter((entry3) => entry3.isFile()).map((entry3) => entry3.name);
|
|
17501
17726
|
} catch {
|
|
17502
17727
|
return [];
|
|
17503
17728
|
}
|
|
17504
17729
|
const out = [];
|
|
17505
17730
|
for (const name of names) {
|
|
17506
17731
|
if (!suffixRe.test(name)) continue;
|
|
17507
|
-
const path =
|
|
17732
|
+
const path = join35(sessionsDir, name);
|
|
17508
17733
|
let raw;
|
|
17509
17734
|
try {
|
|
17510
|
-
raw =
|
|
17735
|
+
raw = readFileSync27(path, "utf8");
|
|
17511
17736
|
} catch {
|
|
17512
17737
|
onSkip?.(name, "unreadable");
|
|
17513
17738
|
continue;
|
|
@@ -17528,7 +17753,7 @@ function createSidecarStore(config) {
|
|
|
17528
17753
|
function clear(sessionsDir, id) {
|
|
17529
17754
|
const path = pathFor(sessionsDir, id);
|
|
17530
17755
|
try {
|
|
17531
|
-
if (
|
|
17756
|
+
if (existsSync23(path)) {
|
|
17532
17757
|
unlinkSync2(path);
|
|
17533
17758
|
return { ok: true, removed: true };
|
|
17534
17759
|
}
|
|
@@ -17580,7 +17805,7 @@ var UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9
|
|
|
17580
17805
|
function locateSession(sessionId) {
|
|
17581
17806
|
const dir = findSessionProjectDir(sessionId);
|
|
17582
17807
|
if (!dir) return { projectDir: null, channel: null, accountId: null };
|
|
17583
|
-
const meta = readSidecarMeta(
|
|
17808
|
+
const meta = readSidecarMeta(join36(dir, `${sessionId}.meta.json`));
|
|
17584
17809
|
return { projectDir: dir, channel: meta.channel, accountId: meta.accountId };
|
|
17585
17810
|
}
|
|
17586
17811
|
function resolveQuoted(sessionId, quotedUuid, sendId) {
|
|
@@ -17598,7 +17823,7 @@ function resolveQuoted(sessionId, quotedUuid, sendId) {
|
|
|
17598
17823
|
let line;
|
|
17599
17824
|
try {
|
|
17600
17825
|
const needle = `"uuid":"${quotedUuid}"`;
|
|
17601
|
-
line =
|
|
17826
|
+
line = readFileSync28(join36(projectDir, `${sessionId}.jsonl`), "utf8").split("\n").find((l) => l.includes(needle));
|
|
17602
17827
|
} catch {
|
|
17603
17828
|
log2(false, 0);
|
|
17604
17829
|
return void 0;
|
|
@@ -17615,16 +17840,16 @@ function resolveQuoted(sessionId, quotedUuid, sendId) {
|
|
|
17615
17840
|
function locateSidecar(sessionId) {
|
|
17616
17841
|
const cfg = claudeConfigDir();
|
|
17617
17842
|
if (!cfg) return null;
|
|
17618
|
-
const projectsRoot =
|
|
17843
|
+
const projectsRoot = join36(cfg, "projects");
|
|
17619
17844
|
let slugs;
|
|
17620
17845
|
try {
|
|
17621
|
-
slugs =
|
|
17846
|
+
slugs = readdirSync19(projectsRoot, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
17622
17847
|
} catch {
|
|
17623
17848
|
return null;
|
|
17624
17849
|
}
|
|
17625
17850
|
for (const slug of slugs) {
|
|
17626
|
-
const metaPath =
|
|
17627
|
-
if (
|
|
17851
|
+
const metaPath = join36(projectsRoot, slug, `${sessionId}.meta.json`);
|
|
17852
|
+
if (existsSync24(metaPath)) return readSidecarMeta(metaPath);
|
|
17628
17853
|
}
|
|
17629
17854
|
return null;
|
|
17630
17855
|
}
|
|
@@ -17633,7 +17858,7 @@ function readTargetOwner(sessionId) {
|
|
|
17633
17858
|
if (sidecar !== null) return { found: true, owner: sidecar.adminUserId };
|
|
17634
17859
|
const { projectDir } = locateSession(sessionId);
|
|
17635
17860
|
if (projectDir !== null) {
|
|
17636
|
-
return { found: true, owner: readSidecarMeta(
|
|
17861
|
+
return { found: true, owner: readSidecarMeta(join36(projectDir, `${sessionId}.meta.json`)).adminUserId };
|
|
17637
17862
|
}
|
|
17638
17863
|
return { found: false, owner: null };
|
|
17639
17864
|
}
|
|
@@ -17641,7 +17866,7 @@ function readSourceRowMeta(sessionId) {
|
|
|
17641
17866
|
const sidecar = locateSidecar(sessionId);
|
|
17642
17867
|
if (sidecar !== null) return sidecar;
|
|
17643
17868
|
const { projectDir } = locateSession(sessionId);
|
|
17644
|
-
if (projectDir !== null) return readSidecarMeta(
|
|
17869
|
+
if (projectDir !== null) return readSidecarMeta(join36(projectDir, `${sessionId}.meta.json`));
|
|
17645
17870
|
return null;
|
|
17646
17871
|
}
|
|
17647
17872
|
function ownedByRequester(owner, requesterUserId, primaryUserId) {
|
|
@@ -17654,7 +17879,7 @@ function sessionSidecarExists(sessionId) {
|
|
|
17654
17879
|
function jsonlSizeBytes(projectDir, sessionId) {
|
|
17655
17880
|
if (projectDir === null) return null;
|
|
17656
17881
|
try {
|
|
17657
|
-
return statSync18(
|
|
17882
|
+
return statSync18(join36(projectDir, `${sessionId}.jsonl`)).size;
|
|
17658
17883
|
} catch {
|
|
17659
17884
|
return null;
|
|
17660
17885
|
}
|
|
@@ -17782,10 +18007,10 @@ function latestAdminWebchatSessionId(requesterUserId, primaryUserId, scopeAccoun
|
|
|
17782
18007
|
const cfg = claudeConfigDir();
|
|
17783
18008
|
if (!cfg) return null;
|
|
17784
18009
|
let best = null;
|
|
17785
|
-
for (const { path, isSubagent, archived } of enumerateJsonls(
|
|
18010
|
+
for (const { path, isSubagent, archived } of enumerateJsonls(join36(cfg, "projects"))) {
|
|
17786
18011
|
if (isSubagent || archived) continue;
|
|
17787
18012
|
const id = basename11(path).slice(0, -".jsonl".length);
|
|
17788
|
-
const meta = readSidecarMeta(
|
|
18013
|
+
const meta = readSidecarMeta(join36(dirname11(path), `${id}.meta.json`));
|
|
17789
18014
|
if (meta.role !== "admin" || meta.channel !== "webchat") continue;
|
|
17790
18015
|
if (multiAccount && meta.accountId !== scopeAccountId) continue;
|
|
17791
18016
|
let mtimeMs;
|
|
@@ -18145,9 +18370,9 @@ ${timeline}`;
|
|
|
18145
18370
|
console.error(`[webchat:settings] op=${op} outcome=refused value=${value} accountId=none reason=no-account-for-session`);
|
|
18146
18371
|
return c.json({ error: "account unresolved" }, 503);
|
|
18147
18372
|
}
|
|
18148
|
-
const accountJsonPath =
|
|
18373
|
+
const accountJsonPath = join36(account.accountDir, "account.json");
|
|
18149
18374
|
try {
|
|
18150
|
-
const parsed = JSON.parse(
|
|
18375
|
+
const parsed = JSON.parse(readFileSync28(accountJsonPath, "utf8"));
|
|
18151
18376
|
if (op === "model") parsed.adminModel = value;
|
|
18152
18377
|
else if (op === "effort") parsed.effort = value;
|
|
18153
18378
|
else parsed.adminPermissionMode = value;
|
|
@@ -18193,7 +18418,7 @@ ${timeline}`;
|
|
|
18193
18418
|
const cfg2 = claudeConfigDir();
|
|
18194
18419
|
if (cfg2) {
|
|
18195
18420
|
const source2 = resolveBridgeSource(
|
|
18196
|
-
|
|
18421
|
+
join36(cfg2, "sessions"),
|
|
18197
18422
|
target,
|
|
18198
18423
|
(id) => locateSession(id).projectDir !== null
|
|
18199
18424
|
);
|
|
@@ -18220,7 +18445,7 @@ ${timeline}`;
|
|
|
18220
18445
|
const cfg = claudeConfigDir();
|
|
18221
18446
|
let projectDir = null;
|
|
18222
18447
|
if (cfg) {
|
|
18223
|
-
for (const { path } of enumerateJsonls(
|
|
18448
|
+
for (const { path } of enumerateJsonls(join36(cfg, "projects"))) {
|
|
18224
18449
|
if (basename11(path) === `${sessionId}.jsonl`) {
|
|
18225
18450
|
projectDir = dirname11(path);
|
|
18226
18451
|
break;
|
|
@@ -18228,7 +18453,7 @@ ${timeline}`;
|
|
|
18228
18453
|
}
|
|
18229
18454
|
}
|
|
18230
18455
|
if (source === "latest" && requesterUserId !== null) {
|
|
18231
|
-
const owner = readSidecarMeta(
|
|
18456
|
+
const owner = readSidecarMeta(join36(projectDir ?? "", `${sessionId}.meta.json`)).adminUserId;
|
|
18232
18457
|
if (owner !== null && owner !== requesterUserId && requesterUserId !== primaryUserId) {
|
|
18233
18458
|
console.error(`[webchat:inbound] op=session-resolve-foreign key=${sessionId.slice(0, 8)} owner=${owner.slice(0, 8)} requester=${requesterUserId.slice(0, 8)}`);
|
|
18234
18459
|
}
|
|
@@ -18258,54 +18483,6 @@ ${timeline}`;
|
|
|
18258
18483
|
|
|
18259
18484
|
// server/routes/webchat-greeting.ts
|
|
18260
18485
|
import { resolve as resolve24 } from "path";
|
|
18261
|
-
|
|
18262
|
-
// app/lib/claude-agent/specialist-roster.ts
|
|
18263
|
-
import { existsSync as existsSync24, readFileSync as readFileSync28, readdirSync as readdirSync19 } from "fs";
|
|
18264
|
-
import { join as join36 } from "path";
|
|
18265
|
-
function listSpecialistCardNames(specialistsDir) {
|
|
18266
|
-
if (!existsSync24(specialistsDir)) return [];
|
|
18267
|
-
return readdirSync19(specialistsDir).filter((f) => f.endsWith(".md")).map((f) => f.slice(0, -3)).sort();
|
|
18268
|
-
}
|
|
18269
|
-
function field(fm, name) {
|
|
18270
|
-
const m = fm.match(new RegExp(`^${name}:\\s*(.*?)\\r?$`, "m"));
|
|
18271
|
-
if (!m) return null;
|
|
18272
|
-
let value = m[1].trim();
|
|
18273
|
-
if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
|
|
18274
|
-
value = value.slice(1, -1);
|
|
18275
|
-
}
|
|
18276
|
-
return value || null;
|
|
18277
|
-
}
|
|
18278
|
-
function readSpecialistRoster(specialistsDir) {
|
|
18279
|
-
if (!existsSync24(specialistsDir)) return { specialists: [], skipped: [] };
|
|
18280
|
-
const entries2 = readdirSync19(specialistsDir);
|
|
18281
|
-
const specialists = [];
|
|
18282
|
-
const skipped = [];
|
|
18283
|
-
for (const file of entries2.sort()) {
|
|
18284
|
-
if (!file.endsWith(".md")) continue;
|
|
18285
|
-
let raw;
|
|
18286
|
-
try {
|
|
18287
|
-
raw = readFileSync28(join36(specialistsDir, file), "utf-8");
|
|
18288
|
-
} catch (err) {
|
|
18289
|
-
skipped.push({ file, reason: err instanceof Error ? err.message : String(err) });
|
|
18290
|
-
continue;
|
|
18291
|
-
}
|
|
18292
|
-
const fm = raw.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
18293
|
-
if (!fm) {
|
|
18294
|
-
skipped.push({ file, reason: "no-frontmatter" });
|
|
18295
|
-
continue;
|
|
18296
|
-
}
|
|
18297
|
-
const name = field(fm[1], "name");
|
|
18298
|
-
if (!name) {
|
|
18299
|
-
skipped.push({ file, reason: "missing-name" });
|
|
18300
|
-
continue;
|
|
18301
|
-
}
|
|
18302
|
-
const summary = field(fm[1], "summary") ?? field(fm[1], "description") ?? "";
|
|
18303
|
-
specialists.push({ name, summary });
|
|
18304
|
-
}
|
|
18305
|
-
return { specialists, skipped };
|
|
18306
|
-
}
|
|
18307
|
-
|
|
18308
|
-
// server/routes/webchat-greeting.ts
|
|
18309
18486
|
var OUTSTANDING_TASK_STATUSES = ["pending", "active", "running"];
|
|
18310
18487
|
var UPCOMING_EVENT_STATUSES = ["scheduled", "due"];
|
|
18311
18488
|
var TASK_ITEMS_CAP = 5;
|
|
@@ -18563,15 +18740,6 @@ async function setManagedBotAccessSettings(managingBotToken, userId, isAccessRes
|
|
|
18563
18740
|
return r.ok ? { ok: true } : { ok: false, error: r.error };
|
|
18564
18741
|
}
|
|
18565
18742
|
|
|
18566
|
-
// app/lib/telegram/gateway/instance.ts
|
|
18567
|
-
var instance = null;
|
|
18568
|
-
function setTelegramGateway(gw) {
|
|
18569
|
-
instance = gw;
|
|
18570
|
-
}
|
|
18571
|
-
function getTelegramGateway() {
|
|
18572
|
-
return instance;
|
|
18573
|
-
}
|
|
18574
|
-
|
|
18575
18743
|
// app/lib/telegram/access-control.ts
|
|
18576
18744
|
function checkTelegramAccess(params) {
|
|
18577
18745
|
const { senderId, entry: entry3, chatId, chatType } = params;
|
|
@@ -20432,7 +20600,7 @@ function noteLocationTurn() {
|
|
|
20432
20600
|
locationTurns += 1;
|
|
20433
20601
|
}
|
|
20434
20602
|
function liveLocationCensusLine(accountsRoot, now) {
|
|
20435
|
-
let
|
|
20603
|
+
let records5 = 0;
|
|
20436
20604
|
let current = 0;
|
|
20437
20605
|
let expired = 0;
|
|
20438
20606
|
let oldestAgeMs = 0;
|
|
@@ -20441,7 +20609,7 @@ function liveLocationCensusLine(accountsRoot, now) {
|
|
|
20441
20609
|
const path = join39(accountsRoot, entry3, LIVE_LOCATION_FILE);
|
|
20442
20610
|
if (!existsSync26(path) || !statSync19(path).isFile()) continue;
|
|
20443
20611
|
for (const rec of Object.values(readAll(path))) {
|
|
20444
|
-
|
|
20612
|
+
records5 += 1;
|
|
20445
20613
|
if (isExpired(rec, now)) expired += 1;
|
|
20446
20614
|
else current += 1;
|
|
20447
20615
|
oldestAgeMs = Math.max(oldestAgeMs, now - rec.at);
|
|
@@ -20454,7 +20622,7 @@ function liveLocationCensusLine(accountsRoot, now) {
|
|
|
20454
20622
|
sharesStarted = 0;
|
|
20455
20623
|
locationTurns = 0;
|
|
20456
20624
|
const ratio = shares === 0 ? "none" : String(turns / shares);
|
|
20457
|
-
return `${LIVE_LOCATION_CENSUS_TAG} records=${
|
|
20625
|
+
return `${LIVE_LOCATION_CENSUS_TAG} records=${records5} current=${current} expired=${expired} oldestAgeMs=${oldestAgeMs} shares=${shares} turnsPerShare=${ratio}`;
|
|
20458
20626
|
}
|
|
20459
20627
|
|
|
20460
20628
|
// app/lib/telegram/business-connection.ts
|
|
@@ -22950,7 +23118,7 @@ var MAX_URL_LEN = 500;
|
|
|
22950
23118
|
var MAX_UA_LEN = 400;
|
|
22951
23119
|
var MAX_FILE_LEN = 300;
|
|
22952
23120
|
var RATE_LIMIT_PER_MIN = 20;
|
|
22953
|
-
var
|
|
23121
|
+
var WINDOW_MS4 = 60 * 1e3;
|
|
22954
23122
|
var rateHits = /* @__PURE__ */ new Map();
|
|
22955
23123
|
var ERROR_KINDS = /* @__PURE__ */ new Set(["uncaught", "unhandled-rejection", "subresource"]);
|
|
22956
23124
|
function rateKey(ip, cls) {
|
|
@@ -22960,7 +23128,7 @@ function checkRateLimit2(ip, cls) {
|
|
|
22960
23128
|
const key2 = rateKey(ip, cls);
|
|
22961
23129
|
const now = Date.now();
|
|
22962
23130
|
const rec = rateHits.get(key2);
|
|
22963
|
-
if (!rec || now - rec.windowStart >=
|
|
23131
|
+
if (!rec || now - rec.windowStart >= WINDOW_MS4) {
|
|
22964
23132
|
rateHits.set(key2, { windowStart: now, count: 1, blocked: 0, lastLoggedBlocked: 0 });
|
|
22965
23133
|
return { allow: true, blocked: 0, shouldLog: false };
|
|
22966
23134
|
}
|
|
@@ -22975,12 +23143,12 @@ function checkRateLimit2(ip, cls) {
|
|
|
22975
23143
|
}
|
|
22976
23144
|
registerLoop({
|
|
22977
23145
|
name: "client-error-rate-cleanup",
|
|
22978
|
-
intervalMs:
|
|
23146
|
+
intervalMs: WINDOW_MS4,
|
|
22979
23147
|
run: () => {
|
|
22980
23148
|
const now = Date.now();
|
|
22981
23149
|
let purged = 0;
|
|
22982
23150
|
for (const [key2, rec] of rateHits) {
|
|
22983
|
-
if (now - rec.windowStart >=
|
|
23151
|
+
if (now - rec.windowStart >= WINDOW_MS4 * 2) {
|
|
22984
23152
|
rateHits.delete(key2);
|
|
22985
23153
|
purged += 1;
|
|
22986
23154
|
}
|
|
@@ -26148,18 +26316,18 @@ var ALLOWED_EVENTS = /* @__PURE__ */ new Set([
|
|
|
26148
26316
|
]);
|
|
26149
26317
|
var app27 = new Hono();
|
|
26150
26318
|
app27.post("/", async (c) => {
|
|
26151
|
-
const
|
|
26319
|
+
const TAG83 = "[admin:events]";
|
|
26152
26320
|
let body;
|
|
26153
26321
|
try {
|
|
26154
26322
|
body = await c.req.json();
|
|
26155
26323
|
} catch (err) {
|
|
26156
26324
|
const detail = err instanceof Error ? err.message : String(err);
|
|
26157
|
-
console.error(`${
|
|
26325
|
+
console.error(`${TAG83} reject reason=body-not-json detail=${detail}`);
|
|
26158
26326
|
return c.json({ ok: false, detail: "Request body was not valid JSON" }, 400);
|
|
26159
26327
|
}
|
|
26160
26328
|
const event = typeof body.event === "string" ? body.event : "";
|
|
26161
26329
|
if (!ALLOWED_EVENTS.has(event)) {
|
|
26162
|
-
console.error(`${
|
|
26330
|
+
console.error(`${TAG83} reject reason=event-not-allowed event=${JSON.stringify(event)}`);
|
|
26163
26331
|
return c.json({ ok: false, detail: `Event "${event}" is not allowed` }, 400);
|
|
26164
26332
|
}
|
|
26165
26333
|
const rawFields = body.fields && typeof body.fields === "object" ? body.fields : {};
|
|
@@ -35459,13 +35627,13 @@ app68.get("/", requireAdminSession, async (c) => {
|
|
|
35459
35627
|
sampleCpu(sampledAt);
|
|
35460
35628
|
const cpu = sampleProcessCpu(sampledAt);
|
|
35461
35629
|
const loopRows = listLoops();
|
|
35462
|
-
const
|
|
35630
|
+
const armed3 = armedCount();
|
|
35463
35631
|
const byState = loopRows.reduce((acc, r) => {
|
|
35464
35632
|
acc[r.state] = (acc[r.state] ?? 0) + 1;
|
|
35465
35633
|
return acc;
|
|
35466
35634
|
}, {});
|
|
35467
35635
|
console.log(
|
|
35468
|
-
`${TAG62} op=loops req=${req} armed=${
|
|
35636
|
+
`${TAG62} op=loops req=${req} armed=${armed3} rendered=${loopRows.length} procPct=${cpu.processPct?.toFixed(1) ?? "null"} attributedPct=${cpu.attributedPct?.toFixed(1) ?? "null"} ` + Object.entries(byState).map(([s, n]) => `${s}=${n}`).join(" ")
|
|
35469
35637
|
);
|
|
35470
35638
|
return c.json({
|
|
35471
35639
|
rows,
|
|
@@ -35477,7 +35645,7 @@ app68.get("/", requireAdminSession, async (c) => {
|
|
|
35477
35645
|
// vocabulary renders as a dash meaning "not measured". The check runs both
|
|
35478
35646
|
// ways: a key the page does not know about fails as an excess property.
|
|
35479
35647
|
loops: {
|
|
35480
|
-
armed:
|
|
35648
|
+
armed: armed3,
|
|
35481
35649
|
rows: loopRows,
|
|
35482
35650
|
// The server's own CPU beside what the registry can explain. The GAP is
|
|
35483
35651
|
// the point: loops summing to 2% against a process at 60% says the cost
|
|
@@ -37733,11 +37901,29 @@ function startSharedFolderCensus() {
|
|
|
37733
37901
|
});
|
|
37734
37902
|
}
|
|
37735
37903
|
|
|
37904
|
+
// app/lib/accounts-state-census.ts
|
|
37905
|
+
var TAG70 = "[accounts-state]";
|
|
37906
|
+
function runAccountsStateCensus(accountsDir, nowMs) {
|
|
37907
|
+
const { dirs, provisioning, abandoned } = censusAccountDirs(accountsDir, nowMs);
|
|
37908
|
+
console.error(
|
|
37909
|
+
`${TAG70} op=stub-census dirs=${dirs} provisioning=${provisioning.length} abandoned=${abandoned.length} abandonedIds=${abandoned.length > 0 ? abandoned.join(",") : "none"}`
|
|
37910
|
+
);
|
|
37911
|
+
return `${dirs} account dir(s), ${abandoned.length} abandoned`;
|
|
37912
|
+
}
|
|
37913
|
+
function startAccountsStateCensus() {
|
|
37914
|
+
registerLoop({
|
|
37915
|
+
name: "accounts-state-census",
|
|
37916
|
+
intervalMs: 60 * 60 * 1e3,
|
|
37917
|
+
firstRunDelayMs: 0,
|
|
37918
|
+
run: () => runAccountsStateCensus()
|
|
37919
|
+
});
|
|
37920
|
+
}
|
|
37921
|
+
|
|
37736
37922
|
// app/lib/cred-refresh-census.ts
|
|
37737
37923
|
import { readdirSync as readdirSync33, readFileSync as readFileSync57 } from "fs";
|
|
37738
37924
|
import { homedir as homedir4 } from "os";
|
|
37739
37925
|
import { join as join67 } from "path";
|
|
37740
|
-
var
|
|
37926
|
+
var TAG71 = "[claude-auth]";
|
|
37741
37927
|
function refreshTokenLength(raw) {
|
|
37742
37928
|
let data;
|
|
37743
37929
|
try {
|
|
@@ -37781,7 +37967,7 @@ function runCredRefreshCensus(home = homedir4()) {
|
|
|
37781
37967
|
const blank = rows.filter(isBlank).length;
|
|
37782
37968
|
const detail = rows.map((r) => `${r.brand}:${r.refreshTokenLen === null ? "unreadable" : r.refreshTokenLen}`).join(",");
|
|
37783
37969
|
console.log(
|
|
37784
|
-
`${
|
|
37970
|
+
`${TAG71} op=cred-refresh-census result=${censusResult(rows)} brands=${rows.length} blank=${blank} detail=${detail}`
|
|
37785
37971
|
);
|
|
37786
37972
|
return `${rows.length} brand(s), ${blank} blank`;
|
|
37787
37973
|
}
|
|
@@ -38707,14 +38893,14 @@ async function fanOut(p) {
|
|
|
38707
38893
|
}
|
|
38708
38894
|
|
|
38709
38895
|
// app/lib/channel-delivery/delivery-census.ts
|
|
38710
|
-
var
|
|
38711
|
-
var
|
|
38896
|
+
var WINDOW_MS5 = 60 * 60 * 1e3;
|
|
38897
|
+
var records4 = [];
|
|
38712
38898
|
function noteTurnEnd(door, role, outcome, now) {
|
|
38713
|
-
|
|
38899
|
+
records4.push({ door, role, outcome, atMs: now });
|
|
38714
38900
|
}
|
|
38715
38901
|
function readDeliveryCensus(door, now) {
|
|
38716
|
-
|
|
38717
|
-
const mine =
|
|
38902
|
+
records4 = records4.filter((r) => now - r.atMs <= WINDOW_MS5);
|
|
38903
|
+
const mine = records4.filter((r) => r.door === door);
|
|
38718
38904
|
const undelivered = mine.filter((r) => r.outcome === "undelivered");
|
|
38719
38905
|
return {
|
|
38720
38906
|
turnEnds: mine.length,
|
|
@@ -39429,9 +39615,9 @@ var WaGateway = class {
|
|
|
39429
39615
|
};
|
|
39430
39616
|
|
|
39431
39617
|
// app/lib/whatsapp/gateway/duplicate-sender-audit.ts
|
|
39432
|
-
function findDuplicateSenderGroups(
|
|
39618
|
+
function findDuplicateSenderGroups(records5) {
|
|
39433
39619
|
const buckets2 = /* @__PURE__ */ new Map();
|
|
39434
|
-
for (const r of
|
|
39620
|
+
for (const r of records5) {
|
|
39435
39621
|
if (r.channel !== "whatsapp" || !r.senderId) continue;
|
|
39436
39622
|
const canonical = normalizeTarget(r.senderId);
|
|
39437
39623
|
if (!canonical) continue;
|
|
@@ -39452,9 +39638,9 @@ function logDuplicateSenderGroups(groups) {
|
|
|
39452
39638
|
);
|
|
39453
39639
|
}
|
|
39454
39640
|
}
|
|
39455
|
-
function findCrossAccountSenderGroups(
|
|
39641
|
+
function findCrossAccountSenderGroups(records5) {
|
|
39456
39642
|
const byCanonical = /* @__PURE__ */ new Map();
|
|
39457
|
-
for (const r of
|
|
39643
|
+
for (const r of records5) {
|
|
39458
39644
|
if (r.channel !== "whatsapp" || !r.senderId || !r.accountId) continue;
|
|
39459
39645
|
const canonical = normalizeTarget(r.senderId);
|
|
39460
39646
|
if (!canonical) continue;
|
|
@@ -40982,14 +41168,14 @@ function makeFileDelivery(opts) {
|
|
|
40982
41168
|
}
|
|
40983
41169
|
|
|
40984
41170
|
// app/lib/webchat/file-delivery.ts
|
|
40985
|
-
var
|
|
41171
|
+
var TAG72 = "[webchat-adaptor]";
|
|
40986
41172
|
function platformRoot2() {
|
|
40987
41173
|
return process.env.MAXY_PLATFORM_ROOT || "";
|
|
40988
41174
|
}
|
|
40989
41175
|
function makeWebchatSendFile(entry3) {
|
|
40990
41176
|
return async (filePath) => {
|
|
40991
41177
|
if (!entry3.accountId) {
|
|
40992
|
-
console.error(`${
|
|
41178
|
+
console.error(`${TAG72} file-delivery reject reason=no-account sender=${entry3.senderId}`);
|
|
40993
41179
|
return { ok: false, error: "no-account" };
|
|
40994
41180
|
}
|
|
40995
41181
|
const accountDir = resolve50(platformRoot2(), "..", "data/accounts", entry3.accountId);
|
|
@@ -40997,14 +41183,14 @@ function makeWebchatSendFile(entry3) {
|
|
|
40997
41183
|
const resolved = realpathSync9(filePath);
|
|
40998
41184
|
const accountResolved = realpathSync9(accountDir);
|
|
40999
41185
|
if (!resolved.startsWith(accountResolved + "/")) {
|
|
41000
|
-
console.error(`${
|
|
41186
|
+
console.error(`${TAG72} file-delivery reject reason=outside_account_directory sender=${entry3.senderId}`);
|
|
41001
41187
|
return { ok: false, error: "outside-account" };
|
|
41002
41188
|
}
|
|
41003
41189
|
return { ok: true };
|
|
41004
41190
|
} catch (err) {
|
|
41005
41191
|
const code = err.code;
|
|
41006
41192
|
console.error(
|
|
41007
|
-
`${
|
|
41193
|
+
`${TAG72} file-delivery reject reason=${code === "ENOENT" ? "not-found" : "path-error"} sender=${entry3.senderId}`
|
|
41008
41194
|
);
|
|
41009
41195
|
return { ok: false, error: code === "ENOENT" ? "not-found" : "path-error" };
|
|
41010
41196
|
}
|
|
@@ -41013,7 +41199,7 @@ function makeWebchatSendFile(entry3) {
|
|
|
41013
41199
|
function makeWebchatFileDelivery(entry3) {
|
|
41014
41200
|
return makeFileDelivery({
|
|
41015
41201
|
entry: entry3,
|
|
41016
|
-
tag:
|
|
41202
|
+
tag: TAG72,
|
|
41017
41203
|
channel: "webchat",
|
|
41018
41204
|
sendFile: makeWebchatSendFile(entry3),
|
|
41019
41205
|
deferUntilVerdict: true
|
|
@@ -41092,7 +41278,7 @@ function buildPublicWebchatSpawnRequest(input) {
|
|
|
41092
41278
|
}
|
|
41093
41279
|
|
|
41094
41280
|
// app/lib/whatsapp/inbound/file-delivery-bridge.ts
|
|
41095
|
-
var
|
|
41281
|
+
var TAG73 = "[whatsapp-adaptor]";
|
|
41096
41282
|
var SEND_USER_FILE2 = "SendUserFile";
|
|
41097
41283
|
var WHATSAPP_SEND_DOCUMENT = "whatsapp-send-document";
|
|
41098
41284
|
function platformRoot3() {
|
|
@@ -41110,7 +41296,7 @@ function makeWhatsAppSendFile(entry3, maxyAccountId) {
|
|
|
41110
41296
|
});
|
|
41111
41297
|
if (result.ok) return { ok: true };
|
|
41112
41298
|
console.error(
|
|
41113
|
-
`${
|
|
41299
|
+
`${TAG73} file-delivery reject reason=send-failed sender=${entry3.senderId} status=${result.status} message=${result.error}`
|
|
41114
41300
|
);
|
|
41115
41301
|
return { ok: false, error: result.error };
|
|
41116
41302
|
};
|
|
@@ -41118,7 +41304,7 @@ function makeWhatsAppSendFile(entry3, maxyAccountId) {
|
|
|
41118
41304
|
function makeWhatsAppFileDelivery(entry3, maxyAccountId) {
|
|
41119
41305
|
const shared = makeFileDelivery({
|
|
41120
41306
|
entry: entry3,
|
|
41121
|
-
tag:
|
|
41307
|
+
tag: TAG73,
|
|
41122
41308
|
channel: "whatsapp",
|
|
41123
41309
|
sendFile: makeWhatsAppSendFile(entry3, maxyAccountId)
|
|
41124
41310
|
});
|
|
@@ -41153,7 +41339,7 @@ function makeWhatsAppFileDelivery(entry3, maxyAccountId) {
|
|
|
41153
41339
|
if (!delivered) {
|
|
41154
41340
|
const fileField = call2.filePath !== void 0 ? ` file=${call2.filePath}` : "";
|
|
41155
41341
|
console.error(
|
|
41156
|
-
`${
|
|
41342
|
+
`${TAG73} file-delivery-unreconciled sender=${entry3.senderId} sessionId=${sid} tool=${WHATSAPP_SEND_DOCUMENT}${fileField}`
|
|
41157
41343
|
);
|
|
41158
41344
|
}
|
|
41159
41345
|
}
|
|
@@ -41319,7 +41505,7 @@ function whatsappDoorLabel(doorId) {
|
|
|
41319
41505
|
}
|
|
41320
41506
|
|
|
41321
41507
|
// app/lib/channel-delivery/refusal-notice.ts
|
|
41322
|
-
var
|
|
41508
|
+
var TAG74 = "[channel-delivery]";
|
|
41323
41509
|
var notified = /* @__PURE__ */ new Set();
|
|
41324
41510
|
function refusalNoticeText(reason) {
|
|
41325
41511
|
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.`;
|
|
@@ -41328,19 +41514,19 @@ async function sendRefusalNotice(input) {
|
|
|
41328
41514
|
if (notified.has(input.doorId)) return;
|
|
41329
41515
|
const fields = `channel=${input.channel} sender=${input.sender} reason=${input.reason}`;
|
|
41330
41516
|
if (!input.send) {
|
|
41331
|
-
console.error(`${
|
|
41517
|
+
console.error(`${TAG74} op=refusal-notice-failed ${fields} error=no-target`);
|
|
41332
41518
|
return;
|
|
41333
41519
|
}
|
|
41334
41520
|
try {
|
|
41335
41521
|
await input.send(guardOutbound(input.sender, refusalNoticeText(input.reason)));
|
|
41336
41522
|
} catch (e) {
|
|
41337
41523
|
console.error(
|
|
41338
|
-
`${
|
|
41524
|
+
`${TAG74} op=refusal-notice-failed ${fields} error=${e instanceof Error ? e.message : String(e)}`
|
|
41339
41525
|
);
|
|
41340
41526
|
return;
|
|
41341
41527
|
}
|
|
41342
41528
|
notified.add(input.doorId);
|
|
41343
|
-
console.error(`${
|
|
41529
|
+
console.error(`${TAG74} op=refusal-notice ${fields} status=${input.status}`);
|
|
41344
41530
|
}
|
|
41345
41531
|
function clearRefusalNotice(doorId) {
|
|
41346
41532
|
notified.delete(doorId);
|
|
@@ -41614,6 +41800,19 @@ function createTelegramChannelRoutes(deps) {
|
|
|
41614
41800
|
return app81;
|
|
41615
41801
|
}
|
|
41616
41802
|
|
|
41803
|
+
// app/lib/telegram/operator-sent-suppression.ts
|
|
41804
|
+
var OPERATOR_SENT_LATCH_MS = 3e5;
|
|
41805
|
+
var armed2 = /* @__PURE__ */ new Map();
|
|
41806
|
+
function armOperatorSent(key2, now) {
|
|
41807
|
+
armed2.set(key2, now);
|
|
41808
|
+
}
|
|
41809
|
+
function takeOperatorSent(key2, now) {
|
|
41810
|
+
const at = armed2.get(key2);
|
|
41811
|
+
if (at === void 0) return false;
|
|
41812
|
+
armed2.delete(key2);
|
|
41813
|
+
return now - at <= OPERATOR_SENT_LATCH_MS;
|
|
41814
|
+
}
|
|
41815
|
+
|
|
41617
41816
|
// app/lib/telegram/gateway/telegram-spawn-census.ts
|
|
41618
41817
|
var byBot = /* @__PURE__ */ new Map();
|
|
41619
41818
|
function bucket(botId) {
|
|
@@ -41841,6 +42040,11 @@ var TelegramGateway = class {
|
|
|
41841
42040
|
const willDeliverNow = this.hub.isReady(key2);
|
|
41842
42041
|
const source = input.source ?? "user";
|
|
41843
42042
|
this.replies.set(key2, input.reply);
|
|
42043
|
+
if (source === "operator-sent") {
|
|
42044
|
+
const at = Date.now();
|
|
42045
|
+
armOperatorSent(key2, at);
|
|
42046
|
+
noteManualRecorded(key2, at);
|
|
42047
|
+
}
|
|
41844
42048
|
let standingRules;
|
|
41845
42049
|
if (input.role === "admin" && this.deps.fetchStandingRules) {
|
|
41846
42050
|
const res = await this.deps.fetchStandingRules(input.accountId);
|
|
@@ -42012,10 +42216,10 @@ function buildTelegramSpawnRequest(input) {
|
|
|
42012
42216
|
}
|
|
42013
42217
|
|
|
42014
42218
|
// server/telegram-ensure-session.ts
|
|
42015
|
-
var
|
|
42219
|
+
var TAG75 = "[telegram-inbound]";
|
|
42016
42220
|
function reportReused(botId, channelKey, result) {
|
|
42017
42221
|
if (!result.reused) return;
|
|
42018
|
-
console.error(`${
|
|
42222
|
+
console.error(`${TAG75} op=spawn-reused botId=${botId} key=${channelKey} sessionId=${result.sessionId}`);
|
|
42019
42223
|
}
|
|
42020
42224
|
function buildTelegramEnsureSession(deps) {
|
|
42021
42225
|
return async (input) => {
|
|
@@ -42079,10 +42283,10 @@ function buildTelegramEnsureSession(deps) {
|
|
|
42079
42283
|
return;
|
|
42080
42284
|
}
|
|
42081
42285
|
console.error(
|
|
42082
|
-
`${
|
|
42286
|
+
`${TAG75} op=telegram-spawn-door botId=${input.botId} role=specialist door=rc specialist=${input.specialist}`
|
|
42083
42287
|
);
|
|
42084
42288
|
console.error(
|
|
42085
|
-
`${
|
|
42289
|
+
`${TAG75} op=spawn botId=${input.botId} sessionId=${req.sessionId} targetAccountId=${input.accountId} role=specialist specialist=${input.specialist}`
|
|
42086
42290
|
);
|
|
42087
42291
|
reportReused(input.botId, req.channelKey, result2);
|
|
42088
42292
|
noteSpawnOk2(input.botId);
|
|
@@ -42117,10 +42321,10 @@ function buildTelegramEnsureSession(deps) {
|
|
|
42117
42321
|
return;
|
|
42118
42322
|
}
|
|
42119
42323
|
console.error(
|
|
42120
|
-
`${
|
|
42324
|
+
`${TAG75} op=telegram-spawn-door botId=${input.botId} role=public door=rc agent=${input.agentSlug}`
|
|
42121
42325
|
);
|
|
42122
42326
|
console.error(
|
|
42123
|
-
`${
|
|
42327
|
+
`${TAG75} op=spawn botId=${input.botId} sessionId=${result2.sessionId} targetAccountId=${input.accountId} role=public`
|
|
42124
42328
|
);
|
|
42125
42329
|
reportReused(input.botId, req.channelKey, result2);
|
|
42126
42330
|
noteSpawnOk2(input.botId);
|
|
@@ -42144,7 +42348,7 @@ function buildTelegramEnsureSession(deps) {
|
|
|
42144
42348
|
return;
|
|
42145
42349
|
}
|
|
42146
42350
|
console.error(
|
|
42147
|
-
`${
|
|
42351
|
+
`${TAG75} op=spawn botId=${input.botId} sessionId=${req.sessionId} targetAccountId=${input.accountId} role=admin`
|
|
42148
42352
|
);
|
|
42149
42353
|
reportReused(input.botId, req.channelKey, result);
|
|
42150
42354
|
noteSpawnOk2(input.botId);
|
|
@@ -42163,7 +42367,7 @@ function buildTelegramEnsureSession(deps) {
|
|
|
42163
42367
|
import { realpathSync as realpathSync10 } from "fs";
|
|
42164
42368
|
import { readFile as readFile15, stat as stat10 } from "fs/promises";
|
|
42165
42369
|
import { resolve as resolve51, basename as basename18 } from "path";
|
|
42166
|
-
var
|
|
42370
|
+
var TAG76 = "[telegram:outbound]";
|
|
42167
42371
|
var TELEGRAM_DOCUMENT_MAX_BYTES = 50 * 1024 * 1024;
|
|
42168
42372
|
async function sendTelegramDocument(input) {
|
|
42169
42373
|
const { botToken, chatId, filePath, caption, maxyAccountId, platformRoot: platformRoot5 } = input;
|
|
@@ -42180,10 +42384,10 @@ async function sendTelegramDocument(input) {
|
|
|
42180
42384
|
} catch (err) {
|
|
42181
42385
|
const code = err.code;
|
|
42182
42386
|
if (code === "ENOENT") {
|
|
42183
|
-
console.error(`${
|
|
42387
|
+
console.error(`${TAG76} document ENOENT scope=account-dir accountDir=${accountDir} maxyAccountId=${maxyAccountId}`);
|
|
42184
42388
|
return { ok: false, status: 500, error: `Account directory not resolvable for ${maxyAccountId}` };
|
|
42185
42389
|
}
|
|
42186
|
-
console.error(`${
|
|
42390
|
+
console.error(`${TAG76} document path error scope=account-dir maxyAccountId=${maxyAccountId}: ${String(err)}`);
|
|
42187
42391
|
return { ok: false, status: 500, error: String(err) };
|
|
42188
42392
|
}
|
|
42189
42393
|
let resolvedPath;
|
|
@@ -42192,14 +42396,14 @@ async function sendTelegramDocument(input) {
|
|
|
42192
42396
|
} catch (err) {
|
|
42193
42397
|
const code = err.code;
|
|
42194
42398
|
if (code === "ENOENT") {
|
|
42195
|
-
console.error(`${
|
|
42399
|
+
console.error(`${TAG76} document ENOENT scope=file path=${filePath} maxyAccountId=${maxyAccountId}`);
|
|
42196
42400
|
return { ok: false, status: 404, error: `File not found: ${filePath}` };
|
|
42197
42401
|
}
|
|
42198
|
-
console.error(`${
|
|
42402
|
+
console.error(`${TAG76} document path error scope=file maxyAccountId=${maxyAccountId}: ${String(err)}`);
|
|
42199
42403
|
return { ok: false, status: 500, error: String(err) };
|
|
42200
42404
|
}
|
|
42201
42405
|
if (!resolvedPath.startsWith(accountResolved + "/")) {
|
|
42202
|
-
console.error(`${
|
|
42406
|
+
console.error(`${TAG76} document REJECTED reason=outside_account_directory maxyAccountId=${maxyAccountId}`);
|
|
42203
42407
|
return { ok: false, status: 403, error: "Access denied: file is outside the account directory" };
|
|
42204
42408
|
}
|
|
42205
42409
|
const fileStat = await stat10(resolvedPath);
|
|
@@ -42232,24 +42436,24 @@ async function sendTelegramDocument(input) {
|
|
|
42232
42436
|
error = e instanceof Error ? e.message : String(e);
|
|
42233
42437
|
}
|
|
42234
42438
|
console.error(
|
|
42235
|
-
`${
|
|
42439
|
+
`${TAG76} sent document to=${chatId} file=${filename} bytes=${fileStat.size} ok=${ok2}` + (messageId !== void 0 ? ` id=${messageId}` : "")
|
|
42236
42440
|
);
|
|
42237
42441
|
return ok2 ? { ok: true, messageId } : { ok: false, status: 500, error };
|
|
42238
42442
|
}
|
|
42239
42443
|
|
|
42240
42444
|
// app/lib/telegram/outbound/file-delivery.ts
|
|
42241
|
-
var
|
|
42445
|
+
var TAG77 = "[telegram:outbound]";
|
|
42242
42446
|
function platformRoot4() {
|
|
42243
42447
|
return process.env.MAXY_PLATFORM_ROOT || "";
|
|
42244
42448
|
}
|
|
42245
42449
|
function makeTelegramSendFile(entry3, botToken) {
|
|
42246
42450
|
return async (filePath, caption) => {
|
|
42247
42451
|
if (!botToken) {
|
|
42248
|
-
console.error(`${
|
|
42452
|
+
console.error(`${TAG77} file-delivery reject reason=no-bot-token sender=${entry3.senderId} role=${entry3.role}`);
|
|
42249
42453
|
return { ok: false, error: "no-bot-token" };
|
|
42250
42454
|
}
|
|
42251
42455
|
if (entry3.replyTarget == null) {
|
|
42252
|
-
console.error(`${
|
|
42456
|
+
console.error(`${TAG77} file-delivery reject reason=no-reply-target sender=${entry3.senderId} role=${entry3.role}`);
|
|
42253
42457
|
return { ok: false, error: "no-reply-target" };
|
|
42254
42458
|
}
|
|
42255
42459
|
const result = await sendTelegramDocument({
|
|
@@ -42266,7 +42470,7 @@ function makeTelegramSendFile(entry3, botToken) {
|
|
|
42266
42470
|
function makeTelegramFileDelivery(entry3, botToken) {
|
|
42267
42471
|
return makeFileDelivery({
|
|
42268
42472
|
entry: entry3,
|
|
42269
|
-
tag:
|
|
42473
|
+
tag: TAG77,
|
|
42270
42474
|
channel: "telegram",
|
|
42271
42475
|
sendFile: makeTelegramSendFile(entry3, botToken)
|
|
42272
42476
|
});
|
|
@@ -42334,23 +42538,23 @@ function noteCardCrossChat(sessionId) {
|
|
|
42334
42538
|
entry2(sessionId).crossChat += 1;
|
|
42335
42539
|
}
|
|
42336
42540
|
function cardCensusLines() {
|
|
42337
|
-
let
|
|
42541
|
+
let armed3 = 0;
|
|
42338
42542
|
let suppressed = 0;
|
|
42339
42543
|
let delivered = 0;
|
|
42340
42544
|
let persisted = 0;
|
|
42341
42545
|
let sent = 0;
|
|
42342
42546
|
let crossChat = 0;
|
|
42343
42547
|
for (const e of sessions3.values()) {
|
|
42344
|
-
|
|
42548
|
+
armed3 += e.armed;
|
|
42345
42549
|
suppressed += e.suppressed;
|
|
42346
42550
|
delivered += e.delivered;
|
|
42347
42551
|
persisted += e.persisted;
|
|
42348
42552
|
sent += e.sent;
|
|
42349
42553
|
crossChat += e.crossChat;
|
|
42350
42554
|
}
|
|
42351
|
-
const silent = Math.max(0,
|
|
42555
|
+
const silent = Math.max(0, armed3 - suppressed - delivered);
|
|
42352
42556
|
return [
|
|
42353
|
-
`[telegram-card-suppression-census] sessions=${sessions3.size} armed=${
|
|
42557
|
+
`[telegram-card-suppression-census] sessions=${sessions3.size} armed=${armed3} suppressed=${suppressed} silent-turns=${silent} sent=${sent} persisted=${persisted} cross-chat=${crossChat}`
|
|
42354
42558
|
];
|
|
42355
42559
|
}
|
|
42356
42560
|
|
|
@@ -42403,6 +42607,7 @@ function startTelegramNativeFileFollower(input) {
|
|
|
42403
42607
|
let lastChatActionAt = Number.NEGATIVE_INFINITY;
|
|
42404
42608
|
let turnOpen = false;
|
|
42405
42609
|
let cardSentThisTurn = false;
|
|
42610
|
+
let operatorSentThisTurn = false;
|
|
42406
42611
|
let heartbeat = null;
|
|
42407
42612
|
const send = (driver2) => {
|
|
42408
42613
|
lastChatActionAt = Date.now();
|
|
@@ -42427,7 +42632,15 @@ function startTelegramNativeFileFollower(input) {
|
|
|
42427
42632
|
lastChatActionAt = Number.NEGATIVE_INFINITY;
|
|
42428
42633
|
};
|
|
42429
42634
|
const onTurnStart = (kind) => {
|
|
42430
|
-
if (kind === "inbound")
|
|
42635
|
+
if (kind === "inbound") {
|
|
42636
|
+
cardSentThisTurn = false;
|
|
42637
|
+
operatorSentThisTurn = takeOperatorSent(channelKey, Date.now());
|
|
42638
|
+
if (operatorSentThisTurn) {
|
|
42639
|
+
console.error(
|
|
42640
|
+
`[telegram-public] op=operator-sent-armed sessionId=${input.sessionId.slice(0, 8)} key=${channelKey}`
|
|
42641
|
+
);
|
|
42642
|
+
}
|
|
42643
|
+
}
|
|
42431
42644
|
if (turnOpen) return;
|
|
42432
42645
|
turnOpen = true;
|
|
42433
42646
|
stopHeartbeat();
|
|
@@ -42566,6 +42779,13 @@ function startTelegramNativeFileFollower(input) {
|
|
|
42566
42779
|
// Ungated by design: whatever woke the turn, the reader and the chats show
|
|
42567
42780
|
// the same thing. Task 2666 adds the one exception above.
|
|
42568
42781
|
onAnswer: async (answer) => {
|
|
42782
|
+
if (operatorSentThisTurn) {
|
|
42783
|
+
noteManualSuppressed(channelKey, Date.now());
|
|
42784
|
+
console.error(
|
|
42785
|
+
`[telegram-public] op=text-suppressed sessionId=${input.sessionId.slice(0, 8)} messageId=${answer.messageId} reason=operator-sent`
|
|
42786
|
+
);
|
|
42787
|
+
return;
|
|
42788
|
+
}
|
|
42569
42789
|
if (cardSentThisTurn) {
|
|
42570
42790
|
noteCardSuppressed(input.sessionId);
|
|
42571
42791
|
console.error(
|
|
@@ -42707,7 +42927,7 @@ function adminFanTargets(p) {
|
|
|
42707
42927
|
|
|
42708
42928
|
// app/lib/channel-pty-bridge/public-session-end-review.ts
|
|
42709
42929
|
import { randomUUID as randomUUID14 } from "crypto";
|
|
42710
|
-
var
|
|
42930
|
+
var TAG78 = "[public-session-review]";
|
|
42711
42931
|
var CONSUMED_CAP = 500;
|
|
42712
42932
|
var consumed = /* @__PURE__ */ new Set();
|
|
42713
42933
|
function consumeOnce(sessionId) {
|
|
@@ -42734,7 +42954,7 @@ async function fetchJsonl(sessionId) {
|
|
|
42734
42954
|
return await res.text();
|
|
42735
42955
|
} catch (err) {
|
|
42736
42956
|
console.error(
|
|
42737
|
-
`${
|
|
42957
|
+
`${TAG78} jsonl-fetch-failed sessionId=${sessionId} err="${err instanceof Error ? err.message : String(err)}"`
|
|
42738
42958
|
);
|
|
42739
42959
|
return null;
|
|
42740
42960
|
}
|
|
@@ -42758,7 +42978,7 @@ async function fetchPriorWrites(sliceToken, accountId) {
|
|
|
42758
42978
|
const res = await fetch(url);
|
|
42759
42979
|
if (!res.ok) {
|
|
42760
42980
|
console.error(
|
|
42761
|
-
`${
|
|
42981
|
+
`${TAG78} prior-writes-fetch-failed sliceToken=${sliceToken.slice(0, 8)} status=${res.status}`
|
|
42762
42982
|
);
|
|
42763
42983
|
return [];
|
|
42764
42984
|
}
|
|
@@ -42766,7 +42986,7 @@ async function fetchPriorWrites(sliceToken, accountId) {
|
|
|
42766
42986
|
return Array.isArray(body.writes) ? body.writes : [];
|
|
42767
42987
|
} catch (err) {
|
|
42768
42988
|
console.error(
|
|
42769
|
-
`${
|
|
42989
|
+
`${TAG78} prior-writes-fetch-threw sliceToken=${sliceToken.slice(0, 8)} err="${err instanceof Error ? err.message : String(err)}"`
|
|
42770
42990
|
);
|
|
42771
42991
|
return [];
|
|
42772
42992
|
}
|
|
@@ -42795,7 +43015,7 @@ function composeInitialMessage(input) {
|
|
|
42795
43015
|
}
|
|
42796
43016
|
async function dispatchReviewer(input, initialMessage) {
|
|
42797
43017
|
const sessionId = randomUUID14();
|
|
42798
|
-
console.log(`${
|
|
43018
|
+
console.log(`${TAG78} route target=rc-spawn sessionId=${sessionId.slice(0, 8)} sourceSession=${input.sessionId.slice(0, 8)}`);
|
|
42799
43019
|
const spawned = await managerRcSpawn({
|
|
42800
43020
|
sessionId,
|
|
42801
43021
|
initialMessage,
|
|
@@ -42819,21 +43039,21 @@ async function firePublicSessionEndReview(input) {
|
|
|
42819
43039
|
const dispatchedAt = Date.now();
|
|
42820
43040
|
if (consumed.has(input.sessionId)) {
|
|
42821
43041
|
console.log(
|
|
42822
|
-
`${
|
|
43042
|
+
`${TAG78} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-already-reviewed`
|
|
42823
43043
|
);
|
|
42824
43044
|
return;
|
|
42825
43045
|
}
|
|
42826
43046
|
const jsonl = await fetchJsonl(input.sessionId);
|
|
42827
43047
|
if (!jsonl) {
|
|
42828
43048
|
console.log(
|
|
42829
|
-
`${
|
|
43049
|
+
`${TAG78} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-jsonl-missing`
|
|
42830
43050
|
);
|
|
42831
43051
|
return;
|
|
42832
43052
|
}
|
|
42833
43053
|
const operatorTurns = countOperatorTurns(jsonl);
|
|
42834
43054
|
if (operatorTurns === 0) {
|
|
42835
43055
|
console.log(
|
|
42836
|
-
`${
|
|
43056
|
+
`${TAG78} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-no-turns`
|
|
42837
43057
|
);
|
|
42838
43058
|
return;
|
|
42839
43059
|
}
|
|
@@ -42847,19 +43067,19 @@ async function firePublicSessionEndReview(input) {
|
|
|
42847
43067
|
});
|
|
42848
43068
|
if (!consumeOnce(input.sessionId)) {
|
|
42849
43069
|
console.log(
|
|
42850
|
-
`${
|
|
43070
|
+
`${TAG78} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-already-reviewed`
|
|
42851
43071
|
);
|
|
42852
43072
|
return;
|
|
42853
43073
|
}
|
|
42854
43074
|
const dispatched = await dispatchReviewer(input, initialMessage);
|
|
42855
43075
|
if (!dispatched.ok) {
|
|
42856
43076
|
console.error(
|
|
42857
|
-
`${
|
|
43077
|
+
`${TAG78} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-spawn-failed reason=${dispatched.reason}`
|
|
42858
43078
|
);
|
|
42859
43079
|
return;
|
|
42860
43080
|
}
|
|
42861
43081
|
console.log(
|
|
42862
|
-
`${
|
|
43082
|
+
`${TAG78} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=dispatched managerSessionId=${dispatched.managerSessionId} operatorTurns=${operatorTurns} priorWrites=${priorWrites.length} ms=${Date.now() - dispatchedAt}`
|
|
42863
43083
|
);
|
|
42864
43084
|
}
|
|
42865
43085
|
|
|
@@ -43128,10 +43348,10 @@ function* walkTelegramSidecars() {
|
|
|
43128
43348
|
}
|
|
43129
43349
|
|
|
43130
43350
|
// server/telegram-group-census.ts
|
|
43131
|
-
var
|
|
43351
|
+
var TAG79 = "[telegram-audit]";
|
|
43132
43352
|
var PRESENT_STATUSES = /* @__PURE__ */ new Set(["member", "administrator", "creator"]);
|
|
43133
43353
|
function buildGroupCensusLine(c) {
|
|
43134
|
-
return `${
|
|
43354
|
+
return `${TAG79} op=group-census bots=${c.bots} groups=${c.groups} present=${c.present} absent=${c.absent} privacyOff=${c.privacyOff}`;
|
|
43135
43355
|
}
|
|
43136
43356
|
async function runTelegramGroupCensus(accounts, deps) {
|
|
43137
43357
|
const counts = { bots: 0, groups: 0, present: 0, absent: 0, privacyOff: 0 };
|
|
@@ -43162,10 +43382,10 @@ async function runTelegramGroupCensus(accounts, deps) {
|
|
|
43162
43382
|
}
|
|
43163
43383
|
|
|
43164
43384
|
// server/telegram-channel-census.ts
|
|
43165
|
-
var
|
|
43385
|
+
var TAG80 = "[telegram-audit]";
|
|
43166
43386
|
var ADMIN_STATUSES = /* @__PURE__ */ new Set(["administrator", "creator"]);
|
|
43167
43387
|
function buildChannelCensusLine(c) {
|
|
43168
|
-
return `${
|
|
43388
|
+
return `${TAG80} op=channel-census bots=${c.bots} channels=${c.channels} admin=${c.admin} notAdmin=${c.notAdmin} noPostRight=${c.noPostRight}`;
|
|
43169
43389
|
}
|
|
43170
43390
|
async function runTelegramChannelCensus(accounts, deps) {
|
|
43171
43391
|
const counts = { bots: 0, channels: 0, admin: 0, notAdmin: 0, noPostRight: 0 };
|
|
@@ -43197,7 +43417,7 @@ async function runTelegramChannelCensus(accounts, deps) {
|
|
|
43197
43417
|
}
|
|
43198
43418
|
|
|
43199
43419
|
// server/telegram-graph-duplicate-census.ts
|
|
43200
|
-
var
|
|
43420
|
+
var TAG81 = "[telegram-audit]";
|
|
43201
43421
|
var DUPLICATE_QUERY = `
|
|
43202
43422
|
MATCH (m:Message)
|
|
43203
43423
|
WHERE m.accountId = $accountId AND m.channel = 'telegram'
|
|
@@ -43224,12 +43444,12 @@ async function runTelegramGraphDuplicateCensus(accountIds, deps) {
|
|
|
43224
43444
|
const sessions4 = asSessions(Array.isArray(row.sessions) ? row.sessions : []);
|
|
43225
43445
|
const named = sessions4.length > 0 ? ` ids=${sessions4.join(",")}` : "";
|
|
43226
43446
|
lines.push(
|
|
43227
|
-
`${
|
|
43447
|
+
`${TAG81} op=graph-duplicate accountId=${accountId} messages=${messages} sessions=${sessions4.length}${named}`
|
|
43228
43448
|
);
|
|
43229
43449
|
} catch (err) {
|
|
43230
43450
|
const reason = err instanceof Error ? err.message : String(err);
|
|
43231
43451
|
lines.push(
|
|
43232
|
-
`${
|
|
43452
|
+
`${TAG81} FAIL op=graph-duplicate accountId=${accountId} reason=${reason.slice(0, 100)}`
|
|
43233
43453
|
);
|
|
43234
43454
|
}
|
|
43235
43455
|
}
|
|
@@ -43237,9 +43457,9 @@ async function runTelegramGraphDuplicateCensus(accountIds, deps) {
|
|
|
43237
43457
|
}
|
|
43238
43458
|
|
|
43239
43459
|
// server/telegram-identity-census.ts
|
|
43240
|
-
var
|
|
43460
|
+
var TAG82 = "[telegram-audit]";
|
|
43241
43461
|
function buildIdentityCensusLine(c) {
|
|
43242
|
-
return `${
|
|
43462
|
+
return `${TAG82} op=identity-census bots=${c.bots} ids=${c.ids} bound=${c.bound} unbound=${c.unbound} ambiguous=${c.ambiguous}`;
|
|
43243
43463
|
}
|
|
43244
43464
|
async function runTelegramIdentityCensus(accounts, deps) {
|
|
43245
43465
|
const counts = { bots: 0, ids: 0, bound: 0, unbound: 0, ambiguous: 0 };
|
|
@@ -44213,16 +44433,16 @@ function runDuplicateSenderAudit() {
|
|
|
44213
44433
|
const configDir = process.env.CLAUDE_CONFIG_DIR;
|
|
44214
44434
|
if (!configDir) return;
|
|
44215
44435
|
const projectsRoot = join76(configDir, "projects");
|
|
44216
|
-
const
|
|
44436
|
+
const records5 = [];
|
|
44217
44437
|
for (const { path: jsonlPath, isSubagent, archived } of enumerateJsonls(projectsRoot)) {
|
|
44218
44438
|
if (isSubagent || archived) continue;
|
|
44219
44439
|
const sessionId = jsonlPath.slice(jsonlPath.lastIndexOf("/") + 1).replace(/\.jsonl$/, "");
|
|
44220
44440
|
const metaPath = jsonlPath.replace(/\.jsonl$/, ".meta.json");
|
|
44221
44441
|
const meta = readSidecarMeta(metaPath);
|
|
44222
|
-
|
|
44442
|
+
records5.push({ sessionId, channel: meta.channel, senderId: meta.senderId, accountId: meta.accountId });
|
|
44223
44443
|
}
|
|
44224
|
-
logDuplicateSenderGroups(findDuplicateSenderGroups(
|
|
44225
|
-
logCrossAccountSenderGroups(findCrossAccountSenderGroups(
|
|
44444
|
+
logDuplicateSenderGroups(findDuplicateSenderGroups(records5));
|
|
44445
|
+
logCrossAccountSenderGroups(findCrossAccountSenderGroups(records5));
|
|
44226
44446
|
const outbound = waGateway.takeOutboundAccountCensus();
|
|
44227
44447
|
console.error(
|
|
44228
44448
|
`[whatsapp-native] op=outbound-account-mismatch sends=${outbound.sends} mismatched=${outbound.mismatched}`
|
|
@@ -45584,6 +45804,13 @@ registerLoop({
|
|
|
45584
45804
|
`[telegram-instruct-census] op=rejected detail=${err instanceof Error ? err.message : String(err)}`
|
|
45585
45805
|
);
|
|
45586
45806
|
}
|
|
45807
|
+
try {
|
|
45808
|
+
runTelegramManualSendCensus(Date.now());
|
|
45809
|
+
} catch (err) {
|
|
45810
|
+
console.error(
|
|
45811
|
+
`[telegram-manual-census] op=rejected detail=${err instanceof Error ? err.message : String(err)}`
|
|
45812
|
+
);
|
|
45813
|
+
}
|
|
45587
45814
|
try {
|
|
45588
45815
|
runTelegramNotifyPublishCensus(Date.now());
|
|
45589
45816
|
} catch (err) {
|
|
@@ -46080,12 +46307,12 @@ startAuthHealthHeartbeat();
|
|
|
46080
46307
|
const loopHist = monitorEventLoopDelay({ resolution: 50 });
|
|
46081
46308
|
loopHist.enable();
|
|
46082
46309
|
const LOUD_THRESHOLD_MS = 1e3;
|
|
46083
|
-
const
|
|
46310
|
+
const WINDOW_MS6 = 3e4;
|
|
46084
46311
|
registerLoop({
|
|
46085
46312
|
name: "event-loop-lag",
|
|
46086
|
-
intervalMs:
|
|
46313
|
+
intervalMs: WINDOW_MS6,
|
|
46087
46314
|
run: () => {
|
|
46088
|
-
const w = readAndResetWindow(loopHist,
|
|
46315
|
+
const w = readAndResetWindow(loopHist, WINDOW_MS6);
|
|
46089
46316
|
const line = formatLagWindow(w);
|
|
46090
46317
|
if (w.maxMs >= LOUD_THRESHOLD_MS) console.error(line);
|
|
46091
46318
|
else console.log(line);
|
|
@@ -46343,6 +46570,7 @@ registerLoop({
|
|
|
46343
46570
|
});
|
|
46344
46571
|
startGraphHealthTimer();
|
|
46345
46572
|
startSharedFolderCensus();
|
|
46573
|
+
startAccountsStateCensus();
|
|
46346
46574
|
startCredRefreshCensus();
|
|
46347
46575
|
void migrateUploads().catch((err) => console.error(`[uploads-migrate] failed err="${err instanceof Error ? err.message : String(err)}"`)).finally(() => {
|
|
46348
46576
|
void startFileWatcher().catch((err) => {
|