@peasant-labs/fairtrade 0.0.19 → 0.0.20

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.
@@ -1,16 +1,26 @@
1
1
  /**
2
+ * A single checkbox - checked, unchecked, or mixed (indeterminate).
3
+ *
2
4
  * @typedef {Object} CheckboxProps
3
5
  * @property {boolean} [checked] controlled checked state (pair with onChange)
4
6
  * @property {boolean} [defaultChecked] initial state for uncontrolled use (default false)
7
+ * @property {boolean} [indeterminate] mixed state: draws a dash and reports the mixed
8
+ * accessible state while `checked` stays false (default false)
5
9
  * @property {(checked: boolean, event: import('react').ChangeEvent<HTMLInputElement>) => void} [onChange]
6
10
  * @property {boolean} [disabled] native disabled attribute (default false)
7
11
  * @property {import('react').ReactNode} [children] label text (rendered as passed, not lowercased)
8
12
  */
9
13
  /**
10
14
  * A single checkbox: <label class="check"> wrapping the styled <input type="checkbox" class="check-box">.
15
+ *
16
+ * `indeterminate` is a mixed state, distinct from checked: it renders its own dash and is exposed to
17
+ * assistive technology as `aria-checked="mixed"`, so the state is never carried by the mark alone.
18
+ * The mixed flag is not a DOM attribute on a native checkbox; it is the input's `indeterminate` IDL
19
+ * property, which is why the component owns a ref. A click on a mixed checkbox reports `true`, exactly
20
+ * as a plain unchecked checkbox would.
11
21
  * @param {CheckboxProps & import('react').InputHTMLAttributes<HTMLInputElement>} props
12
22
  */
13
- export default function Checkbox({ checked, defaultChecked, onChange, disabled, children, ...rest }: CheckboxProps & import("react").InputHTMLAttributes<HTMLInputElement>): import("react").JSX.Element;
23
+ export default function Checkbox({ checked, defaultChecked, indeterminate, onChange, disabled, children, ...rest }: CheckboxProps & import("react").InputHTMLAttributes<HTMLInputElement>): import("react").JSX.Element;
14
24
  /**
15
25
  * @typedef {Object} RadioProps
16
26
  * @property {string} name shared group name; radios must come in groups of >=2 so any one
@@ -53,6 +63,9 @@ export function Radio({ name, value, checked, defaultChecked, onChange, disabled
53
63
  * @param {RadioGroupProps & import('react').HTMLAttributes<HTMLDivElement>} props
54
64
  */
55
65
  export function RadioGroup({ name, value, defaultValue, onChange, options, ariaLabel, ...rest }: RadioGroupProps & import("react").HTMLAttributes<HTMLDivElement>): import("react").JSX.Element;
