@agi-fans/dsh-tui 0.16.0 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/lib/CHANGELOG.md +18 -1
  2. package/lib/chrome/tool-args.d.ts +9 -0
  3. package/lib/chrome/tool-args.js +20 -0
  4. package/lib/chrome/tool-args.js.map +1 -0
  5. package/lib/chrome/tool-renderers.js +4 -13
  6. package/lib/chrome/tool-renderers.js.map +1 -1
  7. package/lib/commands/session.js +2 -4
  8. package/lib/commands/session.js.map +1 -1
  9. package/lib/runtime/composer-images.d.ts +44 -0
  10. package/lib/runtime/composer-images.js +149 -0
  11. package/lib/runtime/composer-images.js.map +1 -0
  12. package/lib/runtime/herdr-agent.d.ts +95 -0
  13. package/lib/runtime/herdr-agent.js +258 -0
  14. package/lib/runtime/herdr-agent.js.map +1 -0
  15. package/lib/runtime/plain-tui.d.ts +34 -0
  16. package/lib/runtime/plain-tui.js +119 -0
  17. package/lib/runtime/plain-tui.js.map +1 -0
  18. package/lib/runtime/provider-local.d.ts +3 -0
  19. package/lib/runtime/provider-local.js +107 -268
  20. package/lib/runtime/provider-local.js.map +1 -1
  21. package/lib/runtime/tool-presentation.js +15 -0
  22. package/lib/runtime/tool-presentation.js.map +1 -1
  23. package/lib/session/content-text.d.ts +12 -0
  24. package/lib/session/content-text.js +13 -0
  25. package/lib/session/content-text.js.map +1 -0
  26. package/lib/session/history-store.js.map +1 -0
  27. package/lib/session/json-file.d.ts +5 -0
  28. package/lib/session/json-file.js +21 -0
  29. package/lib/session/json-file.js.map +1 -0
  30. package/lib/session/model-favorites.js +15 -25
  31. package/lib/session/model-favorites.js.map +1 -1
  32. package/lib/session/release-notes.js +1 -18
  33. package/lib/session/release-notes.js.map +1 -1
  34. package/lib/session/session-controller.js +64 -140
  35. package/lib/session/session-controller.js.map +1 -1
  36. package/lib/session/session-library.js +4 -14
  37. package/lib/session/session-library.js.map +1 -1
  38. package/lib/session/subagent-roster.js +13 -43
  39. package/lib/session/subagent-roster.js.map +1 -1
  40. package/lib/session/subagent-tracker.d.ts +58 -0
  41. package/lib/session/subagent-tracker.js +129 -0
  42. package/lib/session/subagent-tracker.js.map +1 -0
  43. package/lib/session/update-check.js +2 -15
  44. package/lib/session/update-check.js.map +1 -1
  45. package/lib/session/version-compare.d.ts +3 -0
  46. package/lib/session/version-compare.js +21 -0
  47. package/lib/session/version-compare.js.map +1 -0
  48. package/lib/views/event-views.d.ts +11 -270
  49. package/lib/views/event-views.js +12 -964
  50. package/lib/views/event-views.js.map +1 -1
  51. package/lib/views/settings-list.js +12 -11
  52. package/lib/views/settings-list.js.map +1 -1
  53. package/lib/views/transcript-render.d.ts +179 -0
  54. package/lib/views/transcript-render.js +916 -0
  55. package/lib/views/transcript-render.js.map +1 -0
  56. package/lib/views/transcript-types.d.ts +104 -0
  57. package/lib/views/transcript-types.js +53 -0
  58. package/lib/views/transcript-types.js.map +1 -0
  59. package/package.json +2 -1
  60. package/lib/views/history-store.js.map +0 -1
  61. /package/lib/{views → session}/history-store.d.ts +0 -0
  62. /package/lib/{views → session}/history-store.js +0 -0
