@cardstack/boxel-cli 0.2.0-unstable.448 → 0.3.0-unstable.13

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 (879) hide show
  1. package/bundled-types/base/-private.d.ts +1 -0
  2. package/bundled-types/base/address.d.ts +17 -0
  3. package/bundled-types/base/ai-app-generator.d.ts +14 -0
  4. package/bundled-types/base/amount-with-currency.d.ts +10 -0
  5. package/bundled-types/base/avif-image-def.d.ts +12 -0
  6. package/bundled-types/base/avif-meta-extractor.d.ts +4 -0
  7. package/bundled-types/base/base64-image.d.ts +25 -0
  8. package/bundled-types/base/big-integer.d.ts +12 -0
  9. package/bundled-types/base/boolean.d.ts +14 -0
  10. package/bundled-types/base/brand-functional-palette.d.ts +16 -0
  11. package/bundled-types/base/brand-guide.d.ts +26 -0
  12. package/bundled-types/base/brand-logo.d.ts +29 -0
  13. package/bundled-types/base/card-api.d.ts +513 -0
  14. package/bundled-types/base/card-serialization.d.ts +47 -0
  15. package/bundled-types/base/cards-grid.d.ts +10 -0
  16. package/bundled-types/base/code-ref.d.ts +14 -0
  17. package/bundled-types/base/codemirror-editor.d.ts +135 -0
  18. package/bundled-types/base/color-field/components/advanced-color-picker.d.ts +66 -0
  19. package/bundled-types/base/color-field/components/color-picker-field.d.ts +22 -0
  20. package/bundled-types/base/color-field/components/color-wheel-picker.d.ts +44 -0
  21. package/bundled-types/base/color-field/components/contrast-checker-addon.d.ts +14 -0
  22. package/bundled-types/base/color-field/components/recent-colors-addon.d.ts +19 -0
  23. package/bundled-types/base/color-field/components/slider-picker.d.ts +40 -0
  24. package/bundled-types/base/color-field/components/swatches-picker.d.ts +5 -0
  25. package/bundled-types/base/color-field/modifiers/setup-element-modifier.d.ts +10 -0
  26. package/bundled-types/base/color-field/util/color-field-signature.d.ts +9 -0
  27. package/bundled-types/base/color-field/util/color-utils.d.ts +96 -0
  28. package/bundled-types/base/color-field/util/css-color-parsers.d.ts +11 -0
  29. package/bundled-types/base/color.d.ts +10 -0
  30. package/bundled-types/base/command.d.ts +593 -0
  31. package/bundled-types/base/commands/search-card-result.d.ts +36 -0
  32. package/bundled-types/base/components/age.d.ts +22 -0
  33. package/bundled-types/base/components/business-days.d.ts +16 -0
  34. package/bundled-types/base/components/card-list.d.ts +25 -0
  35. package/bundled-types/base/components/cards-grid-layout.d.ts +58 -0
  36. package/bundled-types/base/components/countdown.d.ts +31 -0
  37. package/bundled-types/base/components/expiration-warning.d.ts +24 -0
  38. package/bundled-types/base/components/time-ago.d.ts +24 -0
  39. package/bundled-types/base/components/time-slots.d.ts +20 -0
  40. package/bundled-types/base/components/timeline.d.ts +22 -0
  41. package/bundled-types/base/contains-many-component.d.ts +7 -0
  42. package/bundled-types/base/coordinate.d.ts +7 -0
  43. package/bundled-types/base/country.d.ts +23 -0
  44. package/bundled-types/base/css-value.d.ts +6 -0
  45. package/bundled-types/base/csv-file-def.d.ts +29 -0
  46. package/bundled-types/base/currency.d.ts +16 -0
  47. package/bundled-types/base/date/day.d.ts +9 -0
  48. package/bundled-types/base/date/month-day.d.ts +10 -0
  49. package/bundled-types/base/date/month-year.d.ts +9 -0
  50. package/bundled-types/base/date/month.d.ts +9 -0
  51. package/bundled-types/base/date/quarter.d.ts +10 -0
  52. package/bundled-types/base/date/week.d.ts +9 -0
  53. package/bundled-types/base/date/year.d.ts +9 -0
  54. package/bundled-types/base/date-range-field.d.ts +12 -0
  55. package/bundled-types/base/date.d.ts +12 -0
  56. package/bundled-types/base/datetime-stamp.d.ts +7 -0
  57. package/bundled-types/base/datetime.d.ts +12 -0
  58. package/bundled-types/base/default-templates/atom.d.ts +10 -0
  59. package/bundled-types/base/default-templates/card-info.d.ts +32 -0
  60. package/bundled-types/base/default-templates/embedded.d.ts +11 -0
  61. package/bundled-types/base/default-templates/field-edit.d.ts +10 -0
  62. package/bundled-types/base/default-templates/file-def-edit.d.ts +8 -0
  63. package/bundled-types/base/default-templates/fitted.d.ts +12 -0
  64. package/bundled-types/base/default-templates/head.d.ts +13 -0
  65. package/bundled-types/base/default-templates/image-def-atom.d.ts +8 -0
  66. package/bundled-types/base/default-templates/image-def-embedded.d.ts +8 -0
  67. package/bundled-types/base/default-templates/image-def-fitted.d.ts +8 -0
  68. package/bundled-types/base/default-templates/image-def-isolated.d.ts +8 -0
  69. package/bundled-types/base/default-templates/isolated-and-edit.d.ts +15 -0
  70. package/bundled-types/base/default-templates/markdown-fallback.d.ts +19 -0
  71. package/bundled-types/base/default-templates/markdown.d.ts +60 -0
  72. package/bundled-types/base/default-templates/missing-template.d.ts +13 -0
  73. package/bundled-types/base/default-templates/theme-dashboard.d.ts +126 -0
  74. package/bundled-types/base/detailed-style-reference.d.ts +48 -0
  75. package/bundled-types/base/email.d.ts +10 -0
  76. package/bundled-types/base/enum.d.ts +30 -0
  77. package/bundled-types/base/ethereum-address.d.ts +13 -0
  78. package/bundled-types/base/field-component.d.ts +65 -0
  79. package/bundled-types/base/field-support.d.ts +55 -0
  80. package/bundled-types/base/file-api.d.ts +2 -0
  81. package/bundled-types/base/file-menu-items.d.ts +4 -0
  82. package/bundled-types/base/gif-image-def.d.ts +12 -0
  83. package/bundled-types/base/gif-meta-extractor.d.ts +4 -0
  84. package/bundled-types/base/gts-file-def.d.ts +7 -0
  85. package/bundled-types/base/helpers/country.d.ts +3198 -0
  86. package/bundled-types/base/helpers/sanitized-html.d.ts +2 -0
  87. package/bundled-types/base/helpers/set-background-image.d.ts +2 -0
  88. package/bundled-types/base/image-file-def.d.ts +1 -0
  89. package/bundled-types/base/image.d.ts +8 -0
  90. package/bundled-types/base/index.d.ts +1 -0
  91. package/bundled-types/base/join-the-community.d.ts +14 -0
  92. package/bundled-types/base/jpg-image-def.d.ts +12 -0
  93. package/bundled-types/base/jpg-meta-extractor.d.ts +4 -0
  94. package/bundled-types/base/json-file-def.d.ts +23 -0
  95. package/bundled-types/base/links-to-editor.d.ts +22 -0
  96. package/bundled-types/base/links-to-many-component.d.ts +7 -0
  97. package/bundled-types/base/llm-model.d.ts +6 -0
  98. package/bundled-types/base/markdown-file-def.d.ts +25 -0
  99. package/bundled-types/base/markdown-helpers.d.ts +26 -0
  100. package/bundled-types/base/markdown.d.ts +1 -0
  101. package/bundled-types/base/matrix-event.d.ts +400 -0
  102. package/bundled-types/base/menu-items.d.ts +21 -0
  103. package/bundled-types/base/number/components/badge-counter.d.ts +32 -0
  104. package/bundled-types/base/number/components/badge-metric.d.ts +34 -0
  105. package/bundled-types/base/number/components/badge-notification.d.ts +38 -0
  106. package/bundled-types/base/number/components/gauge.d.ts +45 -0
  107. package/bundled-types/base/number/components/number-input.d.ts +27 -0
  108. package/bundled-types/base/number/components/progress-bar.d.ts +44 -0
  109. package/bundled-types/base/number/components/progress-circle.d.ts +41 -0
  110. package/bundled-types/base/number/components/score.d.ts +41 -0
  111. package/bundled-types/base/number/components/stat.d.ts +38 -0
  112. package/bundled-types/base/number/util/index.d.ts +29 -0
  113. package/bundled-types/base/number.d.ts +52 -0
  114. package/bundled-types/base/percentage.d.ts +9 -0
  115. package/bundled-types/base/phone-number.d.ts +25 -0
  116. package/bundled-types/base/png-image-def.d.ts +12 -0
  117. package/bundled-types/base/png-meta-extractor.d.ts +4 -0
  118. package/bundled-types/base/positioned-card.d.ts +7 -0
  119. package/bundled-types/base/query-field-support.d.ts +6 -0
  120. package/bundled-types/base/realm-config.d.ts +16 -0
  121. package/bundled-types/base/realm.d.ts +7 -0
  122. package/bundled-types/base/resources/command-data.d.ts +43 -0
  123. package/bundled-types/base/response-field.d.ts +6 -0
  124. package/bundled-types/base/rich-markdown.d.ts +30 -0
  125. package/bundled-types/base/shared-state.d.ts +1 -0
  126. package/bundled-types/base/skill-plus.d.ts +79 -0
  127. package/bundled-types/base/skill-reference.d.ts +12 -0
  128. package/bundled-types/base/skill-set.d.ts +18 -0
  129. package/bundled-types/base/skill.d.ts +21 -0
  130. package/bundled-types/base/spec.d.ts +108 -0
  131. package/bundled-types/base/string.d.ts +2 -0
  132. package/bundled-types/base/structured-theme-variables.d.ts +85 -0
  133. package/bundled-types/base/structured-theme.d.ts +32 -0
  134. package/bundled-types/base/style-reference.d.ts +14 -0
  135. package/bundled-types/base/svg-image-def.d.ts +12 -0
  136. package/bundled-types/base/svg-meta-extractor.d.ts +12 -0
  137. package/bundled-types/base/system-card.d.ts +17 -0
  138. package/bundled-types/base/tag.d.ts +15 -0
  139. package/bundled-types/base/text-area.d.ts +2 -0
  140. package/bundled-types/base/text-file-def.d.ts +23 -0
  141. package/bundled-types/base/text-input-validator.d.ts +13 -0
  142. package/bundled-types/base/theme.d.ts +2 -0
  143. package/bundled-types/base/time/duration.d.ts +14 -0
  144. package/bundled-types/base/time/relative-time.d.ts +10 -0
  145. package/bundled-types/base/time/time-range.d.ts +11 -0
  146. package/bundled-types/base/time.d.ts +9 -0
  147. package/bundled-types/base/ts-file-def.d.ts +26 -0
  148. package/bundled-types/base/ts-highlight.d.ts +1 -0
  149. package/bundled-types/base/types/@cardstack/boxel-host/index.d.ts +5 -0
  150. package/bundled-types/base/types/ember-css-url/index.d.ts +15 -0
  151. package/bundled-types/base/typography.d.ts +14 -0
  152. package/bundled-types/base/url.d.ts +13 -0
  153. package/bundled-types/base/watched-array.d.ts +7 -0
  154. package/bundled-types/base/webp-image-def.d.ts +12 -0
  155. package/bundled-types/base/webp-meta-extractor.d.ts +4 -0
  156. package/bundled-types/base/website.d.ts +8 -0
  157. package/bundled-types/base/welcome-to-boxel.d.ts +22 -0
  158. package/bundled-types/boxel-ui/components/accordion/index.gts +50 -0
  159. package/bundled-types/boxel-ui/components/accordion/item/index.gts +156 -0
  160. package/bundled-types/boxel-ui/components/accordion/usage.gts +157 -0
  161. package/bundled-types/boxel-ui/components/add-button/index.gts +46 -0
  162. package/bundled-types/boxel-ui/components/add-button/usage.gts +54 -0
  163. package/bundled-types/boxel-ui/components/alert/index.gts +151 -0
  164. package/bundled-types/boxel-ui/components/alert/usage.gts +66 -0
  165. package/bundled-types/boxel-ui/components/avatar/index.gts +79 -0
  166. package/bundled-types/boxel-ui/components/avatar/usage.gts +96 -0
  167. package/bundled-types/boxel-ui/components/basic-fitted/index.gts +340 -0
  168. package/bundled-types/boxel-ui/components/basic-fitted/usage.gts +223 -0
  169. package/bundled-types/boxel-ui/components/button/index.gts +416 -0
  170. package/bundled-types/boxel-ui/components/button/usage.gts +334 -0
  171. package/bundled-types/boxel-ui/components/card-container/index.gts +251 -0
  172. package/bundled-types/boxel-ui/components/card-container/usage.gts +53 -0
  173. package/bundled-types/boxel-ui/components/card-header/index.gts +473 -0
  174. package/bundled-types/boxel-ui/components/card-header/usage.gts +295 -0
  175. package/bundled-types/boxel-ui/components/circle-spinner/index.gts +42 -0
  176. package/bundled-types/boxel-ui/components/circle-spinner/usage.gts +48 -0
  177. package/bundled-types/boxel-ui/components/color-palette/index.gts +134 -0
  178. package/bundled-types/boxel-ui/components/color-palette/usage.gts +69 -0
  179. package/bundled-types/boxel-ui/components/color-picker/index.gts +125 -0
  180. package/bundled-types/boxel-ui/components/color-picker/usage.gts +56 -0
  181. package/bundled-types/boxel-ui/components/container/index.gts +67 -0
  182. package/bundled-types/boxel-ui/components/container/usage.gts +59 -0
  183. package/bundled-types/boxel-ui/components/context-button/index.gts +184 -0
  184. package/bundled-types/boxel-ui/components/context-button/usage.gts +125 -0
  185. package/bundled-types/boxel-ui/components/copy-button/index.gts +79 -0
  186. package/bundled-types/boxel-ui/components/copy-button/usage.gts +25 -0
  187. package/bundled-types/boxel-ui/components/date-range-picker/index.gts +211 -0
  188. package/bundled-types/boxel-ui/components/date-range-picker/setup.gts +11 -0
  189. package/bundled-types/boxel-ui/components/date-range-picker/usage.gts +52 -0
  190. package/bundled-types/boxel-ui/components/drag-and-drop/index.gts +256 -0
  191. package/bundled-types/boxel-ui/components/drag-and-drop/usage.gts +142 -0
  192. package/bundled-types/boxel-ui/components/dropdown/index.gts +478 -0
  193. package/bundled-types/boxel-ui/components/dropdown/trigger/index.gts +70 -0
  194. package/bundled-types/boxel-ui/components/dropdown/trigger/usage.gts +54 -0
  195. package/bundled-types/boxel-ui/components/dropdown/usage.gts +119 -0
  196. package/bundled-types/boxel-ui/components/email-input/index.gts +111 -0
  197. package/bundled-types/boxel-ui/components/email-input/usage.gts +75 -0
  198. package/bundled-types/boxel-ui/components/entity-icon-display/index.gts +144 -0
  199. package/bundled-types/boxel-ui/components/entity-icon-display/usage.gts +54 -0
  200. package/bundled-types/boxel-ui/components/entity-thumbnail-display/index.gts +148 -0
  201. package/bundled-types/boxel-ui/components/entity-thumbnail-display/usage.gts +76 -0
  202. package/bundled-types/boxel-ui/components/field-container/index.gts +150 -0
  203. package/bundled-types/boxel-ui/components/field-container/usage.gts +188 -0
  204. package/bundled-types/boxel-ui/components/filter-list/index.gts +255 -0
  205. package/bundled-types/boxel-ui/components/filter-list/usage.gts +153 -0
  206. package/bundled-types/boxel-ui/components/fitted-card-container/index.gts +66 -0
  207. package/bundled-types/boxel-ui/components/fitted-card-container/usage.gts +81 -0
  208. package/bundled-types/boxel-ui/components/grid-container/grid-item-container/index.gts +37 -0
  209. package/bundled-types/boxel-ui/components/grid-container/index.gts +116 -0
  210. package/bundled-types/boxel-ui/components/grid-container/usage.gts +105 -0
  211. package/bundled-types/boxel-ui/components/header/index.gts +101 -0
  212. package/bundled-types/boxel-ui/components/header/usage.gts +116 -0
  213. package/bundled-types/boxel-ui/components/icon-button/index.gts +148 -0
  214. package/bundled-types/boxel-ui/components/icon-button/usage.gts +249 -0
  215. package/bundled-types/boxel-ui/components/input/index.gts +560 -0
  216. package/bundled-types/boxel-ui/components/input/usage.gts +449 -0
  217. package/bundled-types/boxel-ui/components/input-group/accessories/index.gts +191 -0
  218. package/bundled-types/boxel-ui/components/input-group/controls/index.gts +54 -0
  219. package/bundled-types/boxel-ui/components/input-group/index.gts +347 -0
  220. package/bundled-types/boxel-ui/components/input-group/usage.gts +437 -0
  221. package/bundled-types/boxel-ui/components/kanban/card.gts +89 -0
  222. package/bundled-types/boxel-ui/components/kanban/column-header.gts +151 -0
  223. package/bundled-types/boxel-ui/components/kanban/drag.gts +1007 -0
  224. package/bundled-types/boxel-ui/components/kanban/engine.ts +247 -0
  225. package/bundled-types/boxel-ui/components/kanban/ghost.gts +64 -0
  226. package/bundled-types/boxel-ui/components/kanban/index.gts +16 -0
  227. package/bundled-types/boxel-ui/components/kanban/modifiers.gts +42 -0
  228. package/bundled-types/boxel-ui/components/kanban/plane-inner.gts +525 -0
  229. package/bundled-types/boxel-ui/components/kanban/plane.gts +163 -0
  230. package/bundled-types/boxel-ui/components/kanban/usage.gts +392 -0
  231. package/bundled-types/boxel-ui/components/label/index.gts +64 -0
  232. package/bundled-types/boxel-ui/components/loading-indicator/index.gts +78 -0
  233. package/bundled-types/boxel-ui/components/loading-indicator/usage.gts +72 -0
  234. package/bundled-types/boxel-ui/components/menu/index.gts +267 -0
  235. package/bundled-types/boxel-ui/components/menu/usage.gts +100 -0
  236. package/bundled-types/boxel-ui/components/message/index.gts +146 -0
  237. package/bundled-types/boxel-ui/components/message/usage.gts +263 -0
  238. package/bundled-types/boxel-ui/components/modal/index.gts +159 -0
  239. package/bundled-types/boxel-ui/components/modal/usage.gts +206 -0
  240. package/bundled-types/boxel-ui/components/multi-select/after-options.gts +59 -0
  241. package/bundled-types/boxel-ui/components/multi-select/index.gts +230 -0
  242. package/bundled-types/boxel-ui/components/multi-select/selected-item.gts +91 -0
  243. package/bundled-types/boxel-ui/components/multi-select/trigger.gts +190 -0
  244. package/bundled-types/boxel-ui/components/multi-select/usage.gts +420 -0
  245. package/bundled-types/boxel-ui/components/phone-input/index.gts +149 -0
  246. package/bundled-types/boxel-ui/components/phone-input/usage.gts +73 -0
  247. package/bundled-types/boxel-ui/components/picker/before-options-with-search.gts +340 -0
  248. package/bundled-types/boxel-ui/components/picker/index.gts +427 -0
  249. package/bundled-types/boxel-ui/components/picker/option-row.gts +270 -0
  250. package/bundled-types/boxel-ui/components/picker/selected-item.gts +171 -0
  251. package/bundled-types/boxel-ui/components/picker/trigger-labeled.gts +216 -0
  252. package/bundled-types/boxel-ui/components/picker/usage.gts +179 -0
  253. package/bundled-types/boxel-ui/components/pill/index.gts +231 -0
  254. package/bundled-types/boxel-ui/components/pill/usage.gts +230 -0
  255. package/bundled-types/boxel-ui/components/progress-bar/index.gts +124 -0
  256. package/bundled-types/boxel-ui/components/progress-bar/usage.gts +131 -0
  257. package/bundled-types/boxel-ui/components/progress-radial/index.gts +95 -0
  258. package/bundled-types/boxel-ui/components/progress-radial/usage.gts +79 -0
  259. package/bundled-types/boxel-ui/components/radio-input/index.gts +143 -0
  260. package/bundled-types/boxel-ui/components/radio-input/item.gts +210 -0
  261. package/bundled-types/boxel-ui/components/radio-input/usage.gts +303 -0
  262. package/bundled-types/boxel-ui/components/realm-icon/index.gts +129 -0
  263. package/bundled-types/boxel-ui/components/realm-icon/usage.gts +62 -0
  264. package/bundled-types/boxel-ui/components/resizable-panel-group/handle.gts +180 -0
  265. package/bundled-types/boxel-ui/components/resizable-panel-group/index.gts +341 -0
  266. package/bundled-types/boxel-ui/components/resizable-panel-group/panel.gts +86 -0
  267. package/bundled-types/boxel-ui/components/resizable-panel-group/usage.gts +350 -0
  268. package/bundled-types/boxel-ui/components/resizable-panel-group/utils/adjust-layout-by-delta.ts +231 -0
  269. package/bundled-types/boxel-ui/components/resizable-panel-group/utils/assert.ts +10 -0
  270. package/bundled-types/boxel-ui/components/resizable-panel-group/utils/calculate-delta-percentage.ts +41 -0
  271. package/bundled-types/boxel-ui/components/resizable-panel-group/utils/calculate-unsafe-default-layout.ts +53 -0
  272. package/bundled-types/boxel-ui/components/resizable-panel-group/utils/compare-layouts.ts +12 -0
  273. package/bundled-types/boxel-ui/components/resizable-panel-group/utils/const.ts +6 -0
  274. package/bundled-types/boxel-ui/components/resizable-panel-group/utils/determine-pivot-indices.ts +15 -0
  275. package/bundled-types/boxel-ui/components/resizable-panel-group/utils/dom/get-panel-element.ts +10 -0
  276. package/bundled-types/boxel-ui/components/resizable-panel-group/utils/dom/get-panel-elements-for-group.ts +8 -0
  277. package/bundled-types/boxel-ui/components/resizable-panel-group/utils/dom/get-panel-group-element.ts +21 -0
  278. package/bundled-types/boxel-ui/components/resizable-panel-group/utils/dom/get-resize-handle-element-index.ts +14 -0
  279. package/bundled-types/boxel-ui/components/resizable-panel-group/utils/dom/get-resize-handle-element.ts +12 -0
  280. package/bundled-types/boxel-ui/components/resizable-panel-group/utils/dom/get-resize-handle-elements-for-group.ts +10 -0
  281. package/bundled-types/boxel-ui/components/resizable-panel-group/utils/fuzzy-layouts-equal.ts +22 -0
  282. package/bundled-types/boxel-ui/components/resizable-panel-group/utils/fuzzy-numbers.ts +21 -0
  283. package/bundled-types/boxel-ui/components/resizable-panel-group/utils/get-resize-event-coordinates.ts +8 -0
  284. package/bundled-types/boxel-ui/components/resizable-panel-group/utils/get-resize-event-cursor-position.ts +10 -0
  285. package/bundled-types/boxel-ui/components/resizable-panel-group/utils/panel-resize-handle-registry.ts +446 -0
  286. package/bundled-types/boxel-ui/components/resizable-panel-group/utils/resize-panel.ts +35 -0
  287. package/bundled-types/boxel-ui/components/resizable-panel-group/utils/types.ts +23 -0
  288. package/bundled-types/boxel-ui/components/resizable-panel-group/utils/validate-panel-group-layout.ts +86 -0
  289. package/bundled-types/boxel-ui/components/select/index.gts +882 -0
  290. package/bundled-types/boxel-ui/components/select/trigger.gts +132 -0
  291. package/bundled-types/boxel-ui/components/select/usage.gts +353 -0
  292. package/bundled-types/boxel-ui/components/skeleton-placeholder/index.gts +89 -0
  293. package/bundled-types/boxel-ui/components/skeleton-placeholder/usage.gts +102 -0
  294. package/bundled-types/boxel-ui/components/sort-dropdown/index.gts +91 -0
  295. package/bundled-types/boxel-ui/components/sort-dropdown/usage.gts +77 -0
  296. package/bundled-types/boxel-ui/components/swatch/index.gts +81 -0
  297. package/bundled-types/boxel-ui/components/swatch/usage.gts +57 -0
  298. package/bundled-types/boxel-ui/components/switch/index.gts +95 -0
  299. package/bundled-types/boxel-ui/components/switch/usage.gts +79 -0
  300. package/bundled-types/boxel-ui/components/tabbed-header/index.gts +141 -0
  301. package/bundled-types/boxel-ui/components/tabbed-header/usage.gts +103 -0
  302. package/bundled-types/boxel-ui/components/tag/index.gts +50 -0
  303. package/bundled-types/boxel-ui/components/tag/usage.gts +89 -0
  304. package/bundled-types/boxel-ui/components/tag-list/index.gts +85 -0
  305. package/bundled-types/boxel-ui/components/tag-list/usage.gts +129 -0
  306. package/bundled-types/boxel-ui/components/tooltip/index.gts +306 -0
  307. package/bundled-types/boxel-ui/components/tooltip/usage.gts +168 -0
  308. package/bundled-types/boxel-ui/components/view-selector/index.gts +166 -0
  309. package/bundled-types/boxel-ui/components/view-selector/usage.gts +149 -0
  310. package/bundled-types/boxel-ui/components.ts +169 -0
  311. package/bundled-types/boxel-ui/helpers/add-class-to-svg.ts +8 -0
  312. package/bundled-types/boxel-ui/helpers/clipboard.ts +21 -0
  313. package/bundled-types/boxel-ui/helpers/cn.ts +12 -0
  314. package/bundled-types/boxel-ui/helpers/color-tools.ts +331 -0
  315. package/bundled-types/boxel-ui/helpers/compact.ts +3 -0
  316. package/bundled-types/boxel-ui/helpers/contrast-color.ts +32 -0
  317. package/bundled-types/boxel-ui/helpers/css-var.ts +41 -0
  318. package/bundled-types/boxel-ui/helpers/currency-format.ts +25 -0
  319. package/bundled-types/boxel-ui/helpers/dayjs-format.ts +27 -0
  320. package/bundled-types/boxel-ui/helpers/deterministic-color-from-string.ts +45 -0
  321. package/bundled-types/boxel-ui/helpers/element.ts +16 -0
  322. package/bundled-types/boxel-ui/helpers/extract-css-variables.ts +126 -0
  323. package/bundled-types/boxel-ui/helpers/format-age.ts +72 -0
  324. package/bundled-types/boxel-ui/helpers/format-countdown.ts +110 -0
  325. package/bundled-types/boxel-ui/helpers/format-currency.ts +95 -0
  326. package/bundled-types/boxel-ui/helpers/format-date-time.ts +567 -0
  327. package/bundled-types/boxel-ui/helpers/format-duration.ts +143 -0
  328. package/bundled-types/boxel-ui/helpers/format-file-size.ts +49 -0
  329. package/bundled-types/boxel-ui/helpers/format-list.ts +73 -0
  330. package/bundled-types/boxel-ui/helpers/format-names.ts +103 -0
  331. package/bundled-types/boxel-ui/helpers/format-number.ts +140 -0
  332. package/bundled-types/boxel-ui/helpers/format-ordinal.ts +115 -0
  333. package/bundled-types/boxel-ui/helpers/format-period.ts +188 -0
  334. package/bundled-types/boxel-ui/helpers/format-relative-time.ts +789 -0
  335. package/bundled-types/boxel-ui/helpers/generate-css-variables.ts +47 -0
  336. package/bundled-types/boxel-ui/helpers/markdown-escape.ts +36 -0
  337. package/bundled-types/boxel-ui/helpers/math-helpers.ts +18 -0
  338. package/bundled-types/boxel-ui/helpers/menu-divider.ts +15 -0
  339. package/bundled-types/boxel-ui/helpers/menu-item.ts +76 -0
  340. package/bundled-types/boxel-ui/helpers/optional.ts +7 -0
  341. package/bundled-types/boxel-ui/helpers/pick.ts +11 -0
  342. package/bundled-types/boxel-ui/helpers/sanitize-html.ts +45 -0
  343. package/bundled-types/boxel-ui/helpers/string.ts +15 -0
  344. package/bundled-types/boxel-ui/helpers/theme-css.ts +148 -0
  345. package/bundled-types/boxel-ui/helpers/truth-helpers.ts +48 -0
  346. package/bundled-types/boxel-ui/helpers/validate-email-format.ts +138 -0
  347. package/bundled-types/boxel-ui/helpers/validate-phone-format.ts +201 -0
  348. package/bundled-types/boxel-ui/helpers.ts +134 -0
  349. package/bundled-types/boxel-ui/icons/ai-bw.gts +22 -0
  350. package/bundled-types/boxel-ui/icons/arrow-left.gts +25 -0
  351. package/bundled-types/boxel-ui/icons/arrow-right.gts +28 -0
  352. package/bundled-types/boxel-ui/icons/arrow-top-left.gts +22 -0
  353. package/bundled-types/boxel-ui/icons/arrow-up.gts +25 -0
  354. package/bundled-types/boxel-ui/icons/atom.gts +26 -0
  355. package/bundled-types/boxel-ui/icons/boxel-icon-with-text.gts +29 -0
  356. package/bundled-types/boxel-ui/icons/boxel-icon.gts +34 -0
  357. package/bundled-types/boxel-ui/icons/card-definition.gts +26 -0
  358. package/bundled-types/boxel-ui/icons/card-instance.gts +26 -0
  359. package/bundled-types/boxel-ui/icons/card.gts +24 -0
  360. package/bundled-types/boxel-ui/icons/cardbot-lg.gts +24 -0
  361. package/bundled-types/boxel-ui/icons/caret-down.gts +23 -0
  362. package/bundled-types/boxel-ui/icons/caret-up.gts +23 -0
  363. package/bundled-types/boxel-ui/icons/check-mark.gts +23 -0
  364. package/bundled-types/boxel-ui/icons/chevron-right.gts +23 -0
  365. package/bundled-types/boxel-ui/icons/copy.gts +28 -0
  366. package/bundled-types/boxel-ui/icons/diagonal-arrow-left-up.gts +21 -0
  367. package/bundled-types/boxel-ui/icons/download.gts +19 -0
  368. package/bundled-types/boxel-ui/icons/dropdown-arrow-down.gts +20 -0
  369. package/bundled-types/boxel-ui/icons/dropdown-arrow-filled.gts +19 -0
  370. package/bundled-types/boxel-ui/icons/dropdown-arrow-up.gts +20 -0
  371. package/bundled-types/boxel-ui/icons/edit.gts +14 -0
  372. package/bundled-types/boxel-ui/icons/embedded.gts +34 -0
  373. package/bundled-types/boxel-ui/icons/exclamation-circle.gts +26 -0
  374. package/bundled-types/boxel-ui/icons/exclamation.gts +20 -0
  375. package/bundled-types/boxel-ui/icons/eye.gts +19 -0
  376. package/bundled-types/boxel-ui/icons/failure-bordered.gts +26 -0
  377. package/bundled-types/boxel-ui/icons/field.gts +26 -0
  378. package/bundled-types/boxel-ui/icons/file-alert.gts +28 -0
  379. package/bundled-types/boxel-ui/icons/file.gts +27 -0
  380. package/bundled-types/boxel-ui/icons/fitted.gts +42 -0
  381. package/bundled-types/boxel-ui/icons/folder.gts +26 -0
  382. package/bundled-types/boxel-ui/icons/form.gts +38 -0
  383. package/bundled-types/boxel-ui/icons/four-lines.gts +21 -0
  384. package/bundled-types/boxel-ui/icons/grid-3x3.gts +26 -0
  385. package/bundled-types/boxel-ui/icons/group.gts +22 -0
  386. package/bundled-types/boxel-ui/icons/head.gts +28 -0
  387. package/bundled-types/boxel-ui/icons/highlight-icon.gts +46 -0
  388. package/bundled-types/boxel-ui/icons/icon-circle-selected.gts +25 -0
  389. package/bundled-types/boxel-ui/icons/icon-circle.gts +25 -0
  390. package/bundled-types/boxel-ui/icons/icon-code.gts +22 -0
  391. package/bundled-types/boxel-ui/icons/icon-funnel.gts +23 -0
  392. package/bundled-types/boxel-ui/icons/icon-globe.gts +19 -0
  393. package/bundled-types/boxel-ui/icons/icon-grid.gts +68 -0
  394. package/bundled-types/boxel-ui/icons/icon-hexagon.gts +22 -0
  395. package/bundled-types/boxel-ui/icons/icon-inherit.gts +19 -0
  396. package/bundled-types/boxel-ui/icons/icon-link.gts +20 -0
  397. package/bundled-types/boxel-ui/icons/icon-list.gts +40 -0
  398. package/bundled-types/boxel-ui/icons/icon-minus-circle.gts +26 -0
  399. package/bundled-types/boxel-ui/icons/icon-pencil-crossed-out.gts +33 -0
  400. package/bundled-types/boxel-ui/icons/icon-pencil-not-crossed-out.gts +21 -0
  401. package/bundled-types/boxel-ui/icons/icon-pencil.gts +23 -0
  402. package/bundled-types/boxel-ui/icons/icon-plus-circle.gts +31 -0
  403. package/bundled-types/boxel-ui/icons/icon-plus-thin.gts +19 -0
  404. package/bundled-types/boxel-ui/icons/icon-plus.gts +20 -0
  405. package/bundled-types/boxel-ui/icons/icon-search-thick.gts +27 -0
  406. package/bundled-types/boxel-ui/icons/icon-search.gts +25 -0
  407. package/bundled-types/boxel-ui/icons/icon-table.gts +44 -0
  408. package/bundled-types/boxel-ui/icons/icon-trash.gts +24 -0
  409. package/bundled-types/boxel-ui/icons/icon-turn-down-right.gts +18 -0
  410. package/bundled-types/boxel-ui/icons/icon-x.gts +21 -0
  411. package/bundled-types/boxel-ui/icons/image-placeholder.gts +30 -0
  412. package/bundled-types/boxel-ui/icons/isolated.gts +20 -0
  413. package/bundled-types/boxel-ui/icons/loading-indicator.gts +26 -0
  414. package/bundled-types/boxel-ui/icons/lock.gts +23 -0
  415. package/bundled-types/boxel-ui/icons/markdown.gts +19 -0
  416. package/bundled-types/boxel-ui/icons/profile.gts +23 -0
  417. package/bundled-types/boxel-ui/icons/publish-site-icon.gts +25 -0
  418. package/bundled-types/boxel-ui/icons/rows-4.gts +26 -0
  419. package/bundled-types/boxel-ui/icons/select-all.gts +25 -0
  420. package/bundled-types/boxel-ui/icons/send.gts +21 -0
  421. package/bundled-types/boxel-ui/icons/sparkle.gts +21 -0
  422. package/bundled-types/boxel-ui/icons/star-filled.gts +25 -0
  423. package/bundled-types/boxel-ui/icons/star-half-fill.gts +27 -0
  424. package/bundled-types/boxel-ui/icons/star.gts +25 -0
  425. package/bundled-types/boxel-ui/icons/success-bordered.gts +30 -0
  426. package/bundled-types/boxel-ui/icons/three-dots-horizontal.gts +21 -0
  427. package/bundled-types/boxel-ui/icons/triangle-left.gts +23 -0
  428. package/bundled-types/boxel-ui/icons/triangle-right.gts +23 -0
  429. package/bundled-types/boxel-ui/icons/types.ts +10 -0
  430. package/bundled-types/boxel-ui/icons/upload.gts +20 -0
  431. package/bundled-types/boxel-ui/icons/warning.gts +19 -0
  432. package/bundled-types/boxel-ui/icons.gts +249 -0
  433. package/bundled-types/boxel-ui/modifiers/auto-focus.ts +7 -0
  434. package/bundled-types/boxel-ui/modifiers/set-css-var.ts +24 -0
  435. package/bundled-types/boxel-ui/modifiers.ts +14 -0
  436. package/bundled-types/boxel-ui/types/@cardstack/boxel-ui/index.d.ts +3 -0
  437. package/bundled-types/boxel-ui/types/ember-css-url/index.d.ts +15 -0
  438. package/bundled-types/boxel-ui/types/ember-draggable-modifiers/index.d.ts +109 -0
  439. package/bundled-types/boxel-ui/types/ember-draggable-modifiers/utils.d.ts +7 -0
  440. package/bundled-types/boxel-ui/types/ember-focus-trap/index.d.ts +20 -0
  441. package/bundled-types/boxel-ui/types/ember-power-calendar/components/index.d.ts +9 -0
  442. package/bundled-types/boxel-ui/types/ember-resize-modifier/index.d.ts +14 -0
  443. package/bundled-types/boxel-ui/types/ember-set-body-class/index.d.ts +12 -0
  444. package/bundled-types/boxel-ui/types/ember-sortable/index.d.ts +52 -0
  445. package/bundled-types/boxel-ui/types/global.d.ts +7 -0
  446. package/bundled-types/boxel-ui/usage.ts +112 -0
  447. package/bundled-types/boxel-ui/utils/date-utils.ts +192 -0
  448. package/bundled-types/boxel-ui/utils/fitted-formats.ts +161 -0
  449. package/bundled-types/host-app/app.ts +22 -0
  450. package/bundled-types/host-app/commands/add-field-to-card-definition.ts +74 -0
  451. package/bundled-types/host-app/commands/ai-assistant.ts +203 -0
  452. package/bundled-types/host-app/commands/apply-markdown-edit.ts +203 -0
  453. package/bundled-types/host-app/commands/apply-search-replace-block.ts +225 -0
  454. package/bundled-types/host-app/commands/ask-ai.ts +66 -0
  455. package/bundled-types/host-app/commands/authed-fetch.ts +53 -0
  456. package/bundled-types/host-app/commands/bot-requests/create-listing-pr-request.ts +77 -0
  457. package/bundled-types/host-app/commands/bot-requests/send-bot-trigger-event.ts +53 -0
  458. package/bundled-types/host-app/commands/can-read-realm.ts +34 -0
  459. package/bundled-types/host-app/commands/cancel-indexing-job.ts +29 -0
  460. package/bundled-types/host-app/commands/check-correctness.ts +309 -0
  461. package/bundled-types/host-app/commands/copy-and-edit.ts +311 -0
  462. package/bundled-types/host-app/commands/copy-card-as-markdown.ts +41 -0
  463. package/bundled-types/host-app/commands/copy-card-to-stack.ts +70 -0
  464. package/bundled-types/host-app/commands/copy-card.ts +67 -0
  465. package/bundled-types/host-app/commands/copy-file-to-realm.ts +82 -0
  466. package/bundled-types/host-app/commands/copy-source.ts +46 -0
  467. package/bundled-types/host-app/commands/create-ai-assistant-room.ts +144 -0
  468. package/bundled-types/host-app/commands/create-and-open-submission-workflow-card.ts +30 -0
  469. package/bundled-types/host-app/commands/create-specs.ts +422 -0
  470. package/bundled-types/host-app/commands/create-submission-workflow.ts +172 -0
  471. package/bundled-types/host-app/commands/evaluate-module.ts +119 -0
  472. package/bundled-types/host-app/commands/execute-atomic-operations.ts +44 -0
  473. package/bundled-types/host-app/commands/fetch-card-json.ts +33 -0
  474. package/bundled-types/host-app/commands/full-reindex-realm.ts +30 -0
  475. package/bundled-types/host-app/commands/generate-example-cards.ts +298 -0
  476. package/bundled-types/host-app/commands/generate-readme-spec.ts +116 -0
  477. package/bundled-types/host-app/commands/generate-theme-example.ts +147 -0
  478. package/bundled-types/host-app/commands/generate-thumbnail.ts +247 -0
  479. package/bundled-types/host-app/commands/get-all-realm-metas.ts +38 -0
  480. package/bundled-types/host-app/commands/get-available-realm-identifiers.ts +29 -0
  481. package/bundled-types/host-app/commands/get-card-type-schema.ts +59 -0
  482. package/bundled-types/host-app/commands/get-card.ts +34 -0
  483. package/bundled-types/host-app/commands/get-catalog-realm-identifiers.ts +29 -0
  484. package/bundled-types/host-app/commands/get-default-writable-realm.ts +28 -0
  485. package/bundled-types/host-app/commands/get-events-from-room.ts +70 -0
  486. package/bundled-types/host-app/commands/get-realm-of-resource-identifier.ts +37 -0
  487. package/bundled-types/host-app/commands/get-user-system-card.ts +38 -0
  488. package/bundled-types/host-app/commands/index.ts +590 -0
  489. package/bundled-types/host-app/commands/instantiate-card.ts +185 -0
  490. package/bundled-types/host-app/commands/invalidate-realm-identifiers.ts +33 -0
  491. package/bundled-types/host-app/commands/invite-user-to-room.ts +34 -0
  492. package/bundled-types/host-app/commands/lint-and-fix.ts +60 -0
  493. package/bundled-types/host-app/commands/listing-action-build.ts +79 -0
  494. package/bundled-types/host-app/commands/listing-action-init.ts +106 -0
  495. package/bundled-types/host-app/commands/listing-create.ts +632 -0
  496. package/bundled-types/host-app/commands/listing-generate-example.ts +83 -0
  497. package/bundled-types/host-app/commands/listing-install.ts +227 -0
  498. package/bundled-types/host-app/commands/listing-remix.ts +150 -0
  499. package/bundled-types/host-app/commands/listing-update-specs.ts +116 -0
  500. package/bundled-types/host-app/commands/listing-use.ts +97 -0
  501. package/bundled-types/host-app/commands/one-shot-llm-request.ts +209 -0
  502. package/bundled-types/host-app/commands/open-ai-assistant-room.ts +38 -0
  503. package/bundled-types/host-app/commands/open-create-listing-modal.ts +52 -0
  504. package/bundled-types/host-app/commands/open-in-interact-mode.ts +36 -0
  505. package/bundled-types/host-app/commands/open-workspace.ts +38 -0
  506. package/bundled-types/host-app/commands/patch-card-instance.ts +108 -0
  507. package/bundled-types/host-app/commands/patch-code.ts +243 -0
  508. package/bundled-types/host-app/commands/patch-fields.ts +304 -0
  509. package/bundled-types/host-app/commands/patch-theme.ts +52 -0
  510. package/bundled-types/host-app/commands/persist-module-inspector-view.ts +41 -0
  511. package/bundled-types/host-app/commands/populate-with-sample-data.ts +84 -0
  512. package/bundled-types/host-app/commands/preview-format.ts +52 -0
  513. package/bundled-types/host-app/commands/read-binary-file.ts +62 -0
  514. package/bundled-types/host-app/commands/read-card-for-ai-assistant.ts +50 -0
  515. package/bundled-types/host-app/commands/read-file-for-ai-assistant.ts +46 -0
  516. package/bundled-types/host-app/commands/read-source.ts +46 -0
  517. package/bundled-types/host-app/commands/read-text-file.ts +44 -0
  518. package/bundled-types/host-app/commands/register-bot.ts +42 -0
  519. package/bundled-types/host-app/commands/reindex-realm.ts +30 -0
  520. package/bundled-types/host-app/commands/retry-submission-workflow.ts +119 -0
  521. package/bundled-types/host-app/commands/sanitize-module-list.ts +83 -0
  522. package/bundled-types/host-app/commands/save-card.ts +44 -0
  523. package/bundled-types/host-app/commands/screenshot-card.ts +148 -0
  524. package/bundled-types/host-app/commands/search-and-choose.ts +180 -0
  525. package/bundled-types/host-app/commands/search-cards.ts +102 -0
  526. package/bundled-types/host-app/commands/search-google-images.ts +100 -0
  527. package/bundled-types/host-app/commands/send-ai-assistant-message.ts +122 -0
  528. package/bundled-types/host-app/commands/send-request-via-proxy.ts +70 -0
  529. package/bundled-types/host-app/commands/serialize-card.ts +45 -0
  530. package/bundled-types/host-app/commands/set-active-llm.ts +39 -0
  531. package/bundled-types/host-app/commands/set-user-system-card.ts +29 -0
  532. package/bundled-types/host-app/commands/show-card.ts +102 -0
  533. package/bundled-types/host-app/commands/show-file.ts +39 -0
  534. package/bundled-types/host-app/commands/store-add.ts +37 -0
  535. package/bundled-types/host-app/commands/summarize-session.ts +82 -0
  536. package/bundled-types/host-app/commands/switch-submode.ts +112 -0
  537. package/bundled-types/host-app/commands/sync-openrouter-models.ts +373 -0
  538. package/bundled-types/host-app/commands/transform-cards.ts +59 -0
  539. package/bundled-types/host-app/commands/unregister-bot.ts +29 -0
  540. package/bundled-types/host-app/commands/update-code-path-with-selection.ts +45 -0
  541. package/bundled-types/host-app/commands/update-playground-selection.ts +37 -0
  542. package/bundled-types/host-app/commands/update-room-skills.ts +231 -0
  543. package/bundled-types/host-app/commands/utils.ts +178 -0
  544. package/bundled-types/host-app/commands/validate-realm.ts +40 -0
  545. package/bundled-types/host-app/commands/write-binary-file.ts +142 -0
  546. package/bundled-types/host-app/commands/write-text-file.ts +104 -0
  547. package/bundled-types/host-app/components/.gitkeep +0 -0
  548. package/bundled-types/host-app/components/ai-assistant/action-bar.gts +188 -0
  549. package/bundled-types/host-app/components/ai-assistant/ai-assist-button-active-bg.webp +0 -0
  550. package/bundled-types/host-app/components/ai-assistant/ai-assist-button-active-bg@2x.webp +0 -0
  551. package/bundled-types/host-app/components/ai-assistant/ai-assist-button-active-bg@3x.webp +0 -0
  552. package/bundled-types/host-app/components/ai-assistant/ai-assist-icon-animated.webp +0 -0
  553. package/bundled-types/host-app/components/ai-assistant/ai-assist-icon-bw.png +0 -0
  554. package/bundled-types/host-app/components/ai-assistant/ai-assist-icon-bw@2x.png +0 -0
  555. package/bundled-types/host-app/components/ai-assistant/ai-assist-icon-bw@3x.png +0 -0
  556. package/bundled-types/host-app/components/ai-assistant/ai-assist-icon.webp +0 -0
  557. package/bundled-types/host-app/components/ai-assistant/ai-assist-icon@2x.webp +0 -0
  558. package/bundled-types/host-app/components/ai-assistant/ai-assist-icon@3x.webp +0 -0
  559. package/bundled-types/host-app/components/ai-assistant/apply-button/index.gts +226 -0
  560. package/bundled-types/host-app/components/ai-assistant/apply-button/usage.gts +81 -0
  561. package/bundled-types/host-app/components/ai-assistant/attached-file-dropdown-menu.gts +179 -0
  562. package/bundled-types/host-app/components/ai-assistant/attachment-picker/attach-button.gts +176 -0
  563. package/bundled-types/host-app/components/ai-assistant/attachment-picker/attached-items.gts +271 -0
  564. package/bundled-types/host-app/components/ai-assistant/attachment-picker/index.gts +144 -0
  565. package/bundled-types/host-app/components/ai-assistant/attachment-picker/usage.gts +127 -0
  566. package/bundled-types/host-app/components/ai-assistant/button.gts +60 -0
  567. package/bundled-types/host-app/components/ai-assistant/chat-input/index.gts +203 -0
  568. package/bundled-types/host-app/components/ai-assistant/chat-input/usage.gts +68 -0
  569. package/bundled-types/host-app/components/ai-assistant/code-block/actions.gts +58 -0
  570. package/bundled-types/host-app/components/ai-assistant/code-block/apply-code-patch-button.gts +66 -0
  571. package/bundled-types/host-app/components/ai-assistant/code-block/command-header.gts +115 -0
  572. package/bundled-types/host-app/components/ai-assistant/code-block/diff-editor-header.gts +209 -0
  573. package/bundled-types/host-app/components/ai-assistant/code-block/index.gts +228 -0
  574. package/bundled-types/host-app/components/ai-assistant/code-block/patch-footer.gts +32 -0
  575. package/bundled-types/host-app/components/ai-assistant/code-block/view-code-button.gts +73 -0
  576. package/bundled-types/host-app/components/ai-assistant/focus-pill/index.gts +60 -0
  577. package/bundled-types/host-app/components/ai-assistant/focus-pill/usage.gts +45 -0
  578. package/bundled-types/host-app/components/ai-assistant/llm-mode-toggle.gts +113 -0
  579. package/bundled-types/host-app/components/ai-assistant/llm-select.gts +158 -0
  580. package/bundled-types/host-app/components/ai-assistant/message/aibot-message.gts +374 -0
  581. package/bundled-types/host-app/components/ai-assistant/message/attachments.gts +153 -0
  582. package/bundled-types/host-app/components/ai-assistant/message/index.gts +678 -0
  583. package/bundled-types/host-app/components/ai-assistant/message/meta.gts +66 -0
  584. package/bundled-types/host-app/components/ai-assistant/message/text-content.gts +32 -0
  585. package/bundled-types/host-app/components/ai-assistant/message/usage.gts +182 -0
  586. package/bundled-types/host-app/components/ai-assistant/message/user-message.gts +52 -0
  587. package/bundled-types/host-app/components/ai-assistant/new-session-button.gts +126 -0
  588. package/bundled-types/host-app/components/ai-assistant/new-session-settings.gts +180 -0
  589. package/bundled-types/host-app/components/ai-assistant/new-session.gts +83 -0
  590. package/bundled-types/host-app/components/ai-assistant/panel-popover.gts +102 -0
  591. package/bundled-types/host-app/components/ai-assistant/panel.gts +453 -0
  592. package/bundled-types/host-app/components/ai-assistant/past-session-item.gts +323 -0
  593. package/bundled-types/host-app/components/ai-assistant/past-sessions.gts +115 -0
  594. package/bundled-types/host-app/components/ai-assistant/rename-session.gts +144 -0
  595. package/bundled-types/host-app/components/ai-assistant/restore-file-modal.gts +105 -0
  596. package/bundled-types/host-app/components/ai-assistant/skill-menu/index.gts +190 -0
  597. package/bundled-types/host-app/components/ai-assistant/skill-menu/skill-toggle.gts +168 -0
  598. package/bundled-types/host-app/components/ai-assistant/skill-menu/usage.gts +48 -0
  599. package/bundled-types/host-app/components/ai-assistant/toast.gts +293 -0
  600. package/bundled-types/host-app/components/card-catalog/modal.gts +579 -0
  601. package/bundled-types/host-app/components/card-error.gts +41 -0
  602. package/bundled-types/host-app/components/card-instance-picker/index.gts +54 -0
  603. package/bundled-types/host-app/components/card-pill.gts +189 -0
  604. package/bundled-types/host-app/components/card-prerender.gts +880 -0
  605. package/bundled-types/host-app/components/card-renderer.gts +84 -0
  606. package/bundled-types/host-app/components/card-search/constants.ts +76 -0
  607. package/bundled-types/host-app/components/card-search/item-button.gts +243 -0
  608. package/bundled-types/host-app/components/card-search/panel.gts +150 -0
  609. package/bundled-types/host-app/components/card-search/search-bar.gts +218 -0
  610. package/bundled-types/host-app/components/card-search/search-content.gts +604 -0
  611. package/bundled-types/host-app/components/card-search/search-result-header.gts +165 -0
  612. package/bundled-types/host-app/components/card-search/search-result-section.gts +545 -0
  613. package/bundled-types/host-app/components/card-search/section-header.gts +117 -0
  614. package/bundled-types/host-app/components/editor/directory.gts +308 -0
  615. package/bundled-types/host-app/components/editor/file-tree.gts +69 -0
  616. package/bundled-types/host-app/components/editor/import-module.gts +27 -0
  617. package/bundled-types/host-app/components/editor/indexed-file-tree.gts +572 -0
  618. package/bundled-types/host-app/components/editor/recent-files.gts +141 -0
  619. package/bundled-types/host-app/components/file-pill.gts +206 -0
  620. package/bundled-types/host-app/components/head-format-preview.gts +781 -0
  621. package/bundled-types/host-app/components/host-mode/breadcrumb-item.gts +150 -0
  622. package/bundled-types/host-app/components/host-mode/breadcrumbs.gts +131 -0
  623. package/bundled-types/host-app/components/host-mode/card.gts +199 -0
  624. package/bundled-types/host-app/components/host-mode/content.gts +195 -0
  625. package/bundled-types/host-app/components/host-mode/stack-item.gts +310 -0
  626. package/bundled-types/host-app/components/host-mode/stack.gts +91 -0
  627. package/bundled-types/host-app/components/matrix/auth-container.gts +66 -0
  628. package/bundled-types/host-app/components/matrix/auth.gts +73 -0
  629. package/bundled-types/host-app/components/matrix/forgot-password.gts +487 -0
  630. package/bundled-types/host-app/components/matrix/login.gts +241 -0
  631. package/bundled-types/host-app/components/matrix/register-user.gts +843 -0
  632. package/bundled-types/host-app/components/matrix/room-message-command.gts +330 -0
  633. package/bundled-types/host-app/components/matrix/room-message.gts +261 -0
  634. package/bundled-types/host-app/components/matrix/room.gts +1872 -0
  635. package/bundled-types/host-app/components/matrix/user-profile.gts +99 -0
  636. package/bundled-types/host-app/components/modal-container.gts +171 -0
  637. package/bundled-types/host-app/components/operator-mode/binary-file-info.gts +77 -0
  638. package/bundled-types/host-app/components/operator-mode/card-adoption-chain.gts +99 -0
  639. package/bundled-types/host-app/components/operator-mode/card-error-detail.gts +87 -0
  640. package/bundled-types/host-app/components/operator-mode/card-error.gts +177 -0
  641. package/bundled-types/host-app/components/operator-mode/card-schema-editor.gts +616 -0
  642. package/bundled-types/host-app/components/operator-mode/card-url-bar.gts +197 -0
  643. package/bundled-types/host-app/components/operator-mode/choose-file-modal.gts +562 -0
  644. package/bundled-types/host-app/components/operator-mode/choose-subscription-plan-modal.gts +517 -0
  645. package/bundled-types/host-app/components/operator-mode/code-editor.gts +736 -0
  646. package/bundled-types/host-app/components/operator-mode/code-submode/editor-indicator.gts +128 -0
  647. package/bundled-types/host-app/components/operator-mode/code-submode/format-chooser.gts +589 -0
  648. package/bundled-types/host-app/components/operator-mode/code-submode/inner-container.gts +162 -0
  649. package/bundled-types/host-app/components/operator-mode/code-submode/left-panel-toggle.gts +267 -0
  650. package/bundled-types/host-app/components/operator-mode/code-submode/module-inspector.gts +836 -0
  651. package/bundled-types/host-app/components/operator-mode/code-submode/playground/field-chooser-modal.gts +97 -0
  652. package/bundled-types/host-app/components/operator-mode/code-submode/playground/instance-chooser-dropdown.gts +346 -0
  653. package/bundled-types/host-app/components/operator-mode/code-submode/playground/playground-background.png +0 -0
  654. package/bundled-types/host-app/components/operator-mode/code-submode/playground/playground-panel.gts +1274 -0
  655. package/bundled-types/host-app/components/operator-mode/code-submode/playground/playground-preview.gts +155 -0
  656. package/bundled-types/host-app/components/operator-mode/code-submode/playground/playground.gts +98 -0
  657. package/bundled-types/host-app/components/operator-mode/code-submode/playground/spec-search.gts +70 -0
  658. package/bundled-types/host-app/components/operator-mode/code-submode/schema-editor.gts +205 -0
  659. package/bundled-types/host-app/components/operator-mode/code-submode/spec-preview-badge.gts +72 -0
  660. package/bundled-types/host-app/components/operator-mode/code-submode/spec-preview.gts +432 -0
  661. package/bundled-types/host-app/components/operator-mode/code-submode/toggle-button.gts +72 -0
  662. package/bundled-types/host-app/components/operator-mode/code-submode.gts +1030 -0
  663. package/bundled-types/host-app/components/operator-mode/container.gts +270 -0
  664. package/bundled-types/host-app/components/operator-mode/context-menu-button.gts +95 -0
  665. package/bundled-types/host-app/components/operator-mode/copy-button.gts +277 -0
  666. package/bundled-types/host-app/components/operator-mode/create-file-modal.gts +1087 -0
  667. package/bundled-types/host-app/components/operator-mode/create-listing-modal.gts +513 -0
  668. package/bundled-types/host-app/components/operator-mode/definition-container/base.gts +222 -0
  669. package/bundled-types/host-app/components/operator-mode/definition-container/clickable.gts +59 -0
  670. package/bundled-types/host-app/components/operator-mode/definition-container/divider.gts +48 -0
  671. package/bundled-types/host-app/components/operator-mode/definition-container/index.gts +108 -0
  672. package/bundled-types/host-app/components/operator-mode/delete-modal.gts +123 -0
  673. package/bundled-types/host-app/components/operator-mode/detail-panel-selector.gts +320 -0
  674. package/bundled-types/host-app/components/operator-mode/detail-panel.gts +834 -0
  675. package/bundled-types/host-app/components/operator-mode/edit-field-modal.gts +450 -0
  676. package/bundled-types/host-app/components/operator-mode/error-display.gts +590 -0
  677. package/bundled-types/host-app/components/operator-mode/host-submode/open-site-popover.gts +127 -0
  678. package/bundled-types/host-app/components/operator-mode/host-submode/publishing-realm-popover.gts +159 -0
  679. package/bundled-types/host-app/components/operator-mode/host-submode.gts +373 -0
  680. package/bundled-types/host-app/components/operator-mode/interact-submode/neighbor-stack-trigger.gts +116 -0
  681. package/bundled-types/host-app/components/operator-mode/interact-submode.gts +1021 -0
  682. package/bundled-types/host-app/components/operator-mode/new-file-button.gts +187 -0
  683. package/bundled-types/host-app/components/operator-mode/operator-mode-overlays.gts +511 -0
  684. package/bundled-types/host-app/components/operator-mode/overlays.gts +342 -0
  685. package/bundled-types/host-app/components/operator-mode/preview-panel/fitted-format-gallery.gts +127 -0
  686. package/bundled-types/host-app/components/operator-mode/preview-panel/index.gts +443 -0
  687. package/bundled-types/host-app/components/operator-mode/preview-panel/markdown-preview.gts +175 -0
  688. package/bundled-types/host-app/components/operator-mode/preview-panel/metadata-panel.gts +214 -0
  689. package/bundled-types/host-app/components/operator-mode/preview-panel/rendered-markdown.gts +718 -0
  690. package/bundled-types/host-app/components/operator-mode/private-dependency-violation.gts +70 -0
  691. package/bundled-types/host-app/components/operator-mode/profile/profile-email.gts +686 -0
  692. package/bundled-types/host-app/components/operator-mode/profile/profile-settings-modal.gts +454 -0
  693. package/bundled-types/host-app/components/operator-mode/profile/profile-subscription.gts +170 -0
  694. package/bundled-types/host-app/components/operator-mode/profile-info-popover.gts +263 -0
  695. package/bundled-types/host-app/components/operator-mode/publish-realm-modal.gts +1529 -0
  696. package/bundled-types/host-app/components/operator-mode/remove-field-modal.gts +135 -0
  697. package/bundled-types/host-app/components/operator-mode/send-error-to-ai-assistant.gts +195 -0
  698. package/bundled-types/host-app/components/operator-mode/stack-item.gts +1341 -0
  699. package/bundled-types/host-app/components/operator-mode/stack.gts +191 -0
  700. package/bundled-types/host-app/components/operator-mode/submode-layout.gts +781 -0
  701. package/bundled-types/host-app/components/operator-mode/syntax-error-display.gts +72 -0
  702. package/bundled-types/host-app/components/operator-mode/workspace-chooser/add-workspace.gts +282 -0
  703. package/bundled-types/host-app/components/operator-mode/workspace-chooser/index.gts +299 -0
  704. package/bundled-types/host-app/components/operator-mode/workspace-chooser/item-container.gts +50 -0
  705. package/bundled-types/host-app/components/operator-mode/workspace-chooser/workspace-loading-indicator.gts +50 -0
  706. package/bundled-types/host-app/components/operator-mode/workspace-chooser/workspace.gts +1079 -0
  707. package/bundled-types/host-app/components/pill-menu/index.gts +281 -0
  708. package/bundled-types/host-app/components/pill-menu/usage.gts +64 -0
  709. package/bundled-types/host-app/components/prerendered-card-search.gts +274 -0
  710. package/bundled-types/host-app/components/realm-dropdown.gts +209 -0
  711. package/bundled-types/host-app/components/realm-picker/index.gts +142 -0
  712. package/bundled-types/host-app/components/search-sheet/index.gts +426 -0
  713. package/bundled-types/host-app/components/search-sheet/usage.gts +99 -0
  714. package/bundled-types/host-app/components/submode-switcher.gts +260 -0
  715. package/bundled-types/host-app/components/type-picker/index.gts +111 -0
  716. package/bundled-types/host-app/components/with-known-realms-loaded.gts +47 -0
  717. package/bundled-types/host-app/components/with-loaded-realm.gts +39 -0
  718. package/bundled-types/host-app/components/with-subscription-data.gts +247 -0
  719. package/bundled-types/host-app/config/environment.ts +66 -0
  720. package/bundled-types/host-app/deprecation-workflow.js +30 -0
  721. package/bundled-types/host-app/lib/browser-queue.ts +198 -0
  722. package/bundled-types/host-app/lib/codemirror-context.ts +1081 -0
  723. package/bundled-types/host-app/lib/command-definitions.ts +41 -0
  724. package/bundled-types/host-app/lib/download-realm.ts +9 -0
  725. package/bundled-types/host-app/lib/example-card-helpers.ts +99 -0
  726. package/bundled-types/host-app/lib/externals.ts +247 -0
  727. package/bundled-types/host-app/lib/field-path-parser.ts +520 -0
  728. package/bundled-types/host-app/lib/file-def-manager.ts +712 -0
  729. package/bundled-types/host-app/lib/file-upload-state.ts +6 -0
  730. package/bundled-types/host-app/lib/formatted-message/utils.ts +272 -0
  731. package/bundled-types/host-app/lib/gc-card-store.ts +1084 -0
  732. package/bundled-types/host-app/lib/host-base-command.ts +29 -0
  733. package/bundled-types/host-app/lib/html-component.ts +144 -0
  734. package/bundled-types/host-app/lib/html-to-markdown.ts +96 -0
  735. package/bundled-types/host-app/lib/isolated-render.gts +90 -0
  736. package/bundled-types/host-app/lib/known-file-meta-urls.ts +17 -0
  737. package/bundled-types/host-app/lib/limited-set.ts +68 -0
  738. package/bundled-types/host-app/lib/matrix-classes/member.ts +28 -0
  739. package/bundled-types/host-app/lib/matrix-classes/message-builder.ts +444 -0
  740. package/bundled-types/host-app/lib/matrix-classes/message-code-patch-result.ts +44 -0
  741. package/bundled-types/host-app/lib/matrix-classes/message-command.ts +109 -0
  742. package/bundled-types/host-app/lib/matrix-classes/message.ts +239 -0
  743. package/bundled-types/host-app/lib/matrix-classes/room.ts +174 -0
  744. package/bundled-types/host-app/lib/matrix-utils.ts +114 -0
  745. package/bundled-types/host-app/lib/mutex.ts +62 -0
  746. package/bundled-types/host-app/lib/prerender-fetch-headers.ts +46 -0
  747. package/bundled-types/host-app/lib/prerender-util.ts +31 -0
  748. package/bundled-types/host-app/lib/public-path.ts +1 -0
  749. package/bundled-types/host-app/lib/random-name.ts +26 -0
  750. package/bundled-types/host-app/lib/realm-utils.ts +45 -0
  751. package/bundled-types/host-app/lib/search-cache-key.ts +33 -0
  752. package/bundled-types/host-app/lib/search-in-flight-key.ts +28 -0
  753. package/bundled-types/host-app/lib/search-replace-block-parsing.ts +101 -0
  754. package/bundled-types/host-app/lib/setup-globals.ts +15 -0
  755. package/bundled-types/host-app/lib/sqlite-adapter.ts +510 -0
  756. package/bundled-types/host-app/lib/stack-item.ts +164 -0
  757. package/bundled-types/host-app/lib/utils.ts +84 -0
  758. package/bundled-types/host-app/lib/window-error-handler.ts +132 -0
  759. package/bundled-types/host-app/router.ts +31 -0
  760. package/bundled-types/host-app/services/ai-assistant-panel-service.ts +850 -0
  761. package/bundled-types/host-app/services/billing-service.ts +208 -0
  762. package/bundled-types/host-app/services/card-service.ts +373 -0
  763. package/bundled-types/host-app/services/card-type-service.ts +226 -0
  764. package/bundled-types/host-app/services/code-semantics-service.ts +297 -0
  765. package/bundled-types/host-app/services/command-service.ts +975 -0
  766. package/bundled-types/host-app/services/environment-service.ts +26 -0
  767. package/bundled-types/host-app/services/error-display.ts +42 -0
  768. package/bundled-types/host-app/services/file-upload.ts +212 -0
  769. package/bundled-types/host-app/services/host-mode-service.ts +381 -0
  770. package/bundled-types/host-app/services/host-mode-state-service.ts +160 -0
  771. package/bundled-types/host-app/services/loader-service.ts +148 -0
  772. package/bundled-types/host-app/services/local-indexer.ts +68 -0
  773. package/bundled-types/host-app/services/local-persistence-service.ts +296 -0
  774. package/bundled-types/host-app/services/logger-service.ts +13 -0
  775. package/bundled-types/host-app/services/matrix-sdk-loader.ts +346 -0
  776. package/bundled-types/host-app/services/matrix-service.ts +2287 -0
  777. package/bundled-types/host-app/services/message-service.ts +84 -0
  778. package/bundled-types/host-app/services/module-contents-service.ts +333 -0
  779. package/bundled-types/host-app/services/monaco-service.ts +333 -0
  780. package/bundled-types/host-app/services/network.ts +101 -0
  781. package/bundled-types/host-app/services/operator-mode-state-service.ts +1591 -0
  782. package/bundled-types/host-app/services/playground-panel-service.ts +236 -0
  783. package/bundled-types/host-app/services/queue.ts +30 -0
  784. package/bundled-types/host-app/services/realm-info-service.ts +37 -0
  785. package/bundled-types/host-app/services/realm-server.ts +1209 -0
  786. package/bundled-types/host-app/services/realm.ts +1413 -0
  787. package/bundled-types/host-app/services/recent-cards-service.ts +174 -0
  788. package/bundled-types/host-app/services/recent-files-service.ts +224 -0
  789. package/bundled-types/host-app/services/render-error-state.ts +55 -0
  790. package/bundled-types/host-app/services/render-service.ts +362 -0
  791. package/bundled-types/host-app/services/render-store.ts +27 -0
  792. package/bundled-types/host-app/services/reset.ts +19 -0
  793. package/bundled-types/host-app/services/scroll-position-service.ts +81 -0
  794. package/bundled-types/host-app/services/spec-panel-service.ts +107 -0
  795. package/bundled-types/host-app/services/store.ts +2540 -0
  796. package/bundled-types/host-app/utils/assert-never.ts +3 -0
  797. package/bundled-types/host-app/utils/auth-error-guard.ts +183 -0
  798. package/bundled-types/host-app/utils/auth-service-worker-registration.ts +123 -0
  799. package/bundled-types/host-app/utils/card-search/query-builder.ts +169 -0
  800. package/bundled-types/host-app/utils/card-search/section-pagination.ts +57 -0
  801. package/bundled-types/host-app/utils/card-search/sections.ts +240 -0
  802. package/bundled-types/host-app/utils/card-search/type-filter.ts +124 -0
  803. package/bundled-types/host-app/utils/card-search/types.ts +11 -0
  804. package/bundled-types/host-app/utils/card-search/url.ts +23 -0
  805. package/bundled-types/host-app/utils/clipboard.ts +23 -0
  806. package/bundled-types/host-app/utils/editor/boxel-formatter.ts +65 -0
  807. package/bundled-types/host-app/utils/editor/editor-language.ts +88 -0
  808. package/bundled-types/host-app/utils/editor/monaco-test-waiter.ts +302 -0
  809. package/bundled-types/host-app/utils/file-def-attributes-extractor.ts +438 -0
  810. package/bundled-types/host-app/utils/file-name.ts +38 -0
  811. package/bundled-types/host-app/utils/id-from-card-or-url.ts +11 -0
  812. package/bundled-types/host-app/utils/lint-formatting.ts +57 -0
  813. package/bundled-types/host-app/utils/local-storage-keys.ts +28 -0
  814. package/bundled-types/host-app/utils/normalized-dir-path.ts +3 -0
  815. package/bundled-types/host-app/utils/prettify-messages.ts +21 -0
  816. package/bundled-types/host-app/utils/prettify-prompts.ts +21 -0
  817. package/bundled-types/host-app/utils/realm-index-boilerplate.ts +27 -0
  818. package/bundled-types/host-app/utils/register-boxel-transition.ts +17 -0
  819. package/bundled-types/host-app/utils/render-desync-detector.ts +362 -0
  820. package/bundled-types/host-app/utils/render-error.ts +455 -0
  821. package/bundled-types/host-app/utils/render-timer-stub.ts +249 -0
  822. package/bundled-types/host-app/utils/run-while-active.ts +14 -0
  823. package/bundled-types/host-app/utils/schema-editor.ts +25 -0
  824. package/bundled-types/host-app/utils/text-suggestion.ts +82 -0
  825. package/bundled-types/host-app/utils/titleize.ts +10 -0
  826. package/bundled-types/host-app/utils/uuid.ts +13 -0
  827. package/bundled-types/host-tests/helpers/adapter.ts +464 -0
  828. package/bundled-types/host-tests/helpers/base-realm.ts +464 -0
  829. package/bundled-types/host-tests/helpers/cards/view-card-demo.ts +119 -0
  830. package/bundled-types/host-tests/helpers/field-test-helpers.gts +54 -0
  831. package/bundled-types/host-tests/helpers/image-fixture.ts +3 -0
  832. package/bundled-types/host-tests/helpers/index.gts +2099 -0
  833. package/bundled-types/host-tests/helpers/indexer.ts +293 -0
  834. package/bundled-types/host-tests/helpers/interact-submode-setup.gts +551 -0
  835. package/bundled-types/host-tests/helpers/mock-matrix/_client.ts +1042 -0
  836. package/bundled-types/host-tests/helpers/mock-matrix/_sdk.ts +71 -0
  837. package/bundled-types/host-tests/helpers/mock-matrix/_server-state.ts +343 -0
  838. package/bundled-types/host-tests/helpers/mock-matrix/_sliding-sync.ts +140 -0
  839. package/bundled-types/host-tests/helpers/mock-matrix/_utils.ts +146 -0
  840. package/bundled-types/host-tests/helpers/mock-matrix.ts +200 -0
  841. package/bundled-types/host-tests/helpers/operator-mode-parameters-match.ts +71 -0
  842. package/bundled-types/host-tests/helpers/operator-mode-state.ts +18 -0
  843. package/bundled-types/host-tests/helpers/percy-snapshot.ts +228 -0
  844. package/bundled-types/host-tests/helpers/playground.ts +130 -0
  845. package/bundled-types/host-tests/helpers/realm-server-mock/index.ts +100 -0
  846. package/bundled-types/host-tests/helpers/realm-server-mock/routes.ts +617 -0
  847. package/bundled-types/host-tests/helpers/realm-server-mock/types.ts +24 -0
  848. package/bundled-types/host-tests/helpers/recent-files-cards.ts +86 -0
  849. package/bundled-types/host-tests/helpers/render-component.ts +40 -0
  850. package/bundled-types/host-tests/helpers/setup-qunit.js +164 -0
  851. package/bundled-types/host-tests/helpers/setup.ts +349 -0
  852. package/bundled-types/host-tests/helpers/shard-warmup.ts +72 -0
  853. package/bundled-types/host-tests/helpers/stream.ts +60 -0
  854. package/bundled-types/host-tests/helpers/test-auth.ts +27 -0
  855. package/bundled-types/host-tests/helpers/test-realm-registry.ts +23 -0
  856. package/bundled-types/host-tests/helpers/test-realm-service-worker.ts +92 -0
  857. package/bundled-types/host-tests/helpers/uncaught-exceptions.ts +16 -0
  858. package/bundled-types/host-tests/helpers/visit-operator-mode.ts +39 -0
  859. package/bundled-types/host-types/@cardstack/host/index.d.ts +3 -0
  860. package/bundled-types/host-types/@joplin/turndown-plugin-gfm/index.d.ts +15 -0
  861. package/bundled-types/host-types/@sqlite.org/sqlite-wasm/index.d.ts +122 -0
  862. package/bundled-types/host-types/ember-click-outside/modifiers/on-click-outside.ts +16 -0
  863. package/bundled-types/host-types/ember-concurrency/helpers/perform.d.ts +3 -0
  864. package/bundled-types/host-types/ember-css-url/index.d.ts +15 -0
  865. package/bundled-types/host-types/ember-data/types/registries/model.d.ts +6 -0
  866. package/bundled-types/host-types/ember-elsewhere/from-elsewhere.d.ts +12 -0
  867. package/bundled-types/host-types/ember-elsewhere/to-elsewhere.d.ts +16 -0
  868. package/bundled-types/host-types/ember-focus-trap/index.d.ts +4 -0
  869. package/bundled-types/host-types/ember-keyboard/modifiers/on-key.d.ts +15 -0
  870. package/bundled-types/host-types/index.d.ts +6 -0
  871. package/bundled-types/local-types/eslint-js.d.ts +5 -0
  872. package/bundled-types/local-types/index.d.ts +115 -0
  873. package/bundled-types/local-types/marked-gfm-heading-id.d.ts +12 -0
  874. package/bundled-types/local-types/matrix-js-sdk/index.d.ts +11 -0
  875. package/bundled-types/local-types/package.json +13 -0
  876. package/bundled-types/shims/boxel-cli-shims.d.ts +10 -0
  877. package/dist/index.js +100 -100
  878. package/package.json +13 -7
  879. package/src/commands/parse.ts +277 -34
