@dxos/plugin-debug 0.10.0 → 0.11.1

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 (236) hide show
  1. package/PLUGIN.mdl +12 -325
  2. package/README.md +4 -14
  3. package/dist/lib/DebugPlugin.mjs +29 -0
  4. package/dist/lib/DebugPlugin.mjs.map +1 -0
  5. package/dist/lib/DebugPlugin.node.mjs +10 -0
  6. package/dist/lib/DebugPlugin.node.mjs.map +1 -0
  7. package/dist/lib/DebugPlugin.workerd.mjs +8 -0
  8. package/dist/lib/DebugPlugin.workerd.mjs.map +1 -0
  9. package/dist/lib/capabilities.mjs +11 -0
  10. package/dist/lib/capabilities.mjs.map +1 -0
  11. package/dist/lib/chunk-DebugObjectPanel.mjs +58 -0
  12. package/dist/lib/chunk-DebugObjectPanel.mjs.map +1 -0
  13. package/dist/lib/chunk-DebugSettings.mjs +237 -0
  14. package/dist/lib/chunk-DebugSettings.mjs.map +1 -0
  15. package/dist/lib/chunk-DebugSpaceObjectsPanel.mjs +39 -0
  16. package/dist/lib/chunk-DebugSpaceObjectsPanel.mjs.map +1 -0
  17. package/dist/lib/chunk-DebugStatus.mjs +117 -0
  18. package/dist/lib/chunk-DebugStatus.mjs.map +1 -0
  19. package/dist/lib/chunk-LogStatus.mjs +44 -0
  20. package/dist/lib/chunk-LogStatus.mjs.map +1 -0
  21. package/dist/lib/chunk-SpaceGenerator.mjs +208 -0
  22. package/dist/lib/chunk-SpaceGenerator.mjs.map +1 -0
  23. package/dist/lib/chunk-StatsPanel.mjs +58 -0
  24. package/dist/lib/chunk-StatsPanel.mjs.map +1 -0
  25. package/dist/lib/chunk-Wireframe.mjs +60 -0
  26. package/dist/lib/chunk-Wireframe.mjs.map +1 -0
  27. package/dist/lib/chunk-app-graph-builder.mjs +76 -0
  28. package/dist/lib/chunk-app-graph-builder.mjs.map +1 -0
  29. package/dist/lib/chunk-log-recording.mjs +17 -0
  30. package/dist/lib/chunk-log-recording.mjs.map +1 -0
  31. package/dist/lib/chunk-meta.mjs +36 -0
  32. package/dist/lib/chunk-meta.mjs.map +1 -0
  33. package/dist/lib/chunk-react-surface.mjs +193 -0
  34. package/dist/lib/chunk-react-surface.mjs.map +1 -0
  35. package/dist/lib/chunk-settings.mjs +23 -0
  36. package/dist/lib/chunk-settings.mjs.map +1 -0
  37. package/dist/lib/chunk-stats-panel.mjs +56 -0
  38. package/dist/lib/chunk-stats-panel.mjs.map +1 -0
  39. package/dist/lib/chunk-types.mjs +60 -0
  40. package/dist/lib/chunk-types.mjs.map +1 -0
  41. package/dist/lib/components.mjs +763 -0
  42. package/dist/lib/components.mjs.map +1 -0
  43. package/dist/lib/containers.mjs +14 -0
  44. package/dist/lib/containers.mjs.map +1 -0
  45. package/dist/lib/index.mjs +3 -0
  46. package/dist/lib/meta.mjs +2 -0
  47. package/dist/lib/plugin.mjs +8 -0
  48. package/dist/lib/plugin.mjs.map +1 -0
  49. package/dist/lib/translations.mjs +38 -0
  50. package/dist/lib/translations.mjs.map +1 -0
  51. package/dist/lib/types.mjs +2 -0
  52. package/dist/types/src/DebugPlugin.d.ts.map +1 -1
  53. package/dist/types/src/capabilities/DebugSurfaces.d.ts +25 -0
  54. package/dist/types/src/capabilities/DebugSurfaces.d.ts.map +1 -0
  55. package/dist/types/src/capabilities/app-graph-builder.d.ts +1 -1
  56. package/dist/types/src/capabilities/index.d.ts +4 -1
  57. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  58. package/dist/types/src/capabilities/log-recording.d.ts +10 -0
  59. package/dist/types/src/capabilities/log-recording.d.ts.map +1 -0
  60. package/dist/types/src/capabilities/react-surface.d.ts +1 -1
  61. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
  62. package/dist/types/src/capabilities/settings.d.ts +1 -1
  63. package/dist/types/src/capabilities/stats-panel.d.ts +16 -0
  64. package/dist/types/src/capabilities/stats-panel.d.ts.map +1 -0
  65. package/dist/types/src/components/SchemaTable/SchemaTable.d.ts +4 -3
  66. package/dist/types/src/components/SchemaTable/SchemaTable.d.ts.map +1 -1
  67. package/dist/types/src/components/SpaceGenerator/ObjectGenerator.d.ts.map +1 -1
  68. package/dist/types/src/containers/DebugObjectPanel/DebugObjectPanel.d.ts +4 -1
  69. package/dist/types/src/containers/DebugObjectPanel/DebugObjectPanel.d.ts.map +1 -1
  70. package/dist/types/src/containers/DebugSettings/DebugSettings.d.ts +4 -1
  71. package/dist/types/src/containers/DebugSettings/DebugSettings.d.ts.map +1 -1
  72. package/dist/types/src/containers/DebugSettings/DebugSettings.stories.d.ts +30 -58
  73. package/dist/types/src/containers/DebugSettings/DebugSettings.stories.d.ts.map +1 -1
  74. package/dist/types/src/containers/DebugSpaceObjectsPanel/DebugSpaceObjectsPanel.d.ts +4 -1
  75. package/dist/types/src/containers/DebugSpaceObjectsPanel/DebugSpaceObjectsPanel.d.ts.map +1 -1
  76. package/dist/types/src/containers/DebugStatus/DebugStatus.d.ts +4 -1
  77. package/dist/types/src/containers/DebugStatus/DebugStatus.d.ts.map +1 -1
  78. package/dist/types/src/containers/LogStatus/LogStatus.d.ts +6 -0
  79. package/dist/types/src/containers/LogStatus/LogStatus.d.ts.map +1 -0
  80. package/dist/types/src/containers/LogStatus/index.d.ts +2 -0
  81. package/dist/types/src/containers/LogStatus/index.d.ts.map +1 -0
  82. package/dist/types/src/containers/SpaceGenerator/SpaceGenerator.d.ts +1 -1
  83. package/dist/types/src/containers/SpaceGenerator/SpaceGenerator.d.ts.map +1 -1
  84. package/dist/types/src/containers/StatsPanel/StatsPanel.d.ts +6 -0
  85. package/dist/types/src/containers/StatsPanel/StatsPanel.d.ts.map +1 -0
  86. package/dist/types/src/containers/StatsPanel/index.d.ts +2 -0
  87. package/dist/types/src/containers/StatsPanel/index.d.ts.map +1 -0
  88. package/dist/types/src/containers/Wireframe/Wireframe.d.ts +4 -1
  89. package/dist/types/src/containers/Wireframe/Wireframe.d.ts.map +1 -1
  90. package/dist/types/src/containers/index.d.ts +4 -6
  91. package/dist/types/src/containers/index.d.ts.map +1 -1
  92. package/dist/types/src/translations.d.ts +26 -57
  93. package/dist/types/src/translations.d.ts.map +1 -1
  94. package/dist/types/src/types/DebugNodes.d.ts +7 -0
  95. package/dist/types/src/types/DebugNodes.d.ts.map +1 -0
  96. package/dist/types/src/types/DebugSurface.d.ts +8 -0
  97. package/dist/types/src/types/DebugSurface.d.ts.map +1 -0
  98. package/dist/types/src/types/debug.d.ts +3 -1
  99. package/dist/types/src/types/debug.d.ts.map +1 -1
  100. package/dist/types/src/types/index.d.ts +2 -2
  101. package/dist/types/src/types/index.d.ts.map +1 -1
  102. package/dist/types/tsconfig.tsbuildinfo +1 -1
  103. package/dx.config.ts +8 -13
  104. package/package.json +61 -63
  105. package/src/DebugPlugin.node.ts +1 -1
  106. package/src/DebugPlugin.tsx +10 -27
  107. package/src/DebugPlugin.workerd.ts +1 -1
  108. package/src/capabilities/DebugSurfaces.tsx +146 -0
  109. package/src/capabilities/app-graph-builder.ts +39 -373
  110. package/src/capabilities/index.ts +3 -2
  111. package/src/capabilities/log-recording.ts +20 -0
  112. package/src/capabilities/react-surface.ts +123 -0
  113. package/src/capabilities/stats-panel.ts +74 -0
  114. package/src/components/SchemaTable/SchemaTable.tsx +6 -5
  115. package/src/components/SpaceGenerator/ObjectGenerator.tsx +9 -3
  116. package/src/components/SpaceGenerator/presets.ts +2 -2
  117. package/src/components/index.ts +1 -1
  118. package/src/containers/DebugObjectPanel/DebugObjectPanel.tsx +20 -20
  119. package/src/containers/DebugSettings/DebugSettings.tsx +4 -3
  120. package/src/containers/DebugSpaceObjectsPanel/DebugSpaceObjectsPanel.tsx +4 -2
  121. package/src/containers/DebugStatus/DebugStatus.tsx +2 -0
  122. package/src/containers/LogStatus/LogStatus.tsx +51 -0
  123. package/src/containers/LogStatus/index.ts +5 -0
  124. package/src/containers/SpaceGenerator/SpaceGenerator.tsx +108 -10
  125. package/src/containers/StatsPanel/StatsPanel.tsx +74 -0
  126. package/src/containers/StatsPanel/index.ts +5 -0
  127. package/src/containers/Wireframe/Wireframe.tsx +2 -0
  128. package/src/containers/index.ts +9 -7
  129. package/src/index.ts +1 -1
  130. package/src/meta.ts +1 -1
  131. package/src/plugin.ts +1 -1
  132. package/src/translations.ts +8 -52
  133. package/src/types/DebugNodes.ts +18 -0
  134. package/src/types/DebugSurface.ts +16 -0
  135. package/src/types/debug.ts +3 -1
  136. package/src/types/index.ts +3 -3
  137. package/dist/lib/neutral/DebugGraph-G4FWS57E.mjs +0 -15
  138. package/dist/lib/neutral/DebugGraph-G4FWS57E.mjs.map +0 -7
  139. package/dist/lib/neutral/DebugObjectPanel-QSGQJ3LM.mjs +0 -61
  140. package/dist/lib/neutral/DebugObjectPanel-QSGQJ3LM.mjs.map +0 -7
  141. package/dist/lib/neutral/DebugPlugin.mjs +0 -59
  142. package/dist/lib/neutral/DebugPlugin.mjs.map +0 -7
  143. package/dist/lib/neutral/DebugPlugin.node.mjs +0 -18
  144. package/dist/lib/neutral/DebugPlugin.node.mjs.map +0 -7
  145. package/dist/lib/neutral/DebugPlugin.workerd.mjs +0 -12
  146. package/dist/lib/neutral/DebugPlugin.workerd.mjs.map +0 -7
  147. package/dist/lib/neutral/DebugSettings-Q3WUL6YQ.mjs +0 -229
  148. package/dist/lib/neutral/DebugSettings-Q3WUL6YQ.mjs.map +0 -7
  149. package/dist/lib/neutral/DebugSpaceObjectsPanel-AXFZWEIM.mjs +0 -36
  150. package/dist/lib/neutral/DebugSpaceObjectsPanel-AXFZWEIM.mjs.map +0 -7
  151. package/dist/lib/neutral/DebugStatus-H2BAHN26.mjs +0 -122
  152. package/dist/lib/neutral/DebugStatus-H2BAHN26.mjs.map +0 -7
  153. package/dist/lib/neutral/DevtoolsOverviewContainer-DWQHTK7D.mjs +0 -24
  154. package/dist/lib/neutral/DevtoolsOverviewContainer-DWQHTK7D.mjs.map +0 -7
  155. package/dist/lib/neutral/GithubPanel-4CSJRVKE.mjs +0 -177
  156. package/dist/lib/neutral/GithubPanel-4CSJRVKE.mjs.map +0 -7
  157. package/dist/lib/neutral/RegistryPanel-64GIYJHN.mjs +0 -161
  158. package/dist/lib/neutral/RegistryPanel-64GIYJHN.mjs.map +0 -7
  159. package/dist/lib/neutral/SpaceGenerator-Y35G6DRV.mjs +0 -146
  160. package/dist/lib/neutral/SpaceGenerator-Y35G6DRV.mjs.map +0 -7
  161. package/dist/lib/neutral/Wireframe-WD7S2AUU.mjs +0 -52
  162. package/dist/lib/neutral/Wireframe-WD7S2AUU.mjs.map +0 -7
  163. package/dist/lib/neutral/app-graph-builder-UKG4WVYK.mjs +0 -619
  164. package/dist/lib/neutral/app-graph-builder-UKG4WVYK.mjs.map +0 -7
  165. package/dist/lib/neutral/capabilities/index.mjs +0 -15
  166. package/dist/lib/neutral/capabilities/index.mjs.map +0 -7
  167. package/dist/lib/neutral/chunk-72QXLYMI.mjs +0 -118
  168. package/dist/lib/neutral/chunk-72QXLYMI.mjs.map +0 -7
  169. package/dist/lib/neutral/chunk-J5LGTIGS.mjs +0 -10
  170. package/dist/lib/neutral/chunk-J5LGTIGS.mjs.map +0 -7
  171. package/dist/lib/neutral/chunk-R5C4CKOF.mjs +0 -54
  172. package/dist/lib/neutral/chunk-R5C4CKOF.mjs.map +0 -7
  173. package/dist/lib/neutral/components/index.mjs +0 -961
  174. package/dist/lib/neutral/components/index.mjs.map +0 -7
  175. package/dist/lib/neutral/containers/index.mjs +0 -27
  176. package/dist/lib/neutral/containers/index.mjs.map +0 -7
  177. package/dist/lib/neutral/index.mjs +0 -20
  178. package/dist/lib/neutral/index.mjs.map +0 -7
  179. package/dist/lib/neutral/meta.json +0 -1
  180. package/dist/lib/neutral/meta.mjs +0 -8
  181. package/dist/lib/neutral/meta.mjs.map +0 -7
  182. package/dist/lib/neutral/plugin.mjs +0 -12
  183. package/dist/lib/neutral/plugin.mjs.map +0 -7
  184. package/dist/lib/neutral/react-context-UJURDOO6.mjs +0 -17
  185. package/dist/lib/neutral/react-context-UJURDOO6.mjs.map +0 -7
  186. package/dist/lib/neutral/react-surface-URESE7J4.mjs +0 -484
  187. package/dist/lib/neutral/react-surface-URESE7J4.mjs.map +0 -7
  188. package/dist/lib/neutral/settings-5I2674B6.mjs +0 -28
  189. package/dist/lib/neutral/settings-5I2674B6.mjs.map +0 -7
  190. package/dist/lib/neutral/translations.mjs +0 -91
  191. package/dist/lib/neutral/translations.mjs.map +0 -7
  192. package/dist/lib/neutral/types/index.mjs +0 -16
  193. package/dist/lib/neutral/types/index.mjs.map +0 -7
  194. package/dist/types/src/DebugPlugin.test.d.ts +0 -2
  195. package/dist/types/src/DebugPlugin.test.d.ts.map +0 -1
  196. package/dist/types/src/capabilities/react-context.d.ts +0 -5
  197. package/dist/types/src/capabilities/react-context.d.ts.map +0 -1
  198. package/dist/types/src/containers/DebugGraph/DebugGraph.d.ts +0 -8
  199. package/dist/types/src/containers/DebugGraph/DebugGraph.d.ts.map +0 -1
  200. package/dist/types/src/containers/DebugGraph/index.d.ts +0 -2
  201. package/dist/types/src/containers/DebugGraph/index.d.ts.map +0 -1
  202. package/dist/types/src/containers/DevtoolsOverviewContainer/DevtoolsOverviewContainer.d.ts +0 -3
  203. package/dist/types/src/containers/DevtoolsOverviewContainer/DevtoolsOverviewContainer.d.ts.map +0 -1
  204. package/dist/types/src/containers/DevtoolsOverviewContainer/index.d.ts +0 -2
  205. package/dist/types/src/containers/DevtoolsOverviewContainer/index.d.ts.map +0 -1
  206. package/dist/types/src/containers/GithubPanel/GithubComponent.d.ts +0 -15
  207. package/dist/types/src/containers/GithubPanel/GithubComponent.d.ts.map +0 -1
  208. package/dist/types/src/containers/GithubPanel/GithubComponent.stories.d.ts +0 -106
  209. package/dist/types/src/containers/GithubPanel/GithubComponent.stories.d.ts.map +0 -1
  210. package/dist/types/src/containers/GithubPanel/GithubPanel.d.ts +0 -3
  211. package/dist/types/src/containers/GithubPanel/GithubPanel.d.ts.map +0 -1
  212. package/dist/types/src/containers/GithubPanel/index.d.ts +0 -2
  213. package/dist/types/src/containers/GithubPanel/index.d.ts.map +0 -1
  214. package/dist/types/src/containers/RegistryPanel/RegistryPanel.d.ts +0 -3
  215. package/dist/types/src/containers/RegistryPanel/RegistryPanel.d.ts.map +0 -1
  216. package/dist/types/src/containers/RegistryPanel/index.d.ts +0 -2
  217. package/dist/types/src/containers/RegistryPanel/index.d.ts.map +0 -1
  218. package/dist/types/src/types/Devtools.d.ts +0 -57
  219. package/dist/types/src/types/Devtools.d.ts.map +0 -1
  220. package/dist/types/src/types/surface.d.ts +0 -4
  221. package/dist/types/src/types/surface.d.ts.map +0 -1
  222. package/src/DebugPlugin.test.ts +0 -29
  223. package/src/capabilities/react-context.tsx +0 -25
  224. package/src/capabilities/react-surface.tsx +0 -504
  225. package/src/containers/DebugGraph/DebugGraph.tsx +0 -14
  226. package/src/containers/DebugGraph/index.ts +0 -5
  227. package/src/containers/DevtoolsOverviewContainer/DevtoolsOverviewContainer.tsx +0 -27
  228. package/src/containers/DevtoolsOverviewContainer/index.ts +0 -5
  229. package/src/containers/GithubPanel/GithubComponent.stories.tsx +0 -38
  230. package/src/containers/GithubPanel/GithubComponent.tsx +0 -192
  231. package/src/containers/GithubPanel/GithubPanel.tsx +0 -17
  232. package/src/containers/GithubPanel/index.ts +0 -5
  233. package/src/containers/RegistryPanel/RegistryPanel.tsx +0 -150
  234. package/src/containers/RegistryPanel/index.ts +0 -5
  235. package/src/types/Devtools.ts +0 -73
  236. package/src/types/surface.ts +0 -10
