@dxos/plugin-thread 0.8.4-main.67995b8 → 0.8.4-main.dedc0f3

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 (248) hide show
  1. package/dist/lib/browser/ChannelContainer-4PYFOIDK.mjs +16 -0
  2. package/dist/lib/browser/{ChatContainer-AIGIWAUG.mjs → ChatContainer-EXNNREYB.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-RMPTWSTF.mjs} +4 -4
  6. package/dist/lib/browser/call-manager-RMPTWSTF.mjs.map +7 -0
  7. package/dist/lib/browser/{chunk-LGSDKXPF.mjs → chunk-4APCDRSH.mjs} +1 -1
  8. package/dist/lib/browser/{chunk-LGSDKXPF.mjs.map → chunk-4APCDRSH.mjs.map} +1 -1
  9. package/dist/lib/browser/{chunk-KWPRNHTK.mjs → chunk-7W7QK5ZP.mjs} +232 -230
  10. package/dist/lib/browser/chunk-7W7QK5ZP.mjs.map +7 -0
  11. package/dist/lib/browser/chunk-G4CNILRR.mjs +23 -0
  12. package/dist/lib/browser/{chunk-FR7KJPNY.mjs.map → chunk-G4CNILRR.mjs.map} +3 -3
  13. package/dist/lib/browser/{chunk-GCLD5ESP.mjs → chunk-KTWYVC5X.mjs} +22 -12
  14. package/dist/lib/browser/chunk-KTWYVC5X.mjs.map +7 -0
  15. package/dist/lib/browser/chunk-PBMNFG3B.mjs +376 -0
  16. package/dist/lib/browser/chunk-PBMNFG3B.mjs.map +7 -0
  17. package/dist/lib/browser/{chunk-ERWASUQK.mjs → chunk-RI3Z6MK3.mjs} +38 -6
  18. package/dist/lib/{node-esm/chunk-25ABSYP2.mjs.map → browser/chunk-RI3Z6MK3.mjs.map} +4 -4
  19. package/dist/lib/browser/{chunk-6NSMBO3B.mjs → chunk-XYUJXHYV.mjs} +55 -5
  20. package/dist/lib/browser/chunk-XYUJXHYV.mjs.map +7 -0
  21. package/dist/lib/browser/{chunk-ZE7KWN36.mjs → chunk-ZCEU5K23.mjs} +461 -240
  22. package/dist/lib/browser/chunk-ZCEU5K23.mjs.map +7 -0
  23. package/dist/lib/browser/chunk-ZH2WPTNP.mjs +618 -0
  24. package/dist/lib/browser/chunk-ZH2WPTNP.mjs.map +7 -0
  25. package/dist/lib/browser/index.mjs +20 -9
  26. package/dist/lib/browser/index.mjs.map +3 -3
  27. package/dist/lib/browser/{intent-resolver-JFGLZ6VI.mjs → intent-resolver-J7OCP2P6.mjs} +67 -9
  28. package/dist/lib/browser/intent-resolver-J7OCP2P6.mjs.map +7 -0
  29. package/dist/lib/browser/{markdown-M3FMR7OD.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-JEUSQXI6.mjs → react-root-XKOD4KRB.mjs} +9 -9
  33. package/dist/lib/browser/{react-surface-XWS6GIZY.mjs → react-surface-GVGZRBDK.mjs} +9 -9
  34. package/dist/lib/browser/react-surface-GVGZRBDK.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-7FXCKO7X.mjs → ChannelContainer-KQQEZWUN.mjs} +7 -7
  42. package/dist/lib/node-esm/{ChatContainer-IQUWU426.mjs → ChatContainer-QVQKFBWA.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-QAREJFVX.mjs} +4 -4
  46. package/dist/lib/node-esm/call-manager-QAREJFVX.mjs.map +7 -0
  47. package/dist/lib/node-esm/{chunk-OU5BYIDO.mjs → chunk-2V3WSLUZ.mjs} +55 -5
  48. package/dist/lib/node-esm/chunk-2V3WSLUZ.mjs.map +7 -0
  49. package/dist/lib/node-esm/chunk-4T45PCKP.mjs +25 -0
  50. package/dist/lib/node-esm/{chunk-2CXOK2TD.mjs.map → chunk-4T45PCKP.mjs.map} +3 -3
  51. package/dist/lib/node-esm/chunk-DKCQCENK.mjs +377 -0
  52. package/dist/lib/node-esm/chunk-DKCQCENK.mjs.map +7 -0
  53. package/dist/lib/node-esm/{chunk-25ABSYP2.mjs → chunk-JNPKMT7O.mjs} +38 -6
  54. package/dist/lib/node-esm/chunk-JNPKMT7O.mjs.map +7 -0
  55. package/dist/lib/node-esm/chunk-LE2LIYGX.mjs +619 -0
  56. package/dist/lib/node-esm/chunk-LE2LIYGX.mjs.map +7 -0
  57. package/dist/lib/node-esm/{chunk-TDFHTCZZ.mjs → chunk-P6E247RF.mjs} +22 -12
  58. package/dist/lib/node-esm/chunk-P6E247RF.mjs.map +7 -0
  59. package/dist/lib/node-esm/{chunk-75RJ5DJI.mjs → chunk-PYTVBN5J.mjs} +1 -1
  60. package/dist/lib/node-esm/{chunk-75RJ5DJI.mjs.map → chunk-PYTVBN5J.mjs.map} +1 -1
  61. package/dist/lib/node-esm/{chunk-C3XFMUAY.mjs → chunk-SNKFZQST.mjs} +232 -230
  62. package/dist/lib/node-esm/chunk-SNKFZQST.mjs.map +7 -0
  63. package/dist/lib/node-esm/{chunk-IHDNQLLR.mjs → chunk-TIPIOH2J.mjs} +461 -240
  64. package/dist/lib/node-esm/chunk-TIPIOH2J.mjs.map +7 -0
  65. package/dist/lib/node-esm/index.mjs +20 -9
  66. package/dist/lib/node-esm/index.mjs.map +3 -3
  67. package/dist/lib/node-esm/{intent-resolver-OXGNQ44Y.mjs → intent-resolver-SR2LW4HF.mjs} +67 -9
  68. package/dist/lib/node-esm/intent-resolver-SR2LW4HF.mjs.map +7 -0
  69. package/dist/lib/node-esm/{markdown-INKTE4MH.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-XYYY2JXZ.mjs → react-root-4JWDRIQB.mjs} +9 -9
  73. package/dist/lib/node-esm/{react-surface-MJ33KPYE.mjs → react-surface-WLQUVRAX.mjs} +9 -9
  74. package/dist/lib/node-esm/react-surface-WLQUVRAX.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 +4 -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 +7 -0
  116. package/dist/types/src/components/CallDebugPanel.d.ts.map +1 -1
  117. package/dist/types/src/components/CallSidebar.d.ts.map +1 -1
  118. package/dist/types/src/components/ChannelContainer.d.ts.map +1 -1
  119. package/dist/types/src/components/ChannelContainer.stories.d.ts +88 -3
  120. package/dist/types/src/components/ChannelContainer.stories.d.ts.map +1 -1
  121. package/dist/types/src/components/Chat.stories.d.ts +90 -4
  122. package/dist/types/src/components/Chat.stories.d.ts.map +1 -1
  123. package/dist/types/src/components/ChatContainer.d.ts.map +1 -1
  124. package/dist/types/src/components/Comments.stories.d.ts +156 -3
  125. package/dist/types/src/components/Comments.stories.d.ts.map +1 -1
  126. package/dist/types/src/components/CommentsContainer.d.ts.map +1 -1
  127. package/dist/types/src/components/CommentsThreadContainer.d.ts +2 -2
  128. package/dist/types/src/components/CommentsThreadContainer.d.ts.map +1 -1
  129. package/dist/types/src/components/Lobby/Lobby.d.ts.map +1 -1
  130. package/dist/types/src/components/Media/VideoObject.d.ts +1 -1
  131. package/dist/types/src/components/Media/VideoObject.stories.d.ts +15 -3
  132. package/dist/types/src/components/Media/VideoObject.stories.d.ts.map +1 -1
  133. package/dist/types/src/components/MessageContainer.d.ts +4 -1
  134. package/dist/types/src/components/MessageContainer.d.ts.map +1 -1
  135. package/dist/types/src/components/Participant/Participant.d.ts.map +1 -1
  136. package/dist/types/src/components/Participant/ParticipantGrid.d.ts.map +1 -1
  137. package/dist/types/src/components/ResponsiveGrid/ResponsiveContainer.stories.d.ts +154 -2
  138. package/dist/types/src/components/ResponsiveGrid/ResponsiveContainer.stories.d.ts.map +1 -1
  139. package/dist/types/src/components/ResponsiveGrid/ResponsiveGrid.stories.d.ts +156 -3
  140. package/dist/types/src/components/ResponsiveGrid/ResponsiveGrid.stories.d.ts.map +1 -1
  141. package/dist/types/src/components/ResponsiveGrid/ResponsiveGridItem.d.ts.map +1 -1
  142. package/dist/types/src/components/ThreadComplementary.d.ts.map +1 -1
  143. package/dist/types/src/components/command-extension.d.ts.map +1 -1
  144. package/dist/types/src/components/testing.d.ts +1 -0
  145. package/dist/types/src/components/testing.d.ts.map +1 -1
  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 +3 -1
  153. package/dist/types/src/translations.d.ts.map +1 -1
  154. package/dist/types/src/types/schema.d.ts +123 -108
  155. package/dist/types/src/types/schema.d.ts.map +1 -1
  156. package/dist/types/src/types/types.d.ts +255 -170
  157. package/dist/types/src/types/types.d.ts.map +1 -1
  158. package/dist/types/tsconfig.tsbuildinfo +1 -1
  159. package/package.json +56 -54
  160. package/src/ThreadPlugin.tsx +9 -2
  161. package/src/calls/call-manager.ts +2 -2
  162. package/src/calls/call-swarm-synchronizer.ts +1 -1
  163. package/src/calls/media-manager.ts +60 -34
  164. package/src/calls/types.ts +8 -4
  165. package/src/calls/util/calls-service.ts +65 -14
  166. package/src/calls/util/stub-media-streams.ts +62 -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 +38 -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 +5 -5
  179. package/src/components/CallDebugPanel.tsx +108 -49
  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 +3 -3
  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 +3 -1
  208. package/src/types/types.ts +21 -12
  209. package/src/typings/peermetrics-webrtc-stats.d.ts +17 -1
  210. package/src/typings.d.ts +8 -0
  211. package/dist/lib/browser/ChannelContainer-3GIE7ASU.mjs +0 -16
  212. package/dist/lib/browser/app-graph-builder-N7BE5TYW.mjs.map +0 -7
  213. package/dist/lib/browser/call-manager-NIPDYUVD.mjs.map +0 -7
  214. package/dist/lib/browser/chunk-3SGRT4NM.mjs +0 -367
  215. package/dist/lib/browser/chunk-3SGRT4NM.mjs.map +0 -7
  216. package/dist/lib/browser/chunk-6NSMBO3B.mjs.map +0 -7
  217. package/dist/lib/browser/chunk-ERWASUQK.mjs.map +0 -7
  218. package/dist/lib/browser/chunk-FR7KJPNY.mjs +0 -21
  219. package/dist/lib/browser/chunk-GCLD5ESP.mjs.map +0 -7
  220. package/dist/lib/browser/chunk-KWPRNHTK.mjs.map +0 -7
  221. package/dist/lib/browser/chunk-VUWC4IJM.mjs +0 -479
  222. package/dist/lib/browser/chunk-VUWC4IJM.mjs.map +0 -7
  223. package/dist/lib/browser/chunk-ZE7KWN36.mjs.map +0 -7
  224. package/dist/lib/browser/intent-resolver-JFGLZ6VI.mjs.map +0 -7
  225. package/dist/lib/browser/markdown-M3FMR7OD.mjs.map +0 -7
  226. package/dist/lib/browser/react-surface-XWS6GIZY.mjs.map +0 -7
  227. package/dist/lib/node-esm/app-graph-builder-VCW76Z6V.mjs.map +0 -7
  228. package/dist/lib/node-esm/call-manager-D6O5ZJJ4.mjs.map +0 -7
  229. package/dist/lib/node-esm/chunk-2CXOK2TD.mjs +0 -23
  230. package/dist/lib/node-esm/chunk-2MFNK53T.mjs +0 -480
  231. package/dist/lib/node-esm/chunk-2MFNK53T.mjs.map +0 -7
  232. package/dist/lib/node-esm/chunk-C3XFMUAY.mjs.map +0 -7
  233. package/dist/lib/node-esm/chunk-FLBFYGBK.mjs +0 -368
  234. package/dist/lib/node-esm/chunk-FLBFYGBK.mjs.map +0 -7
  235. package/dist/lib/node-esm/chunk-IHDNQLLR.mjs.map +0 -7
  236. package/dist/lib/node-esm/chunk-OU5BYIDO.mjs.map +0 -7
  237. package/dist/lib/node-esm/chunk-TDFHTCZZ.mjs.map +0 -7
  238. package/dist/lib/node-esm/intent-resolver-OXGNQ44Y.mjs.map +0 -7
  239. package/dist/lib/node-esm/markdown-INKTE4MH.mjs.map +0 -7
  240. package/dist/lib/node-esm/react-surface-MJ33KPYE.mjs.map +0 -7
  241. /package/dist/lib/browser/{ChannelContainer-3GIE7ASU.mjs.map → ChannelContainer-4PYFOIDK.mjs.map} +0 -0
  242. /package/dist/lib/browser/{ChatContainer-AIGIWAUG.mjs.map → ChatContainer-EXNNREYB.mjs.map} +0 -0
  243. /package/dist/lib/browser/{react-root-JEUSQXI6.mjs.map → react-root-XKOD4KRB.mjs.map} +0 -0
  244. /package/dist/lib/browser/{settings-E32MTL7A.mjs.map → settings-GRKEID73.mjs.map} +0 -0
  245. /package/dist/lib/node-esm/{ChannelContainer-7FXCKO7X.mjs.map → ChannelContainer-KQQEZWUN.mjs.map} +0 -0
  246. /package/dist/lib/node-esm/{ChatContainer-IQUWU426.mjs.map → ChatContainer-QVQKFBWA.mjs.map} +0 -0
  247. /package/dist/lib/node-esm/{react-root-XYYY2JXZ.mjs.map → react-root-4JWDRIQB.mjs.map} +0 -0
  248. /package/dist/lib/node-esm/{settings-SJ24YG7M.mjs.map → settings-F2ODVNNW.mjs.map} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/plugin-thread",
