@aui.io/apollo 0.1.11 → 0.1.13

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 (160) hide show
  1. package/node_modules/@aui.io/apollo-cli/package.json +3 -3
  2. package/node_modules/@aui.io/apollo-core/package.json +1 -1
  3. package/node_modules/@aui.io/apollo-tui/dist/src/actions/ActionPalette.d.ts +3 -1
  4. package/node_modules/@aui.io/apollo-tui/dist/src/actions/ActionPalette.js +7 -2
  5. package/node_modules/@aui.io/apollo-tui/dist/src/actions/ActionPalette.js.map +1 -1
  6. package/node_modules/@aui.io/apollo-tui/dist/src/activity/ActivityDrawer.d.ts +3 -1
  7. package/node_modules/@aui.io/apollo-tui/dist/src/activity/ActivityDrawer.js +8 -3
  8. package/node_modules/@aui.io/apollo-tui/dist/src/activity/ActivityDrawer.js.map +1 -1
  9. package/node_modules/@aui.io/apollo-tui/dist/src/activity/ActivitySummary.js.map +1 -1
  10. package/node_modules/@aui.io/apollo-tui/dist/src/activity/operationStore.js +4 -3
  11. package/node_modules/@aui.io/apollo-tui/dist/src/activity/operationStore.js.map +1 -1
  12. package/node_modules/@aui.io/apollo-tui/dist/src/author/AuthorHome.d.ts +12 -4
  13. package/node_modules/@aui.io/apollo-tui/dist/src/author/AuthorHome.js +67 -9
  14. package/node_modules/@aui.io/apollo-tui/dist/src/author/AuthorHome.js.map +1 -1
  15. package/node_modules/@aui.io/apollo-tui/dist/src/author/DiffView.d.ts +7 -1
  16. package/node_modules/@aui.io/apollo-tui/dist/src/author/DiffView.js +35 -8
  17. package/node_modules/@aui.io/apollo-tui/dist/src/author/DiffView.js.map +1 -1
  18. package/node_modules/@aui.io/apollo-tui/dist/src/author/SessionPane.d.ts +9 -2
  19. package/node_modules/@aui.io/apollo-tui/dist/src/author/SessionPane.js +24 -5
  20. package/node_modules/@aui.io/apollo-tui/dist/src/author/SessionPane.js.map +1 -1
  21. package/node_modules/@aui.io/apollo-tui/dist/src/author/ValidationView.js +2 -1
  22. package/node_modules/@aui.io/apollo-tui/dist/src/author/ValidationView.js.map +1 -1
  23. package/node_modules/@aui.io/apollo-tui/dist/src/author/VersionsView.js +4 -3
  24. package/node_modules/@aui.io/apollo-tui/dist/src/author/VersionsView.js.map +1 -1
  25. package/node_modules/@aui.io/apollo-tui/dist/src/author/data.d.ts +9 -0
  26. package/node_modules/@aui.io/apollo-tui/dist/src/author/data.js +31 -1
  27. package/node_modules/@aui.io/apollo-tui/dist/src/author/data.js.map +1 -1
  28. package/node_modules/@aui.io/apollo-tui/dist/src/author/session.d.ts +10 -1
  29. package/node_modules/@aui.io/apollo-tui/dist/src/author/session.js +19 -6
  30. package/node_modules/@aui.io/apollo-tui/dist/src/author/session.js.map +1 -1
  31. package/node_modules/@aui.io/apollo-tui/dist/src/context/ContextSwitcher.d.ts +3 -1
  32. package/node_modules/@aui.io/apollo-tui/dist/src/context/ContextSwitcher.js +7 -2
  33. package/node_modules/@aui.io/apollo-tui/dist/src/context/ContextSwitcher.js.map +1 -1
  34. package/node_modules/@aui.io/apollo-tui/dist/src/index.d.ts +4 -3
  35. package/node_modules/@aui.io/apollo-tui/dist/src/index.js +4 -3
  36. package/node_modules/@aui.io/apollo-tui/dist/src/index.js.map +1 -1
  37. package/node_modules/@aui.io/apollo-tui/dist/src/lib/actions.d.ts +3 -0
  38. package/node_modules/@aui.io/apollo-tui/dist/src/lib/actions.js +3 -0
  39. package/node_modules/@aui.io/apollo-tui/dist/src/lib/actions.js.map +1 -1
  40. package/node_modules/@aui.io/apollo-tui/dist/src/lib/jsonview.d.ts +31 -0
  41. package/node_modules/@aui.io/apollo-tui/dist/src/lib/jsonview.js +114 -0
  42. package/node_modules/@aui.io/apollo-tui/dist/src/lib/jsonview.js.map +1 -0
  43. package/node_modules/@aui.io/apollo-tui/dist/src/lib/sheet.js +10 -7
  44. package/node_modules/@aui.io/apollo-tui/dist/src/lib/sheet.js.map +1 -1
  45. package/node_modules/@aui.io/apollo-tui/dist/src/opentui-app.js +200 -90
  46. package/node_modules/@aui.io/apollo-tui/dist/src/opentui-app.js.map +1 -1
  47. package/node_modules/@aui.io/apollo-tui/dist/src/shell/Breadcrumb.d.ts +5 -2
  48. package/node_modules/@aui.io/apollo-tui/dist/src/shell/Breadcrumb.js +10 -4
  49. package/node_modules/@aui.io/apollo-tui/dist/src/shell/Breadcrumb.js.map +1 -1
  50. package/node_modules/@aui.io/apollo-tui/dist/src/shell/FooterHints.js +3 -2
  51. package/node_modules/@aui.io/apollo-tui/dist/src/shell/FooterHints.js.map +1 -1
  52. package/node_modules/@aui.io/apollo-tui/dist/src/shell/ModeNav.d.ts +2 -1
  53. package/node_modules/@aui.io/apollo-tui/dist/src/shell/ModeNav.js +29 -3
  54. package/node_modules/@aui.io/apollo-tui/dist/src/shell/ModeNav.js.map +1 -1
  55. package/node_modules/@aui.io/apollo-tui/dist/src/talk/Composer.d.ts +3 -1
  56. package/node_modules/@aui.io/apollo-tui/dist/src/talk/Composer.js +4 -3
  57. package/node_modules/@aui.io/apollo-tui/dist/src/talk/Composer.js.map +1 -1
  58. package/node_modules/@aui.io/apollo-tui/dist/src/talk/InspectorPane.d.ts +8 -3
  59. package/node_modules/@aui.io/apollo-tui/dist/src/talk/InspectorPane.js +7 -5
  60. package/node_modules/@aui.io/apollo-tui/dist/src/talk/InspectorPane.js.map +1 -1
  61. package/node_modules/@aui.io/apollo-tui/dist/src/talk/TalkView.d.ts +15 -2
  62. package/node_modules/@aui.io/apollo-tui/dist/src/talk/TalkView.js +22 -5
  63. package/node_modules/@aui.io/apollo-tui/dist/src/talk/TalkView.js.map +1 -1
  64. package/node_modules/@aui.io/apollo-tui/dist/src/talk/ThreadsPane.d.ts +5 -2
  65. package/node_modules/@aui.io/apollo-tui/dist/src/talk/ThreadsPane.js +10 -4
  66. package/node_modules/@aui.io/apollo-tui/dist/src/talk/ThreadsPane.js.map +1 -1
  67. package/node_modules/@aui.io/apollo-tui/dist/src/talk/data.d.ts +14 -3
  68. package/node_modules/@aui.io/apollo-tui/dist/src/talk/data.js +12 -2
  69. package/node_modules/@aui.io/apollo-tui/dist/src/talk/data.js.map +1 -1
  70. package/node_modules/@aui.io/apollo-tui/dist/src/theme/glyphs.d.ts +52 -0
  71. package/node_modules/@aui.io/apollo-tui/dist/src/theme/glyphs.js +76 -0
  72. package/node_modules/@aui.io/apollo-tui/dist/src/theme/glyphs.js.map +1 -0
  73. package/node_modules/@aui.io/apollo-tui/dist/src/theme/syntax.d.ts +20 -0
  74. package/node_modules/@aui.io/apollo-tui/dist/src/theme/syntax.js +54 -0
  75. package/node_modules/@aui.io/apollo-tui/dist/src/theme/syntax.js.map +1 -0
  76. package/node_modules/@aui.io/apollo-tui/dist/src/theme/tokens.d.ts +26 -8
  77. package/node_modules/@aui.io/apollo-tui/dist/src/theme/tokens.js +46 -8
  78. package/node_modules/@aui.io/apollo-tui/dist/src/theme/tokens.js.map +1 -1
  79. package/node_modules/@aui.io/apollo-tui/dist/src/ui/JsonPane.d.ts +12 -0
  80. package/node_modules/@aui.io/apollo-tui/dist/src/ui/JsonPane.js +22 -0
  81. package/node_modules/@aui.io/apollo-tui/dist/src/ui/JsonPane.js.map +1 -0
  82. package/node_modules/@aui.io/apollo-tui/dist/src/ui/PickerPane.d.ts +3 -1
  83. package/node_modules/@aui.io/apollo-tui/dist/src/ui/PickerPane.js +8 -3
  84. package/node_modules/@aui.io/apollo-tui/dist/src/ui/PickerPane.js.map +1 -1
  85. package/node_modules/@aui.io/apollo-tui/dist/src/ui/SheetPane.js +3 -2
  86. package/node_modules/@aui.io/apollo-tui/dist/src/ui/SheetPane.js.map +1 -1
  87. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/LICENSE +21 -0
  88. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/README.md +269 -0
  89. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/debug/tree-sitter.cjs +4558 -0
  90. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/debug/tree-sitter.cjs.map +7 -0
  91. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/debug/tree-sitter.js +4516 -0
  92. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/debug/tree-sitter.js.map +7 -0
  93. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/debug/tree-sitter.wasm +0 -0
  94. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/debug/tree-sitter.wasm.map +31 -0
  95. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/alloc.c +48 -0
  96. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/alloc.h +41 -0
  97. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/array.h +291 -0
  98. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/atomic.h +68 -0
  99. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/clock.h +146 -0
  100. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/error_costs.h +11 -0
  101. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/get_changed_ranges.c +523 -0
  102. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/get_changed_ranges.h +36 -0
  103. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/host.h +21 -0
  104. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/language.c +293 -0
  105. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/language.h +293 -0
  106. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/length.h +52 -0
  107. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/lexer.c +483 -0
  108. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/lexer.h +54 -0
  109. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/lib.c +12 -0
  110. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/node.c +875 -0
  111. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/parser.c +2297 -0
  112. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/parser.h +286 -0
  113. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/point.h +48 -0
  114. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/query.c +4347 -0
  115. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/reduce_action.h +34 -0
  116. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/reusable_node.h +95 -0
  117. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/stack.c +912 -0
  118. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/stack.h +133 -0
  119. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/subtree.c +1034 -0
  120. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/subtree.h +399 -0
  121. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/tree-sitter.c +987 -0
  122. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/tree-sitter.cjs +2988 -0
  123. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/tree-sitter.wasm +0 -0
  124. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/tree-sitter.wasm.map +1 -0
  125. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/tree.c +170 -0
  126. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/tree.h +31 -0
  127. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/tree_cursor.c +716 -0
  128. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/tree_cursor.h +48 -0
  129. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/ts_assert.h +11 -0
  130. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/unicode.h +75 -0
  131. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/wasm_store.c +1937 -0
  132. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/wasm_store.h +31 -0
  133. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/package.json +98 -0
  134. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/src/bindings.ts +26 -0
  135. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/src/constants.ts +133 -0
  136. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/src/index.ts +31 -0
  137. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/src/language.ts +291 -0
  138. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/src/lookahead_iterator.ts +75 -0
  139. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/src/marshal.ts +176 -0
  140. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/src/node.ts +646 -0
  141. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/src/parser.ts +325 -0
  142. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/src/query.ts +973 -0
  143. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/src/tree.ts +145 -0
  144. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/src/tree_cursor.ts +318 -0
  145. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/tree-sitter.cjs +4031 -0
  146. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/tree-sitter.cjs.map +7 -0
  147. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/tree-sitter.js +3980 -0
  148. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/tree-sitter.js.map +7 -0
  149. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/tree-sitter.wasm +0 -0
  150. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/tree-sitter.wasm.map +30 -0
  151. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/web-tree-sitter.d.ts +1030 -0
  152. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/web-tree-sitter.d.ts.map +56 -0
  153. package/node_modules/@aui.io/apollo-tui/package.json +6 -3
  154. package/package.json +7 -5
  155. package/node_modules/@aui.io/apollo-tui/dist/src/components/glyph.d.ts +0 -19
  156. package/node_modules/@aui.io/apollo-tui/dist/src/components/glyph.js +0 -41
  157. package/node_modules/@aui.io/apollo-tui/dist/src/components/glyph.js.map +0 -1
  158. package/node_modules/@aui.io/apollo-tui/dist/src/lib/attractor.d.ts +0 -82
  159. package/node_modules/@aui.io/apollo-tui/dist/src/lib/attractor.js +0 -231
  160. package/node_modules/@aui.io/apollo-tui/dist/src/lib/attractor.js.map +0 -1