@@ -0,0 +1,129 @@
1
+ /**
2
+ * SubagentTracker — Session/SessionEvent stream -> published TuiSubagentRoster.
3
+ *
4
+ * Owns the live SubagentRoster, the epoch that fences the async catalog
5
+ * listing, and the snapshot-identity dedup that keeps unchanged rosters off
6
+ * the wire. The controller supplies Harness lookups (depth, agent status,
7
+ * session list, durable children) and owns where the snapshot lands.
8
+ */
9
+ import { SubagentRoster } from "./subagent-roster.js";
10
+ export class SubagentTracker {
11
+ #deps;
12
+ #roster = new SubagentRoster();
13
+ #published;
14
+ #epoch = 0;
15
+ constructor(deps) {
16
+ this.#deps = deps;
17
+ }
18
+ /** Whether the roster already tracks this session id. */
19
+ owns(id) {
20
+ return this.#roster.owns(id);
21
+ }
22
+ /** The current published snapshot, or undefined for an empty roster. */
23
+ snapshot() {
24
+ return this.#roster.snapshot();
25
+ }
26
+ /** Drop all tracked children and invalidate any in-flight catalog listing. */
27
+ reset() {
28
+ this.#epoch += 1;
29
+ this.#roster.reset();
30
+ }
31
+ /** Remember a freshly created session when it descends from the root. */
32
+ noteSession(session) {
33
+ const depth = this.#deps.depth(session);
34
+ if (depth === undefined)
35
+ return;
36
+ const parentId = session.header.parentSession;
37
+ this.#roster.remember({
38
+ id: session.id,
39
+ ...(parentId === undefined ? {} : { parentId }),
40
+ depth,
41
+ phase: this.#deps.agentStatus(session.id) === 'running' ? 'running' : 'starting',
42
+ });
43
+ this.#publish();
44
+ }
45
+ /** Fold one durable child event into its roster row. */
46
+ noteEvent(session, event) {
47
+ const depth = this.#deps.depth(session);
48
+ if (depth === undefined)
49
+ return;
50
+ this.#roster.apply(session, depth, event, this.#deps.agentStatus(session.id));
51
+ this.#publish();
52
+ }
53
+ /** Add the direct children a Session's durable catalog declares. */
54
+ observeCatalog(session, events) {
55
+ if (this.#roster.observeCatalog(session.id, events))
56
+ this.#publish();
57
+ }
58
+ /** Apply a live agent-status change, hydrating cold children on first sight. */
59
+ noteStatus(session, status) {
60
+ if (this.#roster.owns(session.id)) {
61
+ this.#roster.setAgentStatus(session.id, status);
62
+ this.#publish();
63
+ return;
64
+ }
65
+ const depth = this.#deps.depth(session);
66
+ if (depth === undefined)
67
+ return;
68
+ this.#roster.hydrate(session, depth, this.#deps.agentStatus(session.id) ?? status);
69
+ this.#publish();
70
+ }
71
+ /** Mark a disposed session gone so its running tools settle. */
72
+ noteGone(session) {
73
+ if (!this.#roster.owns(session.id))
74
+ return;
75
+ this.#roster.setAgentStatus(session.id, 'gone');
76
+ this.#publish();
77
+ }
78
+ /**
79
+ * Rebuild the roster around the active root: live sessions hydrate from
80
+ * their own events, then the durable catalog lists children that are not
81
+ * loaded. A stale listing is fenced by the epoch and a root re-check.
82
+ */
83
+ sync() {
84
+ const rootId = this.#deps.rootId();
85
+ const epoch = this.#epoch + 1;
86
+ this.#epoch = epoch;
87
+ if (rootId === undefined) {
88
+ this.#roster.reset();
89
+ this.#publish();
90
+ return;
91
+ }
92
+ this.#roster.reset(rootId);
93
+ for (const session of this.#deps.sessions()) {
94
+ const depth = this.#deps.depth(session);
95
+ if (depth === undefined)
96
+ continue;
97
+ this.#roster.hydrate(session, depth, this.#deps.agentStatus(session.id));
98
+ }
99
+ this.#publish();
100
+ const listed = this.#deps.listChildren(rootId);
101
+ if (listed === undefined)
102
+ return;
103
+ void listed.then((entries) => {
104
+ if (epoch !== this.#epoch || this.#deps.rootId() !== rootId)
105
+ return;
106
+ for (const entry of entries) {
107
+ if (entry.kind !== 'child')
108
+ continue;
109
+ this.#roster.remember({
110
+ id: entry.id,
111
+ depth: 1,
112
+ mode: entry.mode,
113
+ ...(entry.label === undefined ? {} : { label: entry.label }),
114
+ phase: entry.activity === 'running' ? 'running' : 'waiting',
115
+ });
116
+ }
117
+ this.#publish();
118
+ }, () => undefined);
119
+ }
120
+ /** Push the roster when its snapshot identity changed since the last push. */
121
+ #publish() {
122
+ const roster = this.#roster.snapshot();
123
+ if (roster === this.#published)
124
+ return;
125
+ this.#published = roster;
126
+ this.#deps.publish(roster);
127
+ }
128
+ }
129
+ //# sourceMappingURL=subagent-tracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subagent-tracker.js","sourceRoot":"","sources":["../../src/session/subagent-tracker.ts"],"names":[],"mappings":"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"}
@@ -1,21 +1,8 @@
1
1
  /** Cached, transport-neutral npm update decision. */
