@dxos/plugin-thread 0.8.4-main.2e9d522 → 0.8.4-main.5ea62a8

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 (247) hide show
  1. package/dist/lib/browser/ChannelContainer-GHDNEZT2.mjs +16 -0
  2. package/dist/lib/browser/{ChatContainer-AIGIWAUG.mjs → ChatContainer-42ALOWUA.mjs} +4 -4
  3. package/dist/lib/browser/{app-graph-builder-N7BE5TYW.mjs → app-graph-builder-FHAOPO57.mjs} +5 -5
  4. package/dist/lib/browser/app-graph-builder-FHAOPO57.mjs.map +7 -0
  5. package/dist/lib/browser/{call-manager-NIPDYUVD.mjs → call-manager-EW2QC6Q4.mjs} +4 -4
  6. package/dist/lib/browser/call-manager-EW2QC6Q4.mjs.map +7 -0
  7. package/dist/lib/browser/chunk-2I277V52.mjs +23 -0
  8. package/dist/lib/browser/{chunk-4OYAYON2.mjs.map → chunk-2I277V52.mjs.map} +3 -3
  9. package/dist/lib/browser/{chunk-ERWASUQK.mjs → chunk-2P3GVRHP.mjs} +38 -6
  10. package/dist/lib/{node-esm/chunk-25ABSYP2.mjs.map → browser/chunk-2P3GVRHP.mjs.map} +4 -4
  11. package/dist/lib/browser/{chunk-LGSDKXPF.mjs → chunk-4APCDRSH.mjs} +1 -1
  12. package/dist/lib/browser/{chunk-LGSDKXPF.mjs.map → chunk-4APCDRSH.mjs.map} +1 -1
  13. package/dist/lib/browser/chunk-H63NDV62.mjs +376 -0
  14. package/dist/lib/browser/chunk-H63NDV62.mjs.map +7 -0
  15. package/dist/lib/browser/chunk-J26C57ZY.mjs +548 -0
  16. package/dist/lib/browser/chunk-J26C57ZY.mjs.map +7 -0
  17. package/dist/lib/browser/{chunk-6NSMBO3B.mjs → chunk-KEXJGF2R.mjs} +4 -4
  18. package/dist/lib/browser/chunk-KEXJGF2R.mjs.map +7 -0
  19. package/dist/lib/browser/{chunk-GCLD5ESP.mjs → chunk-KTWYVC5X.mjs} +22 -12
  20. package/dist/lib/browser/chunk-KTWYVC5X.mjs.map +7 -0
  21. package/dist/lib/browser/{chunk-KWPRNHTK.mjs → chunk-TQJYDFBU.mjs} +232 -230
  22. package/dist/lib/browser/chunk-TQJYDFBU.mjs.map +7 -0
  23. package/dist/lib/browser/{chunk-ZE7KWN36.mjs → chunk-TUSBPMNU.mjs} +398 -174
  24. package/dist/lib/browser/chunk-TUSBPMNU.mjs.map +7 -0
  25. package/dist/lib/browser/index.mjs +18 -8
  26. package/dist/lib/browser/index.mjs.map +3 -3
  27. package/dist/lib/browser/{intent-resolver-JFGLZ6VI.mjs → intent-resolver-IB5GYU2D.mjs} +68 -9
  28. package/dist/lib/browser/intent-resolver-IB5GYU2D.mjs.map +7 -0
  29. package/dist/lib/browser/{markdown-GEXBVJYN.mjs → markdown-Z677YORA.mjs} +4 -4
  30. package/dist/lib/browser/markdown-Z677YORA.mjs.map +7 -0
  31. package/dist/lib/browser/meta.json +1 -1
  32. package/dist/lib/browser/{react-root-X4UIVGTX.mjs → react-root-PTTTW2MO.mjs} +9 -9
  33. package/dist/lib/browser/{react-surface-YCYEFBPM.mjs → react-surface-X2VB6P37.mjs} +9 -9
  34. package/dist/lib/browser/react-surface-X2VB6P37.mjs.map +7 -0
  35. package/dist/lib/browser/{settings-E32MTL7A.mjs → settings-GRKEID73.mjs} +2 -2
  36. package/dist/lib/browser/{state-H6CYONWE.mjs → state-2T4KDWBX.mjs} +2 -2
  37. package/dist/lib/browser/{state-H6CYONWE.mjs.map → state-2T4KDWBX.mjs.map} +2 -2
  38. package/dist/lib/browser/toolkit-KUPIIFC6.mjs +80 -0
  39. package/dist/lib/browser/toolkit-KUPIIFC6.mjs.map +7 -0
  40. package/dist/lib/browser/types/index.mjs +1 -1
  41. package/dist/lib/node-esm/{ChannelContainer-DET6T5N2.mjs → ChannelContainer-D5E2S6AI.mjs} +7 -7
  42. package/dist/lib/node-esm/{ChatContainer-IQUWU426.mjs → ChatContainer-4EGHKHIU.mjs} +4 -4
  43. package/dist/lib/node-esm/{app-graph-builder-VCW76Z6V.mjs → app-graph-builder-XEYWX5FC.mjs} +5 -5
  44. package/dist/lib/node-esm/app-graph-builder-XEYWX5FC.mjs.map +7 -0
  45. package/dist/lib/node-esm/{call-manager-D6O5ZJJ4.mjs → call-manager-N3KASRDQ.mjs} +4 -4
  46. package/dist/lib/node-esm/call-manager-N3KASRDQ.mjs.map +7 -0
  47. package/dist/lib/node-esm/{chunk-C3XFMUAY.mjs → chunk-CCE5LHBE.mjs} +232 -230
  48. package/dist/lib/node-esm/chunk-CCE5LHBE.mjs.map +7 -0
  49. package/dist/lib/node-esm/{chunk-25ABSYP2.mjs → chunk-CTZ75IFK.mjs} +38 -6
  50. package/dist/lib/node-esm/chunk-CTZ75IFK.mjs.map +7 -0
  51. package/dist/lib/node-esm/{chunk-IHDNQLLR.mjs → chunk-JR7KESLL.mjs} +398 -174
  52. package/dist/lib/node-esm/chunk-JR7KESLL.mjs.map +7 -0
  53. package/dist/lib/node-esm/chunk-NNKKNW57.mjs +549 -0
  54. package/dist/lib/node-esm/chunk-NNKKNW57.mjs.map +7 -0
  55. package/dist/lib/node-esm/{chunk-TDFHTCZZ.mjs → chunk-P6E247RF.mjs} +22 -12
  56. package/dist/lib/node-esm/chunk-P6E247RF.mjs.map +7 -0
  57. package/dist/lib/node-esm/{chunk-75RJ5DJI.mjs → chunk-PYTVBN5J.mjs} +1 -1
  58. package/dist/lib/node-esm/{chunk-75RJ5DJI.mjs.map → chunk-PYTVBN5J.mjs.map} +1 -1
  59. package/dist/lib/node-esm/{chunk-OU5BYIDO.mjs → chunk-S3D7DTBF.mjs} +4 -4
  60. package/dist/lib/node-esm/chunk-S3D7DTBF.mjs.map +7 -0
  61. package/dist/lib/node-esm/chunk-UHZQTPXU.mjs +377 -0
  62. package/dist/lib/node-esm/chunk-UHZQTPXU.mjs.map +7 -0
  63. package/dist/lib/node-esm/chunk-UJ2QNRLS.mjs +25 -0
  64. package/dist/lib/node-esm/{chunk-GW37AAM4.mjs.map → chunk-UJ2QNRLS.mjs.map} +3 -3
  65. package/dist/lib/node-esm/index.mjs +18 -8
  66. package/dist/lib/node-esm/index.mjs.map +3 -3
  67. package/dist/lib/node-esm/{intent-resolver-OXGNQ44Y.mjs → intent-resolver-VIMI5VLH.mjs} +68 -9
  68. package/dist/lib/node-esm/intent-resolver-VIMI5VLH.mjs.map +7 -0
  69. package/dist/lib/node-esm/{markdown-LIJZDK2J.mjs → markdown-FL4IXLRP.mjs} +4 -4
  70. package/dist/lib/node-esm/markdown-FL4IXLRP.mjs.map +7 -0
  71. package/dist/lib/node-esm/meta.json +1 -1
  72. package/dist/lib/node-esm/{react-root-M7J6PZVW.mjs → react-root-2HHRRUME.mjs} +9 -9
  73. package/dist/lib/node-esm/{react-surface-IRSEKM42.mjs → react-surface-OLN3XNND.mjs} +9 -9
  74. package/dist/lib/node-esm/react-surface-OLN3XNND.mjs.map +7 -0
  75. package/dist/lib/node-esm/{settings-SJ24YG7M.mjs → settings-F2ODVNNW.mjs} +2 -2
  76. package/dist/lib/node-esm/{state-D7WNDT3N.mjs → state-62TQKQVB.mjs} +2 -2
  77. package/dist/lib/node-esm/{state-D7WNDT3N.mjs.map → state-62TQKQVB.mjs.map} +2 -2
  78. package/dist/lib/node-esm/toolkit-KZIS7G36.mjs +81 -0
  79. package/dist/lib/node-esm/toolkit-KZIS7G36.mjs.map +7 -0
  80. package/dist/lib/node-esm/types/index.mjs +1 -1
  81. package/dist/types/src/ThreadPlugin.d.ts.map +1 -1
  82. package/dist/types/src/calls/call-manager.d.ts.map +1 -1
  83. package/dist/types/src/calls/call-swarm-synchronizer.d.ts.map +1 -1
  84. package/dist/types/src/calls/media-manager.d.ts +1 -1
  85. package/dist/types/src/calls/media-manager.d.ts.map +1 -1
  86. package/dist/types/src/calls/types.d.ts +1 -1
  87. package/dist/types/src/calls/types.d.ts.map +1 -1
  88. package/dist/types/src/calls/util/calls-service.d.ts +2 -2
  89. package/dist/types/src/calls/util/calls-service.d.ts.map +1 -1
  90. package/dist/types/src/calls/util/stub-media-streams.d.ts.map +1 -1
  91. package/dist/types/src/calls-service.stories.d.ts +10 -8
  92. package/dist/types/src/calls-service.stories.d.ts.map +1 -1
  93. package/dist/types/src/capabilities/app-graph-builder.d.ts +1 -1
  94. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
  95. package/dist/types/src/capabilities/call-manager.d.ts +1 -1
  96. package/dist/types/src/capabilities/call-manager.d.ts.map +1 -1
  97. package/dist/types/src/capabilities/capabilities.d.ts +2 -2
  98. package/dist/types/src/capabilities/capabilities.d.ts.map +1 -1
  99. package/dist/types/src/capabilities/index.d.ts +11 -10
  100. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  101. package/dist/types/src/capabilities/intent-resolver.d.ts +1 -1
  102. package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -1
  103. package/dist/types/src/capabilities/markdown.d.ts +1 -1
  104. package/dist/types/src/capabilities/markdown.d.ts.map +1 -1
  105. package/dist/types/src/capabilities/react-root.d.ts +2 -2
  106. package/dist/types/src/capabilities/react-surface.d.ts +1 -1
  107. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
  108. package/dist/types/src/capabilities/settings.d.ts +1 -1
  109. package/dist/types/src/capabilities/state.d.ts +2 -2
  110. package/dist/types/src/capabilities/state.d.ts.map +1 -1
  111. package/dist/types/src/capabilities/toolkit.d.ts +5 -0
  112. package/dist/types/src/capabilities/toolkit.d.ts.map +1 -0
  113. package/dist/types/src/components/Call/Call.d.ts.map +1 -1
  114. package/dist/types/src/components/Call/Toolbar.d.ts.map +1 -1
  115. package/dist/types/src/components/CallDebugPanel.d.ts.map +1 -1
  116. package/dist/types/src/components/CallSidebar.d.ts.map +1 -1
  117. package/dist/types/src/components/ChannelContainer.d.ts.map +1 -1
  118. package/dist/types/src/components/ChannelContainer.stories.d.ts +87 -3
  119. package/dist/types/src/components/ChannelContainer.stories.d.ts.map +1 -1
  120. package/dist/types/src/components/Chat.stories.d.ts +89 -4
  121. package/dist/types/src/components/Chat.stories.d.ts.map +1 -1
  122. package/dist/types/src/components/ChatContainer.d.ts.map +1 -1
  123. package/dist/types/src/components/Comments.stories.d.ts +154 -3
  124. package/dist/types/src/components/Comments.stories.d.ts.map +1 -1
  125. package/dist/types/src/components/CommentsContainer.d.ts.map +1 -1
  126. package/dist/types/src/components/CommentsThreadContainer.d.ts +2 -2
  127. package/dist/types/src/components/CommentsThreadContainer.d.ts.map +1 -1
  128. package/dist/types/src/components/Lobby/Lobby.d.ts.map +1 -1
  129. package/dist/types/src/components/Media/VideoObject.d.ts +1 -1
  130. package/dist/types/src/components/Media/VideoObject.stories.d.ts +15 -3
  131. package/dist/types/src/components/Media/VideoObject.stories.d.ts.map +1 -1
  132. package/dist/types/src/components/MessageContainer.d.ts +4 -1
  133. package/dist/types/src/components/MessageContainer.d.ts.map +1 -1
  134. package/dist/types/src/components/Participant/Participant.d.ts.map +1 -1
  135. package/dist/types/src/components/Participant/ParticipantGrid.d.ts.map +1 -1
  136. package/dist/types/src/components/ResponsiveGrid/ResponsiveContainer.stories.d.ts +152 -2
  137. package/dist/types/src/components/ResponsiveGrid/ResponsiveContainer.stories.d.ts.map +1 -1
  138. package/dist/types/src/components/ResponsiveGrid/ResponsiveGrid.stories.d.ts +154 -3
  139. package/dist/types/src/components/ResponsiveGrid/ResponsiveGrid.stories.d.ts.map +1 -1
  140. package/dist/types/src/components/ResponsiveGrid/ResponsiveGridItem.d.ts.map +1 -1
  141. package/dist/types/src/components/ThreadComplementary.d.ts.map +1 -1
  142. package/dist/types/src/components/command-extension.d.ts.map +1 -1
  143. package/dist/types/src/components/testing.d.ts +1 -0
  144. package/dist/types/src/components/testing.d.ts.map +1 -1
  145. package/dist/types/src/extensions/threads.d.ts +2 -2
  146. package/dist/types/src/extensions/threads.d.ts.map +1 -1
  147. package/dist/types/src/hooks/index.d.ts +1 -0
  148. package/dist/types/src/hooks/index.d.ts.map +1 -1
  149. package/dist/types/src/hooks/useBlackCanvasStreamTrack.d.ts +2 -0
  150. package/dist/types/src/hooks/useBlackCanvasStreamTrack.d.ts.map +1 -0
  151. package/dist/types/src/hooks/useVideoStreamTrack.d.ts.map +1 -1
  152. package/dist/types/src/translations.d.ts +1 -0
  153. package/dist/types/src/translations.d.ts.map +1 -1
  154. package/dist/types/src/types/schema.d.ts +122 -107
  155. package/dist/types/src/types/schema.d.ts.map +1 -1
  156. package/dist/types/src/types/types.d.ts +253 -168
  157. package/dist/types/src/types/types.d.ts.map +1 -1
  158. package/dist/types/tsconfig.tsbuildinfo +1 -1
  159. package/package.json +51 -47
  160. package/src/ThreadPlugin.tsx +9 -2
  161. package/src/calls/call-manager.ts +1 -1
  162. package/src/calls/call-swarm-synchronizer.ts +1 -1
  163. package/src/calls/media-manager.ts +58 -33
  164. package/src/calls/types.ts +1 -1
  165. package/src/calls/util/calls-service.ts +56 -10
  166. package/src/calls/util/stub-media-streams.ts +4 -5
  167. package/src/calls-service.stories.tsx +76 -60
  168. package/src/capabilities/app-graph-builder.ts +8 -5
  169. package/src/capabilities/call-manager.ts +3 -2
  170. package/src/capabilities/capabilities.ts +2 -2
  171. package/src/capabilities/index.ts +1 -0
  172. package/src/capabilities/intent-resolver.ts +39 -4
  173. package/src/capabilities/markdown.ts +4 -3
  174. package/src/capabilities/react-surface.tsx +5 -4
  175. package/src/capabilities/state.ts +2 -1
  176. package/src/capabilities/toolkit.ts +78 -0
  177. package/src/components/Call/Call.tsx +3 -2
  178. package/src/components/Call/Toolbar.tsx +2 -2
  179. package/src/components/CallDebugPanel.tsx +1 -1
  180. package/src/components/CallSidebar.tsx +2 -1
  181. package/src/components/ChannelContainer.stories.tsx +6 -5
  182. package/src/components/ChannelContainer.tsx +7 -6
  183. package/src/components/Chat.stories.tsx +28 -26
  184. package/src/components/ChatContainer.tsx +8 -4
  185. package/src/components/Comments.stories.tsx +33 -29
  186. package/src/components/CommentsContainer.tsx +2 -1
  187. package/src/components/CommentsThreadContainer.tsx +9 -7
  188. package/src/components/Lobby/Lobby.tsx +1 -1
  189. package/src/components/Media/VideoObject.stories.tsx +30 -27
  190. package/src/components/MessageContainer.tsx +43 -9
  191. package/src/components/Participant/Participant.tsx +13 -7
  192. package/src/components/Participant/ParticipantGrid.tsx +2 -1
  193. package/src/components/ResponsiveGrid/ResponsiveContainer.stories.tsx +6 -5
  194. package/src/components/ResponsiveGrid/ResponsiveGrid.stories.tsx +42 -39
  195. package/src/components/ResponsiveGrid/ResponsiveGrid.tsx +1 -1
  196. package/src/components/ResponsiveGrid/ResponsiveGridItem.tsx +2 -2
  197. package/src/components/ThreadComplementary.tsx +38 -8
  198. package/src/components/ThreadSettings.tsx +2 -2
  199. package/src/components/command-extension.ts +5 -2
  200. package/src/components/testing.ts +22 -0
  201. package/src/extensions/threads.ts +6 -6
  202. package/src/hooks/index.ts +1 -0
  203. package/src/hooks/useBlackCanvasStreamTrack.tsx +27 -0
  204. package/src/hooks/useDebugMode.ts +1 -1
  205. package/src/hooks/useVideoStreamTrack.tsx +5 -2
  206. package/src/testing/stories.ts +2 -2
  207. package/src/translations.ts +1 -0
  208. package/src/types/types.ts +21 -12
  209. package/src/typings.d.ts +8 -0
  210. package/dist/lib/browser/ChannelContainer-IY2UIRLF.mjs +0 -16
  211. package/dist/lib/browser/app-graph-builder-N7BE5TYW.mjs.map +0 -7
  212. package/dist/lib/browser/call-manager-NIPDYUVD.mjs.map +0 -7
  213. package/dist/lib/browser/chunk-4OYAYON2.mjs +0 -21
  214. package/dist/lib/browser/chunk-6NSMBO3B.mjs.map +0 -7
  215. package/dist/lib/browser/chunk-ERWASUQK.mjs.map +0 -7
  216. package/dist/lib/browser/chunk-GCLD5ESP.mjs.map +0 -7
  217. package/dist/lib/browser/chunk-KWPRNHTK.mjs.map +0 -7
  218. package/dist/lib/browser/chunk-VUWC4IJM.mjs +0 -479
  219. package/dist/lib/browser/chunk-VUWC4IJM.mjs.map +0 -7
  220. package/dist/lib/browser/chunk-XLPJXUKO.mjs +0 -367
  221. package/dist/lib/browser/chunk-XLPJXUKO.mjs.map +0 -7
  222. package/dist/lib/browser/chunk-ZE7KWN36.mjs.map +0 -7
  223. package/dist/lib/browser/intent-resolver-JFGLZ6VI.mjs.map +0 -7
  224. package/dist/lib/browser/markdown-GEXBVJYN.mjs.map +0 -7
  225. package/dist/lib/browser/react-surface-YCYEFBPM.mjs.map +0 -7
  226. package/dist/lib/node-esm/app-graph-builder-VCW76Z6V.mjs.map +0 -7
  227. package/dist/lib/node-esm/call-manager-D6O5ZJJ4.mjs.map +0 -7
  228. package/dist/lib/node-esm/chunk-2MFNK53T.mjs +0 -480
  229. package/dist/lib/node-esm/chunk-2MFNK53T.mjs.map +0 -7
  230. package/dist/lib/node-esm/chunk-C3XFMUAY.mjs.map +0 -7
  231. package/dist/lib/node-esm/chunk-GW37AAM4.mjs +0 -23
  232. package/dist/lib/node-esm/chunk-IHDNQLLR.mjs.map +0 -7
  233. package/dist/lib/node-esm/chunk-J4NSON5Q.mjs +0 -368
  234. package/dist/lib/node-esm/chunk-J4NSON5Q.mjs.map +0 -7
  235. package/dist/lib/node-esm/chunk-OU5BYIDO.mjs.map +0 -7
  236. package/dist/lib/node-esm/chunk-TDFHTCZZ.mjs.map +0 -7
  237. package/dist/lib/node-esm/intent-resolver-OXGNQ44Y.mjs.map +0 -7
  238. package/dist/lib/node-esm/markdown-LIJZDK2J.mjs.map +0 -7
  239. package/dist/lib/node-esm/react-surface-IRSEKM42.mjs.map +0 -7
  240. /package/dist/lib/browser/{ChannelContainer-IY2UIRLF.mjs.map → ChannelContainer-GHDNEZT2.mjs.map} +0 -0
  241. /package/dist/lib/browser/{ChatContainer-AIGIWAUG.mjs.map → ChatContainer-42ALOWUA.mjs.map} +0 -0
  242. /package/dist/lib/browser/{react-root-X4UIVGTX.mjs.map → react-root-PTTTW2MO.mjs.map} +0 -0
  243. /package/dist/lib/browser/{settings-E32MTL7A.mjs.map → settings-GRKEID73.mjs.map} +0 -0
  244. /package/dist/lib/node-esm/{ChannelContainer-DET6T5N2.mjs.map → ChannelContainer-D5E2S6AI.mjs.map} +0 -0
  245. /package/dist/lib/node-esm/{ChatContainer-IQUWU426.mjs.map → ChatContainer-4EGHKHIU.mjs.map} +0 -0
  246. /package/dist/lib/node-esm/{react-root-M7J6PZVW.mjs.map → react-root-2HHRRUME.mjs.map} +0 -0
  247. /package/dist/lib/node-esm/{settings-SJ24YG7M.mjs.map → settings-F2ODVNNW.mjs.map} +0 -0
