@peasant-labs/fairtrade 0.0.62 → 0.0.63

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/dist/lib/share.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { _ as e, c as t, g as n, h as r, m as i, p as a, v as o } from "./time-CpVBzcqQ.js";
2
2
  import { r as s } from "./format-B3uT2wzU.js";
3
- import { c, s as l, t as u } from "./adapter-BSfSbqWE.js";
3
+ import { l as c, t as l, u } from "./adapter-ChziRV1K.js";
4
4
  import { jsx as d, jsxs as f } from "react/jsx-runtime";
5
5
  //#region public/tokens.json
6
6
  var p = {
@@ -556,7 +556,7 @@ function y(e) {
556
556
  return s(e);
557
557
  }
558
558
  function ce(e, t) {
559
- return l({
559
+ return c({
560
560
  title: typeof e.title == "string" && e.title.trim() !== "" ? e.title.trim() : void 0,
561
561
  hasNormalizedEvidence: t.session.hasNormalizedEvidence,
562
562
  firstTaskPrompt: t.tasks?.[0]?.prompt,
@@ -570,11 +570,11 @@ function le(e) {
570
570
  if (typeof n.harness != "string" || !Array.isArray(n.turns)) return null;
571
571
  let r;
572
572
  try {
573
- r = u(n);
573
+ r = l(n);
574
574
  } catch {
575
575
  return null;
576
576
  }
577
- let i = r.session, a = ce(n, r), o = typeof i.harness == "string" ? i.harness : "", s = oe(o) ? t[o] : null, l = n.turns.find((e) => e?.role === "user" && (e.depth ?? 0) === 0), d = typeof l?.content == "string" ? l.content : "", f = ae(i.harness === "cursor" ? c(d) : d).trim(), p = f || a, m = i.inputSubmissionCount, h = i.totalTokens, g = !r.usageScopes?.length && h != null, _ = m != null && g ? {
577
+ let i = r.session, a = ce(n, r), o = typeof i.harness == "string" ? i.harness : "", s = oe(o) ? t[o] : null, c = n.turns.find((e) => e?.role === "user" && (e.depth ?? 0) === 0), d = typeof c?.content == "string" ? c.content : "", f = ae(i.harness === "cursor" ? u(d) : d).trim(), p = f || a, m = i.inputSubmissionCount, h = i.totalTokens, g = !r.usageScopes?.length && h != null, _ = m != null && g ? {
578
578
  prompts: Number(m),
579
579
  tokens: Number(h)
580
580
  } : null;
@@ -1,17 +1,31 @@
1
1
  /** @typedef {import('./view-model.js').TurnVM} TurnVM */
2
2
  /**
3
3
  * @param {object} props
4
- * @param {TurnVM[]} [props.turns]
4
+ * @param {TurnVM[]} [props.turns] legacy turn mode
5
+ * @param {ScrubberTick[]} [props.ticks] segment sample; takes precedence over `turns`
5
6
  * @param {number} [props.active] the active TURN INDEX (TurnVM.index)
7
+ * @param {number} [props.activeTick] the active SEGMENT INDEX when `ticks` is supplied
6
8
  * @param {(clientX: number, track: HTMLElement) => void} [props.onSeek]
9
+ * @param {(tick: ScrubberTick) => void} [props.onSeekTick]
7
10
  * @param {{ current: boolean }} [props.draggingRef] shared drag latch; defaults to an internal ref
8
11
  */
9
- export default function Scrubber({ turns, active, onSeek, draggingRef }: {
12
+ export default function Scrubber({ turns, ticks, active, activeTick, onSeek, onSeekTick, draggingRef }: {
10
13
  turns?: TurnVM[];
14
+ ticks?: ScrubberTick[];
11
15
  active?: number;
16
+ activeTick?: number;
12
17
  onSeek?: (clientX: number, track: HTMLElement) => void;
18
+ onSeekTick?: (tick: ScrubberTick) => void;
13
19
  draggingRef?: {
14
20
  current: boolean;
15
21
  };
16
22
  }): import("react").JSX.Element;
17
23
  export type TurnVM = import("./view-model.js").TurnVM;
24
+ export type ScrubberTick = {
25
+ key: string;
26
+ index: number;
27
+ firstTurn: number;
28
+ lastTurn: number;
29
+ label: string;
30
+ leftPct: number;
31
+ };
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @param {object} props
3
+ * @param {SegmentBoundaryVM} props.boundary
4
+ * @param {(segmentIndex: number) => void} [props.onLoadMore]
5
+ * @param {boolean} [props.loading] the host is fetching the adjacent segment
6
+ */
7
+ export default function TranscriptBoundary({ boundary, onLoadMore, loading }: {
8
+ boundary: SegmentBoundaryVM;
9
+ onLoadMore?: (segmentIndex: number) => void;
10
+ loading?: boolean;
11
+ }): import("react").JSX.Element;
12
+ /** @typedef {import('./segments.js').SegmentBoundaryVM} SegmentBoundaryVM */
13
+ /** Thrown when a host mounts the boundary without the unloaded-edge descriptor. */
14
+ export class TranscriptSegmentBoundaryError extends Error {
15
+ /**
16
+ * @param {string} message
17
+ */
18
+ constructor(message: string);
19
+ }
20
+ export type SegmentBoundaryVM = import("./segments.js").SegmentBoundaryVM;
@@ -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, sidebarLayout: sidebarLayoutProp, onSidebarLayoutChange, zen: zenProp, onZenChange, readerWidth: readerWidthProp, onReaderWidthChange, 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, breadcrumbContext, beforeHeader, LinkComponent, renderTurnPanel, renderTurnActions, anchorHref, headerActions, utilityActions, streamPrelude, showTail, showOutcome, showSearchTrigger, footer, presentation, subtitle, pullRequests, headingLevel, integrity, transcriptContentHash, contentHash, }: TranscriptViewerProps): import("react").JSX.Element;
4
+ export default function TranscriptViewer({ viewModel, capabilities, callbacks, theme: themeProp, onThemeChange, graphSlot, activeTab: activeTabProp, onTabChange, viewMode: viewModeProp, onViewModeChange, sidebarLayout: sidebarLayoutProp, onSidebarLayoutChange, zen: zenProp, onZenChange, readerWidth: readerWidthProp, onReaderWidthChange, 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, breadcrumbContext, beforeHeader, LinkComponent, renderTurnPanel, renderTurnActions, anchorHref, headerActions, utilityActions, streamPrelude, showTail, showOutcome, showSearchTrigger, footer, presentation, subtitle, pullRequests, headingLevel, integrity, transcriptContentHash, contentHash, directory, segments: segmentsProp, window: windowProp, onLoadSegment, onLoadWindow, }: TranscriptViewerProps): import("react").JSX.Element;
5
5
  export const READER_FULL: "full";
6
6
  export type TranscriptViewerProps = import("./state-capabilities.js").TranscriptViewerProps;
7
7
  export type TranscriptFilters = import("./state-capabilities.js").TranscriptFilters;
@@ -20,6 +20,22 @@ export function thinkingDurationMs(previous: TurnDetail | undefined, turn: TurnD
20
20
  * @returns {TurnDetail[]}
21
21
  */
22
22
  export function prefilterTurns(turns: TurnDetail[]): TurnDetail[];
23
+ /** @param {TurnVM[]} turnVMs @returns {FileEntryVM[]} */
24
+ /**
25
+ * Aggregate the per-file read/edit/write counts and churn from cooked turns. Shared
26
+ * by the whole-transcript view model and a segmented viewer's loaded regions, so the
27
+ * Files tab has one derivation.
28
+ * @param {TurnVM[]} turnVMs
29
+ * @returns {FileEntryVM[]}
30
+ */
31
+ export function buildFiles(turnVMs: TurnVM[]): FileEntryVM[];
32
+ /**
33
+ * Tool-group counts for a set of cooked turns. Shared by the full filter index and a
34
+ * segmented viewer's loaded regions.
35
+ * @param {TurnVM[]} turnVMs
36
+ * @returns {Record<ToolGroup, number>}
37
+ */
38
+ export function buildToolGroupCounts(turnVMs: TurnVM[]): Record<ToolGroup, number>;
23
39
  /**
24
40
  * Project the canonical wire payload (folded turns) into the cooked
25
41
  * `TranscriptViewModel` every dumb transcript component renders. The SOLE
@@ -22,6 +22,7 @@ export { default as TranscriptCheckRow } from "./CheckRow.jsx";
22
22
  export { default as TranscriptViewSwitch } from "./ViewSwitch.jsx";
23
23
  export { default as TranscriptMinimap } from "./Minimap.jsx";
24
24
  export { default as TranscriptScrubber } from "./Scrubber.jsx";
25
+ export { default as TranscriptSegmentBoundary } from "./TranscriptBoundary.jsx";
25
26
  export { default as TranscriptScorecard } from "./Scorecard.jsx";
26
27
  export { default as TranscriptLabelPopover } from "./LabelPopover.jsx";
27
28
  export { default as useTranscriptInitialPosition } from "./useTranscriptInitialPosition.jsx";
@@ -44,6 +45,12 @@ export type SessionScorecard = import("./wire-types.js").SessionScorecard;
44
45
  export type CommitInfo = import("./wire-types.js").CommitInfo;
45
46
  export type AnnotationSummary = import("./wire-types.js").AnnotationSummary;
46
47
  export type SessionDetailPayload = import("./wire-types.js").SessionDetailPayload;
48
+ export type TranscriptSegmentDirectory = import("./wire-types.js").TranscriptSegmentDirectory;
49
+ export type TranscriptSegmentRef = import("./wire-types.js").TranscriptSegmentRef;
50
+ export type TranscriptSegment = import("./wire-types.js").TranscriptSegment;
51
+ export type TranscriptTurn = import("./wire-types.js").TranscriptTurn;
52
+ export type TranscriptWindow = import("./wire-types.js").TranscriptWindow;
53
+ export type SessionDetailHeaderPayload = import("./wire-types.js").SessionDetailHeaderPayload;
47
54
  export type TranscriptWireInput = import("./wire-types.js").TranscriptWireInput;
48
55
  export type TranscriptViewerProps = import("./state-capabilities.js").TranscriptViewerProps;
49
56
  export type TranscriptInitialPosition = import("./state-capabilities.js").TranscriptInitialPosition;
@@ -59,6 +66,12 @@ export type Presentation = import("./state-capabilities.js").Presentation;
59
66
  export type TranscriptTab = import("./state-capabilities.js").TranscriptTab;
60
67
  export type ViewMode = import("./state-capabilities.js").ViewMode;
61
68
  export type TranscriptViewModel = import("./view-model.js").TranscriptViewModel;
69
+ export type SegmentDirectoryVM = import("./segments.js").SegmentDirectoryVM;
70
+ export type SegmentRefVM = import("./segments.js").SegmentRefVM;
71
+ export type SegmentVM = import("./segments.js").SegmentVM;
72
+ export type SegmentWindowVM = import("./segments.js").SegmentWindowVM;
73
+ export type SegmentRegionVM = import("./segments.js").SegmentRegionVM;
74
+ export type SegmentBoundaryVM = import("./segments.js").SegmentBoundaryVM;
62
75
  export type RelationshipVM = import("./view-model.js").RelationshipVM;
63
76
  export type EarlierHistoryVM = import("./view-model.js").EarlierHistoryVM;
64
77
  export type AdaptTranscriptOptions = import("./adapter.js").AdaptTranscriptOptions;
@@ -82,10 +95,11 @@ export type PhaseVM = import("./view-model.js").PhaseVM;
82
95
  export type ScorecardBandVM = import("./view-model.js").ScorecardBandVM;
83
96
  export type TranscriptAnalyticsVM = import("./view-model.js").TranscriptAnalyticsVM;
84
97
  export { ROLES, ENTRY_TYPES, TOOL_CALL_KINDS, STOP_REASONS, SESSION_OUTCOMES, HARNESSES } from "./wire-types.js";
85
- export { adaptTranscript, prefilterTurns, diffLines } from "./adapter.js";
98
+ export { adaptTranscript, prefilterTurns, diffLines, buildFiles, buildToolGroupCounts } from "./adapter.js";
86
99
  export { computeTasks, computeTurnLabels, buildTaskWaterfall, annotateTranscript, computePersonalMedians, detectPhases, assessScorecard, computeAnalytics, computeTaskGroups, phaseLabel } from "./analytics.js";
87
100
  export { formatRelative, formatDurationMins, formatDurationMs, formatDurationSeconds, formatDateLong, isKnownTime } from "./time.js";
88
101
  export { summarizePrompt, composeSessionTitle, projectLabel, cleanSessionTitle, unwrapUserQuery } from "./title.js";
89
102
  export { default as TranscriptDiffEntryCard, DiffHunks as TranscriptDiffHunks } from "./DiffEntryCard.jsx";
90
103
  export { default as TranscriptViewer, READER_FULL } from "./TranscriptViewer.jsx";
104
+ export { SEGMENT_SCRUBBER_TICKS, SEGMENT_OVERSCAN_TURNS, boundaryCaption, formatByteExtent, loadedFiles, loadedRegions, loadedScope, loadedToolGroupCounts, mountedCardBound, normaliseSegments, regionBoundaries, scrubberTicks, turnsFromSegments, windowCoverage } from "./segments.js";
91
105
  export { advanceTranscriptInitialPositionConsumption, normalizeTranscriptInitialPosition, resolveTranscriptInitialPosition, shouldApplyTranscriptInitialPosition, transcriptInitialPositionReadiness, transcriptInitialPositionToken } from "./initial-position.js";
@@ -0,0 +1,146 @@
1
+ /** Turn a host's loaded segments into a sorted list. Accepts an array, a record keyed by
2
+ segment index, or a `Map`; each segment keeps all of its own fields. */
3
+ export function normaliseSegments(segments: any): any[];
4
+ /** The loaded turns, in identity order, without duplicates. A turn is the transport
5
+ unit's content, so the same identity must never render twice when two loads
6
+ overlap at a region edge. */
7
+ export function turnsFromSegments(segments: any): any[];
8
+ /** Merge adjacent loaded segments into rendered regions. A segment load that touches a
9
+ region extends it; a load that does not stays a separate region. */
10
+ export function loadedRegions(directory: any, segments: any): SegmentRegionVM[];
11
+ /**
12
+ * One boundary per unloaded edge adjacent to a rendered region, in document order.
13
+ * A gap between two regions gets one boundary with one load-more control (the
14
+ * proposal's boundary carries one control, not a pager); the control advances the
15
+ * older region into the gap.
16
+ *
17
+ * @param {SegmentDirectoryVM | null | undefined} directory
18
+ * @param {SegmentRegionVM[]} regions
19
+ * @returns {SegmentBoundaryVM[]}
20
+ */
21
+ export function regionBoundaries(directory: SegmentDirectoryVM | null | undefined, regions: SegmentRegionVM[]): SegmentBoundaryVM[];
22
+ /** Human byte extent: the boundary caption's size, and the truncation notice's own. */
23
+ export function formatByteExtent(bytes: any): string;
24
+ /** The boundary's caption: the unloaded extent on that side, in turns, segments and bytes. */
25
+ export function boundaryCaption(boundary: any): string;
26
+ /** The fixed scrubber sample over the directory. Never one tick per turn. */
27
+ export function scrubberTicks(directory: any): {
28
+ key: string;
29
+ index: any;
30
+ firstTurn: any;
31
+ lastTurn: any;
32
+ label: string;
33
+ leftPct: number;
34
+ }[];
35
+ /** What the trace count and the Files tab have actually read. */
36
+ export function loadedScope(directory: any, regions: any): {
37
+ loadedSegments: any;
38
+ totalSegments: number;
39
+ loadedTurns: any;
40
+ totalTurns: number;
41
+ complete: boolean;
42
+ filesText: string;
43
+ };
44
+ /** Whether every covering segment a window descriptor names is in hand. */
45
+ export function windowCoverage(window: any, segments: any): {
46
+ required: boolean;
47
+ complete: boolean;
48
+ missing: any;
49
+ indexes: any[];
50
+ };
51
+ /** The mounted-card bound: the turns of the loaded segments, and nothing else. */
52
+ export function mountedCardBound(segments: any): any;
53
+ /** The Files tab derived from the turns in hand: file, read/edit/write counts, churn,
54
+ and the first loaded turn that touched it. The one derivation lives in `adapter.js`,
55
+ so a segmented viewer and a whole-transcript view model cannot disagree. */
56
+ export function loadedFiles(turns: any): import("./view-model.js").FileEntryVM[];
57
+ /** Tool-group counts scoped to the turns the viewer actually holds. */
58
+ export function loadedToolGroupCounts(turns: any): Record<import("./view-model.js").ToolGroup, number>;
59
+ /** Whether a turn is a wordless assistant turn: a run of model actions that may have
60
+ started in a segment the reader has not loaded. */
61
+ export function isWordlessAssistant(turn: any): boolean;
62
+ /** @typedef {import('./view-model.js').TurnVM} TurnVM */
63
+ /** The scrubber's fixed sample size; the mounted tick count is `min(this, totalSegments)`. */
64
+ export const SEGMENT_SCRUBBER_TICKS: 200;
65
+ /** Extra turns a mounted region may draw beyond the turns it was given. The viewer
66
+ never invents turn content, so the overscan budget stays zero and the bound is the
67
+ loaded segments' own turns. Named so a surface cannot quietly grow it. */
68
+ export const SEGMENT_OVERSCAN_TURNS: 0;
69
+ export type TurnVM = import("./view-model.js").TurnVM;
70
+ /**
71
+ * One segment reference from the directory.
72
+ */
73
+ export type SegmentRefVM = {
74
+ index: number;
75
+ firstTurn: number;
76
+ lastTurn: number;
77
+ byteLength: number;
78
+ };
79
+ /**
80
+ * The transcript's only global index.
81
+ */
82
+ export type SegmentDirectoryVM = {
83
+ sessionId?: string;
84
+ revision?: string;
85
+ totalTurns: number;
86
+ totalSegments: number;
87
+ segments?: SegmentRefVM[];
88
+ directoryPage?: number;
89
+ directoryPerPage?: number;
90
+ };
91
+ /**
92
+ * One loaded segment, already cooked to `TurnVM`s.
93
+ */
94
+ export type SegmentVM = {
95
+ index: number;
96
+ firstTurn: number;
97
+ lastTurn: number;
98
+ byteLength: number;
99
+ hasOlder?: boolean;
100
+ hasNewer?: boolean;
101
+ turns: TurnVM[];
102
+ };
103
+ /**
104
+ * A window descriptor. It carries no turn content: only where the window is and
105
+ * which segments cover it.
106
+ */
107
+ export type SegmentWindowVM = {
108
+ sessionId?: string;
109
+ revision?: string;
110
+ requestedAnchor: number;
111
+ anchorTurn: number;
112
+ span: number;
113
+ firstTurn: number;
114
+ lastTurn: number;
115
+ segments: number[];
116
+ hasOlder?: boolean;
117
+ hasNewer?: boolean;
118
+ };
119
+ /**
120
+ * One contiguous run of loaded segments.
121
+ */
122
+ export type SegmentRegionVM = {
123
+ key: string;
124
+ firstSegment: number;
125
+ lastSegment: number;
126
+ firstTurn: number;
127
+ lastTurn: number;
128
+ refs: SegmentRefVM[];
129
+ turns: TurnVM[];
130
+ };
131
+ /**
132
+ * One unloaded edge in front of a rendered region.
133
+ */
134
+ export type SegmentBoundaryVM = {
135
+ key: string;
136
+ side: "older" | "newer" | "between" | "all";
137
+ firstTurn: number;
138
+ lastTurn: number;
139
+ segmentIndexes: number[];
140
+ segmentCount: number;
141
+ byteLength: number;
142
+ /**
143
+ * the segment a load-more on this edge appends/prepends
144
+ */
145
+ loadSegment: number;
146
+ };
@@ -126,6 +126,10 @@ export type ViewerCallbacks = {
126
126
  * authorized read target only; host owns current route and Back restoration
127
127
  */
128
128
  onNavigateRelationship?: (navigation: import("@peasant-labs/schema").SessionRelationshipNavigation) => void;
129
+ /**
130
+ * the reader asked for a bounded turn in full; the host performs the existing continuation read and replaces that turn
131
+ */
132
+ onLoadFullTurn?: (turnIndex: number) => void;
129
133
  };
130
134
  /**
131
135
  * What the `graphSlot` render-prop receives. The composite owns NO graph engine
@@ -335,6 +339,26 @@ export type TranscriptViewerBaseProps = {
335
339
  * the bare hash of the content `viewModel` was cooked from (the content route's `Village-Content-Hash` header). Turns are marked only when it equals `transcriptContentHash` and both are non-empty
336
340
  */
337
341
  contentHash?: string | null;
342
+ /**
343
+ * the transcript's only global index (segment refs, totals, revision). Supplied with `segments`, the viewer renders loaded regions instead of a whole-session turn list
344
+ */
345
+ directory?: import("./segments.js").SegmentDirectoryVM | null;
346
+ /**
347
+ * the segments the host has loaded, already cooked to `TurnVM`s; the viewer never mounts a turn it was not given
348
+ */
349
+ segments?: import("./segments.js").SegmentVM[] | Map<number, import("./segments.js").SegmentVM> | Record<number, import("./segments.js").SegmentVM>;
350
+ /**
351
+ * a jump descriptor: where the window is and which covering segments to load. It carries no turn content
352
+ */
353
+ window?: import("./segments.js").SegmentWindowVM | null;
354
+ /**
355
+ * load one segment; the boundary, the scrubber and a window all request through this one path
356
+ */
357
+ onLoadSegment?: (segmentIndex: number) => void | Promise<unknown>;
358
+ /**
359
+ * resolve a jump's window descriptor from a turn identity
360
+ */
361
+ onLoadWindow?: (anchorTurn: number, span?: number) => void | Promise<unknown>;
338
362
  };
339
363
  /**
340
364
  * The full legacy trail and the ancestor-only context are alternative contracts.
@@ -397,6 +397,18 @@ export type TurnVM = {
397
397
  * annotations targeting this turn (may be empty)
398
398
  */
399
399
  annotations: AnnotationVM[];
400
+ /**
401
+ * the segment this turn arrived in, when read as part of loaded regions
402
+ */
403
+ segmentIndex?: number;
404
+ /**
405
+ * this turn's own text was bounded by the served-text bound
406
+ */
407
+ truncated?: boolean;
408
+ /**
409
+ * pre-bound JSON size of content + arguments + result; the truncation notice's size
410
+ */
411
+ byteLength?: number;
400
412
  };
401
413
  /**
402
414
  * A cooked annotation, already resolved to the turn it targets. The adapter maps
@@ -11,6 +11,12 @@
11
11
  /** @typedef {import('@peasant-labs/schema').CommitInfo} CommitInfo */
12
12
  /** @typedef {import('@peasant-labs/schema').AnnotationSummary} AnnotationSummary */
13
13
  /** @typedef {import('@peasant-labs/schema').SessionDetailPayload} SessionDetailPayload */
14
+ /** @typedef {import('@peasant-labs/schema').TranscriptSegmentDirectory} TranscriptSegmentDirectory */
15
+ /** @typedef {import('@peasant-labs/schema').TranscriptSegmentRef} TranscriptSegmentRef */
16
+ /** @typedef {import('@peasant-labs/schema').TranscriptSegment} TranscriptSegment */
17
+ /** @typedef {import('@peasant-labs/schema').TranscriptTurn} TranscriptTurn */
18
+ /** @typedef {import('@peasant-labs/schema').TranscriptWindow} TranscriptWindow */
19
+ /** @typedef {import('@peasant-labs/schema').SessionDetailHeaderPayload} SessionDetailHeaderPayload */
14
20
  /** Canonical schema values exposed for compatibility with existing consumers. @type {readonly Role[]} */
15
21
  export const ROLES: readonly Role[];
16
22
  /** @type {readonly EntryType[]} */
@@ -36,6 +42,12 @@ export type SessionScorecard = import("@peasant-labs/schema").SessionScorecard;
36
42
  export type CommitInfo = import("@peasant-labs/schema").CommitInfo;
37
43
  export type AnnotationSummary = import("@peasant-labs/schema").AnnotationSummary;
38
44
  export type SessionDetailPayload = import("@peasant-labs/schema").SessionDetailPayload;
45
+ export type TranscriptSegmentDirectory = import("@peasant-labs/schema").TranscriptSegmentDirectory;
46
+ export type TranscriptSegmentRef = import("@peasant-labs/schema").TranscriptSegmentRef;
47
+ export type TranscriptSegment = import("@peasant-labs/schema").TranscriptSegment;
48
+ export type TranscriptTurn = import("@peasant-labs/schema").TranscriptTurn;
49
+ export type TranscriptWindow = import("@peasant-labs/schema").TranscriptWindow;
50
+ export type SessionDetailHeaderPayload = import("@peasant-labs/schema").SessionDetailHeaderPayload;
39
51
  export type LegacyCommit = {
40
52
  hash: string;
41
53
  message: string;
@@ -20,6 +20,22 @@ export function thinkingDurationMs(previous: TurnDetail | undefined, turn: TurnD
20
20
  * @returns {TurnDetail[]}
21
21
  */
22
22
  export function prefilterTurns(turns: TurnDetail[]): TurnDetail[];
23
+ /** @param {TurnVM[]} turnVMs @returns {FileEntryVM[]} */
24
+ /**
25
+ * Aggregate the per-file read/edit/write counts and churn from cooked turns. Shared
26
+ * by the whole-transcript view model and a segmented viewer's loaded regions, so the
27
+ * Files tab has one derivation.
28
+ * @param {TurnVM[]} turnVMs
29
+ * @returns {FileEntryVM[]}
30
+ */
31
+ export function buildFiles(turnVMs: TurnVM[]): FileEntryVM[];
32
+ /**
33
+ * Tool-group counts for a set of cooked turns. Shared by the full filter index and a
34
+ * segmented viewer's loaded regions.
35
+ * @param {TurnVM[]} turnVMs
36
+ * @returns {Record<ToolGroup, number>}
37
+ */
38
+ export function buildToolGroupCounts(turnVMs: TurnVM[]): Record<ToolGroup, number>;
23
39
  /**
24
40
  * Project the canonical wire payload (folded turns) into the cooked
25
41
  * `TranscriptViewModel` every dumb transcript component renders. The SOLE
@@ -397,6 +397,18 @@ export type TurnVM = {
397
397
  * annotations targeting this turn (may be empty)
398
398
  */
399
399
  annotations: AnnotationVM[];
400
+ /**
401
+ * the segment this turn arrived in, when read as part of loaded regions
402
+ */
403
+ segmentIndex?: number;
404
+ /**
405
+ * this turn's own text was bounded by the served-text bound
406
+ */
407
+ truncated?: boolean;
408
+ /**
409
+ * pre-bound JSON size of content + arguments + result; the truncation notice's size
410
+ */
411
+ byteLength?: number;
400
412
  };
401
413
  /**
402
414
  * A cooked annotation, already resolved to the turn it targets. The adapter maps
@@ -11,6 +11,12 @@
11
11
  /** @typedef {import('@peasant-labs/schema').CommitInfo} CommitInfo */
12
12
  /** @typedef {import('@peasant-labs/schema').AnnotationSummary} AnnotationSummary */
13
13
  /** @typedef {import('@peasant-labs/schema').SessionDetailPayload} SessionDetailPayload */
14
+ /** @typedef {import('@peasant-labs/schema').TranscriptSegmentDirectory} TranscriptSegmentDirectory */
15
+ /** @typedef {import('@peasant-labs/schema').TranscriptSegmentRef} TranscriptSegmentRef */
16
+ /** @typedef {import('@peasant-labs/schema').TranscriptSegment} TranscriptSegment */
17
+ /** @typedef {import('@peasant-labs/schema').TranscriptTurn} TranscriptTurn */
18
+ /** @typedef {import('@peasant-labs/schema').TranscriptWindow} TranscriptWindow */
19
+ /** @typedef {import('@peasant-labs/schema').SessionDetailHeaderPayload} SessionDetailHeaderPayload */
14
20
  /** Canonical schema values exposed for compatibility with existing consumers. @type {readonly Role[]} */
15
21
  export const ROLES: readonly Role[];
16
22
  /** @type {readonly EntryType[]} */
@@ -36,6 +42,12 @@ export type SessionScorecard = import("@peasant-labs/schema").SessionScorecard;
36
42
  export type CommitInfo = import("@peasant-labs/schema").CommitInfo;
37
43
  export type AnnotationSummary = import("@peasant-labs/schema").AnnotationSummary;
38
44
  export type SessionDetailPayload = import("@peasant-labs/schema").SessionDetailPayload;
45
+ export type TranscriptSegmentDirectory = import("@peasant-labs/schema").TranscriptSegmentDirectory;
46
+ export type TranscriptSegmentRef = import("@peasant-labs/schema").TranscriptSegmentRef;
47
+ export type TranscriptSegment = import("@peasant-labs/schema").TranscriptSegment;
48
+ export type TranscriptTurn = import("@peasant-labs/schema").TranscriptTurn;
49
+ export type TranscriptWindow = import("@peasant-labs/schema").TranscriptWindow;
50
+ export type SessionDetailHeaderPayload = import("@peasant-labs/schema").SessionDetailHeaderPayload;
39
51
  export type LegacyCommit = {
40
52
  hash: string;
41
53
  message: string;