@dxos/plugin-thread 0.11.0 → 0.12.0-next-bbabc02363f18d7643ea4160e3a7a7809870fd0d

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 (135) hide show
  1. package/dist/lib/ChannelBackend.mjs +42 -0
  2. package/dist/lib/ChannelBackend.mjs.map +1 -0
  3. package/dist/lib/ThreadCapabilities.mjs +11 -0
  4. package/dist/lib/ThreadCapabilities.mjs.map +1 -0
  5. package/dist/lib/ThreadEvents.mjs +15 -0
  6. package/dist/lib/ThreadEvents.mjs.map +1 -0
  7. package/dist/lib/ThreadOperation.mjs +51 -0
  8. package/dist/lib/ThreadOperation.mjs.map +1 -0
  9. package/dist/lib/ThreadPlugin.mjs +5 -9
  10. package/dist/lib/ThreadPlugin.mjs.map +1 -1
  11. package/dist/lib/ThreadPlugin.node.mjs +4 -8
  12. package/dist/lib/ThreadPlugin.node.mjs.map +1 -1
  13. package/dist/lib/ThreadPlugin.workerd.mjs +4 -8
  14. package/dist/lib/ThreadPlugin.workerd.mjs.map +1 -1
  15. package/dist/lib/capabilities/node.mjs +10 -3
  16. package/dist/lib/capabilities/node.mjs.map +1 -1
  17. package/dist/lib/capabilities.mjs +14 -6
  18. package/dist/lib/capabilities.mjs.map +1 -1
  19. package/dist/lib/chunk-ChannelArticle.mjs +9 -7
  20. package/dist/lib/chunk-ChannelArticle.mjs.map +1 -1
  21. package/dist/lib/chunk-ChannelCreatePanel.mjs +4 -3
  22. package/dist/lib/chunk-ChannelCreatePanel.mjs.map +1 -1
  23. package/dist/lib/chunk-ThreadArticle.mjs +1 -1
  24. package/dist/lib/chunk-app-graph-builder.mjs +11 -7
  25. package/dist/lib/chunk-app-graph-builder.mjs.map +1 -1
  26. package/dist/lib/chunk-append-channel-message.mjs +6 -4
  27. package/dist/lib/chunk-append-channel-message.mjs.map +1 -1
  28. package/dist/lib/chunk-channel-backend-feed.mjs +4 -4
  29. package/dist/lib/chunk-channel-backend-feed.mjs.map +1 -1
  30. package/dist/lib/chunk-create-channel.mjs +6 -4
  31. package/dist/lib/chunk-create-channel.mjs.map +1 -1
  32. package/dist/lib/chunk-create-object.mjs +7 -5
  33. package/dist/lib/chunk-create-object.mjs.map +1 -1
  34. package/dist/lib/chunk-meta.mjs +1 -1
  35. package/dist/lib/chunk-meta.mjs.map +1 -1
  36. package/dist/lib/chunk-operation-handler.mjs +3 -2
  37. package/dist/lib/chunk-operation-handler.mjs.map +1 -1
  38. package/dist/lib/chunk-paths.mjs +1 -1
  39. package/dist/lib/chunk-paths.mjs.map +1 -1
  40. package/dist/lib/chunk-react-surface.mjs +4 -3
  41. package/dist/lib/chunk-react-surface.mjs.map +1 -1
  42. package/dist/lib/chunk-rolldown-runtime.mjs +13 -0
  43. package/dist/lib/components.mjs +1 -1
  44. package/dist/lib/hooks.mjs +2 -1
  45. package/dist/lib/hooks.mjs.map +1 -1
  46. package/dist/lib/index.mjs +5 -2
  47. package/dist/lib/operations.mjs +4 -2
  48. package/dist/lib/operations.mjs.map +1 -1
  49. package/dist/lib/plugin.mjs +2 -3
  50. package/dist/lib/plugin.mjs.map +1 -1
  51. package/dist/types/src/ThreadPlugin.d.ts +1 -1
  52. package/dist/types/src/ThreadPlugin.d.ts.map +1 -1
  53. package/dist/types/src/ThreadPlugin.node.d.ts +1 -1
  54. package/dist/types/src/ThreadPlugin.node.d.ts.map +1 -1
  55. package/dist/types/src/ThreadPlugin.workerd.d.ts +1 -1
  56. package/dist/types/src/ThreadPlugin.workerd.d.ts.map +1 -1
  57. package/dist/types/src/capabilities/app-graph-builder.d.ts +2 -2
  58. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
  59. package/dist/types/src/capabilities/channel-backend-feed.d.ts +3 -3
  60. package/dist/types/src/capabilities/channel-backend-feed.d.ts.map +1 -1
  61. package/dist/types/src/capabilities/create-object.d.ts +2 -2
  62. package/dist/types/src/capabilities/create-object.d.ts.map +1 -1
  63. package/dist/types/src/capabilities/index.d.ts +6 -7
  64. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  65. package/dist/types/src/capabilities/node.d.ts +3 -4
  66. package/dist/types/src/capabilities/node.d.ts.map +1 -1
  67. package/dist/types/src/capabilities/operation-handler.d.ts +2 -3
  68. package/dist/types/src/capabilities/operation-handler.d.ts.map +1 -1
  69. package/dist/types/src/capabilities/react-surface.d.ts +2 -2
  70. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
  71. package/dist/types/src/containers/ChannelArticle/ChannelArticle.d.ts.map +1 -1
  72. package/dist/types/src/containers/ChannelArticle/ChannelArticle.stories.d.ts +1 -1
  73. package/dist/types/src/containers/ChannelCreatePanel/ChannelCreatePanel.d.ts +1 -1
  74. package/dist/types/src/containers/ChannelCreatePanel/ChannelCreatePanel.d.ts.map +1 -1
  75. package/dist/types/src/containers/ThreadArticle/ThreadArticle.stories.d.ts +1 -1
  76. package/dist/types/src/containers/ThreadArticle/ThreadArticle.stories.d.ts.map +1 -1
  77. package/dist/types/src/hooks/useMessages.d.ts.map +1 -1
  78. package/dist/types/src/index.d.ts +4 -1
  79. package/dist/types/src/index.d.ts.map +1 -1
  80. package/dist/types/src/operations/append-channel-message.d.ts +2 -2
  81. package/dist/types/src/operations/append-channel-message.d.ts.map +1 -1
  82. package/dist/types/src/operations/create-channel.d.ts +2 -2
  83. package/dist/types/src/operations/create-channel.d.ts.map +1 -1
  84. package/dist/types/src/operations/index.d.ts +1 -1
  85. package/dist/types/src/operations/index.d.ts.map +1 -1
  86. package/dist/types/src/plugin.d.ts +1 -2
  87. package/dist/types/src/plugin.d.ts.map +1 -1
  88. package/dist/types/src/types/{channel-backend.d.ts → ChannelBackend.d.ts} +1 -1
  89. package/dist/types/src/types/ChannelBackend.d.ts.map +1 -0
  90. package/dist/types/src/types/ChannelBackend.test.d.ts +2 -0
  91. package/dist/types/src/types/ChannelBackend.test.d.ts.map +1 -0
  92. package/dist/types/src/types/ThreadCapabilities.d.ts +2 -2
  93. package/dist/types/src/types/ThreadCapabilities.d.ts.map +1 -1
  94. package/dist/types/src/types/ThreadEvents.d.ts +8 -0
  95. package/dist/types/src/types/ThreadEvents.d.ts.map +1 -0
  96. package/dist/types/src/types/ThreadOperation.d.ts +2 -2
  97. package/dist/types/src/types/ThreadOperation.d.ts.map +1 -1
  98. package/dist/types/tsconfig.tsbuildinfo +1 -1
  99. package/package.json +67 -43
  100. package/src/ThreadPlugin.node.ts +5 -11
  101. package/src/ThreadPlugin.tsx +17 -18
  102. package/src/ThreadPlugin.workerd.ts +5 -11
  103. package/src/capabilities/app-graph-builder.ts +13 -7
  104. package/src/capabilities/channel-backend-feed.ts +4 -4
  105. package/src/capabilities/create-object.ts +8 -6
  106. package/src/capabilities/index.ts +22 -9
  107. package/src/capabilities/node.ts +17 -10
  108. package/src/capabilities/operation-handler.ts +4 -4
  109. package/src/capabilities/react-surface.ts +3 -2
  110. package/src/containers/ChannelArticle/ChannelArticle.stories.tsx +6 -6
  111. package/src/containers/ChannelArticle/ChannelArticle.tsx +9 -4
  112. package/src/containers/ChannelCreatePanel/ChannelCreatePanel.tsx +4 -3
  113. package/src/containers/ThreadArticle/ThreadArticle.stories.tsx +3 -2
  114. package/src/hooks/useMessages.ts +3 -2
  115. package/src/index.ts +5 -1
  116. package/src/meta.ts +1 -1
  117. package/src/operations/append-channel-message.ts +6 -4
  118. package/src/operations/create-channel.ts +6 -4
  119. package/src/operations/index.ts +8 -5
  120. package/src/paths.ts +1 -1
  121. package/src/plugin.ts +1 -3
  122. package/src/types/{channel-backend.test.ts → ChannelBackend.test.ts} +1 -1
  123. package/src/types/ThreadCapabilities.ts +4 -2
  124. package/src/types/ThreadEvents.ts +16 -0
  125. package/src/types/ThreadOperation.ts +2 -2
  126. package/dist/lib/chunk-types.mjs +0 -99
  127. package/dist/lib/chunk-types.mjs.map +0 -1
  128. package/dist/lib/types.mjs +0 -2
  129. package/dist/types/src/types/channel-backend.d.ts.map +0 -1
  130. package/dist/types/src/types/channel-backend.test.d.ts +0 -2
  131. package/dist/types/src/types/channel-backend.test.d.ts.map +0 -1
  132. package/dist/types/src/types/index.d.ts +0 -4
  133. package/dist/types/src/types/index.d.ts.map +0 -1
  134. package/src/types/index.ts +0 -7
  135. /package/src/types/{channel-backend.ts → ChannelBackend.ts} +0 -0