@@ -14,7 +14,6 @@ import { resolveContext } from "@aui.io/apollo-core/config/index.js";
14
14
  import { listVersions } from "@aui.io/apollo-core/services/bundles.js";
15
15
  import { createClients } from "@aui.io/apollo-core/services/clients.js";
16
16
  import { listAgentThreads, listThreads, resolveSendVersion, sendMessage, } from "@aui.io/apollo-core/services/messaging.js";
17
- import { GlyphController } from "./components/glyph.js";
18
17
  import { applyPick, chatOverlay, destructiveSpec, IMPORT_LIVE_PREFIX, loadPickerCatalog, refreshContext, runDestructive, runSheetAction, runSimpleCommand, } from "./lib/actions.js";
19
18
  import { filterCommands, PLACE_ONBOARD_COMMAND, resolveCommand, SLASH_COMMANDS, } from "./lib/commands.js";
20
19
  import { checkConfirm, createConfirm } from "./lib/confirm.js";
@@ -47,11 +46,13 @@ import { Composer } from "./talk/Composer.js";
47
46
  import { agentOrdinal, beginSend, cancelSend, composerDisabledReason, hasPendingSend, inspectorMeta, lastAgentTurnIndex, settleSend, talkLayout, talkRows, threadSummaries, turnRowOffset, } from "./talk/data.js";
