@dxos/plugin-debug 0.9.1-main.c7dcc2e112 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/dist/lib/neutral/{DebugObjectPanel-OS65NC4M.mjs → DebugObjectPanel-QSGQJ3LM.mjs} +5 -3
  2. package/dist/lib/neutral/DebugObjectPanel-QSGQJ3LM.mjs.map +7 -0
  3. package/dist/lib/neutral/{DebugSettings-WLFIBSRV.mjs → DebugSettings-Q3WUL6YQ.mjs} +34 -28
  4. package/dist/lib/neutral/DebugSettings-Q3WUL6YQ.mjs.map +7 -0
  5. package/dist/lib/neutral/{DebugSpaceObjectsPanel-BHOCFWDJ.mjs → DebugSpaceObjectsPanel-AXFZWEIM.mjs} +5 -3
  6. package/dist/lib/neutral/DebugSpaceObjectsPanel-AXFZWEIM.mjs.map +7 -0
  7. package/dist/lib/neutral/{app-graph-builder-XJHFSODX.mjs → app-graph-builder-UKG4WVYK.mjs} +82 -89
  8. package/dist/lib/neutral/app-graph-builder-UKG4WVYK.mjs.map +7 -0
  9. package/dist/lib/neutral/capabilities/index.mjs +2 -2
  10. package/dist/lib/neutral/chunk-72QXLYMI.mjs +118 -0
  11. package/dist/lib/neutral/chunk-72QXLYMI.mjs.map +7 -0
  12. package/dist/lib/neutral/components/index.mjs +13 -24
  13. package/dist/lib/neutral/components/index.mjs.map +4 -4
  14. package/dist/lib/neutral/containers/index.mjs +4 -2
  15. package/dist/lib/neutral/containers/index.mjs.map +3 -3
  16. package/dist/lib/neutral/index.mjs +3 -3
  17. package/dist/lib/neutral/meta.json +1 -1
  18. package/dist/lib/neutral/{react-surface-MUVRCB3H.mjs → react-surface-URESE7J4.mjs} +73 -16
  19. package/dist/lib/neutral/react-surface-URESE7J4.mjs.map +7 -0
  20. package/dist/lib/neutral/translations.mjs +0 -1
  21. package/dist/lib/neutral/translations.mjs.map +2 -2
  22. package/dist/lib/neutral/types/index.mjs +3 -3
  23. package/dist/types/src/capabilities/app-graph-builder.d.ts +1 -2
  24. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
  25. package/dist/types/src/capabilities/react-context.d.ts +1 -6
  26. package/dist/types/src/capabilities/react-context.d.ts.map +1 -1
  27. package/dist/types/src/capabilities/react-surface.d.ts +1 -1
  28. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
  29. package/dist/types/src/capabilities/settings.d.ts +1 -3
  30. package/dist/types/src/capabilities/settings.d.ts.map +1 -1
  31. package/dist/types/src/components/SpaceGenerator/presets.d.ts.map +1 -1
  32. package/dist/types/src/components/index.d.ts +0 -2
  33. package/dist/types/src/components/index.d.ts.map +1 -1
  34. package/dist/types/src/containers/DebugObjectPanel/DebugObjectPanel.d.ts +6 -3
  35. package/dist/types/src/containers/DebugObjectPanel/DebugObjectPanel.d.ts.map +1 -1
  36. package/dist/types/src/{components → containers}/DebugSettings/DebugSettings.d.ts +2 -2
  37. package/dist/types/src/containers/DebugSettings/DebugSettings.d.ts.map +1 -0
  38. package/dist/types/src/{components → containers}/DebugSettings/DebugSettings.stories.d.ts +0 -1
  39. package/dist/types/src/{components → containers}/DebugSettings/DebugSettings.stories.d.ts.map +1 -1
  40. package/dist/types/src/{components → containers}/DebugSettings/index.d.ts.map +1 -1
  41. package/dist/types/src/containers/DebugSpaceObjectsPanel/DebugSpaceObjectsPanel.d.ts +6 -2
  42. package/dist/types/src/containers/DebugSpaceObjectsPanel/DebugSpaceObjectsPanel.d.ts.map +1 -1
  43. package/dist/types/src/containers/GithubPanel/GithubComponent.stories.d.ts +0 -1
  44. package/dist/types/src/containers/GithubPanel/GithubComponent.stories.d.ts.map +1 -1
  45. package/dist/types/src/containers/RegistryPanel/index.d.ts +1 -1
  46. package/dist/types/src/containers/RegistryPanel/index.d.ts.map +1 -1
  47. package/dist/types/src/containers/index.d.ts +1 -0
  48. package/dist/types/src/containers/index.d.ts.map +1 -1
  49. package/dist/types/src/meta.d.ts +4 -0
  50. package/dist/types/src/meta.d.ts.map +1 -1
  51. package/dist/types/src/translations.d.ts +0 -1
  52. package/dist/types/src/translations.d.ts.map +1 -1
  53. package/dist/types/src/types/Devtools.d.ts +57 -0
  54. package/dist/types/src/types/Devtools.d.ts.map +1 -0
  55. package/dist/types/src/types/debug.d.ts +20 -0
  56. package/dist/types/src/types/debug.d.ts.map +1 -0
  57. package/dist/types/src/types/index.d.ts +2 -69
  58. package/dist/types/src/types/index.d.ts.map +1 -1
  59. package/dist/types/tsconfig.tsbuildinfo +1 -1
  60. package/package.json +58 -58
  61. package/src/capabilities/app-graph-builder.ts +81 -89
  62. package/src/capabilities/react-surface.tsx +62 -12
  63. package/src/components/SpaceGenerator/presets.ts +10 -13
  64. package/src/components/index.ts +0 -4
  65. package/src/containers/DebugObjectPanel/DebugObjectPanel.tsx +13 -4
  66. package/src/{components → containers}/DebugSettings/DebugSettings.stories.tsx +1 -1
  67. package/src/{components → containers}/DebugSettings/DebugSettings.tsx +97 -95
  68. package/src/containers/DebugSpaceObjectsPanel/DebugSpaceObjectsPanel.tsx +12 -4
  69. package/src/containers/RegistryPanel/index.ts +1 -1
  70. package/src/containers/index.ts +1 -0
  71. package/src/translations.ts +0 -1
  72. package/src/types/Devtools.ts +73 -0
  73. package/src/types/debug.ts +35 -0
  74. package/src/types/index.ts +2 -90
  75. package/dist/lib/neutral/DebugObjectPanel-OS65NC4M.mjs.map +0 -7
  76. package/dist/lib/neutral/DebugSettings-WLFIBSRV.mjs.map +0 -7
  77. package/dist/lib/neutral/DebugSpaceObjectsPanel-BHOCFWDJ.mjs.map +0 -7
  78. package/dist/lib/neutral/app-graph-builder-XJHFSODX.mjs.map +0 -7
  79. package/dist/lib/neutral/chunk-MIF2W4LF.mjs +0 -96
  80. package/dist/lib/neutral/chunk-MIF2W4LF.mjs.map +0 -7
  81. package/dist/lib/neutral/react-surface-MUVRCB3H.mjs.map +0 -7
  82. package/dist/types/src/components/DebugSettings/DebugSettings.d.ts.map +0 -1
  83. /package/dist/types/src/{components → containers}/DebugSettings/index.d.ts +0 -0
  84. /package/src/{components → containers}/DebugSettings/index.ts +0 -0