@@ -0,0 +1,74 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import { Atom } from '@effect-atom/atom';
6
+ import * as Effect from 'effect/Effect';
7
+
8
+ import { Capabilities, Capability } from '@dxos/app-framework';
9
+ import { AppCapabilities } from '@dxos/app-toolkit';
10
+
11
+ import { meta } from '#meta';
12
+
13
+ type StatsPanelOptions = {
14
+ /** Persist the store to localStorage (hydrate on load, save on write). */
15
+ persist?: boolean;
16
+ };
17
+
18
+ const STORAGE_KEY = `${meta.profile.key}.statsPanel`;
19
+
20
+ /**
21
+ * Contributes the {@link AppCapabilities.StatsPanel} store: a single reactive atom holding one
22
+ * compartment per plugin, keyed by plugin key. Read access spans the whole store; writes are scoped
23
+ * to a compartment via `compartment(pluginKey)`. Kept alive with `Atom.keepAlive` so a background
24
+ * writer (e.g. a sync operation) can populate it before any surface subscribes. When `persist` is set
25
+ * the store hydrates from and saves to localStorage so stats survive a reload.
26
+ */
27
+ export default Capability.makeModule(
28
+ Effect.fnUntraced(function* ({ persist = true }: StatsPanelOptions = {}) {
29
+ const registry = yield* Capability.get(Capabilities.AtomRegistry);
30
+ const canPersist = persist && typeof localStorage !== 'undefined';
31
+
32
+ const hydrate = (): Record<string, unknown> => {
33
+ if (!canPersist) {
34
+ return {};
35
+ }
36
+ try {
37
+ const raw = localStorage.getItem(STORAGE_KEY);
38
+ return raw ? JSON.parse(raw) : {};
39
+ } catch {
40
+ // Best-effort: a malformed/unavailable value just starts empty.
41
+ return {};
42
+ }
43
+ };
44
+
45
+ const statsAtom = Atom.make<Record<string, unknown>>(hydrate()).pipe(Atom.keepAlive);
46
+
47
+ const save = () => {
48
+ if (!canPersist) {
49
+ return;
50
+ }
51
+ try {
52
+ localStorage.setItem(STORAGE_KEY, JSON.stringify(registry.get(statsAtom)));
53
+ } catch {
54
+ // Best-effort: localStorage may be disabled or over quota; the in-memory atom is authoritative.
55
+ }
56
+ };
57
+
58
+ return Capability.contributes(AppCapabilities.StatsPanel, {
59
+ statsAtom,
60
+ get: (pluginKey) => registry.get(statsAtom)[pluginKey],
61
+ compartment: (pluginKey) => ({
62
+ set: (stats) => {
63
+ registry.set(statsAtom, { ...registry.get(statsAtom), [pluginKey]: stats });
64
+ save();
65
+ },
66
+ clear: () => {
67
+ const { [pluginKey]: _removed, ...rest } = registry.get(statsAtom);
68
+ registry.set(statsAtom, rest);
69
+ save();
70
+ },
71
+ }),
72
+ });
73
+ }),
74
+ );
@@ -4,18 +4,19 @@
4
4
 
