@dxos/react-ui-trace 0.11.1 → 0.13.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 (115) hide show
  1. package/README.md +1 -1
  2. package/dist/lib/index.mjs +1722 -561
  3. package/dist/lib/index.mjs.map +1 -1
  4. package/dist/lib/testing.mjs +3 -3
  5. package/dist/lib/testing.mjs.map +1 -1
  6. package/dist/lib/translations.mjs +5 -0
  7. package/dist/lib/translations.mjs.map +1 -1
  8. package/dist/types/src/components/Gantt/Gantt.d.ts +109 -24
  9. package/dist/types/src/components/Gantt/Gantt.d.ts.map +1 -1
  10. package/dist/types/src/components/Gantt/Gantt.stories.d.ts +73 -3
  11. package/dist/types/src/components/Gantt/Gantt.stories.d.ts.map +1 -1
  12. package/dist/types/src/components/Gantt/gantt-rows.d.ts +26 -0
  13. package/dist/types/src/components/Gantt/gantt-rows.d.ts.map +1 -0
  14. package/dist/types/src/components/Gantt/gantt-rows.test.d.ts +2 -0
  15. package/dist/types/src/components/Gantt/gantt-rows.test.d.ts.map +1 -0
  16. package/dist/types/src/components/Gantt/gantt-scale.d.ts +57 -0
  17. package/dist/types/src/components/Gantt/gantt-scale.d.ts.map +1 -0
  18. package/dist/types/src/components/Gantt/gantt-scale.test.d.ts +2 -0
  19. package/dist/types/src/components/Gantt/gantt-scale.test.d.ts.map +1 -0
  20. package/dist/types/src/components/Gantt/index.d.ts +2 -0
  21. package/dist/types/src/components/Gantt/index.d.ts.map +1 -1
  22. package/dist/types/src/components/Gantt/useEnter.d.ts +13 -0
  23. package/dist/types/src/components/Gantt/useEnter.d.ts.map +1 -0
  24. package/dist/types/src/components/Gantt/useRangeTween.d.ts +12 -0
  25. package/dist/types/src/components/Gantt/useRangeTween.d.ts.map +1 -0
  26. package/dist/types/src/components/ProcessTree/ProcessTree.d.ts +3 -3
  27. package/dist/types/src/components/ProcessTree/ProcessTree.d.ts.map +1 -1
  28. package/dist/types/src/components/ProcessTree/ProcessTree.stories.d.ts.map +1 -1
  29. package/dist/types/src/components/Timeline/Timeline.d.ts +10 -2
  30. package/dist/types/src/components/Timeline/Timeline.d.ts.map +1 -1
  31. package/dist/types/src/components/Timeline/Timeline.stories.d.ts +8 -4
  32. package/dist/types/src/components/Timeline/Timeline.stories.d.ts.map +1 -1
  33. package/dist/types/src/components/Timeline/timeline-layout.d.ts +35 -0
  34. package/dist/types/src/components/Timeline/timeline-layout.d.ts.map +1 -0
  35. package/dist/types/src/components/Timeline/timeline-layout.test.d.ts +2 -0
  36. package/dist/types/src/components/Timeline/timeline-layout.test.d.ts.map +1 -0
  37. package/dist/types/src/components/TracePanel/SpanTreeView.d.ts +15 -0
  38. package/dist/types/src/components/TracePanel/SpanTreeView.d.ts.map +1 -0
  39. package/dist/types/src/components/TracePanel/TracePanel.d.ts +3 -3
  40. package/dist/types/src/components/TracePanel/TracePanel.d.ts.map +1 -1
  41. package/dist/types/src/components/TracePanel/TracePanel.stories.d.ts +46 -0
  42. package/dist/types/src/components/TracePanel/TracePanel.stories.d.ts.map +1 -0
  43. package/dist/types/src/components/TracePanel/trace-filter.d.ts +7 -2
  44. package/dist/types/src/components/TracePanel/trace-filter.d.ts.map +1 -1
  45. package/dist/types/src/components/TracePanel/useTraceMenu.d.ts.map +1 -1
  46. package/dist/types/src/execution-graph/execution-graph.d.ts +1 -1
  47. package/dist/types/src/execution-graph/execution-graph.d.ts.map +1 -1
  48. package/dist/types/src/hooks/useExecutionGraph.d.ts +2 -2
  49. package/dist/types/src/hooks/useExecutionGraph.d.ts.map +1 -1
  50. package/dist/types/src/hooks/useSessionTimeline.d.ts +1 -1
  51. package/dist/types/src/hooks/useSessionTimeline.d.ts.map +1 -1
  52. package/dist/types/src/hooks/useTraceMessages.d.ts +1 -1
  53. package/dist/types/src/hooks/useTraceMessages.d.ts.map +1 -1
  54. package/dist/types/src/session-timeline/TaskHistory.stories.d.ts +12 -0
  55. package/dist/types/src/session-timeline/TaskHistory.stories.d.ts.map +1 -0
  56. package/dist/types/src/session-timeline/gantt-mapping.d.ts +14 -0
  57. package/dist/types/src/session-timeline/gantt-mapping.d.ts.map +1 -0
  58. package/dist/types/src/session-timeline/gantt-mapping.test.d.ts +2 -0
  59. package/dist/types/src/session-timeline/gantt-mapping.test.d.ts.map +1 -0
  60. package/dist/types/src/session-timeline/index.d.ts +1 -0
  61. package/dist/types/src/session-timeline/index.d.ts.map +1 -1
  62. package/dist/types/src/session-timeline/session-timeline.d.ts +17 -2
  63. package/dist/types/src/session-timeline/session-timeline.d.ts.map +1 -1
  64. package/dist/types/src/session-timeline/types.d.ts +32 -0
  65. package/dist/types/src/session-timeline/types.d.ts.map +1 -1
  66. package/dist/types/src/testing/simulated-agent.d.ts +3 -2
  67. package/dist/types/src/testing/simulated-agent.d.ts.map +1 -1
  68. package/dist/types/src/testing/test-trace.d.ts +2 -2
  69. package/dist/types/src/testing/test-trace.d.ts.map +1 -1
  70. package/dist/types/src/translations.d.ts +5 -0
  71. package/dist/types/src/translations.d.ts.map +1 -1
  72. package/dist/types/tsconfig.tsbuildinfo +1 -1
  73. package/package.json +30 -26
  74. package/src/components/Gantt/Gantt.stories.tsx +914 -96
  75. package/src/components/Gantt/Gantt.tsx +964 -261
  76. package/src/components/Gantt/gantt-rows.test.ts +123 -0
  77. package/src/components/Gantt/gantt-rows.ts +71 -0
  78. package/src/components/Gantt/gantt-scale.test.ts +105 -0
  79. package/src/components/Gantt/gantt-scale.ts +143 -0
  80. package/src/components/Gantt/index.ts +2 -0
  81. package/src/components/Gantt/useEnter.ts +33 -0
  82. package/src/components/Gantt/useRangeTween.ts +61 -0
  83. package/src/components/ProcessTree/ProcessTree.stories.tsx +2 -3
  84. package/src/components/ProcessTree/ProcessTree.tsx +99 -90
  85. package/src/components/Timeline/Timeline.stories.tsx +110 -22
  86. package/src/components/Timeline/Timeline.tsx +319 -271
  87. package/src/components/Timeline/timeline-layout.test.ts +177 -0
  88. package/src/components/Timeline/timeline-layout.ts +153 -0
  89. package/src/components/TracePanel/SpanTreeView.tsx +39 -0
  90. package/src/components/TracePanel/TracePanel.stories.tsx +106 -0
  91. package/src/components/TracePanel/TracePanel.tsx +113 -106
  92. package/src/components/TracePanel/trace-filter.test.ts +31 -2
  93. package/src/components/TracePanel/trace-filter.ts +28 -3
  94. package/src/components/TracePanel/useTraceMenu.ts +0 -1
  95. package/src/execution-graph/SPEC.md +10 -10
  96. package/src/execution-graph/execution-graph.test.ts +5 -6
  97. package/src/execution-graph/execution-graph.ts +108 -60
  98. package/src/execution-graph/pending-block-status.ts +1 -1
  99. package/src/execution-graph/sub-agent-delegation.test.ts +1 -1
  100. package/src/hooks/useExecutionGraph.ts +14 -11
  101. package/src/hooks/useSessionTimeline.ts +35 -9
  102. package/src/hooks/useTraceMessages.ts +1 -1
  103. package/src/session-timeline/TaskHistory.stories.tsx +142 -0
  104. package/src/session-timeline/gantt-mapping.test.ts +118 -0
  105. package/src/session-timeline/gantt-mapping.ts +158 -0
  106. package/src/session-timeline/index.ts +1 -0
  107. package/src/session-timeline/session-timeline.test.ts +567 -19
  108. package/src/session-timeline/session-timeline.ts +433 -62
  109. package/src/session-timeline/types.ts +14 -0
  110. package/src/testing/simulated-agent.ts +3 -2
  111. package/src/testing/test-trace.ts +2 -2
  112. package/src/translations.ts +8 -2
  113. package/dist/types/src/execution-graph/remote-snapshot.test.d.ts +0 -2
  114. package/dist/types/src/execution-graph/remote-snapshot.test.d.ts.map +0 -1
  115. package/src/execution-graph/remote-snapshot.test.ts +0 -116