48
47
  import { NEW_THREAD_ROW, threadsRowCount } from "./talk/ThreadsPane.js";
49
48
  import { TalkView } from "./talk/TalkView.js";
49
+ import { jsonDefaultExpanded, jsonRows, toggleJsonPath, } from "./lib/jsonview.js";
50
50
  import { ConfirmPane } from "./ui/ConfirmPane.js";
51
51
  import { PickerPane } from "./ui/PickerPane.js";
52
52
  import { SheetPane } from "./ui/SheetPane.js";
53
- import { AMBER, DIM, FAINT, FG, TEAL, TEAL_DIM } from "./theme/tokens.js";
54
- const VERSION = process.env.npm_package_version ?? "0.1.10";
53
+ import { G } from "./theme/glyphs.js";
54
+ import { AMBER, DIM, FAINT, FG, RICH, TEAL, TEAL_DIM } from "./theme/tokens.js";
55
+ const VERSION = process.env.npm_package_version ?? "0.1.11";
55
56
  const REGISTRY = buildActionRegistry();
56
57
  /** Author-mode single-letter quick actions (typed + Enter). */
57
58
  const AUTHOR_QUICK = {
@@ -68,7 +69,7 @@ const AUTHOR_VIEW_FOCUS = {
68
69
  validation: "author-validation",
69
70
  versions: "author-versions",
70
71
  };
71
- function App({ context: initialContext, initialScope, glyph, onQuit }) {
72
+ function App({ context: initialContext, initialScope, onQuit }) {
72
73
  const [context, setContext] = useState(initialContext);
73
74
  const [scope, setScope] = useState(initialScope);
74
75
  const [mode, setMode] = useState("author");
@@ -86,6 +87,11 @@ function App({ context: initialContext, initialScope, glyph, onQuit }) {
86
87
  const [activityCursor, setActivityCursor] = useState();
87
88
  const [paneTitle, setPaneTitle] = useState();
88
89
  const [paneLines, setPaneLines] = useState([]);
90
+ /** Structured payload behind the inline trace/debug overlay (JSON tree). */
91
+ const [paneJson, setPaneJson] = useState(undefined);
92
+ /** Expanded container paths for whichever trace/debug tree is on screen —
93
+ * inline overlay and inspector are mutually exclusive by layout width. */
94
+ const [jsonExpanded, setJsonExpanded] = useState(new Set());
89
95
  const [working, setWorking] = useState(false);
90
96
  const [trace, setTrace] = useState(false);
91
97
  const [localMode, setLocalMode] = useState(false);
@@ -96,7 +102,6 @@ function App({ context: initialContext, initialScope, glyph, onQuit }) {
96
102
  */
97
103
  const [talkTag, setTalkTag] = useState(undefined);
98
104
  const [vars, setVars] = useState([]);
99
- const [frame, setFrame] = useState(glyph.frame());
100
105
  // Author workbench state (Phase 3).
101
106
  const [authorView, setAuthorView] = useState("home");
102
107
  const [snapshot, setSnapshot] = useState();
@@ -158,6 +163,11 @@ function App({ context: initialContext, initialScope, glyph, onQuit }) {
158
163
  const turnFeedRef = useRef([]);
159
164
  /** The one scrollable content pane on screen (diff/validation/versions/talk). */
160
165
  const contentScrollRef = useRef(null);
166
+ /** Turn/unit anchor renderables — position-exact scroll targets. Markdown
167
+ * block rows have variable height, so row counts alone can't locate a
168
+ * turn; the anchor's layout y (relative to the scroll content) can. */
169
+ const talkTurnRefs = useRef(new Map());
170
+ const sessionUnitRefs = useRef(new Map());
161
171
  /** Remote bundle contents cached per bound tag (content diffs). */
162
172
  const remoteFilesRef = useRef(undefined);
163
173
  /** Detects agent switches to reset per-agent author state. */
@@ -212,7 +222,9 @@ function App({ context: initialContext, initialScope, glyph, onQuit }) {
212
222
  /** Session rows are pre-wrapped to the pane width → exact scroll offsets. */
213
223
  const sessionPaneWidth = Math.max(30, termWidth - 8);
214
224
  const sessionRowsView = useMemo(() => authorSession
215
- ? sessionRows(authorSession, sessionExpanded, sessionPaneWidth, queuedPrompts)
225
+ ? sessionRows(authorSession, sessionExpanded, sessionPaneWidth, queuedPrompts, {
226
+ markdown: RICH,
227
+ })
216
228
  : [], [authorSession, sessionExpanded, sessionPaneWidth, queuedPrompts]);
217
229
  // Talk workbench derivations: panes by width, pre-wrapped rows, pending.
218
230
  const talkLayoutEffective = useMemo(() => talkLayout(termWidth), [termWidth]);
@@ -229,9 +241,18 @@ function App({ context: initialContext, initialScope, glyph, onQuit }) {
229
241
  8 -
230
242
  (talkLayoutEffective.threads ? talkLayoutEffective.threadsWidth : 0) -
231
243
  (talkLayoutEffective.inspector ? talkLayoutEffective.inspectorWidth : 0));
232
- const talkRowsView = useMemo(() => talkRows(chat, conversationWidth, Date.now()),
244
+ const talkRowsView = useMemo(() => talkRows(chat, conversationWidth, Date.now(), { markdown: RICH }),
233
245
  // talkTick re-times the pending row twice a second.
234
246
  [chat, conversationWidth, talkTick]);
247
+ /** JSON trees for trace/debug — inline overlay and inspector variants. */
248
+ const overlayJsonRows = useMemo(() => (paneJson === undefined ? undefined : jsonRows(paneJson, jsonExpanded)), [paneJson, jsonExpanded]);
249
+ const inspectorJsonRows = useMemo(() => inspectorFetch?.data === undefined
250
+ ? undefined
251
+ : jsonRows(inspectorFetch.data, jsonExpanded), [inspectorFetch, jsonExpanded]);
252
+ /** Click on an expandable tree row toggles that container. */
253
+ function toggleJsonRow(row) {
254
+ setJsonExpanded((prev) => toggleJsonPath(prev, row.path));
255
+ }
235
256
  const talkCursorClamped = clampPickerCursor(talkCursor, chat.length);
236
257
  /** What sends run against, for the composer label and inspector (^B picks). */
237
258
  const talkVersionLabel = talkTag === "latest"
@@ -330,15 +351,6 @@ function App({ context: initialContext, initialScope, glyph, onQuit }) {
330
351
  const browseRoot = bundleSrcRoot(context) ?? context.workspaceRoot;
331
352
  /** Subviews need an agent — except diff, which browses any place. */
332
353
  const authorViewEffective = authorEmpty && !(authorView === "diff" && browseRoot) ? "home" : authorView;
333
- useEffect(() => {
334
- if (mode !== "author" || !authorEmpty)
335
- return;
336
- const id = setInterval(() => setFrame(glyph.frame()), 33);
337
- return () => clearInterval(id);
338
- }, [mode, authorEmpty, glyph]);
339
- useEffect(() => {
340
- glyph.setWorking(working);
341
- }, [working, glyph]);
342
354
  // Human names for the strip (workspace manifest, project/org APIs) —
343
355
  // ids render immediately, names overlay when resolved; stale results
344
356
  // (context changed meanwhile) are dropped.
@@ -470,6 +482,8 @@ function App({ context: initialContext, initialScope, glyph, onQuit }) {
470
482
  // Keep the transcript visible: cursor on the newest unit pins the pane to
471
483
  // the bottom (streaming rows grow below the unit's label — bottom-pinning
472
484
  // keeps live text on screen); browsing history centers the selected unit.
485
+ // Centering scrolls to the unit anchor's measured position when available
486
+ // (markdown rows are taller than one line); row offsets are the fallback.
473
487
  useEffect(() => {
474
488
  if (mode !== "author" || authorViewEffective !== "home")
475
489
  return;
@@ -482,13 +496,14 @@ function App({ context: initialContext, initialScope, glyph, onQuit }) {
482
496
  const cursor = clampPickerCursor(sessionCursor, count);
483
497
  const viewport = Math.max(4, box.height || 10);
484
498
  if (cursor >= count - 1) {
485
- box.scrollTo({
486
- x: 0,
487
- y: Math.max(0, sessionRowsView.length - viewport + 1),
488
- });
499
+ box.scrollTo({ x: 0, y: Math.max(0, box.scrollHeight) });
489
500
  return;
490
501
  }
491
- const offset = unitRowOffset(sessionRowsView, cursor);
502
+ const anchor = sessionUnitRefs.current.get(cursor);
503
+ const measured = anchor ? anchor.y - box.content.y : -1;
504
+ const offset = measured >= 0 && measured <= box.scrollHeight
505
+ ? measured
506
+ : unitRowOffset(sessionRowsView, cursor);
492
507
  box.scrollTo({ x: 0, y: Math.max(0, offset - Math.floor(viewport / 2)) });
493
508
  }, [sessionCursor, sessionRowsView, authorSession, mode, authorViewEffective]);
494
509
  // Queued prompts drain in order once the running turn settles. (Effect,
@@ -521,6 +536,8 @@ function App({ context: initialContext, initialScope, glyph, onQuit }) {
521
536
  }, [chat]);
522
537
  // Conversation scroll follows the selection: newest turn pins the pane to
523
538
  // the bottom (the pending row grows there); history centers the selection.
539
+ // Centering scrolls to the turn header's measured position when available
540
+ // (markdown rows are taller than one line); row offsets are the fallback.
524
541
  useEffect(() => {
525
542
  if (mode !== "talk" || chat.length === 0)
526
543
  return;
@@ -530,10 +547,14 @@ function App({ context: initialContext, initialScope, glyph, onQuit }) {
530
547
  const cursor = clampPickerCursor(talkCursor, chat.length);
531
548
  const viewport = Math.max(4, box.height || 10);
532
549
  if (cursor >= chat.length - 1) {
533
- box.scrollTo({ x: 0, y: Math.max(0, talkRowsView.length - viewport + 1) });
550
+ box.scrollTo({ x: 0, y: Math.max(0, box.scrollHeight) });
534
551
  return;
535
552
  }
536
- const offset = turnRowOffset(talkRowsView, cursor);
553
+ const anchor = talkTurnRefs.current.get(cursor);
554
+ const measured = anchor ? anchor.y - box.content.y : -1;
555
+ const offset = measured >= 0 && measured <= box.scrollHeight
556
+ ? measured
557
+ : turnRowOffset(talkRowsView, cursor);
537
558
  box.scrollTo({ x: 0, y: Math.max(0, offset - Math.floor(viewport / 2)) });
538
559
  }, [talkCursor, talkRowsView, chat, mode]);
539
560
  // Threads pane data: lazy, once per context (invalidated on new threads).
@@ -656,7 +677,15 @@ function App({ context: initialContext, initialScope, glyph, onQuit }) {
656
677
  return { kind: "error", path: previewTarget, message: diffFiles.message };
657
678
  }
658
679
  if (previewDiffLines) {
659
- return { kind: "diff", path: previewTarget, lines: previewDiffLines };
680
+ return {
681
+ kind: "diff",
682
+ path: previewTarget,
683
+ lines: previewDiffLines,
684
+ // Both sides ride along for the rich <diff> renderable (unified
685
+ // patch is serialized in the view); plain paths use `lines`.
686
+ before: diffFiles.remote[previewTarget],
687
+ after: diffFiles.local[previewTarget],
688
+ };
660
689
  }
661
690
  const content = diffFiles.local[previewTarget];
662
691
  if (content === undefined) {
@@ -1079,6 +1108,7 @@ function App({ context: initialContext, initialScope, glyph, onQuit }) {
1079
1108
  setPaneTitle((title) => {
1080
1109
  if (title && /^(trace|debug)/i.test(title)) {
1081
1110
  setPaneLines([]);
1111
+ setPaneJson(undefined);
1082
1112
  return undefined;
1083
1113
  }
1084
1114
  return title;
@@ -1112,6 +1142,10 @@ function App({ context: initialContext, initialScope, glyph, onQuit }) {
1112
1142
  if (result.paneLines) {
1113
1143
  setPaneLines(result.paneLines);
1114
1144
  setPaneTitle(result.paneTitle ?? "result");
1145
+ // Structured payloads render as a collapsible tree instead of the
1146
+ // stringified lines; fresh payload → fresh default expansion.
1147
+ setPaneJson(result.paneJson);
1148
+ setJsonExpanded(result.paneJson !== undefined ? jsonDefaultExpanded(result.paneJson) : new Set());
1115
1149
  }
1116
1150
  if (result.needConfirm) {
1117
1151
  setConfirm(createConfirm(result.needConfirm.title, result.needConfirm.phrase, result.needConfirm.action, result.needConfirm.args));
@@ -1188,13 +1222,13 @@ function App({ context: initialContext, initialScope, glyph, onQuit }) {
1188
1222
  else {
1189
1223
  const errors = v.result.findings.filter((f) => f.level !== "warning").length;
1190
1224
  if (errors > 0 || !v.result.valid) {
1191
- lines.push(`! validation ${errors} error(s) — push will fail until fixed`);
1225
+ lines.push(`! validation ${G.fail} ${errors} error(s) — push will fail until fixed`);
1192
1226
  }
1193
1227
  else if (v.stale) {
1194
- lines.push(`! validation but stale — files changed since ${relativeTime(v.at)}`);
1228
+ lines.push(`! validation ${G.ok} but stale — files changed since ${relativeTime(v.at)}`);
1195
1229
  }
1196
1230
  else {
1197
- lines.push(`validation ${relativeTime(v.at)}`);
1231
+ lines.push(`validation ${G.ok} ${relativeTime(v.at)}`);
1198
1232
  }
1199
1233
  }
1200
1234
  return lines;
@@ -1408,7 +1442,7 @@ function App({ context: initialContext, initialScope, glyph, onQuit }) {
1408
1442
  break;
1409
1443
  case "action": {
1410
1444
  const label = `${event.label}${event.detail ? ` — ${event.detail}` : ""}`;
1411
- turnFeedRef.current.push(`⚙ ${label}`);
1445
+ turnFeedRef.current.push(`${G.gear} ${label}`);
1412
1446
  operationStore.progress(opId, label);
1413
1447
  break;
1414
1448
  }
@@ -1430,7 +1464,7 @@ function App({ context: initialContext, initialScope, glyph, onQuit }) {
1430
1464
  case "error":
1431
1465
  turnHandleRef.current = undefined;
1432
1466
  turnOpIdRef.current = undefined;
1433
- turnFeedRef.current.push(`✕ ${event.message}`);
1467
+ turnFeedRef.current.push(`${G.fail} ${event.message}`);
1434
1468
  operationStore.fail(opId, event.message, [...turnFeedRef.current]);
1435
1469
  break;
1436
1470
  }
@@ -1493,7 +1527,7 @@ function App({ context: initialContext, initialScope, glyph, onQuit }) {
1493
1527
  // called out rather than silently defaulting to some other tag.
1494
1528
  const note = kind === "import-version" &&
1495
1529
  !items[0]?.label.startsWith(IMPORT_LIVE_PREFIX)
1496
- ? "⚠ no live version — pick a tag"
1530
+ ? `${G.warn} no live version — pick a tag`
1497
1531
  : undefined;
1498
1532
  setSheet(undefined);
1499
1533
  setPaletteCursor(undefined);
@@ -1903,7 +1937,15 @@ function App({ context: initialContext, initialScope, glyph, onQuit }) {
1903
1937
  setMode("talk");
1904
1938
  if (target !== cursor)
1905
1939
  setTalkCursor(target);
1906
- setInspectorFetch({ turn: target, kind, lines: result.paneLines ?? [] });
1940
+ setInspectorFetch({
1941
+ turn: target,
1942
+ kind,
1943
+ lines: result.paneLines ?? [],
1944
+ data: result.paneJson,
1945
+ });
1946
+ setJsonExpanded(result.paneJson !== undefined
1947
+ ? jsonDefaultExpanded(result.paneJson)
1948
+ : new Set());
1907
1949
  setToast(`${kind} · reply #${ordinal ?? "?"} → inspector`);
1908
1950
  }
1909
1951
  else {
@@ -1917,21 +1959,72 @@ function App({ context: initialContext, initialScope, glyph, onQuit }) {
1917
1959
  setWorking(false);
1918
1960
  }
1919
1961
  }
1962
+ /** Enter/click on a diff-tree row: toggle a dir, or preview a file. */
1963
+ function activateDiffRow(index) {
1964
+ const rows = stateRef.current.diffRows;
1965
+ const row = rows[clampPickerCursor(index, rows.length)];
1966
+ if (row?.kind === "dir") {
1967
+ setDiffCollapsed((prev) => {
1968
+ const next = new Set(prev);
1969
+ if (next.has(row.path))
1970
+ next.delete(row.path);
1971
+ else
1972
+ next.add(row.path);
1973
+ return next;
1974
+ });
1975
+ }
1976
+ else if (row) {
1977
+ setPreviewPath(row.path);
1978
+ setFileDiff({ path: row.path });
1979
+ }
1980
+ }
1981
+ /** Enter/second click on a session unit: expand/collapse its body. */
1982
+ function toggleSessionUnitBody(index) {
1983
+ const units = stateRef.current.authorSession?.units ?? [];
1984
+ const unit = units[clampPickerCursor(index, units.length)];
1985
+ if (unit &&
1986
+ unit.body.length > 0 &&
1987
+ (unit.kind === "action" || unit.kind === "thinking")) {
1988
+ setSessionExpanded((prev) => {
1989
+ const next = new Set(prev);
1990
+ if (next.has(unit.id))
1991
+ next.delete(unit.id);
1992
+ else
1993
+ next.add(unit.id);
1994
+ return next;
1995
+ });
1996
+ }
1997
+ }
1998
+ /** Run a palette action (Enter on the highlight or a mouse click). */
1999
+ function activatePaletteAction(action) {
2000
+ const reason = action.disabledReason?.(stateRef.current.context);
2001
+ setPaletteCursor(undefined);
2002
+ if (reason && !action.command.requiresAuth) {
2003
+ // Auth gaps route to login via ensureAuth; other gaps just explain.
2004
+ setToast(`${action.title} — ${reason}`);
2005
+ return;
2006
+ }
2007
+ void runCommand(action.command, "");
2008
+ }
2009
+ /** Open the thread at a threads-pane row (row 0 starts a new thread). */
2010
+ function activateThreadRow(row) {
2011
+ const current = stateRef.current;
2012
+ const clamped = clampPickerCursor(row, threadsRowCount(current.threads));
2013
+ if (clamped === NEW_THREAD_ROW) {
2014
+ const cmd = SLASH_COMMANDS.find((c) => c.name === "new");
2015
+ if (cmd)
2016
+ void runCommand(cmd, "");
2017
+ return;
2018
+ }
2019
+ const picked = current.threads?.[clamped - 1];
2020
+ if (picked)
2021
+ void openThread(picked.id);
2022
+ }
1920
2023
  /** Enter in the composer: threads focus opens; otherwise send the draft. */
1921
2024
  function handleComposerSend() {
1922
2025
  const current = stateRef.current;
1923
2026
  if (current.talkFocus === "threads") {
1924
- const count = threadsRowCount(current.threads);
1925
- const row = clampPickerCursor(current.threadCursor, count);
1926
- if (row === NEW_THREAD_ROW) {
1927
- const cmd = SLASH_COMMANDS.find((c) => c.name === "new");
1928
- if (cmd)
1929
- void runCommand(cmd, "");
1930
- return;
1931
- }
1932
- const picked = current.threads?.[row - 1];
1933
- if (picked)
1934
- void openThread(picked.id);
2027
+ activateThreadRow(current.threadCursor);
1935
2028
  return;
1936
2029
  }
1937
2030
  const text = (composerRef.current?.plainText ?? "").trim();
@@ -2049,15 +2142,7 @@ function App({ context: initialContext, initialScope, glyph, onQuit }) {
2049
2142
  return;
2050
2143
  }
2051
2144
  const highlight = clampPickerCursor(current.paletteCursor, matches.length);
2052
- const action = matches[highlight];
2053
- const reason = action.disabledReason?.(current.context);
2054
- setPaletteCursor(undefined);
2055
- if (reason && !action.command.requiresAuth) {
2056
- // Auth gaps route to login via ensureAuth; other gaps just explain.
2057
- setToast(`${action.title} — ${reason}`);
2058
- return;
2059
- }
2060
- void runCommand(action.command, "");
2145
+ activatePaletteAction(matches[highlight]);
2061
2146
  return;
2062
2147
  }
2063
2148
  if (current.switcherCursor !== undefined) {
@@ -2090,22 +2175,7 @@ function App({ context: initialContext, initialScope, glyph, onQuit }) {
2090
2175
  current.mode === "author" &&
2091
2176
  current.authorView === "diff" &&
2092
2177
  !current.fileDiff) {
2093
- const rows = current.diffRows;
2094
- const row = rows[clampPickerCursor(current.diffCursor, rows.length)];
2095
- if (row?.kind === "dir") {
2096
- setDiffCollapsed((prev) => {
2097
- const next = new Set(prev);
2098
- if (next.has(row.path))
2099
- next.delete(row.path);
2100
- else
2101
- next.add(row.path);
2102
- return next;
2103
- });
2104
- }
2105
- else if (row) {
2106
- setPreviewPath(row.path);
2107
- setFileDiff({ path: row.path });
2108
- }
2178
+ activateDiffRow(clampPickerCursor(current.diffCursor, current.diffRows.length));
2109
2179
  return;
2110
2180
  }
2111
2181
  // Enter on a session unit: expand/collapse its body (tool input/result).
@@ -2114,19 +2184,7 @@ function App({ context: initialContext, initialScope, glyph, onQuit }) {
2114
2184
  current.authorView === "home" &&
2115
2185
  current.authorSession) {
2116
2186
  const units = current.authorSession.units;
2117
- const unit = units[clampPickerCursor(current.sessionCursor, units.length)];
2118
- if (unit &&
2119
- unit.body.length > 0 &&
2120
- (unit.kind === "action" || unit.kind === "thinking")) {
2121
- setSessionExpanded((prev) => {
2122
- const next = new Set(prev);
2123
- if (next.has(unit.id))
2124
- next.delete(unit.id);
2125
- else
2126
- next.add(unit.id);
2127
- return next;
2128
- });
2129
- }
2187
+ toggleSessionUnitBody(clampPickerCursor(current.sessionCursor, units.length));
2130
2188
  return;
2131
2189
  }
2132
2190
  if (line === "")
@@ -2228,7 +2286,14 @@ function App({ context: initialContext, initialScope, glyph, onQuit }) {
2228
2286
  ? 0
2229
2287
  : Math.max(0, Math.min(pickerCursor - Math.floor(PICKER_PAGE / 3), pickerVisible.length - PICKER_PAGE));
2230
2288
  const pickerWindow = pickerVisible.slice(pickerWindowStart, pickerWindowStart + PICKER_PAGE);
2231
- return (_jsxs("box", { style: { flexDirection: "column", flexGrow: 1, paddingLeft: 1, paddingRight: 1 }, children: [_jsx(Breadcrumb, { scope: scope, working: working }), _jsx(ModeNav, { active: mode }), _jsx("box", { style: {
2289
+ return (_jsxs("box", { style: { flexDirection: "column", flexGrow: 1, paddingLeft: 1, paddingRight: 1 }, children: [_jsx(Breadcrumb, { scope: scope, working: working, onSegment: (row) => {
2290
+ // Open the ^G switcher on the clicked segment's row.
2291
+ const index = CONTEXT_ROWS.findIndex((r) => r.id === row);
2292
+ setSwitcherCursor(index >= 0 ? index : 0);
2293
+ } }), _jsx(ModeNav, { active: mode, onSelect: (id) => {
2294
+ if (!confirm)
2295
+ setMode(id);
2296
+ } }), _jsx("box", { style: {
2232
2297
  flexDirection: "column",
2233
2298
  flexGrow: 1,
2234
2299
  flexShrink: 1,
@@ -2241,11 +2306,61 @@ function App({ context: initialContext, initialScope, glyph, onQuit }) {
2241
2306
  ? `${picker.command.name} — ${picker.note}`
2242
2307
  : picker.command.name, filter: pickerFilter, dismissHint: picker.command.name === "place-onboard"
2243
2308
  ? "Esc continue without place"
2244
- : undefined })) : confirm ? (_jsx(ConfirmPane, { confirm: confirm })) : sheet && sheetCommand ? (_jsx(SheetPane, { sheet: sheet })) : paletteOpen ? (_jsx(ActionPalettePane, { actions: paletteMatches, cursor: paletteHighlight, query: input, context: context, pageSize: pickerPageSize() })) : switcherOpen ? (_jsx(ContextSwitcherPane, { scope: scope, cursor: clampPickerCursor(switcherCursor ?? 0, CONTEXT_ROWS.length) })) : activityOpen ? (_jsx(ActivityDrawerPane, { operations: orderedOps, cursor: clampPickerCursor(activityCursor ?? 0, orderedOps.length), pageSize: pickerPageSize(), now: Date.now() })) : mode === "author" ? (authorViewEffective === "home" ? (_jsx(AuthorHome, { scope: scope, snapshot: snapshot, validation: validation, frame: frame, working: working, version: VERSION, paneTitle: paneTitle, paneLines: paneLines, session: authorSession, sessionRows: sessionRowsView, sessionCursor: clampPickerCursor(sessionCursor, authorSession?.units.length ?? 0), sessionScrollRef: contentScrollRef, backendLabel: authorBackend.label, backendDetection: backendDetection })) : authorViewEffective === "diff" ? (_jsx(DiffView, { rows: diffRows, cursor: clampPickerCursor(diffCursor, diffRows.length), treeTitle: hasAgent
2309
+ : undefined, onPick: (item) => {
2310
+ setInput("");
2311
+ void finishPick(picker.command, item.id, picker.sheet, picker.sheetField);
2312
+ } })) : confirm ? (_jsx(ConfirmPane, { confirm: confirm })) : sheet && sheetCommand ? (_jsx(SheetPane, { sheet: sheet })) : paletteOpen ? (_jsx(ActionPalettePane, { actions: paletteMatches, cursor: paletteHighlight, query: input, context: context, pageSize: pickerPageSize(), onPick: (index) => {
2313
+ const action = paletteMatches[index];
2314
+ if (!action)
2315
+ return;
2316
+ setInput("");
2317
+ activatePaletteAction(action);
2318
+ } })) : switcherOpen ? (_jsx(ContextSwitcherPane, { scope: scope, cursor: clampPickerCursor(switcherCursor ?? 0, CONTEXT_ROWS.length), onPick: (index) => {
2319
+ const row = CONTEXT_ROWS[index];
2320
+ setSwitcherCursor(undefined);
2321
+ if (!row)
2322
+ return;
2323
+ const command = SLASH_COMMANDS.find((c) => c.name === row.id);
2324
+ if (command)
2325
+ void runCommand(command, "");
2326
+ } })) : activityOpen ? (_jsx(ActivityDrawerPane, { operations: orderedOps, cursor: clampPickerCursor(activityCursor ?? 0, orderedOps.length), pageSize: pickerPageSize(), now: Date.now(), onPick: (index) => {
2327
+ const op = orderedOps[index];
2328
+ if (!op)
2329
+ return;
2330
+ const selected = index === clampPickerCursor(activityCursor ?? 0, orderedOps.length);
2331
+ // Click selects; a second click on a failed row retries it.
2332
+ if (selected && op.status === "failed" && op.retry)
2333
+ retryOperation(op);
2334
+ else
2335
+ setActivityCursor(index);
2336
+ } })) : mode === "author" ? (authorViewEffective === "home" ? (_jsx(AuthorHome, { scope: scope, snapshot: snapshot, validation: validation, version: VERSION, paneTitle: paneTitle, paneLines: paneLines, session: authorSession, sessionRows: sessionRowsView, sessionCursor: clampPickerCursor(sessionCursor, authorSession?.units.length ?? 0), sessionScrollRef: contentScrollRef, sessionUnitRefs: sessionUnitRefs, backendLabel: authorBackend.label, backendDetection: backendDetection, onSelectUnit: (unit) => {
2337
+ const clamped = clampPickerCursor(sessionCursor, authorSession?.units.length ?? 0);
2338
+ // Click selects; clicking the selected unit toggles its body.
2339
+ if (unit === clamped)
2340
+ toggleSessionUnitBody(unit);
2341
+ else
2342
+ setSessionCursor(unit);
2343
+ }, onWelcomeStep: (step) => {
2344
+ const command = SLASH_COMMANDS.find((c) => c.name === step);
2345
+ if (command)
2346
+ void runCommand(command, "");
2347
+ } })) : authorViewEffective === "diff" ? (_jsx(DiffView, { rows: diffRows, cursor: clampPickerCursor(diffCursor, diffRows.length), treeTitle: hasAgent
2245
2348
  ? statusByPath.size > 0
2246
2349
  ? `changes (${changesSummary(snapshot?.diff)})`
2247
2350
  : "files (clean)"
2248
- : "files", preview: preview, style: diffStyleEffective, remoteTag: scope.version, expanded: Boolean(fileDiff), sidebarWidth: Math.max(24, Math.min(36, Math.floor(termWidth / 4))), pageSize: pickerPageSize(), scrollRef: contentScrollRef })) : authorViewEffective === "validation" ? (_jsx(ValidationViewPane, { record: validation, scrollRef: contentScrollRef })) : (_jsx(VersionsViewPane, { versions: versions ?? [], currentTag: scope.version, scrollRef: contentScrollRef }))) : (_jsx(TalkView, { chat: chat, rows: talkRowsView, cursor: talkCursorClamped, focusPane: talkFocus, layout: talkLayoutEffective, threads: threads, threadsLoading: threadsLoading, threadCursor: clampPickerCursor(threadCursor, threadsRowCount(threads)), threadId: threadId, localMode: localMode, trace: trace, vars: vars, inspectorMetaLines: inspectorMetaLines, inspectorFetch: inspectorFetch, paneTitle: paneTitle, paneLines: paneLines, pageSize: pickerPageSize(), scrollRef: contentScrollRef, inspectorScrollRef: inspectorScrollRef })) }), slashOpen && slashMatches.length > 0 && (_jsx("box", { title: " commands ", style: {
2351
+ : "files", preview: preview, style: diffStyleEffective, remoteTag: scope.version, expanded: Boolean(fileDiff), sidebarWidth: Math.max(24, Math.min(36, Math.floor(termWidth / 4))), pageSize: pickerPageSize(), scrollRef: contentScrollRef, onRowClick: (index) => {
2352
+ setDiffCursor(index);
2353
+ // Dirs toggle; file preview follows the cursor effect.
2354
+ if (diffRows[index]?.kind === "dir")
2355
+ activateDiffRow(index);
2356
+ } })) : authorViewEffective === "validation" ? (_jsx(ValidationViewPane, { record: validation, scrollRef: contentScrollRef })) : (_jsx(VersionsViewPane, { versions: versions ?? [], currentTag: scope.version, scrollRef: contentScrollRef }))) : (_jsx(TalkView, { chat: chat, rows: talkRowsView, cursor: talkCursorClamped, focusPane: talkFocus, layout: talkLayoutEffective, threads: threads, threadsLoading: threadsLoading, threadCursor: clampPickerCursor(threadCursor, threadsRowCount(threads)), threadId: threadId, localMode: localMode, trace: trace, vars: vars, inspectorMetaLines: inspectorMetaLines, inspectorFetch: inspectorFetch, paneTitle: paneTitle, paneLines: paneLines, overlayJson: overlayJsonRows, inspectorJson: inspectorJsonRows, onJsonToggle: toggleJsonRow, onSelectTurn: (turn) => {
2357
+ setTalkFocus("chat");
2358
+ setTalkCursor(turn);
2359
+ }, onSelectThread: (row) => {
2360
+ setTalkFocus("threads");
2361
+ setThreadCursor(row);
2362
+ activateThreadRow(row);
2363
+ }, pageSize: pickerPageSize(), scrollRef: contentScrollRef, inspectorScrollRef: inspectorScrollRef, turnRefs: talkTurnRefs })) }), slashOpen && slashMatches.length > 0 && (_jsx("box", { title: " commands ", style: {
2249
2364
  border: true,
2250
2365
  borderStyle: "rounded",
2251
2366
  borderColor: TEAL_DIM,
@@ -2253,7 +2368,7 @@ function App({ context: initialContext, initialScope, glyph, onQuit }) {
2253
2368
  flexShrink: 0,
2254
2369
  paddingLeft: 1,
2255
2370
  paddingRight: 1,
2256
- }, children: slashMatches.map((cmd) => (_jsxs("text", { children: [_jsxs("span", { fg: TEAL, children: ["/", cmd.name.padEnd(16)] }), _jsx("span", { fg: DIM, children: cmd.summary })] }, cmd.name))) })), latestOp && !activityOpen && (_jsx(ActivitySummaryLine, { operation: latestOp, now: Date.now() })), toast && (_jsxs("text", { fg: DIM, style: { paddingLeft: 1, flexShrink: 0 }, children: ["\u21B3 ", toast] })), talkComposerActive ? (_jsx(Composer, { targetLabel: `${scope.agent !== "—" ? scope.agent : "agent"} on ${localMode ? "local bundle" : `${scope.env} · ${talkVersionLabel}`}`, draft: composer, disabledReason: composerReason, pending: talkPending, taRef: composerRef, onDraftChange: setComposer, onSend: handleComposerSend })) : (_jsx("box", { style: {
2371
+ }, children: slashMatches.map((cmd) => (_jsxs("text", { children: [_jsxs("span", { fg: TEAL, children: ["/", cmd.name.padEnd(16)] }), _jsx("span", { fg: DIM, children: cmd.summary })] }, cmd.name))) })), latestOp && !activityOpen && (_jsx(ActivitySummaryLine, { operation: latestOp, now: Date.now() })), toast && (_jsxs("text", { fg: DIM, style: { paddingLeft: 1, flexShrink: 0 }, children: [G.branch, " ", toast] })), talkComposerActive ? (_jsx(Composer, { targetLabel: `${scope.agent !== "—" ? scope.agent : "agent"} on ${localMode ? "local bundle" : `${scope.env} · ${talkVersionLabel}`}`, draft: composer, disabledReason: composerReason, pending: talkPending, taRef: composerRef, onDraftChange: setComposer, onSend: handleComposerSend, onFocusRequest: () => setTalkFocus("chat") })) : (_jsx("box", { style: {
2257
2372
  border: true,
2258
2373
  borderStyle: "rounded",
2259
2374
  borderColor: working ? AMBER : TEAL_DIM,
@@ -2279,11 +2394,6 @@ function App({ context: initialContext, initialScope, glyph, onQuit }) {
2279
2394
  export async function runOpenTui() {
2280
2395
  const context = await resolveContext({});
2281
2396
  const scope = scopeFromContext(context);
2282
- const glyph = new GlyphController(context.agentId ?? context.projectId ?? "apollo", {
2283
- width: 10,
2284
- height: 4,
2285
- compact: true,
2286
- });
2287
2397
  const renderer = await createCliRenderer({
2288
2398
  // Ctrl+C is an app key (cancel turn / clear input / quit) — see matchCtrlC.
2289
2399
  exitOnCtrlC: false,
@@ -2293,7 +2403,7 @@ export async function runOpenTui() {
2293
2403
  });
2294
2404
  const root = createRoot(renderer);
2295
2405
  const code = await new Promise((resolve) => {
2296
- root.render(_jsx(App, { context: context, initialScope: scope, glyph: glyph, onQuit: resolve }));
2406
+ root.render(_jsx(App, { context: context, initialScope: scope, onQuit: resolve }));
2297
2407
  });
2298
2408
  root.unmount();
2299
2409
  renderer.destroy();