3
- "version": "0.8.4-main.67995b8",
3
+ "version": "0.8.4-main.dedc0f3",
4
4
  "description": "DXOS Threads Surface plugin",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -10,16 +10,16 @@
10
10
  "type": "module",
11
11
  "exports": {
12
12
  ".": {
13
+ "source": "./src/index.ts",
13
14
  "types": "./dist/types/src/index.d.ts",
14
15
  "browser": "./dist/lib/browser/index.mjs",
15
- "node": "./dist/lib/node-esm/index.mjs",
16
- "source": "./src/index.ts"
16
+ "node": "./dist/lib/node-esm/index.mjs"
17
17
  },
18
18
  "./types": {
19
+ "source": "./src/types/index.ts",
19
20
  "types": "./dist/types/src/types/index.d.ts",
20
21
  "browser": "./dist/lib/browser/types/index.mjs",
21
- "node": "./dist/lib/node-esm/types/index.mjs",
22
- "source": "./src/types/index.ts"
22
+ "node": "./dist/lib/node-esm/types/index.mjs"
23
23
  }
24
24
  },
25
25
  "types": "dist/types/src/index.d.ts",
@@ -35,9 +35,10 @@
35
35
  "src"
36
36
  ],
37
37
  "dependencies": {
38
- "@codemirror/language": "^6.10.3",
39
- "@codemirror/state": "^6.4.1",
40
- "@codemirror/view": "^6.34.1",
38
+ "@codemirror/language": "^6.11.3",
39
+ "@codemirror/state": "^6.5.2",
40
+ "@codemirror/view": "^6.38.2",
41
+ "@effect/ai": "0.25.2",
41
42
  "@peermetrics/webrtc-stats": "5.7.1",
42
43
  "@preact-signals/safe-react": "^0.9.0",
43
44
  "@preact/signals-core": "^1.9.0",
@@ -45,58 +46,59 @@
45
46
  "extendable-media-recorder": "^9.2.19",
46
47
  "extendable-media-recorder-wav-encoder": "^7.0.123",
47
48
  "md5-hex": "5.0.0",
48
- "react-resize-detector": "^12.0.2",
49
+ "react-resize-detector": "^11.0.1",
49
50
  "wavefile": "^11.0.0",
50
- "@dxos/app-framework": "0.8.4-main.67995b8",
51
- "@dxos/async": "0.8.4-main.67995b8",
52
- "@dxos/codec-protobuf": "0.8.4-main.67995b8",
53
- "@dxos/context": "0.8.4-main.67995b8",
54
- "@dxos/debug": "0.8.4-main.67995b8",
55
- "@dxos/display-name": "0.8.4-main.67995b8",
56
- "@dxos/echo": "0.8.4-main.67995b8",
57
- "@dxos/devtools": "0.8.4-main.67995b8",
58
- "@dxos/invariant": "0.8.4-main.67995b8",
59
- "@dxos/echo-schema": "0.8.4-main.67995b8",
60
- "@dxos/live-object": "0.8.4-main.67995b8",
61
- "@dxos/keys": "0.8.4-main.67995b8",
62
- "@dxos/local-storage": "0.8.4-main.67995b8",
63
- "@dxos/log": "0.8.4-main.67995b8",
64
- "@dxos/plugin-attention": "0.8.4-main.67995b8",
65
- "@dxos/plugin-client": "0.8.4-main.67995b8",
66
- "@dxos/plugin-deck": "0.8.4-main.67995b8",
67
- "@dxos/plugin-graph": "0.8.4-main.67995b8",
68
- "@dxos/plugin-markdown": "0.8.4-main.67995b8",
69
- "@dxos/protocols": "0.8.4-main.67995b8",
70
- "@dxos/plugin-observability": "0.8.4-main.67995b8",
71
- "@dxos/plugin-space": "0.8.4-main.67995b8",
72
- "@dxos/react-client": "0.8.4-main.67995b8",
73
- "@dxos/react-ui-attention": "0.8.4-main.67995b8",
74
- "@dxos/react-ui-dnd": "0.8.4-main.67995b8",
75
- "@dxos/react-ui-form": "0.8.4-main.67995b8",
76
- "@dxos/react-ui-sfx": "0.8.4-main.67995b8",
77
- "@dxos/react-ui-editor": "0.8.4-main.67995b8",
78
- "@dxos/react-ui-menu": "0.8.4-main.67995b8",
79
- "@dxos/react-ui-syntax-highlighter": "0.8.4-main.67995b8",
80
- "@dxos/react-ui-tabs": "0.8.4-main.67995b8",
81
- "@dxos/schema": "0.8.4-main.67995b8",
82
- "@dxos/react-ui-thread": "0.8.4-main.67995b8",
83
- "@dxos/util": "0.8.4-main.67995b8",
84
- "@dxos/react-ui-stack": "0.8.4-main.67995b8"
51
+ "@dxos/app-framework": "0.8.4-main.dedc0f3",
52
+ "@dxos/assistant": "0.8.4-main.dedc0f3",
53
+ "@dxos/context": "0.8.4-main.dedc0f3",
54
+ "@dxos/codec-protobuf": "0.8.4-main.dedc0f3",
55
+ "@dxos/debug": "0.8.4-main.dedc0f3",
56
+ "@dxos/devtools": "0.8.4-main.dedc0f3",
57
+ "@dxos/display-name": "0.8.4-main.dedc0f3",
58
+ "@dxos/echo": "0.8.4-main.dedc0f3",
59
+ "@dxos/echo-schema": "0.8.4-main.dedc0f3",
60
+ "@dxos/keys": "0.8.4-main.dedc0f3",
61
+ "@dxos/invariant": "0.8.4-main.dedc0f3",
62
+ "@dxos/local-storage": "0.8.4-main.dedc0f3",
63
+ "@dxos/live-object": "0.8.4-main.dedc0f3",
64
+ "@dxos/log": "0.8.4-main.dedc0f3",
65
+ "@dxos/plugin-attention": "0.8.4-main.dedc0f3",
66
+ "@dxos/plugin-client": "0.8.4-main.dedc0f3",
67
+ "@dxos/async": "0.8.4-main.dedc0f3",
68
+ "@dxos/plugin-deck": "0.8.4-main.dedc0f3",
69
+ "@dxos/plugin-graph": "0.8.4-main.dedc0f3",
70
+ "@dxos/plugin-markdown": "0.8.4-main.dedc0f3",
71
+ "@dxos/plugin-observability": "0.8.4-main.dedc0f3",
72
+ "@dxos/plugin-space": "0.8.4-main.dedc0f3",
73
+ "@dxos/react-client": "0.8.4-main.dedc0f3",
74
+ "@dxos/protocols": "0.8.4-main.dedc0f3",
75
+ "@dxos/react-ui-attention": "0.8.4-main.dedc0f3",
76
+ "@dxos/react-ui-form": "0.8.4-main.dedc0f3",
77
+ "@dxos/react-ui-sfx": "0.8.4-main.dedc0f3",
78
+ "@dxos/react-ui-editor": "0.8.4-main.dedc0f3",
79
+ "@dxos/react-ui-dnd": "0.8.4-main.dedc0f3",
80
+ "@dxos/react-ui-menu": "0.8.4-main.dedc0f3",
81
+ "@dxos/react-ui-stack": "0.8.4-main.dedc0f3",
82
+ "@dxos/react-ui-tabs": "0.8.4-main.dedc0f3",
83
+ "@dxos/react-ui-syntax-highlighter": "0.8.4-main.dedc0f3",
84
+ "@dxos/schema": "0.8.4-main.dedc0f3",
85
+ "@dxos/util": "0.8.4-main.dedc0f3",
86
+ "@dxos/react-ui-thread": "0.8.4-main.dedc0f3"
85
87
  },
