@cardstack/boxel-cli 0.3.2-unstable.61 → 0.4.0-unstable.0

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 (312) hide show
  1. package/bundled-test-harness/assets/adapter-unm-Xq4g.js +2 -0
  2. package/bundled-test-harness/assets/{add-field-to-card-definition-command-test-DkxmkPH6.js → add-field-to-card-definition-command-test-CCaDu5uP.js} +2 -2
  3. package/bundled-test-harness/assets/{add-workspace-test-BMKxSlaC.js → add-workspace-test-B_ih3mkL.js} +2 -2
  4. package/bundled-test-harness/assets/{ai-assistant-test-C3LjW9Uz.js → ai-assistant-test-CrQxlWpZ.js} +7 -6
  5. package/bundled-test-harness/assets/{ai-function-generation-test-WqD9vlzP.js → ai-function-generation-test-BkTvuCnq.js} +1 -1
  6. package/bundled-test-harness/assets/{ai-module-creation-test-CeP1V90-.js → ai-module-creation-test-CMLVMpYm.js} +3 -3
  7. package/bundled-test-harness/assets/{app-C8fZHSIY.js → app-BQLXfOdp.js} +309 -21
  8. package/bundled-test-harness/assets/{apply-markdown-edit-test-VkN9mVg4.js → apply-markdown-edit-test-CpeCS12T.js} +2 -2
  9. package/bundled-test-harness/assets/{apply-search-replace-block-test-C4GiLUbz.js → apply-search-replace-block-test-Czoi47xr.js} +1 -1
  10. package/bundled-test-harness/assets/{auth-service-worker-registration-CGUqW_lr.js → auth-service-worker-registration-C3rAs9Yi.js} +1 -1
  11. package/bundled-test-harness/assets/{auth-service-worker-test-DjVH_n4v.js → auth-service-worker-test-DTHQyoUg.js} +3 -3
  12. package/bundled-test-harness/assets/{authed-fetch-test-PT9AWQEk.js → authed-fetch-test-BRqybmXe.js} +2 -2
  13. package/bundled-test-harness/assets/{avif-image-def-test-BMFnvMFY.js → avif-image-def-test-BVwv4Ahc.js} +1 -1
  14. package/bundled-test-harness/assets/{basic-test-B5EcLZRP.js → basic-test-Dbky79J2.js} +1 -1
  15. package/bundled-test-harness/assets/{binary-upload-dedupe-test-BvQVNF95.js → binary-upload-dedupe-test-B7dPaGQN.js} +3 -3
  16. package/bundled-test-harness/assets/{bot-registration-test-Cy1HY7PT.js → bot-registration-test-zrufhFTo.js} +2 -2
  17. package/bundled-test-harness/assets/{box-test-BTOPLQ3k.js → box-test-B85wfMJn.js} +1 -1
  18. package/bundled-test-harness/assets/{brand-guide-attachments-test-C4R_z8N5.js → brand-guide-attachments-test-C8-n-naq.js} +2 -2
  19. package/bundled-test-harness/assets/{brand-guide-custom-css-test-Me-k86li.js → brand-guide-custom-css-test-B2fmvFp4.js} +2 -2
  20. package/bundled-test-harness/assets/{brand-logo-mark-field-test-DcCSpYJq.js → brand-logo-mark-field-test-CJ4s6jjd.js} +2 -2
  21. package/bundled-test-harness/assets/{broken-link-template-test-BRD2BX45.js → broken-link-template-test-BAc48VK4.js} +1 -1
  22. package/bundled-test-harness/assets/{can-read-realm-test-_flXUfS4.js → can-read-realm-test-mHnz9-_s.js} +2 -2
  23. package/bundled-test-harness/assets/{cancel-indexing-job-test-0JyPszPo.js → cancel-indexing-job-test-Drx2ghoA.js} +2 -2
  24. package/bundled-test-harness/assets/{card-api-test-BpeMpeQ0.js → card-api-test-BmiwtCFR.js} +2 -2
  25. package/bundled-test-harness/assets/{card-basics-test-C-UCeun-.js → card-basics-test-DZs6Zh6Z.js} +2 -2
  26. package/bundled-test-harness/assets/{card-catalog-test-4K3_LE47.js → card-catalog-test-D2mEHOpL.js} +3 -3
  27. package/bundled-test-harness/assets/{card-copy-test-BFFsV3G-.js → card-copy-test-DpSavuvN.js} +3 -3
  28. package/bundled-test-harness/assets/{card-def-field-def-relationships-test-CRjFV5pq.js → card-def-field-def-relationships-test-DYX_ubhX.js} +3 -3
  29. package/bundled-test-harness/assets/{card-def-menu-items-test-DQNnU_0P.js → card-def-menu-items-test-DLO6TEhC.js} +1 -1
  30. package/bundled-test-harness/assets/{card-delete-test-DOyt5y-x.js → card-delete-test-Bmp8Ue48.js} +3 -3
  31. package/bundled-test-harness/assets/{card-playground-test-CiESzD5-.js → card-playground-test-DxoIBbjx.js} +3 -3
  32. package/bundled-test-harness/assets/{card-search-adorn-test-DdTUl5RY.js → card-search-adorn-test-CEA5iAcD.js} +1 -1
  33. package/bundled-test-harness/assets/{card-search-selection-menu-test-BJFUbgA1.js → card-search-selection-menu-test-DOLM6HU0.js} +1 -1
  34. package/bundled-test-harness/assets/{check-correctness-test-B4E7WXSZ.js → check-correctness-test-DR1rUhtU.js} +1 -1
  35. package/bundled-test-harness/assets/{check-domain-availability-test-BnmsW2P7.js → check-domain-availability-test-BYAkVLGj.js} +2 -2
  36. package/bundled-test-harness/assets/{code-patches-test-6Lvfhm1l.js → code-patches-test-BDg35i4X.js} +1 -1
  37. package/bundled-test-harness/assets/{code-ref-test-BWuTdZ2e.js → code-ref-test-BZGL3teK.js} +1 -1
  38. package/bundled-test-harness/assets/{code-submode-test-DPzE9tKe.js → code-submode-test-DIiXgCRB.js} +3 -3
  39. package/bundled-test-harness/assets/{codeblocks-test-MV1tHflj.js → codeblocks-test-B-i0v3er.js} +3 -3
  40. package/bundled-test-harness/assets/{codemirror-editor-test-SD3gDmHw.js → codemirror-editor-test-e1Yn_b_1.js} +1 -1
  41. package/bundled-test-harness/assets/{color-field-test-C_7cf4Z2.js → color-field-test-okcvtdsF.js} +2 -2
  42. package/bundled-test-harness/assets/{commands-calling-test-Br4sMoMf.js → commands-calling-test-BETL8EWm.js} +2 -2
  43. package/bundled-test-harness/assets/{commands-test-COT9Ck-6.js → commands-test-C13_nhjT.js} +1 -1
  44. package/bundled-test-harness/assets/{commands-test-71b4Fun5.js → commands-test-D1X-Kikc.js} +3 -3
  45. package/bundled-test-harness/assets/{computed-test-BbCVTMkD.js → computed-test-C2j8r-e_.js} +2 -2
  46. package/bundled-test-harness/assets/{container-BVdtw4NT.js → container-DYJ5z0jP.js} +3 -3
  47. package/bundled-test-harness/assets/{copy-and-edit-test-1xrTe8p1.js → copy-and-edit-test-DqV_dpu_.js} +1 -1
  48. package/bundled-test-harness/assets/{copy-card-test-D0rXx03h.js → copy-card-test-B4dNP03f.js} +1 -1
  49. package/bundled-test-harness/assets/{copy-file-to-realm-test-DxW5PABL.js → copy-file-to-realm-test-oGK9EM0P.js} +1 -1
  50. package/bundled-test-harness/assets/{copy-source-test-Dy83btnV.js → copy-source-test-GtNFw5fv.js} +2 -2
  51. package/bundled-test-harness/assets/{create-file-test-DimDxpRl.js → create-file-test-2WPpTJ5F.js} +1 -1
  52. package/bundled-test-harness/assets/{create-file-test-COppMhde.js → create-file-test-HxkEMHWL.js} +2 -2
  53. package/bundled-test-harness/assets/{create-listing-modal-test-D57Altg2.js → create-listing-modal-test-BIG3NbX-.js} +4 -4
  54. package/bundled-test-harness/assets/{create-listing-pr-request-test-HJmFkx_x.js → create-listing-pr-request-test-2ZRF_IBk.js} +2 -2
  55. package/bundled-test-harness/assets/{create-spec-test-C-4bkoj3.js → create-spec-test-JVOisAUl.js} +1 -1
  56. package/bundled-test-harness/assets/{csv-file-def-test-GOmD6Ikx.js → csv-file-def-test-DIVp_7a6.js} +1 -1
  57. package/bundled-test-harness/assets/{date-time-fields-test-BYn57092.js → date-time-fields-test-BWdrrYdj.js} +2 -2
  58. package/bundled-test-harness/assets/{debug-message-test-CNzx_IFI.js → debug-message-test-CAzyW7l3.js} +3 -3
  59. package/bundled-test-harness/assets/{diffing-test-PA40XPFB.js → diffing-test-JzXF051K.js} +1 -1
  60. package/bundled-test-harness/assets/{editor-test-Dg1fTno0.js → editor-test-j9znzFxy.js} +2 -2
  61. package/bundled-test-harness/assets/{email-field-test-rPWkRvgR.js → email-field-test-D4vZ2Qnc.js} +2 -2
  62. package/bundled-test-harness/assets/{enum-field-test-DjQ-sjAR.js → enum-field-test-DtZ_sOiA.js} +2 -2
  63. package/bundled-test-harness/assets/{error-display-test-Cp1vgWSg.js → error-display-test-Btk0RcqS.js} +1 -1
  64. package/bundled-test-harness/assets/{evaluate-module-test-Bm6adsJS.js → evaluate-module-test-C_F1Y9Az.js} +1 -1
  65. package/bundled-test-harness/assets/{execute-atomic-operations-test-BAB2vv15.js → execute-atomic-operations-test-D_z5eJ6K.js} +2 -2
  66. package/bundled-test-harness/assets/fallback-banner-live-delete-test-I7o8HPay.js +209 -0
  67. package/bundled-test-harness/assets/{fallback-banner-test-DpCz2idU.js → fallback-banner-test-Bh-BDHwS.js} +3 -3
  68. package/bundled-test-harness/assets/{fallback-banner-test-Md-3yTpX.js → fallback-banner-test-DSjH5ank.js} +1 -1
  69. package/bundled-test-harness/assets/{fallback-models-test-DcB9u65l.js → fallback-models-test-GjvpcpvS.js} +3 -3
  70. package/bundled-test-harness/assets/{fetch-card-json-test-CPHdklsi.js → fetch-card-json-test-BPfTOr4N.js} +2 -2
  71. package/bundled-test-harness/assets/{field-configuration-test-Da5xu3ar.js → field-configuration-test-CH1Kc0iA.js} +2 -2
  72. package/bundled-test-harness/assets/{field-markdown-domain-test-7aY4gMQ3.js → field-markdown-domain-test-COaJBBzN.js} +2 -2
  73. package/bundled-test-harness/assets/{field-markdown-primitives-test-B8UurS_m.js → field-markdown-primitives-test-C52WikZw.js} +2 -2
  74. package/bundled-test-harness/assets/{field-markdown-specialized-test-CHiWEV2t.js → field-markdown-specialized-test-Cmq-3t4u.js} +2 -2
  75. package/bundled-test-harness/assets/{field-playground-test-DBVHB2_g.js → field-playground-test-DbXri11f.js} +3 -3
  76. package/bundled-test-harness/assets/{field-support-predicates-test-i8LXzh_P.js → field-support-predicates-test-ni5pZ9sU.js} +1 -1
  77. package/bundled-test-harness/assets/{field-test-helpers-F8iX3xAt.js → field-test-helpers-BLApZo43.js} +1 -1
  78. package/bundled-test-harness/assets/{file-attachment-test-yfZsKhWQ.js → file-attachment-test-CtV6jG8f.js} +3 -3
  79. package/bundled-test-harness/assets/{file-chooser-test-JOvGg1N8.js → file-chooser-test-C9VwTWSW.js} +2 -2
  80. package/bundled-test-harness/assets/{file-def-live-reload-test-B_XsrkaB.js → file-def-live-reload-test--L4MvUj5.js} +1 -1
  81. package/bundled-test-harness/assets/{file-def-menu-items-test-CkZrFXrK.js → file-def-menu-items-test-B_dVulF7.js} +1 -1
  82. package/bundled-test-harness/assets/{file-def-navigation-test-CyO27adK.js → file-def-navigation-test-B4_pzEXy.js} +1 -1
  83. package/bundled-test-harness/assets/{file-def-serialization-test-1XrP63F8.js → file-def-serialization-test-IoGIzKST.js} +1 -1
  84. package/bundled-test-harness/assets/{file-def-test-BJEhQN1c.js → file-def-test-CT8jTLQy.js} +1 -1
  85. package/bundled-test-harness/assets/{file-tree-test-DQSPDeb2.js → file-tree-test-DQNSRISM.js} +2 -2
  86. package/bundled-test-harness/assets/{flac-audio-def-test-CeyxsGOr.js → flac-audio-def-test-CEt7tShK.js} +1 -1
  87. package/bundled-test-harness/assets/{formatted-aibot-message-test-D09eSldQ.js → formatted-aibot-message-test-DRdKZ8lg.js} +2 -2
  88. package/bundled-test-harness/assets/{formatted-user-message-test-DmX95kEo.js → formatted-user-message-test-By3DTUBk.js} +2 -2
  89. package/bundled-test-harness/assets/{freestyle-test-KaFCs8l2.js → freestyle-test-BOVAHn_7.js} +1 -1
  90. package/bundled-test-harness/assets/{full-reindex-realm-test-BCUSPZuX.js → full-reindex-realm-test-BQji9QK_.js} +2 -2
  91. package/bundled-test-harness/assets/{garbage-collection-test-BJmgY3IQ.js → garbage-collection-test-bPtmt69E.js} +1 -1
  92. package/bundled-test-harness/assets/{general-test-B5RcCakW.js → general-test-pIZFE9Ii.js} +3 -3
  93. package/bundled-test-harness/assets/{generate-example-cards-one-shot-test-Bh9_GXLK.js → generate-example-cards-one-shot-test-DtYqN3qW.js} +1 -1
  94. package/bundled-test-harness/assets/{get-available-realm-identifiers-test-C18mJr3L.js → get-available-realm-identifiers-test-BiHIbpFc.js} +2 -2
  95. package/bundled-test-harness/assets/{get-catalog-realm-identifiers-test-vDnl-arI.js → get-catalog-realm-identifiers-test-B4EVfXvp.js} +2 -2
  96. package/bundled-test-harness/assets/{get-default-writable-realm-test-Co4F_EH-.js → get-default-writable-realm-test-C2izRfTp.js} +2 -2
  97. package/bundled-test-harness/assets/{get-published-realms-test-D6auThJu.js → get-published-realms-test-CJlYS6SA.js} +1 -1
  98. package/bundled-test-harness/assets/{get-realm-of-resource-identifier-test-BeVoQztL.js → get-realm-of-resource-identifier-test-DZG0gROs.js} +2 -2
  99. package/bundled-test-harness/assets/{get-relationship-membership-state-test-Cm_VeTXw.js → get-relationship-membership-state-test-wOVStpnA.js} +1 -1
  100. package/bundled-test-harness/assets/{get-user-system-card-test-CAc-Ainy.js → get-user-system-card-test-Bf_il1b_.js} +2 -2
  101. package/bundled-test-harness/assets/{gif-image-def-test-Co2Woq8R.js → gif-image-def-test-DD4BOFUq.js} +1 -1
  102. package/bundled-test-harness/assets/{gts-file-def-test-DMhWqyxZ.js → gts-file-def-test-KrlOMcTY.js} +1 -1
  103. package/bundled-test-harness/assets/{head-format-preview-test-DPOjt1cu.js → head-format-preview-test-CGzx-i_Q.js} +2 -2
  104. package/bundled-test-harness/assets/{helpers-BIQP26gX.js → helpers-CR-27yCL.js} +1 -1
  105. package/bundled-test-harness/assets/{host-mode-service-BYjO5JXT.js → host-mode-service-BPYfmILw.js} +1 -1
  106. package/bundled-test-harness/assets/{host-mode-test-D9kRy5kW.js → host-mode-test-sjKqSasU.js} +3 -3
  107. package/bundled-test-harness/assets/{host-submode-test-Zy7-q9vh.js → host-submode-test-CvezMbrv.js} +1 -1
  108. package/bundled-test-harness/assets/{hydratable-card-test-DvgHojHD.js → hydratable-card-test-Ds6x3mv5.js} +1 -1
  109. package/bundled-test-harness/assets/{index-query-engine-test-Bk52a889.js → index-query-engine-test-DvgGBuTy.js} +1 -1
  110. package/bundled-test-harness/assets/{index-writer-test-DNeo1Uod.js → index-writer-test-BMajX3Mj.js} +1 -1
  111. package/bundled-test-harness/assets/{inspector-test-OaFEP4S0.js → inspector-test-COfLlQnO.js} +3 -3
  112. package/bundled-test-harness/assets/{instance-filter-matcher-test-PeeLVGMO.js → instance-filter-matcher-test-DUeZ6eiv.js} +1 -1
  113. package/bundled-test-harness/assets/{instantiate-card-test-C0Y8FG7w.js → instantiate-card-test-Ba3rd5Zn.js} +1 -1
  114. package/bundled-test-harness/assets/{interact-submode-creation-and-permissions-test-Cp3YiIQG.js → interact-submode-creation-and-permissions-test-Dr-clTrg.js} +4 -4
  115. package/bundled-test-harness/assets/{interact-submode-setup-CtFp9kvB.js → interact-submode-setup-D23oc2q6.js} +1 -1
  116. package/bundled-test-harness/assets/{interact-submode-test-B_JqGk2t.js → interact-submode-test-t8HEq7Bp.js} +2 -2
  117. package/bundled-test-harness/assets/{invalidate-realm-identifiers-test-Dpa0TzwS.js → invalidate-realm-identifiers-test-Bl1RP3Kp.js} +2 -2
  118. package/bundled-test-harness/assets/{invite-user-to-room-test-DXzTeCgP.js → invite-user-to-room-test-Q26QQwvj.js} +2 -2
  119. package/bundled-test-harness/assets/{isolated-render-test-DVzQEdsY.js → isolated-render-test-Bc2ASFB1.js} +1 -1
  120. package/bundled-test-harness/assets/{job-priority-header-test-J8emfVrj.js → job-priority-header-test-CDDfX3mF.js} +1 -1
  121. package/bundled-test-harness/assets/{jpg-image-def-test-D7txmQ4U.js → jpg-image-def-test-DGjpMEj5.js} +1 -1
  122. package/bundled-test-harness/assets/{json-file-def-test-C3W6amHE.js → json-file-def-test-8NlQ7NyF.js} +1 -1
  123. package/bundled-test-harness/assets/{linksto-broken-link-placeholder-test-nZIKEYDd.js → linksto-broken-link-placeholder-test-OPR5aao3.js} +2 -2
  124. package/bundled-test-harness/assets/{linksto-error-sentinel-test-E5UdAPkR.js → linksto-error-sentinel-test-DNEi2-4f.js} +1 -1
  125. package/bundled-test-harness/assets/{linksto-many-broken-link-placeholder-test-D5lhE5y-.js → linksto-many-broken-link-placeholder-test-Bl3-UMZt.js} +2 -2
  126. package/bundled-test-harness/assets/{linksto-many-per-slot-access-test-uONh3sy8.js → linksto-many-per-slot-access-test-Cv88sT3k.js} +1 -1
  127. package/bundled-test-harness/assets/{linksto-sentinel-roundtrip-test-CUbMHhoz.js → linksto-sentinel-roundtrip-test-DDrNtJgY.js} +1 -1
  128. package/bundled-test-harness/assets/{linksto-singular-js-access-contract-test-Doycge43.js → linksto-singular-js-access-contract-test-CMOxHvSS.js} +1 -1
  129. package/bundled-test-harness/assets/{live-test-pbHzyWf7.js → live-test-BfSJ7dPf.js} +6 -6
  130. package/bundled-test-harness/assets/live-test-CfcRApCW.js +2 -0
  131. package/bundled-test-harness/assets/{loader-parallel-prefetch-test-cfEJV65W.js → loader-parallel-prefetch-test-DchEbilk.js} +1 -1
  132. package/bundled-test-harness/assets/{loader-test-DZX-dw3F.js → loader-test-LyM1F2ON.js} +1 -1
  133. package/bundled-test-harness/assets/{loading-test-PwEVbSuF.js → loading-test-DrK02DRI.js} +2 -2
  134. package/bundled-test-harness/assets/{local-storage-keys-Do9I1BSV.js → local-storage-keys-C0jyxDKn.js} +4 -1
  135. package/bundled-test-harness/assets/{m4a-audio-def-test-Dkbh40DD.js → m4a-audio-def-test-B1PZDu-M.js} +1 -1
  136. package/bundled-test-harness/assets/{main-CE7KR5Ht.js → main-CrtBvhng.js} +1 -1
  137. package/bundled-test-harness/assets/{markdown-fallback-test-BHejXXnE.js → markdown-fallback-test-D32xPo5m.js} +2 -2
  138. package/bundled-test-harness/assets/{markdown-file-def-test-BOvu8beB.js → markdown-file-def-test-2_0tc-pT.js} +1 -1
  139. package/bundled-test-harness/assets/{markdown-helpers-test-Be9UUlnA.js → markdown-helpers-test-D6Ty5K6K.js} +1 -1
  140. package/bundled-test-harness/assets/{markdown-highlighting-test-D-jxOaxc.js → markdown-highlighting-test-CD22pEyx.js} +2 -2
  141. package/bundled-test-harness/assets/{markdown-preview-test-D2kl56R1.js → markdown-preview-test-BTdN_033.js} +2 -2
  142. package/bundled-test-harness/assets/{matrix-service-sliding-sync-test-Cl1D6ID4.js → matrix-service-sliding-sync-test-Co9EhDYF.js} +1 -1
  143. package/bundled-test-harness/assets/{message-service-subscription-test-OvYUTr8V.js → message-service-subscription-test-BK3W9wng.js} +2 -2
  144. package/bundled-test-harness/assets/{mock-matrix-CD6YHaHR.js → mock-matrix-Bkfl9ACG.js} +6 -2
  145. package/bundled-test-harness/assets/{mock-matrix-Dt4s2hUe.js → mock-matrix-DbxVPkSl.js} +1 -1
  146. package/bundled-test-harness/assets/{module-transpile-cache-test-Bj11UbQJ.js → module-transpile-cache-test-BFmN6_si.js} +1 -1
  147. package/bundled-test-harness/assets/{mp3-audio-def-test-C6tzxO6X.js → mp3-audio-def-test-DorbFtva.js} +1 -1
  148. package/bundled-test-harness/assets/{number-field-test-l5WRd3N9.js → number-field-test-C9F_sOf8.js} +2 -2
  149. package/bundled-test-harness/assets/{ogg-audio-def-test-CQ04xrfS.js → ogg-audio-def-test-DRXLSBVQ.js} +1 -1
  150. package/bundled-test-harness/assets/{open-create-listing-modal-test-VxITHH84.js → open-create-listing-modal-test-Yp6EOMGK.js} +1 -1
  151. package/bundled-test-harness/assets/open-image-in-new-tab-test-B-jsojF0.js +52 -0
  152. package/bundled-test-harness/assets/{open-workspace-test-goAg_TVx.js → open-workspace-test-DrkNS6zm.js} +1 -1
  153. package/bundled-test-harness/assets/{operator-mode-acceptance-test-DO3lt95I.js → operator-mode-acceptance-test-CXQkU0xV.js} +5 -5
  154. package/bundled-test-harness/assets/{operator-mode-card-catalog-test-C3e1--M7.js → operator-mode-card-catalog-test-DjTCHu2f.js} +4 -4
  155. package/bundled-test-harness/assets/{operator-mode-links-test-AWhMhHM2.js → operator-mode-links-test-EeNC7Or8.js} +4 -4
  156. package/bundled-test-harness/assets/{operator-mode-state-service-test-BICXMa5O.js → operator-mode-state-service-test-cwdudDwm.js} +2 -2
  157. package/bundled-test-harness/assets/{operator-mode-test-DMyFaXHK.js → operator-mode-test-Cdm2eu3n.js} +4 -4
  158. package/bundled-test-harness/assets/{operator-mode-ui-test-z2SU5ozt.js → operator-mode-ui-test-yWX9IF_q.js} +4 -4
  159. package/bundled-test-harness/assets/{overlay-menu-items-test-Dkulmtpn.js → overlay-menu-items-test-D2yM2xsl.js} +3 -3
  160. package/bundled-test-harness/assets/{panel-BXXk_P7h.js → panel-DBvohlmr.js} +50 -26
  161. package/bundled-test-harness/assets/{past-sessions-test-gKLwZO61.js → past-sessions-test-DqEv1zfI.js} +3 -3
  162. package/bundled-test-harness/assets/{patch-code-test-CIdB45Nv.js → patch-code-test-Y34298iq.js} +1 -1
  163. package/bundled-test-harness/assets/{patch-fields-test-CBGnqUme.js → patch-fields-test-D1aSP1q_.js} +1 -1
  164. package/bundled-test-harness/assets/{patch-instance-test-DmDpfS3p.js → patch-instance-test-DHBeFzYI.js} +1 -1
  165. package/bundled-test-harness/assets/{persist-module-inspector-view-test-D6vpSfX4.js → persist-module-inspector-view-test-DDYttEKD.js} +2 -2
  166. package/bundled-test-harness/assets/{phone-number-field-test-DogtMkDx.js → phone-number-field-test-CUY1miSH.js} +2 -2
  167. package/bundled-test-harness/assets/{playground-CMnQXTzR.js → playground-DFwsIC-9.js} +2 -2
  168. package/bundled-test-harness/assets/{png-image-def-test-BzfrYGhY.js → png-image-def-test-C9COAyWm.js} +1 -1
  169. package/bundled-test-harness/assets/{prerender-file-extract-test-C-1R1B32.js → prerender-file-extract-test-B76NnPJt.js} +1 -1
  170. package/bundled-test-harness/assets/{prerender-html-test-1XGnbGuQ.js → prerender-html-test-ImXJjrpR.js} +1 -1
  171. package/bundled-test-harness/assets/{prerender-meta-test-B02oGS-5.js → prerender-meta-test-xIFFdF1X.js} +1 -1
  172. package/bundled-test-harness/assets/{prerender-module-test-CSKywVQA.js → prerender-module-test-CoxYOMro.js} +1 -1
  173. package/bundled-test-harness/assets/{prerendered-card-search-test-Cf_Hvr4P.js → prerendered-card-search-test-BTgiRYnI.js} +1 -1
  174. package/bundled-test-harness/assets/{preview-format-test-DBKtwgvo.js → preview-format-test-DjS1vxlt.js} +3 -3
  175. package/bundled-test-harness/assets/{preview-test-dgbtaeLg.js → preview-test-CcGZEu6Y.js} +2 -2
  176. package/bundled-test-harness/assets/{publish-realm-test-B4c6TqTI.js → publish-realm-test-Cqq_X3L4.js} +2 -2
  177. package/bundled-test-harness/assets/{query-field-barrier-test-DytVxOcd.js → query-field-barrier-test-CeDBxTwq.js} +2 -2
  178. package/bundled-test-harness/assets/{query-field-error-sentinel-test-Cs2wXQuL.js → query-field-error-sentinel-test-CwOzGgRw.js} +2 -2
  179. package/bundled-test-harness/assets/{query-field-schema-test-ByfKD-mO.js → query-field-schema-test-CXt4ktVo.js} +1 -1
  180. package/bundled-test-harness/assets/{query-fields-test-SlJNtzM3.js → query-fields-test-CrsGkXWE.js} +1 -1
  181. package/bundled-test-harness/assets/{read-card-for-ai-assistant-test-BzThkf4s.js → read-card-for-ai-assistant-test-DORLxJXd.js} +2 -2
  182. package/bundled-test-harness/assets/{read-file-for-ai-assistant-test-CV5PoqSP.js → read-file-for-ai-assistant-test-DyyCSmMv.js} +2 -2
  183. package/bundled-test-harness/assets/{read-source-test-jfWyZkQO.js → read-source-test-hAUdteMO.js} +2 -2
  184. package/bundled-test-harness/assets/{read-text-file-test-Kg6tx07O.js → read-text-file-test-juQ-OJET.js} +2 -2
  185. package/bundled-test-harness/assets/{realm-oWsFVfdH.js → realm-CxU8jc8l.js} +2 -2
  186. package/bundled-test-harness/assets/{realm-config-routing-rule-edit-test-VyMT__jT.js → realm-config-routing-rule-edit-test-E5AhFXfq.js} +3 -3
  187. package/bundled-test-harness/assets/{realm-field-test-CBmQY3Va.js → realm-field-test-wqNbmdgM.js} +2 -2
  188. package/bundled-test-harness/assets/{realm-indexing-test-CQ29IEno.js → realm-indexing-test-DTuwfnZZ.js} +1 -1
  189. package/bundled-test-harness/assets/{realm-querying-test-PR_91CCq.js → realm-querying-test-ojIOXC3n.js} +1 -1
  190. package/bundled-test-harness/assets/{realm-test-C6Kw7gWx.js → realm-test-MgXPmHwc.js} +1 -1
  191. package/bundled-test-harness/assets/{reasoning-test-M4JuH0RZ.js → reasoning-test-ChZJb8sD.js} +3 -3
  192. package/bundled-test-harness/assets/{recent-files-cards-D845sggD.js → recent-files-cards-BICbCMhW.js} +1 -1
  193. package/bundled-test-harness/assets/{recent-files-test-Du5oiGDf.js → recent-files-test-Df_1aE3G.js} +2 -2
  194. package/bundled-test-harness/assets/{reindex-realm-test-BrgFBbOc.js → reindex-realm-test-DDYvNGWh.js} +2 -2
  195. package/bundled-test-harness/assets/{relationship-loading-state-test-CnCYYtmY.js → relationship-loading-state-test-C2EialRQ.js} +1 -1
  196. package/bundled-test-harness/assets/{render-component-BJwKMGDa.js → render-component-DLXpC-Bc.js} +1 -1
  197. package/bundled-test-harness/assets/{rendered-markdown-test-BvQ96-0V.js → rendered-markdown-test-DblOECt_.js} +2 -2
  198. package/bundled-test-harness/assets/{rich-markdown-field-test-neZFxfcc.js → rich-markdown-field-test-B34TJAq8.js} +2 -2
  199. package/bundled-test-harness/assets/{room-message-test-DWEcr5le.js → room-message-test-DQ2x7ymr.js} +2 -2
  200. package/bundled-test-harness/assets/{sanitize-module-list-test-B4VjLVx_.js → sanitize-module-list-test-BTFw8-Do.js} +2 -2
  201. package/bundled-test-harness/assets/{schema-editor-test-CHeST1JD.js → schema-editor-test-w7ANspy0.js} +1 -1
  202. package/bundled-test-harness/assets/{schema-generation-test-G4ZL90Sn.js → schema-generation-test-DxhNMqOe.js} +2 -2
  203. package/bundled-test-harness/assets/{scrolling-test-D3Asc3Yr.js → scrolling-test-Drdch9wf.js} +4 -4
  204. package/bundled-test-harness/assets/{search-and-choose-test-DMB-Nv1z.js → search-and-choose-test-BhIWdkFp.js} +2 -2
  205. package/bundled-test-harness/assets/{search-command-test-BNZzENdS.js → search-command-test-BlTBufTS.js} +1 -1
  206. package/bundled-test-harness/assets/{search-correlation-id-test-tM-SfbrA.js → search-correlation-id-test-BR7bFNCy.js} +1 -1
  207. package/bundled-test-harness/assets/{search-data-test-CYrjasBZ.js → search-data-test-bc2foKLa.js} +2 -2
  208. package/bundled-test-harness/assets/{search-google-images-test-DzFbLWZE.js → search-google-images-test-C96iDOxU.js} +1 -1
  209. package/bundled-test-harness/assets/{search-test-CBH8l5JD.js → search-test-iR0wammw.js} +2 -2
  210. package/bundled-test-harness/assets/{send-ai-assistant-message-test-CAlK3x0a.js → send-ai-assistant-message-test-BmJdWdzI.js} +2 -2
  211. package/bundled-test-harness/assets/{send-bot-trigger-event-test-CwI4Rkf8.js → send-bot-trigger-event-test-CJCAf2db.js} +2 -2
  212. package/bundled-test-harness/assets/{send-request-via-proxy-test-BRuk6sv0.js → send-request-via-proxy-test-DSdZppno.js} +2 -2
  213. package/bundled-test-harness/assets/{sending-test-BA2F7Hfk.js → sending-test-6i0F6n4v.js} +269 -11
  214. package/bundled-test-harness/assets/{serialization-test-DHTHfzsn.js → serialization-test-CE3TeQ4Z.js} +2 -2
  215. package/bundled-test-harness/assets/{set-user-system-card-test-Ct8xegEY.js → set-user-system-card-test-JZW2LcIA.js} +2 -2
  216. package/bundled-test-harness/assets/{setup-v4v1a2Qc.js → setup-C5QslpqI.js} +1 -1
  217. package/bundled-test-harness/assets/{setup-BfvQ1zfD.js → setup-DeQyrqyx.js} +1 -1
  218. package/bundled-test-harness/assets/{show-card-test-7VGIdTJh.js → show-card-test-B41I3EWZ.js} +3 -3
  219. package/bundled-test-harness/assets/{skills-test-NKDA1G9S.js → skills-test-Dl7uEBNz.js} +3 -3
  220. package/bundled-test-harness/assets/{spec-test-61E0gdIB.js → spec-test-DytzFxZb.js} +3 -3
  221. package/bundled-test-harness/assets/{store-BM5pUF94.js → store-CbIxTljQ.js} +30 -0
  222. package/bundled-test-harness/assets/{store-add-test-mRtjroP0.js → store-add-test-ulvv9A3X.js} +2 -2
  223. package/bundled-test-harness/assets/{store-test-CVHw6LMN.js → store-test-Dkf9wBLg.js} +77 -4
  224. package/bundled-test-harness/assets/{summarize-session-test-UZOGVM_F.js → summarize-session-test-BcXrj1r3.js} +2 -2
  225. package/bundled-test-harness/assets/{svg-image-def-test-Dqjy84jw.js → svg-image-def-test-DW1rtFSA.js} +1 -1
  226. package/bundled-test-harness/assets/{switch-submode-test-MWnyo759.js → switch-submode-test-CX0YxbVu.js} +2 -2
  227. package/bundled-test-harness/assets/{test-support-BfonQA4V.js → test-support-CCargU9V.js} +1 -1
  228. package/bundled-test-harness/assets/{tests-DQLSvmHe.js → tests-D1v0wSnN.js} +265 -263
  229. package/bundled-test-harness/assets/{text-file-def-test-DlyCDiM4.js → text-file-def-test-Bl2R6NO8.js} +1 -1
  230. package/bundled-test-harness/assets/{text-input-validator-test-Ccx-4gLo.js → text-input-validator-test-CT3c7m8B.js} +3 -3
  231. package/bundled-test-harness/assets/{text-suggestion-test-mIvJOTS7.js → text-suggestion-test-CbJWk97Q.js} +1 -1
  232. package/bundled-test-harness/assets/{theme-card-test-Bs3Q034n.js → theme-card-test-DyOWEJRn.js} +2 -2
  233. package/bundled-test-harness/assets/{transform-cards-test-BsTtRP0g.js → transform-cards-test-3PsuM2Sv.js} +2 -2
  234. package/bundled-test-harness/assets/{ts-file-def-test-DtWzgXkt.js → ts-file-def-test-BoXA3RgL.js} +1 -1
  235. package/bundled-test-harness/assets/{unpublish-realm-test-BFJEMQL7.js → unpublish-realm-test-CgiIcZ6j.js} +2 -2
  236. package/bundled-test-harness/assets/{update-room-skills-test-BrFhA3El.js → update-room-skills-test-B-BI7daL.js} +3 -3
  237. package/bundled-test-harness/assets/{use-ai-assistant-test-BsyBY6-a.js → use-ai-assistant-test-BEiEjFOH.js} +2 -2
  238. package/bundled-test-harness/assets/user-message-Bbw4pQmd.css +22 -0
  239. package/bundled-test-harness/assets/{user-message-BFN7dtqK.js → user-message-CVG3cgJq.js} +2 -2
  240. package/bundled-test-harness/assets/{validate-realm-test-DQlQ-pWZ.js → validate-realm-test-DBx-3YG9.js} +2 -2
  241. package/bundled-test-harness/assets/{wav-audio-def-test-BZ0oLTT1.js → wav-audio-def-test-CPJl6Hpr.js} +1 -1
  242. package/bundled-test-harness/assets/{webp-image-def-test-tuOTQeTt.js → webp-image-def-test-Bh3SOpDa.js} +1 -1
  243. package/bundled-test-harness/assets/{workspace-chooser-delete-test-D_Gp78-R.js → workspace-chooser-delete-test-1n1lqK_X.js} +3 -3
  244. package/bundled-test-harness/assets/{workspace-chooser-test-CuJ4pgJh.js → workspace-chooser-test-wcKYsTgx.js} +1 -1
  245. package/bundled-test-harness/assets/{workspace-delete-multiple-test-BUmKPHGp.js → workspace-delete-multiple-test-DlXWFVK1.js} +1 -1
  246. package/bundled-test-harness/assets/{write-binary-file-test-D1h4TED_.js → write-binary-file-test-BkADCn85.js} +2 -2
  247. package/bundled-test-harness/assets/{write-text-file-test-DKA9TpIm.js → write-text-file-test-C9K0doTU.js} +2 -2
  248. package/bundled-test-harness/index.html +12 -12
  249. package/bundled-test-harness/tests/index.html +15 -15
  250. package/bundled-types/host-app/components/ai-assistant/chat-input/index.gts +2 -1
  251. package/bundled-types/host-app/components/ai-assistant/message/user-message.gts +6 -2
  252. package/bundled-types/host-app/components/matrix/room.gts +115 -44
  253. package/bundled-types/host-app/lib/matrix-classes/message-builder.ts +13 -0
  254. package/bundled-types/host-app/services/local-persistence-service.ts +179 -0
  255. package/bundled-types/host-app/services/matrix-service.ts +372 -1
  256. package/bundled-types/host-app/services/store.ts +70 -0
  257. package/bundled-types/host-app/utils/local-storage-keys.ts +2 -0
  258. package/bundled-types/host-tests/helpers/mock-matrix/_client.ts +3 -0
  259. package/bundled-types/host-tests/helpers/mock-matrix/_utils.ts +3 -0
  260. package/bundled-types/host-tests/helpers/mock-matrix.ts +1 -0
  261. package/dist/index.js +246 -242
  262. package/package.json +3 -3
  263. package/src/commands/realm/index.ts +2 -0
  264. package/src/commands/realm/ingest-card.ts +567 -0
  265. package/src/commands/realm/pull.ts +9 -13
  266. package/src/commands/realm/push.ts +10 -14
  267. package/src/commands/realm/status.ts +14 -18
  268. package/src/commands/realm/sync.ts +9 -13
  269. package/src/lib/auth-resolver.ts +15 -2
  270. package/bundled-test-harness/assets/adapter-Dk9jvNQb.js +0 -2
  271. package/bundled-test-harness/assets/live-test-B7uB4aVp.js +0 -2
  272. package/bundled-test-harness/assets/user-message-B8olA3Ml.css +0 -18
  273. /package/bundled-test-harness/assets/{ai-assistant-panel-service-test-B2pqk_1r.js → ai-assistant-panel-service-test-DEeul-zv.js} +0 -0
  274. /package/bundled-test-harness/assets/{amd-transpile-test-ftXbwnFz.js → amd-transpile-test-DmEkMdCo.js} +0 -0
  275. /package/bundled-test-harness/assets/{apply-boxel-formatting-test-BSzr4sNI.js → apply-boxel-formatting-test-RixVcq5N.js} +0 -0
  276. /package/bundled-test-harness/assets/{auth-error-guard-test-BxIq12aN.js → auth-error-guard-test-beazl6s5.js} +0 -0
  277. /package/bundled-test-harness/assets/{bfm-card-references-test-6aAhfBzH.js → bfm-card-references-test-IEbg0jo-.js} +0 -0
  278. /package/bundled-test-harness/assets/{cached-fetch-test-CPr-eiq_.js → cached-fetch-test-DlnnpQGz.js} +0 -0
  279. /package/bundled-test-harness/assets/{card-directory-name-test-BS8WD3oH.js → card-directory-name-test-QKl1Ykz6.js} +0 -0
  280. /package/bundled-test-harness/assets/{card-search-query-builder-test-zp6muUB1.js → card-search-query-builder-test-BWc5lDv3.js} +0 -0
  281. /package/bundled-test-harness/assets/{code-patching-test-BZPvPsMr.js → code-patching-test-BRNMumI6.js} +0 -0
  282. /package/bundled-test-harness/assets/{code-semantics-service-test-BBjJ3EF3.js → code-semantics-service-test-CJOSUAQH.js} +0 -0
  283. /package/bundled-test-harness/assets/{command-definitions-test-BcMJzIBM.js → command-definitions-test-De0BMqHI.js} +0 -0
  284. /package/bundled-test-harness/assets/{convert-to-class-name-test-DmF3wUKb.js → convert-to-class-name-test-B7ILkHei.js} +0 -0
  285. /package/bundled-test-harness/assets/{extract-css-variables-test-FIZxFxaL.js → extract-css-variables-test-Di5CFXG-.js} +0 -0
  286. /package/bundled-test-harness/assets/{fetcher-test-g2cjjXxV.js → fetcher-test-Cb8cS9JN.js} +0 -0
  287. /package/bundled-test-harness/assets/{field-path-parser-test-DkY-DFQN.js → field-path-parser-test-Db4kG7EB.js} +0 -0
  288. /package/bundled-test-harness/assets/{file-def-manager-canonicalize-test-Dlf4HlLX.js → file-def-manager-canonicalize-test-Cq5B5KN4.js} +0 -0
  289. /package/bundled-test-harness/assets/{generate-css-variables-test-De4LPdBt.js → generate-css-variables-test-BahavIHR.js} +0 -0
  290. /package/bundled-test-harness/assets/{get-type-refs-from-filter-test-DmDF_dTY.js → get-type-refs-from-filter-test-CH5flf8B.js} +0 -0
  291. /package/bundled-test-harness/assets/{last-modified-date-test-C2hEJ3xU.js → last-modified-date-test-C_jV0b05.js} +0 -0
  292. /package/bundled-test-harness/assets/{limited-set-test-SLbA1cwS.js → limited-set-test-CcpIJCrn.js} +0 -0
  293. /package/bundled-test-harness/assets/{loader-icon-error-test-DTo5t1OQ.js → loader-icon-error-test-Bc_L-0Zb.js} +0 -0
  294. /package/bundled-test-harness/assets/{loader-retry-test-CPFmHSUN.js → loader-retry-test-DQ0E0a0N.js} +0 -0
  295. /package/bundled-test-harness/assets/{login-error-text-test-BGvtn9op.js → login-error-text-test-BsNV9TOq.js} +0 -0
  296. /package/bundled-test-harness/assets/{marked-sync-test-CaZYJo4x.js → marked-sync-test-JSqOc6hu.js} +0 -0
  297. /package/bundled-test-harness/assets/{mutex-test-p2qp1xRj.js → mutex-test-BDkeJutn.js} +0 -0
  298. /package/bundled-test-harness/assets/{plan-install-test-CrYUs1-G.js → plan-install-test-fUZIttPZ.js} +0 -0
  299. /package/bundled-test-harness/assets/{qs-test-DEH8SHFS.js → qs-test-CminVD53.js} +0 -0
  300. /package/bundled-test-harness/assets/{query-field-normalization-test-DrqBkUxD.js → query-field-normalization-test-B9alzE_u.js} +0 -0
  301. /package/bundled-test-harness/assets/{queue-test-CS3aOeHM.js → queue-test-BvWT6K7Z.js} +0 -0
  302. /package/bundled-test-harness/assets/{realm-index-card-id-test-FV_gOG_K.js → realm-index-card-id-test-hvCyEpGZ.js} +0 -0
  303. /package/bundled-test-harness/assets/{realm-paths-test-CvXB4BUZ.js → realm-paths-test-DrwpPXyh.js} +0 -0
  304. /package/bundled-test-harness/assets/{render-component-BabSF5nE.js → render-component-DY19erxA.js} +0 -0
  305. /package/bundled-test-harness/assets/{render-error-test-CvMDARjN.js → render-error-test-BC4QmstW.js} +0 -0
  306. /package/bundled-test-harness/assets/{render-service-test-DRCvv7lo.js → render-service-test-BkCkB3a2.js} +0 -0
  307. /package/bundled-test-harness/assets/{render-timer-stub-test-CVa_rjXp.js → render-timer-stub-test-cnMPidgA.js} +0 -0
  308. /package/bundled-test-harness/assets/{search-cache-key-test-r83Xl6Io.js → search-cache-key-test-DI0DKzU5.js} +0 -0
  309. /package/bundled-test-harness/assets/{search-in-flight-key-test-BmqFzX6o.js → search-in-flight-key-test-DyRDbEX1.js} +0 -0
  310. /package/bundled-test-harness/assets/{unified-search-results-test-D9v-CCog.js → unified-search-results-test-BF8Dps_j.js} +0 -0
  311. /package/bundled-test-harness/assets/{url-test-DtekKUme.js → url-test-DkEL_mbR.js} +0 -0
  312. /package/bundled-test-harness/assets/{workspace-delete-summary-test-B8qyNd7w.js → workspace-delete-summary-test-B7rnzX95.js} +0 -0
