@cardstack/boxel-cli 0.13.0-unstable.4 → 0.13.0-unstable.6

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 (1058) hide show
  1. package/bundled-realms/pretui/components/doc-report.gts +2 -2
  2. package/bundled-realms/pretui/components/doc-report.usage.gts +3 -3
  3. package/bundled-realms/pretui/components/form-field.md +1 -1
  4. package/bundled-realms/pretui/components/icon-button.md +1 -1
  5. package/bundled-realms/pretui/components/popup.md +1 -1
  6. package/bundled-realms/pretui/components/switch.gts +13 -0
  7. package/bundled-realms/pretui/components/switch.md +5 -3
  8. package/bundled-realms/pretui/components/theme-frame.gts +49 -22
  9. package/bundled-realms/pretui/components/tooltip.gts +141 -42
  10. package/bundled-realms/pretui/components/tooltip.md +10 -12
  11. package/bundled-realms/pretui/components/tooltip.usage.gts +3 -5
  12. package/bundled-realms/pretui/docs/structure.md +1 -1
  13. package/bundled-realms/pretui/internal/overlay.gts +4 -2
  14. package/bundled-realms/pretui/pretui-css.gts +6 -2
  15. package/bundled-realms/pretui/theme-scoped-css.gts +262 -0
  16. package/bundled-test-harness/assets/account-switch-failed-test-DwAZq6Sc.js +45 -0
  17. package/bundled-test-harness/assets/adapter-C_6pnsx1.js +2 -0
  18. package/bundled-test-harness/assets/add-field-to-card-definition-tool-test-zMYtJWBv.js +112 -0
  19. package/bundled-test-harness/assets/ai-assistant-create-workspace-test-CwhAV-Ow.js +130 -0
  20. package/bundled-test-harness/assets/ai-assistant-panel-relogin-test-DNgclkGJ.js +46 -0
  21. package/bundled-test-harness/assets/ai-assistant-test-DGYFiRTb.js +2223 -0
  22. package/bundled-test-harness/assets/ai-function-generation-test-Dj6WzKkh.js +1176 -0
  23. package/bundled-test-harness/assets/ai-module-creation-test-C4zhhxaZ.js +151 -0
  24. package/bundled-test-harness/assets/aibot-message-BShcljQ9.js +1312 -0
  25. package/bundled-test-harness/assets/app-DiEYqT6T.js +14146 -0
  26. package/bundled-test-harness/assets/apply-markdown-edit-test-CPhfeg1i.js +230 -0
  27. package/bundled-test-harness/assets/ask-user-picker-NVRkhKwt.js +370 -0
  28. package/bundled-test-harness/assets/ask-user-picker-test-SsZqFm9W.js +39 -0
  29. package/bundled-test-harness/assets/assistant-transcript-test-DesuBCIB.js +57 -0
  30. package/bundled-test-harness/assets/audio-metadata-extractor-test-8JM6oZXG.js +1176 -0
  31. package/bundled-test-harness/assets/authed-fetch-test-yPTMe-9V.js +73 -0
  32. package/bundled-test-harness/assets/avif-image-def-test-Kyknj908.js +187 -0
  33. package/bundled-test-harness/assets/basic-test-D9OrrMaq.js +139 -0
  34. package/bundled-test-harness/assets/binary-upload-dedupe-test-C0RFmHma.js +308 -0
  35. package/bundled-test-harness/assets/bot-registration-test-Bk2lTaCW.js +97 -0
  36. package/bundled-test-harness/assets/box-test-BbV9sMyU.js +50 -0
  37. package/bundled-test-harness/assets/brand-guide-attachments-test-z4wTsKbI.js +84 -0
  38. package/bundled-test-harness/assets/brand-guide-custom-css-test-BlSJE8xo.js +196 -0
  39. package/bundled-test-harness/assets/brand-guide-edit-test-DJ1OQ6IB.js +140 -0
  40. package/bundled-test-harness/assets/brand-logo-mark-field-test-ux7eetkO.js +86 -0
  41. package/bundled-test-harness/assets/broken-link-template-test-CqB3MWyw.js +192 -0
  42. package/bundled-test-harness/assets/bundled-base-modules-test-B2oNLZSJ.js +54 -0
  43. package/bundled-test-harness/assets/bundled-base-oracle-test-DelPfFjn.js +37 -0
  44. package/bundled-test-harness/assets/buried-stack-item-scroll-test-Ixsl1tS0.js +236 -0
  45. package/bundled-test-harness/assets/button-BvYQm_A1.js +141 -0
  46. package/bundled-test-harness/assets/bxl-cyclic-graph-test-p23WCLRW.js +47 -0
  47. package/bundled-test-harness/assets/bxl-expression-test-CVTQYT_C.js +250 -0
  48. package/bundled-test-harness/assets/bxl-indexing-test-D_A7X2sr.js +212 -0
  49. package/bundled-test-harness/assets/bxl-platform-module-test-Cltfyybp.js +71 -0
  50. package/bundled-test-harness/assets/can-invoke-test-CVfE1l1V.js +455 -0
  51. package/bundled-test-harness/assets/can-read-realm-test-CIz6WX_K.js +56 -0
  52. package/bundled-test-harness/assets/cancel-indexing-job-test-0LlrOgYK.js +69 -0
  53. package/bundled-test-harness/assets/capture-test-diHIWmh0.js +360 -0
  54. package/bundled-test-harness/assets/card-api-test-Ci9b0ghP.js +198 -0
  55. package/bundled-test-harness/assets/card-basics-test-RKQoQWZD.js +5364 -0
  56. package/bundled-test-harness/assets/card-chooser-paging-test-BN21sDpP.js +235 -0
  57. package/bundled-test-harness/assets/card-chooser-test-C9jDiIgM.js +393 -0
  58. package/bundled-test-harness/assets/card-context-search-results-KmkXJbmC.js +30 -0
  59. package/bundled-test-harness/assets/card-context-search-results-test-CpMr8OlX.js +184 -0
  60. package/bundled-test-harness/assets/card-def-field-def-relationships-test-D_30xak6.js +562 -0
  61. package/bundled-test-harness/assets/card-def-menu-items-test-ohuHc0b4.js +228 -0
  62. package/bundled-test-harness/assets/card-delete-test-BlsD9Xw4.js +466 -0
  63. package/bundled-test-harness/assets/card-error-3q1o3i0e.js +72 -0
  64. package/bundled-test-harness/assets/card-error-awaiting-index-test-DPgYKfbF.js +53 -0
  65. package/bundled-test-harness/assets/card-info-thumbnail-picker-test-CVfeJyjt.js +219 -0
  66. package/bundled-test-harness/assets/card-playground-test-D-7bi4PQ.js +1491 -0
  67. package/bundled-test-harness/assets/card-prerender-DemTfK_a.js +12939 -0
  68. package/bundled-test-harness/assets/card-thunk-error-test-DCBh1vRT.js +48 -0
  69. package/bundled-test-harness/assets/card-type-service-test-DXPrfVYk.js +161 -0
  70. package/bundled-test-harness/assets/check-correctness-test-DjE7r1X2.js +1093 -0
  71. package/bundled-test-harness/assets/check-domain-availability-test-U10xSKbY.js +98 -0
  72. package/bundled-test-harness/assets/chip-0r_r9SC8.js +44 -0
  73. package/bundled-test-harness/assets/choreo-CZUXQKjf.js +1110 -0
  74. package/bundled-test-harness/assets/choreo-D8RcLuoq.js +2 -0
  75. package/bundled-test-harness/assets/choreo-feature-reel-test-DRGloCAJ.js +155 -0
  76. package/bundled-test-harness/assets/choreo-gallery-build-order-test-BR-r7gaw.js +436 -0
  77. package/bundled-test-harness/assets/choreo-gallery-compositor-test-CWRLfcNT.js +399 -0
  78. package/bundled-test-harness/assets/choreo-gallery-cover-test-BT05gNKC.js +214 -0
  79. package/bundled-test-harness/assets/choreo-gallery-crossing-stage-test-WJ7FmjYi.js +133 -0
  80. package/bundled-test-harness/assets/choreo-gallery-demos-alive-test-C-yxdVT_.js +42 -0
  81. package/bundled-test-harness/assets/choreo-gallery-drift-test-HX1mK3od.js +620 -0
  82. package/bundled-test-harness/assets/choreo-gallery-escort-test-jZEVk_V4.js +187 -0
  83. package/bundled-test-harness/assets/choreo-gallery-films-test-DLDQzsxb.js +140 -0
  84. package/bundled-test-harness/assets/choreo-gallery-filter-test-BJv8KEeP.js +46 -0
  85. package/bundled-test-harness/assets/choreo-gallery-fold-test-BssKC8A8.js +180 -0
  86. package/bundled-test-harness/assets/choreo-gallery-guide-pages-test-DS41eNNV.js +114 -0
  87. package/bundled-test-harness/assets/choreo-gallery-guides-test-DTj7yEKp.js +321 -0
  88. package/bundled-test-harness/assets/choreo-gallery-hang-test-BqJLmeFF.js +426 -0
  89. package/bundled-test-harness/assets/choreo-gallery-highlight-test-B1Q7-ICm.js +60 -0
  90. package/bundled-test-harness/assets/choreo-gallery-inline-edit-test-7My9lVam.js +370 -0
  91. package/bundled-test-harness/assets/choreo-gallery-interruption-test-BlIAaGrw.js +176 -0
  92. package/bundled-test-harness/assets/choreo-gallery-lone-stack-test-C9NnYIP8.js +104 -0
  93. package/bundled-test-harness/assets/choreo-gallery-navigation-test-CWzXkvbW.js +193 -0
  94. package/bundled-test-harness/assets/choreo-gallery-playhead-transport-test-CwdiZWeI.js +111 -0
  95. package/bundled-test-harness/assets/choreo-gallery-poplayout-subtree-test-D55fxwTn.js +127 -0
  96. package/bundled-test-harness/assets/choreo-gallery-presence-modes-test-D8Wxv0lb.js +100 -0
  97. package/bundled-test-harness/assets/choreo-gallery-presentation-test-BLoWfp6G.js +157 -0
  98. package/bundled-test-harness/assets/choreo-gallery-reduced-motion-test-D5XxTBDS.js +145 -0
  99. package/bundled-test-harness/assets/choreo-gallery-sheet-standalone-test-DrHTTvss.js +89 -0
  100. package/bundled-test-harness/assets/choreo-gallery-sheet-test-BFVdnM_b.js +48 -0
  101. package/bundled-test-harness/assets/choreo-gallery-site-test-BhEBHdvI.js +237 -0
  102. package/bundled-test-harness/assets/choreo-gallery-stage-DcKKsdcu.js +256 -0
  103. package/bundled-test-harness/assets/choreo-gallery-stage-keyboard-test-Fcc6SC3F.js +102 -0
  104. package/bundled-test-harness/assets/choreo-gallery-stages-test-Cb-ADpxK.js +35 -0
  105. package/bundled-test-harness/assets/choreo-gallery-subdivision-test-DMJ6C9FW.js +138 -0
  106. package/bundled-test-harness/assets/choreo-gallery-table-plan-test-CAjSUdLJ.js +144 -0
  107. package/bundled-test-harness/assets/choreo-gallery-theater-test-B-3IZMj9.js +252 -0
  108. package/bundled-test-harness/assets/choreo-gallery-tuning-test-BVxK5Ry_.js +95 -0
  109. package/bundled-test-harness/assets/choreo-gallery-widget-room-test-uWBH1EKE.js +88 -0
  110. package/bundled-test-harness/assets/choreo-gallery-wires-test-Bo4Sd1Vn.js +148 -0
  111. package/bundled-test-harness/assets/client-telemetry-test-DFM4mML2.js +340 -0
  112. package/bundled-test-harness/assets/clip-DY6N6K67.js +92 -0
  113. package/bundled-test-harness/assets/clip-DzXoPdp-.js +2 -0
  114. package/bundled-test-harness/assets/code-block-DRE8KQZQ.js +502 -0
  115. package/bundled-test-harness/assets/code-ref-test-CDcqE8_C.js +163 -0
  116. package/bundled-test-harness/assets/code-submode-availability-test-DPTqZYYm.js +198 -0
  117. package/bundled-test-harness/assets/code-submode-test-AHV4mzJ4.js +1839 -0
  118. package/bundled-test-harness/assets/codeblocks-test-D6ijVvEL.js +418 -0
  119. package/bundled-test-harness/assets/codemirror-editor-test-BeAMVivu.js +1512 -0
  120. package/bundled-test-harness/assets/codemirror-embed-toolbar-test-Bnb7_KUT.js +366 -0
  121. package/bundled-test-harness/assets/color-field-test-CR6gGEqE.js +212 -0
  122. package/bundled-test-harness/assets/compaction-test-CjEsY0uG.js +150 -0
  123. package/bundled-test-harness/assets/computed-test-DtyZGgdc.js +1320 -0
  124. package/bundled-test-harness/assets/container-BYGZImLU.css +5101 -0
  125. package/bundled-test-harness/assets/container-CBZZ8uFw.js +10925 -0
  126. package/bundled-test-harness/assets/content-preview-components-test-BztI4fz-.js +462 -0
  127. package/bundled-test-harness/assets/copy-and-edit-test-Cqw7kcur.js +292 -0
  128. package/bundled-test-harness/assets/copy-card-test-D5m3eVEH.js +218 -0
  129. package/bundled-test-harness/assets/copy-file-to-realm-test-FPY-6Ddm.js +148 -0
  130. package/bundled-test-harness/assets/copy-source-test-9pJD-qey.js +56 -0
  131. package/bundled-test-harness/assets/create-file-test-DjMf88u_.js +1086 -0
  132. package/bundled-test-harness/assets/create-file-test-XbgOqg38.js +464 -0
  133. package/bundled-test-harness/assets/create-listing-modal-test-De7b4vu3.js +273 -0
  134. package/bundled-test-harness/assets/create-listing-pr-request-test-CBtIV0Z8.js +117 -0
  135. package/bundled-test-harness/assets/create-spec-test-4xR0gM7E.js +256 -0
  136. package/bundled-test-harness/assets/create-submission-workflow-test-DQpWrpGT.js +132 -0
  137. package/bundled-test-harness/assets/create-workspace-test-BQAudgpS.js +104 -0
  138. package/bundled-test-harness/assets/credential-fields-test-DXKBdbZD.js +200 -0
  139. package/bundled-test-harness/assets/csv-file-def-test-Cnp4y834.js +102 -0
  140. package/bundled-test-harness/assets/dashboard-CmuOhIYC.js +3628 -0
  141. package/bundled-test-harness/assets/dashboard-CzN49x74.css +2400 -0
  142. package/bundled-test-harness/assets/dashboard-add-workspace-test-T32hWB-g.js +50 -0
  143. package/bundled-test-harness/assets/dashboard-agents-test-BN5maCgQ.js +334 -0
  144. package/bundled-test-harness/assets/dashboard-archive-test-BzwUte_Z.js +128 -0
  145. package/bundled-test-harness/assets/dashboard-delete-test-D2Gcp81V.js +163 -0
  146. package/bundled-test-harness/assets/dashboard-duplicate-offer-test-BgKNIr35.js +71 -0
  147. package/bundled-test-harness/assets/dashboard-duplicate-test-D7JEWylc.js +222 -0
  148. package/bundled-test-harness/assets/dashboard-get-started-test-DOGPzGoA.js +374 -0
  149. package/bundled-test-harness/assets/dashboard-ir2bakJS.js +142 -0
  150. package/bundled-test-harness/assets/dashboard-pinned-cards-test-Bn_P9xJU.js +220 -0
  151. package/bundled-test-harness/assets/dashboard-publish-test-64sGQ0nG.js +70 -0
  152. package/bundled-test-harness/assets/dashboard-reindex-test-DJjYq1ct.js +115 -0
  153. package/bundled-test-harness/assets/dashboard-section-rail-test-ZkAhWu5V.js +169 -0
  154. package/bundled-test-harness/assets/dashboard-state-test-BbkpPB5L.js +162 -0
  155. package/bundled-test-harness/assets/dashboard-test-CBLdPrSt.js +545 -0
  156. package/bundled-test-harness/assets/dashboard-unreachable-notice-test-DFT3R1Zx.js +62 -0
  157. package/bundled-test-harness/assets/dashboard-workspace-test-DqBdCFo2.js +537 -0
  158. package/bundled-test-harness/assets/dashboard-workspaces-section-test-CH1HDfxR.js +410 -0
  159. package/bundled-test-harness/assets/data-file-def-preview-test-CNsZwQEJ.js +155 -0
  160. package/bundled-test-harness/assets/date-time-fields-test-CEFaZTnF.js +359 -0
  161. package/bundled-test-harness/assets/debug-message-test-Ck3BfFv3.js +117 -0
  162. package/bundled-test-harness/assets/declared-captures-test-C-0yPRU7.js +879 -0
  163. package/bundled-test-harness/assets/delete-workspace-test-CZOwGy78.js +102 -0
  164. package/bundled-test-harness/assets/diffing-test-BEKI905O.js +210 -0
  165. package/bundled-test-harness/assets/download-file-to-realm-test-C1kAGDll.js +119 -0
  166. package/bundled-test-harness/assets/editor-test-C9x5ZY6g.js +688 -0
  167. package/bundled-test-harness/assets/edits-D76-aanh.js +651 -0
  168. package/bundled-test-harness/assets/email-field-test-LGkrB_2B.js +75 -0
  169. package/bundled-test-harness/assets/enum-field-test-CPyV1J-m.js +935 -0
  170. package/bundled-test-harness/assets/error-display-test-bWuUtfIG.js +343 -0
  171. package/bundled-test-harness/assets/evaluate-module-test-CbS5h8t3.js +91 -0
  172. package/bundled-test-harness/assets/execute-atomic-operations-test-B4Kfco0k.js +113 -0
  173. package/bundled-test-harness/assets/externals-k-2ZBepK.js +4393 -0
  174. package/bundled-test-harness/assets/fallback-banner-live-delete-test-CuFiH1D8.js +207 -0
  175. package/bundled-test-harness/assets/fallback-banner-test-CqSRN7D8.js +225 -0
  176. package/bundled-test-harness/assets/fallback-banner-test-DQkrFE4-.js +53 -0
  177. package/bundled-test-harness/assets/fallback-models-test-BWekNxC0.js +161 -0
  178. package/bundled-test-harness/assets/fetch-card-json-test-DULUqUEu.js +61 -0
  179. package/bundled-test-harness/assets/field-configuration-test-BXZq28xa.js +551 -0
  180. package/bundled-test-harness/assets/field-markdown-domain-test-DdXCifs6.js +616 -0
  181. package/bundled-test-harness/assets/field-markdown-oversize-test-DouPPTHX.js +88 -0
  182. package/bundled-test-harness/assets/field-markdown-primitives-test-DSRGJeyl.js +365 -0
  183. package/bundled-test-harness/assets/field-markdown-specialized-test-DlTYLl_s.js +534 -0
  184. package/bundled-test-harness/assets/field-playground-test-NhS4VvoN.js +894 -0
  185. package/bundled-test-harness/assets/field-support-predicates-test-DWpyT1Qf.js +167 -0
  186. package/bundled-test-harness/assets/file-attachment-test-LwZf-BSY.js +796 -0
  187. package/bundled-test-harness/assets/file-chooser-panel-test-DuAqD9bn.js +153 -0
  188. package/bundled-test-harness/assets/file-chooser-test-CjaXXwpT.js +504 -0
  189. package/bundled-test-harness/assets/file-def-format-templates-test-BDs4OmHq.js +380 -0
  190. package/bundled-test-harness/assets/file-def-live-reload-test-BqTdnq-W.js +124 -0
  191. package/bundled-test-harness/assets/file-def-menu-items-test-DqdINXsD.js +138 -0
  192. package/bundled-test-harness/assets/file-def-navigation-test-BPGr0SQy.js +109 -0
  193. package/bundled-test-harness/assets/file-def-serialization-test-CvjW-FlC.js +89 -0
  194. package/bundled-test-harness/assets/file-def-test-C-Yv_NjS.js +216 -0
  195. package/bundled-test-harness/assets/file-preview-live-reload-test-MzwGwasU.js +310 -0
  196. package/bundled-test-harness/assets/file-resource-primitives-test-D3GmfqNs.js +255 -0
  197. package/bundled-test-harness/assets/file-tree-from-index-test-CfldnUgm.js +96 -0
  198. package/bundled-test-harness/assets/file-tree-test--0ZCPRe9.js +851 -0
  199. package/bundled-test-harness/assets/file-view-model-test-BDIAeBV8.js +346 -0
  200. package/bundled-test-harness/assets/filedef-export-shape-test-B2tgU404.js +61 -0
  201. package/bundled-test-harness/assets/film-Bf73ypzi.js +4074 -0
  202. package/bundled-test-harness/assets/film-C54lhaiU.js +2 -0
  203. package/bundled-test-harness/assets/film-DPcMEHYu.js +13 -0
  204. package/bundled-test-harness/assets/flac-audio-def-test-ByoXMoQ1.js +143 -0
  205. package/bundled-test-harness/assets/font-metadata-extractor-test-hawLTDTG.js +415 -0
  206. package/bundled-test-harness/assets/formatted-aibot-message-test-BahBj3x8.js +109 -0
  207. package/bundled-test-harness/assets/formatted-user-message-test-CodbrU3t.js +43 -0
  208. package/bundled-test-harness/assets/freestyle-test-faQhSciz.js +17 -0
  209. package/bundled-test-harness/assets/full-reindex-realm-test-CE5RJTIC.js +101 -0
  210. package/bundled-test-harness/assets/garbage-collection-test-v-3sev77.js +403 -0
  211. package/bundled-test-harness/assets/general-test-DKZPBtSb.js +923 -0
  212. package/bundled-test-harness/assets/generate-example-cards-one-shot-test-CucWyrkH.js +65 -0
  213. package/bundled-test-harness/assets/generic-file-def-preview-test-_EDRsebi.js +71 -0
  214. package/bundled-test-harness/assets/get-available-realm-identifiers-test-CV023yek.js +47 -0
  215. package/bundled-test-harness/assets/get-catalog-realm-identifiers-test--DOu3DyV.js +47 -0
  216. package/bundled-test-harness/assets/get-default-writable-realm-test-Bic8jl6R.js +54 -0
  217. package/bundled-test-harness/assets/get-published-realms-test-DrA5YcFN.js +71 -0
  218. package/bundled-test-harness/assets/get-realm-of-resource-identifier-test-jfU6SIWn.js +54 -0
  219. package/bundled-test-harness/assets/get-relationship-membership-state-test-Ccy2Z7MN.js +1308 -0
  220. package/bundled-test-harness/assets/get-user-system-card-test-Bmq2lmWv.js +67 -0
  221. package/bundled-test-harness/assets/gif-image-def-test-N1mMQC-X.js +188 -0
  222. package/bundled-test-harness/assets/glimmer-motion-and-choreo-in-cards-test-BkUDjiTs.js +160 -0
  223. package/bundled-test-harness/assets/glimmer-motion-and-choreo-test-DsFWCzTs.js +74 -0
  224. package/bundled-test-harness/assets/gts-file-def-test-BL1jpQ9J.js +100 -0
  225. package/bundled-test-harness/assets/head-format-preview-test-BVCaPQqc.js +158 -0
  226. package/bundled-test-harness/assets/helpers-Ds68JxHe.js +5 -0
  227. package/bundled-test-harness/assets/host-mode-service-B4bisRdR.js +262 -0
  228. package/bundled-test-harness/assets/host-mode-test-BmkN2PCJ.js +831 -0
  229. package/bundled-test-harness/assets/host-submode-test-C6SxQ796.js +1392 -0
  230. package/bundled-test-harness/assets/html-component-test-CNQ9wF0Q.js +65 -0
  231. package/bundled-test-harness/assets/html-def-test-BcaCVVQq.js +160 -0
  232. package/bundled-test-harness/assets/html-meta-extractor-test-BU1hjkTp.js +60 -0
  233. package/bundled-test-harness/assets/hydratable-card-test-CX6MWiti.js +426 -0
  234. package/bundled-test-harness/assets/icon-button-C1zH38Nc.js +67 -0
  235. package/bundled-test-harness/assets/image-metadata-extractor-test-CakSBPZ_.js +1109 -0
  236. package/bundled-test-harness/assets/index-changes-test-D8RtgfyG.js +367 -0
  237. package/bundled-test-harness/assets/index-query-engine-test-BETfoYOK.js +2593 -0
  238. package/bundled-test-harness/assets/index-writer-test-B_bR2fjw.js +3040 -0
  239. package/bundled-test-harness/assets/inspector-test-BwPXJj1S.js +2058 -0
  240. package/bundled-test-harness/assets/instance-filter-matcher-test-BSVCg59b.js +788 -0
  241. package/bundled-test-harness/assets/instantiate-card-test-BVQhZjpq.js +164 -0
  242. package/bundled-test-harness/assets/interact-submode-creation-and-permissions-test-DzQLG41H.js +475 -0
  243. package/bundled-test-harness/assets/interact-submode-setup-C5bKXq73.js +566 -0
  244. package/bundled-test-harness/assets/invalidate-realm-identifiers-test-Cd3dpjhB.js +99 -0
  245. package/bundled-test-harness/assets/invite-user-to-room-test-Brabz1tt.js +142 -0
  246. package/bundled-test-harness/assets/invoke-card-operation-test-C1Q1FUf4.js +333 -0
  247. package/bundled-test-harness/assets/isolated-render-test-BLJfS7BU.js +51 -0
  248. package/bundled-test-harness/assets/job-scoped-doc-cache-test-Bgv5woaB.js +181 -0
  249. package/bundled-test-harness/assets/job-scoped-instance-residency-test-C_bB6KpR.js +103 -0
  250. package/bundled-test-harness/assets/jpg-image-def-test-gdLIKocD.js +697 -0
  251. package/bundled-test-harness/assets/json-file-def-test-CPYMRBY-.js +95 -0
  252. package/bundled-test-harness/assets/key-notices-badge-test-DemslfLw.js +155 -0
  253. package/bundled-test-harness/assets/key-readiness-test-5tq5JycL.js +190 -0
  254. package/bundled-test-harness/assets/linksto-broken-link-placeholder-test-BbhDZ2PH.js +398 -0
  255. package/bundled-test-harness/assets/linksto-error-sentinel-test-C2t7fFPi.js +238 -0
  256. package/bundled-test-harness/assets/linksto-many-broken-link-placeholder-test--U_UvUty.js +354 -0
  257. package/bundled-test-harness/assets/linksto-many-per-slot-access-test-Dj3Xy0ZF.js +303 -0
  258. package/bundled-test-harness/assets/linksto-sentinel-reload-test-D0dK4Jjs.js +197 -0
  259. package/bundled-test-harness/assets/linksto-sentinel-roundtrip-test---IYiXok.js +260 -0
  260. package/bundled-test-harness/assets/linksto-singular-js-access-contract-test-CT04MhES.js +196 -0
  261. package/bundled-test-harness/assets/lint-and-fix-test-aadgx7rX.js +51 -0
  262. package/bundled-test-harness/assets/live-test-BGij_vuc.js +100 -0
  263. package/bundled-test-harness/assets/live-test-CppvValf.js +2 -0
  264. package/bundled-test-harness/assets/load-default-skills-test-Cp2m_ebp.js +74 -0
  265. package/bundled-test-harness/assets/loader-parallel-prefetch-test-vU_26Jqu.js +257 -0
  266. package/bundled-test-harness/assets/loader-test-CTaw8K_B.js +482 -0
  267. package/bundled-test-harness/assets/loading-test-DGGt4qZZ.js +63 -0
  268. package/bundled-test-harness/assets/m4a-audio-def-test-DAiReOXH.js +190 -0
  269. package/bundled-test-harness/assets/main-bXHwJ0CN.js +5 -0
  270. package/bundled-test-harness/assets/markdown-embed-chooser-modal-test-CIXq9FqR.js +470 -0
  271. package/bundled-test-harness/assets/markdown-embed-chooser-test-zFGh9WfP.js +334 -0
  272. package/bundled-test-harness/assets/markdown-embed-preview-pane-test-Byn_WFwY.js +447 -0
  273. package/bundled-test-harness/assets/markdown-embed-preview-test-Y3iFMttg.js +368 -0
  274. package/bundled-test-harness/assets/markdown-fallback-test-Br1TPkLZ.js +316 -0
  275. package/bundled-test-harness/assets/markdown-file-def-test-Crm2MAnq.js +380 -0
  276. package/bundled-test-harness/assets/markdown-helpers-test-CZ9Vvywc.js +188 -0
  277. package/bundled-test-harness/assets/markdown-highlighting-test-CFMkoVDl.js +244 -0
  278. package/bundled-test-harness/assets/markdown-preview-lOh-MyqF.js +72 -0
  279. package/bundled-test-harness/assets/markdown-preview-test-B8w0fFIy.js +238 -0
  280. package/bundled-test-harness/assets/markdown-skill-frontmatter-test-aH6HQly1.js +146 -0
  281. package/bundled-test-harness/assets/markdown-skill-search-test-CiNLQs-5.js +80 -0
  282. package/bundled-test-harness/assets/matrix-service-account-switch-sessions-test-DaA8w1Jj.js +63 -0
  283. package/bundled-test-harness/assets/matrix-service-boot-assembly-test-21GIlf55.js +300 -0
  284. package/bundled-test-harness/assets/matrix-service-personal-realm-test-jn9DUENm.js +125 -0
  285. package/bundled-test-harness/assets/matrix-service-realm-servers-test-eNZVJakl.js +55 -0
  286. package/bundled-test-harness/assets/matrix-service-realms-list-updated-test-Cabm8_dY.js +132 -0
  287. package/bundled-test-harness/assets/matrix-service-relogin-test-C77EFgjc.js +59 -0
  288. package/bundled-test-harness/assets/matrix-service-sliding-sync-test-BgM0fPiO.js +35 -0
  289. package/bundled-test-harness/assets/menu-Cl50TSFe.js +3561 -0
  290. package/bundled-test-harness/assets/message-service-subscription-test-CfEqH2jP.js +110 -0
  291. package/bundled-test-harness/assets/message-service-test-DsTzH1In.js +144 -0
  292. package/bundled-test-harness/assets/message-tool-test-C5xVfTtj.js +33 -0
  293. package/bundled-test-harness/assets/midi-audio-def-test-goLRCNCZ.js +182 -0
  294. package/bundled-test-harness/assets/migrate-skill-test-yPCbVfxG.js +161 -0
  295. package/bundled-test-harness/assets/mini-YXjrY_tH.js +1404 -0
  296. package/bundled-test-harness/assets/mini-card-chooser-test-DrllikHB.js +272 -0
  297. package/bundled-test-harness/assets/mini-file-chooser-test-BfqayhmI.js +201 -0
  298. package/bundled-test-harness/assets/mock-matrix-C7BrPS6S.js +2 -0
  299. package/bundled-test-harness/assets/mock-matrix-FjsXmU7-.js +15107 -0
  300. package/bundled-test-harness/assets/modal-BgaZavcs.js +322 -0
  301. package/bundled-test-harness/assets/model-cost-tier-test-BGg-sJML.js +174 -0
  302. package/bundled-test-harness/assets/model-file-extract-test-CjEBupY5.js +206 -0
  303. package/bundled-test-harness/assets/module-transpile-cache-test-XW6DDsmz.js +67 -0
  304. package/bundled-test-harness/assets/monaco-test-DkoRuFiQ.js +100 -0
  305. package/bundled-test-harness/assets/mp3-audio-def-test-v369NNsQ.js +133 -0
  306. package/bundled-test-harness/assets/multiple-stacks-test-CJpYPWdM.js +208 -0
  307. package/bundled-test-harness/assets/nested-query-field-render-test-CfDrBcUN.js +249 -0
  308. package/bundled-test-harness/assets/no-stacks-test-MmsJeLpz.js +48 -0
  309. package/bundled-test-harness/assets/number-field-test-A7B2r0M5.js +184 -0
  310. package/bundled-test-harness/assets/office-file-def-test-BNRvFmCB.js +263 -0
  311. package/bundled-test-harness/assets/office-metadata-extractor-test-zlDoEIEp.js +218 -0
  312. package/bundled-test-harness/assets/office-poster-capture-test-DdFEaOxR.js +203 -0
  313. package/bundled-test-harness/assets/ogg-audio-def-test-kk91BzQY.js +196 -0
  314. package/bundled-test-harness/assets/open-create-listing-modal-test-D1Dl1pov.js +131 -0
  315. package/bundled-test-harness/assets/open-image-in-new-tab-test-DyCmdMyO.js +52 -0
  316. package/bundled-test-harness/assets/open-secure-window-test-dz1vPudF.js +253 -0
  317. package/bundled-test-harness/assets/open-workspace-test-BvTcskzP.js +46 -0
  318. package/bundled-test-harness/assets/operation-lowering-test-omU66bkJ.js +2957 -0
  319. package/bundled-test-harness/assets/operations-invocation-test-BMj42rQe.js +523 -0
  320. package/bundled-test-harness/assets/operations-optimistic-test-KJLyzT8v.js +203 -0
  321. package/bundled-test-harness/assets/operations-query-test-J3HcnaoK.js +459 -0
  322. package/bundled-test-harness/assets/operations-store-reconciliation-test-CkbGBMBQ.js +406 -0
  323. package/bundled-test-harness/assets/operations-test-C7zXXpRW.js +2518 -0
  324. package/bundled-test-harness/assets/operator-mode-acceptance-test-BPolI_RD.js +1195 -0
  325. package/bundled-test-harness/assets/operator-mode-card-chooser-test-DjTQgizt.js +1036 -0
  326. package/bundled-test-harness/assets/operator-mode-links-test-DSEqy5Db.js +797 -0
  327. package/bundled-test-harness/assets/operator-mode-test-CB7BNDNE.js +696 -0
  328. package/bundled-test-harness/assets/operator-mode-ui-test-C1OhF1il.js +1045 -0
  329. package/bundled-test-harness/assets/overlay-D2rQi8lJ.js +427 -0
  330. package/bundled-test-harness/assets/overlay-menu-items-test-CPN31yBJ.js +331 -0
  331. package/bundled-test-harness/assets/overlays-B-qMEPhY.js +2 -0
  332. package/bundled-test-harness/assets/overlays-DSf2je0c.js +75 -0
  333. package/bundled-test-harness/assets/overlays-detached-element-test-C73nMXes.js +56 -0
  334. package/bundled-test-harness/assets/panel-DjrC7DxA.js +15124 -0
  335. package/bundled-test-harness/assets/past-sessions-test-BSIS2Hlq.js +321 -0
  336. package/bundled-test-harness/assets/patch-fields-test-Bp2IE0Jw.js +1014 -0
  337. package/bundled-test-harness/assets/patch-instance-test-DssuRGKP.js +348 -0
  338. package/bundled-test-harness/assets/pdf-file-def-test-Barj9ffD.js +111 -0
  339. package/bundled-test-harness/assets/pdf-metadata-extractor-test-B7KnXcIm.js +130 -0
  340. package/bundled-test-harness/assets/permission-checking-realm-test-BD4O0nen.js +306 -0
  341. package/bundled-test-harness/assets/persist-module-inspector-view-test-BIdbkdPr.js +60 -0
  342. package/bundled-test-harness/assets/persist-scroll-position-test-Bhb7wJiy.js +254 -0
  343. package/bundled-test-harness/assets/phone-number-field-test-C2yuCrXY.js +73 -0
  344. package/bundled-test-harness/assets/pill-menu-test-BIp91YXi.js +60 -0
  345. package/bundled-test-harness/assets/plate-CJq1veVA.js +41 -0
  346. package/bundled-test-harness/assets/plate-CwAvOUfL.js +2 -0
  347. package/bundled-test-harness/assets/player-Digk7omr.js +2 -0
  348. package/bundled-test-harness/assets/player-vsjosoN_.js +82 -0
  349. package/bundled-test-harness/assets/playground-B02e8uqB.js +58 -0
  350. package/bundled-test-harness/assets/plural-field-components-test-C1acuN-A.js +198 -0
  351. package/bundled-test-harness/assets/png-image-def-test-B9QeVo1f.js +266 -0
  352. package/bundled-test-harness/assets/policy-audit-confirmation-test-CeVquvc_.js +155 -0
  353. package/bundled-test-harness/assets/policy-scoped-search-test-SFPiIqR3.js +339 -0
  354. package/bundled-test-harness/assets/prerender-file-extract-test-HSJKAHyO.js +346 -0
  355. package/bundled-test-harness/assets/prerender-html-test-BTAcFCme.js +670 -0
  356. package/bundled-test-harness/assets/prerender-meta-test-Csyz2b21.js +614 -0
  357. package/bundled-test-harness/assets/prerender-module-test-DpTYAbmI.js +409 -0
  358. package/bundled-test-harness/assets/prerender-persistence-block-test-BhIt-7kK.js +124 -0
  359. package/bundled-test-harness/assets/prerender-pre-model-error-test-DxKPQKqx.js +61 -0
  360. package/bundled-test-harness/assets/prerender-serialize-cycle-test-C8V5YWQO.js +134 -0
  361. package/bundled-test-harness/assets/prerendered-html-read-test-Cq7JVGwg.js +191 -0
  362. package/bundled-test-harness/assets/pretui-components-test-Ducr9fLT.css +743 -0
  363. package/bundled-test-harness/assets/pretui-components-test-Hs0uyIUQ.js +992 -0
  364. package/bundled-test-harness/assets/pretui-primitives-CRs8NRm0.js +69 -0
  365. package/bundled-test-harness/assets/preview-format-test-cCqLrfdY.js +103 -0
  366. package/bundled-test-harness/assets/preview-test-BMqJSoR1.js +474 -0
  367. package/bundled-test-harness/assets/process-card-test-578tfDvr.js +94 -0
  368. package/bundled-test-harness/assets/profile-settings-modal-CVnNl7Yu.js +990 -0
  369. package/bundled-test-harness/assets/publish-realm-COoeWexp.js +82 -0
  370. package/bundled-test-harness/assets/publish-realm-test-a5nkx0Ov.js +210 -0
  371. package/bundled-test-harness/assets/query-field-barrier-test-qX3xVPfk.js +113 -0
  372. package/bundled-test-harness/assets/query-field-error-sentinel-test-V6JDPFLX.js +201 -0
  373. package/bundled-test-harness/assets/query-field-membership-status-test-CK7eDf-K.js +323 -0
  374. package/bundled-test-harness/assets/query-field-page-optin-test-B5YBHUvU.js +126 -0
  375. package/bundled-test-harness/assets/query-field-schema-test-D4SjOGlK.js +231 -0
  376. package/bundled-test-harness/assets/query-field-search-throttle-test-BVkm1-D8.js +154 -0
  377. package/bundled-test-harness/assets/query-field-stale-prerender-test-9g7hcD91.js +152 -0
  378. package/bundled-test-harness/assets/query-fields-test-CQYqhzpN.js +535 -0
  379. package/bundled-test-harness/assets/quick-look-test-CE0o6lJ4.js +139 -0
  380. package/bundled-test-harness/assets/read-card-for-ai-assistant-test-D0mJorwH.js +91 -0
  381. package/bundled-test-harness/assets/read-file-for-ai-assistant-test-B_F_2GEB.js +45 -0
  382. package/bundled-test-harness/assets/read-source-test-BgJV4B4F.js +67 -0
  383. package/bundled-test-harness/assets/read-text-file-test-DaeLzg4u.js +124 -0
  384. package/bundled-test-harness/assets/realm-C_a9su1j.js +2858 -0
  385. package/bundled-test-harness/assets/realm-api-keys-D5USFOoS.js +2 -0
  386. package/bundled-test-harness/assets/realm-api-keys-m_VOcixC.js +578 -0
  387. package/bundled-test-harness/assets/realm-api-keys-test-BVs7f5Dz.js +109 -0
  388. package/bundled-test-harness/assets/realm-api-keys-test-C_uZnTmq.js +588 -0
  389. package/bundled-test-harness/assets/realm-config-m5eccPW8.js +833 -0
  390. package/bundled-test-harness/assets/realm-config-policy-standing-test-Ber-IXpc.js +290 -0
  391. package/bundled-test-harness/assets/realm-config-routing-rule-edit-test-3Xqt5VlM.js +274 -0
  392. package/bundled-test-harness/assets/realm-config-settings-test-CkalhbDF.js +187 -0
  393. package/bundled-test-harness/assets/realm-field-test-B_PUoqnk.js +100 -0
  394. package/bundled-test-harness/assets/realm-indexing-test-8iLjeV_e.js +4380 -0
  395. package/bundled-test-harness/assets/realm-policy-fitted-test-Bptvra0U.js +206 -0
  396. package/bundled-test-harness/assets/realm-policy-test-DwG0qqXE.js +1141 -0
  397. package/bundled-test-harness/assets/realm-querying-test-Dvw26A6Q.js +1067 -0
  398. package/bundled-test-harness/assets/realm-server-form-agnostic-test-DrXQH0UP.js +96 -0
  399. package/bundled-test-harness/assets/realm-server-subscriber-test-Dkj23vQK.js +46 -0
  400. package/bundled-test-harness/assets/realm-service-info-test-CdRlDhj-.js +67 -0
  401. package/bundled-test-harness/assets/realm-test-DGYN48Qx.js +2364 -0
  402. package/bundled-test-harness/assets/realm-token-refresh-test-CEWATL9h.js +153 -0
  403. package/bundled-test-harness/assets/realm-url-tooltip-test-8ZjTNPuy.js +78 -0
  404. package/bundled-test-harness/assets/reasoning-test-BV49AYg2.js +221 -0
  405. package/bundled-test-harness/assets/recent-files-test-Dc6L6Dm4.js +450 -0
  406. package/bundled-test-harness/assets/reindex-realm-test-CFRSt39u.js +117 -0
  407. package/bundled-test-harness/assets/relationship-loading-state-test-FKbtOFUr.js +290 -0
  408. package/bundled-test-harness/assets/remix-card-test-CKGC_Sgq.js +58 -0
  409. package/bundled-test-harness/assets/rendered-markdown-DXiDN91F.js +292 -0
  410. package/bundled-test-harness/assets/rendered-markdown-test-n3MlXmmu.js +587 -0
  411. package/bundled-test-harness/assets/resident-instance-reuse-test-BjdhE6CM.js +82 -0
  412. package/bundled-test-harness/assets/result-tile-o6dtjgX4.js +144 -0
  413. package/bundled-test-harness/assets/rich-markdown-field-test-VXr6l20h.js +1647 -0
  414. package/bundled-test-harness/assets/room-message-test-BrjJ2wMs.js +484 -0
  415. package/bundled-test-harness/assets/run-P_7TsreC.js +4017 -0
  416. package/bundled-test-harness/assets/run-realm-code-DsBUf1si.js +2964 -0
  417. package/bundled-test-harness/assets/run-realm-code-test-cS0DzaKo.js +3844 -0
  418. package/bundled-test-harness/assets/sanitize-module-list-test-CvuOOiUY.js +85 -0
  419. package/bundled-test-harness/assets/save-card-skip-index-wait-test-fpJ1eq32.js +89 -0
  420. package/bundled-test-harness/assets/schema-editor-test-NkKjCgyf.js +785 -0
  421. package/bundled-test-harness/assets/schema-generation-test-Dmg3lWl7.js +28 -0
  422. package/bundled-test-harness/assets/scrolling-test-B0GNYGYc.js +412 -0
  423. package/bundled-test-harness/assets/search-adorn-test-CZebk7_y.js +136 -0
  424. package/bundled-test-harness/assets/search-and-choose-test-Bd4NZUup.js +154 -0
  425. package/bundled-test-harness/assets/search-correlation-id-test-DXKlEO55.js +139 -0
  426. package/bundled-test-harness/assets/search-entries-result-test-QQawA8Fm.js +234 -0
  427. package/bundled-test-harness/assets/search-entries-test-3DlqGPQq.js +1486 -0
  428. package/bundled-test-harness/assets/search-entries-tool-test-D1TvDE9D.js +504 -0
  429. package/bundled-test-harness/assets/search-google-images-test-DqsoQGr1.js +166 -0
  430. package/bundled-test-harness/assets/search-results-DGrNaPxh.js +266 -0
  431. package/bundled-test-harness/assets/search-results-test-CqVHYNRt.js +578 -0
  432. package/bundled-test-harness/assets/search-selection-menu-test-D6bIjKiH.js +108 -0
  433. package/bundled-test-harness/assets/search-sheet-files-test-Bf37TQXo.js +126 -0
  434. package/bundled-test-harness/assets/search-sheet-persistence-test-CV4_XdxR.js +131 -0
  435. package/bundled-test-harness/assets/search-test-Dlb-wg3a.js +2249 -0
  436. package/bundled-test-harness/assets/search-tool-test-BJLgVMoL.js +156 -0
  437. package/bundled-test-harness/assets/searchable-option-test-CcbfMqIL.js +322 -0
  438. package/bundled-test-harness/assets/searchable-search-doc-test-yH9fLGNS.js +1271 -0
  439. package/bundled-test-harness/assets/section-rail-CNFCebtT.js +113 -0
  440. package/bundled-test-harness/assets/section-rail-test-KNJAWWl6.js +256 -0
  441. package/bundled-test-harness/assets/secure-sign-in-Dyljp0Th.js +174 -0
  442. package/bundled-test-harness/assets/secure-sign-in-test-QnqNuTP3.js +373 -0
  443. package/bundled-test-harness/assets/segmented-control-DxJdoJ4Z.js +173 -0
  444. package/bundled-test-harness/assets/select-BiQTg2ts.js +175 -0
  445. package/bundled-test-harness/assets/send-ai-assistant-message-test-CAn7M2dZ.js +52 -0
  446. package/bundled-test-harness/assets/send-bot-trigger-event-test-qBu5E_jy.js +56 -0
  447. package/bundled-test-harness/assets/send-request-via-proxy-test-CLuwLBq_.js +380 -0
  448. package/bundled-test-harness/assets/sending-test-H0AaBSgi.js +659 -0
  449. package/bundled-test-harness/assets/serialization-rri-form-audit-test-hMJukiKt.js +136 -0
  450. package/bundled-test-harness/assets/serialization-test-W5e3wKbz.js +8758 -0
  451. package/bundled-test-harness/assets/set-user-system-card-test-CjgWLkNV.js +59 -0
  452. package/bundled-test-harness/assets/setup-CssMNvui.js +772 -0
  453. package/bundled-test-harness/assets/setup-D8YXvK-p.js +2 -0
  454. package/bundled-test-harness/assets/shared-link-target-reuse-test-D42UO8DC.js +207 -0
  455. package/bundled-test-harness/assets/show-card-test-CHEaS514.js +365 -0
  456. package/bundled-test-harness/assets/signed-capture-link-test-BgEu0F-S.js +132 -0
  457. package/bundled-test-harness/assets/single-stack-test-DYcu_v7Z.js +652 -0
  458. package/bundled-test-harness/assets/skills-test-ChmKhADX.js +648 -0
  459. package/bundled-test-harness/assets/skip-boot-index-guard-test-BzRIncDN.js +46 -0
  460. package/bundled-test-harness/assets/spec-test-BYvFR6Xb.js +1077 -0
  461. package/bundled-test-harness/assets/spinner-Bx9x55NA.js +49 -0
  462. package/bundled-test-harness/assets/src-C1hYFgVl.js +216 -0
  463. package/bundled-test-harness/assets/src-CIlLx7Lu.js +5 -0
  464. package/bundled-test-harness/assets/stick-to-bottom-resize-test-DMHsAG0v.js +56 -0
  465. package/bundled-test-harness/assets/store-add-test-D_9IHQjZ.js +50 -0
  466. package/bundled-test-harness/assets/store-module-rebuild-test-BRGZoLRV.js +454 -0
  467. package/bundled-test-harness/assets/store-search-test-3G8JHuj2.js +175 -0
  468. package/bundled-test-harness/assets/store-test-BiKKDqqW.js +3672 -0
  469. package/bundled-test-harness/assets/structured-theme-test-11TNsgUW.js +377 -0
  470. package/bundled-test-harness/assets/summarize-session-test-CwzD_ZbD.js +172 -0
  471. package/bundled-test-harness/assets/svg-image-def-test-zV6aMK9q.js +167 -0
  472. package/bundled-test-harness/assets/switch-submode-test-DQU2cP5_.js +168 -0
  473. package/bundled-test-harness/assets/sync-openrouter-models-test-xrXVaC2H.js +97 -0
  474. package/bundled-test-harness/assets/test-support-BGl3rthw.js +3 -0
  475. package/bundled-test-harness/assets/test-support-BcBv__98.js +99 -0
  476. package/bundled-test-harness/assets/tests-CmM9imwB.js +3598 -0
  477. package/bundled-test-harness/assets/text-file-def-test-Cyq78UFY.js +94 -0
  478. package/bundled-test-harness/assets/text-input-validator-test-DBj7TaM_.js +156 -0
  479. package/bundled-test-harness/assets/text-suggestion-test-C4XAqWqY.js +340 -0
  480. package/bundled-test-harness/assets/theme-card-test-dVNz4tgU.js +621 -0
  481. package/bundled-test-harness/assets/theme-dashboard-nav-test-DYSn5pqo.js +196 -0
  482. package/bundled-test-harness/assets/theme-scheme-island-test-C1WpkfEP.js +264 -0
  483. package/bundled-test-harness/assets/theme-scoped-css-parity-test-BVluppsE.js +176 -0
  484. package/bundled-test-harness/assets/titles-DCvAhECF.js +52 -0
  485. package/bundled-test-harness/assets/titles-ZPeArtS1.js +2 -0
  486. package/bundled-test-harness/assets/to-device-streaming-test-BJ4J1cXe.js +163 -0
  487. package/bundled-test-harness/assets/token-usage-test-WUf4r4fQ.js +160 -0
  488. package/bundled-test-harness/assets/tools-J_Knr_W6.js +774 -0
  489. package/bundled-test-harness/assets/tools-calling-test-CfqZX0Ed.js +200 -0
  490. package/bundled-test-harness/assets/tools-test-B4x58ZmI.js +1624 -0
  491. package/bundled-test-harness/assets/tools-test-Cvau5219.js +3204 -0
  492. package/bundled-test-harness/assets/tooltip-B0rEgyMW.css +66 -0
  493. package/bundled-test-harness/assets/tooltip-DvUMUgVX.js +195 -0
  494. package/bundled-test-harness/assets/transform-cards-test-CYQbZeD9.js +341 -0
  495. package/bundled-test-harness/assets/ts-file-def-preview-test-m39f8Zio.js +95 -0
  496. package/bundled-test-harness/assets/ts-file-def-test-xIcL5xWe.js +92 -0
  497. package/bundled-test-harness/assets/ttf-font-def-test-ClQ2SzFF.js +206 -0
  498. package/bundled-test-harness/assets/turn-settling-test-DZoL2mRT.js +160 -0
  499. package/bundled-test-harness/assets/turn-summary-Bmt7ZxTS.js +1039 -0
  500. package/bundled-test-harness/assets/unpublish-realm-test-0ToTJczx.js +102 -0
  501. package/bundled-test-harness/assets/update-room-skills-test-o_j8NOUV.js +240 -0
  502. package/bundled-test-harness/assets/use-ai-assistant-test-D7HFpxKJ.js +384 -0
  503. package/bundled-test-harness/assets/user-message-BAOt1hS3.js +262 -0
  504. package/bundled-test-harness/assets/validate-realm-test-e3xIbNLB.js +67 -0
  505. package/bundled-test-harness/assets/video-metadata-extractor-test-D8naLSlg.js +520 -0
  506. package/bundled-test-harness/assets/view-visually-test-BuhGau5E.js +335 -0
  507. package/bundled-test-harness/assets/virtual-network-reset-test-CgaFNGPi.js +96 -0
  508. package/bundled-test-harness/assets/wav-audio-def-test-CWG_UdCh.js +160 -0
  509. package/bundled-test-harness/assets/webp-image-def-test-sN4yw8Zu.js +226 -0
  510. package/bundled-test-harness/assets/workspace-0LfPqbYB.js +445 -0
  511. package/bundled-test-harness/assets/workspace-a11y-test-DQxYDRAP.js +197 -0
  512. package/bundled-test-harness/assets/workspace-actions-jGJSfl8M.js +588 -0
  513. package/bundled-test-harness/assets/workspace-behavior-test-BnF-bmBN.js +338 -0
  514. package/bundled-test-harness/assets/workspace-delete-multiple-test-D-rxPDuT.js +212 -0
  515. package/bundled-test-harness/assets/workspace-delete-summary-test-C2-Mve5R.js +63 -0
  516. package/bundled-test-harness/assets/workspace-hosting-test-BvDKdlOb.js +138 -0
  517. package/bundled-test-harness/assets/workspace-indexing-test-B34T3kqD.js +71 -0
  518. package/bundled-test-harness/assets/workspace-test-CJivgv-m.js +51 -0
  519. package/bundled-test-harness/assets/workspace-test-CuSRpPnQ.js +385 -0
  520. package/bundled-test-harness/assets/workspace-timestamp-labels-test-aWgjdbCp.js +68 -0
  521. package/bundled-test-harness/assets/workspace-unit-test-DHMUf2KT.js +122 -0
  522. package/bundled-test-harness/assets/write-binary-file-test-P-hVQuin.js +124 -0
  523. package/bundled-test-harness/assets/write-text-file-test-fXvJueDd.js +191 -0
  524. package/bundled-test-harness/assets/zip-archive-test-C2P5CUSR.js +285 -0
  525. package/bundled-test-harness/assets/zip-file-def-test-BfJZAmGt.js +164 -0
  526. package/bundled-test-harness/boxel-ui-checksum.txt +1 -1
  527. package/bundled-test-harness/index.html +48 -48
  528. package/bundled-test-harness/tests/index.html +50 -50
  529. package/bundled-types/boxel-ui/helpers/theme-scoped-css.ts +4 -0
  530. package/bundled-types/choreo/choreo.gts +58 -2
  531. package/bundled-types/choreo/compile.ts +5 -0
  532. package/bundled-types/choreo/layout-probe.ts +100 -0
  533. package/bundled-types/choreo/run.ts +99 -4
  534. package/bundled-types/host-app/components/operator-mode/dashboard/get-started.gts +152 -7
  535. package/bundled-types/host-app/components/operator-mode/dashboard/index.gts +2 -0
  536. package/bundled-types/host-app/components/operator-mode/dashboard/workspace.gts +5 -3
  537. package/bundled-types/host-app/components/operator-mode/dashboard-modals/workspace-modals.gts +5 -22
  538. package/bundled-types/host-app/components/operator-mode/host-submode/publishing-realm-popover.gts +1 -1
  539. package/bundled-types/host-app/components/operator-mode/host-submode.gts +111 -37
  540. package/bundled-types/host-app/components/operator-mode/motion/stack-motion.gts +92 -33
  541. package/bundled-types/host-app/components/operator-mode/publish-realm-modal.gts +1 -0
  542. package/bundled-types/host-app/components/operator-mode/stack-item.gts +2 -2
  543. package/bundled-types/host-app/components/operator-mode/stack.gts +36 -25
  544. package/bundled-types/host-app/components/operator-mode/submode-layout.gts +2 -2
  545. package/bundled-types/host-app/lib/modal-focus-trap.ts +33 -0
  546. package/bundled-types/host-app/lib/workspace-actions.ts +21 -0
  547. package/bundled-types/host-app/services/host-mode-service.ts +39 -0
  548. package/bundled-types/host-app/services/realm.ts +14 -0
  549. package/bundled-types/host-tests/helpers/dashboard.ts +67 -0
  550. package/package.json +1 -1
  551. package/bundled-test-harness/assets/account-switch-failed-test-FytUFiPO.js +0 -45
  552. package/bundled-test-harness/assets/adapter-DvmPwSZv.js +0 -2
  553. package/bundled-test-harness/assets/add-field-to-card-definition-tool-test-DN525jiY.js +0 -112
  554. package/bundled-test-harness/assets/ai-assistant-create-workspace-test-q3tKqVJQ.js +0 -130
  555. package/bundled-test-harness/assets/ai-assistant-panel-relogin-test-DgeXcCyi.js +0 -46
  556. package/bundled-test-harness/assets/ai-assistant-test-lDIGPKFP.js +0 -2223
  557. package/bundled-test-harness/assets/ai-function-generation-test-D5GbLyvL.js +0 -1176
  558. package/bundled-test-harness/assets/ai-module-creation-test-I3-j2beD.js +0 -151
  559. package/bundled-test-harness/assets/aibot-message-Dmsjifs6.js +0 -1312
  560. package/bundled-test-harness/assets/app-BS9_-DhN.js +0 -14146
  561. package/bundled-test-harness/assets/apply-markdown-edit-test-4zlwt0Db.js +0 -230
  562. package/bundled-test-harness/assets/ask-user-picker-Dr-0qpNr.js +0 -370
  563. package/bundled-test-harness/assets/ask-user-picker-test-633AFdmS.js +0 -39
  564. package/bundled-test-harness/assets/assistant-transcript-test-BgRnLvMg.js +0 -57
  565. package/bundled-test-harness/assets/audio-metadata-extractor-test-4xsQqL-0.js +0 -1176
  566. package/bundled-test-harness/assets/authed-fetch-test-663mT5_N.js +0 -73
  567. package/bundled-test-harness/assets/avif-image-def-test-h01BPIJy.js +0 -187
  568. package/bundled-test-harness/assets/basic-test-DiD6T-8Q.js +0 -139
  569. package/bundled-test-harness/assets/binary-upload-dedupe-test-CkjMPO_e.js +0 -308
  570. package/bundled-test-harness/assets/bot-registration-test-CFZHpwdj.js +0 -97
  571. package/bundled-test-harness/assets/box-test-C3pSy5ED.js +0 -50
  572. package/bundled-test-harness/assets/brand-guide-attachments-test-EoC_u7Vc.js +0 -84
  573. package/bundled-test-harness/assets/brand-guide-custom-css-test-Dn3fvblr.js +0 -196
  574. package/bundled-test-harness/assets/brand-guide-edit-test-NeiT3MyK.js +0 -140
  575. package/bundled-test-harness/assets/brand-logo-mark-field-test-C2A1EnBB.js +0 -86
  576. package/bundled-test-harness/assets/broken-link-template-test-CWn6V5zZ.js +0 -192
  577. package/bundled-test-harness/assets/bundled-base-modules-test-D7mLzpsw.js +0 -54
  578. package/bundled-test-harness/assets/bundled-base-oracle-test-I7xCId_k.js +0 -37
  579. package/bundled-test-harness/assets/buried-stack-item-scroll-test-DFBev0h-.js +0 -236
  580. package/bundled-test-harness/assets/button-BeSuhveJ.js +0 -207
  581. package/bundled-test-harness/assets/bxl-cyclic-graph-test-DPykwvvx.js +0 -47
  582. package/bundled-test-harness/assets/bxl-expression-test-LBWJiFb9.js +0 -250
  583. package/bundled-test-harness/assets/bxl-indexing-test-BuZmLk7y.js +0 -212
  584. package/bundled-test-harness/assets/bxl-platform-module-test-BNIvlkCM.js +0 -71
  585. package/bundled-test-harness/assets/can-invoke-test-t-bFIIeX.js +0 -455
  586. package/bundled-test-harness/assets/can-read-realm-test-2Q_MzRT9.js +0 -56
  587. package/bundled-test-harness/assets/cancel-indexing-job-test-QeYxEukn.js +0 -69
  588. package/bundled-test-harness/assets/capture-test-CJmJG8YR.js +0 -360
  589. package/bundled-test-harness/assets/card-api-test-B43I510H.js +0 -198
  590. package/bundled-test-harness/assets/card-basics-test-CBClzP2y.js +0 -5364
  591. package/bundled-test-harness/assets/card-chooser-paging-test-HEVzf6pR.js +0 -235
  592. package/bundled-test-harness/assets/card-chooser-test-GfjBRPFI.js +0 -393
  593. package/bundled-test-harness/assets/card-context-search-results-CoSr4EdS.js +0 -30
  594. package/bundled-test-harness/assets/card-context-search-results-test-BLMlZu9t.js +0 -184
  595. package/bundled-test-harness/assets/card-def-field-def-relationships-test-DEBOzKan.js +0 -562
  596. package/bundled-test-harness/assets/card-def-menu-items-test-88_h8o0D.js +0 -228
  597. package/bundled-test-harness/assets/card-delete-test-DKom1phy.js +0 -466
  598. package/bundled-test-harness/assets/card-error-awaiting-index-test-DEwgFZMP.js +0 -53
  599. package/bundled-test-harness/assets/card-error-r6_cXst9.js +0 -72
  600. package/bundled-test-harness/assets/card-info-thumbnail-picker-test-B7LiY15e.js +0 -219
  601. package/bundled-test-harness/assets/card-playground-test-CgyIJHui.js +0 -1491
  602. package/bundled-test-harness/assets/card-prerender-rPfzpIOU.js +0 -12939
  603. package/bundled-test-harness/assets/card-thunk-error-test-L0pvg4Ce.js +0 -48
  604. package/bundled-test-harness/assets/card-type-service-test-B2dhqxSD.js +0 -161
  605. package/bundled-test-harness/assets/check-correctness-test-DgqaLlCW.js +0 -1093
  606. package/bundled-test-harness/assets/check-domain-availability-test-B0hJHY5l.js +0 -98
  607. package/bundled-test-harness/assets/chip-D01NW3WH.js +0 -44
  608. package/bundled-test-harness/assets/choreo-D2Jl79RU.js +0 -1019
  609. package/bundled-test-harness/assets/choreo-_E8SOEe-.js +0 -2
  610. package/bundled-test-harness/assets/choreo-feature-reel-test-WLjsZDmS.js +0 -155
  611. package/bundled-test-harness/assets/choreo-gallery-build-order-test-6jnS8PsS.js +0 -436
  612. package/bundled-test-harness/assets/choreo-gallery-compositor-test-CbUZsVB6.js +0 -399
  613. package/bundled-test-harness/assets/choreo-gallery-cover-test-CbvAStgk.js +0 -214
  614. package/bundled-test-harness/assets/choreo-gallery-crossing-stage-test-tdjvUSa6.js +0 -133
  615. package/bundled-test-harness/assets/choreo-gallery-demos-alive-test-CsnM3hQK.js +0 -42
  616. package/bundled-test-harness/assets/choreo-gallery-drift-test-DG2LQTa7.js +0 -620
  617. package/bundled-test-harness/assets/choreo-gallery-escort-test-mn3-qXP1.js +0 -187
  618. package/bundled-test-harness/assets/choreo-gallery-films-test-BuktaC0D.js +0 -140
  619. package/bundled-test-harness/assets/choreo-gallery-filter-test-Dd-zpps0.js +0 -46
  620. package/bundled-test-harness/assets/choreo-gallery-fold-test-CWc1ijGc.js +0 -180
  621. package/bundled-test-harness/assets/choreo-gallery-guide-pages-test-tk2QmYPU.js +0 -114
  622. package/bundled-test-harness/assets/choreo-gallery-guides-test-DVbf1zM4.js +0 -321
  623. package/bundled-test-harness/assets/choreo-gallery-hang-test-B7EFp2dx.js +0 -426
  624. package/bundled-test-harness/assets/choreo-gallery-highlight-test-BFgbdesP.js +0 -60
  625. package/bundled-test-harness/assets/choreo-gallery-inline-edit-test-DJb8FC5R.js +0 -370
  626. package/bundled-test-harness/assets/choreo-gallery-interruption-test-DWyMXo5D.js +0 -176
  627. package/bundled-test-harness/assets/choreo-gallery-lone-stack-test-D3b8LsJ6.js +0 -104
  628. package/bundled-test-harness/assets/choreo-gallery-navigation-test-CjjU6Rvn.js +0 -193
  629. package/bundled-test-harness/assets/choreo-gallery-playhead-transport-test-Le_h3QWU.js +0 -111
  630. package/bundled-test-harness/assets/choreo-gallery-poplayout-subtree-test-Cp-DlWj4.js +0 -127
  631. package/bundled-test-harness/assets/choreo-gallery-presence-modes-test-DayS4GCJ.js +0 -100
  632. package/bundled-test-harness/assets/choreo-gallery-presentation-test-DeAfuFS7.js +0 -157
  633. package/bundled-test-harness/assets/choreo-gallery-reduced-motion-test-BgPWpggq.js +0 -145
  634. package/bundled-test-harness/assets/choreo-gallery-sheet-standalone-test-PzyoMNYv.js +0 -89
  635. package/bundled-test-harness/assets/choreo-gallery-sheet-test-CxaiNBkL.js +0 -48
  636. package/bundled-test-harness/assets/choreo-gallery-site-test-6xtSntS5.js +0 -237
  637. package/bundled-test-harness/assets/choreo-gallery-stage-E6Q5r-zU.js +0 -256
  638. package/bundled-test-harness/assets/choreo-gallery-stage-keyboard-test-C7aWMr9a.js +0 -102
  639. package/bundled-test-harness/assets/choreo-gallery-stages-test-CDWWgC61.js +0 -35
  640. package/bundled-test-harness/assets/choreo-gallery-subdivision-test-Bkp15XJv.js +0 -138
  641. package/bundled-test-harness/assets/choreo-gallery-table-plan-test-CcGRi_3O.js +0 -144
  642. package/bundled-test-harness/assets/choreo-gallery-theater-test-Qph5pLT_.js +0 -252
  643. package/bundled-test-harness/assets/choreo-gallery-tuning-test-C4DhFLVA.js +0 -95
  644. package/bundled-test-harness/assets/choreo-gallery-widget-room-test-LK493r1M.js +0 -88
  645. package/bundled-test-harness/assets/choreo-gallery-wires-test-B7SeUCc8.js +0 -148
  646. package/bundled-test-harness/assets/client-telemetry-test-DGmHzAFx.js +0 -340
  647. package/bundled-test-harness/assets/clip-BpYQPVz_.js +0 -2
  648. package/bundled-test-harness/assets/clip-CNaYbIwL.js +0 -92
  649. package/bundled-test-harness/assets/code-block-Cp2CJo5-.js +0 -502
  650. package/bundled-test-harness/assets/code-ref-test-C8JBHDb-.js +0 -163
  651. package/bundled-test-harness/assets/code-submode-availability-test-CzG1Tv6L.js +0 -198
  652. package/bundled-test-harness/assets/code-submode-test-BclVWjm5.js +0 -1839
  653. package/bundled-test-harness/assets/codeblocks-test-CmQlyxN7.js +0 -418
  654. package/bundled-test-harness/assets/codemirror-editor-test-B74H_yn8.js +0 -1512
  655. package/bundled-test-harness/assets/codemirror-embed-toolbar-test-Bz6VEysU.js +0 -366
  656. package/bundled-test-harness/assets/color-field-test-DMCPQKIP.js +0 -212
  657. package/bundled-test-harness/assets/compaction-test-saQCLBrQ.js +0 -150
  658. package/bundled-test-harness/assets/computed-test-C05HliJC.js +0 -1320
  659. package/bundled-test-harness/assets/container-Cqcwrd-m.js +0 -10857
  660. package/bundled-test-harness/assets/container-h3Wc26qn.css +0 -5097
  661. package/bundled-test-harness/assets/content-preview-components-test-DZPj4_CU.js +0 -462
  662. package/bundled-test-harness/assets/copy-and-edit-test-DiXTQNTF.js +0 -292
  663. package/bundled-test-harness/assets/copy-card-test-ys7GquUY.js +0 -218
  664. package/bundled-test-harness/assets/copy-file-to-realm-test-Gn0Wn4vT.js +0 -148
  665. package/bundled-test-harness/assets/copy-source-test-BTLrOmPm.js +0 -56
  666. package/bundled-test-harness/assets/create-file-test-BCeIW-Rt.js +0 -464
  667. package/bundled-test-harness/assets/create-file-test-DbHQ5JsS.js +0 -1086
  668. package/bundled-test-harness/assets/create-listing-modal-test-CeHc4ter.js +0 -273
  669. package/bundled-test-harness/assets/create-listing-pr-request-test-DXbJNfMh.js +0 -117
  670. package/bundled-test-harness/assets/create-spec-test-BDIZoyHT.js +0 -256
  671. package/bundled-test-harness/assets/create-submission-workflow-test-Bix5J-3A.js +0 -132
  672. package/bundled-test-harness/assets/create-workspace-test-BmNnLHwC.js +0 -104
  673. package/bundled-test-harness/assets/credential-fields-test-NK1F4QWn.js +0 -200
  674. package/bundled-test-harness/assets/csv-file-def-test-BSfs4TTP.js +0 -102
  675. package/bundled-test-harness/assets/dashboard-C4T7ffKY.js +0 -3576
  676. package/bundled-test-harness/assets/dashboard-CFeHuP5-.js +0 -81
  677. package/bundled-test-harness/assets/dashboard-DQlpW-ux.css +0 -2392
  678. package/bundled-test-harness/assets/dashboard-add-workspace-test--rr6objf.js +0 -50
  679. package/bundled-test-harness/assets/dashboard-agents-test-D1y8H4xH.js +0 -334
  680. package/bundled-test-harness/assets/dashboard-archive-test-bN4EQaXv.js +0 -128
  681. package/bundled-test-harness/assets/dashboard-delete-test-BvsASb8B.js +0 -163
  682. package/bundled-test-harness/assets/dashboard-duplicate-offer-test-DEsd5ZzZ.js +0 -71
  683. package/bundled-test-harness/assets/dashboard-duplicate-test-BnR0sTgB.js +0 -222
  684. package/bundled-test-harness/assets/dashboard-get-started-test-DG4uUXLv.js +0 -246
  685. package/bundled-test-harness/assets/dashboard-pinned-cards-test-AoGGVRAS.js +0 -220
  686. package/bundled-test-harness/assets/dashboard-reindex-test-BN9a96Xp.js +0 -115
  687. package/bundled-test-harness/assets/dashboard-section-rail-test-B3OT9V2T.js +0 -169
  688. package/bundled-test-harness/assets/dashboard-state-test-BY0Zqrmj.js +0 -162
  689. package/bundled-test-harness/assets/dashboard-test-C13oNpWt.js +0 -545
  690. package/bundled-test-harness/assets/dashboard-unreachable-notice-test-DZIV4x5j.js +0 -62
  691. package/bundled-test-harness/assets/dashboard-workspace-test-CBnOQViI.js +0 -537
  692. package/bundled-test-harness/assets/dashboard-workspaces-section-test-KU8ZVOYp.js +0 -396
  693. package/bundled-test-harness/assets/data-file-def-preview-test-CI5gcdtK.js +0 -155
  694. package/bundled-test-harness/assets/date-time-fields-test-D2CpR_Pb.js +0 -359
  695. package/bundled-test-harness/assets/debug-message-test-Df1kHesw.js +0 -117
  696. package/bundled-test-harness/assets/declared-captures-test-hQ43zuox.js +0 -879
  697. package/bundled-test-harness/assets/delete-workspace-test-BhfMKsix.js +0 -102
  698. package/bundled-test-harness/assets/diffing-test-CHRh55mC.js +0 -210
  699. package/bundled-test-harness/assets/download-file-to-realm-test-CC1HURCi.js +0 -119
  700. package/bundled-test-harness/assets/editor-test-DkeCv28f.js +0 -688
  701. package/bundled-test-harness/assets/edits-BSJqtUXM.js +0 -651
  702. package/bundled-test-harness/assets/email-field-test-DihK0suO.js +0 -75
  703. package/bundled-test-harness/assets/enum-field-test-Gja3bzt5.js +0 -935
  704. package/bundled-test-harness/assets/error-display-test-GhYZu7cp.js +0 -343
  705. package/bundled-test-harness/assets/evaluate-module-test-D_t4CiUq.js +0 -91
  706. package/bundled-test-harness/assets/execute-atomic-operations-test-xtou8Zeg.js +0 -113
  707. package/bundled-test-harness/assets/externals-B02-sD_L.js +0 -4393
  708. package/bundled-test-harness/assets/fallback-banner-live-delete-test-DtxzNXdE.js +0 -207
  709. package/bundled-test-harness/assets/fallback-banner-test-BfmiQ_68.js +0 -53
  710. package/bundled-test-harness/assets/fallback-banner-test-DLtTdmvn.js +0 -225
  711. package/bundled-test-harness/assets/fallback-models-test-BxNJxhfd.js +0 -161
  712. package/bundled-test-harness/assets/fetch-card-json-test-DofKbzvC.js +0 -61
  713. package/bundled-test-harness/assets/field-configuration-test-SUoPaXWy.js +0 -551
  714. package/bundled-test-harness/assets/field-markdown-domain-test-BwtR0dPP.js +0 -616
  715. package/bundled-test-harness/assets/field-markdown-oversize-test-D8UJcBc3.js +0 -88
  716. package/bundled-test-harness/assets/field-markdown-primitives-test-D5_ZdoDO.js +0 -365
  717. package/bundled-test-harness/assets/field-markdown-specialized-test-Dpd5hs04.js +0 -534
  718. package/bundled-test-harness/assets/field-playground-test-CzhYzKGv.js +0 -894
  719. package/bundled-test-harness/assets/field-support-predicates-test-BSvVOFth.js +0 -167
  720. package/bundled-test-harness/assets/file-attachment-test-fM-yFedm.js +0 -796
  721. package/bundled-test-harness/assets/file-chooser-panel-test-CKj8YTdY.js +0 -153
  722. package/bundled-test-harness/assets/file-chooser-test-Bs8jFXqa.js +0 -504
  723. package/bundled-test-harness/assets/file-def-format-templates-test-CxrRoWoD.js +0 -380
  724. package/bundled-test-harness/assets/file-def-live-reload-test-X_8YEkve.js +0 -124
  725. package/bundled-test-harness/assets/file-def-menu-items-test-Dx879o_o.js +0 -138
  726. package/bundled-test-harness/assets/file-def-navigation-test-MMI_EEO1.js +0 -109
  727. package/bundled-test-harness/assets/file-def-serialization-test-B5lguBQD.js +0 -89
  728. package/bundled-test-harness/assets/file-def-test-Di9QWcrj.js +0 -216
  729. package/bundled-test-harness/assets/file-preview-live-reload-test-aqx93A7c.js +0 -310
  730. package/bundled-test-harness/assets/file-resource-primitives-test-a5abpcSB.js +0 -255
  731. package/bundled-test-harness/assets/file-tree-from-index-test-CnruGxJ8.js +0 -96
  732. package/bundled-test-harness/assets/file-tree-test-BCyWDdSE.js +0 -851
  733. package/bundled-test-harness/assets/file-view-model-test-BfpLa01Y.js +0 -346
  734. package/bundled-test-harness/assets/filedef-export-shape-test-CQ9XbrzS.js +0 -61
  735. package/bundled-test-harness/assets/film-CL1zj_bJ.js +0 -2
  736. package/bundled-test-harness/assets/film-Dq_quZ31.js +0 -13
  737. package/bundled-test-harness/assets/film-xbkQa060.js +0 -4074
  738. package/bundled-test-harness/assets/flac-audio-def-test-BmVp9dMx.js +0 -143
  739. package/bundled-test-harness/assets/focus-Dm4wkM72.js +0 -306
  740. package/bundled-test-harness/assets/font-metadata-extractor-test-OWEh9_MS.js +0 -415
  741. package/bundled-test-harness/assets/formatted-aibot-message-test-BpHsWpuV.js +0 -109
  742. package/bundled-test-harness/assets/formatted-user-message-test-DZW5TAr0.js +0 -43
  743. package/bundled-test-harness/assets/freestyle-test-D_uaPU_3.js +0 -17
  744. package/bundled-test-harness/assets/full-reindex-realm-test-C6vHL5kC.js +0 -101
  745. package/bundled-test-harness/assets/garbage-collection-test-D-Ao4t2n.js +0 -403
  746. package/bundled-test-harness/assets/general-test-PSGI8W0z.js +0 -923
  747. package/bundled-test-harness/assets/generate-example-cards-one-shot-test-J-m-0E6W.js +0 -65
  748. package/bundled-test-harness/assets/generic-file-def-preview-test-BAsOhTYU.js +0 -71
  749. package/bundled-test-harness/assets/get-available-realm-identifiers-test-D5PBOr97.js +0 -47
  750. package/bundled-test-harness/assets/get-catalog-realm-identifiers-test-NM9UURHE.js +0 -47
  751. package/bundled-test-harness/assets/get-default-writable-realm-test-BxXc9a3J.js +0 -54
  752. package/bundled-test-harness/assets/get-published-realms-test-C8TJEc4-.js +0 -71
  753. package/bundled-test-harness/assets/get-realm-of-resource-identifier-test-Dt8CB6lS.js +0 -54
  754. package/bundled-test-harness/assets/get-relationship-membership-state-test-9_8x3myJ.js +0 -1308
  755. package/bundled-test-harness/assets/get-user-system-card-test-k0UO-uba.js +0 -67
  756. package/bundled-test-harness/assets/gif-image-def-test-BWrqPGDX.js +0 -188
  757. package/bundled-test-harness/assets/glimmer-motion-and-choreo-in-cards-test-BgG8QI9E.js +0 -160
  758. package/bundled-test-harness/assets/glimmer-motion-and-choreo-test-BKOvNyCN.js +0 -74
  759. package/bundled-test-harness/assets/gts-file-def-test-BCRHwDeZ.js +0 -100
  760. package/bundled-test-harness/assets/head-format-preview-test-DnfUhniI.js +0 -158
  761. package/bundled-test-harness/assets/helpers-DklkegO_.js +0 -5
  762. package/bundled-test-harness/assets/host-mode-service-vOfN0smp.js +0 -232
  763. package/bundled-test-harness/assets/host-mode-test-CCCJFz6_.js +0 -831
  764. package/bundled-test-harness/assets/host-submode-test-CtCfbuPA.js +0 -1342
  765. package/bundled-test-harness/assets/html-component-test-CWyhb5ZX.js +0 -65
  766. package/bundled-test-harness/assets/html-def-test-Cb8C2lUx.js +0 -160
  767. package/bundled-test-harness/assets/html-meta-extractor-test-BHT9Rtir.js +0 -60
  768. package/bundled-test-harness/assets/hydratable-card-test-DpgpdesD.js +0 -426
  769. package/bundled-test-harness/assets/icon-button-ABCGVF3C.js +0 -67
  770. package/bundled-test-harness/assets/image-metadata-extractor-test-ClhPTouq.js +0 -1109
  771. package/bundled-test-harness/assets/index-changes-test-CgnVr3LH.js +0 -367
  772. package/bundled-test-harness/assets/index-query-engine-test-CQTwju5_.js +0 -2593
  773. package/bundled-test-harness/assets/index-writer-test-IoVOoZT2.js +0 -3040
  774. package/bundled-test-harness/assets/inspector-test-BN2Ieb77.js +0 -2058
  775. package/bundled-test-harness/assets/instance-filter-matcher-test-Bq-_Sy89.js +0 -788
  776. package/bundled-test-harness/assets/instantiate-card-test-DEeDTzFV.js +0 -164
  777. package/bundled-test-harness/assets/interact-submode-creation-and-permissions-test-DP6kOyJS.js +0 -475
  778. package/bundled-test-harness/assets/interact-submode-setup-B0_cHqH-.js +0 -566
  779. package/bundled-test-harness/assets/invalidate-realm-identifiers-test-9uUD91Pw.js +0 -99
  780. package/bundled-test-harness/assets/invite-user-to-room-test-CcDA45Ac.js +0 -142
  781. package/bundled-test-harness/assets/invoke-card-operation-test-DmUtgueM.js +0 -333
  782. package/bundled-test-harness/assets/isolated-render-test-B2eXNHu6.js +0 -51
  783. package/bundled-test-harness/assets/job-scoped-doc-cache-test-DF9D7cOc.js +0 -181
  784. package/bundled-test-harness/assets/job-scoped-instance-residency-test-CSS8xUU5.js +0 -103
  785. package/bundled-test-harness/assets/jpg-image-def-test-voECMTht.js +0 -697
  786. package/bundled-test-harness/assets/json-file-def-test-8Y4KLjUC.js +0 -95
  787. package/bundled-test-harness/assets/key-notices-badge-test-d1mYqx0e.js +0 -155
  788. package/bundled-test-harness/assets/key-readiness-test-BtCg7PCk.js +0 -190
  789. package/bundled-test-harness/assets/linksto-broken-link-placeholder-test-CyCMbJnN.js +0 -398
  790. package/bundled-test-harness/assets/linksto-error-sentinel-test-BDW572-v.js +0 -238
  791. package/bundled-test-harness/assets/linksto-many-broken-link-placeholder-test-B4wM97hD.js +0 -354
  792. package/bundled-test-harness/assets/linksto-many-per-slot-access-test-BhJmtJ0_.js +0 -303
  793. package/bundled-test-harness/assets/linksto-sentinel-reload-test-BpBQ5V_i.js +0 -197
  794. package/bundled-test-harness/assets/linksto-sentinel-roundtrip-test-pkBBl4e9.js +0 -260
  795. package/bundled-test-harness/assets/linksto-singular-js-access-contract-test-Bb6wjUdD.js +0 -196
  796. package/bundled-test-harness/assets/lint-and-fix-test-CcMLn-co.js +0 -51
  797. package/bundled-test-harness/assets/live-test-AyBnq7BX.js +0 -2
  798. package/bundled-test-harness/assets/live-test-CgnAcIDw.js +0 -100
  799. package/bundled-test-harness/assets/load-default-skills-test-BIOwtx0Y.js +0 -74
  800. package/bundled-test-harness/assets/loader-parallel-prefetch-test-D5_oRSER.js +0 -257
  801. package/bundled-test-harness/assets/loader-test-DSc_jR1c.js +0 -482
  802. package/bundled-test-harness/assets/loading-test-8pldx7S-.js +0 -63
  803. package/bundled-test-harness/assets/m4a-audio-def-test-BDI5apzM.js +0 -190
  804. package/bundled-test-harness/assets/main-5kHyCkdm.js +0 -5
  805. package/bundled-test-harness/assets/markdown-embed-chooser-modal-test-Wud0s7WZ.js +0 -470
  806. package/bundled-test-harness/assets/markdown-embed-chooser-test-DVzzS-0C.js +0 -334
  807. package/bundled-test-harness/assets/markdown-embed-preview-pane-test-B5W_iqsi.js +0 -447
  808. package/bundled-test-harness/assets/markdown-embed-preview-test-CZF_s0fB.js +0 -368
  809. package/bundled-test-harness/assets/markdown-fallback-test-fT6BS4W7.js +0 -316
  810. package/bundled-test-harness/assets/markdown-file-def-test-B1aTzazR.js +0 -380
  811. package/bundled-test-harness/assets/markdown-helpers-test-gNKZf7Mw.js +0 -188
  812. package/bundled-test-harness/assets/markdown-highlighting-test-Du5_CQmD.js +0 -244
  813. package/bundled-test-harness/assets/markdown-preview-h-_aJhRc.js +0 -72
  814. package/bundled-test-harness/assets/markdown-preview-test-DJvoVsXw.js +0 -238
  815. package/bundled-test-harness/assets/markdown-skill-frontmatter-test-VwJi3Paj.js +0 -146
  816. package/bundled-test-harness/assets/markdown-skill-search-test-ysCdf0xM.js +0 -80
  817. package/bundled-test-harness/assets/matrix-service-account-switch-sessions-test-K2JuMy36.js +0 -63
  818. package/bundled-test-harness/assets/matrix-service-boot-assembly-test-CkdL_-os.js +0 -300
  819. package/bundled-test-harness/assets/matrix-service-personal-realm-test-Dy1DultK.js +0 -125
  820. package/bundled-test-harness/assets/matrix-service-realm-servers-test-DHDDKuEg.js +0 -55
  821. package/bundled-test-harness/assets/matrix-service-realms-list-updated-test-DcTbZpMl.js +0 -132
  822. package/bundled-test-harness/assets/matrix-service-relogin-test-D3NQktoa.js +0 -59
  823. package/bundled-test-harness/assets/matrix-service-sliding-sync-test-6CAflWOA.js +0 -35
  824. package/bundled-test-harness/assets/menu-kUSaJIPq.js +0 -3562
  825. package/bundled-test-harness/assets/message-service-subscription-test-DaQdgDWi.js +0 -110
  826. package/bundled-test-harness/assets/message-service-test-BsGEgM_m.js +0 -144
  827. package/bundled-test-harness/assets/message-tool-test-BB_4kw1V.js +0 -33
  828. package/bundled-test-harness/assets/midi-audio-def-test-BbbkFjqf.js +0 -182
  829. package/bundled-test-harness/assets/migrate-skill-test-X9xImDuq.js +0 -161
  830. package/bundled-test-harness/assets/mini-AwF31elJ.js +0 -1404
  831. package/bundled-test-harness/assets/mini-card-chooser-test-BZtrEiWu.js +0 -272
  832. package/bundled-test-harness/assets/mini-file-chooser-test-MIHW3kCI.js +0 -201
  833. package/bundled-test-harness/assets/mock-matrix-Dd8k0DNa.js +0 -15107
  834. package/bundled-test-harness/assets/mock-matrix-DhPN_34j.js +0 -2
  835. package/bundled-test-harness/assets/modal-LTh3_oHK.js +0 -322
  836. package/bundled-test-harness/assets/model-cost-tier-test-h1IkU9mp.js +0 -174
  837. package/bundled-test-harness/assets/model-file-extract-test-ntSo0wZF.js +0 -206
  838. package/bundled-test-harness/assets/module-transpile-cache-test-CDeRaaeP.js +0 -67
  839. package/bundled-test-harness/assets/monaco-test-C0Fa744D.js +0 -100
  840. package/bundled-test-harness/assets/mp3-audio-def-test-B4j4qR9H.js +0 -133
  841. package/bundled-test-harness/assets/multiple-stacks-test-BhA25ywL.js +0 -208
  842. package/bundled-test-harness/assets/nested-query-field-render-test-S9Y8YNKB.js +0 -249
  843. package/bundled-test-harness/assets/no-stacks-test-B7VciWyg.js +0 -48
  844. package/bundled-test-harness/assets/number-field-test-CS74lDPN.js +0 -184
  845. package/bundled-test-harness/assets/office-file-def-test-2cKc1pmd.js +0 -263
  846. package/bundled-test-harness/assets/office-metadata-extractor-test-DC8Fo-OW.js +0 -218
  847. package/bundled-test-harness/assets/office-poster-capture-test-Ba0_5UrT.js +0 -203
  848. package/bundled-test-harness/assets/ogg-audio-def-test-CIPQ1d4w.js +0 -196
  849. package/bundled-test-harness/assets/open-create-listing-modal-test-bmQkY5Zl.js +0 -131
  850. package/bundled-test-harness/assets/open-image-in-new-tab-test-DBD7_vMH.js +0 -52
  851. package/bundled-test-harness/assets/open-secure-window-test-BgeuYAqz.js +0 -253
  852. package/bundled-test-harness/assets/open-workspace-test-DRHGljV0.js +0 -46
  853. package/bundled-test-harness/assets/operation-lowering-test-CH1c0pSH.js +0 -2957
  854. package/bundled-test-harness/assets/operations-invocation-test-B1YkCLrv.js +0 -523
  855. package/bundled-test-harness/assets/operations-optimistic-test-DAbtOwsC.js +0 -203
  856. package/bundled-test-harness/assets/operations-query-test-9p1ZIDe-.js +0 -459
  857. package/bundled-test-harness/assets/operations-store-reconciliation-test-D0EQh3w2.js +0 -406
  858. package/bundled-test-harness/assets/operations-test-BQhlrfe3.js +0 -2518
  859. package/bundled-test-harness/assets/operator-mode-acceptance-test-DtHnonEb.js +0 -1195
  860. package/bundled-test-harness/assets/operator-mode-card-chooser-test-DQUxZxaq.js +0 -1036
  861. package/bundled-test-harness/assets/operator-mode-links-test-BJ26HllS.js +0 -797
  862. package/bundled-test-harness/assets/operator-mode-test-DIPDI0qt.js +0 -696
  863. package/bundled-test-harness/assets/operator-mode-ui-test-CfA-fAh4.js +0 -1045
  864. package/bundled-test-harness/assets/overlay-DecPh3nt.js +0 -123
  865. package/bundled-test-harness/assets/overlay-menu-items-test-C6XqjLtu.js +0 -331
  866. package/bundled-test-harness/assets/overlays-Ctp8ePzZ.js +0 -75
  867. package/bundled-test-harness/assets/overlays-CzWpSg5T.js +0 -2
  868. package/bundled-test-harness/assets/overlays-detached-element-test-DvL_8Bb5.js +0 -56
  869. package/bundled-test-harness/assets/panel-CImumikB.js +0 -15124
  870. package/bundled-test-harness/assets/past-sessions-test-N6riGN_I.js +0 -321
  871. package/bundled-test-harness/assets/patch-fields-test-D30_-KwQ.js +0 -1014
  872. package/bundled-test-harness/assets/patch-instance-test-C5rGscZq.js +0 -348
  873. package/bundled-test-harness/assets/pdf-file-def-test-DtiqGRvZ.js +0 -111
  874. package/bundled-test-harness/assets/pdf-metadata-extractor-test-FU02KmdV.js +0 -130
  875. package/bundled-test-harness/assets/permission-checking-realm-test-DqdNJDwU.js +0 -306
  876. package/bundled-test-harness/assets/persist-module-inspector-view-test-BHOAgPVy.js +0 -60
  877. package/bundled-test-harness/assets/persist-scroll-position-test-qtmS518r.js +0 -254
  878. package/bundled-test-harness/assets/phone-number-field-test-DhdaM7uL.js +0 -73
  879. package/bundled-test-harness/assets/pill-menu-test-C9Mrrepl.js +0 -60
  880. package/bundled-test-harness/assets/plate-9n-sXyCw.js +0 -41
  881. package/bundled-test-harness/assets/plate-BnZcAk-_.js +0 -2
  882. package/bundled-test-harness/assets/player-Cu5b4LEJ.js +0 -82
  883. package/bundled-test-harness/assets/player-unk2mkxV.js +0 -2
  884. package/bundled-test-harness/assets/playground-BwA8wFGK.js +0 -58
  885. package/bundled-test-harness/assets/plural-field-components-test-CFNQKETg.js +0 -198
  886. package/bundled-test-harness/assets/png-image-def-test-DG5Vhlqb.js +0 -266
  887. package/bundled-test-harness/assets/policy-audit-confirmation-test-yfKU47LR.js +0 -155
  888. package/bundled-test-harness/assets/policy-scoped-search-test-BjQRDYqR.js +0 -339
  889. package/bundled-test-harness/assets/prerender-file-extract-test-CEU4SaAZ.js +0 -346
  890. package/bundled-test-harness/assets/prerender-html-test-CGB3ClCS.js +0 -670
  891. package/bundled-test-harness/assets/prerender-meta-test-xqc4fW_0.js +0 -614
  892. package/bundled-test-harness/assets/prerender-module-test-CI1TmZw-.js +0 -409
  893. package/bundled-test-harness/assets/prerender-persistence-block-test-Da0dJO_N.js +0 -124
  894. package/bundled-test-harness/assets/prerender-pre-model-error-test-BVLyhk8R.js +0 -61
  895. package/bundled-test-harness/assets/prerender-serialize-cycle-test-glJFfxHU.js +0 -134
  896. package/bundled-test-harness/assets/prerendered-html-read-test-Mp4L0VHQ.js +0 -191
  897. package/bundled-test-harness/assets/pretui-components-test-BBpA9UnA.js +0 -991
  898. package/bundled-test-harness/assets/pretui-components-test-BqFq7rw_.css +0 -730
  899. package/bundled-test-harness/assets/preview-format-test-C55Bwcur.js +0 -103
  900. package/bundled-test-harness/assets/preview-test-CTAhRGU8.js +0 -474
  901. package/bundled-test-harness/assets/process-card-test-UjqpuxB7.js +0 -94
  902. package/bundled-test-harness/assets/profile-settings-modal-C8bCgTMK.js +0 -989
  903. package/bundled-test-harness/assets/publish-realm-ixUB4FPK.js +0 -82
  904. package/bundled-test-harness/assets/publish-realm-test-CrrsdL4W.js +0 -210
  905. package/bundled-test-harness/assets/query-field-barrier-test-DjivFE93.js +0 -113
  906. package/bundled-test-harness/assets/query-field-error-sentinel-test-0HwnV4Mw.js +0 -201
  907. package/bundled-test-harness/assets/query-field-membership-status-test-C8yTTBkc.js +0 -323
  908. package/bundled-test-harness/assets/query-field-page-optin-test-D4l_GcII.js +0 -126
  909. package/bundled-test-harness/assets/query-field-schema-test-DDbcNNm5.js +0 -231
  910. package/bundled-test-harness/assets/query-field-search-throttle-test-CXp50Ax0.js +0 -154
  911. package/bundled-test-harness/assets/query-field-stale-prerender-test-DErzt-Cv.js +0 -152
  912. package/bundled-test-harness/assets/query-fields-test-Dz67fdSl.js +0 -535
  913. package/bundled-test-harness/assets/quick-look-test-B1ijDsh_.js +0 -139
  914. package/bundled-test-harness/assets/read-card-for-ai-assistant-test-DJxZ16H_.js +0 -91
  915. package/bundled-test-harness/assets/read-file-for-ai-assistant-test-BoRQkZ8c.js +0 -45
  916. package/bundled-test-harness/assets/read-source-test-Bl-NjchO.js +0 -67
  917. package/bundled-test-harness/assets/read-text-file-test-CP37CZoo.js +0 -124
  918. package/bundled-test-harness/assets/realm-CaK5mkT-.js +0 -2852
  919. package/bundled-test-harness/assets/realm-api-keys-BNUFWbGR.js +0 -579
  920. package/bundled-test-harness/assets/realm-api-keys-CkshxhXC.js +0 -2
  921. package/bundled-test-harness/assets/realm-api-keys-test-BP8xifjn.js +0 -109
  922. package/bundled-test-harness/assets/realm-api-keys-test-CwdK9YXp.js +0 -588
  923. package/bundled-test-harness/assets/realm-config-iKwE3Htp.js +0 -833
  924. package/bundled-test-harness/assets/realm-config-policy-standing-test-BgVEIDnB.js +0 -290
  925. package/bundled-test-harness/assets/realm-config-routing-rule-edit-test-BoJoKzmX.js +0 -274
  926. package/bundled-test-harness/assets/realm-config-settings-test-Kxw-GHye.js +0 -187
  927. package/bundled-test-harness/assets/realm-field-test-CdGOxrFb.js +0 -100
  928. package/bundled-test-harness/assets/realm-indexing-test-CHtsBV2b.js +0 -4380
  929. package/bundled-test-harness/assets/realm-policy-fitted-test--DhNZSdC.js +0 -206
  930. package/bundled-test-harness/assets/realm-policy-test-D7714iVa.js +0 -1141
  931. package/bundled-test-harness/assets/realm-querying-test-Cj1ekZ0H.js +0 -1067
  932. package/bundled-test-harness/assets/realm-server-form-agnostic-test-CZFPNJfD.js +0 -96
  933. package/bundled-test-harness/assets/realm-server-subscriber-test-C86WmBp0.js +0 -46
  934. package/bundled-test-harness/assets/realm-service-info-test-CdgcwKDR.js +0 -67
  935. package/bundled-test-harness/assets/realm-test-DPoLsvKz.js +0 -2364
  936. package/bundled-test-harness/assets/realm-token-refresh-test-Ch35Siwi.js +0 -153
  937. package/bundled-test-harness/assets/realm-url-tooltip-test-x8xWOENK.js +0 -78
  938. package/bundled-test-harness/assets/reasoning-test-BxpE8Jvf.js +0 -221
  939. package/bundled-test-harness/assets/recent-files-test-DTmEzPLq.js +0 -450
  940. package/bundled-test-harness/assets/reindex-realm-test-BQ8KULn4.js +0 -117
  941. package/bundled-test-harness/assets/relationship-loading-state-test-BJoArPWf.js +0 -290
  942. package/bundled-test-harness/assets/remix-card-test-DsTA1KoG.js +0 -58
  943. package/bundled-test-harness/assets/rendered-markdown-DvukulDO.js +0 -292
  944. package/bundled-test-harness/assets/rendered-markdown-test-DxGptXSV.js +0 -587
  945. package/bundled-test-harness/assets/resident-instance-reuse-test-ZWnVu8uj.js +0 -82
  946. package/bundled-test-harness/assets/result-tile-CPyI6Vmv.js +0 -144
  947. package/bundled-test-harness/assets/rich-markdown-field-test-CdygoXIO.js +0 -1647
  948. package/bundled-test-harness/assets/room-message-test-D3NfMqH0.js +0 -484
  949. package/bundled-test-harness/assets/run-D_Px28eF.js +0 -3956
  950. package/bundled-test-harness/assets/run-realm-code-qWCZxmJ7.js +0 -2964
  951. package/bundled-test-harness/assets/run-realm-code-test-UzyeEJq6.js +0 -3844
  952. package/bundled-test-harness/assets/sanitize-module-list-test-Babq44bP.js +0 -85
  953. package/bundled-test-harness/assets/save-card-skip-index-wait-test-BcELXlQ_.js +0 -89
  954. package/bundled-test-harness/assets/schema-editor-test-CEvruZbt.js +0 -785
  955. package/bundled-test-harness/assets/schema-generation-test-hYAMdCrn.js +0 -28
  956. package/bundled-test-harness/assets/scrolling-test-DVIsh-_1.js +0 -412
  957. package/bundled-test-harness/assets/search-adorn-test-CkVhqFd0.js +0 -136
  958. package/bundled-test-harness/assets/search-and-choose-test-DUhOB3FV.js +0 -154
  959. package/bundled-test-harness/assets/search-correlation-id-test-Drn4r26N.js +0 -139
  960. package/bundled-test-harness/assets/search-entries-result-test-DTCRJ_wc.js +0 -234
  961. package/bundled-test-harness/assets/search-entries-test-CE0B47pw.js +0 -1486
  962. package/bundled-test-harness/assets/search-entries-tool-test-C4aG0ckM.js +0 -504
  963. package/bundled-test-harness/assets/search-google-images-test-LyhcB2f3.js +0 -166
  964. package/bundled-test-harness/assets/search-results-D4pSne0x.js +0 -266
  965. package/bundled-test-harness/assets/search-results-test-CRZHhqhn.js +0 -578
  966. package/bundled-test-harness/assets/search-selection-menu-test-B7Y3E_nj.js +0 -108
  967. package/bundled-test-harness/assets/search-sheet-files-test-C2y534g8.js +0 -126
  968. package/bundled-test-harness/assets/search-sheet-persistence-test-DePC59Bk.js +0 -131
  969. package/bundled-test-harness/assets/search-test-Dy8NxFkU.js +0 -2249
  970. package/bundled-test-harness/assets/search-tool-test-lctDaMH3.js +0 -156
  971. package/bundled-test-harness/assets/searchable-option-test-CE64M8oM.js +0 -322
  972. package/bundled-test-harness/assets/searchable-search-doc-test-C6u3mVvT.js +0 -1271
  973. package/bundled-test-harness/assets/section-rail-B_UQX00B.js +0 -113
  974. package/bundled-test-harness/assets/section-rail-test-DIda7MIw.js +0 -256
  975. package/bundled-test-harness/assets/secure-sign-in-CqqqfQG8.js +0 -174
  976. package/bundled-test-harness/assets/secure-sign-in-test-DimbVr_W.js +0 -373
  977. package/bundled-test-harness/assets/segmented-control-iePxSdTS.js +0 -173
  978. package/bundled-test-harness/assets/select-tNs6_xwW.js +0 -175
  979. package/bundled-test-harness/assets/send-ai-assistant-message-test-2GVrMF9Z.js +0 -52
  980. package/bundled-test-harness/assets/send-bot-trigger-event-test-B_3dKfGN.js +0 -56
  981. package/bundled-test-harness/assets/send-request-via-proxy-test-_clNWyYc.js +0 -380
  982. package/bundled-test-harness/assets/sending-test-DCPFXUVg.js +0 -659
  983. package/bundled-test-harness/assets/serialization-rri-form-audit-test-BI0zCs8Y.js +0 -136
  984. package/bundled-test-harness/assets/serialization-test-bjdtVlZL.js +0 -8758
  985. package/bundled-test-harness/assets/set-user-system-card-test-BUv1vL08.js +0 -59
  986. package/bundled-test-harness/assets/setup-BW1mmC7C.js +0 -772
  987. package/bundled-test-harness/assets/setup-DsIcFT-T.js +0 -2
  988. package/bundled-test-harness/assets/shared-link-target-reuse-test-9NeJEjkb.js +0 -207
  989. package/bundled-test-harness/assets/show-card-test-mfyLwusD.js +0 -365
  990. package/bundled-test-harness/assets/signed-capture-link-test-BOtKNCAM.js +0 -132
  991. package/bundled-test-harness/assets/single-stack-test-B4MGjaLk.js +0 -652
  992. package/bundled-test-harness/assets/skills-test-BuP-Yzk1.js +0 -648
  993. package/bundled-test-harness/assets/skip-boot-index-guard-test-Cmrx2-K7.js +0 -46
  994. package/bundled-test-harness/assets/spec-test-BhZDdhVQ.js +0 -1077
  995. package/bundled-test-harness/assets/spinner-CpIBUG9m.js +0 -49
  996. package/bundled-test-harness/assets/src-DGHttmW-.js +0 -216
  997. package/bundled-test-harness/assets/src-DaNDSbp7.js +0 -5
  998. package/bundled-test-harness/assets/stick-to-bottom-resize-test-Dpy3OVum.js +0 -56
  999. package/bundled-test-harness/assets/store-add-test-_IYS8o74.js +0 -50
  1000. package/bundled-test-harness/assets/store-module-rebuild-test-B5VMaICy.js +0 -454
  1001. package/bundled-test-harness/assets/store-search-test-C2VZabrH.js +0 -175
  1002. package/bundled-test-harness/assets/store-test-D6PObxoD.js +0 -3672
  1003. package/bundled-test-harness/assets/structured-theme-test-BHjVeMf-.js +0 -377
  1004. package/bundled-test-harness/assets/summarize-session-test-BFtTuhe0.js +0 -172
  1005. package/bundled-test-harness/assets/svg-image-def-test-BL6lkWUX.js +0 -167
  1006. package/bundled-test-harness/assets/switch-submode-test-6Uv3bZMl.js +0 -168
  1007. package/bundled-test-harness/assets/sync-openrouter-models-test-Dp9E05tL.js +0 -97
  1008. package/bundled-test-harness/assets/test-support-DYm8XZ0E.js +0 -3
  1009. package/bundled-test-harness/assets/test-support-DfnhiIMV.js +0 -99
  1010. package/bundled-test-harness/assets/tests-CZk0Iag2.js +0 -3596
  1011. package/bundled-test-harness/assets/text-file-def-test-CHdC0yIU.js +0 -94
  1012. package/bundled-test-harness/assets/text-input-validator-test-B9ZR8XPU.js +0 -156
  1013. package/bundled-test-harness/assets/text-suggestion-test-CGLspKFQ.js +0 -340
  1014. package/bundled-test-harness/assets/theme-card-test-CXZvSEvG.js +0 -621
  1015. package/bundled-test-harness/assets/theme-dashboard-nav-test-CkEE0ILk.js +0 -196
  1016. package/bundled-test-harness/assets/theme-scheme-island-test-URXTjipF.js +0 -264
  1017. package/bundled-test-harness/assets/titles-C6enAdIv.js +0 -2
  1018. package/bundled-test-harness/assets/titles-Dft1HoUT.js +0 -52
  1019. package/bundled-test-harness/assets/to-device-streaming-test-D33ZOc9o.js +0 -163
  1020. package/bundled-test-harness/assets/token-usage-test-BHQlU4J4.js +0 -160
  1021. package/bundled-test-harness/assets/tools-CrudqfS3.js +0 -774
  1022. package/bundled-test-harness/assets/tools-calling-test-jo7IREau.js +0 -200
  1023. package/bundled-test-harness/assets/tools-test-D1wMfUa0.js +0 -1624
  1024. package/bundled-test-harness/assets/tools-test-Dn1LYsXp.js +0 -3204
  1025. package/bundled-test-harness/assets/tooltip-8Wyz4IIn.css +0 -68
  1026. package/bundled-test-harness/assets/tooltip-CqwLzRz5.js +0 -134
  1027. package/bundled-test-harness/assets/transform-cards-test-BPhwPFtp.js +0 -341
  1028. package/bundled-test-harness/assets/ts-file-def-preview-test-Bq3zTgw8.js +0 -95
  1029. package/bundled-test-harness/assets/ts-file-def-test-GLswMl7O.js +0 -92
  1030. package/bundled-test-harness/assets/ttf-font-def-test-DQulvUWs.js +0 -206
  1031. package/bundled-test-harness/assets/turn-settling-test-BspmOUQP.js +0 -160
  1032. package/bundled-test-harness/assets/turn-summary-9A8nvC0-.js +0 -1039
  1033. package/bundled-test-harness/assets/unpublish-realm-test-SkYPEhDz.js +0 -102
  1034. package/bundled-test-harness/assets/update-room-skills-test-cTxb-WU6.js +0 -240
  1035. package/bundled-test-harness/assets/use-ai-assistant-test-uaqW1T_A.js +0 -384
  1036. package/bundled-test-harness/assets/user-message-BudkIP-3.js +0 -262
  1037. package/bundled-test-harness/assets/validate-realm-test-DxrGgH9n.js +0 -67
  1038. package/bundled-test-harness/assets/video-metadata-extractor-test-B2pe-Iqa.js +0 -520
  1039. package/bundled-test-harness/assets/view-visually-test-PNon6fUo.js +0 -335
  1040. package/bundled-test-harness/assets/virtual-network-reset-test-uYJLaQHf.js +0 -96
  1041. package/bundled-test-harness/assets/wav-audio-def-test-F4OrFFR4.js +0 -160
  1042. package/bundled-test-harness/assets/webp-image-def-test-B0a_-Vya.js +0 -226
  1043. package/bundled-test-harness/assets/workspace-Cyftysy9.js +0 -440
  1044. package/bundled-test-harness/assets/workspace-a11y-test-sKiPDcbl.js +0 -197
  1045. package/bundled-test-harness/assets/workspace-actions-BuawjFmZ.js +0 -561
  1046. package/bundled-test-harness/assets/workspace-behavior-test-CKa-pb3T.js +0 -338
  1047. package/bundled-test-harness/assets/workspace-delete-multiple-test-Dt2weG5R.js +0 -212
  1048. package/bundled-test-harness/assets/workspace-delete-summary-test-CkqgFqZ8.js +0 -63
  1049. package/bundled-test-harness/assets/workspace-hosting-test-Ci7EEtHP.js +0 -138
  1050. package/bundled-test-harness/assets/workspace-indexing-test-BPVxxY6W.js +0 -71
  1051. package/bundled-test-harness/assets/workspace-test-CWr7vFbg.js +0 -385
  1052. package/bundled-test-harness/assets/workspace-test-INNpQovc.js +0 -51
  1053. package/bundled-test-harness/assets/workspace-timestamp-labels-test-CigQb5wr.js +0 -68
  1054. package/bundled-test-harness/assets/workspace-unit-test-BwVKpuXT.js +0 -122
  1055. package/bundled-test-harness/assets/write-binary-file-test-BKP3gv1k.js +0 -124
  1056. package/bundled-test-harness/assets/write-text-file-test-B6ijTKTa.js +0 -191
  1057. package/bundled-test-harness/assets/zip-archive-test-C-PBzkTn.js +0 -285
  1058. package/bundled-test-harness/assets/zip-file-def-test-FyCzJT-9.js +0 -164