@@ -0,0 +1,42 @@
1
+ import { t as __exportAll } from "./chunk-rolldown-runtime.mjs";
2
+ import * as Schema from "effect/Schema";
3
+ import * as SchemaAST from "effect/SchemaAST";
4
+ //#region src/types/ChannelBackend.ts
5
+ var ChannelBackend_exports = /* @__PURE__ */ __exportAll({
6
+ assertUniqueKinds: () => assertUniqueKinds,
7
+ buildChannelFormSchema: () => buildChannelFormSchema,
8
+ resolveProvider: () => resolveProvider
9
+ });
10
+ /** Finds the provider matching a `Channel.backend.kind`. */
11
+ var resolveProvider = (providers, kind) => providers.find((provider) => provider.kind === kind);
12
+ /** Throws if two providers share a `kind` (which would make resolution order-dependent). */
13
+ var assertUniqueKinds = (providers) => {
14
+ const seen = /* @__PURE__ */ new Set();
15
+ for (const provider of providers) {
16
+ if (seen.has(provider.kind)) throw new Error(`Duplicate channel backend kind: ${provider.kind}`);
17
+ seen.add(provider.kind);
18
+ }
19
+ };
20
+ /**
21
+ * Builds the create-channel form schema from the registered providers.
22
+ *
23
+ * With a single provider whose create-fields are empty the form is just a
24
+ * `name` field (today's behaviour). With multiple providers (or extra fields)
25
+ * it becomes `{ name?, backend: Union(<{ kind: Literal(p.kind) } & p.createFields>) }`,
26
+ * which react-ui-form renders as a `kind` Select plus the selected branch's fields.
27
+ */
28
+ var buildChannelFormSchema = (providers) => {
29
+ assertUniqueKinds(providers);
30
+ if (!(providers.length > 1 || providers.some((provider) => fieldCount(provider.createFields) > 0))) return Schema.Struct({ name: Schema.optional(Schema.String) });
31
+ const branches = providers.map((provider) => Schema.extend(Schema.Struct({ kind: Schema.Literal(provider.kind) }), provider.createFields));
32
+ const backend = branches.length === 1 ? branches[0] : Schema.Union(...branches);
33
+ return Schema.Struct({
34
+ name: Schema.optional(Schema.String),
35
+ backend
36
+ });
37
+ };
38
+ var fieldCount = (schema) => SchemaAST.getPropertySignatures(schema.ast).length;
39
+ //#endregion
40
+ export { assertUniqueKinds, buildChannelFormSchema, resolveProvider, ChannelBackend_exports as t };
41
+
42
+ //# sourceMappingURL=ChannelBackend.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChannelBackend.mjs","names":[],"sources":["../../src/types/ChannelBackend.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Schema from 'effect/Schema';\nimport * as SchemaAST from 'effect/SchemaAST';\n\nimport * as ThreadCapabilities from './ThreadCapabilities';\n\n/** Finds the provider matching a `Channel.backend.kind`. */\nexport const resolveProvider = (\n providers: readonly ThreadCapabilities.ChannelBackendProvider[],\n kind: string,\n): ThreadCapabilities.ChannelBackendProvider | undefined => providers.find((provider) => provider.kind === kind);\n\n/** Throws if two providers share a `kind` (which would make resolution order-dependent). */\nexport const assertUniqueKinds = (providers: readonly ThreadCapabilities.ChannelBackendProvider[]): void => {\n const seen = new Set<string>();\n for (const provider of providers) {\n if (seen.has(provider.kind)) {\n throw new Error(`Duplicate channel backend kind: ${provider.kind}`);\n }\n seen.add(provider.kind);\n }\n};\n\n/**\n * Builds the create-channel form schema from the registered providers.\n *\n * With a single provider whose create-fields are empty the form is just a\n * `name` field (today's behaviour). With multiple providers (or extra fields)\n * it becomes `{ name?, backend: Union(<{ kind: Literal(p.kind) } & p.createFields>) }`,\n * which react-ui-form renders as a `kind` Select plus the selected branch's fields.\n */\nexport const buildChannelFormSchema = (\n providers: readonly ThreadCapabilities.ChannelBackendProvider[],\n): Schema.Schema.AnyNoContext => {\n assertUniqueKinds(providers);\n const needsSelector = providers.length > 1 || providers.some((provider) => fieldCount(provider.createFields) > 0);\n if (!needsSelector) {\n return Schema.Struct({ name: Schema.optional(Schema.String) });\n }\n\n const branches = providers.map((provider) =>\n Schema.extend(Schema.Struct({ kind: Schema.Literal(provider.kind) }), provider.createFields),\n );\n const backend = branches.length === 1 ? branches[0] : Schema.Union(...branches);\n return Schema.Struct({\n name: Schema.optional(Schema.String),\n backend,\n });\n};\n\nconst fieldCount = (schema: Schema.Schema.AnyNoContext): number => SchemaAST.getPropertySignatures(schema.ast).length;\n"],"mappings":";;;;;;;;;;AAUA,IAAa,mBACX,WACA,SAC0D,UAAU,MAAM,aAAa,SAAS,SAAS,IAAI;;AAG/G,IAAa,qBAAqB,cAA0E;CAC1G,MAAM,uBAAO,IAAI,IAAY;CAC7B,KAAK,MAAM,YAAY,WAAW;EAChC,IAAI,KAAK,IAAI,SAAS,IAAI,GACxB,MAAM,IAAI,MAAM,mCAAmC,SAAS,MAAM;EAEpE,KAAK,IAAI,SAAS,IAAI;CACxB;AACF;;;;;;;;;AAUA,IAAa,0BACX,cAC+B;CAC/B,kBAAkB,SAAS;CAE3B,IAAI,EADkB,UAAU,SAAS,KAAK,UAAU,MAAM,aAAa,WAAW,SAAS,YAAY,IAAI,CAAC,IAE9G,OAAO,OAAO,OAAO,EAAE,MAAM,OAAO,SAAS,OAAO,MAAM,EAAE,CAAC;CAG/D,MAAM,WAAW,UAAU,KAAK,aAC9B,OAAO,OAAO,OAAO,OAAO,EAAE,MAAM,OAAO,QAAQ,SAAS,IAAI,EAAE,CAAC,GAAG,SAAS,YAAY,CAC7F;CACA,MAAM,UAAU,SAAS,WAAW,IAAI,SAAS,KAAK,OAAO,MAAM,GAAG,QAAQ;CAC9E,OAAO,OAAO,OAAO;EACnB,MAAM,OAAO,SAAS,OAAO,MAAM;EACnC;CACF,CAAC;AACH;AAEA,IAAM,cAAc,WAA+C,UAAU,sBAAsB,OAAO,GAAG,CAAC,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { t as __exportAll } from "./chunk-rolldown-runtime.mjs";
2
+ import * as Capability from "@dxos/app-framework/Capability";
3
+ import { meta } from "#meta";
4
+ //#region src/types/ThreadCapabilities.ts
5
+ var ThreadCapabilities_exports = /* @__PURE__ */ __exportAll({ ChannelBackend: () => ChannelBackend });
6
+ /** Registry of channel-message backends. Collect with `Capability.getAll`. */
7
+ var ChannelBackend = Capability.make()(`${meta.profile.key}.capability.channelBackend`);
8
+ //#endregion
9
+ export { ChannelBackend, ThreadCapabilities_exports as t };
10
+
11
+ //# sourceMappingURL=ThreadCapabilities.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ThreadCapabilities.mjs","names":[],"sources":["../../src/types/ThreadCapabilities.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\n// @import-as-namespace\n\nimport * as Effect from 'effect/Effect';\nimport type * as Schema from 'effect/Schema';\n\nimport * as Capability from '@dxos/app-framework/Capability';\nimport { type Obj } from '@dxos/echo';\nimport { type Channel, type Message } from '@dxos/types';\n\nimport { meta } from '#meta';\n\n/**\n * A pluggable message backend for a `Channel`. Providers are contributed by\n * plugins and resolved by `Channel.backend.kind`.\n */\nexport interface ChannelBackendProvider {\n /** Stable backend id; matches `Channel.backend.kind`. */\n kind: string;\n /** Human-readable label shown in the create-channel form. */\n label: string;\n /** Icon name (phosphor) for the create-channel form. */\n icon?: string;\n /**\n * Per-backend create-form inputs (a struct; excludes the `kind` discriminant\n * and the channel `name`, which the panel adds). Empty struct when the backend\n * needs no extra input (e.g. the local feed).\n */\n createFields: Schema.Schema.AnyNoContext;\n /** Builds the provider's config object from the collected create-form inputs. */\n makeConfig: (options: Record<string, unknown>) => Obj.Any;\n /**\n * Subscribes to the channel's messages. Invokes `onMessages` with the current\n * list immediately and on every change. Returns an unsubscribe function.\n */\n subscribe: (channel: Channel.Channel, onMessages: (messages: readonly Message.Message[]) => void) => () => void;\n /** Sends a message through the backend. */\n send: (channel: Channel.Channel, message: Message.Message) => Effect.Effect<void, Error, Capability.Service>;\n /** Whether the channel is read-only. Defaults to \"channel has foreign-key Obj.Meta\". */\n readOnly?: (channel: Channel.Channel) => boolean;\n}\n\n/** Registry of channel-message backends. Collect with `Capability.getAll`. */\nexport const ChannelBackend = Capability.make<ChannelBackendProvider>()(\n `${meta.profile.key}.capability.channelBackend`,\n);\n"],"mappings":";;;;;;AA8CA,IAAa,iBAAiB,WAAW,KAA6B,CAAC,CACrE,GAAG,KAAK,QAAQ,IAAI,2BACtB"}
@@ -0,0 +1,15 @@
1
+ import { t as __exportAll } from "./chunk-rolldown-runtime.mjs";
2
+ import { meta } from "#meta";
3
+ import * as ActivationEvent from "@dxos/app-framework/ActivationEvent";
4
+ //#region src/types/ThreadEvents.ts
5
+ var ThreadEvents_exports = /* @__PURE__ */ __exportAll({ Start: () => Start });
6
+ /**
7
+ * The feature's start event: the plugin's start-gated modules (and cross-plugin
8
+ * contributions consumed by this feature) activate here. Fired on demand and by the
9
+ * host's idle trickle.
10
+ */
11
+ var Start = ActivationEvent.pluginStart(meta.profile.key);
12
+ //#endregion
13
+ export { Start, ThreadEvents_exports as t };
14
+
15
+ //# sourceMappingURL=ThreadEvents.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ThreadEvents.mjs","names":[],"sources":["../../src/types/ThreadEvents.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\n// @import-as-namespace\n\nimport * as ActivationEvent from '@dxos/app-framework/ActivationEvent';\n\nimport { meta } from '#meta';\n\n/**\n * The feature's start event: the plugin's start-gated modules (and cross-plugin\n * contributions consumed by this feature) activate here. Fired on demand and by the\n * host's idle trickle.\n */\nexport const Start = ActivationEvent.pluginStart(meta.profile.key);\n"],"mappings":";;;;;;;;;;AAeA,IAAa,QAAQ,gBAAgB,YAAY,KAAK,QAAQ,GAAG"}
@@ -0,0 +1,51 @@
1
+ import { t as __exportAll } from "./chunk-rolldown-runtime.mjs";
2
+ import * as Schema from "effect/Schema";
3
+ import * as Capability from "@dxos/app-framework/Capability";
4
+ import { meta } from "#meta";
5
+ import * as Operation from "@dxos/compute/Operation";
6
+ import { DXN, Key, Type } from "@dxos/echo";
7
+ import { Actor, Channel } from "@dxos/types";
8
+ //#region src/types/ThreadOperation.ts
9
+ var ThreadOperation_exports = /* @__PURE__ */ __exportAll({
10
+ AppendChannelMessage: () => AppendChannelMessage,
11
+ CreateChannel: () => CreateChannel
12
+ });
13
+ var makeKey = (name) => DXN.make(`${meta.profile.key}.operation.${name}`);
14
+ var CreateChannel = Operation.make({
15
+ meta: {
16
+ key: makeKey("createChannel"),
17
+ name: "Create Channel",
18
+ icon: "ph--hash--regular"
19
+ },
20
+ services: [Capability.Service],
21
+ input: Schema.Struct({
22
+ spaceId: Key.SpaceId,
23
+ name: Schema.optional(Schema.String),
24
+ /** Backend provider id; defaults to the local feed backend. */
25
+ kind: Schema.optional(Schema.String),
26
+ /** Per-backend create options passed to the provider's makeConfig. */
27
+ options: Schema.optional(Schema.Record({
28
+ key: Schema.String,
29
+ value: Schema.Any
30
+ }))
31
+ }),
32
+ output: Schema.Struct({ object: Type.getSchema(Channel.Channel) })
33
+ });
34
+ var AppendChannelMessage = Operation.make({
35
+ meta: {
36
+ key: makeKey("appendChannelMessage"),
37
+ name: "Append Channel Message",
38
+ icon: "ph--chat-text--regular"
39
+ },
40
+ services: [Capability.Service],
41
+ input: Schema.Struct({
42
+ channel: Type.getSchema(Channel.Channel),
43
+ sender: Actor.Actor,
44
+ text: Schema.String
45
+ }),
46
+ output: Schema.Void
47
+ });
48
+ //#endregion
49
+ export { AppendChannelMessage, CreateChannel, ThreadOperation_exports as t };
50
+
51
+ //# sourceMappingURL=ThreadOperation.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ThreadOperation.mjs","names":[],"sources":["../../src/types/ThreadOperation.ts"],"sourcesContent":["//\n// Copyright 2025 DXOS.org\n//\n\n// @import-as-namespace\n\nimport * as Schema from 'effect/Schema';\n\nimport * as Capability from '@dxos/app-framework/Capability';\nimport * as Operation from '@dxos/compute/Operation';\nimport { DXN, Key, Type } from '@dxos/echo';\n// Person is referenced in Actor.Actor's inferred type; importing it allows TypeScript to name\n// it in the emitted .d.ts for AppendChannelMessage.\n// eslint-disable-next-line unused-imports/no-unused-imports\nimport { Actor, Channel, type Person } from '@dxos/types';\n\nimport { meta } from '#meta';\n\nconst makeKey = (name: string) => DXN.make(`${meta.profile.key}.operation.${name}`);\n\nexport const CreateChannel = Operation.make({\n meta: { key: makeKey('createChannel'), name: 'Create Channel', icon: 'ph--hash--regular' },\n services: [Capability.Service],\n input: Schema.Struct({\n spaceId: Key.SpaceId,\n name: Schema.optional(Schema.String),\n /** Backend provider id; defaults to the local feed backend. */\n kind: Schema.optional(Schema.String),\n /** Per-backend create options passed to the provider's makeConfig. */\n options: Schema.optional(Schema.Record({ key: Schema.String, value: Schema.Any })),\n }),\n output: Schema.Struct({\n object: Type.getSchema(Channel.Channel),\n }),\n});\n\nexport const AppendChannelMessage = Operation.make({\n meta: {\n key: makeKey('appendChannelMessage'),\n name: 'Append Channel Message',\n icon: 'ph--chat-text--regular',\n },\n // Note: Database.Service is provided inside the handler from space.db, not at the\n // operation level — the runtime can't fulfill it without a space context.\n services: [Capability.Service],\n input: Schema.Struct({\n channel: Type.getSchema(Channel.Channel),\n sender: Actor.Actor,\n text: Schema.String,\n }),\n output: Schema.Void,\n});\n"],"mappings":";;;;;;;;;;;;AAkBA,IAAM,WAAW,SAAiB,IAAI,KAAK,GAAG,KAAK,QAAQ,IAAI,aAAa,MAAM;AAElF,IAAa,gBAAgB,UAAU,KAAK;CAC1C,MAAM;EAAE,KAAK,QAAQ,eAAe;EAAG,MAAM;EAAkB,MAAM;CAAoB;CACzF,UAAU,CAAC,WAAW,OAAO;CAC7B,OAAO,OAAO,OAAO;EACnB,SAAS,IAAI;EACb,MAAM,OAAO,SAAS,OAAO,MAAM;;EAEnC,MAAM,OAAO,SAAS,OAAO,MAAM;;EAEnC,SAAS,OAAO,SAAS,OAAO,OAAO;GAAE,KAAK,OAAO;GAAQ,OAAO,OAAO;EAAI,CAAC,CAAC;CACnF,CAAC;CACD,QAAQ,OAAO,OAAO,EACpB,QAAQ,KAAK,UAAU,QAAQ,OAAO,EACxC,CAAC;AACH,CAAC;AAED,IAAa,uBAAuB,UAAU,KAAK;CACjD,MAAM;EACJ,KAAK,QAAQ,sBAAsB;EACnC,MAAM;EACN,MAAM;CACR;CAGA,UAAU,CAAC,WAAW,OAAO;CAC7B,OAAO,OAAO,OAAO;EACnB,SAAS,KAAK,UAAU,QAAQ,OAAO;EACvC,QAAQ,MAAM;EACd,MAAM,OAAO;CACf,CAAC;CACD,QAAQ,OAAO;AACjB,CAAC"}
@@ -1,7 +1,7 @@
1
- import { ActivationEvents, Plugin } from "@dxos/app-framework";
2
1
  import { meta } from "#meta";
