@kolisachint/hoocode-agent 0.4.105 → 0.4.107

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 (289) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/cli/args.d.ts.map +1 -1
  3. package/dist/cli/args.js +4 -4
  4. package/dist/cli/args.js.map +1 -1
  5. package/dist/cli.d.ts.map +1 -1
  6. package/dist/cli.js +0 -1
  7. package/dist/cli.js.map +1 -1
  8. package/dist/config.d.ts.map +1 -1
  9. package/dist/config.js +2 -2
  10. package/dist/config.js.map +1 -1
  11. package/dist/core/agent-session.d.ts +1 -3
  12. package/dist/core/agent-session.d.ts.map +1 -1
  13. package/dist/core/agent-session.js +2 -2
  14. package/dist/core/agent-session.js.map +1 -1
  15. package/dist/core/bash-executor.d.ts.map +1 -1
  16. package/dist/core/bash-executor.js +1 -1
  17. package/dist/core/bash-executor.js.map +1 -1
  18. package/dist/core/extension-mcp-servers.d.ts +1 -1
  19. package/dist/core/extension-mcp-servers.d.ts.map +1 -1
  20. package/dist/core/extension-mcp-servers.js +1 -1
  21. package/dist/core/extension-mcp-servers.js.map +1 -1
  22. package/dist/core/extensions/plugins/index.d.ts.map +1 -1
  23. package/dist/core/extensions/plugins/index.js +1 -1
  24. package/dist/core/extensions/plugins/index.js.map +1 -1
  25. package/dist/core/extensions/types.d.ts +1 -3
  26. package/dist/core/extensions/types.d.ts.map +1 -1
  27. package/dist/core/extensions/types.js.map +1 -1
  28. package/dist/core/index.d.ts +1 -1
  29. package/dist/core/index.d.ts.map +1 -1
  30. package/dist/core/index.js.map +1 -1
  31. package/dist/core/mode-prompts.d.ts +1 -1
  32. package/dist/core/mode-prompts.d.ts.map +1 -1
  33. package/dist/core/mode-prompts.js +1 -1
  34. package/dist/core/mode-prompts.js.map +1 -1
  35. package/dist/core/package-manager.d.ts.map +1 -1
  36. package/dist/core/package-manager.js +1 -1
  37. package/dist/core/package-manager.js.map +1 -1
  38. package/dist/core/sdk.d.ts.map +1 -1
  39. package/dist/core/sdk.js +1 -2
  40. package/dist/core/sdk.js.map +1 -1
  41. package/dist/core/session-manager.d.ts +2 -97
  42. package/dist/core/session-manager.d.ts.map +1 -1
  43. package/dist/core/session-manager.js +4 -65
  44. package/dist/core/session-manager.js.map +1 -1
  45. package/dist/core/settings-manager.d.ts.map +1 -1
  46. package/dist/core/settings-manager.js +2 -3
  47. package/dist/core/settings-manager.js.map +1 -1
  48. package/dist/core/telemetry.d.ts.map +1 -1
  49. package/dist/core/telemetry.js +1 -1
  50. package/dist/core/telemetry.js.map +1 -1
  51. package/dist/core/timings.d.ts +1 -1
  52. package/dist/core/timings.d.ts.map +1 -1
  53. package/dist/core/timings.js +2 -2
  54. package/dist/core/timings.js.map +1 -1
  55. package/dist/core/tools/{browser-continue.d.ts → browser/browser-continue.d.ts} +1 -1
  56. package/dist/core/tools/browser/browser-continue.d.ts.map +1 -0
  57. package/dist/core/tools/{browser-continue.js → browser/browser-continue.js} +2 -2
  58. package/dist/core/tools/browser/browser-continue.js.map +1 -0
  59. package/dist/core/tools/{browser-run.d.ts → browser/browser-run.d.ts} +2 -2
  60. package/dist/core/tools/browser/browser-run.d.ts.map +1 -0
  61. package/dist/core/tools/{browser-run.js → browser/browser-run.js} +2 -2
  62. package/dist/core/tools/browser/browser-run.js.map +1 -0
  63. package/dist/core/tools/browser/browsertools-shared.d.ts.map +1 -0
  64. package/dist/core/tools/{browsertools-shared.js → browser/browsertools-shared.js} +1 -1
  65. package/dist/core/tools/browser/browsertools-shared.js.map +1 -0
  66. package/dist/core/tools/browser/index.d.ts +8 -0
  67. package/dist/core/tools/browser/index.d.ts.map +1 -0
  68. package/dist/core/tools/browser/index.js +8 -0
  69. package/dist/core/tools/browser/index.js.map +1 -0
  70. package/dist/core/tools/{docedit.d.ts → doc/docedit.d.ts} +2 -2
  71. package/dist/core/tools/doc/docedit.d.ts.map +1 -0
  72. package/dist/core/tools/{docedit.js → doc/docedit.js} +7 -7
  73. package/dist/core/tools/doc/docedit.js.map +1 -0
  74. package/dist/core/tools/{docgrep.d.ts → doc/docgrep.d.ts} +2 -2
  75. package/dist/core/tools/doc/docgrep.d.ts.map +1 -0
  76. package/dist/core/tools/{docgrep.js → doc/docgrep.js} +6 -6
  77. package/dist/core/tools/doc/docgrep.js.map +1 -0
  78. package/dist/core/tools/{docpeek.d.ts → doc/docpeek.d.ts} +2 -2
  79. package/dist/core/tools/{docpeek.js.map → doc/docpeek.d.ts.map} +1 -1
  80. package/dist/core/tools/{docpeek.js → doc/docpeek.js} +6 -6
  81. package/dist/core/tools/doc/docpeek.js.map +1 -0
  82. package/dist/core/tools/{docread.d.ts → doc/docread.d.ts} +2 -2
  83. package/dist/core/tools/doc/docread.d.ts.map +1 -0
  84. package/dist/core/tools/{docread.js → doc/docread.js} +6 -6
  85. package/dist/core/tools/doc/docread.js.map +1 -0
  86. package/dist/core/tools/{docscan.d.ts → doc/docscan.d.ts} +2 -2
  87. package/dist/core/tools/doc/docscan.d.ts.map +1 -0
  88. package/dist/core/tools/{docscan.js → doc/docscan.js} +6 -6
  89. package/dist/core/tools/doc/docscan.js.map +1 -0
  90. package/dist/core/tools/{docwrite.d.ts → doc/docwrite.d.ts} +1 -1
  91. package/dist/core/tools/doc/docwrite.d.ts.map +1 -0
  92. package/dist/core/tools/{docwrite.js → doc/docwrite.js} +6 -6
  93. package/dist/core/tools/doc/docwrite.js.map +1 -0
  94. package/dist/core/tools/doc/index.d.ts +11 -0
  95. package/dist/core/tools/doc/index.d.ts.map +1 -0
  96. package/dist/core/tools/doc/index.js +11 -0
  97. package/dist/core/tools/doc/index.js.map +1 -0
  98. package/dist/core/tools/grep.d.ts.map +1 -1
  99. package/dist/core/tools/grep.js +1 -1
  100. package/dist/core/tools/grep.js.map +1 -1
  101. package/dist/core/tools/index.d.ts +42 -28
  102. package/dist/core/tools/index.d.ts.map +1 -1
  103. package/dist/core/tools/index.js +61 -199
  104. package/dist/core/tools/index.js.map +1 -1
  105. package/dist/core/tools/output-accumulator.d.ts.map +1 -1
  106. package/dist/core/tools/output-accumulator.js +1 -1
  107. package/dist/core/tools/output-accumulator.js.map +1 -1
  108. package/dist/core/tools/read.d.ts.map +1 -1
  109. package/dist/core/tools/read.js +1 -1
  110. package/dist/core/tools/read.js.map +1 -1
  111. package/dist/extensions/core/ask-options.d.ts +10 -0
  112. package/dist/extensions/core/ask-options.d.ts.map +1 -0
  113. package/dist/extensions/core/ask-options.js +83 -0
  114. package/dist/extensions/core/ask-options.js.map +1 -0
  115. package/dist/extensions/core/config.d.ts +80 -0
  116. package/dist/extensions/core/config.d.ts.map +1 -0
  117. package/dist/extensions/core/config.js +110 -0
  118. package/dist/extensions/core/config.js.map +1 -0
  119. package/dist/extensions/core/cost.d.ts +11 -0
  120. package/dist/extensions/core/cost.d.ts.map +1 -0
  121. package/dist/extensions/core/cost.js +64 -0
  122. package/dist/extensions/core/cost.js.map +1 -0
  123. package/dist/extensions/core/hoo-core.d.ts +16 -179
  124. package/dist/extensions/core/hoo-core.d.ts.map +1 -1
  125. package/dist/extensions/core/hoo-core.js +27 -1663
  126. package/dist/extensions/core/hoo-core.js.map +1 -1
  127. package/dist/extensions/core/loop.d.ts +15 -0
  128. package/dist/extensions/core/loop.d.ts.map +1 -0
  129. package/dist/extensions/core/loop.js +235 -0
  130. package/dist/extensions/core/loop.js.map +1 -0
  131. package/dist/extensions/core/marketplace.d.ts +17 -0
  132. package/dist/extensions/core/marketplace.d.ts.map +1 -0
  133. package/dist/extensions/core/marketplace.js +167 -0
  134. package/dist/extensions/core/marketplace.js.map +1 -0
  135. package/dist/extensions/core/mcp-loader.d.ts +26 -0
  136. package/dist/extensions/core/mcp-loader.d.ts.map +1 -0
  137. package/dist/extensions/core/mcp-loader.js +391 -0
  138. package/dist/extensions/core/mcp-loader.js.map +1 -0
  139. package/dist/extensions/core/modes.d.ts +56 -0
  140. package/dist/extensions/core/modes.d.ts.map +1 -0
  141. package/dist/extensions/core/modes.js +268 -0
  142. package/dist/extensions/core/modes.js.map +1 -0
  143. package/dist/extensions/core/permission-gate.d.ts +10 -0
  144. package/dist/extensions/core/permission-gate.d.ts.map +1 -0
  145. package/dist/extensions/core/permission-gate.js +167 -0
  146. package/dist/extensions/core/permission-gate.js.map +1 -0
  147. package/dist/extensions/core/scaffold.d.ts +9 -0
  148. package/dist/extensions/core/scaffold.d.ts.map +1 -0
  149. package/dist/extensions/core/scaffold.js +146 -0
  150. package/dist/extensions/core/scaffold.js.map +1 -0
  151. package/dist/extensions/core/thinking-escalation.d.ts +18 -0
  152. package/dist/extensions/core/thinking-escalation.d.ts.map +1 -0
  153. package/dist/extensions/core/thinking-escalation.js +70 -0
  154. package/dist/extensions/core/thinking-escalation.js.map +1 -0
  155. package/dist/index.d.ts +2 -3
  156. package/dist/index.d.ts.map +1 -1
  157. package/dist/index.js +3 -4
  158. package/dist/index.js.map +1 -1
  159. package/dist/main.d.ts.map +1 -1
  160. package/dist/main.js +2 -2
  161. package/dist/main.js.map +1 -1
  162. package/dist/modes/interactive/command-executor.d.ts +0 -5
  163. package/dist/modes/interactive/command-executor.d.ts.map +1 -1
  164. package/dist/modes/interactive/command-executor.js +0 -7
  165. package/dist/modes/interactive/command-executor.js.map +1 -1
  166. package/dist/modes/interactive/components/branch-summary-message.d.ts +1 -1
  167. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
  168. package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
  169. package/dist/modes/interactive/components/compaction-summary-message.d.ts +1 -1
  170. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
  171. package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
  172. package/dist/modes/interactive/components/custom-message.d.ts +1 -1
  173. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
  174. package/dist/modes/interactive/components/custom-message.js.map +1 -1
  175. package/dist/modes/interactive/components/index.d.ts +0 -2
  176. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  177. package/dist/modes/interactive/components/index.js +0 -2
  178. package/dist/modes/interactive/components/index.js.map +1 -1
  179. package/dist/modes/interactive/extension-chrome.d.ts +56 -0
  180. package/dist/modes/interactive/extension-chrome.d.ts.map +1 -0
  181. package/dist/modes/interactive/extension-chrome.js +172 -0
  182. package/dist/modes/interactive/extension-chrome.js.map +1 -0
  183. package/dist/modes/interactive/extension-dialogs.d.ts +82 -0
  184. package/dist/modes/interactive/extension-dialogs.d.ts.map +1 -0
  185. package/dist/modes/interactive/extension-dialogs.js +259 -0
  186. package/dist/modes/interactive/extension-dialogs.js.map +1 -0
  187. package/dist/modes/interactive/interactive-mode.d.ts +11 -161
  188. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  189. package/dist/modes/interactive/interactive-mode.js +263 -1571
  190. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  191. package/dist/modes/interactive/resource-display.d.ts +59 -0
  192. package/dist/modes/interactive/resource-display.d.ts.map +1 -0
  193. package/dist/modes/interactive/resource-display.js +499 -0
  194. package/dist/modes/interactive/resource-display.js.map +1 -0
  195. package/dist/modes/interactive/startup-checks.d.ts +17 -0
  196. package/dist/modes/interactive/startup-checks.d.ts.map +1 -0
  197. package/dist/modes/interactive/startup-checks.js +102 -0
  198. package/dist/modes/interactive/startup-checks.js.map +1 -0
  199. package/dist/modes/interactive/team-focus.d.ts +56 -0
  200. package/dist/modes/interactive/team-focus.d.ts.map +1 -0
  201. package/dist/modes/interactive/team-focus.js +167 -0
  202. package/dist/modes/interactive/team-focus.js.map +1 -0
  203. package/dist/modes/interactive/voice/voice-controller.d.ts +66 -0
  204. package/dist/modes/interactive/voice/voice-controller.d.ts.map +1 -0
  205. package/dist/modes/interactive/voice/voice-controller.js +312 -0
  206. package/dist/modes/interactive/voice/voice-controller.js.map +1 -0
  207. package/dist/modes/interactive/voice/voice-panel.d.ts.map +1 -0
  208. package/dist/modes/interactive/voice/voice-panel.js.map +1 -0
  209. package/dist/modes/interactive/{voice-transcribe.d.ts → voice/voice-transcribe.d.ts} +16 -1
  210. package/dist/modes/interactive/voice/voice-transcribe.d.ts.map +1 -0
  211. package/dist/modes/interactive/{voice-transcribe.js → voice/voice-transcribe.js} +31 -4
  212. package/dist/modes/interactive/voice/voice-transcribe.js.map +1 -0
  213. package/dist/modes/rpc/rpc-client.d.ts +1 -2
  214. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  215. package/dist/modes/rpc/rpc-client.js.map +1 -1
  216. package/dist/modes/rpc/rpc-types.d.ts +1 -2
  217. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  218. package/dist/modes/rpc/rpc-types.js.map +1 -1
  219. package/dist/resources-cli.d.ts.map +1 -1
  220. package/dist/resources-cli.js +1 -1
  221. package/dist/resources-cli.js.map +1 -1
  222. package/dist/utils/tools-manager.d.ts.map +1 -1
  223. package/dist/utils/tools-manager.js +1 -1
  224. package/dist/utils/tools-manager.js.map +1 -1
  225. package/dist/utils/version-check.d.ts.map +1 -1
  226. package/dist/utils/version-check.js +2 -2
  227. package/dist/utils/version-check.js.map +1 -1
  228. package/docs/project-local-resources.md +1 -1
  229. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  230. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  231. package/examples/extensions/sandbox/package.json +1 -1
  232. package/examples/extensions/with-deps/package.json +1 -1
  233. package/package.json +4 -4
  234. package/dist/core/compaction/branch-summarization.d.ts +0 -88
  235. package/dist/core/compaction/branch-summarization.d.ts.map +0 -1
  236. package/dist/core/compaction/branch-summarization.js +0 -243
  237. package/dist/core/compaction/branch-summarization.js.map +0 -1
  238. package/dist/core/compaction/compaction.d.ts +0 -123
  239. package/dist/core/compaction/compaction.d.ts.map +0 -1
  240. package/dist/core/compaction/compaction.js +0 -635
  241. package/dist/core/compaction/compaction.js.map +0 -1
  242. package/dist/core/compaction/index.d.ts +0 -7
  243. package/dist/core/compaction/index.d.ts.map +0 -1
  244. package/dist/core/compaction/index.js +0 -7
  245. package/dist/core/compaction/index.js.map +0 -1
  246. package/dist/core/compaction/utils.d.ts +0 -38
  247. package/dist/core/compaction/utils.d.ts.map +0 -1
  248. package/dist/core/compaction/utils.js +0 -156
  249. package/dist/core/compaction/utils.js.map +0 -1
  250. package/dist/core/messages.d.ts +0 -124
  251. package/dist/core/messages.d.ts.map +0 -1
  252. package/dist/core/messages.js +0 -221
  253. package/dist/core/messages.js.map +0 -1
  254. package/dist/core/tools/browser-continue.d.ts.map +0 -1
  255. package/dist/core/tools/browser-continue.js.map +0 -1
  256. package/dist/core/tools/browser-run.d.ts.map +0 -1
  257. package/dist/core/tools/browser-run.js.map +0 -1
  258. package/dist/core/tools/browsertools-shared.d.ts.map +0 -1
  259. package/dist/core/tools/browsertools-shared.js.map +0 -1
  260. package/dist/core/tools/docedit.d.ts.map +0 -1
  261. package/dist/core/tools/docedit.js.map +0 -1
  262. package/dist/core/tools/docgrep.d.ts.map +0 -1
  263. package/dist/core/tools/docgrep.js.map +0 -1
  264. package/dist/core/tools/docpeek.d.ts.map +0 -1
  265. package/dist/core/tools/docread.d.ts.map +0 -1
  266. package/dist/core/tools/docread.js.map +0 -1
  267. package/dist/core/tools/docscan.d.ts.map +0 -1
  268. package/dist/core/tools/docscan.js.map +0 -1
  269. package/dist/core/tools/docwrite.d.ts.map +0 -1
  270. package/dist/core/tools/docwrite.js.map +0 -1
  271. package/dist/core/tools/output-compression.d.ts +0 -53
  272. package/dist/core/tools/output-compression.d.ts.map +0 -1
  273. package/dist/core/tools/output-compression.js +0 -392
  274. package/dist/core/tools/output-compression.js.map +0 -1
  275. package/dist/modes/interactive/components/armin.d.ts +0 -34
  276. package/dist/modes/interactive/components/armin.d.ts.map +0 -1
  277. package/dist/modes/interactive/components/armin.js +0 -333
  278. package/dist/modes/interactive/components/armin.js.map +0 -1
  279. package/dist/modes/interactive/components/daxnuts.d.ts +0 -23
  280. package/dist/modes/interactive/components/daxnuts.d.ts.map +0 -1
  281. package/dist/modes/interactive/components/daxnuts.js +0 -140
  282. package/dist/modes/interactive/components/daxnuts.js.map +0 -1
  283. package/dist/modes/interactive/components/voice-panel.d.ts.map +0 -1
  284. package/dist/modes/interactive/components/voice-panel.js.map +0 -1
  285. package/dist/modes/interactive/voice-transcribe.d.ts.map +0 -1
  286. package/dist/modes/interactive/voice-transcribe.js.map +0 -1
  287. /package/dist/core/tools/{browsertools-shared.d.ts → browser/browsertools-shared.d.ts} +0 -0
  288. /package/dist/modes/interactive/{components → voice}/voice-panel.d.ts +0 -0
  289. /package/dist/modes/interactive/{components → voice}/voice-panel.js +0 -0
