@dxos/plugin-thread 0.9.1-staging.ee54ba693a → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (166) hide show
  1. package/dist/lib/{neutral/ThreadPlugin.mjs → ThreadPlugin.mjs} +26 -66
  2. package/dist/lib/ThreadPlugin.mjs.map +1 -0
  3. package/dist/lib/ThreadPlugin.node.mjs +19 -0
  4. package/dist/lib/ThreadPlugin.node.mjs.map +1 -0
  5. package/dist/lib/ThreadPlugin.workerd.mjs +19 -0
  6. package/dist/lib/ThreadPlugin.workerd.mjs.map +1 -0
  7. package/dist/lib/capabilities/node.mjs +8 -0
  8. package/dist/lib/capabilities/node.mjs.map +1 -0
  9. package/dist/lib/capabilities.mjs +11 -0
  10. package/dist/lib/capabilities.mjs.map +1 -0
  11. package/dist/lib/chunk-ChannelArticle.mjs +104 -0
  12. package/dist/lib/chunk-ChannelArticle.mjs.map +1 -0
  13. package/dist/lib/chunk-ChannelCreatePanel.mjs +41 -0
  14. package/dist/lib/chunk-ChannelCreatePanel.mjs.map +1 -0
  15. package/dist/lib/chunk-ThreadArticle.mjs +58 -0
  16. package/dist/lib/chunk-ThreadArticle.mjs.map +1 -0
  17. package/dist/lib/chunk-app-graph-builder.mjs +49 -0
  18. package/dist/lib/chunk-app-graph-builder.mjs.map +1 -0
  19. package/dist/lib/chunk-append-channel-message.mjs +30 -0
  20. package/dist/lib/chunk-append-channel-message.mjs.map +1 -0
  21. package/dist/lib/chunk-channel-backend-feed.mjs +68 -0
  22. package/dist/lib/chunk-channel-backend-feed.mjs.map +1 -0
  23. package/dist/lib/chunk-create-channel.mjs +31 -0
  24. package/dist/lib/chunk-create-channel.mjs.map +1 -0
  25. package/dist/lib/chunk-create-object.mjs +36 -0
  26. package/dist/lib/chunk-create-object.mjs.map +1 -0
  27. package/dist/lib/{neutral/chunk-A5JYVGL2.mjs → chunk-meta.mjs} +20 -25
  28. package/dist/lib/chunk-meta.mjs.map +1 -0
  29. package/dist/lib/chunk-operation-handler.mjs +11 -0
  30. package/dist/lib/chunk-operation-handler.mjs.map +1 -0
  31. package/dist/lib/chunk-paths.mjs +8 -0
  32. package/dist/lib/chunk-paths.mjs.map +1 -0
  33. package/dist/lib/chunk-react-surface.mjs +38 -0
  34. package/dist/lib/chunk-react-surface.mjs.map +1 -0
  35. package/dist/lib/chunk-types.mjs +99 -0
  36. package/dist/lib/chunk-types.mjs.map +1 -0
  37. package/dist/lib/components.mjs +105 -0
  38. package/dist/lib/components.mjs.map +1 -0
  39. package/dist/lib/containers.mjs +9 -0
  40. package/dist/lib/containers.mjs.map +1 -0
  41. package/dist/lib/hooks.mjs +45 -0
  42. package/dist/lib/hooks.mjs.map +1 -0
  43. package/dist/lib/index.mjs +5 -0
  44. package/dist/lib/meta.mjs +2 -0
  45. package/dist/lib/operations.mjs +7 -0
  46. package/dist/lib/operations.mjs.map +1 -0
  47. package/dist/lib/plugin.mjs +9 -0
  48. package/dist/lib/plugin.mjs.map +1 -0
  49. package/dist/lib/translations.mjs +84 -0
  50. package/dist/lib/translations.mjs.map +1 -0
  51. package/dist/lib/types.mjs +2 -0
  52. package/dist/types/src/ThreadPlugin.d.ts.map +1 -1
  53. package/dist/types/src/ThreadPlugin.node.d.ts.map +1 -1
  54. package/dist/types/src/capabilities/app-graph-builder.d.ts +1 -1
  55. package/dist/types/src/capabilities/channel-backend-feed.d.ts +1 -1
  56. package/dist/types/src/capabilities/channel-backend-feed.d.ts.map +1 -1
  57. package/dist/types/src/capabilities/create-object.d.ts +1 -1
  58. package/dist/types/src/capabilities/index.d.ts +0 -1
  59. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  60. package/dist/types/src/capabilities/node.d.ts +5 -0
  61. package/dist/types/src/capabilities/node.d.ts.map +1 -0
  62. package/dist/types/src/capabilities/operation-handler.d.ts +1 -1
  63. package/dist/types/src/capabilities/react-surface.d.ts +1 -1
  64. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
  65. package/dist/types/src/components/{Chat/Chat.d.ts → MessageThread/MessageThread.d.ts} +11 -12
  66. package/dist/types/src/components/MessageThread/MessageThread.d.ts.map +1 -0
  67. package/dist/types/src/components/MessageThread/index.d.ts +2 -0
  68. package/dist/types/src/components/MessageThread/index.d.ts.map +1 -0
  69. package/dist/types/src/components/index.d.ts +1 -1
  70. package/dist/types/src/components/index.d.ts.map +1 -1
  71. package/dist/types/src/containers/ChannelArticle/ChannelArticle.d.ts +4 -9
  72. package/dist/types/src/containers/ChannelArticle/ChannelArticle.d.ts.map +1 -1
  73. package/dist/types/src/containers/ChannelArticle/ChannelArticle.stories.d.ts +4 -1
  74. package/dist/types/src/containers/ChannelArticle/ChannelArticle.stories.d.ts.map +1 -1
  75. package/dist/types/src/containers/ChannelCreatePanel/ChannelCreatePanel.d.ts +4 -8
  76. package/dist/types/src/containers/ChannelCreatePanel/ChannelCreatePanel.d.ts.map +1 -1
  77. package/dist/types/src/containers/ThreadArticle/ThreadArticle.d.ts +1 -3
  78. package/dist/types/src/containers/ThreadArticle/ThreadArticle.d.ts.map +1 -1
  79. package/dist/types/src/containers/ThreadArticle/ThreadArticle.stories.d.ts.map +1 -1
  80. package/dist/types/src/util.d.ts +14 -3
  81. package/dist/types/src/util.d.ts.map +1 -1
  82. package/dist/types/tsconfig.tsbuildinfo +1 -1
  83. package/dx.config.ts +2 -1
  84. package/package.json +54 -46
  85. package/src/ThreadPlugin.node.ts +1 -2
  86. package/src/ThreadPlugin.test.ts +5 -2
  87. package/src/ThreadPlugin.tsx +1 -10
  88. package/src/capabilities/app-graph-builder.ts +5 -3
  89. package/src/capabilities/index.ts +0 -1
  90. package/src/capabilities/node.ts +18 -0
  91. package/src/capabilities/{react-surface.tsx → react-surface.ts} +6 -14
  92. package/src/components/{Chat/Chat.tsx → MessageThread/MessageThread.tsx} +20 -17
  93. package/src/components/{Chat → MessageThread}/index.ts +1 -1
  94. package/src/components/index.ts +1 -1
  95. package/src/containers/ChannelArticle/ChannelArticle.stories.tsx +4 -1
  96. package/src/containers/ChannelArticle/ChannelArticle.tsx +6 -4
  97. package/src/containers/ChannelCreatePanel/ChannelCreatePanel.tsx +4 -3
  98. package/src/containers/ThreadArticle/ThreadArticle.stories.tsx +4 -2
  99. package/src/containers/ThreadArticle/ThreadArticle.tsx +30 -18
  100. package/src/paths.ts +3 -3
  101. package/src/util.ts +21 -7
  102. package/dist/lib/neutral/ChannelArticle-CTYSCRTR.mjs +0 -122
  103. package/dist/lib/neutral/ChannelArticle-CTYSCRTR.mjs.map +0 -7
  104. package/dist/lib/neutral/ChannelCreatePanel-NUXXKHZQ.mjs +0 -38
  105. package/dist/lib/neutral/ChannelCreatePanel-NUXXKHZQ.mjs.map +0 -7
  106. package/dist/lib/neutral/ThreadArticle-ROQXQLEZ.mjs +0 -57
  107. package/dist/lib/neutral/ThreadArticle-ROQXQLEZ.mjs.map +0 -7
  108. package/dist/lib/neutral/ThreadPlugin.mjs.map +0 -7
  109. package/dist/lib/neutral/ThreadPlugin.node.mjs +0 -29
  110. package/dist/lib/neutral/ThreadPlugin.node.mjs.map +0 -7
  111. package/dist/lib/neutral/ThreadPlugin.workerd.mjs +0 -27
  112. package/dist/lib/neutral/ThreadPlugin.workerd.mjs.map +0 -7
  113. package/dist/lib/neutral/app-graph-builder-NZOWDFE5.mjs +0 -65
  114. package/dist/lib/neutral/app-graph-builder-NZOWDFE5.mjs.map +0 -7
  115. package/dist/lib/neutral/append-channel-message-YIIJY6GX.mjs +0 -34
  116. package/dist/lib/neutral/append-channel-message-YIIJY6GX.mjs.map +0 -7
  117. package/dist/lib/neutral/capabilities/index.mjs +0 -19
  118. package/dist/lib/neutral/capabilities/index.mjs.map +0 -7
  119. package/dist/lib/neutral/channel-backend-feed-TOS55NID.mjs +0 -57
  120. package/dist/lib/neutral/channel-backend-feed-TOS55NID.mjs.map +0 -7
  121. package/dist/lib/neutral/chunk-5VTDNDBV.mjs +0 -109
  122. package/dist/lib/neutral/chunk-5VTDNDBV.mjs.map +0 -7
  123. package/dist/lib/neutral/chunk-A5JYVGL2.mjs.map +0 -7
  124. package/dist/lib/neutral/chunk-GM3SGQMJ.mjs +0 -69
  125. package/dist/lib/neutral/chunk-GM3SGQMJ.mjs.map +0 -7
  126. package/dist/lib/neutral/chunk-J5LGTIGS.mjs +0 -10
  127. package/dist/lib/neutral/chunk-J5LGTIGS.mjs.map +0 -7
  128. package/dist/lib/neutral/chunk-J7OTCRYF.mjs +0 -12
  129. package/dist/lib/neutral/chunk-J7OTCRYF.mjs.map +0 -7
  130. package/dist/lib/neutral/chunk-XPUQE4Y7.mjs +0 -8
  131. package/dist/lib/neutral/chunk-XPUQE4Y7.mjs.map +0 -7
  132. package/dist/lib/neutral/components/index.mjs +0 -96
  133. package/dist/lib/neutral/components/index.mjs.map +0 -7
  134. package/dist/lib/neutral/containers/index.mjs +0 -13
  135. package/dist/lib/neutral/containers/index.mjs.map +0 -7
  136. package/dist/lib/neutral/create-channel-4CA7P2M5.mjs +0 -41
  137. package/dist/lib/neutral/create-channel-4CA7P2M5.mjs.map +0 -7
  138. package/dist/lib/neutral/create-object-O3TZ2MCJ.mjs +0 -45
  139. package/dist/lib/neutral/create-object-O3TZ2MCJ.mjs.map +0 -7
  140. package/dist/lib/neutral/hooks/index.mjs +0 -11
  141. package/dist/lib/neutral/hooks/index.mjs.map +0 -7
  142. package/dist/lib/neutral/index.mjs +0 -34
  143. package/dist/lib/neutral/index.mjs.map +0 -7
  144. package/dist/lib/neutral/meta.json +0 -1
  145. package/dist/lib/neutral/meta.mjs +0 -10
  146. package/dist/lib/neutral/meta.mjs.map +0 -7
  147. package/dist/lib/neutral/navigation-resolver-LSTZL32O.mjs +0 -18
  148. package/dist/lib/neutral/navigation-resolver-LSTZL32O.mjs.map +0 -7
  149. package/dist/lib/neutral/operation-handler-RU6K2S4L.mjs +0 -13
  150. package/dist/lib/neutral/operation-handler-RU6K2S4L.mjs.map +0 -7
  151. package/dist/lib/neutral/operations/index.mjs +0 -8
  152. package/dist/lib/neutral/operations/index.mjs.map +0 -7
  153. package/dist/lib/neutral/plugin.mjs +0 -16
  154. package/dist/lib/neutral/plugin.mjs.map +0 -7
  155. package/dist/lib/neutral/react-surface-H2EKIMSK.mjs +0 -49
  156. package/dist/lib/neutral/react-surface-H2EKIMSK.mjs.map +0 -7
  157. package/dist/lib/neutral/translations.mjs +0 -91
  158. package/dist/lib/neutral/translations.mjs.map +0 -7
  159. package/dist/lib/neutral/types/index.mjs +0 -16
  160. package/dist/lib/neutral/types/index.mjs.map +0 -7
  161. package/dist/types/src/capabilities/navigation-resolver.d.ts +0 -5
  162. package/dist/types/src/capabilities/navigation-resolver.d.ts.map +0 -1
  163. package/dist/types/src/components/Chat/Chat.d.ts.map +0 -1
  164. package/dist/types/src/components/Chat/index.d.ts +0 -2
  165. package/dist/types/src/components/Chat/index.d.ts.map +0 -1
  166. package/src/capabilities/navigation-resolver.ts +0 -20