@@ -276,6 +276,7 @@ export default class Room extends Component<Signature> {
276
276
  @onSend={{this.sendMessage}}
277
277
  @onPaste={{this.handleChatInputPaste}}
278
278
  @canSend={{this.canSend}}
279
+ @isSending={{this.isSending}}
279
280
  data-test-message-field={{@roomId}}
280
281
  />
281
282
  {{#if this.aiAssistantPanelService.isFocusPillVisible}}
@@ -612,6 +613,10 @@ export default class Room extends Component<Signature> {
612
613
  constructor(owner: Owner, args: Signature['Args']) {
613
614
  super(owner, args);
614
615
  this.doMatrixEventFlush.perform();
616
+ // Replay any persisted optimistic sends from a prior tab/session before
617
+ // matrix-js-sdk's /sync delivers real echoes — entries left in 'not_sent'
618
+ // surface the retry alert; matched real echoes reconcile via the cgi bridge.
619
+ this.matrixService.ensurePendingSendsHydrated(this.args.roomId);
615
620
  registerDestructor(this, () => {
616
621
  this.cleanupScrollState();
617
622
  this.getConversationScrollability = undefined;
@@ -1599,33 +1604,68 @@ export default class Room extends Component<Signature> {
1599
1604
  keepInputAndAttachments = false,
1600
1605
  ) => {
1601
1606
  this.unknownMessageSendError = undefined;
1602
- let messageToSend = this.matrixService.getMessageToSend(this.args.roomId);
1603
- let cardsToSend =
1604
- this.matrixService.getCardsToSend(this.args.roomId) ?? undefined;
1605
- let cardsToSendCopy = cardsToSend ? [...cardsToSend] : undefined;
1606
- let filesToSend =
1607
- this.matrixService.getFilesToSend(this.args.roomId) ?? undefined;
1608
- let filesToSendCopy = filesToSend ? [...filesToSend] : undefined;
1609
- const shouldClearDraft = !keepInputAndAttachments;
1610
-
1611
- // We copy the draft and attachments into local variables before clearing them
1612
- // (unless we're intentionally preserving the user's current draft for a retry).
1613
- // Clearing immediately empties the input so the user sees that their message is “in flight”.
1614
- // If the send fails, we restore those saved values in the catch block so nothing is lost.
1615
- if (shouldClearDraft) {
1616
- this.matrixService.setMessageToSend(this.args.roomId, undefined);
1617
- this.matrixService.setCardsToSend(this.args.roomId, undefined);
1618
- this.matrixService.setFilesToSend(this.args.roomId, undefined);
1607
+ const isRetry = keepInputAndAttachments;
1608
+ const roomId = this.args.roomId;
1609
+
1610
+ // Snapshot the click-time inputs and render an optimistic bubble before
1611
+ // any awaited work. The pre-send pipeline (skill / command / card / file
1612
+ // serialization + upload) can take seconds; without this snapshot the
1613
+ // user sees an empty transcript while the pipeline runs.
1614
+ let snapshotBody = message ?? '';
1615
+ let snapshotCardIds: string[] = [];
1616
+ if (cardsOrIds) {
1617
+ if (typeof cardsOrIds[0] === 'string') {
1618
+ snapshotCardIds = (cardsOrIds as string[]).slice();
1619
+ } else {
1620
+ snapshotCardIds = (cardsOrIds as CardDef[])
1621
+ .map((c) => c.id as unknown as string)
1622
+ .filter((id) => Boolean(id));
1623
+ }
1624
+ }
1625
+ let snapshotFiles = files ?? [];
1626
+
1627
+ if (!isRetry) {
1628
+ let originServerTs = await this.matrixService.addOptimisticEvent(
1629
+ roomId,
1630
+ {
1631
+ body: snapshotBody,
1632
+ clientGeneratedId,
1633
+ attachedCardIds: snapshotCardIds,
1634
+ attachedFiles: snapshotFiles.map((f) => f.serialize()),
1635
+ },
1636
+ );
1637
+ // Persist before clearing the draft so a tab close mid-pipeline still
1638
+ // restores the bubble on reload. Share the synthetic event's ts so
1639
+ // hydration reconstructs an identical origin_server_ts — otherwise
1640
+ // MessageBuilder.updateMessage may early-return when the real echo
1641
+ // arrives with an earlier ts.
1642
+ this.matrixService.persistOptimisticSend(roomId, {
1643
+ clientGeneratedId,
1644
+ body: snapshotBody,
1645
+ attachedCardIds: snapshotCardIds,
1646
+ attachedFiles: snapshotFiles.map((f) => f.serialize()),
1647
+ createdAt: originServerTs,
1648
+ });
1649
+
1650
+ this.matrixService.setMessageToSend(roomId, undefined);
1651
+ this.matrixService.setCardsToSend(roomId, undefined);
1652
+ this.matrixService.setFilesToSend(roomId, undefined);
1619
1653
  this._fileUploadStates.clear();
1654
+ } else {
1655
+ // Retry — flip the existing bubble back to 'sending' and clear any
1656
+ // prior error so the alert / Retry button hides while the pipeline runs.
1657
+ this.matrixService.patchPendingSend(roomId, clientGeneratedId, {
1658
+ status: 'sending',
1659
+ });
1620
1660
  }
1621
1661
 
1622
- let openCardIds = new Set([
1623
- ...(this.operatorModeStateService.getOpenCardIds() || []),
1624
- ...this.autoAttachedCardIds,
1625
- ]) as Set<RealmResourceIdentifier>;
1626
- let context =
1627
- await this.operatorModeStateService.getSummaryForAIBot(openCardIds);
1628
1662
  try {
1663
+ let openCardIds = new Set([
1664
+ ...(this.operatorModeStateService.getOpenCardIds() || []),
1665
+ ...this.autoAttachedCardIds,
1666
+ ]) as Set<RealmResourceIdentifier>;
1667
+ let context =
1668
+ await this.operatorModeStateService.getSummaryForAIBot(openCardIds);
1629
1669
  let cards: CardDef[] | undefined = [];
1630
1670
  if (typeof cardsOrIds?.[0] === 'string') {
1631
1671
  // we use detached instances since these are just
@@ -1657,7 +1697,7 @@ export default class Room extends Component<Signature> {
1657
1697
  }
1658
1698
 
1659
1699
  await this.matrixService.sendMessage(
1660
- this.args.roomId,
1700
+ roomId,
1661
1701
  message,
1662
1702
  cards,
1663
1703
  files,
@@ -1666,24 +1706,32 @@ export default class Room extends Component<Signature> {
1666
1706
  );
1667
1707
  } catch (e) {
1668
1708
  console.error(e);
1669
- this.unknownMessageSendError =
1670
- 'There was an error sending your message. This could be due to network issues, or serialization issues with the cards or files you are trying to send. It might be helpful to refresh the page and try again.';
1671
1709
 
1672
- if (shouldClearDraft) {
1673
- this.matrixService.setMessageToSend(this.args.roomId, messageToSend);
1674
- this.matrixService.setCardsToSend(
1675
- this.args.roomId,
1676
- cardsToSendCopy && cardsToSendCopy.length > 0
1677
- ? cardsToSendCopy
1678
- : undefined,
1679
- );
1680
- this.matrixService.setFilesToSend(
1681
- this.args.roomId,
1682
- filesToSendCopy && filesToSendCopy.length > 0
1683
- ? filesToSendCopy
1684
- : undefined,
1710
+ // Inverse delivery race: client.sendEvent may have already handed the
1711
+ // event to matrix (status === 'sent') before a downstream throw escaped
1712
+ // into this catch. Flipping the bubble to 'not_sent' in that case
1713
+ // would briefly contradict the server's view. Consult the SDK's own
1714
+ // EventStatus first; only stamp 'not_sent' when matrix agrees the send
1715
+ // didn't land.
1716
+ let matrixStatus = this.matrixService.findPendingMatrixEventStatus(
1717
+ roomId,
1718
+ clientGeneratedId,
1719
+ );
1720
+ if (matrixStatus === 'sent') {
1721
+ console.warn(
1722
+ `sendMessage threw after matrix accepted clientGeneratedId=${clientGeneratedId}; ` +
1723
+ 'leaving bubble in sending state for reconciliation.',
1685
1724
  );
1725
+ return;
1686
1726
  }
1727
+
1728
+ this.unknownMessageSendError =
1729
+ 'There was an error sending your message. This could be due to network issues, or serialization issues with the cards or files you are trying to send. It might be helpful to refresh the page and try again.';
1730
+
1731
+ this.matrixService.patchPendingSend(roomId, clientGeneratedId, {
1732
+ status: 'not_sent',
1733
+ errorMessage: 'Failed to send',
1734
+ });
1687
1735
  }
1688
1736
  },
1689
1737
  );
@@ -1717,6 +1765,10 @@ export default class Room extends Component<Signature> {
1717
1765
  },
1718
1766
  );
1719
1767
 
1768
+ private get isSending() {
1769
+ return this.doSendMessage.isRunning;
1770
+ }
1771
+
1720
1772
  private get canSend() {
1721
1773
  return (
1722
1774
  !this.doSendMessage.isRunning &&
@@ -1729,7 +1781,16 @@ export default class Room extends Component<Signature> {
1729
1781
  ) &&
1730
1782
  !this.hasFileUploadIssues &&
1731
1783
  !!this.room &&
1732
- !this.messages.some((m) => this.isPendingMessage(m)) &&
1784
+ // Block input only on a *failed* prior send. `doSendMessage` is an
1785
+ // enqueueTask, so concurrent sends are already serialized; a healthy
1786
+ // 'sending' bubble awaiting the matrix echo doesn't need a second
1787
+ // guard. A 'not_sent' bubble does need attention before the next send,
1788
+ // matching the retry-alert UX.
1789
+ !this.messages.some(
1790
+ (m) =>
1791
+ m.author.userId === this.matrixService.userId &&
1792
+ m.status === 'not_sent',
1793
+ ) &&
1733
1794
  !this.matrixService.isLoadingTimeline &&
1734
1795
  !this.aiAssistantPanelService.isPreparingSession
1735
1796
  );
@@ -1817,10 +1878,20 @@ export default class Room extends Component<Signature> {
1817
1878
  }
1818
1879
 
1819
1880
  private get generatingResults() {
1820
- return (
1821
- this.messages[this.messages.length - 1] &&
1822
- !this.messages[this.messages.length - 1].isStreamingFinished
1823
- );
1881
+ let lastMessage = this.messages[this.messages.length - 1];
1882
+ if (!lastMessage) {
1883
+ return false;
1884
+ }
1885
+ // The banner means "the AI is generating a reply". Only consider the bot's
1886
+ // streaming state — user messages don't carry `isStreamingFinished` on the
1887
+ // wire, so they read as not-streamed-yet even after they've landed. With
1888
+ // the optimistic bubble appearing at click-time, the user's message is the
1889
+ // last message for a longer window than before; without this author gate
1890
+ // the banner shows on the user's own pending bubble.
1891
+ if (lastMessage.author.userId !== this.matrixService.aiBotUserId) {
1892
+ return false;
1893
+ }
1894
+ return !lastMessage.isStreamingFinished;
1824
1895
  }
1825
1896
 
1826
1897
  @cached
@@ -228,6 +228,19 @@ export default class MessageBuilder {
228
228
  message.errorMessage = this.errorMessage;
229
229
  message.reloadBillingData = shouldReloadBillingData(this.event.content);
230
230
 
231
+ // Refresh attached card/file metadata so an optimistic synthetic — which
232
+ // names attached cards from URL slugs alone — gets its names/types
233
+ // replaced by the real echo's serialized FileDef shape (title-cased,
234
+ // proper contentType, etc.) without re-creating the Message instance.
235
+ if (
236
+ this.event.content.msgtype === APP_BOXEL_MESSAGE_MSGTYPE ||
237
+ this.event.content.msgtype === APP_BOXEL_CODE_PATCH_CORRECTNESS_MSGTYPE
238
+ ) {
239
+ message.attachedCardIds = this.attachedCardIds;
240
+ message.attachedCardsAsFiles = this.attachedCardsAsFiles;
241
+ message.attachedFiles = this.attachedFiles;
242
+ }
243
+
231
244
  let encodedCommandRequests =
232
245
  (this.event.content as CardMessageContent)[
233
246
  APP_BOXEL_COMMAND_REQUESTS_KEY
@@ -7,6 +7,7 @@ import type { SerializedFileDef } from 'https://cardstack.com/base/file-api';
7
7
 
8
8
  import {
9
9
  AiAssistantMessageDrafts,
10
+ AiAssistantPendingSends,
10
11
  CurrentRoomIdPersistenceKey,
11
12
  } from '../utils/local-storage-keys';
12
13
 
@@ -30,6 +31,23 @@ type DraftUpdate = {
30
31
  attachedFiles?: StoredFileDraft[] | undefined;
31
32
  };
32
33
 
34
+ export type StoredPendingFile = Pick<
35
+ SerializedFileDef,
36
+ 'sourceUrl' | 'name' | 'url' | 'contentType' | 'contentHash'
37
+ > & { contentSize?: number };
38
+
39
+ export type PendingSendStatus = 'sending' | 'not_sent';
40
+
41
+ export type StoredPendingSend = {
42
+ clientGeneratedId: string;
43
+ body: string;
44
+ attachedCardIds: string[];
45
+ attachedFiles: StoredPendingFile[];
46
+ createdAt: number;
47
+ status: PendingSendStatus;
48
+ errorMessage?: string;
49
+ };
50
+
33
51
  export default class LocalPersistenceService extends Service {
34
52
  // Using sessionStorage for agent id because we want:
35
53
  // - to keep the same agent id if user reloads the page (or tab)
@@ -287,6 +305,167 @@ export default class LocalPersistenceService extends Service {
287
305
  let hasFiles = draft.attachedFiles && draft.attachedFiles.length > 0;
288
306
  return !hasMessage && !hasCards && !hasFiles;
289
307
  }
308
+
309
+ getPendingSends(roomId: string): StoredPendingSend[] {
310
+ return this.readPendingSends()[roomId] ?? [];
311
+ }
312
+
313
+ upsertPendingSend(roomId: string, entry: StoredPendingSend) {
314
+ let all = this.readPendingSends();
315
+ let list = all[roomId] ? [...all[roomId]] : [];
316
+ let index = list.findIndex(
317
+ (e) => e.clientGeneratedId === entry.clientGeneratedId,
318
+ );
319
+ if (index >= 0) {
320
+ list[index] = entry;
321
+ } else {
322
+ list.push(entry);
323
+ }
324
+ all[roomId] = list;
325
+ this.writePendingSends(all);
326
+ }
327
+
328
+ updatePendingSendStatus(
329
+ roomId: string,
330
+ clientGeneratedId: string,
331
+ update: { status: PendingSendStatus; errorMessage?: string },
332
+ ) {
333
+ let all = this.readPendingSends();
334
+ let list = all[roomId];
335
+ if (!list) {
336
+ return;
337
+ }
338
+ let index = list.findIndex(
339
+ (e) => e.clientGeneratedId === clientGeneratedId,
340
+ );
341
+ if (index < 0) {
342
+ return;
343
+ }
344
+ let next = [...list];
345
+ next[index] = {
346
+ ...next[index],
347
+ status: update.status,
348
+ errorMessage: update.errorMessage,
349
+ };
350
+ all[roomId] = next;
351
+ this.writePendingSends(all);
352
+ }
353
+
354
+ removePendingSend(roomId: string, clientGeneratedId: string) {
355
+ let all = this.readPendingSends();
356
+ let list = all[roomId];
357
+ if (!list) {
358
+ return;
359
+ }
360
+ let next = list.filter((e) => e.clientGeneratedId !== clientGeneratedId);
361
+ if (next.length === 0) {
362
+ delete all[roomId];
363
+ } else {
364
+ all[roomId] = next;
365
+ }
366
+ this.writePendingSends(all);
367
+ }
368
+
369
+ private readPendingSends(): Record<string, StoredPendingSend[]> {
370
+ let raw = window.localStorage.getItem(AiAssistantPendingSends);
371
+ if (!raw) {
372
+ return {};
373
+ }
374
+ try {
375
+ let parsed = JSON.parse(raw);
376
+ if (!parsed || typeof parsed !== 'object') {
377
+ return {};
378
+ }
379
+ let sanitized: Record<string, StoredPendingSend[]> = {};
380
+ for (let [roomId, list] of Object.entries(
381
+ parsed as Record<string, unknown>,
382
+ )) {
383
+ if (!Array.isArray(list)) {
384
+ continue;
385
+ }
386
+ let entries = list
387
+ .map((entry) => this.sanitizePendingSend(entry))
388
+ .filter((e): e is StoredPendingSend => Boolean(e));
389
+ if (entries.length > 0) {
390
+ sanitized[roomId] = entries;
391
+ }
392
+ }
393
+ return sanitized;
394
+ } catch {
395
+ window.localStorage.removeItem(AiAssistantPendingSends);
396
+ return {};
397
+ }
398
+ }
399
+
400
+ private sanitizePendingSend(value: unknown): StoredPendingSend | undefined {
401
+ if (!value || typeof value !== 'object') {
402
+ return;
403
+ }
404
+ let cgi = (value as { clientGeneratedId?: unknown }).clientGeneratedId;
405
+ if (typeof cgi !== 'string' || cgi.length === 0) {
406
+ return;
407
+ }
408
+ let body = (value as { body?: unknown }).body;
409
+ let attachedCardIds = (value as { attachedCardIds?: unknown })
410
+ .attachedCardIds;
411
+ let attachedFiles = (value as { attachedFiles?: unknown }).attachedFiles;
412
+ let createdAt = Number((value as { createdAt?: unknown }).createdAt);
413
+ let status = (value as { status?: unknown }).status;
414
+ let errorMessage = (value as { errorMessage?: unknown }).errorMessage;
415
+
416
+ return {
417
+ clientGeneratedId: cgi,
418
+ body: typeof body === 'string' ? body : '',
419
+ attachedCardIds: Array.isArray(attachedCardIds)
420
+ ? attachedCardIds.filter(
421
+ (id): id is string => typeof id === 'string' && id.length > 0,
422
+ )
423
+ : [],
424
+ attachedFiles: Array.isArray(attachedFiles)
425
+ ? (attachedFiles
426
+ .map((file) => this.sanitizePendingFile(file))
427
+ .filter(Boolean) as StoredPendingFile[])
428
+ : [],
429
+ createdAt: Number.isFinite(createdAt) ? createdAt : 0,
430
+ status: status === 'not_sent' ? 'not_sent' : 'sending',
431
+ errorMessage: typeof errorMessage === 'string' ? errorMessage : undefined,
432
+ };
433
+ }
434
+
435
+ private sanitizePendingFile(file: unknown): StoredPendingFile | undefined {
436
+ if (!file || typeof file !== 'object') {
437
+ return;
438
+ }
439
+ let sourceUrl = (file as { sourceUrl?: unknown }).sourceUrl;
440
+ if (typeof sourceUrl !== 'string' || sourceUrl.length === 0) {
441
+ return;
442
+ }
443
+ let name = (file as { name?: unknown }).name;
444
+ let url = (file as { url?: unknown }).url;
445
+ let contentType = (file as { contentType?: unknown }).contentType;
446
+ let contentHash = (file as { contentHash?: unknown }).contentHash;
447
+ let contentSize = (file as { contentSize?: unknown }).contentSize;
448
+ return {
449
+ sourceUrl,
450
+ ...(typeof name === 'string' ? { name } : {}),
451
+ ...(typeof url === 'string' ? { url } : {}),
452
+ ...(typeof contentType === 'string' ? { contentType } : {}),
453
+ ...(typeof contentHash === 'string' ? { contentHash } : {}),
454
+ ...(typeof contentSize === 'number' ? { contentSize } : {}),
455
+ };
456
+ }
457
+
458
+ private writePendingSends(all: Record<string, StoredPendingSend[]>) {
459
+ let entries = Object.entries(all).filter(([, list]) => list.length > 0);
460
+ if (entries.length === 0) {
461
+ window.localStorage.removeItem(AiAssistantPendingSends);
462
+ return;
463
+ }
464
+ window.localStorage.setItem(
465
+ AiAssistantPendingSends,
466
+ JSON.stringify(Object.fromEntries(entries)),
467
+ );
468
+ }
290
469
  }
291
470
 
292
471
  declare module '@ember/service' {