@aui.io/apollo 0.1.12 → 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 (144) 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 +6 -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 +6 -2
  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/author/AuthorHome.d.ts +12 -4
  10. package/node_modules/@aui.io/apollo-tui/dist/src/author/AuthorHome.js +64 -7
  11. package/node_modules/@aui.io/apollo-tui/dist/src/author/AuthorHome.js.map +1 -1
  12. package/node_modules/@aui.io/apollo-tui/dist/src/author/DiffView.d.ts +7 -1
  13. package/node_modules/@aui.io/apollo-tui/dist/src/author/DiffView.js +33 -7
  14. package/node_modules/@aui.io/apollo-tui/dist/src/author/DiffView.js.map +1 -1
  15. package/node_modules/@aui.io/apollo-tui/dist/src/author/SessionPane.d.ts +9 -2
  16. package/node_modules/@aui.io/apollo-tui/dist/src/author/SessionPane.js +22 -4
  17. package/node_modules/@aui.io/apollo-tui/dist/src/author/SessionPane.js.map +1 -1
  18. package/node_modules/@aui.io/apollo-tui/dist/src/author/data.d.ts +9 -0
  19. package/node_modules/@aui.io/apollo-tui/dist/src/author/data.js +29 -0
  20. package/node_modules/@aui.io/apollo-tui/dist/src/author/data.js.map +1 -1
  21. package/node_modules/@aui.io/apollo-tui/dist/src/author/session.d.ts +10 -1
  22. package/node_modules/@aui.io/apollo-tui/dist/src/author/session.js +13 -1
  23. package/node_modules/@aui.io/apollo-tui/dist/src/author/session.js.map +1 -1
  24. package/node_modules/@aui.io/apollo-tui/dist/src/context/ContextSwitcher.d.ts +3 -1
  25. package/node_modules/@aui.io/apollo-tui/dist/src/context/ContextSwitcher.js +6 -2
  26. package/node_modules/@aui.io/apollo-tui/dist/src/context/ContextSwitcher.js.map +1 -1
  27. package/node_modules/@aui.io/apollo-tui/dist/src/index.d.ts +3 -4
  28. package/node_modules/@aui.io/apollo-tui/dist/src/index.js +3 -4
  29. package/node_modules/@aui.io/apollo-tui/dist/src/index.js.map +1 -1
  30. package/node_modules/@aui.io/apollo-tui/dist/src/lib/actions.d.ts +3 -0
  31. package/node_modules/@aui.io/apollo-tui/dist/src/lib/actions.js +3 -0
  32. package/node_modules/@aui.io/apollo-tui/dist/src/lib/actions.js.map +1 -1
  33. package/node_modules/@aui.io/apollo-tui/dist/src/lib/jsonview.d.ts +31 -0
  34. package/node_modules/@aui.io/apollo-tui/dist/src/lib/jsonview.js +114 -0
  35. package/node_modules/@aui.io/apollo-tui/dist/src/lib/jsonview.js.map +1 -0
  36. package/node_modules/@aui.io/apollo-tui/dist/src/opentui-app.js +193 -88
  37. package/node_modules/@aui.io/apollo-tui/dist/src/opentui-app.js.map +1 -1
  38. package/node_modules/@aui.io/apollo-tui/dist/src/shell/Breadcrumb.d.ts +5 -2
  39. package/node_modules/@aui.io/apollo-tui/dist/src/shell/Breadcrumb.js +10 -4
  40. package/node_modules/@aui.io/apollo-tui/dist/src/shell/Breadcrumb.js.map +1 -1
  41. package/node_modules/@aui.io/apollo-tui/dist/src/shell/ModeNav.d.ts +2 -1
  42. package/node_modules/@aui.io/apollo-tui/dist/src/shell/ModeNav.js +29 -3
  43. package/node_modules/@aui.io/apollo-tui/dist/src/shell/ModeNav.js.map +1 -1
  44. package/node_modules/@aui.io/apollo-tui/dist/src/talk/Composer.d.ts +3 -1
  45. package/node_modules/@aui.io/apollo-tui/dist/src/talk/Composer.js +2 -2
  46. package/node_modules/@aui.io/apollo-tui/dist/src/talk/Composer.js.map +1 -1
  47. package/node_modules/@aui.io/apollo-tui/dist/src/talk/InspectorPane.d.ts +8 -3
  48. package/node_modules/@aui.io/apollo-tui/dist/src/talk/InspectorPane.js +7 -5
  49. package/node_modules/@aui.io/apollo-tui/dist/src/talk/InspectorPane.js.map +1 -1
  50. package/node_modules/@aui.io/apollo-tui/dist/src/talk/TalkView.d.ts +15 -2
  51. package/node_modules/@aui.io/apollo-tui/dist/src/talk/TalkView.js +21 -5
  52. package/node_modules/@aui.io/apollo-tui/dist/src/talk/TalkView.js.map +1 -1
  53. package/node_modules/@aui.io/apollo-tui/dist/src/talk/ThreadsPane.d.ts +5 -2
  54. package/node_modules/@aui.io/apollo-tui/dist/src/talk/ThreadsPane.js +8 -3
  55. package/node_modules/@aui.io/apollo-tui/dist/src/talk/ThreadsPane.js.map +1 -1
  56. package/node_modules/@aui.io/apollo-tui/dist/src/talk/data.d.ts +14 -3
  57. package/node_modules/@aui.io/apollo-tui/dist/src/talk/data.js +12 -2
  58. package/node_modules/@aui.io/apollo-tui/dist/src/talk/data.js.map +1 -1
  59. package/node_modules/@aui.io/apollo-tui/dist/src/theme/syntax.d.ts +20 -0
  60. package/node_modules/@aui.io/apollo-tui/dist/src/theme/syntax.js +54 -0
  61. package/node_modules/@aui.io/apollo-tui/dist/src/theme/syntax.js.map +1 -0
  62. package/node_modules/@aui.io/apollo-tui/dist/src/theme/tokens.d.ts +6 -0
  63. package/node_modules/@aui.io/apollo-tui/dist/src/theme/tokens.js +6 -0
  64. package/node_modules/@aui.io/apollo-tui/dist/src/theme/tokens.js.map +1 -1
  65. package/node_modules/@aui.io/apollo-tui/dist/src/ui/JsonPane.d.ts +12 -0
  66. package/node_modules/@aui.io/apollo-tui/dist/src/ui/JsonPane.js +22 -0
  67. package/node_modules/@aui.io/apollo-tui/dist/src/ui/JsonPane.js.map +1 -0
  68. package/node_modules/@aui.io/apollo-tui/dist/src/ui/PickerPane.d.ts +3 -1
  69. package/node_modules/@aui.io/apollo-tui/dist/src/ui/PickerPane.js +6 -2
  70. package/node_modules/@aui.io/apollo-tui/dist/src/ui/PickerPane.js.map +1 -1
  71. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/LICENSE +21 -0
  72. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/README.md +269 -0
  73. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/debug/tree-sitter.cjs +4558 -0
  74. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/debug/tree-sitter.cjs.map +7 -0
  75. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/debug/tree-sitter.js +4516 -0
  76. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/debug/tree-sitter.js.map +7 -0
  77. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/debug/tree-sitter.wasm +0 -0
  78. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/debug/tree-sitter.wasm.map +31 -0
  79. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/alloc.c +48 -0
  80. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/alloc.h +41 -0
  81. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/array.h +291 -0
  82. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/atomic.h +68 -0
  83. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/clock.h +146 -0
  84. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/error_costs.h +11 -0
  85. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/get_changed_ranges.c +523 -0
  86. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/get_changed_ranges.h +36 -0
  87. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/host.h +21 -0
  88. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/language.c +293 -0
  89. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/language.h +293 -0
  90. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/length.h +52 -0
  91. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/lexer.c +483 -0
  92. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/lexer.h +54 -0
  93. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/lib.c +12 -0
  94. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/node.c +875 -0
  95. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/parser.c +2297 -0
  96. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/parser.h +286 -0
  97. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/point.h +48 -0
  98. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/query.c +4347 -0
  99. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/reduce_action.h +34 -0
  100. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/reusable_node.h +95 -0
  101. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/stack.c +912 -0
  102. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/stack.h +133 -0
  103. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/subtree.c +1034 -0
  104. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/subtree.h +399 -0
  105. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/tree-sitter.c +987 -0
  106. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/tree-sitter.cjs +2988 -0
  107. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/tree-sitter.wasm +0 -0
  108. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/tree-sitter.wasm.map +1 -0
  109. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/tree.c +170 -0
  110. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/tree.h +31 -0
  111. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/tree_cursor.c +716 -0
  112. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/tree_cursor.h +48 -0
  113. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/ts_assert.h +11 -0
  114. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/unicode.h +75 -0
  115. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/wasm_store.c +1937 -0
  116. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/lib/wasm_store.h +31 -0
  117. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/package.json +98 -0
  118. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/src/bindings.ts +26 -0
  119. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/src/constants.ts +133 -0
  120. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/src/index.ts +31 -0
  121. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/src/language.ts +291 -0
  122. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/src/lookahead_iterator.ts +75 -0
  123. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/src/marshal.ts +176 -0
  124. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/src/node.ts +646 -0
  125. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/src/parser.ts +325 -0
  126. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/src/query.ts +973 -0
  127. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/src/tree.ts +145 -0
  128. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/src/tree_cursor.ts +318 -0
  129. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/tree-sitter.cjs +4031 -0
  130. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/tree-sitter.cjs.map +7 -0
  131. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/tree-sitter.js +3980 -0
  132. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/tree-sitter.js.map +7 -0
  133. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/tree-sitter.wasm +0 -0
  134. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/tree-sitter.wasm.map +30 -0
  135. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/web-tree-sitter.d.ts +1030 -0
  136. package/node_modules/@aui.io/apollo-tui/node_modules/web-tree-sitter/web-tree-sitter.d.ts.map +56 -0
  137. package/node_modules/@aui.io/apollo-tui/package.json +5 -3
  138. package/package.json +7 -5
  139. package/node_modules/@aui.io/apollo-tui/dist/src/components/glyph.d.ts +0 -19
  140. package/node_modules/@aui.io/apollo-tui/dist/src/components/glyph.js +0 -41
  141. package/node_modules/@aui.io/apollo-tui/dist/src/components/glyph.js.map +0 -1
  142. package/node_modules/@aui.io/apollo-tui/dist/src/lib/attractor.d.ts +0 -82
  143. package/node_modules/@aui.io/apollo-tui/dist/src/lib/attractor.js +0 -231
  144. package/node_modules/@aui.io/apollo-tui/dist/src/lib/attractor.js.map +0 -1