3
2
  import { Channel, Message, Thread } from "@dxos/types";
4
- import { AppPlugin } from "@dxos/app-toolkit";
3
+ import * as Plugin from "@dxos/app-framework/Plugin";
4
+ import * as AppCapability from "@dxos/app-toolkit/AppCapability";
5
5
  import { translations } from "@dxos/react-ui-thread/translations";
6
6
  import { AppGraphBuilder, ChannelBackendFeed, CreateObject, OperationHandler, ReactSurface } from "#capabilities";
7
7
  import { translations as translations$1 } from "#translations";
@@ -9,20 +9,16 @@ import { translations as translations$1 } from "#translations";
9
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
10
  //#endregion
11
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: [
12
+ var ThreadPlugin = Plugin.define(meta).pipe(Plugin.addModule(AppGraphBuilder), Plugin.addModule(CreateObject), Plugin.addModule(OperationHandler), Plugin.addModule(AppCapability.schema([
13
13
  Channel.Channel,
14
14
  Message.Message,
15
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: {
16
+ ])), Plugin.addModule(ReactSurface), Plugin.addModule(AppCapability.translations([...translations$1, ...translations])), Plugin.addModule(ChannelBackendFeed), Plugin.addModule(AppCapability.pluginAsset({
21
17
  pluginId: meta.profile.key,
22
18
  path: "PLUGIN.mdl",
23
19
  content: PLUGIN_default,
24
20
  mimeType: "application/x-mdl"
25
- } }), Plugin.make);
21
+ })), Plugin.make);
26
22
  //#endregion