@@ -0,0 +1,3204 @@
1
+ import { s as __toESM } from "./chunk-Rp0pCe6z.js";
2
+ import { r as initializeDeferredDecorator, t as decorateFieldV2 } from "./runtime--fcdnjmJ-BoCBNIsz.js";
3
+ import { Bn as APP_BOXEL_CONTINUATION_OF_CONTENT_KEY, Br as testRealmURL, Jo as isCardInstance, Kn as APP_BOXEL_MESSAGE_MSGTYPE, Rc as Deferred, Un as APP_BOXEL_EXTERNAL_FIELDS_KEY, Wn as APP_BOXEL_HAS_CONTINUATION_CONTENT_KEY, Wr as AI_BOT_EXECUTOR, Yr as buildToolFunctionNameFromResolvedRef, ar as APP_BOXEL_TOOL_REQUESTS_KEY, cr as APP_BOXEL_TOOL_RESULT_WITH_NO_OUTPUT_MSGTYPE, lr as APP_BOXEL_TOOL_RESULT_WITH_OUTPUT_MSGTYPE, or as APP_BOXEL_TOOL_RESULT_EVENT_TYPE, rr as APP_BOXEL_STOP_GENERATING_EVENT_TYPE, sr as APP_BOXEL_TOOL_RESULT_REL_TYPE, tr as APP_BOXEL_RESPONSE_STREAM_EVENT_TYPE } from "./runtime-common-BTaLJEw-.js";
4
+ import { T as rri } from "./paths-C9-NYXnM.js";
5
+ import { q as skillCardRef } from "./constants-Icc0nFW-.js";
6
+ import { t as config } from "./environment-DIUJgBKt.js";
7
+ import { wt as setComponentTemplate } from "./cache-DtDz7X5V-Wn8jRDfL.js";
8
+ import { H as templateFactory } from "./index-DaCZcoCY-CgzbilMy.js";
9
+ import { n as Submodes } from "./submode-switcher-BpDa9Rui.js";
10
+ import "./component-BJO47HTh.js";
11
+ import { t as Component } from "./dist-CkA1rgqO.js";
12
+ import "./template-factory-ds9s0u8l.js";
13
+ import { t as OperatorModeContainer } from "./container-CBZZ8uFw.js";
14
+ import { t as STOPPED_TOOL_CALL_REASON } from "./stop-lrhqMDul.js";
15
+ import { M as waitUntil, T as settled, a as find, d as click, o as waitFor, s as fillIn } from "./dist-BOAdzfkP.js";
16
+ import { t as require_qunit } from "./qunit-C-Foo4Nd.js";
17
+ import { D as realmConfigCardJSON, Et as percySnapshot, F as setupLocalIndexing, I as setupOnSave, L as setupRealmCacheTeardown, M as setupCardLogs, P as setupIntegrationTestRealm, Z as withCachedRealmSetup, g as delay, lt as setupRenderingTest, o as addSkillToAiAssistant, ot as setupOperatorModeStateCleanup, t as setupMockMatrix } from "./mock-matrix-FjsXmU7-.js";
18
+ import { r as getService } from "./dist-CPfIHBla.js";
19
+ import { A as field, H as linksTo, U as linksToMany, a as CardDef, l as FieldDef, s as Component$1, w as contains } from "./card-api-Cc8uZunB.js";
20
+ import { t as string_default } from "./string-5IAMEUit.js";
21
+ import { n as renderComponent } from "./render-component-B15Z0e2v.js";
22
+ //#region tests/integration/components/ai-assistant-panel/e75beeb704.css
23
+ var import_qunit = /* @__PURE__ */ __toESM(require_qunit());
24
+ //#endregion
25
+ //#region tests/integration/components/ai-assistant-panel/tools-test.gts
26
+ function registeredRealmPrefixes() {
27
+ let { virtualNetwork } = getService("network");
28
+ return Object.fromEntries(virtualNetwork.knownRealms().map((prefix) => [prefix, virtualNetwork.toURLHref(prefix)]));
29
+ }
30
+ function menuItem(label) {
31
+ return [...document.querySelectorAll("[data-test-pretui-menu-panel] [role=\"menuitem\"]")].find((row) => row.textContent?.trim() === label);
32
+ }
33
+ (0, import_qunit.module)("Integration | ai-assistant-panel | tools", function(hooks) {
34
+ const realmName = "Operator Mode Workspace";
35
+ const readOnlyRealmName = "Read Only Workspace";
36
+ const readOnlyRealmURL = "http://test-realm/read-only/";
37
+ const searchCardsToolName = buildToolFunctionNameFromResolvedRef({
38
+ module: "@cardstack/boxel-host/commands/search-cards",
39
+ name: "SearchCardsByTypeAndTitleTool"
40
+ });
41
+ let loader;
42
+ let operatorModeStateService;
43
+ setupRenderingTest(hooks);
44
+ setupOperatorModeStateCleanup(hooks);
45
+ hooks.beforeEach(function() {
46
+ loader = getService("loader-service").loader;
47
+ });
48
+ setupLocalIndexing(hooks);
49
+ setupRealmCacheTeardown(hooks);
50
+ setupOnSave(hooks);
51
+ setupCardLogs(hooks, async () => await loader.import("@cardstack/base/card-api"));
52
+ let mockMatrixUtils = setupMockMatrix(hooks, {
53
+ loggedInAs: "@testuser:localhost",
54
+ activeRealms: [testRealmURL, readOnlyRealmURL],
55
+ realmPermissions: {
56
+ [testRealmURL]: ["read", "write"],
57
+ [readOnlyRealmURL]: ["read"]
58
+ },
59
+ autostart: true,
60
+ now: (() => {
61
+ let clock = new Date(2024, 8, 19).getTime();
62
+ return () => clock += 10;
63
+ })()
64
+ });
65
+ let { createAndJoinRoom, simulateRemoteMessage, simulateToDeviceEvent, getRoomEvents } = mockMatrixUtils;
66
+ let noop = () => {};
67
+ hooks.beforeEach(async function() {
68
+ operatorModeStateService = getService("operator-mode-state-service");
69
+ class Pet extends CardDef {
70
+ static displayName = "Pet";
71
+ static {
72
+ decorateFieldV2(this.prototype, "name", [field], function() {
73
+ return contains(string_default);
74
+ });
75
+ }
76
+ #name = (initializeDeferredDecorator(this, "name"), void 0);
77
+ static {
78
+ decorateFieldV2(this.prototype, "cardTitle", [field], function() {
79
+ return contains(string_default, { computeVia: function() {
80
+ return this.name;
81
+ } });
82
+ });
83
+ }
84
+ #cardTitle = (initializeDeferredDecorator(this, "cardTitle"), void 0);
85
+ static fitted = class Fitted extends Component$1 {
86
+ static {
87
+ setComponentTemplate(templateFactory({
88
+ "id": "IHMPzHnr",
89
+ "block": "[[[10,\"h3\"],[15,\"data-test-pet\",[30,1,[\"name\"]]],[12],[1,\"\\n \"],[8,[30,2,[\"name\"]],null,null,null],[1,\"\\n\"],[13]],[\"@model\",\"@fields\"],[]]",
90
+ "moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/components/ai-assistant-panel/tools-test.gts",
91
+ "isStrictMode": true
92
+ }), this);
93
+ }
94
+ };
95
+ }
96
+ class Address extends FieldDef {
97
+ static displayName = "Address";
98
+ static {
99
+ decorateFieldV2(this.prototype, "city", [field], function() {
100
+ return contains(string_default);
101
+ });
102
+ }
103
+ #city = (initializeDeferredDecorator(this, "city"), void 0);
104
+ static {
105
+ decorateFieldV2(this.prototype, "country", [field], function() {
106
+ return contains(string_default);
107
+ });
108
+ }
109
+ #country = (initializeDeferredDecorator(this, "country"), void 0);
110
+ static embedded = class Embedded extends Component$1 {
111
+ static {
112
+ setComponentTemplate(templateFactory({
113
+ "id": "0uTOjQm9",
114
+ "block": "[[[10,0],[14,\"data-test-address\",\"\"],[12],[1,\"\\n \"],[10,\"h3\"],[15,\"data-test-city\",[30,1,[\"city\"]]],[12],[1,\"\\n \"],[8,[30,2,[\"city\"]],null,null,null],[1,\"\\n \"],[13],[1,\"\\n \"],[10,\"h3\"],[15,\"data-test-country\",[30,1,[\"country\"]]],[12],[1,\"\\n \"],[8,[30,2,[\"country\"]],null,null,null],[1,\"\\n \"],[13],[1,\"\\n\"],[13]],[\"@model\",\"@fields\"],[]]",
115
+ "moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/components/ai-assistant-panel/tools-test.gts",
116
+ "isStrictMode": true
117
+ }), this);
118
+ }
119
+ };
120
+ }
121
+ class Person extends CardDef {
122
+ static displayName = "Person";
123
+ static {
124
+ decorateFieldV2(this.prototype, "firstName", [field], function() {
125
+ return contains(string_default);
126
+ });
127
+ }
128
+ #firstName = (initializeDeferredDecorator(this, "firstName"), void 0);
129
+ static {
130
+ decorateFieldV2(this.prototype, "pet", [field], function() {
131
+ return linksTo(Pet);
132
+ });
133
+ }
134
+ #pet = (initializeDeferredDecorator(this, "pet"), void 0);
135
+ static {
136
+ decorateFieldV2(this.prototype, "friends", [field], function() {
137
+ return linksToMany(Pet);
138
+ });
139
+ }
140
+ #friends = (initializeDeferredDecorator(this, "friends"), void 0);
141
+ static {
142
+ decorateFieldV2(this.prototype, "firstLetterOfTheName", [field], function() {
143
+ return contains(string_default, { computeVia: function() {
144
+ return this.firstName[0];
145
+ } });
146
+ });
147
+ }
148
+ #firstLetterOfTheName = (initializeDeferredDecorator(this, "firstLetterOfTheName"), void 0);
149
+ static {
150
+ decorateFieldV2(this.prototype, "cardTitle", [field], function() {
151
+ return contains(string_default, { computeVia: function() {
152
+ return this.firstName;
153
+ } });
154
+ });
155
+ }
156
+ #cardTitle = (initializeDeferredDecorator(this, "cardTitle"), void 0);
157
+ static {
158
+ decorateFieldV2(this.prototype, "address", [field], function() {
159
+ return contains(Address);
160
+ });
161
+ }
162
+ #address = (initializeDeferredDecorator(this, "address"), void 0);
163
+ static isolated = class Isolated extends Component$1 {
164
+ static {
165
+ setComponentTemplate(templateFactory({
166
+ "id": "86ylgsLt",
167
+ "block": "[[[10,\"h2\"],[15,\"data-test-person\",[30,1,[\"firstName\"]]],[14,\"data-scopedcss-a14586af1f-8d94048c9a\",\"\"],[12],[1,\"\\n \"],[8,[30,2,[\"firstName\"]],[[24,\"data-scopedcss-a14586af1f-8d94048c9a\",\"\"]],null,null],[1,\"\\n\"],[13],[1,\"\\n\"],[10,2],[15,\"data-test-first-letter-of-the-name\",[30,1,[\"firstLetterOfTheName\"]]],[14,\"data-scopedcss-a14586af1f-8d94048c9a\",\"\"],[12],[1,\"\\n \"],[8,[30,2,[\"firstLetterOfTheName\"]],[[24,\"data-scopedcss-a14586af1f-8d94048c9a\",\"\"]],null,null],[1,\"\\n\"],[13],[1,\"\\nPet:\\n\"],[10,0],[14,0,\"pet-container\"],[14,\"data-scopedcss-a14586af1f-8d94048c9a\",\"\"],[12],[1,\"\\n \"],[8,[30,2,[\"pet\"]],[[24,\"data-scopedcss-a14586af1f-8d94048c9a\",\"\"]],null,null],[1,\"\\n\"],[13],[1,\"\\nFriends:\\n\"],[8,[30,2,[\"friends\"]],[[24,\"data-scopedcss-a14586af1f-8d94048c9a\",\"\"]],null,null],[1,\"\\n\"],[10,0],[14,\"data-test-addresses\",\"\"],[14,\"data-scopedcss-a14586af1f-8d94048c9a\",\"\"],[12],[1,\"Address: \"],[8,[30,2,[\"address\"]],[[24,\"data-scopedcss-a14586af1f-8d94048c9a\",\"\"]],null,null],[13],[1,\"\\n\"]],[\"@model\",\"@fields\"],[]]",
168
+ "moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/components/ai-assistant-panel/tools-test.gts",
169
+ "isStrictMode": true
170
+ }), this);
171
+ }
172
+ };
173
+ }
174
+ let petMango = new Pet({ name: "Mango" });
175
+ let petJackie = new Pet({ name: "Jackie" });
176
+ await withCachedRealmSetup(async () => {
177
+ await setupIntegrationTestRealm({
178
+ mockMatrixUtils,
179
+ contents: {
180
+ "address.gts": { Address },
181
+ "hello.txt": "Hello, world!",
182
+ "person.gts": { Person },
183
+ "pet.gts": { Pet },
184
+ "Pet/mango.json": petMango,
185
+ "Pet/jackie.json": petJackie,
186
+ "Person/fadhlan.json": new Person({
187
+ firstName: "Fadhlan",
188
+ address: new Address({
189
+ city: "Bandung",
190
+ country: "Indonesia"
191
+ }),
192
+ pet: petMango
193
+ }),
194
+ "Person/burcu.json": new Person({
195
+ firstName: "Burcu",
196
+ friends: [petJackie, petMango]
197
+ }),
198
+ "Person/mickey.json": new Person({ firstName: "Mickey" }),
199
+ "Person/justin.json": new Person({ firstName: "Justin" }),
200
+ "Person/ian.json": new Person({ firstName: "Ian" }),
201
+ "Person/matic.json": new Person({ firstName: "Matic" }),
202
+ "Person/buck.json": new Person({ firstName: "Buck" }),
203
+ "Person/hassan.json": new Person({ firstName: "Hassan" }),
204
+ "Skill/boxel-environment.json": { data: {
205
+ attributes: {
206
+ title: "Boxel Environment",
207
+ description: "Test environment skill",
208
+ instructions: "Test skill card for environment commands",
209
+ commands: [
210
+ {
211
+ codeRef: {
212
+ name: "SearchCardsByTypeAndTitleTool",
213
+ module: "@cardstack/boxel-host/commands/search-cards"
214
+ },
215
+ requiresApproval: false
216
+ },
217
+ {
218
+ codeRef: {
219
+ name: "SearchCardsByQueryTool",
220
+ module: "@cardstack/boxel-host/commands/search-cards"
221
+ },
222
+ requiresApproval: false
223
+ },
224
+ {
225
+ codeRef: {
226
+ name: "default",
227
+ module: "@cardstack/boxel-host/commands/read-file-for-ai-assistant"
228
+ },
229
+ requiresApproval: false
230
+ },
231
+ {
232
+ codeRef: {
233
+ name: "default",
234
+ module: "@cardstack/boxel-host/commands/read-card-for-ai-assistant"
235
+ },
236
+ requiresApproval: false
237
+ }
238
+ ]
239
+ },
240
+ meta: { adoptsFrom: skillCardRef }
241
+ } },
242
+ "realm.json": realmConfigCardJSON({ name: realmName })
243
+ }
244
+ });
245
+ await setupIntegrationTestRealm({
246
+ mockMatrixUtils,
247
+ realmURL: readOnlyRealmURL,
248
+ contents: {
249
+ "pet.gts": `
250
+ import { contains, field, CardDef } from "@cardstack/base/card-api";
251
+ import StringField from "@cardstack/base/string";
252
+ export class Pet extends CardDef {
253
+ static displayName = 'Pet';
254
+ @field name = contains(StringField);
255
+ }
256
+ `,
257
+ "person.gts": `
258
+ import { contains, field, linksTo, CardDef } from "@cardstack/base/card-api";
259
+ import StringField from "@cardstack/base/string";
260
+ import { Pet } from "./pet";
261
+ export class Person extends CardDef {
262
+ static displayName = 'Person';
263
+ @field firstName = contains(StringField);
264
+ @field pet = linksTo(Pet);
265
+ }
266
+ `,
267
+ "Person/ian.json": { data: {
268
+ type: "card",
269
+ attributes: { firstName: "Ian" },
270
+ relationships: { pet: { data: {
271
+ type: "card",
272
+ id: `${readOnlyRealmURL}Pet/rose`
273
+ } } },
274
+ meta: { adoptsFrom: {
275
+ module: "./person",
276
+ name: "Person"
277
+ } }
278
+ } },
279
+ "Pet/rose.json": { data: {
280
+ type: "card",
281
+ attributes: { name: "Rose" },
282
+ meta: { adoptsFrom: {
283
+ module: "./pet",
284
+ name: "Pet"
285
+ } }
286
+ } },
287
+ "realm.json": realmConfigCardJSON({ name: readOnlyRealmName })
288
+ }
289
+ });
290
+ });
291
+ });
292
+ function setCardInOperatorModeState(cardURL, format = "isolated") {
293
+ operatorModeStateService.restore({ stacks: cardURL ? [[{
294
+ id: cardURL,
295
+ format
296
+ }]] : [[]] });
297
+ }
298
+ async function openAiAssistant() {
299
+ await waitFor("[data-test-open-ai-assistant]");
300
+ await click("[data-test-open-ai-assistant]");
301
+ await waitFor("[data-test-room-settled]");
302
+ let roomId = document.querySelector("[data-test-room]")?.getAttribute("data-test-room");
303
+ if (!roomId) throw new Error("Expected a room ID");
304
+ return roomId;
305
+ }
306
+ async function renderAiAssistantPanel(id) {
307
+ setCardInOperatorModeState(id);
308
+ await renderComponent(class TestDriver extends Component {
309
+ static {
310
+ setComponentTemplate(templateFactory({
311
+ "id": "hk0qKyFP",
312
+ "block": "[[[8,[32,0],null,[[\"@onClose\"],[[32,1]]],null]],[],[]]",
313
+ "moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/components/ai-assistant-panel/tools-test.gts",
314
+ "scope": () => [OperatorModeContainer, noop],
315
+ "isStrictMode": true
316
+ }), this);
317
+ }
318
+ });
319
+ return await openAiAssistant();
320
+ }
321
+ const TOOL_RESULT_TIMEOUT_MS = 1e4;
322
+ async function waitForToolResult(selector = "[data-test-tool-result-header]") {
323
+ let startedAt = performance.now();
324
+ try {
325
+ await waitFor(selector, { timeout: TOOL_RESULT_TIMEOUT_MS });
326
+ } catch (e) {
327
+ let applyButtons = [...document.querySelectorAll("[data-test-tool-call-apply]")].map((el) => el.getAttribute("data-test-tool-call-apply"));
328
+ console.error(`[tool-result-wait] no ${selector} after ${Math.round(performance.now() - startedAt)}ms; messages=${document.querySelectorAll("[data-test-message-idx]").length}; applyStates=${JSON.stringify(applyButtons)} (a tool that reached "applied" points at the result card load; see any [tool-result-card] lines)`);
329
+ throw e;
330
+ }
331
+ console.log(`[tool-result-wait] ${selector} after ${Math.round(performance.now() - startedAt)}ms`);
332
+ }
333
+ (0, import_qunit.test)("it allows chat commands to change cards in the stack", async function(assert) {
334
+ assert.expect(4);
335
+ let roomId = await renderAiAssistantPanel(`${testRealmURL}Person/fadhlan`);
336
+ await waitFor("[data-test-person]");
337
+ assert.dom("[data-test-boxel-card-header-title]").hasText("Person - Fadhlan");
338
+ assert.dom("[data-test-person]").hasText("Fadhlan");
339
+ simulateRemoteMessage(roomId, "@aibot:localhost", {
340
+ body: "i am the body",
341
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
342
+ format: "org.matrix.custom.html",
343
+ isStreamingFinished: true,
344
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: [{
345
+ id: "change-cards-in-stack",
346
+ name: "patchCardInstance",
347
+ arguments: JSON.stringify({ attributes: {
348
+ cardId: `${testRealmURL}Person/fadhlan`,
349
+ patch: { attributes: { firstName: "Dave" } }
350
+ } })
351
+ }],
352
+ "m.relates_to": {
353
+ rel_type: "m.replace",
354
+ event_id: "patch1"
355
+ }
356
+ });
357
+ await waitFor("[data-test-tool-call-apply]");
358
+ this.onSave((_, json) => {
359
+ if (typeof json === "string") throw new Error("expected JSON save data");
360
+ assert.strictEqual(json.data.attributes?.firstName, "Dave");
361
+ });
362
+ await click("[data-test-pretui-tool-gate-action=\"apply\"]");
363
+ await waitFor("[data-test-tool-call-card-idle]");
364
+ assert.dom("[data-test-person]").hasText("Dave");
365
+ });
366
+ (0, import_qunit.test)("when a command is being prepared, apply button is shown in preparing state", async function(assert) {
367
+ setCardInOperatorModeState(`${testRealmURL}Person/fadhlan`);
368
+ await renderComponent(class TestDriver extends Component {
369
+ static {
370
+ setComponentTemplate(templateFactory({
371
+ "id": "hk0qKyFP",
372
+ "block": "[[[8,[32,0],null,[[\"@onClose\"],[[32,1]]],null]],[],[]]",
373
+ "moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/components/ai-assistant-panel/tools-test.gts",
374
+ "scope": () => [OperatorModeContainer, noop],
375
+ "isStrictMode": true
376
+ }), this);
377
+ }
378
+ });
379
+ await waitFor("[data-test-person=\"Fadhlan\"]");
380
+ let roomId = createAndJoinRoom({
381
+ sender: "@testuser:localhost",
382
+ name: "test room 1"
383
+ });
384
+ let initialEventId = simulateRemoteMessage(roomId, "@aibot:localhost", {
385
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
386
+ body: "Changing",
387
+ format: "org.matrix.custom.html",
388
+ isStreamingFinished: false
389
+ });
390
+ simulateRemoteMessage(roomId, "@aibot:localhost", {
391
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
392
+ body: "Changing first name to Evie",
393
+ format: "org.matrix.custom.html",
394
+ isStreamingFinished: false,
395
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: [{
396
+ id: "6545dc5a-01a1-47d6-b2f7-493d2ff5a0c2",
397
+ name: "patchCardInstance"
398
+ }],
399
+ "m.relates_to": {
400
+ rel_type: "m.replace",
401
+ event_id: initialEventId
402
+ }
403
+ });
404
+ await settled();
405
+ await click("[data-test-open-ai-assistant]");
406
+ await waitFor("[data-test-room-name=\"test room 1\"]");
407
+ assert.dom("[data-test-message-idx]").exists({ count: 1 });
408
+ await waitFor("[data-test-message-idx=\"0\"] [data-test-pretui-tool-row][data-state=\"streaming\"]");
409
+ assert.dom("[data-test-message-idx=\"0\"] [data-test-pretui-tool-row][data-state=\"streaming\"]").exists();
410
+ });
411
+ (0, import_qunit.test)("it does not display the streaming indicator when ai bot sends a command", async function(assert) {
412
+ simulateRemoteMessage(await renderAiAssistantPanel(), "@aibot:localhost", {
413
+ body: "i am the body",
414
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
415
+ format: "org.matrix.custom.html",
416
+ isStreamingFinished: true,
417
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: [{
418
+ id: "fb8fef81-2142-4861-a902-d5614b0aea52",
419
+ name: "patchCardInstance",
420
+ arguments: JSON.stringify({ attributes: {
421
+ cardId: `${testRealmURL}Person/fadhlan`,
422
+ patch: { attributes: { firstName: "Dave" } }
423
+ } })
424
+ }]
425
+ });
426
+ await waitFor("[data-test-message-idx=\"0\"]");
427
+ assert.dom("[data-test-message-idx=\"0\"] [data-test-ai-avatar]").doesNotHaveClass("ai-avatar-animated", "ai bot patch message does not have a spinner");
428
+ });
429
+ (0, import_qunit.test)("when command is done streaming, apply button is shown in ready state", async function(assert) {
430
+ setCardInOperatorModeState(`${testRealmURL}Person/fadhlan`);
431
+ await renderComponent(class TestDriver extends Component {
432
+ static {
433
+ setComponentTemplate(templateFactory({
434
+ "id": "hk0qKyFP",
435
+ "block": "[[[8,[32,0],null,[[\"@onClose\"],[[32,1]]],null]],[],[]]",
436
+ "moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/components/ai-assistant-panel/tools-test.gts",
437
+ "scope": () => [OperatorModeContainer, noop],
438
+ "isStrictMode": true
439
+ }), this);
440
+ }
441
+ });
442
+ await waitFor("[data-test-person=\"Fadhlan\"]");
443
+ let roomId = createAndJoinRoom({
444
+ sender: "@testuser:localhost",
445
+ name: "test room 1"
446
+ });
447
+ let initialEventId = simulateRemoteMessage(roomId, "@aibot:localhost", {
448
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
449
+ body: "Changing",
450
+ format: "org.matrix.custom.html",
451
+ isStreamingFinished: false
452
+ });
453
+ simulateRemoteMessage(roomId, "@aibot:localhost", {
454
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
455
+ body: "Changing first names",
456
+ format: "org.matrix.custom.html",
457
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: [{
458
+ id: "6545dc5a-01a1-47d6-b2f7-493d2ff5a0c2",
459
+ name: "patchCardInstance"
460
+ }],
461
+ isStreamingFinished: false,
462
+ "m.relates_to": {
463
+ rel_type: "m.replace",
464
+ event_id: initialEventId
465
+ }
466
+ });
467
+ await settled();
468
+ await click("[data-test-open-ai-assistant]");
469
+ await waitFor("[data-test-room-name=\"test room 1\"]");
470
+ assert.dom("[data-test-message-idx]").exists({ count: 1 });
471
+ await waitFor("[data-test-message-idx=\"0\"] [data-test-pretui-tool-row][data-state=\"streaming\"]");
472
+ assert.dom("[data-test-message-idx=\"0\"] [data-test-pretui-tool-row][data-state=\"streaming\"]").exists();
473
+ simulateRemoteMessage(roomId, "@aibot:localhost", {
474
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
475
+ body: "Changing first names",
476
+ format: "org.matrix.custom.html",
477
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: [{
478
+ id: "6545dc5a-01a1-47d6-b2f7-493d2ff5a0c2",
479
+ name: "patchCardInstance",
480
+ arguments: JSON.stringify({ attributes: {
481
+ cardId: `${testRealmURL}Person/fadhlan`,
482
+ patch: { attributes: { firstName: "Evie" } }
483
+ } })
484
+ }, {
485
+ id: "f2da5504-b92f-480a-986a-56ec606d240e",
486
+ name: "patchCardInstance",
487
+ arguments: JSON.stringify({ attributes: {
488
+ cardId: `${testRealmURL}Person/hassan`,
489
+ patch: { attributes: { firstName: "Ivana" } }
490
+ } })
491
+ }],
492
+ isStreamingFinished: false,
493
+ "m.relates_to": {
494
+ rel_type: "m.replace",
495
+ event_id: initialEventId
496
+ }
497
+ });
498
+ await settled();
499
+ assert.dom("[data-test-message-idx]").exists({ count: 1 });
500
+ await waitFor("[data-test-message-idx=\"0\"] [data-test-pretui-tool-row][data-state=\"streaming\"]");
501
+ assert.dom("[data-test-message-idx=\"0\"] [data-test-pretui-tool-row][data-state=\"streaming\"]").exists({ count: 2 }, "each call still arriving is a streaming row");
502
+ simulateRemoteMessage(roomId, "@aibot:localhost", {
503
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
504
+ body: "Changing first names",
505
+ format: "org.matrix.custom.html",
506
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: [{
507
+ id: "6545dc5a-01a1-47d6-b2f7-493d2ff5a0c2",
508
+ name: "patchCardInstance",
509
+ arguments: JSON.stringify({ attributes: {
510
+ cardId: `${testRealmURL}Person/fadhlan`,
511
+ patch: { attributes: { firstName: "Evie" } }
512
+ } })
513
+ }, {
514
+ id: "f2da5504-b92f-480a-986a-56ec606d240e",
515
+ name: "patchCardInstance",
516
+ arguments: JSON.stringify({ attributes: {
517
+ cardId: `${testRealmURL}Person/hassan`,
518
+ patch: { attributes: { firstName: "Ivana" } }
519
+ } })
520
+ }],
521
+ isStreamingFinished: true,
522
+ "m.relates_to": {
523
+ rel_type: "m.replace",
524
+ event_id: initialEventId
525
+ }
526
+ });
527
+ await settled();
528
+ assert.dom("[data-test-message-idx]").exists({ count: 1 });
529
+ await waitFor("[data-test-message-idx=\"0\"] [data-test-tool-call-apply]");
530
+ assert.dom("[data-test-message-idx=\"0\"] [data-test-pretui-tool-row][data-state=\"streaming\"]").doesNotExist("every call has arrived");
531
+ assert.dom("[data-test-message-idx=\"0\"] [data-test-tool-call-apply=\"ready\"]").exists({ count: 2 });
532
+ });
533
+ (0, import_qunit.test)("after command is executed, a command result event will be dispatched", async function(assert) {
534
+ setCardInOperatorModeState(`${testRealmURL}Person/fadhlan`);
535
+ await renderComponent(class TestDriver extends Component {
536
+ static {
537
+ setComponentTemplate(templateFactory({
538
+ "id": "hk0qKyFP",
539
+ "block": "[[[8,[32,0],null,[[\"@onClose\"],[[32,1]]],null]],[],[]]",
540
+ "moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/components/ai-assistant-panel/tools-test.gts",
541
+ "scope": () => [OperatorModeContainer, noop],
542
+ "isStrictMode": true
543
+ }), this);
544
+ }
545
+ });
546
+ await waitFor("[data-test-person=\"Fadhlan\"]");
547
+ let roomId = createAndJoinRoom({
548
+ sender: "@testuser:localhost",
549
+ name: "test room 1"
550
+ });
551
+ simulateRemoteMessage(roomId, "@aibot:localhost", {
552
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
553
+ body: "Changing first name to Evie",
554
+ format: "org.matrix.custom.html",
555
+ isStreamingFinished: true,
556
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: [{
557
+ id: "result-event-dispatch",
558
+ name: "patchCardInstance",
559
+ arguments: JSON.stringify({ attributes: {
560
+ cardId: `${testRealmURL}Person/fadhlan`,
561
+ patch: { attributes: { firstName: "Evie" } }
562
+ } })
563
+ }]
564
+ });
565
+ let commandResultEvents = getRoomEvents(roomId).filter((event) => event.type === "app.boxel.toolResult" && event.content["m.relates_to"]?.rel_type === "app.boxel.toolAnnotation" && event.content["m.relates_to"]?.key === "applied");
566
+ assert.strictEqual(commandResultEvents.length, 0, "command result event is not dispatched");
567
+ await settled();
568
+ await click("[data-test-open-ai-assistant]");
569
+ await waitFor("[data-test-room-name=\"test room 1\"]");
570
+ await waitFor("[data-test-message-idx=\"0\"] [data-test-tool-call-apply]");
571
+ await click("[data-test-message-idx=\"0\"] [data-test-pretui-tool-gate-action=\"apply\"]");
572
+ await waitFor("[data-test-tool-call-card-idle]");
573
+ assert.dom("[data-test-message-idx=\"0\"] [data-test-tool-call-apply=\"applied\"]").exists();
574
+ commandResultEvents = getRoomEvents(roomId).filter((event) => event.type === "app.boxel.toolResult" && event.content["m.relates_to"]?.rel_type === "app.boxel.toolAnnotation" && event.content["m.relates_to"]?.key === "applied");
575
+ assert.strictEqual(commandResultEvents.length, 1, "command result event is dispatched");
576
+ assert.deepEqual(JSON.parse(commandResultEvents[0].content.data).context, {
577
+ agentId: getService("matrix-service").agentId,
578
+ submode: "interact",
579
+ debug: false,
580
+ openCardIds: ["http://test-realm/test/Person/fadhlan"],
581
+ realmPrefixes: registeredRealmPrefixes(),
582
+ realmUrl: "http://test-realm/test/",
583
+ realmPermissions: {
584
+ canRead: true,
585
+ canWrite: true
586
+ }
587
+ }, "command result event contains the context");
588
+ });
589
+ (0, import_qunit.test)("after search command is executed, a command result event is dispatched", async function(assert) {
590
+ setCardInOperatorModeState(`${testRealmURL}Person/fadhlan`);
591
+ await renderComponent(class TestDriver extends Component {
592
+ static {
593
+ setComponentTemplate(templateFactory({
594
+ "id": "hk0qKyFP",
595
+ "block": "[[[8,[32,0],null,[[\"@onClose\"],[[32,1]]],null]],[],[]]",
596
+ "moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/components/ai-assistant-panel/tools-test.gts",
597
+ "scope": () => [OperatorModeContainer, noop],
598
+ "isStrictMode": true
599
+ }), this);
600
+ }
601
+ });
602
+ await waitFor("[data-test-person=\"Fadhlan\"]");
603
+ let roomId = createAndJoinRoom({
604
+ sender: "@testuser:localhost",
605
+ name: "test room 1"
606
+ });
607
+ simulateRemoteMessage(roomId, "@aibot:localhost", {
608
+ body: "Changing first name to Evie",
609
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
610
+ format: "org.matrix.custom.html",
611
+ isStreamingFinished: true,
612
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: [{
613
+ id: "search-result-dispatch",
614
+ name: "patchCardInstance",
615
+ arguments: JSON.stringify({ attributes: {
616
+ cardId: `${testRealmURL}Person/fadhlan`,
617
+ patch: { attributes: { firstName: "Evie" } }
618
+ } })
619
+ }]
620
+ });
621
+ let commandResultEvents = getRoomEvents(roomId).filter((event) => event.type === APP_BOXEL_TOOL_RESULT_EVENT_TYPE);
622
+ assert.strictEqual(commandResultEvents.length, 0, "command result event is not dispatched");
623
+ await settled();
624
+ await click("[data-test-open-ai-assistant]");
625
+ await waitFor("[data-test-room-name=\"test room 1\"]");
626
+ await waitFor("[data-test-message-idx=\"0\"] [data-test-tool-call-apply]");
627
+ await click("[data-test-message-idx=\"0\"] [data-test-pretui-tool-gate-action=\"apply\"]");
628
+ await waitFor("[data-test-tool-call-card-idle]");
629
+ assert.dom("[data-test-message-idx=\"0\"] [data-test-tool-call-apply=\"applied\"]").exists();
630
+ commandResultEvents = getRoomEvents(roomId).filter((event) => event.type === APP_BOXEL_TOOL_RESULT_EVENT_TYPE);
631
+ assert.strictEqual(commandResultEvents.length, 1, "command result event is dispatched");
632
+ assert.deepEqual(JSON.parse(commandResultEvents[0].content.data).context, {
633
+ agentId: getService("matrix-service").agentId,
634
+ submode: "interact",
635
+ debug: false,
636
+ openCardIds: ["http://test-realm/test/Person/fadhlan"],
637
+ realmPrefixes: registeredRealmPrefixes(),
638
+ realmUrl: "http://test-realm/test/",
639
+ realmPermissions: {
640
+ canRead: true,
641
+ canWrite: true
642
+ }
643
+ }, "command result event contains the context");
644
+ });
645
+ (0, import_qunit.test)("it can search for card instances that is of the same card type as the card shared", async function(assert) {
646
+ let roomId = await renderAiAssistantPanel(`${testRealmURL}Pet/mango.json`);
647
+ await addSkillToAiAssistant(`${testRealmURL}Skill/boxel-environment`);
648
+ simulateRemoteMessage(roomId, "@aibot:localhost", {
649
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
650
+ body: "Search for the following card",
651
+ format: "org.matrix.custom.html",
652
+ isStreamingFinished: true,
653
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: [{
654
+ id: "search1",
655
+ name: searchCardsToolName,
656
+ arguments: JSON.stringify({
657
+ description: "Searching for card",
658
+ attributes: { type: {
659
+ module: `${testRealmURL}pet`,
660
+ name: "Pet"
661
+ } }
662
+ })
663
+ }],
664
+ data: { context: { agentId: getService("matrix-service").agentId } }
665
+ });
666
+ await waitForToolResult();
667
+ assert.dom("[data-test-ai-message-content]").containsText("Search for the following card");
668
+ assert.dom("[data-test-ai-message-content] [data-test-pretui-tool-row-toggle]").exists({ count: 1 });
669
+ assert.dom("[data-test-message-idx=\"0\"] [data-test-tool-result-header]").containsText("SearchCardsByTypeAndTitle", "the result's meta line names the call");
670
+ assert.dom(".result-list li").exists({ count: 2 });
671
+ assert.dom(".result-list li:nth-child(1)").containsText("Jackie");
672
+ assert.dom(".result-list li:nth-child(2)").containsText("Mango");
673
+ assert.dom("[data-test-toggle-show-button]").doesNotExist();
674
+ });
675
+ (0, import_qunit.test)("it can search for card instances based upon title of card", async function(assert) {
676
+ let roomId = await renderAiAssistantPanel(`${testRealmURL}Pet/mango.json`);
677
+ await addSkillToAiAssistant(`${testRealmURL}Skill/boxel-environment`);
678
+ simulateRemoteMessage(roomId, "@aibot:localhost", {
679
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
680
+ body: "Search for the following card",
681
+ format: "org.matrix.custom.html",
682
+ isStreamingFinished: true,
683
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: [{
684
+ id: "search1",
685
+ name: searchCardsToolName,
686
+ arguments: JSON.stringify({
687
+ description: "Searching for card",
688
+ attributes: { cardTitle: "Mango" }
689
+ })
690
+ }],
691
+ data: { context: { agentId: getService("matrix-service").agentId } }
692
+ });
693
+ await waitForToolResult();
694
+ assert.dom("[data-test-ai-message-content]").containsText("Search for the following card");
695
+ assert.dom("[data-test-ai-message-content] [data-test-pretui-tool-row-toggle]").exists({ count: 1 });
696
+ assert.dom("[data-test-message-idx=\"0\"] [data-test-boxel-tool-call-result]").exists("the search results card shows in the row");
697
+ assert.dom(".result-list li:nth-child(1)").containsText("Mango");
698
+ assert.dom("[data-test-toggle-show-button]").doesNotExist();
699
+ });
700
+ (0, import_qunit.test)("toggle more search results", async function(assert) {
701
+ let roomId = await renderAiAssistantPanel(`${testRealmURL}Person/fadhlan.json`);
702
+ await addSkillToAiAssistant(`${testRealmURL}Skill/boxel-environment`);
703
+ simulateRemoteMessage(roomId, "@aibot:localhost", {
704
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
705
+ body: "Search for the following card",
706
+ format: "org.matrix.custom.html",
707
+ isStreamingFinished: true,
708
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: [{
709
+ id: "721c8c78-d8c1-4cc1-a7e9-51d2d3143e4d",
710
+ name: searchCardsToolName,
711
+ arguments: JSON.stringify({
712
+ description: "Searching for card",
713
+ attributes: { type: {
714
+ module: `${testRealmURL}person`,
715
+ name: "Person"
716
+ } }
717
+ })
718
+ }],
719
+ data: { context: { agentId: getService("matrix-service").agentId } }
720
+ });
721
+ await waitForToolResult();
722
+ let resultCard = find("[data-test-message-idx=\"0\"] [data-test-boxel-tool-call-result]");
723
+ let cardStyle = window.getComputedStyle(resultCard);
724
+ assert.notStrictEqual(cardStyle.color, cardStyle.backgroundColor, "result body text contrasts with its background");
725
+ assert.dom(".result-list li:nth-child(6)").doesNotExist();
726
+ assert.dom("[data-test-toggle-show-button]").containsText("Show 3 more results");
727
+ await click("[data-test-toggle-show-button]");
728
+ await waitFor(".result-list li", { count: 8 });
729
+ assert.dom("[data-test-toggle-show-button]").containsText("See Less");
730
+ assert.dom(".result-list li:nth-child(1)").containsText("Buck");
731
+ assert.dom(".result-list li:nth-child(2)").containsText("Burcu");
732
+ assert.dom(".result-list li:nth-child(3)").containsText("Fadhlan");
733
+ assert.dom(".result-list li:nth-child(4)").containsText("Hassan");
734
+ assert.dom(".result-list li:nth-child(5)").containsText("Ian");
735
+ assert.dom(".result-list li:nth-child(6)").containsText("Justin");
736
+ assert.dom(".result-list li:nth-child(7)").containsText("Matic");
737
+ assert.dom(".result-list li:nth-child(8)").containsText("Mickey");
738
+ await click("[data-test-toggle-show-button]");
739
+ assert.dom(".result-list li:nth-child(1)").containsText("Buck");
740
+ assert.dom(".result-list li:nth-child(2)").containsText("Burcu");
741
+ assert.dom(".result-list li:nth-child(3)").containsText("Fadhlan");
742
+ assert.dom(".result-list li:nth-child(4)").containsText("Hassan");
743
+ assert.dom(".result-list li:nth-child(5)").containsText("Ian");
744
+ assert.dom(".result-list li:nth-child(6)").doesNotExist();
745
+ });
746
+ (0, import_qunit.test)("it can copy search results card to workspace", async function(assert) {
747
+ const id = `${testRealmURL}Person/fadhlan`;
748
+ const roomId = await renderAiAssistantPanel(`${id}.json`);
749
+ await addSkillToAiAssistant(`${testRealmURL}Skill/boxel-environment`);
750
+ const toolArgs = {
751
+ description: "Search for Person cards",
752
+ attributes: { type: {
753
+ module: `${testRealmURL}person`,
754
+ name: "Person"
755
+ } }
756
+ };
757
+ simulateRemoteMessage(roomId, "@aibot:localhost", {
758
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
759
+ body: "Search for the following card",
760
+ format: "org.matrix.custom.html",
761
+ isStreamingFinished: true,
762
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: [{
763
+ id: "fd4515fb-ed4d-4005-9782-4e844d7d4d9c",
764
+ name: searchCardsToolName,
765
+ arguments: JSON.stringify(toolArgs)
766
+ }],
767
+ data: { context: { agentId: getService("matrix-service").agentId } }
768
+ });
769
+ await waitForToolResult();
770
+ assert.dom(`[data-test-stack-card="${id}"]`).exists();
771
+ assert.dom("[data-test-message-idx=\"0\"] [data-test-boxel-tool-call-result]").exists("the search results card shows in the row");
772
+ let resultListItem = "[data-test-result-list] > li";
773
+ assert.dom(`${resultListItem}:nth-child(1)`).containsText("Buck");
774
+ assert.dom(`${resultListItem}:nth-child(5)`).containsText("Ian");
775
+ const rightStackItem = "[data-test-operator-mode-stack=\"1\"] [data-test-stack-card-index=\"0\"]";
776
+ assert.dom(rightStackItem).doesNotExist();
777
+ await click("[data-test-tool-result-container] [data-test-more-options-button]");
778
+ await click(menuItem("Copy to Workspace"));
779
+ assert.dom(`${rightStackItem} [data-test-boxel-card-header-title]`).hasText("Search Results - Search Results");
780
+ const savedCard = `[data-test-card="${document.querySelector(rightStackItem)?.getAttribute("data-stack-card")}"] [data-test-tool-result-isolated]`;
781
+ assert.dom(`${savedCard} header`).hasText("Search Results 8 Results");
782
+ assert.dom(`${savedCard} [data-test-boxel-field]`).exists({ count: 2 });
783
+ assert.dom(`${savedCard} [data-test-boxel-field]:nth-child(1)`).hasText(`Description Query: { "type": { "module": "http://test-realm/test/person", "name": "Person" } }`);
784
+ resultListItem = `${savedCard} ${resultListItem}`;
785
+ assert.dom(resultListItem).exists({ count: 8 });
786
+ assert.dom(`${resultListItem}:nth-child(1)`).containsText("Buck");
787
+ assert.dom(`${resultListItem}:nth-child(6)`).containsText("Justin");
788
+ assert.dom(`${resultListItem}:nth-child(8)`).containsText("Mickey");
789
+ });
790
+ (0, import_qunit.test)("copy to workspace menu item is shown for writable realm", async function(assert) {
791
+ const roomId = await renderAiAssistantPanel(`${`${testRealmURL}Person/fadhlan`}.json`);
792
+ await addSkillToAiAssistant(`${testRealmURL}Skill/boxel-environment`);
793
+ const toolArgs = {
794
+ description: "Search for Person cards",
795
+ attributes: { type: {
796
+ module: `${testRealmURL}person`,
797
+ name: "Person"
798
+ } }
799
+ };
800
+ simulateRemoteMessage(roomId, "@aibot:localhost", {
801
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
802
+ body: "Search for the following card",
803
+ format: "org.matrix.custom.html",
804
+ isStreamingFinished: true,
805
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: [{
806
+ id: "9a5b7422-87de-4a93-9f07-9b7c40b75b1e",
807
+ name: searchCardsToolName,
808
+ arguments: JSON.stringify(toolArgs)
809
+ }],
810
+ data: { context: { agentId: getService("matrix-service").agentId } }
811
+ });
812
+ await waitForToolResult();
813
+ await click("[data-test-tool-result-container] [data-test-more-options-button]");
814
+ assert.ok(menuItem("Copy to Workspace"), "the menu offers the copy");
815
+ });
816
+ (0, import_qunit.test)("copy to workspace menu item is hidden for read-only realm", async function(assert) {
817
+ const roomId = await renderAiAssistantPanel(`${`${readOnlyRealmURL}Person/ian`}.json`);
818
+ await addSkillToAiAssistant(`${testRealmURL}Skill/boxel-environment`);
819
+ const toolArgs = {
820
+ description: "Search for Person cards",
821
+ attributes: { type: {
822
+ module: `${testRealmURL}person`,
823
+ name: "Person"
824
+ } }
825
+ };
826
+ simulateRemoteMessage(roomId, "@aibot:localhost", {
827
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
828
+ body: "Search for the following card",
829
+ format: "org.matrix.custom.html",
830
+ isStreamingFinished: true,
831
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: [{
832
+ id: "6c6e2d73-8e09-4b44-a0d9-688f36b73be8",
833
+ name: searchCardsToolName,
834
+ arguments: JSON.stringify(toolArgs)
835
+ }],
836
+ data: { context: { agentId: getService("matrix-service").agentId } }
837
+ });
838
+ await waitForToolResult();
839
+ assert.dom("[data-test-tool-result-container] [data-test-more-options-button]").doesNotExist();
840
+ assert.notOk(menuItem("Copy to Workspace"), "no copy is offered");
841
+ });
842
+ (0, import_qunit.test)("it can copy search results card to workspace (no cards in stack)", async function(assert) {
843
+ const id = `${testRealmURL}Person/fadhlan`;
844
+ const roomId = await renderAiAssistantPanel(`${id}.json`);
845
+ await addSkillToAiAssistant(`${testRealmURL}Skill/boxel-environment`);
846
+ const toolArgs = {
847
+ description: "Search for Person cards",
848
+ attributes: { type: {
849
+ module: `${testRealmURL}person`,
850
+ name: "Person"
851
+ } }
852
+ };
853
+ simulateRemoteMessage(roomId, "@aibot:localhost", {
854
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
855
+ body: "Search for the following card",
856
+ format: "org.matrix.custom.html",
857
+ isStreamingFinished: true,
858
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: [{
859
+ id: "ffd1a3d0-0bd4-491a-a907-b96ec9d8902c",
860
+ name: searchCardsToolName,
861
+ arguments: JSON.stringify(toolArgs)
862
+ }],
863
+ data: { context: { agentId: getService("matrix-service").agentId } }
864
+ });
865
+ await waitForToolResult();
866
+ assert.dom(`[data-test-stack-card="${id}"]`).exists();
867
+ await click("[data-test-close-button]");
868
+ assert.dom(`[data-test-stack-card="${id}"]`).doesNotExist();
869
+ assert.dom(`[data-test-stack-card="${testRealmURL}index"]`).exists();
870
+ await click("[data-test-close-button]");
871
+ assert.dom("[data-test-message-idx=\"0\"] [data-test-boxel-tool-call-result]").exists("the search results card shows in the row");
872
+ assert.dom("[data-test-message-idx=\"0\"] [data-test-toggle-show-button]").containsText("Show 3 more results");
873
+ let resultListItem = "[data-test-result-list] > li";
874
+ assert.dom(`${resultListItem}:nth-child(1)`).containsText("Buck");
875
+ assert.dom(`${resultListItem}:nth-child(5)`).containsText("Ian");
876
+ const stackItem = "[data-test-operator-mode-stack=\"0\"] [data-test-stack-card-index=\"0\"]";
877
+ assert.dom(stackItem).doesNotExist();
878
+ await click("[data-test-tool-result-container] [data-test-more-options-button]");
879
+ await click(menuItem("Copy to Workspace"));
880
+ assert.dom(`${stackItem} [data-test-boxel-card-header-title]`).hasText("Search Results - Search Results");
881
+ const savedCard = `[data-test-card="${document.querySelector(stackItem)?.getAttribute("data-stack-card")}"] [data-test-tool-result-isolated]`;
882
+ assert.dom(`${savedCard} header`).hasText("Search Results 8 Results");
883
+ assert.dom(`${savedCard} [data-test-boxel-field]`).exists({ count: 2 });
884
+ assert.dom(`${savedCard} [data-test-boxel-field]:nth-child(1)`).hasText(`Description Query: { "type": { "module": "http://test-realm/test/person", "name": "Person" } }`);
885
+ resultListItem = `${savedCard} ${resultListItem}`;
886
+ assert.dom(resultListItem).exists({ count: 8 });
887
+ assert.dom(`${resultListItem}:nth-child(1)`).containsText("Buck");
888
+ assert.dom(`${resultListItem}:nth-child(6)`).containsText("Justin");
889
+ assert.dom(`${resultListItem}:nth-child(8)`).containsText("Mickey");
890
+ });
891
+ (0, import_qunit.test)("it maintains status of View Code panel as additional events stream in", async function(assert) {
892
+ setCardInOperatorModeState(`${testRealmURL}Person/fadhlan`);
893
+ await renderComponent(class TestDriver extends Component {
894
+ static {
895
+ setComponentTemplate(templateFactory({
896
+ "id": "hk0qKyFP",
897
+ "block": "[[[8,[32,0],null,[[\"@onClose\"],[[32,1]]],null]],[],[]]",
898
+ "moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/components/ai-assistant-panel/tools-test.gts",
899
+ "scope": () => [OperatorModeContainer, noop],
900
+ "isStrictMode": true
901
+ }), this);
902
+ }
903
+ });
904
+ await waitFor("[data-test-person=\"Fadhlan\"]");
905
+ simulateRemoteMessage(createAndJoinRoom({
906
+ sender: "@testuser:localhost",
907
+ name: "test room 1"
908
+ }), "@aibot:localhost", {
909
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
910
+ body: "Changing first name to Evie",
911
+ format: "org.matrix.custom.html",
912
+ isStreamingFinished: true,
913
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: [{
914
+ id: "view-code-panel-status",
915
+ name: "patchCardInstance",
916
+ arguments: JSON.stringify({ attributes: {
917
+ cardId: `${testRealmURL}Person/fadhlan`,
918
+ patch: { attributes: { firstName: "Evie" } }
919
+ } })
920
+ }]
921
+ });
922
+ await settled();
923
+ await click("[data-test-open-ai-assistant]");
924
+ await waitFor("[data-test-room-name=\"test room 1\"]");
925
+ assert.dom("[data-test-ai-message-content] [data-test-pretui-code]").doesNotExist("View Code panel should not yet be open");
926
+ await click("[data-test-pretui-tool-row-toggle]");
927
+ assert.dom("[data-test-ai-message-content] [data-test-pretui-code]").exists("View Code panel should be open");
928
+ await fillIn("[data-test-message-field]", "Asking a question about what I saw in the proposed code...");
929
+ await click("[data-test-send-message-btn]");
930
+ assert.dom("[data-test-ai-message-content] [data-test-pretui-code]").exists("View Code panel should remain open");
931
+ await percySnapshot(assert);
932
+ });
933
+ (0, import_qunit.test)("\"Hide Info\" collapses the code area even after the message re-mounts while expanded", async function(assert) {
934
+ setCardInOperatorModeState(`${testRealmURL}Person/fadhlan`);
935
+ await renderComponent(class TestDriver extends Component {
936
+ static {
937
+ setComponentTemplate(templateFactory({
938
+ "id": "hk0qKyFP",
939
+ "block": "[[[8,[32,0],null,[[\"@onClose\"],[[32,1]]],null]],[],[]]",
940
+ "moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/components/ai-assistant-panel/tools-test.gts",
941
+ "scope": () => [OperatorModeContainer, noop],
942
+ "isStrictMode": true
943
+ }), this);
944
+ }
945
+ });
946
+ await waitFor("[data-test-person=\"Fadhlan\"]");
947
+ simulateRemoteMessage(createAndJoinRoom({
948
+ sender: "@testuser:localhost",
949
+ name: "test room 1"
950
+ }), "@aibot:localhost", {
951
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
952
+ body: "Changing first name to Evie",
953
+ format: "org.matrix.custom.html",
954
+ isStreamingFinished: true,
955
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: [{
956
+ id: "hide-info-height",
957
+ name: "patchCardInstance",
958
+ arguments: JSON.stringify({ attributes: {
959
+ cardId: `${testRealmURL}Person/fadhlan`,
960
+ patch: { attributes: { firstName: "Evie" } }
961
+ } })
962
+ }]
963
+ });
964
+ await settled();
965
+ await click("[data-test-open-ai-assistant]");
966
+ await waitFor("[data-test-room-name=\"test room 1\"]");
967
+ await click("[data-test-pretui-tool-row-toggle]");
968
+ await waitFor("[data-test-pretui-code]");
969
+ await click("[data-test-close-ai-assistant]");
970
+ await click("[data-test-open-ai-assistant]");
971
+ await waitFor("[data-test-pretui-code]");
972
+ await settled();
973
+ await click("[data-test-pretui-tool-row-toggle]");
974
+ assert.dom("[data-test-pretui-code]").doesNotExist("code editor is removed after Hide Info");
975
+ let codeBlockSelector = "[data-test-tool-call-id=\"hide-info-height\"] [data-test-tool-code-block]";
976
+ assert.dom(codeBlockSelector).exists("tool code block element exists");
977
+ let codeBlock = find(codeBlockSelector);
978
+ assert.strictEqual(codeBlock.style.height, "", "no inline height is left behind so the block collapses to its header-only height");
979
+ });
980
+ (0, import_qunit.test)("expanding a tall tool call does not leave an empty gap below the code", async function(assert) {
981
+ setCardInOperatorModeState(`${testRealmURL}Person/fadhlan`);
982
+ await renderComponent(class TestDriver extends Component {
983
+ static {
984
+ setComponentTemplate(templateFactory({
985
+ "id": "hk0qKyFP",
986
+ "block": "[[[8,[32,0],null,[[\"@onClose\"],[[32,1]]],null]],[],[]]",
987
+ "moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/components/ai-assistant-panel/tools-test.gts",
988
+ "scope": () => [OperatorModeContainer, noop],
989
+ "isStrictMode": true
990
+ }), this);
991
+ }
992
+ });
993
+ await waitFor("[data-test-person=\"Fadhlan\"]");
994
+ let roomId = createAndJoinRoom({
995
+ sender: "@testuser:localhost",
996
+ name: "test room 1"
997
+ });
998
+ let attributes = Object.fromEntries(Array.from({ length: 30 }, (_, i) => [`field${i}`, `value ${i}`]));
999
+ simulateRemoteMessage(roomId, "@aibot:localhost", {
1000
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
1001
+ body: "Applying a large patch",
1002
+ format: "org.matrix.custom.html",
1003
+ isStreamingFinished: true,
1004
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: [{
1005
+ id: "tall-tool-call",
1006
+ name: "patchCardInstance",
1007
+ arguments: JSON.stringify({ attributes: {
1008
+ cardId: `${testRealmURL}Person/fadhlan`,
1009
+ patch: { attributes }
1010
+ } })
1011
+ }]
1012
+ });
1013
+ await settled();
1014
+ await click("[data-test-open-ai-assistant]");
1015
+ await waitFor("[data-test-room-name=\"test room 1\"]");
1016
+ await click("[data-test-pretui-tool-row-toggle]");
1017
+ await waitFor("[data-test-pretui-code]");
1018
+ await settled();
1019
+ let codeBlockSelector = "[data-test-tool-call-id=\"tall-tool-call\"] [data-test-pretui-code]";
1020
+ assert.dom(codeBlockSelector).exists("tool code block element exists");
1021
+ let codeBlock = find(codeBlockSelector);
1022
+ assert.strictEqual(codeBlock.style.height, "", "no inline height is stamped when the code is expanded");
1023
+ let childrenHeight = [...codeBlock.children].reduce((sum, child) => sum + child.offsetHeight, 0);
1024
+ assert.ok(codeBlock.offsetHeight <= childrenHeight + 4, `expanded code block height (${codeBlock.offsetHeight}px) should not exceed its rendered children (${childrenHeight}px)`);
1025
+ });
1026
+ (0, import_qunit.test)("when command in a message with continuations is done streaming, apply button is shown in ready state", async function(assert) {
1027
+ setCardInOperatorModeState(`${testRealmURL}Person/fadhlan`);
1028
+ await renderComponent(class TestDriver extends Component {
1029
+ static {
1030
+ setComponentTemplate(templateFactory({
1031
+ "id": "hk0qKyFP",
1032
+ "block": "[[[8,[32,0],null,[[\"@onClose\"],[[32,1]]],null]],[],[]]",
1033
+ "moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/components/ai-assistant-panel/tools-test.gts",
1034
+ "scope": () => [OperatorModeContainer, noop],
1035
+ "isStrictMode": true
1036
+ }), this);
1037
+ }
1038
+ });
1039
+ await waitFor("[data-test-person=\"Fadhlan\"]");
1040
+ let roomId = createAndJoinRoom({
1041
+ sender: "@testuser:localhost",
1042
+ name: "test room 1"
1043
+ });
1044
+ let initialEventId = simulateRemoteMessage(roomId, "@aibot:localhost", {
1045
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
1046
+ body: "Changing",
1047
+ format: "org.matrix.custom.html",
1048
+ isStreamingFinished: false
1049
+ });
1050
+ simulateRemoteMessage(roomId, "@aibot:localhost", {
1051
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
1052
+ body: "Changing first",
1053
+ format: "org.matrix.custom.html",
1054
+ isStreamingFinished: true,
1055
+ [APP_BOXEL_HAS_CONTINUATION_CONTENT_KEY]: true,
1056
+ "m.relates_to": {
1057
+ rel_type: "m.replace",
1058
+ event_id: initialEventId
1059
+ }
1060
+ });
1061
+ let continuationEventId = simulateRemoteMessage(roomId, "@aibot:localhost", {
1062
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
1063
+ body: "Changing first names",
1064
+ format: "org.matrix.custom.html",
1065
+ [APP_BOXEL_CONTINUATION_OF_CONTENT_KEY]: initialEventId,
1066
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: [{
1067
+ id: "6545dc5a-01a1-47d6-b2f7-493d2ff5a0c2",
1068
+ name: "patchCard"
1069
+ }],
1070
+ isStreamingFinished: false
1071
+ });
1072
+ await settled();
1073
+ await click("[data-test-open-ai-assistant]");
1074
+ await waitFor("[data-test-room-name=\"test room 1\"]");
1075
+ assert.dom("[data-test-message-idx]").exists({ count: 1 });
1076
+ await waitFor("[data-test-message-idx=\"0\"] [data-test-pretui-tool-row][data-state=\"streaming\"]");
1077
+ assert.dom("[data-test-message-idx=\"0\"] [data-test-pretui-tool-row][data-state=\"streaming\"]").exists();
1078
+ simulateRemoteMessage(roomId, "@aibot:localhost", {
1079
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
1080
+ body: "Changing first names",
1081
+ format: "org.matrix.custom.html",
1082
+ [APP_BOXEL_CONTINUATION_OF_CONTENT_KEY]: initialEventId,
1083
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: [{
1084
+ id: "6545dc5a-01a1-47d6-b2f7-493d2ff5a0c2",
1085
+ name: "patchCard",
1086
+ arguments: JSON.stringify({ attributes: {
1087
+ cardId: `${testRealmURL}Person/fadhlan`,
1088
+ patch: { attributes: { firstName: "Evie" } }
1089
+ } })
1090
+ }, {
1091
+ id: "f2da5504-b92f-480a-986a-56ec606d240e",
1092
+ name: "patchCard",
1093
+ arguments: JSON.stringify({ attributes: {
1094
+ cardId: `${testRealmURL}Person/hassan`,
1095
+ patch: { attributes: { firstName: "Ivana" } }
1096
+ } })
1097
+ }],
1098
+ isStreamingFinished: false,
1099
+ "m.relates_to": {
1100
+ rel_type: "m.replace",
1101
+ event_id: continuationEventId
1102
+ }
1103
+ });
1104
+ await settled();
1105
+ assert.dom("[data-test-message-idx]").exists({ count: 1 });
1106
+ await waitFor("[data-test-message-idx=\"0\"] [data-test-pretui-tool-row][data-state=\"streaming\"]");
1107
+ assert.dom("[data-test-message-idx=\"0\"] [data-test-pretui-tool-row][data-state=\"streaming\"]").exists({ count: 2 }, "each call still arriving is a streaming row");
1108
+ simulateRemoteMessage(roomId, "@aibot:localhost", {
1109
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
1110
+ body: "Changing first names",
1111
+ format: "org.matrix.custom.html",
1112
+ [APP_BOXEL_CONTINUATION_OF_CONTENT_KEY]: initialEventId,
1113
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: [{
1114
+ id: "6545dc5a-01a1-47d6-b2f7-493d2ff5a0c2",
1115
+ name: "patchCard",
1116
+ arguments: JSON.stringify({ attributes: {
1117
+ cardId: `${testRealmURL}Person/fadhlan`,
1118
+ patch: { attributes: { firstName: "Evie" } }
1119
+ } })
1120
+ }, {
1121
+ id: "f2da5504-b92f-480a-986a-56ec606d240e",
1122
+ name: "patchCard",
1123
+ arguments: JSON.stringify({ attributes: {
1124
+ cardId: `${testRealmURL}Person/hassan`,
1125
+ patch: { attributes: { firstName: "Ivana" } }
1126
+ } })
1127
+ }],
1128
+ isStreamingFinished: true,
1129
+ "m.relates_to": {
1130
+ rel_type: "m.replace",
1131
+ event_id: continuationEventId
1132
+ }
1133
+ });
1134
+ await settled();
1135
+ assert.dom("[data-test-message-idx]").exists({ count: 1 });
1136
+ await waitFor("[data-test-message-idx=\"0\"] [data-test-tool-call-apply]");
1137
+ assert.dom("[data-test-message-idx=\"0\"] [data-test-pretui-tool-row][data-state=\"streaming\"]").doesNotExist("every call has arrived");
1138
+ assert.dom("[data-test-message-idx=\"0\"] [data-test-tool-call-apply=\"ready\"]").exists({ count: 2 });
1139
+ });
1140
+ (0, import_qunit.skip)("command that returns a FileForAttachmentCard result is specially handled to attach the file", async function(assert) {
1141
+ setCardInOperatorModeState(`${testRealmURL}Person/fadhlan`);
1142
+ await renderComponent(class TestDriver extends Component {
1143
+ static {
1144
+ setComponentTemplate(templateFactory({
1145
+ "id": "hk0qKyFP",
1146
+ "block": "[[[8,[32,0],null,[[\"@onClose\"],[[32,1]]],null]],[],[]]",
1147
+ "moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/components/ai-assistant-panel/tools-test.gts",
1148
+ "scope": () => [OperatorModeContainer, noop],
1149
+ "isStrictMode": true
1150
+ }), this);
1151
+ }
1152
+ });
1153
+ await waitFor("[data-test-person=\"Fadhlan\"]");
1154
+ let roomId = createAndJoinRoom({
1155
+ sender: "@testuser:localhost",
1156
+ name: "test room 1"
1157
+ });
1158
+ await settled();
1159
+ await click("[data-test-open-ai-assistant]");
1160
+ await waitFor("[data-test-room-name=\"test room 1\"]", { timeout: 1e4 });
1161
+ await addSkillToAiAssistant(`${testRealmURL}Skill/boxel-environment`);
1162
+ simulateRemoteMessage(roomId, "@aibot:localhost", {
1163
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
1164
+ body: "Reading hello file",
1165
+ format: "org.matrix.custom.html",
1166
+ isStreamingFinished: true,
1167
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: [{
1168
+ id: "0ce51dc1-c819-4d6d-9f4f-77fbf60e9a0a",
1169
+ name: "read-file-for-ai-assistant_a831",
1170
+ arguments: JSON.stringify({ attributes: { fileIdentifier: `${testRealmURL}hello.txt` } })
1171
+ }]
1172
+ });
1173
+ let commandResultEvents = getRoomEvents(roomId).filter((event) => event.type === "app.boxel.toolResult" && event.content["m.relates_to"]?.rel_type === "app.boxel.toolAnnotation" && event.content["m.relates_to"]?.key === "applied");
1174
+ assert.strictEqual(commandResultEvents.length, 0, "command result event is not dispatched");
1175
+ await settled();
1176
+ await waitFor("[data-test-message-idx=\"0\"] [data-test-tool-call-apply]");
1177
+ await click("[data-test-message-idx=\"0\"] [data-test-pretui-tool-gate-action=\"apply\"]");
1178
+ await waitFor("[data-test-tool-call-card-idle]");
1179
+ assert.dom("[data-test-message-idx=\"0\"] [data-test-tool-call-apply=\"applied\"]").exists();
1180
+ commandResultEvents = getRoomEvents(roomId).filter((event) => event.type === "app.boxel.toolResult" && event.content["m.relates_to"]?.rel_type === "app.boxel.toolAnnotation" && event.content["m.relates_to"]?.key === "applied");
1181
+ assert.strictEqual(commandResultEvents.length, 1, "command result event is dispatched");
1182
+ assert.deepEqual(JSON.parse(commandResultEvents[0].content.data).attachedFiles.length, 1, "command result event contains an attached file");
1183
+ assert.deepEqual(JSON.parse(commandResultEvents[0].content.data).attachedFiles[0].name, "hello.txt", "command result event contains attached file");
1184
+ assert.deepEqual(JSON.parse(commandResultEvents[0].content.data).attachedFiles[0].sourceUrl, "http://test-realm/test/hello.txt", "command result event contains file whose url was reference in the input of the command as an attached file");
1185
+ });
1186
+ (0, import_qunit.skip)("command that returns a CardForAttachmentCard result is specially handled to attach the card", async function(assert) {
1187
+ setCardInOperatorModeState(`${testRealmURL}Person/fadhlan`);
1188
+ await renderComponent(class TestDriver extends Component {
1189
+ static {
1190
+ setComponentTemplate(templateFactory({
1191
+ "id": "hk0qKyFP",
1192
+ "block": "[[[8,[32,0],null,[[\"@onClose\"],[[32,1]]],null]],[],[]]",
1193
+ "moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/components/ai-assistant-panel/tools-test.gts",
1194
+ "scope": () => [OperatorModeContainer, noop],
1195
+ "isStrictMode": true
1196
+ }), this);
1197
+ }
1198
+ });
1199
+ await waitFor("[data-test-person=\"Fadhlan\"]");
1200
+ let roomId = createAndJoinRoom({
1201
+ sender: "@testuser:localhost",
1202
+ name: "test room 1"
1203
+ });
1204
+ await settled();
1205
+ await click("[data-test-open-ai-assistant]");
1206
+ await waitFor("[data-test-room-name=\"test room 1\"]", { timeout: 1e4 });
1207
+ await addSkillToAiAssistant(`${testRealmURL}Skill/boxel-environment`);
1208
+ simulateRemoteMessage(roomId, "@aibot:localhost", {
1209
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
1210
+ body: "Reading card",
1211
+ format: "org.matrix.custom.html",
1212
+ isStreamingFinished: true,
1213
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: [{
1214
+ id: "1ef9a66a-2201-4874-a156-9705acb1ac13",
1215
+ name: "read-card-for-ai-assistant_dd38",
1216
+ arguments: JSON.stringify({ attributes: { cardId: `${testRealmURL}Pet/mango` } })
1217
+ }]
1218
+ });
1219
+ let commandResultEvents = getRoomEvents(roomId).filter((event) => event.type === "app.boxel.toolResult" && event.content["m.relates_to"]?.rel_type === "app.boxel.toolAnnotation" && event.content["m.relates_to"]?.key === "applied");
1220
+ assert.strictEqual(commandResultEvents.length, 0, "command result event is not dispatched");
1221
+ await settled();
1222
+ await waitFor("[data-test-message-idx=\"0\"] [data-test-tool-call-apply]");
1223
+ await click("[data-test-message-idx=\"0\"] [data-test-pretui-tool-gate-action=\"apply\"]");
1224
+ await waitFor("[data-test-tool-call-card-idle]");
1225
+ assert.dom("[data-test-message-idx=\"0\"] [data-test-tool-call-apply=\"applied\"]").exists();
1226
+ commandResultEvents = getRoomEvents(roomId).filter((event) => event.type === "app.boxel.toolResult" && event.content["m.relates_to"]?.rel_type === "app.boxel.toolAnnotation" && event.content["m.relates_to"]?.key === "applied");
1227
+ assert.strictEqual(commandResultEvents.length, 1, "command result event is dispatched");
1228
+ assert.deepEqual(JSON.parse(commandResultEvents[0].content.data).attachedCards.length, 1, "command result event contains an attached file");
1229
+ assert.deepEqual(JSON.parse(commandResultEvents[0].content.data).attachedCards[0].name, "Mango", "command result event contains attached card");
1230
+ assert.deepEqual(JSON.parse(commandResultEvents[0].content.data).attachedCards[0].sourceUrl, "http://test-realm/test/Pet/mango", "command result event contains file whose url was reference in the input of the command as an attached file");
1231
+ });
1232
+ (0, import_qunit.test)("commandResult event_id is sourced from current room state, not a streaming snapshot", async function(assert) {
1233
+ setCardInOperatorModeState(`${testRealmURL}Person/fadhlan`);
1234
+ await renderComponent(class TestDriver extends Component {
1235
+ static {
1236
+ setComponentTemplate(templateFactory({
1237
+ "id": "hk0qKyFP",
1238
+ "block": "[[[8,[32,0],null,[[\"@onClose\"],[[32,1]]],null]],[],[]]",
1239
+ "moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/components/ai-assistant-panel/tools-test.gts",
1240
+ "scope": () => [OperatorModeContainer, noop],
1241
+ "isStrictMode": true
1242
+ }), this);
1243
+ }
1244
+ });
1245
+ await waitFor("[data-test-person=\"Fadhlan\"]");
1246
+ let roomId = createAndJoinRoom({
1247
+ sender: "@testuser:localhost",
1248
+ name: "test room 1"
1249
+ });
1250
+ let commandRequestId = "cmd-request-id";
1251
+ let streamingEventId = simulateRemoteMessage(roomId, "@aibot:localhost", {
1252
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
1253
+ body: "Changing",
1254
+ format: "org.matrix.custom.html",
1255
+ isStreamingFinished: false
1256
+ });
1257
+ let replacedEventId = simulateRemoteMessage(roomId, "@aibot:localhost", {
1258
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
1259
+ body: "Changing first name to Evie",
1260
+ format: "org.matrix.custom.html",
1261
+ isStreamingFinished: true,
1262
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: [{
1263
+ id: commandRequestId,
1264
+ name: "patchCardInstance",
1265
+ arguments: JSON.stringify({ attributes: {
1266
+ cardId: `${testRealmURL}Person/fadhlan`,
1267
+ patch: { attributes: { firstName: "Evie" } }
1268
+ } })
1269
+ }],
1270
+ "m.relates_to": {
1271
+ rel_type: "m.replace",
1272
+ event_id: streamingEventId
1273
+ }
1274
+ });
1275
+ await settled();
1276
+ await click("[data-test-open-ai-assistant]");
1277
+ await waitFor("[data-test-room-name=\"test room 1\"]");
1278
+ await waitFor("[data-test-message-idx=\"0\"] [data-test-tool-call-apply]");
1279
+ await click("[data-test-message-idx=\"0\"] [data-test-pretui-tool-gate-action=\"apply\"]");
1280
+ await waitFor("[data-test-tool-call-card-idle]");
1281
+ assert.dom("[data-test-message-idx=\"0\"] [data-test-tool-call-apply=\"applied\"]").exists("MessageTool status should flip to applied even though commandResult.m.relates_to.event_id is the m.replace id, not the streaming id the cache is keyed by");
1282
+ let commandResultEvents = getRoomEvents(roomId).filter((event) => event.type === "app.boxel.toolResult" && event.content["m.relates_to"]?.rel_type === "app.boxel.toolAnnotation");
1283
+ assert.strictEqual(commandResultEvents.length, 1, "exactly one commandResult should be dispatched");
1284
+ assert.strictEqual(commandResultEvents[0].content["m.relates_to"]?.event_id, replacedEventId, "commandResult.m.relates_to.event_id should be the bot message event_id currently in room.events that owns the toolRequest, not a stale snapshot of the streaming/original id");
1285
+ assert.notStrictEqual(commandResultEvents[0].content["m.relates_to"]?.event_id, streamingEventId, "commandResult should not reference the original/streaming event_id once a later event in room.events owns the toolRequest");
1286
+ });
1287
+ (0, import_qunit.test)("an applied command on a streamed bot message still renders applied after reload (m.replace edits stripped)", async function(assert) {
1288
+ setCardInOperatorModeState(`${testRealmURL}Person/fadhlan`);
1289
+ await renderComponent(class TestDriver extends Component {
1290
+ static {
1291
+ setComponentTemplate(templateFactory({
1292
+ "id": "hk0qKyFP",
1293
+ "block": "[[[8,[32,0],null,[[\"@onClose\"],[[32,1]]],null]],[],[]]",
1294
+ "moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/components/ai-assistant-panel/tools-test.gts",
1295
+ "scope": () => [OperatorModeContainer, noop],
1296
+ "isStrictMode": true
1297
+ }), this);
1298
+ }
1299
+ });
1300
+ await waitFor("[data-test-person=\"Fadhlan\"]");
1301
+ let roomId = createAndJoinRoom({
1302
+ sender: "@testuser:localhost",
1303
+ name: "test room 1"
1304
+ });
1305
+ let commandRequestId = "cmd-request-id";
1306
+ let strippedEditEventId = "stripped-edit-event-id";
1307
+ simulateRemoteMessage(roomId, "@aibot:localhost", {
1308
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
1309
+ body: "Changing first name to Evie",
1310
+ format: "org.matrix.custom.html",
1311
+ isStreamingFinished: true,
1312
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: [{
1313
+ id: commandRequestId,
1314
+ name: "patchCardInstance",
1315
+ arguments: JSON.stringify({ attributes: {
1316
+ cardId: `${testRealmURL}Person/fadhlan`,
1317
+ patch: { attributes: { firstName: "Evie" } }
1318
+ } })
1319
+ }]
1320
+ });
1321
+ simulateRemoteMessage(roomId, "@aibot:localhost", {
1322
+ msgtype: APP_BOXEL_TOOL_RESULT_WITH_NO_OUTPUT_MSGTYPE,
1323
+ commandRequestId,
1324
+ "m.relates_to": {
1325
+ rel_type: APP_BOXEL_TOOL_RESULT_REL_TYPE,
1326
+ key: "applied",
1327
+ event_id: strippedEditEventId
1328
+ },
1329
+ data: {}
1330
+ }, { type: APP_BOXEL_TOOL_RESULT_EVENT_TYPE });
1331
+ await settled();
1332
+ await click("[data-test-open-ai-assistant]");
1333
+ await waitFor("[data-test-room-name=\"test room 1\"]");
1334
+ await waitFor("[data-test-message-idx=\"0\"]");
1335
+ assert.dom("[data-test-message-idx=\"0\"] [data-test-tool-call-apply=\"applied\"]").exists("a command applied before reload still renders applied even though its commandResult links to a stripped m.replace edit id; correlation is by commandRequestId, not the dangling event_id");
1336
+ });
1337
+ (0, import_qunit.test)("an applied commandResult flips only its own bot message, not a sibling message that also carries a command", async function(assert) {
1338
+ setCardInOperatorModeState(`${testRealmURL}Person/fadhlan`);
1339
+ await renderComponent(class TestDriver extends Component {
1340
+ static {
1341
+ setComponentTemplate(templateFactory({
1342
+ "id": "hk0qKyFP",
1343
+ "block": "[[[8,[32,0],null,[[\"@onClose\"],[[32,1]]],null]],[],[]]",
1344
+ "moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/components/ai-assistant-panel/tools-test.gts",
1345
+ "scope": () => [OperatorModeContainer, noop],
1346
+ "isStrictMode": true
1347
+ }), this);
1348
+ }
1349
+ });
1350
+ await waitFor("[data-test-person=\"Fadhlan\"]");
1351
+ let roomId = createAndJoinRoom({
1352
+ sender: "@testuser:localhost",
1353
+ name: "test room 1"
1354
+ });
1355
+ let firstCommandRequestId = "first-cmd-request-id";
1356
+ let secondCommandRequestId = "second-cmd-request-id";
1357
+ let strippedEditEventId = "stripped-edit-event-id";
1358
+ simulateRemoteMessage(roomId, "@aibot:localhost", {
1359
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
1360
+ body: "Changing first name to Evie",
1361
+ format: "org.matrix.custom.html",
1362
+ isStreamingFinished: true,
1363
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: [{
1364
+ id: firstCommandRequestId,
1365
+ name: "patchCardInstance",
1366
+ arguments: JSON.stringify({ attributes: {
1367
+ cardId: `${testRealmURL}Person/fadhlan`,
1368
+ patch: { attributes: { firstName: "Evie" } }
1369
+ } })
1370
+ }]
1371
+ });
1372
+ simulateRemoteMessage(roomId, "@aibot:localhost", {
1373
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
1374
+ body: "Changing first name to Mango",
1375
+ format: "org.matrix.custom.html",
1376
+ isStreamingFinished: true,
1377
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: [{
1378
+ id: secondCommandRequestId,
1379
+ name: "patchCardInstance",
1380
+ arguments: JSON.stringify({ attributes: {
1381
+ cardId: `${testRealmURL}Person/fadhlan`,
1382
+ patch: { attributes: { firstName: "Mango" } }
1383
+ } })
1384
+ }]
1385
+ });
1386
+ simulateRemoteMessage(roomId, "@aibot:localhost", {
1387
+ msgtype: APP_BOXEL_TOOL_RESULT_WITH_NO_OUTPUT_MSGTYPE,
1388
+ commandRequestId: secondCommandRequestId,
1389
+ "m.relates_to": {
1390
+ rel_type: APP_BOXEL_TOOL_RESULT_REL_TYPE,
1391
+ key: "applied",
1392
+ event_id: strippedEditEventId
1393
+ },
1394
+ data: {}
1395
+ }, { type: APP_BOXEL_TOOL_RESULT_EVENT_TYPE });
1396
+ await settled();
1397
+ await click("[data-test-open-ai-assistant]");
1398
+ await waitFor("[data-test-room-name=\"test room 1\"]");
1399
+ await waitFor("[data-test-message-idx=\"1\"]");
1400
+ assert.dom("[data-test-message-idx=\"1\"] [data-test-tool-call-apply=\"applied\"]").exists("the bot message whose commandRequestId owns the applied result renders applied");
1401
+ assert.dom("[data-test-message-idx=\"0\"] [data-test-tool-call-apply=\"ready\"]").exists("the sibling bot message, which has no result of its own, stays ready — the applied status did not bleed across messages");
1402
+ });
1403
+ (0, import_qunit.test)("Accept All bar does not flash for an always-auto-executed command (checkCorrectness)", async function(assert) {
1404
+ simulateRemoteMessage(await renderAiAssistantPanel(), "@aibot:localhost", {
1405
+ body: "checking correctness",
1406
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
1407
+ format: "org.matrix.custom.html",
1408
+ isStreamingFinished: true,
1409
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: [{
1410
+ id: "cs-11647-check-correctness",
1411
+ name: "checkCorrectness",
1412
+ arguments: "{}"
1413
+ }],
1414
+ data: { context: { agentId: getService("matrix-service").agentId } }
1415
+ });
1416
+ await waitFor("[data-test-message-idx=\"0\"]");
1417
+ assert.dom("[data-test-accept-all]").doesNotExist("Accept All button must not paint in the debounce window before auto-execute starts");
1418
+ await settled();
1419
+ assert.dom("[data-test-accept-all]").doesNotExist("Accept All button still hidden after the auto-execute debounce window elapses");
1420
+ });
1421
+ (0, import_qunit.test)("Accept All bar does not flash for a requiresApproval=false command", async function(assert) {
1422
+ setCardInOperatorModeState(`${testRealmURL}Person/fadhlan`);
1423
+ await renderComponent(class TestDriver extends Component {
1424
+ static {
1425
+ setComponentTemplate(templateFactory({
1426
+ "id": "hk0qKyFP",
1427
+ "block": "[[[8,[32,0],null,[[\"@onClose\"],[[32,1]]],null]],[],[]]",
1428
+ "moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/components/ai-assistant-panel/tools-test.gts",
1429
+ "scope": () => [OperatorModeContainer, noop],
1430
+ "isStrictMode": true
1431
+ }), this);
1432
+ }
1433
+ });
1434
+ await waitFor("[data-test-person=\"Fadhlan\"]");
1435
+ createAndJoinRoom({
1436
+ sender: "@testuser:localhost",
1437
+ name: "auto-exec via skill"
1438
+ });
1439
+ await settled();
1440
+ await click("[data-test-open-ai-assistant]");
1441
+ await waitFor("[data-test-room-name=\"auto-exec via skill\"]", { timeout: 1e4 });
1442
+ await addSkillToAiAssistant(`${testRealmURL}Skill/boxel-environment`);
1443
+ simulateRemoteMessage(document.querySelector("[data-test-room]").getAttribute("data-test-room"), "@aibot:localhost", {
1444
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
1445
+ body: "Reading hello file",
1446
+ format: "org.matrix.custom.html",
1447
+ isStreamingFinished: true,
1448
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: [{
1449
+ id: "cs-11647-no-approval",
1450
+ name: "read-file-for-ai-assistant_a831",
1451
+ arguments: JSON.stringify({ attributes: { fileIdentifier: `${testRealmURL}hello.txt` } })
1452
+ }],
1453
+ data: { context: { agentId: getService("matrix-service").agentId } }
1454
+ });
1455
+ await waitFor("[data-test-message-idx=\"0\"]");
1456
+ assert.dom("[data-test-accept-all]").doesNotExist("Accept All button suppressed for requiresApproval=false commands");
1457
+ });
1458
+ (0, import_qunit.test)("per-command Apply button does not flash Run before auto-execute starts", async function(assert) {
1459
+ simulateRemoteMessage(await renderAiAssistantPanel(), "@aibot:localhost", {
1460
+ body: "checking correctness",
1461
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
1462
+ format: "org.matrix.custom.html",
1463
+ isStreamingFinished: true,
1464
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: [{
1465
+ id: "cs-11647-apply-button",
1466
+ name: "checkCorrectness",
1467
+ arguments: "{}"
1468
+ }],
1469
+ data: { context: { agentId: getService("matrix-service").agentId } }
1470
+ });
1471
+ await waitFor("[data-test-message-idx=\"0\"] [data-test-tool-call-apply]");
1472
+ assert.dom("[data-test-message-idx=\"0\"] [data-test-tool-call-apply=\"ready\"]").doesNotExist("per-command Apply button must not show the ready/Run state for an auto-executed command");
1473
+ assert.dom("[data-test-message-idx=\"0\"] [data-test-tool-call-apply=\"applying\"]").exists("per-command Apply button shows the applying spinner instead");
1474
+ assert.dom("[data-test-message-idx=\"0\"] [data-test-tool-call-card-idle]").doesNotExist("data-test-tool-call-card-idle agrees with applyButtonState while the synthetic spinner is on");
1475
+ });
1476
+ (0, import_qunit.test)("stuck-processing helper dispatches an invalid commandResult for each auto-executable command", async function(assert) {
1477
+ let roomId = await renderAiAssistantPanel();
1478
+ let matrixService = getService("matrix-service");
1479
+ let toolService = getService("tool-service");
1480
+ simulateRemoteMessage(roomId, "@aibot:localhost", {
1481
+ body: "checking correctness",
1482
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
1483
+ format: "org.matrix.custom.html",
1484
+ isStreamingFinished: true,
1485
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: [{
1486
+ id: "cs-11647-stuck-auto",
1487
+ name: "checkCorrectness",
1488
+ arguments: "{}"
1489
+ }, {
1490
+ id: "cs-11647-stuck-manual",
1491
+ name: "patchCardInstance",
1492
+ arguments: JSON.stringify({ attributes: {
1493
+ cardId: `${testRealmURL}Person/fadhlan`,
1494
+ patch: { attributes: { firstName: "Dave" } }
1495
+ } })
1496
+ }],
1497
+ data: { context: { agentId: matrixService.agentId } }
1498
+ });
1499
+ await waitFor("[data-test-message-idx=\"0\"] [data-test-tool-call-apply]");
1500
+ let roomResource = matrixService.roomResources.get(roomId);
1501
+ let message = roomResource.messages.find((m) => m.tools?.length === 2);
1502
+ assert.ok(message, "two-command bot message lands in the room resource");
1503
+ let captured = [];
1504
+ let originalSend = matrixService.sendToolResultEvent.bind(matrixService);
1505
+ matrixService.sendToolResultEvent = async (params) => {
1506
+ captured.push({
1507
+ toolCallId: params.toolCallId,
1508
+ failureReason: params.failureReason
1509
+ });
1510
+ };
1511
+ try {
1512
+ await toolService.invalidateAutoExecutableToolsForStuckProcessing(roomResource, roomId, message.eventId);
1513
+ } finally {
1514
+ matrixService.sendToolResultEvent = originalSend;
1515
+ }
1516
+ assert.strictEqual(captured.length, 1, "only the auto-executable command is invalidated; manual-approval command is left in ready");
1517
+ assert.strictEqual(captured[0]?.toolCallId, "cs-11647-stuck-auto", "the dispatched invalid event targets the auto-executable command");
1518
+ assert.true((captured[0]?.failureReason ?? "").startsWith("Room processing did not finish within"), "failureReason surfaces the stuck-processing cause for the invalidToolCallState alert");
1519
+ });
1520
+ (0, import_qunit.test)("an invalid result is terminal for auto-execution: a later drain pass does not re-resolve the request", async function(assert) {
1521
+ let roomId = await renderAiAssistantPanel();
1522
+ let matrixService = getService("matrix-service");
1523
+ let toolService = getService("tool-service");
1524
+ let captured = [];
1525
+ let originalSend = matrixService.sendToolResultEvent.bind(matrixService);
1526
+ matrixService.sendToolResultEvent = async (params) => {
1527
+ captured.push({
1528
+ toolCallId: params.toolCallId,
1529
+ status: params.status
1530
+ });
1531
+ };
1532
+ try {
1533
+ let eventId = simulateRemoteMessage(roomId, "@aibot:localhost", {
1534
+ body: "Do the thing",
1535
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
1536
+ format: "org.matrix.custom.html",
1537
+ isStreamingFinished: true,
1538
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: [{
1539
+ id: "cs-12103-invalid-terminal",
1540
+ name: "no-such-command",
1541
+ arguments: JSON.stringify({
1542
+ description: "do it",
1543
+ attributes: {}
1544
+ })
1545
+ }],
1546
+ data: { context: { agentId: matrixService.agentId } }
1547
+ });
1548
+ await settled();
1549
+ assert.deepEqual(captured, [{
1550
+ toolCallId: "cs-12103-invalid-terminal",
1551
+ status: "invalid"
1552
+ }], "validation resolves the request invalid exactly once");
1553
+ assert.true(toolService.claimedToolRequestIds.has("cs-12103-invalid-terminal"), "the terminal resolution is recorded locally, not just in the (still in-flight) result event");
1554
+ toolService.queueEventForToolProcessing({
1555
+ event_id: eventId,
1556
+ room_id: roomId,
1557
+ content: {}
1558
+ });
1559
+ await settled();
1560
+ assert.strictEqual(captured.length, 1, "the resolved request gets no second result and is not executed");
1561
+ } finally {
1562
+ matrixService.sendToolResultEvent = originalSend;
1563
+ }
1564
+ });
1565
+ (0, import_qunit.test)("overlapping drain passes resolve a tool request exactly once", async function(assert) {
1566
+ let roomId = await renderAiAssistantPanel();
1567
+ let matrixService = getService("matrix-service");
1568
+ let toolService = getService("tool-service");
1569
+ let captured = [];
1570
+ let originalSend = matrixService.sendToolResultEvent.bind(matrixService);
1571
+ matrixService.sendToolResultEvent = async (params) => {
1572
+ captured.push({
1573
+ toolCallId: params.toolCallId,
1574
+ status: params.status
1575
+ });
1576
+ };
1577
+ let overlapAgentId = "overlap-test-agent";
1578
+ let originalAgentId = matrixService.agentId;
1579
+ try {
1580
+ let eventId = simulateRemoteMessage(roomId, "@aibot:localhost", {
1581
+ body: "Do the thing",
1582
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
1583
+ format: "org.matrix.custom.html",
1584
+ isStreamingFinished: true,
1585
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: [{
1586
+ id: "overlap-victim",
1587
+ name: "checkCorrectness",
1588
+ arguments: "not parseable json, so validation resolves invalid"
1589
+ }],
1590
+ data: { context: { agentId: overlapAgentId } }
1591
+ });
1592
+ await settled();
1593
+ assert.strictEqual(captured.length, 0, "the not-our-agent message is left unresolved by the timeline drain");
1594
+ matrixService.agentId = overlapAgentId;
1595
+ let svc = toolService;
1596
+ svc.toolProcessingEventQueue.push(`${roomId}|${eventId}`);
1597
+ let firstPass = svc.drainToolProcessingQueue();
1598
+ await Promise.resolve();
1599
+ svc.flushToolProcessingQueue = void 0;
1600
+ svc.toolProcessingEventQueue.push(`${roomId}|${eventId}`);
1601
+ let secondPass = svc.drainToolProcessingQueue();
1602
+ await Promise.all([firstPass, secondPass]);
1603
+ await settled();
1604
+ assert.deepEqual(captured, [{
1605
+ toolCallId: "overlap-victim",
1606
+ status: "invalid"
1607
+ }], "the request gets exactly one terminal result across both passes");
1608
+ } finally {
1609
+ matrixService.agentId = originalAgentId;
1610
+ matrixService.sendToolResultEvent = originalSend;
1611
+ }
1612
+ });
1613
+ const discoveredSkillUrl = `${testRealmURL}Skill/boxel-environment`;
1614
+ const discoveredHostToolName = buildToolFunctionNameFromResolvedRef({
1615
+ module: "@cardstack/boxel-host/commands/read-file-for-ai-assistant",
1616
+ name: "default"
1617
+ });
1618
+ function simulateDiscoveredToolResult(roomId) {
1619
+ simulateRemoteMessage(roomId, "@aibot:localhost", {
1620
+ msgtype: APP_BOXEL_TOOL_RESULT_WITH_OUTPUT_MSGTYPE,
1621
+ commandRequestId: "earlier-skill-read",
1622
+ "m.relates_to": {
1623
+ rel_type: APP_BOXEL_TOOL_RESULT_REL_TYPE,
1624
+ key: "applied",
1625
+ event_id: "earlier-bot-message"
1626
+ },
1627
+ data: {
1628
+ attachedFiles: [],
1629
+ discoveredTools: [{
1630
+ sourceSkillUrl: discoveredSkillUrl,
1631
+ codeRef: {
1632
+ module: "@cardstack/boxel-host/commands/read-file-for-ai-assistant",
1633
+ name: "default"
1634
+ },
1635
+ functionName: discoveredHostToolName,
1636
+ requiresApproval: false,
1637
+ definition: {
1638
+ type: "function",
1639
+ function: {
1640
+ name: discoveredHostToolName,
1641
+ description: "Read a file",
1642
+ parameters: {
1643
+ type: "object",
1644
+ properties: {}
1645
+ }
1646
+ }
1647
+ }
1648
+ }]
1649
+ }
1650
+ }, { type: APP_BOXEL_TOOL_RESULT_EVENT_TYPE });
1651
+ }
1652
+ async function seedDiscoveredHostToolTurn(roomId) {
1653
+ let agentId = getService("matrix-service").agentId;
1654
+ simulateDiscoveredToolResult(roomId);
1655
+ let streamingEventId = simulateRemoteMessage(roomId, "@aibot:localhost", {
1656
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
1657
+ body: "Reading",
1658
+ format: "org.matrix.custom.html",
1659
+ isStreamingFinished: false,
1660
+ data: { context: { agentId } }
1661
+ });
1662
+ await settled();
1663
+ return streamingEventId;
1664
+ }
1665
+ function holdDiscoveredSkillLoads() {
1666
+ let store = getService("store");
1667
+ let toolService = getService("tool-service");
1668
+ let originalValidateTimeoutMs = toolService.validateTimeoutMs;
1669
+ toolService.validateTimeoutMs = 6e4;
1670
+ let release = new Deferred();
1671
+ let heldLoads = 0;
1672
+ let originalGet = store.get;
1673
+ store.get = async (id, ...rest) => {
1674
+ if (id === discoveredSkillUrl) {
1675
+ heldLoads++;
1676
+ await release.promise;
1677
+ }
1678
+ return originalGet.call(store, id, ...rest);
1679
+ };
1680
+ return {
1681
+ get heldLoads() {
1682
+ return heldLoads;
1683
+ },
1684
+ async reached() {
1685
+ await waitUntil(() => heldLoads > 0, {
1686
+ timeout: 5e3,
1687
+ timeoutMessage: "the final edit never started resolving the discovered host tool (no load of its skill within 5s)"
1688
+ });
1689
+ },
1690
+ release() {
1691
+ release.fulfill();
1692
+ store.get = originalGet;
1693
+ toolService.validateTimeoutMs = originalValidateTimeoutMs;
1694
+ }
1695
+ };
1696
+ }
1697
+ function failDiscoveredSkillLoads() {
1698
+ let store = getService("store");
1699
+ let originalGet = store.get;
1700
+ store.get = async (id, ...rest) => {
1701
+ if (id === discoveredSkillUrl) throw new Error("simulated skill load failure");
1702
+ return originalGet.call(store, id, ...rest);
1703
+ };
1704
+ return { restore() {
1705
+ store.get = originalGet;
1706
+ } };
1707
+ }
1708
+ function failCommandModuleImport() {
1709
+ let loaderPrototype = Object.getPrototypeOf(getService("loader-service").loader);
1710
+ let originalImport = loaderPrototype.import;
1711
+ let importsRefused = 0;
1712
+ loaderPrototype.import = async function(moduleId, ...rest) {
1713
+ if (String(moduleId).includes("read-file-for-ai-assistant")) {
1714
+ importsRefused++;
1715
+ throw new Error("simulated command module load failure");
1716
+ }
1717
+ return originalImport.call(this, moduleId, ...rest);
1718
+ };
1719
+ return {
1720
+ get importsRefused() {
1721
+ return importsRefused;
1722
+ },
1723
+ restore() {
1724
+ loaderPrototype.import = originalImport;
1725
+ }
1726
+ };
1727
+ }
1728
+ function finalEditWithHostTool(streamingEventId, body, toolRequests) {
1729
+ return {
1730
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
1731
+ body,
1732
+ format: "org.matrix.custom.html",
1733
+ isStreamingFinished: true,
1734
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: [...toolRequests, {
1735
+ id: "slow-host-read",
1736
+ name: discoveredHostToolName,
1737
+ arguments: JSON.stringify({ attributes: { fileIdentifier: `${testRealmURL}hello.txt` } })
1738
+ }],
1739
+ "m.relates_to": {
1740
+ rel_type: "m.replace",
1741
+ event_id: streamingEventId
1742
+ },
1743
+ data: { context: { agentId: getService("matrix-service").agentId } }
1744
+ };
1745
+ }
1746
+ async function drainIsValidating(toolCallId) {
1747
+ let toolService = getService("tool-service");
1748
+ await waitUntil(() => toolService.validationSteps.has(toolCallId), {
1749
+ timeout: 5e3,
1750
+ timeoutMessage: `the tool drain never started validating ${toolCallId}`
1751
+ });
1752
+ }
1753
+ (0, import_qunit.test)("a host tool whose resolution outlasts a room-processing restart still runs", async function(assert) {
1754
+ let roomId = await renderAiAssistantPanel();
1755
+ let streamingEventId = await seedDiscoveredHostToolTurn(roomId);
1756
+ let hold = holdDiscoveredSkillLoads();
1757
+ try {
1758
+ simulateRemoteMessage(roomId, "@aibot:localhost", finalEditWithHostTool(streamingEventId, "Reading", [{
1759
+ id: "bot-run-read",
1760
+ name: "readRealmFile",
1761
+ arguments: JSON.stringify({ path: "hello.txt" }),
1762
+ executedBy: AI_BOT_EXECUTOR
1763
+ }]));
1764
+ await hold.reached();
1765
+ simulateRemoteMessage(roomId, "@aibot:localhost", {
1766
+ msgtype: APP_BOXEL_TOOL_RESULT_WITH_NO_OUTPUT_MSGTYPE,
1767
+ commandRequestId: "bot-run-read",
1768
+ "m.relates_to": {
1769
+ rel_type: APP_BOXEL_TOOL_RESULT_REL_TYPE,
1770
+ key: "applied",
1771
+ event_id: streamingEventId
1772
+ }
1773
+ }, { type: APP_BOXEL_TOOL_RESULT_EVENT_TYPE });
1774
+ await drainIsValidating("slow-host-read");
1775
+ assert.strictEqual(hold.heldLoads, 1, "neither the restarted room pass nor the drain starts a second resolution");
1776
+ } finally {
1777
+ hold.release();
1778
+ }
1779
+ await settled();
1780
+ let hostToolResults = getRoomEvents(roomId).filter((event) => event.type === "app.boxel.toolResult" && event.content.commandRequestId === "slow-host-read");
1781
+ assert.strictEqual(hostToolResults.length, 1, "the host tool resolved after the restart is run and its result posted");
1782
+ assert.strictEqual(hostToolResults[0]?.content["m.relates_to"]?.key, "applied", `the host tool ran successfully (failure reason: ${hostToolResults[0]?.content.failureReason ?? "none"})`);
1783
+ assert.dom("[data-test-tool-call-apply=\"applying\"]").doesNotExist("no tool is left spinning in the applying state");
1784
+ });
1785
+ (0, import_qunit.test)("a response-stream preview that arrives while the final edit resolves its tools does not overwrite it", async function(assert) {
1786
+ let roomId = await renderAiAssistantPanel();
1787
+ let streamingEventId = await seedDiscoveredHostToolTurn(roomId);
1788
+ let matrixService = getService("matrix-service");
1789
+ let hold = holdDiscoveredSkillLoads();
1790
+ try {
1791
+ simulateRemoteMessage(roomId, "@aibot:localhost", finalEditWithHostTool(streamingEventId, "The final answer.", []));
1792
+ await hold.reached();
1793
+ simulateToDeviceEvent(APP_BOXEL_RESPONSE_STREAM_EVENT_TYPE, {
1794
+ roomId,
1795
+ parentEventId: streamingEventId,
1796
+ sequence: 99,
1797
+ body: "A stale preview.",
1798
+ reasoning: "",
1799
+ toolRequests: []
1800
+ }, matrixService.aiBotUserId);
1801
+ await delay(100);
1802
+ } finally {
1803
+ hold.release();
1804
+ }
1805
+ await settled();
1806
+ let message = matrixService.roomResources.get(roomId).messageForEventId(streamingEventId);
1807
+ assert.strictEqual(message.body, "The final answer.", "the final edit keeps its body");
1808
+ assert.true(message.isStreamingFinished, "the message stays finished");
1809
+ assert.dom(`[data-test-room="${roomId}"]`).doesNotContainText("A stale preview.");
1810
+ });
1811
+ (0, import_qunit.test)("a host tool whose command never resolves gets a terminal invalid result and the room keeps processing", async function(assert) {
1812
+ let roomId = await renderAiAssistantPanel();
1813
+ let streamingEventId = await seedDiscoveredHostToolTurn(roomId);
1814
+ let fail = failDiscoveredSkillLoads();
1815
+ try {
1816
+ simulateRemoteMessage(roomId, "@aibot:localhost", finalEditWithHostTool(streamingEventId, "Reading", []));
1817
+ await settled();
1818
+ } finally {
1819
+ fail.restore();
1820
+ }
1821
+ await settled();
1822
+ let hostToolResults = getRoomEvents(roomId).filter((event) => event.type === "app.boxel.toolResult" && event.content.commandRequestId === "slow-host-read");
1823
+ assert.strictEqual(hostToolResults.length, 1, "exactly one terminal result is posted for the request that never resolved");
1824
+ assert.strictEqual(hostToolResults[0]?.content["m.relates_to"]?.key, "invalid", "the unresolvable tool is reported invalid");
1825
+ assert.dom("[data-test-tool-call-apply=\"applying\"]").doesNotExist("no tool is left spinning in the applying state");
1826
+ simulateRemoteMessage(roomId, "@aibot:localhost", {
1827
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
1828
+ body: "Still alive",
1829
+ format: "org.matrix.custom.html",
1830
+ isStreamingFinished: true,
1831
+ data: { context: { agentId: getService("matrix-service").agentId } }
1832
+ });
1833
+ await settled();
1834
+ assert.dom(`[data-test-room="${roomId}"]`).containsText("Still alive", "the room keeps processing later events");
1835
+ });
1836
+ (0, import_qunit.test)("a host tool renamed by the final edit runs as the renamed tool, not the stale one", async function(assert) {
1837
+ let roomId = await renderAiAssistantPanel();
1838
+ let streamingEventId = await seedDiscoveredHostToolTurn(roomId);
1839
+ simulateRemoteMessage(roomId, "@aibot:localhost", {
1840
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
1841
+ body: "Reading",
1842
+ format: "org.matrix.custom.html",
1843
+ isStreamingFinished: false,
1844
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: [{
1845
+ id: "slow-host-read",
1846
+ name: "read-file-for"
1847
+ }],
1848
+ "m.relates_to": {
1849
+ rel_type: "m.replace",
1850
+ event_id: streamingEventId
1851
+ },
1852
+ data: { context: { agentId: getService("matrix-service").agentId } }
1853
+ });
1854
+ await settled();
1855
+ let hold = holdDiscoveredSkillLoads();
1856
+ try {
1857
+ simulateRemoteMessage(roomId, "@aibot:localhost", finalEditWithHostTool(streamingEventId, "Reading", []));
1858
+ await hold.reached();
1859
+ await drainIsValidating("slow-host-read");
1860
+ assert.strictEqual(getRoomEvents(roomId).filter((event) => event.type === "app.boxel.toolResult" && event.content.commandRequestId === "slow-host-read").length, 0, "the drain waits for the renamed tool instead of validating the stale name");
1861
+ } finally {
1862
+ hold.release();
1863
+ }
1864
+ await settled();
1865
+ let hostToolResults = getRoomEvents(roomId).filter((event) => event.type === "app.boxel.toolResult" && event.content.commandRequestId === "slow-host-read");
1866
+ assert.strictEqual(hostToolResults.length, 1, "exactly one result");
1867
+ assert.strictEqual(hostToolResults[0]?.content["m.relates_to"]?.key, "applied", `the renamed tool ran (failure reason: ${hostToolResults[0]?.content.failureReason ?? "none"})`);
1868
+ });
1869
+ (0, import_qunit.test)("a call that already has a result is not answered again when its command no longer resolves", async function(assert) {
1870
+ let roomId = await renderAiAssistantPanel();
1871
+ let streamingEventId = await seedDiscoveredHostToolTurn(roomId);
1872
+ let fail = failDiscoveredSkillLoads();
1873
+ try {
1874
+ simulateRemoteMessage(roomId, "@aibot:localhost", finalEditWithHostTool(streamingEventId, "Reading", []));
1875
+ simulateRemoteMessage(roomId, "@testuser:localhost", {
1876
+ msgtype: APP_BOXEL_TOOL_RESULT_WITH_NO_OUTPUT_MSGTYPE,
1877
+ commandRequestId: "slow-host-read",
1878
+ "m.relates_to": {
1879
+ rel_type: APP_BOXEL_TOOL_RESULT_REL_TYPE,
1880
+ key: "applied",
1881
+ event_id: streamingEventId
1882
+ }
1883
+ }, { type: APP_BOXEL_TOOL_RESULT_EVENT_TYPE });
1884
+ await settled();
1885
+ } finally {
1886
+ fail.restore();
1887
+ }
1888
+ let hostToolResults = getRoomEvents(roomId).filter((event) => event.type === "app.boxel.toolResult" && event.content.commandRequestId === "slow-host-read");
1889
+ assert.deepEqual(hostToolResults.map((event) => event.content["m.relates_to"]?.key), ["applied"], "only the existing result, no contradictory invalid");
1890
+ });
1891
+ (0, import_qunit.test)("a call whose command fails to load gets a terminal invalid result saying it could not be prepared", async function(assert) {
1892
+ let roomId = await renderAiAssistantPanel();
1893
+ let streamingEventId = await seedDiscoveredHostToolTurn(roomId);
1894
+ let toolService = getService("tool-service");
1895
+ let originalValidateTimeoutMs = toolService.validateTimeoutMs;
1896
+ toolService.validateTimeoutMs = 6e4;
1897
+ let fail = failCommandModuleImport();
1898
+ try {
1899
+ simulateRemoteMessage(roomId, "@aibot:localhost", finalEditWithHostTool(streamingEventId, "Reading", []));
1900
+ await settled();
1901
+ } finally {
1902
+ fail.restore();
1903
+ toolService.validateTimeoutMs = originalValidateTimeoutMs;
1904
+ }
1905
+ let hostToolResults = getRoomEvents(roomId).filter((event) => event.type === "app.boxel.toolResult" && event.content.commandRequestId === "slow-host-read");
1906
+ assert.strictEqual(hostToolResults.length, 1, "exactly one result");
1907
+ assert.strictEqual(hostToolResults[0]?.content["m.relates_to"]?.key, "invalid", "the call is reported invalid");
1908
+ assert.true(String(hostToolResults[0]?.content.failureReason).includes("could not be prepared (simulated command module load failure)"), `the reason names the load failure: ${hostToolResults[0]?.content.failureReason}`);
1909
+ assert.dom("[data-test-tool-call-apply=\"applying\"]").doesNotExist("no tool is left spinning in the applying state");
1910
+ });
1911
+ (0, import_qunit.test)("a validation that times out and then finds the call invalid leaves only the failed result", async function(assert) {
1912
+ let roomId = await renderAiAssistantPanel();
1913
+ let streamingEventId = await seedDiscoveredHostToolTurn(roomId);
1914
+ let toolService = getService("tool-service");
1915
+ let originalValidateTimeoutMs = toolService.validateTimeoutMs;
1916
+ let hold = holdDiscoveredSkillLoads();
1917
+ toolService.validateTimeoutMs = 200;
1918
+ let fail = failCommandModuleImport();
1919
+ let toolResults = () => getRoomEvents(roomId).filter((event) => event.type === "app.boxel.toolResult" && event.content.commandRequestId === "slow-host-read");
1920
+ try {
1921
+ simulateRemoteMessage(roomId, "@aibot:localhost", finalEditWithHostTool(streamingEventId, "Reading", []));
1922
+ await hold.reached();
1923
+ await waitUntil(() => toolResults().length > 0, {
1924
+ timeout: 5e3,
1925
+ timeoutMessage: "the drain never reported the validation timeout"
1926
+ });
1927
+ } finally {
1928
+ hold.release();
1929
+ }
1930
+ try {
1931
+ await waitUntil(() => toolService.validationsInFlight === 0, {
1932
+ timeout: 1e4,
1933
+ timeoutMessage: "the timed-out validation never finished"
1934
+ });
1935
+ await settled();
1936
+ } finally {
1937
+ fail.restore();
1938
+ toolService.validateTimeoutMs = originalValidateTimeoutMs;
1939
+ }
1940
+ assert.true(fail.importsRefused > 0, "the timed-out validation went on to the command module import");
1941
+ assert.deepEqual(toolResults().map((event) => event.content["m.relates_to"]?.key), ["failed"], "only the timeout result, no contradictory invalid");
1942
+ });
1943
+ (0, import_qunit.test)("a call whose invalid result cannot be sent still gets a failed result", async function(assert) {
1944
+ let roomId = await renderAiAssistantPanel();
1945
+ let streamingEventId = await seedDiscoveredHostToolTurn(roomId);
1946
+ let toolService = getService("tool-service");
1947
+ let originalValidateTimeoutMs = toolService.validateTimeoutMs;
1948
+ toolService.validateTimeoutMs = 6e4;
1949
+ let matrixService = getService("matrix-service");
1950
+ let originalSend = matrixService.sendToolResultEvent;
1951
+ let refusedSends = 0;
1952
+ matrixService.sendToolResultEvent = async function(params, ...rest) {
1953
+ if (params.status === "invalid") {
1954
+ refusedSends++;
1955
+ throw new Error("simulated invalid result send failure");
1956
+ }
1957
+ return originalSend.call(matrixService, params, ...rest);
1958
+ };
1959
+ let fail = failCommandModuleImport();
1960
+ try {
1961
+ simulateRemoteMessage(roomId, "@aibot:localhost", finalEditWithHostTool(streamingEventId, "Reading", []));
1962
+ await settled();
1963
+ } finally {
1964
+ fail.restore();
1965
+ matrixService.sendToolResultEvent = originalSend;
1966
+ toolService.validateTimeoutMs = originalValidateTimeoutMs;
1967
+ }
1968
+ let hostToolResults = getRoomEvents(roomId).filter((event) => event.type === "app.boxel.toolResult" && event.content.commandRequestId === "slow-host-read");
1969
+ assert.strictEqual(refusedSends, 1, "the invalid result was refused");
1970
+ assert.deepEqual(hostToolResults.map((event) => event.content["m.relates_to"]?.key), ["failed"], "the call still gets a terminal result");
1971
+ let failureReason = String(hostToolResults[0]?.content.failureReason);
1972
+ assert.true(failureReason.includes("could not be prepared (simulated command module load failure)"), `the reason still says why the call was invalid: ${failureReason}`);
1973
+ assert.true(failureReason.includes("simulated invalid result send failure"), `the reason names the send failure: ${failureReason}`);
1974
+ });
1975
+ (0, import_qunit.test)("another agent's call that first resolved to no command is resolved again when its request finishes", async function(assert) {
1976
+ let roomId = await renderAiAssistantPanel();
1977
+ let otherAgentContext = { context: { agentId: "another-agent" } };
1978
+ let streamingEventId = simulateRemoteMessage(roomId, "@aibot:localhost", {
1979
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
1980
+ body: "Reading",
1981
+ format: "org.matrix.custom.html",
1982
+ isStreamingFinished: false,
1983
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: [{
1984
+ id: "other-agent-read",
1985
+ name: discoveredHostToolName
1986
+ }],
1987
+ data: otherAgentContext
1988
+ });
1989
+ await settled();
1990
+ let roomResource = getService("matrix-service").roomResources.get(roomId);
1991
+ let tool = () => roomResource.messageForEventId(streamingEventId).tools.find((t) => t.id === "other-agent-read");
1992
+ assert.strictEqual(tool().codeRef, void 0, "no command is found yet");
1993
+ simulateDiscoveredToolResult(roomId);
1994
+ simulateRemoteMessage(roomId, "@aibot:localhost", {
1995
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
1996
+ body: "Reading",
1997
+ format: "org.matrix.custom.html",
1998
+ isStreamingFinished: true,
1999
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: [{
2000
+ id: "other-agent-read",
2001
+ name: discoveredHostToolName,
2002
+ arguments: JSON.stringify({ attributes: { fileIdentifier: `${testRealmURL}hello.txt` } })
2003
+ }],
2004
+ "m.relates_to": {
2005
+ rel_type: "m.replace",
2006
+ event_id: streamingEventId
2007
+ },
2008
+ data: otherAgentContext
2009
+ });
2010
+ await settled();
2011
+ assert.strictEqual(tool().codeRef?.module, "@cardstack/boxel-host/commands/read-file-for-ai-assistant", "the finished call resolves to its command in a tab whose drain doesn't run it");
2012
+ assert.strictEqual(tool().actionVerb, "Send", "the command's action verb");
2013
+ assert.strictEqual(getRoomEvents(roomId).filter((event) => event.type === "app.boxel.toolResult" && event.content.commandRequestId === "other-agent-read").length, 0, "this tab does not run another agent's call");
2014
+ });
2015
+ (0, import_qunit.test)("Accept All bar still renders for a command that requires user approval", async function(assert) {
2016
+ simulateRemoteMessage(await renderAiAssistantPanel(`${testRealmURL}Person/fadhlan`), "@aibot:localhost", {
2017
+ body: "patching",
2018
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
2019
+ format: "org.matrix.custom.html",
2020
+ isStreamingFinished: true,
2021
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: [{
2022
+ id: "cs-11647-patch",
2023
+ name: "patchCardInstance",
2024
+ arguments: JSON.stringify({ attributes: {
2025
+ cardId: `${testRealmURL}Person/fadhlan`,
2026
+ patch: { attributes: { firstName: "Dave" } }
2027
+ } })
2028
+ }]
2029
+ });
2030
+ await waitFor("[data-test-accept-all]");
2031
+ assert.dom("[data-test-accept-all]").exists("manual approval bar still renders for commands that need user approval");
2032
+ assert.dom("[data-test-stop-generating]").doesNotExist("nothing runs until the user approves, so there is no Stop");
2033
+ });
2034
+ function stubToolValidation({ held = false, heldToolIds, rejectSend } = {}) {
2035
+ let toolService = getService("tool-service");
2036
+ let matrixService = getService("matrix-service");
2037
+ let release;
2038
+ let released = held || heldToolIds ? new Promise((resolve) => release = resolve) : Promise.resolve();
2039
+ let validating = /* @__PURE__ */ new Set();
2040
+ let originalValidate = toolService.validate;
2041
+ toolService.validate = async (messageTool) => {
2042
+ if (messageTool.id) validating.add(messageTool.id);
2043
+ if (!heldToolIds || heldToolIds.includes(messageTool.id ?? "")) await released;
2044
+ return { valid: true };
2045
+ };
2046
+ let results = [];
2047
+ let originalSend = matrixService.sendToolResultEvent;
2048
+ matrixService.sendToolResultEvent = async function(params) {
2049
+ results.push({
2050
+ toolCallId: params.toolCallId,
2051
+ status: params.status,
2052
+ failureReason: params.failureReason,
2053
+ resumesAssistant: params.resumesAssistant
2054
+ });
2055
+ if (rejectSend?.(params)) throw new Error("the result could not be sent");
2056
+ return originalSend.call(this, params);
2057
+ };
2058
+ return {
2059
+ results,
2060
+ validating,
2061
+ release: () => release?.(),
2062
+ restore() {
2063
+ release?.();
2064
+ toolService.validate = originalValidate;
2065
+ matrixService.sendToolResultEvent = originalSend;
2066
+ }
2067
+ };
2068
+ }
2069
+ function checkCorrectnessCall(toolCallId) {
2070
+ return {
2071
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: [{
2072
+ id: toolCallId,
2073
+ name: "checkCorrectness",
2074
+ arguments: "{}"
2075
+ }],
2076
+ data: { context: { agentId: getService("matrix-service").agentId } }
2077
+ };
2078
+ }
2079
+ async function stopWhileStreaming(roomId, toolCallId, stop, toolRequests = checkCorrectnessCall(toolCallId)) {
2080
+ let streamingEventId = simulateRemoteMessage(roomId, "@aibot:localhost", {
2081
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
2082
+ body: "Checking",
2083
+ format: "org.matrix.custom.html",
2084
+ isStreamingFinished: false,
2085
+ data: { context: { agentId: getService("matrix-service").agentId } }
2086
+ });
2087
+ await waitFor("[data-test-stop-generating]");
2088
+ await stop();
2089
+ await waitUntil(() => !document.querySelector("[data-test-stop-generating]"), { timeout: 5e3 });
2090
+ simulateRemoteMessage(roomId, "@aibot:localhost", {
2091
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
2092
+ body: "Checking correctness",
2093
+ format: "org.matrix.custom.html",
2094
+ isStreamingFinished: true,
2095
+ ...toolRequests,
2096
+ "m.relates_to": {
2097
+ rel_type: "m.replace",
2098
+ event_id: streamingEventId
2099
+ }
2100
+ });
2101
+ return streamingEventId;
2102
+ }
2103
+ function patchPersonCall(toolCallId) {
2104
+ return {
2105
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: [{
2106
+ id: toolCallId,
2107
+ name: "patchCardInstance",
2108
+ arguments: JSON.stringify({ attributes: {
2109
+ cardId: `${testRealmURL}Person/fadhlan`,
2110
+ patch: { attributes: { firstName: "Dave" } }
2111
+ } })
2112
+ }],
2113
+ data: { context: { agentId: getService("matrix-service").agentId } }
2114
+ };
2115
+ }
2116
+ (0, import_qunit.test)("Stop is offered while a tool of the answer runs", async function(assert) {
2117
+ let roomId = await renderAiAssistantPanel();
2118
+ let stub = stubToolValidation({ held: true });
2119
+ try {
2120
+ simulateRemoteMessage(roomId, "@aibot:localhost", {
2121
+ body: "checking correctness",
2122
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
2123
+ format: "org.matrix.custom.html",
2124
+ isStreamingFinished: true,
2125
+ ...checkCorrectnessCall("running-tool")
2126
+ });
2127
+ await waitFor("[data-test-stop-generating]");
2128
+ assert.dom("[data-test-ai-assistant-action-bar]").containsText("Running tools", "the bar says tools are running");
2129
+ } finally {
2130
+ stub.restore();
2131
+ }
2132
+ });
2133
+ (0, import_qunit.test)("a tool the user stopped before it started never runs", async function(assert) {
2134
+ let roomId = await renderAiAssistantPanel();
2135
+ let stub = stubToolValidation();
2136
+ try {
2137
+ await stopWhileStreaming(roomId, "stopped-before-run", () => click("[data-test-stop-generating]"));
2138
+ await waitUntil(() => stub.results.length > 0, { timeout: 1e4 });
2139
+ await settled();
2140
+ assert.strictEqual(JSON.stringify(stub.results), JSON.stringify([{
2141
+ toolCallId: "stopped-before-run",
2142
+ status: "canceled",
2143
+ failureReason: STOPPED_TOOL_CALL_REASON
2144
+ }]), "the tool is answered as canceled instead of run");
2145
+ assert.dom("[data-test-tool-call-apply=\"canceled\"]").exists("the tool reads as canceled");
2146
+ assert.dom("[data-test-stop-generating]").doesNotExist("Stop is not offered again for the stopped loop");
2147
+ } finally {
2148
+ stub.restore();
2149
+ }
2150
+ });
2151
+ (0, import_qunit.test)("a stop sent from the user's other client keeps a tool here from starting", async function(assert) {
2152
+ let roomId = await renderAiAssistantPanel();
2153
+ let stub = stubToolValidation();
2154
+ try {
2155
+ await stopWhileStreaming(roomId, "stopped-elsewhere", async () => {
2156
+ simulateRemoteMessage(roomId, "@testuser:localhost", {}, { type: APP_BOXEL_STOP_GENERATING_EVENT_TYPE });
2157
+ });
2158
+ await waitUntil(() => stub.results.length > 0, { timeout: 1e4 });
2159
+ await settled();
2160
+ assert.strictEqual(JSON.stringify(stub.results.map(({ toolCallId, status }) => ({
2161
+ toolCallId,
2162
+ status
2163
+ }))), JSON.stringify([{
2164
+ toolCallId: "stopped-elsewhere",
2165
+ status: "canceled"
2166
+ }]));
2167
+ } finally {
2168
+ stub.restore();
2169
+ }
2170
+ });
2171
+ (0, import_qunit.test)("a stop whose timestamp reads earlier than the answer still stops that answer", async function(assert) {
2172
+ let roomId = await renderAiAssistantPanel();
2173
+ let stub = stubToolValidation();
2174
+ try {
2175
+ await stopWhileStreaming(roomId, "stopped-with-skewed-clock", async () => {
2176
+ simulateRemoteMessage(roomId, "@testuser:localhost", {}, {
2177
+ type: APP_BOXEL_STOP_GENERATING_EVENT_TYPE,
2178
+ origin_server_ts: 1
2179
+ });
2180
+ });
2181
+ await waitUntil(() => stub.results.length > 0, { timeout: 1e4 });
2182
+ await settled();
2183
+ assert.strictEqual(JSON.stringify(stub.results.map(({ toolCallId, status }) => ({
2184
+ toolCallId,
2185
+ status
2186
+ }))), JSON.stringify([{
2187
+ toolCallId: "stopped-with-skewed-clock",
2188
+ status: "canceled"
2189
+ }]));
2190
+ } finally {
2191
+ stub.restore();
2192
+ }
2193
+ });
2194
+ (0, import_qunit.test)("a stop the server has not confirmed yet holds although its clock reads earlier than the prompt", async function(assert) {
2195
+ let roomId = await renderAiAssistantPanel();
2196
+ let stub = stubToolValidation();
2197
+ let releaseSend;
2198
+ let held = false;
2199
+ mockMatrixUtils.setSendEventInterceptor(async () => {
2200
+ if (held) return;
2201
+ held = true;
2202
+ await new Promise((resolve) => releaseSend = resolve);
2203
+ });
2204
+ try {
2205
+ let serverAhead = Date.now() + 3600 * 1e3;
2206
+ simulateRemoteMessage(roomId, "@testuser:localhost", {
2207
+ body: "check it",
2208
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
2209
+ format: "org.matrix.custom.html"
2210
+ }, { origin_server_ts: serverAhead });
2211
+ let streamingEventId = simulateRemoteMessage(roomId, "@aibot:localhost", {
2212
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
2213
+ body: "Checking",
2214
+ format: "org.matrix.custom.html",
2215
+ isStreamingFinished: false,
2216
+ data: { context: { agentId: getService("matrix-service").agentId } }
2217
+ }, { origin_server_ts: serverAhead + 1 });
2218
+ await waitFor("[data-test-stop-generating]");
2219
+ let matrixService = getService("matrix-service");
2220
+ matrixService.sendStopGeneratingEvent(roomId);
2221
+ let roomResource = matrixService.roomResources.get(roomId);
2222
+ await waitUntil(() => roomResource.events.some((event) => event.type === "app.boxel.stopGenerating" && event.status === "sending"));
2223
+ simulateRemoteMessage(roomId, "@aibot:localhost", {
2224
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
2225
+ body: "Checking correctness",
2226
+ format: "org.matrix.custom.html",
2227
+ isStreamingFinished: true,
2228
+ ...checkCorrectnessCall("stopped-while-sending"),
2229
+ "m.relates_to": {
2230
+ rel_type: "m.replace",
2231
+ event_id: streamingEventId
2232
+ }
2233
+ }, { origin_server_ts: serverAhead + 2 });
2234
+ await waitUntil(() => stub.results.length > 0, { timeout: 1e4 });
2235
+ await settled();
2236
+ assert.strictEqual(JSON.stringify(stub.results.map(({ toolCallId, status }) => ({
2237
+ toolCallId,
2238
+ status
2239
+ }))), JSON.stringify([{
2240
+ toolCallId: "stopped-while-sending",
2241
+ status: "canceled"
2242
+ }]));
2243
+ } finally {
2244
+ mockMatrixUtils.setSendEventInterceptor(void 0);
2245
+ releaseSend?.();
2246
+ stub.restore();
2247
+ }
2248
+ });
2249
+ (0, import_qunit.test)("a stop during a later tool's validation keeps the tools validated before it from starting", async function(assert) {
2250
+ let roomId = await renderAiAssistantPanel();
2251
+ let stub = stubToolValidation({ heldToolIds: ["validated-last"] });
2252
+ try {
2253
+ simulateRemoteMessage(roomId, "@aibot:localhost", {
2254
+ body: "checking correctness twice",
2255
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
2256
+ format: "org.matrix.custom.html",
2257
+ isStreamingFinished: true,
2258
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: [{
2259
+ id: "validated-first",
2260
+ name: "checkCorrectness",
2261
+ arguments: "{}"
2262
+ }, {
2263
+ id: "validated-last",
2264
+ name: "checkCorrectness",
2265
+ arguments: "{}"
2266
+ }],
2267
+ data: { context: { agentId: getService("matrix-service").agentId } }
2268
+ });
2269
+ await waitUntil(() => stub.validating.has("validated-last"), { timeout: 1e4 });
2270
+ simulateRemoteMessage(roomId, "@testuser:localhost", {}, { type: APP_BOXEL_STOP_GENERATING_EVENT_TYPE });
2271
+ let roomResource = getService("matrix-service").roomResources.get(roomId);
2272
+ await waitUntil(() => roomResource.stopState.inForce !== void 0);
2273
+ stub.release();
2274
+ await waitUntil(() => stub.results.length === 2, { timeout: 1e4 });
2275
+ await settled();
2276
+ assert.strictEqual(JSON.stringify(stub.results.map(({ toolCallId, status }) => ({
2277
+ toolCallId,
2278
+ status
2279
+ }))), JSON.stringify([{
2280
+ toolCallId: "validated-first",
2281
+ status: "canceled"
2282
+ }, {
2283
+ toolCallId: "validated-last",
2284
+ status: "canceled"
2285
+ }]), "neither tool had started when the user stopped, so neither runs");
2286
+ } finally {
2287
+ stub.restore();
2288
+ }
2289
+ });
2290
+ (0, import_qunit.test)("Stop is not offered for a tool another of the user's clients runs", async function(assert) {
2291
+ simulateRemoteMessage(await renderAiAssistantPanel(), "@aibot:localhost", {
2292
+ body: "checking correctness",
2293
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
2294
+ format: "org.matrix.custom.html",
2295
+ isStreamingFinished: true,
2296
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: [{
2297
+ id: "other-client-tool",
2298
+ name: "checkCorrectness",
2299
+ arguments: "{}"
2300
+ }],
2301
+ data: { context: { agentId: "another-client-agent" } }
2302
+ });
2303
+ let offered = "[data-test-accept-all], [data-test-tool-call-id=\"other-client-tool\"] [data-test-pretui-tool-gate-action=\"apply\"]";
2304
+ await waitFor(offered);
2305
+ assert.dom("[data-test-stop-generating]").doesNotExist("only the client that runs the tool offers Stop for it");
2306
+ assert.dom(offered).exists("this client offers the call like any other");
2307
+ });
2308
+ (0, import_qunit.test)("a message from the user after a stop lets the next tools run", async function(assert) {
2309
+ let roomId = await renderAiAssistantPanel();
2310
+ let stub = stubToolValidation();
2311
+ try {
2312
+ await stopWhileStreaming(roomId, "stopped-first", () => click("[data-test-stop-generating]"));
2313
+ await waitUntil(() => stub.results.length > 0, { timeout: 1e4 });
2314
+ simulateRemoteMessage(roomId, "@testuser:localhost", {
2315
+ body: "try again",
2316
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
2317
+ format: "org.matrix.custom.html"
2318
+ });
2319
+ simulateRemoteMessage(roomId, "@aibot:localhost", {
2320
+ body: "checking correctness again",
2321
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
2322
+ format: "org.matrix.custom.html",
2323
+ isStreamingFinished: true,
2324
+ ...checkCorrectnessCall("after-new-message")
2325
+ });
2326
+ await waitUntil(() => stub.results.some((r) => r.toolCallId === "after-new-message"), { timeout: 2e4 });
2327
+ await settled();
2328
+ assert.notStrictEqual(stub.results.find((r) => r.toolCallId === "after-new-message")?.status, "canceled", "the stop no longer applies after the user writes again");
2329
+ } finally {
2330
+ stub.restore();
2331
+ }
2332
+ });
2333
+ (0, import_qunit.test)("running a tool of the stopped answer by hand resumes the assistant", async function(assert) {
2334
+ let roomId = await renderAiAssistantPanel(`${testRealmURL}Person/fadhlan`);
2335
+ let stub = stubToolValidation();
2336
+ try {
2337
+ await stopWhileStreaming(roomId, "run-after-stop", () => click("[data-test-stop-generating]"), patchPersonCall("run-after-stop"));
2338
+ await waitFor("[data-test-tool-call-apply=\"ready\"]");
2339
+ let roomResource = getService("matrix-service").roomResources.get(roomId);
2340
+ assert.ok(roomResource.stopState.inForce, "the stop is in force");
2341
+ await click("[data-test-pretui-tool-gate-action=\"apply\"]");
2342
+ await waitUntil(() => stub.results.length > 0, { timeout: 1e4 });
2343
+ await settled();
2344
+ assert.strictEqual(JSON.stringify(stub.results), JSON.stringify([{
2345
+ toolCallId: "run-after-stop",
2346
+ status: "applied",
2347
+ resumesAssistant: true
2348
+ }]), "the result says the user asked for the call to go ahead");
2349
+ assert.notOk(roomResource.stopState.inForce, "the result lifts the stop");
2350
+ simulateRemoteMessage(roomId, "@aibot:localhost", {
2351
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
2352
+ body: "Applied, now",
2353
+ format: "org.matrix.custom.html",
2354
+ isStreamingFinished: false,
2355
+ data: { context: { agentId: getService("matrix-service").agentId } }
2356
+ });
2357
+ await waitFor("[data-test-stop-generating]");
2358
+ assert.dom("[data-test-stop-generating]").exists("Stop is offered again for the answer that follows");
2359
+ } finally {
2360
+ stub.restore();
2361
+ }
2362
+ });
2363
+ (0, import_qunit.test)("every answer sends a result; the last call waiting on a message also gets a reaction", async function(assert) {
2364
+ let roomId = await renderAiAssistantPanel();
2365
+ let stub = stubToolValidation();
2366
+ let matrixService = getService("matrix-service");
2367
+ let originalReact = matrixService.sendReactionEvent;
2368
+ let reactions = [];
2369
+ matrixService.sendReactionEvent = async (_roomId, eventId, key) => {
2370
+ reactions.push({
2371
+ eventId,
2372
+ key
2373
+ });
2374
+ return { event_id: "$reaction" };
2375
+ };
2376
+ try {
2377
+ let eventId = simulateRemoteMessage(roomId, "@aibot:localhost", {
2378
+ body: "may I read these?",
2379
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
2380
+ format: "org.matrix.custom.html",
2381
+ isStreamingFinished: true,
2382
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: ["approved-read", "declined-read"].map((id) => ({
2383
+ id,
2384
+ name: "readUrl",
2385
+ arguments: JSON.stringify({ url: `https://example.com/${id}` }),
2386
+ executedBy: AI_BOT_EXECUTOR,
2387
+ approvalRequired: true
2388
+ }))
2389
+ });
2390
+ let roomResource = getService("matrix-service").roomResources.get(roomId);
2391
+ await waitUntil(() => roomResource.messages[0]?.tools.length === 2, { timeout: 1e4 });
2392
+ let [approved, declined] = roomResource.messages[0].tools;
2393
+ let toolService = getService("tool-service");
2394
+ await toolService.answerApproval.unlinked().perform(approved, "approve");
2395
+ await toolService.answerApproval.unlinked().perform(declined, "decline");
2396
+ await settled();
2397
+ assert.strictEqual(JSON.stringify(stub.results.map(({ toolCallId, status, resumesAssistant }) => ({
2398
+ toolCallId,
2399
+ status,
2400
+ resumesAssistant
2401
+ }))), JSON.stringify([{
2402
+ toolCallId: "approved-read",
2403
+ status: "approved",
2404
+ resumesAssistant: true
2405
+ }, {
2406
+ toolCallId: "declined-read",
2407
+ status: "invalid"
2408
+ }]), "each answer is a result ai-bot acts on");
2409
+ assert.deepEqual(reactions, [{
2410
+ eventId,
2411
+ key: "👎"
2412
+ }], "only the last call waiting on the message adds a 👎, since a reaction answers the whole message");
2413
+ } finally {
2414
+ matrixService.sendReactionEvent = originalReact;
2415
+ stub.restore();
2416
+ }
2417
+ });
2418
+ (0, import_qunit.test)("a reaction after each call has its result changes neither answer", async function(assert) {
2419
+ let roomId = await renderAiAssistantPanel();
2420
+ let eventId = simulateRemoteMessage(roomId, "@aibot:localhost", {
2421
+ body: "may I read these?",
2422
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
2423
+ format: "org.matrix.custom.html",
2424
+ isStreamingFinished: true,
2425
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: ["approved-read", "declined-read"].map((id) => ({
2426
+ id,
2427
+ name: "readUrl",
2428
+ arguments: JSON.stringify({ url: `https://example.com/${id}` }),
2429
+ executedBy: AI_BOT_EXECUTOR,
2430
+ approvalRequired: true
2431
+ }))
2432
+ });
2433
+ let roomResource = getService("matrix-service").roomResources.get(roomId);
2434
+ await waitUntil(() => roomResource.messages[0]?.tools.length === 2, { timeout: 1e4 });
2435
+ for (let [commandRequestId, key] of [["approved-read", "approved"], ["declined-read", "invalid"]]) simulateRemoteMessage(roomId, "@testuser:localhost", {
2436
+ msgtype: APP_BOXEL_TOOL_RESULT_WITH_NO_OUTPUT_MSGTYPE,
2437
+ commandRequestId,
2438
+ "m.relates_to": {
2439
+ rel_type: APP_BOXEL_TOOL_RESULT_REL_TYPE,
2440
+ key,
2441
+ event_id: eventId
2442
+ },
2443
+ data: {}
2444
+ }, { type: APP_BOXEL_TOOL_RESULT_EVENT_TYPE });
2445
+ simulateRemoteMessage(roomId, "@testuser:localhost", { "m.relates_to": {
2446
+ rel_type: "m.annotation",
2447
+ event_id: eventId,
2448
+ key: "👎"
2449
+ } }, { type: "m.reaction" });
2450
+ await settled();
2451
+ let [approved, declined] = roomResource.messages[0].tools;
2452
+ assert.strictEqual(approved.toolCallStatus, "approved");
2453
+ assert.strictEqual(approved.approvalAnswer, void 0, "the 👎 that follows the last answer does not decline the approved call");
2454
+ assert.strictEqual(declined.toolCallStatus, "invalid");
2455
+ });
2456
+ (0, import_qunit.test)("a 👍 from a room member approves the held call and says who", async function(assert) {
2457
+ let roomId = await renderAiAssistantPanel();
2458
+ let stub = stubToolValidation();
2459
+ try {
2460
+ let eventId = simulateRemoteMessage(roomId, "@aibot:localhost", {
2461
+ body: "may I read this?",
2462
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
2463
+ format: "org.matrix.custom.html",
2464
+ isStreamingFinished: true,
2465
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: [{
2466
+ id: "held-read",
2467
+ name: "readUrl",
2468
+ arguments: JSON.stringify({ url: "https://example.com/a" }),
2469
+ executedBy: AI_BOT_EXECUTOR,
2470
+ approvalRequired: true
2471
+ }]
2472
+ });
2473
+ await waitFor("[data-test-tool-call-id=\"held-read\"] [data-test-tool-call-approval]");
2474
+ simulateRemoteMessage(roomId, "@rupert:localhost", { "m.relates_to": {
2475
+ rel_type: "m.annotation",
2476
+ event_id: eventId,
2477
+ key: "👍"
2478
+ } }, { type: "m.reaction" });
2479
+ await waitFor("[data-test-tool-call-approval-answer=\"approve\"]");
2480
+ assert.dom("[data-test-tool-call-approval-answer=\"approve\"]").includesText("👍");
2481
+ assert.dom("[data-test-tool-call-id=\"held-read\"] [data-test-tool-call-approval]").doesNotExist("the call no longer asks");
2482
+ assert.strictEqual(stub.results.length, 0, "the host sends no result of its own");
2483
+ } finally {
2484
+ stub.restore();
2485
+ }
2486
+ });
2487
+ (0, import_qunit.test)("a canceled result that cannot be sent shows the tool as failed, not spinning", async function(assert) {
2488
+ let roomId = await renderAiAssistantPanel();
2489
+ let stub = stubToolValidation({ rejectSend: ({ status }) => status === "canceled" });
2490
+ try {
2491
+ await stopWhileStreaming(roomId, "canceled-send-fails", () => click("[data-test-stop-generating]"));
2492
+ await waitUntil(() => stub.results.length > 0, { timeout: 1e4 });
2493
+ await settled();
2494
+ assert.strictEqual(stub.results[0]?.status, "canceled");
2495
+ assert.dom("[data-test-tool-call-apply=\"failed\"]").exists("the tool offers Retry instead of a spinner");
2496
+ } finally {
2497
+ stub.restore();
2498
+ }
2499
+ });
2500
+ (0, import_qunit.test)("a tool already running when the user stops keeps its spinner until its result lands", async function(assert) {
2501
+ let roomId = await renderAiAssistantPanel();
2502
+ let toolService = getService("tool-service");
2503
+ toolService.currentlyExecutingToolRequestIds.add("already-running");
2504
+ try {
2505
+ let eventId = await stopWhileStreaming(roomId, "already-running", () => click("[data-test-stop-generating]"));
2506
+ await waitFor("[data-test-tool-call-apply=\"applying\"]");
2507
+ assert.dom("[data-test-tool-call-apply=\"canceled\"]").doesNotExist("a running tool is not shown as canceled");
2508
+ await settled();
2509
+ toolService.currentlyExecutingToolRequestIds.delete("already-running");
2510
+ simulateRemoteMessage(roomId, "@testuser:localhost", {
2511
+ msgtype: APP_BOXEL_TOOL_RESULT_WITH_NO_OUTPUT_MSGTYPE,
2512
+ commandRequestId: "already-running",
2513
+ "m.relates_to": {
2514
+ rel_type: APP_BOXEL_TOOL_RESULT_REL_TYPE,
2515
+ key: "applied",
2516
+ event_id: eventId
2517
+ }
2518
+ }, { type: APP_BOXEL_TOOL_RESULT_EVENT_TYPE });
2519
+ await waitFor("[data-test-tool-call-apply=\"applied\"]", { timeout: 1e4 });
2520
+ assert.dom("[data-test-tool-call-apply=\"applied\"]").exists("its result still lands");
2521
+ } finally {
2522
+ toolService.currentlyExecutingToolRequestIds.delete("already-running");
2523
+ }
2524
+ });
2525
+ (0, import_qunit.test)("Stop is not offered for an answer that ended in an error", async function(assert) {
2526
+ simulateRemoteMessage(await renderAiAssistantPanel(), "@aibot:localhost", {
2527
+ body: "reading",
2528
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
2529
+ format: "org.matrix.custom.html",
2530
+ isStreamingFinished: true,
2531
+ errorMessage: "The model stopped answering",
2532
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: [{
2533
+ id: "read-that-never-ran",
2534
+ name: "readUrl",
2535
+ arguments: JSON.stringify({ url: "https://example.com" }),
2536
+ executedBy: AI_BOT_EXECUTOR
2537
+ }]
2538
+ });
2539
+ await waitFor("[data-test-message-idx=\"0\"]");
2540
+ await settled();
2541
+ assert.dom("[data-test-stop-generating]").doesNotExist("the bot never reached its call, so nothing is running");
2542
+ });
2543
+ (0, import_qunit.test)("Stop is not offered for a tool whose result could not be sent", async function(assert) {
2544
+ let roomId = await renderAiAssistantPanel();
2545
+ let stub = stubToolValidation({ held: true });
2546
+ try {
2547
+ simulateRemoteMessage(roomId, "@aibot:localhost", {
2548
+ body: "checking correctness",
2549
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
2550
+ format: "org.matrix.custom.html",
2551
+ isStreamingFinished: true,
2552
+ ...checkCorrectnessCall("result-never-sent")
2553
+ });
2554
+ await waitFor("[data-test-stop-generating]");
2555
+ getService("matrix-service").failedToolState.set("result-never-sent", /* @__PURE__ */ new Error("the result could not be sent"));
2556
+ await settled();
2557
+ assert.dom("[data-test-stop-generating]").doesNotExist("no result will ever come, so nothing is running");
2558
+ } finally {
2559
+ stub.restore();
2560
+ }
2561
+ });
2562
+ (0, import_qunit.test)("a stopped answer's tool stays stopped after the user writes again", async function(assert) {
2563
+ let roomId = await renderAiAssistantPanel();
2564
+ let stub = stubToolValidation({ held: true });
2565
+ try {
2566
+ simulateRemoteMessage(roomId, "@aibot:localhost", {
2567
+ body: "checking correctness",
2568
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
2569
+ format: "org.matrix.custom.html",
2570
+ isStreamingFinished: true,
2571
+ ...checkCorrectnessCall("stopped-then-written")
2572
+ });
2573
+ await waitUntil(() => stub.validating.has("stopped-then-written"), { timeout: 1e4 });
2574
+ simulateRemoteMessage(roomId, "@testuser:localhost", {}, { type: APP_BOXEL_STOP_GENERATING_EVENT_TYPE });
2575
+ simulateRemoteMessage(roomId, "@testuser:localhost", {
2576
+ body: "never mind",
2577
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
2578
+ format: "org.matrix.custom.html"
2579
+ });
2580
+ let roomResource = getService("matrix-service").roomResources.get(roomId);
2581
+ await waitUntil(() => roomResource.messages.length === 2);
2582
+ assert.notOk(roomResource.stopState.inForce, "the stop is lifted");
2583
+ stub.release();
2584
+ await waitUntil(() => stub.results.length > 0, { timeout: 1e4 });
2585
+ await settled();
2586
+ assert.strictEqual(stub.results[0]?.status, "canceled", "the tool the user stopped never runs, lifted stop or not");
2587
+ } finally {
2588
+ stub.restore();
2589
+ }
2590
+ });
2591
+ (0, import_qunit.test)("running one tool of a stopped answer by hand does not start its others", async function(assert) {
2592
+ let roomId = await renderAiAssistantPanel();
2593
+ let stub = stubToolValidation({ heldToolIds: ["left-over"] });
2594
+ try {
2595
+ let eventId = await stopWhileStreaming(roomId, "left-over", () => click("[data-test-stop-generating]"), {
2596
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: [...patchPersonCall("run-by-hand")[APP_BOXEL_TOOL_REQUESTS_KEY], {
2597
+ id: "left-over",
2598
+ name: "checkCorrectness",
2599
+ arguments: "{}"
2600
+ }],
2601
+ data: { context: { agentId: getService("matrix-service").agentId } }
2602
+ });
2603
+ await waitUntil(() => stub.validating.has("left-over"), { timeout: 1e4 });
2604
+ simulateRemoteMessage(roomId, "@testuser:localhost", {
2605
+ msgtype: APP_BOXEL_TOOL_RESULT_WITH_NO_OUTPUT_MSGTYPE,
2606
+ commandRequestId: "run-by-hand",
2607
+ resumesAssistant: true,
2608
+ "m.relates_to": {
2609
+ rel_type: APP_BOXEL_TOOL_RESULT_REL_TYPE,
2610
+ key: "applied",
2611
+ event_id: eventId
2612
+ }
2613
+ }, { type: APP_BOXEL_TOOL_RESULT_EVENT_TYPE });
2614
+ let roomResource = getService("matrix-service").roomResources.get(roomId);
2615
+ await waitUntil(() => !roomResource.stopState.inForce);
2616
+ stub.release();
2617
+ await waitUntil(() => stub.results.length > 0, { timeout: 1e4 });
2618
+ await settled();
2619
+ assert.strictEqual(JSON.stringify(stub.results.map(({ toolCallId, status }) => ({
2620
+ toolCallId,
2621
+ status
2622
+ }))), JSON.stringify([{
2623
+ toolCallId: "left-over",
2624
+ status: "canceled"
2625
+ }]), "the user asked for one call, not the rest");
2626
+ } finally {
2627
+ stub.restore();
2628
+ }
2629
+ });
2630
+ (0, import_qunit.test)("a call's latest result and the room's last activity follow the timeline, not the order events arrived in", async function(assert) {
2631
+ let roomId = await renderAiAssistantPanel(`${testRealmURL}Person/fadhlan`);
2632
+ let now = Date.now();
2633
+ let eventId = simulateRemoteMessage(roomId, "@aibot:localhost", {
2634
+ body: "patching",
2635
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
2636
+ format: "org.matrix.custom.html",
2637
+ isStreamingFinished: true,
2638
+ ...patchPersonCall("retried-patch")
2639
+ }, { origin_server_ts: now });
2640
+ let result = (key, origin_server_ts) => simulateRemoteMessage(roomId, "@testuser:localhost", {
2641
+ msgtype: APP_BOXEL_TOOL_RESULT_WITH_NO_OUTPUT_MSGTYPE,
2642
+ commandRequestId: "retried-patch",
2643
+ "m.relates_to": {
2644
+ rel_type: APP_BOXEL_TOOL_RESULT_REL_TYPE,
2645
+ key,
2646
+ event_id: eventId
2647
+ }
2648
+ }, {
2649
+ type: APP_BOXEL_TOOL_RESULT_EVENT_TYPE,
2650
+ origin_server_ts
2651
+ });
2652
+ result("applied", now + 2e3);
2653
+ await waitFor("[data-test-tool-call-apply=\"applied\"]");
2654
+ result("failed", now + 1e3);
2655
+ await settled();
2656
+ assert.dom("[data-test-tool-call-apply=\"applied\"]").exists("the later result is the outcome, whenever it arrived");
2657
+ let roomResource = getService("matrix-service").roomResources.get(roomId);
2658
+ assert.strictEqual(roomResource.lastActiveTimestamp, now + 2e3, "the room was last active at its newest event");
2659
+ });
2660
+ function simulateShowCardResult(roomId, snapshotFirstName, cardId = `${testRealmURL}Person/fadhlan`) {
2661
+ let snapshotUrl = "mxc://mock-server/fadhlan-snapshot";
2662
+ let matrixService = getService("matrix-service");
2663
+ let originalDownload = matrixService.downloadCardFileDef.bind(matrixService);
2664
+ matrixService.downloadCardFileDef = async (serializedFile) => {
2665
+ if (serializedFile.url !== snapshotUrl) return originalDownload(serializedFile);
2666
+ return { data: {
2667
+ id: cardId,
2668
+ type: "card",
2669
+ attributes: { firstName: snapshotFirstName },
2670
+ meta: { adoptsFrom: {
2671
+ module: `${testRealmURL}person`,
2672
+ name: "Person"
2673
+ } }
2674
+ } };
2675
+ };
2676
+ let commandRequestId = "show-card-request-id";
2677
+ simulateRemoteMessage(roomId, "@aibot:localhost", {
2678
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
2679
+ body: "Showing the card",
2680
+ format: "org.matrix.custom.html",
2681
+ isStreamingFinished: true,
2682
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: [{
2683
+ id: commandRequestId,
2684
+ name: "showCard",
2685
+ arguments: JSON.stringify({ attributes: { cardId } })
2686
+ }]
2687
+ });
2688
+ simulateRemoteMessage(roomId, "@aibot:localhost", {
2689
+ msgtype: APP_BOXEL_TOOL_RESULT_WITH_OUTPUT_MSGTYPE,
2690
+ commandRequestId,
2691
+ "m.relates_to": {
2692
+ rel_type: APP_BOXEL_TOOL_RESULT_REL_TYPE,
2693
+ key: "applied",
2694
+ event_id: "bot-message-event-id"
2695
+ },
2696
+ data: { card: {
2697
+ url: snapshotUrl,
2698
+ sourceUrl: cardId,
2699
+ name: "Fadhlan",
2700
+ contentType: "application/vnd.card+json"
2701
+ } }
2702
+ }, { type: APP_BOXEL_TOOL_RESULT_EVENT_TYPE });
2703
+ }
2704
+ (0, import_qunit.test)("rendering a tool result that snapshots a card already in the store leaves the live instance untouched", async function(assert) {
2705
+ let roomId = await renderAiAssistantPanel(`${testRealmURL}Person/fadhlan`);
2706
+ await waitFor("[data-test-person=\"Fadhlan\"]");
2707
+ let savedFirstNames = [];
2708
+ this.onSave((_, json) => {
2709
+ if (typeof json === "string") throw new Error("expected JSON save data");
2710
+ savedFirstNames.push(json.data.attributes?.firstName);
2711
+ });
2712
+ simulateShowCardResult(roomId, "Stale");
2713
+ await waitForToolResult("[data-test-boxel-tool-call-result]");
2714
+ await settled();
2715
+ assert.dom("[data-test-person]").hasText("Fadhlan", "the card in the stack still shows the live data");
2716
+ let live = getService("store").peek(`${testRealmURL}Person/fadhlan`);
2717
+ assert.strictEqual(live?.firstName, "Fadhlan", "the resident instance keeps its live fields");
2718
+ assert.dom("[data-test-boxel-tool-call-result]").containsText("Fadhlan", "the tool result renders the live card");
2719
+ assert.deepEqual(savedFirstNames, [], "rendering the tool result does not save anything");
2720
+ live.firstName = "Fadhlan Updated";
2721
+ await settled();
2722
+ assert.dom("[data-test-boxel-tool-call-result]").containsText("Fadhlan Updated", "the tool result follows the resident instance");
2723
+ assert.deepEqual(savedFirstNames, ["Fadhlan Updated"], "the autosave writes the live value");
2724
+ });
2725
+ (0, import_qunit.test)("rendering a tool result that snapshots a card not yet in the store loads the live card instead of the snapshot", async function(assert) {
2726
+ let roomId = await renderAiAssistantPanel();
2727
+ this.onSave(() => {
2728
+ assert.ok(false, "rendering a tool result must not trigger a save");
2729
+ });
2730
+ simulateShowCardResult(roomId, "Stale");
2731
+ await waitForToolResult("[data-test-boxel-tool-call-result]");
2732
+ await settled();
2733
+ let live = getService("store").peek(`${testRealmURL}Person/fadhlan`);
2734
+ assert.strictEqual(live?.firstName, "Fadhlan", "the store holds the live card, not the room snapshot");
2735
+ assert.dom("[data-test-boxel-tool-call-result]").containsText("Fadhlan", "the tool result renders the live card");
2736
+ });
2737
+ (0, import_qunit.test)("rendering a tool result whose live card no longer exists renders the snapshot without installing it under the card id", async function(assert) {
2738
+ let roomId = await renderAiAssistantPanel();
2739
+ this.onSave(() => {
2740
+ assert.ok(false, "rendering a tool result must not trigger a save");
2741
+ });
2742
+ let deletedId = `${testRealmURL}Person/deleted`;
2743
+ simulateShowCardResult(roomId, "Snapshot", deletedId);
2744
+ await waitForToolResult("[data-test-boxel-tool-call-result]");
2745
+ await settled();
2746
+ assert.dom("[data-test-boxel-tool-call-result]").containsText("Snapshot", "the tool result falls back to rendering the snapshot");
2747
+ let store = getService("store");
2748
+ assert.false(isCardInstance(store.peek(deletedId)), "the snapshot is not installed in the store under the realm id");
2749
+ });
2750
+ (0, import_qunit.test)("opening a fold of messages that each ran the same tool shows every call", async function(assert) {
2751
+ let roomId = await renderAiAssistantPanel();
2752
+ let renameTo = (name) => {
2753
+ let requestId = `rename-${name}`;
2754
+ simulateRemoteMessage(roomId, "@aibot:localhost", {
2755
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
2756
+ body: "",
2757
+ format: "org.matrix.custom.html",
2758
+ isStreamingFinished: true,
2759
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: [{
2760
+ id: requestId,
2761
+ name: "patchCardInstance",
2762
+ arguments: JSON.stringify({
2763
+ description: `Rename to ${name}`,
2764
+ attributes: {
2765
+ cardId: `${testRealmURL}Person/fadhlan`,
2766
+ patch: { attributes: { firstName: name } }
2767
+ }
2768
+ })
2769
+ }]
2770
+ });
2771
+ simulateRemoteMessage(roomId, "@aibot:localhost", {
2772
+ msgtype: APP_BOXEL_TOOL_RESULT_WITH_NO_OUTPUT_MSGTYPE,
2773
+ commandRequestId: requestId,
2774
+ "m.relates_to": {
2775
+ rel_type: APP_BOXEL_TOOL_RESULT_REL_TYPE,
2776
+ key: "applied",
2777
+ event_id: requestId
2778
+ },
2779
+ data: {}
2780
+ }, { type: APP_BOXEL_TOOL_RESULT_EVENT_TYPE });
2781
+ };
2782
+ for (let name of [
2783
+ "Ada",
2784
+ "Bea",
2785
+ "Cy",
2786
+ "Dee"
2787
+ ]) renameTo(name);
2788
+ await waitFor("[data-test-message-idx=\"3\"] [data-test-tool-run-group=\"4\"]");
2789
+ for (let index of [
2790
+ 0,
2791
+ 1,
2792
+ 2
2793
+ ]) assert.dom(`[data-test-message-idx="${index}"]`).doesNotExist(`the earlier message ${index} folds into the latest`);
2794
+ assert.dom("[data-test-message-idx=\"3\"] [data-test-pretui-tool-group-header]").containsText("×4", "the latest message reads as the whole run");
2795
+ await click("[data-test-message-idx=\"3\"] [data-test-pretui-tool-group-header]");
2796
+ assert.dom("[data-test-message-idx=\"3\"] [data-test-tool-run-group] [data-test-tool-call-apply=\"applied\"]").exists({ count: 4 }, "opening the fold shows every call of the run");
2797
+ for (let name of [
2798
+ "Ada",
2799
+ "Bea",
2800
+ "Cy",
2801
+ "Dee"
2802
+ ]) assert.dom("[data-test-message-idx=\"3\"] [data-test-tool-run-group]").containsText(`to ${name}`, `the call renaming to ${name} shows`);
2803
+ renameTo("Eve");
2804
+ await waitFor("[data-test-message-idx=\"4\"] [data-test-tool-run-group=\"5\"]");
2805
+ assert.dom("[data-test-message-idx=\"4\"] [data-test-tool-run-group] [data-test-tool-call-apply=\"applied\"]").exists({ count: 5 }, "the fold stays open as the run grows");
2806
+ await click("[data-test-message-idx=\"4\"] [data-test-pretui-tool-group-header]");
2807
+ renameTo("Fay");
2808
+ await waitFor("[data-test-message-idx=\"5\"] [data-test-tool-run-group=\"6\"]");
2809
+ assert.dom("[data-test-message-idx=\"5\"] [data-test-pretui-tool-group-header]").hasAttribute("aria-expanded", "false", "the fold stays closed as the run grows");
2810
+ });
2811
+ (0, import_qunit.test)("a run of two messages that each ran the same tool folds into one group", async function(assert) {
2812
+ let roomId = await renderAiAssistantPanel();
2813
+ for (let name of ["Ada", "Bea"]) {
2814
+ let requestId = `rename-${name}`;
2815
+ simulateRemoteMessage(roomId, "@aibot:localhost", {
2816
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
2817
+ body: "",
2818
+ format: "org.matrix.custom.html",
2819
+ isStreamingFinished: true,
2820
+ [APP_BOXEL_TOOL_REQUESTS_KEY]: [{
2821
+ id: requestId,
2822
+ name: "patchCardInstance",
2823
+ arguments: JSON.stringify({
2824
+ description: `Rename to ${name}`,
2825
+ attributes: {
2826
+ cardId: `${testRealmURL}Person/fadhlan`,
2827
+ patch: { attributes: { firstName: name } }
2828
+ }
2829
+ })
2830
+ }]
2831
+ });
2832
+ simulateRemoteMessage(roomId, "@aibot:localhost", {
2833
+ msgtype: APP_BOXEL_TOOL_RESULT_WITH_NO_OUTPUT_MSGTYPE,
2834
+ commandRequestId: requestId,
2835
+ "m.relates_to": {
2836
+ rel_type: APP_BOXEL_TOOL_RESULT_REL_TYPE,
2837
+ key: "applied",
2838
+ event_id: requestId
2839
+ },
2840
+ data: {}
2841
+ }, { type: APP_BOXEL_TOOL_RESULT_EVENT_TYPE });
2842
+ }
2843
+ await waitFor("[data-test-message-idx=\"1\"] [data-test-tool-run-group=\"2\"]");
2844
+ assert.dom("[data-test-message-idx=\"0\"]").doesNotExist("the earlier message folds into the latest");
2845
+ assert.dom("[data-test-message-idx=\"1\"] [data-test-pretui-tool-group-header]").containsText("×2", "the latest message reads as both calls");
2846
+ await click("[data-test-message-idx=\"1\"] [data-test-pretui-tool-group-header]");
2847
+ assert.dom("[data-test-message-idx=\"1\"] [data-test-tool-run-group] [data-test-tool-call-apply=\"applied\"]").exists({ count: 2 }, "opening the fold shows both calls");
2848
+ });
2849
+ function simulateToolResult(roomId, { requestId, toolName, resultDoc, args = {}, inMedia = false }) {
2850
+ let resultUrl = `mxc://mock-server/${requestId}-result`;
2851
+ let matrixService = getService("matrix-service");
2852
+ let originalDownload = matrixService.downloadCardFileDef.bind(matrixService);
2853
+ matrixService.downloadCardFileDef = async (serializedFile) => {
2854
+ if (serializedFile.url !== resultUrl) return originalDownload(serializedFile);
2855
+ return resultDoc;
2856
+ };
2857
+ let toolRequests = [{
2858
+ id: requestId,
2859
+ name: toolName,
2860
+ arguments: JSON.stringify(args)
2861
+ }];
2862
+ let requestsField = { [APP_BOXEL_TOOL_REQUESTS_KEY]: toolRequests };
2863
+ if (inMedia) {
2864
+ let requestsUrl = `mxc://mock-server/${requestId}-requests`;
2865
+ let mediaId = requestsUrl.slice(18);
2866
+ let originalFetch = matrixService.fetchMatrixHostedFile.bind(matrixService);
2867
+ matrixService.fetchMatrixHostedFile = async (url) => url.endsWith(`/${mediaId}`) ? new Response(JSON.stringify(toolRequests)) : originalFetch(url);
2868
+ requestsField = { [APP_BOXEL_EXTERNAL_FIELDS_KEY]: { [APP_BOXEL_TOOL_REQUESTS_KEY]: requestsUrl } };
2869
+ }
2870
+ simulateRemoteMessage(roomId, "@aibot:localhost", {
2871
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
2872
+ body: `Running ${toolName}`,
2873
+ format: "org.matrix.custom.html",
2874
+ isStreamingFinished: true,
2875
+ ...requestsField
2876
+ });
2877
+ simulateRemoteMessage(roomId, "@aibot:localhost", {
2878
+ msgtype: APP_BOXEL_TOOL_RESULT_WITH_OUTPUT_MSGTYPE,
2879
+ commandRequestId: requestId,
2880
+ "m.relates_to": {
2881
+ rel_type: APP_BOXEL_TOOL_RESULT_REL_TYPE,
2882
+ key: "applied",
2883
+ event_id: "bot-message-event-id"
2884
+ },
2885
+ data: { card: {
2886
+ url: resultUrl,
2887
+ sourceUrl: resultUrl,
2888
+ name: `${toolName} result`,
2889
+ contentType: "application/vnd.card+json"
2890
+ } }
2891
+ }, { type: APP_BOXEL_TOOL_RESULT_EVENT_TYPE });
2892
+ }
2893
+ function baseCommandResultDoc(name, attributes) {
2894
+ return { data: {
2895
+ type: "card",
2896
+ attributes,
2897
+ meta: { adoptsFrom: {
2898
+ module: rri("@cardstack/base/command"),
2899
+ name
2900
+ } }
2901
+ } };
2902
+ }
2903
+ (0, import_qunit.test)("a result card whose type has no view of its own stays out of the chat", async function(assert) {
2904
+ simulateToolResult(await renderAiAssistantPanel(), {
2905
+ requestId: "data-only-result",
2906
+ toolName: "oneShotLLMRequest",
2907
+ resultDoc: baseCommandResultDoc("OneShotLLMRequestResult", { output: "a reply for the model" })
2908
+ });
2909
+ await waitFor("[data-test-message-idx=\"0\"] [data-test-tool-call-apply]");
2910
+ await settled();
2911
+ assert.dom("[data-test-message-idx=\"0\"] [data-test-tool-call-apply=\"applied\"]").exists("the tool row shows the call as applied");
2912
+ assert.dom("[data-test-tool-result-container]").doesNotExist("the data-only result card is not rendered");
2913
+ });
2914
+ (0, import_qunit.test)("a result card whose type has its own embedded view is shown", async function(assert) {
2915
+ simulateToolResult(await renderAiAssistantPanel(), {
2916
+ requestId: "patch-fields-result",
2917
+ toolName: "patchFields",
2918
+ resultDoc: baseCommandResultDoc("PatchFieldsOutput", {
2919
+ success: true,
2920
+ updatedFields: ["firstName"],
2921
+ errors: {}
2922
+ })
2923
+ });
2924
+ await waitForToolResult();
2925
+ assert.dom("[data-test-tool-result-header]").containsText("patchFields", "the result's meta line names the call");
2926
+ assert.dom("[data-test-boxel-tool-call-result]").containsText("Updated 1 field: firstName.");
2927
+ });
2928
+ (0, import_qunit.test)("a failed correctness check shows its failed state without a result card", async function(assert) {
2929
+ simulateToolResult(await renderAiAssistantPanel(), {
2930
+ requestId: "failed-correctness-check",
2931
+ toolName: "checkCorrectness",
2932
+ resultDoc: baseCommandResultDoc("CorrectnessResultCard", {
2933
+ correct: false,
2934
+ errors: ["The card does not render"],
2935
+ warnings: []
2936
+ })
2937
+ });
2938
+ await waitFor("[data-test-message-idx=\"0\"] [data-test-tool-call-apply=\"applied-with-error\"]");
2939
+ assert.dom("[data-test-message-idx=\"0\"] .room-message-tool.is-failed").exists("the tool row shows the failed check");
2940
+ assert.dom("[data-test-tool-result-container]").doesNotExist("the correctness result card is not rendered");
2941
+ });
2942
+ (0, import_qunit.test)("a check of several targets lists its errors and counts the rest", async function(assert) {
2943
+ let roomId = await renderAiAssistantPanel();
2944
+ let target = (n) => `${testRealmURL}Product/${n}`;
2945
+ simulateToolResult(roomId, {
2946
+ requestId: "batched-correctness-check",
2947
+ toolName: "checkCorrectness",
2948
+ args: {
2949
+ description: "Check 3 cards and 1 file",
2950
+ attributes: { targets: [
2951
+ {
2952
+ type: "file",
2953
+ ref: `${testRealmURL}product.gts`
2954
+ },
2955
+ {
2956
+ type: "card",
2957
+ ref: target(1)
2958
+ },
2959
+ {
2960
+ type: "card",
2961
+ ref: target(2)
2962
+ },
2963
+ {
2964
+ type: "card",
2965
+ ref: target(3)
2966
+ }
2967
+ ] }
2968
+ },
2969
+ resultDoc: baseCommandResultDoc("CorrectnessResultCard", {
2970
+ correct: false,
2971
+ errors: [`${target(2)}: price must be a number`],
2972
+ warnings: [],
2973
+ targetResults: [{
2974
+ targetType: "card",
2975
+ targetRef: target(2),
2976
+ errors: [`${target(2)}: price must be a number`],
2977
+ warnings: []
2978
+ }],
2979
+ checkedCount: 4,
2980
+ passedCount: 3
2981
+ })
2982
+ });
2983
+ await waitFor("[data-test-message-idx=\"0\"] [data-test-tool-call-apply=\"applied-with-error\"]");
2984
+ await click("[data-test-message-idx=\"0\"] [data-test-pretui-tool-row-toggle]");
2985
+ await waitFor("[data-test-message-idx=\"0\"] [data-test-check-outcome]");
2986
+ assert.dom("[data-test-message-idx=\"0\"] [data-test-pretui-tool-row-title]").hasText("Checked 3 cards and 1 file · errors", "the row counts what it checked");
2987
+ assert.dom("[data-test-message-idx=\"0\"] [data-test-check-outcome]").containsText(`${target(2)}: price must be a number`, "the error is listed").containsText("No errors in the other 2 cards and 1 file", "the passing targets are counted");
2988
+ });
2989
+ (0, import_qunit.test)("a check request carried in Matrix media is shown like an inline one", async function(assert) {
2990
+ let roomId = await renderAiAssistantPanel();
2991
+ let target = (n) => `${testRealmURL}Product/${n}`;
2992
+ simulateToolResult(roomId, {
2993
+ requestId: "media-correctness-check",
2994
+ toolName: "checkCorrectness",
2995
+ inMedia: true,
2996
+ args: {
2997
+ description: "Check 2 cards",
2998
+ attributes: { targets: [{
2999
+ type: "card",
3000
+ ref: target(1)
3001
+ }, {
3002
+ type: "card",
3003
+ ref: target(2)
3004
+ }] }
3005
+ },
3006
+ resultDoc: baseCommandResultDoc("CorrectnessResultCard", {
3007
+ correct: true,
3008
+ errors: [],
3009
+ warnings: [],
3010
+ targetResults: [],
3011
+ checkedCount: 2,
3012
+ passedCount: 2
3013
+ })
3014
+ });
3015
+ await waitFor("[data-test-message-idx=\"0\"] [data-test-pretui-tool-row-title]");
3016
+ assert.dom("[data-test-message-idx=\"0\"] [data-test-pretui-tool-row-title]").containsText("Checked 2 cards", "the request was read from media");
3017
+ });
3018
+ (0, import_qunit.test)("a view-visually result shows the image the assistant looked at", async function(assert) {
3019
+ let roomId = await renderAiAssistantPanel();
3020
+ let imageUrl = new URL("/_matrix/client/v1/media/download/localhost/brand-guide-capture", config.matrixURL).href;
3021
+ let pngBytes = Uint8Array.from(atob("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=="), (c) => c.charCodeAt(0));
3022
+ mockMatrixUtils.getUploadedContents().set(imageUrl, pngBytes.buffer);
3023
+ simulateToolResult(roomId, {
3024
+ requestId: "view-visually-result",
3025
+ toolName: "view-visually",
3026
+ resultDoc: baseCommandResultDoc("ViewVisuallyResult", {
3027
+ sourceUrl: `${testRealmURL}brand-guide.html`,
3028
+ kind: "file",
3029
+ format: "isolated",
3030
+ attachedImages: [{
3031
+ name: "brand-guide.html (isolated).png",
3032
+ url: imageUrl,
3033
+ contentType: "image/png"
3034
+ }]
3035
+ })
3036
+ });
3037
+ await waitFor("[data-test-view-visually-image][src^=\"blob:\"]");
3038
+ assert.dom("[data-test-view-visually-title]").hasText("View of brand-guide.html");
3039
+ assert.dom("[data-test-boxel-tool-call-result]").containsText(`${testRealmURL}brand-guide.html`);
3040
+ let image = find("[data-test-view-visually-image]");
3041
+ await image.decode();
3042
+ assert.strictEqual(image.naturalWidth, 1, "the image loads from the room media downloaded with the session");
3043
+ });
3044
+ (0, import_qunit.test)("room media is loaded with the Matrix session only from the homeserver", async function(assert) {
3045
+ let matrixService = getService("matrix-service");
3046
+ let elsewhere = "https://elsewhere.example/_matrix/client/v1/media/download/x/y";
3047
+ assert.strictEqual(await matrixService.loadRoomMedia(elsewhere), elsewhere, "a URL on another origin comes back unchanged, without a download");
3048
+ let realmFile = `${testRealmURL}brand-guide.png`;
3049
+ assert.strictEqual(await matrixService.loadRoomMedia(realmFile), realmFile, "a URL that is not room media comes back unchanged");
3050
+ let homeserverApi = new URL("/_matrix/client/v3/sync", config.matrixURL).href;
3051
+ assert.strictEqual(await matrixService.loadRoomMedia(homeserverApi), homeserverApi, "a homeserver URL outside its media downloads comes back unchanged");
3052
+ });
3053
+ (0, import_qunit.test)("a run-realm-code result lists the files it saved and the captures it took", async function(assert) {
3054
+ let roomId = await renderAiAssistantPanel();
3055
+ let captureUrl = new URL("/_matrix/client/v1/media/download/localhost/run-capture", config.matrixURL).href;
3056
+ let pngBytes = Uint8Array.from(atob("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=="), (c) => c.charCodeAt(0));
3057
+ mockMatrixUtils.getUploadedContents().set(captureUrl, pngBytes.buffer);
3058
+ let savedFile = `${testRealmURL}brand-guide.html`;
3059
+ simulateToolResult(roomId, {
3060
+ requestId: "run-realm-code-result",
3061
+ toolName: "run-realm-code",
3062
+ resultDoc: baseCommandResultDoc("RunRealmCodeResult", {
3063
+ files: [{
3064
+ fileUrl: savedFile,
3065
+ status: "saved"
3066
+ }],
3067
+ scriptResult: "done",
3068
+ captures: [{
3069
+ name: "brand-guide.html (isolated).png",
3070
+ url: captureUrl,
3071
+ contentType: "image/png"
3072
+ }]
3073
+ })
3074
+ });
3075
+ await waitFor("[data-test-realm-code-capture][src^=\"blob:\"]");
3076
+ assert.dom(`[data-test-realm-code-file="${savedFile}"]`).exists("the saved file is listed; its check says it was saved");
3077
+ assert.dom("[data-test-boxel-tool-call-result]").doesNotContainText("done", "the script's own result stays out of the chat");
3078
+ });
3079
+ (0, import_qunit.test)("a file in a turn's changed files opens in code mode", async function(assert) {
3080
+ let roomId = await renderAiAssistantPanel();
3081
+ let changedFile = `${testRealmURL}hello-world.gts`;
3082
+ simulateRemoteMessage(roomId, "@testuser:localhost", {
3083
+ body: "Change the greeting",
3084
+ msgtype: "m.text"
3085
+ });
3086
+ simulateToolResult(roomId, {
3087
+ requestId: "run-realm-code-edit",
3088
+ toolName: "run-realm-code",
3089
+ resultDoc: baseCommandResultDoc("RunRealmCodeResult", { files: [{
3090
+ fileUrl: changedFile,
3091
+ status: "saved",
3092
+ diff: "- greeting = 'Hello';\n+ greeting = 'Hi';"
3093
+ }] })
3094
+ });
3095
+ simulateRemoteMessage(roomId, "@aibot:localhost", {
3096
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
3097
+ body: "Changed the greeting.",
3098
+ format: "org.matrix.custom.html",
3099
+ isStreamingFinished: true
3100
+ });
3101
+ await waitFor("[data-test-pretui-turn-changes-file$=\"hello-world.gts\"]");
3102
+ assert.strictEqual(operatorModeStateService.state.submode, Submodes.Interact, "the app starts in interact mode");
3103
+ await click("[data-test-pretui-turn-changes-file$=\"hello-world.gts\"]");
3104
+ await waitUntil(() => operatorModeStateService.state.submode === Submodes.Code);
3105
+ assert.strictEqual(operatorModeStateService.state.codePath, rri(changedFile), "code mode opens on the changed file, not on the previous one");
3106
+ });
3107
+ (0, import_qunit.test)("a run-realm-code result says why it could not show a card", async function(assert) {
3108
+ simulateToolResult(await renderAiAssistantPanel(), {
3109
+ requestId: "run-realm-code-not-shown",
3110
+ toolName: "run-realm-code",
3111
+ resultDoc: baseCommandResultDoc("RunRealmCodeResult", {
3112
+ files: [],
3113
+ scriptResult: JSON.stringify({ show: "images/red.png" }),
3114
+ captures: [],
3115
+ showError: "The card was not shown. images/red.png is a file"
3116
+ })
3117
+ });
3118
+ await waitFor("[data-test-realm-code-show-error]");
3119
+ assert.dom("[data-test-realm-code-show-error]").containsText("The card was not shown", "the reason is shown");
3120
+ });
3121
+ (0, import_qunit.test)("a run-realm-code result lists its UI moves, a failed one with why", async function(assert) {
3122
+ simulateToolResult(await renderAiAssistantPanel(), {
3123
+ requestId: "run-realm-code-ui-actions",
3124
+ toolName: "run-realm-code",
3125
+ resultDoc: baseCommandResultDoc("RunRealmCodeResult", {
3126
+ files: [],
3127
+ scriptResult: "",
3128
+ captures: [],
3129
+ uiActions: [{
3130
+ action: "openFile",
3131
+ target: `${testRealmURL}pet.gts`,
3132
+ status: "done"
3133
+ }, {
3134
+ action: "previewFormat",
3135
+ target: `${testRealmURL}Pet/mango (fitted)`,
3136
+ status: "failed",
3137
+ detail: "Card not found"
3138
+ }]
3139
+ })
3140
+ });
3141
+ await waitFor("[data-test-realm-code-ui-action=\"previewFormat\"]");
3142
+ assert.dom("[data-test-realm-code-ui-action=\"openFile\"]").exists("a done UI move is said too, so the reader sees what moved");
3143
+ assert.dom("[data-test-realm-code-ui-action=\"previewFormat\"]").containsText("Card not found", "a failed action says why");
3144
+ });
3145
+ (0, import_qunit.test)("a run-realm-code result lists the workspaces it created and deleted", async function(assert) {
3146
+ let roomId = await renderAiAssistantPanel();
3147
+ let created = "http://test-realm/new-workspace/";
3148
+ let deleted = "http://test-realm/old-workspace/";
3149
+ simulateToolResult(roomId, {
3150
+ requestId: "run-realm-code-workspaces",
3151
+ toolName: "run-realm-code",
3152
+ resultDoc: baseCommandResultDoc("RunRealmCodeResult", {
3153
+ files: [],
3154
+ scriptResult: "",
3155
+ captures: [],
3156
+ createdWorkspaces: [created],
3157
+ deletedWorkspaces: [deleted]
3158
+ })
3159
+ });
3160
+ await waitFor("[data-test-realm-code-created-workspace]");
3161
+ assert.dom("[data-test-realm-code-created-workspace]").containsText(created, "the created workspace is listed");
3162
+ assert.dom("[data-test-realm-code-deleted-workspace]").containsText(deleted, "the deleted workspace is listed");
3163
+ });
3164
+ (0, import_qunit.test)("a run-realm-code result that wrote nothing and had no failure stays out of the chat", async function(assert) {
3165
+ let roomId = await renderAiAssistantPanel();
3166
+ let store = getService("store");
3167
+ let addWithoutPersisting = store.addWithoutPersisting.bind(store);
3168
+ let resultCardMade = new Promise((resolve) => {
3169
+ store.addWithoutPersisting = async (...args) => {
3170
+ let card = await addWithoutPersisting(...args);
3171
+ resolve();
3172
+ return card;
3173
+ };
3174
+ });
3175
+ simulateToolResult(roomId, {
3176
+ requestId: "run-realm-code-read-only",
3177
+ toolName: "run-realm-code",
3178
+ resultDoc: baseCommandResultDoc("RunRealmCodeResult", {
3179
+ files: [],
3180
+ scriptResult: JSON.stringify({ show: "Pet/mango" }),
3181
+ captures: [{
3182
+ name: "pet.gts (isolated).png",
3183
+ url: new URL("/_matrix/client/v1/media/download/localhost/read-only-capture", config.matrixURL).href,
3184
+ contentType: "image/png"
3185
+ }],
3186
+ shownCard: `${testRealmURL}Pet/mango`,
3187
+ uiActions: [{
3188
+ action: "switchSubmode",
3189
+ target: "code",
3190
+ status: "done"
3191
+ }, {
3192
+ action: "openFile",
3193
+ target: `${testRealmURL}pet.gts`,
3194
+ status: "done"
3195
+ }]
3196
+ })
3197
+ });
3198
+ await resultCardMade;
3199
+ await settled();
3200
+ assert.dom("[data-test-message-idx=\"0\"] [data-test-tool-call-apply=\"applied\"]").exists("the tool row shows the call as applied");
3201
+ assert.dom("[data-test-message-idx=\"0\"] [data-test-pretui-card-embed]").doesNotExist("a run that only read, captured, and opened things has no result card");
3202
+ });
3203
+ });
3204
+ //#endregion