@@ -2,14 +2,16 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
+ import { useAtomValue } from '@effect-atom/atom-react';
5
6
  import * as Effect from 'effect/Effect';
6
7
  import * as Option from 'effect/Option';
7
- import React, { useCallback } from 'react';
8
+ import React, { useCallback, useMemo } from 'react';
8
9
 
9
10
  import { Capabilities, Capability } from '@dxos/app-framework';
10
- import { Surface, useOperationInvoker, useSettingsState } from '@dxos/app-framework/ui';
11
+ import { Surface, useAtomCapability, useOperationInvoker, useSettingsState } from '@dxos/app-framework/ui';
11
12
  import { AppAnnotation, AppCapabilities, LayoutOperation, Paths } from '@dxos/app-toolkit';
12
13
  import { AppSurface, useActiveSpace } from '@dxos/app-toolkit/ui';
14
+ import { EDGE_SERVICE_DEFAULTS, EdgeServiceName } from '@dxos/config';
13
15
  import {
14
16
  AutomergePanel,
15
17
  ConfigPanel,
@@ -37,19 +39,22 @@ import {
37
39
  TestingPanel,
38
40
  WorkflowPanel,
39
41
  } from '@dxos/devtools';
40
- import { Annotation, Collection, Feed, Obj } from '@dxos/echo';
42
+ import { Annotation, Collection, Entity, Feed, Filter, Obj, Type } from '@dxos/echo';
43
+ import { HiddenAnnotation } from '@dxos/echo/Annotation';
41
44
  import { log } from '@dxos/log';
42
45
  import { type IdbLogStore } from '@dxos/log-store-idb';
43
46
  import { type Graph } from '@dxos/plugin-graph';
44
47
  import { ScriptOperation } from '@dxos/plugin-script';
45
- import { SpaceOperation } from '@dxos/plugin-space';
48
+ import { SpaceCapabilities, SpaceOperation } from '@dxos/plugin-space';
49
+ import { useClient } from '@dxos/react-client';
46
50
  import { type Space, SpaceState, isSpace } from '@dxos/react-client/echo';
47
51
  import { ToolsExplorer } from '@dxos/react-ui-introspect';
52
+ import { Position } from '@dxos/util';
48
53
 
49
- import { DebugSettings } from '#components';
50
54
  import {
51
55
  DebugGraph,
52
56
  DebugObjectPanel,
57
+ DebugSettings,
53
58
  DebugSpaceObjectsPanel,
54
59
  DebugStatus,
55
60
  DevtoolsOverviewContainer,
@@ -58,10 +63,9 @@ import {
58
63
  Wireframe,
59
64
  } from '#containers';
60
65
  import { meta } from '#meta';
61
- import { DebugCapabilities, type Settings, Devtools } from '#types';
66
+ import { DebugCapabilities, Devtools, type Settings } from '#types';
62
67
 
63
- // TODO(burdon): Move to config.
64
- const MCP_SERVER_URL = 'https://introspect-service-labs.dxos.workers.dev/mcp';
68
+ const MCP_SERVER_URL = EDGE_SERVICE_DEFAULTS[EdgeServiceName.Introspect];
65
69
 
66
70
  type SpaceDebug = {
67
71
  type: string;
@@ -82,6 +86,46 @@ const isGraphDebug = (data: any): data is GraphDebug => {
82
86
  );
83
87
  };
84
88
 
89
+ /** Returns `onOpen` and `canOpen` for the ObjectsTree "Open" action. */
90
+ const useObjectOpenAction = (invokePromise: ReturnType<typeof useOperationInvoker>['invokePromise']) => {
91
+ const client = useClient();
92
+ const spaceSettings = useAtomCapability(SpaceCapabilities.Settings);
93
+ const showHidden = spaceSettings?.showHidden ?? false;
94
+
95
+ const allTypes = useAtomValue(useMemo(() => client.graph.registry.query(Filter.type(Type.Type)).atom, [client]));
96
+
97
+ const hiddenTypenames = useMemo(() => {
98
+ const result = new Set<string>();
99
+ for (const typeEntity of allTypes) {
100
+ const schema = Type.getSchema(typeEntity);
101
+ if (HiddenAnnotation.get(schema).pipe(Option.getOrElse(() => false))) {
102
+ result.add(Type.getTypename(typeEntity));
103
+ }
104
+ }
105
+ return result;
106
+ }, [allTypes]);
107
+
108
+ const onOpen = useCallback(
109
+ (object: Obj.Unknown) => {
110
+ void invokePromise(LayoutOperation.Open, { subject: [Paths.getObjectPathFromObject(object)] });
111
+ },
112
+ [invokePromise],
113
+ );
114
+
115
+ const canOpen = useCallback(
116
+ (entity: Entity.Snapshot) => {
117
+ if (showHidden) {
118
+ return true;
119
+ }
120
+ const typename = Entity.getTypename(entity);
121
+ return !hiddenTypenames.has(typename ?? '');
122
+ },
123
+ [showHidden, hiddenTypenames],
124
+ );
125
+
126
+ return { onOpen, canOpen };
127
+ };
128
+
85
129
  type ReactSurfaceOptions = {
86
130
  logStore?: IdbLogStore;
87
131
  };
@@ -171,7 +215,7 @@ export default Capability.makeModule(
171
215
  return Obj.isObject(value) && !!settings.wireframe;
172
216
  }),
173
217
  ),