27
23
  export { ThreadPlugin, ThreadPlugin as default };
28
24
 
@@ -1 +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"}
1
+ {"version":3,"file":"ThreadPlugin.mjs","names":[],"sources":["../../src/ThreadPlugin.tsx"],"sourcesContent":["//\n// Copyright 2023 DXOS.org\n//\n\nimport * as Plugin from '@dxos/app-framework/Plugin';\nimport * as AppCapability from '@dxos/app-toolkit/AppCapability';\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 Plugin.addModule(AppGraphBuilder),\n Plugin.addModule(CreateObject),\n Plugin.addModule(OperationHandler),\n Plugin.addModule(AppCapability.schema([Channel.Channel, Message.Message, Thread.Thread])),\n Plugin.addModule(ReactSurface),\n Plugin.addModule(AppCapability.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(ChannelBackendFeed),\n Plugin.addModule(\n AppCapability.pluginAsset({\n pluginId: meta.profile.key,\n path: 'PLUGIN.mdl',\n content: pluginSpec,\n mimeType: 'application/x-mdl',\n }),\n ),\n Plugin.make,\n);\n\nexport default ThreadPlugin;\n"],"mappings":";;;;;;;;;;;AAkBA,IAAa,eAAe,OAAO,OAAO,IAAI,CAAC,CAAC,KAC9C,OAAO,UAAU,eAAe,GAChC,OAAO,UAAU,YAAY,GAC7B,OAAO,UAAU,gBAAgB,GACjC,OAAO,UAAU,cAAc,OAAO;CAAC,QAAQ;CAAS,QAAQ;CAAS,OAAO;AAAM,CAAC,CAAC,GACxF,OAAO,UAAU,YAAY,GAC7B,OAAO,UAAU,cAAc,aAAa,CAAC,GAAG,gBAAc,GAAG,YAAkB,CAAC,CAAC,GAGrF,OAAO,UAAU,kBAAkB,GACnC,OAAO,UACL,cAAc,YAAY;CACxB,UAAU,KAAK,QAAQ;CACvB,MAAM;CACN,SAAS;CACT,UAAU;AACZ,CAAC,CACH,GACA,OAAO,IACT"}
@@ -1,18 +1,14 @@
1
- import { ActivationEvents, Plugin } from "@dxos/app-framework";
2
1
  import { meta } from "#meta";
