@deepseek-ai/dsh-client-ui-trajectory 0.0.1-rc.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.
package/lib/index.js ADDED
@@ -0,0 +1,6 @@
1
+ //#region lib/types/index.js
2
+ /** Host loader entry for the browser-only trajectory plugin. */
3
+ /** Provides no host-side behavior. */
4
+ function apply() {}
5
+ //#endregion
6
+ export { apply };
@@ -0,0 +1,25 @@
1
+ //#region lib/types/invariant.js
2
+ /**
3
+ * Package-owned invariant companion for `@deepseek-ai/dsh-client-ui-trajectory`.
4
+ * @module @deepseek-ai/dsh-client-ui-trajectory/invariant
5
+ */
6
+ const PACKAGE_NAME = "@deepseek-ai/dsh-client-ui-trajectory";
7
+ /** Cordis companion plugin name. */
8
+ const name = "client-ui-trajectory-invariant";
9
+ /** Service required before the companion can reserve package ownership. */
10
+ const inject = ["invariants"];
11
+ /**
12
+ * No runtime invariant: a pure-consumer plugin — it emits no cordis events
13
+ * and owns no mutable cross-plugin state; its view-slot registration is a
14
+ * plain effect whose disposal the slot ledger's own specs and this
15
+ * package's behavior specs observe directly.
16
+ */
17
+ const install = () => {};
18
+ /**
19
+ * Register this package's invariant companion.
20
+ * @param ctx - Cordis context carrying the invariant service.
21
+ * @returns the installed registration's disposer after setup succeeds.
22
+ */
23
+ const apply = (ctx) => Promise.resolve(ctx.invariants.register(PACKAGE_NAME, install));
24
+ //#endregion
25
+ export { apply, inject, name };
@@ -0,0 +1,10 @@
1
+ import { formatElapsedSeconds, type TrajectoryCellProps } from './trajectory-record.ts';
2
+ export { formatElapsedSeconds };
3
+ export type { AssistantMetricDetail, TrajectoryCellKind, TrajectoryCellProps, } from './trajectory-record.ts';
4
+ /**
5
+ * Render one trajectory step cell.
6
+ * @param props - index, kind, text, time, and optional Message metrics.
7
+ * @returns the cell element.
8
+ */
9
+ export declare function TrajectoryCell({ index, kind, text, inputDetail: _inputDetail, promptDetail: _promptDetail, previousPromptDetail: _previousPromptDetail, outputDetail: _outputDetail, thinkingDetail: _thinkingDetail, sourceBlocks: _sourceBlocks, outputBlocks: _outputBlocks, schemaDetail: _schemaDetail, assistantMetrics: _assistantMetrics, result: _result, callId: _callId, isError: _isError, timeSeconds, startedAt: _startedAt, input, output, think, selected, className, ...rest }: TrajectoryCellProps): import("react").JSX.Element;
10
+ //# sourceMappingURL=TrajectoryCell.d.ts.map
@@ -0,0 +1,13 @@
1
+ export interface TrajectoryGroupHeaderProps {
2
+ /** Group title (`Message`, `Step 1`, …). */
3
+ title: string;
4
+ /** Secondary summary (`49 s`, `2.2 s skill`, …). */
5
+ description?: string;
6
+ }
7
+ /**
8
+ * Render a Message/Step group header inside a turn body.
9
+ * @param props - title and optional description.
10
+ * @returns the group header element.
11
+ */
12
+ export declare function TrajectoryGroupHeader({ title, description }: TrajectoryGroupHeaderProps): import("react").JSX.Element;
13
+ //# sourceMappingURL=TrajectoryGroupHeader.d.ts.map
@@ -0,0 +1,98 @@
1
+ /** Turn-aware trajectory event ledger with a local record inspector. */
2
+ import type { AssistantRequestConfig } from '@deepseek-ai/dsh-client-runtime/client';
3
+ import type { TrajectoryCellProps } from './trajectory-record.ts';
4
+ import { type TrajectoryTurnModel } from './layout.ts';
5
+ /** Props for the trajectory ledger. */
6
+ export interface TrajectoryTableProps {
7
+ /** Session-global request numbers for the request groups visible in this context. */
8
+ requestNumbers?: readonly TrajectoryRequestNumber[];
9
+ /** Grouped records in display order. */
10
+ turns: readonly TrajectoryTurnModel[];
11
+ /** In-flight cells whose content replaces the matching structural record index. */
12
+ streamingCells?: readonly TrajectoryCellProps[];
13
+ /** Record indexes emphasized by the active timeline focus. */
14
+ timelineFocusIndexes?: ReadonlySet<number> | null;
15
+ /** Record indexes retained by the active live search, or null without a query. */
16
+ searchMatchIndexes?: ReadonlySet<number> | null;
17
+ /** Report the record currently selected in the local inspector. */
18
+ onSelectedIndexChange?: (index: number | null) => void;
19
+ /** Report a direct user selection from a ledger row. */
20
+ onRecordSelect?: (index: number) => void;
21
+ /** One externally requested record selection; a new object repeats the request. */
22
+ recordSelection?: {
23
+ readonly index: number;
24
+ } | null;
25
+ /** One externally requested record focus without changing inspector selection. */
26
+ recordFocus?: {
27
+ readonly index: number;
28
+ } | null;
29
+ /** Whether the initial history tail is still loading. */
30
+ historyLoading?: boolean;
31
+ /** First loaded raw event, used to preserve scroll position after prepending a page. */
32
+ historyStartSeq?: number | undefined;
33
+ /** Whether one older history page can be requested. */
34
+ hasOlderRecords?: boolean;
35
+ /** Load one older history page. */
36
+ onLoadOlder?: () => Promise<boolean>;
37
+ /** Clear selection state owned by the ledger host. */
38
+ onClearSelection?: () => void;
39
+ /** Turn ids whose rows after the first are folded into a summary. */
40
+ collapsedTurns: ReadonlySet<number>;
41
+ /** Toggle one turn between folded and expanded. */
42
+ onToggleTurn: (turn: number) => void;
43
+ /** Stable Assistant record ids whose tool calls are folded. */
44
+ collapsedAssistants: ReadonlySet<string>;
45
+ /** Toggle tool calls under one assistant record. */
46
+ onToggleAssistant: (id: string) => void;
47
+ /** One-shot cross-view inspect: open and scroll to this call's record. */
48
+ inspectCallId?: string | null;
49
+ /** Acknowledge a consumed (or unresolvable) inspect request. */
50
+ onInspectApplied?: (() => void) | undefined;
51
+ }
52
+ /** Request-inspector fields shared by ordinary generation and compaction. */
53
+ interface TrajectoryRequestNumberBase {
54
+ /** Request anchor event sequence; absent for the currently streaming ordinary request. */
55
+ seq?: number;
56
+ group: string;
57
+ number: number;
58
+ status?: 'complete' | 'running' | 'error';
59
+ startedAt?: number;
60
+ completedAt?: number | null;
61
+ error?: string;
62
+ retry?: number;
63
+ maxRetries?: number;
64
+ retryDelayMs?: number;
65
+ resultSeq?: number;
66
+ provider?: string;
67
+ model?: string;
68
+ requestConfig?: AssistantRequestConfig;
69
+ usage?: TrajectoryUsage;
70
+ cumulativeUsage?: TrajectoryUsage;
71
+ }
72
+ /** One purpose-discriminated request identity paired with its session-global number. */
73
+ export type TrajectoryRequestNumber = TrajectoryRequestNumberBase & ({
74
+ purpose?: 'assistant';
75
+ turn: number;
76
+ step: number;
77
+ } | {
78
+ purpose: 'compaction';
79
+ turn: number | null;
80
+ step: 0;
81
+ });
82
+ /** Disjoint provider token buckets for one request or a session prefix. */
83
+ export interface TrajectoryUsage {
84
+ input?: number;
85
+ cacheRead?: number;
86
+ cacheWrite?: number;
87
+ output?: number;
88
+ reasoning?: number;
89
+ }
90
+ /**
91
+ * Render trajectory events as a dense ledger with turn and step separators.
92
+ * Clicking ledger whitespace clears the active record or request selection.
93
+ * @param props - Grouped trajectory data and whole-ledger fold state.
94
+ * @returns The ledger and an optional local record inspector.
95
+ */
96
+ export declare function TrajectoryTable({ requestNumbers: sessionRequestNumbers, turns, streamingCells, timelineFocusIndexes, searchMatchIndexes, onSelectedIndexChange, onRecordSelect, recordSelection, recordFocus, historyLoading, historyStartSeq, hasOlderRecords, onLoadOlder, onClearSelection, collapsedTurns, onToggleTurn, collapsedAssistants, onToggleAssistant, inspectCallId, onInspectApplied, }: TrajectoryTableProps): import("react").JSX.Element;
97
+ export {};
98
+ //# sourceMappingURL=TrajectoryTable.d.ts.map
@@ -0,0 +1,24 @@
1
+ /** Chrome-Network-style overview timeline for focusing the trajectory ledger. */
2
+ import type { TrajectoryTurnModel } from './layout.ts';
3
+ import { type TrajectoryTimelineMode, type TrajectoryTimeRange } from './timeline.ts';
4
+ /** Props for the fixed full-domain overview above the trajectory ledger. */
5
+ export interface TrajectoryTimelineProps {
6
+ turns: readonly TrajectoryTurnModel[];
7
+ mode: TrajectoryTimelineMode;
8
+ range: TrajectoryTimeRange | null;
9
+ /** Whether the loaded timeline omits an earlier history prefix. */
10
+ hasEarlierRecords?: boolean;
11
+ /** Load one earlier history page from the truncation control. */
12
+ onLoadEarlier?: () => Promise<boolean>;
13
+ selectedIndex?: number | null;
14
+ /** Record indexes matching the active ledger search, or null without a query. */
15
+ searchMatchIndexes?: ReadonlySet<number> | null;
16
+ onRangeChange: (range: TrajectoryTimeRange | null) => void;
17
+ /** Select a directly clicked timeline block. */
18
+ onRecordSelect?: (index: number) => void;
19
+ /** Bring the nearest record into view after clicking timeline whitespace. */
20
+ onRecordFocus?: (index: number) => void;
21
+ }
22
+ /** Overview renderer with drag ranges, click-sized focus, and Escape reset. */
23
+ export declare const TrajectoryTimeline: import("react").MemoExoticComponent<({ turns, mode, range, hasEarlierRecords, onLoadEarlier, selectedIndex, searchMatchIndexes, onRangeChange, onRecordSelect, onRecordFocus, }: TrajectoryTimelineProps) => import("react").JSX.Element>;
24
+ //# sourceMappingURL=TrajectoryTimeline.d.ts.map
@@ -0,0 +1,30 @@
1
+ /** Trajectory toolbar: timeline and ledger fold controls. */
2
+ export interface TrajectoryToolbarProps {
3
+ /** Whether timeline blocks use recorded durations instead of equal widths. */
4
+ actualDuration: boolean;
5
+ /** Select recorded-duration or equal-width blocks. */
6
+ onActualDurationChange: (actualDuration: boolean) => void;
7
+ /** Whether recorded timing retains idle gaps between operations. */
8
+ actualTime: boolean;
9
+ /** Select complete wall-clock timing or idle-compressed timing. */
10
+ onActualTimeChange: (actualTime: boolean) => void;
11
+ /** Whether every collapsible turn is currently folded. */
12
+ allTurnsCollapsed: boolean;
13
+ /** Fold or expand every collapsible turn. */
14
+ onToggleAllTurns: () => void;
15
+ /** Whether every collapsible assistant's tool calls are currently folded. */
16
+ allAssistantsCollapsed: boolean;
17
+ /** Fold or expand tool calls under every collapsible assistant. */
18
+ onToggleAllAssistants: () => void;
19
+ /** Current live ledger search query. */
20
+ searchQuery: string;
21
+ /** Update the live ledger search query. */
22
+ onSearchQueryChange: (query: string) => void;
23
+ }
24
+ /**
25
+ * Render the sticky trajectory toolbar.
26
+ * @param props - rendered counts and whole-list fold state.
27
+ * @returns the toolbar element.
28
+ */
29
+ export declare function TrajectoryToolbar({ actualDuration, onActualDurationChange, actualTime, onActualTimeChange, allTurnsCollapsed, onToggleAllTurns, allAssistantsCollapsed, onToggleAllAssistants, searchQuery, onSearchQueryChange, }: TrajectoryToolbarProps): import("react").JSX.Element;
30
+ //# sourceMappingURL=TrajectoryToolbar.d.ts.map
@@ -0,0 +1,14 @@
1
+ import type { ReactNode } from 'react';
2
+ export interface TrajectoryTurnProps {
3
+ /** 1-based turn index for the sticky header. */
4
+ turn: number;
5
+ /** Message / Step headers and TrajectoryCell rows. */
6
+ children?: ReactNode;
7
+ }
8
+ /**
9
+ * Render one turn section (sticky header + body).
10
+ * @param props - turn index and body children.
11
+ * @returns the turn section element.
12
+ */
13
+ export declare function TrajectoryTurn({ turn, children }: TrajectoryTurnProps): import("react").JSX.Element;
14
+ //# sourceMappingURL=TrajectoryTurn.d.ts.map
@@ -0,0 +1,11 @@
1
+ export interface TrajectoryTurnHeaderProps {
2
+ /** 1-based turn index shown as `Turn N`. */
3
+ turn: number;
4
+ }
5
+ /**
6
+ * Render the sticky turn header row.
7
+ * @param props.turn - turn index.
8
+ * @returns the sticky header element.
9
+ */
10
+ export declare function TrajectoryTurnHeader({ turn }: TrajectoryTurnHeaderProps): import("react").JSX.Element;
11
+ //# sourceMappingURL=TrajectoryTurnHeader.d.ts.map
@@ -0,0 +1,16 @@
1
+ /** Trajectory view: compact summary over a turn-aware event ledger. */
2
+ import type { ConvViewProps } from '@deepseek-ai/dsh-client-ui-conversation/client';
3
+ import type { InjectFace } from '@deepseek-ai/dsh-client-ui-slots';
4
+ import type { SessionHistoryFace, SnapshotStore } from '@deepseek-ai/dsh-client-runtime/client';
5
+ /** Session-history paging needed by the event-complete trajectory view. */
6
+ export interface TrajectoryViewInjected {
7
+ hooks: {
8
+ history: SessionHistoryFace;
9
+ duration: SnapshotStore<boolean>;
10
+ };
11
+ loadHistoryTail: (signal: AbortSignal) => Promise<void>;
12
+ loadOlderHistory: (signal: AbortSignal) => Promise<boolean>;
13
+ setActualDuration: (actualDuration: boolean) => void;
14
+ }
15
+ export declare function TrajectoryView({ useHistory, useDuration, loadHistoryTail, loadOlderHistory, setActualDuration, inspect, onInspectDone, }: ConvViewProps & InjectFace<TrajectoryViewInjected>): import("react").JSX.Element;
16
+ //# sourceMappingURL=TrajectoryView.d.ts.map
@@ -0,0 +1,29 @@
1
+ /** Rewind-delimited trajectory branches assembled across surface rewrites. */
2
+ import type { ConversationContext, ConversationNode, RequestView } from '@deepseek-ai/dsh-client-runtime/client';
3
+ /** One continuous context branch; compactions stay inline while rewinds start a successor branch. */
4
+ export interface TrajectoryContextBranch {
5
+ id: number;
6
+ /** Identity stable when older context generations are prepended. */
7
+ key: string;
8
+ contexts: readonly ConversationContext[];
9
+ latest: ConversationContext;
10
+ nodes: readonly ConversationNode[];
11
+ /** Seq that opened this branch; earlier requests require retained cited surface events. */
12
+ startSeq: number;
13
+ /** Exact pre-rewind surface records inherited by this branch. */
14
+ retainedSurfaceSeqs: ReadonlySet<number>;
15
+ }
16
+ /**
17
+ * Join context generations across compaction/rewrite operations and split only at rewind.
18
+ * @param contexts - Append-only context generations from the runtime fold.
19
+ * @returns Rewind-delimited branches in creation order.
20
+ */
21
+ export declare function deriveTrajectoryContextBranches(contexts: readonly ConversationContext[]): readonly TrajectoryContextBranch[];
22
+ /**
23
+ * Test whether a provider request belongs to one rewind branch.
24
+ * @param branch - Branch carrying the exact inherited surface event seqs.
25
+ * @param request - Provider request to classify.
26
+ * @returns Whether the request began on this branch or produced a retained surface record.
27
+ */
28
+ export declare function trajectoryBranchContainsRequest(branch: TrajectoryContextBranch, request: RequestView): boolean;
29
+ //# sourceMappingURL=context-branches.d.ts.map
@@ -0,0 +1,7 @@
1
+ import { type SnapshotStore } from '@deepseek-ai/dsh-client-runtime/client';
2
+ /**
3
+ * Create the browser-wide trajectory duration preference source.
4
+ * @returns a persisted source shared by every session view in one plugin lifecycle.
5
+ */
6
+ export declare function createTrajectoryDurationStore(): SnapshotStore<boolean>;
7
+ //# sourceMappingURL=duration-store.d.ts.map
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Browser trajectory plugin contributing one entry to the conversation view
3
+ * slot without defining a service.
4
+ */
5
+ import type { Context } from '@deepseek-ai/cordis';
6
+ /** Required services: the conversation view slot and independent history source. */
7
+ export declare const inject: string[];
8
+ /**
9
+ * Client plugin body: register the trajectory view tab. The registration
10
+ * rides the slot service's effect wrapper, so plugin unload removes the tab.
11
+ * @param ctx - client root context.
12
+ */
13
+ export declare function apply(ctx: Context): void;
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Trajectory list fold: expand assistant blocks, attach usage to Message,
3
+ * own-duration times, in-flight partial/runningCalls, and group descriptions.
4
+ */
5
+ import type { ConversationSnapshot, RequestInspectionSnapshot, RequestView } from '@deepseek-ai/dsh-client-runtime/client';
6
+ import type { TrajectoryCellProps } from './trajectory-record.ts';
7
+ /** One Message or Step group inside a turn. */
8
+ export interface TrajectoryGroupModel {
9
+ title: string;
10
+ description?: string;
11
+ cells: readonly TrajectoryCellProps[];
12
+ }
13
+ /** One sticky turn, or a standalone compaction section between turns. */
14
+ export interface TrajectoryTurnModel {
15
+ turn: number | null;
16
+ groups: readonly TrajectoryGroupModel[];
17
+ }
18
+ /** Snapshot slice the trajectory view folds. */
19
+ export interface TrajectoryLayoutInput {
20
+ nodes: ConversationSnapshot['nodes'];
21
+ partial: ConversationSnapshot['partial'];
22
+ runningCalls: ConversationSnapshot['runningCalls'];
23
+ requests?: readonly RequestView[];
24
+ callSchemas?: RequestInspectionSnapshot['callSchemas'];
25
+ }
26
+ /**
27
+ * Fold a snapshot into turn → Message/Step groups with expanded cells.
28
+ * @param input - nodes plus in-flight partial/runningCalls.
29
+ * @returns turns ordered by first appearance.
30
+ */
31
+ export declare function deriveTrajectoryLayout(input: TrajectoryLayoutInput): readonly TrajectoryTurnModel[];
32
+ /**
33
+ * Append the changing in-flight assistant cells to a stable finalized layout.
34
+ * @param turns - Finalized layout derived with an empty-block partial anchor.
35
+ * @param partial - Current in-flight assistant projection.
36
+ * @param lastIndex - Highest cell index in the finalized layout.
37
+ * @returns The original layout without a partial, otherwise a layout sharing every unaffected turn.
38
+ */
39
+ export declare function appendTrajectoryPartialLayout(turns: readonly TrajectoryTurnModel[], partial: ConversationSnapshot['partial'], lastIndex: number): readonly TrajectoryTurnModel[];
40
+ /**
41
+ * Build a bounded one-line ledger preview without parsing the complete Markdown document.
42
+ * Full source remains on the cell for the inspector.
43
+ * @param text - Untrusted message, reasoning, payload, or result text.
44
+ * @returns A compact preview capped independently from the retained source.
45
+ */
46
+ export declare function trajectoryPreviewText(text: string): string;
47
+ //# sourceMappingURL=layout.d.ts.map
@@ -0,0 +1,50 @@
1
+ /** Operation-sequence and recorded-time projections for the trajectory overview. */
2
+ import type { TrajectoryTurnModel } from './layout.ts';
3
+ import type { TrajectoryCellKind } from './trajectory-record.ts';
4
+ /** Horizontal projection used by the trajectory timeline. */
5
+ export type TrajectoryTimelineMode = 'sequence' | 'duration' | 'time' | 'actual';
6
+ /** Inclusive selection in the active timeline projection's domain. */
7
+ export interface TrajectoryTimeRange {
8
+ start: number;
9
+ end: number;
10
+ }
11
+ /** One ledger record projected into the active timeline domain. */
12
+ export interface TrajectoryTimelineSpan extends TrajectoryTimeRange {
13
+ index: number;
14
+ isError: boolean;
15
+ kind: TrajectoryCellKind;
16
+ label: string;
17
+ lane: number;
18
+ }
19
+ /** One turn boundary in the active timeline domain. */
20
+ export interface TrajectoryTimelineTurnBoundary {
21
+ turn: number;
22
+ time: number;
23
+ }
24
+ /** Full-domain model used by the overview. */
25
+ export interface TrajectoryTimelineModel extends TrajectoryTimeRange {
26
+ spans: readonly TrajectoryTimelineSpan[];
27
+ turnBoundaries: readonly TrajectoryTimelineTurnBoundary[];
28
+ }
29
+ /**
30
+ * Format a timeline duration as an integer-millisecond label.
31
+ * @param milliseconds - Non-negative duration in milliseconds.
32
+ * @returns Millisecond label with thousands separators.
33
+ */
34
+ export declare function formatTimelineOffset(milliseconds: number): string;
35
+ /**
36
+ * Project every visible record into a stable three-lane timeline.
37
+ * @param turns - Unfiltered trajectory layout.
38
+ * @param mode - Independent equal/recorded duration and compressed/complete time projection.
39
+ * @returns Timeline model, or `null` when no record is visible.
40
+ */
41
+ export declare function deriveTrajectoryTimeline(turns: readonly TrajectoryTurnModel[], mode?: TrajectoryTimelineMode): TrajectoryTimelineModel | null;
42
+ /**
43
+ * Identify records active at any point inside an inclusive selected interval.
44
+ * @param turns - Unfiltered trajectory layout.
45
+ * @param range - Selected interval in the active projection.
46
+ * @param mode - Independent equal/recorded duration and compressed/complete time projection.
47
+ * @returns Record indexes inside the focus interval.
48
+ */
49
+ export declare function trajectoryTimelineFocusIndexes(turns: readonly TrajectoryTurnModel[], range: TrajectoryTimeRange, mode?: TrajectoryTimelineMode): ReadonlySet<number>;
50
+ //# sourceMappingURL=timeline.d.ts.map
@@ -0,0 +1,101 @@
1
+ /** Shared trajectory record data and formatting contracts. */
2
+ import type { HTMLAttributes } from 'react';
3
+ import type { ConversationPromptSnapshot } from '@deepseek-ai/dsh-client-runtime/client';
4
+ /** Closed set of trajectory record kinds. */
5
+ export type TrajectoryCellKind = 'system' | 'user' | 'context' | 'compacted' | 'message' | 'tool' | 'subtool';
6
+ /** Recorded inputs needed to derive assistant TTFT and decode throughput. */
7
+ export interface AssistantMetricDetail {
8
+ timingRecorded: boolean;
9
+ stepStartTime: number | null;
10
+ firstTokenTime: number | null;
11
+ completedTime: number | null;
12
+ usageProvided: boolean;
13
+ outputTokens: number | null;
14
+ }
15
+ /** One source content block preserved in model order for the details panel. */
16
+ export interface TrajectorySourceBlock {
17
+ type: string;
18
+ content: string;
19
+ imageSrc?: string;
20
+ imageAlt?: string;
21
+ callId?: string;
22
+ toolName?: string;
23
+ }
24
+ /** Data and optional presentation attributes for one trajectory record. */
25
+ export interface TrajectoryCellProps extends HTMLAttributes<HTMLDivElement> {
26
+ /** 1-based record index shown as `#N`. */
27
+ index: number;
28
+ /** Projection-stable identity when no single source event owns the record lifecycle. */
29
+ recordId?: string;
30
+ kind: TrajectoryCellKind;
31
+ /** Single-line summary; CSS ellipsis when it overflows. */
32
+ text: string;
33
+ /** Whether this user record opens a new model turn. */
34
+ opensTurn?: boolean;
35
+ /** Source session-event seq for cross-record navigation. */
36
+ sourceSeq?: number;
37
+ /** Producer role and name from a user-role message or context injection. */
38
+ messageSource?: unknown;
39
+ /** Producer-owned model-hidden metadata carried beside the message source. */
40
+ /** A separator-only anchor for an auxiliary request with no visible record. */
41
+ requestOnly?: boolean;
42
+ /** Full request/message content for the details panel. */
43
+ inputDetail?: string;
44
+ /** Complete system-prompt/tool-catalog state introduced by a SYSTEM record. */
45
+ promptDetail?: ConversationPromptSnapshot;
46
+ /** System-prompt/tool-catalog state replaced by a SYSTEM update. */
47
+ previousPromptDetail?: ConversationPromptSnapshot;
48
+ /** Full assistant/tool result content for the details panel. */
49
+ outputDetail?: string;
50
+ /** Full assistant reasoning content for the details panel. */
51
+ thinkingDetail?: string;
52
+ /** Original message blocks in source order for the details panel. */
53
+ sourceBlocks?: readonly TrajectorySourceBlock[];
54
+ /** Original tool result blocks in source order for the details panel. */
55
+ outputBlocks?: readonly TrajectorySourceBlock[];
56
+ /** Call-time model-visible tool schema for the details panel. */
57
+ schemaDetail?: string;
58
+ /** Assistant-only timing and token facts for the details panel. */
59
+ assistantMetrics?: AssistantMetricDetail;
60
+ /** Tool-only result summary paired with the call in the same record. */
61
+ result?: string;
62
+ /** Tool call id used to link message source blocks to tool records. */
63
+ callId?: string;
64
+ /** Tool-only result failure state. */
65
+ isError?: boolean;
66
+ /** Own duration in seconds, or `null` when no duration is known. */
67
+ timeSeconds: number | null;
68
+ /** Unix epoch milliseconds when this operation actually started, when known. */
69
+ startedAt?: number | null;
70
+ /** Message-only prompt token count. */
71
+ input?: number;
72
+ /** Message-only input tokens served from a provider cache. */
73
+ cacheRead?: number;
74
+ /** Message-only input tokens written into a provider cache. */
75
+ cacheWrite?: number;
76
+ /** Message-only completion token count. */
77
+ output?: number;
78
+ /** Message-only reasoning token count. */
79
+ think?: number;
80
+ /** Whether the legacy standalone cell renders its selection treatment. */
81
+ selected?: boolean;
82
+ }
83
+ /**
84
+ * Resolve the identity that survives prepending older projected records.
85
+ * @param cell - Projected trajectory record.
86
+ * @returns Stable identity from the owning event or tool call, with a fixture fallback.
87
+ */
88
+ export declare function trajectoryRecordId(cell: TrajectoryCellProps): string;
89
+ /**
90
+ * Format a duration in milliseconds with thousands separators.
91
+ * @param milliseconds - Duration in milliseconds, or `null` when absent.
92
+ * @returns `—` when unknown, otherwise an integer-millisecond label.
93
+ */
94
+ export declare function formatDurationMillis(milliseconds: number | null): string;
95
+ /**
96
+ * Format an elapsed duration given in seconds as a millisecond label.
97
+ * @param seconds - Duration seconds, or `null` when absent.
98
+ * @returns `—` when unknown, otherwise an integer-millisecond label.
99
+ */
100
+ export declare function formatElapsedSeconds(seconds: number | null): string;
101
+ //# sourceMappingURL=trajectory-record.d.ts.map
@@ -0,0 +1,34 @@
1
+ /** Pure projection from trajectory records to measurable virtual ledger rows. */
2
+ import type { TrajectoryCellProps } from './trajectory-record.ts';
3
+ /** Minimal record shape required by the trajectory virtual-row projection. */
4
+ export interface VirtualizableTrajectoryRecord {
5
+ cell: TrajectoryCellProps;
6
+ collapsedSummaryKind?: 'turn' | 'assistant';
7
+ }
8
+ /** One logical record retained inside a measurable virtual row. */
9
+ export interface TrajectoryVirtualRowEntry<T extends VirtualizableTrajectoryRecord> {
10
+ logicalIndex: number;
11
+ record: T;
12
+ }
13
+ /** One virtualizer item, which may carry zero-height request boundaries. */
14
+ export interface TrajectoryVirtualRow<T extends VirtualizableTrajectoryRecord> {
15
+ entries: readonly TrajectoryVirtualRowEntry<T>[];
16
+ height: number;
17
+ key: string;
18
+ }
19
+ /**
20
+ * Derive the DOM-safe row identity shared by React, the virtualizer, and
21
+ * browser scroll contracts.
22
+ * @param record - Display record whose identity is required.
23
+ * @returns Stable record identity with a suffix for synthetic fold summaries.
24
+ */
25
+ export declare function trajectoryVirtualRecordKey(record: VirtualizableTrajectoryRecord): string;
26
+ /**
27
+ * Attach separator-only records to the next content row so the virtualizer
28
+ * never owns a zero-height item. A terminal separator retains its CSS-owned
29
+ * lower-marker clearance as a standalone item.
30
+ * @param records - Final search/fold projection in ledger order.
31
+ * @returns Measurable virtual rows with original logical positions retained.
32
+ */
33
+ export declare function groupTrajectoryVirtualRows<T extends VirtualizableTrajectoryRecord>(records: readonly T[]): readonly TrajectoryVirtualRow<T>[];
34
+ //# sourceMappingURL=trajectory-virtual-rows.d.ts.map
@@ -0,0 +1,4 @@
1
+ /** Host loader entry for the browser-only trajectory plugin. */
2
+ /** Provides no host-side behavior. */
3
+ export declare function apply(): void;
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Package-owned invariant companion for `@deepseek-ai/dsh-client-ui-trajectory`.
3
+ * @module @deepseek-ai/dsh-client-ui-trajectory/invariant
4
+ */
5
+ import type { Context } from '@deepseek-ai/cordis';
6
+ /** Cordis companion plugin name. */
7
+ export declare const name = "client-ui-trajectory-invariant";
8
+ /** Service required before the companion can reserve package ownership. */
9
+ export declare const inject: string[];
10
+ /**
11
+ * Register this package's invariant companion.
12
+ * @param ctx - Cordis context carrying the invariant service.
13
+ * @returns the installed registration's disposer after setup succeeds.
14
+ */
15
+ export declare const apply: (ctx: Context) => Promise<() => void>;
16
+ //# sourceMappingURL=invariant.d.ts.map
package/package.json ADDED
@@ -0,0 +1,76 @@
1
+ {
2
+ "name": "@deepseek-ai/dsh-client-ui-trajectory",
3
+ "description": "Trajectory event ledger with an interactive timing overview: pure-consumer plugin registering into the conversation ViewMap (no service)",
4
+ "version": "0.0.1-rc.1",
5
+ "publishConfig": {
6
+ "access": "restricted"
7
+ },
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/deepseek-ai/deepseek-harness.git",
11
+ "directory": "packages/client/ui-trajectory"
12
+ },
13
+ "type": "module",
14
+ "main": "lib/index.js",
15
+ "types": "lib/types/index.d.ts",
16
+ "exports": {
17
+ ".": {
18
+ "types": "./lib/types/index.d.ts",
19
+ "default": "./lib/index.js"
20
+ },
21
+ "./invariant": {
22
+ "types": "./lib/types/invariant.d.ts",
23
+ "default": "./lib/invariant.js"
24
+ },
25
+ "./client": {
26
+ "types": "./lib/types/client/index.d.ts",
27
+ "default": "./lib/client.js"
28
+ },
29
+ "./src/*": "./src/*",
30
+ "./package.json": "./package.json"
31
+ },
32
+ "dsh": {
33
+ "client": {
34
+ "inject": [
35
+ "@deepseek-ai/dsh-client-runtime",
36
+ "@deepseek-ai/dsh-client-ui-conversation"
37
+ ],
38
+ "platform": "web"
39
+ }
40
+ },
41
+ "license": "BSD-3-Clause",
42
+ "dependencies": {
43
+ "@tanstack/react-virtual": "^3.14.9",
44
+ "diff": "^9.0.0"
45
+ },
46
+ "peerDependencies": {
47
+ "react": "^18.2.0",
48
+ "react-dom": "^18.2.0",
49
+ "@deepseek-ai/dsh-client-runtime": "^0.0.1-rc.1",
50
+ "@deepseek-ai/dsh-invariants": "^0.0.1-rc.1",
51
+ "@deepseek-ai/dsh-client-ui-primitives": "^0.0.1-rc.1",
52
+ "@deepseek-ai/cordis": "^4.0.1-rc.1"
53
+ },
54
+ "devDependencies": {
55
+ "@types/react": "~18.3.1",
56
+ "@types/react-dom": "~18.3.0",
57
+ "react": "^18.2.0",
58
+ "react-dom": "^18.2.0",
59
+ "@deepseek-ai/dsh-client-ui-primitives": "^0.0.1-rc.1",
60
+ "@deepseek-ai/dsh-client-runtime": "^0.0.1-rc.1",
61
+ "@deepseek-ai/dsh-client-ui-slots": "^0.0.1-rc.1",
62
+ "@deepseek-ai/dsh-client-ui-conversation": "^0.0.1-rc.1",
63
+ "@deepseek-ai/dsh-invariants": "^0.0.1-rc.1",
64
+ "@deepseek-ai/cordis": "^4.0.1-rc.1"
65
+ },
66
+ "files": [
67
+ "lib/index.js",
68
+ "lib/invariant.js",
69
+ "lib/client.js",
70
+ "lib/types/**/*.d.ts"
71
+ ],
72
+ "scripts": {
73
+ "bundle": "tsdown",
74
+ "watch": "tsdown --watch"
75
+ }
76
+ }