@openeryc/pi-coding-agent 0.75.25 → 0.75.27

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 (314) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/cli/config-selector.d.ts +1 -13
  3. package/dist/cli/config-selector.d.ts.map +1 -1
  4. package/dist/cli/config-selector.js +4 -29
  5. package/dist/cli/config-selector.js.map +1 -1
  6. package/dist/cli/list-models.d.ts.map +1 -1
  7. package/dist/cli/list-models.js +1 -1
  8. package/dist/cli/list-models.js.map +1 -1
  9. package/dist/core/agent-session.d.ts +1 -0
  10. package/dist/core/agent-session.d.ts.map +1 -1
  11. package/dist/core/agent-session.js +20 -0
  12. package/dist/core/agent-session.js.map +1 -1
  13. package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
  14. package/dist/core/export-html/tool-renderer.js.map +1 -1
  15. package/dist/core/extensions/loader.d.ts.map +1 -1
  16. package/dist/core/extensions/loader.js +1 -1
  17. package/dist/core/extensions/loader.js.map +1 -1
  18. package/dist/core/extensions/runner.d.ts +1 -1
  19. package/dist/core/extensions/runner.d.ts.map +1 -1
  20. package/dist/core/extensions/runner.js +1 -1
  21. package/dist/core/extensions/runner.js.map +1 -1
  22. package/dist/core/extensions/types.d.ts +1 -1
  23. package/dist/core/extensions/types.d.ts.map +1 -1
  24. package/dist/core/extensions/types.js.map +1 -1
  25. package/dist/core/keybindings.d.ts +7 -135
  26. package/dist/core/keybindings.d.ts.map +1 -1
  27. package/dist/core/keybindings.js +1 -1
  28. package/dist/core/keybindings.js.map +1 -1
  29. package/dist/core/mcp/client.d.ts +38 -0
  30. package/dist/core/mcp/client.d.ts.map +1 -0
  31. package/dist/core/mcp/client.js +88 -0
  32. package/dist/core/mcp/client.js.map +1 -0
  33. package/dist/core/mcp/index.d.ts +3 -0
  34. package/dist/core/mcp/index.d.ts.map +1 -0
  35. package/dist/core/mcp/index.js +3 -0
  36. package/dist/core/mcp/index.js.map +1 -0
  37. package/dist/core/mcp/manager.d.ts +11 -0
  38. package/dist/core/mcp/manager.d.ts.map +1 -0
  39. package/dist/core/mcp/manager.js +99 -0
  40. package/dist/core/mcp/manager.js.map +1 -0
  41. package/dist/core/settings-manager.d.ts +10 -0
  42. package/dist/core/settings-manager.d.ts.map +1 -1
  43. package/dist/core/settings-manager.js +3 -0
  44. package/dist/core/settings-manager.js.map +1 -1
  45. package/dist/core/tools/bash.d.ts.map +1 -1
  46. package/dist/core/tools/bash.js +1 -1
  47. package/dist/core/tools/bash.js.map +1 -1
  48. package/dist/core/tools/edit.d.ts +1 -1
  49. package/dist/core/tools/edit.d.ts.map +1 -1
  50. package/dist/core/tools/edit.js +1 -1
  51. package/dist/core/tools/edit.js.map +1 -1
  52. package/dist/core/tools/find.d.ts.map +1 -1
  53. package/dist/core/tools/find.js +1 -1
  54. package/dist/core/tools/find.js.map +1 -1
  55. package/dist/core/tools/grep.d.ts.map +1 -1
  56. package/dist/core/tools/grep.js +1 -1
  57. package/dist/core/tools/grep.js.map +1 -1
  58. package/dist/core/tools/index.d.ts +3 -1
  59. package/dist/core/tools/index.d.ts.map +1 -1
  60. package/dist/core/tools/index.js +27 -1
  61. package/dist/core/tools/index.js.map +1 -1
  62. package/dist/core/tools/ls.d.ts.map +1 -1
  63. package/dist/core/tools/ls.js +1 -1
  64. package/dist/core/tools/ls.js.map +1 -1
  65. package/dist/core/tools/read.d.ts.map +1 -1
  66. package/dist/core/tools/read.js +1 -1
  67. package/dist/core/tools/read.js.map +1 -1
  68. package/dist/core/tools/render-utils.d.ts.map +1 -1
  69. package/dist/core/tools/render-utils.js +1 -1
  70. package/dist/core/tools/render-utils.js.map +1 -1
  71. package/dist/core/tools/web-fetch.d.ts +15 -0
  72. package/dist/core/tools/web-fetch.d.ts.map +1 -0
  73. package/dist/core/tools/web-fetch.js +52 -0
  74. package/dist/core/tools/web-fetch.js.map +1 -0
  75. package/dist/core/tools/web-search.d.ts +18 -0
  76. package/dist/core/tools/web-search.d.ts.map +1 -0
  77. package/dist/core/tools/web-search.js +83 -0
  78. package/dist/core/tools/web-search.js.map +1 -0
  79. package/dist/core/tools/write.d.ts.map +1 -1
  80. package/dist/core/tools/write.js +1 -1
  81. package/dist/core/tools/write.js.map +1 -1
  82. package/dist/core/tui-stubs.d.ts +95 -0
  83. package/dist/core/tui-stubs.d.ts.map +1 -0
  84. package/dist/core/tui-stubs.js +90 -0
  85. package/dist/core/tui-stubs.js.map +1 -0
  86. package/dist/index.d.ts +5 -3
  87. package/dist/index.d.ts.map +1 -1
  88. package/dist/index.js +7 -5
  89. package/dist/index.js.map +1 -1
  90. package/dist/main.d.ts.map +1 -1
  91. package/dist/main.js +14 -106
  92. package/dist/main.js.map +1 -1
  93. package/dist/modes/index.d.ts +0 -4
  94. package/dist/modes/index.d.ts.map +1 -1
  95. package/dist/modes/index.js +0 -4
  96. package/dist/modes/index.js.map +1 -1
  97. package/dist/modes/interactive/components/diff.d.ts +1 -8
  98. package/dist/modes/interactive/components/diff.d.ts.map +1 -1
  99. package/dist/modes/interactive/components/diff.js +2 -131
  100. package/dist/modes/interactive/components/diff.js.map +1 -1
  101. package/dist/modes/interactive/components/keybinding-hints.d.ts +2 -12
  102. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
  103. package/dist/modes/interactive/components/keybinding-hints.js +4 -33
  104. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
  105. package/dist/modes/interactive/components/visual-truncate.d.ts +1 -19
  106. package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -1
  107. package/dist/modes/interactive/components/visual-truncate.js +4 -31
  108. package/dist/modes/interactive/components/visual-truncate.js.map +1 -1
  109. package/dist/modes/interactive/theme/theme.d.ts +27 -89
  110. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  111. package/dist/modes/interactive/theme/theme.js +44 -992
  112. package/dist/modes/interactive/theme/theme.js.map +1 -1
  113. package/dist/package-manager-cli.d.ts.map +1 -1
  114. package/dist/package-manager-cli.js +1 -1
  115. package/dist/package-manager-cli.js.map +1 -1
  116. package/npm-shrinkwrap.json +240 -246
  117. package/package.json +6 -7
  118. package/dist/cli/session-picker.d.ts +0 -9
  119. package/dist/cli/session-picker.d.ts.map +0 -1
  120. package/dist/cli/session-picker.js +0 -35
  121. package/dist/cli/session-picker.js.map +0 -1
  122. package/dist/modes/interactive/assets/clankolas.png +0 -0
  123. package/dist/modes/interactive/components/armin.d.ts +0 -34
  124. package/dist/modes/interactive/components/armin.d.ts.map +0 -1
  125. package/dist/modes/interactive/components/armin.js +0 -333
  126. package/dist/modes/interactive/components/armin.js.map +0 -1
  127. package/dist/modes/interactive/components/assistant-message.d.ts +0 -20
  128. package/dist/modes/interactive/components/assistant-message.d.ts.map +0 -1
  129. package/dist/modes/interactive/components/assistant-message.js +0 -121
  130. package/dist/modes/interactive/components/assistant-message.js.map +0 -1
  131. package/dist/modes/interactive/components/bash-execution.d.ts +0 -34
  132. package/dist/modes/interactive/components/bash-execution.d.ts.map +0 -1
  133. package/dist/modes/interactive/components/bash-execution.js +0 -175
  134. package/dist/modes/interactive/components/bash-execution.js.map +0 -1
  135. package/dist/modes/interactive/components/bordered-loader.d.ts +0 -16
  136. package/dist/modes/interactive/components/bordered-loader.d.ts.map +0 -1
  137. package/dist/modes/interactive/components/bordered-loader.js +0 -54
  138. package/dist/modes/interactive/components/bordered-loader.js.map +0 -1
  139. package/dist/modes/interactive/components/branch-summary-message.d.ts +0 -16
  140. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +0 -1
  141. package/dist/modes/interactive/components/branch-summary-message.js +0 -44
  142. package/dist/modes/interactive/components/branch-summary-message.js.map +0 -1
  143. package/dist/modes/interactive/components/compaction-summary-message.d.ts +0 -16
  144. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +0 -1
  145. package/dist/modes/interactive/components/compaction-summary-message.js +0 -45
  146. package/dist/modes/interactive/components/compaction-summary-message.js.map +0 -1
  147. package/dist/modes/interactive/components/config-selector.d.ts +0 -71
  148. package/dist/modes/interactive/components/config-selector.d.ts.map +0 -1
  149. package/dist/modes/interactive/components/config-selector.js +0 -506
  150. package/dist/modes/interactive/components/config-selector.js.map +0 -1
  151. package/dist/modes/interactive/components/countdown-timer.d.ts +0 -14
  152. package/dist/modes/interactive/components/countdown-timer.d.ts.map +0 -1
  153. package/dist/modes/interactive/components/countdown-timer.js +0 -33
  154. package/dist/modes/interactive/components/countdown-timer.js.map +0 -1
  155. package/dist/modes/interactive/components/custom-editor.d.ts +0 -21
  156. package/dist/modes/interactive/components/custom-editor.d.ts.map +0 -1
  157. package/dist/modes/interactive/components/custom-editor.js +0 -70
  158. package/dist/modes/interactive/components/custom-editor.js.map +0 -1
  159. package/dist/modes/interactive/components/custom-message.d.ts +0 -20
  160. package/dist/modes/interactive/components/custom-message.d.ts.map +0 -1
  161. package/dist/modes/interactive/components/custom-message.js +0 -79
  162. package/dist/modes/interactive/components/custom-message.js.map +0 -1
  163. package/dist/modes/interactive/components/daxnuts.d.ts +0 -23
  164. package/dist/modes/interactive/components/daxnuts.d.ts.map +0 -1
  165. package/dist/modes/interactive/components/daxnuts.js +0 -140
  166. package/dist/modes/interactive/components/daxnuts.js.map +0 -1
  167. package/dist/modes/interactive/components/dynamic-border.d.ts +0 -15
  168. package/dist/modes/interactive/components/dynamic-border.d.ts.map +0 -1
  169. package/dist/modes/interactive/components/dynamic-border.js +0 -21
  170. package/dist/modes/interactive/components/dynamic-border.js.map +0 -1
  171. package/dist/modes/interactive/components/earendil-announcement.d.ts +0 -5
  172. package/dist/modes/interactive/components/earendil-announcement.d.ts.map +0 -1
  173. package/dist/modes/interactive/components/earendil-announcement.js +0 -40
  174. package/dist/modes/interactive/components/earendil-announcement.js.map +0 -1
  175. package/dist/modes/interactive/components/extension-editor.d.ts +0 -20
  176. package/dist/modes/interactive/components/extension-editor.d.ts.map +0 -1
  177. package/dist/modes/interactive/components/extension-editor.js +0 -119
  178. package/dist/modes/interactive/components/extension-editor.js.map +0 -1
  179. package/dist/modes/interactive/components/extension-input.d.ts +0 -23
  180. package/dist/modes/interactive/components/extension-input.d.ts.map +0 -1
  181. package/dist/modes/interactive/components/extension-input.js +0 -61
  182. package/dist/modes/interactive/components/extension-input.js.map +0 -1
  183. package/dist/modes/interactive/components/extension-selector.d.ts +0 -26
  184. package/dist/modes/interactive/components/extension-selector.d.ts.map +0 -1
  185. package/dist/modes/interactive/components/extension-selector.js +0 -83
  186. package/dist/modes/interactive/components/extension-selector.js.map +0 -1
  187. package/dist/modes/interactive/components/footer.d.ts +0 -27
  188. package/dist/modes/interactive/components/footer.d.ts.map +0 -1
  189. package/dist/modes/interactive/components/footer.js +0 -201
  190. package/dist/modes/interactive/components/footer.js.map +0 -1
  191. package/dist/modes/interactive/components/index.d.ts +0 -32
  192. package/dist/modes/interactive/components/index.d.ts.map +0 -1
  193. package/dist/modes/interactive/components/index.js +0 -33
  194. package/dist/modes/interactive/components/index.js.map +0 -1
  195. package/dist/modes/interactive/components/login-dialog.d.ts +0 -46
  196. package/dist/modes/interactive/components/login-dialog.d.ts.map +0 -1
  197. package/dist/modes/interactive/components/login-dialog.js +0 -160
  198. package/dist/modes/interactive/components/login-dialog.js.map +0 -1
  199. package/dist/modes/interactive/components/model-selector.d.ts +0 -47
  200. package/dist/modes/interactive/components/model-selector.d.ts.map +0 -1
  201. package/dist/modes/interactive/components/model-selector.js +0 -278
  202. package/dist/modes/interactive/components/model-selector.js.map +0 -1
  203. package/dist/modes/interactive/components/oauth-selector.d.ts +0 -31
  204. package/dist/modes/interactive/components/oauth-selector.d.ts.map +0 -1
  205. package/dist/modes/interactive/components/oauth-selector.js +0 -165
  206. package/dist/modes/interactive/components/oauth-selector.js.map +0 -1
  207. package/dist/modes/interactive/components/scoped-models-selector.d.ts +0 -42
  208. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +0 -1
  209. package/dist/modes/interactive/components/scoped-models-selector.js +0 -290
  210. package/dist/modes/interactive/components/scoped-models-selector.js.map +0 -1
  211. package/dist/modes/interactive/components/session-selector-search.d.ts +0 -23
  212. package/dist/modes/interactive/components/session-selector-search.d.ts.map +0 -1
  213. package/dist/modes/interactive/components/session-selector-search.js +0 -155
  214. package/dist/modes/interactive/components/session-selector-search.js.map +0 -1
  215. package/dist/modes/interactive/components/session-selector.d.ts +0 -96
  216. package/dist/modes/interactive/components/session-selector.d.ts.map +0 -1
  217. package/dist/modes/interactive/components/session-selector.js +0 -861
  218. package/dist/modes/interactive/components/session-selector.js.map +0 -1
  219. package/dist/modes/interactive/components/settings-selector.d.ts +0 -69
  220. package/dist/modes/interactive/components/settings-selector.d.ts.map +0 -1
  221. package/dist/modes/interactive/components/settings-selector.js +0 -390
  222. package/dist/modes/interactive/components/settings-selector.js.map +0 -1
  223. package/dist/modes/interactive/components/show-images-selector.d.ts +0 -10
  224. package/dist/modes/interactive/components/show-images-selector.d.ts.map +0 -1
  225. package/dist/modes/interactive/components/show-images-selector.js +0 -39
  226. package/dist/modes/interactive/components/show-images-selector.js.map +0 -1
  227. package/dist/modes/interactive/components/skill-invocation-message.d.ts +0 -17
  228. package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +0 -1
  229. package/dist/modes/interactive/components/skill-invocation-message.js +0 -47
  230. package/dist/modes/interactive/components/skill-invocation-message.js.map +0 -1
  231. package/dist/modes/interactive/components/theme-selector.d.ts +0 -11
  232. package/dist/modes/interactive/components/theme-selector.d.ts.map +0 -1
  233. package/dist/modes/interactive/components/theme-selector.js +0 -50
  234. package/dist/modes/interactive/components/theme-selector.js.map +0 -1
  235. package/dist/modes/interactive/components/thinking-selector.d.ts +0 -11
  236. package/dist/modes/interactive/components/thinking-selector.d.ts.map +0 -1
  237. package/dist/modes/interactive/components/thinking-selector.js +0 -51
  238. package/dist/modes/interactive/components/thinking-selector.js.map +0 -1
  239. package/dist/modes/interactive/components/tool-execution.d.ts +0 -63
  240. package/dist/modes/interactive/components/tool-execution.d.ts.map +0 -1
  241. package/dist/modes/interactive/components/tool-execution.js +0 -295
  242. package/dist/modes/interactive/components/tool-execution.js.map +0 -1
  243. package/dist/modes/interactive/components/tree-selector.d.ts +0 -89
  244. package/dist/modes/interactive/components/tree-selector.d.ts.map +0 -1
  245. package/dist/modes/interactive/components/tree-selector.js +0 -1093
  246. package/dist/modes/interactive/components/tree-selector.js.map +0 -1
  247. package/dist/modes/interactive/components/user-message-selector.d.ts +0 -30
  248. package/dist/modes/interactive/components/user-message-selector.d.ts.map +0 -1
  249. package/dist/modes/interactive/components/user-message-selector.js +0 -114
  250. package/dist/modes/interactive/components/user-message-selector.js.map +0 -1
  251. package/dist/modes/interactive/components/user-message.d.ts +0 -10
  252. package/dist/modes/interactive/components/user-message.d.ts.map +0 -1
  253. package/dist/modes/interactive/components/user-message.js +0 -29
  254. package/dist/modes/interactive/components/user-message.js.map +0 -1
  255. package/dist/modes/interactive/interactive-mode.d.ts +0 -375
  256. package/dist/modes/interactive/interactive-mode.d.ts.map +0 -1
  257. package/dist/modes/interactive/interactive-mode.js +0 -4799
  258. package/dist/modes/interactive/interactive-mode.js.map +0 -1
  259. package/dist/modes/interactive/theme/dark.json +0 -86
  260. package/dist/modes/interactive/theme/light.json +0 -85
  261. package/dist/modes/interactive/theme/theme-schema.json +0 -335
  262. package/examples/extensions/border-status-editor.ts +0 -150
  263. package/examples/extensions/built-in-tool-renderer.ts +0 -249
  264. package/examples/extensions/custom-footer.ts +0 -64
  265. package/examples/extensions/custom-header.ts +0 -73
  266. package/examples/extensions/custom-provider-anthropic/index.ts +0 -604
  267. package/examples/extensions/custom-provider-anthropic/package-lock.json +0 -24
  268. package/examples/extensions/custom-provider-anthropic/package.json +0 -19
  269. package/examples/extensions/custom-provider-gitlab-duo/index.ts +0 -349
  270. package/examples/extensions/custom-provider-gitlab-duo/package.json +0 -16
  271. package/examples/extensions/custom-provider-gitlab-duo/test.ts +0 -82
  272. package/examples/extensions/doom-overlay/README.md +0 -46
  273. package/examples/extensions/doom-overlay/doom/build/doom.js +0 -21
  274. package/examples/extensions/doom-overlay/doom/build/doom.wasm +0 -0
  275. package/examples/extensions/doom-overlay/doom/build.sh +0 -152
  276. package/examples/extensions/doom-overlay/doom/doomgeneric_pi.c +0 -72
  277. package/examples/extensions/doom-overlay/doom-component.ts +0 -132
  278. package/examples/extensions/doom-overlay/doom-engine.ts +0 -173
  279. package/examples/extensions/doom-overlay/doom-keys.ts +0 -104
  280. package/examples/extensions/doom-overlay/index.ts +0 -74
  281. package/examples/extensions/doom-overlay/wad-finder.ts +0 -51
  282. package/examples/extensions/github-issue-autocomplete.ts +0 -185
  283. package/examples/extensions/handoff.ts +0 -191
  284. package/examples/extensions/interactive-shell.ts +0 -196
  285. package/examples/extensions/message-renderer.ts +0 -59
  286. package/examples/extensions/minimal-mode.ts +0 -426
  287. package/examples/extensions/modal-editor.ts +0 -85
  288. package/examples/extensions/overlay-qa-tests.ts +0 -1379
  289. package/examples/extensions/overlay-test.ts +0 -153
  290. package/examples/extensions/plan-mode/index.ts +0 -340
  291. package/examples/extensions/preset.ts +0 -430
  292. package/examples/extensions/qna.ts +0 -122
  293. package/examples/extensions/question.ts +0 -264
  294. package/examples/extensions/questionnaire.ts +0 -427
  295. package/examples/extensions/rainbow-editor.ts +0 -88
  296. package/examples/extensions/sandbox/index.ts +0 -321
  297. package/examples/extensions/sandbox/package-lock.json +0 -92
  298. package/examples/extensions/sandbox/package.json +0 -19
  299. package/examples/extensions/snake.ts +0 -343
  300. package/examples/extensions/space-invaders.ts +0 -560
  301. package/examples/extensions/ssh.ts +0 -220
  302. package/examples/extensions/status-line.ts +0 -32
  303. package/examples/extensions/structured-output.ts +0 -65
  304. package/examples/extensions/subagent/index.ts +0 -1009
  305. package/examples/extensions/summarize.ts +0 -206
  306. package/examples/extensions/tic-tac-toe.ts +0 -1008
  307. package/examples/extensions/todo.ts +0 -297
  308. package/examples/extensions/tools.ts +0 -141
  309. package/examples/extensions/truncated-tool.ts +0 -195
  310. package/examples/extensions/with-deps/index.ts +0 -32
  311. package/examples/extensions/with-deps/package-lock.json +0 -31
  312. package/examples/extensions/with-deps/package.json +0 -22
  313. package/examples/extensions/working-indicator.ts +0 -123
  314. package/examples/rpc-extension-ui.ts +0 -632