3
2
  import { Channel, Message, Thread } from "@dxos/types";
4
- import { AppPlugin } from "@dxos/app-toolkit";
3
+ import * as Plugin from "@dxos/app-framework/Plugin";
4
+ import * as AppCapability from "@dxos/app-toolkit/AppCapability";
5
5
  import { ChannelBackendFeed, OperationHandler } from "#capabilities";
6
6
  //#region src/ThreadPlugin.node.ts
7
- var ThreadPlugin = Plugin.define(meta).pipe(AppPlugin.addOperationHandlerModule({ activate: OperationHandler }), AppPlugin.addSchemaModule({ schema: [
7
+ var ThreadPlugin = Plugin.define(meta).pipe(Plugin.addModule(OperationHandler), Plugin.addModule(AppCapability.schema([
8
8
  Channel.Channel,
9
9
  Message.Message,
10
10
  Thread.Thread
11
- ] }), Plugin.addModule({
12
- id: "channel-backend-feed",
13
- activatesOn: ActivationEvents.Startup,
14
- activate: ChannelBackendFeed
15
- }), Plugin.make);
11
+ ])), Plugin.addModule(ChannelBackendFeed), Plugin.make);
16
12
  //#endregion
17
13
  export { ThreadPlugin, ThreadPlugin as default };
18
14
 
@@ -1 +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"}
1
+ {"version":3,"file":"ThreadPlugin.node.mjs","names":[],"sources":["../../src/ThreadPlugin.node.ts"],"sourcesContent":["//\n// Copyright 2023 DXOS.org\n//\n\nimport * as Plugin from '@dxos/app-framework/Plugin';\nimport * as AppCapability from '@dxos/app-toolkit/AppCapability';\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 Plugin.addModule(OperationHandler),\n Plugin.addModule(AppCapability.schema([Channel.Channel, Message.Message, Thread.Thread])),\n Plugin.addModule(ChannelBackendFeed),\n Plugin.make,\n);\n\nexport default ThreadPlugin;\n"],"mappings":";;;;;;AAWA,IAAa,eAAe,OAAO,OAAO,IAAI,CAAC,CAAC,KAC9C,OAAO,UAAU,gBAAgB,GACjC,OAAO,UAAU,cAAc,OAAO;CAAC,QAAQ;CAAS,QAAQ;CAAS,OAAO;AAAM,CAAC,CAAC,GACxF,OAAO,UAAU,kBAAkB,GACnC,OAAO,IACT"}
@@ -1,18 +1,14 @@
1
- import { ActivationEvents, Plugin } from "@dxos/app-framework";
2
1
  import { meta } from "#meta";
3
2
  import { Channel, Message, Thread } from "@dxos/types";
4
- import { AppPlugin } from "@dxos/app-toolkit";
3
+ import * as Plugin from "@dxos/app-framework/Plugin";
4
+ import * as AppCapability from "@dxos/app-toolkit/AppCapability";
5
5
  import { ChannelBackendFeed, OperationHandler } from "#capabilities";
6
6
  //#region src/ThreadPlugin.workerd.ts
7
- var ThreadPlugin = Plugin.define(meta).pipe(AppPlugin.addOperationHandlerModule({ activate: OperationHandler }), AppPlugin.addSchemaModule({ schema: [
7
+ var ThreadPlugin = Plugin.define(meta).pipe(Plugin.addModule(OperationHandler), Plugin.addModule(AppCapability.schema([
8
8
  Channel.Channel,
9
9
  Message.Message,
10
10
  Thread.Thread
11
- ] }), Plugin.addModule({
12
- id: "channel-backend-feed",
13
- activatesOn: ActivationEvents.Startup,
14
- activate: ChannelBackendFeed
15
- }), Plugin.make);
11
+ ])), Plugin.addModule(ChannelBackendFeed), Plugin.make);
16
12
  //#endregion
17
13
  export { ThreadPlugin, ThreadPlugin as default };
18
14
 