5
5
  import React from 'react';
6
6
 
7
- import { IconButton } from '@dxos/react-ui';
7
+ import { IconButton, ThemedClassName } from '@dxos/react-ui';
8
+ import { mx } from '@dxos/ui-theme';
8
9
 
9
- export type SchemaTableProps = {
10
+ export type SchemaTableProps = ThemedClassName<{
10
11
  types: any[];
11
12
  objects?: Record<string, number | undefined>;
12
13
  label: string;
13
14
  onClick: (typename: string) => void;
14
- };
15
+ }>;
15
16
 
16
- export const SchemaTable = ({ types, objects = {}, label, onClick }: SchemaTableProps) => {
17
+ export const SchemaTable = ({ classNames, types, objects = {}, label, onClick }: SchemaTableProps) => {
17
18
  return (
18
- <div className='grid grid-cols-[1fr_80px_40px] gap-1 overflow-none'>
19
+ <div className={mx('grid grid-cols-[1fr_80px_40px] gap-1 overflow-none', classNames)}>
19
20
  <h2 className='p-2'>{label}</h2>
20
21
  {types.map((type) => (
21
22
  <div key={type.typename} className='grid grid-cols-subgrid col-span-3 items-center'>
@@ -6,10 +6,11 @@ import { addressToA1Notation } from '@dxos/compute-hyperformula';
6
6
  import { ComputeGraph, ComputeGraphModel, DEFAULT_OUTPUT, NODE_INPUT, NODE_OUTPUT } from '@dxos/conductor';
7
7
  import { EID, Filter, Key, Type, View } from '@dxos/echo';
8
8
  import { OperationInvoker } from '@dxos/operation';
9
+ import { Drawing } from '@dxos/plugin-illustrator';
9
10
  import { Markdown } from '@dxos/plugin-markdown';
10
11
  import { Sheet } from '@dxos/plugin-sheet';
11
- import { Sketch } from '@dxos/plugin-sketch';
12
12
  import { SpaceOperation } from '@dxos/plugin-space';
13
+ import { Tldraw } from '@dxos/plugin-tldraw';
13
14
  import { random } from '@dxos/random';
14
15
  import { type Client } from '@dxos/react-client';
15
16
  import { type Space } from '@dxos/react-client/echo';
@@ -70,10 +71,15 @@ export const staticGenerators = new Map<string, ObjectGenerator<any>>([
70
71
  },
71
72
  ],
72
73
  [
73
- Type.getTypename(Sketch.Sketch),
74
+ Type.getTypename(Drawing.Drawing),
74
75
  async (space, n, cb) => {
75
76
  const objects = range(n).map(() => {
76
- const obj = space.db.add(Sketch.make({ name: random.commerce.productName() }));
77
+ const obj = space.db.add(
78
+ Drawing.make({
79
+ name: random.commerce.productName(),
80
+ canvas: Drawing.makeCanvas({ schema: Tldraw.TLDRAW_SCHEMA }),
81
+ }),
82
+ );
77
83
  return obj;
78
84
  });
79
85
 
@@ -121,8 +121,8 @@ export const generator = () => ({
121
121
  invariant(mailbox, 'Mailbox not found');
122
122
  const mailboxFeed = await mailbox.feed?.tryLoad();
123
123
  invariant(mailboxFeed, 'Mailbox missing feed reference');
124
- const queueDxn = Feed.getQueueUri(mailboxFeed);
125
- invariant(queueDxn, 'Mailbox feed missing queue DXN key');
124
+ const feedUri = Feed.getFeedUri(mailboxFeed);
125
+ invariant(feedUri, 'Mailbox feed missing feed URI');
126
126
  const tag = await space.db.query(Filter.type(Tag.Tag, { label: 'Investor' })).first();
127
127
  const tagUri = Obj.getURI(tag);
128
128
 
@@ -1,5 +1,5 @@
1
1
  //
2
- // Copyright 2023 DXOS.org
2
+ // Copyright 2026 DXOS.org
3
3
  //
4
4
 
5
5
  export * from './SchemaTable';
@@ -7,9 +7,9 @@ import React, { useMemo, useState } from 'react';
7
7
  import { AppSurface } from '@dxos/app-toolkit/ui';
8
8
  import { ObjectsTree } from '@dxos/devtools';
9
9
  import { type Entity, Filter, Json, Obj, Query } from '@dxos/echo';
10
+ import { useQuery } from '@dxos/echo-react';
10
11
  import type { EntityId } from '@dxos/keys';
11
- import { useQuery } from '@dxos/react-client/echo';
12
- import { Clipboard, Input, Panel, ScrollArea, Toolbar } from '@dxos/react-ui';
12
+ import { Clipboard, Panel, ScrollArea, Toolbar } from '@dxos/react-ui';
13
13
  import { Syntax } from '@dxos/react-ui-syntax-highlighter';
14
14
  import { mx } from '@dxos/ui-theme';
15
15
 
@@ -24,12 +24,17 @@ export type DebugObjectPanelProps = Pick<
24
24
  export const DebugObjectPanel = ({ role, companionTo, onOpen, canOpen }: DebugObjectPanelProps) => {
25
25
  const db = Obj.getDatabase(companionTo);
26
26
  const [selectedId, setSelectedId] = useState<EntityId | null>(null);
27
- const [depth, setDepth] = useState(0);
28
- const [selectedObject] = useQuery(
29
- db,
30
- Query.select(Filter.id(selectedId ?? companionTo.id)).options({ deleted: 'include' }),
27
+ // Include feeds so that feed-backed objects (e.g. synced games) resolve in the selection query.
28
+ const selectionQuery = useMemo(
29
+ () =>
30
+ db
31
+ ? Query.select(Filter.id(selectedId ?? companionTo.id))
32
+ .options({ deleted: 'include' })
33
+ .from(db, { includeFeeds: true })
34
+ : Query.select(Filter.nothing()),
35
+ [db, selectedId, companionTo.id],
31
36
  );
32
- const refReplacer = useMemo(() => (db ? Json.createRefReplacer({ db, depth }) : undefined), [db, depth]);
37
+ const [selectedObject] = useQuery(db, selectionQuery);
33
38
 
34
39
  return (
35
40
  <Clipboard.Provider>
@@ -38,7 +43,7 @@ export const DebugObjectPanel = ({ role, companionTo, onOpen, canOpen }: DebugOb
38
43
  <Toolbar.Root />
39
44
  </Panel.Toolbar>
40
45
  <Panel.Content asChild>
41
- <div className={mx('grid divide-y divide-separator', db && 'grid-rows-[1fr_2fr]')}>
46
+ <div className={mx('grid divide-y divide-subdued-separator', db && 'grid-rows-[1fr_2fr]')}>
42
47
  {db && (
43
48
  <ScrollArea.Root>
44
49
  <ScrollArea.Viewport>
@@ -52,22 +57,15 @@ export const DebugObjectPanel = ({ role, companionTo, onOpen, canOpen }: DebugOb
52
57
  </ScrollArea.Viewport>
53
58
  </ScrollArea.Root>
54
59
  )}
55
- <Syntax.Root data={selectedObject} replacer={refReplacer}>
60
+ <Syntax.Root
61
+ data={selectedObject}
62
+ getReplacer={(depth) => (db ? Json.createRefReplacer({ db, depth }) : undefined)}
63
+ >
56
64
  <Panel.Root>
57
65
  <Panel.Toolbar asChild>
58
66
  <Toolbar.Root classNames='grid grid-cols-[1fr_3rem]'>
59
67
  <Syntax.Filter />
60
- <Input.Root>
61
- <Input.TextInput
62
- variant='subdued'
63
- type='number'
64
- min={0}
65
- step={1}
66
- aria-label='Ref depth'
67
- value={depth}
68
- onChange={(event) => setDepth(Math.max(0, Number(event.target.value) || 0))}
69
- />
70
- </Input.Root>
68
+ <Syntax.Depth />
71
69
  </Toolbar.Root>
72
70
  </Panel.Toolbar>
73
71
  <Panel.Content asChild>
@@ -83,3 +81,5 @@ export const DebugObjectPanel = ({ role, companionTo, onOpen, canOpen }: DebugOb
83
81
  </Clipboard.Provider>
84
82
  );
85
83
  };
84
+
85
+ DebugObjectPanel.displayName = 'DebugObjectPanel';
@@ -8,7 +8,7 @@ import { AppCapabilities, AppSpace } from '@dxos/app-toolkit';
8
8
  import { type AppSurface } from '@dxos/app-toolkit/ui';
9
9
  import { type ConfigProto, SaveConfig, Storage, defs } from '@dxos/config';
10
10
  import { log } from '@dxos/log';
11
- import { type IdbLogStore } from '@dxos/log-store-idb';
11
+ import { type IdbLogStore, MANUAL_LOG_EXPORT_MAX_BYTES } from '@dxos/log-store-idb';
12
12
  import { useClient } from '@dxos/react-client';
13
13
  import { IconButton, Input, Select, Toast, useFileDownload, useTranslation } from '@dxos/react-ui';
14
14
  import { Form } from '@dxos/react-ui-form';
@@ -92,8 +92,7 @@ export const DebugSettings = ({ settings, onSettingsChange, logStore, onUpload }
92
92
  }, [client, download, handleToast, onUpload, t]);
93
93
 
94
94
  const handleDownloadLogs = useCallback(async () => {
95
- const ndjson = await logStore.export();
96
- const file = new Blob([ndjson], { type: 'application/x-ndjson' });
95
+ const file = await logStore.exportBlob({ maxSize: MANUAL_LOG_EXPORT_MAX_BYTES });
97
96
  const fileName = `composer-logs-${new Date().toISOString().slice(0, 19).replace(/:/g, '-')}.ndjson`;
98
97
  download(file, fileName);
99
98
  }, [download, logStore]);
@@ -259,3 +258,5 @@ const updateConfig = (config: ConfigProto, setConfig: (newConfig: ConfigProto) =
259
258
  await SaveConfig(storageConfigCopy);
260
259
  });
261
260
  };
261
+
262
+ DebugSettings.displayName = 'DebugSettings';
@@ -7,8 +7,8 @@ import React, { useState } from 'react';
7
7
  import { type AppSurface } from '@dxos/app-toolkit/ui';
8
8
  import { ObjectsTree } from '@dxos/devtools';
9
9
  import { type Entity, Filter, Obj, Query } from '@dxos/echo';
10
+ import { useQuery } from '@dxos/echo-react';
10
11
  import { type EntityId } from '@dxos/keys';
11
- import { useQuery } from '@dxos/react-client/echo';
12
12
  import { Clipboard, Grid, Input, Panel, ScrollArea, Toolbar } from '@dxos/react-ui';
13
13
  import { JsonHighlighter } from '@dxos/react-ui-syntax-highlighter';
14
14
 
@@ -35,7 +35,7 @@ export const DebugSpaceObjectsPanel = ({ space, onOpen, canOpen }: DebugSpaceObj
35
35
  </Toolbar.Root>
36
36
  </Panel.Toolbar>
37
37
  <Panel.Content asChild>
38
- <Grid rows={2} classNames='divide-y divide-separator'>
38
+ <Grid rows={2} classNames='divide-y divide-subdued-separator'>
39
39
  <ScrollArea.Root>
40
40
  <ScrollArea.Viewport>
41
41
  <ObjectsTree
@@ -53,3 +53,5 @@ export const DebugSpaceObjectsPanel = ({ space, onOpen, canOpen }: DebugSpaceObj
53
53
  </Clipboard.Provider>
54
54
  );
55
55
  };
56
+
57
+ DebugSpaceObjectsPanel.displayName = 'DebugSpaceObjectsPanel';
@@ -210,3 +210,5 @@ export const DebugStatus = () => {
210
210
  </>
211
211
  );
212
212
  };
213
+
214
+ DebugStatus.displayName = 'DebugStatus';
@@ -0,0 +1,51 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import React from 'react';
6
+
7
+ import { StatusBar } from '@dxos/plugin-status-bar/components';
8
+ import { IconButton, Panel, Popover, useTranslation } from '@dxos/react-ui';
9
+ import { Logger } from '@dxos/react-ui-debug';
10
+
11
+ import { meta } from '#meta';
12
+
13
+ /** Status-bar button that opens the log panel in a popover for a quick glance. */
14
+ export const LogStatus = () => {
15
+ const { t } = useTranslation(meta.profile.key);
16
+
17
+ return (
18
+ <Popover.Root>
19
+ {/* IconButton is the direct trigger child so the trigger ref/handlers/ARIA attach to the button, not the container. */}
20
+ <StatusBar.Item>
21
+ <Popover.Trigger asChild>
22
+ <IconButton variant='ghost' icon='ph--list-magnifying-glass--regular' iconOnly label={t('open-logs.label')} />
23
+ </Popover.Trigger>
24
+ </StatusBar.Item>
25
+ <Popover.Portal>
26
+ <Popover.Content side='top'>
27
+ <Popover.Viewport classNames='w-[40rem] h-[24rem]'>
28
+ <Logger.Root>
29
+ <Panel.Root>
30
+ <Panel.Toolbar asChild>
31
+ <Logger.Toolbar />
32
+ </Panel.Toolbar>
33
+ <Panel.Content asChild>
34
+ <Logger.Content>
35
+ <Logger.List />
36
+ </Logger.Content>
37
+ </Panel.Content>
38
+ <Panel.Statusbar asChild>
39
+ <Logger.Filter />
40
+ </Panel.Statusbar>
41
+ </Panel.Root>
42
+ </Logger.Root>
43
+ </Popover.Viewport>
44
+ <Popover.Arrow />
45
+ </Popover.Content>
46
+ </Popover.Portal>
47
+ </Popover.Root>
48
+ );
49
+ };
50
+
51
+ LogStatus.displayName = 'LogStatus';
@@ -0,0 +1,5 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ export * from './LogStatus';
@@ -2,25 +2,29 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import React, { useCallback, useMemo, useState } from 'react';
5
+ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
6
6
 
7
- import { useOperationInvoker } from '@dxos/app-framework/ui';
7
+ import { useOperationInvoker, useOptionalCapability } from '@dxos/app-framework/ui';
8
+ import { AppCapabilities } from '@dxos/app-toolkit';
9
+ import { useProgress } from '@dxos/app-toolkit/ui';
8
10
  import { ComputeGraph } from '@dxos/conductor';
9
11
  import { Filter, Obj, Type } from '@dxos/echo';
12
+ import { Drawing } from '@dxos/plugin-illustrator';
10
13
  import { Markdown } from '@dxos/plugin-markdown';
11
14
  import { Sheet } from '@dxos/plugin-sheet';
12
- import { Sketch } from '@dxos/plugin-sketch';
13
15
  import { useClient } from '@dxos/react-client';
14
16
  import { type Space } from '@dxos/react-client/echo';
15
- import { IconButton, Input, Panel, ScrollArea, Toolbar, useAsyncEffect } from '@dxos/react-ui';
17
+ import { IconButton, Input, Panel, ScrollArea, ThemedClassName, Toolbar, useAsyncEffect } from '@dxos/react-ui';
16
18
  import { composable, composableProps } from '@dxos/react-ui';
17
19
  import { Organization, Person, Task } from '@dxos/types';
20
+ import { mx } from '@dxos/ui-theme';
18
21
  import { sortKeys } from '@dxos/util';
19
22
 
20
23
  import { type ObjectGenerator, SchemaTable, createGenerator, generator, staticGenerators } from '#components';
24
+ import { meta } from '#meta';
21
25
 
22
26
  // TODO(burdon): Make extensible.
23
- const staticTypes = [Markdown.Document, Sketch.Sketch, Sheet.Sheet, ComputeGraph];
27
+ const staticTypes = [Markdown.Document, Drawing.Drawing, Sheet.Sheet, ComputeGraph];
24
28
  const recordTypes: Type.AnyObj[] = [Organization.Organization, Person.Person, Task.Task];
25
29
 
26
30
  export type SpaceGeneratorProps = {
@@ -94,8 +98,8 @@ export const SpaceGenerator = composable<HTMLDivElement, SpaceGeneratorProps>(
94
98
 
95
99
  return (
96
100
  <Panel.Root {...composableProps(props)} ref={forwardedRef}>
97
- <Panel.Toolbar asChild>
98
- <Toolbar.Root>
101
+ <Panel.Toolbar>
102
+ <Toolbar.Root classNames='dx-document'>
99
103
  <IconButton icon='ph--arrow-clockwise--regular' iconOnly label='Refresh' onClick={updateInfo} />
100
104
  <Toolbar.Separator />
101
105
  <Input.Root>
@@ -115,9 +119,28 @@ export const SpaceGenerator = composable<HTMLDivElement, SpaceGeneratorProps>(
115
119
  <Panel.Content asChild>
116
120
  <ScrollArea.Root thin orientation='vertical'>
117
121
  <ScrollArea.Viewport classNames='dx-document gap-4 divide-y divide-subdued-separator'>
118
- <SchemaTable types={staticTypes} objects={info.objects} label='Static Types' onClick={handleCreateData} />
119
- <SchemaTable types={recordTypes} objects={info.objects} label='Record Types' onClick={handleCreateData} />
120
- <SchemaTable types={presets.types} objects={info.objects} label='Presets' onClick={handleCreateData} />
122
+ <SchemaTable
123
+ classNames='py-1'
124
+ types={staticTypes}
125
+ objects={info.objects}
126
+ label='Static Types'
127
+ onClick={handleCreateData}
128
+ />
129
+ <SchemaTable
130
+ classNames='py-1'
131
+ types={recordTypes}
132
+ objects={info.objects}
133
+ label='Record Types'
134
+ onClick={handleCreateData}
135
+ />
136
+ <SchemaTable
137
+ classNames='py-1'
138
+ types={presets.types}
139
+ objects={info.objects}
140
+ label='Presets'
141
+ onClick={handleCreateData}
142
+ />
143
+ <ProgressGenerator classNames='py-1' />
121
144
  </ScrollArea.Viewport>
122
145
  </ScrollArea.Root>
123
146
  </Panel.Content>
@@ -125,3 +148,78 @@ export const SpaceGenerator = composable<HTMLDivElement, SpaceGeneratorProps>(
125
148
  );
126
149
  },
127
150
  );
151
+
152
+ SpaceGenerator.displayName = 'SpaceGenerator';
153
+
154
+ // Stable key for the test progress monitor within the shared registry.
155
+ const TEST_PROGRESS_NAME = `${meta.profile.key}.test-progress`;
156
+
157
+ type ProgressGeneratorProps = ThemedClassName;
158
+
159
+ // Drives a synthetic progress monitor (10s over 10 steps) so the R0 rail meter can be exercised.
160
+ const ProgressGenerator = ({ classNames }: ProgressGeneratorProps) => {
161
+ const registry = useOptionalCapability(AppCapabilities.ProgressRegistry);
162
+ const monitor = useProgress(TEST_PROGRESS_NAME);
163
+ const running = monitor?.status === 'running';
164
+ const intervalRef = useRef<ReturnType<typeof setInterval> | undefined>(undefined);
165
+
166
+ const clearTimer = useCallback(() => {
167
+ if (intervalRef.current) {
168
+ clearInterval(intervalRef.current);
169
+ intervalRef.current = undefined;
170
+ }
171
+ }, []);
172
+
173
+ const handleStart = useCallback(() => {
174
+ // Guard on the timer ref too: `running` (derived from the registry) can lag a fast second click.
175
+ if (!registry || running || intervalRef.current) {
176
+ return;
177
+ }
178
+
179
+ const steps = 10;
180
+ let current = 0;
181
+ const handle = registry.register(TEST_PROGRESS_NAME, {
182
+ label: 'Test Progress',
183
+ total: steps,
184
+ // Invoked by the meter's cancel control (R0 rail) or the local button.
185
+ onCancel: () => {
186
+ clearTimer();
187
+ handle.remove();
188
+ },
189
+ });
190
+
191
+ intervalRef.current = setInterval(() => {
192
+ current += 1;
193
+ handle.set(current);
194
+ if (current >= steps) {
195
+ clearTimer();
196
+ handle.done();
197
+ handle.remove();
198
+ }
199
+ }, 1_000);
200
+ }, [registry, running, clearTimer]);
201
+
202
+ // Tear down the timer and the registry entry if unmounted mid-run.
203
+ useEffect(
204
+ () => () => {
205
+ clearTimer();
206
+ registry?.cancel(TEST_PROGRESS_NAME);
207
+ },
208
+ [clearTimer, registry],
209
+ );
210
+
211
+ return (
212
+ <div className={mx('flex items-center gap-2 py-1', classNames)}>
213
+ <span className='grow'>Progress Monitor</span>
214
+ {running ? (
215
+ <IconButton
216
+ icon='ph--x--regular'
217
+ label='Cancel test progress'
218
+ onClick={() => registry?.cancel(TEST_PROGRESS_NAME)}
219
+ />
220
+ ) : (
221
+ <IconButton icon='ph--play--regular' label='Start test progress' disabled={!registry} onClick={handleStart} />
222
+ )}
223
+ </div>
224
+ );
225
+ };
@@ -0,0 +1,74 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import { Atom, useAtomValue } from '@effect-atom/atom-react';
6
+ import React, { Fragment } from 'react';
7
+
8
+ import { useOptionalCapability } from '@dxos/app-framework/ui';
9
+ import { AppCapabilities } from '@dxos/app-toolkit';
10
+ import { ScrollArea } from '@dxos/react-ui';
11
+
12
+ // Fallback so the atom hook is called unconditionally when no store is contributed (host plugin not
13
+ // loaded); the panel then renders its empty state.
14
+ const EMPTY = Atom.make<Record<string, unknown>>({});
15
+
16
+ const isRecord = (value: unknown): value is Record<string, unknown> =>
17
+ typeof value === 'object' && value !== null && !Array.isArray(value);
18
+
19
+ /** Renders a leaf value; numbers are monospace so columns of counts align. */
20
+ const formatValue = (value: unknown): string => (typeof value === 'number' ? value.toLocaleString() : String(value));
21
+
22
+ /**
23
+ * Flattens a compartment into `key → value` rows, one level deep: nested objects (e.g. `coverage`)
24
+ * become dotted keys (`coverage.plain`) so everything renders in a single flat table.
25
+ */
26
+ const flatten = (stats: unknown): [string, unknown][] => {
27
+ if (!isRecord(stats)) {
28
+ return [['value', stats]];
29
+ }
30
+
31
+ return Object.entries(stats).flatMap(([key, value]) =>
32
+ isRecord(value)
33
+ ? Object.entries(value).map(([subKey, subValue]): [string, unknown] => [`${key}.${subKey}`, subValue])
34
+ : [[key, value] as [string, unknown]],
35
+ );
36
+ };
37
+
38
+ /**
39
+ * Presentational panel for the {@link AppCapabilities.StatsPanel} store: renders every plugin
40
+ * compartment as a flat key × value table, live (re-renders on each write). Purely generic — it
41
+ * displays whatever each plugin stores, so it works for sync telemetry or any other stats.
42
+ */
43
+ export const StatsPanel = () => {
44
+ const store = useOptionalCapability(AppCapabilities.StatsPanel);
45
+ const stats = useAtomValue(store?.statsAtom ?? EMPTY);
46
+ const compartments = Object.entries(stats);
47
+ if (compartments.length === 0) {
48
+ return <div className='p-2 text-sm text-description'>No stats yet.</div>;
49
+ }
50
+
51
+ return (
52
+ <ScrollArea.Root thin centered padding>
53
+ <ScrollArea.Viewport>
54
+ {compartments.map(([pluginKey, value]) => (
55
+ <section key={pluginKey} className='w-full'>
56
+ <h3 className='text-start font-mono text-xs text-description pbe-1'>{pluginKey}</h3>
57
+ <dl className='grid grid-cols-[auto_minmax(0,1fr)] w-full'>
58
+ {flatten(value).map(([key, cell]) => (
59
+ <Fragment key={key}>
60
+ <dt className='border-be border-separator pbe-1 pbs-1 pie-2 text-description self-start'>{key}</dt>
61
+ <dd className='border-be border-separator pbe-1 pbs-1 truncate font-mono text-end'>
62
+ {formatValue(cell)}
63
+ </dd>
64
+ </Fragment>
65
+ ))}
66
+ </dl>
67
+ </section>
68
+ ))}
69
+ </ScrollArea.Viewport>
70
+ </ScrollArea.Root>
71
+ );
72
+ };
73
+
74
+ StatsPanel.displayName = 'StatsPanel';
@@ -0,0 +1,5 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ export * from './StatsPanel';
@@ -39,3 +39,5 @@ export const Wireframe = ({ classNames, label, object }: WireframeProps) => {
39
39
  </div>
40
40
  );
41
41
  };
42
+
43
+ Wireframe.displayName = 'Wireframe';
@@ -1,16 +1,18 @@
1
1
  //
2
- // Copyright 2023 DXOS.org
2
+ // Copyright 2026 DXOS.org
3
3
  //
4
4
 
5
5
  import { type ComponentType, lazy } from 'react';
6
6
 
7
- export const DebugGraph: ComponentType<any> = lazy(() => import('./DebugGraph'));
8
- export const DebugSettings: ComponentType<any> = lazy(() => import('./DebugSettings'));
9
7
  export const DebugObjectPanel: ComponentType<any> = lazy(() => import('./DebugObjectPanel'));
8
+ export const DebugSettings: ComponentType<any> = lazy(() => import('./DebugSettings'));
9
+ export const DebugSpaceObjectsPanel: ComponentType<any> = lazy(() => import('./DebugSpaceObjectsPanel'));
10
10
  export const DebugStatus: ComponentType<any> = lazy(() => import('./DebugStatus'));
11
- export const DevtoolsOverviewContainer: ComponentType<any> = lazy(() => import('./DevtoolsOverviewContainer'));
11
+ export const LogStatus: ComponentType<any> = lazy(() =>
12
+ import('./LogStatus').then((module) => ({ default: module.LogStatus })),
13
+ );
12
14
  export const SpaceGenerator: ComponentType<any> = lazy(() => import('./SpaceGenerator'));
13
15
  export const Wireframe: ComponentType<any> = lazy(() => import('./Wireframe'));
14
- export const DebugSpaceObjectsPanel: ComponentType<any> = lazy(() => import('./DebugSpaceObjectsPanel'));
15
- export const GithubPanel: ComponentType<any> = lazy(() => import('./GithubPanel'));
16
- export const RegistryPanel: ComponentType<any> = lazy(() => import('./RegistryPanel'));
16
+ export const StatsPanel: ComponentType<any> = lazy(() =>
17
+ import('./StatsPanel').then((module) => ({ default: module.StatsPanel })),
18
+ );
package/src/index.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  //
2
- // Copyright 2023 DXOS.org
2
+ // Copyright 2026 DXOS.org
3
3
  //
4
4
 
5
5
  export * from './meta';
package/src/meta.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  //
2
- // Copyright 2023 DXOS.org
2
+ // Copyright 2026 DXOS.org
3
3
  //
4
4
 
5
5
  import { Plugin } from '@dxos/app-framework';
package/src/plugin.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  //
2
- // Copyright 2023 DXOS.org
2
+ // Copyright 2026 DXOS.org
3
3
  //
4
4
 
5
5
  import { Plugin } from '@dxos/app-framework';