@@ -1,201 +0,0 @@
1
- import { truncateToWidth, visibleWidth } from "@openeryc/pi-tui";
2
- import { theme } from "../theme/theme.js";
3
- /**
4
- * Sanitize text for display in a single-line status.
5
- * Removes newlines, tabs, carriage returns, and other control characters.
6
- */
7
- function sanitizeStatusText(text) {
8
- // Replace newlines, tabs, carriage returns with space, then collapse multiple spaces
9
- return text
10
- .replace(/[\r\n\t]/g, " ")
11
- .replace(/ +/g, " ")
12
- .trim();
13
- }
14
- /**
15
- * Format token counts for compact footer display.
16
- */
17
- function formatTokens(count) {
18
- if (count < 1000)
19
- return count.toString();
20
- if (count < 10000)
21
- return `${(count / 1000).toFixed(1)}k`;
22
- if (count < 1000000)
23
- return `${Math.round(count / 1000)}k`;
24
- if (count < 10000000)
25
- return `${(count / 1000000).toFixed(1)}M`;
26
- return `${Math.round(count / 1000000)}M`;
27
- }
28
- /**
29
- * Footer component that shows pwd, token stats, and context usage.
30
- * Computes token/context stats from session, gets git branch and extension statuses from provider.
31
- */
32
- export class FooterComponent {
33
- autoCompactEnabled = true;
34
- session;
35
- footerData;
36
- constructor(session, footerData) {
37
- this.session = session;
38
- this.footerData = footerData;
39
- }
40
- setSession(session) {
41
- this.session = session;
42
- }
43
- setAutoCompactEnabled(enabled) {
44
- this.autoCompactEnabled = enabled;
45
- }
46
- /**
47
- * No-op: git branch caching now handled by provider.
48
- * Kept for compatibility with existing call sites in interactive-mode.
49
- */
50
- invalidate() {
51
- // No-op: git branch is cached/invalidated by provider
52
- }
53
- /**
54
- * Clean up resources.
55
- * Git watcher cleanup now handled by provider.
56
- */
57
- dispose() {
58
- // Git watcher cleanup handled by provider
59
- }
60
- render(width) {
61
- const state = this.session.state;
62
- // Calculate cumulative usage from ALL session entries (not just post-compaction messages)
63
- let totalInput = 0;
64
- let totalOutput = 0;
65
- let totalCacheRead = 0;
66
- let totalCacheWrite = 0;
67
- let totalCost = 0;
68
- for (const entry of this.session.sessionManager.getEntries()) {
69
- if (entry.type === "message" && entry.message.role === "assistant") {
70
- totalInput += entry.message.usage.input;
71
- totalOutput += entry.message.usage.output;
72
- totalCacheRead += entry.message.usage.cacheRead;
73
- totalCacheWrite += entry.message.usage.cacheWrite;
74
- totalCost += entry.message.usage.cost.total;
75
- }
76
- }
77
- // Calculate context usage from session (handles compaction correctly).
78
- // After compaction, tokens are unknown until the next LLM response.
79
- const contextUsage = this.session.getContextUsage();
80
- const contextWindow = contextUsage?.contextWindow ?? state.model?.contextWindow ?? 0;
81
- const contextPercentValue = contextUsage?.percent ?? 0;
82
- const contextPercent = contextUsage?.percent !== null ? contextPercentValue.toFixed(1) : "?";
83
- // Replace home directory with ~
84
- let pwd = this.session.sessionManager.getCwd();
85
- const home = process.env.HOME || process.env.USERPROFILE;
86
- if (home && pwd.startsWith(home)) {
87
- pwd = `~${pwd.slice(home.length)}`;
88
- }
89
- // Add git branch if available
90
- const branch = this.footerData.getGitBranch();
91
- if (branch) {
92
- pwd = `${pwd} (${branch})`;
93
- }
94
- // Add session name if set
95
- const sessionName = this.session.sessionManager.getSessionName();
96
- if (sessionName) {
97
- pwd = `${pwd} • ${sessionName}`;
98
- }
99
- // Build stats line
100
- const statsParts = [];
101
- if (totalInput)
102
- statsParts.push(`↑${formatTokens(totalInput)}`);
103
- if (totalOutput)
104
- statsParts.push(`↓${formatTokens(totalOutput)}`);
105
- if (totalCacheRead)
106
- statsParts.push(`R${formatTokens(totalCacheRead)}`);
107
- if (totalCacheWrite)
108
- statsParts.push(`W${formatTokens(totalCacheWrite)}`);
109
- // Show cost with "(sub)" indicator if using OAuth subscription
110
- const usingSubscription = state.model ? this.session.modelRegistry.isUsingOAuth(state.model) : false;
111
- if (totalCost || usingSubscription) {
112
- const costStr = `$${totalCost.toFixed(3)}${usingSubscription ? " (sub)" : ""}`;
113
- statsParts.push(costStr);
114
- }
115
- // Colorize context percentage based on usage
116
- let contextPercentStr;
117
- const autoIndicator = this.autoCompactEnabled ? " (auto)" : "";
118
- const contextPercentDisplay = contextPercent === "?"
119
- ? `?/${formatTokens(contextWindow)}${autoIndicator}`
120
- : `${contextPercent}%/${formatTokens(contextWindow)}${autoIndicator}`;
121
- if (contextPercentValue > 90) {
122
- contextPercentStr = theme.fg("error", contextPercentDisplay);
123
- }
124
- else if (contextPercentValue > 70) {
125
- contextPercentStr = theme.fg("warning", contextPercentDisplay);
126
- }
127
- else {
128
- contextPercentStr = contextPercentDisplay;
129
- }
130
- statsParts.push(contextPercentStr);
131
- let statsLeft = statsParts.join(" ");
132
- // Add model name on the right side, plus thinking level if model supports it
133
- const modelName = state.model?.id || "no-model";
134
- let statsLeftWidth = visibleWidth(statsLeft);
135
- // If statsLeft is too wide, truncate it
136
- if (statsLeftWidth > width) {
137
- statsLeft = truncateToWidth(statsLeft, width, "...");
138
- statsLeftWidth = visibleWidth(statsLeft);
139
- }
140
- // Calculate available space for padding (minimum 2 spaces between stats and model)
141
- const minPadding = 2;
142
- // Add thinking level indicator if model supports reasoning
143
- let rightSideWithoutProvider = modelName;
144
- if (state.model?.reasoning) {
145
- const thinkingLevel = state.thinkingLevel || "off";
146
- rightSideWithoutProvider =
147
- thinkingLevel === "off" ? `${modelName} • thinking off` : `${modelName} • ${thinkingLevel}`;
148
- }
149
- // Prepend the provider in parentheses if there are multiple providers and there's enough room
150
- let rightSide = rightSideWithoutProvider;
151
- if (this.footerData.getAvailableProviderCount() > 1 && state.model) {
152
- rightSide = `(${state.model.provider}) ${rightSideWithoutProvider}`;
153
- if (statsLeftWidth + minPadding + visibleWidth(rightSide) > width) {
154
- // Too wide, fall back
155
- rightSide = rightSideWithoutProvider;
156
- }
157
- }
158
- const rightSideWidth = visibleWidth(rightSide);
159
- const totalNeeded = statsLeftWidth + minPadding + rightSideWidth;
160
- let statsLine;
161
- if (totalNeeded <= width) {
162
- // Both fit - add padding to right-align model
163
- const padding = " ".repeat(width - statsLeftWidth - rightSideWidth);
164
- statsLine = statsLeft + padding + rightSide;
165
- }
166
- else {
167
- // Need to truncate right side
168
- const availableForRight = width - statsLeftWidth - minPadding;
169
- if (availableForRight > 0) {
170
- const truncatedRight = truncateToWidth(rightSide, availableForRight, "");
171
- const truncatedRightWidth = visibleWidth(truncatedRight);
172
- const padding = " ".repeat(Math.max(0, width - statsLeftWidth - truncatedRightWidth));
173
- statsLine = statsLeft + padding + truncatedRight;
174
- }
175
- else {
176
- // Not enough space for right side at all
177
- statsLine = statsLeft;
178
- }
179
- }
180
- // Apply dim to each part separately. statsLeft may contain color codes (for context %)
181
- // that end with a reset, which would clear an outer dim wrapper. So we dim the parts
182
- // before and after the colored section independently.
183
- const dimStatsLeft = theme.fg("dim", statsLeft);
184
- const remainder = statsLine.slice(statsLeft.length); // padding + rightSide
185
- const dimRemainder = theme.fg("dim", remainder);
186
- const pwdLine = truncateToWidth(theme.fg("dim", pwd), width, theme.fg("dim", "..."));
187
- const lines = [pwdLine, dimStatsLeft + dimRemainder];
188
- // Add extension statuses on a single line, sorted by key alphabetically
189
- const extensionStatuses = this.footerData.getExtensionStatuses();
190
- if (extensionStatuses.size > 0) {
191
- const sortedStatuses = Array.from(extensionStatuses.entries())
192
- .sort(([a], [b]) => a.localeCompare(b))
193
- .map(([, text]) => sanitizeStatusText(text));
194
- const statusLine = sortedStatuses.join(" ");
195
- // Truncate to terminal width with dim ellipsis for consistency with footer style
196
- lines.push(truncateToWidth(statusLine, width, theme.fg("dim", "...")));
197
- }
198
- return lines;
199
- }
200
- }
201
- //# sourceMappingURL=footer.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"footer.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/footer.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Component, truncateToWidth, visibleWidth } from \"@openeryc/pi-tui\";\nimport type { AgentSession } from \"../../../core/agent-session.ts\";\nimport type { ReadonlyFooterDataProvider } from \"../../../core/footer-data-provider.ts\";\nimport { theme } from \"../theme/theme.ts\";\n\n/**\n * Sanitize text for display in a single-line status.\n * Removes newlines, tabs, carriage returns, and other control characters.\n */\nfunction sanitizeStatusText(text: string): string {\n\t// Replace newlines, tabs, carriage returns with space, then collapse multiple spaces\n\treturn text\n\t\t.replace(/[\\r\\n\\t]/g, \" \")\n\t\t.replace(/ +/g, \" \")\n\t\t.trim();\n}\n\n/**\n * Format token counts for compact footer display.\n */\nfunction formatTokens(count: number): string {\n\tif (count < 1000) return count.toString();\n\tif (count < 10000) return `${(count / 1000).toFixed(1)}k`;\n\tif (count < 1000000) return `${Math.round(count / 1000)}k`;\n\tif (count < 10000000) return `${(count / 1000000).toFixed(1)}M`;\n\treturn `${Math.round(count / 1000000)}M`;\n}\n\n/**\n * Footer component that shows pwd, token stats, and context usage.\n * Computes token/context stats from session, gets git branch and extension statuses from provider.\n */\nexport class FooterComponent implements Component {\n\tprivate autoCompactEnabled = true;\n\tprivate session: AgentSession;\n\tprivate footerData: ReadonlyFooterDataProvider;\n\n\tconstructor(session: AgentSession, footerData: ReadonlyFooterDataProvider) {\n\t\tthis.session = session;\n\t\tthis.footerData = footerData;\n\t}\n\n\tsetSession(session: AgentSession): void {\n\t\tthis.session = session;\n\t}\n\n\tsetAutoCompactEnabled(enabled: boolean): void {\n\t\tthis.autoCompactEnabled = enabled;\n\t}\n\n\t/**\n\t * No-op: git branch caching now handled by provider.\n\t * Kept for compatibility with existing call sites in interactive-mode.\n\t */\n\tinvalidate(): void {\n\t\t// No-op: git branch is cached/invalidated by provider\n\t}\n\n\t/**\n\t * Clean up resources.\n\t * Git watcher cleanup now handled by provider.\n\t */\n\tdispose(): void {\n\t\t// Git watcher cleanup handled by provider\n\t}\n\n\trender(width: number): string[] {\n\t\tconst state = this.session.state;\n\n\t\t// Calculate cumulative usage from ALL session entries (not just post-compaction messages)\n\t\tlet totalInput = 0;\n\t\tlet totalOutput = 0;\n\t\tlet totalCacheRead = 0;\n\t\tlet totalCacheWrite = 0;\n\t\tlet totalCost = 0;\n\n\t\tfor (const entry of this.session.sessionManager.getEntries()) {\n\t\t\tif (entry.type === \"message\" && entry.message.role === \"assistant\") {\n\t\t\t\ttotalInput += entry.message.usage.input;\n\t\t\t\ttotalOutput += entry.message.usage.output;\n\t\t\t\ttotalCacheRead += entry.message.usage.cacheRead;\n\t\t\t\ttotalCacheWrite += entry.message.usage.cacheWrite;\n\t\t\t\ttotalCost += entry.message.usage.cost.total;\n\t\t\t}\n\t\t}\n\n\t\t// Calculate context usage from session (handles compaction correctly).\n\t\t// After compaction, tokens are unknown until the next LLM response.\n\t\tconst contextUsage = this.session.getContextUsage();\n\t\tconst contextWindow = contextUsage?.contextWindow ?? state.model?.contextWindow ?? 0;\n\t\tconst contextPercentValue = contextUsage?.percent ?? 0;\n\t\tconst contextPercent = contextUsage?.percent !== null ? contextPercentValue.toFixed(1) : \"?\";\n\n\t\t// Replace home directory with ~\n\t\tlet pwd = this.session.sessionManager.getCwd();\n\t\tconst home = process.env.HOME || process.env.USERPROFILE;\n\t\tif (home && pwd.startsWith(home)) {\n\t\t\tpwd = `~${pwd.slice(home.length)}`;\n\t\t}\n\n\t\t// Add git branch if available\n\t\tconst branch = this.footerData.getGitBranch();\n\t\tif (branch) {\n\t\t\tpwd = `${pwd} (${branch})`;\n\t\t}\n\n\t\t// Add session name if set\n\t\tconst sessionName = this.session.sessionManager.getSessionName();\n\t\tif (sessionName) {\n\t\t\tpwd = `${pwd} • ${sessionName}`;\n\t\t}\n\n\t\t// Build stats line\n\t\tconst statsParts = [];\n\t\tif (totalInput) statsParts.push(`↑${formatTokens(totalInput)}`);\n\t\tif (totalOutput) statsParts.push(`↓${formatTokens(totalOutput)}`);\n\t\tif (totalCacheRead) statsParts.push(`R${formatTokens(totalCacheRead)}`);\n\t\tif (totalCacheWrite) statsParts.push(`W${formatTokens(totalCacheWrite)}`);\n\n\t\t// Show cost with \"(sub)\" indicator if using OAuth subscription\n\t\tconst usingSubscription = state.model ? this.session.modelRegistry.isUsingOAuth(state.model) : false;\n\t\tif (totalCost || usingSubscription) {\n\t\t\tconst costStr = `$${totalCost.toFixed(3)}${usingSubscription ? \" (sub)\" : \"\"}`;\n\t\t\tstatsParts.push(costStr);\n\t\t}\n\n\t\t// Colorize context percentage based on usage\n\t\tlet contextPercentStr: string;\n\t\tconst autoIndicator = this.autoCompactEnabled ? \" (auto)\" : \"\";\n\t\tconst contextPercentDisplay =\n\t\t\tcontextPercent === \"?\"\n\t\t\t\t? `?/${formatTokens(contextWindow)}${autoIndicator}`\n\t\t\t\t: `${contextPercent}%/${formatTokens(contextWindow)}${autoIndicator}`;\n\t\tif (contextPercentValue > 90) {\n\t\t\tcontextPercentStr = theme.fg(\"error\", contextPercentDisplay);\n\t\t} else if (contextPercentValue > 70) {\n\t\t\tcontextPercentStr = theme.fg(\"warning\", contextPercentDisplay);\n\t\t} else {\n\t\t\tcontextPercentStr = contextPercentDisplay;\n\t\t}\n\t\tstatsParts.push(contextPercentStr);\n\n\t\tlet statsLeft = statsParts.join(\" \");\n\n\t\t// Add model name on the right side, plus thinking level if model supports it\n\t\tconst modelName = state.model?.id || \"no-model\";\n\n\t\tlet statsLeftWidth = visibleWidth(statsLeft);\n\n\t\t// If statsLeft is too wide, truncate it\n\t\tif (statsLeftWidth > width) {\n\t\t\tstatsLeft = truncateToWidth(statsLeft, width, \"...\");\n\t\t\tstatsLeftWidth = visibleWidth(statsLeft);\n\t\t}\n\n\t\t// Calculate available space for padding (minimum 2 spaces between stats and model)\n\t\tconst minPadding = 2;\n\n\t\t// Add thinking level indicator if model supports reasoning\n\t\tlet rightSideWithoutProvider = modelName;\n\t\tif (state.model?.reasoning) {\n\t\t\tconst thinkingLevel = state.thinkingLevel || \"off\";\n\t\t\trightSideWithoutProvider =\n\t\t\t\tthinkingLevel === \"off\" ? `${modelName} • thinking off` : `${modelName} • ${thinkingLevel}`;\n\t\t}\n\n\t\t// Prepend the provider in parentheses if there are multiple providers and there's enough room\n\t\tlet rightSide = rightSideWithoutProvider;\n\t\tif (this.footerData.getAvailableProviderCount() > 1 && state.model) {\n\t\t\trightSide = `(${state.model!.provider}) ${rightSideWithoutProvider}`;\n\t\t\tif (statsLeftWidth + minPadding + visibleWidth(rightSide) > width) {\n\t\t\t\t// Too wide, fall back\n\t\t\t\trightSide = rightSideWithoutProvider;\n\t\t\t}\n\t\t}\n\n\t\tconst rightSideWidth = visibleWidth(rightSide);\n\t\tconst totalNeeded = statsLeftWidth + minPadding + rightSideWidth;\n\n\t\tlet statsLine: string;\n\t\tif (totalNeeded <= width) {\n\t\t\t// Both fit - add padding to right-align model\n\t\t\tconst padding = \" \".repeat(width - statsLeftWidth - rightSideWidth);\n\t\t\tstatsLine = statsLeft + padding + rightSide;\n\t\t} else {\n\t\t\t// Need to truncate right side\n\t\t\tconst availableForRight = width - statsLeftWidth - minPadding;\n\t\t\tif (availableForRight > 0) {\n\t\t\t\tconst truncatedRight = truncateToWidth(rightSide, availableForRight, \"\");\n\t\t\t\tconst truncatedRightWidth = visibleWidth(truncatedRight);\n\t\t\t\tconst padding = \" \".repeat(Math.max(0, width - statsLeftWidth - truncatedRightWidth));\n\t\t\t\tstatsLine = statsLeft + padding + truncatedRight;\n\t\t\t} else {\n\t\t\t\t// Not enough space for right side at all\n\t\t\t\tstatsLine = statsLeft;\n\t\t\t}\n\t\t}\n\n\t\t// Apply dim to each part separately. statsLeft may contain color codes (for context %)\n\t\t// that end with a reset, which would clear an outer dim wrapper. So we dim the parts\n\t\t// before and after the colored section independently.\n\t\tconst dimStatsLeft = theme.fg(\"dim\", statsLeft);\n\t\tconst remainder = statsLine.slice(statsLeft.length); // padding + rightSide\n\t\tconst dimRemainder = theme.fg(\"dim\", remainder);\n\n\t\tconst pwdLine = truncateToWidth(theme.fg(\"dim\", pwd), width, theme.fg(\"dim\", \"...\"));\n\t\tconst lines = [pwdLine, dimStatsLeft + dimRemainder];\n\n\t\t// Add extension statuses on a single line, sorted by key alphabetically\n\t\tconst extensionStatuses = this.footerData.getExtensionStatuses();\n\t\tif (extensionStatuses.size > 0) {\n\t\t\tconst sortedStatuses = Array.from(extensionStatuses.entries())\n\t\t\t\t.sort(([a], [b]) => a.localeCompare(b))\n\t\t\t\t.map(([, text]) => sanitizeStatusText(text));\n\t\t\tconst statusLine = sortedStatuses.join(\" \");\n\t\t\t// Truncate to terminal width with dim ellipsis for consistency with footer style\n\t\t\tlines.push(truncateToWidth(statusLine, width, theme.fg(\"dim\", \"...\")));\n\t\t}\n\n\t\treturn lines;\n\t}\n}\n"]}
@@ -1,32 +0,0 @@
1
- export { ArminComponent } from "./armin.ts";
2
- export { AssistantMessageComponent } from "./assistant-message.ts";
3
- export { BashExecutionComponent } from "./bash-execution.ts";
4
- export { BorderedLoader } from "./bordered-loader.ts";
5
- export { BranchSummaryMessageComponent } from "./branch-summary-message.ts";
6
- export { CompactionSummaryMessageComponent } from "./compaction-summary-message.ts";
7
- export { CustomEditor } from "./custom-editor.ts";
8
- export { CustomMessageComponent } from "./custom-message.ts";
9
- export { DaxnutsComponent } from "./daxnuts.ts";
10
- export { type RenderDiffOptions, renderDiff } from "./diff.ts";
11
- export { DynamicBorder } from "./dynamic-border.ts";
12
- export { ExtensionEditorComponent } from "./extension-editor.ts";
13
- export { ExtensionInputComponent } from "./extension-input.ts";
14
- export { ExtensionSelectorComponent } from "./extension-selector.ts";
15
- export { FooterComponent } from "./footer.ts";
16
- export { keyHint, keyText, rawKeyHint } from "./keybinding-hints.ts";
17
- export { LoginDialogComponent } from "./login-dialog.ts";
18
- export { ModelSelectorComponent } from "./model-selector.ts";
19
- export { OAuthSelectorComponent } from "./oauth-selector.ts";
20
- export { type ModelsCallbacks, type ModelsConfig, ScopedModelsSelectorComponent } from "./scoped-models-selector.ts";
21
- export { SessionSelectorComponent } from "./session-selector.ts";
22
- export { type SettingsCallbacks, type SettingsConfig, SettingsSelectorComponent } from "./settings-selector.ts";
23
- export { ShowImagesSelectorComponent } from "./show-images-selector.ts";
24
- export { SkillInvocationMessageComponent } from "./skill-invocation-message.ts";
25
- export { ThemeSelectorComponent } from "./theme-selector.ts";
26
- export { ThinkingSelectorComponent } from "./thinking-selector.ts";
27
- export { ToolExecutionComponent, type ToolExecutionOptions } from "./tool-execution.ts";
28
- export { TreeSelectorComponent } from "./tree-selector.ts";
29
- export { UserMessageComponent } from "./user-message.ts";
30
- export { UserMessageSelectorComponent } from "./user-message-selector.ts";
31
- export { truncateToVisualLines, type VisualTruncateResult } from "./visual-truncate.ts";
32
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,6BAA6B,EAAE,MAAM,6BAA6B,CAAC;AAC5E,OAAO,EAAE,iCAAiC,EAAE,MAAM,iCAAiC,CAAC;AACpF,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,KAAK,iBAAiB,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EAAE,0BAA0B,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,YAAY,EAAE,6BAA6B,EAAE,MAAM,6BAA6B,CAAC;AACrH,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,EAAE,KAAK,iBAAiB,EAAE,KAAK,cAAc,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AAChH,OAAO,EAAE,2BAA2B,EAAE,MAAM,2BAA2B,CAAC;AACxE,OAAO,EAAE,+BAA+B,EAAE,MAAM,+BAA+B,CAAC;AAChF,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAAE,KAAK,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AACxF,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,4BAA4B,EAAE,MAAM,4BAA4B,CAAC;AAC1E,OAAO,EAAE,qBAAqB,EAAE,KAAK,oBAAoB,EAAE,MAAM,sBAAsB,CAAC","sourcesContent":["// UI Components for extensions\nexport { ArminComponent } from \"./armin.ts\";\nexport { AssistantMessageComponent } from \"./assistant-message.ts\";\nexport { BashExecutionComponent } from \"./bash-execution.ts\";\nexport { BorderedLoader } from \"./bordered-loader.ts\";\nexport { BranchSummaryMessageComponent } from \"./branch-summary-message.ts\";\nexport { CompactionSummaryMessageComponent } from \"./compaction-summary-message.ts\";\nexport { CustomEditor } from \"./custom-editor.ts\";\nexport { CustomMessageComponent } from \"./custom-message.ts\";\nexport { DaxnutsComponent } from \"./daxnuts.ts\";\nexport { type RenderDiffOptions, renderDiff } from \"./diff.ts\";\nexport { DynamicBorder } from \"./dynamic-border.ts\";\nexport { ExtensionEditorComponent } from \"./extension-editor.ts\";\nexport { ExtensionInputComponent } from \"./extension-input.ts\";\nexport { ExtensionSelectorComponent } from \"./extension-selector.ts\";\nexport { FooterComponent } from \"./footer.ts\";\nexport { keyHint, keyText, rawKeyHint } from \"./keybinding-hints.ts\";\nexport { LoginDialogComponent } from \"./login-dialog.ts\";\nexport { ModelSelectorComponent } from \"./model-selector.ts\";\nexport { OAuthSelectorComponent } from \"./oauth-selector.ts\";\nexport { type ModelsCallbacks, type ModelsConfig, ScopedModelsSelectorComponent } from \"./scoped-models-selector.ts\";\nexport { SessionSelectorComponent } from \"./session-selector.ts\";\nexport { type SettingsCallbacks, type SettingsConfig, SettingsSelectorComponent } from \"./settings-selector.ts\";\nexport { ShowImagesSelectorComponent } from \"./show-images-selector.ts\";\nexport { SkillInvocationMessageComponent } from \"./skill-invocation-message.ts\";\nexport { ThemeSelectorComponent } from \"./theme-selector.ts\";\nexport { ThinkingSelectorComponent } from \"./thinking-selector.ts\";\nexport { ToolExecutionComponent, type ToolExecutionOptions } from \"./tool-execution.ts\";\nexport { TreeSelectorComponent } from \"./tree-selector.ts\";\nexport { UserMessageComponent } from \"./user-message.ts\";\nexport { UserMessageSelectorComponent } from \"./user-message-selector.ts\";\nexport { truncateToVisualLines, type VisualTruncateResult } from \"./visual-truncate.ts\";\n"]}
@@ -1,33 +0,0 @@
1
- // UI Components for extensions
2
- export { ArminComponent } from "./armin.js";
3
- export { AssistantMessageComponent } from "./assistant-message.js";
4
- export { BashExecutionComponent } from "./bash-execution.js";
5
- export { BorderedLoader } from "./bordered-loader.js";
6
- export { BranchSummaryMessageComponent } from "./branch-summary-message.js";
7
- export { CompactionSummaryMessageComponent } from "./compaction-summary-message.js";
8
- export { CustomEditor } from "./custom-editor.js";
9
- export { CustomMessageComponent } from "./custom-message.js";
10
- export { DaxnutsComponent } from "./daxnuts.js";
11
- export { renderDiff } from "./diff.js";
12
- export { DynamicBorder } from "./dynamic-border.js";
13
- export { ExtensionEditorComponent } from "./extension-editor.js";
14
- export { ExtensionInputComponent } from "./extension-input.js";
15
- export { ExtensionSelectorComponent } from "./extension-selector.js";
16
- export { FooterComponent } from "./footer.js";
17
- export { keyHint, keyText, rawKeyHint } from "./keybinding-hints.js";
18
- export { LoginDialogComponent } from "./login-dialog.js";
19
- export { ModelSelectorComponent } from "./model-selector.js";
20
- export { OAuthSelectorComponent } from "./oauth-selector.js";
21
- export { ScopedModelsSelectorComponent } from "./scoped-models-selector.js";
22
- export { SessionSelectorComponent } from "./session-selector.js";
23
- export { SettingsSelectorComponent } from "./settings-selector.js";
24
- export { ShowImagesSelectorComponent } from "./show-images-selector.js";
25
- export { SkillInvocationMessageComponent } from "./skill-invocation-message.js";
26
- export { ThemeSelectorComponent } from "./theme-selector.js";
27
- export { ThinkingSelectorComponent } from "./thinking-selector.js";
28
- export { ToolExecutionComponent } from "./tool-execution.js";
29
- export { TreeSelectorComponent } from "./tree-selector.js";
30
- export { UserMessageComponent } from "./user-message.js";
31
- export { UserMessageSelectorComponent } from "./user-message-selector.js";
32
- export { truncateToVisualLines } from "./visual-truncate.js";
33
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/index.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,6BAA6B,EAAE,MAAM,6BAA6B,CAAC;AAC5E,OAAO,EAAE,iCAAiC,EAAE,MAAM,iCAAiC,CAAC;AACpF,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAA0B,UAAU,EAAE,MAAM,WAAW,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EAAE,0BAA0B,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAA2C,6BAA6B,EAAE,MAAM,6BAA6B,CAAC;AACrH,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,EAA+C,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AAChH,OAAO,EAAE,2BAA2B,EAAE,MAAM,2BAA2B,CAAC;AACxE,OAAO,EAAE,+BAA+B,EAAE,MAAM,+BAA+B,CAAC;AAChF,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAA6B,MAAM,qBAAqB,CAAC;AACxF,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,4BAA4B,EAAE,MAAM,4BAA4B,CAAC;AAC1E,OAAO,EAAE,qBAAqB,EAA6B,MAAM,sBAAsB,CAAC","sourcesContent":["// UI Components for extensions\nexport { ArminComponent } from \"./armin.ts\";\nexport { AssistantMessageComponent } from \"./assistant-message.ts\";\nexport { BashExecutionComponent } from \"./bash-execution.ts\";\nexport { BorderedLoader } from \"./bordered-loader.ts\";\nexport { BranchSummaryMessageComponent } from \"./branch-summary-message.ts\";\nexport { CompactionSummaryMessageComponent } from \"./compaction-summary-message.ts\";\nexport { CustomEditor } from \"./custom-editor.ts\";\nexport { CustomMessageComponent } from \"./custom-message.ts\";\nexport { DaxnutsComponent } from \"./daxnuts.ts\";\nexport { type RenderDiffOptions, renderDiff } from \"./diff.ts\";\nexport { DynamicBorder } from \"./dynamic-border.ts\";\nexport { ExtensionEditorComponent } from \"./extension-editor.ts\";\nexport { ExtensionInputComponent } from \"./extension-input.ts\";\nexport { ExtensionSelectorComponent } from \"./extension-selector.ts\";\nexport { FooterComponent } from \"./footer.ts\";\nexport { keyHint, keyText, rawKeyHint } from \"./keybinding-hints.ts\";\nexport { LoginDialogComponent } from \"./login-dialog.ts\";\nexport { ModelSelectorComponent } from \"./model-selector.ts\";\nexport { OAuthSelectorComponent } from \"./oauth-selector.ts\";\nexport { type ModelsCallbacks, type ModelsConfig, ScopedModelsSelectorComponent } from \"./scoped-models-selector.ts\";\nexport { SessionSelectorComponent } from \"./session-selector.ts\";\nexport { type SettingsCallbacks, type SettingsConfig, SettingsSelectorComponent } from \"./settings-selector.ts\";\nexport { ShowImagesSelectorComponent } from \"./show-images-selector.ts\";\nexport { SkillInvocationMessageComponent } from \"./skill-invocation-message.ts\";\nexport { ThemeSelectorComponent } from \"./theme-selector.ts\";\nexport { ThinkingSelectorComponent } from \"./thinking-selector.ts\";\nexport { ToolExecutionComponent, type ToolExecutionOptions } from \"./tool-execution.ts\";\nexport { TreeSelectorComponent } from \"./tree-selector.ts\";\nexport { UserMessageComponent } from \"./user-message.ts\";\nexport { UserMessageSelectorComponent } from \"./user-message-selector.ts\";\nexport { truncateToVisualLines, type VisualTruncateResult } from \"./visual-truncate.ts\";\n"]}
@@ -1,46 +0,0 @@
1
- import { Container, type Focusable, type TUI } from "@openeryc/pi-tui";
2
- /**
3
- * Login dialog component - replaces editor during OAuth login flow
4
- */
5
- export declare class LoginDialogComponent extends Container implements Focusable {
6
- private contentContainer;
7
- private input;
8
- private tui;
9
- private abortController;
10
- private inputResolver?;
11
- private inputRejecter?;
12
- private onComplete;
13
- private _focused;
14
- get focused(): boolean;
15
- set focused(value: boolean);
16
- constructor(tui: TUI, providerId: string, onComplete: (success: boolean, message?: string) => void, providerNameOverride?: string, titleOverride?: string);
17
- get signal(): AbortSignal;
18
- private cancel;
19
- /**
20
- * Called by onAuth callback - show URL and optional instructions
21
- */
22
- showAuth(url: string, instructions?: string): void;
23
- /**
24
- * Show input for manual code/URL entry (for callback server providers)
25
- */
26
- showManualInput(prompt: string): Promise<string>;
27
- /**
28
- * Called by onPrompt callback - show prompt and wait for input
29
- * Note: Does NOT clear content, appends to existing (preserves URL from showAuth)
30
- */
31
- showPrompt(message: string, placeholder?: string): Promise<string>;
32
- /**
33
- * Show informational text without prompting for input.
34
- */
35
- showInfo(lines: string[]): void;
36
- /**
37
- * Show waiting message (for polling flows like GitHub Copilot)
38
- */
39
- showWaiting(message: string): void;
40
- /**
41
- * Called by onProgress callback
42
- */
43
- showProgress(message: string): void;
44
- handleInput(data: string): void;
45
- }
46
- //# sourceMappingURL=login-dialog.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"login-dialog.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/login-dialog.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,KAAK,SAAS,EAAuC,KAAK,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAM5G;;GAEG;AACH,qBAAa,oBAAqB,SAAQ,SAAU,YAAW,SAAS;IACvE,OAAO,CAAC,gBAAgB,CAAY;IACpC,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,GAAG,CAAM;IACjB,OAAO,CAAC,eAAe,CAAyB;IAChD,OAAO,CAAC,aAAa,CAAC,CAA0B;IAChD,OAAO,CAAC,aAAa,CAAC,CAAyB;IAC/C,OAAO,CAAC,UAAU,CAA+C;IAGjE,OAAO,CAAC,QAAQ,CAAS;IACzB,IAAI,OAAO,IAAI,OAAO,CAErB;IACD,IAAI,OAAO,CAAC,KAAK,EAAE,OAAO,EAGzB;IAED,YACC,GAAG,EAAE,GAAG,EACR,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,MAAM,KAAK,IAAI,EACxD,oBAAoB,CAAC,EAAE,MAAM,EAC7B,aAAa,CAAC,EAAE,MAAM,EAmCtB;IAED,IAAI,MAAM,IAAI,WAAW,CAExB;IAED,OAAO,CAAC,MAAM;IAUd;;OAEG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAoBjD;IAED;;OAEG;IACH,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAW/C;IAED;;;OAGG;IACH,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAsBjE;IAED;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAS9B;IAED;;OAEG;IACH,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAKjC;IAED;;OAEG;IACH,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAGlC;IAED,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAU9B;CACD","sourcesContent":["import { getOAuthProviders } from \"@openeryc/pi-ai/oauth\";\nimport { Container, type Focusable, getKeybindings, Input, Spacer, Text, type TUI } from \"@openeryc/pi-tui\";\nimport { exec } from \"child_process\";\nimport { theme } from \"../theme/theme.ts\";\nimport { DynamicBorder } from \"./dynamic-border.ts\";\nimport { keyHint } from \"./keybinding-hints.ts\";\n\n/**\n * Login dialog component - replaces editor during OAuth login flow\n */\nexport class LoginDialogComponent extends Container implements Focusable {\n\tprivate contentContainer: Container;\n\tprivate input: Input;\n\tprivate tui: TUI;\n\tprivate abortController = new AbortController();\n\tprivate inputResolver?: (value: string) => void;\n\tprivate inputRejecter?: (error: Error) => void;\n\tprivate onComplete: (success: boolean, message?: string) => void;\n\n\t// Focusable implementation - propagate to input for IME cursor positioning\n\tprivate _focused = false;\n\tget focused(): boolean {\n\t\treturn this._focused;\n\t}\n\tset focused(value: boolean) {\n\t\tthis._focused = value;\n\t\tthis.input.focused = value;\n\t}\n\n\tconstructor(\n\t\ttui: TUI,\n\t\tproviderId: string,\n\t\tonComplete: (success: boolean, message?: string) => void,\n\t\tproviderNameOverride?: string,\n\t\ttitleOverride?: string,\n\t) {\n\t\tsuper();\n\t\tthis.tui = tui;\n\t\tthis.onComplete = onComplete;\n\n\t\tconst providerInfo = getOAuthProviders().find((p) => p.id === providerId);\n\t\tconst providerName = providerNameOverride || providerInfo?.name || providerId;\n\t\tconst title = titleOverride ?? `Login to ${providerName}`;\n\n\t\t// Top border\n\t\tthis.addChild(new DynamicBorder());\n\n\t\t// Title\n\t\tthis.addChild(new Text(theme.fg(\"accent\", theme.bold(title)), 1, 0));\n\n\t\t// Dynamic content area\n\t\tthis.contentContainer = new Container();\n\t\tthis.addChild(this.contentContainer);\n\n\t\t// Input (always present, used when needed)\n\t\tthis.input = new Input();\n\t\tthis.input.onSubmit = () => {\n\t\t\tif (this.inputResolver) {\n\t\t\t\tthis.inputResolver(this.input.getValue());\n\t\t\t\tthis.inputResolver = undefined;\n\t\t\t\tthis.inputRejecter = undefined;\n\t\t\t}\n\t\t};\n\t\tthis.input.onEscape = () => {\n\t\t\tthis.cancel();\n\t\t};\n\n\t\t// Bottom border\n\t\tthis.addChild(new DynamicBorder());\n\t}\n\n\tget signal(): AbortSignal {\n\t\treturn this.abortController.signal;\n\t}\n\n\tprivate cancel(): void {\n\t\tthis.abortController.abort();\n\t\tif (this.inputRejecter) {\n\t\t\tthis.inputRejecter(new Error(\"Login cancelled\"));\n\t\t\tthis.inputResolver = undefined;\n\t\t\tthis.inputRejecter = undefined;\n\t\t}\n\t\tthis.onComplete(false, \"Login cancelled\");\n\t}\n\n\t/**\n\t * Called by onAuth callback - show URL and optional instructions\n\t */\n\tshowAuth(url: string, instructions?: string): void {\n\t\tthis.contentContainer.clear();\n\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\tconst linkedUrl = `\\x1b]8;;${url}\\x07${url}\\x1b]8;;\\x07`;\n\t\tthis.contentContainer.addChild(new Text(theme.fg(\"accent\", linkedUrl), 1, 0));\n\n\t\tconst clickHint = process.platform === \"darwin\" ? \"Cmd+click to open\" : \"Ctrl+click to open\";\n\t\tconst hyperlink = `\\x1b]8;;${url}\\x07${clickHint}\\x1b]8;;\\x07`;\n\t\tthis.contentContainer.addChild(new Text(theme.fg(\"dim\", hyperlink), 1, 0));\n\n\t\tif (instructions) {\n\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\tthis.contentContainer.addChild(new Text(theme.fg(\"warning\", instructions), 1, 0));\n\t\t}\n\n\t\t// Try to open browser\n\t\tconst openCmd = process.platform === \"darwin\" ? \"open\" : process.platform === \"win32\" ? \"start\" : \"xdg-open\";\n\t\texec(`${openCmd} \"${url}\"`);\n\n\t\tthis.tui.requestRender();\n\t}\n\n\t/**\n\t * Show input for manual code/URL entry (for callback server providers)\n\t */\n\tshowManualInput(prompt: string): Promise<string> {\n\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\tthis.contentContainer.addChild(new Text(theme.fg(\"dim\", prompt), 1, 0));\n\t\tthis.contentContainer.addChild(this.input);\n\t\tthis.contentContainer.addChild(new Text(`(${keyHint(\"tui.select.cancel\", \"to cancel\")})`, 1, 0));\n\t\tthis.tui.requestRender();\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tthis.inputResolver = resolve;\n\t\t\tthis.inputRejecter = reject;\n\t\t});\n\t}\n\n\t/**\n\t * Called by onPrompt callback - show prompt and wait for input\n\t * Note: Does NOT clear content, appends to existing (preserves URL from showAuth)\n\t */\n\tshowPrompt(message: string, placeholder?: string): Promise<string> {\n\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\tthis.contentContainer.addChild(new Text(theme.fg(\"text\", message), 1, 0));\n\t\tif (placeholder) {\n\t\t\tthis.contentContainer.addChild(new Text(theme.fg(\"dim\", `e.g., ${placeholder}`), 1, 0));\n\t\t}\n\t\tthis.contentContainer.addChild(this.input);\n\t\tthis.contentContainer.addChild(\n\t\t\tnew Text(\n\t\t\t\t`(${keyHint(\"tui.select.cancel\", \"to cancel,\")} ${keyHint(\"tui.select.confirm\", \"to submit\")})`,\n\t\t\t\t1,\n\t\t\t\t0,\n\t\t\t),\n\t\t);\n\n\t\tthis.input.setValue(\"\");\n\t\tthis.tui.requestRender();\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tthis.inputResolver = resolve;\n\t\t\tthis.inputRejecter = reject;\n\t\t});\n\t}\n\n\t/**\n\t * Show informational text without prompting for input.\n\t */\n\tshowInfo(lines: string[]): void {\n\t\tthis.contentContainer.clear();\n\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\tfor (const line of lines) {\n\t\t\tthis.contentContainer.addChild(new Text(line, 1, 0));\n\t\t}\n\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\tthis.contentContainer.addChild(new Text(`(${keyHint(\"tui.select.cancel\", \"to close\")})`, 1, 0));\n\t\tthis.tui.requestRender();\n\t}\n\n\t/**\n\t * Show waiting message (for polling flows like GitHub Copilot)\n\t */\n\tshowWaiting(message: string): void {\n\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\tthis.contentContainer.addChild(new Text(theme.fg(\"dim\", message), 1, 0));\n\t\tthis.contentContainer.addChild(new Text(`(${keyHint(\"tui.select.cancel\", \"to cancel\")})`, 1, 0));\n\t\tthis.tui.requestRender();\n\t}\n\n\t/**\n\t * Called by onProgress callback\n\t */\n\tshowProgress(message: string): void {\n\t\tthis.contentContainer.addChild(new Text(theme.fg(\"dim\", message), 1, 0));\n\t\tthis.tui.requestRender();\n\t}\n\n\thandleInput(data: string): void {\n\t\tconst kb = getKeybindings();\n\n\t\tif (kb.matches(data, \"tui.select.cancel\")) {\n\t\t\tthis.cancel();\n\t\t\treturn;\n\t\t}\n\n\t\t// Pass to input\n\t\tthis.input.handleInput(data);\n\t}\n}\n"]}
@@ -1,160 +0,0 @@
1
- import { getOAuthProviders } from "@openeryc/pi-ai/oauth";
2
- import { Container, getKeybindings, Input, Spacer, Text } from "@openeryc/pi-tui";
3
- import { exec } from "child_process";
4
- import { theme } from "../theme/theme.js";
5
- import { DynamicBorder } from "./dynamic-border.js";
6
- import { keyHint } from "./keybinding-hints.js";
7
- /**
8
- * Login dialog component - replaces editor during OAuth login flow
9
- */
10
- export class LoginDialogComponent extends Container {
11
- contentContainer;
12
- input;
13
- tui;
14
- abortController = new AbortController();
15
- inputResolver;
16
- inputRejecter;
17
- onComplete;
18
- // Focusable implementation - propagate to input for IME cursor positioning
19
- _focused = false;
20
- get focused() {
21
- return this._focused;
22
- }
23
- set focused(value) {
24
- this._focused = value;
25
- this.input.focused = value;
26
- }
27
- constructor(tui, providerId, onComplete, providerNameOverride, titleOverride) {
28
- super();
29
- this.tui = tui;
30
- this.onComplete = onComplete;
31
- const providerInfo = getOAuthProviders().find((p) => p.id === providerId);
32
- const providerName = providerNameOverride || providerInfo?.name || providerId;
33
- const title = titleOverride ?? `Login to ${providerName}`;
34
- // Top border
35
- this.addChild(new DynamicBorder());
36
- // Title
37
- this.addChild(new Text(theme.fg("accent", theme.bold(title)), 1, 0));
38
- // Dynamic content area
39
- this.contentContainer = new Container();
40
- this.addChild(this.contentContainer);
41
- // Input (always present, used when needed)
42
- this.input = new Input();
43
- this.input.onSubmit = () => {
44
- if (this.inputResolver) {
45
- this.inputResolver(this.input.getValue());
46
- this.inputResolver = undefined;
47
- this.inputRejecter = undefined;
48
- }
49
- };
50
- this.input.onEscape = () => {
51
- this.cancel();
52
- };
53
- // Bottom border
54
- this.addChild(new DynamicBorder());
55
- }
56
- get signal() {
57
- return this.abortController.signal;
58
- }
59
- cancel() {
60
- this.abortController.abort();
61
- if (this.inputRejecter) {
62
- this.inputRejecter(new Error("Login cancelled"));
63
- this.inputResolver = undefined;
64
- this.inputRejecter = undefined;
65
- }
66
- this.onComplete(false, "Login cancelled");
67
- }
68
- /**
69
- * Called by onAuth callback - show URL and optional instructions
70
- */
71
- showAuth(url, instructions) {
72
- this.contentContainer.clear();
73
- this.contentContainer.addChild(new Spacer(1));
74
- const linkedUrl = `\x1b]8;;${url}\x07${url}\x1b]8;;\x07`;
75
- this.contentContainer.addChild(new Text(theme.fg("accent", linkedUrl), 1, 0));
76
- const clickHint = process.platform === "darwin" ? "Cmd+click to open" : "Ctrl+click to open";
77
- const hyperlink = `\x1b]8;;${url}\x07${clickHint}\x1b]8;;\x07`;
78
- this.contentContainer.addChild(new Text(theme.fg("dim", hyperlink), 1, 0));
79
- if (instructions) {
80
- this.contentContainer.addChild(new Spacer(1));
81
- this.contentContainer.addChild(new Text(theme.fg("warning", instructions), 1, 0));
82
- }
83
- // Try to open browser
84
- const openCmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
85
- exec(`${openCmd} "${url}"`);
86
- this.tui.requestRender();
87
- }
88
- /**
89
- * Show input for manual code/URL entry (for callback server providers)
90
- */
91
- showManualInput(prompt) {
92
- this.contentContainer.addChild(new Spacer(1));
93
- this.contentContainer.addChild(new Text(theme.fg("dim", prompt), 1, 0));
94
- this.contentContainer.addChild(this.input);
95
- this.contentContainer.addChild(new Text(`(${keyHint("tui.select.cancel", "to cancel")})`, 1, 0));
96
- this.tui.requestRender();
97
- return new Promise((resolve, reject) => {
98
- this.inputResolver = resolve;
99
- this.inputRejecter = reject;
100
- });
101
- }
102
- /**
103
- * Called by onPrompt callback - show prompt and wait for input
104
- * Note: Does NOT clear content, appends to existing (preserves URL from showAuth)
105
- */
106
- showPrompt(message, placeholder) {
107
- this.contentContainer.addChild(new Spacer(1));
108
- this.contentContainer.addChild(new Text(theme.fg("text", message), 1, 0));
109
- if (placeholder) {
110
- this.contentContainer.addChild(new Text(theme.fg("dim", `e.g., ${placeholder}`), 1, 0));
111
- }
112
- this.contentContainer.addChild(this.input);
113
- this.contentContainer.addChild(new Text(`(${keyHint("tui.select.cancel", "to cancel,")} ${keyHint("tui.select.confirm", "to submit")})`, 1, 0));
114
- this.input.setValue("");
115
- this.tui.requestRender();
116
- return new Promise((resolve, reject) => {
117
- this.inputResolver = resolve;
118
- this.inputRejecter = reject;
119
- });
120
- }
121
- /**
122
- * Show informational text without prompting for input.
123
- */
124
- showInfo(lines) {
125
- this.contentContainer.clear();
126
- this.contentContainer.addChild(new Spacer(1));
127
- for (const line of lines) {
128
- this.contentContainer.addChild(new Text(line, 1, 0));
129
- }
130
- this.contentContainer.addChild(new Spacer(1));
131
- this.contentContainer.addChild(new Text(`(${keyHint("tui.select.cancel", "to close")})`, 1, 0));
132
- this.tui.requestRender();
133
- }
134
- /**
135
- * Show waiting message (for polling flows like GitHub Copilot)
136
- */
137
- showWaiting(message) {
138
- this.contentContainer.addChild(new Spacer(1));
139
- this.contentContainer.addChild(new Text(theme.fg("dim", message), 1, 0));
140
- this.contentContainer.addChild(new Text(`(${keyHint("tui.select.cancel", "to cancel")})`, 1, 0));
141
- this.tui.requestRender();
142
- }
143
- /**
144
- * Called by onProgress callback
145
- */
146
- showProgress(message) {
147
- this.contentContainer.addChild(new Text(theme.fg("dim", message), 1, 0));
148
- this.tui.requestRender();
149
- }
150
- handleInput(data) {
151
- const kb = getKeybindings();
152
- if (kb.matches(data, "tui.select.cancel")) {
153
- this.cancel();
154
- return;
155
- }
156
- // Pass to input
157
- this.input.handleInput(data);
158
- }
159
- }
160
- //# sourceMappingURL=login-dialog.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"login-dialog.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/login-dialog.ts"],"names":[],"mappings":"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","sourcesContent":["import { getOAuthProviders } from \"@openeryc/pi-ai/oauth\";\nimport { Container, type Focusable, getKeybindings, Input, Spacer, Text, type TUI } from \"@openeryc/pi-tui\";\nimport { exec } from \"child_process\";\nimport { theme } from \"../theme/theme.ts\";\nimport { DynamicBorder } from \"./dynamic-border.ts\";\nimport { keyHint } from \"./keybinding-hints.ts\";\n\n/**\n * Login dialog component - replaces editor during OAuth login flow\n */\nexport class LoginDialogComponent extends Container implements Focusable {\n\tprivate contentContainer: Container;\n\tprivate input: Input;\n\tprivate tui: TUI;\n\tprivate abortController = new AbortController();\n\tprivate inputResolver?: (value: string) => void;\n\tprivate inputRejecter?: (error: Error) => void;\n\tprivate onComplete: (success: boolean, message?: string) => void;\n\n\t// Focusable implementation - propagate to input for IME cursor positioning\n\tprivate _focused = false;\n\tget focused(): boolean {\n\t\treturn this._focused;\n\t}\n\tset focused(value: boolean) {\n\t\tthis._focused = value;\n\t\tthis.input.focused = value;\n\t}\n\n\tconstructor(\n\t\ttui: TUI,\n\t\tproviderId: string,\n\t\tonComplete: (success: boolean, message?: string) => void,\n\t\tproviderNameOverride?: string,\n\t\ttitleOverride?: string,\n\t) {\n\t\tsuper();\n\t\tthis.tui = tui;\n\t\tthis.onComplete = onComplete;\n\n\t\tconst providerInfo = getOAuthProviders().find((p) => p.id === providerId);\n\t\tconst providerName = providerNameOverride || providerInfo?.name || providerId;\n\t\tconst title = titleOverride ?? `Login to ${providerName}`;\n\n\t\t// Top border\n\t\tthis.addChild(new DynamicBorder());\n\n\t\t// Title\n\t\tthis.addChild(new Text(theme.fg(\"accent\", theme.bold(title)), 1, 0));\n\n\t\t// Dynamic content area\n\t\tthis.contentContainer = new Container();\n\t\tthis.addChild(this.contentContainer);\n\n\t\t// Input (always present, used when needed)\n\t\tthis.input = new Input();\n\t\tthis.input.onSubmit = () => {\n\t\t\tif (this.inputResolver) {\n\t\t\t\tthis.inputResolver(this.input.getValue());\n\t\t\t\tthis.inputResolver = undefined;\n\t\t\t\tthis.inputRejecter = undefined;\n\t\t\t}\n\t\t};\n\t\tthis.input.onEscape = () => {\n\t\t\tthis.cancel();\n\t\t};\n\n\t\t// Bottom border\n\t\tthis.addChild(new DynamicBorder());\n\t}\n\n\tget signal(): AbortSignal {\n\t\treturn this.abortController.signal;\n\t}\n\n\tprivate cancel(): void {\n\t\tthis.abortController.abort();\n\t\tif (this.inputRejecter) {\n\t\t\tthis.inputRejecter(new Error(\"Login cancelled\"));\n\t\t\tthis.inputResolver = undefined;\n\t\t\tthis.inputRejecter = undefined;\n\t\t}\n\t\tthis.onComplete(false, \"Login cancelled\");\n\t}\n\n\t/**\n\t * Called by onAuth callback - show URL and optional instructions\n\t */\n\tshowAuth(url: string, instructions?: string): void {\n\t\tthis.contentContainer.clear();\n\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\tconst linkedUrl = `\\x1b]8;;${url}\\x07${url}\\x1b]8;;\\x07`;\n\t\tthis.contentContainer.addChild(new Text(theme.fg(\"accent\", linkedUrl), 1, 0));\n\n\t\tconst clickHint = process.platform === \"darwin\" ? \"Cmd+click to open\" : \"Ctrl+click to open\";\n\t\tconst hyperlink = `\\x1b]8;;${url}\\x07${clickHint}\\x1b]8;;\\x07`;\n\t\tthis.contentContainer.addChild(new Text(theme.fg(\"dim\", hyperlink), 1, 0));\n\n\t\tif (instructions) {\n\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\tthis.contentContainer.addChild(new Text(theme.fg(\"warning\", instructions), 1, 0));\n\t\t}\n\n\t\t// Try to open browser\n\t\tconst openCmd = process.platform === \"darwin\" ? \"open\" : process.platform === \"win32\" ? \"start\" : \"xdg-open\";\n\t\texec(`${openCmd} \"${url}\"`);\n\n\t\tthis.tui.requestRender();\n\t}\n\n\t/**\n\t * Show input for manual code/URL entry (for callback server providers)\n\t */\n\tshowManualInput(prompt: string): Promise<string> {\n\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\tthis.contentContainer.addChild(new Text(theme.fg(\"dim\", prompt), 1, 0));\n\t\tthis.contentContainer.addChild(this.input);\n\t\tthis.contentContainer.addChild(new Text(`(${keyHint(\"tui.select.cancel\", \"to cancel\")})`, 1, 0));\n\t\tthis.tui.requestRender();\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tthis.inputResolver = resolve;\n\t\t\tthis.inputRejecter = reject;\n\t\t});\n\t}\n\n\t/**\n\t * Called by onPrompt callback - show prompt and wait for input\n\t * Note: Does NOT clear content, appends to existing (preserves URL from showAuth)\n\t */\n\tshowPrompt(message: string, placeholder?: string): Promise<string> {\n\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\tthis.contentContainer.addChild(new Text(theme.fg(\"text\", message), 1, 0));\n\t\tif (placeholder) {\n\t\t\tthis.contentContainer.addChild(new Text(theme.fg(\"dim\", `e.g., ${placeholder}`), 1, 0));\n\t\t}\n\t\tthis.contentContainer.addChild(this.input);\n\t\tthis.contentContainer.addChild(\n\t\t\tnew Text(\n\t\t\t\t`(${keyHint(\"tui.select.cancel\", \"to cancel,\")} ${keyHint(\"tui.select.confirm\", \"to submit\")})`,\n\t\t\t\t1,\n\t\t\t\t0,\n\t\t\t),\n\t\t);\n\n\t\tthis.input.setValue(\"\");\n\t\tthis.tui.requestRender();\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tthis.inputResolver = resolve;\n\t\t\tthis.inputRejecter = reject;\n\t\t});\n\t}\n\n\t/**\n\t * Show informational text without prompting for input.\n\t */\n\tshowInfo(lines: string[]): void {\n\t\tthis.contentContainer.clear();\n\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\tfor (const line of lines) {\n\t\t\tthis.contentContainer.addChild(new Text(line, 1, 0));\n\t\t}\n\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\tthis.contentContainer.addChild(new Text(`(${keyHint(\"tui.select.cancel\", \"to close\")})`, 1, 0));\n\t\tthis.tui.requestRender();\n\t}\n\n\t/**\n\t * Show waiting message (for polling flows like GitHub Copilot)\n\t */\n\tshowWaiting(message: string): void {\n\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\tthis.contentContainer.addChild(new Text(theme.fg(\"dim\", message), 1, 0));\n\t\tthis.contentContainer.addChild(new Text(`(${keyHint(\"tui.select.cancel\", \"to cancel\")})`, 1, 0));\n\t\tthis.tui.requestRender();\n\t}\n\n\t/**\n\t * Called by onProgress callback\n\t */\n\tshowProgress(message: string): void {\n\t\tthis.contentContainer.addChild(new Text(theme.fg(\"dim\", message), 1, 0));\n\t\tthis.tui.requestRender();\n\t}\n\n\thandleInput(data: string): void {\n\t\tconst kb = getKeybindings();\n\n\t\tif (kb.matches(data, \"tui.select.cancel\")) {\n\t\t\tthis.cancel();\n\t\t\treturn;\n\t\t}\n\n\t\t// Pass to input\n\t\tthis.input.handleInput(data);\n\t}\n}\n"]}
@@ -1,47 +0,0 @@
1
- import { type Model } from "@openeryc/pi-ai";
2
- import { Container, type Focusable, Input, type TUI } from "@openeryc/pi-tui";
3
- import type { ModelRegistry } from "../../../core/model-registry.ts";
4
- import type { SettingsManager } from "../../../core/settings-manager.ts";
5
- interface ScopedModelItem {
6
- model: Model<any>;
7
- thinkingLevel?: string;
8
- }
9
- /**
10
- * Component that renders a model selector with search
11
- */
12
- export declare class ModelSelectorComponent extends Container implements Focusable {
13
- private searchInput;
14
- private _focused;
15
- get focused(): boolean;
16
- set focused(value: boolean);
17
- private listContainer;
18
- private allModels;
19
- private scopedModelItems;
20
- private activeModels;
21
- private filteredModels;
22
- private selectedIndex;
23
- private currentModel?;
24
- private settingsManager;
25
- private modelRegistry;
26
- private onSelectCallback;
27
- private onCancelCallback;
28
- private errorMessage?;
29
- private tui;
30
- private scopedModels;
31
- private scope;
32
- private scopeText?;
33
- private scopeHintText?;
34
- constructor(tui: TUI, currentModel: Model<any> | undefined, settingsManager: SettingsManager, modelRegistry: ModelRegistry, scopedModels: ReadonlyArray<ScopedModelItem>, onSelect: (model: Model<any>) => void, onCancel: () => void, initialSearchInput?: string);
35
- private loadModels;
36
- private sortModels;
37
- private getScopeText;
38
- private getScopeHintText;
39
- private setScope;
40
- private filterModels;
41
- private updateList;
42
- handleInput(keyData: string): void;
43
- private handleSelect;
44
- getSearchInput(): Input;
45
- }
46
- export {};
47
- //# sourceMappingURL=model-selector.d.ts.map