@@ -0,0 +1,114 @@
1
+ /**
2
+ * JSON tree rows — trace/debug payloads rendered as a collapsible tree
3
+ * (IDE-inspector style: indented `key: value` rows, container previews with
4
+ * child counts) instead of a wall of stringified JSON. Pure data layer:
5
+ * expansion state lives in the caller keyed by stable row paths, the pane
6
+ * component renders rows and reports clicks back by index.
7
+ */
8
+ function kindOf(value) {
9
+ if (value === null || value === undefined)
10
+ return "null";
11
+ if (Array.isArray(value))
12
+ return "array";
13
+ const t = typeof value;
14
+ if (t === "object")
15
+ return "object";
16
+ if (t === "number" || t === "bigint")
17
+ return "number";
18
+ if (t === "boolean")
19
+ return "boolean";
20
+ return "string";
21
+ }
22
+ /** Single-line scalar rendering; strings keep quotes so "" and "3" read. */
23
+ function scalar(value, kind) {
24
+ if (kind === "null")
25
+ return value === undefined ? "undefined" : "null";
26
+ if (kind === "string")
27
+ return JSON.stringify(value);
28
+ return String(value);
29
+ }
30
+ function entries(value) {
31
+ return Array.isArray(value)
32
+ ? value.map((v, i) => [`[${i}]`, v])
33
+ : Object.entries(value);
34
+ }
35
+ function childPath(parent, key, isIndex) {
36
+ return isIndex ? `${parent}${key}` : `${parent}.${key}`;
37
+ }
38
+ /** Flatten `value` into visible rows honoring `expanded` paths. */
39
+ export function jsonRows(value, expanded) {
40
+ const rows = [];
41
+ const walk = (node, path, key, depth) => {
42
+ const kind = kindOf(node);
43
+ if (kind !== "object" && kind !== "array") {
44
+ rows.push({
45
+ path,
46
+ depth,
47
+ key,
48
+ kind,
49
+ value: scalar(node, kind),
50
+ expandable: false,
51
+ expanded: false,
52
+ });
53
+ return;
54
+ }
55
+ const children = entries(node);
56
+ const isOpen = expanded.has(path) && children.length > 0;
57
+ rows.push({
58
+ path,
59
+ depth,
60
+ key,
61
+ kind,
62
+ value: kind === "array"
63
+ ? children.length === 0
64
+ ? "[]"
65
+ : `[${children.length}]`
66
+ : children.length === 0
67
+ ? "{}"
68
+ : `{${children.length}}`,
69
+ expandable: children.length > 0,
70
+ expanded: isOpen,
71
+ });
72
+ if (!isOpen)
73
+ return;
74
+ for (const [childKey, childValue] of children) {
75
+ walk(childValue, childPath(path, childKey, kind === "array"), childKey, depth + 1);
76
+ }
77
+ };
78
+ walk(value, "$", undefined, 0);
79
+ return rows;
80
+ }
81
+ /**
82
+ * Default expansion: containers down to `maxDepth` open (root = depth 0),
83
+ * so a fresh trace shows its shape without a click storm — deep payloads
84
+ * stay behind their previews.
85
+ */
86
+ export function jsonDefaultExpanded(value, maxDepth = 2) {
87
+ const expanded = new Set();
88
+ const walk = (node, path, depth) => {
89
+ const kind = kindOf(node);
90
+ if (kind !== "object" && kind !== "array")
91
+ return;
92
+ const children = entries(node);
93
+ if (children.length === 0)
94
+ return;
95
+ if (depth >= maxDepth)
96
+ return;
97
+ expanded.add(path);
98
+ for (const [key, child] of children) {
99
+ walk(child, childPath(path, key, kind === "array"), depth + 1);
100
+ }
101
+ };
102
+ walk(value, "$", 0);
103
+ return expanded;
104
+ }
105
+ /** Toggle one container; returns a new set (state-friendly). */
106
+ export function toggleJsonPath(expanded, path) {
107
+ const next = new Set(expanded);
108
+ if (next.has(path))
109
+ next.delete(path);
110
+ else
111
+ next.add(path);
112
+ return next;
113
+ }
114
+ //# sourceMappingURL=jsonview.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonview.js","sourceRoot":"","sources":["../../../src/lib/jsonview.ts"],"names":[],"mappings":"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"}
@@ -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,14 +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 { G, unicodeSupported } from "./theme/glyphs.js";
54
- import { AMBER, DIM, FAINT, FG, TEAL, TEAL_DIM } from "./theme/tokens.js";
53
+ import { G } from "./theme/glyphs.js";
54
+ import { AMBER, DIM, FAINT, FG, RICH, TEAL, TEAL_DIM } from "./theme/tokens.js";
55
55
  const VERSION = process.env.npm_package_version ?? "0.1.11";
