@rubytech/create-maxy-code 0.1.432 → 0.1.434

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 (162) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +3 -3
  3. package/payload/platform/plugins/docs/references/admin-ui.md +2 -2
  4. package/payload/server/public/assets/AdminLoginScreens-CMh1pdOp.js +1 -0
  5. package/payload/server/public/assets/AdminShell-X9Bg3AKc.js +2 -0
  6. package/payload/server/public/assets/{Checkbox-BC0c_gbn.js → Checkbox-OCfZCTCO.js} +1 -1
  7. package/payload/server/public/assets/admin-Bi2uYnAg.js +1 -0
  8. package/payload/server/public/assets/{arc-qKfXIt8v.js → arc-Bm9oSOth.js} +1 -1
  9. package/payload/server/public/assets/architecture-YZFGNWBL-Bbnxm4F4.js +1 -0
  10. package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-DkVrGn7G.js → architectureDiagram-Q4EWVU46-C2dK88g3.js} +1 -1
  11. package/payload/server/public/assets/{blockDiagram-DXYQGD6D-DqavswGH.js → blockDiagram-DXYQGD6D-DfLSsjCJ.js} +1 -1
  12. package/payload/server/public/assets/{browser-CvZxNdKw.js → browser-B0ieZy-b.js} +1 -1
  13. package/payload/server/public/assets/{c4Diagram-AHTNJAMY-B7fyKiXe.js → c4Diagram-AHTNJAMY-Bxkmp6OL.js} +1 -1
  14. package/payload/server/public/assets/{calendar-DXxLMF2J.js → calendar-CRL2_9Fl.js} +1 -1
  15. package/payload/server/public/assets/channel-CatPTq-5.js +1 -0
  16. package/payload/server/public/assets/chat-C56bmC6C.js +1 -0
  17. package/payload/server/public/assets/chevron-left-B2DKUxLk.js +1 -0
  18. package/payload/server/public/assets/{chunk-2KRD3SAO-DsgMtGkv.js → chunk-2KRD3SAO-BVNDFwNH.js} +1 -1
  19. package/payload/server/public/assets/{chunk-336JU56O-CkdISfNt.js → chunk-336JU56O-Daz6nMta.js} +2 -2
  20. package/payload/server/public/assets/chunk-426QAEUC-CqLMwOdA.js +1 -0
  21. package/payload/server/public/assets/{chunk-4BX2VUAB-CYpiF2bl.js → chunk-4BX2VUAB-DTldfvwP.js} +1 -1
  22. package/payload/server/public/assets/{chunk-4TB4RGXK-CWyc_F7v.js → chunk-4TB4RGXK-DhM8pwRG.js} +1 -1
  23. package/payload/server/public/assets/{chunk-55IACEB6-BbzKMw2Z.js → chunk-55IACEB6-CzTsbIHo.js} +1 -1
  24. package/payload/server/public/assets/{chunk-5FUZZQ4R-u19Nai9e.js → chunk-5FUZZQ4R-BrcObZhe.js} +1 -1
  25. package/payload/server/public/assets/{chunk-5PVQY5BW-Ba8by6Uy.js → chunk-5PVQY5BW-SFqTuS11.js} +1 -1
  26. package/payload/server/public/assets/{chunk-67CJDMHE-BwUuxtyb.js → chunk-67CJDMHE-EIbrSGOo.js} +1 -1
  27. package/payload/server/public/assets/{chunk-7N4EOEYR-BRH9iM9L.js → chunk-7N4EOEYR-B1D4Jorr.js} +1 -1
  28. package/payload/server/public/assets/{chunk-AA7GKIK3-BGoztgLL.js → chunk-AA7GKIK3-BKHiX4cC.js} +1 -1
  29. package/payload/server/public/assets/{chunk-BSJP7CBP-C5GDAZTl.js → chunk-BSJP7CBP-xBzu29m7.js} +1 -1
  30. package/payload/server/public/assets/{chunk-CIAEETIT-ChY32VPS.js → chunk-CIAEETIT-x2x0gMpL.js} +1 -1
  31. package/payload/server/public/assets/{chunk-EDXVE4YY-CPSD3p6p.js → chunk-EDXVE4YY-D5UkD28M.js} +1 -1
  32. package/payload/server/public/assets/{chunk-ENJZ2VHE-D1oL-iUr.js → chunk-ENJZ2VHE-Dbz67a7E.js} +1 -1
  33. package/payload/server/public/assets/{chunk-FMBD7UC4-CPvYEr54.js → chunk-FMBD7UC4-XfWvuu2F.js} +1 -1
  34. package/payload/server/public/assets/{chunk-FOC6F5B3-9Yyj7Vbz.js → chunk-FOC6F5B3-DfOEDS4q.js} +1 -1
  35. package/payload/server/public/assets/{chunk-ICPOFSXX-BaYgh8FR.js → chunk-ICPOFSXX-D_WEZZvg.js} +2 -2
  36. package/payload/server/public/assets/{chunk-K5T4RW27-5ucpeRvm.js → chunk-K5T4RW27-7O627Xi1.js} +1 -1
  37. package/payload/server/public/assets/{chunk-KGLVRYIC-DW-FHk7T.js → chunk-KGLVRYIC-BXI3XDP9.js} +1 -1
  38. package/payload/server/public/assets/{chunk-LIHQZDEY-CGGVfAyG.js → chunk-LIHQZDEY-B9cFNN0l.js} +1 -1
  39. package/payload/server/public/assets/{chunk-ORNJ4GCN-Bv8EUa5d.js → chunk-ORNJ4GCN-BR3UNDTn.js} +1 -1
  40. package/payload/server/public/assets/{chunk-OYMX7WX6-C1mXJnyw.js → chunk-OYMX7WX6-2wKIEtFZ.js} +1 -1
  41. package/payload/server/public/assets/chunk-QZHKN3VN-CjWy8NJ7.js +1 -0
  42. package/payload/server/public/assets/{chunk-U2HBQHQK-PwSQz6EP.js → chunk-U2HBQHQK-augM3AXB.js} +1 -1
  43. package/payload/server/public/assets/{chunk-X2U36JSP--NPHTBlU.js → chunk-X2U36JSP-BAM9q9ZQ.js} +1 -1
  44. package/payload/server/public/assets/{chunk-XPW4576I-Bbc7Da32.js → chunk-XPW4576I-DxPpji5P.js} +1 -1
  45. package/payload/server/public/assets/{chunk-YZCP3GAM-D-9v8e--.js → chunk-YZCP3GAM-BD3ClFXP.js} +1 -1
  46. package/payload/server/public/assets/{chunk-ZZ45TVLE-CMPg670Q.js → chunk-ZZ45TVLE-CqxhLPep.js} +1 -1
  47. package/payload/server/public/assets/classDiagram-6PBFFD2Q-DHhR5rdN.js +1 -0
  48. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-DH4pAdfu.js +1 -0
  49. package/payload/server/public/assets/clone-DCKzwjWW.js +1 -0
  50. package/payload/server/public/assets/{cose-bilkent-S5V4N54A-NVSb1Bhy.js → cose-bilkent-S5V4N54A-xywWX-9i.js} +1 -1
  51. package/payload/server/public/assets/{dagre-QfLcO-1j.js → dagre-BaHjDQ-8.js} +1 -1
  52. package/payload/server/public/assets/{dagre-KV5264BT-V2Ai1DFl.js → dagre-KV5264BT-ChRpqqiH.js} +1 -1
  53. package/payload/server/public/assets/data-C1ftMulP.js +1 -0
  54. package/payload/server/public/assets/{diagram-5BDNPKRD-Caw21693.js → diagram-5BDNPKRD-KjwTpyBi.js} +1 -1
  55. package/payload/server/public/assets/{diagram-G4DWMVQ6-CgwVkT2q.js → diagram-G4DWMVQ6-DZO9njAF.js} +1 -1
  56. package/payload/server/public/assets/{diagram-MMDJMWI5-DFUrLZhs.js → diagram-MMDJMWI5-Bus-U-TI.js} +1 -1
  57. package/payload/server/public/assets/{diagram-TYMM5635-CEEiEuZJ.js → diagram-TYMM5635-CfJodFgq.js} +1 -1
  58. package/payload/server/public/assets/{erDiagram-SMLLAGMA-CG10NrT3.js → erDiagram-SMLLAGMA-Bt5zqWiW.js} +1 -1
  59. package/payload/server/public/assets/{file-download-B2B2DTar.js → file-download-CHTyUQqS.js} +1 -1
  60. package/payload/server/public/assets/{flatten-DAO0sfCM.js → flatten-Bpu1L63d.js} +1 -1
  61. package/payload/server/public/assets/{flowDiagram-DWJPFMVM-BqkV9Okv.js → flowDiagram-DWJPFMVM-B64Q590S.js} +1 -1
  62. package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-DRiCDQF6.js → ganttDiagram-T4ZO3ILL-BWdgCEpH.js} +1 -1
  63. package/payload/server/public/assets/gitGraph-7Q5UKJZL-Ps5HDzLh.js +1 -0
  64. package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-BZV2voyy.js → gitGraphDiagram-UUTBAWPF-Djq2B0WT.js} +1 -1
  65. package/payload/server/public/assets/{graph-DRNzDBTV.js → graph-CrJ-itbq.js} +3 -3
  66. package/payload/server/public/assets/{graph-labels-DxqDdO7G.js → graph-labels-CmCWaKJT.js} +1 -1
  67. package/payload/server/public/assets/{graphlib-DGPThX8M.js → graphlib-CNJh9_lx.js} +1 -1
  68. package/payload/server/public/assets/info-OMHHGYJF-gtlpwIig.js +1 -0
  69. package/payload/server/public/assets/infoDiagram-42DDH7IO-CPrWlrsa.js +2 -0
  70. package/payload/server/public/assets/{isEmpty-Cb_U81C6.js → isEmpty-DkDEVnMZ.js} +1 -1
  71. package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-BKsAxSvp.js → ishikawaDiagram-UXIWVN3A-V3ACkWCW.js} +1 -1
  72. package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-CmliuOd-.js → journeyDiagram-VCZTEJTY-9T0qZeH3.js} +1 -1
  73. package/payload/server/public/assets/{kanban-definition-6JOO6SKY-DAlElMb-.js → kanban-definition-6JOO6SKY-CxZ0ukx3.js} +1 -1
  74. package/payload/server/public/assets/{line-DKZqLKAC.js → line-DUHKCQZT.js} +1 -1
  75. package/payload/server/public/assets/{linear-CbSGdh1x.js → linear-BgIBblun.js} +1 -1
  76. package/payload/server/public/assets/{maximize-2-DKx6OBKv.js → maximize-2-_cJWIgx2.js} +1 -1
  77. package/payload/server/public/assets/{mermaid-parser.core-DFvbao9C.js → mermaid-parser.core-CyHygs0-.js} +2 -2
  78. package/payload/server/public/assets/{mermaid.core-C0vEBxDm.js → mermaid.core-L55fJBSx.js} +3 -3
  79. package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-CShASUKd.js → mindmap-definition-QFDTVHPH-DczaUX_E.js} +1 -1
  80. package/payload/server/public/assets/operator-B4wN2c53.js +1 -0
  81. package/payload/server/public/assets/{ordinal-H0tVmBDP.js → ordinal-DK3QISRR.js} +1 -1
  82. package/payload/server/public/assets/packet-4T2RLAQJ-DrSn1e0n.js +1 -0
  83. package/payload/server/public/assets/page-BIfOKi9I.js +32 -0
  84. package/payload/server/public/assets/page-C1G57kPZ.js +1 -0
  85. package/payload/server/public/assets/{pdf-render-jAQU0nXt.js → pdf-render-COLA4aPx.js} +1 -1
  86. package/payload/server/public/assets/pie-ZZUOXDRM-C09i6N-g.js +1 -0
  87. package/payload/server/public/assets/{pieDiagram-DEJITSTG-CBZHpDAJ.js → pieDiagram-DEJITSTG-Da5TdnNt.js} +1 -1
  88. package/payload/server/public/assets/public-DmBKnBkr.js +1 -0
  89. package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-n3bB3K91.js → quadrantDiagram-34T5L4WZ-DX7J81uh.js} +1 -1
  90. package/payload/server/public/assets/radar-PYXPWWZC-CMZN2KQH.js +1 -0
  91. package/payload/server/public/assets/{reduce-DAvwat-a.js → reduce-uzWdoyL7.js} +1 -1
  92. package/payload/server/public/assets/{requirementDiagram-MS252O5E-DiDvQK3c.js → requirementDiagram-MS252O5E-DJQGrZPG.js} +1 -1
  93. package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-DWDQQZmd.js → sankeyDiagram-XADWPNL6-Ba8fGz96.js} +1 -1
  94. package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-DmAqRlBT.js → sequenceDiagram-FGHM5R23-BmDPC7qx.js} +1 -1
  95. package/payload/server/public/assets/{stateDiagram-FHFEXIEX-D4R-n6bZ.js → stateDiagram-FHFEXIEX-1VkptYFz.js} +1 -1
  96. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-BdgkPHuh.js +1 -0
  97. package/payload/server/public/assets/tasks-0OcRiBdQ.js +1 -0
  98. package/payload/server/public/assets/time-entry-format-D477WAes.js +1 -0
  99. package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-CjiHGP4l.js → timeline-definition-GMOUNBTQ-B92U3T_f.js} +1 -1
  100. package/payload/server/public/assets/treeView-SZITEDCU-CeuUM5oL.js +1 -0
  101. package/payload/server/public/assets/treemap-W4RFUUIX-C--fAaJv.js +1 -0
  102. package/payload/server/public/assets/{useCopyFeedback-CPEOUSGU.js → useCopyFeedback-CpfVOO26.js} +1 -1
  103. package/payload/server/public/assets/{useSubAccountSwitcher-CdS1CorH.css → useSubAccountSwitcher-BKCWKo97.css} +1 -1
  104. package/payload/server/public/assets/useSubAccountSwitcher-Bo7bnFtC.js +9 -0
  105. package/payload/server/public/assets/useVoiceRecorder-CZPtVpM-.js +2 -0
  106. package/payload/server/public/assets/{vennDiagram-DHZGUBPP-CBdDQ7c-.js → vennDiagram-DHZGUBPP-Y6Wkihrs.js} +1 -1
  107. package/payload/server/public/assets/wardley-RL74JXVD-4WPJ2UA9.js +1 -0
  108. package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-BlIQPKLb.js → wardleyDiagram-NUSXRM2D-iJpfal2z.js} +1 -1
  109. package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-CslKgh9B.js → xychartDiagram-5P7HB3ND-S0bv7oH0.js} +1 -1
  110. package/payload/server/public/browser.html +5 -6
  111. package/payload/server/public/calendar.html +6 -7
  112. package/payload/server/public/chat.html +12 -13
  113. package/payload/server/public/data.html +11 -10
  114. package/payload/server/public/graph.html +10 -11
  115. package/payload/server/public/index.html +14 -14
  116. package/payload/server/public/operator.html +14 -15
  117. package/payload/server/public/public.html +12 -13
  118. package/payload/server/public/tasks.html +4 -5
  119. package/payload/server/server.js +292 -109
  120. package/payload/server/public/assets/AdminLoginScreens-BM45lL5G.js +0 -1
  121. package/payload/server/public/assets/AdminShell-BfLQQ27Z.js +0 -2
  122. package/payload/server/public/assets/admin-B8Eb9Wbj.js +0 -1
  123. package/payload/server/public/assets/architecture-YZFGNWBL-FPHT7s-C.js +0 -1
  124. package/payload/server/public/assets/audio-attachment-mime-Cx5d3Jls.js +0 -2
  125. package/payload/server/public/assets/channel-j70eMvcL.js +0 -1
  126. package/payload/server/public/assets/chat-LEEUAJOG.js +0 -1
  127. package/payload/server/public/assets/chevron-left-CLPxfjDV.js +0 -1
  128. package/payload/server/public/assets/chunk-426QAEUC-D-NcAlTW.js +0 -1
  129. package/payload/server/public/assets/chunk-QZHKN3VN-CAwbQBtf.js +0 -1
  130. package/payload/server/public/assets/classDiagram-6PBFFD2Q-Ct6Rn0vt.js +0 -1
  131. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-B_2XCIFv.js +0 -1
  132. package/payload/server/public/assets/clone-DjPWA_NH.js +0 -1
  133. package/payload/server/public/assets/data-CKojMQSz.js +0 -1
  134. package/payload/server/public/assets/gitGraph-7Q5UKJZL-B8Hx7f-D.js +0 -1
  135. package/payload/server/public/assets/info-OMHHGYJF-BicCJTqU.js +0 -1
  136. package/payload/server/public/assets/infoDiagram-42DDH7IO-tf-8rOez.js +0 -2
  137. package/payload/server/public/assets/operator-OwY_sWTH.js +0 -1
  138. package/payload/server/public/assets/packet-4T2RLAQJ-Ckn_5hq0.js +0 -1
  139. package/payload/server/public/assets/page-B7nCws9K.js +0 -1
  140. package/payload/server/public/assets/page-C3L6-Ufk.js +0 -32
  141. package/payload/server/public/assets/pie-ZZUOXDRM-DzlGQW3J.js +0 -1
  142. package/payload/server/public/assets/play-DHttF4fl.js +0 -1
  143. package/payload/server/public/assets/public-CSLXSSy5.js +0 -1
  144. package/payload/server/public/assets/radar-PYXPWWZC-BHo2YD8b.js +0 -1
  145. package/payload/server/public/assets/square-CHcQHtK8.js +0 -1
  146. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-BcFRbGRu.js +0 -1
  147. package/payload/server/public/assets/tasks-ClfJU1CK.js +0 -1
  148. package/payload/server/public/assets/treeView-SZITEDCU-BtRr5vXp.js +0 -1
  149. package/payload/server/public/assets/treemap-W4RFUUIX-D8p0sbyo.js +0 -1
  150. package/payload/server/public/assets/useSubAccountSwitcher-DyjTbzQR.js +0 -9
  151. package/payload/server/public/assets/wardley-RL74JXVD-DgMn-9ZJ.js +0 -1
  152. /package/payload/server/public/assets/{_baseFor-D3BqAOBr.js → _baseFor-Q4DeIqQC.js} +0 -0
  153. /package/payload/server/public/assets/{array-iYP9fzJp.js → array-WaOTgZu7.js} +0 -0
  154. /package/payload/server/public/assets/{cytoscape.esm-BQSBzPsB.js → cytoscape.esm-CMmjo4hO.js} +0 -0
  155. /package/payload/server/public/assets/{defaultLocale-BrdA1gDi.js → defaultLocale-BxqJVxq5.js} +0 -0
  156. /package/payload/server/public/assets/{dist-Cvgxm7qv.js → dist-Dx-cpU53.js} +0 -0
  157. /package/payload/server/public/assets/{init-Bx0S6pkp.js → init-DX7c5Edh.js} +0 -0
  158. /package/payload/server/public/assets/{katex-BsiH_a6d.js → katex-B2dtGfSp.js} +0 -0
  159. /package/payload/server/public/assets/{path-BLSgTy3w.js → path-CnSyroar.js} +0 -0
  160. /package/payload/server/public/assets/{preload-helper-ClBMtM1g.js → preload-helper-DqboRNgS.js} +0 -0
  161. /package/payload/server/public/assets/{rough.esm-BMOtDaaS.js → rough.esm-eLccZ4OJ.js} +0 -0
  162. /package/payload/server/public/assets/{src-DV4LKv2E.js → src-Dqs1wlnb.js} +0 -0