@@ -0,0 +1,259 @@
1
+ /**
2
+ * Extension dialog primitives: the selector, options pane, confirm, text
3
+ * input, multi-line editor, and custom-component dialogs that swap into the
4
+ * editor slot (or an overlay) and restore the prompt editor when done.
5
+ * Extracted from interactive-mode.ts; consumed by the ExtensionUIContext.
6
+ */
7
+ import { AskOptionsComponent } from "./components/ask-options.js";
8
+ import { ExtensionEditorComponent } from "./components/extension-editor.js";
9
+ import { ExtensionInputComponent } from "./components/extension-input.js";
10
+ import { ExtensionSelectorComponent } from "./components/extension-selector.js";
11
+ import { theme } from "./theme/theme.js";
12
+ export class ExtensionDialogs {
13
+ deps;
14
+ selector = undefined;
15
+ input = undefined;
16
+ askOptionsPane = undefined;
17
+ editorDialog = undefined;
18
+ constructor(deps) {
19
+ this.deps = deps;
20
+ }
21
+ /** True while the options pane is on screen (used to queue team approvals). */
22
+ isAskOptionsOpen() {
23
+ return this.askOptionsPane !== undefined;
24
+ }
25
+ /** Hide whatever dialog is open and restore the prompt editor. */
26
+ reset() {
27
+ if (this.selector) {
28
+ this.hideSelector();
29
+ }
30
+ if (this.input) {
31
+ this.hideInput();
32
+ }
33
+ if (this.askOptionsPane) {
34
+ this.hideAskOptions();
35
+ }
36
+ if (this.editorDialog) {
37
+ this.hideEditor();
38
+ }
39
+ }
40
+ restoreEditor() {
41
+ const editor = this.deps.getEditor();
42
+ this.deps.editorContainer.clear();
43
+ this.deps.editorContainer.addChild(editor);
44
+ this.deps.ui.setFocus(editor);
45
+ this.deps.ui.requestRender();
46
+ }
47
+ /**
48
+ * Show a selector for extensions.
49
+ */
50
+ showSelector(title, options, opts) {
51
+ return new Promise((resolve) => {
52
+ if (opts?.signal?.aborted) {
53
+ resolve(undefined);
54
+ return;
55
+ }
56
+ const onAbort = () => {
57
+ this.hideSelector();
58
+ resolve(undefined);
59
+ };
60
+ opts?.signal?.addEventListener("abort", onAbort, { once: true });
61
+ this.selector = new ExtensionSelectorComponent(title, options, (option) => {
62
+ opts?.signal?.removeEventListener("abort", onAbort);
63
+ this.hideSelector();
64
+ resolve(option);
65
+ }, () => {
66
+ opts?.signal?.removeEventListener("abort", onAbort);
67
+ this.hideSelector();
68
+ resolve(undefined);
69
+ }, { tui: this.deps.ui, timeout: opts?.timeout });
70
+ this.deps.editorContainer.clear();
71
+ this.deps.editorContainer.addChild(this.selector);
72
+ this.deps.ui.setFocus(this.selector);
73
+ this.deps.ui.requestRender();
74
+ });
75
+ }
76
+ /**
77
+ * Hide the extension selector.
78
+ */
79
+ hideSelector() {
80
+ this.selector?.dispose();
81
+ this.selector = undefined;
82
+ this.restoreEditor();
83
+ }
84
+ /**
85
+ * Show the options pane — the agent asking the user one or more questions.
86
+ * Resolves with one answer per question, or undefined if skipped/aborted.
87
+ */
88
+ showAskOptions(questions, opts) {
89
+ return new Promise((resolve) => {
90
+ if (!questions.length || opts?.signal?.aborted) {
91
+ resolve(undefined);
92
+ return;
93
+ }
94
+ const onAbort = () => {
95
+ this.hideAskOptions();
96
+ resolve(undefined);
97
+ };
98
+ opts?.signal?.addEventListener("abort", onAbort, { once: true });
99
+ this.askOptionsPane = new AskOptionsComponent(questions, (answers) => {
100
+ opts?.signal?.removeEventListener("abort", onAbort);
101
+ this.hideAskOptions();
102
+ resolve(answers);
103
+ }, () => {
104
+ opts?.signal?.removeEventListener("abort", onAbort);
105
+ this.hideAskOptions();
106
+ resolve(undefined);
107
+ });
108
+ this.deps.editorContainer.clear();
109
+ this.deps.editorContainer.addChild(this.askOptionsPane);
110
+ this.deps.ui.setFocus(this.askOptionsPane);
111
+ this.deps.ui.requestRender();
112
+ });
113
+ }
114
+ /**
115
+ * Hide the options pane and restore the editor.
116
+ */
117
+ hideAskOptions() {
118
+ if (!this.askOptionsPane)
119
+ return;
120
+ this.askOptionsPane = undefined;
121
+ this.restoreEditor();
122
+ }
123
+ /**
124
+ * Show a confirmation dialog for extensions.
125
+ */
126
+ async confirm(title, message, opts) {
127
+ const result = await this.showSelector(`${title}\n${message}`, ["Yes", "No"], opts);
128
+ return result === "Yes";
129
+ }
130
+ /**
131
+ * Show a text input for extensions.
132
+ */
133
+ showInput(title, placeholder, opts) {
134
+ return new Promise((resolve) => {
135
+ if (opts?.signal?.aborted) {
136
+ resolve(undefined);
137
+ return;
138
+ }
139
+ const onAbort = () => {
140
+ this.hideInput();
141
+ resolve(undefined);
142
+ };
143
+ opts?.signal?.addEventListener("abort", onAbort, { once: true });
144
+ this.input = new ExtensionInputComponent(title, placeholder, (value) => {
145
+ opts?.signal?.removeEventListener("abort", onAbort);
146
+ this.hideInput();
147
+ resolve(value);
148
+ }, () => {
149
+ opts?.signal?.removeEventListener("abort", onAbort);
150
+ this.hideInput();
151
+ resolve(undefined);
152
+ }, { tui: this.deps.ui, timeout: opts?.timeout });
153
+ this.deps.editorContainer.clear();
154
+ this.deps.editorContainer.addChild(this.input);
155
+ this.deps.ui.setFocus(this.input);
156
+ this.deps.ui.requestRender();
157
+ });
158
+ }
159
+ /**
160
+ * Hide the extension input.
161
+ */
162
+ hideInput() {
163
+ this.input?.dispose();
164
+ this.input = undefined;
165
+ this.restoreEditor();
166
+ }
167
+ /**
168
+ * Show a multi-line editor for extensions (with Ctrl+G support).
169
+ */
170
+ showEditor(title, prefill) {
171
+ return new Promise((resolve) => {
172
+ this.editorDialog = new ExtensionEditorComponent(this.deps.ui, this.deps.keybindings, title, prefill, (value) => {
173
+ this.hideEditor();
174
+ resolve(value);
175
+ }, () => {
176
+ this.hideEditor();
177
+ resolve(undefined);
178
+ });
179
+ this.deps.editorContainer.clear();
180
+ this.deps.editorContainer.addChild(this.editorDialog);
181
+ this.deps.ui.setFocus(this.editorDialog);
182
+ this.deps.ui.requestRender();
183
+ });
184
+ }
185
+ /**
186
+ * Hide the extension editor.
187
+ */
188
+ hideEditor() {
189
+ this.editorDialog = undefined;
190
+ this.restoreEditor();
191
+ }
192
+ /** Show a custom component with keyboard focus. Overlay mode renders on top of existing content. */
193
+ async showCustom(factory, options) {
194
+ const savedText = this.deps.getEditor().getText();
195
+ const isOverlay = options?.overlay ?? false;
196
+ const restoreEditorWithText = () => {
197
+ this.restoreEditor();
198
+ this.deps.getEditor().setText(savedText);
199
+ };
200
+ return new Promise((resolve, reject) => {
201
+ let component;
202
+ let closed = false;
203
+ const close = (result) => {
204
+ if (closed)
205
+ return;
206
+ closed = true;
207
+ if (isOverlay)
208
+ this.deps.ui.hideOverlay();
209
+ else
210
+ restoreEditorWithText();
211
+ // Note: both branches above already call requestRender
212
+ resolve(result);
213
+ try {
214
+ component?.dispose?.();
215
+ }
216
+ catch {
217
+ /* ignore dispose errors */
218
+ }
219
+ };
220
+ Promise.resolve(factory(this.deps.ui, theme, this.deps.keybindings, close))
221
+ .then((c) => {
222
+ if (closed)
223
+ return;
224
+ component = c;
225
+ if (isOverlay) {
226
+ // Resolve overlay options - can be static or dynamic function
227
+ const resolveOptions = () => {
228
+ if (options?.overlayOptions) {
229
+ const opts = typeof options.overlayOptions === "function"
230
+ ? options.overlayOptions()
231
+ : options.overlayOptions;
232
+ return opts;
233
+ }
234
+ // Fallback: use component's width property if available
235
+ const w = component.width;
236
+ return w ? { width: w } : undefined;
237
+ };
238
+ const handle = this.deps.ui.showOverlay(component, resolveOptions());
239
+ // Expose handle to caller for visibility control
240
+ options?.onHandle?.(handle);
241
+ }
242
+ else {
243
+ this.deps.editorContainer.clear();
244
+ this.deps.editorContainer.addChild(component);
245
+ this.deps.ui.setFocus(component);
246
+ this.deps.ui.requestRender();
247
+ }
248
+ })
249
+ .catch((err) => {
250
+ if (closed)
251
+ return;
252
+ if (!isOverlay)
253
+ restoreEditorWithText();
254
+ reject(err);
255
+ });
256
+ });
257
+ }
258
+ }
259
+ //# sourceMappingURL=extension-dialogs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension-dialogs.js","sourceRoot":"","sources":["../../../src/modes/interactive/extension-dialogs.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Extension dialog primitives: the selector, options pane, confirm, text\n * input, multi-line editor, and custom-component dialogs that swap into the\n * editor slot (or an overlay) and restore the prompt editor when done.\n * Extracted from interactive-mode.ts; consumed by the ExtensionUIContext.\n */\n\nimport type { Component, Container, OverlayHandle, OverlayOptions, TUI } from \"@kolisachint/hoocode-tui\";\nimport type { AskQuestion, ExtensionUIDialogOptions } from \"../../core/extensions/index.js\";\nimport type { KeybindingsManager } from \"../../core/keybindings.js\";\nimport { AskOptionsComponent } from \"./components/ask-options.js\";\nimport { ExtensionEditorComponent } from \"./components/extension-editor.js\";\nimport { ExtensionInputComponent } from \"./components/extension-input.js\";\nimport { ExtensionSelectorComponent } from \"./components/extension-selector.js\";\nimport { type Theme, theme } from \"./theme/theme.js\";\n\n/** The slice of the interactive mode the dialogs render into. */\nexport interface ExtensionDialogsDeps {\n\tui: TUI;\n\teditorContainer: Container;\n\tkeybindings: KeybindingsManager;\n\t/** The prompt editor (read at call time; the editor can be swapped). */\n\tgetEditor(): Component & { getText(): string; setText(text: string): void };\n}\n\nexport class ExtensionDialogs {\n\tprivate selector: ExtensionSelectorComponent | undefined = undefined;\n\tprivate input: ExtensionInputComponent | undefined = undefined;\n\tprivate askOptionsPane: AskOptionsComponent | undefined = undefined;\n\tprivate editorDialog: ExtensionEditorComponent | undefined = undefined;\n\n\tconstructor(private readonly deps: ExtensionDialogsDeps) {}\n\n\t/** True while the options pane is on screen (used to queue team approvals). */\n\tisAskOptionsOpen(): boolean {\n\t\treturn this.askOptionsPane !== undefined;\n\t}\n\n\t/** Hide whatever dialog is open and restore the prompt editor. */\n\treset(): void {\n\t\tif (this.selector) {\n\t\t\tthis.hideSelector();\n\t\t}\n\t\tif (this.input) {\n\t\t\tthis.hideInput();\n\t\t}\n\t\tif (this.askOptionsPane) {\n\t\t\tthis.hideAskOptions();\n\t\t}\n\t\tif (this.editorDialog) {\n\t\t\tthis.hideEditor();\n\t\t}\n\t}\n\n\tprivate restoreEditor(): void {\n\t\tconst editor = this.deps.getEditor();\n\t\tthis.deps.editorContainer.clear();\n\t\tthis.deps.editorContainer.addChild(editor);\n\t\tthis.deps.ui.setFocus(editor);\n\t\tthis.deps.ui.requestRender();\n\t}\n\n\t/**\n\t * Show a selector for extensions.\n\t */\n\tshowSelector(title: string, options: string[], opts?: ExtensionUIDialogOptions): Promise<string | undefined> {\n\t\treturn new Promise((resolve) => {\n\t\t\tif (opts?.signal?.aborted) {\n\t\t\t\tresolve(undefined);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst onAbort = () => {\n\t\t\t\tthis.hideSelector();\n\t\t\t\tresolve(undefined);\n\t\t\t};\n\t\t\topts?.signal?.addEventListener(\"abort\", onAbort, { once: true });\n\n\t\t\tthis.selector = new ExtensionSelectorComponent(\n\t\t\t\ttitle,\n\t\t\t\toptions,\n\t\t\t\t(option) => {\n\t\t\t\t\topts?.signal?.removeEventListener(\"abort\", onAbort);\n\t\t\t\t\tthis.hideSelector();\n\t\t\t\t\tresolve(option);\n\t\t\t\t},\n\t\t\t\t() => {\n\t\t\t\t\topts?.signal?.removeEventListener(\"abort\", onAbort);\n\t\t\t\t\tthis.hideSelector();\n\t\t\t\t\tresolve(undefined);\n\t\t\t\t},\n\t\t\t\t{ tui: this.deps.ui, timeout: opts?.timeout },\n\t\t\t);\n\n\t\t\tthis.deps.editorContainer.clear();\n\t\t\tthis.deps.editorContainer.addChild(this.selector);\n\t\t\tthis.deps.ui.setFocus(this.selector);\n\t\t\tthis.deps.ui.requestRender();\n\t\t});\n\t}\n\n\t/**\n\t * Hide the extension selector.\n\t */\n\thideSelector(): void {\n\t\tthis.selector?.dispose();\n\t\tthis.selector = undefined;\n\t\tthis.restoreEditor();\n\t}\n\n\t/**\n\t * Show the options pane — the agent asking the user one or more questions.\n\t * Resolves with one answer per question, or undefined if skipped/aborted.\n\t */\n\tshowAskOptions(questions: AskQuestion[], opts?: ExtensionUIDialogOptions): Promise<string[] | undefined> {\n\t\treturn new Promise((resolve) => {\n\t\t\tif (!questions.length || opts?.signal?.aborted) {\n\t\t\t\tresolve(undefined);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst onAbort = () => {\n\t\t\t\tthis.hideAskOptions();\n\t\t\t\tresolve(undefined);\n\t\t\t};\n\t\t\topts?.signal?.addEventListener(\"abort\", onAbort, { once: true });\n\n\t\t\tthis.askOptionsPane = new AskOptionsComponent(\n\t\t\t\tquestions,\n\t\t\t\t(answers) => {\n\t\t\t\t\topts?.signal?.removeEventListener(\"abort\", onAbort);\n\t\t\t\t\tthis.hideAskOptions();\n\t\t\t\t\tresolve(answers);\n\t\t\t\t},\n\t\t\t\t() => {\n\t\t\t\t\topts?.signal?.removeEventListener(\"abort\", onAbort);\n\t\t\t\t\tthis.hideAskOptions();\n\t\t\t\t\tresolve(undefined);\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tthis.deps.editorContainer.clear();\n\t\t\tthis.deps.editorContainer.addChild(this.askOptionsPane);\n\t\t\tthis.deps.ui.setFocus(this.askOptionsPane);\n\t\t\tthis.deps.ui.requestRender();\n\t\t});\n\t}\n\n\t/**\n\t * Hide the options pane and restore the editor.\n\t */\n\thideAskOptions(): void {\n\t\tif (!this.askOptionsPane) return;\n\t\tthis.askOptionsPane = undefined;\n\t\tthis.restoreEditor();\n\t}\n\n\t/**\n\t * Show a confirmation dialog for extensions.\n\t */\n\tasync confirm(title: string, message: string, opts?: ExtensionUIDialogOptions): Promise<boolean> {\n\t\tconst result = await this.showSelector(`${title}\\n${message}`, [\"Yes\", \"No\"], opts);\n\t\treturn result === \"Yes\";\n\t}\n\n\t/**\n\t * Show a text input for extensions.\n\t */\n\tshowInput(title: string, placeholder?: string, opts?: ExtensionUIDialogOptions): Promise<string | undefined> {\n\t\treturn new Promise((resolve) => {\n\t\t\tif (opts?.signal?.aborted) {\n\t\t\t\tresolve(undefined);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst onAbort = () => {\n\t\t\t\tthis.hideInput();\n\t\t\t\tresolve(undefined);\n\t\t\t};\n\t\t\topts?.signal?.addEventListener(\"abort\", onAbort, { once: true });\n\n\t\t\tthis.input = new ExtensionInputComponent(\n\t\t\t\ttitle,\n\t\t\t\tplaceholder,\n\t\t\t\t(value) => {\n\t\t\t\t\topts?.signal?.removeEventListener(\"abort\", onAbort);\n\t\t\t\t\tthis.hideInput();\n\t\t\t\t\tresolve(value);\n\t\t\t\t},\n\t\t\t\t() => {\n\t\t\t\t\topts?.signal?.removeEventListener(\"abort\", onAbort);\n\t\t\t\t\tthis.hideInput();\n\t\t\t\t\tresolve(undefined);\n\t\t\t\t},\n\t\t\t\t{ tui: this.deps.ui, timeout: opts?.timeout },\n\t\t\t);\n\n\t\t\tthis.deps.editorContainer.clear();\n\t\t\tthis.deps.editorContainer.addChild(this.input);\n\t\t\tthis.deps.ui.setFocus(this.input);\n\t\t\tthis.deps.ui.requestRender();\n\t\t});\n\t}\n\n\t/**\n\t * Hide the extension input.\n\t */\n\thideInput(): void {\n\t\tthis.input?.dispose();\n\t\tthis.input = undefined;\n\t\tthis.restoreEditor();\n\t}\n\n\t/**\n\t * Show a multi-line editor for extensions (with Ctrl+G support).\n\t */\n\tshowEditor(title: string, prefill?: string): Promise<string | undefined> {\n\t\treturn new Promise((resolve) => {\n\t\t\tthis.editorDialog = new ExtensionEditorComponent(\n\t\t\t\tthis.deps.ui,\n\t\t\t\tthis.deps.keybindings,\n\t\t\t\ttitle,\n\t\t\t\tprefill,\n\t\t\t\t(value) => {\n\t\t\t\t\tthis.hideEditor();\n\t\t\t\t\tresolve(value);\n\t\t\t\t},\n\t\t\t\t() => {\n\t\t\t\t\tthis.hideEditor();\n\t\t\t\t\tresolve(undefined);\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tthis.deps.editorContainer.clear();\n\t\t\tthis.deps.editorContainer.addChild(this.editorDialog);\n\t\t\tthis.deps.ui.setFocus(this.editorDialog);\n\t\t\tthis.deps.ui.requestRender();\n\t\t});\n\t}\n\n\t/**\n\t * Hide the extension editor.\n\t */\n\thideEditor(): void {\n\t\tthis.editorDialog = undefined;\n\t\tthis.restoreEditor();\n\t}\n\n\t/** Show a custom component with keyboard focus. Overlay mode renders on top of existing content. */\n\tasync showCustom<T>(\n\t\tfactory: (\n\t\t\ttui: TUI,\n\t\t\ttheme: Theme,\n\t\t\tkeybindings: KeybindingsManager,\n\t\t\tdone: (result: T) => void,\n\t\t) => (Component & { dispose?(): void }) | Promise<Component & { dispose?(): void }>,\n\t\toptions?: {\n\t\t\toverlay?: boolean;\n\t\t\toverlayOptions?: OverlayOptions | (() => OverlayOptions);\n\t\t\tonHandle?: (handle: OverlayHandle) => void;\n\t\t},\n\t): Promise<T> {\n\t\tconst savedText = this.deps.getEditor().getText();\n\t\tconst isOverlay = options?.overlay ?? false;\n\n\t\tconst restoreEditorWithText = () => {\n\t\t\tthis.restoreEditor();\n\t\t\tthis.deps.getEditor().setText(savedText);\n\t\t};\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tlet component: Component & { dispose?(): void };\n\t\t\tlet closed = false;\n\n\t\t\tconst close = (result: T) => {\n\t\t\t\tif (closed) return;\n\t\t\t\tclosed = true;\n\t\t\t\tif (isOverlay) this.deps.ui.hideOverlay();\n\t\t\t\telse restoreEditorWithText();\n\t\t\t\t// Note: both branches above already call requestRender\n\t\t\t\tresolve(result);\n\t\t\t\ttry {\n\t\t\t\t\tcomponent?.dispose?.();\n\t\t\t\t} catch {\n\t\t\t\t\t/* ignore dispose errors */\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tPromise.resolve(factory(this.deps.ui, theme, this.deps.keybindings, close))\n\t\t\t\t.then((c) => {\n\t\t\t\t\tif (closed) return;\n\t\t\t\t\tcomponent = c;\n\t\t\t\t\tif (isOverlay) {\n\t\t\t\t\t\t// Resolve overlay options - can be static or dynamic function\n\t\t\t\t\t\tconst resolveOptions = (): OverlayOptions | undefined => {\n\t\t\t\t\t\t\tif (options?.overlayOptions) {\n\t\t\t\t\t\t\t\tconst opts =\n\t\t\t\t\t\t\t\t\ttypeof options.overlayOptions === \"function\"\n\t\t\t\t\t\t\t\t\t\t? options.overlayOptions()\n\t\t\t\t\t\t\t\t\t\t: options.overlayOptions;\n\t\t\t\t\t\t\t\treturn opts;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// Fallback: use component's width property if available\n\t\t\t\t\t\t\tconst w = (component as { width?: number }).width;\n\t\t\t\t\t\t\treturn w ? { width: w } : undefined;\n\t\t\t\t\t\t};\n\t\t\t\t\t\tconst handle = this.deps.ui.showOverlay(component, resolveOptions());\n\t\t\t\t\t\t// Expose handle to caller for visibility control\n\t\t\t\t\t\toptions?.onHandle?.(handle);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.deps.editorContainer.clear();\n\t\t\t\t\t\tthis.deps.editorContainer.addChild(component);\n\t\t\t\t\t\tthis.deps.ui.setFocus(component);\n\t\t\t\t\t\tthis.deps.ui.requestRender();\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t\t.catch((err) => {\n\t\t\t\t\tif (closed) return;\n\t\t\t\t\tif (!isOverlay) restoreEditorWithText();\n\t\t\t\t\treject(err);\n\t\t\t\t});\n\t\t});\n\t}\n}\n"]}
@@ -33,15 +33,7 @@ export declare class InteractiveMode {
33
33
  private defaultEditor;
34
34
  private editor;
35
35
  private editorComponentFactory;
36
- private voiceSession;
37
- private voiceDaemon;
38
- private voiceDaemonUnsupported;
39
- /** True while the voicetools binary is being resolved/downloaded before a session starts. */
40
- private voiceStarting;
41
- /** True while a capture (daemon or legacy) is in flight. */
42
- private voiceActive;
43
- /** The live multi-line status panel for the current capture (undefined when idle). */
44
- private voicePanel;
36
+ private voice;
45
37
  private autocompleteProvider;
46
38
  private autocompleteProviderWrappers;
47
39
  private fdPath;
@@ -85,23 +77,15 @@ export declare class InteractiveMode {
85
77
  private retryEscapeHandler?;
86
78
  private compactionQueuedMessages;
87
79
  private shutdownRequested;
88
- private extensionSelector;
89
- private extensionInput;
90
- private askOptions;
91
- private extensionEditor;
80
+ private dialogs;
92
81
  private extensionTerminalInputUnsubscribers;
93
- private extensionWidgetsAbove;
94
- private extensionWidgetsBelow;
82
+ private chrome;
95
83
  private widgetContainerAbove;
96
84
  private widgetContainerBelow;
97
85
  private taskPanel;
98
- private teamClient;
99
- private teamAttachPanel;
100
- private teamAttachHandle;
101
- private customFooter;
86
+ private teamFocus;
102
87
  private headerContainer;
103
88
  private builtInHeader;
104
- private customHeader;
105
89
  private get session();
106
90
  private _commandExecutor?;
107
91
  /**
@@ -131,37 +115,9 @@ export declare class InteractiveMode {
131
115
  * Initializes the UI, shows warnings, processes initial messages, and starts the interactive loop.
132
116
  */
133
117
  run(): Promise<void>;
134
- private checkForPackageUpdates;
135
- private checkTmuxKeyboardSetup;
136
- /**
137
- * Get changelog entries to display on startup.
138
- * Only shows new entries since last seen version, skips for resumed sessions.
139
- */
140
- private getChangelogForDisplay;
141
- private reportInstallTelemetry;
142
118
  private getMarkdownThemeWithSettings;
143
- private formatDisplayPath;
144
- private formatExtensionDisplayPath;
145
- private formatContextPath;
146
119
  private getStartupExpansionState;
147
- /**
148
- * Get a short path relative to the package root for display.
149
- */
150
- private getShortPath;
151
- private getCompactPathLabel;
152
- private getCompactPackageSourceLabel;
153
- private getCompactExtensionLabel;
154
- private getCompactDisplayPathSegments;
155
- private getCompactNonPackageExtensionLabel;
156
- private getCompactExtensionLabels;
157
- private getDisplaySourceInfo;
158
- private getScopeGroup;
159
- private isPackageSource;
160
- private buildScopeGroups;
161
- private formatScopeGroups;
162
- private findSourceInfoForPath;
163
- private formatPathWithSource;
164
- private formatDiagnostics;
120
+ /** Render the startup/reload resource listing (see resource-display.ts). */
165
121
  private showLoadedResources;
166
122
  private bindCurrentSessionExtensions;
167
123
  private applyRuntimeSettings;
@@ -186,67 +142,14 @@ export declare class InteractiveMode {
186
142
  private setWorkingVisible;
187
143
  private setWorkingIndicator;
188
144
  private setHiddenThinkingLabel;
189
- /**
190
- * Set an extension widget (string array or custom component).
191
- */
192
- private setExtensionWidget;
193
- private clearExtensionWidgets;
194
145
  private resetExtensionUI;
195
- private static readonly MAX_WIDGET_LINES;
196
- /**
197
- * Render all extension widgets to the widget container.
198
- */
199
- private renderWidgets;
200
- private renderWidgetContainer;
201
- /**
202
- * Set a custom footer component, or restore the built-in footer.
203
- */
204
- private setExtensionFooter;
205
- /**
206
- * Set a custom header component, or restore the built-in header.
207
- */
208
- private setExtensionHeader;
209
146
  private addExtensionTerminalInputListener;
210
147
  private clearExtensionTerminalInputListeners;
211
148
  /**
212
149
  * Create the ExtensionUIContext for extensions.
213
150
  */
214
151
  private createExtensionUIContext;
215
- /**
216
- * Show a selector for extensions.
217
- */
218
- private showExtensionSelector;
219
- /**
220
- * Hide the extension selector.
221
- */
222
- private hideExtensionSelector;
223
- /**
224
- * Show the options pane — the agent asking the user one or more questions.
225
- * Resolves with one answer per question, or undefined if skipped/aborted.
226
- */
227
- private showAskOptions;
228
- /**
229
- * Hide the options pane and restore the editor.
230
- */
231
- private hideAskOptions;
232
- private showExtensionConfirm;
233
152
  private promptForMissingSessionCwd;
234
- /**
235
- * Show a text input for extensions.
236
- */
237
- private showExtensionInput;
238
- /**
239
- * Hide the extension input.
240
- */
241
- private hideExtensionInput;
242
- /**
243
- * Show a multi-line editor for extensions (with Ctrl+G support).
244
- */
245
- private showExtensionEditor;
246
- /**
247
- * Hide the extension editor.
248
- */
249
- private hideExtensionEditor;
250
153
  /**
251
154
  * Set a custom editor component from an extension.
252
155
  * Pass undefined to restore the default editor.
@@ -256,7 +159,6 @@ export declare class InteractiveMode {
256
159
  * Show a notification for extensions.
257
160
  */
258
161
  private showExtensionNotify;
259
- private showExtensionCustom;
260
162
  /**
261
163
  * Show an extension error in the UI.
262
164
  */
@@ -265,29 +167,16 @@ export declare class InteractiveMode {
265
167
  private handleClipboardImagePaste;
266
168
  /**
267
169
  * Wire a hooteams connection into the TUI. Called by main.ts when `--team`
268
- * is set, before run(). Enables team focus (app.team.focus), nudging (n),
269
- * the attach side panel (a) on the task panel's teams view, and approval
270
- * gates: task_paused events (and gates already pending on the server)
271
- * surface inline in the attach panel when it shows the paused role,
272
- * otherwise in the options pane; the answer goes back over
273
- * POST /tasks/:id/resume.
170
+ * is set, before run(). See TeamFocusController for the feature itself.
274
171
  */
275
172
  attachTeamClient(client: TeamViewConnection): void;
276
- private presentTeamApproval;
277
- /** Move keyboard focus to the task panel's team roster. */
278
- private enterTeamFocus;
279
- /** Leave team focus: detach any side panel and return focus to the editor. */
280
- private exitTeamFocus;
281
173
  /**
282
- * Inline nudge editor for a role (n in team focus or while attached).
283
- * Swaps the prompt editor for a one-line input; submit fires POST /steer in
284
- * the background (the REPL and team focus are never blocked on the network).
174
+ * Built-in slash commands dispatched by the editor submit handler.
175
+ * `withArgs` commands also match "/name <args>" and receive the full text.
176
+ * Each handler keeps its own editor-clearing order (before vs after the
177
+ * await) — some commands must show their UI before the prompt is wiped.
285
178
  */
286
- private showTeamNudgeInput;
287
- /** Open the attach side panel for a role (a in team focus). */
288
- private showTeamAttach;
289
- /** Detach the side panel; the role keeps running. Safe to call when closed. */
290
- private closeTeamAttach;
179
+ private createBuiltInSlashCommands;
291
180
  private setupEditorSubmitHandler;
292
181
  private subscribeToAgent;
293
182
  private handleEvent;
@@ -299,43 +188,6 @@ export declare class InteractiveMode {
299
188
  * If multiple status messages are emitted back-to-back (without anything else being added to the chat),
300
189
  * we update the previous status line instead of appending new ones to avoid log spam.
301
190
  */
302
- /**
303
- * Toggle voice-to-text capture.
304
- *
305
- * Prefers a persistent `voicetools serve` daemon: the first press probes for
306
- * support and (if found) loads models once, showing a "warming up" spinner;
307
- * every later press reuses the already-warm daemon and jumps straight to
308
- * Listening. Binaries without `serve` support fall back to spawning
309
- * `voicetools transcribe` per press, same as before. Pressing the shortcut
310
- * again while listening (or while still warming up) cancels.
311
- */
312
- private toggleVoiceTranscribe;
313
- /**
314
- * Build the (stable, reused-across-captures) handlers for the daemon.
315
- *
316
- * Every handler bails out once `voiceActive` is false: CANCEL is a soft
317
- * request (unlike the legacy path's `proc.kill()`, it doesn't sever the
318
- * pipe), so the daemon can still have a trailing PARTIAL/FINAL/DONE for the
319
- * just-cancelled capture in flight when the user presses cancel. Without
320
- * this guard that stale text would land in the editor after the panel had
321
- * already collapsed.
322
- *
323
- * v0.1.4 serve streams `PARTIAL <full growing hypothesis>` (live preview,
324
- * never committed) and ends with a single `FINAL <complete text>` (the one
325
- * commit to the editor). `SEGMENT` is still handled for the legacy
326
- * transcribe path and any binary that streams committed chunks directly.
327
- */
328
- private buildVoiceDaemonHandlers;
329
- /** Inject decoded text into the editor via bracketed paste (with a trailing space). */
330
- private commitVoiceText;
331
- private beginDaemonVoiceCapture;
332
- private beginLegacyVoiceCapture;
333
- private resolveVoiceBin;
334
- /** Create (or reuse) the voice panel and mount it in the status container. */
335
- private showVoicePanel;
336
- private showVoiceWarming;
337
- /** Collapse the voice panel back to nothing (idle) and stop its animation. */
338
- private resetVoiceUI;
339
191
  private showStatus;
340
192
  private addMessageToChat;
341
193
  /**
@@ -425,8 +277,6 @@ export declare class InteractiveMode {
425
277
  * Get capitalized display string for an app keybinding action.
426
278
  */
427
279
  private getAppKeyDisplay;
428
- private handleDaxnuts;
429
- private checkDaxnutsEasterEgg;
430
280
  private handleBashCommand;
431
281
  private handleCompactCommand;
432
282
  stop(): void;