@@ -1,69 +1,29 @@
1
- import "./chunk-J5LGTIGS.mjs";
2
-
3
- // src/ThreadPlugin.tsx
4
1
  import { ActivationEvents, Plugin } from "@dxos/app-framework";
5
- import { AppPlugin } from "@dxos/app-toolkit";
6
- import { ClientEvents } from "@dxos/plugin-client";
7
- import { translations as threadTranslations } from "@dxos/react-ui-thread/translations";
8
- import { Channel, Message, Thread } from "@dxos/types";
9
- import { AppGraphBuilder, ChannelBackendFeed, CreateObject, NavigationResolver, OperationHandler, ReactSurface } from "#capabilities";
10
2
  import { meta } from "#meta";
11
- import { translations } from "#translations";
12
-
13
- // raw-loader:/__w/dxos/dxos/packages/plugins/plugin-thread/PLUGIN.mdl
14
- var PLUGIN_default = "---\nid: org.dxos.plugin.thread\nname: ThreadPlugin\nversion: 0.1.0\n---\n\nThreadPlugin provides chat: channels backed by an ECHO feed and free-standing message threads.\nIt renders the channel article + companion surfaces and a thread surface, and contributes the\noperations that create a channel and append messages. Shared message/thread UI comes from\n`@dxos/react-ui-thread`, and the `Channel`/`Message`/`Thread` schema comes from `@dxos/types`.\nDocument comments and the comment-thread AI agent live in `@dxos/plugin-comments`.\n\n## Extensions\n\nThe following extension dialects are used in this document.\n\n| Term | URI |\n|-------------|--------------------------------|\n| `type` | `org.dxos.mdl.type@1.0` |\n| `feat` | `org.dxos.mdl.feat@1.0` |\n| `op` | `org.dxos.mdl.op@1.0` |\n\n## Types\n\n```mdl\ntype Channel\n desc: |\n A chat channel. Defined in @dxos/types. Carries an optional `feed` Ref whose\n queue holds the channel's Message objects in order.\n```\n\n## Operations\n\n```mdl\nop OnCreateSpace\n key: org.dxos.plugin.thread.operation.onCreateSpace\n desc: On space creation, create a default \"General\" channel in the root collection.\n```\n\n```mdl\nop CreateChannel\n key: org.dxos.plugin.thread.operation.createChannel\n desc: Create a new Channel in the given space.\n in:\n spaceId: SpaceId\n name?: String\n out:\n object: Channel\n```\n\n```mdl\nop AppendChannelMessage\n key: org.dxos.plugin.thread.operation.appendChannelMessage\n desc: Append a Message authored by `sender` to the channel's feed.\n in:\n channel: Channel\n sender: Actor\n text: String\n```\n\n## Features\n\n```mdl\nfeat F-1: Channel chat\n req F-1.1: A Channel article MUST render its feed messages newest-last with a\n pinned composer; sending invokes AppendChannelMessage.\n req F-1.2: Externally-synced channels (those carrying foreign-key Obj.Meta) MUST\n render read-only \u2014 the composer is suppressed.\n```\n\n```mdl\nfeat F-2: Thread chat\n req F-2.1: A Thread article MUST render the thread's messages and append new\n messages by pushing onto `thread.messages`.\n```\n";
3
+ import { Channel, Message, Thread } from "@dxos/types";
4
+ import { AppPlugin } from "@dxos/app-toolkit";
5
+ import { translations } from "@dxos/react-ui-thread/translations";
6
+ import { AppGraphBuilder, ChannelBackendFeed, CreateObject, OperationHandler, ReactSurface } from "#capabilities";
7
+ import { translations as translations$1 } from "#translations";
8
+ //#region PLUGIN.mdl?raw
9
+ var PLUGIN_default = "---\nid: org.dxos.plugin.thread\nname: ThreadPlugin\nversion: 0.1.0\n---\n\nThreadPlugin provides chat: channels backed by an ECHO feed and free-standing message threads.\nIt renders the channel article + companion surfaces and a thread surface, and contributes the\noperations that create a channel and append messages. Shared message/thread UI comes from\n`@dxos/react-ui-thread`, and the `Channel`/`Message`/`Thread` schema comes from `@dxos/types`.\nDocument comments and the comment-thread AI agent live in `@dxos/plugin-comments`.\n\n## Extensions\n\nThe following extension dialects are used in this document.\n\n| Term | URI |\n|-------------|--------------------------------|\n| `type` | `org.dxos.mdl.type@1.0` |\n| `feat` | `org.dxos.mdl.feat@1.0` |\n| `op` | `org.dxos.mdl.op@1.0` |\n\n## Types\n\n```mdl\ntype Channel\n desc: |\n A chat channel. Defined in @dxos/types. Carries an optional `feed` Ref whose\n queue holds the channel's Message objects in order.\n```\n\n## Operations\n\n```mdl\nop OnCreateSpace\n key: org.dxos.plugin.thread.operation.onCreateSpace\n desc: On space creation, create a default \"General\" channel in the root collection.\n```\n\n```mdl\nop CreateChannel\n key: org.dxos.plugin.thread.operation.createChannel\n desc: Create a new Channel in the given space.\n in:\n spaceId: SpaceId\n name?: String\n out:\n object: Channel\n```\n\n```mdl\nop AppendChannelMessage\n key: org.dxos.plugin.thread.operation.appendChannelMessage\n desc: Append a Message authored by `sender` to the channel's feed.\n in:\n channel: Channel\n sender: Actor\n text: String\n```\n\n## Features\n\n```mdl\nfeat F-1: Channel chat\n req F-1.1: A Channel article MUST render its feed messages newest-last with a\n pinned composer; sending invokes AppendChannelMessage.\n req F-1.2: Externally-synced channels (those carrying foreign-key Obj.Meta) MUST\n render read-only — the composer is suppressed.\n```\n\n```mdl\nfeat F-2: Thread chat\n req F-2.1: A Thread article MUST render the thread's messages and append new\n messages by pushing onto `thread.messages`.\n```\n";
10
+ //#endregion
11
+ //#region src/ThreadPlugin.tsx
12
+ var ThreadPlugin = Plugin.define(meta).pipe(AppPlugin.addAppGraphModule({ activate: AppGraphBuilder }), AppPlugin.addCreateObjectModule({ activate: CreateObject }), AppPlugin.addOperationHandlerModule({ activate: OperationHandler }), AppPlugin.addSchemaModule({ schema: [
13
+ Channel.Channel,
14
+ Message.Message,
15
+ Thread.Thread
16
+ ] }), AppPlugin.addSurfaceModule({ activate: ReactSurface }), AppPlugin.addTranslationsModule({ translations: [...translations$1, ...translations] }), Plugin.addModule({
17
+ id: "channel-backend-feed",
18
+ activatesOn: ActivationEvents.Startup,
19
+ activate: ChannelBackendFeed
20
+ }), AppPlugin.addPluginAssetModule({ asset: {
21
+ pluginId: meta.profile.key,
22
+ path: "PLUGIN.mdl",
23
+ content: PLUGIN_default,
24
+ mimeType: "application/x-mdl"
25
+ } }), Plugin.make);
26
+ //#endregion
27
+ export { ThreadPlugin, ThreadPlugin as default };
15
28
 