@@ -4,9 +4,14 @@
4
4
 
5
5
  import * as Schema from 'effect/Schema';
6
6
 
7
+ import { palette } from '@dxos/ui-theme';
8
+
7
9
  export const LaneKind = Schema.Literals(['session', 'task']);
8
10
  export type LaneKind = Schema.Schema.Type<typeof LaneKind>;
9
11
 
12
+ export const LaneHue = Schema.Literals([palette.neutral.hue, ...palette.hues.map((style) => style.hue)]);
13
+ export type LaneHue = Schema.Schema.Type<typeof LaneHue>;
14
+
10
15
  export const LaneStatus = Schema.Literals(['pending', 'blocked', 'running', 'review', 'done', 'failed']);
11
16
  export type LaneStatus = Schema.Schema.Type<typeof LaneStatus>;
12
17
 
@@ -53,13 +58,22 @@ export const Lane = Schema.Struct({
53
58
  /** Epoch ms. */
54
59
  start: Schema.optional(Schema.Number),
55
60
  end: Schema.optional(Schema.Number),
61
+ /**
62
+ * Stretches inside `start`..`end` when the lane's task was put down — blocked on a question, say —
63
+ * and later picked up again; the lane is drawn as separate runs around them.
64
+ */
65
+ gaps: Schema.optional(Schema.Array(Schema.Struct({ start: Schema.Number, end: Schema.Number }))),
56
66
  parentId: Schema.optional(Schema.String),
57
67
  sessionId: Schema.optional(Schema.String),
58
68
  taskId: Schema.optional(Schema.String),
69
+ /** The task's hue, hashed from its mnemonic, so the lane matches the task's mnemonic chip. */
70
+ hue: Schema.optional(LaneHue),
59
71
  pid: Schema.optional(Schema.String),
60
72
  /** Lane ids this lane waits on (task dependencies). */
61
73
  blockedOn: Schema.optional(Schema.Array(Schema.String)),
62
74
  delegatedFrom: Schema.optional(DelegationSource),
75
+ /** Node in the supervisor lane this lane's result was folded back into. */
76
+ returnedTo: Schema.optional(DelegationSource),
63
77
  tokens: Schema.optional(TokenUsage),
64
78
  toolCalls: Schema.optional(Schema.Number),
65
79
  });
