@rubytech/create-maxy-code 0.1.377 → 0.1.379

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.
Files changed (155) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +27 -6
  3. package/payload/platform/plugins/docs/references/admin-ui.md +26 -5
  4. package/payload/platform/plugins/whatsapp/references/channels-whatsapp.md +13 -0
  5. package/payload/platform/scripts/lib/read-brand-json.sh +19 -0
  6. package/payload/platform/scripts/seed-neo4j.sh +44 -3
  7. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
  8. package/payload/platform/services/claude-session-manager/dist/http-server.js +100 -13
  9. package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
  10. package/payload/server/{chunk-Y4SHSFGK.js → chunk-ZYS5V5QG.js} +22 -21
  11. package/payload/server/maxy-edge.js +1 -1
  12. package/payload/server/public/assets/{AdminLoginScreens-DVjwrcZa.js → AdminLoginScreens-BHo8w_9J.js} +1 -1
  13. package/payload/server/public/assets/AdminShell-DbTijFVA.js +1 -0
  14. package/payload/server/public/assets/{Checkbox-B8dm2kDD.js → Checkbox-LmjNFccS.js} +1 -1
  15. package/payload/server/public/assets/admin-BBWILfl8.js +1 -0
  16. package/payload/server/public/assets/{arc-Crkz45LN.js → arc-JgkiMDpu.js} +1 -1
  17. package/payload/server/public/assets/architecture-YZFGNWBL-Dh5BzVzk.js +1 -0
  18. package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-C9JThHgP.js → architectureDiagram-Q4EWVU46-CyIbl1bD.js} +1 -1
  19. package/payload/server/public/assets/{blockDiagram-DXYQGD6D-DpsV_HXT.js → blockDiagram-DXYQGD6D-CkcZVblf.js} +1 -1
  20. package/payload/server/public/assets/{browser-BMyQHWKS.js → browser-DtLvD_ES.js} +1 -1
  21. package/payload/server/public/assets/{c4Diagram-AHTNJAMY-CTm_6aKi.js → c4Diagram-AHTNJAMY-VByNuobb.js} +1 -1
  22. package/payload/server/public/assets/calendar-D3i4IqOV.js +1 -0
  23. package/payload/server/public/assets/channel-CFHc3PQ7.js +1 -0
  24. package/payload/server/public/assets/chat-DU-T6blN.js +1 -0
  25. package/payload/server/public/assets/{chunk-2KRD3SAO-1KSJW1q6.js → chunk-2KRD3SAO-BFwiGcqo.js} +1 -1
  26. package/payload/server/public/assets/{chunk-336JU56O-C3t08Ip-.js → chunk-336JU56O-BMCBU-vf.js} +2 -2
  27. package/payload/server/public/assets/chunk-426QAEUC-De9_O1hi.js +1 -0
  28. package/payload/server/public/assets/{chunk-4BX2VUAB-kl1ze33n.js → chunk-4BX2VUAB-RfOeo8_F.js} +1 -1
  29. package/payload/server/public/assets/{chunk-4TB4RGXK-DxpoDoHg.js → chunk-4TB4RGXK-B5xbgonc.js} +1 -1
  30. package/payload/server/public/assets/{chunk-55IACEB6-WM9VJzha.js → chunk-55IACEB6-K8U55ikJ.js} +1 -1
  31. package/payload/server/public/assets/{chunk-5FUZZQ4R-CLH63ZH3.js → chunk-5FUZZQ4R-DgmmsrAc.js} +1 -1
  32. package/payload/server/public/assets/{chunk-5PVQY5BW-DCTb8IAT.js → chunk-5PVQY5BW-DQ6rtehF.js} +1 -1
  33. package/payload/server/public/assets/{chunk-67CJDMHE-BSYzyaoH.js → chunk-67CJDMHE-CC2kfpmQ.js} +1 -1
  34. package/payload/server/public/assets/{chunk-7N4EOEYR-CarJ7O2P.js → chunk-7N4EOEYR-BClZ5bzw.js} +1 -1
  35. package/payload/server/public/assets/{chunk-AA7GKIK3-DTNLyBpH.js → chunk-AA7GKIK3-adtwAFKX.js} +1 -1
  36. package/payload/server/public/assets/{chunk-BSJP7CBP-BFmHflHY.js → chunk-BSJP7CBP-fKY1UWEd.js} +1 -1
  37. package/payload/server/public/assets/{chunk-CIAEETIT-BpjG0IzU.js → chunk-CIAEETIT-knPAMmjG.js} +1 -1
  38. package/payload/server/public/assets/{chunk-EDXVE4YY-2fSowhlW.js → chunk-EDXVE4YY-C7FRKZ5e.js} +1 -1
  39. package/payload/server/public/assets/{chunk-ENJZ2VHE-ClcranGV.js → chunk-ENJZ2VHE-0cgFfv3z.js} +1 -1
  40. package/payload/server/public/assets/{chunk-FMBD7UC4-DLq4BItQ.js → chunk-FMBD7UC4-Dm_Hcblb.js} +1 -1
  41. package/payload/server/public/assets/{chunk-FOC6F5B3-B9QI3Guz.js → chunk-FOC6F5B3-CfCJNXmK.js} +1 -1
  42. package/payload/server/public/assets/{chunk-ICPOFSXX-BAr-Mv1Z.js → chunk-ICPOFSXX-xeu6qrZj.js} +2 -2
  43. package/payload/server/public/assets/{chunk-K5T4RW27-8PvAHasY.js → chunk-K5T4RW27-BQDCSuTh.js} +1 -1
  44. package/payload/server/public/assets/{chunk-KGLVRYIC--aGaDRH5.js → chunk-KGLVRYIC-D6fFAgbM.js} +1 -1
  45. package/payload/server/public/assets/{chunk-LIHQZDEY-BrWj7mw2.js → chunk-LIHQZDEY-Dskwlc-K.js} +1 -1
  46. package/payload/server/public/assets/{chunk-ORNJ4GCN-kYQmkMTi.js → chunk-ORNJ4GCN-CnHIrJeA.js} +1 -1
  47. package/payload/server/public/assets/{chunk-OYMX7WX6-CIsryCWH.js → chunk-OYMX7WX6-B4bnsPkv.js} +1 -1
  48. package/payload/server/public/assets/chunk-QZHKN3VN-COwe7oXR.js +1 -0
  49. package/payload/server/public/assets/{chunk-U2HBQHQK-68X653e3.js → chunk-U2HBQHQK-BeEXzOqV.js} +1 -1
  50. package/payload/server/public/assets/{chunk-X2U36JSP-v3v9soX3.js → chunk-X2U36JSP-D2rpgOqd.js} +1 -1
  51. package/payload/server/public/assets/{chunk-XPW4576I-CW5DPpop.js → chunk-XPW4576I-D-yT82Xf.js} +1 -1
  52. package/payload/server/public/assets/{chunk-YZCP3GAM-B1VP7Rl2.js → chunk-YZCP3GAM-DqxlLBm1.js} +1 -1
  53. package/payload/server/public/assets/{chunk-ZZ45TVLE-DiJrujNY.js → chunk-ZZ45TVLE-CA_Ep0OM.js} +1 -1
  54. package/payload/server/public/assets/classDiagram-6PBFFD2Q-wjL65qaU.js +1 -0
  55. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-D_EIplVd.js +1 -0
  56. package/payload/server/public/assets/clone-CEczy_Ef.js +1 -0
  57. package/payload/server/public/assets/{cose-bilkent-S5V4N54A-BscXxLMc.js → cose-bilkent-S5V4N54A-DWb9mxTa.js} +1 -1
  58. package/payload/server/public/assets/{dagre-MBv6WlCS.js → dagre-B3K7jxOZ.js} +1 -1
  59. package/payload/server/public/assets/{dagre-KV5264BT-DVgGlTQ1.js → dagre-KV5264BT-BhiTISRq.js} +1 -1
  60. package/payload/server/public/assets/data-B_vDxQrO.js +1 -0
  61. package/payload/server/public/assets/{diagram-5BDNPKRD-BmhCaO0a.js → diagram-5BDNPKRD-D5yBIDpm.js} +1 -1
  62. package/payload/server/public/assets/{diagram-G4DWMVQ6-ChU9L8vz.js → diagram-G4DWMVQ6-CSTE1S4d.js} +1 -1
  63. package/payload/server/public/assets/{diagram-MMDJMWI5-Oy409Zc_.js → diagram-MMDJMWI5-D8llv4XY.js} +1 -1
  64. package/payload/server/public/assets/{diagram-TYMM5635-Cn1YByqk.js → diagram-TYMM5635-CITQ7aDM.js} +1 -1
  65. package/payload/server/public/assets/{erDiagram-SMLLAGMA-e17yfLvr.js → erDiagram-SMLLAGMA-BjR5nlmv.js} +1 -1
  66. package/payload/server/public/assets/{flatten-Cl1Bc3dR.js → flatten-DhYYI_lo.js} +1 -1
  67. package/payload/server/public/assets/{flowDiagram-DWJPFMVM-Dqt7sCVZ.js → flowDiagram-DWJPFMVM-Dl6e-E0f.js} +1 -1
  68. package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-B4IhwS2r.js → ganttDiagram-T4ZO3ILL-CppkrFAl.js} +1 -1
  69. package/payload/server/public/assets/gitGraph-7Q5UKJZL-KHAc7IxG.js +1 -0
  70. package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-BDw-PKcI.js → gitGraphDiagram-UUTBAWPF-clV_tnwa.js} +1 -1
  71. package/payload/server/public/assets/{graph-DF_nLsTp.js → graph-ClQeGEH4.js} +3 -3
  72. package/payload/server/public/assets/{graph-labels-HWQ5J7S-.js → graph-labels-OaIKHgMg.js} +1 -1
  73. package/payload/server/public/assets/{graphlib-DPIYk_sg.js → graphlib-Cnk6WL-8.js} +1 -1
  74. package/payload/server/public/assets/info-OMHHGYJF-C6nm3sYf.js +1 -0
  75. package/payload/server/public/assets/infoDiagram-42DDH7IO-DhwCejsr.js +2 -0
  76. package/payload/server/public/assets/{isEmpty-D1pGOD1J.js → isEmpty-DGhq_DBP.js} +1 -1
  77. package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-BRIHsB3G.js → ishikawaDiagram-UXIWVN3A-DUqusmP1.js} +1 -1
  78. package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-aKNgmoHd.js → journeyDiagram-VCZTEJTY-RMEvGtDJ.js} +1 -1
  79. package/payload/server/public/assets/{kanban-definition-6JOO6SKY-cwBwT-nm.js → kanban-definition-6JOO6SKY-BxkwQPCP.js} +1 -1
  80. package/payload/server/public/assets/{line-DVtVRzUA.js → line-CiOuSBlJ.js} +1 -1
  81. package/payload/server/public/assets/{linear-DtoOFPO2.js → linear-D22sItNm.js} +1 -1
  82. package/payload/server/public/assets/{mermaid-parser.core-G7YD_zO3.js → mermaid-parser.core-kvN8ajT-.js} +2 -2
  83. package/payload/server/public/assets/{mermaid.core-DpFyndHm.js → mermaid.core-DKHTTwbg.js} +3 -3
  84. package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-CYXK_Pvz.js → mindmap-definition-QFDTVHPH-CKUJxwdG.js} +1 -1
  85. package/payload/server/public/assets/operator-Dxqfta5U.js +1 -0
  86. package/payload/server/public/assets/{ordinal-CBZeH4Yp.js → ordinal-CibZU3PM.js} +1 -1
  87. package/payload/server/public/assets/packet-4T2RLAQJ-z-APhyNH.js +1 -0
  88. package/payload/server/public/assets/page-BkIb7CHh.js +32 -0
  89. package/payload/server/public/assets/page-Dv_YEOUW.js +1 -0
  90. package/payload/server/public/assets/pie-ZZUOXDRM-D_HVZjir.js +1 -0
  91. package/payload/server/public/assets/{pieDiagram-DEJITSTG-DFo4N6WH.js → pieDiagram-DEJITSTG-CRMabeJN.js} +1 -1
  92. package/payload/server/public/assets/{public-NNHS6mWb.js → public-C_mM8sSZ.js} +1 -1
  93. package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-BlH5iIhl.js → quadrantDiagram-34T5L4WZ-DcrlhDuj.js} +1 -1
  94. package/payload/server/public/assets/radar-PYXPWWZC-DtKBIb3o.js +1 -0
  95. package/payload/server/public/assets/{reduce-PuPlFPRX.js → reduce-Da0RBva0.js} +1 -1
  96. package/payload/server/public/assets/{requirementDiagram-MS252O5E-D5WLty8A.js → requirementDiagram-MS252O5E-DP231rM_.js} +1 -1
  97. package/payload/server/public/assets/{rotate-ccw-CKSJX39F.js → rotate-ccw-VF0b6NTt.js} +1 -1
  98. package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-vB85IxHG.js → sankeyDiagram-XADWPNL6--HM5_dC8.js} +1 -1
  99. package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-Cxraa0Ee.js → sequenceDiagram-FGHM5R23-BsiVmDR9.js} +1 -1
  100. package/payload/server/public/assets/{stateDiagram-FHFEXIEX-BBPssYBx.js → stateDiagram-FHFEXIEX-Cjdhqdjh.js} +1 -1
  101. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-6v4alr7n.js +1 -0
  102. package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-Bgk6PT62.js → timeline-definition-GMOUNBTQ-Cf5xPmSA.js} +1 -1
  103. package/payload/server/public/assets/treeView-SZITEDCU-DbXWs029.js +1 -0
  104. package/payload/server/public/assets/treemap-W4RFUUIX-DUGgqAs9.js +1 -0
  105. package/payload/server/public/assets/useSubAccountSwitcher-CQbgG-FH.js +9 -0
  106. package/payload/server/public/assets/{useSubAccountSwitcher-Ca1GJeBC.css → useSubAccountSwitcher-VzvzZC7h.css} +1 -1
  107. package/payload/server/public/assets/{vennDiagram-DHZGUBPP-B-APTs3L.js → vennDiagram-DHZGUBPP-PCor55Sw.js} +1 -1
  108. package/payload/server/public/assets/wardley-RL74JXVD-Cjn85RON.js +1 -0
  109. package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-CkXJSs_i.js → wardleyDiagram-NUSXRM2D-bokCHsim.js} +1 -1
  110. package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-BkyshPMV.js → xychartDiagram-5P7HB3ND-B2YnsUoQ.js} +1 -1
  111. package/payload/server/public/browser.html +4 -4
  112. package/payload/server/public/calendar.html +4 -4
  113. package/payload/server/public/chat.html +7 -7
  114. package/payload/server/public/data.html +5 -4
  115. package/payload/server/public/graph.html +7 -7
  116. package/payload/server/public/index.html +8 -6
  117. package/payload/server/public/operator.html +9 -9
  118. package/payload/server/public/public.html +7 -7
  119. package/payload/server/server.js +289 -103
  120. package/payload/server/public/assets/AdminShell-CNQxSO9B.js +0 -1
  121. package/payload/server/public/assets/admin-Dfv2e8fn.js +0 -1
  122. package/payload/server/public/assets/architecture-YZFGNWBL-Dma4Bgha.js +0 -1
  123. package/payload/server/public/assets/calendar-CG-2rQ4m.js +0 -1
  124. package/payload/server/public/assets/channel-B_-5bau1.js +0 -1
  125. package/payload/server/public/assets/chat-CRPVhDCc.js +0 -1
  126. package/payload/server/public/assets/chunk-426QAEUC-Dirxdwjh.js +0 -1
  127. package/payload/server/public/assets/chunk-QZHKN3VN-Duipo1kI.js +0 -1
  128. package/payload/server/public/assets/classDiagram-6PBFFD2Q-B3kX5SuB.js +0 -1
  129. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-D761c7Lr.js +0 -1
  130. package/payload/server/public/assets/clone-BrhFv6Tb.js +0 -1
  131. package/payload/server/public/assets/data-Bodds4fv.js +0 -1
  132. package/payload/server/public/assets/gitGraph-7Q5UKJZL-BCQAqtLy.js +0 -1
  133. package/payload/server/public/assets/info-OMHHGYJF-qU7hK50T.js +0 -1
  134. package/payload/server/public/assets/infoDiagram-42DDH7IO-KGdcJeTs.js +0 -2
  135. package/payload/server/public/assets/operator-DH9OAMpe.js +0 -1
  136. package/payload/server/public/assets/packet-4T2RLAQJ-DiU2yS9m.js +0 -1
  137. package/payload/server/public/assets/page--Uj3qG5S.js +0 -32
  138. package/payload/server/public/assets/pie-ZZUOXDRM-zHUKKlVv.js +0 -1
  139. package/payload/server/public/assets/radar-PYXPWWZC-BUnVoaPg.js +0 -1
  140. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-BWmmUwDt.js +0 -1
  141. package/payload/server/public/assets/treeView-SZITEDCU-C3Y-Q52h.js +0 -1
  142. package/payload/server/public/assets/treemap-W4RFUUIX-Dk0qZpAg.js +0 -1
  143. package/payload/server/public/assets/useSubAccountSwitcher-DRITc7qp.js +0 -9
  144. package/payload/server/public/assets/wardley-RL74JXVD-BAWI02OA.js +0 -1
  145. /package/payload/server/public/assets/{_baseFor-brRjpUOX.js → _baseFor-BFYpZGkN.js} +0 -0
  146. /package/payload/server/public/assets/{array-BGFCBI0e.js → array-CYkMkqnU.js} +0 -0
  147. /package/payload/server/public/assets/{cytoscape.esm-TvRJ2tGX.js → cytoscape.esm-DqlHsaog.js} +0 -0
  148. /package/payload/server/public/assets/{defaultLocale-CRZydyG6.js → defaultLocale-Beh6XjaL.js} +0 -0
  149. /package/payload/server/public/assets/{dist-B0CkUodR.js → dist-BMqkacmt.js} +0 -0
  150. /package/payload/server/public/assets/{init-B8gtcn7T.js → init-Rr1s_RiX.js} +0 -0
  151. /package/payload/server/public/assets/{katex-RxgSu_dy.js → katex-pVJiI_rc.js} +0 -0
  152. /package/payload/server/public/assets/{path-DZF-JdEe.js → path-BAQ3hXlG.js} +0 -0
  153. /package/payload/server/public/assets/{preload-helper-CQ36nxok.js → preload-helper-B_l5jfgx.js} +0 -0
  154. /package/payload/server/public/assets/{rough.esm-6CnTHTkH.js → rough.esm-nHaDi0Kw.js} +0 -0
  155. /package/payload/server/public/assets/{src-CR_MU8uy.js → src-CsEKjNXD.js} +0 -0
