@dsh-cc/tui 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (363) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +144 -0
  3. package/lib/bash-history.d.ts +31 -0
  4. package/lib/bash-history.d.ts.map +1 -0
  5. package/lib/bash-history.js +94 -0
  6. package/lib/bash-history.js.map +1 -0
  7. package/lib/compact-fold.d.ts +35 -0
  8. package/lib/compact-fold.d.ts.map +1 -0
  9. package/lib/compact-fold.js +60 -0
  10. package/lib/compact-fold.js.map +1 -0
  11. package/lib/components/arg-completers.d.ts +22 -0
  12. package/lib/components/arg-completers.d.ts.map +1 -0
  13. package/lib/components/arg-completers.js +75 -0
  14. package/lib/components/arg-completers.js.map +1 -0
  15. package/lib/components/code-theme.d.ts +25 -0
  16. package/lib/components/code-theme.d.ts.map +1 -0
  17. package/lib/components/code-theme.js +137 -0
  18. package/lib/components/code-theme.js.map +1 -0
  19. package/lib/components/completion.d.ts +50 -0
  20. package/lib/components/completion.d.ts.map +1 -0
  21. package/lib/components/completion.js +279 -0
  22. package/lib/components/completion.js.map +1 -0
  23. package/lib/components/diff-card.d.ts +29 -0
  24. package/lib/components/diff-card.d.ts.map +1 -0
  25. package/lib/components/diff-card.js +175 -0
  26. package/lib/components/diff-card.js.map +1 -0
  27. package/lib/components/diff-hunks.d.ts +44 -0
  28. package/lib/components/diff-hunks.d.ts.map +1 -0
  29. package/lib/components/diff-hunks.js +188 -0
  30. package/lib/components/diff-hunks.js.map +1 -0
  31. package/lib/components/editor-history.d.ts +23 -0
  32. package/lib/components/editor-history.d.ts.map +1 -0
  33. package/lib/components/editor-history.js +29 -0
  34. package/lib/components/editor-history.js.map +1 -0
  35. package/lib/components/markdown-theme.d.ts +11 -0
  36. package/lib/components/markdown-theme.d.ts.map +1 -0
  37. package/lib/components/markdown-theme.js +29 -0
  38. package/lib/components/markdown-theme.js.map +1 -0
  39. package/lib/components/masked-input.d.ts +24 -0
  40. package/lib/components/masked-input.d.ts.map +1 -0
  41. package/lib/components/masked-input.js +168 -0
  42. package/lib/components/masked-input.js.map +1 -0
  43. package/lib/components/overlay-host.d.ts +31 -0
  44. package/lib/components/overlay-host.d.ts.map +1 -0
  45. package/lib/components/overlay-host.js +128 -0
  46. package/lib/components/overlay-host.js.map +1 -0
  47. package/lib/components/overlays.d.ts +94 -0
  48. package/lib/components/overlays.d.ts.map +1 -0
  49. package/lib/components/overlays.js +450 -0
  50. package/lib/components/overlays.js.map +1 -0
  51. package/lib/components/provider-box.d.ts +23 -0
  52. package/lib/components/provider-box.d.ts.map +1 -0
  53. package/lib/components/provider-box.js +164 -0
  54. package/lib/components/provider-box.js.map +1 -0
  55. package/lib/components/read-group.d.ts +51 -0
  56. package/lib/components/read-group.d.ts.map +1 -0
  57. package/lib/components/read-group.js +105 -0
  58. package/lib/components/read-group.js.map +1 -0
  59. package/lib/components/root-bash.d.ts +36 -0
  60. package/lib/components/root-bash.d.ts.map +1 -0
  61. package/lib/components/root-bash.js +112 -0
  62. package/lib/components/root-bash.js.map +1 -0
  63. package/lib/components/root-types.d.ts +42 -0
  64. package/lib/components/root-types.d.ts.map +1 -0
  65. package/lib/components/root-types.js +8 -0
  66. package/lib/components/root-types.js.map +1 -0
  67. package/lib/components/root-utils.d.ts +22 -0
  68. package/lib/components/root-utils.d.ts.map +1 -0
  69. package/lib/components/root-utils.js +45 -0
  70. package/lib/components/root-utils.js.map +1 -0
  71. package/lib/components/root.d.ts +25 -0
  72. package/lib/components/root.d.ts.map +1 -0
  73. package/lib/components/root.js +357 -0
  74. package/lib/components/root.js.map +1 -0
  75. package/lib/components/theme.d.ts +61 -0
  76. package/lib/components/theme.d.ts.map +1 -0
  77. package/lib/components/theme.js +99 -0
  78. package/lib/components/theme.js.map +1 -0
  79. package/lib/components/transcript.d.ts +43 -0
  80. package/lib/components/transcript.d.ts.map +1 -0
  81. package/lib/components/transcript.js +203 -0
  82. package/lib/components/transcript.js.map +1 -0
  83. package/lib/components/working-line.d.ts +35 -0
  84. package/lib/components/working-line.d.ts.map +1 -0
  85. package/lib/components/working-line.js +66 -0
  86. package/lib/components/working-line.js.map +1 -0
  87. package/lib/effort-catalog.d.ts +27 -0
  88. package/lib/effort-catalog.d.ts.map +1 -0
  89. package/lib/effort-catalog.js +36 -0
  90. package/lib/effort-catalog.js.map +1 -0
  91. package/lib/export-markdown.d.ts +18 -0
  92. package/lib/export-markdown.d.ts.map +1 -0
  93. package/lib/export-markdown.js +124 -0
  94. package/lib/export-markdown.js.map +1 -0
  95. package/lib/harness/approval-preview.d.ts +33 -0
  96. package/lib/harness/approval-preview.d.ts.map +1 -0
  97. package/lib/harness/approval-preview.js +179 -0
  98. package/lib/harness/approval-preview.js.map +1 -0
  99. package/lib/harness/boot-banner.d.ts +14 -0
  100. package/lib/harness/boot-banner.d.ts.map +1 -0
  101. package/lib/harness/boot-banner.js +89 -0
  102. package/lib/harness/boot-banner.js.map +1 -0
  103. package/lib/harness/driver-agent.d.ts +78 -0
  104. package/lib/harness/driver-agent.d.ts.map +1 -0
  105. package/lib/harness/driver-agent.js +314 -0
  106. package/lib/harness/driver-agent.js.map +1 -0
  107. package/lib/harness/driver-agents.d.ts +20 -0
  108. package/lib/harness/driver-agents.d.ts.map +1 -0
  109. package/lib/harness/driver-agents.js +123 -0
  110. package/lib/harness/driver-agents.js.map +1 -0
  111. package/lib/harness/driver-approvals.d.ts +38 -0
  112. package/lib/harness/driver-approvals.d.ts.map +1 -0
  113. package/lib/harness/driver-approvals.js +277 -0
  114. package/lib/harness/driver-approvals.js.map +1 -0
  115. package/lib/harness/driver-bash.d.ts +15 -0
  116. package/lib/harness/driver-bash.d.ts.map +1 -0
  117. package/lib/harness/driver-bash.js +73 -0
  118. package/lib/harness/driver-bash.js.map +1 -0
  119. package/lib/harness/driver-catalog.d.ts +84 -0
  120. package/lib/harness/driver-catalog.d.ts.map +1 -0
  121. package/lib/harness/driver-catalog.js +256 -0
  122. package/lib/harness/driver-catalog.js.map +1 -0
  123. package/lib/harness/driver-ctx.d.ts +462 -0
  124. package/lib/harness/driver-ctx.d.ts.map +1 -0
  125. package/lib/harness/driver-ctx.js +11 -0
  126. package/lib/harness/driver-ctx.js.map +1 -0
  127. package/lib/harness/driver-hud.d.ts +31 -0
  128. package/lib/harness/driver-hud.d.ts.map +1 -0
  129. package/lib/harness/driver-hud.js +204 -0
  130. package/lib/harness/driver-hud.js.map +1 -0
  131. package/lib/harness/driver-live.d.ts +36 -0
  132. package/lib/harness/driver-live.d.ts.map +1 -0
  133. package/lib/harness/driver-live.js +44 -0
  134. package/lib/harness/driver-live.js.map +1 -0
  135. package/lib/harness/driver-modal.d.ts +52 -0
  136. package/lib/harness/driver-modal.d.ts.map +1 -0
  137. package/lib/harness/driver-modal.js +78 -0
  138. package/lib/harness/driver-modal.js.map +1 -0
  139. package/lib/harness/driver-mode.d.ts +35 -0
  140. package/lib/harness/driver-mode.d.ts.map +1 -0
  141. package/lib/harness/driver-mode.js +84 -0
  142. package/lib/harness/driver-mode.js.map +1 -0
  143. package/lib/harness/driver-pickers.d.ts +48 -0
  144. package/lib/harness/driver-pickers.d.ts.map +1 -0
  145. package/lib/harness/driver-pickers.js +249 -0
  146. package/lib/harness/driver-pickers.js.map +1 -0
  147. package/lib/harness/driver-promote.d.ts +29 -0
  148. package/lib/harness/driver-promote.d.ts.map +1 -0
  149. package/lib/harness/driver-promote.js +36 -0
  150. package/lib/harness/driver-promote.js.map +1 -0
  151. package/lib/harness/driver-queue.d.ts +19 -0
  152. package/lib/harness/driver-queue.d.ts.map +1 -0
  153. package/lib/harness/driver-queue.js +281 -0
  154. package/lib/harness/driver-queue.js.map +1 -0
  155. package/lib/harness/driver-run-local.d.ts +32 -0
  156. package/lib/harness/driver-run-local.d.ts.map +1 -0
  157. package/lib/harness/driver-run-local.js +366 -0
  158. package/lib/harness/driver-run-local.js.map +1 -0
  159. package/lib/harness/driver-sessions.d.ts +28 -0
  160. package/lib/harness/driver-sessions.d.ts.map +1 -0
  161. package/lib/harness/driver-sessions.js +386 -0
  162. package/lib/harness/driver-sessions.js.map +1 -0
  163. package/lib/harness/driver.d.ts +22 -0
  164. package/lib/harness/driver.d.ts.map +1 -0
  165. package/lib/harness/driver.js +459 -0
  166. package/lib/harness/driver.js.map +1 -0
  167. package/lib/harness/preset.d.ts +32 -0
  168. package/lib/harness/preset.d.ts.map +1 -0
  169. package/lib/harness/preset.js +34 -0
  170. package/lib/harness/preset.js.map +1 -0
  171. package/lib/harness/session-list.d.ts +65 -0
  172. package/lib/harness/session-list.d.ts.map +1 -0
  173. package/lib/harness/session-list.js +91 -0
  174. package/lib/harness/session-list.js.map +1 -0
  175. package/lib/harness/shell-output.d.ts +44 -0
  176. package/lib/harness/shell-output.d.ts.map +1 -0
  177. package/lib/harness/shell-output.js +90 -0
  178. package/lib/harness/shell-output.js.map +1 -0
  179. package/lib/harness/statusline-cc-transcript.d.ts +51 -0
  180. package/lib/harness/statusline-cc-transcript.d.ts.map +1 -0
  181. package/lib/harness/statusline-cc-transcript.js +191 -0
  182. package/lib/harness/statusline-cc-transcript.js.map +1 -0
  183. package/lib/harness/statusline-command.d.ts +54 -0
  184. package/lib/harness/statusline-command.d.ts.map +1 -0
  185. package/lib/harness/statusline-command.js +161 -0
  186. package/lib/harness/statusline-command.js.map +1 -0
  187. package/lib/harness/statusline-payload.d.ts +79 -0
  188. package/lib/harness/statusline-payload.d.ts.map +1 -0
  189. package/lib/harness/statusline-payload.js +93 -0
  190. package/lib/harness/statusline-payload.js.map +1 -0
  191. package/lib/harness/statusline-settings.d.ts +47 -0
  192. package/lib/harness/statusline-settings.d.ts.map +1 -0
  193. package/lib/harness/statusline-settings.js +57 -0
  194. package/lib/harness/statusline-settings.js.map +1 -0
  195. package/lib/harness/statusline-wiring.d.ts +45 -0
  196. package/lib/harness/statusline-wiring.d.ts.map +1 -0
  197. package/lib/harness/statusline-wiring.js +247 -0
  198. package/lib/harness/statusline-wiring.js.map +1 -0
  199. package/lib/harness/usage-view.d.ts +84 -0
  200. package/lib/harness/usage-view.d.ts.map +1 -0
  201. package/lib/harness/usage-view.js +199 -0
  202. package/lib/harness/usage-view.js.map +1 -0
  203. package/lib/harness/worktree-exit.d.ts +105 -0
  204. package/lib/harness/worktree-exit.d.ts.map +1 -0
  205. package/lib/harness/worktree-exit.js +168 -0
  206. package/lib/harness/worktree-exit.js.map +1 -0
  207. package/lib/history.d.ts +50 -0
  208. package/lib/history.d.ts.map +1 -0
  209. package/lib/history.js +139 -0
  210. package/lib/history.js.map +1 -0
  211. package/lib/index.d.ts +63 -0
  212. package/lib/index.d.ts.map +1 -0
  213. package/lib/index.js +54 -0
  214. package/lib/index.js.map +1 -0
  215. package/lib/input.d.ts +158 -0
  216. package/lib/input.d.ts.map +1 -0
  217. package/lib/input.js +400 -0
  218. package/lib/input.js.map +1 -0
  219. package/lib/invariant.d.ts +14 -0
  220. package/lib/invariant.d.ts.map +1 -0
  221. package/lib/invariant.js +20 -0
  222. package/lib/invariant.js.map +1 -0
  223. package/lib/mode-cycle.d.ts +22 -0
  224. package/lib/mode-cycle.d.ts.map +1 -0
  225. package/lib/mode-cycle.js +32 -0
  226. package/lib/mode-cycle.js.map +1 -0
  227. package/lib/model-catalog.d.ts +22 -0
  228. package/lib/model-catalog.d.ts.map +1 -0
  229. package/lib/model-catalog.js +45 -0
  230. package/lib/model-catalog.js.map +1 -0
  231. package/lib/packaged-preset.d.ts +32 -0
  232. package/lib/packaged-preset.d.ts.map +1 -0
  233. package/lib/packaged-preset.js +94 -0
  234. package/lib/packaged-preset.js.map +1 -0
  235. package/lib/plugin.d.ts +11 -0
  236. package/lib/plugin.d.ts.map +1 -0
  237. package/lib/plugin.js +88 -0
  238. package/lib/plugin.js.map +1 -0
  239. package/lib/profile.d.ts +4 -0
  240. package/lib/profile.d.ts.map +1 -0
  241. package/lib/profile.js +7 -0
  242. package/lib/profile.js.map +1 -0
  243. package/lib/project-sessions.d.ts +29 -0
  244. package/lib/project-sessions.d.ts.map +1 -0
  245. package/lib/project-sessions.js +60 -0
  246. package/lib/project-sessions.js.map +1 -0
  247. package/lib/project.d.ts +75 -0
  248. package/lib/project.d.ts.map +1 -0
  249. package/lib/project.js +196 -0
  250. package/lib/project.js.map +1 -0
  251. package/lib/provider-actions.d.ts +37 -0
  252. package/lib/provider-actions.d.ts.map +1 -0
  253. package/lib/provider-actions.js +417 -0
  254. package/lib/provider-actions.js.map +1 -0
  255. package/lib/provider-command.d.ts +109 -0
  256. package/lib/provider-command.d.ts.map +1 -0
  257. package/lib/provider-command.js +220 -0
  258. package/lib/provider-command.js.map +1 -0
  259. package/lib/provider-detail.d.ts +15 -0
  260. package/lib/provider-detail.d.ts.map +1 -0
  261. package/lib/provider-detail.js +201 -0
  262. package/lib/provider-detail.js.map +1 -0
  263. package/lib/provider-flow.d.ts +191 -0
  264. package/lib/provider-flow.d.ts.map +1 -0
  265. package/lib/provider-flow.js +192 -0
  266. package/lib/provider-flow.js.map +1 -0
  267. package/lib/provider-presets.d.ts +32 -0
  268. package/lib/provider-presets.d.ts.map +1 -0
  269. package/lib/provider-presets.js +105 -0
  270. package/lib/provider-presets.js.map +1 -0
  271. package/lib/provider-read.d.ts +63 -0
  272. package/lib/provider-read.d.ts.map +1 -0
  273. package/lib/provider-read.js +115 -0
  274. package/lib/provider-read.js.map +1 -0
  275. package/lib/provider-settings.d.ts +30 -0
  276. package/lib/provider-settings.d.ts.map +1 -0
  277. package/lib/provider-settings.js +65 -0
  278. package/lib/provider-settings.js.map +1 -0
  279. package/lib/resume-target.d.ts +59 -0
  280. package/lib/resume-target.d.ts.map +1 -0
  281. package/lib/resume-target.js +143 -0
  282. package/lib/resume-target.js.map +1 -0
  283. package/lib/slash.d.ts +44 -0
  284. package/lib/slash.d.ts.map +1 -0
  285. package/lib/slash.js +81 -0
  286. package/lib/slash.js.map +1 -0
  287. package/lib/state/driver-types.d.ts +505 -0
  288. package/lib/state/driver-types.d.ts.map +1 -0
  289. package/lib/state/driver-types.js +8 -0
  290. package/lib/state/driver-types.js.map +1 -0
  291. package/lib/state/driver-usage-types.d.ts +59 -0
  292. package/lib/state/driver-usage-types.d.ts.map +1 -0
  293. package/lib/state/driver-usage-types.js +8 -0
  294. package/lib/state/driver-usage-types.js.map +1 -0
  295. package/lib/statusline.d.ts +63 -0
  296. package/lib/statusline.d.ts.map +1 -0
  297. package/lib/statusline.js +97 -0
  298. package/lib/statusline.js.map +1 -0
  299. package/lib/store/pickers.d.ts +34 -0
  300. package/lib/store/pickers.d.ts.map +1 -0
  301. package/lib/store/pickers.js +111 -0
  302. package/lib/store/pickers.js.map +1 -0
  303. package/lib/store/provider-panel.d.ts +107 -0
  304. package/lib/store/provider-panel.d.ts.map +1 -0
  305. package/lib/store/provider-panel.js +151 -0
  306. package/lib/store/provider-panel.js.map +1 -0
  307. package/lib/store/question.d.ts +21 -0
  308. package/lib/store/question.d.ts.map +1 -0
  309. package/lib/store/question.js +59 -0
  310. package/lib/store/question.js.map +1 -0
  311. package/lib/store/queue.d.ts +27 -0
  312. package/lib/store/queue.d.ts.map +1 -0
  313. package/lib/store/queue.js +34 -0
  314. package/lib/store/queue.js.map +1 -0
  315. package/lib/store/session.d.ts +73 -0
  316. package/lib/store/session.d.ts.map +1 -0
  317. package/lib/store/session.js +172 -0
  318. package/lib/store/session.js.map +1 -0
  319. package/lib/store/subagents.d.ts +16 -0
  320. package/lib/store/subagents.d.ts.map +1 -0
  321. package/lib/store/subagents.js +44 -0
  322. package/lib/store/subagents.js.map +1 -0
  323. package/lib/store/todos.d.ts +35 -0
  324. package/lib/store/todos.d.ts.map +1 -0
  325. package/lib/store/todos.js +68 -0
  326. package/lib/store/todos.js.map +1 -0
  327. package/lib/store/usage.d.ts +15 -0
  328. package/lib/store/usage.d.ts.map +1 -0
  329. package/lib/store/usage.js +27 -0
  330. package/lib/store/usage.js.map +1 -0
  331. package/lib/store/views.d.ts +419 -0
  332. package/lib/store/views.d.ts.map +1 -0
  333. package/lib/store/views.js +3 -0
  334. package/lib/store/views.js.map +1 -0
  335. package/lib/store.d.ts +19 -0
  336. package/lib/store.d.ts.map +1 -0
  337. package/lib/store.js +10 -0
  338. package/lib/store.js.map +1 -0
  339. package/lib/terminal/lease.d.ts +33 -0
  340. package/lib/terminal/lease.d.ts.map +1 -0
  341. package/lib/terminal/lease.js +99 -0
  342. package/lib/terminal/lease.js.map +1 -0
  343. package/lib/tool-card.d.ts +75 -0
  344. package/lib/tool-card.d.ts.map +1 -0
  345. package/lib/tool-card.js +109 -0
  346. package/lib/tool-card.js.map +1 -0
  347. package/lib/tool-verbs.d.ts +12 -0
  348. package/lib/tool-verbs.d.ts.map +1 -0
  349. package/lib/tool-verbs.js +29 -0
  350. package/lib/tool-verbs.js.map +1 -0
  351. package/lib/transcript.d.ts +40 -0
  352. package/lib/transcript.d.ts.map +1 -0
  353. package/lib/transcript.js +413 -0
  354. package/lib/transcript.js.map +1 -0
  355. package/lib/working-line.d.ts +44 -0
  356. package/lib/working-line.d.ts.map +1 -0
  357. package/lib/working-line.js +56 -0
  358. package/lib/working-line.js.map +1 -0
  359. package/package.json +72 -0
  360. package/presets/cc/.dsh-cc-managed.json +5 -0
  361. package/presets/cc/agent.cordis.yml +524 -0
  362. package/presets/cc/preset.yml +3 -0
  363. package/scripts/stage-preset.mjs +26 -0
