@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.
- package/README.md +1 -1
- package/dist/lib/index.mjs +1722 -561
- package/dist/lib/index.mjs.map +1 -1
- package/dist/lib/testing.mjs +3 -3
- package/dist/lib/testing.mjs.map +1 -1
- package/dist/lib/translations.mjs +5 -0
- package/dist/lib/translations.mjs.map +1 -1
- package/dist/types/src/components/Gantt/Gantt.d.ts +109 -24
- package/dist/types/src/components/Gantt/Gantt.d.ts.map +1 -1
- package/dist/types/src/components/Gantt/Gantt.stories.d.ts +73 -3
- package/dist/types/src/components/Gantt/Gantt.stories.d.ts.map +1 -1
- package/dist/types/src/components/Gantt/gantt-rows.d.ts +26 -0
- package/dist/types/src/components/Gantt/gantt-rows.d.ts.map +1 -0
- package/dist/types/src/components/Gantt/gantt-rows.test.d.ts +2 -0
- package/dist/types/src/components/Gantt/gantt-rows.test.d.ts.map +1 -0
- package/dist/types/src/components/Gantt/gantt-scale.d.ts +57 -0
- package/dist/types/src/components/Gantt/gantt-scale.d.ts.map +1 -0
- package/dist/types/src/components/Gantt/gantt-scale.test.d.ts +2 -0
- package/dist/types/src/components/Gantt/gantt-scale.test.d.ts.map +1 -0
- package/dist/types/src/components/Gantt/index.d.ts +2 -0
- package/dist/types/src/components/Gantt/index.d.ts.map +1 -1
- package/dist/types/src/components/Gantt/useEnter.d.ts +13 -0
- package/dist/types/src/components/Gantt/useEnter.d.ts.map +1 -0
- package/dist/types/src/components/Gantt/useRangeTween.d.ts +12 -0
- package/dist/types/src/components/Gantt/useRangeTween.d.ts.map +1 -0
- package/dist/types/src/components/ProcessTree/ProcessTree.d.ts +3 -3
- package/dist/types/src/components/ProcessTree/ProcessTree.d.ts.map +1 -1
- package/dist/types/src/components/ProcessTree/ProcessTree.stories.d.ts.map +1 -1
- package/dist/types/src/components/Timeline/Timeline.d.ts +10 -2
- package/dist/types/src/components/Timeline/Timeline.d.ts.map +1 -1
- package/dist/types/src/components/Timeline/Timeline.stories.d.ts +8 -4
- package/dist/types/src/components/Timeline/Timeline.stories.d.ts.map +1 -1
- package/dist/types/src/components/Timeline/timeline-layout.d.ts +35 -0
- package/dist/types/src/components/Timeline/timeline-layout.d.ts.map +1 -0
- package/dist/types/src/components/Timeline/timeline-layout.test.d.ts +2 -0
- package/dist/types/src/components/Timeline/timeline-layout.test.d.ts.map +1 -0
- package/dist/types/src/components/TracePanel/SpanTreeView.d.ts +15 -0
- package/dist/types/src/components/TracePanel/SpanTreeView.d.ts.map +1 -0
- package/dist/types/src/components/TracePanel/TracePanel.d.ts +3 -3
- package/dist/types/src/components/TracePanel/TracePanel.d.ts.map +1 -1
- package/dist/types/src/components/TracePanel/TracePanel.stories.d.ts +46 -0
- package/dist/types/src/components/TracePanel/TracePanel.stories.d.ts.map +1 -0
- package/dist/types/src/components/TracePanel/trace-filter.d.ts +7 -2
- package/dist/types/src/components/TracePanel/trace-filter.d.ts.map +1 -1
- package/dist/types/src/components/TracePanel/useTraceMenu.d.ts.map +1 -1
- package/dist/types/src/execution-graph/execution-graph.d.ts +1 -1
- package/dist/types/src/execution-graph/execution-graph.d.ts.map +1 -1
- package/dist/types/src/hooks/useExecutionGraph.d.ts +2 -2
- package/dist/types/src/hooks/useExecutionGraph.d.ts.map +1 -1
- package/dist/types/src/hooks/useSessionTimeline.d.ts +1 -1
- package/dist/types/src/hooks/useSessionTimeline.d.ts.map +1 -1
- package/dist/types/src/hooks/useTraceMessages.d.ts +1 -1
- package/dist/types/src/hooks/useTraceMessages.d.ts.map +1 -1
- package/dist/types/src/session-timeline/TaskHistory.stories.d.ts +12 -0
- package/dist/types/src/session-timeline/TaskHistory.stories.d.ts.map +1 -0
- package/dist/types/src/session-timeline/gantt-mapping.d.ts +14 -0
- package/dist/types/src/session-timeline/gantt-mapping.d.ts.map +1 -0
- package/dist/types/src/session-timeline/gantt-mapping.test.d.ts +2 -0
- package/dist/types/src/session-timeline/gantt-mapping.test.d.ts.map +1 -0
- package/dist/types/src/session-timeline/index.d.ts +1 -0
- package/dist/types/src/session-timeline/index.d.ts.map +1 -1
- package/dist/types/src/session-timeline/session-timeline.d.ts +17 -2
- package/dist/types/src/session-timeline/session-timeline.d.ts.map +1 -1
- package/dist/types/src/session-timeline/types.d.ts +32 -0
- package/dist/types/src/session-timeline/types.d.ts.map +1 -1
- package/dist/types/src/testing/simulated-agent.d.ts +3 -2
- package/dist/types/src/testing/simulated-agent.d.ts.map +1 -1
- package/dist/types/src/testing/test-trace.d.ts +2 -2
- package/dist/types/src/testing/test-trace.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +5 -0
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +30 -26
- package/src/components/Gantt/Gantt.stories.tsx +914 -96
- package/src/components/Gantt/Gantt.tsx +964 -261
- package/src/components/Gantt/gantt-rows.test.ts +123 -0
- package/src/components/Gantt/gantt-rows.ts +71 -0
- package/src/components/Gantt/gantt-scale.test.ts +105 -0
- package/src/components/Gantt/gantt-scale.ts +143 -0
- package/src/components/Gantt/index.ts +2 -0
- package/src/components/Gantt/useEnter.ts +33 -0
- package/src/components/Gantt/useRangeTween.ts +61 -0
- package/src/components/ProcessTree/ProcessTree.stories.tsx +2 -3
- package/src/components/ProcessTree/ProcessTree.tsx +99 -90
- package/src/components/Timeline/Timeline.stories.tsx +110 -22
- package/src/components/Timeline/Timeline.tsx +319 -271
- package/src/components/Timeline/timeline-layout.test.ts +177 -0
- package/src/components/Timeline/timeline-layout.ts +153 -0
- package/src/components/TracePanel/SpanTreeView.tsx +39 -0
- package/src/components/TracePanel/TracePanel.stories.tsx +106 -0
- package/src/components/TracePanel/TracePanel.tsx +113 -106
- package/src/components/TracePanel/trace-filter.test.ts +31 -2
- package/src/components/TracePanel/trace-filter.ts +28 -3
- package/src/components/TracePanel/useTraceMenu.ts +0 -1
- package/src/execution-graph/SPEC.md +10 -10
- package/src/execution-graph/execution-graph.test.ts +5 -6
- package/src/execution-graph/execution-graph.ts +108 -60
- package/src/execution-graph/pending-block-status.ts +1 -1
- package/src/execution-graph/sub-agent-delegation.test.ts +1 -1
- package/src/hooks/useExecutionGraph.ts +14 -11
- package/src/hooks/useSessionTimeline.ts +35 -9
- package/src/hooks/useTraceMessages.ts +1 -1
- package/src/session-timeline/TaskHistory.stories.tsx +142 -0
- package/src/session-timeline/gantt-mapping.test.ts +118 -0
- package/src/session-timeline/gantt-mapping.ts +158 -0
- package/src/session-timeline/index.ts +1 -0
- package/src/session-timeline/session-timeline.test.ts +567 -19
- package/src/session-timeline/session-timeline.ts +433 -62
- package/src/session-timeline/types.ts +14 -0
- package/src/testing/simulated-agent.ts +3 -2
- package/src/testing/test-trace.ts +2 -2
- package/src/translations.ts +8 -2
- package/dist/types/src/execution-graph/remote-snapshot.test.d.ts +0 -2
- package/dist/types/src/execution-graph/remote-snapshot.test.d.ts.map +0 -1
- 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 =
|
|
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 =
|
|
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.
|
|
12
|
-
): Process.
|
|
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(() => {}) },
|
package/src/translations.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Copyright 2026 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import
|
|
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 +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
|
-
};
|