@@ -6,6 +6,7 @@ import * as Effect from 'effect/Effect';
6
6
  import * as Schema from 'effect/Schema';
7
7
 
8
8
  import { type ProcessManager } from '@dxos/compute-runtime';
9
+ import * as Operation from '@dxos/compute/Operation';
9
10
  import * as Process from '@dxos/compute/Process';
10
11
  import * as Trace from '@dxos/compute/Trace';
11
12
  import { EntityId } from '@dxos/keys';
@@ -106,7 +107,7 @@ type AgentStep = Schema.Schema.Type<typeof AgentStep>;
106
107
  * it one step, so the caller can interleave the agent's own trace events with the child operation
107
108
  * processes that {@link runScenario} spawns beneath it.
108
109
  */
109
- export const SimulatedAgent = Process.make(
110
+ export const SimulatedAgent = Operation.makeDurable(
110
111
  {
111
112
  key: 'org.dxos.testing.process.agent',
112
113
  input: AgentStep,
@@ -196,7 +197,7 @@ type OperationInput = Schema.Schema.Type<typeof OperationInput>;
196
197
  * Storybook fixture: a {@link Process} that emits the `operation.start`/`operation.end` pair a real
197
198
  * operation process emits, with a simulated execution time in between.
198
199
  */
199
- export const SimulatedOperation = Process.make(
200
+ export const SimulatedOperation = Operation.makeDurable(
200
201
  {
201
202
  key: 'org.dxos.testing.process.operation',
202
203
  input: OperationInput,
@@ -8,8 +8,8 @@ import * as Process from '@dxos/compute/Process';
8
8
  import { Annotation } from '@dxos/echo';
9
9
 
10
10
  export const makeProcess = (
11
- overrides: Partial<Process.Info> & Pick<Process.Info, 'pid' | 'state'> & { name: string },
12
- ): Process.Info => ({
11
+ overrides: Partial<Process.Process> & Pick<Process.Process, 'pid' | 'state'> & { name: string },
12
+ ): Process.Process => ({
13
13
  parentPid: null,
14
14
  key: `test.process.${overrides.name}`,
15
15
  params: { name: overrides.name, annotations: Annotation.buildDictionary(() => {}) },
@@ -2,7 +2,7 @@
2
2
  // Copyright 2026 DXOS.org
3
3
  //
4
4
 
5
- import { type Resource } from '@dxos/react-ui';
5
+ import type * as Theme from '@dxos/react-ui/Theme';
6
6
 
7
7
  export const translationKey = '@dxos/react-ui-trace';
8
8
 
@@ -12,6 +12,12 @@ export const translations = [
12
12
  [translationKey]: {
13
13
  'no-commits.message': 'No events yet',
14
14
 
15
+ 'gantt-axis-time.label': 'Fit to time',
16
+ 'gantt-axis-unit.label': 'One step per event',
17
+ 'gantt-legend-stats.label': 'Show usage',
18
+ 'gantt-legend-title.label': 'Show titles',
19
+ 'gantt-chart.label': 'Timeline',
20
+
15
21
  'trace.label': 'Trace',
16
22
  'trace-processes.label': 'Processes',
17
23
  'trace-details.label': 'Details',
@@ -26,4 +32,4 @@ export const translations = [
26
32
  },
27
33
  },
28
34
  },
29
- ] as const satisfies Resource[];
35
+ ] as const satisfies Theme.Resource[];
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=remote-snapshot.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"remote-snapshot.test.d.ts","sourceRoot":"","sources":["../../../../src/execution-graph/remote-snapshot.test.ts"],"names":[],"mappings":""}
@@ -1,116 +0,0 @@
1
- //
2
- // Copyright 2026 DXOS.org
3
- //
4
-
5
- import { readFileSync } from 'node:fs';
6
- import { join } from 'node:path';
7
- import { describe, test } from 'vitest';
8
-
9
- import * as Trace from '@dxos/compute/Trace';
10
- import { Obj } from '@dxos/echo';
11
-
12
- import { buildExecutionGraph } from './execution-graph.ts';
13
-
14
- /**
15
- * Regression for sub-operations collapsing onto `main` when the event window in `buildSpanTree`
16
- * dropped the parent span's `operation.start`.
17
- *
18
- * The remote trace snapshot has 714 chronological events. The 4th `Run Routine` span hosts every
19
- * `Create object` / `Add schema` / `List schemas` / `Query` / `Add to context` sub-operation.
20
- * Its `operation.start` lives near the front of the stream (index 70). Before the fix, the
21
- * default `eventLimit = 300` would `slice(-300)` away that begin event, leaving the sub-ops'
22
- * `parentPid` lookup unsatisfied — they ended up as top-level collapsible spans rendering their
23
- * end commits on `main`.
24
- */
25
- describe('TracePanel remote snapshot', () => {
26
- test('sub-operations land on their parent Routine branch, never on main', ({ expect }) => {
27
- const messages = loadRemoteTraceMessages(REMOTE_SNAPSHOT);
28
- const { commits } = buildExecutionGraph({ traceMessages: messages });
29
-
30
- // Commits whose message starts with one of these names originate from sub-operations
31
- // (Trace.OperationEnd) — every one should live on the Routine's branch, never on `main`.
32
- const subOpPrefixes = ['Create object', 'Add schema', 'List schemas', 'Query', 'Add to context'];
33
- const isSubOpEnd = (message: string | undefined): boolean =>
34
- message !== undefined && subOpPrefixes.some((prefix) => message.startsWith(prefix));
35
-
36
- const subOpCommits = commits.filter((commit) => isSubOpEnd(commit.message));
37
- expect(subOpCommits.length).toBeGreaterThan(0);
38
-
39
- const onMain = subOpCommits.filter((commit) => commit.branch === 'main');
40
- expect(onMain).toEqual([]);
41
-
42
- // All sub-op end commits share the parent Routine's pid as their branch.
43
- const branches = new Set(subOpCommits.map((commit) => commit.branch));
44
- expect(branches.size).toBe(1);
45
- expect(branches.has('main')).toBe(false);
46
- });
47
-
48
- test('Routine end commits anchor to the previous main commit, not back to their own begin', ({ expect }) => {
49
- // Regression: the multi-Routine snapshot has overlapping top-level Routine spans (R2 starts
50
- // before R1 ends, R4 starts before R3 ends). Previously, R1.end's first parent was
51
- // R1.begin (looked up by `beginCommitIdBySpan`), which drew an edge across R2.begin in the
52
- // rendered timeline. The fix anchors end commits to the immediate predecessor on the
53
- // parent branch (R2.begin) and treats the own-branch tail as a separate merge parent.
54
- const messages = loadRemoteTraceMessages(MULTI_SNAPSHOT);
55
- const { commits } = buildExecutionGraph({ traceMessages: messages });
56
-
57
- const mainCommits = commits.filter((commit) => commit.branch === 'main');
58
- // Sanity check: 4 begin + 4 end Run-Routine commits on main.
59
- expect(mainCommits).toHaveLength(8);
60
-
61
- // For each commit on main, its first parent (if any) must be a commit that appears
62
- // *earlier* in the main commit sequence — no "skip-back" edges to an older begin commit.
63
- const idToMainIndex = new Map(mainCommits.map((commit, index) => [commit.id, index]));
64
- for (let index = 1; index < mainCommits.length; index += 1) {
65
- const commit = mainCommits[index];
66
- const onMainParents = (commit.parents ?? []).filter((parentId) => idToMainIndex.has(parentId));
67
- expect(onMainParents.length).toBeGreaterThan(0);
68
- for (const parentId of onMainParents) {
69
- const parentIndex = idToMainIndex.get(parentId)!;
70
- // Every parent on main must be the immediate predecessor (index - 1). An older parent
71
- // would render an edge that crosses over the intervening commits.
72
- expect(parentIndex).toBe(index - 1);
73
- }
74
- }
75
- });
76
- });
77
-
78
- const REMOTE_SNAPSHOT = 'trace-timeline-remote.dx.json';
79
- const MULTI_SNAPSHOT = 'trace-timeline-multiple.dx.json';
80
-
81
- interface RawMessage {
82
- meta?: Trace.Meta;
83
- isEphemeral?: boolean;
84
- events?: Array<{ type: string; timestamp: number; data: unknown }>;
85
- }
86
-
87
- const loadRemoteTraceMessages = (filename: string): Trace.Message[] => {
88
- const snapshotPath = join(__dirname, '../testing/data', filename);
89
- const json = JSON.parse(readFileSync(snapshotPath, 'utf8')) as unknown;
90
-
91
- const messages: Trace.Message[] = [];
92
- const visit = (node: unknown): void => {
93
- if (Array.isArray(node)) {
94
- node.forEach(visit);
95
- return;
96
- }
97
- if (node === null || typeof node !== 'object') {
98
- return;
99
- }
100
- const candidate = node as RawMessage & Record<string, unknown>;
101
- if (Array.isArray(candidate.events) && candidate.meta && typeof candidate.meta === 'object') {
102
- messages.push(
103
- Obj.make(Trace.Message, {
104
- meta: candidate.meta,
105
- isEphemeral: candidate.isEphemeral ?? false,
106
- events: candidate.events,
107
- }),
108
- );
109
- }
110
- for (const value of Object.values(node as Record<string, unknown>)) {
111
- visit(value);
112
- }
113
- };
114
- visit(json);
115
- return messages;
116
- };