86
88
  "devDependencies": {
87
89
  "@effect-rx/rx-react": "0.38.0",
88
- "@effect/platform": "0.89.0",
90
+ "@effect/platform": "0.90.2",
89
91
  "@types/react": "~18.2.0",
90
92
  "@types/react-dom": "~18.2.0",
91
- "effect": "3.17.0",
93
+ "effect": "3.17.7",
92
94
  "react": "~18.2.0",
93
95
  "react-dom": "~18.2.0",
94
- "vite": "5.4.7",
95
- "@dxos/plugin-theme": "0.8.4-main.67995b8",
96
- "@dxos/random": "0.8.4-main.67995b8",
97
- "@dxos/react-ui": "0.8.4-main.67995b8",
98
- "@dxos/react-ui-theme": "0.8.4-main.67995b8",
99
- "@dxos/storybook-utils": "0.8.4-main.67995b8"
96
+ "vite": "7.1.1",
97
+ "@dxos/plugin-theme": "0.8.4-main.dedc0f3",
98
+ "@dxos/random": "0.8.4-main.dedc0f3",
99
+ "@dxos/react-ui": "0.8.4-main.dedc0f3",
100
+ "@dxos/react-ui-theme": "0.8.4-main.dedc0f3",
101
+ "@dxos/storybook-utils": "0.8.4-main.dedc0f3"
100
102
  },