@@ -0,0 +1,164 @@
1
+ /**
2
+ * `/provider` overlay box (design doc §4.2–§4.6): the two-section provider
3
+ * list with credential badges, the manage detail view (§4.4), the add /
4
+ * custom / rotate wizard phases (§4.3, §4.6), and the remove double-confirm.
5
+ * The wizard's live text entry is a real pi-tui `Input` owned by the runtime
6
+ * (provider-command.ts) and rendered inside this box when a text step is
7
+ * active; the box itself stays a pure function of the panel state.
8
+ * @module @dsh-cc/tui/components/provider-box
9
+ */
10
+ import { Container, Text } from '@dsh-cc/pi-tui';
11
+ import { defaultTheme } from "./theme.js";
12
+ /** Badge text for one row's credential state (§4.2). */
13
+ function badgeText(row) {
14
+ const credential = row.credential;
15
+ if (credential === undefined || credential.badge === 'missing')
16
+ return 'key ✗ missing';
17
+ return `key ✓ (${credential.badge})`;
18
+ }
19
+ const CUSTOM_PROTOCOLS = ['openai-completions', 'openai-responses', 'anthropic-messages'];
20
+ /** Render the live text field's lines inside the box (masked Input shows bullets). */
21
+ function renderField(box, field) {
22
+ if (field === undefined)
23
+ return;
24
+ for (const line of field.render(100))
25
+ box.addChild(new Text(line, 0, 0));
26
+ }
27
+ /**
28
+ * Provider list box: "Providers" title, then the Configured section (live
29
+ * settings dict, document order) and the Available section (presets), with
30
+ * `●`/`○` current markers, credential badges, model counts, ⚠ on configured
31
+ * routes with models but no key, and the directory tail collapsed under
32
+ * "More providers (…)".
33
+ */
34
+ export function createProviderPanelBox(view, theme = defaultTheme, field) {
35
+ const box = new Container();
36
+ if (view.phase === 'detail')
37
+ return detailBox(box, view, theme);
38
+ if (view.phase === 'wizard')
39
+ return wizardBox(box, view, theme, field);
40
+ if (view.phase === 'confirm-remove')
41
+ return confirmRemoveBox(box, view, theme);
42
+ box.addChild(new Text(theme.bold('Providers'), 0, 0));
43
+ const renderRow = (row, index) => {
44
+ const focused = view.phase === 'list' && view.cursor === index;
45
+ const marker = row.isCurrent ? '●' : '○';
46
+ const models = row.modelCount > 0 ? ` ${row.modelCount} models` : '';
47
+ const warning = row.credential?.warning === true ? ' ⚠' : '';
48
+ const prefix = focused ? '❯ ' : ' ';
49
+ box.addChild(new Text(`${prefix}${marker} ${row.route} ${row.displayName} ${badgeText(row)}${models}${warning}`, 0, 0));
50
+ };
51
+ // Rows arrive flat (configured block then available block); the section
52
+ // boundary is the first `available` row.
53
+ const split = view.rows.findIndex(row => row.section === 'available');
54
+ const configuredEnd = split === -1 ? view.rows.length : split;
55
+ box.addChild(new Text(theme.muted(' Configured'), 0, 0));
56
+ for (let index = 0; index < configuredEnd; index += 1)
57
+ renderRow(view.rows[index], index);
58
+ if (configuredEnd < view.rows.length) {
59
+ box.addChild(new Text(theme.muted(' Available'), 0, 0));
60
+ for (let index = configuredEnd; index < view.rows.length; index += 1)
61
+ renderRow(view.rows[index], index);
62
+ }
63
+ if (view.more.length > 0) {
64
+ box.addChild(new Text(` … More providers (${view.more.map(m => m.provider).join(', ')})`, 0, 0));
65
+ }
66
+ if (view.message !== undefined) {
67
+ box.addChild(new Text(theme.warning(view.message), 0, 0));
68
+ }
69
+ box.addChild(new Text(theme.muted('j/k move · enter open · n add custom · esc close'), 0, 0));
70
+ return box;
71
+ }
72
+ /** Detail view (§4.4): resolved facts + raw profile JSON + action rows. */
73
+ function detailBox(box, view, theme) {
74
+ box.addChild(new Text(theme.bold(`Provider ${view.selected ?? ''}`), 0, 0));
75
+ const detail = view.detail;
76
+ if (detail !== undefined) {
77
+ box.addChild(new Text(`endpoint ${detail.endpoint}`, 0, 0));
78
+ box.addChild(new Text(`protocol ${detail.api}`, 0, 0));
79
+ box.addChild(new Text(`models ${detail.modelCount}`, 0, 0));
80
+ box.addChild(new Text(`key ${detail.credentialLine}`, 0, 0));
81
+ box.addChild(new Text(theme.muted('profile (read-only):'), 0, 0));
82
+ for (const line of detail.profileJson.split('\n')) {
83
+ box.addChild(new Text(theme.muted(` ${line}`), 0, 0));
84
+ }
85
+ }
86
+ const actions = view.actions ?? [];
87
+ for (let index = 0; index < actions.length; index += 1) {
88
+ const action = actions[index];
89
+ const marker = (view.actionCursor ?? 0) === index ? '❯ ' : ' ';
90
+ const suffix = action.disabled === true ? ` (unavailable — ${action.reason ?? ''})` : '';
91
+ box.addChild(new Text(`${marker}${action.label}${suffix}`, 0, 0));
92
+ }
93
+ if (view.message !== undefined) {
94
+ box.addChild(new Text(theme.warning(view.message), 0, 0));
95
+ }
96
+ box.addChild(new Text(theme.muted('j/k move · enter select · esc back'), 0, 0));
97
+ return box;
98
+ }
99
+ /** Wizard phases (§4.3/§4.6/rotate): step rail, live field, notes, prompts. */
100
+ function wizardBox(box, view, theme, field) {
101
+ const wizard = view.wizard;
102
+ if (wizard === undefined)
103
+ return box;
104
+ const title = wizard.kind === 'rotate'
105
+ ? `Rotate key — ${wizard.route}`
106
+ : wizard.kind === 'custom' ? 'Add custom provider' : `Add ${wizard.route}${wizard.displayName === undefined ? '' : ` (${wizard.displayName})`}`;
107
+ box.addChild(new Text(theme.bold(title), 0, 0));
108
+ box.addChild(new Text(theme.muted(wizard.steps.map((step, index) => index === wizard.stepIndex ? `[${step}]` : step).join(' → ')), 0, 0));
109
+ const step = wizard.steps[wizard.stepIndex];
110
+ if (step === 'protocol') {
111
+ for (let index = 0; index < CUSTOM_PROTOCOLS.length; index += 1) {
112
+ const marker = (wizard.selectIndex ?? 0) === index ? '❯ ' : ' ';
113
+ box.addChild(new Text(`${marker}${CUSTOM_PROTOCOLS[index]}`, 0, 0));
114
+ }
115
+ }
116
+ else if (step === 'credential' || step === 'key') {
117
+ box.addChild(new Text(theme.muted(`API key for ${wizard.answers['ref'] ?? wizard.route} — stored in ~/.dsh/.credentials.yaml, never in settings`), 0, 0));
118
+ renderField(box, field);
119
+ }
120
+ else if (step === 'models') {
121
+ box.addChild(new Text(theme.muted('model ids — one per entry: id | Name | contextWindow | maxTokens'), 0, 0));
122
+ renderField(box, field);
123
+ box.addChild(new Text(theme.muted('tab fetch from endpoint · enter save'), 0, 0));
124
+ }
125
+ else if (step === 'verify') {
126
+ const verify = wizard.verify;
127
+ if (verify !== undefined)
128
+ box.addChild(new Text(verify.message ?? 'verifying…', 0, 0));
129
+ }
130
+ else if (step === 'done') {
131
+ const where = wizard.answers['ref'] === undefined ? '' : ` — key in ${wizard.answers['ref']}`;
132
+ box.addChild(new Text(`Added ${wizard.route || wizard.answers['route'] || ''}${where}.`, 0, 0));
133
+ box.addChild(new Text(theme.muted('Set as default? enter yes · esc no (/model switches the running session)'), 0, 0));
134
+ }
135
+ else {
136
+ renderField(box, field);
137
+ }
138
+ if (wizard.note !== undefined)
139
+ box.addChild(new Text(theme.warning(wizard.note), 0, 0));
140
+ if (wizard.modelErrors !== undefined) {
141
+ for (const error of wizard.modelErrors)
142
+ box.addChild(new Text(theme.warning(error), 0, 0));
143
+ }
144
+ if (view.message !== undefined)
145
+ box.addChild(new Text(theme.warning(view.message), 0, 0));
146
+ box.addChild(new Text(theme.muted('enter next · esc back'), 0, 0));
147
+ return box;
148
+ }
149
+ /** Remove double-confirm (§4.4): the unset confirm, then the credential-drop offer. */
150
+ function confirmRemoveBox(box, view, theme) {
151
+ box.addChild(new Text(theme.bold(`Remove provider ${view.selected ?? ''}?`), 0, 0));
152
+ if (view.message !== undefined)
153
+ box.addChild(new Text(theme.warning(view.message), 0, 0));
154
+ if (view.stage === 'drop-credential') {
155
+ box.addChild(new Text('Route removed. Also drop the stored credential?', 0, 0));
156
+ box.addChild(new Text(theme.muted('enter drop · x keep · esc keep'), 0, 0));
157
+ }
158
+ else {
159
+ box.addChild(new Text(theme.muted('This unsets llm-pi-ai.providers.' + (view.selected ?? '')), 0, 0));
160
+ box.addChild(new Text(theme.muted('enter remove · esc cancel'), 0, 0));
161
+ }
162
+ return box;
163
+ }
164
+ //# sourceMappingURL=provider-box.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider-box.js","sourceRoot":"","sources":["../../src/components/provider-box.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * View-layer grouping of consecutive completed file-read tool rows. The store
3
+ * keeps a strict 1:1 mapping between rows and durable events, so collapsing
4
+ * N reads into one summary line can only happen here — after the transcript's
5
+ * line-budget clipping and purely for rendering. Nothing in this module feeds
6
+ * back into state.
7
+ * @module @dsh-cc/tui/components/read-group
8
+ */
9
+ import type { TranscriptRow } from '../store.ts';
10
+ /**
11
+ * One slot in the grouped render sequence: either an untouched row (rendered
12
+ * by the normal per-row path) or a group of completed read rows collapsed
13
+ * into a single summary line.
14
+ */
15
+ export type RenderItem = {
16
+ kind: 'row';
17
+ row: TranscriptRow;
18
+ } | {
19
+ kind: 'readGroup';
20
+ rows: readonly TranscriptRow[];
21
+ };
22
+ /**
23
+ * Collapse runs of ≥2 consecutive groupable read rows into `readGroup`
24
+ * items. Any other row (running/errored read, non-read tool, user text,
25
+ * status, …) closes the current segment. Single reads pass through as plain
26
+ * rows so a lone call keeps its familiar per-row rendering.
27
+ */
28
+ export declare function groupReadRows(rows: readonly TranscriptRow[]): readonly RenderItem[];
29
+ /**
30
+ * Stable cache key for a group: its member callId list. Deliberately free of
31
+ * row references — the store replaces row objects in place as results arrive,
32
+ * and the collapsed summary never depends on results.
33
+ */
34
+ export declare function readGroupCacheKey(rows: readonly TranscriptRow[]): string;
35
+ /** Most paths shown before the remainder collapses into "+M more". */
36
+ export declare const READ_GROUP_MAX_PATHS = 4;
37
+ /** Character cap for the rendered path list before it is truncated. */
38
+ export declare const READ_GROUP_LIST_MAX_CHARS = 160;
39
+ /**
40
+ * Extract the display path for one read row: the `file_path`/`path` field of
41
+ * the call's args JSON first, then the presenter title, then the bare tool
42
+ * name as a last resort (so the slot is never empty — an unstyled fallback
43
+ * beats rendering nothing between commas).
44
+ */
45
+ export declare function readDisplayPath(row: TranscriptRow): string;
46
+ /**
47
+ * Render a read group as one line:
48
+ * `⏺ Read N files · a.ts, b.ts +M more`
49
+ */
50
+ export declare function renderReadGroup(rows: readonly TranscriptRow[]): string;
51
+ //# sourceMappingURL=read-group.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-group.d.ts","sourceRoot":"","sources":["../../src/components/read-group.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAEhD;;;;GAIG;AACH,MAAM,MAAM,UAAU,GAClB;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,GAAG,EAAE,aAAa,CAAA;CAAE,GACnC;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,SAAS,aAAa,EAAE,CAAA;CAAE,CAAA;AAgBzD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,SAAS,aAAa,EAAE,GAAG,SAAS,UAAU,EAAE,CAwBnF;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,SAAS,aAAa,EAAE,GAAG,MAAM,CAExE;AAED,sEAAsE;AACtE,eAAO,MAAM,oBAAoB,IAAI,CAAA;AAErC,uEAAuE;AACvE,eAAO,MAAM,yBAAyB,MAAM,CAAA;AAE5C;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAgB1D;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,SAAS,aAAa,EAAE,GAAG,MAAM,CAYtE"}
@@ -0,0 +1,105 @@
1
+ /**
2
+ * View-layer grouping of consecutive completed file-read tool rows. The store
3
+ * keeps a strict 1:1 mapping between rows and durable events, so collapsing
4
+ * N reads into one summary line can only happen here — after the transcript's
5
+ * line-budget clipping and purely for rendering. Nothing in this module feeds
6
+ * back into state.
7
+ * @module @dsh-cc/tui/components/read-group
8
+ */
9
+ /** Tool names that collapse together (case-insensitive). */
10
+ const READ_TOOL_NAMES = new Set(['read', 'read_image']);
11
+ /**
12
+ * A read row is groupable only when it has finished cleanly: a running call
13
+ * still streams its own trail line, and an errored call must stay visible.
14
+ */
15
+ function isGroupableRead(row) {
16
+ return row.kind === 'tool'
17
+ && READ_TOOL_NAMES.has(row.name.toLowerCase())
18
+ && !row.running
19
+ && row.error !== true;
20
+ }
21
+ /**
22
+ * Collapse runs of ≥2 consecutive groupable read rows into `readGroup`
23
+ * items. Any other row (running/errored read, non-read tool, user text,
24
+ * status, …) closes the current segment. Single reads pass through as plain
25
+ * rows so a lone call keeps its familiar per-row rendering.
26
+ */
27
+ export function groupReadRows(rows) {
28
+ const items = [];
29
+ let segment = [];
30
+ const flush = () => {
31
+ if (segment.length === 1) {
32
+ items.push({ kind: 'row', row: segment[0] });
33
+ }
34
+ else if (segment.length > 1) {
35
+ items.push({ kind: 'readGroup', rows: segment });
36
+ }
37
+ segment = [];
38
+ };
39
+ for (const row of rows) {
40
+ if (isGroupableRead(row)) {
41
+ segment.push(row);
42
+ }
43
+ else {
44
+ flush();
45
+ items.push({ kind: 'row', row });
46
+ }
47
+ }
48
+ flush();
49
+ return items;
50
+ }
51
+ /**
52
+ * Stable cache key for a group: its member callId list. Deliberately free of
53
+ * row references — the store replaces row objects in place as results arrive,
54
+ * and the collapsed summary never depends on results.
55
+ */
56
+ export function readGroupCacheKey(rows) {
57
+ return rows.map(row => row.kind === 'tool' ? row.callId : '').join('\n');
58
+ }
59
+ /** Most paths shown before the remainder collapses into "+M more". */
60
+ export const READ_GROUP_MAX_PATHS = 4;
61
+ /** Character cap for the rendered path list before it is truncated. */
62
+ export const READ_GROUP_LIST_MAX_CHARS = 160;
63
+ /**
64
+ * Extract the display path for one read row: the `file_path`/`path` field of
65
+ * the call's args JSON first, then the presenter title, then the bare tool
66
+ * name as a last resort (so the slot is never empty — an unstyled fallback
67
+ * beats rendering nothing between commas).
68
+ */
69
+ export function readDisplayPath(row) {
70
+ if (row.kind !== 'tool')
71
+ return '';
72
+ try {
73
+ const parsed = JSON.parse(row.args);
74
+ if (typeof parsed === 'object' && parsed !== null) {
75
+ const record = parsed;
76
+ for (const key of ['file_path', 'path']) {
77
+ const value = record[key];
78
+ if (typeof value === 'string' && value.length > 0)
79
+ return value;
80
+ }
81
+ }
82
+ }
83
+ catch {
84
+ // Unparseable args fall through to the title fallback.
85
+ }
86
+ if (row.title.length > 0)
87
+ return row.title;
88
+ return row.name;
89
+ }
90
+ /**
91
+ * Render a read group as one line:
92
+ * `⏺ Read N files · a.ts, b.ts +M more`
93
+ */
94
+ export function renderReadGroup(rows) {
95
+ const paths = rows.map(readDisplayPath);
96
+ const shown = paths.slice(0, READ_GROUP_MAX_PATHS);
97
+ const moreCount = paths.length - shown.length;
98
+ const more = moreCount > 0 ? ` +${moreCount} more` : '';
99
+ let list = shown.join(', ');
100
+ if (list.length > READ_GROUP_LIST_MAX_CHARS) {
101
+ list = `${list.slice(0, READ_GROUP_LIST_MAX_CHARS)}…`;
102
+ }
103
+ return `⏺ Read ${rows.length} files · ${list}${more}`;
104
+ }
105
+ //# sourceMappingURL=read-group.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-group.js","sourceRoot":"","sources":["../../src/components/read-group.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * `!` shell-mode behavior for the root pi-tui mount, factored out of
3
+ * components/root.ts so that file stays under its line budget.
4
+ *
5
+ * Shell mode is derived, not stored: the composer is in shell mode exactly
6
+ * while its text starts with `!`. The border switches to the warning role
7
+ * so the mode is visible, ↑/↓ browse the bash-only history stack, and Esc
8
+ * exits the mode ahead of the generic busy-interrupt branch (the ordering
9
+ * in root.ts's input listener is deliberate). Paste normalization lives at
10
+ * the driver's submit — a `!`-prefixed line runs locally no matter how it
11
+ * got into the buffer.
12
+ * @module @dsh-cc/tui/components/root-bash
13
+ */
14
+ import type { Editor, TUI } from '@dsh-cc/pi-tui';
15
+ import type { Theme } from './theme.ts';
16
+ import type { Driver } from '../state/driver-types.ts';
17
+ export interface AttachBashModeArgs {
18
+ editor: Editor;
19
+ driver: Driver;
20
+ tui: TUI;
21
+ theme: Theme;
22
+ }
23
+ export interface BashModeHandle {
24
+ /** True while a `!` command is in flight; the composer is disabled. */
25
+ bashRunning(): boolean;
26
+ inShellMode(): boolean;
27
+ browseBashHistory(towardsOlder: boolean): void;
28
+ resetBashHistoryBrowsing(): void;
29
+ }
30
+ /**
31
+ * Install the `!` shell-mode state and the editor change/submit hooks that
32
+ * drive it. Owns the bash-history browsing stack; assigns editor.onChange /
33
+ * editor.onSubmit exactly as root.ts did inline, so behavior is unchanged.
34
+ */
35
+ export declare function attachBashMode(args: AttachBashModeArgs): BashModeHandle;
36
+ //# sourceMappingURL=root-bash.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"root-bash.d.ts","sourceRoot":"","sources":["../../src/components/root-bash.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAA;AACjD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AACvC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAA;AAGtD,MAAM,WAAW,kBAAkB;IAClC,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,GAAG,EAAE,GAAG,CAAA;IACR,KAAK,EAAE,KAAK,CAAA;CACZ;AAED,MAAM,WAAW,cAAc;IAC7B,uEAAuE;IACvE,WAAW,IAAI,OAAO,CAAA;IACtB,WAAW,IAAI,OAAO,CAAA;IACtB,iBAAiB,CAAC,YAAY,EAAE,OAAO,GAAG,IAAI,CAAA;IAC9C,wBAAwB,IAAI,IAAI,CAAA;CACjC;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,kBAAkB,GAAG,cAAc,CA6FvE"}
@@ -0,0 +1,112 @@
1
+ /**
2
+ * `!` shell-mode behavior for the root pi-tui mount, factored out of
3
+ * components/root.ts so that file stays under its line budget.
4
+ *
5
+ * Shell mode is derived, not stored: the composer is in shell mode exactly
6
+ * while its text starts with `!`. The border switches to the warning role
7
+ * so the mode is visible, ↑/↓ browse the bash-only history stack, and Esc
8
+ * exits the mode ahead of the generic busy-interrupt branch (the ordering
9
+ * in root.ts's input listener is deliberate). Paste normalization lives at
10
+ * the driver's submit — a `!`-prefixed line runs locally no matter how it
11
+ * got into the buffer.
12
+ * @module @dsh-cc/tui/components/root-bash
13
+ */
14
+ import { parseSlash } from "../slash.js";
15
+ /**
16
+ * Install the `!` shell-mode state and the editor change/submit hooks that
17
+ * drive it. Owns the bash-history browsing stack; assigns editor.onChange /
18
+ * editor.onSubmit exactly as root.ts did inline, so behavior is unchanged.
19
+ */
20
+ export function attachBashMode(args) {
21
+ const { editor, driver, tui, theme } = args;
22
+ let bashBrowsing = false;
23
+ let bashBrowsingIndex = -1;
24
+ let bashDraft = '';
25
+ let bashRecallApplied = false;
26
+ let bashRunning = false;
27
+ const inShellMode = () => editor.getText().startsWith('!');
28
+ const resetBashHistoryBrowsing = () => {
29
+ bashBrowsing = false;
30
+ bashBrowsingIndex = -1;
31
+ bashDraft = '';
32
+ };
33
+ /**
34
+ * Browse the bash history stack (driver-owned, newest-first). ↑ walks
35
+ * toward older entries; ↓ walks back and restores the pre-browsing draft
36
+ * past the newest. Recalled entries are re-prefixed with `!` so the buffer
37
+ * stays shell-shaped and Enter re-runs them through the same submit path.
38
+ */
39
+ const browseBashHistory = (towardsOlder) => {
40
+ const entries = driver.bashHistory;
41
+ if (entries.length === 0)
42
+ return;
43
+ if (!bashBrowsing) {
44
+ bashBrowsing = true;
45
+ bashBrowsingIndex = -1;
46
+ bashDraft = editor.getText();
47
+ }
48
+ if (towardsOlder) {
49
+ if (bashBrowsingIndex + 1 >= entries.length)
50
+ return; // clamped at the oldest
51
+ bashBrowsingIndex += 1;
52
+ }
53
+ else {
54
+ bashBrowsingIndex -= 1;
55
+ if (bashBrowsingIndex < 0) {
56
+ // Down past the newest entry: restore the pre-browsing draft.
57
+ const draft = bashDraft;
58
+ resetBashHistoryBrowsing();
59
+ bashRecallApplied = true;
60
+ editor.setText(draft);
61
+ bashRecallApplied = false;
62
+ return;
63
+ }
64
+ }
65
+ bashRecallApplied = true;
66
+ editor.setText(`!${entries[bashBrowsingIndex]}`);
67
+ bashRecallApplied = false;
68
+ };
69
+ // Mirror the shell-mode border on every buffer change: the warning role
70
+ // while the buffer holds a `!`-prefixed line, the accent role otherwise.
71
+ const syncShellModeBorder = () => {
72
+ const styler = inShellMode() ? theme.warning : theme.accent;
73
+ if (editor.borderColor !== styler) {
74
+ editor.borderColor = styler;
75
+ tui.requestRender();
76
+ }
77
+ };
78
+ editor.onChange = (text) => {
79
+ driver.setDraft(text);
80
+ syncShellModeBorder();
81
+ // Any buffer change that was not a bash recall ends history browsing,
82
+ // so the next ↑ starts fresh (mirrors the editor's own navigation).
83
+ if (!bashRecallApplied)
84
+ resetBashHistoryBrowsing();
85
+ };
86
+ editor.onSubmit = (text) => {
87
+ if (text.startsWith('!')) {
88
+ // Shell command: never a composer prompt. While the driver runs it,
89
+ // the composer is disabled — the input listener swallows every key
90
+ // until submit settles (bounded by the command's own timeout).
91
+ resetBashHistoryBrowsing();
92
+ bashRunning = true;
93
+ void driver.submit(text)
94
+ .catch(() => { })
95
+ .then(() => {
96
+ bashRunning = false;
97
+ tui.requestRender();
98
+ });
99
+ return;
100
+ }
101
+ const parsed = parseSlash(text);
102
+ // Only prompts join editor recall; slash commands are not prompts.
103
+ if (parsed.kind === 'none')
104
+ editor.addToHistory(text);
105
+ // Submit is fire-and-forget. Quit/exit finalization — including the
106
+ // /quit worktree-exit confirmation — is owned by the driver's quit path
107
+ // (config.onQuit), not by the onSubmit special-case it used to have here.
108
+ void driver.submit(text);
109
+ };
110
+ return { bashRunning: () => bashRunning, inShellMode, browseBashHistory, resetBashHistoryBrowsing };
111
+ }
112
+ //# sourceMappingURL=root-bash.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"root-bash.js","sourceRoot":"","sources":["../../src/components/root-bash.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAKH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAiBxC;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,IAAwB;IACrD,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,IAAI,CAAA;IAE3C,IAAI,YAAY,GAAG,KAAK,CAAA;IACxB,IAAI,iBAAiB,GAAG,CAAC,CAAC,CAAA;IAC1B,IAAI,SAAS,GAAG,EAAE,CAAA;IAClB,IAAI,iBAAiB,GAAG,KAAK,CAAA;IAC7B,IAAI,WAAW,GAAG,KAAK,CAAA;IAEvB,MAAM,WAAW,GAAG,GAAY,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAA;IAEnE,MAAM,wBAAwB,GAAG,GAAS,EAAE;QAC1C,YAAY,GAAG,KAAK,CAAA;QACpB,iBAAiB,GAAG,CAAC,CAAC,CAAA;QACtB,SAAS,GAAG,EAAE,CAAA;IAChB,CAAC,CAAA;IAED;;;;;OAKG;IACH,MAAM,iBAAiB,GAAG,CAAC,YAAqB,EAAQ,EAAE;QACxD,MAAM,OAAO,GAAG,MAAM,CAAC,WAAW,CAAA;QAClC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAM;QAChC,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,YAAY,GAAG,IAAI,CAAA;YACnB,iBAAiB,GAAG,CAAC,CAAC,CAAA;YACtB,SAAS,GAAG,MAAM,CAAC,OAAO,EAAE,CAAA;QAC9B,CAAC;QACD,IAAI,YAAY,EAAE,CAAC;YACjB,IAAI,iBAAiB,GAAG,CAAC,IAAI,OAAO,CAAC,MAAM;gBAAE,OAAM,CAAC,wBAAwB;YAC5E,iBAAiB,IAAI,CAAC,CAAA;QACxB,CAAC;aAAM,CAAC;YACN,iBAAiB,IAAI,CAAC,CAAA;YACtB,IAAI,iBAAiB,GAAG,CAAC,EAAE,CAAC;gBAC1B,8DAA8D;gBAC9D,MAAM,KAAK,GAAG,SAAS,CAAA;gBACvB,wBAAwB,EAAE,CAAA;gBAC1B,iBAAiB,GAAG,IAAI,CAAA;gBACxB,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;gBACrB,iBAAiB,GAAG,KAAK,CAAA;gBACzB,OAAM;YACR,CAAC;QACH,CAAC;QACD,iBAAiB,GAAG,IAAI,CAAA;QACxB,MAAM,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAA;QAChD,iBAAiB,GAAG,KAAK,CAAA;IAC3B,CAAC,CAAA;IAED,wEAAwE;IACxE,yEAAyE;IACzE,MAAM,mBAAmB,GAAG,GAAS,EAAE;QACrC,MAAM,MAAM,GAAG,WAAW,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAA;QAC3D,IAAI,MAAM,CAAC,WAAW,KAAK,MAAM,EAAE,CAAC;YAClC,MAAM,CAAC,WAAW,GAAG,MAAM,CAAA;YAC3B,GAAG,CAAC,aAAa,EAAE,CAAA;QACrB,CAAC;IACH,CAAC,CAAA;IAED,MAAM,CAAC,QAAQ,GAAG,CAAC,IAAY,EAAQ,EAAE;QACvC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;QACrB,mBAAmB,EAAE,CAAA;QACrB,sEAAsE;QACtE,oEAAoE;QACpE,IAAI,CAAC,iBAAiB;YAAE,wBAAwB,EAAE,CAAA;IACpD,CAAC,CAAA;IACD,MAAM,CAAC,QAAQ,GAAG,CAAC,IAAY,EAAQ,EAAE;QACvC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACzB,oEAAoE;YACpE,mEAAmE;YACnE,+DAA+D;YAC/D,wBAAwB,EAAE,CAAA;YAC1B,WAAW,GAAG,IAAI,CAAA;YAClB,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;iBACrB,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC;iBACf,IAAI,CAAC,GAAG,EAAE;gBACT,WAAW,GAAG,KAAK,CAAA;gBACnB,GAAG,CAAC,aAAa,EAAE,CAAA;YACrB,CAAC,CAAC,CAAA;YACJ,OAAM;QACR,CAAC;QACD,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,CAAA;QAC/B,mEAAmE;QACnE,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM;YAAE,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,CAAA;QACrD,oEAAoE;QACpE,wEAAwE;QACxE,0EAA0E;QAC1E,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IAC1B,CAAC,CAAA;IAED,OAAO,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC,WAAW,EAAE,WAAW,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,CAAA;AACrG,CAAC"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Public mount contracts for the root pi-tui component, split out of root.ts
3
+ * to keep the factory under the line budget. Deliberately a leaf — must not
4
+ * import root.ts.
5
+ * @module @dsh-cc/tui/components/root-types
6
+ */
7
+ import type { Editor, Terminal, TUI, TuiMode } from '@dsh-cc/pi-tui';
8
+ import type { ThemeOverrides } from './theme.ts';
9
+ export interface BuildRootOptions {
10
+ terminal?: Terminal;
11
+ onQuit?: () => void;
12
+ /**
13
+ * 'regular' (default) renders inline into the main screen scrollback;
14
+ * 'fullscreen' enters the alternate screen on start: the transcript scrolls
15
+ * inside a primary ScrollView while the dock (queue, todos, overlays,
16
+ * editor, statusline) stays pinned at the bottom.
17
+ */
18
+ uiMode?: TuiMode;
19
+ /** Fullscreen-only: mouse capture for wheel scrolling and app-owned selection. Default true. */
20
+ mouse?: boolean;
21
+ /**
22
+ * Per-role palette overrides for the terminal theme. Every role accepts a
23
+ * basic ANSI color name or a raw SGR code string; invalid values keep the
24
+ * built-in default, so an absent (or partial) override renders exactly like
25
+ * the historical fixed palette.
26
+ */
27
+ theme?: ThemeOverrides;
28
+ }
29
+ export interface RootHandle {
30
+ readonly tui: TUI;
31
+ readonly editor: Editor;
32
+ readonly mode: TuiMode;
33
+ destroy(): void;
34
+ /**
35
+ * Stop the surface. In fullscreen mode this leaves the alternate screen
36
+ * with the final frame preserved, then replays the chrome through a one-shot
37
+ * main-screen renderer so native scrollback ends up with the same inline
38
+ * layout a regular session would have produced.
39
+ */
40
+ stopForExit(): void;
41
+ }
42
+ //# sourceMappingURL=root-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"root-types.d.ts","sourceRoot":"","sources":["../../src/components/root-types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAA;AACpE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAEhD,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,EAAE,QAAQ,CAAA;IACnB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;IACnB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,gGAAgG;IAChG,KAAK,CAAC,EAAE,OAAO,CAAA;IACf;;;;;OAKG;IACH,KAAK,CAAC,EAAE,cAAc,CAAA;CACtB;AAED,MAAM,WAAW,UAAU;IAC1B,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAA;IACjB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;IACtB,OAAO,IAAI,IAAI,CAAA;IACf;;;;;OAKG;IACH,WAAW,IAAI,IAAI,CAAA;CACnB"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Public mount contracts for the root pi-tui component, split out of root.ts
3
+ * to keep the factory under the line budget. Deliberately a leaf — must not
4
+ * import root.ts.
5
+ * @module @dsh-cc/tui/components/root-types
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=root-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"root-types.js","sourceRoot":"","sources":["../../src/components/root-types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Standalone helpers and constants extracted from the root mount: OS URL
3
+ * opening, active-task text capping, window-title sanitizing, and the
4
+ * double-press quit window.
5
+ * Deliberately a leaf — must not import root.ts.
6
+ * @module @dsh-cc/tui/components/root-utils
7
+ */
8
+ /** How long after the first idle Ctrl+C a second press still quits (ms). */
9
+ export declare const DOUBLE_PRESS_WINDOW_MS = 2000;
10
+ export declare function truncateActive(content: string): string;
11
+ /**
12
+ * Make a string safe for an OSC 0 window-title write: strip control
13
+ * characters, trim, cap the length, and fall back to 'dsh-cc' when nothing
14
+ * printable remains.
15
+ */
16
+ export declare function sanitizeWindowTitle(title: string): string;
17
+ /**
18
+ * Open an OSC 8 hyperlink with the OS handler. Fullscreen mouse capture takes
19
+ * over the terminal's native link activation, so clicks are routed here.
20
+ */
21
+ export declare function openSystemUrl(url: string): void;
22
+ //# sourceMappingURL=root-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"root-utils.d.ts","sourceRoot":"","sources":["../../src/components/root-utils.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,4EAA4E;AAC5E,eAAO,MAAM,sBAAsB,OAAO,CAAA;AAK1C,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEtD;AAWD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIzD;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAM/C"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Standalone helpers and constants extracted from the root mount: OS URL
3
+ * opening, active-task text capping, window-title sanitizing, and the
4
+ * double-press quit window.
5
+ * Deliberately a leaf — must not import root.ts.
6
+ * @module @dsh-cc/tui/components/root-utils
7
+ */
8
+ import { spawn } from 'node:child_process';
9
+ /** How long after the first idle Ctrl+C a second press still quits (ms). */
10
+ export const DOUBLE_PRESS_WINDOW_MS = 2000;
11
+ /** Cap the active-task text shown in the todo strip (ellipsis past the cap). */
12
+ const TODO_ACTIVE_CAP = 60;
13
+ export function truncateActive(content) {
14
+ return content.length > TODO_ACTIVE_CAP ? `${content.slice(0, TODO_ACTIVE_CAP - 1)}…` : content;
15
+ }
16
+ /** Cap the terminal window title (chars, post-sanitize). */
17
+ const WINDOW_TITLE_CAP = 120;
18
+ // C0 controls (ESC/BEL included — they terminate or inject OSC sequences),
19
+ // DEL, and C1 controls. The session-title service already normalizes; this
20
+ // is defense-in-depth on an LLM-derived string crossing into the terminal.
21
+ // eslint-disable-next-line no-control-regex
22
+ const WINDOW_TITLE_CONTROL_CHARS = /[\x00-\x1f\x7f\x80-\x9f]/g;
23
+ /**
24
+ * Make a string safe for an OSC 0 window-title write: strip control
25
+ * characters, trim, cap the length, and fall back to 'dsh-cc' when nothing
26
+ * printable remains.
27
+ */
28
+ export function sanitizeWindowTitle(title) {
29
+ const cleaned = title.replace(WINDOW_TITLE_CONTROL_CHARS, '').trim();
30
+ if (cleaned.length === 0)
31
+ return 'dsh-cc';
32
+ return cleaned.length > WINDOW_TITLE_CAP ? cleaned.slice(0, WINDOW_TITLE_CAP) : cleaned;
33
+ }
34
+ /**
35
+ * Open an OSC 8 hyperlink with the OS handler. Fullscreen mouse capture takes
36
+ * over the terminal's native link activation, so clicks are routed here.
37
+ */
38
+ export function openSystemUrl(url) {
39
+ const child = process.platform === 'win32'
40
+ ? spawn('cmd.exe', ['/c', 'start', '', url], { stdio: 'ignore', detached: true })
41
+ : spawn(process.platform === 'darwin' ? 'open' : 'xdg-open', [url], { stdio: 'ignore', detached: true });
42
+ child.on('error', () => { });
43
+ child.unref();
44
+ }
45
+ //# sourceMappingURL=root-utils.js.map