2
- function numericVersion(version) {
3
- const match = /^(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/u.exec(version);
4
- if (match?.[1] === undefined || match[2] === undefined || match[3] === undefined)
5
- return undefined;
6
- return [Number(match[1]), Number(match[2]), Number(match[3])];
7
- }
2
+ import { compareVersions } from "./version-compare.js";
8
3
  /** Whether a registry version is newer than the running package. */
9
4
  export function isNewerVersion(candidate, current) {
10
- const left = numericVersion(candidate);
11
- const right = numericVersion(current);
12
- if (left === undefined || right === undefined)
13
- return false;
14
- for (let index = 0; index < left.length; index += 1) {
15
- if ((left[index] ?? 0) !== (right[index] ?? 0))
16
- return (left[index] ?? 0) > (right[index] ?? 0);
17
- }
18
- return false;
5
+ return compareVersions(candidate, current) > 0;
19
6
  }
20
7
  /** Resolve the latest version through a bounded cache and return only actionable updates. */
21
8
  export async function checkForUpdate(options) {
@@ -1 +1 @@
1
- {"version":3,"file":"update-check.js","sourceRoot":"","sources":["../../src/session/update-check.ts"],"names":[],"mappings":"AAAA,qDAAqD;AAOrD,SAAS,cAAc,CAAC,OAAe;IACrC,MAAM,KAAK,GAAG,mCAAmC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IAC/D,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,SAAS,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,SAAS,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,SAAS;QAAE,OAAO,SAAS,CAAA;IAClG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;AAC/D,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,cAAc,CAAC,SAAiB,EAAE,OAAe;IAC/D,MAAM,IAAI,GAAG,cAAc,CAAC,SAAS,CAAC,CAAA;IACtC,MAAM,KAAK,GAAG,cAAc,CAAC,OAAO,CAAC,CAAA;IACrC,IAAI,IAAI,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,KAAK,CAAA;IAC3D,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACpD,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAA;IACjG,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED,6FAA6F;AAC7F,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,OAOpC;IACC,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,SAAS,EAAE,CAAA;IACxC,IAAI,aAAqB,CAAA;IACzB,IAAI,MAAM,KAAK,SAAS,IAAI,OAAO,CAAC,GAAG,GAAG,MAAM,CAAC,SAAS,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;QAC/E,aAAa,GAAG,MAAM,CAAC,aAAa,CAAA;IACtC,CAAC;SAAM,CAAC;QACN,aAAa,GAAG,MAAM,OAAO,CAAC,WAAW,EAAE,CAAA;QAC3C,MAAM,OAAO,CAAC,UAAU,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,GAAG,EAAE,aAAa,EAAE,CAAC,CAAA;IACrE,CAAC;IACD,OAAO,cAAc,CAAC,aAAa,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAA;AAC1F,CAAC"}
1
+ {"version":3,"file":"update-check.js","sourceRoot":"","sources":["../../src/session/update-check.ts"],"names":[],"mappings":"AAAA,qDAAqD;AAErD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAOtD,oEAAoE;AACpE,MAAM,UAAU,cAAc,CAAC,SAAiB,EAAE,OAAe;IAC/D,OAAO,eAAe,CAAC,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,CAAA;AAChD,CAAC;AAED,6FAA6F;AAC7F,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,OAOpC;IACC,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,SAAS,EAAE,CAAA;IACxC,IAAI,aAAqB,CAAA;IACzB,IAAI,MAAM,KAAK,SAAS,IAAI,OAAO,CAAC,GAAG,GAAG,MAAM,CAAC,SAAS,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;QAC/E,aAAa,GAAG,MAAM,CAAC,aAAa,CAAA;IACtC,CAAC;SAAM,CAAC;QACN,aAAa,GAAG,MAAM,OAAO,CAAC,WAAW,EAAE,CAAA;QAC3C,MAAM,OAAO,CAAC,UAAU,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,GAAG,EAAE,aAAa,EAAE,CAAC,CAAA;IACrE,CAAC;IACD,OAAO,cAAc,CAAC,aAAa,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAA;AAC1F,CAAC"}
@@ -0,0 +1,3 @@
1
+ /** Three-part numeric version comparison shared by update checks and release notes. */
2
+ /** Compare two `major.minor.patch` versions; unparsable inputs compare equal. */
3
+ export declare function compareVersions(left: string, right: string): number;
@@ -0,0 +1,21 @@
1
+ /** Three-part numeric version comparison shared by update checks and release notes. */
2
+ function versionParts(version) {
3
+ const match = /^(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/u.exec(version);
4
+ if (match?.[1] === undefined || match[2] === undefined || match[3] === undefined)
5
+ return undefined;
6
+ return [Number(match[1]), Number(match[2]), Number(match[3])];
7
+ }
8
+ /** Compare two `major.minor.patch` versions; unparsable inputs compare equal. */
9
+ export function compareVersions(left, right) {
10
+ const a = versionParts(left);
11
+ const b = versionParts(right);
12
+ if (a === undefined || b === undefined)
13
+ return 0;
14
+ for (let index = 0; index < a.length; index += 1) {
15
+ const difference = (a[index] ?? 0) - (b[index] ?? 0);
16
+ if (difference !== 0)
17
+ return difference;
18
+ }
19
+ return 0;
20
+ }
21
+ //# sourceMappingURL=version-compare.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version-compare.js","sourceRoot":"","sources":["../../src/session/version-compare.ts"],"names":[],"mappings":"AAAA,uFAAuF;AAEvF,SAAS,YAAY,CAAC,OAAe;IACnC,MAAM,KAAK,GAAG,mCAAmC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IAC/D,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,SAAS,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,SAAS,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,SAAS;QAAE,OAAO,SAAS,CAAA;IAClG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;AAC/D,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,KAAa;IACzD,MAAM,CAAC,GAAG,YAAY,CAAC,IAAI,CAAC,CAAA;IAC5B,MAAM,CAAC,GAAG,YAAY,CAAC,KAAK,CAAC,CAAA;IAC7B,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,SAAS;QAAE,OAAO,CAAC,CAAA;IAChD,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACjD,MAAM,UAAU,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAA;QACpD,IAAI,UAAU,KAAK,CAAC;YAAE,OAAO,UAAU,CAAA;IACzC,CAAC;IACD,OAAO,CAAC,CAAA;AACV,CAAC"}
@@ -1,118 +1,18 @@
1
1
  /**
2
- * Transcript state machine: SessionEvent -> display blocks, and the pure
3
- * view that composes blocks + status + input into a render frame.
4
-
5
- * applyEvent is the single writer of TranscriptState; renderView is the
6
- * single reader. windowTranscript clips the body the way OMP's ScrollView
7
- * does. Both are pure so the whole rendering pipeline is testable without
8
- * a terminal.
2
+ * Transcript fold: SessionEvent/StreamDelta -> TranscriptState.
3
+ *
4
+ * applyEvent is the single writer of TranscriptState; replayEvents folds an
5
+ * immutable log without repeatedly copying its growing block array. Both are
6
+ * pure so the whole fold is testable without a terminal. Rendering lives in
7
+ * transcript-render.ts; consumers keep importing this module, which re-exports
8
+ * both halves.
9
9
  * @module @agi-fans/dsh-tui
10
10
  */
11
- import type { StreamChunk, ToolCallId, UserMessage } from '@deepseek-ai/dsh-llm';
12
11
  import type { SessionEvent } from '@deepseek-ai/dsh-session';
13
- import type { AutocompleteItem, SlashCommand } from './autocomplete.ts';
14
- import { type HistorySearchState } from './history-search.ts';
15
- import type { Frame, TranscriptScroll } from '../chrome/renderer.ts';
16
- import { type CopySelectorState } from './copy-selector.ts';
17
- import { type SettingsState } from './settings-list.ts';
18
- import { type TrajectoryState } from './trajectory.ts';
19
- import { type AgentHubState } from './agent-hub.ts';
20
- import { type PromptSelectorState } from './prompt-selector.ts';
21
- import { type StatusBarConfig, type StatusPreset } from '../chrome/status-config.ts';
22
- import { type Theme, type ThemeName } from '../chrome/theme.ts';
23
- import type { TuiInspectedSubagent, TuiLoopStatus, TuiRecentSession, TuiSessionControls, TuiSessionStats, TuiSubagentRoster, TuiSubmission } from '../definition.ts';
24
- import { type TuiToolPresentation } from '../chrome/tool-renderers.ts';
25
- import { type ToolInfo } from '../chrome/tools-list.ts';
26
- import type { WelcomeTip } from '../chrome/welcome-tips.ts';
27
- import type { MotionMode } from '../session/tui-settings.ts';
28
- type TodoItem = Extract<SessionEvent, {
29
- type: 'todo/write';
30
- }>['data']['todos'][number];
31
- /** Display state of one tool invocation. */
32
- export type ToolBlockStatus = 'running' | 'ok' | 'error';
33
- /** One rendered block of the transcript. */
34
- export type Block = {
35
- kind: 'user';
36
- text: string;
37
- } | {
38
- kind: 'assistant';
39
- turn: number;
40
- step: number;
41
- text: string;
42
- reasoning: string;
43
- streaming: boolean;
44
- interrupted?: boolean;
45
- } | {
46
- kind: 'tool';
47
- callId: ToolCallId;
48
- name: string;
49
- args: string;
50
- status: ToolBlockStatus;
51
- output: string;
52
- partial?: boolean;
53
- presentation?: TuiToolPresentation;
54
- } | {
55
- kind: 'toolCatalog';
56
- tools: readonly ToolInfo[];
57
- } | {
58
- kind: 'commandOutput';
59
- command: string;
60
- text: string;
61
- } | {
62
- kind: 'notice';
63
- level: 'info' | 'warning' | 'error';
64
- text: string;
65
- framed?: boolean;
66
- };
67
- /** Live session activity controlling the composer and activity row. */
68
- export type SessionStatus = 'idle' | 'running' | 'compacting';
69
- /** Mutable-free transcript state produced by applyEvent. */
70
- export interface TranscriptState {
71
- /** Ordered display blocks (user, assistant, tool). */
72
- blocks: Block[];
73
- /** Whole-agent liveness for the status line. */
74
- status: SessionStatus;
75
- /** The most recent turn number. */
76
- turn: number;
77
- /** Latest whole Todo projection emitted by the Harness for this turn. */
78
- todos: TodoItem[];
79
- /** Lifecycle id of a manual compact command currently owning the UI. */
80
- compactCommandId: string | undefined;
81
- /**
82
- * Durable compaction in flight: its identity, the shadow price its summary
83
- * reported, and the status to restore when it settles. Automatic compaction
84
- * runs inside an open turn, so the restored status is usually `running`.
85
- */
86
- compaction: {
87
- id: string;
88
- events: number;
89
- tokens: number;
90
- resume: SessionStatus;
91
- } | undefined;
92
- /** Durable follow-up turns waiting in the Harness-owned agent inbox. */
93
- nextTurnInbox: UserMessage[];
94
- /** Durable steering/context waiting for a later step (kept for splice fidelity). */
95
- nextStepInbox: UserMessage[];
96
- /**
97
- * Text of the turn that ended in failure, held until the next submission.
98
- * The transcript keeps its own error notice, but that row scrolls away while
99
- * the composer stays fixed, so a failed turn would otherwise leave an
100
- * apparently idle screen behind.
101
- */
102
- turnError: string | undefined;
103
- }
104
- /** Empty starting state. */
105
- export declare function initialTranscript(): TranscriptState;
106
- /**
107
- * One live assistant stream delta: a chunk folded with the owning attempt's
108
- * turn/step (live frames carry neither durable seq nor turn/step; the bridge
109
- * records them from the attempt's start frame).
110
- */
111
- export interface StreamDelta {
112
- readonly turn: number;
113
- readonly step: number;
114
- readonly chunk: StreamChunk;
115
- }
12
+ import type { TuiToolPresentation } from '../chrome/tool-renderers.ts';
13
+ import { type StreamDelta, type TranscriptState } from './transcript-types.ts';
14
+ export * from './transcript-types.ts';
15
+ export * from './transcript-render.ts';
116
16
  /**
117
17
  * Fold one live assistant stream chunk into the transcript state. Durable
118
18
  * settlement still arrives as `assistant/message` (or `assistant/attempt`
@@ -133,162 +33,3 @@ export declare function applyEvent(state: TranscriptState, event: SessionEvent,
133
33
  */
134
34
  export declare function replayEvents(events: readonly SessionEvent[], presentations?: ReadonlyMap<number, TuiToolPresentation>): TranscriptState;
135
35
  /** View options: terminal geometry and live input state. */
136
- export interface ViewOptions {
137
- /** Terminal width in columns. */
138
- width: number;
139
- /** Terminal height in rows; the view keeps the frame inside it. */
140
- height: number;
141
- /** Model name for the fixed footer. */
142
- model: string;
143
- /** Effective reasoning effort for the selected model, including adapter defaults. */
144
- reasoningEffort?: string;
145
- /** Folded session title; rendered only when the footer's `session` item is enabled. */
146
- sessionTitle?: string;
147
- /** Current input buffer text. */
148
- input: string;
149
- /** Cursor column inside the input buffer (0-based, before the prefix). */
150
- inputCursor: number;
151
- /** Number of client-owned image drafts represented by input markers. */
152
- inputImages?: number;
153
- /** Composer submissions accepted while the active turn is still running. */
154
- queuedSubmissions?: readonly TuiSubmission[];
155
- /** Whether to emit color SGR sequences. */
156
- colors: boolean;
157
- /** Working directory shown in the footer. */
158
- pwd?: string;
159
- /** Git branch shown in the footer. */
160
- branch?: string;
161
- /** Product version painted on the welcome title. */
162
- version?: string;
163
- /** Product name painted on the welcome title. */
164
- appName?: string;
165
- /** Spinner phase while a turn or tool is running. */
166
- spinnerFrame?: number;
167
- /** Animation policy for streaming, activity marks, and the working label. */
168
- motion?: MotionMode;
169
- /** 24-bit color; defaults to off so tests stay deterministic. */
170
- trueColor?: boolean;
171
- /** Shipped palette; defaults to dark. */
172
- themeName?: ThemeName;
173
- /** Slash-command popup sitting under the editor. */
174
- autocomplete?: {
175
- items: readonly AutocompleteItem[];
176
- selected: number;
177
- };
178
- /** Ctrl+R history-search overlay; replaces the editor while open. */
179
- historySearch?: HistorySearchState;
180
- /** `/settings` overlay; replaces the editor while open. */
181
- settings?: SettingsState;
182
- /** `/copy` picker overlay; replaces the editor while open. */
183
- copySelector?: CopySelectorState;
184
- /** `/trajectory` full-screen event ledger. */
185
- trajectory?: TrajectoryState;
186
- /** Keyboard-first full-screen descendant roster and inspector. */
187
- agentHub?: AgentHubState;
188
- /** Human-interaction selector; replaces the normal editor while active. */
189
- promptSelector?: PromptSelectorState;
190
- /** Effective local + agent-scoped slash command catalog. */
191
- commands?: readonly SlashCommand[];
192
- /** Durable rows shown in the welcome card. */
193
- recentSessions?: readonly TuiRecentSession[];
194
- /** Startup-stable sample of hints shown in the welcome card. */
195
- welcomeTips?: readonly WelcomeTip[];
196
- /** Whole-session figures rendered in the footer's telemetry row. */
197
- sessionStats?: TuiSessionStats;
198
- /** Harness-owned collaboration and permission state. Permission paints on the composer cap. */
199
- sessionControls?: TuiSessionControls;
200
- /** Process-local repeated-prompt state rendered beside model controls. */
201
- loopStatus?: TuiLoopStatus;
202
- /** Live descendant-subagent roster rendered above the composer. */
203
- subagents?: TuiSubagentRoster;
204
- /** Composer-boundary launcher focus entered with Down on an empty draft. */
205
- subagentLauncherFocused?: boolean;
206
- /** Descendant whose transcript is currently filling the viewport. */
207
- inspected?: TuiInspectedSubagent;
208
- /** Visible groups, order, and label style for the status line. */
209
- statusBar?: StatusBarConfig;
210
- /** Legacy status preset accepted while direct render callers migrate. */
211
- statusPreset?: StatusPreset;
212
- /**
213
- * First transcript row to show (0 = top). Omit or pass +Infinity to pin
214
- * the window to the latest lines — the OMP follow-tail default.
215
- */
216
- scrollStart?: number;
217
- /** Open one transcript block at its first row instead of following the tail. */
218
- focusBlock?: number;
219
- /**
220
- * Active transcript search. Matching block rows containing the query paint
221
- * inverse; `matches` are block indexes in render order and `focus` selects
222
- * the one the caller has scrolled to.
223
- */
224
- transcriptSearch?: {
225
- query: string;
226
- matches: readonly number[];
227
- focus: number;
228
- editing: boolean;
229
- };
230
- /**
231
- * When true, tool blocks paint their full output (OMP `ctrl+o`). Default
232
- * is the collapsed preview of {@link TOOL_COLLAPSED_LINES} rows.
233
- */
234
- toolsExpanded?: boolean;
235
- /** Individual tool calls expanded by the user. */
236
- expandedTools?: ReadonlySet<string>;
237
- }
238
- /** Collapsed tool-output preview height (OMP `DEFAULT_TERMINAL_PREVIEW_LINES`). */
239
- export declare const TOOL_COLLAPSED_LINES = 10;
240
- export declare const TOOL_INPUT_COLLAPSED_LINES = 3;
241
- /**
242
- * Render one transcript block to display lines. Pure; shared by the tty view
243
- * and the non-tty plain printer.
244
- * @param block - the block to render.
245
- * @param theme - active theme.
246
- * @param width - terminal width in columns.
247
- * @param spinnerFrame - activity spinner phase for running tools.
248
- * @param toolsExpanded - paint full tool output instead of the collapsed preview.
249
- * @returns display lines (already width-fitted).
250
- */
251
- export declare function blockLines(block: Block, theme: Theme, width: number, spinnerFrame?: number, toolsExpanded?: boolean): string[];
252
- /** Plain text of one block, used by transcript search and match painting. */
253
- export declare function blockSearchText(block: Block): string;
254
- /** Rows moved per Shift+Arrow (OMP ScrollView `fastScrollLines`). */
255
- export declare const TRANSCRIPT_FAST_SCROLL = 5;
256
- /**
257
- * Window `body` into `budget` rows with ↑/↓ overflow markers.
258
- * `start` is the first body row to keep; non-finite values pin to the tail.
259
- */
260
- export declare function windowTranscript(body: readonly string[], budget: number, start: number, theme: Theme): TranscriptScroll & {
261
- lines: string[];
262
- };
263
- /** Maximum number of queued composer submissions kept visible above the editor. */
264
- export declare const QUEUED_SUBMISSION_PREVIEW = 3;
265
- /** Maximum number of Todo items kept visible above the composer. */
266
- export declare const TODO_PREVIEW = 5;
267
- /** Maximum number of descendant subagents kept visible above the composer. */
268
- export declare const SUBAGENT_PREVIEW = 5;
269
- /** Compact, unframed Todo tree placed above queued messages. */
270
- export declare function renderTodos(todos: readonly TodoItem[], theme: Theme, width: number): string[];
271
- /** Compact, unframed descendant-subagent tree placed above Todos. */
272
- export declare function renderSubagents(roster: TuiSubagentRoster | undefined, theme: Theme, width: number, spinnerFrame?: number, inspectedId?: string, launcherFocused?: boolean): string[];
273
- /** Persistent inspect chrome: stays visible while the child transcript scrolls. */
274
- export declare function renderInspectBanner(inspected: TuiInspectedSubagent | undefined, theme: Theme, width: number, spinnerFrame?: number): string[];
275
- /**
276
- * One fixed row above the composer for a turn that ended in failure.
277
- *
278
- * The transcript keeps its own error notice, but transcript rows scroll into
279
- * native history while the composer stays put: without this row a turn that
280
- * failed while the user was reading elsewhere leaves an apparently idle screen.
281
- * The row is bounded to a single line so it cannot squeeze the transcript.
282
- */
283
- export declare function renderTurnError(text: string, theme: Theme, width: number): string[];
284
- /** Compact, unframed pending-message view placed immediately above the composer. */
285
- export declare function renderQueuedSubmissions(submissions: readonly TuiSubmission[], theme: Theme, width: number, inbox?: readonly UserMessage[]): string[];
286
- /**
287
- * Compose the welcome card, transcript, working row, and rounded editor into
288
- * one frame — the oh-my-pi surface.
289
- * @param state - transcript state.
290
- * @param options - terminal geometry and input state.
291
- * @returns the frame to hand to a renderer.
292
- */
293
- export declare function renderView(state: TranscriptState, options: ViewOptions): Frame;
294
- export {};