16
- // src/ThreadPlugin.tsx
17
- var ThreadPlugin = Plugin.define(meta).pipe(
18
- AppPlugin.addAppGraphModule({
19
- activate: AppGraphBuilder
20
- }),
21
- AppPlugin.addNavigationResolverModule({
22
- activatesOn: ClientEvents.ClientReady,
23
- activate: NavigationResolver
24
- }),
25
- AppPlugin.addCreateObjectModule({
26
- activate: CreateObject
27
- }),
28
- AppPlugin.addOperationHandlerModule({
29
- activate: OperationHandler
30
- }),
31
- AppPlugin.addSchemaModule({
32
- schema: [
33
- Channel.Channel,
34
- Message.Message,
35
- Thread.Thread
36
- ]
37
- }),
38
- AppPlugin.addSurfaceModule({
39
- activate: ReactSurface
40
- }),
41
- AppPlugin.addTranslationsModule({
42
- translations: [
43
- ...translations,
44
- ...threadTranslations
45
- ]
46
- }),
47
- // Default local-feed channel backend. Other plugins contribute additional
48
- // `ChannelBackend` providers (e.g. ATProto) earlier in plugin order.
49
- Plugin.addModule({
50
- id: "channel-backend-feed",
51
- activatesOn: ActivationEvents.Startup,
52
- activate: ChannelBackendFeed
53
- }),
54
- AppPlugin.addPluginAssetModule({
55
- asset: {
56
- pluginId: meta.profile.key,
57
- path: "PLUGIN.mdl",
58
- content: PLUGIN_default,
59
- mimeType: "application/x-mdl"
60
- }
61
- }),
62
- Plugin.make
63
- );
64
- var ThreadPlugin_default = ThreadPlugin;
65
- export {
66
- ThreadPlugin,
67
- ThreadPlugin_default as default
68
- };
69
- //# sourceMappingURL=ThreadPlugin.mjs.map
29
+ //# sourceMappingURL=ThreadPlugin.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ThreadPlugin.mjs","names":[],"sources":["../../src/ThreadPlugin.tsx"],"sourcesContent":["//\n// Copyright 2023 DXOS.org\n//\n\nimport { ActivationEvents, Plugin } from '@dxos/app-framework';\nimport { AppPlugin } from '@dxos/app-toolkit';\nimport { translations as threadTranslations } from '@dxos/react-ui-thread/translations';\nimport { Channel, Message, Thread } from '@dxos/types';\n\nimport { AppGraphBuilder, ChannelBackendFeed, CreateObject, OperationHandler, ReactSurface } from '#capabilities';\nimport { meta } from '#meta';\nimport { translations } from '#translations';\n\n// eslint-disable-next-line import/no-relative-packages\nimport pluginSpec from '../PLUGIN.mdl?raw';\n\n// TODO(wittjosiah): Rename to ChatPlugin.\n\nexport const ThreadPlugin = Plugin.define(meta).pipe(\n AppPlugin.addAppGraphModule({ activate: AppGraphBuilder }),\n AppPlugin.addCreateObjectModule({ activate: CreateObject }),\n AppPlugin.addOperationHandlerModule({ activate: OperationHandler }),\n AppPlugin.addSchemaModule({\n schema: [Channel.Channel, Message.Message, Thread.Thread],\n }),\n AppPlugin.addSurfaceModule({ activate: ReactSurface }),\n AppPlugin.addTranslationsModule({ translations: [...translations, ...threadTranslations] }),\n // Default local-feed channel backend. Other plugins contribute additional\n // `ChannelBackend` providers (e.g. ATProto) earlier in plugin order.\n Plugin.addModule({\n id: 'channel-backend-feed',\n activatesOn: ActivationEvents.Startup,\n activate: ChannelBackendFeed,\n }),\n AppPlugin.addPluginAssetModule({\n asset: { pluginId: meta.profile.key, path: 'PLUGIN.mdl', content: pluginSpec, mimeType: 'application/x-mdl' },\n }),\n Plugin.make,\n);\n\nexport default ThreadPlugin;\n"],"mappings":";;;;;;;;;;;AAkBA,IAAa,eAAe,OAAO,OAAO,IAAI,CAAC,CAAC,KAC9C,UAAU,kBAAkB,EAAE,UAAU,gBAAgB,CAAC,GACzD,UAAU,sBAAsB,EAAE,UAAU,aAAa,CAAC,GAC1D,UAAU,0BAA0B,EAAE,UAAU,iBAAiB,CAAC,GAClE,UAAU,gBAAgB,EACxB,QAAQ;CAAC,QAAQ;CAAS,QAAQ;CAAS,OAAO;AAAM,EAC1D,CAAC,GACD,UAAU,iBAAiB,EAAE,UAAU,aAAa,CAAC,GACrD,UAAU,sBAAsB,EAAE,cAAc,CAAC,GAAG,gBAAc,GAAG,YAAkB,EAAE,CAAC,GAG1F,OAAO,UAAU;CACf,IAAI;CACJ,aAAa,iBAAiB;CAC9B,UAAU;AACZ,CAAC,GACD,UAAU,qBAAqB,EAC7B,OAAO;CAAE,UAAU,KAAK,QAAQ;CAAK,MAAM;CAAc,SAAS;CAAY,UAAU;AAAoB,EAC9G,CAAC,GACD,OAAO,IACT"}
@@ -0,0 +1,19 @@
1
+ import { ActivationEvents, Plugin } from "@dxos/app-framework";
2
+ import { meta } from "#meta";
3
+ import { Channel, Message, Thread } from "@dxos/types";
4
+ import { AppPlugin } from "@dxos/app-toolkit";
5
+ import { ChannelBackendFeed, OperationHandler } from "#capabilities";
6
+ //#region src/ThreadPlugin.node.ts
7
+ var ThreadPlugin = Plugin.define(meta).pipe(AppPlugin.addOperationHandlerModule({ activate: OperationHandler }), AppPlugin.addSchemaModule({ schema: [
8
+ Channel.Channel,
9
+ Message.Message,
10
+ Thread.Thread
11
+ ] }), Plugin.addModule({
12
+ id: "channel-backend-feed",
13
+ activatesOn: ActivationEvents.Startup,
14
+ activate: ChannelBackendFeed
15
+ }), Plugin.make);
16
+ //#endregion
17
+ export { ThreadPlugin, ThreadPlugin as default };
18
+
19
+ //# sourceMappingURL=ThreadPlugin.node.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ThreadPlugin.node.mjs","names":[],"sources":["../../src/ThreadPlugin.node.ts"],"sourcesContent":["//\n// Copyright 2023 DXOS.org\n//\n\nimport { ActivationEvents, Plugin } from '@dxos/app-framework';\nimport { AppPlugin } from '@dxos/app-toolkit';\nimport { Channel, Message, Thread } from '@dxos/types';\n\nimport { ChannelBackendFeed, OperationHandler } from '#capabilities';\nimport { meta } from '#meta';\n\nexport const ThreadPlugin = Plugin.define(meta).pipe(\n AppPlugin.addOperationHandlerModule({ activate: OperationHandler }),\n AppPlugin.addSchemaModule({\n schema: [Channel.Channel, Message.Message, Thread.Thread],\n }),\n Plugin.addModule({\n id: 'channel-backend-feed',\n activatesOn: ActivationEvents.Startup,\n activate: ChannelBackendFeed,\n }),\n Plugin.make,\n);\n\nexport default ThreadPlugin;\n"],"mappings":";;;;;;AAWA,IAAa,eAAe,OAAO,OAAO,IAAI,CAAC,CAAC,KAC9C,UAAU,0BAA0B,EAAE,UAAU,iBAAiB,CAAC,GAClE,UAAU,gBAAgB,EACxB,QAAQ;CAAC,QAAQ;CAAS,QAAQ;CAAS,OAAO;AAAM,EAC1D,CAAC,GACD,OAAO,UAAU;CACf,IAAI;CACJ,aAAa,iBAAiB;CAC9B,UAAU;AACZ,CAAC,GACD,OAAO,IACT"}
@@ -0,0 +1,19 @@
1
+ import { ActivationEvents, Plugin } from "@dxos/app-framework";
2
+ import { meta } from "#meta";
3
+ import { Channel, Message, Thread } from "@dxos/types";
4
+ import { AppPlugin } from "@dxos/app-toolkit";
5
+ import { ChannelBackendFeed, OperationHandler } from "#capabilities";
6
+ //#region src/ThreadPlugin.workerd.ts
7
+ var ThreadPlugin = Plugin.define(meta).pipe(AppPlugin.addOperationHandlerModule({ activate: OperationHandler }), AppPlugin.addSchemaModule({ schema: [
8
+ Channel.Channel,
9
+ Message.Message,
10
+ Thread.Thread
11
+ ] }), Plugin.addModule({
12
+ id: "channel-backend-feed",
13
+ activatesOn: ActivationEvents.Startup,
14
+ activate: ChannelBackendFeed
15
+ }), Plugin.make);
16
+ //#endregion
17
+ export { ThreadPlugin, ThreadPlugin as default };
18
+
19
+ //# sourceMappingURL=ThreadPlugin.workerd.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ThreadPlugin.workerd.mjs","names":[],"sources":["../../src/ThreadPlugin.workerd.ts"],"sourcesContent":["//\n// Copyright 2023 DXOS.org\n//\n\nimport { ActivationEvents, Plugin } from '@dxos/app-framework';\nimport { AppPlugin } from '@dxos/app-toolkit';\nimport { Channel, Message, Thread } from '@dxos/types';\n\nimport { ChannelBackendFeed, OperationHandler } from '#capabilities';\nimport { meta } from '#meta';\n\nexport const ThreadPlugin = Plugin.define(meta).pipe(\n AppPlugin.addOperationHandlerModule({ activate: OperationHandler }),\n AppPlugin.addSchemaModule({\n schema: [Channel.Channel, Message.Message, Thread.Thread],\n }),\n Plugin.addModule({\n id: 'channel-backend-feed',\n activatesOn: ActivationEvents.Startup,\n activate: ChannelBackendFeed,\n }),\n Plugin.make,\n);\n\nexport default ThreadPlugin;\n"],"mappings":";;;;;;AAWA,IAAa,eAAe,OAAO,OAAO,IAAI,CAAC,CAAC,KAC9C,UAAU,0BAA0B,EAAE,UAAU,iBAAiB,CAAC,GAClE,UAAU,gBAAgB,EACxB,QAAQ;CAAC,QAAQ;CAAS,QAAQ;CAAS,OAAO;AAAM,EAC1D,CAAC,GACD,OAAO,UAAU;CACf,IAAI;CACJ,aAAa,iBAAiB;CAC9B,UAAU;AACZ,CAAC,GACD,OAAO,IACT"}
@@ -0,0 +1,8 @@
1
+ import { Capability } from "@dxos/app-framework";
2
+ //#region src/capabilities/node.ts
3
+ var ChannelBackendFeed = Capability.lazy("ChannelBackendFeed", () => import("../chunk-channel-backend-feed.mjs"));
4
+ var OperationHandler = Capability.lazy("OperationHandler", () => import("../chunk-operation-handler.mjs"));
5
+ //#endregion
6
+ export { ChannelBackendFeed, OperationHandler };
7
+
8
+ //# sourceMappingURL=node.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node.mjs","names":[],"sources":["../../../src/capabilities/node.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport { Capability } from '@dxos/app-framework';\nimport type { OperationHandlerSet } from '@dxos/compute';\n\n// The capabilities `ThreadPlugin.node` activates, and only those. `Capability.lazy` defers the\n// import at runtime but a bundler still walks it, so listing the React surfaces here would pull\n// the plugin's components into every node and bun build. `CreateObject` is omitted: its\n// `CreateObjectEntry` carries a `customPanel` React component alongside the object factory.\n// TODO(wittjosiah): Split the panel out of the entry so node can contribute the factory.\n\nexport const ChannelBackendFeed = Capability.lazy('ChannelBackendFeed', () => import('./channel-backend-feed'));\nexport const OperationHandler = Capability.lazy<OperationHandlerSet.OperationHandlerSet>(\n 'OperationHandler',\n () => import('./operation-handler'),\n);\n"],"mappings":";;AAaA,IAAa,qBAAqB,WAAW,KAAK,4BAA4B,OAAO,oCAAyB;AAC9G,IAAa,mBAAmB,WAAW,KACzC,0BACM,OAAO,iCACf"}
@@ -0,0 +1,11 @@
1
+ import { Capability } from "@dxos/app-framework";
2
+ //#region src/capabilities/index.ts
3
+ var AppGraphBuilder = Capability.lazy("AppGraphBuilder", () => import("./chunk-app-graph-builder.mjs"));
4
+ var ChannelBackendFeed = Capability.lazy("ChannelBackendFeed", () => import("./chunk-channel-backend-feed.mjs"));
5
+ var CreateObject = Capability.lazy("CreateObject", () => import("./chunk-create-object.mjs"));
6
+ var OperationHandler = Capability.lazy("OperationHandler", () => import("./chunk-operation-handler.mjs"));
7
+ var ReactSurface = Capability.lazy("ReactSurface", () => import("./chunk-react-surface.mjs"));
8
+ //#endregion
9
+ export { AppGraphBuilder, ChannelBackendFeed, CreateObject, OperationHandler, ReactSurface };
10
+
11
+ //# sourceMappingURL=capabilities.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capabilities.mjs","names":[],"sources":["../../src/capabilities/index.ts"],"sourcesContent":["//\n// Copyright 2025 DXOS.org\n//\n\nimport { Capability } from '@dxos/app-framework';\nimport type { OperationHandlerSet } from '@dxos/compute';\n\nexport const AppGraphBuilder = Capability.lazy('AppGraphBuilder', () => import('./app-graph-builder'));\nexport const ChannelBackendFeed = Capability.lazy('ChannelBackendFeed', () => import('./channel-backend-feed'));\nexport const CreateObject = Capability.lazy('CreateObject', () => import('./create-object'));\nexport const OperationHandler = Capability.lazy<OperationHandlerSet.OperationHandlerSet>(\n 'OperationHandler',\n () => import('./operation-handler'),\n);\nexport const ReactSurface = Capability.lazy('ReactSurface', () => import('./react-surface'));\n"],"mappings":";;AAOA,IAAa,kBAAkB,WAAW,KAAK,yBAAyB,OAAO,gCAAsB;AACrG,IAAa,qBAAqB,WAAW,KAAK,4BAA4B,OAAO,mCAAyB;AAC9G,IAAa,eAAe,WAAW,KAAK,sBAAsB,OAAO,4BAAkB;AAC3F,IAAa,mBAAmB,WAAW,KACzC,0BACM,OAAO,gCACf;AACA,IAAa,eAAe,WAAW,KAAK,sBAAsB,OAAO,4BAAkB"}
@@ -0,0 +1,104 @@
1
+ import { useCallback } from "react";
2
+ import { Surface, useCapabilities, useOperationInvoker } from "@dxos/app-framework/ui";
3
+ import { meta } from "#meta";
4
+ import { Obj } from "@dxos/echo";
5
+ import { AppSurface } from "@dxos/app-toolkit/ui";
6
+ import { Panel } from "@dxos/react-ui";
7
+ import { jsx, jsxs } from "react/jsx-runtime";
8
+ import { CallsCapabilities } from "@dxos/plugin-calls/types";
9
+ import { Atom, useAtomValue } from "@effect-atom/atom-react";
10
+ import { useIdentity, useMembers } from "@dxos/halo-react";
11
+ import { getSpace } from "@dxos/react-client/echo";
12
+ import { Menu, MenuBuilder, useMenuBuilder } from "@dxos/react-ui-menu";
13
+ import { MessageThread } from "#components";
14
+ import { useMessages, useStatus } from "#hooks";
15
+ import { ThreadCapabilities, ThreadOperation, resolveProvider } from "#types";
16
+ //#region src/containers/ChannelArticle/ChannelArticle.tsx
17
+ var NOT_JOINED = Atom.make(false);
18
+ var NO_ROOM = Atom.make(void 0);
19
+ /**
20
+ * Channel article: renders the channel chat inside a document panel. Messages
21
+ * are read and written through the channel's backend provider (resolved by
22
+ * `channel.backend.kind`), so the container is agnostic to where messages are
23
+ * stored. Read-only state defaults to the provider's policy, or to "channel
24
+ * carries foreign-key `Obj.Meta`" when the provider has none. When plugin-calls is present, a
25
+ * "Start video call" action switches the article to the call surface and the chat moves to a companion.
26
+ */
27
+ var ChannelArticle = ({ role, subject: channel, attendableId, chatOnly }) => {
28
+ const identity = useIdentity();
29
+ const space = channel ? getSpace(channel) : void 0;
30
+ const members = useMembers(space?.id);
31
+ const id = channel ? Obj.getURI(channel) : void 0;
32
+ const activity = useStatus(space, id);
33
+ const { invokePromise } = useOperationInvoker();
34
+ const providers = useCapabilities(ThreadCapabilities.ChannelBackend);
35
+ const provider = channel ? resolveProvider(providers, channel.backend.kind) : void 0;
36
+ const messages = useMessages(channel);
37
+ const readOnly = channel ? provider?.readOnly?.(channel) ?? Obj.getMeta(channel).keys.length > 0 : false;
38
+ const callProvider = useCapabilities(CallsCapabilities.CallTransportProvider)[0];
39
+ const callManager = useCapabilities(CallsCapabilities.Manager)[0];
40
+ const joined = useAtomValue(callManager?.joinedAtom ?? NOT_JOINED);
41
+ const currentRoomId = useAtomValue(callManager?.roomIdAtom ?? NO_ROOM);
42
+ const inThisCall = !!id && joined && currentRoomId === id;
43
+ const showCall = inThisCall && !chatOnly;
44
+ const canStartCall = !!callProvider && !inThisCall;
45
+ const handleStartCall = useCallback(async () => {
46
+ if (!callProvider || !id) return;
47
+ await callProvider.join(id);
48
+ }, [callProvider, id]);
49
+ const menuActions = useMenuBuilder(() => {
50
+ const builder = MenuBuilder.make().root({ label: ["channel-toolbar.title", { ns: meta.profile.key }] });
51
+ if (canStartCall) builder.action("start-video-call", {
52
+ label: ["start-video-call.menu", { ns: meta.profile.key }],
53
+ icon: "ph--video-camera--regular"
54
+ }, () => {
55
+ handleStartCall();
56
+ });
57
+ return builder.build();
58
+ }, [canStartCall, handleStartCall]);
59
+ const handleSend = (text) => {
60
+ if (!channel || !identity || readOnly) return false;
61
+ invokePromise(ThreadOperation.AppendChannelMessage, {
62
+ channel,
63
+ sender: { identityDid: identity.did },
64
+ text
65
+ });
66
+ return true;
67
+ };
68
+ if (!space || !channel || !id) return null;
69
+ return /* @__PURE__ */ jsxs(Panel.Root, {
70
+ role,
71
+ children: [canStartCall && /* @__PURE__ */ jsx(Menu.Root, {
72
+ ...menuActions,
73
+ attendableId,
74
+ children: /* @__PURE__ */ jsx(Panel.Toolbar, {
75
+ asChild: true,
76
+ children: /* @__PURE__ */ jsx(Menu.Toolbar, {})
77
+ })
78
+ }), showCall ? /* @__PURE__ */ jsx(Panel.Content, { children: /* @__PURE__ */ jsx(Surface.Surface, {
79
+ type: AppSurface.Article,
80
+ data: {
81
+ subject: { roomId: id },
82
+ attendableId
83
+ },
84
+ limit: 1
85
+ }) }) : /* @__PURE__ */ jsx(Panel.Content, {
86
+ asChild: true,
87
+ children: /* @__PURE__ */ jsx(MessageThread, {
88
+ id,
89
+ classNames: "dx-document",
90
+ identity: identity ?? void 0,
91
+ members,
92
+ messages,
93
+ activity,
94
+ onSend: handleSend,
95
+ readOnly
96
+ })
97
+ })]
98
+ });
99
+ };
100
+ ChannelArticle.displayName = "ChannelArticle";
101
+ //#endregion
102
+ export { ChannelArticle as default };
103
+
104
+ //# sourceMappingURL=chunk-ChannelArticle.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk-ChannelArticle.mjs","names":[],"sources":["../../src/containers/ChannelArticle/ChannelArticle.tsx"],"sourcesContent":["//\n// Copyright 2025 DXOS.org\n//\n\nimport { Atom, useAtomValue } from '@effect-atom/atom-react';\nimport React, { useCallback } from 'react';\n\nimport { Surface, useCapabilities, useOperationInvoker } from '@dxos/app-framework/ui';\nimport { AppSurface } from '@dxos/app-toolkit/ui';\nimport { Obj } from '@dxos/echo';\nimport { useIdentity, useMembers } from '@dxos/halo-react';\nimport { CallsCapabilities } from '@dxos/plugin-calls/types';\nimport { getSpace } from '@dxos/react-client/echo';\nimport { Panel } from '@dxos/react-ui';\nimport { Menu, MenuBuilder, useMenuBuilder } from '@dxos/react-ui-menu';\nimport { type Channel } from '@dxos/types';\n\nimport { MessageThread } from '#components';\nimport { useMessages, useStatus } from '#hooks';\nimport { meta } from '#meta';\nimport { ThreadCapabilities, ThreadOperation, resolveProvider } from '#types';\n\n// Stable fallbacks so `useAtomValue` always receives an atom when plugin-calls isn't present.\nconst NOT_JOINED = Atom.make(false);\nconst NO_ROOM = Atom.make<string | undefined>(undefined);\n\nexport type ChannelArticleProps = AppSurface.ObjectArticleProps<\n Channel.Channel | undefined,\n {\n roomId?: string;\n fullscreen?: boolean;\n /** Always render the chat, even while in this channel's call (used by the in-call chat companion). */\n chatOnly?: boolean;\n }\n>;\n\n/**\n * Channel article: renders the channel chat inside a document panel. Messages\n * are read and written through the channel's backend provider (resolved by\n * `channel.backend.kind`), so the container is agnostic to where messages are\n * stored. Read-only state defaults to the provider's policy, or to \"channel\n * carries foreign-key `Obj.Meta`\" when the provider has none. When plugin-calls is present, a\n * \"Start video call\" action switches the article to the call surface and the chat moves to a companion.\n */\nexport const ChannelArticle = ({ role, subject: channel, attendableId, chatOnly }: ChannelArticleProps) => {\n const identity = useIdentity();\n const space = channel ? getSpace(channel) : undefined;\n const members = useMembers(space?.id);\n const id = channel ? Obj.getURI(channel) : undefined;\n const activity = useStatus(space, id);\n const { invokePromise } = useOperationInvoker();\n\n const providers = useCapabilities(ThreadCapabilities.ChannelBackend);\n const provider = channel ? resolveProvider(providers, channel.backend.kind) : undefined;\n const messages = useMessages(channel);\n const readOnly = channel ? (provider?.readOnly?.(channel) ?? Obj.getMeta(channel).keys.length > 0) : false;\n\n const callProvider = useCapabilities(CallsCapabilities.CallTransportProvider)[0];\n const callManager = useCapabilities(CallsCapabilities.Manager)[0];\n const joined = useAtomValue(callManager?.joinedAtom ?? NOT_JOINED);\n const currentRoomId = useAtomValue(callManager?.roomIdAtom ?? NO_ROOM);\n // `chatOnly` (the in-call chat companion) keeps showing messages so the call lives only in the primary.\n const inThisCall = !!id && joined && currentRoomId === id;\n const showCall = inThisCall && !chatOnly;\n const canStartCall = !!callProvider && !inThisCall;\n\n const handleStartCall = useCallback(async () => {\n if (!callProvider || !id) {\n return;\n }\n await callProvider.join(id);\n }, [callProvider, id]);\n\n const menuActions = useMenuBuilder(() => {\n const builder = MenuBuilder.make().root({ label: ['channel-toolbar.title', { ns: meta.profile.key }] });\n if (canStartCall) {\n builder.action(\n 'start-video-call',\n { label: ['start-video-call.menu', { ns: meta.profile.key }], icon: 'ph--video-camera--regular' },\n () => {\n void handleStartCall();\n },\n );\n }\n return builder.build();\n }, [canStartCall, handleStartCall]);\n\n const handleSend = (text: string) => {\n if (!channel || !identity || readOnly) {\n return false;\n }\n\n void invokePromise(ThreadOperation.AppendChannelMessage, {\n channel,\n sender: { identityDid: identity.did },\n text,\n });\n\n return true;\n };\n\n if (!space || !channel || !id) {\n return null;\n }\n\n return (\n <Panel.Root role={role}>\n {canStartCall && (\n <Menu.Root {...menuActions} attendableId={attendableId}>\n <Panel.Toolbar asChild>\n <Menu.Toolbar />\n </Panel.Toolbar>\n </Menu.Root>\n )}\n {showCall ? (\n <Panel.Content>\n <Surface.Surface type={AppSurface.Article} data={{ subject: { roomId: id }, attendableId }} limit={1} />\n </Panel.Content>\n ) : (\n <Panel.Content asChild>\n <MessageThread\n id={id}\n classNames='dx-document'\n identity={identity ?? undefined}\n members={members}\n messages={messages}\n activity={activity}\n onSend={handleSend}\n readOnly={readOnly}\n />\n </Panel.Content>\n )}\n </Panel.Root>\n );\n};\n\nChannelArticle.displayName = 'ChannelArticle';\n"],"mappings":";;;;;;;;;;;;;;;;AAuBA,IAAM,aAAa,KAAK,KAAK,KAAK;AAClC,IAAM,UAAU,KAAK,KAAyB,KAAA,CAAS;;;;;;;;;AAoBvD,IAAa,kBAAkB,EAAE,MAAM,SAAS,SAAS,cAAc,eAAoC;CACzG,MAAM,WAAW,YAAY;CAC7B,MAAM,QAAQ,UAAU,SAAS,OAAO,IAAI,KAAA;CAC5C,MAAM,UAAU,WAAW,OAAO,EAAE;CACpC,MAAM,KAAK,UAAU,IAAI,OAAO,OAAO,IAAI,KAAA;CAC3C,MAAM,WAAW,UAAU,OAAO,EAAE;CACpC,MAAM,EAAE,kBAAkB,oBAAoB;CAE9C,MAAM,YAAY,gBAAgB,mBAAmB,cAAc;CACnE,MAAM,WAAW,UAAU,gBAAgB,WAAW,QAAQ,QAAQ,IAAI,IAAI,KAAA;CAC9E,MAAM,WAAW,YAAY,OAAO;CACpC,MAAM,WAAW,UAAW,UAAU,WAAW,OAAO,KAAK,IAAI,QAAQ,OAAO,CAAC,CAAC,KAAK,SAAS,IAAK;CAErG,MAAM,eAAe,gBAAgB,kBAAkB,qBAAqB,CAAC,CAAC;CAC9E,MAAM,cAAc,gBAAgB,kBAAkB,OAAO,CAAC,CAAC;CAC/D,MAAM,SAAS,aAAa,aAAa,cAAc,UAAU;CACjE,MAAM,gBAAgB,aAAa,aAAa,cAAc,OAAO;CAErE,MAAM,aAAa,CAAC,CAAC,MAAM,UAAU,kBAAkB;CACvD,MAAM,WAAW,cAAc,CAAC;CAChC,MAAM,eAAe,CAAC,CAAC,gBAAgB,CAAC;CAExC,MAAM,kBAAkB,YAAY,YAAY;EAC9C,IAAI,CAAC,gBAAgB,CAAC,IACpB;EAEF,MAAM,aAAa,KAAK,EAAE;CAC5B,GAAG,CAAC,cAAc,EAAE,CAAC;CAErB,MAAM,cAAc,qBAAqB;EACvC,MAAM,UAAU,YAAY,KAAK,CAAC,CAAC,KAAK,EAAE,OAAO,CAAC,yBAAyB,EAAE,IAAI,KAAK,QAAQ,IAAI,CAAC,EAAE,CAAC;EACtG,IAAI,cACF,QAAQ,OACN,oBACA;GAAE,OAAO,CAAC,yBAAyB,EAAE,IAAI,KAAK,QAAQ,IAAI,CAAC;GAAG,MAAM;EAA4B,SAC1F;GACJ,gBAAqB;EACvB,CACF;EAEF,OAAO,QAAQ,MAAM;CACvB,GAAG,CAAC,cAAc,eAAe,CAAC;CAElC,MAAM,cAAc,SAAiB;EACnC,IAAI,CAAC,WAAW,CAAC,YAAY,UAC3B,OAAO;EAGT,cAAmB,gBAAgB,sBAAsB;GACvD;GACA,QAAQ,EAAE,aAAa,SAAS,IAAI;GACpC;EACF,CAAC;EAED,OAAO;CACT;CAEA,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,IACzB,OAAO;CAGT,OACE,qBAAC,MAAM,MAAP;EAAkB;YAAlB,CACG,gBACC,oBAAC,KAAK,MAAN;GAAW,GAAI;GAA2B;aACxC,oBAAC,MAAM,SAAP;IAAe,SAAA;cACb,oBAAC,KAAK,SAAN,CAAe,CAAA;GACF,CAAA;EACN,CAAA,GAEZ,WACC,oBAAC,MAAM,SAAP,EAAA,UACE,oBAAC,QAAQ,SAAT;GAAiB,MAAM,WAAW;GAAS,MAAM;IAAE,SAAS,EAAE,QAAQ,GAAG;IAAG;GAAa;GAAG,OAAO;EAAI,CAAA,EAC1F,CAAA,IAEf,oBAAC,MAAM,SAAP;GAAe,SAAA;aACb,oBAAC,eAAD;IACM;IACJ,YAAW;IACX,UAAU,YAAY,KAAA;IACb;IACC;IACA;IACV,QAAQ;IACE;GACX,CAAA;EACY,CAAA,CAEP;;AAEhB;AAEA,eAAe,cAAc"}
@@ -0,0 +1,41 @@
1
+ import { useCallback, useMemo } from "react";
2
+ import { useCapabilities } from "@dxos/app-framework/ui";
3
+ import { Obj } from "@dxos/echo";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ import { ThreadCapabilities, buildChannelFormSchema } from "#types";
6
+ import { Form } from "@dxos/react-ui-form";
7
+ //#region src/containers/ChannelCreatePanel/ChannelCreatePanel.tsx
8
+ /**
9
+ * Provider-driven create panel for channels. Reads the registered
10
+ * `ChannelBackend` providers and renders a react-ui-form whose schema is the
11
+ * assembled `{ name?, backend: Union(...) }` — a backend selector plus the
12
+ * selected provider's create fields (just a name field when there is a single
13
+ * field-less provider).
14
+ */
15
+ var ChannelCreatePanel = ({ target, onCreateObject }) => {
16
+ const providers = useCapabilities(ThreadCapabilities.ChannelBackend);
17
+ const schema = useMemo(() => buildChannelFormSchema(providers), [providers]);
18
+ const handleSave = useCallback((values) => {
19
+ const { name, backend } = values;
20
+ const { kind, ...options } = backend ?? {};
21
+ onCreateObject({
22
+ name,
23
+ kind,
24
+ options
25
+ });
26
+ }, [onCreateObject]);
27
+ return /* @__PURE__ */ jsx(Form.Root, {
28
+ autoFocus: true,
29
+ db: Obj.isObject(target) ? Obj.getDatabase(target) : target,
30
+ schema,
31
+ defaultValues: {},
32
+ onSave: handleSave,
33
+ testId: "create-channel-form",
34
+ children: /* @__PURE__ */ jsx(Form.Viewport, { children: /* @__PURE__ */ jsxs(Form.Content, { children: [/* @__PURE__ */ jsx(Form.FieldSet, {}), /* @__PURE__ */ jsx(Form.Submit, {})] }) })
35
+ });
36
+ };
37
+ ChannelCreatePanel.displayName = "ChannelCreatePanel";
38
+ //#endregion
39
+ export { ChannelCreatePanel as default };
40
+
41
+ //# sourceMappingURL=chunk-ChannelCreatePanel.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk-ChannelCreatePanel.mjs","names":[],"sources":["../../src/containers/ChannelCreatePanel/ChannelCreatePanel.tsx"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport React, { useCallback, useMemo } from 'react';\n\nimport { useCapabilities } from '@dxos/app-framework/ui';\nimport { Obj } from '@dxos/echo';\nimport { type SpaceCapabilities } from '@dxos/plugin-space';\nimport { Form } from '@dxos/react-ui-form';\n\nimport { ThreadCapabilities, buildChannelFormSchema } from '#types';\n\n/**\n * Provider-driven create panel for channels. Reads the registered\n * `ChannelBackend` providers and renders a react-ui-form whose schema is the\n * assembled `{ name?, backend: Union(...) }` — a backend selector plus the\n * selected provider's create fields (just a name field when there is a single\n * field-less provider).\n */\nexport const ChannelCreatePanel = ({ target, onCreateObject }: SpaceCapabilities.CreateObjectCustomPanelProps) => {\n const providers = useCapabilities(ThreadCapabilities.ChannelBackend);\n const schema = useMemo(() => buildChannelFormSchema(providers), [providers]);\n\n const handleSave = useCallback(\n (values: { name?: string; backend?: { kind: string } & Record<string, unknown> }) => {\n const { name, backend } = values;\n const { kind, ...options } = backend ?? {};\n void onCreateObject({ name, kind, options });\n },\n [onCreateObject],\n );\n\n return (\n <Form.Root\n autoFocus\n db={Obj.isObject(target) ? Obj.getDatabase(target) : target}\n schema={schema}\n defaultValues={{}}\n onSave={handleSave}\n testId='create-channel-form'\n >\n <Form.Viewport>\n <Form.Content>\n <Form.FieldSet />\n <Form.Submit />\n </Form.Content>\n </Form.Viewport>\n </Form.Root>\n );\n};\n\nChannelCreatePanel.displayName = 'ChannelCreatePanel';\n"],"mappings":";;;;;;;;;;;;;;AAoBA,IAAa,sBAAsB,EAAE,QAAQ,qBAAqE;CAChH,MAAM,YAAY,gBAAgB,mBAAmB,cAAc;CACnE,MAAM,SAAS,cAAc,uBAAuB,SAAS,GAAG,CAAC,SAAS,CAAC;CAE3E,MAAM,aAAa,aAChB,WAAoF;EACnF,MAAM,EAAE,MAAM,YAAY;EAC1B,MAAM,EAAE,MAAM,GAAG,YAAY,WAAW,CAAC;EACzC,eAAoB;GAAE;GAAM;GAAM;EAAQ,CAAC;CAC7C,GACA,CAAC,cAAc,CACjB;CAEA,OACE,oBAAC,KAAK,MAAN;EACE,WAAA;EACA,IAAI,IAAI,SAAS,MAAM,IAAI,IAAI,YAAY,MAAM,IAAI;EAC7C;EACR,eAAe,CAAC;EAChB,QAAQ;EACR,QAAO;YAEP,oBAAC,KAAK,UAAN,EAAA,UACE,qBAAC,KAAK,SAAN,EAAA,UAAA,CACE,oBAAC,KAAK,UAAN,CAAgB,CAAA,GAChB,oBAAC,KAAK,QAAN,CAAc,CAAA,CACF,EAAA,CAAA,EACD,CAAA;CACN,CAAA;AAEf;AAEA,mBAAmB,cAAc"}
@@ -0,0 +1,58 @@
1
+ import { useMemo } from "react";
2
+ import { Obj, Ref } from "@dxos/echo";
3
+ import { Message } from "@dxos/types";
4
+ import { isNonNullable } from "@dxos/util";
5
+ import { Panel, composable, composableProps } from "@dxos/react-ui";
6
+ import { jsx, jsxs } from "react/jsx-runtime";
7
+ import { useIdentity, useMembers } from "@dxos/halo-react";
8
+ import { getSpace } from "@dxos/react-client/echo";
9
+ import { MessageThread } from "#components";
10
+ import { useStatus } from "#hooks";
11
+ //#region src/containers/ThreadArticle/ThreadArticle.tsx
12
+ /**
13
+ * Renders an AutoMerge {@link Thread} as a chat: appends new messages by pushing
14
+ * onto `thread.messages`. Used for comment threads and the meeting in-call chat.
15
+ */
16
+ var ThreadArticle = composable(({ thread, context, autoFocus, current, ...props }, forwardedRef) => {
17
+ const space = getSpace(thread);
18
+ const id = Obj.getURI(thread);
19
+ const identity = useIdentity();
20
+ const members = useMembers(space?.id);
21
+ const activity = useStatus(space, id);
22
+ const messages = useMemo(() => thread.messages.map((message) => message.target).filter(isNonNullable), [thread.messages]);
23
+ const handleSend = (text) => {
24
+ Obj.update(thread, (thread) => {
25
+ thread.messages.push(Ref.make(Obj.make(Message.Message, {
26
+ created: (/* @__PURE__ */ new Date()).toISOString(),
27
+ sender: { identityDid: identity.did },
28
+ blocks: [{
29
+ _tag: "text",
30
+ text
31
+ }],
32
+ properties: context ? { context: Ref.make(context) } : void 0
33
+ })));
34
+ });
35
+ return true;
36
+ };
37
+ if (!space) return null;
38
+ return /* @__PURE__ */ jsxs(Panel.Root, { children: [/* @__PURE__ */ jsx(Panel.Toolbar, {}), /* @__PURE__ */ jsx(Panel.Content, {
39
+ asChild: true,
40
+ children: /* @__PURE__ */ jsx(MessageThread, {
41
+ ...composableProps(props),
42
+ id,
43
+ identity,
44
+ members,
45
+ messages,
46
+ activity,
47
+ onSend: handleSend,
48
+ autoFocus,
49
+ current,
50
+ ref: forwardedRef
51
+ })
52
+ })] });
53
+ });
54
+ ThreadArticle.displayName = "ThreadArticle";
55
+ //#endregion
56
+ export { ThreadArticle as default };
57
+
58
+ //# sourceMappingURL=chunk-ThreadArticle.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk-ThreadArticle.mjs","names":[],"sources":["../../src/containers/ThreadArticle/ThreadArticle.tsx"],"sourcesContent":["//\n// Copyright 2023 DXOS.org\n//\n\nimport React, { useMemo } from 'react';\n\nimport { Obj, Ref } from '@dxos/echo';\nimport { useIdentity, useMembers } from '@dxos/halo-react';\nimport { getSpace } from '@dxos/react-client/echo';\nimport { Panel, type ThemedClassName } from '@dxos/react-ui';\nimport { composable, composableProps } from '@dxos/react-ui';\nimport { type ThreadContentProps } from '@dxos/react-ui-thread';\nimport { Message, type Thread } from '@dxos/types';\nimport { isNonNullable } from '@dxos/util';\n\nimport { MessageThread } from '#components';\nimport { useStatus } from '#hooks';\n\nexport type ThreadArticleProps = ThemedClassName<\n {\n thread: Thread.Thread;\n context?: Obj.Unknown;\n autoFocus?: boolean;\n } & Pick<ThreadContentProps, 'current'>\n>;\n\n/**\n * Renders an AutoMerge {@link Thread} as a chat: appends new messages by pushing\n * onto `thread.messages`. Used for comment threads and the meeting in-call chat.\n */\nexport const ThreadArticle = composable<HTMLDivElement, ThreadArticleProps>(\n ({ thread, context, autoFocus, current, ...props }, forwardedRef) => {\n // Members and presence are space-scoped; a thread outside a space has nothing to resolve against.\n const space = getSpace(thread);\n const id = Obj.getURI(thread);\n const identity = useIdentity()!;\n const members = useMembers(space?.id);\n const activity = useStatus(space, id);\n\n const messages = useMemo(\n () => thread.messages.map((message) => message.target).filter(isNonNullable),\n [thread.messages],\n );\n\n const handleSend = (text: string) => {\n Obj.update(thread, (thread) => {\n thread.messages.push(\n Ref.make(\n Obj.make(Message.Message, {\n created: new Date().toISOString(),\n sender: { identityDid: identity.did },\n blocks: [{ _tag: 'text', text }],\n properties: context ? { context: Ref.make(context) } : undefined,\n }),\n ),\n );\n });\n return true;\n };\n\n if (!space) {\n return null;\n }\n\n return (\n <Panel.Root>\n <Panel.Toolbar></Panel.Toolbar>\n <Panel.Content asChild>\n <MessageThread\n {...composableProps(props)}\n id={id}\n identity={identity}\n members={members}\n messages={messages}\n activity={activity}\n onSend={handleSend}\n autoFocus={autoFocus}\n current={current}\n ref={forwardedRef}\n />\n </Panel.Content>\n </Panel.Root>\n );\n },\n);\n\nThreadArticle.displayName = 'ThreadArticle';\n"],"mappings":";;;;;;;;;;;;;;;AA8BA,IAAa,gBAAgB,YAC1B,EAAE,QAAQ,SAAS,WAAW,SAAS,GAAG,SAAS,iBAAiB;CAEnE,MAAM,QAAQ,SAAS,MAAM;CAC7B,MAAM,KAAK,IAAI,OAAO,MAAM;CAC5B,MAAM,WAAW,YAAY;CAC7B,MAAM,UAAU,WAAW,OAAO,EAAE;CACpC,MAAM,WAAW,UAAU,OAAO,EAAE;CAEpC,MAAM,WAAW,cACT,OAAO,SAAS,KAAK,YAAY,QAAQ,MAAM,CAAC,CAAC,OAAO,aAAa,GAC3E,CAAC,OAAO,QAAQ,CAClB;CAEA,MAAM,cAAc,SAAiB;EACnC,IAAI,OAAO,SAAS,WAAW;GAC7B,OAAO,SAAS,KACd,IAAI,KACF,IAAI,KAAK,QAAQ,SAAS;IACxB,0BAAS,IAAI,KAAK,EAAA,CAAE,YAAY;IAChC,QAAQ,EAAE,aAAa,SAAS,IAAI;IACpC,QAAQ,CAAC;KAAE,MAAM;KAAQ;IAAK,CAAC;IAC/B,YAAY,UAAU,EAAE,SAAS,IAAI,KAAK,OAAO,EAAE,IAAI,KAAA;GACzD,CAAC,CACH,CACF;EACF,CAAC;EACD,OAAO;CACT;CAEA,IAAI,CAAC,OACH,OAAO;CAGT,OACE,qBAAC,MAAM,MAAP,EAAA,UAAA,CACE,oBAAC,MAAM,SAAP,CAA8B,CAAA,GAC9B,oBAAC,MAAM,SAAP;EAAe,SAAA;YACb,oBAAC,eAAD;GACE,GAAI,gBAAgB,KAAK;GACrB;GACM;GACD;GACC;GACA;GACV,QAAQ;GACG;GACF;GACT,KAAK;EACN,CAAA;CACY,CAAA,CACL,EAAA,CAAA;AAEhB,CACF;AAEA,cAAc,cAAc"}
@@ -0,0 +1,49 @@
1
+ import { n as getChannelsPath } from "./chunk-paths.mjs";
2
+ import { Capability } from "@dxos/app-framework";
3
+ import { meta } from "#meta";
4
+ import { Operation } from "@dxos/compute";
5
+ import { Obj, Type } from "@dxos/echo";
6
+ import { Channel } from "@dxos/types";
7
+ import { Position } from "@dxos/util";
8
+ import { AppCapabilities, AppNode, AppNodeMatcher, GraphPath, TypeSection } from "@dxos/app-toolkit";
9
+ import * as Effect from "effect/Effect";
10
+ import { CallsCapabilities } from "@dxos/plugin-calls/types";
11
+ import { GraphBuilder } from "@dxos/plugin-graph";
12
+ import { SpaceOperation } from "@dxos/plugin-space";
13
+ //#region src/capabilities/app-graph-builder.ts
14
+ var channelTypename = Type.getTypename(Channel.Channel);
15
+ var app_graph_builder_default = Capability.makeModule(Effect.fnUntraced(function* () {
16
+ const capabilities = yield* Capability.Service;
17
+ const extensions = yield* Effect.all([TypeSection.createTypeSectionExtension(Channel.Channel, {
18
+ urlKey: "channel",
19
+ match: AppNodeMatcher.whenNavTreeGroup(GraphPath.GroupTypes.communications),
20
+ groupSegment: GraphPath.GroupSegments.communications,
21
+ createObject: (space) => Operation.invoke(SpaceOperation.OpenCreateObject, {
22
+ target: space.db,
23
+ typename: channelTypename,
24
+ targetNodeId: getChannelsPath(space.db.spaceId)
25
+ })
26
+ }), GraphBuilder.createTypeExtension({
27
+ id: "channelChatCompanion",
28
+ type: Channel.Channel,
29
+ connector: (channel, get) => {
30
+ const [callManager] = get(capabilities.atom(CallsCapabilities.Manager));
31
+ if (!callManager) return Effect.succeed([]);
32
+ const joined = get(callManager.joinedAtom);
33
+ const roomId = get(callManager.roomIdAtom);
34
+ if (!joined || roomId !== Obj.getURI(channel)) return Effect.succeed([]);
35
+ return Effect.succeed([AppNode.makeCompanion({
36
+ variant: "chat",
37
+ label: ["channel-companion.label", { ns: meta.profile.key }],
38
+ icon: "ph--hash--regular",
39
+ data: "chat",
40
+ position: Position.first
41
+ })]);
42
+ }
43
+ })]);
44
+ return Capability.contributes(AppCapabilities.AppGraphBuilder, extensions);
45
+ }));
46
+ //#endregion
47
+ export { app_graph_builder_default as default };
48
+
49
+ //# sourceMappingURL=chunk-app-graph-builder.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk-app-graph-builder.mjs","names":[],"sources":["../../src/capabilities/app-graph-builder.ts"],"sourcesContent":["//\n// Copyright 2025 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\nimport { Capability } from '@dxos/app-framework';\nimport { AppCapabilities, AppNode, AppNodeMatcher, GraphPath, TypeSection } from '@dxos/app-toolkit';\nimport { Operation } from '@dxos/compute';\nimport { Obj, Type } from '@dxos/echo';\nimport { CallsCapabilities } from '@dxos/plugin-calls/types';\nimport { GraphBuilder } from '@dxos/plugin-graph';\nimport { SpaceOperation } from '@dxos/plugin-space';\nimport { Channel } from '@dxos/types';\nimport { Position } from '@dxos/util';\n\nimport { meta } from '#meta';\n\nimport { getChannelsPath } from '../paths';\n\nconst channelTypename = Type.getTypename(Channel.Channel);\n\nexport default Capability.makeModule(\n Effect.fnUntraced(function* () {\n const capabilities = yield* Capability.Service;\n\n const extensions = yield* Effect.all([\n TypeSection.createTypeSectionExtension(Channel.Channel, {\n urlKey: 'channel',\n match: AppNodeMatcher.whenNavTreeGroup(GraphPath.GroupTypes.communications),\n groupSegment: GraphPath.GroupSegments.communications,\n createObject: (space) =>\n Operation.invoke(SpaceOperation.OpenCreateObject, {\n target: space.db,\n typename: channelTypename,\n targetNodeId: getChannelsPath(space.db.spaceId),\n }),\n }),\n\n GraphBuilder.createTypeExtension({\n id: 'channelChatCompanion',\n type: Channel.Channel,\n connector: (channel, get) => {\n const [callManager] = get(capabilities.atom(CallsCapabilities.Manager));\n if (!callManager) {\n return Effect.succeed([]);\n }\n const joined = get(callManager.joinedAtom);\n const roomId = get(callManager.roomIdAtom);\n if (!joined || roomId !== Obj.getURI(channel)) {\n return Effect.succeed([]);\n }\n\n return Effect.succeed([\n AppNode.makeCompanion({\n variant: 'chat',\n label: ['channel-companion.label', { ns: meta.profile.key }],\n icon: 'ph--hash--regular',\n data: 'chat',\n position: Position.first,\n }),\n ]);\n },\n }),\n ]);\n\n return Capability.contributes(AppCapabilities.AppGraphBuilder, extensions);\n }),\n);\n"],"mappings":";;;;;;;;;;;;;AAoBA,IAAM,kBAAkB,KAAK,YAAY,QAAQ,OAAO;AAExD,IAAA,4BAAe,WAAW,WACxB,OAAO,WAAW,aAAa;CAC7B,MAAM,eAAe,OAAO,WAAW;CAEvC,MAAM,aAAa,OAAO,OAAO,IAAI,CACnC,YAAY,2BAA2B,QAAQ,SAAS;EACtD,QAAQ;EACR,OAAO,eAAe,iBAAiB,UAAU,WAAW,cAAc;EAC1E,cAAc,UAAU,cAAc;EACtC,eAAe,UACb,UAAU,OAAO,eAAe,kBAAkB;GAChD,QAAQ,MAAM;GACd,UAAU;GACV,cAAc,gBAAgB,MAAM,GAAG,OAAO;EAChD,CAAC;CACL,CAAC,GAED,aAAa,oBAAoB;EAC/B,IAAI;EACJ,MAAM,QAAQ;EACd,YAAY,SAAS,QAAQ;GAC3B,MAAM,CAAC,eAAe,IAAI,aAAa,KAAK,kBAAkB,OAAO,CAAC;GACtE,IAAI,CAAC,aACH,OAAO,OAAO,QAAQ,CAAC,CAAC;GAE1B,MAAM,SAAS,IAAI,YAAY,UAAU;GACzC,MAAM,SAAS,IAAI,YAAY,UAAU;GACzC,IAAI,CAAC,UAAU,WAAW,IAAI,OAAO,OAAO,GAC1C,OAAO,OAAO,QAAQ,CAAC,CAAC;GAG1B,OAAO,OAAO,QAAQ,CACpB,QAAQ,cAAc;IACpB,SAAS;IACT,OAAO,CAAC,2BAA2B,EAAE,IAAI,KAAK,QAAQ,IAAI,CAAC;IAC3D,MAAM;IACN,MAAM;IACN,UAAU,SAAS;GACrB,CAAC,CACH,CAAC;EACH;CACF,CAAC,CACH,CAAC;CAED,OAAO,WAAW,YAAY,gBAAgB,iBAAiB,UAAU;AAC3E,CAAC,CACH"}
@@ -0,0 +1,30 @@
1
+ import { c as resolveProvider, i as ChannelBackend, t as AppendChannelMessage } from "./chunk-types.mjs";
2
+ import { Capability } from "@dxos/app-framework";
3
+ import { Operation } from "@dxos/compute";
4
+ import { Message } from "@dxos/types";
5
+ import * as Effect from "effect/Effect";
6
+ import { invariant } from "@dxos/invariant";
7
+ //#region src/operations/append-channel-message.ts
8
+ var __dxlog_file = "/__w/dxos/dxos/packages/plugins/plugin-thread/src/operations/append-channel-message.ts";
9
+ var handler = AppendChannelMessage.pipe(Operation.withHandler(Effect.fnUntraced(function* ({ channel, sender, text }) {
10
+ const provider = resolveProvider(yield* Capability.getAll(ChannelBackend), channel.backend.kind);
11
+ invariant(provider, `No channel backend for kind: ${channel.backend.kind}`, {
12
+ "~LogMeta": "~LogMeta",
13
+ F: __dxlog_file,
14
+ L: 20,
15
+ S: this,
16
+ A: ["provider", "`No channel backend for kind: ${channel.backend.kind}`"]
17
+ });
18
+ const message = Message.make({
19
+ sender,
20
+ blocks: [{
21
+ _tag: "text",
22
+ text
23
+ }]
24
+ });
25
+ yield* provider.send(channel, message);
26
+ })));
27
+ //#endregion
28
+ export { handler as default };
29
+
30
+ //# sourceMappingURL=chunk-append-channel-message.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk-append-channel-message.mjs","names":[],"sources":["../../src/operations/append-channel-message.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\nimport { Capability } from '@dxos/app-framework';\nimport { Operation } from '@dxos/compute';\nimport { invariant } from '@dxos/invariant';\nimport { Message } from '@dxos/types';\n\nimport { ThreadCapabilities, ThreadOperation, resolveProvider } from '../types';\n\nconst handler: Operation.WithHandler<typeof ThreadOperation.AppendChannelMessage> =\n ThreadOperation.AppendChannelMessage.pipe(\n Operation.withHandler(\n Effect.fnUntraced(function* ({ channel, sender, text }) {\n const providers = yield* Capability.getAll(ThreadCapabilities.ChannelBackend);\n const provider = resolveProvider(providers, channel.backend.kind);\n invariant(provider, `No channel backend for kind: ${channel.backend.kind}`);\n\n const message = Message.make({\n sender,\n blocks: [{ _tag: 'text', text }],\n });\n yield* provider.send(channel, message);\n }),\n ),\n );\n\nexport default handler;\n"],"mappings":";;;;;;;;AAaA,IAAM,UAAA,qBACiC,KACnC,UAAU,YACR,OAAO,WAAW,WAAW,EAAE,SAAS,QAAQ,QAAQ;CAEtD,MAAM,WAAW,gBAAgB,OADR,WAAW,OAAO,cAAiC,GAChC,QAAQ,QAAQ,IAAI;CAChE,UAAU,UAAU,gCAAgC,QAAQ,QAAQ,QAAK;EAAA,YAAA;EAAA,GAAA;EAAA,GAAA;EAAA,GAAA;EAAA,GAAA,CAAA,YAAA,wDAAA;CAAA,CAAC;CAE1E,MAAM,UAAU,QAAQ,KAAK;EAC3B;EACA,QAAQ,CAAC;GAAE,MAAM;GAAQ;EAAK,CAAC;CACjC,CAAC;CACD,OAAO,SAAS,KAAK,SAAS,OAAO;AACvC,CAAC,CACH,CACF"}
@@ -0,0 +1,68 @@
1
+ import { i as ChannelBackend } from "./chunk-types.mjs";
2
+ import * as Schema from "effect/Schema";
3
+ import { Capability } from "@dxos/app-framework";
4
+ import { Database, Feed, Filter, Obj, Query } from "@dxos/echo";
5
+ import { Channel, Message } from "@dxos/types";
6
+ import * as Effect from "effect/Effect";
7
+ import { invariant } from "@dxos/invariant";
8
+ import { ClientCapabilities } from "@dxos/plugin-client";
9
+ //#region src/capabilities/channel-backend-feed.ts
10
+ var __dxlog_file = "/__w/dxos/dxos/packages/plugins/plugin-thread/src/capabilities/channel-backend-feed.ts";
11
+ /**
12
+ * Default local ECHO-feed-backed channel provider. Stores messages in a `Feed`
13
+ * (`makeConfig` → `Feed.make()`), reads them via a reactive database query, and
14
+ * writes via `Feed.append`. This is the backend `Channel.make()` defaults to.
15
+ */
16
+ var feedChannelBackend = {
17
+ kind: Channel.FeedBackendKind,
18
+ label: "Feed",
19
+ icon: "ph--rows--regular",
20
+ createFields: Schema.Struct({}),
21
+ makeConfig: () => Feed.make(),
22
+ subscribe: (channel, onMessages) => {
23
+ const feed = Channel.getFeed(channel);
24
+ const db = Obj.getDatabase(channel);
25
+ if (!feed || !db) {
26
+ onMessages([]);
27
+ return () => {};
28
+ }
29
+ const result = db.query(Query.select(Filter.type(Message.Message)).from(feed));
30
+ return result.subscribe(() => onMessages(result.results), { fire: true });
31
+ },
32
+ send: (channel, message) => Effect.gen(function* () {
33
+ const db = Obj.getDatabase(channel);
34
+ invariant(db, "Database not found", {
35
+ "~LogMeta": "~LogMeta",
36
+ F: __dxlog_file,
37
+ L: 41,
38
+ S: this,
39
+ A: ["db", "'Database not found'"]
40
+ });
41
+ const space = (yield* Capability.get(ClientCapabilities.Client)).spaces.get(db.spaceId);
42
+ invariant(space, "Space not found", {
43
+ "~LogMeta": "~LogMeta",
44
+ F: __dxlog_file,
45
+ L: 44,
46
+ S: this,
47
+ A: ["space", "'Space not found'"]
48
+ });
49
+ const feed = Channel.getFeed(channel);
50
+ invariant(feed, "Channel is not feed-backed", {
51
+ "~LogMeta": "~LogMeta",
52
+ F: __dxlog_file,
53
+ L: 46,
54
+ S: this,
55
+ A: ["feed", "'Channel is not feed-backed'"]
56
+ });
57
+ yield* Feed.append(feed, [message]).pipe(Effect.provide(Database.layer(space.db)));
58
+ }),
59
+ readOnly: (channel) => Obj.getMeta(channel).keys.length > 0
60
+ };
61
+ /** Contributes the default feed-backed channel provider. */
62
+ var ChannelBackendFeed = Capability.makeModule(Effect.fnUntraced(function* () {
63
+ return Capability.contributes(ChannelBackend, feedChannelBackend);
64
+ }));
65
+ //#endregion
66
+ export { ChannelBackendFeed, ChannelBackendFeed as default, feedChannelBackend };
67
+
68
+ //# sourceMappingURL=chunk-channel-backend-feed.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk-channel-backend-feed.mjs","names":[],"sources":["../../src/capabilities/channel-backend-feed.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\nimport * as Schema from 'effect/Schema';\n\nimport { Capability } from '@dxos/app-framework';\nimport { Database, Feed, Filter, Obj, Query } from '@dxos/echo';\nimport { invariant } from '@dxos/invariant';\nimport { ClientCapabilities } from '@dxos/plugin-client';\nimport { Channel, Message } from '@dxos/types';\n\nimport { ThreadCapabilities } from '../types';\n\n/**\n * Default local ECHO-feed-backed channel provider. Stores messages in a `Feed`\n * (`makeConfig` → `Feed.make()`), reads them via a reactive database query, and\n * writes via `Feed.append`. This is the backend `Channel.make()` defaults to.\n */\nexport const feedChannelBackend: ThreadCapabilities.ChannelBackendProvider = {\n kind: Channel.FeedBackendKind,\n label: 'Feed',\n icon: 'ph--rows--regular',\n createFields: Schema.Struct({}),\n makeConfig: () => Feed.make(),\n subscribe: (channel, onMessages) => {\n const feed = Channel.getFeed(channel);\n const db = Obj.getDatabase(channel);\n if (!feed || !db) {\n onMessages([]);\n return () => {};\n }\n\n const result = db.query(Query.select(Filter.type(Message.Message)).from(feed));\n return result.subscribe(() => onMessages(result.results), { fire: true });\n },\n send: (channel, message) =>\n Effect.gen(function* () {\n const db = Obj.getDatabase(channel);\n invariant(db, 'Database not found');\n const client = yield* Capability.get(ClientCapabilities.Client);\n const space = client.spaces.get(db.spaceId);\n invariant(space, 'Space not found');\n const feed = Channel.getFeed(channel);\n invariant(feed, 'Channel is not feed-backed');\n yield* Feed.append(feed, [message]).pipe(Effect.provide(Database.layer(space.db)));\n }),\n readOnly: (channel) => Obj.getMeta(channel).keys.length > 0,\n};\n\n/** Contributes the default feed-backed channel provider. */\nexport const ChannelBackendFeed = Capability.makeModule(\n Effect.fnUntraced(function* () {\n return Capability.contributes(ThreadCapabilities.ChannelBackend, feedChannelBackend);\n }),\n);\n\nexport default ChannelBackendFeed;\n"],"mappings":";;;;;;;;;;;;;;;AAoBA,IAAa,qBAAgE;CAC3E,MAAM,QAAQ;CACd,OAAO;CACP,MAAM;CACN,cAAc,OAAO,OAAO,CAAC,CAAC;CAC9B,kBAAkB,KAAK,KAAK;CAC5B,YAAY,SAAS,eAAe;EAClC,MAAM,OAAO,QAAQ,QAAQ,OAAO;EACpC,MAAM,KAAK,IAAI,YAAY,OAAO;EAClC,IAAI,CAAC,QAAQ,CAAC,IAAI;GAChB,WAAW,CAAC,CAAC;GACb,aAAa,CAAC;EAChB;EAEA,MAAM,SAAS,GAAG,MAAM,MAAM,OAAO,OAAO,KAAK,QAAQ,OAAO,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;EAC7E,OAAO,OAAO,gBAAgB,WAAW,OAAO,OAAO,GAAG,EAAE,MAAM,KAAK,CAAC;CAC1E;CACA,OAAO,SAAS,YACd,OAAO,IAAI,aAAa;EACtB,MAAM,KAAK,IAAI,YAAY,OAAO;EAClC,UAAU,IAAI,sBAAmB;GAAA,YAAA;GAAA,GAAA;GAAA,GAAA;GAAA,GAAA;GAAA,GAAA,CAAA,MAAA,sBAAA;EAAA,CAAC;EAElC,MAAM,SAAQ,OADQ,WAAW,IAAI,mBAAmB,MAAM,EAAA,CACzC,OAAO,IAAI,GAAG,OAAO;EAC1C,UAAU,OAAO,mBAAgB;GAAA,YAAA;GAAA,GAAA;GAAA,GAAA;GAAA,GAAA;GAAA,GAAA,CAAA,SAAA,mBAAA;EAAA,CAAC;EAClC,MAAM,OAAO,QAAQ,QAAQ,OAAO;EACpC,UAAU,MAAM,8BAA2B;GAAA,YAAA;GAAA,GAAA;GAAA,GAAA;GAAA,GAAA;GAAA,GAAA,CAAA,QAAA,8BAAA;EAAA,CAAC;EAC5C,OAAO,KAAK,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,QAAQ,SAAS,MAAM,MAAM,EAAE,CAAC,CAAC;CACnF,CAAC;CACH,WAAW,YAAY,IAAI,QAAQ,OAAO,CAAC,CAAC,KAAK,SAAS;AAC5D;;AAGA,IAAa,qBAAqB,WAAW,WAC3C,OAAO,WAAW,aAAa;CAC7B,OAAO,WAAW,YAAY,gBAAmC,kBAAkB;AACrF,CAAC,CACH"}