@@ -2368,28 +2368,14 @@ function computeBackoff(attempt, config = {}) {
2368
2368
 
2369
2369
  // app/lib/whatsapp/init-queries.ts
2370
2370
  import { inspect as inspect2 } from "util";
2371
- var TAG3 = "[whatsapp:init]";
2372
- var DEFAULT_QUERY_TIMEOUT_MS = 15e3;
2373
- var INSPECT_OPTS2 = {
2374
- depth: null,
2375
- breakLength: Infinity,
2376
- compact: true,
2377
- maxArrayLength: 50
2378
- };
2379
- function formatErr(err) {
2380
- if (err instanceof Error) {
2381
- const base = `${err.name}: ${err.message}`;
2382
- const inspected = inspect2(err, INSPECT_OPTS2);
2383
- return `${base}
2384
- ${inspected}`;
2385
- }
2386
- return inspect2(err, INSPECT_OPTS2);
2387
- }
2371
+
2372
+ // app/lib/whatsapp/with-timeout.ts
2388
2373
  function withTimeout(label, promise, timeoutMs) {
2389
2374
  return new Promise((resolve34, reject) => {
2390
2375
  const timer2 = setTimeout(() => {
2391
2376
  reject(new Error(`${label} timed out after ${timeoutMs}ms`));
2392
2377
  }, timeoutMs);
2378
+ timer2.unref?.();
2393
2379
  promise.then(
2394
2380
  (value) => {
2395
2381
  clearTimeout(timer2);
@@ -2402,6 +2388,25 @@ function withTimeout(label, promise, timeoutMs) {
2402
2388
  );
2403
2389
  });
2404
2390
  }
2391
+
2392
+ // app/lib/whatsapp/init-queries.ts
2393
+ var TAG3 = "[whatsapp:init]";
2394
+ var DEFAULT_QUERY_TIMEOUT_MS = 15e3;
2395
+ var INSPECT_OPTS2 = {
2396
+ depth: null,
2397
+ breakLength: Infinity,
2398
+ compact: true,
2399
+ maxArrayLength: 50
2400
+ };
2401
+ function formatErr(err) {
2402
+ if (err instanceof Error) {
2403
+ const base = `${err.name}: ${err.message}`;
2404
+ const inspected = inspect2(err, INSPECT_OPTS2);
2405
+ return `${base}
2406
+ ${inspected}`;
2407
+ }
2408
+ return inspect2(err, INSPECT_OPTS2);
2409
+ }
2405
2410
  async function runInitQueries(sock, ctx) {
2406
2411
  const startedAt = Date.now();
2407
2412
  const queryTimeoutMs = ctx.queryTimeoutMs ?? DEFAULT_QUERY_TIMEOUT_MS;
@@ -2712,6 +2717,10 @@ function extractMessage(msg) {
2712
2717
  }
2713
2718
  return result;
2714
2719
  }
2720
+ function mediaFallbackBody(extracted) {
2721
+ if (extracted.text) return extracted.text;
2722
+ return extracted.mediaType ? `[${extracted.mediaType}]` : "";
2723
+ }
2715
2724
 
2716
2725
  // app/lib/whatsapp/managed-account.ts
2717
2726
  function normalizeEntry(v) {
@@ -3231,14 +3240,23 @@ function getChannelActivity(accountId) {
3231
3240
 
3232
3241
  // app/lib/whatsapp/outbound/send.ts
3233
3242
  var TAG6 = "[whatsapp:outbound]";
3243
+ function buildQuoted(q) {
3244
+ return {
3245
+ key: {
3246
+ remoteJid: q.remoteJid,
3247
+ id: q.id,
3248
+ fromMe: q.fromMe,
3249
+ ...q.participant ? { participant: q.participant } : {}
3250
+ },
3251
+ message: { conversation: q.body ?? "" }
3252
+ };
3253
+ }
3234
3254
  async function sendTextMessage(sock, to, text, opts) {
3235
3255
  try {
3236
3256
  const jid = to.includes("@") ? to : toWhatsappJid(to);
3237
3257
  const payload = { text };
3238
- if (opts?.quotedMessageId) {
3239
- payload.quoted = { key: { id: opts.quotedMessageId } };
3240
- }
3241
- const result = await sock.sendMessage(jid, payload);
3258
+ const options = opts?.quoted ? { quoted: buildQuoted(opts.quoted) } : void 0;
3259
+ const result = await sock.sendMessage(jid, payload, options);
3242
3260
  const messageId = result?.key?.id;
3243
3261
  if (messageId) {
3244
3262
  trackAgentSentMessage(messageId);
@@ -3314,7 +3332,8 @@ async function sendMediaMessage(sock, to, media, opts) {
3314
3332
  };
3315
3333
  break;
3316
3334
  }
3317
- const result = await sock.sendMessage(jid, payload);
3335
+ const options = opts?.quoted ? { quoted: buildQuoted(opts.quoted) } : void 0;
3336
+ const result = await sock.sendMessage(jid, payload, options);
3318
3337
  const messageId = result?.key?.id;
3319
3338
  if (messageId) {
3320
3339
  trackAgentSentMessage(messageId);
@@ -4134,6 +4153,7 @@ async function storeComponentArtefact(accountId, attachmentId, mimeType, content
4134
4153
  // app/lib/whatsapp/inbound/media.ts
4135
4154
  var TAG9 = "[whatsapp:media]";
4136
4155
  var MEDIA_DIR = "/tmp/maxy-media";
4156
+ var DOWNLOAD_TIMEOUT_MS = 45e3;
4137
4157
  function deterministicAttachmentId(seed) {
4138
4158
  const h = createHash("sha256").update(seed).digest("hex");
4139
4159
  return `${h.slice(0, 8)}-${h.slice(8, 12)}-${h.slice(12, 16)}-${h.slice(16, 20)}-${h.slice(20, 32)}`;
@@ -4204,43 +4224,50 @@ async function downloadInboundMediaBuffer(msg, sock, opts) {
4204
4224
  return void 0;
4205
4225
  }
4206
4226
  const maxBytes = opts?.maxBytes ?? 50 * 1024 * 1024;
4207
- try {
4208
- let buffer = await downloadMediaMessage(
4209
- msg,
4210
- "buffer",
4211
- {},
4212
- {
4213
- reuploadRequest: sock.updateMediaMessage,
4214
- logger: sock.logger
4215
- }
4216
- );
4217
- if (!buffer || buffer.length === 0) {
4218
- console.error(`${TAG9} primary download returned empty, trying direct fallback`);
4219
- const downloadable = getDownloadableContent(content);
4220
- if (downloadable) {
4221
- try {
4222
- const stream2 = await downloadContentFromMessage(downloadable.downloadable, downloadable.mediaType);
4223
- buffer = await streamToBuffer(stream2);
4224
- } catch (fallbackErr) {
4225
- console.error(`${TAG9} direct download fallback failed: ${String(fallbackErr)}`);
4227
+ const timeoutMs = opts?.timeoutMs ?? DOWNLOAD_TIMEOUT_MS;
4228
+ try {
4229
+ return await withTimeout(
4230
+ `whatsapp media download (${mimetype ?? "unknown"})`,
4231
+ (async () => {
4232
+ let buffer = await downloadMediaMessage(
4233
+ msg,
4234
+ "buffer",
4235
+ {},
4236
+ {
4237
+ reuploadRequest: sock.updateMediaMessage,
4238
+ logger: sock.logger
4239
+ }
4240
+ );
4241
+ if (!buffer || buffer.length === 0) {
4242
+ console.error(`${TAG9} primary download returned empty, trying direct fallback`);
4243
+ const downloadable = getDownloadableContent(content);
4244
+ if (downloadable) {
4245
+ try {
4246
+ const stream2 = await downloadContentFromMessage(downloadable.downloadable, downloadable.mediaType);
4247
+ buffer = await streamToBuffer(stream2);
4248
+ } catch (fallbackErr) {
4249
+ console.error(`${TAG9} direct download fallback failed: ${String(fallbackErr)}`);
4250
+ }
4251
+ }
4226
4252
  }
4227
- }
4228
- }
4229
- if (!buffer || buffer.length === 0) {
4230
- console.error(`${TAG9} download failed: empty buffer for ${mimetype ?? "unknown"}`);
4231
- return void 0;
4232
- }
4233
- if (buffer.length > maxBytes) {
4234
- const sizeMB = (buffer.length / (1024 * 1024)).toFixed(1);
4235
- const limitMB = (maxBytes / (1024 * 1024)).toFixed(0);
4236
- console.error(`${TAG9} media too large type=${mimetype ?? "unknown"} size=${sizeMB}MB limit=${limitMB}MB`);
4237
- return void 0;
4238
- }
4239
- return {
4240
- buffer,
4241
- mimetype: mimetype ?? "application/octet-stream",
4242
- filename: inner.documentMessage?.fileName ?? void 0
4243
- };
4253
+ if (!buffer || buffer.length === 0) {
4254
+ console.error(`${TAG9} download failed: empty buffer for ${mimetype ?? "unknown"}`);
4255
+ return void 0;
4256
+ }
4257
+ if (buffer.length > maxBytes) {
4258
+ const sizeMB = (buffer.length / (1024 * 1024)).toFixed(1);
4259
+ const limitMB = (maxBytes / (1024 * 1024)).toFixed(0);
4260
+ console.error(`${TAG9} media too large type=${mimetype ?? "unknown"} size=${sizeMB}MB limit=${limitMB}MB`);
4261
+ return void 0;
4262
+ }
4263
+ return {
4264
+ buffer,
4265
+ mimetype: mimetype ?? "application/octet-stream",
4266
+ filename: inner.documentMessage?.fileName ?? void 0
4267
+ };
4268
+ })(),
4269
+ timeoutMs
4270
+ );
4244
4271
  } catch (err) {
4245
4272
  console.error(`${TAG9} media download failed type=${mimetype ?? "unknown"} error=${String(err)}`);
4246
4273
  return void 0;
@@ -4276,6 +4303,40 @@ async function storeInboundMediaServable(msg, sock, accountId, seed, opts) {
4276
4303
  }
4277
4304
  }
4278
4305
 
4306
+ // app/lib/whatsapp/inbound/bounded-queue.ts
4307
+ function createBoundedQueue(limit, opts) {
4308
+ if (!Number.isInteger(limit) || limit < 1) {
4309
+ throw new Error(`createBoundedQueue: limit must be a positive integer, got ${limit}`);
4310
+ }
4311
+ const maxPending = opts?.maxPending ?? Infinity;
4312
+ if (maxPending !== Infinity && (!Number.isInteger(maxPending) || maxPending < 1)) {
4313
+ throw new Error(`createBoundedQueue: maxPending must be a positive integer or omitted, got ${maxPending}`);
4314
+ }
4315
+ const queue = [];
4316
+ let running = 0;
4317
+ const pump = () => {
4318
+ while (running < limit && queue.length > 0) {
4319
+ const task = queue.shift();
4320
+ running++;
4321
+ void Promise.resolve().then(task).catch(() => {
4322
+ }).finally(() => {
4323
+ running--;
4324
+ pump();
4325
+ });
4326
+ }
4327
+ };
4328
+ return {
4329
+ schedule(task) {
4330
+ if (queue.length >= maxPending) return false;
4331
+ queue.push(task);
4332
+ pump();
4333
+ return true;
4334
+ },
4335
+ active: () => running,
4336
+ pending: () => queue.length
4337
+ };
4338
+ }
4339
+
4279
4340
  // app/lib/whatsapp/inbound/debounce.ts
4280
4341
  var TAG10 = "[whatsapp:debounce]";
4281
4342
  var STT_TAG = "[whatsapp:stt-await]";
@@ -4605,6 +4666,11 @@ var WaReplyError = class extends Error {
4605
4666
  var TAG13 = "[whatsapp:manager]";
4606
4667
  var MAX_RECONNECT_ATTEMPTS = 10;
4607
4668
  var MESSAGE_STORE_MAX = 500;
4669
+ var APPEND_MEDIA_CONCURRENCY = 3;
4670
+ var APPEND_MEDIA_MAX_PENDING = 24;
4671
+ var appendMediaQueue = createBoundedQueue(APPEND_MEDIA_CONCURRENCY, {
4672
+ maxPending: APPEND_MEDIA_MAX_PENDING
4673
+ });
4608
4674
  var connections = /* @__PURE__ */ new Map();
4609
4675
  var configDir = null;
4610
4676
  var whatsAppConfig = {};
@@ -5104,6 +5170,7 @@ function monitorInbound(conn) {
5104
5170
  const remoteJid = msg.key.remoteJid;
5105
5171
  if (!remoteJid || remoteJid === "status@broadcast") continue;
5106
5172
  if (!msg.message) continue;
5173
+ let receiptDeferredToWorker = false;
5107
5174
  const extracted = extractMessage(msg);
5108
5175
  const mediaServable = !!(extracted.mediaType && extracted.mimetype && isSupportedMime(extracted.mimetype));
5109
5176
  if (extracted.text || mediaServable) {
@@ -5160,18 +5227,10 @@ function monitorInbound(conn) {
5160
5227
  remoteJid,
5161
5228
  conn.lidMapping
5162
5229
  );
5163
- let mediaAttachmentId;
5164
- if (mediaServable && !fromMe && conn.sock && upsert.type === "notify") {
5165
- const maxMb = whatsAppConfig.mediaMaxMb ?? 50;
5166
- mediaAttachmentId = await storeInboundMediaServable(
5167
- msg,
5168
- conn.sock,
5169
- conn.platformAccountId,
5170
- `whatsapp-live:${conn.accountId}:${canonicalRemoteJid}:${msg.key.id}`,
5171
- { maxBytes: maxMb * 1024 * 1024 }
5172
- ) ?? void 0;
5173
- }
5174
- await persistWhatsAppMessage({
5230
+ const wantsServableMedia = mediaServable && !fromMe && !!conn.sock;
5231
+ const mediaSeed = `whatsapp-live:${conn.accountId}:${canonicalRemoteJid}:${msg.key.id}`;
5232
+ const maxBytes = (whatsAppConfig.mediaMaxMb ?? 50) * 1024 * 1024;
5233
+ const basePersist = {
5175
5234
  accountId: conn.accountId,
5176
5235
  platformAccountId: conn.platformAccountId,
5177
5236
  remoteJid,
@@ -5182,13 +5241,6 @@ function monitorInbound(conn) {
5182
5241
  fromMe,
5183
5242
  senderPhone,
5184
5243
  selfPhone: conn.selfPhone,
5185
- // A stored media message persists the human caption (or empty) plus
5186
- // the attachment id — the reader shows the inline media, never the
5187
- // synthetic `[document: …]` / `[sticker]` line. If the store failed
5188
- // (no id), fall back to the extracted text so a document/sticker
5189
- // still shows its placeholder rather than a blank bubble.
5190
- body: mediaAttachmentId ? extracted.caption ?? "" : extracted.text,
5191
- attachmentId: mediaAttachmentId,
5192
5244
  timestamp: ts,
5193
5245
  pushName: msg.pushName ?? void 0,
5194
5246
  quoted: extracted.quotedMessage ? {
@@ -5196,13 +5248,64 @@ function monitorInbound(conn) {
5196
5248
  body: extracted.quotedMessage.text,
5197
5249
  sender: extracted.quotedMessage.sender
5198
5250
  } : void 0
5199
- });
5251
+ };
5252
+ if (wantsServableMedia && upsert.type === "append") {
5253
+ const sock2 = conn.sock;
5254
+ const platformAccountId = conn.platformAccountId;
5255
+ const caption = extracted.caption ?? "";
5256
+ const fallbackBody = mediaFallbackBody(extracted);
5257
+ const msgKeyId = msg.key.id;
5258
+ const participant = isGroupJid(remoteJid) ? msg.key.participant ?? void 0 : void 0;
5259
+ const sendReceipts = whatsAppConfig.accounts?.[conn.accountId]?.sendReadReceipts ?? whatsAppConfig.sendReadReceipts ?? true;
5260
+ const sendAppendReceipt = () => {
5261
+ if (sendReceipts && msgKeyId) {
5262
+ sendReadReceipt(sock2, remoteJid, [msgKeyId], participant);
5263
+ }
5264
+ };
5265
+ const accepted = appendMediaQueue.schedule(async () => {
5266
+ const id = await storeInboundMediaServable(msg, sock2, platformAccountId, mediaSeed, { maxBytes }) ?? void 0;
5267
+ const persisted = await persistWhatsAppMessage({
5268
+ ...basePersist,
5269
+ body: id ? caption : fallbackBody,
5270
+ attachmentId: id
5271
+ });
5272
+ if (persisted) sendAppendReceipt();
5273
+ });
5274
+ receiptDeferredToWorker = true;
5275
+ if (!accepted) {
5276
+ console.error(
5277
+ `${TAG13} append-media overflow account=${conn.platformAccountId} msgKey=${msgKeyId ?? "?"} \u2014 pending cap ${APPEND_MEDIA_MAX_PENDING} reached, text-fallback persist, inline media shed`
5278
+ );
5279
+ const persisted = await persistWhatsAppMessage({
5280
+ ...basePersist,
5281
+ body: fallbackBody,
5282
+ attachmentId: void 0
5283
+ });
5284
+ if (persisted) sendAppendReceipt();
5285
+ }
5286
+ } else {
5287
+ let mediaAttachmentId;
5288
+ if (wantsServableMedia) {
5289
+ mediaAttachmentId = await storeInboundMediaServable(
5290
+ msg,
5291
+ conn.sock,
5292
+ conn.platformAccountId,
5293
+ mediaSeed,
5294
+ { maxBytes }
5295
+ ) ?? void 0;
5296
+ }
5297
+ await persistWhatsAppMessage({
5298
+ ...basePersist,
5299
+ body: mediaAttachmentId ? extracted.caption ?? "" : extracted.text,
5300
+ attachmentId: mediaAttachmentId
5301
+ });
5302
+ }
5200
5303
  }
5201
5304
  }
5202
5305
  }
5203
5306
  if (upsert.type === "append") {
5204
5307
  const sendReceipts = whatsAppConfig.accounts?.[conn.accountId]?.sendReadReceipts ?? whatsAppConfig.sendReadReceipts ?? true;
5205
- if (sendReceipts && msg.key.id) {
5308
+ if (sendReceipts && msg.key.id && !receiptDeferredToWorker) {
5206
5309
  sendReadReceipt(
5207
5310
  sock,
5208
5311
  remoteJid,
@@ -9302,15 +9405,28 @@ app4.get("/store-stream", requireAdminSession, (c) => {
9302
9405
  const startedAt = Date.now();
9303
9406
  const lastEventId = c.req.header("Last-Event-ID");
9304
9407
  const uploadsBase = resolve12(DATA_ROOT, "accounts", accountId, "uploads");
9408
+ const byMsgKeyId = /* @__PURE__ */ new Map();
9305
9409
  const toTurn = (r) => {
9306
- const turn = {
9410
+ if (!r.body && !r.attachmentId) {
9411
+ console.log(`[wa-reader] op=store-row msgKeyId=${r.msgKeyId} kind=empty textLen=0`);
9412
+ }
9413
+ let turn = {
9307
9414
  kind: "whatsapp-persisted",
9308
9415
  text: r.body,
9309
9416
  ts: r.dateSent,
9310
9417
  fromMe: r.fromMe,
9311
9418
  senderName: r.senderName,
9312
- origin: r.origin
9419
+ origin: r.origin,
9420
+ msgKeyId: r.msgKeyId
9313
9421
  };
9422
+ if (r.quotedId) {
9423
+ const q = byMsgKeyId.get(r.quotedId);
9424
+ turn = {
9425
+ ...turn,
9426
+ quoted: q ? { body: q.body, sender: q.senderName ?? (q.fromMe ? null : q.senderTelephone || null), fromMe: q.fromMe } : { body: "", sender: r.quotedSender, fromMe: false }
9427
+ };
9428
+ console.log(`[wa-reader] op=store-quote msgId=${r.msgKeyId} quoted=${!!q}`);
9429
+ }
9314
9430
  if (r.attachmentId) {
9315
9431
  const meta = readAttachmentMeta(join14(uploadsBase, r.attachmentId));
9316
9432
  if (meta) return { ...turn, attachments: [meta] };
@@ -9353,6 +9469,7 @@ data: ${JSON.stringify(turn)}
9353
9469
  }
9354
9470
  records.sort((a, b) => a.dateSent.localeCompare(b.dateSent));
9355
9471
  const scope = records.length ? records[records.length - 1].scope : "none";
9472
+ for (const m of records) byMsgKeyId.set(m.msgKeyId, m);
9356
9473
  for (const m of records) send(toTurn(m), offset);
9357
9474
  console.log(
9358
9475
  `[wa-reader] op=open remoteJid=${remoteJid} scope=${scope} messages=${records.length} source=store`
@@ -9373,6 +9490,7 @@ data: ${JSON.stringify(turn)}
9373
9490
  } catch {
9374
9491
  continue;
9375
9492
  }
9493
+ byMsgKeyId.set(rec.msgKeyId, rec);
9376
9494
  send(toTurn(rec), offset);
9377
9495
  n++;
9378
9496
  }
@@ -9425,6 +9543,8 @@ app4.post("/reply", requireAdminSession, async (c) => {
9425
9543
  let remoteJid;
9426
9544
  let text;
9427
9545
  let files = [];
9546
+ let fileRefs = [];
9547
+ let quotedId;
9428
9548
  if (ct.includes("multipart/form-data")) {
9429
9549
  const form = await c.req.formData();
9430
9550
  accountIdRaw = form.get("accountId")?.toString();
@@ -9432,22 +9552,26 @@ app4.post("/reply", requireAdminSession, async (c) => {
9432
9552
  const t = form.get("text")?.toString();
9433
9553
  text = t && t.trim().length ? t : void 0;
9434
9554
  files = form.getAll("files").filter((f) => f instanceof File);
9555
+ fileRefs = form.getAll("fileRefs").filter((r) => typeof r === "string" && r.length > 0);
9556
+ quotedId = form.get("quotedId")?.toString() || void 0;
9435
9557
  } else {
9436
9558
  const body = await c.req.json().catch(() => ({}));
9437
9559
  accountIdRaw = typeof body.accountId === "string" ? body.accountId : void 0;
9438
9560
  remoteJid = typeof body.remoteJid === "string" ? body.remoteJid : void 0;
9439
9561
  text = typeof body.text === "string" && body.text.trim().length ? body.text : void 0;
9562
+ fileRefs = Array.isArray(body.fileRefs) ? body.fileRefs.filter((r) => typeof r === "string" && r.length > 0) : [];
9563
+ quotedId = typeof body.quotedId === "string" && body.quotedId ? body.quotedId : void 0;
9440
9564
  }
9441
- console.log(`${MANUAL_TAG} op=request sendId=${sendId} accountId=${accountIdRaw ?? ""} remoteJid=${remoteJid ?? ""} textLen=${text?.length ?? 0} fileCount=${files.length}`);
9565
+ console.log(`${MANUAL_TAG} op=request sendId=${sendId} accountId=${accountIdRaw ?? ""} remoteJid=${remoteJid ?? ""} textLen=${text?.length ?? 0} fileCount=${files.length} fileRefCount=${fileRefs.length} quoted=${quotedId ?? ""}`);
9442
9566
  if (!accountIdRaw || !remoteJid) {
9443
9567
  exit("rejected");
9444
9568
  return c.json({ error: "accountId and remoteJid are required" }, 400);
9445
9569
  }
9446
- if (!text && files.length === 0) {
9570
+ if (!text && files.length === 0 && fileRefs.length === 0) {
9447
9571
  exit("rejected");
9448
9572
  return c.json({ error: "nothing to send: provide text or attachments" }, 400);
9449
9573
  }
9450
- if (files.length > MAX_ATTACHMENTS) {
9574
+ if (files.length + fileRefs.length > MAX_ATTACHMENTS) {
9451
9575
  exit("rejected");
9452
9576
  return c.json({ error: `at most ${MAX_ATTACHMENTS} attachments` }, 400);
9453
9577
  }
@@ -9482,6 +9606,10 @@ app4.post("/reply", requireAdminSession, async (c) => {
9482
9606
  return c.json({ error: "no existing conversation with this contact", reason: "no-existing-conversation" }, 403);
9483
9607
  }
9484
9608
  const template = convo[convo.length - 1];
9609
+ const quoteTarget = quotedId ? convo.find((r) => r.msgKeyId === quotedId) : void 0;
9610
+ const replyQuoted = quotedId ? { id: quotedId, remoteJid, fromMe: quoteTarget?.fromMe ?? false, body: quoteTarget?.body ?? "" } : void 0;
9611
+ const quotedSenderForRecord = quoteTarget?.senderName ?? null;
9612
+ if (quotedId) console.log(`${MANUAL_TAG} op=reply-quote sendId=${sendId} target=${quotedId} present=${!!quoteTarget}`);
9485
9613
  for (const f of files) {
9486
9614
  if (!isMimeAdmitted(f.type, SUPPORTED_MIME_SET)) {
9487
9615
  exit("rejected");
@@ -9492,6 +9620,38 @@ app4.post("/reply", requireAdminSession, async (c) => {
9492
9620
  return c.json({ error: `"${f.name}" exceeds the 50 MB limit` }, 400);
9493
9621
  }
9494
9622
  }
9623
+ const resolvedRefs = [];
9624
+ for (const ref of fileRefs) {
9625
+ const resolved = resolveDataPath(ref);
9626
+ const withinOwn = resolved.ok && !crossesForeignAccountPartition(resolved.relative, accountId) && isWithinOwnAccountPartition(resolved.relative, accountId);
9627
+ let absolute = "";
9628
+ let size = -1;
9629
+ if (withinOwn) {
9630
+ absolute = resolved.absolute;
9631
+ try {
9632
+ const st = statSync5(absolute);
9633
+ size = st.isFile() ? st.size : -1;
9634
+ } catch {
9635
+ size = -1;
9636
+ }
9637
+ }
9638
+ const ok = size >= 0;
9639
+ console.log(`${MANUAL_TAG} op=reply-file-ref sendId=${sendId} path=${ref} resolved=${absolute} ok=${ok}`);
9640
+ if (!ok) {
9641
+ exit("rejected");
9642
+ return c.json({ error: `device file not found: ${ref}`, reason: "file-ref-unresolved" }, 404);
9643
+ }
9644
+ if (size > MAX_FILE_BYTES) {
9645
+ exit("rejected");
9646
+ return c.json({ error: `"${basename5(absolute)}" exceeds the 50 MB limit` }, 400);
9647
+ }
9648
+ const mime = detectMimeType(absolute);
9649
+ if (!isMimeAdmitted(mime, SUPPORTED_MIME_SET)) {
9650
+ exit("rejected");
9651
+ return c.json({ error: `unsupported file type: ${mime}` }, 400);
9652
+ }
9653
+ resolvedRefs.push({ absolute, mime });
9654
+ }
9495
9655
  const res = resolveSocket(accountId);
9496
9656
  if (!res.ok) {
9497
9657
  console.log(`${MANUAL_TAG} op=socket sendId=${sendId} accountId=${accountId} result=${res.reason} presentKeys=${res.presentKeys.join(",") || "none"}`);
@@ -9512,8 +9672,10 @@ app4.post("/reply", requireAdminSession, async (c) => {
9512
9672
  senderName: null,
9513
9673
  remoteJid,
9514
9674
  msgKeyId: waMessageId,
9515
- quotedId: null,
9516
- quotedSender: null,
9675
+ // Task 1541 item 8 — persist the quote so it survives reload; toTurn
9676
+ // resolves quotedId to the referenced message's body/sender for render.
9677
+ quotedId: quotedId ?? null,
9678
+ quotedSender: quotedSenderForRecord,
9517
9679
  scope: template.scope,
9518
9680
  origin: "operator-manual",
9519
9681
  createdAt: nowIso,
@@ -9527,42 +9689,58 @@ app4.post("/reply", requireAdminSession, async (c) => {
9527
9689
  console.log(`${MANUAL_TAG} op=recorded sendId=${sendId} waMessageId=${waMessageId} present=${present} attachment=${attachmentId ? "yes" : "no"}`);
9528
9690
  };
9529
9691
  let sent = 0;
9530
- if (text) {
9531
- const r = await sendTextMessage(res.sock, remoteJid, text, { accountId: res.accountId });
9532
- if (!r.success) {
9533
- console.log(`${MANUAL_TAG} op=send-fail sendId=${sendId} kind=text error=${r.error ?? ""}`);
9534
- exit("error");
9535
- return c.json({ error: r.error ?? "send failed" }, 500);
9536
- }
9537
- console.log(`${MANUAL_TAG} op=sent sendId=${sendId} kind=text waMessageId=${r.messageId ?? ""}`);
9538
- if (r.messageId) record(r.messageId, text);
9539
- sent++;
9540
- }
9541
- for (let i = 0; i < files.length; i++) {
9542
- const stored = await storeAttachment(accountId, files[i]);
9543
- console.log(`${MANUAL_TAG} op=staged sendId=${sendId} idx=${i} bytes=${stored.sizeBytes} mime=${stored.mimeType}`);
9692
+ const sendStagedFile = async (file, label) => {
9693
+ const stored = await storeAttachment(accountId, file);
9694
+ console.log(`${MANUAL_TAG} op=staged sendId=${sendId} ${label} bytes=${stored.sizeBytes} mime=${stored.mimeType}`);
9544
9695
  const kind = mediaTypeForMime(stored.mimeType);
9545
9696
  let mid;
9546
9697
  if (kind) {
9547
- const buffer = Buffer.from(await files[i].arrayBuffer());
9548
- const r = await sendMediaMessage(res.sock, remoteJid, { type: kind, buffer, mimetype: stored.mimeType, filename: stored.filename, ptt: kind === "audio" }, { accountId: res.accountId });
9698
+ const buffer = Buffer.from(await file.arrayBuffer());
9699
+ const r = await sendMediaMessage(res.sock, remoteJid, { type: kind, buffer, mimetype: stored.mimeType, filename: stored.filename, ptt: kind === "audio" }, { accountId: res.accountId, quoted: replyQuoted });
9549
9700
  if (!r.success) {
9550
- console.log(`${MANUAL_TAG} op=send-fail sendId=${sendId} kind=${kind} idx=${i} error=${r.error ?? ""}`);
9551
- exit("error");
9552
- return c.json({ error: r.error ?? "media send failed" }, 500);
9701
+ console.log(`${MANUAL_TAG} op=send-fail sendId=${sendId} kind=${kind} ${label} error=${r.error ?? ""}`);
9702
+ return { ok: false, status: 500, error: r.error ?? "media send failed" };
9553
9703
  }
9554
9704
  mid = r.messageId;
9555
9705
  } else {
9556
9706
  const r = await sendWhatsAppDocument({ to: remoteJid, filePath: stored.storagePath, accountId: res.accountId, maxyAccountId: accountId, platformRoot: PLATFORM_ROOT });
9557
9707
  if (!r.ok) {
9558
- console.log(`${MANUAL_TAG} op=send-fail sendId=${sendId} kind=document idx=${i} error=${r.error}`);
9559
- exit("error");
9560
- return c.json({ error: r.error }, r.status);
9708
+ console.log(`${MANUAL_TAG} op=send-fail sendId=${sendId} kind=document ${label} error=${r.error}`);
9709
+ return { ok: false, status: r.status, error: r.error };
9561
9710
  }
9562
9711
  mid = r.messageId;
9563
9712
  }
9564
- console.log(`${MANUAL_TAG} op=sent sendId=${sendId} kind=${kind ?? "document"} idx=${i} waMessageId=${mid ?? ""}`);
9713
+ console.log(`${MANUAL_TAG} op=sent sendId=${sendId} kind=${kind ?? "document"} ${label} waMessageId=${mid ?? ""}`);
9565
9714
  if (mid) record(mid, "", stored.attachmentId);
9715
+ return { ok: true };
9716
+ };
9717
+ if (text) {
9718
+ const r = await sendTextMessage(res.sock, remoteJid, text, { accountId: res.accountId, quoted: replyQuoted });
9719
+ if (!r.success) {
9720
+ console.log(`${MANUAL_TAG} op=send-fail sendId=${sendId} kind=text error=${r.error ?? ""}`);
9721
+ exit("error");
9722
+ return c.json({ error: r.error ?? "send failed" }, 500);
9723
+ }
9724
+ console.log(`${MANUAL_TAG} op=sent sendId=${sendId} kind=text waMessageId=${r.messageId ?? ""}`);
9725
+ if (r.messageId) record(r.messageId, text);
9726
+ sent++;
9727
+ }
9728
+ for (let i = 0; i < files.length; i++) {
9729
+ const out = await sendStagedFile(files[i], `idx=${i}`);
9730
+ if (!out.ok) {
9731
+ exit("error");
9732
+ return c.json({ error: out.error }, out.status);
9733
+ }
9734
+ sent++;
9735
+ }
9736
+ for (let i = 0; i < resolvedRefs.length; i++) {
9737
+ const { absolute, mime } = resolvedRefs[i];
9738
+ const file = new File([readFileSync15(absolute)], basename5(absolute), { type: mime });
9739
+ const out = await sendStagedFile(file, `ref=${i}`);
9740
+ if (!out.ok) {
9741
+ exit("error");
9742
+ return c.json({ error: out.error }, out.status);
9743
+ }
9566
9744
  sent++;
9567
9745
  }
9568
9746
  exit("delivered");
@@ -25449,6 +25627,11 @@ app60.get("/data", (c) => {
25449
25627
  if (isPublicHost(host)) return c.text("Not found", 404);
25450
25628
  return c.html(cachedHtml("data.html"));
25451
25629
  });
25630
+ app60.get("/tasks", (c) => {
25631
+ const host = (c.req.header("host") ?? "").split(":")[0];
25632
+ if (isPublicHost(host)) return c.text("Not found", 404);
25633
+ return c.html(cachedHtml("tasks.html"));
25634
+ });
25452
25635
  app60.get("/calendar", (c) => {
25453
25636
  const host = (c.req.header("host") ?? "").split(":")[0];
25454
25637
  if (isPublicHost(host)) return c.text("Not found", 404);
@@ -1 +0,0 @@
1
- import{o as e}from"./chunk-Ck5AOu5v.js";import{_ as t,b as n,h as r,w as i,y as a}from"./useSubAccountSwitcher-DyjTbzQR.js";import{C as o}from"./audio-attachment-mime-Cx5d3Jls.js";import{b as s,y as c}from"./AdminShell-BfLQQ27Z.js";import{t as l}from"./Checkbox-BC0c_gbn.js";var u=`admin-landing-redirected`,d=`/graph`;function f(e){return e.variant===`operator`?!1:e.appState===`chat`&&!e.alreadyRedirected}var p=e(i(),1);function m(e=`admin`){let[t,r]=(0,p.useState)(`loading`),[i,a]=(0,p.useState)(``),[c,l]=(0,p.useState)(``),[m,h]=(0,p.useState)(``),[g,_]=(0,p.useState)(!1),[v,y]=(0,p.useState)(!1),[b,x]=(0,p.useState)(!1),[S,C]=(0,p.useState)(!1),[w,T]=(0,p.useState)(!1),[E,D]=(0,p.useState)(null),[O,k]=(0,p.useState)(null),[A,j]=(0,p.useState)(void 0),[M,N]=(0,p.useState)(null),[P,F]=(0,p.useState)(void 0),[I,L]=(0,p.useState)(null),[R,z]=(0,p.useState)(null),[B,V]=(0,p.useState)(void 0),H=(0,p.useRef)(void 0),[U,W]=(0,p.useState)(!1),[G,K]=(0,p.useState)(!0);(0,p.useEffect)(()=>{typeof window>`u`||fetch(`/api/remote-auth/status`).then(e=>e.ok?e.json():null).then(e=>{e?.configured&&W(!0)}).catch(()=>{})},[]);let q=(0,p.useRef)(null),J=(0,p.useRef)(null);(0,p.useEffect)(()=>{async function e(){let e=null;try{e=sessionStorage.getItem(`maxy-admin-session-key`)}catch{}if(!e)return!1;try{let t=await fetch(`/api/admin/session?session_key=${encodeURIComponent(e)}`);if(t.status===401){try{sessionStorage.removeItem(`maxy-admin-session-key`)}catch{}return!1}if(!t.ok)return!1;let n=await t.json();D(n.session_key),z(n.sessionId??null),j(n.businessName),N(n.role??null),F(n.userName===void 0?null:n.userName),L(n.avatar??null);let i=o(n.thinkingView);return H.current=i,V(i),r(`chat`),!0}catch(e){return console.error(`[admin] session restore failed:`,e),!1}}async function t(n=2){try{let i=await fetch(`/api/health`);if(!i.ok){if(n>0)return await new Promise(e=>setTimeout(e,1500)),t(n-1);console.error(`[admin] health check returned ${i.status} after retries`),r(`set-pin`);return}let a=await i.json();if(!a.pin_configured){r(`set-pin`);return}K(!!a.claude_authenticated);let o=!1;try{o=new URLSearchParams(window.location.search).get(`connect`)===`claude`}catch{}if(o){try{let e=new URL(window.location.href);e.searchParams.delete(`connect`),window.history.replaceState(null,``,e.pathname+e.search+e.hash)}catch{}if(!a.claude_authenticated){r(`connect-claude`);return}}if(await e())return;r(`enter-pin`)}catch(e){if(n>0)return await new Promise(e=>setTimeout(e,1500)),t(n-1);console.error(`[admin] health check failed:`,e),r(`set-pin`)}}t()},[]),(0,p.useEffect)(()=>{t===`chat`&&fetch(`/api/admin/claude-info`).then(e=>{if(e.ok)return e.json()}).then(e=>{e&&k(e)}).catch(()=>{})},[t]),(0,p.useEffect)(()=>{if(typeof window>`u`)return;let n=!1;try{n=sessionStorage.getItem(u)===`1`}catch{}if(f({appState:t,alreadyRedirected:n,variant:e})){try{sessionStorage.setItem(u,`1`)}catch{}console.info(`[admin-ui] landing-redirect target=${d}`),window.location.replace(d)}},[t,e]);let Y=(0,p.useRef)(null);(0,p.useEffect)(()=>{if(t!==`chat`)return;let e=setInterval(async()=>{try{let e=await fetch(`/api/health`);if(e.ok){let t=await e.json();K(t.auth_status!==`dead`&&t.auth_status!==`missing`)}}catch{}if(E)try{let e=await fetch(`/api/admin/session?session_key=${encodeURIComponent(E)}`);if(e.status!==401)return;let t=(await e.clone().json().catch(()=>null))?.code??`unknown-401`;if(t===`remote-auth-required`){n(`heartbeat`,`/api/admin/session`);return}console.warn(`[admin-auth] outcome=heartbeat-detected-expiry code=${t}`),Y.current?.()}catch{}},300*1e3);return()=>clearInterval(e)},[t,E]),(0,p.useEffect)(()=>{t===`connect-claude`&&fetch(`/api/health`).then(e=>e.ok?e.json():null).then(e=>{e?.claude_authenticated&&(K(!0),r(`enter-pin`))}).catch(()=>{})},[t]);async function X(e,t){y(!0);try{let i=await fetch(`/api/admin/session`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({pin:e,...t?{accountId:t}:{}})});if(!i.ok){let e=await i.json().catch(()=>({}));if(i.status===401&&e?.code===`remote-auth-required`){n(`enter-pin`,`/api/admin/session`);return}h(e.error||`Invalid PIN`);return}let s=await i.json();D(s.session_key),z(s.sessionId??null),j(s.businessName),N(s.role??null),F(s.userName===void 0?null:s.userName),L(s.avatar??null);let c=o(s.thinkingView);H.current=c,V(c);try{sessionStorage.setItem(`maxy-admin-session-key`,s.session_key)}catch{}a(``),r(`chat`)}catch(e){console.error(`[admin] connection error:`,e),h(`Could not connect.`)}finally{y(!1)}}let Z=(0,p.useCallback)(async e=>{if(e.preventDefault(),v)return;h(``);let t=c.trim();if(!t){h(`Please enter your name.`);return}if(i.length<4){h(`PIN must be at least 4 characters.`);return}let o=i;y(!0);try{let e=await fetch(`/api/onboarding/set-pin`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({pin:o,name:t})});if(!e.ok){let t=await e.json().catch(()=>({}));if(e.status===401&&t?.code===`remote-auth-required`){n(`set-pin`,`/api/onboarding/set-pin`);return}if(e.status===409){console.log(`[admin] PIN already configured — re-checking health`);try{let e=await fetch(`/api/health`);if(e.ok){let n=await e.json();n.pin_configured&&n.claude_authenticated?r(`enter-pin`):n.pin_configured?r(`connect-claude`):h(t.error||`Failed to set PIN.`)}else r(`enter-pin`)}catch{r(`enter-pin`)}return}h(t.error||`Failed to set PIN.`);return}let i=await fetch(`/api/health`);if((i.ok?await i.json():null)?.claude_authenticated){await X(o);return}a(``),r(`connect-claude`)}catch(e){console.error(`[admin] connection error:`,e),h(`Could not connect.`)}finally{y(!1)}},[i,v,c]),Q=(0,p.useCallback)(async e=>{e.preventDefault(),h(``),await X(i)},[i]),ee=(0,p.useCallback)(async()=>{T(!0);try{if(!await s())return console.warn(`[admin-ui] claude-disconnect not verified — credentials may persist; staying put`),!1;K(!1),D(null),N(null),F(void 0),L(null);try{sessionStorage.removeItem(`maxy-admin-session-key`),sessionStorage.removeItem(u)}catch{}return r(`connect-claude`),!0}finally{T(!1)}},[]),$=(0,p.useCallback)(()=>{D(null),N(null),F(void 0),L(null);try{sessionStorage.removeItem(`maxy-admin-session-key`),sessionStorage.removeItem(u)}catch{}a(``),h(``),r(`enter-pin`)},[]);return(0,p.useEffect)(()=>{Y.current=$},[$]),{appState:t,setAppState:r,pin:i,setPin:a,operatorName:c,setOperatorName:l,pinError:m,setPinError:h,showPin:g,setShowPin:_,pinLoading:v,authPolling:b,setAuthPolling:x,authLoading:S,setAuthLoading:C,disconnecting:w,cacheKey:E,setCacheKey:D,claudeInfo:O,setClaudeInfo:k,businessName:A,role:M,userName:P,userAvatar:I,sessionId:R,setSessionId:z,expandAll:B,setExpandAll:V,expandAllDefaultRef:H,remoteAuthEnabled:U,claudeConnected:G,pinInputRef:q,setPinFormRef:J,handleSetPin:Z,handleLogin:Q,handleDisconnect:ee,handleLogout:$}}var h=a();function g({inputRef:e,value:t,onChange:n,onComplete:r,showPin:i,autoFocus:a}){let o=(0,p.useRef)([]);function s(e,r){r.key===`Backspace`?(r.preventDefault(),t[e]?n(t.slice(0,e)+t.slice(e+1)):e>0&&(n(t.slice(0,e-1)+t.slice(e)),o.current[e-1]?.focus())):r.key===`ArrowLeft`&&e>0?o.current[e-1]?.focus():r.key===`ArrowRight`&&e<5?o.current[e+1]?.focus():r.key===`Enter`&&(r.preventDefault(),r.currentTarget.form?.requestSubmit())}function c(e,i){let a=i.nativeEvent.data;if(!a||!/^\d$/.test(a))return;let s=t.split(``);for(s[e]=a;s.length<e;)s.push(``);let c=s.join(``).replace(/\D/g,``).slice(0,6);n(c),c.length===6?r?.(c):e<5&&o.current[e+1]?.focus()}function l(e){e.preventDefault();let t=e.clipboardData.getData(`text`).replace(/\D/g,``).slice(0,6);t&&(n(t),t.length===6?r?.(t):o.current[t.length]?.focus())}return(0,h.jsx)(`div`,{className:`pin-field`,children:Array.from({length:6}).map((n,r)=>(0,h.jsx)(`input`,{ref:t=>{o.current[r]=t,r===0&&e&&(e.current=t)},type:`text`,inputMode:`numeric`,className:`pin-box${t[r]?` pin-box-filled`:``}`,value:t[r]?i?t[r]:`•`:``,onKeyDown:e=>s(r,e),onInput:e=>c(r,e),onPaste:l,onFocus:e=>e.target.select(),autoFocus:a&&r===0,autoComplete:`off`,maxLength:1,"aria-label":`PIN digit ${r+1}`},r))})}function _(e){let{pin:n,setPin:i,showPin:a,setShowPin:o,pinLoading:s,pinError:u,pinInputRef:d,setPinFormRef:f,onSubmit:p,operatorName:m,setOperatorName:_}=e;return(0,h.jsx)(`div`,{className:`connect-page`,children:(0,h.jsxs)(`div`,{className:`connect-content`,children:[(0,h.jsx)(`img`,{src:t,alt:r.productName,className:`connect-logo connect-logo--maxy`}),!r.logoContainsName&&(0,h.jsxs)(`h1`,{className:`connect-title`,children:[`Welcome to `,r.productName]}),(0,h.jsxs)(`p`,{className:`connect-subtitle`,children:[`Tell `,r.productName,` who you are, then choose a PIN.`]}),(0,h.jsxs)(`form`,{ref:f,onSubmit:p,className:`connect-pin-form`,children:[(0,h.jsxs)(`div`,{className:`pin-input-row`,children:[(0,h.jsx)(`input`,{type:`text`,className:`connect-name-input`,placeholder:`Your full name`,value:m,onChange:e=>_(e.target.value),autoComplete:`name`,autoFocus:!0,required:!0,"aria-label":`Your full name`}),(0,h.jsx)(`div`,{style:{width:38,flexShrink:0},"aria-hidden":`true`})]}),(0,h.jsxs)(`div`,{className:`pin-input-row`,children:[(0,h.jsx)(g,{inputRef:d,value:n,onChange:i,onComplete:()=>{},showPin:a}),(0,h.jsx)(c,{variant:`send`,type:`submit`,disabled:!n||!m.trim(),loading:s,"aria-label":`Set PIN`,children:(0,h.jsxs)(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`,children:[(0,h.jsx)(`line`,{x1:`5`,y1:`12`,x2:`19`,y2:`12`}),(0,h.jsx)(`polyline`,{points:`12 5 19 12 12 19`})]})})]}),(0,h.jsx)(l,{checked:a,onChange:()=>o(e=>!e),label:`Show PIN`})]}),u&&(0,h.jsx)(`p`,{className:`admin-pin-error`,children:u})]})})}function v(e){let{pin:n,setPin:i,showPin:a,setShowPin:o,pinLoading:s,pinError:u,pinInputRef:d,onSubmit:f,remoteAuthEnabled:p,onSignOutRemote:m}=e;return(0,h.jsxs)(`div`,{className:`connect-page`,children:[p&&m&&(0,h.jsx)(`button`,{type:`button`,className:`connect-signout`,onClick:m,children:`Sign out`}),(0,h.jsxs)(`div`,{className:`connect-content`,children:[(0,h.jsx)(`img`,{src:t,alt:r.productName,className:`connect-logo connect-logo--maxy`}),!r.logoContainsName&&(0,h.jsx)(`h1`,{className:`connect-title`,children:r.productName}),(0,h.jsxs)(`form`,{onSubmit:f,className:`connect-pin-form`,children:[(0,h.jsxs)(`div`,{className:`pin-input-row`,children:[(0,h.jsx)(g,{inputRef:d,value:n,onChange:i,onComplete:()=>{},showPin:a,autoFocus:!0}),(0,h.jsx)(c,{variant:`send`,type:`submit`,disabled:!n,loading:s,children:(0,h.jsxs)(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`,children:[(0,h.jsx)(`line`,{x1:`5`,y1:`12`,x2:`19`,y2:`12`}),(0,h.jsx)(`polyline`,{points:`12 5 19 12 12 19`})]})})]}),(0,h.jsx)(`div`,{className:`pin-options`,children:(0,h.jsx)(l,{checked:a,onChange:()=>o(e=>!e),label:`Show PIN`})})]}),u&&(0,h.jsx)(`p`,{className:`admin-pin-error`,children:u})]})]})}function y(e){let{authPolling:n,setAuthPolling:i,authLoading:a,setAuthLoading:o,pinError:s,setPinError:l,setAppState:u}=e,[d,f]=(0,p.useState)(!1),[m,g]=(0,p.useState)(!1),[_,v]=(0,p.useState)(``),[y,b]=(0,p.useState)(``),[x,S]=(0,p.useState)(``);async function C(){S(``);try{let e=await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`paste-code`,code:y})})).json();e.accepted?(S(`Code submitted. Finishing sign-in…`),b(``)):S(e.error||`Could not submit code.`)}catch(e){console.error(`[admin] paste-code error:`,e),S(`Could not submit code.`)}}async function w(){g(!0),l(``);try{let e=await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`launch-browser`})})).json();e.launched?f(!0):e.error&&l(e.error)}catch(e){console.error(`[admin] browser launch error:`,e),l(`Could not launch browser.`)}g(!1)}async function T(){o(!0),l(``);try{let e=await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`})).json();if(e.started){i(!0),f(!0),o(!1),v(e.transport||``);for(let e=0;e<120;e++)if(await new Promise(e=>setTimeout(e,2e3)),(await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`wait`})})).json()).authenticated){await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`stop`})}),u(`enter-pin`);return}l(`Timed out waiting for sign-in. Try again.`),i(!1)}else e.error&&l(e.error)}catch(e){console.error(`[admin] auth flow error:`,e),l(`Could not start auth flow.`)}o(!1)}async function E(){await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`stop`})}),i(!1),l(``)}return n||d?(0,h.jsxs)(`div`,{style:{display:`flex`,flexDirection:`column`,height:`100dvh`,overflow:`auto`},children:[(0,h.jsxs)(`header`,{className:`chat-header`,style:{paddingBottom:`12px`,flexShrink:0,position:`relative`,maxWidth:`680px`,width:`100%`,margin:`0 auto`,padding:`24px 20px 12px`},children:[n?(0,h.jsx)(`button`,{onClick:E,style:{position:`absolute`,top:`12px`,right:`12px`,background:`none`,border:`none`,color:`#999`,fontSize:`13px`,cursor:`pointer`,padding:`4px 8px`},"aria-label":`Cancel`,children:`✕`}):(0,h.jsx)(`button`,{onClick:()=>f(!1),style:{position:`absolute`,top:`12px`,right:`12px`,background:`none`,border:`none`,color:`#999`,fontSize:`13px`,cursor:`pointer`,padding:`4px 8px`},"aria-label":`Close browser`,children:`✕`}),(0,h.jsx)(`img`,{src:`/brand/claude.png`,alt:`Claude`,className:`chat-logo`}),(0,h.jsx)(`h1`,{className:`chat-tagline`,children:`Connect Claude`}),(0,h.jsx)(`p`,{className:`chat-intro`,children:n?`Sign in and authorize in the browser below.`:`Open your email or prepare your accounts, then sign in.`}),!n&&(0,h.jsx)(`div`,{style:{marginTop:`12px`},children:(0,h.jsx)(c,{variant:`primary`,onClick:T,disabled:a,children:a?(0,h.jsxs)(h.Fragment,{children:[(0,h.jsx)(`span`,{className:`spin`,style:{display:`inline-block`},children:`✱`}),` Connecting…`]}):`Sign in to Claude`})}),n&&_===`native`&&(0,h.jsxs)(`div`,{style:{marginTop:`14px`,maxWidth:`420px`,margin:`14px auto 0`,display:`flex`,flexDirection:`column`,gap:`8px`},children:[(0,h.jsx)(`label`,{style:{fontSize:`12px`,color:`#999`,lineHeight:1.4},children:`If the browser didn't finish sign-in, paste the code or full redirect URL from Claude's page:`}),(0,h.jsxs)(`div`,{style:{display:`flex`,gap:`8px`},children:[(0,h.jsx)(`input`,{type:`text`,value:y,onChange:e=>b(e.target.value),placeholder:`Paste code or redirect URL`,style:{flex:1,padding:`8px 10px`,fontSize:`13px`,border:`1px solid #ccc`,borderRadius:`6px`}}),(0,h.jsx)(c,{variant:`primary`,onClick:C,disabled:!y.trim(),children:`Submit`})]}),x&&(0,h.jsx)(`p`,{style:{fontSize:`12px`,color:`#999`,margin:0},children:x})]})]}),(0,h.jsx)(`div`,{style:{flex:1,display:`flex`,flexDirection:`column`,minHeight:0,gap:`10px`,padding:`0 0 16px`},children:(0,h.jsx)(`iframe`,{src:`/vnc-viewer.html`,style:{flex:1,width:`100%`,minHeight:0,border:`none`,background:`#111`,display:`block`},title:`Claude Sign-in`})}),s&&(0,h.jsx)(`p`,{className:`admin-pin-error`,style:{textAlign:`center`,padding:`0 20px 16px`},children:s})]}):(0,h.jsx)(`div`,{className:`connect-page`,children:(0,h.jsxs)(`div`,{className:`connect-content`,children:[(0,h.jsxs)(`div`,{className:`connect-logos`,children:[(0,h.jsx)(`div`,{className:`connect-logo-wrap`,children:(0,h.jsx)(`img`,{src:`/brand/claude.png`,alt:`Claude`,className:`connect-logo`})}),(0,h.jsx)(`svg`,{className:`connect-arrow`,viewBox:`0 0 48 24`,fill:`none`,xmlns:`http://www.w3.org/2000/svg`,children:(0,h.jsx)(`path`,{d:`M0 12h44m0 0l-8-8m8 8l-8 8`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`})}),(0,h.jsxs)(`div`,{className:`connect-logo-wrap`,children:[(0,h.jsx)(`img`,{src:t,alt:r.productName,className:`connect-logo connect-logo--maxy`}),!r.logoContainsName&&(0,h.jsx)(`span`,{className:`connect-logo-label`,children:r.productName})]})]}),(0,h.jsxs)(`h1`,{className:`connect-title`,children:[`Connect Claude to power `,r.productName]}),(0,h.jsx)(`p`,{className:`connect-subtitle`,children:`Sign in with your Anthropic account to get started.`}),(0,h.jsx)(c,{variant:`primary`,onClick:T,disabled:a,children:a?(0,h.jsxs)(h.Fragment,{children:[(0,h.jsx)(`span`,{className:`spin`,style:{display:`inline-block`},children:`✱`}),` Connecting…`]}):`Sign in to Claude`}),(0,h.jsx)(`p`,{style:{marginTop:`6px`,fontSize:`11px`,color:`#999`,maxWidth:`300px`,textAlign:`center`,lineHeight:`1.4`},children:`First time? You may need to sign into your email and Anthropic account in the browser before connecting.`}),(0,h.jsx)(`button`,{onClick:w,disabled:m,style:{marginTop:`12px`,background:`none`,border:`none`,color:`var(--color-primary, #666)`,fontSize:`13px`,cursor:`pointer`,textDecoration:`underline`,textUnderlineOffset:`3px`},children:m?`Launching…`:`Open browser first`}),s&&(0,h.jsx)(`p`,{className:`admin-pin-error`,children:s})]})})}function b({auth:e}){return e.appState===`loading`?(0,h.jsx)(`div`,{className:`connect-page`}):e.appState===`set-pin`?(0,h.jsx)(_,{pin:e.pin,setPin:e.setPin,showPin:e.showPin,setShowPin:e.setShowPin,pinLoading:e.pinLoading,pinError:e.pinError,pinInputRef:e.pinInputRef,setPinFormRef:e.setPinFormRef,onSubmit:e.handleSetPin,operatorName:e.operatorName,setOperatorName:e.setOperatorName}):e.appState===`connect-claude`?(0,h.jsx)(y,{authPolling:e.authPolling,setAuthPolling:e.setAuthPolling,authLoading:e.authLoading,setAuthLoading:e.setAuthLoading,pinError:e.pinError,setPinError:e.setPinError,setAppState:e.setAppState}):e.appState===`enter-pin`?(0,h.jsx)(v,{pin:e.pin,setPin:e.setPin,showPin:e.showPin,setShowPin:e.setShowPin,pinLoading:e.pinLoading,pinError:e.pinError,pinInputRef:e.pinInputRef,onSubmit:e.handleLogin,remoteAuthEnabled:e.remoteAuthEnabled,onSignOutRemote:()=>{console.info(`[admin-ui] remote-auth sign-out → /__remote-auth/logout`),window.location.href=`/__remote-auth/logout`}}):null}export{m as n,b as t};