@@ -0,0 +1,2287 @@
1
+ import { registerDestructor } from '@ember/destroyable';
2
+ import type Owner from '@ember/owner';
3
+ import { getOwner } from '@ember/owner';
4
+ import type RouterService from '@ember/routing/router-service';
5
+ import { debounce } from '@ember/runloop';
6
+ import Service, { service } from '@ember/service';
7
+ import { isTesting } from '@embroider/macros';
8
+ import { cached, tracked } from '@glimmer/tracking';
9
+
10
+ import { dropTask, task, timeout } from 'ember-concurrency';
11
+ import window from 'ember-window-mock';
12
+ import { cloneDeep } from 'lodash';
13
+
14
+ import { Filter } from 'matrix-js-sdk';
15
+ import {
16
+ type SlidingSync,
17
+ type MSC3575List,
18
+ SlidingSyncEvent,
19
+ SlidingSyncState,
20
+ type MSC3575SlidingSyncResponse,
21
+ } from 'matrix-js-sdk/lib/sliding-sync';
22
+ import stringify from 'safe-stable-stringify';
23
+ import { TrackedMap } from 'tracked-built-ins';
24
+ import { v4 as uuidv4 } from 'uuid';
25
+
26
+ import type {
27
+ LooseCardResource,
28
+ ResolvedCodeRef,
29
+ } from '@cardstack/runtime-common';
30
+ import {
31
+ aiBotUsername,
32
+ submissionBotUsername,
33
+ logger,
34
+ isCardInstance,
35
+ Deferred,
36
+ SEARCH_MARKER,
37
+ REPLACE_MARKER,
38
+ SEPARATOR_MARKER,
39
+ isCardErrorJSONAPI,
40
+ } from '@cardstack/runtime-common';
41
+
42
+ import { getPromptParts } from '@cardstack/runtime-common/ai';
43
+ import { getMatrixUsername } from '@cardstack/runtime-common/matrix-client';
44
+
45
+ import {
46
+ APP_BOXEL_CODE_PATCH_RESULT_EVENT_TYPE,
47
+ APP_BOXEL_CODE_PATCH_RESULT_MSGTYPE,
48
+ APP_BOXEL_CODE_PATCH_RESULT_REL_TYPE,
49
+ APP_BOXEL_COMMAND_RESULT_EVENT_TYPE,
50
+ APP_BOXEL_COMMAND_RESULT_REL_TYPE,
51
+ APP_BOXEL_COMMAND_RESULT_WITH_NO_OUTPUT_MSGTYPE,
52
+ APP_BOXEL_COMMAND_RESULT_WITH_OUTPUT_MSGTYPE,
53
+ APP_BOXEL_MESSAGE_MSGTYPE,
54
+ APP_BOXEL_REALM_EVENT_TYPE,
55
+ APP_BOXEL_REALM_SERVER_EVENT_MSGTYPE,
56
+ APP_BOXEL_REALMS_EVENT_TYPE,
57
+ APP_BOXEL_WORKSPACE_FAVORITES_EVENT_TYPE,
58
+ APP_BOXEL_ACTIVE_LLM,
59
+ APP_BOXEL_LLM_MODE,
60
+ APP_BOXEL_ROOM_SKILLS_EVENT_TYPE,
61
+ APP_BOXEL_STOP_GENERATING_EVENT_TYPE,
62
+ SLIDING_SYNC_AI_ROOM_LIST_NAME,
63
+ SLIDING_SYNC_AUTH_ROOM_LIST_NAME,
64
+ SLIDING_SYNC_LIST_RANGE_END,
65
+ SLIDING_SYNC_LIST_TIMELINE_LIMIT,
66
+ SLIDING_SYNC_TIMEOUT,
67
+ type LLMMode,
68
+ APP_BOXEL_COMMAND_REQUESTS_KEY,
69
+ APP_BOXEL_SYSTEM_CARD_EVENT_TYPE,
70
+ } from '@cardstack/runtime-common/matrix-constants';
71
+
72
+ import {
73
+ type Submode,
74
+ Submodes,
75
+ } from '@cardstack/host/components/submode-switcher';
76
+ import ENV from '@cardstack/host/config/environment';
77
+
78
+ import type IndexController from '@cardstack/host/controllers/index';
79
+
80
+ import type { TempEvent } from '@cardstack/host/lib/matrix-classes/room';
81
+ import Room from '@cardstack/host/lib/matrix-classes/room';
82
+ import { getRandomBackgroundURL, iconURLFor } from '@cardstack/host/lib/utils';
83
+ import { getMatrixProfile } from '@cardstack/host/resources/matrix-profile';
84
+ import { clearLocalStorage } from '@cardstack/host/utils/local-storage-keys';
85
+
86
+ import type { BaseDef, CardDef } from 'https://cardstack.com/base/card-api';
87
+ import type * as CardAPI from 'https://cardstack.com/base/card-api';
88
+ import type {
89
+ CardForAttachmentCard,
90
+ FileForAttachmentCard,
91
+ } from 'https://cardstack.com/base/command';
92
+ import type * as FileAPI from 'https://cardstack.com/base/file-api';
93
+ import type { FileDef } from 'https://cardstack.com/base/file-api';
94
+ import type {
95
+ BoxelContext,
96
+ BotTriggerContent,
97
+ CardMessageContent,
98
+ MatrixEvent as DiscreteMatrixEvent,
99
+ CodePatchResultContent,
100
+ CodePatchStatus,
101
+ CommandResultWithNoOutputContent,
102
+ CommandResultWithOutputContent,
103
+ RealmEventContent,
104
+ Tool,
105
+ CommandResultStatus,
106
+ } from 'https://cardstack.com/base/matrix-event';
107
+
108
+ import type * as SkillModule from 'https://cardstack.com/base/skill';
109
+ import type { SystemCard } from 'https://cardstack.com/base/system-card';
110
+
111
+ import UpdateRoomSkillsCommand from '../commands/update-room-skills';
112
+ import { addPatchTools } from '../commands/utils';
113
+ import { getUniqueValidCommandDefinitions } from '../lib/command-definitions';
114
+ import { isSkillCard } from '../lib/file-def-manager';
115
+ import { skillCardURL, devSkillId, envSkillId } from '../lib/utils';
116
+ import { importResource } from '../resources/import';
117
+
118
+ import { getRoom } from '../resources/room';
119
+
120
+ import type CardService from './card-service';
121
+ import type CommandService from './command-service';
122
+ import type LoaderService from './loader-service';
123
+ import type LocalPersistenceService from './local-persistence-service';
124
+ import type LoggerService from './logger-service';
125
+ import type MatrixSDKLoader from './matrix-sdk-loader';
126
+ import type { ExtendedClient, ExtendedMatrixSDK } from './matrix-sdk-loader';
127
+ import type MessageService from './message-service';
128
+ import type NetworkService from './network';
129
+ import type { SerializedState as OperatorModeSerializedState } from './operator-mode-state-service';
130
+ import type RealmService from './realm';
131
+ import type RealmServerService from './realm-server';
132
+ import type ResetService from './reset';
133
+ import type StoreService from './store';
134
+ import type { RoomResource } from '../resources/room';
135
+ import type { MatrixClient } from 'matrix-js-sdk';
136
+ import type {
137
+ LoginResponse,
138
+ MatrixEvent,
139
+ RoomMember,
140
+ EmittedEvents,
141
+ } from 'matrix-js-sdk';
142
+
143
+ import type * as MatrixSDK from 'matrix-js-sdk';
144
+
145
+ const { matrixURL, defaultSystemCardId } = ENV;
146
+ const STATE_EVENTS_OF_INTEREST = ['m.room.create', 'm.room.name'];
147
+
148
+ const realmEventsLogger = logger('realm:events');
149
+
150
+ export default class MatrixService extends Service {
151
+ @service declare private loaderService: LoaderService;
152
+ @service declare private loggerService: LoggerService;
153
+ @service declare private cardService: CardService;
154
+ @service declare private commandService: CommandService;
155
+ @service declare private realm: RealmService;
156
+ @service declare private matrixSdkLoader: MatrixSDKLoader;
157
+ @service declare private messageService: MessageService;
158
+ @service declare private realmServer: RealmServerService;
159
+ @service declare private router: RouterService;
160
+ @service declare private reset: ResetService;
161
+ @service declare private network: NetworkService;
162
+ @service declare private store: StoreService;
163
+ @service declare private localPersistenceService: LocalPersistenceService;
164
+ @tracked private _client: ExtendedClient | undefined;
165
+ @tracked private _isInitializingNewUser = false;
166
+ @tracked private postLoginCompleted = false;
167
+ @tracked private _currentRoomId: string | undefined;
168
+ @tracked private timelineLoadingState: Map<string, boolean> =
169
+ new TrackedMap();
170
+
171
+ @tracked private storage: Storage | undefined;
172
+ @tracked workspaceFavorites: string[] = [];
173
+
174
+ profile = getMatrixProfile(this, () => this.userId);
175
+
176
+ private roomDataMap: TrackedMap<string, Room> = new TrackedMap();
177
+ private startedAtTs = -1;
178
+
179
+ // TODO This seems very bad. we should not be sharing Resources with anyone that
180
+ // wants one--resources are tied to the lifetime of their owner, who knows
181
+ // which owner made these and who is consuming these. we need to refactor this out..
182
+ roomResourcesCache: TrackedMap<string, RoomResource> = new TrackedMap();
183
+ canceledActionMessageIdByRoom: TrackedMap<string, string> = new TrackedMap();
184
+ messagesToSend: TrackedMap<string, string | undefined> = new TrackedMap();
185
+ cardsToSend: TrackedMap<string, string[] | undefined> = new TrackedMap();
186
+ filesToSend: TrackedMap<string, FileDef[] | undefined> = new TrackedMap();
187
+ failedCommandState: TrackedMap<string, Error> = new TrackedMap();
188
+ reasoningExpandedState: TrackedMap<string, boolean> = new TrackedMap();
189
+ flushTimeline: Promise<void> | undefined;
190
+ flushMembership: Promise<void> | undefined;
191
+ flushRoomState: Promise<void> | undefined;
192
+ private roomMembershipQueue: { event: MatrixEvent; member: RoomMember }[] =
193
+ [];
194
+ private timelineQueue: { event: MatrixEvent; oldEventId?: string }[] = [];
195
+ private roomStateQueue: MatrixSDK.RoomState[] = [];
196
+ #ready: Promise<void>;
197
+ #clientReadyDeferred = new Deferred<void>();
198
+ #matrixSDK: ExtendedMatrixSDK | undefined;
199
+ #eventBindings: [EmittedEvents, (...arg: any[]) => void][] | undefined;
200
+ currentUserEventReadReceipts: TrackedMap<string, { readAt: Date }> =
201
+ new TrackedMap();
202
+
203
+ private slidingSync: SlidingSync | undefined;
204
+ private aiRoomIds: Set<string> = new Set();
205
+ private restoredDraftRooms = new Set<string>();
206
+ @tracked private _isLoadingMoreAIRooms = false;
207
+ private initialSyncCompleted = false;
208
+ private initialSyncCompletedDeferred = new Deferred<void>();
209
+ private roomsWaitingForSync: Map<string, Deferred<void>> = new Map();
210
+ @tracked private _systemCard: SystemCard | undefined;
211
+ agentId: string | undefined;
212
+
213
+ constructor(owner: Owner) {
214
+ super(owner);
215
+ this.reset.register(this);
216
+ this.setLoggerLevelFromEnvironment();
217
+ this.setAgentId();
218
+ this.#ready = this.loadState.perform();
219
+ registerDestructor(this, () => this.teardownClient());
220
+ }
221
+
222
+ setMessageToSend(roomId: string, message: string | undefined) {
223
+ this.ensureMessageDraftRestored(roomId);
224
+ if (message === undefined) {
225
+ this.messagesToSend.delete(roomId);
226
+ } else {
227
+ this.messagesToSend.set(roomId, message);
228
+ }
229
+ this.localPersistenceService.setMessageDraft(roomId, message);
230
+ }
231
+
232
+ getMessageToSend(roomId: string) {
233
+ this.ensureMessageDraftRestored(roomId);
234
+ return this.messagesToSend.get(roomId);
235
+ }
236
+
237
+ setCardsToSend(roomId: string, cardIds: string[] | undefined) {
238
+ this.ensureMessageDraftRestored(roomId);
239
+ let sanitized = cardIds?.filter(
240
+ (id): id is string => typeof id === 'string' && id.length > 0,
241
+ );
242
+ if (sanitized && sanitized.length > 0) {
243
+ this.cardsToSend.set(roomId, [...new Set(sanitized)]);
244
+ } else {
245
+ this.cardsToSend.delete(roomId);
246
+ sanitized = undefined;
247
+ }
248
+ this.localPersistenceService.setAttachedCardIds(roomId, sanitized);
249
+ }
250
+
251
+ getCardsToSend(roomId: string) {
252
+ this.ensureMessageDraftRestored(roomId);
253
+ return this.cardsToSend.get(roomId);
254
+ }
255
+
256
+ setFilesToSend(roomId: string, files: FileDef[] | undefined) {
257
+ this.ensureMessageDraftRestored(roomId);
258
+ let nextFiles = files && files.length > 0 ? [...files] : undefined;
259
+ if (nextFiles) {
260
+ this.filesToSend.set(roomId, nextFiles);
261
+ } else {
262
+ this.filesToSend.delete(roomId);
263
+ }
264
+ this.localPersistenceService.setAttachedFiles(
265
+ roomId,
266
+ nextFiles?.map((file) => file.serialize()),
267
+ );
268
+ }
269
+
270
+ getFilesToSend(roomId: string) {
271
+ this.ensureMessageDraftRestored(roomId);
272
+ return this.filesToSend.get(roomId);
273
+ }
274
+
275
+ private setAgentId() {
276
+ this.agentId = this.localPersistenceService.getAgentId();
277
+ }
278
+
279
+ private setLoggerLevelFromEnvironment() {
280
+ // This will pick up the level if it's in LOG_LEVELS
281
+ logger('matrix');
282
+ }
283
+
284
+ private addEventReadReceipt(eventId: string, receipt: { readAt: Date }) {
285
+ if (isTesting()) {
286
+ console.log(`[read-receipt-trace] arrived event=${eventId}`);
287
+ }
288
+ this.currentUserEventReadReceipts.set(eventId, receipt);
289
+ }
290
+
291
+ get currentRoomId(): string | undefined {
292
+ return this._currentRoomId;
293
+ }
294
+
295
+ set currentRoomId(value: string | undefined) {
296
+ this._currentRoomId = value;
297
+ if (value) {
298
+ this.loadAllTimelineEvents(value);
299
+ }
300
+
301
+ this.localPersistenceService.setCurrentRoomId(value);
302
+ }
303
+
304
+ get ready() {
305
+ return this.#ready;
306
+ }
307
+
308
+ private cardAPIModule = importResource(
309
+ this,
310
+ () => 'https://cardstack.com/base/card-api',
311
+ );
312
+
313
+ private fileAPIModule = importResource(
314
+ this,
315
+ () => 'https://cardstack.com/base/file-api',
316
+ );
317
+
318
+ private loadState = task(async () => {
319
+ await this.requestStorageAccess();
320
+ await this.loadSDK();
321
+ });
322
+
323
+ private get inIframe() {
324
+ return !isTesting() && window.top !== window.self;
325
+ }
326
+
327
+ async requestStorageAccess() {
328
+ if (this.inIframe) {
329
+ this.storage = await getStorage();
330
+ } else {
331
+ this.storage = window.localStorage;
332
+ }
333
+
334
+ return this.storage;
335
+ }
336
+
337
+ private saveAuth(auth: LoginResponse) {
338
+ this.storage?.setItem('auth', JSON.stringify(auth));
339
+ }
340
+
341
+ private getAuth(): LoginResponse | undefined {
342
+ let auth = this.storage?.getItem('auth');
343
+ if (!auth) {
344
+ return;
345
+ }
346
+ return JSON.parse(auth) as LoginResponse;
347
+ }
348
+
349
+ private async loadSDK() {
350
+ await this.cardAPIModule.loaded;
351
+ await this.fileAPIModule.loaded;
352
+ // The matrix SDK is VERY big so we only load it when we need it
353
+ this.#matrixSDK = await this.matrixSdkLoader.load();
354
+ this._client = this.matrixSDK.createClient({
355
+ baseUrl: matrixURL,
356
+ });
357
+ this.#clientReadyDeferred.fulfill();
358
+
359
+ // building the event bindings like this so that we can consistently bind
360
+ // and unbind these events programmatically--this way if we add a new event
361
+ // we won't forget to unbind it.
362
+
363
+ this.#eventBindings = [
364
+ [this.matrixSDK.RoomMemberEvent.Membership, this.onMembership],
365
+ [this.matrixSDK.RoomEvent.Timeline, this.onTimeline],
366
+ [this.matrixSDK.RoomEvent.LocalEchoUpdated, this.onUpdateEventStatus],
367
+ [this.matrixSDK.RoomEvent.Receipt, this.onReceipt],
368
+ [this.matrixSDK.RoomStateEvent.Update, this.onRoomStateUpdate],
369
+ [
370
+ this.matrixSDK.ClientEvent.AccountData,
371
+ async (e) => {
372
+ switch (e.event.type) {
373
+ case APP_BOXEL_REALMS_EVENT_TYPE:
374
+ await this.realmServer.setAvailableRealmURLs(
375
+ e.event.content.realms,
376
+ );
377
+ // Only do this after we've completed our overall login
378
+ if (this.postLoginCompleted) {
379
+ await this.loginToRealms();
380
+ await this.loadMoreAuthRooms(e.event.content.realms);
381
+ }
382
+ break;
383
+ case APP_BOXEL_SYSTEM_CARD_EVENT_TYPE:
384
+ await this.setSystemCard(e.event.content.id);
385
+ break;
386
+ }
387
+ },
388
+ ],
389
+ ];
390
+ }
391
+
392
+ get isLoggedIn() {
393
+ return this._client?.isLoggedIn() === true && this.postLoginCompleted;
394
+ }
395
+
396
+ private get client() {
397
+ if (!this._client) {
398
+ throw new Error(`cannot use matrix client before matrix SDK has loaded`);
399
+ }
400
+ return this._client;
401
+ }
402
+
403
+ get userId() {
404
+ return this.client.getUserId();
405
+ }
406
+
407
+ get aiBotUserId() {
408
+ let server = this.userId!.split(':')[1];
409
+ return `@${aiBotUsername}:${server}`;
410
+ }
411
+
412
+ get submissionBotUserId() {
413
+ let server = this.userId!.split(':')[1];
414
+ return `@${submissionBotUsername}:${server}`;
415
+ }
416
+
417
+ getFullUserId(username: string) {
418
+ if (username.includes(':')) {
419
+ return username;
420
+ }
421
+ let server = this.userId?.split(':')[1];
422
+ if (!server) {
423
+ throw new Error('Matrix server is unavailable for user id');
424
+ }
425
+ let localpart = username.startsWith('@') ? username.slice(1) : username;
426
+ return `@${localpart}:${server}`;
427
+ }
428
+
429
+ async isUserInRoom(roomId: string, userId: string) {
430
+ try {
431
+ let state = await this.getStateEvent(roomId, 'm.room.member', userId);
432
+ return state?.membership === 'invite' || state?.membership === 'join';
433
+ } catch (_error) {
434
+ return false;
435
+ }
436
+ }
437
+
438
+ get userName() {
439
+ return this.userId ? getMatrixUsername(this.userId) : null;
440
+ }
441
+
442
+ get cardAPI() {
443
+ if (this.cardAPIModule.error) {
444
+ throw new Error(
445
+ `Error loading Card API: ${JSON.stringify(this.cardAPIModule.error)}`,
446
+ );
447
+ }
448
+ if (!this.cardAPIModule.module) {
449
+ throw new Error(
450
+ `bug: Card API has not loaded yet--make sure to await this.loaded before using the api`,
451
+ );
452
+ }
453
+ return this.cardAPIModule.module as typeof CardAPI;
454
+ }
455
+
456
+ get fileAPI() {
457
+ if (this.fileAPIModule.error) {
458
+ throw new Error(
459
+ `Error loading File API: ${JSON.stringify(this.fileAPIModule.error)}`,
460
+ );
461
+ }
462
+ if (!this.fileAPIModule.module) {
463
+ throw new Error(
464
+ `bug: File API has not loaded yet--make sure to await this.loaded before using the api`,
465
+ );
466
+ }
467
+ return this.fileAPIModule.module as typeof FileAPI;
468
+ }
469
+
470
+ private get matrixSDK() {
471
+ if (!this.#matrixSDK) {
472
+ throw new Error(`cannot use matrix SDK before it has loaded`);
473
+ }
474
+ return this.#matrixSDK;
475
+ }
476
+
477
+ get privateChatPreset() {
478
+ return this.matrixSDK.Preset.PrivateChat;
479
+ }
480
+
481
+ get aiBotPowerLevel() {
482
+ return 50; // this is required to set the room name
483
+ }
484
+
485
+ async waitForInitialSync() {
486
+ await this.initialSyncCompletedDeferred.promise;
487
+ }
488
+
489
+ get flushAll() {
490
+ return Promise.all([
491
+ this.flushMembership ?? Promise.resolve(),
492
+ this.flushTimeline ?? Promise.resolve(),
493
+ this.flushRoomState ?? Promise.resolve(),
494
+ ]);
495
+ }
496
+
497
+ async logout() {
498
+ let client = this._client;
499
+ try {
500
+ // Logout should synchronously move the app into a logged-out state.
501
+ // Waiting on background Matrix flush promises first can leave the
502
+ // authenticated shell visible for an arbitrarily long time.
503
+ this.clearAuth();
504
+ this.postLoginCompleted = false;
505
+ // Logout is the explicit boundary where we forget persisted workspace UI
506
+ // state for the signed-in user. Generic reset paths must stay in-memory
507
+ // only so tests and app reloads do not accidentally wipe durable state.
508
+ clearLocalStorage(window.localStorage);
509
+ this.reset.resetAll();
510
+ this.loaderService.resetSessionBoundary('logout');
511
+ this.unbindEventListeners();
512
+ await client?.logout(true);
513
+ // when user logs out we transition them back to an empty stack with the
514
+ // workspace chooser open. this way we don't inadvertently leak private
515
+ // card id's in the URL
516
+ this.router.transitionTo('index-root', {
517
+ queryParams: {
518
+ operatorModeState: stringify({
519
+ stacks: [],
520
+ submode: Submodes.Interact,
521
+ workspaceChooserOpened: true,
522
+ } as OperatorModeSerializedState),
523
+ sid: null,
524
+ clientSecret: null,
525
+ },
526
+ });
527
+ } catch (e) {
528
+ console.log('Error logging out of Matrix', e);
529
+ } finally {
530
+ this.resetState();
531
+ }
532
+ }
533
+
534
+ get isInitializingNewUser() {
535
+ return this._isInitializingNewUser;
536
+ }
537
+
538
+ async initializeNewUser(
539
+ auth: LoginResponse,
540
+ displayName: string,
541
+ registrationToken?: string,
542
+ ) {
543
+ await this.ready;
544
+
545
+ displayName = displayName.trim();
546
+ this._isInitializingNewUser = true;
547
+
548
+ this.configureClientWithAuth(auth);
549
+
550
+ let userId = auth.user_id;
551
+
552
+ if (!userId) {
553
+ throw new Error(
554
+ `bug: there is no userId associated with the matrix client`,
555
+ );
556
+ }
557
+
558
+ await this.start({ auth, registrationToken });
559
+ this.setDisplayName(displayName);
560
+
561
+ await this.realmServer.authenticateToAllAccessibleRealms();
562
+
563
+ await Promise.all([
564
+ this.createPersonalRealmForUser({
565
+ endpoint: 'personal',
566
+ name: `${displayName}'s Workspace`,
567
+ iconURL: iconURLFor(displayName),
568
+ backgroundURL: getRandomBackgroundURL(),
569
+ }),
570
+ this.realmServer.fetchCatalogRealms(),
571
+ ]);
572
+
573
+ this.router.refresh();
574
+ this._isInitializingNewUser = false;
575
+ }
576
+
577
+ private configureClientWithAuth(auth: LoginResponse) {
578
+ let {
579
+ access_token: accessToken,
580
+ user_id: userId,
581
+ device_id: deviceId,
582
+ } = auth;
583
+
584
+ if (!accessToken) {
585
+ throw new Error(
586
+ `Cannot create matrix client from auth that has no access token: ${JSON.stringify(
587
+ auth,
588
+ null,
589
+ 2,
590
+ )}`,
591
+ );
592
+ }
593
+ if (!userId) {
594
+ throw new Error(
595
+ `Cannot create matrix client from auth that has no user id: ${JSON.stringify(
596
+ auth,
597
+ null,
598
+ 2,
599
+ )}`,
600
+ );
601
+ }
602
+ if (!deviceId) {
603
+ throw new Error(
604
+ `Cannot create matrix client from auth that has no device id: ${JSON.stringify(
605
+ auth,
606
+ null,
607
+ 2,
608
+ )}`,
609
+ );
610
+ }
611
+
612
+ this._client = this.matrixSDK.createClient({
613
+ baseUrl: matrixURL,
614
+ accessToken,
615
+ userId,
616
+ deviceId,
617
+ });
618
+
619
+ this.realmServer.setClient(this.client);
620
+ this.saveAuth(auth);
621
+ }
622
+
623
+ public async createPersonalRealmForUser({
624
+ endpoint,
625
+ name,
626
+ iconURL,
627
+ backgroundURL,
628
+ }: {
629
+ endpoint: string;
630
+ name: string;
631
+ iconURL?: string;
632
+ backgroundURL?: string;
633
+ }) {
634
+ let personalRealmURL = await this.realmServer.createRealm({
635
+ endpoint,
636
+ name,
637
+ iconURL,
638
+ backgroundURL,
639
+ });
640
+
641
+ await this.appendRealmToAccountData(personalRealmURL.href);
642
+ }
643
+
644
+ public async appendRealmToAccountData(realmURLString: string) {
645
+ let { realms = [] } =
646
+ ((await this.client.getAccountDataFromServer(
647
+ APP_BOXEL_REALMS_EVENT_TYPE,
648
+ )) as { realms: string[] }) ?? {};
649
+
650
+ // Clone the account data instead of using it directly,
651
+ // since mutating the original object would modify the Matrix client’s store
652
+ // and prevent updates from being sent back to the server.
653
+ let newRealms = [...realms, realmURLString];
654
+ await this.client.setAccountData(APP_BOXEL_REALMS_EVENT_TYPE, {
655
+ realms: newRealms,
656
+ });
657
+ await this.realmServer.setAvailableRealmURLs(newRealms);
658
+ }
659
+
660
+ public async removeRealmFromAccountData(realmURLString: string) {
661
+ let { realms = [] } =
662
+ ((await this.client.getAccountDataFromServer(
663
+ APP_BOXEL_REALMS_EVENT_TYPE,
664
+ )) as { realms: string[] }) ?? {};
665
+
666
+ let newRealms = realms.filter((realmURL) => realmURL !== realmURLString);
667
+ await this.client.setAccountData(APP_BOXEL_REALMS_EVENT_TYPE, {
668
+ realms: newRealms,
669
+ });
670
+ await this.realmServer.setAvailableRealmURLs(newRealms);
671
+ }
672
+
673
+ public async getWorkspaceFavorites(): Promise<string[]> {
674
+ let { favorites = [] } =
675
+ ((await this.client.getAccountDataFromServer(
676
+ APP_BOXEL_WORKSPACE_FAVORITES_EVENT_TYPE,
677
+ )) as { favorites: string[] }) ?? {};
678
+ return favorites;
679
+ }
680
+
681
+ public async addWorkspaceFavorite(realmURL: string): Promise<void> {
682
+ let { favorites = [] } =
683
+ ((await this.client.getAccountDataFromServer(
684
+ APP_BOXEL_WORKSPACE_FAVORITES_EVENT_TYPE,
685
+ )) as { favorites: string[] }) ?? {};
686
+
687
+ if (!favorites.includes(realmURL)) {
688
+ let newFavorites = [...favorites, realmURL];
689
+ await this.client.setAccountData(
690
+ APP_BOXEL_WORKSPACE_FAVORITES_EVENT_TYPE,
691
+ { favorites: newFavorites },
692
+ );
693
+ this.workspaceFavorites = newFavorites;
694
+ }
695
+ }
696
+
697
+ public async removeWorkspaceFavorite(realmURL: string): Promise<void> {
698
+ let { favorites = [] } =
699
+ ((await this.client.getAccountDataFromServer(
700
+ APP_BOXEL_WORKSPACE_FAVORITES_EVENT_TYPE,
701
+ )) as { favorites: string[] }) ?? {};
702
+
703
+ let newFavorites = favorites.filter((url) => url !== realmURL);
704
+ await this.client.setAccountData(APP_BOXEL_WORKSPACE_FAVORITES_EVENT_TYPE, {
705
+ favorites: newFavorites,
706
+ });
707
+ this.workspaceFavorites = newFavorites;
708
+ }
709
+
710
+ async setDisplayName(displayName: string) {
711
+ await this.client.setDisplayName(displayName);
712
+ }
713
+
714
+ async reloadProfile() {
715
+ await this.profile.load.perform();
716
+ }
717
+
718
+ async start(
719
+ opts: {
720
+ auth?: MatrixSDK.LoginResponse;
721
+ refreshRoutes?: true;
722
+ registrationToken?: string;
723
+ } = {},
724
+ ) {
725
+ await this.ready;
726
+
727
+ let { auth, refreshRoutes, registrationToken } = opts;
728
+ if (!auth) {
729
+ auth = this.getAuth();
730
+ if (!auth) {
731
+ return;
732
+ }
733
+ }
734
+
735
+ this.configureClientWithAuth(auth);
736
+
737
+ if (this.client.isLoggedIn()) {
738
+ this.realmServer.setClient(this.client);
739
+ await this.realmServer.login(registrationToken);
740
+ this.saveAuth(auth);
741
+ this.bindEventListeners();
742
+
743
+ try {
744
+ let deviceId = this.client.getDeviceId();
745
+ if (deviceId) {
746
+ let { last_seen_ts } = await this.client.getDevice(deviceId);
747
+ if (last_seen_ts) {
748
+ this.startedAtTs = last_seen_ts;
749
+ }
750
+ }
751
+ if (this.startedAtTs === -1) {
752
+ this.startedAtTs = 0;
753
+ }
754
+ let [accountDataContent, favoritesData] = await Promise.all([
755
+ this.client.getAccountDataFromServer(
756
+ APP_BOXEL_REALMS_EVENT_TYPE,
757
+ ) as Promise<{ realms: string[] } | null>,
758
+ this.client.getAccountDataFromServer(
759
+ APP_BOXEL_WORKSPACE_FAVORITES_EVENT_TYPE,
760
+ ) as Promise<{ favorites: string[] } | null>,
761
+ ]);
762
+ this.workspaceFavorites = favoritesData?.favorites ?? [];
763
+
764
+ let noRealmsLoggedIn = Array.from(this.realm.realms.entries()).every(
765
+ ([_url, realmResource]) => !realmResource.isLoggedIn,
766
+ );
767
+
768
+ await Promise.all([
769
+ this.realmServer.fetchCatalogRealms(),
770
+ this.realmServer.setAvailableRealmURLs(
771
+ accountDataContent?.realms ?? [],
772
+ ),
773
+ ]);
774
+
775
+ await this.realm.prefetchRealmInfos(
776
+ this.realmServer.availableRealmURLs,
777
+ );
778
+
779
+ await this.initSlidingSync(accountDataContent);
780
+ await this.client.startClient({ slidingSync: this.slidingSync });
781
+ let systemCardAccountData = (await this.client.getAccountDataFromServer(
782
+ APP_BOXEL_SYSTEM_CARD_EVENT_TYPE,
783
+ )) as { id?: string } | null;
784
+ await this.setSystemCard(systemCardAccountData?.id);
785
+ if (noRealmsLoggedIn) {
786
+ // In this case we want to authenticate to all accessible realms in a single request,
787
+ // for performance reasons (otherwise we would make 2 auth requests for
788
+ // each realm, which could be a lot of requests).
789
+
790
+ await this.realmServer.authenticateToAllAccessibleRealms();
791
+ }
792
+ // Login here triggers other setup code that needs to happen after
793
+ // otherwise we don't have the realm info.
794
+ // This should be cleaned up as we move to single logins
795
+ await this.loginToRealms();
796
+
797
+ this.postLoginCompleted = true;
798
+ } catch (e) {
799
+ console.log('Error starting Matrix client', e);
800
+ await this.logout();
801
+ }
802
+
803
+ let indexController = getOwner(this)!.lookup(
804
+ 'controller:index',
805
+ ) as IndexController;
806
+
807
+ if (indexController.authRedirect) {
808
+ console.log(
809
+ 'authRedirect exists, redirecting to ' + indexController.authRedirect,
810
+ );
811
+ window.location.href = indexController.authRedirect;
812
+ } else if (refreshRoutes) {
813
+ await this.router.refresh();
814
+ }
815
+ }
816
+ }
817
+
818
+ private async initSlidingSync(accountData?: { realms: string[] } | null) {
819
+ let lists: Map<string, MSC3575List> = new Map();
820
+ lists.set(SLIDING_SYNC_AI_ROOM_LIST_NAME, {
821
+ ranges: [[0, SLIDING_SYNC_LIST_RANGE_END]],
822
+ filters: {
823
+ is_dm: false,
824
+ },
825
+ timeline_limit: SLIDING_SYNC_LIST_TIMELINE_LIMIT,
826
+ required_state: [['*', '*']],
827
+ });
828
+ lists.set(SLIDING_SYNC_AUTH_ROOM_LIST_NAME, {
829
+ ranges: [[0, accountData?.realms.length ?? SLIDING_SYNC_LIST_RANGE_END]],
830
+ filters: {
831
+ is_dm: true,
832
+ },
833
+ timeline_limit: SLIDING_SYNC_LIST_TIMELINE_LIMIT,
834
+ required_state: [['*', '*']],
835
+ });
836
+ this.slidingSync = new this.matrixSdkLoader.SlidingSync(
837
+ this.client.baseUrl,
838
+ lists,
839
+ {
840
+ timeline_limit: SLIDING_SYNC_LIST_TIMELINE_LIMIT,
841
+ },
842
+ this.client as any,
843
+ SLIDING_SYNC_TIMEOUT,
844
+ );
845
+
846
+ this.slidingSync.on(
847
+ SlidingSyncEvent.Lifecycle,
848
+ this.onSlidingSyncLifecycle,
849
+ );
850
+
851
+ return this.slidingSync;
852
+ }
853
+
854
+ onSlidingSyncLifecycle = (
855
+ state: SlidingSyncState,
856
+ resp: MSC3575SlidingSyncResponse | null,
857
+ ) => {
858
+ let list = resp?.lists[SLIDING_SYNC_AI_ROOM_LIST_NAME] as
859
+ | { ops: { room_ids: string[] }[] }
860
+ | undefined;
861
+ let roomIds: string[] = list?.ops?.[0]?.room_ids ?? [];
862
+ switch (state) {
863
+ case SlidingSyncState.Complete:
864
+ if (!this.initialSyncCompleted) {
865
+ Promise.allSettled([
866
+ this.drainRoomState(),
867
+ this.drainMembership(),
868
+ this.drainTimeline(),
869
+ ]).then(() => {
870
+ this.initialSyncCompleted = true;
871
+ this.initialSyncCompletedDeferred.fulfill();
872
+ });
873
+ }
874
+ roomIds.forEach((id) => this.roomsWaitingForSync.get(id)?.fulfill());
875
+ break;
876
+ case SlidingSyncState.RequestFinished:
877
+ roomIds.forEach((id) => this.aiRoomIds.add(id));
878
+ break;
879
+ }
880
+ };
881
+
882
+ async loginToRealms() {
883
+ // This is where we would actually load user-specific choices out of the
884
+ // user's profile based on this.client.getUserId();
885
+ let activeRealms = this.realmServer.availableRealmURLs;
886
+
887
+ await Promise.all(
888
+ activeRealms.map(async (realmURL: string) => {
889
+ try {
890
+ // Our authorization-middleware can login automatically after seeing a
891
+ // 401, but this preemptive login makes it possible to see
892
+ // canWrite===true on realms that are publicly readable.
893
+ await this.realm.login(realmURL);
894
+ } catch (err) {
895
+ console.warn(
896
+ `Unable to establish session with realm ${realmURL}`,
897
+ err,
898
+ );
899
+ }
900
+ }),
901
+ );
902
+ }
903
+
904
+ async createRealmSession(realmURL: URL) {
905
+ await this.#clientReadyDeferred.promise;
906
+ return this.client.createRealmSession(realmURL);
907
+ }
908
+
909
+ async sendEvent(
910
+ roomId: string,
911
+ eventType: string,
912
+ content:
913
+ | BotTriggerContent
914
+ | CardMessageContent
915
+ | CodePatchResultContent
916
+ | CommandResultWithNoOutputContent
917
+ | CommandResultWithOutputContent,
918
+ ) {
919
+ let roomData = this.ensureRoomData(roomId);
920
+ return roomData.mutex.dispatch(async () => {
921
+ if ('data' in content) {
922
+ const encodedContent = {
923
+ ...content,
924
+ data: JSON.stringify(content.data),
925
+ };
926
+ return await this.client.sendEvent(roomId, eventType, encodedContent);
927
+ } else {
928
+ return await this.client.sendEvent(roomId, eventType, content);
929
+ }
930
+ });
931
+ }
932
+
933
+ async downloadCardFileDef(cardFileDef: FileAPI.SerializedFile) {
934
+ return await this.client.downloadCardFileDef(cardFileDef);
935
+ }
936
+
937
+ // Re-upload skills and commands. FileDefManager's cache will ensure we don't re-upload the same content.
938
+ // If there are new urls and content hashes for skills or commands, The room state will be updated.
939
+ async updateSkillsAndCommandsIfNeeded(roomId: string) {
940
+ await this.updateStateEvent(
941
+ roomId,
942
+ APP_BOXEL_ROOM_SKILLS_EVENT_TYPE,
943
+ '',
944
+ async (currentSkillsConfig) => {
945
+ let enabledSkillCardFileDefs =
946
+ (currentSkillsConfig?.enabledSkillCards ??
947
+ []) as FileAPI.SerializedFile[];
948
+ let enabledCommandDefinitions: SkillModule.CommandField[] = [];
949
+ let enabledSkillCards = (
950
+ await Promise.all(
951
+ enabledSkillCardFileDefs.map(async (fileDef) => {
952
+ const card = await this.store.get<SkillModule.Skill>(
953
+ fileDef.sourceUrl,
954
+ );
955
+ if (isSkillCard in card) {
956
+ enabledCommandDefinitions = enabledCommandDefinitions.concat(
957
+ (card as SkillModule.Skill).commands ?? [],
958
+ );
959
+ }
960
+ return card;
961
+ }),
962
+ )
963
+ ).filter((card) => isSkillCard in card) as SkillModule.Skill[];
964
+ let enabledSkillFileDefs = await this.uploadCards(
965
+ enabledSkillCards as CardDef[],
966
+ );
967
+ // get the unique subset of enabledCommandDefinitions by functionName
968
+ enabledCommandDefinitions = this.getUniqueCommandDefinitions(
969
+ enabledCommandDefinitions,
970
+ );
971
+ let enabledCommandDefFileDefs = await this.uploadCommandDefinitions(
972
+ enabledCommandDefinitions,
973
+ );
974
+ return {
975
+ enabledSkillCards: enabledSkillFileDefs.map((fileDef) =>
976
+ fileDef.serialize(),
977
+ ),
978
+ disabledSkillCards: currentSkillsConfig?.disabledSkillCards ?? [],
979
+ commandDefinitions: enabledCommandDefFileDefs.map((fileDef) =>
980
+ fileDef.serialize(),
981
+ ),
982
+ };
983
+ },
984
+ );
985
+ }
986
+
987
+ async downloadAsFileInBrowser(serializedFile: FileAPI.SerializedFile) {
988
+ return await this.client.downloadAsFileInBrowser(serializedFile);
989
+ }
990
+
991
+ public getUniqueCommandDefinitions(
992
+ commandDefinitions: SkillModule.CommandField[],
993
+ ): SkillModule.CommandField[] {
994
+ return getUniqueValidCommandDefinitions(commandDefinitions);
995
+ }
996
+
997
+ async uploadCards(cards: CardDef[]) {
998
+ let cardFileDefs = await this.client.uploadCards(cards);
999
+ return cardFileDefs;
1000
+ }
1001
+
1002
+ async uploadCommandDefinitions(
1003
+ commandDefinitions: SkillModule.CommandField[],
1004
+ ) {
1005
+ let validCommandDefinitions =
1006
+ getUniqueValidCommandDefinitions(commandDefinitions);
1007
+ if (validCommandDefinitions.length === 0) {
1008
+ return [];
1009
+ }
1010
+ let commandFileDefs = await this.client.uploadCommandDefinitions(
1011
+ validCommandDefinitions,
1012
+ );
1013
+ return commandFileDefs;
1014
+ }
1015
+
1016
+ async cacheContentHashIfNeeded(event: DiscreteMatrixEvent) {
1017
+ await this.client.cacheContentHashIfNeeded(event);
1018
+ }
1019
+
1020
+ async sendStopGeneratingEvent(roomId: string) {
1021
+ return await this.client.sendEvent(
1022
+ roomId,
1023
+ APP_BOXEL_STOP_GENERATING_EVENT_TYPE,
1024
+ {},
1025
+ );
1026
+ }
1027
+
1028
+ async sendCommandResultEvent(params: {
1029
+ roomId: string;
1030
+ invokedToolFromEventId: string;
1031
+ toolCallId: string;
1032
+ status: CommandResultStatus;
1033
+ resultCard?: CardDef;
1034
+ failureReason?: string;
1035
+ attachedCards?: CardDef[];
1036
+ attachedFiles?: FileDef[];
1037
+ context?: BoxelContext;
1038
+ }) {
1039
+ let resultCardFileDef: FileDef | undefined;
1040
+ if (params.resultCard) {
1041
+ [resultCardFileDef] = await this.client.uploadCards([params.resultCard]);
1042
+ }
1043
+ let contentData = await this.withContextAndAttachments(
1044
+ params.context,
1045
+ params.attachedCards || [],
1046
+ params.attachedFiles || [],
1047
+ );
1048
+ if ((params.resultCard as FileForAttachmentCard)?.fileForAttachment) {
1049
+ contentData.attachedFiles.push(
1050
+ (
1051
+ (params.resultCard as FileForAttachmentCard)!
1052
+ .fileForAttachment as unknown as FileDef
1053
+ ).serialize(),
1054
+ );
1055
+ resultCardFileDef = undefined; // don't send the card as a result if the file is attached
1056
+ }
1057
+ if ((params.resultCard as CardForAttachmentCard)?.cardForAttachment) {
1058
+ contentData.attachedCards.push(
1059
+ (
1060
+ (params.resultCard as CardForAttachmentCard)!
1061
+ .cardForAttachment as unknown as FileDef
1062
+ ).serialize(),
1063
+ );
1064
+ resultCardFileDef = undefined; // don't send the card as a result if the card is attached
1065
+ }
1066
+ let content:
1067
+ | CommandResultWithNoOutputContent
1068
+ | CommandResultWithOutputContent;
1069
+ if (resultCardFileDef === undefined) {
1070
+ content = {
1071
+ msgtype: APP_BOXEL_COMMAND_RESULT_WITH_NO_OUTPUT_MSGTYPE,
1072
+ commandRequestId: params.toolCallId,
1073
+ failureReason: params.failureReason,
1074
+ 'm.relates_to': {
1075
+ event_id: params.invokedToolFromEventId,
1076
+ key: params.status,
1077
+ rel_type: APP_BOXEL_COMMAND_RESULT_REL_TYPE,
1078
+ },
1079
+ data: contentData,
1080
+ };
1081
+ } else {
1082
+ content = {
1083
+ msgtype: APP_BOXEL_COMMAND_RESULT_WITH_OUTPUT_MSGTYPE,
1084
+ 'm.relates_to': {
1085
+ event_id: params.invokedToolFromEventId,
1086
+ key: params.status,
1087
+ rel_type: APP_BOXEL_COMMAND_RESULT_REL_TYPE,
1088
+ },
1089
+ commandRequestId: params.toolCallId,
1090
+ failureReason: params.failureReason,
1091
+ data: {
1092
+ ...contentData,
1093
+ card: resultCardFileDef.serialize(),
1094
+ },
1095
+ };
1096
+ }
1097
+ try {
1098
+ return await this.sendEvent(
1099
+ params.roomId,
1100
+ APP_BOXEL_COMMAND_RESULT_EVENT_TYPE,
1101
+ content,
1102
+ );
1103
+ } catch (e) {
1104
+ throw new Error(
1105
+ `Error sending command result event: ${
1106
+ 'message' in (e as Error) ? (e as Error).message : e
1107
+ }`,
1108
+ );
1109
+ }
1110
+ }
1111
+
1112
+ async sendCodePatchResultEvent(
1113
+ roomId: string,
1114
+ eventId: string,
1115
+ codeBlockIndex: number,
1116
+ resultKey: CodePatchStatus,
1117
+ attachedCards: CardDef[] = [],
1118
+ attachedFiles: FileDef[] = [],
1119
+ context: BoxelContext,
1120
+ lintIssues?: string[],
1121
+ failureReason?: string | undefined,
1122
+ ) {
1123
+ let contentData = await this.withContextAndAttachments(
1124
+ context,
1125
+ attachedCards,
1126
+ attachedFiles,
1127
+ );
1128
+ let normalizedLintIssues = lintIssues || [];
1129
+ let data: CodePatchResultContent['data'] = {
1130
+ ...contentData,
1131
+ ...(normalizedLintIssues.length
1132
+ ? { lintIssues: normalizedLintIssues }
1133
+ : {}),
1134
+ };
1135
+ let content: CodePatchResultContent = {
1136
+ msgtype: APP_BOXEL_CODE_PATCH_RESULT_MSGTYPE,
1137
+ codeBlockIndex,
1138
+ failureReason,
1139
+ 'm.relates_to': {
1140
+ event_id: eventId,
1141
+ key: resultKey,
1142
+ rel_type: APP_BOXEL_CODE_PATCH_RESULT_REL_TYPE,
1143
+ },
1144
+ data,
1145
+ };
1146
+ try {
1147
+ return await this.sendEvent(
1148
+ roomId,
1149
+ APP_BOXEL_CODE_PATCH_RESULT_EVENT_TYPE,
1150
+ content,
1151
+ );
1152
+ } catch (e) {
1153
+ throw new Error(
1154
+ `Error sending code patch result event: ${
1155
+ 'message' in (e as Error) ? (e as Error).message : e
1156
+ }`,
1157
+ );
1158
+ }
1159
+ }
1160
+
1161
+ async uploadFiles(files: FileDef[]) {
1162
+ return await this.client.uploadFiles(files);
1163
+ }
1164
+
1165
+ async prefetchFileContent(file: FileDef) {
1166
+ return await this.client.prefetchFileContent(file);
1167
+ }
1168
+
1169
+ async prefetchLocalFileContent(
1170
+ file: FileDef,
1171
+ bytes: Uint8Array,
1172
+ contentType: string,
1173
+ ) {
1174
+ return await this.client.prefetchLocalFileContent(file, bytes, contentType);
1175
+ }
1176
+
1177
+ async fetchMatrixHostedFile(matrixFileUrl: string) {
1178
+ let response = await fetch(matrixFileUrl, {
1179
+ headers: {
1180
+ Authorization: `Bearer ${this.client.getAccessToken()}`,
1181
+ },
1182
+ });
1183
+ return response;
1184
+ }
1185
+
1186
+ async sendMessage(
1187
+ roomId: string,
1188
+ body: string | undefined,
1189
+ attachedCards: CardDef[] = [],
1190
+ attachedFiles: FileDef[] = [],
1191
+ clientGeneratedId = uuidv4(),
1192
+ context?: BoxelContext,
1193
+ ): Promise<void> {
1194
+ let tools: Tool[] = [];
1195
+ // Open cards are attached automatically
1196
+ // If they are not attached, the user is not allowing us to
1197
+ // modify them
1198
+ let openCardIds = context?.openCardIds ?? [];
1199
+ let patchableCards = attachedCards
1200
+ .filter((c) => openCardIds.includes(c.id))
1201
+ .filter((c) => this.realm.canWrite(c.id));
1202
+ // Generate tool calls for patching currently open cards permitted for modification
1203
+ tools = tools.concat(
1204
+ await addPatchTools(
1205
+ this.commandService.commandContext,
1206
+ patchableCards,
1207
+ this.cardAPI,
1208
+ ),
1209
+ );
1210
+
1211
+ await this.updateSkillsAndCommandsIfNeeded(roomId);
1212
+ let contentData = await this.withContextAndAttachments(
1213
+ context,
1214
+ attachedCards,
1215
+ attachedFiles,
1216
+ );
1217
+
1218
+ await this.sendEvent(roomId, 'm.room.message', {
1219
+ msgtype: APP_BOXEL_MESSAGE_MSGTYPE,
1220
+ body: body || '',
1221
+ format: 'org.matrix.custom.html',
1222
+ clientGeneratedId,
1223
+ data: {
1224
+ attachedFiles: contentData.attachedFiles,
1225
+ attachedCards: contentData.attachedCards,
1226
+ context: {
1227
+ ...contentData.context,
1228
+ tools,
1229
+ debug: context?.debug,
1230
+ functions: [],
1231
+ },
1232
+ },
1233
+ } as CardMessageContent);
1234
+ }
1235
+
1236
+ private async withContextAndAttachments(
1237
+ context?: BoxelContext,
1238
+ attachedCards: CardDef[] = [],
1239
+ attachedFiles: FileDef[] = [],
1240
+ ): Promise<{
1241
+ context: BoxelContext | undefined;
1242
+ attachedCards: ReturnType<FileDef['serialize']>[];
1243
+ attachedFiles: ReturnType<FileDef['serialize']>[];
1244
+ }> {
1245
+ let cardFileDefs = await this.uploadCards(attachedCards);
1246
+ // Skip files that were already eagerly uploaded by startFileUpload (url
1247
+ // differs from sourceUrl, meaning they already point to Matrix media).
1248
+ let filesToUpload = attachedFiles.filter(
1249
+ (f) => !f.url || f.url === f.sourceUrl,
1250
+ );
1251
+ let uploadedBySourceUrl = new Map<string, FileDef>();
1252
+ if (filesToUpload.length > 0) {
1253
+ let uploaded = await this.uploadFiles(filesToUpload);
1254
+ for (let file of uploaded) {
1255
+ if (file.sourceUrl) {
1256
+ uploadedBySourceUrl.set(file.sourceUrl, file);
1257
+ }
1258
+ }
1259
+ }
1260
+ let filesForMessage = attachedFiles.map((file) => {
1261
+ let replacement = file.sourceUrl
1262
+ ? uploadedBySourceUrl.get(file.sourceUrl)
1263
+ : undefined;
1264
+ return replacement ?? file;
1265
+ });
1266
+
1267
+ return {
1268
+ context,
1269
+ attachedCards: cardFileDefs.map((file: FileDef) => file.serialize()),
1270
+ attachedFiles: filesForMessage.map((file: FileDef) => file.serialize()),
1271
+ };
1272
+ }
1273
+
1274
+ getLastActiveTimestamp(roomId: string, defaultTimestamp: number) {
1275
+ let matrixRoom = this.client.getRoom(roomId);
1276
+ let lastMatrixEvent = matrixRoom?.getLastActiveTimestamp();
1277
+ return lastMatrixEvent ?? defaultTimestamp;
1278
+ }
1279
+
1280
+ async requestRegisterEmailToken(
1281
+ email: string,
1282
+ clientSecret: string,
1283
+ sendAttempt: number,
1284
+ ) {
1285
+ return await this.client.requestEmailToken(
1286
+ 'registration',
1287
+ email,
1288
+ clientSecret,
1289
+ sendAttempt,
1290
+ );
1291
+ }
1292
+
1293
+ async requestChangeEmailToken(
1294
+ email: string,
1295
+ clientSecret: string,
1296
+ sendAttempt: number,
1297
+ ) {
1298
+ return await this.client.requestEmailToken(
1299
+ 'threepid',
1300
+ email,
1301
+ clientSecret,
1302
+ sendAttempt,
1303
+ );
1304
+ }
1305
+
1306
+ async login(usernameOrEmail: string, password: string) {
1307
+ try {
1308
+ const cred = await this.client.loginWithPassword(
1309
+ usernameOrEmail,
1310
+ password,
1311
+ );
1312
+ return cred;
1313
+ } catch (error) {
1314
+ try {
1315
+ const cred = await this.client.loginWithEmail(
1316
+ usernameOrEmail,
1317
+ password,
1318
+ );
1319
+ return cred;
1320
+ } catch (error2) {
1321
+ throw error;
1322
+ }
1323
+ }
1324
+ }
1325
+
1326
+ getRoomData(roomId: string) {
1327
+ return this.roomDataMap.get(roomId);
1328
+ }
1329
+
1330
+ private setRoomData(roomId: string, roomData: Room) {
1331
+ this.roomDataMap.set(roomId, roomData);
1332
+ if (!this.roomResourcesCache.has(roomId)) {
1333
+ this.roomResourcesCache.set(
1334
+ roomId,
1335
+ getRoom(
1336
+ this,
1337
+ () => roomId,
1338
+ () => {
1339
+ let data = this.getRoomData(roomId);
1340
+ // Return both _events and _roomState (via hasRoomState) so the
1341
+ // resource re-runs when either changes. processRoomTask returns
1342
+ // early if the aiBot isn't in memberIds, and memberIds is
1343
+ // derived from _roomState (set by drainRoomState) independently
1344
+ // from _events (updated by drainTimeline). Encoding both as the
1345
+ // returned arg ensures invalidation regardless of whether
1346
+ // ember-resources reacts to consumed-but-unreturned tracked deps
1347
+ // or only to argument value changes.
1348
+ return [data?.events, data?.hasRoomState] as const;
1349
+ },
1350
+ ),
1351
+ );
1352
+ }
1353
+ }
1354
+
1355
+ async loadDefaultSkills(submode: Submode) {
1356
+ let interactModeDefaultSkills = [envSkillId];
1357
+
1358
+ let codeModeDefaultSkills = [
1359
+ devSkillId,
1360
+ envSkillId,
1361
+ skillCardURL('source-code-editing'),
1362
+ ];
1363
+
1364
+ let defaultSkills;
1365
+
1366
+ if (submode === 'code') {
1367
+ defaultSkills = codeModeDefaultSkills;
1368
+ } else {
1369
+ defaultSkills = interactModeDefaultSkills;
1370
+ }
1371
+
1372
+ return (
1373
+ await Promise.all(
1374
+ defaultSkills.map(async (skillCardURL) => {
1375
+ let maybeCard = await this.store.get<SkillModule.Skill>(skillCardURL);
1376
+ return isCardInstance(maybeCard) ? maybeCard : undefined;
1377
+ }),
1378
+ )
1379
+ ).filter(Boolean) as SkillModule.Skill[];
1380
+ }
1381
+
1382
+ @cached
1383
+ get roomResources() {
1384
+ let resources: TrackedMap<string, RoomResource> = new TrackedMap();
1385
+ for (let roomId of this.roomDataMap.keys()) {
1386
+ if (!this.roomResourcesCache.get(roomId)) {
1387
+ continue;
1388
+ }
1389
+ resources.set(roomId, this.roomResourcesCache.get(roomId)!);
1390
+ }
1391
+ return resources;
1392
+ }
1393
+
1394
+ resetState() {
1395
+ this.teardownClient();
1396
+ this.roomDataMap.clear();
1397
+ this.roomMembershipQueue = [];
1398
+ this.roomStateQueue = [];
1399
+ for (let roomResource of this.roomResourcesCache.values()) {
1400
+ roomResource.teardown();
1401
+ }
1402
+ this.roomResourcesCache.clear();
1403
+ this.canceledActionMessageIdByRoom.clear();
1404
+ this.failedCommandState.clear();
1405
+ this.reasoningExpandedState.clear();
1406
+ this.timelineQueue = [];
1407
+ this.flushMembership = undefined;
1408
+ this.flushTimeline = undefined;
1409
+ this.flushRoomState = undefined;
1410
+ this.timelineLoadingState.clear();
1411
+ this._client = this.#matrixSDK?.createClient({ baseUrl: matrixURL });
1412
+ this._currentRoomId = undefined;
1413
+ this._isInitializingNewUser = false;
1414
+ this.postLoginCompleted = false;
1415
+ this._isLoadingMoreAIRooms = false;
1416
+ this.messagesToSend.clear();
1417
+ this.cardsToSend.clear();
1418
+ this.filesToSend.clear();
1419
+ this.currentUserEventReadReceipts.clear();
1420
+ this.restoredDraftRooms = new Set();
1421
+ this.aiRoomIds.clear();
1422
+ this.initialSyncCompleted = false;
1423
+ this.initialSyncCompletedDeferred = new Deferred<void>();
1424
+ this.roomsWaitingForSync.clear();
1425
+ this._systemCard = undefined;
1426
+ this.startedAtTs = -1;
1427
+ this.#clientReadyDeferred = new Deferred<void>();
1428
+ }
1429
+
1430
+ private teardownClient() {
1431
+ if (this.#eventBindings && this._client) {
1432
+ this.unbindEventListeners();
1433
+ }
1434
+ this.slidingSync?.off?.(
1435
+ SlidingSyncEvent.Lifecycle,
1436
+ this.onSlidingSyncLifecycle,
1437
+ );
1438
+ this.slidingSync?.stop?.();
1439
+ this.slidingSync = undefined;
1440
+ this._client?.stopClient?.();
1441
+ }
1442
+
1443
+ markActionAsCanceled(roomId: string, eventId: string) {
1444
+ this.canceledActionMessageIdByRoom.set(roomId, eventId);
1445
+ }
1446
+
1447
+ getLastCanceledActionEventId(roomId: string): string | undefined {
1448
+ return this.canceledActionMessageIdByRoom.get(roomId);
1449
+ }
1450
+
1451
+ private bindEventListeners() {
1452
+ if (!this.#eventBindings) {
1453
+ throw new Error(
1454
+ `cannot bind to matrix events before the matrix SDK has loaded`,
1455
+ );
1456
+ }
1457
+ for (let [event, handler] of this.#eventBindings) {
1458
+ this.client.on(event, handler);
1459
+ }
1460
+ }
1461
+ private unbindEventListeners() {
1462
+ if (!this.#eventBindings) {
1463
+ throw new Error(
1464
+ `cannot unbind to matrix events before the matrix SDK has loaded`,
1465
+ );
1466
+ }
1467
+ for (let [event, handler] of this.#eventBindings) {
1468
+ this.client.off(event, handler);
1469
+ }
1470
+ }
1471
+
1472
+ async createRoom(opts: MatrixSDK.ICreateRoomOpts) {
1473
+ let result = await this.client.createRoom(opts);
1474
+ await this.waitForRoomSync(result.room_id);
1475
+ return result;
1476
+ }
1477
+
1478
+ async waitForRoomSync(roomId: string) {
1479
+ let deferred = this.roomsWaitingForSync.get(roomId);
1480
+ if (!deferred) {
1481
+ deferred = new Deferred<void>();
1482
+ this.roomsWaitingForSync.set(roomId, deferred);
1483
+ }
1484
+ await deferred.promise;
1485
+ this.roomsWaitingForSync.delete(roomId);
1486
+ }
1487
+
1488
+ async createCard<T extends typeof BaseDef>(
1489
+ codeRef: ResolvedCodeRef,
1490
+ attr: Record<string, any>,
1491
+ ) {
1492
+ let data: LooseCardResource = {
1493
+ meta: {
1494
+ adoptsFrom: codeRef,
1495
+ },
1496
+ attributes: {
1497
+ ...attr,
1498
+ },
1499
+ };
1500
+ let card = await this.cardAPI.createFromSerialized<T>(
1501
+ data,
1502
+ { data },
1503
+ undefined,
1504
+ );
1505
+ return card;
1506
+ }
1507
+
1508
+ async getProfileInfo(userId: string) {
1509
+ return await this.client.getProfileInfo(userId);
1510
+ }
1511
+
1512
+ async getThreePids() {
1513
+ return await this.client.getThreePids();
1514
+ }
1515
+
1516
+ async addThreePidOnly(data: MatrixSDK.IAddThreePidOnlyBody) {
1517
+ return await this.client.addThreePidOnly(data);
1518
+ }
1519
+
1520
+ async deleteThreePid(medium: string, address: string) {
1521
+ return await this.client.deleteThreePid(medium, address);
1522
+ }
1523
+
1524
+ async setPowerLevel(roomId: string, userId: string, powerLevel: number) {
1525
+ let roomData = this.ensureRoomData(roomId);
1526
+ await roomData.mutex.dispatch(async () => {
1527
+ return this.client.setPowerLevel(roomId, userId, powerLevel);
1528
+ });
1529
+ }
1530
+
1531
+ async inviteUserToRoom(roomId: string, userId: string) {
1532
+ let roomData = this.ensureRoomData(roomId);
1533
+ await roomData.mutex.dispatch(async () => {
1534
+ return this.client.invite(roomId, userId);
1535
+ });
1536
+ }
1537
+
1538
+ async getStateEvent(
1539
+ roomId: string,
1540
+ eventType: string,
1541
+ stateKey: string = '',
1542
+ ) {
1543
+ return this.client.getStateEvent(roomId, eventType, stateKey);
1544
+ }
1545
+
1546
+ async getStateEventSafe(
1547
+ roomId: string,
1548
+ eventType: string,
1549
+ stateKey: string = '',
1550
+ ) {
1551
+ try {
1552
+ return await this.client.getStateEvent(roomId, eventType, stateKey);
1553
+ } catch (e: unknown) {
1554
+ if (e instanceof Error && 'errcode' in e && e.errcode === 'M_NOT_FOUND') {
1555
+ // this is fine, it just means the state event doesn't exist yet
1556
+ return undefined;
1557
+ } else {
1558
+ throw e;
1559
+ }
1560
+ }
1561
+ }
1562
+
1563
+ async sendStateEvent(
1564
+ roomId: string,
1565
+ eventType: string,
1566
+ content: Record<string, any>,
1567
+ stateKey: string = '',
1568
+ ) {
1569
+ let roomData = this.ensureRoomData(roomId);
1570
+ await roomData.mutex.dispatch(async () => {
1571
+ return this.client.sendStateEvent(roomId, eventType, content, stateKey);
1572
+ });
1573
+ }
1574
+
1575
+ async updateStateEvent(
1576
+ roomId: string,
1577
+ eventType: string,
1578
+ stateKey: string = '',
1579
+ transformContent: (
1580
+ content: Record<string, any>,
1581
+ ) => Promise<Record<string, any>>,
1582
+ ) {
1583
+ let roomData = this.ensureRoomData(roomId);
1584
+ await roomData.mutex.dispatch(async () => {
1585
+ let currentContent = await this.getStateEventSafe(
1586
+ roomId,
1587
+ eventType,
1588
+ stateKey,
1589
+ );
1590
+
1591
+ // Store the original content string for comparison
1592
+ let currentContentString = stringify(currentContent ?? {});
1593
+ let newContent = await transformContent(currentContent ?? {});
1594
+
1595
+ // Skip sending state event if content hasn't changed
1596
+ if (currentContentString === stringify(newContent)) {
1597
+ return;
1598
+ }
1599
+
1600
+ return this.client.sendStateEvent(
1601
+ roomId,
1602
+ eventType,
1603
+ newContent,
1604
+ stateKey,
1605
+ );
1606
+ });
1607
+ }
1608
+
1609
+ async leave(roomId: string) {
1610
+ let roomData = this.ensureRoomData(roomId);
1611
+ await roomData.mutex.dispatch(async () => {
1612
+ return this.client.leave(roomId);
1613
+ });
1614
+ }
1615
+
1616
+ async forget(roomId: string) {
1617
+ let roomData = this.ensureRoomData(roomId);
1618
+ await roomData.mutex.dispatch(async () => {
1619
+ return this.client.forget(roomId);
1620
+ });
1621
+ }
1622
+
1623
+ async setRoomName(roomId: string, name: string) {
1624
+ let roomData = this.ensureRoomData(roomId);
1625
+ await roomData.mutex.dispatch(async () => {
1626
+ return this.client.setRoomName(roomId, name);
1627
+ });
1628
+ }
1629
+
1630
+ async requestPasswordEmailToken(
1631
+ email: string,
1632
+ clientSecret: string,
1633
+ sendAttempt: number,
1634
+ nextLink?: string,
1635
+ ) {
1636
+ return await this.client.requestPasswordEmailToken(
1637
+ email,
1638
+ clientSecret,
1639
+ sendAttempt,
1640
+ nextLink,
1641
+ );
1642
+ }
1643
+
1644
+ async setPassword(
1645
+ authDict: MatrixSDK.AuthDict,
1646
+ newPassword: string,
1647
+ logoutDevices?: boolean,
1648
+ ) {
1649
+ return await this.client.setPassword(authDict, newPassword, logoutDevices);
1650
+ }
1651
+
1652
+ async registerRequest(data: MatrixSDK.RegisterRequest, kind?: string) {
1653
+ return await this.client.registerRequest(data, kind);
1654
+ }
1655
+
1656
+ // Type of matrixEvent is a partial MatrixEvent because a couple of places
1657
+ // where this method is called don't have the full MatrixEvent type available
1658
+ async sendReadReceipt(
1659
+ matrixEvent: Pick<MatrixEvent, 'getId' | 'getRoomId' | 'getTs'>,
1660
+ ) {
1661
+ return await this.client.sendReadReceipt(matrixEvent as MatrixEvent);
1662
+ }
1663
+
1664
+ async isUsernameAvailable(username: string) {
1665
+ return await this.client.isUsernameAvailable(username);
1666
+ }
1667
+
1668
+ private async loadAllTimelineEvents(roomId: string) {
1669
+ let roomData = this.ensureRoomData(roomId);
1670
+ let room = this.client.getRoom(roomId);
1671
+ let roomResource = this.roomResources.get(roomId);
1672
+
1673
+ if (!room || !roomResource) {
1674
+ throw new Error(`Cannot find room with id ${roomId}`);
1675
+ }
1676
+
1677
+ if (this.timelineLoadingState.get(roomId)) {
1678
+ return;
1679
+ }
1680
+
1681
+ this.timelineLoadingState.set(roomId, true);
1682
+ try {
1683
+ // Create a filter that includes all events
1684
+ let filter = new Filter(this.client.getUserId()!, 'old_messages');
1685
+ filter.setDefinition({
1686
+ room: {
1687
+ timeline: {
1688
+ limit: 100,
1689
+ not_types: [APP_BOXEL_STOP_GENERATING_EVENT_TYPE],
1690
+ 'org.matrix.msc3874.not_rel_types': ['m.replace'],
1691
+ },
1692
+ },
1693
+ });
1694
+
1695
+ // Get or create a filtered timeline set
1696
+ let timelineSet = room.getOrCreateFilteredTimelineSet(filter, {
1697
+ prepopulateTimeline: true,
1698
+ useSyncEvents: true,
1699
+ });
1700
+
1701
+ let timeline = timelineSet.getLiveTimeline();
1702
+ if (timeline.getPaginationToken('b' as MatrixSDK.Direction) == null) {
1703
+ return;
1704
+ }
1705
+
1706
+ while (timeline.getPaginationToken('b' as MatrixSDK.Direction) != null) {
1707
+ await this.client.paginateEventTimeline(timeline, {
1708
+ backwards: true,
1709
+ });
1710
+ }
1711
+
1712
+ let rs = room.getLiveTimeline().getState('f' as MatrixSDK.Direction);
1713
+ if (rs) {
1714
+ roomData.notifyRoomStateUpdated(rs);
1715
+ }
1716
+
1717
+ // Wait for all events to be loaded in roomResource
1718
+ let events = timeline.getEvents();
1719
+ this.timelineQueue.push(...events.map((e) => ({ event: e })));
1720
+ await this.drainTimeline();
1721
+ await this.roomResources.get(roomId)?.processing;
1722
+ } finally {
1723
+ this.timelineLoadingState.set(roomId, false);
1724
+ }
1725
+ }
1726
+
1727
+ get isLoadingTimeline() {
1728
+ if (!this.currentRoomId) {
1729
+ return false;
1730
+ }
1731
+ return this.timelineLoadingState.get(this.currentRoomId) ?? false;
1732
+ }
1733
+
1734
+ async sendActiveLLMEvent(
1735
+ roomId: string,
1736
+ model: string,
1737
+ config?: {
1738
+ toolsSupported?: boolean;
1739
+ reasoningEffort?: string;
1740
+ inputModalities?: string[];
1741
+ },
1742
+ ) {
1743
+ let resolvedConfig = config;
1744
+ if (!resolvedConfig) {
1745
+ let modelConfiguration = this.systemCard?.modelConfigurations?.find(
1746
+ (configuration) => configuration.modelId === model,
1747
+ );
1748
+ if (modelConfiguration) {
1749
+ resolvedConfig = {
1750
+ toolsSupported: modelConfiguration.toolsSupported,
1751
+ reasoningEffort: modelConfiguration.reasoningEffort,
1752
+ inputModalities: modelConfiguration.inputModalities,
1753
+ };
1754
+ }
1755
+ }
1756
+
1757
+ await this.client.sendStateEvent(roomId, APP_BOXEL_ACTIVE_LLM, {
1758
+ model,
1759
+ toolsSupported: resolvedConfig?.toolsSupported,
1760
+ reasoningEffort: resolvedConfig?.reasoningEffort,
1761
+ inputModalities: resolvedConfig?.inputModalities,
1762
+ });
1763
+ }
1764
+
1765
+ async sendLLMModeEvent(roomId: string, mode: LLMMode) {
1766
+ await this.client.sendStateEvent(roomId, APP_BOXEL_LLM_MODE, { mode });
1767
+ }
1768
+
1769
+ private async addRoomEvent(event: TempEvent, oldEventId?: string) {
1770
+ let { room_id: roomId } = event;
1771
+
1772
+ if (!roomId) {
1773
+ throw new Error(
1774
+ `bug: roomId is undefined for event ${JSON.stringify(event, null, 2)}`,
1775
+ );
1776
+ }
1777
+
1778
+ //We don't need to store auth room events
1779
+ if (!this.aiRoomIds.has(roomId)) {
1780
+ return;
1781
+ }
1782
+ let roomData = this.ensureRoomData(roomId);
1783
+ roomData.addEvent(event, oldEventId);
1784
+ }
1785
+
1786
+ private ensureRoomData(roomId: string) {
1787
+ let roomData = this.getRoomData(roomId);
1788
+ if (!roomData) {
1789
+ roomData = new Room(roomId);
1790
+ this.setRoomData(roomId, roomData);
1791
+ }
1792
+ return roomData;
1793
+ }
1794
+
1795
+ private onMembership = (event: MatrixEvent, member: RoomMember) => {
1796
+ this.roomMembershipQueue.push({ event, member });
1797
+ debounce(this, this.drainMembership, 100);
1798
+ };
1799
+
1800
+ private async drainMembership() {
1801
+ await this.flushMembership;
1802
+
1803
+ let eventsDrained: () => void;
1804
+ this.flushMembership = new Promise((res) => (eventsDrained = res));
1805
+
1806
+ try {
1807
+ let events = [...this.roomMembershipQueue];
1808
+ this.roomMembershipQueue = [];
1809
+
1810
+ await Promise.all(
1811
+ events.map(({ event: { event, status } }) =>
1812
+ this.addRoomEvent({ ...event, status }),
1813
+ ),
1814
+ );
1815
+
1816
+ // For rooms that we have been invited to we are unable to get the full
1817
+ // timeline event yet (it's not available until we join the room), but we
1818
+ // still need to get enough room state events to reasonably render the
1819
+ // room card.
1820
+ for (let {
1821
+ event: { event: rawEvent },
1822
+ member,
1823
+ } of events) {
1824
+ let event = rawEvent as DiscreteMatrixEvent;
1825
+ let { room_id: roomId } = rawEvent as DiscreteMatrixEvent;
1826
+ if (!roomId) {
1827
+ throw new Error(
1828
+ `bug: roomId is undefined for event ${JSON.stringify(
1829
+ event,
1830
+ null,
1831
+ 2,
1832
+ )}`,
1833
+ );
1834
+ }
1835
+ let room = this.client.getRoom(roomId);
1836
+ if (!room) {
1837
+ throw new Error(
1838
+ `bug: should never get here--matrix sdk returned a null room for ${roomId}`,
1839
+ );
1840
+ }
1841
+
1842
+ if (
1843
+ member.userId === this.client.getUserId() &&
1844
+ event.type === 'm.room.member' &&
1845
+ room.getMyMembership() === 'invite'
1846
+ ) {
1847
+ if (event.content.membership === 'invite') {
1848
+ let stateEvents = room
1849
+ .getLiveTimeline()
1850
+ .getState('f' as MatrixSDK.Direction)?.events;
1851
+ if (!stateEvents) {
1852
+ throw new Error(
1853
+ `bug: cannot get state events for room ${roomId}`,
1854
+ );
1855
+ }
1856
+ for (let eventType of STATE_EVENTS_OF_INTEREST) {
1857
+ let events = stateEvents.get(eventType);
1858
+ if (!events) {
1859
+ continue;
1860
+ }
1861
+ await Promise.all(
1862
+ [...events.values()]
1863
+ .map((e) => ({
1864
+ ...e.event,
1865
+ // annoyingly these events have been stripped of their id's
1866
+ event_id: `${roomId}_${eventType}_${e.localTimestamp}`,
1867
+ status: e.status,
1868
+ }))
1869
+ .map((event) => this.addRoomEvent(event)),
1870
+ );
1871
+ }
1872
+ }
1873
+ }
1874
+ }
1875
+ } finally {
1876
+ eventsDrained!();
1877
+ }
1878
+ }
1879
+
1880
+ private onReceipt = async (e: MatrixEvent) => {
1881
+ let userId = this.client.credentials.userId;
1882
+ if (userId) {
1883
+ let eventIds = Object.keys(e.getContent());
1884
+ for (let eventId of eventIds) {
1885
+ let receipt = e.getContent()[eventId]['m.read'][userId];
1886
+ if (receipt) {
1887
+ this.addEventReadReceipt(eventId, { readAt: receipt.ts });
1888
+ }
1889
+ }
1890
+ }
1891
+ };
1892
+
1893
+ private onRoomStateUpdate = (rs: MatrixSDK.RoomState) => {
1894
+ this.roomStateQueue.push(rs);
1895
+ debounce(this, this.drainRoomState, 100);
1896
+ };
1897
+
1898
+ private drainRoomState = async () => {
1899
+ await this.flushRoomState;
1900
+
1901
+ let roomStateUpdatesDrained: () => void;
1902
+ this.flushRoomState = new Promise((res) => (roomStateUpdatesDrained = res));
1903
+
1904
+ let roomStates = [...this.roomStateQueue];
1905
+ this.roomStateQueue = [];
1906
+ const roomStateMap = new Map<string, MatrixSDK.RoomState>();
1907
+ for (const rs of roomStates) {
1908
+ roomStateMap.set(rs.roomId, rs);
1909
+ }
1910
+ roomStates = Array.from(roomStateMap.values());
1911
+ for (let rs of roomStates) {
1912
+ // The auth rooms are not stored
1913
+ // so we don't need to process the state updates
1914
+ if (!this.aiRoomIds.has(rs.roomId)) {
1915
+ continue;
1916
+ }
1917
+ let roomData = this.ensureRoomData(rs.roomId);
1918
+ roomData.notifyRoomStateUpdated(rs);
1919
+ }
1920
+ roomStateUpdatesDrained!();
1921
+ };
1922
+
1923
+ private onTimeline = (e: MatrixEvent) => {
1924
+ this.timelineQueue.push({ event: e });
1925
+ debounce(this, this.drainTimeline, 100);
1926
+ };
1927
+
1928
+ private onUpdateEventStatus = (
1929
+ e: MatrixEvent,
1930
+ _room: unknown,
1931
+ maybeOldEventId?: string,
1932
+ ) => {
1933
+ this.timelineQueue.push({ event: e, oldEventId: maybeOldEventId });
1934
+ debounce(this, this.drainTimeline, 100);
1935
+ };
1936
+
1937
+ private buildEventForProcessing(event: MatrixEvent) {
1938
+ // Restructure the event, ensuring keys exist
1939
+ let restructuredEvent = {
1940
+ ...event.event,
1941
+ status: event.status,
1942
+ content: event.getContent() || undefined,
1943
+ error: event.error ?? undefined,
1944
+ };
1945
+ // Make a deep copy of the event to avoid mutating the original Matrix SDK event
1946
+ // This is necessary because the event returned is one we pass in, and this function
1947
+ // may run before the event itself is sent.
1948
+ // To avoid hard to track down bugs, we make a deep copy of the event here.
1949
+ return cloneDeep(restructuredEvent);
1950
+ }
1951
+
1952
+ private async drainTimeline() {
1953
+ await this.flushTimeline;
1954
+
1955
+ let eventsDrained: () => void;
1956
+ this.flushTimeline = new Promise((res) => (eventsDrained = res));
1957
+ try {
1958
+ let events = [...this.timelineQueue];
1959
+ this.timelineQueue = [];
1960
+ for (let { event, oldEventId } of events) {
1961
+ await this.client?.decryptEventIfNeeded(event);
1962
+ await this.processDecryptedEvent(
1963
+ this.buildEventForProcessing(event),
1964
+ oldEventId,
1965
+ );
1966
+ }
1967
+ } finally {
1968
+ eventsDrained!();
1969
+ }
1970
+ }
1971
+
1972
+ private async processDecryptedEvent(event: TempEvent, oldEventId?: string) {
1973
+ // Graceful test teardown: ignore late events after the service is destroyed.
1974
+ if (this.isDestroying || this.isDestroyed) {
1975
+ return;
1976
+ }
1977
+
1978
+ let { room_id: roomId } = event;
1979
+ if (!roomId) {
1980
+ throw new Error(
1981
+ `bug: roomId is undefined for event ${JSON.stringify(event, null, 2)}`,
1982
+ );
1983
+ }
1984
+ let room = this.client.getRoom(roomId);
1985
+ if (!room) {
1986
+ throw new Error(
1987
+ `bug: should never get here--matrix sdk returned a null room for ${roomId}`,
1988
+ );
1989
+ }
1990
+
1991
+ let userId = this.client.getUserId();
1992
+ if (!userId) {
1993
+ throw new Error(
1994
+ `bug: userId is required for event ${JSON.stringify(event, null, 2)}`,
1995
+ );
1996
+ }
1997
+
1998
+ // We might still receive events from the rooms that the user has left.
1999
+ let member = room.getMember(userId);
2000
+ if (!member || member.membership !== 'join') {
2001
+ return;
2002
+ }
2003
+
2004
+ if (!this.aiRoomIds.has(roomId)) {
2005
+ this.processDecryptedEventFromAuthRoom(event);
2006
+ return;
2007
+ }
2008
+ await this.addRoomEvent(event, oldEventId);
2009
+
2010
+ if (
2011
+ event.type === 'm.room.message' &&
2012
+ event.content?.[APP_BOXEL_COMMAND_REQUESTS_KEY]?.length &&
2013
+ event.content?.isStreamingFinished
2014
+ ) {
2015
+ this.commandService.queueEventForCommandProcessing(event);
2016
+ }
2017
+
2018
+ // Queue code patches for processing
2019
+ if (
2020
+ event.type === 'm.room.message' &&
2021
+ event.content?.body &&
2022
+ event.content?.isStreamingFinished
2023
+ ) {
2024
+ // Check if the message contains code patches by looking for search/replace blocks
2025
+ let body = event.content.body as string;
2026
+ if (
2027
+ body.includes(SEARCH_MARKER) &&
2028
+ body.includes(SEPARATOR_MARKER) &&
2029
+ body.includes(REPLACE_MARKER)
2030
+ ) {
2031
+ this.commandService.queueEventForCodePatchProcessing(event);
2032
+ }
2033
+ }
2034
+ }
2035
+
2036
+ private async processDecryptedEventFromAuthRoom(event: TempEvent) {
2037
+ // patch in any missing room events--this will support dealing with local
2038
+ // echoes, migrating older histories as well as handle any matrix syncing gaps
2039
+ // that might occur
2040
+ if (
2041
+ event.type === 'm.room.message' &&
2042
+ event.content?.msgtype === APP_BOXEL_REALM_SERVER_EVENT_MSGTYPE
2043
+ ) {
2044
+ await this.realmServer.handleEvent(event);
2045
+ } else if (
2046
+ event.type === APP_BOXEL_REALM_EVENT_TYPE &&
2047
+ event.sender &&
2048
+ event.content
2049
+ ) {
2050
+ realmEventsLogger.debug('Received realm event', event);
2051
+ if (
2052
+ this.startedAtTs === -1 ||
2053
+ (event.origin_server_ts || 0) < this.startedAtTs
2054
+ ) {
2055
+ realmEventsLogger.debug(
2056
+ 'Ignoring realm event because it occurred before the client started',
2057
+ event,
2058
+ );
2059
+ return;
2060
+ }
2061
+
2062
+ const content = event.content as RealmEventContent;
2063
+ if (!content.realmURL) {
2064
+ realmEventsLogger.debug(
2065
+ 'Ignoring realm event because no realm URL was provided',
2066
+ event,
2067
+ );
2068
+ return;
2069
+ }
2070
+
2071
+ (content as any).origin_server_ts = event.origin_server_ts;
2072
+ this.messageService.relayRealmEvent(content);
2073
+ }
2074
+ }
2075
+
2076
+ private clearAuth() {
2077
+ this.storage?.removeItem('auth');
2078
+ this.localPersistenceService.setCurrentRoomId(undefined);
2079
+ }
2080
+
2081
+ async activateCodingSkill() {
2082
+ if (!this.currentRoomId) {
2083
+ return;
2084
+ }
2085
+
2086
+ let updateRoomSkillsCommand = new UpdateRoomSkillsCommand(
2087
+ this.commandService.commandContext,
2088
+ );
2089
+ let defaultSkills = await this.loadDefaultSkills('code');
2090
+ await updateRoomSkillsCommand.execute({
2091
+ roomId: this.currentRoomId,
2092
+ skillCardIdsToActivate: defaultSkills.map((s) => s.id),
2093
+ });
2094
+ }
2095
+
2096
+ loadMoreAIRooms() {
2097
+ this.loadMoreAIRoomsTask.perform();
2098
+ }
2099
+
2100
+ private loadMoreAIRoomsTask = dropTask(async () => {
2101
+ if (!this.slidingSync) {
2102
+ throw new Error(
2103
+ 'To load more AI rooms, sliding sync must be initialized',
2104
+ );
2105
+ }
2106
+
2107
+ let currentList = this.slidingSync.getListParams(
2108
+ SLIDING_SYNC_AI_ROOM_LIST_NAME,
2109
+ );
2110
+ if (!currentList) return;
2111
+
2112
+ let currentRange = currentList.ranges[0];
2113
+ if (!currentRange) return;
2114
+
2115
+ if (this.aiRoomIds.size < currentRange[1] - 1) {
2116
+ return;
2117
+ }
2118
+
2119
+ let newEndRange = currentRange[1] + 10;
2120
+
2121
+ this._isLoadingMoreAIRooms = true;
2122
+ try {
2123
+ // Temporarily disable timeout to get immediate response when changing list ranges.
2124
+ // Without this, the server would hold the request open for 30 seconds waiting for
2125
+ // "new" data, even though we want the expanded range data immediately.
2126
+ // This prevents the poor UX of waiting 30 seconds after calling setListRanges.
2127
+ // @ts-expect-error bypassing "private readonly" TS annotation
2128
+ this.slidingSync.timeoutMS = 0;
2129
+ await this.slidingSync.setListRanges(SLIDING_SYNC_AI_ROOM_LIST_NAME, [
2130
+ [0, newEndRange],
2131
+ ]);
2132
+ } finally {
2133
+ // Restore normal long-polling timeout for efficient background syncing
2134
+ // @ts-expect-error bypassing "private readonly" TS annotation
2135
+ this.slidingSync.timeoutMS = SLIDING_SYNC_TIMEOUT;
2136
+ await timeout(500); // keep the spinner up a bit longer while the new rooms are rendered
2137
+ this._isLoadingMoreAIRooms = false;
2138
+ }
2139
+ });
2140
+
2141
+ get isLoadingMoreAIRooms() {
2142
+ return this._isLoadingMoreAIRooms;
2143
+ }
2144
+
2145
+ get systemCard() {
2146
+ return this._systemCard;
2147
+ }
2148
+
2149
+ private async setSystemCard(systemCardId: string | undefined) {
2150
+ // Set the system card to use
2151
+ // If there is none, we fall back to the default
2152
+ if (!systemCardId) {
2153
+ systemCardId = defaultSystemCardId;
2154
+ }
2155
+ if (!systemCardId) {
2156
+ this.store.dropReference(this._systemCard?.id);
2157
+ this._systemCard = undefined;
2158
+ return;
2159
+ }
2160
+ if (systemCardId === this._systemCard?.id) {
2161
+ // it's OK to call this multiple times with the same system card id
2162
+ // we shouldn't do anything.
2163
+ return;
2164
+ }
2165
+ let systemCard = await this.store.get<SystemCard>(systemCardId);
2166
+ if (isCardErrorJSONAPI(systemCard)) {
2167
+ console.error('Error loading system card:', systemCard);
2168
+ return;
2169
+ }
2170
+
2171
+ this.store.dropReference(this._systemCard?.id);
2172
+ this.store.addReference(systemCardId);
2173
+ this._systemCard = systemCard;
2174
+ }
2175
+
2176
+ async setUserSystemCard(systemCardId: string | undefined) {
2177
+ // This sets the users account data for their preferred system card
2178
+ // If there is none, we fall back to the default
2179
+ await this.client.setAccountData(APP_BOXEL_SYSTEM_CARD_EVENT_TYPE, {
2180
+ id: systemCardId,
2181
+ });
2182
+ }
2183
+
2184
+ async loadMoreAuthRooms(realms: string[]) {
2185
+ if (!this.slidingSync) {
2186
+ throw new Error(
2187
+ 'To load more auth rooms, sliding sync must be initialized',
2188
+ );
2189
+ }
2190
+
2191
+ let currentList = this.slidingSync.getListParams(
2192
+ SLIDING_SYNC_AUTH_ROOM_LIST_NAME,
2193
+ );
2194
+ if (!currentList) return;
2195
+
2196
+ let currentRange = currentList.ranges[0];
2197
+ if (!currentRange) return;
2198
+ if (realms.length - 1 <= currentRange[1]) {
2199
+ return;
2200
+ }
2201
+
2202
+ let newEndRange = realms.length - 1;
2203
+ await this.slidingSync.setListRanges(SLIDING_SYNC_AUTH_ROOM_LIST_NAME, [
2204
+ [0, newEndRange],
2205
+ ]);
2206
+ }
2207
+
2208
+ private ensureMessageDraftRestored(roomId: string) {
2209
+ if (this.restoredDraftRooms.has(roomId)) {
2210
+ return;
2211
+ }
2212
+ this.restoredDraftRooms.add(roomId);
2213
+
2214
+ let draft = this.localPersistenceService.getDraft(roomId);
2215
+ if (!draft) {
2216
+ return;
2217
+ }
2218
+
2219
+ if (typeof draft.message === 'string' && draft.message.length > 0) {
2220
+ this.messagesToSend.set(roomId, draft.message);
2221
+ }
2222
+
2223
+ if (draft.attachedCardIds && draft.attachedCardIds.length > 0) {
2224
+ this.cardsToSend.set(roomId, [...draft.attachedCardIds]);
2225
+ }
2226
+
2227
+ if (draft.attachedFiles && draft.attachedFiles.length > 0) {
2228
+ let fileDefs = draft.attachedFiles
2229
+ .map((file) => this.fileAPI.createFileDef(file))
2230
+ .filter(Boolean);
2231
+ if (fileDefs.length > 0) {
2232
+ this.filesToSend.set(roomId, fileDefs as FileDef[]);
2233
+ }
2234
+ }
2235
+ }
2236
+
2237
+ async getPromptParts(roomId: string) {
2238
+ const roomResource = this.roomResourcesCache.get(roomId);
2239
+ if (!roomResource) {
2240
+ throw new Error(`Room ${roomId} not found`);
2241
+ }
2242
+
2243
+ const events = roomResource.events;
2244
+ if (!events || events.length === 0) {
2245
+ throw new Error('No events found in the current room to summarize');
2246
+ }
2247
+
2248
+ const promptParts = await getPromptParts(
2249
+ events,
2250
+ this.aiBotUserId,
2251
+ this.client as unknown as MatrixClient,
2252
+ );
2253
+
2254
+ return promptParts;
2255
+ }
2256
+ }
2257
+
2258
+ async function getStorage() {
2259
+ let storage;
2260
+
2261
+ try {
2262
+ // Chrome requires finer-grained permissions requests
2263
+ // @ts-expect-error our Typescript version doesn’t know about this API
2264
+ if (document['requestStorageAccessFor']) {
2265
+ let requestOptions = {
2266
+ localStorage: true,
2267
+ };
2268
+
2269
+ storage = // @ts-expect-error nor about passing options and getting a handle back
2270
+ (await document.requestStorageAccess(requestOptions)).localStorage;
2271
+ } else {
2272
+ await document.requestStorageAccess();
2273
+ storage = window.localStorage;
2274
+ }
2275
+ } catch (e) {
2276
+ console.error('Error accessing storage', e);
2277
+ storage = window.localStorage;
2278
+ }
2279
+
2280
+ return storage;
2281
+ }
2282
+
2283
+ declare module '@ember/service' {
2284
+ interface Registry {
2285
+ 'matrix-service': MatrixService;
2286
+ }
2287
+ }