66
+ /**
67
+ * A single checkbox - checked, unchecked, or mixed (indeterminate).
68
+ */
56
69
  export type CheckboxProps = {
57
70
  /**
58
71
  * controlled checked state (pair with onChange)
@@ -62,6 +75,11 @@ export type CheckboxProps = {
62
75
  * initial state for uncontrolled use (default false)
63
76
  */
64
77
  defaultChecked?: boolean;
78
+ /**
79
+ * mixed state: draws a dash and reports the mixed
80
+ * accessible state while `checked` stays false (default false)
81
+ */
82
+ indeterminate?: boolean;
65
83
  onChange?: (checked: boolean, event: import("react").ChangeEvent<HTMLInputElement>) => void;
66
84
  /**
67
85
  * native disabled attribute (default false)
@@ -0,0 +1,226 @@
1
+ /**
2
+ * HelperGroup - a count chip inside one owner-anchored tree of saved threads.
3
+ *
4
+ * Presentation only: the host passes the complete authorized member set for the
5
+ * exact scope. No wire decoding, membership inference, fetching, paging, or
6
+ * selection storage occurs here. renderMember receives the original row,
7
+ * including its route-specific data.
8
+ *
9
+ * A helper tree is the ordinary row a host retained (`HelperGroupListItem`'s
10
+ * `owner`), the immediate groups that hang off it (`HelperGroup`), and the
11
+ * member rows those groups hold. The count chip sits ONE indent step inside the
12
+ * tree, between the owner row and the members it discloses, and carries no
13
+ * checkbox of its own. Members render only while the chip is open, each as a
14
+ * row like the owner's: title, middot facts, an individual checkbox, and
15
+ * host-authorized navigation.
16
+ *
17
+ * One continuous connector traces the centre of every MOUNTED row checkbox:
18
+ * verticals run in the parent's column, one square step lands on the deeper
19
+ * row's line, and one column is kept per depth, so a row the host never mounted
20
+ * is never traced. The connector is measured, never authored: mount,
21
+ * expand/collapse, a row that gains or loses its checkbox, and a resize all
22
+ * re-measure it.
23
+ *
24
+ * @param {object} props
25
+ * @param {string} props.groupId
26
+ * @param {string} props.memberScope - exact scope token the members belong to;
27
+ * a changed scope resets uncontrolled disclosure, never inherits it
28
+ * @param {number} props.helperThreadCount - saved threads, never review/message totals
29
+ * @param {unknown[]} [props.members]
30
+ * @param {(row: any) => import('react').ReactNode} props.renderMember
31
+ * @param {(row: any) => string} props.getMemberKey - stable local/public transcript ID
32
+ * @param {boolean} [props.expanded] - controlled disclosure for host Back restoration
33
+ * @param {(expanded: boolean) => void} [props.onExpandedChange]
34
+ * @param {boolean} [props.scopeExpired] - fail-closed: hides members, offers only
35
+ * an originating-list refresh, never loads anything broader
36
+ * @param {() => void} [props.onRefreshList] - refresh the originating query,
37
+ * never an all-members fallback
38
+ * @param {(row: any) => boolean} [props.isMemberSelected] - host-owned selection
39
+ * predicate; supply it whenever renderMember draws per-member checkboxes, so
40
+ * the CLOSED control can state a selection the viewer cannot see
41
+ * @param {import('react').ReactNode} [props.memberFooter] - host-rendered slot
42
+ * placed immediately after the member rows (or the empty notice) inside the
43
+ * open body: THE canonical position for host paging controls ("page X of Y",
44
+ * previous/next). Paging fetch, page/limit state, and the server counts stay
45
+ * host-owned; the group never fetches, stores a page, or reads a scope token,
46
+ * and renders the slot only while it is open and not scope-expired.
47
+ */
48
+ export default function HelperGroup(props: {
49
+ groupId: string;
50
+ memberScope: string;
51
+ helperThreadCount: number;
52
+ members?: unknown[];
53
+ renderMember: (row: any) => import("react").ReactNode;
54
+ getMemberKey: (row: any) => string;
55
+ expanded?: boolean;
56
+ onExpandedChange?: (expanded: boolean) => void;
57
+ scopeExpired?: boolean;
58
+ onRefreshList?: () => void;
59
+ isMemberSelected?: (row: any) => boolean;
60
+ memberFooter?: import("react").ReactNode;
61
+ }): import("react").JSX.Element;
62
+ /**
63
+ * Roll one owner row and its helper members up into the owner checkbox state.
64
+ * The owner's own row is part of the rollup, so a tree whose owner is selected
65
+ * but whose members are not states `partial`, never a clean `checked`.
66
+ * @param {string|undefined|null} ownerId
67
+ * @param {Array<string|undefined|null>} memberIds
68
+ * @param {(id: string) => boolean} isSelected
69
+ * @returns {'checked'|'unchecked'|'partial'}
70
+ */
71
+ export function helperOwnerState(ownerId: string | undefined | null, memberIds: Array<string | undefined | null>, isSelected: (id: string) => boolean): "checked" | "unchecked" | "partial";
72
+ /**
73
+ * The selection state of one helper tree: the DISPLAYED selection is the whole
74
+ * tree while the select-all override is active, and the manual set otherwise.
75
+ * Selection STATE stays host-owned; this is the value useHelperSelection stores.
76
+ * @typedef {object} HelperSelectionState
77
+ * @property {boolean} allActive - true while the select-all override is engaged
78
+ * @property {Set<string>} manual - the configured and hand-picked selection
79
+ */
80
+ /**
81
+ * The ids a tree currently DISPLAYS, owner first then members, or the manual set
82
+ * while the override is off. Ids are de-duplicated, and a missing owner (a
83
+ * helper-only result) is dropped.
84
+ * @param {HelperSelectionState} state
85
+ * @param {string|undefined|null} ownerId
86
+ * @param {Array<string|undefined|null>} memberIds
87
+ * @returns {string[]}
88
+ */
89
+ export function helperSelectionIds(state: HelperSelectionState, ownerId: string | undefined | null, memberIds: Array<string | undefined | null>): string[];
90
+ /**
91
+ * Toggle the owner checkbox: engage the all-selection from the manual side, or
92
+ * restore the manual selection from the all side. The manual set is never touched,
93
+ * so a manual member pick survives the cycle.
94
+ * @param {HelperSelectionState} state
95
+ * @returns {HelperSelectionState}
96
+ */
97
+ export function helperOwnerToggle(state: HelperSelectionState): HelperSelectionState;
98
+ /**
99
+ * Toggle one member checkbox. The write lands on the manual side and ends any
100
+ * all-selection: while the override is active the base is the DISPLAYED
101
+ * all-selection, so unticking one member keeps every other row selected and the
102
+ * next owner press restores all-but-that-member.
103
+ * @param {HelperSelectionState} state
104
+ * @param {string|undefined|null} ownerId
105
+ * @param {Array<string|undefined|null>} memberIds
106
+ * @param {string} memberId
107
+ * @param {boolean} checked
108
+ * @returns {HelperSelectionState}
109
+ */
110
+ export function helperMemberToggle(state: HelperSelectionState, ownerId: string | undefined | null, memberIds: Array<string | undefined | null>, memberId: string, checked: boolean): HelperSelectionState;
111
+ /**
112
+ * Hold the canonical helper-tree selection for one owner. The selection lives in
113
+ * the calling host, never in the components.
114
+ *
115
+ * A changed owner or member set is a different tree, so the hook resets to that
116
+ * tree's configured selection instead of carrying a pick across a scenario switch.
117
+ * @param {object} [config]
118
+ * @param {string} [config.ownerId] the tree's owner row id; omit for a
119
+ * helper-only result, where every member selects on its own
120
+ * @param {string[]} [config.memberIds] every helper member under that owner
121
+ * @param {string[]} [config.initialSelectedIds] the configured manual selection
122
+ * @returns {{selectedIds: string[], isSelected: (id: string) => boolean,
123
+ * ownerState: 'checked'|'unchecked'|'partial',
124
+ * onSelect: (id: string, checked: boolean) => void}}
125
+ */
126
+ export function useHelperSelection({ ownerId, memberIds, initialSelectedIds }?: {
127
+ ownerId?: string;
128
+ memberIds?: string[];
129
+ initialSelectedIds?: string[];
130
+ }): {
131
+ selectedIds: string[];
132
+ isSelected: (id: string) => boolean;
133
+ ownerState: "checked" | "unchecked" | "partial";
134
+ onSelect: (id: string, checked: boolean) => void;
135
+ };
136
+ /**
137
+ * One owner-anchored helper tree: an ordinary row (or an explicit unavailable
138
+ * context) above its immediate helper groups, traced by ONE measured connector.
139
+ *
140
+ * The tree owns the connector, not the rows: every mounted row registers its
141
+ * element here, the tree measures the centre of each mounted row checkbox after
142
+ * each change and on resize, and the single path is drawn behind the rows. The
143
+ * connector is a selection aid only - it carries no meaning that the rows and
144
+ * their checkboxes do not already carry.
145
+ *
146
+ * For a helper-only result supply ownerStatus instead of owner; no fake title
147
+ * or owner action is rendered. Keep distinct unresolved containers keyed by
148
+ * backend group ID.
149
+ * @param {object} props
150
+ * @param {import('react').ReactNode} [props.owner]
151
+ * @param {string} [props.ownerStatus]
152
+ * @param {import('react').ReactNode} props.children - immediate HelperGroup children
153
+ */
154
+ export function HelperGroupListItem({ owner, ownerStatus, children }: {
155
+ owner?: import("react").ReactNode;
156
+ ownerStatus?: string;
157
+ children: import("react").ReactNode;
158
+ }): import("react").JSX.Element;
159
+ /**
160
+ * One helper member drawn as the ordinary list row it is: title, a facts line
161
+ * with middot separators, an optional individual checkbox, and host-authorized
162
+ * navigation. Display-only when selection and navigation are both absent. The
163
+ * two optional behaviors are individual-only: a per-thread checkbox and
164
+ * host-authorized open navigation. No aggregate selection, no self-built links,
165
+ * no per-row disclosure. Hosts map scalar display props from their typed row and
166
+ * preserve route-specific status/usage/ordinary-child exits in children. These
167
+ * are UI props, not another wire DTO.
168
+ *
169
+ * Inside a helper tree the row registers itself so the tree can trace its
170
+ * checkbox; outside one it renders exactly as before. Because a host can turn
171
+ * selection off after mount, every render schedules a re-measure - the checkbox
172
+ * may have appeared or gone.
173
+ *
174
+ * Facts that have no measured value state that honestly ("unknown input
175
+ * submissions"), and a count of one singularizes: a row never claims "1 input
176
+ * submissions" or "1 turns". The separator falls BETWEEN facts that survive, so
177
+ * a row cannot open or end its facts line with a stray middot.
178
+ * @param {object} props
179
+ * @param {string} props.id - individual transcript identity, never a group ID
180
+ * @param {string} props.title - verbatim user content
181
+ * @param {string} [props.provider]
182
+ * @param {number} [props.inputSubmissionCount]
183
+ * @param {number} [props.turnCount]
184
+ * @param {string} [props.href] - host-created authorized route
185
+ * @param {(id: string, event: import('react').MouseEvent) => void} [props.onOpen]
186
+ * @param {boolean} [props.selected]
187
+ * @param {boolean} [props.selectionDisabled]
188
+ * @param {boolean} [props.indeterminate] - mixed state for a row that rolls
189
+ * helper members up (the tree owner); ignored without `onSelect`
190
+ * @param {(id: string, selected: boolean) => void} [props.onSelect]
191
+ * @param {import('react').ReactNode} [props.children]
192
+ */
193
+ export function HelperThreadRow({ id, title, provider, inputSubmissionCount, turnCount, href, onOpen, selected, selectionDisabled, indeterminate, onSelect, children }: {
194
+ id: string;
195
+ title: string;
196
+ provider?: string;
197
+ inputSubmissionCount?: number;
198
+ turnCount?: number;
199
+ href?: string;
200
+ onOpen?: (id: string, event: import("react").MouseEvent) => void;
201
+ selected?: boolean;
202
+ selectionDisabled?: boolean;
203
+ indeterminate?: boolean;
204
+ onSelect?: (id: string, selected: boolean) => void;
205
+ children?: import("react").ReactNode;
206
+ }): import("react").JSX.Element;
207
+ export namespace HELPER_OWNER_STATE {
208
+ let CHECKED: string;
209
+ let UNCHECKED: string;
210
+ let PARTIAL: string;
211
+ }
212
+ /**
213
+ * The selection state of one helper tree: the DISPLAYED selection is the whole
214
+ * tree while the select-all override is active, and the manual set otherwise.
215
+ * Selection STATE stays host-owned; this is the value useHelperSelection stores.
216
+ */
217
+ export type HelperSelectionState = {
218
+ /**
219
+ * - true while the select-all override is engaged
220
+ */
221
+ allActive: boolean;
222
+ /**
223
+ * - the configured and hand-picked selection
224
+ */
225
+ manual: Set<string>;
226
+ };
@@ -0,0 +1,36 @@
1
+ /**
2
+ * PromptDigest — the prompts behind a pull request, rendered read-only from the schema type.
3
+ *
4
+ * @param {object} props
5
+ * @param {PromptDigestPayload} props.digest - the digest exactly as Village computed it. the
6
+ * component renders the items it is given: it never builds, fetches, budgets, or collapses
7
+ * a chain. a collapsed chain arrives as data, its session boundary items standing in for
8
+ * the runs of prompts they hold.
9
+ * @param {(item: PromptDigestItemPayload) => string} [props.itemHref] - resolves one chain item to
10
+ * its link target; the item's `kind` selects the destination (`session` -> the transcript on
11
+ * Village, `prompt` and `skill` -> that turn in the shared transcript viewer, `commit` -> the
12
+ * commit on GitHub). omit it and the chain renders as plain rows; the component owns no routes.
13
+ * @param {PromptAuthor} [props.author] - the writer of these prompts, supplied by the page (not
14
+ * wire data). when given, every prompt row's avatar renders the writer's GitHub profile
15
+ * photo via the existing `Avatar` family; when omitted, prompt rows keep today's generic
16
+ * glyph.
17
+ * @param {string} [props.className] - extra classes appended after `.pd`
18
+ */
19
+ export default function PromptDigest({ digest, itemHref, author, className, ...rest }: {
20
+ digest: PromptDigestPayload;
21
+ itemHref?: (item: PromptDigestItemPayload) => string;
22
+ author?: PromptAuthor;
23
+ className?: string;
24
+ }): import("react").JSX.Element;
25
+ export type PromptDigestPayload = import("@peasant-labs/schema").PromptDigest;
26
+ export type PromptDigestItemPayload = import("@peasant-labs/schema").PromptDigestItem;
27
+ export type PromptAuthor = {
28
+ /**
29
+ * - the GitHub login; also the avatar's accessible name.
30
+ */
31
+ login: string;
32
+ /**
33
+ * - the GitHub profile photo url.
34
+ */
35
+ avatarUrl: string;
36
+ };
@@ -18,6 +18,7 @@ export { default as PolicySelect } from "./PolicySelect.jsx";
18
18
  export { default as MapCanvas } from "./MapCanvas.jsx";
19
19
  export { default as StepsWaterfall } from "./StepsWaterfall.jsx";
20
20
  export { default as GroupedMultiSelect } from "./GroupedMultiSelect.jsx";
21
+ export { default as PromptDigest } from "./PromptDigest.jsx";
21
22
  export { default as ToolCallRenderer } from "./ToolRenderers.jsx";
22
23
  export { default as Tour } from "./Tour.jsx";
23
24
  export { default as FacetRail } from "./FacetRail.jsx";
@@ -35,6 +36,7 @@ export { Avatar, AvatarGroup, Kbd, KbdChord, Tag } from "./Avatar.jsx";
35
36
  export { default as BrandMark, resolveBrand } from "./BrandMark.jsx";
36
37
  export { providerAccent, providerDisplayName } from "./provider-policy.js";
37
38
  export { Skeleton, Progress, Spinner, Toast, FeedbackPanel } from "./Feedback.jsx";
39
+ export { default as HelperGroup, HelperGroupListItem, HelperThreadRow, useHelperSelection, helperOwnerState, helperSelectionIds, helperOwnerToggle, helperMemberToggle, HELPER_OWNER_STATE } from "./HelperGroup.jsx";
38
40
  export { default as Timeline, TimelineItem, ToolCall, ThinkingBlock } from "./Timeline.jsx";
39
41
  export { default as ToastProvider, useToast } from "./ToastHost.jsx";
40
42
  export { default as DateRange, DateRangeCalendar, formatRange, DATE_PRESETS } from "./DateRange.jsx";
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Current-source navigation and retained history use only cooked evidence.
3
+ * No parent fetch occurs when a reader opens an earlier section.
4
+ * @param {object} props
5
+ * @param {import('./view-model.js').RelationshipVM[]} [props.relationships]
6
+ * @param {import('./view-model.js').EarlierHistoryVM[]} [props.earlierHistory]
7
+ * @param {import('./state-capabilities.js').ViewerCallbacks['onNavigateRelationship']} [props.onNavigate]
8
+ * @param {Record<string, boolean>} props.open
9
+ * @param {(id: string) => void} props.toggle
10
+ * @param {Record<string, boolean>} props.openTools
11
+ * @param {(id: string) => void} props.toggleTool
12
+ */
13
+ export default function TranscriptContext({ relationships, earlierHistory, onNavigate, open, toggle, openTools, toggleTool }: {
14
+ relationships?: import("./view-model.js").RelationshipVM[];
15
+ earlierHistory?: import("./view-model.js").EarlierHistoryVM[];
16
+ onNavigate?: import("./state-capabilities.js").ViewerCallbacks["onNavigateRelationship"];
17
+ open: Record<string, boolean>;
18
+ toggle: (id: string) => void;
19
+ openTools: Record<string, boolean>;
20
+ toggleTool: (id: string) => void;
21
+ }): import("react").JSX.Element;
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @param {TranscriptViewerProps} props
3
3
  */
4
- export default function TranscriptViewer({ viewModel, capabilities, callbacks, theme: themeProp, onThemeChange, graphSlot, activeTab: activeTabProp, onTabChange, viewMode: viewModeProp, onViewModeChange, leftRailOpen: leftRailOpenProp, onLeftRailOpenChange, rightRailOpen: rightRailOpenProp, onRightRailOpenChange, openTools: openToolsProp, onOpenToolsChange, initialPosition: initialPositionProp, activeTurn: activeTurnProp, onActiveTurnChange, search: searchProp, onSearchChange, filters: filtersProp, onFiltersChange, savedLabels: savedLabelsProp, onSavedLabelsChange, shareOpen: shareOpenProp, onShareOpenChange, moreOpen: moreOpenProp, onMoreOpenChange, breadcrumb, LinkComponent, renderTurnPanel, renderTurnActions, anchorHref, headerActions, streamPrelude, }: TranscriptViewerProps): import("react").JSX.Element;
4
+ export default function TranscriptViewer({ viewModel, capabilities, callbacks, theme: themeProp, onThemeChange, graphSlot, activeTab: activeTabProp, onTabChange, viewMode: viewModeProp, onViewModeChange, leftRailOpen: leftRailOpenProp, onLeftRailOpenChange, rightRailOpen: rightRailOpenProp, onRightRailOpenChange, openTools: openToolsProp, onOpenToolsChange, earlierHistoryOpen: earlierHistoryOpenProp, onEarlierHistoryOpenChange, initialPosition: initialPositionProp, activeTurn: activeTurnProp, onActiveTurnChange, search: searchProp, onSearchChange, filters: filtersProp, onFiltersChange, savedLabels: savedLabelsProp, onSavedLabelsChange, shareOpen: shareOpenProp, onShareOpenChange, moreOpen: moreOpenProp, onMoreOpenChange, breadcrumb, LinkComponent, renderTurnPanel, renderTurnActions, anchorHref, headerActions, streamPrelude, }: TranscriptViewerProps): import("react").JSX.Element;
5
5
  export type TranscriptViewerProps = import("./state-capabilities.js").TranscriptViewerProps;
6
6
  export type TranscriptFilters = import("./state-capabilities.js").TranscriptFilters;
7
7
  export type TraceReadingSnapshot = {
@@ -2,7 +2,8 @@
2
2
  export default function UsageDisclosure({ usage }: {
3
3
  usage?: import("@peasant-labs/schema").UsageDetail;
4
4
  }): import("react").JSX.Element;
5
- /** @param {{scopes?: import('./view-model.js').UsageScopeVM[]}} props */
6
- export function UsageScopes({ scopes }: {
5
+ /** @param {{scopes?: import('./view-model.js').UsageScopeVM[], label?: string}} props */
6
+ export function UsageScopes({ scopes, label }: {
7
7
  scopes?: import("./view-model.js").UsageScopeVM[];
8
+ label?: string;
8
9
  }): import("react").JSX.Element;
@@ -1,8 +1,8 @@
1
1
  /**
2
- * Default turn prefilter the adapter applies to `payload.turns`: drop turns with
3
- * neither content nor tool calls (and short tool-less system banners), then
4
- * collapse adjacent same-role turns with identical content (a streaming
5
- * artifact), preferring the tool-bearing copy. Pure, order-preserving. Exported
2
+ * Default turn prefilter the adapter applies independently per partition:
3
+ * preserve normalized evidence, including unknown provenance and folded refs.
4
+ * Only truly legacy rows lose empty/short banners or collapse equal adjacent
5
+ * content, preferring the tool-bearing copy. Pure, order-preserving. Exported
6
6
  * so a host that pre-scopes turns can run the SAME filter.
7
7
  * @param {TurnDetail[]} turns
8
8
  * @returns {TurnDetail[]}
@@ -59,4 +59,8 @@ export type AdaptTranscriptOptions = {
59
59
  * post-resolution projection by canonical turn index
60
60
  */
61
61
  visibleTurnIndices?: readonly number[];
62
+ /**
63
+ * separately authorized read metadata; never durable content
64
+ */
65
+ relationshipNavigation?: import("@peasant-labs/schema").SessionRelationshipNavigation[];
62
66
  };
@@ -49,6 +49,9 @@ export type Theme = import("./state-capabilities.js").Theme;
49
49
  export type TranscriptTab = import("./state-capabilities.js").TranscriptTab;
50
50
  export type ViewMode = import("./state-capabilities.js").ViewMode;
51
51
  export type TranscriptViewModel = import("./view-model.js").TranscriptViewModel;
52
+ export type RelationshipVM = import("./view-model.js").RelationshipVM;
53
+ export type EarlierHistoryVM = import("./view-model.js").EarlierHistoryVM;
54
+ export type AdaptTranscriptOptions = import("./adapter.js").AdaptTranscriptOptions;
52
55
  export type SessionVM = import("./view-model.js").SessionVM;
53
56
  export type SessionGitVM = import("./view-model.js").SessionGitVM;
54
57
  export type CommitVM = import("./view-model.js").CommitVM;
@@ -79,6 +79,8 @@ export type ViewerCapabilities = {
79
79
  * capability is true (see ViewerCapabilities). `onLabel` carries the popover's
80
80
  * cooked result; `onExport` carries the requested format. The viewer never
81
81
  * mutates the host's data — it reports intent through these.
82
+ * Relationship navigation is gated by authorized read evidence rather than a
83
+ * mutation capability; no usable target or no callback means no active control.
82
84
  */
83
85
  export type ViewerCallbacks = {
84
86
  onEdit?: () => void;
@@ -87,6 +89,10 @@ export type ViewerCallbacks = {
87
89
  onCopyLink?: () => void;
88
90
  onChangeVisibility?: () => void;
89
91
  onExport?: (format: "json" | "jsonl" | "markdown") => void;
92
+ /**
93
+ * authorized read target only; host owns current route and Back restoration
94
+ */
95
+ onNavigateRelationship?: (navigation: import("@peasant-labs/schema").SessionRelationshipNavigation) => void;
90
96
  };
91
97
  /**
92
98
  * What the `graphSlot` render-prop receives. The composite owns NO graph engine
@@ -151,6 +157,14 @@ export type TranscriptViewerProps = {
151
157
  */
152
158
  openTools?: Record<string, boolean>;
153
159
  onOpenToolsChange?: (openTools: Record<string, boolean>) => void;
160
+ /**
161
+ * section id to disclosure state, default closed
162
+ */
163
+ earlierHistoryOpen?: Record<string, boolean>;
164
+ /**
165
+ * persist with host route state for Back
166
+ */
167
+ onEarlierHistoryOpenChange?: (open: Record<string, boolean>) => void;
154
168
  /**
155
169
  * one-time position; null clears, and session/target/requestKey changes rearm
156
170
  */
@@ -51,6 +51,10 @@
51
51
  * @property {number} tokensIn
52
52
  * @property {number} tokensOut
53
53
  * @property {number} turnCount
54
+ * @property {number} [inputSubmissionCount] absent means unmeasured, never inferred from turns
55
+ * @property {boolean} [hasNormalizedEvidence] prevents legacy prompt-derived title inference
56
+ * @property {import('@peasant-labs/schema').SessionPurpose} [purpose]
57
+ * @property {string} [rootSessionId]
54
58
  * @property {number} toolCallCount
55
59
  * @property {string} [title] editorial session title/summary (render-when-present; else the consumer derives one from the first prompt). Not a wire field — supplied by a curated consumer.
56
60
  * @property {string} [project]
@@ -148,6 +152,16 @@ export type SessionVM = {
148
152
  tokensIn: number;
149
153
  tokensOut: number;
150
154
  turnCount: number;
155
+ /**
156
+ * absent means unmeasured, never inferred from turns
157
+ */
158
+ inputSubmissionCount?: number;
159
+ /**
160
+ * prevents legacy prompt-derived title inference
161
+ */
162
+ hasNormalizedEvidence?: boolean;
163
+ purpose?: import("@peasant-labs/schema").SessionPurpose;
164
+ rootSessionId?: string;
151
165
  toolCallCount: number;
152
166
  /**
153
167
  * editorial session title/summary (render-when-present; else the consumer derives one from the first prompt). Not a wire field — supplied by a curated consumer.
@@ -206,6 +220,14 @@ export type ToolCallVM = {
206
220
  * display name (e.g. "Read", "Bash")
207
221
  */
208
222
  name: string;
223
+ callEntryRef?: string;
224
+ resultEntryRef?: string;
225
+ callProvenance?: import("@peasant-labs/schema").ContentProvenance;
226
+ resultProvenance?: import("@peasant-labs/schema").ContentProvenance;
227
+ /**
228
+ * main or earlier-N, never a native coordinate
229
+ */
230
+ partition?: string;
209
231
  /**
210
232
  * separately recorded namespace; empty string remains present evidence
211
233
  */
@@ -270,6 +292,16 @@ export type ThinkingVM = {
270
292
  */
271
293
  export type TurnVM = {
272
294
  index: number;
295
+ /**
296
+ * partition-scoped stable rendering key
297
+ */
298
+ identity?: string;
299
+ /**
300
+ * main or earlier-N; main index navigation stays unchanged
301
+ */
302
+ partition?: string;
303
+ sourceEntryRef?: string;
304
+ provenance?: import("@peasant-labs/schema").ContentProvenance;
273
305
  role: import("./wire-types.js").Role;
274
306
  /**
275
307
  * display label, e.g. "1a" / "2"
@@ -607,6 +639,14 @@ export type TranscriptViewModel = {
607
639
  * render-when-present
608
640
  */
609
641
  analytics?: TranscriptAnalyticsVM;
642
+ /**
643
+ * authorized current-target navigation, cooked once
644
+ */
645
+ relationships?: RelationshipVM[];
646
+ /**
647
+ * separate index domains, collapsed by default
648
+ */
649
+ earlierHistory?: EarlierHistoryVM[];
610
650
  /**
611
651
  * non-conversational, including unattached records
612
652
  */
@@ -630,3 +670,21 @@ export type UsageScopeVM = {
630
670
  tokens: UsageFieldVM[];
631
671
  cost: UsageFieldVM[];
632
672
  };
673
+ export type RelationshipVM = {
674
+ kind: import("@peasant-labs/schema").SessionRelationshipKind;
675
+ label: string;
676
+ statusLabel: string;
677
+ note?: string;
678
+ /**
679
+ * only usable, authorized targets
680
+ */
681
+ navigation?: import("@peasant-labs/schema").SessionRelationshipNavigation;
682
+ };
683
+ export type EarlierHistoryVM = {
684
+ id: string;
685
+ state: import("@peasant-labs/schema").EarlierHistoryState;
686
+ explanation: string;
687
+ turns: TurnVM[];
688
+ nativeMetadata?: import("@peasant-labs/schema").NativeMetadataRecord[];
689
+ usageScopes: UsageScopeVM[];
690
+ };