@@ -1 +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"}
1
+ {"version":3,"file":"ThreadPlugin.workerd.mjs","names":[],"sources":["../../src/ThreadPlugin.workerd.ts"],"sourcesContent":["//\n// Copyright 2023 DXOS.org\n//\n\nimport * as Plugin from '@dxos/app-framework/Plugin';\nimport * as AppCapability from '@dxos/app-toolkit/AppCapability';\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 Plugin.addModule(OperationHandler),\n Plugin.addModule(AppCapability.schema([Channel.Channel, Message.Message, Thread.Thread])),\n Plugin.addModule(ChannelBackendFeed),\n Plugin.make,\n);\n\nexport default ThreadPlugin;\n"],"mappings":";;;;;;AAWA,IAAa,eAAe,OAAO,OAAO,IAAI,CAAC,CAAC,KAC9C,OAAO,UAAU,gBAAgB,GACjC,OAAO,UAAU,cAAc,OAAO;CAAC,QAAQ;CAAS,QAAQ;CAAS,OAAO;AAAM,CAAC,CAAC,GACxF,OAAO,UAAU,kBAAkB,GACnC,OAAO,IACT"}
@@ -1,7 +1,14 @@
1
- import { Capability } from "@dxos/app-framework";
1
+ import { ChannelBackend } from "../ThreadCapabilities.mjs";
2
+ import { Start } from "../ThreadEvents.mjs";
3
+ import * as Capability from "@dxos/app-framework/Capability";
4
+ import * as AppCapability from "@dxos/app-toolkit/AppCapability";
5
+ import * as ActivationEvents from "@dxos/app-framework/ActivationEvents";
2
6
  //#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"));
7
+ var ChannelBackendFeed = Capability.lazyModule("ChannelBackendFeed", {
8
+ provides: [ChannelBackend],
9
+ activatesOn: Start
10
+ }, () => import("../chunk-channel-backend-feed.mjs"));
11
+ var OperationHandler = AppCapability.operationHandler(() => import("../chunk-operation-handler.mjs"), { activatesOn: ActivationEvents.Idle });
5
12
  //#endregion
6
13
  export { ChannelBackendFeed, OperationHandler };
7
14
 
@@ -1 +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"}
1
+ {"version":3,"file":"node.mjs","names":[],"sources":["../../../src/capabilities/node.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport * as ActivationEvents from '@dxos/app-framework/ActivationEvents';\nimport * as Capability from '@dxos/app-framework/Capability';\nimport * as AppCapability from '@dxos/app-toolkit/AppCapability';\n\nimport * as ThreadCapabilities from '../types/ThreadCapabilities';\nimport * as ThreadEvents from '../types/ThreadEvents';\n\n// The capabilities `ThreadPlugin.node` activates, and only those. A lazy module defers its import at\n// runtime but a bundler still walks it, so listing the React surfaces here would pull the plugin's\n// components into every node and bun build. `CreateObject` is omitted: its `CreateObjectEntry`\n// 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.lazyModule(\n 'ChannelBackendFeed',\n { provides: [ThreadCapabilities.ChannelBackend], activatesOn: ThreadEvents.Start },\n () => import('./channel-backend-feed'),\n);\nexport const OperationHandler = AppCapability.operationHandler(() => import('./operation-handler'), {\n activatesOn: ActivationEvents.Idle,\n});\n"],"mappings":";;;;;;AAiBA,IAAa,qBAAqB,WAAW,WAC3C,sBACA;CAAE,UAAU,CAAC,cAAiC;CAAG,aAAa;AAAmB,SAC3E,OAAO,oCACf;AACA,IAAa,mBAAmB,cAAc,uBAAuB,OAAO,mCAAwB,EAClG,aAAa,iBAAiB,KAChC,CAAC"}
@@ -1,10 +1,18 @@
1
- import { Capability } from "@dxos/app-framework";
1
+ import { ChannelBackend } from "./ThreadCapabilities.mjs";
2
+ import { Start } from "./ThreadEvents.mjs";
3
+ import * as Capability from "@dxos/app-framework/Capability";
4
+ import * as AppCapability from "@dxos/app-toolkit/AppCapability";
5
+ import * as ActivationEvents from "@dxos/app-framework/ActivationEvents";
6
+ import * as SpaceCapability from "@dxos/plugin-space/SpaceCapability";
2
7
  //#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
+ var AppGraphBuilder = AppCapability.appGraphBuilder(() => import("./chunk-app-graph-builder.mjs"));
9
+ var ChannelBackendFeed = Capability.lazyModule("ChannelBackendFeed", {
10
+ provides: [ChannelBackend],
11
+ activatesOn: Start
12
+ }, () => import("./chunk-channel-backend-feed.mjs"));
13
+ var CreateObject = SpaceCapability.createObject(() => import("./chunk-create-object.mjs"));
14
+ var OperationHandler = AppCapability.operationHandler(() => import("./chunk-operation-handler.mjs"), { activatesOn: ActivationEvents.Idle });
15
+ var ReactSurface = AppCapability.surface(() => import("./chunk-react-surface.mjs"), { roles: ["org.dxos.role.article"] });
8
16
  //#endregion
9
17
  export { AppGraphBuilder, ChannelBackendFeed, CreateObject, OperationHandler, ReactSurface };
10
18
 
@@ -1 +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"}
1
+ {"version":3,"file":"capabilities.mjs","names":[],"sources":["../../src/capabilities/index.ts"],"sourcesContent":["//\n// Copyright 2025 DXOS.org\n//\n\nimport * as ActivationEvents from '@dxos/app-framework/ActivationEvents';\nimport * as Capability from '@dxos/app-framework/Capability';\nimport * as AppCapability from '@dxos/app-toolkit/AppCapability';\nimport * as SpaceCapability from '@dxos/plugin-space/SpaceCapability';\n\nimport * as ThreadCapabilities from '../types/ThreadCapabilities';\nimport * as ThreadEvents from '../types/ThreadEvents';\n\n// The graph builder reads the call manager OPTIONALLY (reactive atom with an absence guard),\n// so no spec-level require: a hard cross-plugin require would fail this plugin whenever\n// plugin-calls is disabled. Cross-feature requires are only valid with a plugin-level dependsOn.\nexport const AppGraphBuilder = AppCapability.appGraphBuilder(() => import('./app-graph-builder'));\nexport const ChannelBackendFeed = Capability.lazyModule(\n 'ChannelBackendFeed',\n { provides: [ThreadCapabilities.ChannelBackend], activatesOn: ThreadEvents.Start },\n () => import('./channel-backend-feed'),\n);\nexport const CreateObject = SpaceCapability.createObject(() => import('./create-object'));\nexport const OperationHandler = AppCapability.operationHandler(() => import('./operation-handler'), {\n activatesOn: ActivationEvents.Idle,\n});\nexport const ReactSurface = AppCapability.surface(() => import('./react-surface'), {\n roles: ['org.dxos.role.article'],\n});\n"],"mappings":";;;;;;;AAeA,IAAa,kBAAkB,cAAc,sBAAsB,OAAO,gCAAsB;AAChG,IAAa,qBAAqB,WAAW,WAC3C,sBACA;CAAE,UAAU,CAAC,cAAiC;CAAG,aAAa;AAAmB,SAC3E,OAAO,mCACf;AACA,IAAa,eAAe,gBAAgB,mBAAmB,OAAO,4BAAkB;AACxF,IAAa,mBAAmB,cAAc,uBAAuB,OAAO,kCAAwB,EAClG,aAAa,iBAAiB,KAChC,CAAC;AACD,IAAa,eAAe,cAAc,cAAc,OAAO,8BAAoB,EACjF,OAAO,CAAC,uBAAuB,EACjC,CAAC"}
@@ -1,18 +1,20 @@
1
- import { useCallback } from "react";
2
- import { Surface, useCapabilities, useOperationInvoker } from "@dxos/app-framework/ui";
1
+ import { resolveProvider } from "./ChannelBackend.mjs";
2
+ import { ChannelBackend } from "./ThreadCapabilities.mjs";
3
+ import { AppendChannelMessage } from "./ThreadOperation.mjs";
3
4
  import { meta } from "#meta";