@@ -4,6 +4,7 @@
4
4
 
5
5
  import '@dxos-theme';
6
6
 
7
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
7
8
  import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
8
9
 
9
10
  import { scheduleTask, sleep } from '@dxos/async';
@@ -16,11 +17,12 @@ import { Button } from '@dxos/react-ui';
16
17
  import { Json } from '@dxos/react-ui-syntax-highlighter';
17
18
  import { withLayout, withTheme } from '@dxos/storybook-utils';
18
19
 
19
- import { type TrackObject, CallsServicePeer, CALLS_URL } from './calls';
20
- import { useInaudibleAudioStreamTrack, useVideoStreamTrack } from './hooks';
21
- // @ts-ignore
22
- import video from '../testing/video.mp4';
20
+ const testVideo = new URL('../testing/video.mp4', import.meta.url).href;
23
21
 
22
+ import { CALLS_URL, CallsServicePeer, type TrackObject } from './calls';
23
+ import { useBlackCanvasStreamTrack, useInaudibleAudioStreamTrack, useVideoStreamTrack } from './hooks';
24
+
25
+ // TODO(burdon): THIS IS TOO COMPLEX FOR A TEST SETUP.
24
26
  const pushAndPullTrack = (mediaStreamTrack?: MediaStreamTrack) => {
25
27
  const config = useConfig();
26
28
  const callsConfig = {
@@ -35,16 +37,18 @@ const pushAndPullTrack = (mediaStreamTrack?: MediaStreamTrack) => {
35
37
  const [pulledTrack, setPulledTrack] = useState<MediaStreamTrack | undefined>(undefined);
36
38
  const hadRun = useRef(false);
37
39
 
40
+ const deps: any[] = [];
38
41
  // Push/pull video stream track to cloudflare.
39
42
  useEffect(() => {
40
43
  if (hadRun.current || !mediaStreamTrack || !peerPush || !peerPull) {
41
- log.info('not running', { hadRun: hadRun.current, mediaStreamTrack, peerPush, peerPull });
42
44
  return;
43
45
  }
44
46
  hadRun.current = true;
45
47
  const ctx = Context.default();
48
+ log.info('setting up ctx', { ctx, mediaStreamTrack, peerPush, peerPull });
49
+ deps.push([ctx, mediaStreamTrack, peerPush, peerPull]);
46
50
  ctx.onDispose(() => {
47
- log.info('disposing ctx', { ctx });
51
+ log.info('disposing ctx', {});
48
52
  });
49
53
  scheduleTask(
50
54
  ctx,
@@ -60,15 +64,12 @@ const pushAndPullTrack = (mediaStreamTrack?: MediaStreamTrack) => {
60
64
  // Push track to cloudflare.
61
65
  performance.mark('push:begin');
62
66
  log.info('pushing track', { track: mediaStreamTrack });
63
- trackInfo.current = await peerPush.pushTrack({ track: mediaStreamTrack });
67
+ trackInfo.current = await peerPush.pushTrack({ track: mediaStreamTrack, ctx: Context.default() });
64
68
  performance.mark('push:end');
65
69
  const pushTime = performance.measure('push', 'push:begin', 'push:end').duration;
66
70
  log.info('successfully pushed track', { pushTime, trackInfo: trackInfo.current });
67
71
  setMetrics((prev) => ({ ...prev, 'time to push track [ms]': Math.round(pushTime) }));
68
72
 
69
- // Wait for cloudflare to process the track.
70
- await sleep(1000);
71
-
72
73
  // Pull track from cloudflare.
73
74
  performance.mark('pullTrack:begin');
74
75
  pullCtx.current = Context.default();
@@ -104,7 +105,10 @@ const pushAndPullTrack = (mediaStreamTrack?: MediaStreamTrack) => {
104
105
 
105
106
  const rePullTrack = useCallback(async () => {
106
107
  performance.mark('rePullVideo:begin');
107
- invariant(pulledTrack);
108
+ if (!pulledTrack) {
109
+ log.info('no pulled track, skipping re-pull', { pulledTrack });
110
+ return;
111
+ }
108
112
  pulledTrack.stop();
109
113
  await pullCtx.current!.dispose();
110
114
  pullCtx.current = Context.default();
@@ -123,11 +127,55 @@ const pushAndPullTrack = (mediaStreamTrack?: MediaStreamTrack) => {
123
127
  pulledTrack,
124
128
  rePullTrack,
125
129
  metrics,
130
+ pushService: peerPush,
131
+ pullService: peerPull,
126
132
  };
127
133
  };
128
134
 
135
+ type StoryProps = { source: string };
136
+
137
+ const DefaultStory = ({ source }: StoryProps) => {
138
+ const pushVideoElement = useRef<HTMLVideoElement>(null);
139
+ const pullVideoElement = useRef<HTMLVideoElement>(null);
140
+ // Get video stream track.
141
+ const videoStreamTrack = useVideoStreamTrack(pushVideoElement, source);
142
+ const { pulledTrack, rePullTrack, metrics } = pushAndPullTrack(videoStreamTrack);
143
+ const hadRun = useRef(false);
144
+
145
+ // Push/pull video stream track to cloudflare.
146
+ useEffect(() => {
147
+ if (!pulledTrack || hadRun.current) {
148
+ return;
149
+ }
150
+ hadRun.current = true;
151
+ const ctx = Context.default();
152
+ scheduleTask(ctx, async () => {
153
+ pullVideoElement.current!.srcObject = new MediaStream([pulledTrack]);
154
+ await pullVideoElement.current!.play();
155
+ });
156
+
157
+ return () => {
158
+ void ctx.dispose();
159
+ };
160
+ }, [pulledTrack]);
161
+
162
+ return (
163
+ <div className='grid grid-rows-3 gap-4 items-center'>
164
+ <video ref={pushVideoElement} muted autoPlay loop />
165
+ <div className='flex flex-col gap-4'>
166
+ <video ref={pullVideoElement} muted />
167
+ <Button disabled={!pulledTrack} onClick={rePullTrack}>
168
+ Re-pull video
169
+ </Button>
170
+ </div>
171
+ <Json data={metrics} />
172
+ </div>
173
+ );
174
+ };
175
+
129
176
  const meta = {
130
177
  title: 'plugins/plugin-thread/calls-service',
178
+ render: DefaultStory,
131
179
  decorators: [
132
180
  withClientProvider({
133
181
  config: new Config({
@@ -144,66 +192,21 @@ const meta = {
144
192
  parameters: {
145
193
  layout: 'centered',
146
194
  },
147
- };
195
+ } satisfies Meta<typeof DefaultStory>;
148
196
 
149
197
  export default meta;
150
198
 
151
- export const Default = {
152
- render: ({ videoSrc }: { videoSrc: string }) => {
153
- const pushVideoElement = useRef<HTMLVideoElement>(null);
154
- const pullVideoElement = useRef<HTMLVideoElement>(null);
155
- // Get video stream track.
156
- const videoStreamTrack = useVideoStreamTrack(pushVideoElement, videoSrc);
157
- const { pulledTrack, rePullTrack, metrics } = pushAndPullTrack(videoStreamTrack);
158
- const hadRun = useRef(false);
159
-
160
- // Push/pull video stream track to cloudflare.
161
- useEffect(() => {
162
- if (!pulledTrack || hadRun.current) {
163
- return;
164
- }
165
- hadRun.current = true;
166
- const ctx = Context.default();
167
- scheduleTask(ctx, async () => {
168
- pullVideoElement.current!.srcObject = new MediaStream([pulledTrack]);
169
- await pullVideoElement.current!.play();
170
- });
171
-
172
- return () => {
173
- void ctx.dispose();
174
- };
175
- }, [pulledTrack]);
199
+ type Story = StoryObj<typeof meta>;
176
200
 
177
- return (
178
- <div className='grid grid-rows-3 gap-4 items-center'>
179
- <video ref={pushVideoElement} muted autoPlay loop />
180
- <div className='flex flex-col gap-4'>
181
- <video ref={pullVideoElement} muted />
182
- <Button
183
- disabled={
184
- !(
185
- pullVideoElement?.current?.srcObject instanceof MediaStream &&
186
- pullVideoElement.current.srcObject.getTracks()[0]
187
- )
188
- }
189
- onClick={rePullTrack}
190
- >
191
- Re-pull video
192
- </Button>
193
- </div>
194
- <Json data={metrics} />
195
- </div>
196
- );
197
- },
201
+ export const Default: Story = {
198
202
  args: {
199
- videoSrc: video,
203
+ source: testVideo,
200
204
  },
201
205
  };
202
206
 
203
207
  export const InaudibleAudioStreamTrack = {
204
208
  render: () => {
205
209
  const audioStreamTrack = useInaudibleAudioStreamTrack();
206
-
207
210
  const { rePullTrack, metrics } = pushAndPullTrack(audioStreamTrack);
208
211
 
209
212
  return (
@@ -214,3 +217,16 @@ export const InaudibleAudioStreamTrack = {
214
217
  );
215
218
  },
216
219
  };
220
+
221
+ export const BlackVideoStreamTrack = {
222
+ render: () => {
223
+ const videoStreamTrack = useBlackCanvasStreamTrack();
224
+ const { rePullTrack, metrics } = pushAndPullTrack(videoStreamTrack);
225
+ return (
226
+ <div className='flex flex-col gap-4 items-center'>
227
+ <Json data={metrics} />
228
+ <Button onClick={rePullTrack}>Re-pull audio</Button>
229
+ </div>
230
+ );
231
+ },
232
+ };
@@ -5,18 +5,21 @@
5
5
  import { Rx } from '@effect-rx/rx-react';
6
6
  import { Option, pipe } from 'effect';
7
7
 
8
- import { Capabilities, contributes, createIntent, type PluginContext } from '@dxos/app-framework';
8
+ import { Capabilities, type PluginContext, contributes, createIntent } from '@dxos/app-framework';
9
9
  import { Obj } from '@dxos/echo';
10
10
  import { AttentionCapabilities } from '@dxos/plugin-attention';
11
- import { PLANK_COMPANION_TYPE, ATTENDABLE_PATH_SEPARATOR, DECK_COMPANION_TYPE } from '@dxos/plugin-deck/types';
12
- import { createExtension, ROOT_ID, rxFromSignal } from '@dxos/plugin-graph';
11
+ import { ATTENDABLE_PATH_SEPARATOR, DECK_COMPANION_TYPE, PLANK_COMPANION_TYPE } from '@dxos/plugin-deck/types';
12
+ import { ROOT_ID, createExtension, rxFromSignal } from '@dxos/plugin-graph';
13
13
  import { fullyQualifiedId } from '@dxos/react-client/echo';
14
14
 
15
- import { ThreadCapabilities } from './capabilities';
16
- import { meta, THREAD_PLUGIN } from '../meta';
15
+ import { THREAD_PLUGIN, meta } from '../meta';
17
16
  import { ChannelType, ThreadAction } from '../types';
18
17
  import { getAnchor } from '../util';
19
18
 
19
+ import { ThreadCapabilities } from './capabilities';
20
+
21
+ // TODO(wittjosiah): Highlight active calls in L1.
22
+ // Track active meetings by subscribing to meetings query and polling the swarms of recent meetings in the space.
20
23
  export default (context: PluginContext) => {
21
24
  const resolve = (typename: string) =>
22
25
  context.getCapabilities(Capabilities.Metadata).find(({ id }) => id === typename)?.metadata ?? {};
@@ -2,12 +2,13 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { contributes, type PluginContext } from '@dxos/app-framework';
5
+ import { type PluginContext, contributes } from '@dxos/app-framework';
6
6
  import { ClientCapabilities } from '@dxos/plugin-client';
7
7
 
8
- import { ThreadCapabilities } from './capabilities';
9
8
  import { CallManager } from '../calls';
10
9
 
10
+ import { ThreadCapabilities } from './capabilities';
11
+
11
12
  export default async (context: PluginContext) => {
12
13
  const client = context.getCapability(ClientCapabilities.Client);
13
14
  const callManager = new CallManager(client);
@@ -5,9 +5,9 @@
5
5
  import { defineCapability } from '@dxos/app-framework';
6
6
  import { type DeepReadonly } from '@dxos/util';
7
7
 
8
- import { type CallState, type MediaState, type CallManager } from '../calls';
8
+ import { type CallManager, type CallState, type MediaState } from '../calls';
9
9
  import { THREAD_PLUGIN } from '../meta';
10
- import { type ViewState, type ThreadState, type ChannelType } from '../types';
10
+ import { type ChannelType, type ThreadState, type ViewState } from '../types';
11
11
 
12
12
  export namespace ThreadCapabilities {
13
13
  export const CallManager = defineCapability<CallManager>(`${THREAD_PLUGIN}/capability/call-manager`);
@@ -12,5 +12,6 @@ export const ReactRoot = lazy(() => import('./react-root'));
12
12
  export const ReactSurface = lazy(() => import('./react-surface'));
13
13
  export const ThreadSettings = lazy(() => import('./settings'));
14
14
  export const ThreadState = lazy(() => import('./state'));
15
+ export const Toolkit = lazy(() => import('./toolkit'));
15
16
 
16
17
  export * from './capabilities';
@@ -4,20 +4,21 @@
4
4
 
5
5
  import { Effect } from 'effect';
6
6
 
7
- import { Capabilities, contributes, createIntent, createResolver, type PluginContext } from '@dxos/app-framework';
7
+ import { Capabilities, type PluginContext, contributes, createIntent, createResolver } from '@dxos/app-framework';
8
8
  import { sleep } from '@dxos/async';
9
9
  import { Obj, Relation, Type } from '@dxos/echo';
10
10
  import { invariant } from '@dxos/invariant';
11
11
  import { ATTENDABLE_PATH_SEPARATOR, DeckAction } from '@dxos/plugin-deck/types';
12
12
  import { ObservabilityAction } from '@dxos/plugin-observability/types';
13
13
  import { CollectionAction, SpaceAction } from '@dxos/plugin-space/types';
14
- import { fullyQualifiedId, getSpace, Ref } from '@dxos/react-client/echo';
14
+ import { Ref, fullyQualifiedId, getSpace } from '@dxos/react-client/echo';
15
15
  import { AnchoredTo, DataType } from '@dxos/schema';
16
16
 
17
- import { ThreadCapabilities } from './capabilities';
18
17
  import { THREAD_PLUGIN } from '../meta';
19
18
  import { ChannelType, ThreadAction, ThreadType } from '../types';
20
19
 
20
+ import { ThreadCapabilities } from './capabilities';
21
+
21
22
  export default (context: PluginContext) =>
22
23
  contributes(Capabilities.IntentResolver, [
23
24
  createResolver({
@@ -94,6 +95,40 @@ export default (context: PluginContext) =>
94
95
  };
95
96
  },
96
97
  }),
98
+ createResolver({
99
+ intent: ThreadAction.AddProposal,
100
+ resolve: ({ text, anchor, sender, subject }) => {
101
+ console.log('add-proposal', text, anchor, sender, subject);
102
+ const space = getSpace(subject);
103
+ invariant(space, 'Space not found');
104
+
105
+ const subjectId = fullyQualifiedId(subject);
106
+ const proposal = Obj.make(DataType.Message, {
107
+ created: new Date().toISOString(),
108
+ sender,
109
+ blocks: [{ _tag: 'proposal', text }],
110
+ });
111
+ const thread = Obj.make(ThreadType, { name: 'Proposal', messages: [Ref.make(proposal)], status: 'active' });
112
+
113
+ return {
114
+ intents: [
115
+ createIntent(SpaceAction.AddObject, { object: thread, target: space, hidden: true }),
116
+ createIntent(SpaceAction.AddRelation, {
117
+ space,
118
+ schema: AnchoredTo,
119
+ source: thread,
120
+ target: subject,
121
+ fields: { anchor },
122
+ }),
123
+ createIntent(ThreadAction.Select, { current: fullyQualifiedId(thread) }),
124
+ createIntent(DeckAction.ChangeCompanion, {
125
+ primary: subjectId,
126
+ companion: `${subjectId}${ATTENDABLE_PATH_SEPARATOR}comments`,
127
+ }),
128
+ ],
129
+ };
130
+ },
131
+ }),
97
132
  createResolver({
98
133
  intent: ThreadAction.Select,
99
134
  resolve: ({ current }) => {
@@ -197,7 +232,6 @@ export default (context: PluginContext) =>
197
232
  const subjectId = fullyQualifiedId(subject);
198
233
  const space = getSpace(subject);
199
234
  invariant(space, 'Space not found');
200
- const intents = [];
201
235
 
202
236
  const message = Obj.make(DataType.Message, {
203
237
  created: new Date().toISOString(),
@@ -208,6 +242,7 @@ export default (context: PluginContext) =>
208
242
  });
209
243
  thread.messages.push(Ref.make(message));
210
244
 
245
+ const intents = [];
211
246
  const draft = state.drafts[subjectId]?.find((a) => a.id === anchor.id);
212
247
  if (draft) {
213
248
  // Move draft to document.
@@ -4,15 +4,16 @@
4
4
 
5
5
  import { EditorView } from '@codemirror/view';
6
6
 
7
- import { Capabilities, contributes, createIntent, type PluginContext } from '@dxos/app-framework';
7
+ import { Capabilities, type PluginContext, contributes, createIntent } from '@dxos/app-framework';
8
8
  import { ATTENDABLE_PATH_SEPARATOR, DeckAction } from '@dxos/plugin-deck/types';
9
9
  import { MarkdownCapabilities } from '@dxos/plugin-markdown';
10
10
  import { fullyQualifiedId } from '@dxos/react-client/echo';
11
- import { commentClickedEffect, commentsState, type EditorState, overlap } from '@dxos/react-ui-editor';
11
+ import { type EditorState, commentClickedEffect, commentsState, overlap } from '@dxos/react-ui-editor';
12
12
 
13
- import { ThreadCapabilities } from './capabilities';
14
13
  import { threads } from '../extensions';
15
14
 
15
+ import { ThreadCapabilities } from './capabilities';
16
+
16
17
  export default (context: PluginContext) =>
17
18
  contributes(MarkdownCapabilities.Extensions, [
18
19
  ({ document: doc }) => {
@@ -9,17 +9,18 @@ import { Obj, type Ref } from '@dxos/echo';
9
9
  import { SettingsStore } from '@dxos/local-storage';
10
10
  import { getSpace } from '@dxos/react-client/echo';
11
11
 
12
- import { ThreadCapabilities } from './capabilities';
13
12
  import {
14
- CallSidebar,
15
13
  CallDebugPanel,
14
+ CallSidebar,
16
15
  ChannelContainer,
16
+ ChatContainer,
17
17
  ThreadComplementary,
18
18
  ThreadSettings,
19
- ChatContainer,
20
19
  } from '../components';
21
20
  import { THREAD_PLUGIN } from '../meta';
22
- import { ChannelType, ThreadType, type ThreadSettingsProps } from '../types';
21
+ import { ChannelType, type ThreadSettingsProps, ThreadType } from '../types';
22
+
23
+ import { ThreadCapabilities } from './capabilities';
23
24
 
24
25
  export default () =>
25
26
  contributes(Capabilities.ReactSurface, [
@@ -5,9 +5,10 @@
5
5
  import { contributes } from '@dxos/app-framework';
6
6
  import { live } from '@dxos/live-object';
7
7
 
8
- import { ThreadCapabilities } from './capabilities';
9
8
  import { type ThreadState, type ViewStore } from '../types';
10
9
 
10
+ import { ThreadCapabilities } from './capabilities';
11
+
11
12
  const initialViewState = { showResolvedThreads: false };
12
13
 
13
14
  export default () => {
@@ -0,0 +1,78 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { AiTool, AiToolkit } from '@effect/ai';
6
+ import { Array, Effect, Schema, pipe } from 'effect';
7
+
8
+ import { Capabilities, type PluginContext, contributes, createIntent } from '@dxos/app-framework';
9
+ import { ArtifactId, computeDiffsWithCursors } from '@dxos/assistant';
10
+ import { type SpaceId } from '@dxos/keys';
11
+ import { ClientCapabilities } from '@dxos/plugin-client';
12
+ import { type Markdown } from '@dxos/plugin-markdown/types';
13
+ import { createDocAccessor } from '@dxos/react-client/echo';
14
+ import { trim } from '@dxos/util';
15
+
16
+ import { ThreadAction } from '../types';
17
+
18
+ // TODO(wittjosiah): How to make this work for more than Documents?
19
+ class Toolkit extends AiToolkit.make(
20
+ AiTool.make('add-proposals', {
21
+ description: trim`
22
+ Proposes a set of changes to a document.
23
+ `,
24
+ parameters: {
25
+ id: ArtifactId,
26
+ diffs: Schema.Array(Schema.String).annotations({
27
+ description: 'The diffs to propose for the document.',
28
+ }),
29
+ },
30
+ success: Schema.Any,
31
+ failure: Schema.Never,
32
+ }),
33
+ ) {
34
+ static layer = (context: PluginContext) =>
35
+ Toolkit.toLayer({
36
+ 'add-proposals': ({ id, diffs: _diffs }) =>
37
+ Effect.gen(function* () {
38
+ // TODO(wittjosiah): Get capabilities via layers.
39
+ const { dispatch } = context.getCapability(Capabilities.IntentDispatcher);
40
+ const client = context.getCapability(ClientCapabilities.Client);
41
+ const state = context.getCapability(Capabilities.Layout);
42
+
43
+ const dxn = ArtifactId.toDXN(id, state.workspace as SpaceId);
44
+
45
+ const echoDxn = dxn.asEchoDXN();
46
+ if (!echoDxn) {
47
+ throw new Error(`Invalid object ID: ${id}`);
48
+ }
49
+
50
+ const space = client.spaces.get(echoDxn.spaceId!);
51
+ const object = space?.db.getObjectById<Markdown.Document>(echoDxn.echoId);
52
+ if (!object) {
53
+ throw new Error(`Object not found: ${id}`);
54
+ }
55
+
56
+ const content = yield* Effect.promise(() => object.content.load());
57
+ const accessor = createDocAccessor(content, ['content']);
58
+ yield* pipe(
59
+ computeDiffsWithCursors(accessor, _diffs),
60
+ Array.map(({ cursor, text }) =>
61
+ createIntent(ThreadAction.AddProposal, {
62
+ subject: object,
63
+ sender: { role: 'assistant' },
64
+ anchor: cursor,
65
+ text,
66
+ }),
67
+ ),
68
+ Array.map(dispatch),
69
+ Effect.allWith({ concurrency: 'unbounded' }),
70
+ );
71
+ }).pipe(Effect.orDie),
72
+ });
73
+ }
74
+
75
+ export default (context: PluginContext) => [
76
+ contributes(Capabilities.Toolkit, Toolkit),
77
+ contributes(Capabilities.ToolkitHandler, Toolkit.layer(context)),
78
+ ];
@@ -2,17 +2,18 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import React, { type PropsWithChildren, type FC } from 'react';
5
+ import React, { type FC, type PropsWithChildren } from 'react';
6
6
 
7
7
  import { useCapability } from '@dxos/app-framework';
8
8
  import { type ThemedClassName } from '@dxos/react-ui';
9
9
 
10
- import { Toolbar, type ToolbarProps } from './Toolbar';
11
10
  import { ThreadCapabilities } from '../../capabilities';
12
11
  import { useDebugMode } from '../../hooks';
13
12
  import { AudioStream } from '../Media';
14
13
  import { ParticipantGrid } from '../Participant';
15
14
 
15
+ import { Toolbar, type ToolbarProps } from './Toolbar';
16
+
16
17
  //
17
18
  // Root
18
19
  //
@@ -5,14 +5,14 @@
5
5
  import React from 'react';
6
6
 
7
7
  import { useAppGraph, useCapability } from '@dxos/app-framework';
8
- import { useNode, useActions } from '@dxos/plugin-graph';
8
+ import { useActions, useNode } from '@dxos/plugin-graph';
9
9
  import { fullyQualifiedId } from '@dxos/react-client/echo';
10
10
  import {
11
11
  Icon,
12
12
  IconButton,
13
13
  type IconButtonProps,
14
- type ThemedClassName,
15
14
  Toolbar as NativeToolbar,
15
+ type ThemedClassName,
16
16
  toLocalizedString,
17
17
  useTranslation,
18
18
  } from '@dxos/react-ui';
@@ -7,7 +7,7 @@ import React, { useEffect, useMemo, useState } from 'react';
7
7
 
8
8
  import { Panel } from '@dxos/devtools';
9
9
  import { log } from '@dxos/log';
10
- import { Input, useTranslation, type ThemedClassName } from '@dxos/react-ui';
10
+ import { Input, type ThemedClassName, useTranslation } from '@dxos/react-ui';
11
11
  import { Json } from '@dxos/react-ui-syntax-highlighter';
12
12
 
13
13
  import { type GlobalState } from '../calls';
@@ -6,9 +6,10 @@ import React from 'react';
6
6
 
7
7
  import { useCapability } from '@dxos/app-framework';
8
8
 
9
- import { ChannelContainer } from './ChannelContainer';
10
9
  import { ThreadCapabilities } from '../capabilities';
11
10
 
11
+ import { ChannelContainer } from './ChannelContainer';
12
+
12
13
  export const CallSidebar = () => {
13
14
  const call = useCapability(ThreadCapabilities.CallManager);
14
15
  return <ChannelContainer roomId={call.roomId} />;
@@ -12,13 +12,14 @@ import { withPluginManager } from '@dxos/app-framework/testing';
12
12
  import { ClientCapabilities } from '@dxos/plugin-client';
13
13
  import { Query, useQuery, useSpace } from '@dxos/react-client/echo';
14
14
  import { DataType } from '@dxos/schema';
15
- import { withLayout, ColumnContainer } from '@dxos/storybook-utils';
15
+ import { ColumnContainer, withLayout } from '@dxos/storybook-utils';
16
16
 
17
- import { ChannelContainer, type ChannelContainerProps } from './ChannelContainer';
18
17
  import { createThreadPlugins } from '../testing';
19
18
  import { translations } from '../translations';
20
19
  import { ChannelType, ThreadType } from '../types';
21
20
 
21
+ import { ChannelContainer, type ChannelContainerProps } from './ChannelContainer';
22
+
22
23
  // TODO(wittjosiah): Channel doesn't render full height.
23
24
  const Story = ({ roomId }: ChannelContainerProps) => {
24
25
  const space = useSpace();
@@ -30,7 +31,7 @@ const Story = ({ roomId }: ChannelContainerProps) => {
30
31
  return <ChannelContainer channel={channel} roomId={roomId} />;
31
32
  };
32
33
 
33
- const meta: Meta<ChannelContainerProps> = {
34
+ const meta = {
34
35
  title: 'plugins/plugin-thread/ChannelContainer',
35
36
  component: ChannelContainer,
36
37
  render: (args) => <Story {...args} />,
@@ -44,11 +45,11 @@ const meta: Meta<ChannelContainerProps> = {
44
45
  parameters: {
45
46
  translations,
46
47
  },
47
- };
48
+ } satisfies Meta<typeof ChannelContainer>;
48
49
 
49
50
  export default meta;
50
51
 
51
- type Story = StoryObj<ChannelContainerProps>;
52
+ type Story = StoryObj<typeof meta>;
52
53
 
53
54
  export const Default: Story = {
54
55
  args: {
@@ -3,7 +3,7 @@
3
3
  //
4
4
 
5
5
  import { Rx } from '@effect-rx/rx-react';
6
- import React, { useCallback, useEffect, useMemo, useState, type ChangeEvent } from 'react';
6
+ import React, { type ChangeEvent, useCallback, useEffect, useMemo, useState } from 'react';
7
7
 
8
8
  import { useCapabilities, useCapability } from '@dxos/app-framework';
9
9
  import { Context } from '@dxos/context';
@@ -12,18 +12,19 @@ import { log } from '@dxos/log';
12
12
  import { useClient } from '@dxos/react-client';
13
13
  import { fullyQualifiedId, getSpace } from '@dxos/react-client/echo';
14
14
  import { useIdentity } from '@dxos/react-client/halo';
15
- import { useTranslation, Input, ElevationProvider, type ThemedClassName } from '@dxos/react-ui';
16
- import { ControlGroup, ControlItemInput, ControlGroupButton } from '@dxos/react-ui-form';
17
- import { ToolbarMenu, MenuProvider, createMenuAction, useMenuActions, createMenuItemGroup } from '@dxos/react-ui-menu';
15
+ import { ElevationProvider, Input, type ThemedClassName, useTranslation } from '@dxos/react-ui';
16
+ import { ControlGroup, ControlGroupButton, ControlItemInput } from '@dxos/react-ui-form';
17
+ import { MenuProvider, ToolbarMenu, createMenuAction, createMenuItemGroup, useMenuActions } from '@dxos/react-ui-menu';
18
18
  import { useSoundEffect } from '@dxos/react-ui-sfx';
19
19
  import { StackItem } from '@dxos/react-ui-stack';
20
20
 
21
- import { Call } from './Call';
22
- import ChatContainer from './ChatContainer';
23
21
  import { ThreadCapabilities } from '../capabilities';
24
22
  import { meta } from '../meta';
25
23
  import { type ChannelType } from '../types';
26
24
 
25
+ import { Call } from './Call';
26
+ import ChatContainer from './ChatContainer';
27
+
27
28
  export type ChannelContainerProps = {
28
29
  channel?: ChannelType;
29
30
  roomId?: string;