101
103
  "peerDependencies": {
102
104
  "@effect-rx/rx-react": "^0.34.1",
@@ -104,8 +106,8 @@
104
106
  "effect": "^3.13.3",
105
107
  "react": "~18.2.0",
106
108
  "react-dom": "~18.2.0",
107
- "@dxos/react-ui": "0.8.4-main.67995b8",
108
- "@dxos/react-ui-theme": "0.8.4-main.67995b8"
109
+ "@dxos/react-ui": "0.8.4-main.dedc0f3",
110
+ "@dxos/react-ui-theme": "0.8.4-main.dedc0f3"
109
111
  },
110
112
  "publishConfig": {
111
113
  "access": "public"
@@ -2,7 +2,7 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import { Capabilities, contributes, createIntent, defineModule, definePlugin, Events } from '@dxos/app-framework';
5
+ import { Capabilities, Events, contributes, createIntent, defineModule, definePlugin } from '@dxos/app-framework';
6
6
  import { Ref } from '@dxos/echo';
7
7
  import { ClientCapabilities, ClientEvents } from '@dxos/plugin-client';
8
8
  import { MarkdownEvents } from '@dxos/plugin-markdown';
@@ -19,8 +19,9 @@ import {
19
19
  ReactRoot,
20
20
  ReactSurface,
21
21
  ThreadState,
22
+ Toolkit,
22
23
  } from './capabilities';
23
- import { meta, THREAD_ITEM } from './meta';
24
+ import { THREAD_ITEM, meta } from './meta';
24
25
  import { translations } from './translations';
25
26
  import { ChannelType, ThreadAction, ThreadType } from './types';
26
27
 
@@ -152,4 +153,10 @@ export const ThreadPlugin = () =>
152
153
  activatesOn: Events.SetupAppGraph,
153
154
  activate: AppGraphBuilder,
154
155
  }),