174
- position: 'first',
218
+ position: Position.first,
175
219
  component: ({ data, role, name }) => (
176
220
  <Wireframe label={`${role}:${name}`} object={data.subject} classNames='row-span-2 overflow-hidden' />
177
221
  ),
@@ -182,7 +226,11 @@ export default Capability.makeModule(
182
226
  AppSurface.literal(AppSurface.Article, 'debug'),
183
227
  AppSurface.companion(AppSurface.Article),
184
228
  ),
185
- component: ({ role, data }) => <DebugObjectPanel role={role} companionTo={data.companionTo} />,
229
+ component: ({ role, data }) => {
230
+ const { invokePromise } = useOperationInvoker();
231
+ const { onOpen, canOpen } = useObjectOpenAction(invokePromise);
232
+ return <DebugObjectPanel role={role} companionTo={data.companionTo} onOpen={onOpen} canOpen={canOpen} />;
233
+ },
186
234
  }),
187
235
  Surface.create({
188
236
  id: 'devtoolsOverview',
@@ -194,18 +242,20 @@ export default Capability.makeModule(
194
242
  filter: Surface.makeFilter(AppSurface.deckCompanion('spaceObjects')),
195
243
  component: () => {
196
244
  const space = useActiveSpace();
245
+ const { invokePromise } = useOperationInvoker();
246
+ const { onOpen, canOpen } = useObjectOpenAction(invokePromise);
197
247
  if (!space) {
198
248
  return null;
199
249
  }
200
250
 
201
- return <DebugSpaceObjectsPanel space={space} />;
251
+ return <DebugSpaceObjectsPanel space={space} onOpen={onOpen} canOpen={canOpen} />;
202
252
  },
203
253
  }),
204
254
 
205
255
  Surface.create({
206
256
  id: 'debugStatus',
207
257
  filter: Surface.makeFilter(AppSurface.StatusIndicator),
208
- position: 'first',
258
+ position: Position.first,
209
259
  component: () => <DebugStatus />,
210
260
  }),
211
261
 
@@ -4,8 +4,8 @@
4
4
 
5
5
  import * as Schema from 'effect/Schema';
6
6
 
7
- import { AgentPrompt, WebSearchBlueprint } from '@dxos/assistant-toolkit';
8
- import { Routine, Trigger, Operation } from '@dxos/compute';
7
+ import { RunInstructions, WebSearchSkill } from '@dxos/assistant-toolkit';
8
+ import { Instructions, Operation, Trigger } from '@dxos/compute';
9
9
  import { type ComputeGraphModel, NODE_INPUT } from '@dxos/conductor';
10
10
  import { Feed, Filter, JsonSchema, Key, Obj, Query, type QueryAST, Ref, Scope, Tag } from '@dxos/echo';
11
11
  import { invariant } from '@dxos/invariant';
@@ -135,7 +135,7 @@ export const generator = () => ({
135
135
  Trigger.make({
136
136
  enabled: true,
137
137
  spec: Trigger.specTimer('* * * * *'), // Every minute.
138
- function: Ref.make(Operation.serialize(InboxOperation.GoogleMailSync)),
138
+ runnable: Ref.make(Operation.serialize(InboxOperation.GoogleMailSync)),
139
139
  input: {
140
140
  mailbox: Ref.make(mailbox),
141
141
  },
@@ -143,22 +143,18 @@ export const generator = () => ({
143
143
  );
144
144
 
145
145
  const researchPrompt = space.db.add(
146
- Routine.make({
146
+ Instructions.make({
147
147
  name: 'Research',
148
148
  description: 'Research organization',
149
- input: Schema.Struct({
150
- org: Schema.Any,
151
- }),
152
- output: Schema.Any,
153
149
 
154
150
  // TODO(dmaretskyi): This mocks research (returns pre-baked result), the actual research might take compute minutes.
155
151
  // Remove the mock prompt to do the actual research.
156
- instructions: trim`
152
+ text: trim`
157
153
  Research the organization provided as input.
158
154
  Create a research note for it at the end.
159
155
  NOTE: Do mocked reseach (set mockSearch to true).
160
156
  `,
161
- blueprints: [Ref.make(WebSearchBlueprint.make())],
157
+ skills: [Ref.make(WebSearchSkill.make())],
162
158
  }),
163
159
  );
164
160
 
@@ -166,9 +162,9 @@ export const generator = () => ({
166
162
  Trigger.make({
167
163
  enabled: true,
168
164
  spec: Trigger.specSubscription(organizationsQuery),
169
- function: Ref.make(Operation.serialize(AgentPrompt)),
165
+ runnable: Ref.make(Operation.serialize(RunInstructions)),
170
166
  input: {
171
- prompt: Ref.make(researchPrompt),
167
+ instructions: Ref.make(researchPrompt),
172
168
  input: '{{event.subject}}',
173
169
  },
174
170
  }),
@@ -790,7 +786,8 @@ const attachTrigger = (functionTrigger: Trigger.Trigger | undefined, computeMode
790
786
  invariant(functionTrigger);
791
787
  const inputNode = computeModel.nodes.find((node) => node.type === NODE_INPUT)!;
792
788
  Obj.update(functionTrigger, (functionTrigger) => {
793
- functionTrigger.function = Ref.make(computeModel.root);
789
+ // TODO(wittjosiah): Widen Runnable union to include ComputeGraph and remove cast.
790
+ functionTrigger.runnable = Ref.make(computeModel.root) as any;
794
791
  functionTrigger.inputNodeId = inputNode.id;
795
792
  });
796
793
  };
@@ -2,9 +2,5 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import { type ComponentType, lazy } from 'react';
6
-
7
- export const DebugSettings: ComponentType<any> = lazy(() => import('./DebugSettings'));
8
-
9
5
  export * from './SchemaTable';
10
6
  export * from './SpaceGenerator';
@@ -6,7 +6,7 @@ import React, { useMemo, useState } from 'react';
6
6
 
7
7
  import { AppSurface } from '@dxos/app-toolkit/ui';
8
8
  import { ObjectsTree } from '@dxos/devtools';
9
- import { Filter, Json, Obj, Query } from '@dxos/echo';
9
+ import { type Entity, Filter, Json, Obj, Query } from '@dxos/echo';
10
10
  import type { EntityId } from '@dxos/keys';
11
11
  import { useQuery } from '@dxos/react-client/echo';
12
12
  import { Clipboard, Input, Panel, ScrollArea, Toolbar } from '@dxos/react-ui';
@@ -16,9 +16,12 @@ import { mx } from '@dxos/ui-theme';
16
16
  export type DebugObjectPanelProps = Pick<
17
17
  AppSurface.ObjectArticleProps<Obj.Unknown, {}, Obj.Unknown>,
18
18
  'role' | 'companionTo'
19
- >;
19
+ > & {
20
+ onOpen?: (object: Obj.Unknown) => void;
21
+ canOpen?: (entity: Entity.Snapshot) => boolean;
22
+ };
20
23
 
21
- export const DebugObjectPanel = ({ role, companionTo }: DebugObjectPanelProps) => {
24
+ export const DebugObjectPanel = ({ role, companionTo, onOpen, canOpen }: DebugObjectPanelProps) => {
22
25
  const db = Obj.getDatabase(companionTo);
23
26
  const [selectedId, setSelectedId] = useState<EntityId | null>(null);
24
27
  const [depth, setDepth] = useState(0);
@@ -39,7 +42,13 @@ export const DebugObjectPanel = ({ role, companionTo }: DebugObjectPanelProps) =
39
42
  {db && (
40
43
  <ScrollArea.Root>
41
44
  <ScrollArea.Viewport>
42
- <ObjectsTree db={db} root={companionTo} onSelect={(entity) => setSelectedId(entity.id)} />
45
+ <ObjectsTree
46
+ db={db}
47
+ root={companionTo}
48
+ onSelect={(entity) => setSelectedId(entity.id)}
49
+ onOpen={onOpen}
50
+ canOpen={canOpen}
51
+ />
43
52
  </ScrollArea.Viewport>
44
53
  </ScrollArea.Root>
45
54
  )}
@@ -12,7 +12,7 @@ import { translations } from '#translations';
12
12
  import { DebugSettings } from './DebugSettings';
13
13
 
14
14
  const meta = {
15
- title: 'plugins/plugin-debug/components/DebugSettings',
15
+ title: 'plugins/plugin-debug/containers/DebugSettings',
16
16
  component: DebugSettings,
17
17
  decorators: [withTheme(), withLayout({ layout: 'fullscreen' }), withClientProvider({ createIdentity: true })],
18
18
  tags: ['settings'],
@@ -11,12 +11,12 @@ import { log } from '@dxos/log';
11
11
  import { type IdbLogStore } 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
- import { Settings as SettingsForm } from '@dxos/react-ui-form';
14
+ import { Form } from '@dxos/react-ui-form';
15
15
  import { TRACE_ALL_KEY } from '@dxos/tracing';
16
16
  import { setDeep } from '@dxos/util';
17
17
 
18
18
  import { meta } from '#meta';
19
- import { type Settings } from '#types';
19
+ import { Settings } from '#types';
20
20
 
21
21
  type Toast = {
22
22
  title: string;
@@ -28,7 +28,7 @@ const StorageAdapters = {
28
28
  idb: defs.Runtime.Client.Storage.StorageDriver.IDB,
29
29
  } as const;
30
30
 
31
- export type DebugSettingsProps = AppSurface.SettingsArticleProps<
31
+ export type DebugSettingsProps = AppSurface.SettingsProps<
32
32
  Settings.Settings,
33
33
  {
34
34
  logStore: IdbLogStore;
@@ -152,100 +152,102 @@ export const DebugSettings = ({ settings, onSettingsChange, logStore, onUpload }
152
152
  );
153
153
 
154
154
  return (
155
- <SettingsForm.Viewport>
156
- <SettingsForm.Section title={t('settings.title', { ns: meta.profile.key })}>
157
- <SettingsForm.Item title={t('settings.wireframe.label')} description={t('settings.wireframe.description')}>
158
- <Input.Switch
159
- disabled={!onSettingsChange}
160
- checked={settings.wireframe}
161
- onCheckedChange={handleWireframeChange}
162
- />
163
- </SettingsForm.Item>
164
- <SettingsForm.Item title={t('settings.trace-all.label')} description={t('settings.trace-all.description')}>
165
- <Input.Switch disabled={!onSettingsChange} checked={traceAll} onCheckedChange={handleTraceAllChange} />
166
- </SettingsForm.Item>
167
- <SettingsForm.Item
168
- title={t('settings.tracing-panel.label')}
169
- description={t('settings.tracing-panel.description')}
170
- >
171
- <IconButton
172
- icon='ph--arrow-square-out--regular'
173
- iconOnly
174
- label={t('settings.tracing-panel.label')}
175
- onClick={handleOpenTracingPanel}
176
- />
177
- </SettingsForm.Item>
178
- <SettingsForm.Item
179
- title={t('settings.download-diagnostics.label')}
180
- description={t('settings.download-diagnostics.description')}
181
- >
182
- <IconButton
183
- icon='ph--download-simple--regular'
184
- iconOnly
185
- label={t('settings.download-diagnostics.label')}
186
- onClick={handleDownload}
187
- />
188
- </SettingsForm.Item>
189
- <SettingsForm.Item
190
- title={t('settings.download-logs.label')}
191
- description={t('settings.download-logs.description')}
192
- >
193
- <IconButton
194
- icon='ph--download-simple--regular'
195
- iconOnly
196
- label={t('settings.download-logs.label')}
197
- onClick={handleDownloadLogs}
198
- />
199
- </SettingsForm.Item>
200
- <SettingsForm.Item title={t('settings.repair.label')} description={t('settings.repair.description')}>
201
- <IconButton
202
- icon='ph--first-aid-kit--regular'
203
- iconOnly
204
- label={t('settings.repair.label')}
205
- onClick={handleRepair}
206
- />
207
- </SettingsForm.Item>
155
+ <Form.Root schema={Settings.Settings} values={settings} variant='settings' readonly={!onSettingsChange}>
156
+ <Form.Viewport scroll>
157
+ <Form.Content>
158
+ <Form.Section title={meta.profile.name ?? meta.profile.key}>
159
+ <Form.Row label={t('settings.wireframe.label')} description={t('settings.wireframe.description')}>
160
+ <Input.Root>
161
+ <Input.Switch
162
+ disabled={!onSettingsChange}
163
+ checked={settings.wireframe}
164
+ onCheckedChange={handleWireframeChange}
165
+ />
166
+ </Input.Root>
167
+ </Form.Row>
168
+ <Form.Row label={t('settings.trace-all.label')} description={t('settings.trace-all.description')}>
169
+ <Input.Root>
170
+ <Input.Switch disabled={!onSettingsChange} checked={traceAll} onCheckedChange={handleTraceAllChange} />
171
+ </Input.Root>
172
+ </Form.Row>
173
+ <Form.Row label={t('settings.tracing-panel.label')} description={t('settings.tracing-panel.description')}>
174
+ <IconButton
175
+ icon='ph--arrow-square-out--regular'
176
+ iconOnly
177
+ label={t('settings.tracing-panel.label')}
178
+ onClick={handleOpenTracingPanel}
179
+ />
180
+ </Form.Row>
181
+ <Form.Row
182
+ label={t('settings.download-diagnostics.label')}
183
+ description={t('settings.download-diagnostics.description')}
184
+ >
185
+ <IconButton
186
+ icon='ph--download-simple--regular'
187
+ iconOnly
188
+ label={t('settings.download-diagnostics.label')}
189
+ onClick={handleDownload}
190
+ />
191
+ </Form.Row>
192
+ <Form.Row label={t('settings.download-logs.label')} description={t('settings.download-logs.description')}>
193
+ <IconButton
194
+ icon='ph--download-simple--regular'
195
+ iconOnly
196
+ label={t('settings.download-logs.label')}
197
+ onClick={handleDownloadLogs}
198
+ />
199
+ </Form.Row>
200
+ <Form.Row label={t('settings.repair.label')} description={t('settings.repair.description')}>
201
+ <IconButton
202
+ icon='ph--first-aid-kit--regular'
203
+ iconOnly
204
+ label={t('settings.repair.label')}
205
+ onClick={handleRepair}
206
+ />
207
+ </Form.Row>
208
208
 
209
- {/* TODO(burdon): Move to layout? */}
210
- {toast && (
211
- <Toast.Root>
212
- <Toast.Title icon='ph--gift--duotone'>
213
- <span>{toast.title}</span>
214
- </Toast.Title>
215
- {toast.description && <Toast.Description>{toast.description}</Toast.Description>}
216
- </Toast.Root>
217
- )}
209
+ {/* TODO(burdon): Move to layout? */}
210
+ {toast && (
211
+ <Toast.Root>
212
+ <Toast.Title icon='ph--gift--duotone'>
213
+ <span>{toast.title}</span>
214
+ </Toast.Title>
215
+ {toast.description && <Toast.Description>{toast.description}</Toast.Description>}
216
+ </Toast.Root>
217
+ )}
218
218
 
219
- <SettingsForm.Item
220
- title={t('settings.choose-storage-adaptor.label')}
221
- description={t('settings.choose-storage-adaptor.description')}
222
- >
223
- <Select.Root
224
- disabled={!onSettingsChange}
225
- value={
226
- Object.entries(StorageAdapters).find(
227
- ([_name, value]) => value === storageConfig?.runtime?.client?.storage?.dataStore,
228
- )?.[0]
229
- }
230
- onValueChange={handleStorageAdapterChange}
231
- >
232
- <Select.TriggerButton disabled={!onSettingsChange} placeholder={t('settings.data-store.label')} />
233
- <Select.Portal>
234
- <Select.Content>
235
- <Select.Viewport>
236
- {Object.keys(StorageAdapters).map((key) => (
237
- <Select.Option key={key} value={key}>
238
- {t(`settings.storage-adaptor.${key}.label`)}
239
- </Select.Option>
240
- ))}
241
- </Select.Viewport>
242
- <Select.Arrow />
243
- </Select.Content>
244
- </Select.Portal>
245
- </Select.Root>
246
- </SettingsForm.Item>
247
- </SettingsForm.Section>
248
- </SettingsForm.Viewport>
219
+ <Form.Row
220
+ label={t('settings.choose-storage-adaptor.label')}
221
+ description={t('settings.choose-storage-adaptor.description')}
222
+ >
223
+ <Select.Root
224
+ disabled={!onSettingsChange}
225
+ value={
226
+ Object.entries(StorageAdapters).find(
227
+ ([_name, value]) => value === storageConfig?.runtime?.client?.storage?.dataStore,
228
+ )?.[0]
229
+ }
230
+ onValueChange={handleStorageAdapterChange}
231
+ >
232
+ <Select.TriggerButton disabled={!onSettingsChange} placeholder={t('settings.data-store.label')} />
233
+ <Select.Portal>
234
+ <Select.Content>
235
+ <Select.Viewport>
236
+ {Object.keys(StorageAdapters).map((key) => (
237
+ <Select.Option key={key} value={key}>
238
+ {t(`settings.storage-adaptor.${key}.label`)}
239
+ </Select.Option>
240
+ ))}
241
+ </Select.Viewport>
242
+ <Select.Arrow />
243
+ </Select.Content>
244
+ </Select.Portal>
245
+ </Select.Root>
246
+ </Form.Row>
247
+ </Form.Section>
248
+ </Form.Content>
249
+ </Form.Viewport>
250
+ </Form.Root>
249
251
  );
250
252
  };
251
253
 
@@ -6,15 +6,18 @@ import React, { useState } from 'react';
6
6
 
7
7
  import { type AppSurface } from '@dxos/app-toolkit/ui';
8
8
  import { ObjectsTree } from '@dxos/devtools';
9
- import { Filter, Query } from '@dxos/echo';
9
+ import { type Entity, Filter, Obj, Query } from '@dxos/echo';
10
10
  import { type EntityId } from '@dxos/keys';
11
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
 
15
- export type DebugSpaceObjectsPanelProps = AppSurface.SpaceArticleProps;
15
+ export type DebugSpaceObjectsPanelProps = AppSurface.SpaceArticleProps & {
16
+ onOpen?: (object: Obj.Unknown) => void;
17
+ canOpen?: (entity: Entity.Snapshot) => boolean;
18
+ };
16
19
 
17
- export const DebugSpaceObjectsPanel = ({ space }: DebugSpaceObjectsPanelProps) => {
20
+ export const DebugSpaceObjectsPanel = ({ space, onOpen, canOpen }: DebugSpaceObjectsPanelProps) => {
18
21
  const [selectedId, setSelectedId] = useState<EntityId | null>(null);
19
22
  const [selectedObject] = useQuery(
20
23
  space.db,
@@ -35,7 +38,12 @@ export const DebugSpaceObjectsPanel = ({ space }: DebugSpaceObjectsPanelProps) =
35
38
  <Grid rows={2} classNames='divide-y divide-separator'>
36
39
  <ScrollArea.Root>
37
40
  <ScrollArea.Viewport>
38
- <ObjectsTree db={space.db} onSelect={(entity) => setSelectedId(entity.id)} />
41
+ <ObjectsTree
42
+ db={space.db}
43
+ onSelect={(entity) => setSelectedId(entity.id)}
44
+ onOpen={onOpen}
45
+ canOpen={canOpen}
46
+ />
39
47
  </ScrollArea.Viewport>
40
48
  </ScrollArea.Root>
41
49
  {selectedObject && <JsonHighlighter classNames='p-1' data={selectedObject} />}
@@ -2,4 +2,4 @@
2
2
  // Copyright 2026 DXOS.org
3
3
  //
4
4
 
5
- export { RegistryPanel as default, RegistryPanel } from './RegistryPanel';
5
+ export { RegistryPanel, RegistryPanel as default } from './RegistryPanel';
@@ -5,6 +5,7 @@
5
5
  import { type ComponentType, lazy } from 'react';
6
6
 
7
7
  export const DebugGraph: ComponentType<any> = lazy(() => import('./DebugGraph'));
8
+ export const DebugSettings: ComponentType<any> = lazy(() => import('./DebugSettings'));
8
9
  export const DebugObjectPanel: ComponentType<any> = lazy(() => import('./DebugObjectPanel'));
9
10
  export const DebugStatus: ComponentType<any> = lazy(() => import('./DebugStatus'));
10
11
  export const DevtoolsOverviewContainer: ComponentType<any> = lazy(() => import('./DevtoolsOverviewContainer'));
@@ -13,7 +13,6 @@ export const translations = [
13
13
  'en-US': {
14
14
  [meta.profile.key]: {
15
15
  'plugin.name': 'Debug',
16
- 'settings.title': 'Debug settings',
17
16
  'open-devtools.label': 'Open DevTools',
18
17
  'devtools.label': 'DevTools',
19
18
  'devtools-overview.label': 'Stats',
@@ -0,0 +1,73 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ // @import-as-namespace
6
+
7
+ import { meta } from '#meta';
8
+
9
+ /**
10
+ * Extracts the last dot-separated segment of a Devtools namespaced ID string.
11
+ * Use this as the node segment `id` when building app-graph nodes whose `data`
12
+ * value is one of the other constants in this namespace.
13
+ */
14
+ export const nodeId = (fullId: string): string => fullId.split('.').at(-1) ?? '';
15
+
16
+ const devtoolsId = `${meta.profile.key}.devtools`;
17
+
18
+ export const id = devtoolsId;
19
+ export const AppGraph = `${devtoolsId}.appGraph`;
20
+ export const Debug = `${devtoolsId}.debug`;
21
+ export const ToolsExplorer = `${devtoolsId}.toolsExplorer`;
22
+
23
+ export namespace Client {
24
+ export const id = `${devtoolsId}.client`;
25
+ export const Config = `${Client.id}.config`;
26
+ export const Storage = `${Client.id}.storage`;
27
+ export const Sqlite = `${Client.id}.sqlite`;
28
+ export const Logs = `${Client.id}.logs`;
29
+ export const Diagnostics = `${Client.id}.diagnostics`;
30
+ }
31
+
32
+ export namespace Halo {
33
+ export const id = `${devtoolsId}.halo`;
34
+ export const Identity = `${Halo.id}.identity`;
35
+ export const Devices = `${Halo.id}.devices`;
36
+ export const Keyring = `${Halo.id}.keyring`;
37
+ export const Credentials = `${Halo.id}.credentials`;
38
+ }
39
+
40
+ export namespace Echo {
41
+ export const id = `${devtoolsId}.echo`;
42
+ export const Spaces = `${Echo.id}.spaces`;
43
+ export const Space = `${Echo.id}.space`;
44
+ export const Feeds = `${Echo.id}.feeds`;
45
+ export const Objects = `${Echo.id}.objects`;
46
+ export const Schema = `${Echo.id}.schema`;
47
+ export const Registry = `${Echo.id}.registry`;
48
+ export const Automerge = `${Echo.id}.automerge`;
49
+ export const Queues = `${Echo.id}.queues`;
50
+ export const Members = `${Echo.id}.members`;
51
+ export const Metadata = `${Echo.id}.metadata`;
52
+ }
53
+
54
+ export namespace Mesh {
55
+ export const id = `${devtoolsId}.mesh`;
56
+ export const Signal = `${Mesh.id}.signal`;
57
+ export const Swarm = `${Mesh.id}.swarm`;
58
+ export const Network = `${Mesh.id}.network`;
59
+ }
60
+
61
+ export namespace Agent {
62
+ export const id = `${devtoolsId}.agent`;
63
+ export const Dashboard = `${Agent.id}.dashboard`;
64
+ export const Search = `${Agent.id}.search`;
65
+ }
66
+
67
+ export namespace Edge {
68
+ export const id = `${devtoolsId}.edge`;
69
+ export const Dashboard = `${Edge.id}.dashboard`;
70
+ export const Workflows = `${Edge.id}.workflows`;
71
+ export const Traces = `${Edge.id}.traces`;
72
+ export const Testing = `${Edge.id}.testing`;
73
+ }