4
5
  import { Obj } from "@dxos/echo";
6
+ import { useCallback } from "react";
7
+ import { Surface, useCapabilities, useOperationInvoker } from "@dxos/app-framework/ui";
5
8
  import { AppSurface } from "@dxos/app-toolkit/ui";
6
9
  import { Panel } from "@dxos/react-ui";
7
10
  import { jsx, jsxs } from "react/jsx-runtime";
8
- import { CallsCapabilities } from "@dxos/plugin-calls/types";
11
+ import * as CallsCapabilities from "@dxos/plugin-calls/CallsCapabilities";
9
12
  import { Atom, useAtomValue } from "@effect-atom/atom-react";
10
13
  import { useIdentity, useMembers } from "@dxos/halo-react";
11
14
  import { getSpace } from "@dxos/react-client/echo";
12
15
  import { Menu, MenuBuilder, useMenuBuilder } from "@dxos/react-ui-menu";
13
16
  import { MessageThread } from "#components";
14
17
  import { useMessages, useStatus } from "#hooks";
15
- import { ThreadCapabilities, ThreadOperation, resolveProvider } from "#types";
16
18
  //#region src/containers/ChannelArticle/ChannelArticle.tsx
17
19
  var NOT_JOINED = Atom.make(false);
18
20
  var NO_ROOM = Atom.make(void 0);
@@ -31,7 +33,7 @@ var ChannelArticle = ({ role, subject: channel, attendableId, chatOnly }) => {
31
33
  const id = channel ? Obj.getURI(channel) : void 0;
32
34
  const activity = useStatus(space, id);
33
35
  const { invokePromise } = useOperationInvoker();
34
- const providers = useCapabilities(ThreadCapabilities.ChannelBackend);
36
+ const providers = useCapabilities(ChannelBackend);
35
37
  const provider = channel ? resolveProvider(providers, channel.backend.kind) : void 0;
36
38
  const messages = useMessages(channel);
37
39
  const readOnly = channel ? provider?.readOnly?.(channel) ?? Obj.getMeta(channel).keys.length > 0 : false;
@@ -58,7 +60,7 @@ var ChannelArticle = ({ role, subject: channel, attendableId, chatOnly }) => {
58
60
  }, [canStartCall, handleStartCall]);