56
- /** Resolved once — glyph support can't change mid-session. */
57
- const UNICODE_OK = unicodeSupported();
58
56
  const REGISTRY = buildActionRegistry();
59
57
  /** Author-mode single-letter quick actions (typed + Enter). */
60
58
  const AUTHOR_QUICK = {
@@ -71,7 +69,7 @@ const AUTHOR_VIEW_FOCUS = {
71
69
  validation: "author-validation",
72
70
  versions: "author-versions",
73
71
  };
74
- function App({ context: initialContext, initialScope, glyph, onQuit }) {
72
+ function App({ context: initialContext, initialScope, onQuit }) {
75
73
  const [context, setContext] = useState(initialContext);
76
74
  const [scope, setScope] = useState(initialScope);
77
75
  const [mode, setMode] = useState("author");
@@ -89,6 +87,11 @@ function App({ context: initialContext, initialScope, glyph, onQuit }) {
89
87
  const [activityCursor, setActivityCursor] = useState();
90
88
  const [paneTitle, setPaneTitle] = useState();
91
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());
92
95
  const [working, setWorking] = useState(false);
93
96
  const [trace, setTrace] = useState(false);
94
97
  const [localMode, setLocalMode] = useState(false);
@@ -99,9 +102,6 @@ function App({ context: initialContext, initialScope, glyph, onQuit }) {
99
102
  */
100
103
  const [talkTag, setTalkTag] = useState(undefined);
101
104
  const [vars, setVars] = useState([]);
102
- // The brand orb draws on a Braille canvas — decorative, so it simply
103
- // disappears on terminals without Unicode fonts instead of garbling.
104
- const [frame, setFrame] = useState(UNICODE_OK ? glyph.frame() : []);
105
105
  // Author workbench state (Phase 3).
106
106
  const [authorView, setAuthorView] = useState("home");
107
107
  const [snapshot, setSnapshot] = useState();
@@ -163,6 +163,11 @@ function App({ context: initialContext, initialScope, glyph, onQuit }) {
163
163
  const turnFeedRef = useRef([]);
164
164
  /** The one scrollable content pane on screen (diff/validation/versions/talk). */
165
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());
166
171
  /** Remote bundle contents cached per bound tag (content diffs). */
167
172
  const remoteFilesRef = useRef(undefined);
168
173
  /** Detects agent switches to reset per-agent author state. */
@@ -217,7 +222,9 @@ function App({ context: initialContext, initialScope, glyph, onQuit }) {
217
222
  /** Session rows are pre-wrapped to the pane width → exact scroll offsets. */
218
223
  const sessionPaneWidth = Math.max(30, termWidth - 8);
219
224
  const sessionRowsView = useMemo(() => authorSession
220
- ? sessionRows(authorSession, sessionExpanded, sessionPaneWidth, queuedPrompts)
225
+ ? sessionRows(authorSession, sessionExpanded, sessionPaneWidth, queuedPrompts, {
226
+ markdown: RICH,
227
+ })
221
228
  : [], [authorSession, sessionExpanded, sessionPaneWidth, queuedPrompts]);
222
229
  // Talk workbench derivations: panes by width, pre-wrapped rows, pending.
223
230
  const talkLayoutEffective = useMemo(() => talkLayout(termWidth), [termWidth]);
@@ -234,9 +241,18 @@ function App({ context: initialContext, initialScope, glyph, onQuit }) {
234
241
  8 -
235
242
  (talkLayoutEffective.threads ? talkLayoutEffective.threadsWidth : 0) -
236
243
  (talkLayoutEffective.inspector ? talkLayoutEffective.inspectorWidth : 0));
237
- const talkRowsView = useMemo(() => talkRows(chat, conversationWidth, Date.now()),
244
+ const talkRowsView = useMemo(() => talkRows(chat, conversationWidth, Date.now(), { markdown: RICH }),
238
245
  // talkTick re-times the pending row twice a second.
239
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
+ }
240
256
  const talkCursorClamped = clampPickerCursor(talkCursor, chat.length);
241
257
  /** What sends run against, for the composer label and inspector (^B picks). */
242
258
  const talkVersionLabel = talkTag === "latest"
@@ -335,15 +351,6 @@ function App({ context: initialContext, initialScope, glyph, onQuit }) {
335
351
  const browseRoot = bundleSrcRoot(context) ?? context.workspaceRoot;
336
352
  /** Subviews need an agent — except diff, which browses any place. */
337
353
  const authorViewEffective = authorEmpty && !(authorView === "diff" && browseRoot) ? "home" : authorView;
338
- useEffect(() => {
339
- if (!UNICODE_OK || mode !== "author" || !authorEmpty)
340
- return;
341
- const id = setInterval(() => setFrame(glyph.frame()), 33);
342
- return () => clearInterval(id);
343
- }, [mode, authorEmpty, glyph]);
344
- useEffect(() => {
345
- glyph.setWorking(working);
346
- }, [working, glyph]);
347
354
  // Human names for the strip (workspace manifest, project/org APIs) —
348
355
  // ids render immediately, names overlay when resolved; stale results
349
356
  // (context changed meanwhile) are dropped.
@@ -475,6 +482,8 @@ function App({ context: initialContext, initialScope, glyph, onQuit }) {
475
482
  // Keep the transcript visible: cursor on the newest unit pins the pane to
476
483
  // the bottom (streaming rows grow below the unit's label — bottom-pinning
477
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.
478
487
  useEffect(() => {
479
488
  if (mode !== "author" || authorViewEffective !== "home")
480
489
  return;
@@ -487,13 +496,14 @@ function App({ context: initialContext, initialScope, glyph, onQuit }) {
487
496
  const cursor = clampPickerCursor(sessionCursor, count);
488
497
  const viewport = Math.max(4, box.height || 10);
489
498
  if (cursor >= count - 1) {
490
- box.scrollTo({
491
- x: 0,
492
- y: Math.max(0, sessionRowsView.length - viewport + 1),
493
- });
499
+ box.scrollTo({ x: 0, y: Math.max(0, box.scrollHeight) });
494
500
  return;
495
501
  }
496
- 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);
497
507
  box.scrollTo({ x: 0, y: Math.max(0, offset - Math.floor(viewport / 2)) });
498
508
  }, [sessionCursor, sessionRowsView, authorSession, mode, authorViewEffective]);
499
509
  // Queued prompts drain in order once the running turn settles. (Effect,
@@ -526,6 +536,8 @@ function App({ context: initialContext, initialScope, glyph, onQuit }) {
526
536
  }, [chat]);
527
537
  // Conversation scroll follows the selection: newest turn pins the pane to
528
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.
529
541
  useEffect(() => {
530
542
  if (mode !== "talk" || chat.length === 0)
531
543
  return;
@@ -535,10 +547,14 @@ function App({ context: initialContext, initialScope, glyph, onQuit }) {
535
547
  const cursor = clampPickerCursor(talkCursor, chat.length);
536
548
  const viewport = Math.max(4, box.height || 10);
537
549
  if (cursor >= chat.length - 1) {
538
- box.scrollTo({ x: 0, y: Math.max(0, talkRowsView.length - viewport + 1) });
550
+ box.scrollTo({ x: 0, y: Math.max(0, box.scrollHeight) });
539
551
  return;
540
552
  }
541
- 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);
542
558
  box.scrollTo({ x: 0, y: Math.max(0, offset - Math.floor(viewport / 2)) });
543
559
  }, [talkCursor, talkRowsView, chat, mode]);
544
560
  // Threads pane data: lazy, once per context (invalidated on new threads).
@@ -661,7 +677,15 @@ function App({ context: initialContext, initialScope, glyph, onQuit }) {
661
677
  return { kind: "error", path: previewTarget, message: diffFiles.message };
662
678
  }
663
679
  if (previewDiffLines) {
664
- 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
+ };
665
689
  }
666
690
  const content = diffFiles.local[previewTarget];
667
691
  if (content === undefined) {
@@ -1084,6 +1108,7 @@ function App({ context: initialContext, initialScope, glyph, onQuit }) {
1084
1108
  setPaneTitle((title) => {
1085
1109
  if (title && /^(trace|debug)/i.test(title)) {
1086
1110
  setPaneLines([]);
1111
+ setPaneJson(undefined);
1087
1112
  return undefined;
1088
1113
  }
1089
1114
  return title;
@@ -1117,6 +1142,10 @@ function App({ context: initialContext, initialScope, glyph, onQuit }) {
1117
1142
  if (result.paneLines) {
1118
1143
  setPaneLines(result.paneLines);
1119
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());
1120
1149
  }
1121
1150
  if (result.needConfirm) {
1122
1151
  setConfirm(createConfirm(result.needConfirm.title, result.needConfirm.phrase, result.needConfirm.action, result.needConfirm.args));
@@ -1908,7 +1937,15 @@ function App({ context: initialContext, initialScope, glyph, onQuit }) {
1908
1937
  setMode("talk");
1909
1938
  if (target !== cursor)
1910
1939
  setTalkCursor(target);
1911
- 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());
1912
1949
  setToast(`${kind} · reply #${ordinal ?? "?"} → inspector`);
1913
1950
  }
1914
1951
  else {
@@ -1922,21 +1959,72 @@ function App({ context: initialContext, initialScope, glyph, onQuit }) {
1922
1959
  setWorking(false);
1923
1960
  }
1924
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
+ }
1925
2023
  /** Enter in the composer: threads focus opens; otherwise send the draft. */
1926
2024
  function handleComposerSend() {
1927
2025
  const current = stateRef.current;
1928
2026
  if (current.talkFocus === "threads") {
1929
- const count = threadsRowCount(current.threads);
1930
- const row = clampPickerCursor(current.threadCursor, count);
1931
- if (row === NEW_THREAD_ROW) {
1932
- const cmd = SLASH_COMMANDS.find((c) => c.name === "new");
1933
- if (cmd)
1934
- void runCommand(cmd, "");
1935
- return;
1936
- }
1937
- const picked = current.threads?.[row - 1];
1938
- if (picked)
1939
- void openThread(picked.id);
2027
+ activateThreadRow(current.threadCursor);
1940
2028
  return;
1941
2029
  }
1942
2030
  const text = (composerRef.current?.plainText ?? "").trim();
@@ -2054,15 +2142,7 @@ function App({ context: initialContext, initialScope, glyph, onQuit }) {
2054
2142
  return;
2055
2143
  }
2056
2144
  const highlight = clampPickerCursor(current.paletteCursor, matches.length);
2057
- const action = matches[highlight];
2058
- const reason = action.disabledReason?.(current.context);
2059
- setPaletteCursor(undefined);
2060
- if (reason && !action.command.requiresAuth) {
2061
- // Auth gaps route to login via ensureAuth; other gaps just explain.
2062
- setToast(`${action.title} — ${reason}`);
2063
- return;
2064
- }
2065
- void runCommand(action.command, "");
2145
+ activatePaletteAction(matches[highlight]);
2066
2146
  return;
2067
2147
  }
2068
2148
  if (current.switcherCursor !== undefined) {
@@ -2095,22 +2175,7 @@ function App({ context: initialContext, initialScope, glyph, onQuit }) {
2095
2175
  current.mode === "author" &&
2096
2176
  current.authorView === "diff" &&
2097
2177
  !current.fileDiff) {
2098
- const rows = current.diffRows;
2099
- const row = rows[clampPickerCursor(current.diffCursor, rows.length)];
2100
- if (row?.kind === "dir") {
2101
- setDiffCollapsed((prev) => {
2102
- const next = new Set(prev);
2103
- if (next.has(row.path))
2104
- next.delete(row.path);
2105
- else
2106
- next.add(row.path);
2107
- return next;
2108
- });
2109
- }
2110
- else if (row) {
2111
- setPreviewPath(row.path);
2112
- setFileDiff({ path: row.path });
2113
- }
2178
+ activateDiffRow(clampPickerCursor(current.diffCursor, current.diffRows.length));
2114
2179
  return;
2115
2180
  }
2116
2181
  // Enter on a session unit: expand/collapse its body (tool input/result).
@@ -2119,19 +2184,7 @@ function App({ context: initialContext, initialScope, glyph, onQuit }) {
2119
2184
  current.authorView === "home" &&
2120
2185
  current.authorSession) {
2121
2186
  const units = current.authorSession.units;
2122
- const unit = units[clampPickerCursor(current.sessionCursor, units.length)];
2123
- if (unit &&
2124
- unit.body.length > 0 &&
2125
- (unit.kind === "action" || unit.kind === "thinking")) {
2126
- setSessionExpanded((prev) => {
2127
- const next = new Set(prev);
2128
- if (next.has(unit.id))
2129
- next.delete(unit.id);
2130
- else
2131
- next.add(unit.id);
2132
- return next;
2133
- });
2134
- }
2187
+ toggleSessionUnitBody(clampPickerCursor(current.sessionCursor, units.length));
2135
2188
  return;
2136
2189
  }
2137
2190
  if (line === "")
@@ -2233,7 +2286,14 @@ function App({ context: initialContext, initialScope, glyph, onQuit }) {
2233
2286
  ? 0
2234
2287
  : Math.max(0, Math.min(pickerCursor - Math.floor(PICKER_PAGE / 3), pickerVisible.length - PICKER_PAGE));
2235
2288
  const pickerWindow = pickerVisible.slice(pickerWindowStart, pickerWindowStart + PICKER_PAGE);
2236
- 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: {
2237
2297
  flexDirection: "column",
2238
2298
  flexGrow: 1,
2239
2299
  flexShrink: 1,
@@ -2246,11 +2306,61 @@ function App({ context: initialContext, initialScope, glyph, onQuit }) {
2246
2306
  ? `${picker.command.name} — ${picker.note}`
2247
2307
  : picker.command.name, filter: pickerFilter, dismissHint: picker.command.name === "place-onboard"
2248
2308
  ? "Esc continue without place"
2249
- : 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
2250
2348
  ? statusByPath.size > 0
2251
2349
  ? `changes (${changesSummary(snapshot?.diff)})`
2252
2350
  : "files (clean)"
2253
- : "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: {
2254
2364
  border: true,
2255
2365
  borderStyle: "rounded",
2256
2366
  borderColor: TEAL_DIM,
@@ -2258,7 +2368,7 @@ function App({ context: initialContext, initialScope, glyph, onQuit }) {
2258
2368
  flexShrink: 0,
2259
2369
  paddingLeft: 1,
2260
2370
  paddingRight: 1,
2261
- }, 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 })) : (_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: {
2262
2372
  border: true,
2263
2373
  borderStyle: "rounded",
2264
2374
  borderColor: working ? AMBER : TEAL_DIM,
@@ -2284,11 +2394,6 @@ function App({ context: initialContext, initialScope, glyph, onQuit }) {
2284
2394
  export async function runOpenTui() {
2285
2395
  const context = await resolveContext({});
2286
2396
  const scope = scopeFromContext(context);
2287
- const glyph = new GlyphController(context.agentId ?? context.projectId ?? "apollo", {
2288
- width: 10,
2289
- height: 4,
2290
- compact: true,
2291
- });
2292
2397
  const renderer = await createCliRenderer({
2293
2398
  // Ctrl+C is an app key (cancel turn / clear input / quit) — see matchCtrlC.
2294
2399
  exitOnCtrlC: false,
@@ -2298,7 +2403,7 @@ export async function runOpenTui() {
2298
2403
  });
2299
2404
  const root = createRoot(renderer);
2300
2405
  const code = await new Promise((resolve) => {
2301
- root.render(_jsx(App, { context: context, initialScope: scope, glyph: glyph, onQuit: resolve }));
2406
+ root.render(_jsx(App, { context: context, initialScope: scope, onQuit: resolve }));
2302
2407
  });
2303
2408
  root.unmount();
2304
2409
  renderer.destroy();