156
+ defineModule({
157
+ id: `${meta.id}/module/toolkit`,
158
+ // TODO(wittjosiah): Shouldn't use the startup event.
159
+ activatesOn: Events.Startup,
160
+ activate: Toolkit,
161
+ }),
155
162
  ]);
@@ -12,7 +12,7 @@ import { live } from '@dxos/live-object';
12
12
  import { type Tracks } from '@dxos/protocols/proto/dxos/edge/calls';
13
13
  import { isNonNullable } from '@dxos/util';
14
14
 
15
- import { CallSwarmSynchronizer, type CallState } from './call-swarm-synchronizer';
15
+ import { type CallState, CallSwarmSynchronizer } from './call-swarm-synchronizer';
16
16
  import { MediaManager, type MediaState } from './media-manager';
17
17
  import { type ActivityState, CALLS_URL, type EncodedTrackName, TrackNameCodec, type UserState } from './types';
18
18
 
@@ -210,7 +210,7 @@ export class CallManager extends Resource {
210
210
 
211
211
  private _onCallStateUpdated(state: CallState): void {
212
212
  const tracksToPull = state.users
213
- ?.filter((user) => user.joined && user.id !== state.self?.id)
213
+ ?.filter((user) => user.joined && user.id !== state.self!.id)
214
214
  ?.flatMap((user) => [user.tracks?.video, user.tracks?.audio, user.tracks?.screenshare])
215
215
  .filter(isNonNullable);
216
216
  this._mediaManager._schedulePullTracks(tracksToPull as EncodedTrackName[]);
@@ -17,7 +17,7 @@ import { type Device, type NetworkService } from '@dxos/protocols/proto/dxos/cli
17
17
  import { ConnectionState, type SwarmResponse } from '@dxos/protocols/proto/dxos/edge/messenger';
18
18
  import { isNonNullable } from '@dxos/util';
19
19
 
20
- import { codec, type ActivityState, type UserState } from './types';
20
+ import { type ActivityState, type UserState, codec } from './types';
21
21
 
22
22
  export type CallState = {
23
23
  /**
@@ -3,11 +3,12 @@
3
3
  //
4
4
 
5
5
  import { DeferredTask, Event, sleep, synchronized } from '@dxos/async';
6
- import { cancelWithContext, type Context, Resource } from '@dxos/context';
6
+ import { type Context, Resource, cancelWithContext } from '@dxos/context';
7
+ import { invariant } from '@dxos/invariant';
7
8
  import { log } from '@dxos/log';
8
9
 
9
10
  import { SpeakingMonitor } from './speaking-monitor';
10
- import { TrackNameCodec, type EncodedTrackName, type TrackObject } from './types';
11
+ import { type EncodedTrackName, TrackNameCodec, type TrackObject } from './types';
11
12
  import {
12
13
  type CallsServiceConfig,
13
14
  CallsServicePeer,
@@ -48,13 +49,13 @@ const VIDEO_WIDTH = 1280;
48
49
  const VIDEO_HEIGHT = 720;
49
50
  const MAX_WEB_CAM_FRAMERATE = 24;
50
51
  const MAX_WEB_CAM_BITRATE = 120_0000;
51
- const RETRY_INTERVAL = 500;
52
+ const RETRY_INTERVAL = 100;
52
53
 
53
54
  export type MediaManagerParams = {
54
55
  serviceConfig: CallsServiceConfig;
55
56
  };
56
57
 
57
- const USE_INAUDIBLE_AUDIO = false;
58
+ const USE_INAUDIBLE_AUDIO = true;
58
59
 
59
60
  export class MediaManager extends Resource {
60
61
  public readonly stateUpdated = new Event<MediaState>();
@@ -248,7 +249,7 @@ export class MediaManager extends Resource {
248
249
  });
249
250
 
250
251
  // Pull new tracks.
251
- await Promise.all(tracksToPull.map((name) => this._pullTrack(name)));
252
+ const pullResults = await Promise.all(tracksToPull.map((name) => this._pullTrack(name)));
252
253
 
253
254
  // Close old tracks.
254
255
  await Promise.all([...audioTracksToClose, ...videoStreamsToClose].map(([_, { ctx }]) => ctx.dispose()));
@@ -258,6 +259,13 @@ export class MediaManager extends Resource {
258
259
  currentVideoStreams: Object.keys(this._state.pulledVideoStreams),
259
260
  });
260
261
  this.stateUpdated.emit(this._state);
262
+
263
+ if (pullResults.some(({ shouldRetry }) => shouldRetry)) {
264
+ await cancelWithContext(this._ctx, sleep(RETRY_INTERVAL));
265
+ log.info('retrying pull tracks', { tracksToPull });
266
+ invariant(this._pullTracksTask);
267
+ this._pullTracksTask.schedule();
268
+ }
261
269
  }
262
270
 
263
271
  private async _pushTracks(): Promise<void> {
@@ -266,38 +274,47 @@ export class MediaManager extends Resource {
266
274
  }
267
275
 
268
276
  let updated = false;
269
- const [pushedVideoTrack, pushedAudioTrack, pushedScreenshareTrack] = await Promise.all([
270
- this._pushTrack(this._state.videoTrack, this._state.pushedVideoTrack, [
277
+ const [pushVideoResult, pushAudioResult, pushScreenshareResult] = await Promise.all([
278
+ this._maybePushTrack(this._state.videoTrack, this._state.pushedVideoTrack, [
271
279
  { maxFramerate: MAX_WEB_CAM_FRAMERATE, maxBitrate: MAX_WEB_CAM_BITRATE },
272
280
  ]),
273
- this._pushTrack(this._state.audioTrack, this._state.pushedAudioTrack, [{ networkPriority: 'high' }]),
274
- this._pushTrack(this._state.screenshareTrack, this._state.pushedScreenshareTrack),
281
+ this._maybePushTrack(this._state.audioTrack, this._state.pushedAudioTrack, [{ networkPriority: 'high' }]),
282
+ this._maybePushTrack(this._state.screenshareTrack, this._state.pushedScreenshareTrack),
275
283
  ]);
276
284
 
277
- if (pushedVideoTrack !== this._state.pushedVideoTrack) {
278
- this._state.pushedVideoTrack = pushedVideoTrack;
285
+ if (pushVideoResult.track !== this._state.pushedVideoTrack) {
286
+ this._state.pushedVideoTrack = pushVideoResult.track;
279
287
  updated = true;
280
288
  }
281
- if (pushedAudioTrack !== this._state.pushedAudioTrack) {
282
- this._state.pushedAudioTrack = pushedAudioTrack;
289
+ if (pushAudioResult.track !== this._state.pushedAudioTrack) {
290
+ this._state.pushedAudioTrack = pushAudioResult.track;
283
291
  updated = true;
284
292
  }
285
- if (pushedScreenshareTrack !== this._state.pushedScreenshareTrack) {
286
- this._state.pushedScreenshareTrack = pushedScreenshareTrack;
293
+ if (pushScreenshareResult.track !== this._state.pushedScreenshareTrack) {
294
+ this._state.pushedScreenshareTrack = pushScreenshareResult.track;
287
295
  updated = true;
288
296
  }
289
- if (!updated) {
290
- return;
297
+
298
+ const shouldRetry = pushVideoResult.shouldRetry || pushAudioResult.shouldRetry || pushScreenshareResult.shouldRetry;
299
+
300
+ if (updated) {
301
+ this.stateUpdated.emit(this._state);
291
302
  }
292
303
 
293
- this.stateUpdated.emit(this._state);
304
+ if (shouldRetry) {
305
+ await cancelWithContext(this._ctx, sleep(RETRY_INTERVAL));
306
+ log.info('retrying push tracks', { pushVideoResult, pushAudioResult, pushScreenshareResult });
307
+ invariant(this._pushTracksTask);
308
+ this._pushTracksTask.schedule();
309
+ }
294
310
  }
295
311
 
296
- private async _pullTrack(name: EncodedTrackName): Promise<void> {
312
+ private async _pullTrack(name: EncodedTrackName): Promise<{ shouldRetry: boolean }> {
297
313
  const ctx = this._ctx.derive();
298
314
  try {
299
315
  const trackData = TrackNameCodec.decode(name);
300
- const track = await this._state.peer!.pullTrack({ trackData, ctx });
316
+ // We need to set mid here to `undefined`, because mid is peer specific.
317
+ const track = await this._state.peer!.pullTrack({ trackData: { ...trackData, mid: undefined }, ctx });
301
318
  if (track?.readyState === 'ended') {
302
319
  throw new Error('Pulled track ended immediately');
303
320
  }
@@ -306,7 +323,7 @@ export class MediaManager extends Resource {
306
323
  case 'audio': {
307
324
  this._state.pulledAudioTracks[name] = { track, ctx };
308
325
  ctx.onDispose(() => delete this._state.pulledAudioTracks[name]);
309
- break;
326
+ return { shouldRetry: false };
310
327
  }
311
328
  case 'video': {
312
329
  const mediaStream = new MediaStream();
@@ -317,33 +334,42 @@ export class MediaManager extends Resource {
317
334
  track.stop();
318
335
  delete this._state.pulledVideoStreams[name];
319
336
  });
320
- break;
337
+ return { shouldRetry: false };
321
338
  }
322
339
  default:
323
340
  throw new Error(`Invalid track kind: ${track?.kind}`);
324
341
  }
325
342
  } catch (err) {
326
- log.verbose('failed to pull track', { err, name });
343
+ log.info('failed to pull track', { err, name });
327
344
  void ctx.dispose();
328
- await cancelWithContext(this._ctx, sleep(RETRY_INTERVAL));
329
- log.verbose('retrying pull track', { name });
330
- this._pullTracksTask!.schedule();
345
+ return { shouldRetry: true };
331
346
  }
332
347
  }
333
348
 
334
- private async _pushTrack(
349
+ private async _maybePushTrack(
335
350
  track?: MediaStreamTrack,
336
351
  previousTrack?: TrackObject,
337
352
  encodings?: RTCRtpEncodingParameters[],
338
- ): Promise<TrackObject | undefined> {
353
+ ): Promise<{ track?: TrackObject; shouldRetry?: boolean }> {
339
354
  if (!track && !previousTrack) {
340
- return;
355
+ return { track: undefined };
341
356
  }
342
357
 
343
- return this._state.peer!.pushTrack({
344
- track: track ?? null,
345
- previousTrack,
346
- encodings,
347
- });
358
+ const ctx = this._ctx.derive();
359
+
360
+ try {
361
+ return {
362
+ track: await this._state.peer!.pushTrack({
363
+ ctx,
364
+ track: track ?? null,
365
+ previousTrack,
366
+ encodings,
367
+ }),
368
+ };
369
+ } catch (err) {
370
+ log.info('failed to push track', { err, track, previousTrack, encodings });
371
+ void ctx.dispose();
372
+ return { shouldRetry: true };
373
+ }
348
374
  }
349
375
  }
@@ -2,11 +2,12 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
+ import { invariant } from '@dxos/invariant';
5
6
  import { buf } from '@dxos/protocols/buf';
6
7
  import {
7
8
  type ActivitySchema,
8
- UserStateSchema,
9
9
  type UserState as UserStateProto,
10
+ UserStateSchema,
10
11
  } from '@dxos/protocols/buf/dxos/edge/calls_pb';
11
12
 
12
13
  /**
@@ -61,10 +62,13 @@ export type EncodedTrackName = string & { __brand: 'EncodedTrackName' };
61
62
 
62
63
  export const TrackNameCodec = {
63
64
  encode: (trackData: TrackObject): EncodedTrackName => {
64
- return (trackData.sessionId + '/' + trackData.trackName) as EncodedTrackName;
65
+ invariant(trackData.sessionId);
66
+ invariant(trackData.trackName);
67
+ invariant(trackData.mid);
68
+ return (trackData.sessionId + '/' + trackData.trackName + '/' + trackData.mid) as EncodedTrackName;
65
69
  },
66
70
  decode: (name: EncodedTrackName): TrackObject => {
67
- const [sessionId, trackName] = name.split('/');
68
- return { sessionId, trackName, location: 'remote' };
71
+ const [sessionId, trackName, mid] = name.split('/');
72
+ return { sessionId, trackName, location: 'remote', mid };
69
73
  },
70
74
  };
@@ -2,21 +2,22 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import { PersistentLifecycle } from '@dxos/async';
5
+ import { PersistentLifecycle, Trigger, scheduleTask } from '@dxos/async';
6
6
  import { type Context, Resource } from '@dxos/context';
7
7
  import { invariant } from '@dxos/invariant';
8
8
  import { log } from '@dxos/log';
9
9
 
10
- import { HistoryCache } from './history-cache';
11
- import { BulkRequestDispatcher, FIFOScheduler } from './task-scheduling';
12
10
  import {
13
- type SessionResponse,
14
11
  type ErrorResponse,
15
12
  type RenegotiationResponse,
13
+ type SessionResponse,
16
14
  type TrackObject,
17
15
  type TracksResponse,
18
16
  } from '../types';
19
17
 
18
+ import { HistoryCache } from './history-cache';
19
+ import { BulkRequestDispatcher, FIFOScheduler } from './task-scheduling';
20
+
20
21
  const NETWORK_TIMEOUT = 5_000;
21
22
 
22
23
  export type Session = {
@@ -32,12 +33,14 @@ export type CallsServiceConfig = {
32
33
 
33
34
  export type HistoryRecord =
34
35
  | {
36
+ endpoint: string;
35
37
  type: 'request';
36
38
  time: string;
37
39
  method: string;
38
40
  body: any;
39
41
  }
40
42
  | {
43
+ endpoint: string;
41
44
  type: 'response';
42
45
  time: string;
43
46
  status: number;
@@ -115,7 +118,7 @@ export class CallsServicePeer extends Resource {
115
118
  });
116
119
  peerConnection.addEventListener('connectionstatechange', () => {
117
120
  if (peerConnection.connectionState === 'failed' || peerConnection.connectionState === 'closed') {
118
- log.warn('calls connection failed', { state: peerConnection.connectionState });
121
+ log.info('calls connection failed', { state: peerConnection.connectionState });
119
122
  void this._persistentLifecycle.scheduleRestart();
120
123
  }
121
124
  });
@@ -124,7 +127,7 @@ export class CallsServicePeer extends Resource {
124
127
  peerConnection.addEventListener('iceconnectionstatechange', () => {
125
128
  clearTimeout(iceTimeout);
126
129
  if (peerConnection.iceConnectionState === 'failed' || peerConnection.iceConnectionState === 'closed') {
127
- log.warn('calls connection to ICEs failed', { state: peerConnection.iceConnectionState });
130
+ log.info('calls connection to ICEs failed', { state: peerConnection.iceConnectionState });
128
131
  void this._persistentLifecycle.scheduleRestart();
129
132
  } else if (peerConnection.iceConnectionState === 'disconnected') {
130
133
  // TODO(mykola): we should start to inspect the connection stats from here on for
@@ -137,7 +140,7 @@ export class CallsServicePeer extends Resource {
137
140
  return;
138
141
  }
139
142
 
140
- log.warn('calls iceConnectionState timed out', { state: peerConnection.iceConnectionState, timeoutSeconds });
143
+ log.info('calls iceConnectionState timed out', { state: peerConnection.iceConnectionState, timeoutSeconds });
141
144
  void this._persistentLifecycle.scheduleRestart();
142
145
  }, timeoutSeconds * 1_000);
143
146
  }
@@ -154,6 +157,7 @@ export class CallsServicePeer extends Resource {
154
157
 
155
158
  private async _fetch<T extends ErrorResponse>(relativePath: string, requestInit?: RequestInit): Promise<T> {
156
159
  this.history.push({
160
+ endpoint: relativePath,
157
161
  type: 'request',
158
162
  time: new Date().toISOString(),
159
163
  method: requestInit?.method ?? 'GET',
@@ -169,6 +173,7 @@ export class CallsServicePeer extends Resource {
169
173
  try {
170
174
  const data = (await response.clone().json()) as T;
171
175
  this.history.push({
176
+ endpoint: relativePath,
172
177
  type: 'response',
173
178
  time: new Date().toISOString(),
174
179
  status: response.status,
@@ -182,6 +187,7 @@ export class CallsServicePeer extends Resource {
182
187
  } catch (error) {
183
188
  const text = await response.text();
184
189
  this.history.push({
190
+ endpoint: relativePath,
185
191
  type: 'response',
186
192
  time: new Date().toISOString(),
187
193
  status: response.status,
@@ -203,11 +209,11 @@ export class CallsServicePeer extends Resource {
203
209
  sessionId,
204
210
  trackName,
205
211
  }: {
212
+ ctx: Context;
206
213
  peerConnection: RTCPeerConnection;
207
214
  transceiver: RTCRtpTransceiver;
208
215
  sessionId: string;
209
216
  trackName: string;
210
- ctx?: Context;
211
217
  }): Promise<TrackObject | void> {
212
218
  log.verbose('pushing track ', trackName);
213
219
  const pushedTrackPromise = this.pushTrackDispatcher
@@ -245,9 +251,13 @@ export class CallsServicePeer extends Resource {
245
251
  };
246
252
  }),
247
253
  )
248
- .then(({ tracks }) => {
254
+ .then(async ({ tracks }) => {
249
255
  const trackData = tracks.find((t) => t.mid === transceiver.mid);
250
256
  if (trackData) {
257
+ // we wait for the transceiver to start sending data before we emit
258
+ // the track metadata to ensure that the track will be able to be
259
+ // pulled before making the metadata available to anyone else.
260
+ // await waitForTransceiverToSendData(ctx, transceiver);
251
261
  return {
252
262
  ...trackData,
253
263
  sessionId,
@@ -256,9 +266,6 @@ export class CallsServicePeer extends Resource {
256
266
  } else {
257
267
  log.error('missing track data');
258
268
  }
259
- })
260
- .catch((err) => {
261
- log.catch(err);
262
269
  });
263
270
 
264
271
  const onDispose = async () => {
@@ -280,8 +287,8 @@ export class CallsServicePeer extends Resource {
280
287
  previousTrack,
281
288
  }: {
282
289
  track: MediaStreamTrack | null;
290
+ ctx: Context;
283
291
  encodings?: RTCRtpEncodingParameters[];
284
- ctx?: Context;
285
292
  previousTrack?: TrackObject;
286
293
  }): Promise<TrackObject | undefined> {
287
294
  await this.waitUntilOpen();
@@ -404,7 +411,7 @@ export class CallsServicePeer extends Resource {
404
411
  })
405
412
  .catch((err) => log.catch(err));
406
413
  } else {
407
- log.warn('missing track info', { trackData, availableTracks: Array.from(trackMap.keys()) });
414
+ log.info('missing track info', { trackData, availableTracks: Array.from(trackMap.keys()) });
408
415
  }
409
416
  });
410
417
 
@@ -528,3 +535,47 @@ const peerConnectionIsConnected = async (peerConnection: RTCPeerConnection) => {
528
535
  await connected;
529
536
  }
530
537
  };
538
+
539
+ const INITIAL_DELAY = 50;
540
+ const MAX_DELAY = 500;
541
+ const MAX_RETRIES = 20;
542
+ const WAIT_FOR_DATA_TIMEOUT = 10_000;
543
+
544
+ const waitForTransceiverToSendData = async (ctx: Context, transceiver: RTCRtpTransceiver): Promise<void> => {
545
+ let delay = INITIAL_DELAY;
546
+ let checks = 0;
547
+ const waitForData = new Trigger();
548
+ ctx.onDispose(() => waitForData.throw(new Error('Transceiver was closed')));
549
+
550
+ const checkStats = async () => {
551
+ if (ctx.disposed) return;
552
+
553
+ try {
554
+ const stats = await transceiver.sender.getStats();
555
+ let dataFound = false;
556
+ stats.forEach((stat) => {
557
+ if (stat.type === 'outbound-rtp' && stat.bytesSent > 0) {
558
+ dataFound = true;
559
+ }
560
+ });
561
+
562
+ if (dataFound) {
563
+ waitForData.wake();
564
+ return;
565
+ }
566
+ } catch {
567
+ // Stats might not be available yet, continue checking
568
+ }
569
+ checks++;
570
+ if (checks > MAX_RETRIES) {
571
+ waitForData.throw(new Error('Transceiver did not send data'));
572
+ return;
573
+ }
574
+
575
+ delay = Math.min(delay * 2, MAX_DELAY); // Exponential backoff with max cap
576
+ scheduleTask(ctx, checkStats, delay);
577
+ };
578
+
579
+ void checkStats();
580
+ return waitForData.wait({ timeout: WAIT_FOR_DATA_TIMEOUT });
581
+ };