@dxos/plugin-markdown 0.8.2-staging.7ac8446 → 0.8.3-main.672df60

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 (227) hide show
  1. package/dist/lib/browser/MarkdownContainer-DGPA7SEG.mjs +588 -0
  2. package/dist/lib/browser/MarkdownContainer-DGPA7SEG.mjs.map +7 -0
  3. package/dist/lib/browser/MarkdownPreview-KQN2TGK6.mjs +80 -0
  4. package/dist/lib/browser/MarkdownPreview-KQN2TGK6.mjs.map +7 -0
  5. package/dist/lib/browser/anchor-sort-VS4OZVPP.mjs +32 -0
  6. package/dist/lib/browser/anchor-sort-VS4OZVPP.mjs.map +7 -0
  7. package/dist/lib/browser/{app-graph-serializer-NOXI4IQ5.mjs → app-graph-serializer-V6RLEHVY.mjs} +5 -6
  8. package/dist/lib/browser/app-graph-serializer-V6RLEHVY.mjs.map +7 -0
  9. package/dist/lib/browser/{artifact-definition-CE6J6NY4.mjs → artifact-definition-5NAODQLG.mjs} +65 -17
  10. package/dist/lib/browser/artifact-definition-5NAODQLG.mjs.map +7 -0
  11. package/dist/lib/browser/{chunk-3ULJ4FIJ.mjs → chunk-77NGW7EO.mjs} +12 -26
  12. package/dist/lib/browser/chunk-77NGW7EO.mjs.map +7 -0
  13. package/dist/lib/browser/{chunk-QXDKFACU.mjs → chunk-C5RABVIX.mjs} +6 -5
  14. package/dist/lib/browser/chunk-C5RABVIX.mjs.map +7 -0
  15. package/dist/lib/browser/chunk-ECSM56YC.mjs +80 -0
  16. package/dist/lib/browser/chunk-ECSM56YC.mjs.map +7 -0
  17. package/dist/lib/browser/chunk-OTOPAFWC.mjs +20 -0
  18. package/dist/lib/browser/chunk-OTOPAFWC.mjs.map +7 -0
  19. package/dist/lib/browser/{chunk-NAGMSX77.mjs → chunk-QVJETNGS.mjs} +2 -2
  20. package/dist/lib/{node-esm/chunk-ETXPC5VP.mjs.map → browser/chunk-QVJETNGS.mjs.map} +1 -1
  21. package/dist/lib/browser/index.mjs +34 -18
  22. package/dist/lib/browser/index.mjs.map +3 -3
  23. package/dist/lib/browser/intent-resolver-4GDYST4Y.mjs +65 -0
  24. package/dist/lib/browser/intent-resolver-4GDYST4Y.mjs.map +7 -0
  25. package/dist/lib/browser/meta.json +1 -1
  26. package/dist/lib/browser/react-surface-DM6B4UUJ.mjs +200 -0
  27. package/dist/lib/browser/react-surface-DM6B4UUJ.mjs.map +7 -0
  28. package/dist/lib/browser/{settings-GCSS3Y4Z.mjs → settings-W5CK4PXP.mjs} +4 -4
  29. package/dist/lib/browser/settings-W5CK4PXP.mjs.map +7 -0
  30. package/dist/lib/browser/{state-O7P5JDIH.mjs → state-KI6PJ6DT.mjs} +3 -3
  31. package/dist/lib/browser/state-KI6PJ6DT.mjs.map +7 -0
  32. package/dist/lib/browser/types/index.mjs +3 -1
  33. package/dist/lib/node/MarkdownContainer-BZK66EQD.cjs +601 -0
  34. package/dist/lib/node/MarkdownContainer-BZK66EQD.cjs.map +7 -0
  35. package/dist/lib/node/MarkdownPreview-H7FFIWJH.cjs +103 -0
  36. package/dist/lib/node/MarkdownPreview-H7FFIWJH.cjs.map +7 -0
  37. package/dist/lib/node/{thread-42R57L4K.cjs → anchor-sort-NHVF23EU.cjs} +15 -20
  38. package/dist/lib/node/anchor-sort-NHVF23EU.cjs.map +7 -0
  39. package/dist/lib/node/{app-graph-serializer-HKK3SEDN.cjs → app-graph-serializer-CLALIYN3.cjs} +10 -11
  40. package/dist/lib/node/app-graph-serializer-CLALIYN3.cjs.map +7 -0
  41. package/dist/lib/node/{artifact-definition-XGADFWCQ.cjs → artifact-definition-VEAHK7BX.cjs} +68 -21
  42. package/dist/lib/node/artifact-definition-VEAHK7BX.cjs.map +7 -0
  43. package/dist/lib/node/chunk-BBDDZLQH.cjs +58 -0
  44. package/dist/lib/node/chunk-BBDDZLQH.cjs.map +7 -0
  45. package/dist/lib/node/{chunk-7QVONRSI.cjs → chunk-G7RBJX22.cjs} +13 -41
  46. package/dist/lib/node/chunk-G7RBJX22.cjs.map +7 -0
  47. package/dist/lib/node/{chunk-DZXTXSXX.cjs → chunk-IFYSBQE5.cjs} +5 -5
  48. package/dist/lib/node/{chunk-DZXTXSXX.cjs.map → chunk-IFYSBQE5.cjs.map} +1 -1
  49. package/dist/lib/node/{chunk-UEXGNGSS.cjs → chunk-RQS4KBMG.cjs} +45 -39
  50. package/dist/lib/node/chunk-RQS4KBMG.cjs.map +7 -0
  51. package/dist/lib/node/{chunk-H5MYVP6F.cjs → chunk-ZDTL47I7.cjs} +9 -8
  52. package/dist/lib/node/chunk-ZDTL47I7.cjs.map +7 -0
  53. package/dist/lib/node/index.cjs +43 -28
  54. package/dist/lib/node/index.cjs.map +3 -3
  55. package/dist/lib/node/intent-resolver-AUZVK3NZ.cjs +78 -0
  56. package/dist/lib/node/intent-resolver-AUZVK3NZ.cjs.map +7 -0
  57. package/dist/lib/node/meta.json +1 -1
  58. package/dist/lib/node/react-surface-QBW4FFXF.cjs +213 -0
  59. package/dist/lib/node/react-surface-QBW4FFXF.cjs.map +7 -0
  60. package/dist/lib/node/{settings-S2ISUVIH.cjs → settings-IRKU3WPM.cjs} +7 -7
  61. package/dist/lib/node/settings-IRKU3WPM.cjs.map +7 -0
  62. package/dist/lib/node/{state-L44SG3ZM.cjs → state-KKDRAG7X.cjs} +7 -7
  63. package/dist/lib/node/state-KKDRAG7X.cjs.map +7 -0
  64. package/dist/lib/node/types/index.cjs +8 -6
  65. package/dist/lib/node/types/index.cjs.map +2 -2
  66. package/dist/lib/node-esm/MarkdownContainer-2DYVQ6RC.mjs +589 -0
  67. package/dist/lib/node-esm/MarkdownContainer-2DYVQ6RC.mjs.map +7 -0
  68. package/dist/lib/node-esm/MarkdownPreview-JUIXYYKF.mjs +81 -0
  69. package/dist/lib/node-esm/MarkdownPreview-JUIXYYKF.mjs.map +7 -0
  70. package/dist/lib/node-esm/anchor-sort-G2HLCYFK.mjs +33 -0
  71. package/dist/lib/node-esm/anchor-sort-G2HLCYFK.mjs.map +7 -0
  72. package/dist/lib/node-esm/{app-graph-serializer-QQ2CTHOQ.mjs → app-graph-serializer-C3RNTQGM.mjs} +5 -6
  73. package/dist/lib/node-esm/app-graph-serializer-C3RNTQGM.mjs.map +7 -0
  74. package/dist/lib/node-esm/{artifact-definition-WRG5ZRN5.mjs → artifact-definition-7TIJW2CO.mjs} +65 -17
  75. package/dist/lib/node-esm/artifact-definition-7TIJW2CO.mjs.map +7 -0
  76. package/dist/lib/node-esm/{chunk-F6UHVLH7.mjs → chunk-6RPARLIK.mjs} +12 -26
  77. package/dist/lib/node-esm/chunk-6RPARLIK.mjs.map +7 -0
  78. package/dist/lib/node-esm/{chunk-ETXPC5VP.mjs → chunk-JXXDCSMW.mjs} +2 -2
  79. package/dist/lib/{browser/chunk-NAGMSX77.mjs.map → node-esm/chunk-JXXDCSMW.mjs.map} +1 -1
  80. package/dist/lib/node-esm/chunk-KK7LP3UQ.mjs +22 -0
  81. package/dist/lib/node-esm/chunk-KK7LP3UQ.mjs.map +7 -0
  82. package/dist/lib/node-esm/chunk-NCMPVEXO.mjs +81 -0
  83. package/dist/lib/node-esm/chunk-NCMPVEXO.mjs.map +7 -0
  84. package/dist/lib/node-esm/{chunk-JAVD67QP.mjs → chunk-TCFJNUAE.mjs} +6 -5
  85. package/dist/lib/node-esm/chunk-TCFJNUAE.mjs.map +7 -0
  86. package/dist/lib/node-esm/index.mjs +34 -18
  87. package/dist/lib/node-esm/index.mjs.map +3 -3
  88. package/dist/lib/node-esm/intent-resolver-FTNXUNI2.mjs +66 -0
  89. package/dist/lib/node-esm/intent-resolver-FTNXUNI2.mjs.map +7 -0
  90. package/dist/lib/node-esm/meta.json +1 -1
  91. package/dist/lib/node-esm/react-surface-A4VAOQG6.mjs +201 -0
  92. package/dist/lib/node-esm/react-surface-A4VAOQG6.mjs.map +7 -0
  93. package/dist/lib/node-esm/{settings-ZDIFTK4N.mjs → settings-MK7D7LHQ.mjs} +4 -4
  94. package/dist/lib/node-esm/settings-MK7D7LHQ.mjs.map +7 -0
  95. package/dist/lib/node-esm/{state-DWPOKLEY.mjs → state-LLGVRYKL.mjs} +3 -3
  96. package/dist/lib/node-esm/state-LLGVRYKL.mjs.map +7 -0
  97. package/dist/lib/node-esm/types/index.mjs +3 -1
  98. package/dist/types/src/MarkdownPlugin.d.ts.map +1 -1
  99. package/dist/types/src/capabilities/anchor-sort.d.ts +6 -0
  100. package/dist/types/src/capabilities/anchor-sort.d.ts.map +1 -0
  101. package/dist/types/src/capabilities/app-graph-serializer.d.ts +2 -2
  102. package/dist/types/src/capabilities/app-graph-serializer.d.ts.map +1 -1
  103. package/dist/types/src/capabilities/artifact-definition.d.ts.map +1 -1
  104. package/dist/types/src/capabilities/index.d.ts +7 -7
  105. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  106. package/dist/types/src/capabilities/intent-resolver.d.ts +2 -2
  107. package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -1
  108. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
  109. package/dist/types/src/capabilities/state.d.ts +2 -2
  110. package/dist/types/src/capabilities/state.d.ts.map +1 -1
  111. package/dist/types/src/components/MarkdownContainer.d.ts +5 -3
  112. package/dist/types/src/components/MarkdownContainer.d.ts.map +1 -1
  113. package/dist/types/src/components/MarkdownEditor/MarkdownEditor.d.ts +24 -0
  114. package/dist/types/src/components/MarkdownEditor/MarkdownEditor.d.ts.map +1 -0
  115. package/dist/types/src/components/{MarkdownEditor.stories.d.ts → MarkdownEditor/MarkdownEditor.stories.d.ts} +3 -3
  116. package/dist/types/src/components/MarkdownEditor/MarkdownEditor.stories.d.ts.map +1 -0
  117. package/dist/types/src/components/MarkdownEditor/index.d.ts +2 -0
  118. package/dist/types/src/components/MarkdownEditor/index.d.ts.map +1 -0
  119. package/dist/types/src/components/MarkdownPreview/MarkdownPreview.d.ts +6 -0
  120. package/dist/types/src/components/MarkdownPreview/MarkdownPreview.d.ts.map +1 -0
  121. package/dist/types/src/components/MarkdownPreview/MarkdownPreview.stories.d.ts +23 -0
  122. package/dist/types/src/components/MarkdownPreview/MarkdownPreview.stories.d.ts.map +1 -0
  123. package/dist/types/src/components/MarkdownPreview/index.d.ts +4 -0
  124. package/dist/types/src/components/MarkdownPreview/index.d.ts.map +1 -0
  125. package/dist/types/src/components/{MarkdownSettings.d.ts → MarkdownSettings/MarkdownSettings.d.ts} +1 -1
  126. package/dist/types/src/components/MarkdownSettings/MarkdownSettings.d.ts.map +1 -0
  127. package/dist/types/src/components/MarkdownSettings/index.d.ts +2 -0
  128. package/dist/types/src/components/MarkdownSettings/index.d.ts.map +1 -0
  129. package/dist/types/src/components/Suggestions.stories.d.ts +12 -0
  130. package/dist/types/src/components/Suggestions.stories.d.ts.map +1 -0
  131. package/dist/types/src/components/Toolbar.stories.d.ts +2 -2
  132. package/dist/types/src/components/Toolbar.stories.d.ts.map +1 -1
  133. package/dist/types/src/components/index.d.ts +2 -1
  134. package/dist/types/src/components/index.d.ts.map +1 -1
  135. package/dist/types/src/extensions.d.ts +8 -5
  136. package/dist/types/src/extensions.d.ts.map +1 -1
  137. package/dist/types/src/hooks/useSelectCurrentThread.d.ts.map +1 -1
  138. package/dist/types/src/translations.d.ts +4 -42
  139. package/dist/types/src/translations.d.ts.map +1 -1
  140. package/dist/types/src/types/schema.d.ts +29 -129
  141. package/dist/types/src/types/schema.d.ts.map +1 -1
  142. package/dist/types/src/types/types.d.ts +40 -88
  143. package/dist/types/src/types/types.d.ts.map +1 -1
  144. package/dist/types/src/util.d.ts +1 -0
  145. package/dist/types/src/util.d.ts.map +1 -1
  146. package/dist/types/tsconfig.tsbuildinfo +1 -1
  147. package/package.json +47 -34
  148. package/src/MarkdownPlugin.tsx +22 -12
  149. package/src/capabilities/anchor-sort.ts +30 -0
  150. package/src/capabilities/app-graph-serializer.ts +4 -5
  151. package/src/capabilities/artifact-definition.ts +48 -10
  152. package/src/capabilities/index.ts +1 -1
  153. package/src/capabilities/intent-resolver.ts +40 -12
  154. package/src/capabilities/react-surface.tsx +20 -5
  155. package/src/capabilities/settings.ts +2 -2
  156. package/src/capabilities/state.ts +4 -4
  157. package/src/components/MarkdownContainer.tsx +20 -7
  158. package/src/components/{MarkdownEditor.stories.tsx → MarkdownEditor/MarkdownEditor.stories.tsx} +22 -35
  159. package/src/components/{MarkdownEditor.tsx → MarkdownEditor/MarkdownEditor.tsx} +32 -73
  160. package/src/components/MarkdownEditor/index.ts +5 -0
  161. package/src/components/MarkdownPreview/MarkdownPreview.stories.tsx +73 -0
  162. package/src/components/MarkdownPreview/MarkdownPreview.tsx +71 -0
  163. package/src/components/MarkdownPreview/index.ts +9 -0
  164. package/src/components/{MarkdownSettings.tsx → MarkdownSettings/MarkdownSettings.tsx} +2 -2
  165. package/src/components/MarkdownSettings/index.ts +5 -0
  166. package/src/components/Suggestions.stories.tsx +217 -0
  167. package/src/components/Toolbar.stories.tsx +29 -29
  168. package/src/components/index.ts +1 -0
  169. package/src/extensions.tsx +82 -48
  170. package/src/hooks/useSelectCurrentThread.tsx +2 -2
  171. package/src/translations.ts +3 -3
  172. package/src/types/schema.ts +22 -15
  173. package/src/types/types.ts +23 -21
  174. package/src/util.tsx +8 -4
  175. package/dist/lib/browser/MarkdownContainer-T3HU27RE.mjs +0 -563
  176. package/dist/lib/browser/MarkdownContainer-T3HU27RE.mjs.map +0 -7
  177. package/dist/lib/browser/app-graph-serializer-NOXI4IQ5.mjs.map +0 -7
  178. package/dist/lib/browser/artifact-definition-CE6J6NY4.mjs.map +0 -7
  179. package/dist/lib/browser/chunk-3ULJ4FIJ.mjs.map +0 -7
  180. package/dist/lib/browser/chunk-QXDKFACU.mjs.map +0 -7
  181. package/dist/lib/browser/chunk-YCJNW2RU.mjs +0 -75
  182. package/dist/lib/browser/chunk-YCJNW2RU.mjs.map +0 -7
  183. package/dist/lib/browser/intent-resolver-42GQ6HNZ.mjs +0 -50
  184. package/dist/lib/browser/intent-resolver-42GQ6HNZ.mjs.map +0 -7
  185. package/dist/lib/browser/react-surface-RQX3CPFV.mjs +0 -176
  186. package/dist/lib/browser/react-surface-RQX3CPFV.mjs.map +0 -7
  187. package/dist/lib/browser/settings-GCSS3Y4Z.mjs.map +0 -7
  188. package/dist/lib/browser/state-O7P5JDIH.mjs.map +0 -7
  189. package/dist/lib/browser/thread-3QGCFNVZ.mjs +0 -37
  190. package/dist/lib/browser/thread-3QGCFNVZ.mjs.map +0 -7
  191. package/dist/lib/node/MarkdownContainer-6ZJIFAP6.cjs +0 -576
  192. package/dist/lib/node/MarkdownContainer-6ZJIFAP6.cjs.map +0 -7
  193. package/dist/lib/node/app-graph-serializer-HKK3SEDN.cjs.map +0 -7
  194. package/dist/lib/node/artifact-definition-XGADFWCQ.cjs.map +0 -7
  195. package/dist/lib/node/chunk-7QVONRSI.cjs.map +0 -7
  196. package/dist/lib/node/chunk-H5MYVP6F.cjs.map +0 -7
  197. package/dist/lib/node/chunk-UEXGNGSS.cjs.map +0 -7
  198. package/dist/lib/node/intent-resolver-NW27BF3W.cjs +0 -63
  199. package/dist/lib/node/intent-resolver-NW27BF3W.cjs.map +0 -7
  200. package/dist/lib/node/react-surface-5X3SMHGI.cjs +0 -189
  201. package/dist/lib/node/react-surface-5X3SMHGI.cjs.map +0 -7
  202. package/dist/lib/node/settings-S2ISUVIH.cjs.map +0 -7
  203. package/dist/lib/node/state-L44SG3ZM.cjs.map +0 -7
  204. package/dist/lib/node/thread-42R57L4K.cjs.map +0 -7
  205. package/dist/lib/node-esm/MarkdownContainer-URAPTO37.mjs +0 -564
  206. package/dist/lib/node-esm/MarkdownContainer-URAPTO37.mjs.map +0 -7
  207. package/dist/lib/node-esm/app-graph-serializer-QQ2CTHOQ.mjs.map +0 -7
  208. package/dist/lib/node-esm/artifact-definition-WRG5ZRN5.mjs.map +0 -7
  209. package/dist/lib/node-esm/chunk-4AM4VU3Y.mjs +0 -76
  210. package/dist/lib/node-esm/chunk-4AM4VU3Y.mjs.map +0 -7
  211. package/dist/lib/node-esm/chunk-F6UHVLH7.mjs.map +0 -7
  212. package/dist/lib/node-esm/chunk-JAVD67QP.mjs.map +0 -7
  213. package/dist/lib/node-esm/intent-resolver-7HOMUVHR.mjs +0 -51
  214. package/dist/lib/node-esm/intent-resolver-7HOMUVHR.mjs.map +0 -7
  215. package/dist/lib/node-esm/react-surface-6IKC3G46.mjs +0 -177
  216. package/dist/lib/node-esm/react-surface-6IKC3G46.mjs.map +0 -7
  217. package/dist/lib/node-esm/settings-ZDIFTK4N.mjs.map +0 -7
  218. package/dist/lib/node-esm/state-DWPOKLEY.mjs.map +0 -7
  219. package/dist/lib/node-esm/thread-R2KHZD6V.mjs +0 -38
  220. package/dist/lib/node-esm/thread-R2KHZD6V.mjs.map +0 -7
  221. package/dist/types/src/capabilities/thread.d.ts +0 -6
  222. package/dist/types/src/capabilities/thread.d.ts.map +0 -1
  223. package/dist/types/src/components/MarkdownEditor.d.ts +0 -39
  224. package/dist/types/src/components/MarkdownEditor.d.ts.map +0 -1
  225. package/dist/types/src/components/MarkdownEditor.stories.d.ts.map +0 -1
  226. package/dist/types/src/components/MarkdownSettings.d.ts.map +0 -1
  227. package/src/capabilities/thread.ts +0 -35