@@ -41,6 +41,7 @@ import {
41
41
  embed,
42
42
  emitMissingOnResolve,
43
43
  ensureConversation,
44
+ fetchAccountName,
44
45
  fetchBranding,
45
46
  findMissingPlugins,
46
47
  findRecentConversation,
@@ -71,7 +72,6 @@ import {
71
72
  loadAdminUserName,
72
73
  loadPersonNameByElementId,
73
74
  loadUserProfile,
74
- loadWhatsappSenderName,
75
75
  migrateLegacyRemotePassword,
76
76
  persistMessage,
77
77
  projectAgent,
@@ -109,7 +109,7 @@ import {
109
109
  vncLog,
110
110
  walkPremiumBundles,
111
111
  writeAdminUserAndPerson
112
- } from "./chunk-Y4SHSFGK.js";
112
+ } from "./chunk-ZYS5V5QG.js";
113
113
  import {
114
114
  __commonJS,
115
115
  __toESM
@@ -1868,6 +1868,24 @@ function readSelfId(authDir) {
1868
1868
  return { e164: null, jid: null, lid: null };
1869
1869
  }
1870
1870
  }
1871
+ function credsCensus(authDir) {
1872
+ const raw = readCredsJsonRaw(resolveCredsPath(authDir));
1873
+ if (!raw) return { credsPresent: false, registered: false, hasAccountSignature: false, e164: null };
1874
+ try {
1875
+ const parsed = JSON.parse(raw);
1876
+ const registered = parsed?.registered === true;
1877
+ const hasAccountSignature = parsed?.account != null;
1878
+ let e164 = null;
1879
+ const jid = parsed?.me?.id;
1880
+ if (jid) {
1881
+ const match = jid.match(/^(\d+)(?::\d+)?@s\.whatsapp\.net$/i);
1882
+ if (match) e164 = match[1];
1883
+ }
1884
+ return { credsPresent: true, registered, hasAccountSignature, e164 };
1885
+ } catch {
1886
+ return { credsPresent: true, registered: false, hasAccountSignature: false, e164: null };
1887
+ }
1888
+ }
1871
1889
  async function clearAuth(authDir) {
1872
1890
  try {
1873
1891
  await fs.access(authDir);
@@ -2026,13 +2044,22 @@ function enqueueSaveCreds(authDir, saveCreds) {
2026
2044
  });
2027
2045
  }
2028
2046
  async function createWaSocket(opts) {
2029
- const { authDir, onQr, onConnectionUpdate, silent } = opts;
2047
+ const { authDir, onQr, onConnectionUpdate, silent, correlationId, account, getCodeIssuedTs } = opts;
2048
+ const cid = correlationId ?? "none";
2049
+ const acct = account ?? "unknown";
2030
2050
  await fs2.mkdir(authDir, { recursive: true });
2031
2051
  maybeRestoreCredsFromBackup(authDir);
2032
2052
  const { state, saveCreds } = await useMultiFileAuthState(authDir);
2033
2053
  const { version } = await fetchLatestBaileysVersion();
2054
+ if (!silent) {
2055
+ const preCensus = credsCensus(authDir);
2056
+ console.error(
2057
+ `${TAG2} op=creds-pre cid=${cid} account=${acct} credsPresent=${preCensus.credsPresent} registered=${preCensus.registered} hasAccount=${preCensus.hasAccountSignature}`
2058
+ );
2059
+ }
2060
+ const openTs = Date.now();
2034
2061
  console.error(
2035
- `${TAG2} creating socket authDir=${authDir} baileysVersion=${baileysPkgVersion} waProtocolVersion=${version.join(".")}`
2062
+ `${TAG2} op=socket-open cid=${cid} account=${acct} baileysVersion=${baileysPkgVersion} waProtocolVersion=${version.join(".")} openTs=${openTs}`
2036
2063
  );
2037
2064
  const baileysLogger = createBaileysLogger();
2038
2065
  const sock = makeWASocket({
@@ -2053,6 +2080,9 @@ async function createWaSocket(opts) {
2053
2080
  enqueueSaveCreds(authDir, saveCreds);
2054
2081
  });
2055
2082
  let qrSequence = 0;
2083
+ let everOpen = false;
2084
+ let lastQrTs = 0;
2085
+ let pairSuccessLogged = false;
2056
2086
  sock.ev.on("connection.update", (update) => {
2057
2087
  try {
2058
2088
  const parts = [];
@@ -2068,17 +2098,40 @@ async function createWaSocket(opts) {
2068
2098
  if (!silent && parts.length > 0) {
2069
2099
  console.error(`${TAG2} connection.update ${parts.join(" ")}`);
2070
2100
  }
2101
+ if (update.qr && !silent) {
2102
+ const now = Date.now();
2103
+ const sinceLastRefMs = lastQrTs ? now - lastQrTs : null;
2104
+ lastQrTs = now;
2105
+ console.error(
2106
+ `${TAG2} op=qr cid=${cid} qr=#${qrSequence} sinceOpenMs=${now - openTs} sinceLastRefMs=${sinceLastRefMs ?? "n/a"}`
2107
+ );
2108
+ }
2109
+ if (update.isNewLogin === true && !pairSuccessLogged && !silent) {
2110
+ pairSuccessLogged = true;
2111
+ const codeIssuedTs = getCodeIssuedTs?.();
2112
+ const sinceCodeIssuedMs = codeIssuedTs ? Date.now() - codeIssuedTs : null;
2113
+ const afterCensus = credsCensus(authDir);
2114
+ console.error(
2115
+ `${TAG2} op=pair-success cid=${cid} account=${acct} sinceCodeIssuedMs=${sinceCodeIssuedMs ?? "n/a"} hasAccountAfter=${afterCensus.hasAccountSignature}`
2116
+ );
2117
+ }
2071
2118
  if (update.qr && onQr) {
2072
2119
  onQr(update.qr);
2073
2120
  }
2074
2121
  if (update.connection === "close") {
2075
2122
  const status = getStatusCode(update.lastDisconnect?.error);
2123
+ if (!silent) {
2124
+ console.error(
2125
+ `${TAG2} op=close cid=${cid} account=${acct} status=${status ?? "unknown"} reason="${formatError(update.lastDisconnect?.error)}" socketLifeMs=${Date.now() - openTs} kind=${closeKind(status, everOpen)}`
2126
+ );
2127
+ }
2076
2128
  if (status === DisconnectReason.loggedOut && !silent) {
2077
2129
  console.error(`${TAG2} session logged out (401) \u2014 re-link required`);
2078
2130
  }
2079
2131
  }
2080
- if (update.connection === "open" && !silent) {
2081
- console.error(`${TAG2} connected`);
2132
+ if (update.connection === "open") {
2133
+ everOpen = true;
2134
+ if (!silent) console.error(`${TAG2} connected`);
2082
2135
  }
2083
2136
  onConnectionUpdate?.(update);
2084
2137
  } catch (err) {
@@ -2142,6 +2195,12 @@ function extractBoomDetails(err) {
2142
2195
  if (!statusCode && !error && !message) return null;
2143
2196
  return { statusCode, error, message };
2144
2197
  }
2198
+ function closeKind(status, everOpen) {
2199
+ if (status === DisconnectReason.restartRequired) return "restart-required-515";
2200
+ if (status === DisconnectReason.loggedOut) return "logged-out-401";
2201
+ if (status === 408) return everOpen ? "conn-lost-408" : "qr-refs-ended-408";
2202
+ return "other";
2203
+ }
2145
2204
 
2146
2205
  // app/lib/whatsapp/reconnect.ts
2147
2206
  import { DisconnectReason as DisconnectReason2 } from "@whiskeysockets/baileys";
@@ -3101,6 +3160,9 @@ var STORE_ROOT = () => join3(process.env.MAXY_DIR_OVERRIDE ?? MAXY_DIR, "data",
3101
3160
  function conversationFile(platformAccountId, remoteJid) {
3102
3161
  return join3(STORE_ROOT(), platformAccountId, `${remoteJid}.jsonl`);
3103
3162
  }
3163
+ function conversationFilePath(platformAccountId, remoteJid) {
3164
+ return conversationFile(platformAccountId, remoteJid);
3165
+ }
3104
3166
  function parseLines(raw) {
3105
3167
  const out = [];
3106
3168
  for (const line of raw.split("\n")) {
@@ -6054,6 +6116,13 @@ async function runPostPairing(login) {
6054
6116
  }
6055
6117
  async function loginConnectionLoop(accountId, login) {
6056
6118
  let attempt = 0;
6119
+ const cidShort = login.id.slice(0, 8);
6120
+ const logTerminal = (outcome, errMsg) => {
6121
+ const fc = credsCensus(login.authDir);
6122
+ console.error(
6123
+ `${TAG17} op=terminal cid=${cidShort} outcome=${outcome} credsFinal={registered=${fc.registered},account=${fc.hasAccountSignature},me=${fc.e164 ?? "null"}}` + (errMsg ? ` error="${errMsg}"` : "")
6124
+ );
6125
+ };
6057
6126
  while (true) {
6058
6127
  try {
6059
6128
  await waitForConnection(login.sock);
@@ -6062,6 +6131,7 @@ async function loginConnectionLoop(accountId, login) {
6062
6131
  await runPostPairing(current);
6063
6132
  current.connected = true;
6064
6133
  console.error(`${TAG17} loginConnectionLoop: connected account=${accountId} attempt=${attempt} configPersisted=${current.configPersisted}`);
6134
+ logTerminal("connected");
6065
6135
  }
6066
6136
  return;
6067
6137
  } catch (err) {
@@ -6078,6 +6148,7 @@ async function loginConnectionLoop(accountId, login) {
6078
6148
  current.error = formatError(err);
6079
6149
  }
6080
6150
  current.errorStatus = getStatusCode(err);
6151
+ logTerminal("error", current.error);
6081
6152
  return;
6082
6153
  }
6083
6154
  attempt++;
@@ -6089,14 +6160,19 @@ async function loginConnectionLoop(accountId, login) {
6089
6160
  await new Promise((r) => setTimeout(r, delay));
6090
6161
  const afterDelay = activeLogins.get(accountId);
6091
6162
  if (afterDelay?.id !== login.id) return;
6163
+ const rc = credsCensus(login.authDir);
6164
+ console.error(
6165
+ `${TAG17} op=reconnect cid=${cidShort} attempt=${attempt}/${LOGIN_MAX_RECONNECTS} withRegistered=${rc.registered} withAccount=${rc.hasAccountSignature}`
6166
+ );
6092
6167
  try {
6093
- const newSock = await createWaSocket({ authDir: login.authDir });
6168
+ const newSock = await createWaSocket({ authDir: login.authDir, correlationId: cidShort, account: accountId });
6094
6169
  current.sock = newSock;
6095
6170
  } catch (sockErr) {
6096
6171
  console.error(
6097
6172
  `${TAG17} reconnect socket creation failed (attempt ${attempt}/${LOGIN_MAX_RECONNECTS}): ${String(sockErr)}`
6098
6173
  );
6099
6174
  current.error = `Reconnection failed: ${String(sockErr)}`;
6175
+ logTerminal("error", current.error);
6100
6176
  return;
6101
6177
  }
6102
6178
  }
@@ -6104,11 +6180,13 @@ async function loginConnectionLoop(accountId, login) {
6104
6180
  }
6105
6181
  async function startLogin(opts) {
6106
6182
  const { accountId, authDir, phone, accountDir = null, force, timeoutMs = 3e4 } = opts;
6183
+ const loginId = randomUUID6();
6184
+ const cid = loginId.slice(0, 8);
6107
6185
  const existing0 = activeLogins.get(accountId);
6108
6186
  const hasAuth = await authExists(authDir);
6109
6187
  const selfId = readSelfId(authDir);
6110
6188
  console.error(
6111
- `${TAG17} startLogin account=${accountId} force=${!!force} hasAuth=${hasAuth}` + (existing0 ? ` activeLogin={id=${existing0.id.slice(0, 8)},age=${Math.round((Date.now() - existing0.startedAt) / 1e3)}s,hasCode=${!!existing0.pairingCode}}` : " activeLogin=none")
6189
+ `${TAG17} op=start cid=${cid} account=${accountId} force=${!!force} hasAuth=${hasAuth}` + (existing0 ? ` activeLogin={id=${existing0.id.slice(0, 8)},age=${Math.round((Date.now() - existing0.startedAt) / 1e3)}s,hasCode=${!!existing0.pairingCode}}` : " activeLogin=none")
6112
6190
  );
6113
6191
  if (hasAuth && !force) {
6114
6192
  const who = selfId.e164 ?? selfId.jid ?? "unknown";
@@ -6147,21 +6225,32 @@ async function startLogin(opts) {
6147
6225
  );
6148
6226
  let requested = false;
6149
6227
  let sock;
6228
+ let socketOpenTs = 0;
6229
+ let codeIssuedTs;
6150
6230
  try {
6151
6231
  sock = await createWaSocket({
6152
6232
  authDir,
6233
+ correlationId: cid,
6234
+ account: accountId,
6235
+ getCodeIssuedTs: () => codeIssuedTs,
6153
6236
  // The first QR event means the noise handshake is complete and the
6154
6237
  // socket can send the pairing IQ — the safe moment to request the code.
6155
6238
  // We never render the QR; it is only a readiness signal.
6156
6239
  onQr: () => {
6157
6240
  if (requested) return;
6158
6241
  requested = true;
6242
+ console.error(
6243
+ `${TAG17} op=pairing-request cid=${cid} account=${accountId} qrRef=#1 sinceOpenMs=${socketOpenTs ? Date.now() - socketOpenTs : 0}`
6244
+ );
6159
6245
  void sock.requestPairingCode(digits).then((code) => {
6160
6246
  clearTimeout(codeTimer);
6247
+ codeIssuedTs = Date.now();
6161
6248
  const current = activeLogins.get(accountId);
6162
6249
  if (current?.id !== login.id) return;
6163
6250
  if (!current.pairingCode) current.pairingCode = code;
6164
- console.error(`${TAG17} pairing-code-issued account=${accountId} phone=${maskPhone(digits)} codeLen=${code.length}`);
6251
+ console.error(
6252
+ `${TAG17} op=code-issued cid=${cid} account=${accountId} phone=${maskPhone(digits)} codeLen=${code.length} sinceOpenMs=${socketOpenTs ? codeIssuedTs - socketOpenTs : 0}`
6253
+ );
6165
6254
  resolveCode?.(code);
6166
6255
  }).catch((err) => {
6167
6256
  clearTimeout(codeTimer);
@@ -6169,6 +6258,7 @@ async function startLogin(opts) {
6169
6258
  });
6170
6259
  }
6171
6260
  });
6261
+ socketOpenTs = Date.now();
6172
6262
  } catch (err) {
6173
6263
  clearTimeout(codeTimer);
6174
6264
  resetActiveLogin(accountId);
@@ -6178,7 +6268,7 @@ async function startLogin(opts) {
6178
6268
  accountId,
6179
6269
  authDir,
6180
6270
  accountDir,
6181
- id: randomUUID6(),
6271
+ id: loginId,
6182
6272
  sock,
6183
6273
  startedAt: Date.now(),
6184
6274
  phone: digits,
@@ -6473,6 +6563,10 @@ function reconcileCredsOnDisk(opts) {
6473
6563
  for (const accountId of listCredsAccountIds(credsRoot)) {
6474
6564
  if (liveAccountIds.has(accountId)) continue;
6475
6565
  const authDir = join9(credsRoot, accountId);
6566
+ const census = credsCensus(authDir);
6567
+ if (census.registered && !census.hasAccountSignature) {
6568
+ console.error(`${TAG19} op=half-registered account=${accountId} registered=true hasAccount=false`);
6569
+ }
6476
6570
  const selfPhone = readSelfId(authDir).e164 ?? void 0;
6477
6571
  const configured = accountDir ? isAccountConfigured(accountDir, accountId) : false;
6478
6572
  console.error(
@@ -6946,9 +7040,39 @@ function selectReaderChannelSessions(rows) {
6946
7040
  lastMessageAt: r.lastMessageAt,
6947
7041
  modelGated: r.modelGated,
6948
7042
  model: r.model,
6949
- rowType: "session"
7043
+ source: "session"
6950
7044
  }));
6951
7045
  }
7046
+ function buildStoreConversationRows(accountId, convos) {
7047
+ const rows = [];
7048
+ for (const [remoteJid, messages] of convos) {
7049
+ if (messages.length === 0) continue;
7050
+ const last = messages[messages.length - 1];
7051
+ const scope = last.scope;
7052
+ const isGroup = remoteJid.endsWith("@g.us");
7053
+ const senderTelephone = isGroup ? null : messages[0].senderTelephone;
7054
+ const senderName = messages.find((m) => m.senderName)?.senderName ?? null;
7055
+ rows.push({
7056
+ sessionId: "",
7057
+ projectDir: "",
7058
+ title: remoteJid,
7059
+ senderId: senderTelephone,
7060
+ startedAt: messages[0].dateSent,
7061
+ channel: "whatsapp",
7062
+ role: scope === "admin" ? "admin" : "public",
7063
+ operatorName: null,
7064
+ whatsappName: senderName,
7065
+ lastMessageAt: last.dateSent,
7066
+ modelGated: false,
7067
+ model: null,
7068
+ source: "store",
7069
+ accountId,
7070
+ remoteJid,
7071
+ scope
7072
+ });
7073
+ }
7074
+ return rows.sort((a, b) => (b.lastMessageAt ?? "").localeCompare(a.lastMessageAt ?? ""));
7075
+ }
6952
7076
 
6953
7077
  // server/routes/admin/sidebar-sessions.ts
6954
7078
  var SESSION_ID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\.jsonl$/i;
@@ -7743,7 +7867,7 @@ app4.get("/conversations", requireAdminSession, async (c) => {
7743
7867
  model: lastAssistantModel(body)
7744
7868
  });
7745
7869
  }
7746
- const selected = selectReaderChannelSessions(rows);
7870
+ const sessionRows = selectReaderChannelSessions(rows).filter((r) => r.channel !== "whatsapp");
7747
7871
  const account = resolveAccount();
7748
7872
  let users = [];
7749
7873
  if (account) {
@@ -7756,13 +7880,11 @@ app4.get("/conversations", requireAdminSession, async (c) => {
7756
7880
  }
7757
7881
  const admins = account?.config.admins ?? [];
7758
7882
  const nameBySender = /* @__PURE__ */ new Map();
7759
- const whatsappNameBySender = /* @__PURE__ */ new Map();
7760
- const distinct = [...new Set(selected.map((r) => r.senderId).filter((s) => !!s))];
7883
+ const distinct = [...new Set(sessionRows.map((r) => r.senderId).filter((s) => !!s))];
7761
7884
  await Promise.all(
7762
7885
  distinct.map(async (senderId) => {
7763
7886
  if (!account) {
7764
7887
  nameBySender.set(senderId, null);
7765
- whatsappNameBySender.set(senderId, null);
7766
7888
  return;
7767
7889
  }
7768
7890
  const idRes = classifyAdminUserId(users, admins, senderId);
@@ -7770,57 +7892,19 @@ app4.get("/conversations", requireAdminSession, async (c) => {
7770
7892
  const { name, reason } = resolveOperatorDisplay(idRes, nameRes);
7771
7893
  if (reason) console.error(`[wa-reader] op=operator-unresolved senderId=${senderId} reason=${reason}`);
7772
7894
  nameBySender.set(senderId, name);
7773
- if (!name) {
7774
- const waName = await loadWhatsappSenderName(account.accountId, senderId);
7775
- if (waName) console.error(`[wa-reader] op=operator-name-fallback senderId=${senderId} source=whatsapp-pushname`);
7776
- whatsappNameBySender.set(senderId, waName);
7777
- } else {
7778
- whatsappNameBySender.set(senderId, null);
7779
- }
7780
7895
  })
7781
7896
  );
7782
- const conversations = selected.map((r) => ({
7897
+ const sessionConversations = sessionRows.map((r) => ({
7783
7898
  ...r,
7784
- operatorName: r.senderId ? nameBySender.get(r.senderId) ?? null : null,
7785
- whatsappName: r.senderId ? whatsappNameBySender.get(r.senderId) ?? null : null,
7786
- rowType: "session"
7899
+ operatorName: r.senderId ? nameBySender.get(r.senderId) ?? null : null
7787
7900
  }));
7788
- const includePersistedOnly = c.req.query("includePersistedOnly") === "1";
7789
- let persistedOnlyRows = [];
7790
- if (includePersistedOnly && account) {
7791
- const allConvos = readAllConversations(account.accountId);
7792
- const coveredSenderIds = new Set(
7793
- conversations.filter((cv) => cv.role === "public" && cv.channel === "whatsapp" && cv.senderId).map((cv) => cv.senderId)
7794
- );
7795
- for (const [remoteJid, messages] of allConvos) {
7796
- if (messages.length === 0) continue;
7797
- const isGroup = remoteJid.endsWith("@g.us");
7798
- const senderTelephone = isGroup ? null : messages[0].senderTelephone;
7799
- if (!isGroup && senderTelephone && coveredSenderIds.has(senderTelephone)) continue;
7800
- const last = messages[messages.length - 1];
7801
- const resolvedName = isGroup ? null : messages.find((m) => m.senderName)?.senderName ?? null;
7802
- persistedOnlyRows.push({
7803
- sessionId: `persisted:${account.accountId}:${remoteJid}`,
7804
- projectDir: "",
7805
- title: remoteJid,
7806
- senderId: senderTelephone,
7807
- startedAt: messages[0].dateSent,
7808
- channel: "whatsapp",
7809
- role: "public",
7810
- operatorName: null,
7811
- whatsappName: resolvedName,
7812
- lastMessageAt: last.dateSent,
7813
- modelGated: false,
7814
- model: null,
7815
- rowType: "persisted-only",
7816
- accountId: account.accountId,
7817
- remoteJid
7818
- });
7819
- }
7820
- }
7821
- const allRows = [...conversations, ...persistedOnlyRows];
7822
- console.log(`[wa-reader] op=full-list accountId=${account?.accountId ?? "null"} sessionRows=${conversations.length} persistedOnlyRows=${persistedOnlyRows.length}`);
7823
- return c.json({ conversations: allRows });
7901
+ const storeRows = account ? buildStoreConversationRows(account.accountId, readAllConversations(account.accountId)) : [];
7902
+ const adminScope = storeRows.filter((r) => r.scope === "admin").length;
7903
+ const publicScope = storeRows.length - adminScope;
7904
+ console.log(
7905
+ `[wa-reader] op=list accountId=${account?.accountId ?? "null"} conversations=${storeRows.length} adminScope=${adminScope} publicScope=${publicScope}`
7906
+ );
7907
+ return c.json({ conversations: [...sessionConversations, ...storeRows] });
7824
7908
  });
7825
7909
  function readFrom(path2, from) {
7826
7910
  const end = statSync4(path2).size;
@@ -8160,7 +8244,7 @@ app4.get("/directive", requireAdminSession, (c) => {
8160
8244
  }
8161
8245
  return c.text(body);
8162
8246
  });
8163
- app4.get("/persisted-messages", requireAdminSession, async (c) => {
8247
+ app4.get("/store-stream", requireAdminSession, (c) => {
8164
8248
  const accountIdRaw = c.req.query("accountId");
8165
8249
  const remoteJid = c.req.query("remoteJid");
8166
8250
  if (!accountIdRaw || !remoteJid) {
@@ -8175,16 +8259,108 @@ app4.get("/persisted-messages", requireAdminSession, async (c) => {
8175
8259
  if (!isUserJid(remoteJid) && !isGroupJid(remoteJid)) {
8176
8260
  return c.json({ error: "invalid remoteJid" }, 400);
8177
8261
  }
8178
- const messages = readConversation(accountId, remoteJid);
8179
- const turns = messages.map((m) => ({
8262
+ const file = conversationFilePath(accountId, remoteJid);
8263
+ const encoder = new TextEncoder();
8264
+ const connId = `${remoteJid.slice(0, 12)}-${process.hrtime.bigint().toString(36).slice(-6)}`;
8265
+ const startedAt = Date.now();
8266
+ const lastEventId = c.req.header("Last-Event-ID");
8267
+ const toTurn = (r) => ({
8180
8268
  kind: "whatsapp-persisted",
8181
- text: m.body,
8182
- ts: m.dateSent,
8183
- fromMe: m.fromMe,
8184
- senderName: m.senderName
8185
- }));
8186
- console.log(`[wa-reader] op=persisted-messages accountId=${accountId} remoteJid=${remoteJid} count=${turns.length}`);
8187
- return c.json({ turns });
8269
+ text: r.body,
8270
+ ts: r.dateSent,
8271
+ fromMe: r.fromMe,
8272
+ senderName: r.senderName
8273
+ });
8274
+ const readable = new ReadableStream({
8275
+ start(controller) {
8276
+ const send = (turn, id) => {
8277
+ try {
8278
+ controller.enqueue(encoder.encode(`id: ${id}
8279
+ data: ${JSON.stringify(turn)}
8280
+
8281
+ `));
8282
+ } catch {
8283
+ }
8284
+ };
8285
+ const fileEnd0 = (() => {
8286
+ try {
8287
+ return statSync4(file).size;
8288
+ } catch {
8289
+ return 0;
8290
+ }
8291
+ })();
8292
+ let offset = resumeOffset(lastEventId, fileEnd0);
8293
+ if (offset === 0) {
8294
+ const records = [];
8295
+ try {
8296
+ const { buf, end } = readFrom(file, 0);
8297
+ offset = end;
8298
+ for (const line of buf.toString("utf8").split("\n")) {
8299
+ if (!line.trim()) continue;
8300
+ try {
8301
+ records.push(JSON.parse(line));
8302
+ } catch {
8303
+ }
8304
+ }
8305
+ } catch {
8306
+ offset = fileEnd0;
8307
+ }
8308
+ records.sort((a, b) => a.dateSent.localeCompare(b.dateSent));
8309
+ const scope = records.length ? records[records.length - 1].scope : "none";
8310
+ for (const m of records) send(toTurn(m), offset);
8311
+ console.log(
8312
+ `[wa-reader] op=open remoteJid=${remoteJid} scope=${scope} messages=${records.length} source=store`
8313
+ );
8314
+ }
8315
+ const drain = () => {
8316
+ try {
8317
+ const { buf, end } = readFrom(file, offset);
8318
+ if (end <= offset) return;
8319
+ const { lines, nextOffset } = splitNewLines(buf, offset);
8320
+ offset = nextOffset;
8321
+ let n = 0;
8322
+ for (const line of lines) {
8323
+ if (!line.trim()) continue;
8324
+ let rec;
8325
+ try {
8326
+ rec = JSON.parse(line);
8327
+ } catch {
8328
+ continue;
8329
+ }
8330
+ send(toTurn(rec), offset);
8331
+ n++;
8332
+ }
8333
+ if (n > 0) console.log(`[wa-reader] op=store-drain conn=${connId} turns=${n}`);
8334
+ } catch {
8335
+ }
8336
+ };
8337
+ let watcher = null;
8338
+ try {
8339
+ watcher = watch(file, drain);
8340
+ } catch {
8341
+ }
8342
+ const poll = setInterval(drain, 1e3);
8343
+ const heartbeat = setInterval(() => {
8344
+ try {
8345
+ controller.enqueue(encoder.encode(": ping\n\n"));
8346
+ } catch {
8347
+ }
8348
+ }, 2e4);
8349
+ c.req.raw.signal.addEventListener("abort", () => {
8350
+ watcher?.close();
8351
+ clearInterval(poll);
8352
+ clearInterval(heartbeat);
8353
+ console.log(`[wa-reader] op=store-close conn=${connId} ranMs=${Date.now() - startedAt}`);
8354
+ try {
8355
+ controller.close();
8356
+ } catch {
8357
+ }
8358
+ });
8359
+ }
8360
+ });
8361
+ return new Response(readable, {
8362
+ headers: { "Content-Type": "text/event-stream", "Cache-Control": "no-cache", Connection: "keep-alive" }
8363
+ });
8188
8364
  });
8189
8365
  var whatsapp_reader_default = app4;
8190
8366
 
@@ -8714,9 +8890,9 @@ var WEBCHAT_ADMIN_KEY = "webchat-admin";
8714
8890
  var UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
8715
8891
  function locateSession(sessionId) {
8716
8892
  const dir = findSessionProjectDir(sessionId);
8717
- if (!dir) return { projectDir: null, channel: null };
8893
+ if (!dir) return { projectDir: null, channel: null, accountId: null };
8718
8894
  const meta = readSidecarMeta(join18(dir, `${sessionId}.meta.json`));
8719
- return { projectDir: dir, channel: meta.channel };
8895
+ return { projectDir: dir, channel: meta.channel, accountId: meta.accountId };
8720
8896
  }
8721
8897
  function locateSidecar(sessionId) {
8722
8898
  const cfg = claudeConfigDir();
@@ -8732,7 +8908,7 @@ function locateSidecar(sessionId) {
8732
8908
  const metaPath = join18(projectsRoot, slug, `${sessionId}.meta.json`);
8733
8909
  if (existsSync10(metaPath)) {
8734
8910
  const meta = readSidecarMeta(metaPath);
8735
- return { channel: meta.channel, adminUserId: meta.adminUserId };
8911
+ return { channel: meta.channel, adminUserId: meta.adminUserId, accountId: meta.accountId };
8736
8912
  }
8737
8913
  }
8738
8914
  return null;
@@ -9010,6 +9186,7 @@ function createWebchatRoutes(deps) {
9010
9186
  }
9011
9187
  let deliveryKey = WEBCHAT_ADMIN_KEY;
9012
9188
  let deliverySessionId;
9189
+ let deliveryAccountId = accountId;
9013
9190
  const explicitTarget = target !== void 0;
9014
9191
  if (target === void 0) {
9015
9192
  const latest = latestAdminWebchatSessionId(requesterUserId, primaryUserId, scopeAccountId, multiAccount);
@@ -9022,7 +9199,7 @@ function createWebchatRoutes(deps) {
9022
9199
  }
9023
9200
  }
9024
9201
  if (target !== void 0) {
9025
- let { projectDir, channel } = locateSession(target);
9202
+ let { projectDir, channel, accountId: sessionAccountId } = locateSession(target);
9026
9203
  if (projectDir === null) {
9027
9204
  const sidecar = locateSidecar(target);
9028
9205
  if (sidecar === null) {
@@ -9030,6 +9207,7 @@ function createWebchatRoutes(deps) {
9030
9207
  return c.json({ error: "session not found" }, 404);
9031
9208
  }
9032
9209
  channel = sidecar.channel;
9210
+ sessionAccountId = sidecar.accountId;
9033
9211
  }
9034
9212
  const binding = conflictingBinding(channel);
9035
9213
  if (binding !== null) {
@@ -9038,6 +9216,7 @@ function createWebchatRoutes(deps) {
9038
9216
  }
9039
9217
  deliveryKey = `session:${target}`;
9040
9218
  deliverySessionId = target;
9219
+ deliveryAccountId = sessionAccountId ?? accountId;
9041
9220
  }
9042
9221
  if (isMultipart) {
9043
9222
  const kind = files.some((f) => isAudioMime(f.type)) ? "voice" : "files";
@@ -9114,7 +9293,7 @@ ${note}` : note;
9114
9293
  }
9115
9294
  const adminUserId = requesterUserId ?? void 0;
9116
9295
  if (deliverySessionId !== void 0) {
9117
- await deps.handleInbound({ role: "admin", accountId, key: deliveryKey, text, sessionId: deliverySessionId, adminUserId });
9296
+ await deps.handleInbound({ role: "admin", accountId: deliveryAccountId, key: deliveryKey, text, sessionId: deliverySessionId, adminUserId });
9118
9297
  } else {
9119
9298
  await deps.handleInbound({ role: "admin", accountId: bootstrapAccountId, key: deliveryKey, text, adminUserId });
9120
9299
  }
@@ -10443,12 +10622,7 @@ async function createAdminSession(accountId, thinkingView, userId, userName, rol
10443
10622
  const cacheKey = fingerprintSessionKey(signedSessionToken);
10444
10623
  registerSession(cacheKey, "admin", accountId, void 0, userId, userName, role);
10445
10624
  if (userId) setWantsPriorConversation(cacheKey);
10446
- let businessName;
10447
- try {
10448
- const branding = await fetchBranding(accountId);
10449
- businessName = branding?.name || void 0;
10450
- } catch {
10451
- }
10625
+ const businessName = await fetchAccountName(accountId) || void 0;
10452
10626
  let initialSessionId = null;
10453
10627
  try {
10454
10628
  const ensured = await ensureConversation(
@@ -10486,12 +10660,7 @@ function operatorRoleFor(config, userId) {
10486
10660
  async function buildAccountOptionList(accounts, userId) {
10487
10661
  return Promise.all(
10488
10662
  accounts.map(async (a) => {
10489
- let businessName;
10490
- try {
10491
- const branding = await fetchBranding(a.accountId);
10492
- businessName = branding?.name || void 0;
10493
- } catch {
10494
- }
10663
+ const businessName = await fetchAccountName(a.accountId) || void 0;
10495
10664
  return { accountId: a.accountId, businessName, role: operatorRoleFor(a.config, userId) };
10496
10665
  })
10497
10666
  );
@@ -10512,12 +10681,7 @@ app11.get("/", async (c) => {
10512
10681
  }
10513
10682
  const account = resolveAccount();
10514
10683
  const thinkingView = account?.config.thinkingView ?? "default";
10515
- let businessName;
10516
- try {
10517
- const branding = await fetchBranding(accountId);
10518
- businessName = branding?.name || void 0;
10519
- } catch {
10520
- }
10684
+ const businessName = await fetchAccountName(accountId) || void 0;
10521
10685
  const role = getRoleForSession(cacheKey);
10522
10686
  console.log(`[admin-session] role=${role ?? "null"} cacheKey=${cacheKey.slice(0, 8)} phase=restore`);
10523
10687
  const restoredUserId = getUserIdForSession(cacheKey);
@@ -16292,8 +16456,10 @@ app29.post("/", requireAdminSession, async (c) => {
16292
16456
  return c.json({ error: "sessionId must be a v4 UUID" }, 400);
16293
16457
  }
16294
16458
  const base = managerBase("session-delete:wrapper");
16459
+ const accountId = getAccountIdForSession(c.var.cacheKey);
16460
+ const acctQuery = accountId ? `?accountId=${encodeURIComponent(accountId)}` : "";
16295
16461
  try {
16296
- const stop = await fetch(`${base}/${sessionId}/stop`, { method: "POST" });
16462
+ const stop = await fetch(`${base}/${sessionId}/stop${acctQuery}`, { method: "POST" });
16297
16463
  if (stop.status !== 204 && stop.status !== 200 && stop.status !== 404) {
16298
16464
  console.error(`[session-delete] sessionId=${sessionId} stop-status=${stop.status}`);
16299
16465
  return c.json({ error: `stop-failed-${stop.status}` }, 502);
@@ -16304,7 +16470,7 @@ app29.post("/", requireAdminSession, async (c) => {
16304
16470
  }
16305
16471
  let del;
16306
16472
  try {
16307
- del = await fetch(`${base}/${sessionId}`, { method: "DELETE" });
16473
+ del = await fetch(`${base}/${sessionId}${acctQuery}`, { method: "DELETE" });
16308
16474
  } catch (err) {
16309
16475
  console.error(`[session-delete] sessionId=${sessionId} delete-unreachable err=${err instanceof Error ? err.message : String(err)}`);
16310
16476
  return c.json({ error: "manager-unreachable" }, 502);
@@ -16333,9 +16499,11 @@ app30.post("/", requireAdminSession, async (c) => {
16333
16499
  if (!SESSION_ID_RE2.test(sessionId)) {
16334
16500
  return c.json({ error: "sessionId must be a v4 UUID" }, 400);
16335
16501
  }
16502
+ const accountId = getAccountIdForSession(c.var.cacheKey);
16503
+ const acctQuery = accountId ? `?accountId=${encodeURIComponent(accountId)}` : "";
16336
16504
  let res;
16337
16505
  try {
16338
- res = await fetch(`${managerBase("session-stop:wrapper")}/${sessionId}/stop`, { method: "POST" });
16506
+ res = await fetch(`${managerBase("session-stop:wrapper")}/${sessionId}/stop${acctQuery}`, { method: "POST" });
16339
16507
  } catch (err) {
16340
16508
  console.error(`[session-stop] sessionId=${sessionId} manager-unreachable err=${err instanceof Error ? err.message : String(err)}`);
16341
16509
  return c.json({ error: "manager-unreachable" }, 502);
@@ -20416,6 +20584,12 @@ function buildWaSpawnRequest(input) {
20416
20584
  role: input.role,
20417
20585
  channel: "whatsapp",
20418
20586
  personId,
20587
+ // Task 1325 — the account whose WhatsApp received this inbound is the
20588
+ // session's own account (the sessionId hashes it). Threading it as
20589
+ // targetAccountId makes a message-triggered resume of a client-account
20590
+ // session resolve under that account, not the manager's boot-time house
20591
+ // default (which fired for every non-webchat resume before this).
20592
+ targetAccountId: input.accountId,
20419
20593
  waChannel: { senderId: input.senderId, gatewayUrl: input.gatewayUrl, serverPath: input.serverPath },
20420
20594
  logContext: `channel=whatsapp-native role=${input.role} senderId=${input.senderId}`
20421
20595
  };
@@ -21725,6 +21899,12 @@ function buildTelegramSpawnRequest(input) {
21725
21899
  role: input.role,
21726
21900
  channel: "telegram",
21727
21901
  personId,
21902
+ // Task 1325 — the account whose Telegram bot received this inbound is the
21903
+ // session's own account (the sessionId hashes it). Threading it as
21904
+ // targetAccountId makes a message-triggered resume of a client-account
21905
+ // session resolve under that account, not the manager's boot-time house
21906
+ // default. Mirror of the WhatsApp builder.
21907
+ targetAccountId: input.accountId,
21728
21908
  telegramChannel: { senderId: input.senderId, gatewayUrl: input.gatewayUrl, serverPath: input.serverPath },
21729
21909
  logContext: `channel=telegram-native role=${input.role} senderId=${input.senderId}`
21730
21910
  };
@@ -22503,12 +22683,14 @@ var webchatGateway = new WebchatGateway({
22503
22683
  senderId: key,
22504
22684
  adminUserId,
22505
22685
  webchatChannel: { key, gatewayUrl, serverPath },
22506
- // Task 1318 — the manager tags the spawned session's sidecar
22686
+ // Task 1318 / 1325 — the manager tags the spawned session's sidecar
22507
22687
  // (meta.accountId) and scopes its ACCOUNT_DIR from this. `accountId`
22508
- // here is exactly what POST /send resolved for this inbound: HOUSE for
22509
- // an existing-session delivery, the viewer's scoped sub-account for a
22510
- // fresh bootstrap the same value the sessionId hash above already
22511
- // used, so the two never disagree.
22688
+ // here is exactly what POST /send resolved for this inbound: the target
22689
+ // session's OWN account for an existing-session delivery (Task 1325
22690
+ // read from its sidecar, so a client-account session resumes under its
22691
+ // own account, never house), the viewer's scoped sub-account for a fresh
22692
+ // bootstrap — the same value the sessionId hash above already used, so
22693
+ // the two never disagree.
22512
22694
  targetAccountId: accountId,
22513
22695
  logContext: `channel=webchat key=${key} role=${role}`
22514
22696
  });
@@ -23272,6 +23454,10 @@ app55.get("/graph", (c) => {
23272
23454
  });
23273
23455
  app55.get("/chat", (c) => {
23274
23456
  const host = (c.req.header("host") ?? "").split(":")[0];
23457
+ if (isOperatorHost(host, getOperatorDomains())) {
23458
+ console.log(`[host-class] host=${host} class=operator served=operator.html`);
23459
+ return c.html(cachedHtml("operator.html"));
23460
+ }
23275
23461
  if (isPublicHost(host)) return c.text("Not found", 404);
23276
23462
  return c.html(cachedHtml("chat.html"));
23277
23463
  });