59
61
  const handleSend = (text) => {
60
62
  if (!channel || !identity || readOnly) return false;
61
- invokePromise(ThreadOperation.AppendChannelMessage, {
63
+ invokePromise(AppendChannelMessage, {
62
64
  channel,
63
65
  sender: { identityDid: identity.did },
64
66
  text
@@ -73,7 +75,7 @@ var ChannelArticle = ({ role, subject: channel, attendableId, chatOnly }) => {
73
75
  attendableId,
74
76
  children: /* @__PURE__ */ jsx(Panel.Toolbar, {
75
77
  asChild: true,
76
- children: /* @__PURE__ */ jsx(Menu.Toolbar, {})
78
+ children: /* @__PURE__ */ jsx(Menu.Toolbar, { children: /* @__PURE__ */ jsx(Menu.Items, {}) })
77
79
  })
78
80
  }), showCall ? /* @__PURE__ */ jsx(Panel.Content, { children: /* @__PURE__ */ jsx(Surface.Surface, {
79
81
  type: AppSurface.Article,
@@ -1 +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"}
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 * as CallsCapabilities from '@dxos/plugin-calls/CallsCapabilities';\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';\n\nimport * as ChannelBackend from '../../types/ChannelBackend';\nimport * as ThreadCapabilities from '../../types/ThreadCapabilities';\nimport * as ThreadOperation from '../../types/ThreadOperation';\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 ? ChannelBackend.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 <Menu.Items />\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":";;;;;;;;;;;;;;;;;;AA0BA,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,cAAiC;CACnE,MAAM,WAAW,UAAU,gBAA+B,WAAW,QAAQ,QAAQ,IAAI,IAAI,KAAA;CAC7F,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,sBAAsC;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,EAAA,UACE,oBAAC,KAAK,OAAN,CAAa,CAAA,EACD,CAAA;GACD,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"}
@@ -1,8 +1,9 @@
1
+ import { buildChannelFormSchema } from "./ChannelBackend.mjs";
2
+ import { ChannelBackend } from "./ThreadCapabilities.mjs";
3
+ import { Obj } from "@dxos/echo";
1
4
  import { useCallback, useMemo } from "react";
2
5
  import { useCapabilities } from "@dxos/app-framework/ui";
3
- import { Obj } from "@dxos/echo";
4
6
  import { jsx, jsxs } from "react/jsx-runtime";
5
- import { ThreadCapabilities, buildChannelFormSchema } from "#types";
6
7
  import { Form } from "@dxos/react-ui-form";
7
8
  //#region src/containers/ChannelCreatePanel/ChannelCreatePanel.tsx
8
9
  /**
@@ -13,7 +14,7 @@ import { Form } from "@dxos/react-ui-form";
13
14
  * field-less provider).
14
15
  */
15
16
  var ChannelCreatePanel = ({ target, onCreateObject }) => {
16
- const providers = useCapabilities(ThreadCapabilities.ChannelBackend);
17
+ const providers = useCapabilities(ChannelBackend);
17
18
  const schema = useMemo(() => buildChannelFormSchema(providers), [providers]);
18
19
  const handleSave = useCallback((values) => {
19
20
  const { name, backend } = values;
@@ -1 +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"}
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 * as SpaceCapabilities from '@dxos/plugin-space/SpaceCapabilities';\nimport { Form } from '@dxos/react-ui-form';\n\nimport * as ChannelBackend from '../../types/ChannelBackend';\nimport * as ThreadCapabilities from '../../types/ThreadCapabilities';\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(() => ChannelBackend.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":";;;;;;;;;;;;;;;AAqBA,IAAa,sBAAsB,EAAE,QAAQ,qBAAqE;CAChH,MAAM,YAAY,gBAAgB,cAAiC;CACnE,MAAM,SAAS,cAAc,uBAAsC,SAAS,GAAG,CAAC,SAAS,CAAC;CAE1F,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"}
@@ -1,6 +1,6 @@
1
- import { useMemo } from "react";
2
1
  import { Obj, Ref } from "@dxos/echo";
3
2
  import { Message } from "@dxos/types";
3
+ import { useMemo } from "react";
4
4
  import { isNonNullable } from "@dxos/util";
5
5
  import { Panel, composable, composableProps } from "@dxos/react-ui";
6
6
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -1,19 +1,23 @@
1
1
  import { n as getChannelsPath } from "./chunk-paths.mjs";
2
- import { Capability } from "@dxos/app-framework";
2
+ import * as Capability from "@dxos/app-framework/Capability";
3
3
  import { meta } from "#meta";
4
- import { Operation } from "@dxos/compute";
4
+ import * as Operation from "@dxos/compute/Operation";
5
5
  import { Obj, Type } from "@dxos/echo";
6
6
  import { Channel } from "@dxos/types";
7
7
  import { Position } from "@dxos/util";
8
- import { AppCapabilities, AppNode, AppNodeMatcher, GraphPath, TypeSection } from "@dxos/app-toolkit";
8
+ import * as GraphPath from "@dxos/app-toolkit/GraphPath";
9
9
  import * as Effect from "effect/Effect";
10
- import { CallsCapabilities } from "@dxos/plugin-calls/types";
10
+ import * as AppCapabilities from "@dxos/app-toolkit/AppCapabilities";
11
+ import * as AppNode from "@dxos/app-toolkit/AppNode";
12
+ import * as AppNodeMatcher from "@dxos/app-toolkit/AppNodeMatcher";
13
+ import * as TypeSection from "@dxos/app-toolkit/TypeSection";
14
+ import * as CallsCapabilities from "@dxos/plugin-calls/CallsCapabilities";
11
15
  import { GraphBuilder } from "@dxos/plugin-graph";
12
16
  import { SpaceOperation } from "@dxos/plugin-space";
13
17
  //#region src/capabilities/app-graph-builder.ts
14
18
  var channelTypename = Type.getTypename(Channel.Channel);
15
19
  var app_graph_builder_default = Capability.makeModule(Effect.fnUntraced(function* () {
16
- const capabilities = yield* Capability.Service;
20
+ const callManagerAtom = yield* Capability.atom(CallsCapabilities.Manager);
17
21
  const extensions = yield* Effect.all([TypeSection.createTypeSectionExtension(Channel.Channel, {
18
22
  urlKey: "channel",
19
23
  match: AppNodeMatcher.whenNavTreeGroup(GraphPath.GroupTypes.communications),
@@ -27,7 +31,7 @@ var app_graph_builder_default = Capability.makeModule(Effect.fnUntraced(function
27
31
  id: "channelChatCompanion",
28
32
  type: Channel.Channel,
29
33
  connector: (channel, get) => {
30
- const [callManager] = get(capabilities.atom(CallsCapabilities.Manager));
34
+ const [callManager] = get(callManagerAtom);
31
35
  if (!callManager) return Effect.succeed([]);
32
36
  const joined = get(callManager.joinedAtom);
33
37
  const roomId = get(callManager.roomIdAtom);
@@ -41,7 +45,7 @@ var app_graph_builder_default = Capability.makeModule(Effect.fnUntraced(function
41
45
  })]);
42
46
  }
43
47
  })]);
44
- return Capability.contributes(AppCapabilities.AppGraphBuilder, extensions);
48
+ return Capability.contribute(AppCapabilities.AppGraphBuilder, extensions);
45
49
  }));
46
50
  //#endregion
47
51
  export { app_graph_builder_default as default };
@@ -1 +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"}
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 * as Capability from '@dxos/app-framework/Capability';\nimport * as AppCapabilities from '@dxos/app-toolkit/AppCapabilities';\nimport * as AppNode from '@dxos/app-toolkit/AppNode';\nimport * as AppNodeMatcher from '@dxos/app-toolkit/AppNodeMatcher';\nimport * as GraphPath from '@dxos/app-toolkit/GraphPath';\nimport * as TypeSection from '@dxos/app-toolkit/TypeSection';\nimport * as Operation from '@dxos/compute/Operation';\nimport { Obj, Type } from '@dxos/echo';\nimport * as CallsCapabilities from '@dxos/plugin-calls/CallsCapabilities';\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 // Read reactively so the extension establishes a dependency and heals once this\n // capability lands (dependency modules contribute individually, not batched per wave).\n const callManagerAtom = yield* Capability.atom(CallsCapabilities.Manager);\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(callManagerAtom);\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.contribute(AppCapabilities.AppGraphBuilder, extensions);\n }),\n);\n"],"mappings":";;;;;;;;;;;;;;;;;AAwBA,IAAM,kBAAkB,KAAK,YAAY,QAAQ,OAAO;AAExD,IAAA,4BAAe,WAAW,WACxB,OAAO,WAAW,aAAa;CAG7B,MAAM,kBAAkB,OAAO,WAAW,KAAK,kBAAkB,OAAO;CAExE,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,eAAe;GACzC,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,WAAW,gBAAgB,iBAAiB,UAAU;AAC1E,CAAC,CACH"}
@@ -1,6 +1,8 @@
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";
1
+ import { resolveProvider } from "./ChannelBackend.mjs";
2
+ import { ChannelBackend } from "./ThreadCapabilities.mjs";
3
+ import { AppendChannelMessage } from "./ThreadOperation.mjs";
4
+ import * as Capability from "@dxos/app-framework/Capability";
5
+ import * as Operation from "@dxos/compute/Operation";
4
6
  import { Message } from "@dxos/types";
5
7
  import * as Effect from "effect/Effect";
6
8
  import { invariant } from "@dxos/invariant";
@@ -11,7 +13,7 @@ var handler = AppendChannelMessage.pipe(Operation.withHandler(Effect.fnUntraced(
11
13
  invariant(provider, `No channel backend for kind: ${channel.backend.kind}`, {
12
14
  "~LogMeta": "~LogMeta",
13
15
  F: __dxlog_file,
14
- L: 20,
16
+ L: 22,
15
17
  S: this,
16
18
  A: ["provider", "`No channel backend for kind: ${channel.backend.kind}`"]
17
19
  });
@@ -1 +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"}
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 * as Capability from '@dxos/app-framework/Capability';\nimport * as Operation from '@dxos/compute/Operation';\nimport { invariant } from '@dxos/invariant';\nimport { Message } from '@dxos/types';\n\nimport * as ChannelBackend from '../types/ChannelBackend';\nimport * as ThreadCapabilities from '../types/ThreadCapabilities';\nimport * as ThreadOperation from '../types/ThreadOperation';\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 = ChannelBackend.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":";;;;;;;;;;AAeA,IAAM,UAAA,qBACiC,KACnC,UAAU,YACR,OAAO,WAAW,WAAW,EAAE,SAAS,QAAQ,QAAQ;CAEtD,MAAM,WAAW,gBAA+B,OADvB,WAAW,OAAO,cAAiC,GACjB,QAAQ,QAAQ,IAAI;CAC/E,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"}