@@ -2,14 +2,19 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { Capabilities, contributes, type PromiseIntentDispatcher } from '@dxos/app-framework';
6
- import { ArtifactId, defineArtifact, defineTool, ToolResult } from '@dxos/artifact';
7
- import { isInstanceOf, S } from '@dxos/echo-schema';
5
+ import { pipe, Schema } from 'effect';
6
+
7
+ import { createTool, ToolResult } from '@dxos/ai';
8
+ import { Capabilities, chain, contributes, createIntent, type PromiseIntentDispatcher } from '@dxos/app-framework';
9
+ import { ArtifactId, defineArtifact } from '@dxos/artifact';
10
+ import { createArtifactElement } from '@dxos/assistant';
11
+ import { isInstanceOf } from '@dxos/echo-schema';
8
12
  import { invariant, assertArgument } from '@dxos/invariant';
13
+ import { SpaceAction } from '@dxos/plugin-space/types';
9
14
  import { Filter, fullyQualifiedId, type Space } from '@dxos/react-client/echo';
10
15
 
11
16
  import { meta } from '../meta';
12
- import { DocumentType } from '../types';
17
+ import { DocumentType, MarkdownAction } from '../types';
13
18
 
14
19
  // TODO(burdon): Factor out.
15
20
  declare global {
@@ -30,15 +35,48 @@ export default () => {
30
35
  `,
31
36
  schema: DocumentType,
32
37
  tools: [
33
- defineTool(meta.id, {
38
+ createTool(meta.id, {
39
+ name: 'create',
40
+ description: 'Create a new markdown document',
41
+ caption: 'Creating document...',
42
+ schema: Schema.Struct({
43
+ name: Schema.optional(Schema.String).annotations({
44
+ description: 'Optional name for the document.',
45
+ }),
46
+ content: Schema.String.annotations({
47
+ description: 'The content of the document.',
48
+ }),
49
+ }),
50
+ execute: async ({ name, content }, { extensions }) => {
51
+ invariant(extensions?.space, 'No space');
52
+ invariant(extensions?.dispatch, 'No intent dispatcher');
53
+
54
+ const intent = pipe(
55
+ createIntent(MarkdownAction.Create, {
56
+ spaceId: extensions.space.id,
57
+ name,
58
+ content,
59
+ }),
60
+ chain(SpaceAction.AddObject, { target: extensions.space }),
61
+ );
62
+
63
+ const { data, error } = await extensions.dispatch(intent);
64
+ if (!data || error) {
65
+ return ToolResult.Error(error?.message ?? 'Failed to create document');
66
+ }
67
+
68
+ return ToolResult.Success(createArtifactElement(data.id));
69
+ },
70
+ }),
71
+ createTool(meta.id, {
34
72
  name: 'list',
35
73
  description: 'List all markdown documents in the current space.',
36
74
  caption: 'Listing markdown documents...',
37
- schema: S.Struct({}),
75
+ schema: Schema.Struct({}),
38
76
  execute: async (_input, { extensions }) => {
39
77
  invariant(extensions?.space, 'No space');
40
78
  const space = extensions.space;
41
- const { objects: documents } = await space.db.query(Filter.schema(DocumentType)).run();
79
+ const { objects: documents } = await space.db.query(Filter.type(DocumentType)).run();
42
80
  const documentInfo = documents.map((doc) => {
43
81
  invariant(isInstanceOf(DocumentType, doc));
44
82
  return {
@@ -51,16 +89,16 @@ export default () => {
51
89
  return ToolResult.Success(documentInfo);
52
90
  },
53
91
  }),
54
- defineTool(meta.id, {
92
+ createTool(meta.id, {
55
93
  name: 'inspect',
56
94
  description: 'Read the content of a markdown document.',
57
95
  caption: 'Inspecting markdown document...',
58
- schema: S.Struct({
96
+ schema: Schema.Struct({
59
97
  id: ArtifactId,
60
98
  }),
61
99
  execute: async ({ id }, { extensions }) => {
62
100
  invariant(extensions?.space, 'No space');
63
- const document = await extensions.space.db.query({ id: ArtifactId.toDXN(id).toString() }).first();
101
+ const document = await extensions.space.db.query(Filter.ids(ArtifactId.toDXN(id).toString())).first();
64
102
  assertArgument(isInstanceOf(DocumentType, document), 'Invalid type');
65
103
 
66
104
  const { content } = await document.content?.load();
@@ -4,12 +4,12 @@
4
4
 
5
5
  import { lazy } from '@dxos/app-framework';
6
6
 
7
+ export const AnchorSort = lazy(() => import('./anchor-sort'));
7
8
  export const AppGraphSerializer = lazy(() => import('./app-graph-serializer'));
8
9
  export const ArtifactDefinition = lazy(() => import('./artifact-definition'));
9
10
  export const IntentResolver = lazy(() => import('./intent-resolver'));
10
11
  export const ReactSurface = lazy(() => import('./react-surface'));
11
12
  export const MarkdownSettings = lazy(() => import('./settings'));
12
13
  export const MarkdownState = lazy(() => import('./state'));
13
- export const Thread = lazy(() => import('./thread'));
14
14
 
15
15
  export * from './capabilities';
@@ -2,25 +2,32 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { Capabilities, contributes, createResolver, type PluginsContext } from '@dxos/app-framework';
6
- import { ObjectId } from '@dxos/echo-schema';
7
- import { DXN, QueueSubspaceTags } from '@dxos/keys';
8
- import { makeRef, create, refFromDXN } from '@dxos/live-object';
9
- import { TextType } from '@dxos/schema';
5
+ import { next as A } from '@automerge/automerge';
6
+ import { Option, pipe, type Schema } from 'effect';
7
+
8
+ import {
9
+ Capabilities,
10
+ CollaborationActions,
11
+ contributes,
12
+ createResolver,
13
+ type PluginContext,
14
+ } from '@dxos/app-framework';
15
+ import { isInstanceOf } from '@dxos/echo-schema';
16
+ import { live } from '@dxos/live-object';
17
+ import { createDocAccessor, getRangeFromCursor, Ref } from '@dxos/react-client/echo';
18
+ import { DataType } from '@dxos/schema';
10
19
 
11
20
  import { MarkdownCapabilities } from './capabilities';
12
21
  import { DocumentType, MarkdownAction } from '../types';
13
22
 
14
- export default (context: PluginsContext) =>
23
+ export default (context: PluginContext) =>
15
24
  contributes(Capabilities.IntentResolver, [
16
25
  createResolver({
17
26
  intent: MarkdownAction.Create,
18
- resolve: ({ name, spaceId, content }) => {
19
- const doc = create(DocumentType, {
27
+ resolve: ({ name, content }) => {
28
+ const doc = live(DocumentType, {
20
29
  name,
21
- content: makeRef(create(TextType, { content: content ?? '' })),
22
- assistantChatQueue: refFromDXN(new DXN(DXN.kind.QUEUE, [QueueSubspaceTags.DATA, spaceId, ObjectId.random()])),
23
- threads: [],
30
+ content: Ref.make(live(DataType.Text, { content: content ?? '' })),
24
31
  });
25
32
 
26
33
  return { data: { object: doc } };
@@ -29,8 +36,29 @@ export default (context: PluginsContext) =>
29
36
  createResolver({
30
37
  intent: MarkdownAction.SetViewMode,
31
38
  resolve: ({ id, viewMode }) => {
32
- const { state } = context.requestCapability(MarkdownCapabilities.State);
39
+ const { state } = context.getCapability(MarkdownCapabilities.State);
33
40
  state.viewMode[id] = viewMode;
34
41
  },
35
42
  }),
43
+ createResolver({
44
+ intent: CollaborationActions.InsertContent,
45
+ filter: (
46
+ data,
47
+ ): data is Omit<Schema.Schema.Type<typeof CollaborationActions.InsertContent.fields.input>, 'target'> & {
48
+ target: DocumentType;
49
+ } => isInstanceOf(DocumentType, data.target),
50
+ resolve: async ({ target, object: objectRef, at, label }) => {
51
+ const text = await target.content.load();
52
+ const accessor = createDocAccessor(text, ['content']);
53
+ const { start, end } = pipe(
54
+ Option.fromNullable(at),
55
+ Option.flatMap((at) => Option.fromNullable(getRangeFromCursor(accessor, at))),
56
+ Option.getOrElse(() => ({ start: text.content.length - 1, end: text.content.length - 1 })),
57
+ );
58
+ accessor.handle.change((doc) => {
59
+ const ref = `[${label ?? 'Generated content'}]](${objectRef.dxn.toString()})\n`;
60
+ A.splice(doc, accessor.path.slice(), start, end - start, ref);
61
+ });
62
+ },
63
+ }),
36
64
  ]);
@@ -7,11 +7,12 @@ import React from 'react';
7
7
  import { createSurface, contributes, Capabilities, useCapability } from '@dxos/app-framework';
8
8
  import { isInstanceOf } from '@dxos/echo-schema';
9
9
  import { SettingsStore } from '@dxos/local-storage';
10
+ import { AttentionCapabilities } from '@dxos/plugin-attention';
10
11
  import { fullyQualifiedId } from '@dxos/react-client/echo';
11
- import { TextType } from '@dxos/schema';
12
+ import { DataType } from '@dxos/schema';
12
13
 
13
14
  import { MarkdownCapabilities } from './capabilities';
14
- import { MarkdownContainer, MarkdownSettings } from '../components';
15
+ import { MarkdownContainer, MarkdownSettings, MarkdownPreview } from '../components';
15
16
  import { MARKDOWN_PLUGIN } from '../meta';
16
17
  import { DocumentType, isEditorModel, type MarkdownSettingsProps } from '../types';
17
18
 
@@ -23,9 +24,11 @@ export default () =>
23
24
  filter: (data): data is { subject: DocumentType; variant: undefined } =>
24
25
  isInstanceOf(DocumentType, data.subject) && !data.variant,
25
26
  component: ({ data, role }) => {
27
+ const selectionManager = useCapability(AttentionCapabilities.Selection);
26
28
  const settingsStore = useCapability(Capabilities.SettingsStore);
27
29
  const settings = settingsStore.getStore<MarkdownSettingsProps>(MARKDOWN_PLUGIN)!.value;
28
30
  const { state, editorState, getViewMode, setViewMode } = useCapability(MarkdownCapabilities.State);
31
+ const viewMode = getViewMode(fullyQualifiedId(data.subject));
29
32
 
30
33
  return (
31
34
  <MarkdownContainer
@@ -33,8 +36,9 @@ export default () =>
33
36
  object={data.subject}
34
37
  role={role}
35
38
  settings={settings}
39
+ selectionManager={selectionManager}
36
40
  extensionProviders={state.extensionProviders}
37
- viewMode={getViewMode(fullyQualifiedId(data.subject))}
41
+ viewMode={viewMode}
38
42
  editorStateStore={editorState}
39
43
  onViewModeChange={setViewMode}
40
44
  />
@@ -44,9 +48,10 @@ export default () =>
44
48
  createSurface({
45
49
  id: `${MARKDOWN_PLUGIN}/text`,
46
50
  role: ['article', 'section', 'tabpanel'],
47
- filter: (data): data is { id: string; subject: TextType } =>
48
- typeof data.id === 'string' && isInstanceOf(TextType, data.subject),
51
+ filter: (data): data is { id: string; subject: DataType.Text } =>
52
+ typeof data.id === 'string' && isInstanceOf(DataType.Text, data.subject),
49
53
  component: ({ data, role }) => {
54
+ const selectionManager = useCapability(AttentionCapabilities.Selection);
50
55
  const settingsStore = useCapability(Capabilities.SettingsStore);
51
56
  const settings = settingsStore.getStore<MarkdownSettingsProps>(MARKDOWN_PLUGIN)!.value;
52
57
  const { state, editorState, getViewMode, setViewMode } = useCapability(MarkdownCapabilities.State);
@@ -57,6 +62,7 @@ export default () =>
57
62
  object={data.subject}
58
63
  role={role}
59
64
  settings={settings}
65
+ selectionManager={selectionManager}
60
66
  extensionProviders={state.extensionProviders}
61
67
  viewMode={getViewMode(data.id)}
62
68
  editorStateStore={editorState}
@@ -70,6 +76,7 @@ export default () =>
70
76
  role: ['article', 'section'],
71
77
  filter: (data): data is { subject: { id: string; text: string } } => isEditorModel(data.subject),
72
78
  component: ({ data, role }) => {
79
+ const selectionManager = useCapability(AttentionCapabilities.Selection);
73
80
  const settingsStore = useCapability(Capabilities.SettingsStore);
74
81
  const settings = settingsStore.getStore<MarkdownSettingsProps>(MARKDOWN_PLUGIN)!.value;
75
82
  const { state, editorState, getViewMode, setViewMode } = useCapability(MarkdownCapabilities.State);
@@ -80,6 +87,7 @@ export default () =>
80
87
  object={data.subject}
81
88
  role={role}
82
89
  settings={settings}
90
+ selectionManager={selectionManager}
83
91
  extensionProviders={state.extensionProviders}
84
92
  viewMode={getViewMode(data.subject.id)}
85
93
  editorStateStore={editorState}
@@ -95,4 +103,11 @@ export default () =>
95
103
  data.subject instanceof SettingsStore && data.subject.prefix === MARKDOWN_PLUGIN,
96
104
  component: ({ data: { subject } }) => <MarkdownSettings settings={subject.value} />,
97
105
  }),
106
+ createSurface({
107
+ id: `${MARKDOWN_PLUGIN}/preview`,
108
+ role: 'popover',
109
+ filter: (data): data is { subject: DocumentType | DataType.Text } =>
110
+ isInstanceOf(DocumentType, data.subject) || isInstanceOf(DataType.Text, data.subject),
111
+ component: ({ data, role }) => <MarkdownPreview {...data} role={role} />,
112
+ }),
98
113
  ]);
@@ -3,13 +3,13 @@
3
3
  //
4
4
 
5
5
  import { Capabilities, contributes } from '@dxos/app-framework';
6
- import { create } from '@dxos/live-object';
6
+ import { live } from '@dxos/live-object';
7
7
 
8
8
  import { MARKDOWN_PLUGIN } from '../meta';
9
9
  import { type MarkdownSettingsProps, MarkdownSettingsSchema } from '../types';
10
10
 
11
11
  export default () => {
12
- const settings = create<MarkdownSettingsProps>({
12
+ const settings = live<MarkdownSettingsProps>({
13
13
  defaultViewMode: 'preview',
14
14
  toolbar: true,
15
15
  numberedHeadings: true,
@@ -2,7 +2,7 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { Capabilities, contributes, type PluginsContext } from '@dxos/app-framework';
5
+ import { Capabilities, contributes, type PluginContext } from '@dxos/app-framework';
6
6
  import { LocalStorageStore } from '@dxos/local-storage';
7
7
  import { type EditorViewMode, createEditorStateStore } from '@dxos/react-ui-editor';
8
8
 
@@ -10,9 +10,8 @@ import { MarkdownCapabilities } from './capabilities';
10
10
  import { MARKDOWN_PLUGIN } from '../meta';
11
11
  import { type MarkdownPluginState, type MarkdownSettingsProps } from '../types';
12
12
 
13
- export default (context: PluginsContext) => {
13
+ export default (context: PluginContext) => {
14
14
  const state = new LocalStorageStore<MarkdownPluginState>(MARKDOWN_PLUGIN, { extensionProviders: [], viewMode: {} });
15
-
16
15
  state.prop({ key: 'viewMode', type: LocalStorageStore.json<{ [key: string]: EditorViewMode }>() });
17
16
 
18
17
  // TODO(wittjosiah): Fold into state.
@@ -20,12 +19,13 @@ export default (context: PluginsContext) => {
20
19
 
21
20
  const getViewMode = (id: string) => {
22
21
  const defaultViewMode = context
23
- .requestCapability(Capabilities.SettingsStore)
22
+ .getCapability(Capabilities.SettingsStore)
24
23
  .getStore<MarkdownSettingsProps>(MARKDOWN_PLUGIN)!.value.defaultViewMode;
25
24
  return (id && state.values.viewMode[id]) || defaultViewMode;
26
25
  };
27
26
 
28
27
  const setViewMode = (id: string, viewMode: EditorViewMode) => (state.values.viewMode[id] = viewMode);
29
28
 
29
+ // Return object with methods.
30
30
  return contributes(MarkdownCapabilities.State, { state: state.values, editorState, getViewMode, setViewMode });
31
31
  };
@@ -2,12 +2,14 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
+ import { Rx } from '@effect-rx/rx-react';
5
6
  import React, { useEffect, useMemo } from 'react';
6
7
 
7
- import { Capabilities, useCapabilities } from '@dxos/app-framework';
8
+ import { Capabilities, useAppGraph, useCapabilities } from '@dxos/app-framework';
8
9
  import { isInstanceOf } from '@dxos/echo-schema';
9
10
  import { fullyQualifiedId, getSpace } from '@dxos/react-client/echo';
10
- import { TextType } from '@dxos/schema';
11
+ import { type SelectionManager } from '@dxos/react-ui-attention';
12
+ import { DataType } from '@dxos/schema';
11
13
 
12
14
  import { MarkdownEditor, type MarkdownEditorProps } from './MarkdownEditor';
13
15
  import { useExtensions } from '../extensions';
@@ -19,25 +21,26 @@ export type MarkdownContainerProps = Pick<
19
21
  'role' | 'extensionProviders' | 'viewMode' | 'editorStateStore' | 'onViewModeChange'
20
22
  > & {
21
23
  id: string;
22
- object: DocumentType | TextType | any;
24
+ object: DocumentType | DataType.Text | any;
23
25
  settings: MarkdownSettingsProps;
26
+ selectionManager?: SelectionManager;
24
27
  };
25
28
 
26
- // TODO(burdon): Move toolbar here.
27
29
  // TODO(burdon): Factor out difference for ECHO and non-ECHO objects; i.e., single component.
28
30
  const MarkdownContainer = ({
29
31
  id,
30
32
  role,
31
33
  object,
32
34
  settings,
35
+ selectionManager,
33
36
  viewMode,
34
37
  editorStateStore,
35
38
  onViewModeChange,
36
39
  }: MarkdownContainerProps) => {
37
40
  const scrollPastEnd = role === 'article';
38
41
  const doc = isInstanceOf(DocumentType, object) ? object : undefined;
39
- const text = isInstanceOf(TextType, object) ? object : undefined;
40
- const extensions = useExtensions({ document: doc, text, id, settings, viewMode, editorStateStore });
42
+ const text = isInstanceOf(DataType.Text, object) ? object : undefined;
43
+ const extensions = useExtensions({ document: doc, text, id, settings, selectionManager, viewMode, editorStateStore });
41
44
 
42
45
  if (doc) {
43
46
  return (
@@ -61,13 +64,13 @@ const MarkdownContainer = ({
61
64
  extensions={extensions}
62
65
  viewMode={viewMode}
63
66
  toolbar={settings.toolbar}
64
- comment={false}
65
67
  inputMode={settings.editorInputMode}
66
68
  scrollPastEnd={scrollPastEnd}
67
69
  onViewModeChange={onViewModeChange}
68
70
  />
69
71
  );
70
72
  } else {
73
+ // TODO(burdon): Normalize with above.
71
74
  return (
72
75
  <MarkdownEditor
73
76
  id={id}
@@ -115,12 +118,22 @@ export const DocumentEditor = ({ id, document: doc, settings, viewMode, ...props
115
118
  return async (file: File) => upload!(file, space);
116
119
  }, [space, upload]);
117
120
 
121
+ const { graph } = useAppGraph();
122
+ const customActions = useMemo(() => {
123
+ return Rx.make((get) => {
124
+ const actions = get(graph.actions(id));
125
+ const nodes = actions.filter((action) => action.properties.disposition === 'toolbar');
126
+ return { nodes, edges: nodes.map((node) => ({ source: 'root', target: node.id })) };
127
+ });
128
+ }, [graph]);
129
+
118
130
  return (
119
131
  <MarkdownEditor
120
132
  id={id}
121
133
  initialValue={doc.content?.target?.content}
122
134
  viewMode={viewMode}
123
135
  toolbar={settings.toolbar}
136
+ customActions={customActions}
124
137
  inputMode={settings.editorInputMode}
125
138
  onFileUpload={handleFileUpload}
126
139
  {...props}
@@ -10,19 +10,14 @@ import React, { useMemo } from 'react';
10
10
  import { IntentPlugin } from '@dxos/app-framework';
11
11
  import { withPluginManager } from '@dxos/app-framework/testing';
12
12
  import { createDocAccessor, createObject } from '@dxos/react-client/echo';
13
- import { Main } from '@dxos/react-ui';
14
- import { AttendableContainer } from '@dxos/react-ui-attention';
15
13
  import { withAttention } from '@dxos/react-ui-attention/testing';
16
- import { editorWithToolbarLayout, automerge, translations as editorTranslations } from '@dxos/react-ui-editor';
17
- import { topbarBlockPaddingStart } from '@dxos/react-ui-theme';
14
+ import { automerge, translations as editorTranslations } from '@dxos/react-ui-editor';
18
15
  import { withLayout, withTheme } from '@dxos/storybook-utils';
19
16
 
20
17
  import { MarkdownEditor, type MarkdownEditorProps } from './MarkdownEditor';
21
- import translations from '../translations';
18
+ import translations from '../../translations';
22
19
 
23
- const content = Array.from({ length: 100 })
24
- .map((_, i) => `Line ${i + 1}`)
25
- .join('\n');
20
+ const content = Array.from({ length: 100 }, (_, i) => `Line ${i + 1}`).join('\n');
26
21
 
27
22
  type StoryProps = MarkdownEditorProps & {
28
23
  content?: string;
@@ -32,19 +27,26 @@ type StoryProps = MarkdownEditorProps & {
32
27
  const DefaultStory = ({ content = '# Test', toolbar }: StoryProps) => {
33
28
  const doc = useMemo(() => createObject({ content }), [content]);
34
29
  const extensions = useMemo(() => [automerge(createDocAccessor(doc, ['content']))], [doc]);
35
- return (
36
- <Main.Content
37
- bounce
38
- data-toolbar={toolbar ? 'enabled' : 'disabled'}
39
- classNames={[topbarBlockPaddingStart, editorWithToolbarLayout]}
40
- >
41
- <AttendableContainer id='test'>
42
- <MarkdownEditor id='test' initialValue={doc.content} extensions={extensions} toolbar={toolbar} />
43
- </AttendableContainer>
44
- </Main.Content>
45
- );
30
+ return <MarkdownEditor id='test' initialValue={doc.content} extensions={extensions} toolbar={toolbar} />;
46
31
  };
47
32
 
33
+ const meta: Meta<typeof MarkdownEditor> = {
34
+ title: 'plugins/plugin-markdown/MarkdownEditor',
35
+ component: MarkdownEditor,
36
+ render: DefaultStory,
37
+ decorators: [
38
+ withPluginManager({ plugins: [IntentPlugin()] }),
39
+ withAttention,
40
+ withTheme,
41
+ withLayout({ fullscreen: true }),
42
+ ],
43
+ parameters: {
44
+ translations: [...translations, ...editorTranslations],
45
+ },
46
+ };
47
+
48
+ export default meta;
49
+
48
50
  export const Default = {
49
51
  args: {
50
52
  content,
@@ -53,22 +55,7 @@ export const Default = {
53
55
 
54
56
  export const WithToolbar = {
55
57
  args: {
56
- content,
57
58
  toolbar: true,
59
+ content,
58
60
  },
59
61
  };
60
-
61
- const meta: Meta<typeof MarkdownEditor> = {
62
- title: 'plugins/plugin-markdown/EditorMain',
63
- component: MarkdownEditor,
64
- render: DefaultStory,
65
- decorators: [
66
- withTheme,
67
- withLayout({ tooltips: true }),
68
- withAttention,
69
- withPluginManager({ plugins: [IntentPlugin()] }),
70
- ],
71
- parameters: { layout: 'fullscreen', translations: [...translations, ...editorTranslations] },
72
- };
73
-
74
- export default meta;