@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,115 @@
1
+ /** Settings namespace carrying the provider profiles (doc D1/D2). */
2
+ export const PROVIDER_SETTINGS_NAMESPACE = 'llm-pi-ai';
3
+ /** Usage line for unknown/unsupported subcommands (§4.1 — never silent). */
4
+ export const PROVIDER_USAGE = 'Usage: /provider [list | add <preset-id> | remove <route>]';
5
+ /**
6
+ * Read the `llm-pi-ai` section's user-layer `providers` dict (§4.2). The
7
+ * service may be absent, the namespace unregistered, or the stored shape
8
+ * junk — every degradation returns `{}` so the overlay renders honestly.
9
+ */
10
+ export function readConfiguredProviders(settings) {
11
+ if (settings === undefined || typeof settings.describe !== 'function')
12
+ return {};
13
+ let descriptors;
14
+ try {
15
+ descriptors = settings.describe() ?? [];
16
+ }
17
+ catch {
18
+ return {};
19
+ }
20
+ const descriptor = descriptors.find((entry) => entry !== null && typeof entry === 'object' && String(entry.ns) === PROVIDER_SETTINGS_NAMESPACE);
21
+ const user = descriptor?.user;
22
+ const providers = user !== null && typeof user === 'object' ? user.providers : undefined;
23
+ if (providers === null || typeof providers !== 'object' || Array.isArray(providers))
24
+ return {};
25
+ const out = {};
26
+ for (const [route, profile] of Object.entries(providers)) {
27
+ // Coerce junk entries away: only object profiles are provider shapes.
28
+ if (profile !== null && typeof profile === 'object')
29
+ out[route] = profile;
30
+ }
31
+ return out;
32
+ }
33
+ /**
34
+ * Credential-state snapshots for each ref (§4.2 badges). Tolerant of an
35
+ * absent service and a throwing `describe` — a failed describe is an unknown
36
+ * state, rendered as unconfigured, never an overlay crash.
37
+ */
38
+ export async function credentialStates(credentials, refs) {
39
+ const out = {};
40
+ if (credentials === undefined)
41
+ return out;
42
+ for (const ref of refs) {
43
+ try {
44
+ if (typeof credentials.describe !== 'function')
45
+ return out;
46
+ const state = await credentials.describe(ref);
47
+ if (state !== undefined && state !== null && typeof state === 'object')
48
+ out[ref] = state;
49
+ }
50
+ catch {
51
+ // Unknown state: omit — badgeFor renders missing.
52
+ }
53
+ }
54
+ return out;
55
+ }
56
+ /**
57
+ * Configurable-provider directory (C8). Absent service or junk entries
58
+ * degrade to `[]`; throwing discovery degrades to `[]` too.
59
+ */
60
+ export function loadDirectory(llm) {
61
+ try {
62
+ const entries = llm?.listConfigurableProviders?.();
63
+ if (!Array.isArray(entries))
64
+ return [];
65
+ return entries.filter((entry) => entry !== null && typeof entry === 'object' && typeof entry.provider === 'string');
66
+ }
67
+ catch {
68
+ return [];
69
+ }
70
+ }
71
+ /** Subcommand table per §4.1: bare, list, add/remove with a required id. */
72
+ export function parseProviderArgs(rest) {
73
+ const trimmed = rest.trim();
74
+ if (trimmed === '')
75
+ return { kind: 'open' };
76
+ if (trimmed === 'list')
77
+ return { kind: 'list' };
78
+ for (const kind of ['add', 'remove']) {
79
+ if (trimmed === kind || trimmed.startsWith(`${kind} `)) {
80
+ const route = trimmed.slice(kind.length).trim();
81
+ if (route === '')
82
+ return { kind: 'invalid' };
83
+ return { kind, route };
84
+ }
85
+ }
86
+ return { kind: 'invalid' };
87
+ }
88
+ /** Badge text for one row (`✓ (managed)` / `✓ (env)` / `✗ missing`). */
89
+ function credentialBadgeText(row) {
90
+ const credential = row.credential;
91
+ if (credential === undefined || credential.badge === 'missing')
92
+ return 'key ✗ missing';
93
+ return `key ✓ (${credential.badge})`;
94
+ }
95
+ /**
96
+ * §4.1 `/provider list` — plain-text rendering of the same two-section data
97
+ * the overlay shows (script-friendly chat output).
98
+ */
99
+ export function renderProviderList(list) {
100
+ const lines = ['Providers', ' Configured'];
101
+ for (const row of list.configured) {
102
+ const marker = row.isCurrent ? '●' : '○';
103
+ const models = row.modelCount > 0 ? ` ${row.modelCount} models` : '';
104
+ lines.push(` ${marker} ${row.route} ${row.displayName} ${credentialBadgeText(row)}${models}${row.credential?.warning === true ? ' ⚠' : ''}`);
105
+ }
106
+ lines.push(' Available');
107
+ for (const row of list.available) {
108
+ lines.push(` ○ ${row.route} ${row.displayName}`);
109
+ }
110
+ if (list.more.length > 0) {
111
+ lines.push(` … More providers (${list.more.map(m => m.provider).join(', ')})`);
112
+ }
113
+ return lines.join('\n');
114
+ }
115
+ //# sourceMappingURL=provider-read.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider-read.js","sourceRoot":"","sources":["../src/provider-read.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import { type SettingsDescribeLike } from './provider-read.ts';
2
+ import type { ProviderCore } from './provider-command.ts';
3
+ /** One path-op for the settings cascade facade (doc D8a: `{op:'set'|'unset', path}`). */
4
+ export type ProviderSettingsOp = {
5
+ op: 'set' | 'unset';
6
+ path: readonly string[];
7
+ value?: unknown;
8
+ };
9
+ /**
10
+ * Duck-typed write-capable settings seam (doc D1/D8): `describe` supplies the
11
+ * revision guard, `mutate` writes path ops, `replace` writes a whole
12
+ * namespace (the agent-default-model seed, D8c).
13
+ */
14
+ export type SettingsWriteLike = SettingsDescribeLike & {
15
+ mutate?(ns: string, ops: readonly ProviderSettingsOp[], revision?: unknown): Promise<unknown>;
16
+ replace?(ns: string, value: unknown, revision?: unknown): Promise<unknown>;
17
+ };
18
+ export declare const settingsWriteOf: (core: ProviderCore) => SettingsWriteLike | undefined;
19
+ /**
20
+ * Revision-guarded path-op write with one conflict retry (D1/D8a, the
21
+ * writeAllowRule precedent). Returns the verbatim error message on failure
22
+ * (§7: rendered as-is, previous routes keep serving).
23
+ */
24
+ export declare const writeRoute: (core: ProviderCore, op: ProviderSettingsOp) => Promise<string | undefined>;
25
+ /**
26
+ * D8(c) agent-default-model seed: opportunistic — all failures degrade to a
27
+ * note and the running session is never touched.
28
+ */
29
+ export declare const setAsDefault: (core: ProviderCore, route: string) => Promise<void>;
30
+ //# sourceMappingURL=provider-settings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider-settings.d.ts","sourceRoot":"","sources":["../src/provider-settings.ts"],"names":[],"mappings":"AAQA,OAAO,EAA+B,KAAK,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AAG3F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AAEzD,yFAAyF;AACzF,MAAM,MAAM,kBAAkB,GAAG;IAAE,EAAE,EAAE,KAAK,GAAG,OAAO,CAAC;IAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,CAAA;AAElG;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,GAAG,oBAAoB,GAAG;IACrD,MAAM,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,kBAAkB,EAAE,EAAE,QAAQ,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IAC7F,OAAO,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;CAC3E,CAAA;AAED,eAAO,MAAM,eAAe,GAAI,MAAM,YAAY,KAAG,iBAAiB,GAAG,SACX,CAAA;AAU9D;;;;GAIG;AACH,eAAO,MAAM,UAAU,GAAU,MAAM,YAAY,EAAE,IAAI,kBAAkB,KAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAevG,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,YAAY,GAAU,MAAM,YAAY,EAAE,OAAO,MAAM,KAAG,OAAO,CAAC,IAAI,CAclF,CAAA"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * `/provider` settings-write seam (design doc docs/plans/2026-09-05-provider-
3
+ * management.md doc D1/D8a/D8c): the duck-typed write-capable settings seam,
4
+ * the revision-guarded path-op write, and the agent-default-model seed.
5
+ * Split out of provider-command.ts purely for line budget.
6
+ * @module @dsh-cc/tui/provider-command-settings
7
+ */
8
+ import { isSettingsConflict } from "./harness/approval-preview.js";
9
+ import { PROVIDER_SETTINGS_NAMESPACE } from "./provider-read.js";
10
+ import { setMessage } from "./store/provider-panel.js";
11
+ export const settingsWriteOf = (core) => core.rt.ctx.get('settings');
12
+ const revisionOf = (settings, ns = PROVIDER_SETTINGS_NAMESPACE) => {
13
+ try {
14
+ return settings?.describe?.().find(entry => String(entry.ns) === ns)?.revision;
15
+ }
16
+ catch {
17
+ return undefined;
18
+ }
19
+ };
20
+ /**
21
+ * Revision-guarded path-op write with one conflict retry (D1/D8a, the
22
+ * writeAllowRule precedent). Returns the verbatim error message on failure
23
+ * (§7: rendered as-is, previous routes keep serving).
24
+ */
25
+ export const writeRoute = async (core, op) => {
26
+ const settings = settingsWriteOf(core);
27
+ if (settings === undefined || typeof settings.mutate !== 'function') {
28
+ return 'No writable settings provider is mounted.';
29
+ }
30
+ for (let attempt = 0; attempt < 2; attempt += 1) {
31
+ try {
32
+ await settings.mutate(PROVIDER_SETTINGS_NAMESPACE, [op], revisionOf(settings));
33
+ return undefined;
34
+ }
35
+ catch (error) {
36
+ if (attempt === 0 && isSettingsConflict(error))
37
+ continue;
38
+ return error instanceof Error ? error.message : String(error);
39
+ }
40
+ }
41
+ return undefined;
42
+ };
43
+ /**
44
+ * D8(c) agent-default-model seed: opportunistic — all failures degrade to a
45
+ * note and the running session is never touched.
46
+ */
47
+ export const setAsDefault = async (core, route) => {
48
+ const llm = core.rt.ctx.get('llm');
49
+ const settings = settingsWriteOf(core);
50
+ try {
51
+ const models = await llm?.listModels(route);
52
+ const model = Array.isArray(models) ? models[0]?.id : undefined;
53
+ if (model === undefined || model === '')
54
+ throw new Error('no models are registered for the route yet');
55
+ if (settings === undefined || typeof settings.replace !== 'function')
56
+ throw new Error('no writable settings provider is mounted');
57
+ await settings.replace('agent-default-model', { provider: route, model }, revisionOf(settings, 'agent-default-model'));
58
+ core.patch(p => setMessage(p, `Default model set to ${route}/${model} for new sessions — /model switches the running one.`));
59
+ }
60
+ catch (error) {
61
+ const reason = error instanceof Error ? error.message : String(error);
62
+ core.patch(p => setMessage(p, `Could not set the default model: ${reason} — this step is optional; /model can pick any registered route.`));
63
+ }
64
+ };
65
+ //# sourceMappingURL=provider-settings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider-settings.js","sourceRoot":"","sources":["../src/provider-settings.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Cross-process resume marker. The TUI writes the live session id AND reads
3
+ * it back itself on boot (project-keyed auto-resume); the `dsh-cc` launcher
4
+ * no longer reads markers — it only translates CLI flags into env for the
5
+ * TUI. Session records themselves stay in harness persistence.
6
+ *
7
+ * Markers are keyed by the session's *project* (the main git root; worktrees
8
+ * collapse onto it), so a worktree and its main checkout share the "last
9
+ * session" anchor. The new marker lives at
10
+ * `$DSH_HOME/tui/projects/<projectKey>/resume.txt` (the same bucket as
11
+ * per-project history and the session sidecar index).
12
+ *
13
+ * A legacy marker (`resume-<sha256(resolve(cwd))[:16]>.txt`, cwd-bucketed)
14
+ * is dual-read on boot and dual-written/cleared alongside the new one, so
15
+ * pre-P3 launchers that read it keep working during the transition. The
16
+ * legacy dual-write is removed in 0.4.0.
17
+ *
18
+ * @module @dsh-cc/tui/resume-target
19
+ */
20
+ export interface ResumeTargetOptions {
21
+ /** Data directory. Defaults to `$DSH_HOME/tui` or `~/.dsh/tui`. */
22
+ home?: string;
23
+ /** Session cwd whose PROJECT keys the new marker. Defaults to `process.cwd()`. */
24
+ cwd?: string;
25
+ /** cwd bucket for the legacy marker. Defaults to `cwd`. */
26
+ legacyCwd?: string;
27
+ }
28
+ /**
29
+ * On-disk path of the NEW project-keyed resume marker for `cwd`. Exported so
30
+ * tests can lock the scheme. (Multiple clients call this per boot, so the
31
+ * underlying `resolveProject` is memoised in project.ts — no per-call git.)
32
+ */
33
+ export declare function resumeMarkerFile(options?: ResumeTargetOptions): string;
34
+ /**
35
+ * On-disk path of the legacy cwd-bucketed marker (`resume-<hash>.txt`),
36
+ * used during the pre-P3 transition. Keyed by `legacyCwd ?? cwd`.
37
+ */
38
+ export declare function legacyResumeMarkerFile(options?: ResumeTargetOptions): string;
39
+ /**
40
+ * Persist the session id the next boot should attach. Idempotent on the NEW
41
+ * marker: if it already holds exactly `sessionId` this is a no-op (the
42
+ * legacy marker is not consulted). Otherwise the new (project-keyed) marker
43
+ * is written, plus a legacy dual-write for pre-P3 launchers.
44
+ */
45
+ export declare function writeResumeTarget(sessionId: string, options?: ResumeTargetOptions): void;
46
+ /**
47
+ * Forget the marker(s) — a fresh session. Blanks both the new and the legacy
48
+ * marker (best-effort); the legacy side is keyed by `legacyCwd ?? cwd`.
49
+ */
50
+ export declare function clearResumeTarget(options?: ResumeTargetOptions): void;
51
+ /**
52
+ * The stored session id, or undefined when absent/blank.
53
+ *
54
+ * Dual-read, order pinned: blank/absent files are discarded first, then the
55
+ * survivors are compared by `statSync().mtimeMs` — newer wins, ties go to the
56
+ * new (project-keyed) marker.
57
+ */
58
+ export declare function readResumeTarget(options?: ResumeTargetOptions): string | undefined;
59
+ //# sourceMappingURL=resume-target.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resume-target.d.ts","sourceRoot":"","sources":["../src/resume-target.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAQH,MAAM,WAAW,mBAAmB;IAClC,mEAAmE;IACnE,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,kFAAkF;IAClF,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,2DAA2D;IAC3D,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAYD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,mBAAwB,GAAG,MAAM,CAI1E;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,GAAE,mBAAwB,GAAG,MAAM,CAGhF;AAWD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE,mBAAwB,GAAG,IAAI,CAiB5F;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,mBAAwB,GAAG,IAAI,CAQzE;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,mBAAwB,GAAG,MAAM,GAAG,SAAS,CA0BtF"}
@@ -0,0 +1,143 @@
1
+ /**
2
+ * Cross-process resume marker. The TUI writes the live session id AND reads
3
+ * it back itself on boot (project-keyed auto-resume); the `dsh-cc` launcher
4
+ * no longer reads markers — it only translates CLI flags into env for the
5
+ * TUI. Session records themselves stay in harness persistence.
6
+ *
7
+ * Markers are keyed by the session's *project* (the main git root; worktrees
8
+ * collapse onto it), so a worktree and its main checkout share the "last
9
+ * session" anchor. The new marker lives at
10
+ * `$DSH_HOME/tui/projects/<projectKey>/resume.txt` (the same bucket as
11
+ * per-project history and the session sidecar index).
12
+ *
13
+ * A legacy marker (`resume-<sha256(resolve(cwd))[:16]>.txt`, cwd-bucketed)
14
+ * is dual-read on boot and dual-written/cleared alongside the new one, so
15
+ * pre-P3 launchers that read it keep working during the transition. The
16
+ * legacy dual-write is removed in 0.4.0.
17
+ *
18
+ * @module @dsh-cc/tui/resume-target
19
+ */
20
+ import { createHash } from 'node:crypto';
21
+ import { mkdirSync, readFileSync, statSync, writeFileSync } from 'node:fs';
22
+ import { homedir } from 'node:os';
23
+ import { dirname, join, resolve } from 'node:path';
24
+ import { resolveProject } from "./project.js";
25
+ function dataDir(options = {}) {
26
+ if (options.home !== undefined)
27
+ return options.home;
28
+ const dshHome = process.env.DSH_HOME ?? join(homedir(), '.dsh');
29
+ return join(dshHome, 'tui');
30
+ }
31
+ function legacyKey(cwd) {
32
+ return createHash('sha256').update(resolve(cwd)).digest('hex').slice(0, 16);
33
+ }
34
+ /**
35
+ * On-disk path of the NEW project-keyed resume marker for `cwd`. Exported so
36
+ * tests can lock the scheme. (Multiple clients call this per boot, so the
37
+ * underlying `resolveProject` is memoised in project.ts — no per-call git.)
38
+ */
39
+ export function resumeMarkerFile(options = {}) {
40
+ const cwd = options.cwd ?? process.cwd();
41
+ const key = resolveProject(cwd).projectKey;
42
+ return join(dataDir(options), 'projects', key, 'resume.txt');
43
+ }
44
+ /**
45
+ * On-disk path of the legacy cwd-bucketed marker (`resume-<hash>.txt`),
46
+ * used during the pre-P3 transition. Keyed by `legacyCwd ?? cwd`.
47
+ */
48
+ export function legacyResumeMarkerFile(options = {}) {
49
+ const cwd = options.legacyCwd ?? options.cwd ?? process.cwd();
50
+ return join(dataDir(options), `resume-${legacyKey(cwd)}.txt`);
51
+ }
52
+ /** The trimmed contents of a file, or '' when absent. */
53
+ function quietRead(file) {
54
+ try {
55
+ return readFileSync(file, 'utf8').trim();
56
+ }
57
+ catch {
58
+ return '';
59
+ }
60
+ }
61
+ /**
62
+ * Persist the session id the next boot should attach. Idempotent on the NEW
63
+ * marker: if it already holds exactly `sessionId` this is a no-op (the
64
+ * legacy marker is not consulted). Otherwise the new (project-keyed) marker
65
+ * is written, plus a legacy dual-write for pre-P3 launchers.
66
+ */
67
+ export function writeResumeTarget(sessionId, options = {}) {
68
+ const id = sessionId.trim();
69
+ if (id.length === 0)
70
+ return;
71
+ const newFile = resumeMarkerFile(options);
72
+ if (quietRead(newFile) === id)
73
+ return; // F4: dedupe against the NEW marker only.
74
+ mkdirSync(dirname(newFile), { recursive: true });
75
+ writeFileSync(newFile, `${id}\n`);
76
+ // TODO(0.4.0): remove legacy dual-write (transition compat for pre-P3 launchers)
77
+ const legacyFile = legacyResumeMarkerFile(options);
78
+ try {
79
+ mkdirSync(dirname(legacyFile), { recursive: true });
80
+ writeFileSync(legacyFile, `${id}\n`);
81
+ }
82
+ catch {
83
+ // Best effort — a pre-P3 launcher just misses the anchor in this process.
84
+ }
85
+ }
86
+ /**
87
+ * Forget the marker(s) — a fresh session. Blanks both the new and the legacy
88
+ * marker (best-effort); the legacy side is keyed by `legacyCwd ?? cwd`.
89
+ */
90
+ export function clearResumeTarget(options = {}) {
91
+ for (const file of [resumeMarkerFile(options), legacyResumeMarkerFile(options)]) {
92
+ try {
93
+ writeFileSync(file, '');
94
+ }
95
+ catch {
96
+ // Best effort — the marker is a launcher nicety.
97
+ }
98
+ }
99
+ }
100
+ /**
101
+ * The stored session id, or undefined when absent/blank.
102
+ *
103
+ * Dual-read, order pinned: blank/absent files are discarded first, then the
104
+ * survivors are compared by `statSync().mtimeMs` — newer wins, ties go to the
105
+ * new (project-keyed) marker.
106
+ */
107
+ export function readResumeTarget(options = {}) {
108
+ const candidates = [
109
+ { path: resumeMarkerFile(options), content: '', isNew: true },
110
+ { path: legacyResumeMarkerFile(options), content: '', isNew: false },
111
+ ];
112
+ let survivors = 0;
113
+ let winner;
114
+ for (const candidate of candidates) {
115
+ const content = quietRead(candidate.path);
116
+ if (content.length === 0)
117
+ continue;
118
+ candidate.content = content;
119
+ survivors += 1;
120
+ winner = candidate;
121
+ }
122
+ if (survivors === 0)
123
+ return undefined;
124
+ if (survivors === 1)
125
+ return winner?.content;
126
+ // Two survivors: compare their mtimes; ties favour the new marker.
127
+ const older = candidates.find(c => !c.isNew) ?? candidates[0];
128
+ const newer = candidates.find(c => c.isNew) ?? candidates[1];
129
+ let mtimeOlder = -Infinity;
130
+ let mtimeNewer = -Infinity;
131
+ try {
132
+ mtimeOlder = statSync(older.path).mtimeMs;
133
+ }
134
+ catch { /* treat as oldest */ }
135
+ try {
136
+ mtimeNewer = statSync(newer.path).mtimeMs;
137
+ }
138
+ catch { /* treat as oldest */ }
139
+ if (mtimeOlder === mtimeNewer)
140
+ return newer.content;
141
+ return mtimeOlder > mtimeNewer ? older.content : newer.content;
142
+ }
143
+ //# sourceMappingURL=resume-target.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resume-target.js","sourceRoot":"","sources":["../src/resume-target.ts"],"names":[],"mappings":"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"}
package/lib/slash.d.ts ADDED
@@ -0,0 +1,44 @@
1
+ /**
2
+ * TUI-local slash parsing. Harness commands still dispatch through
3
+ * `ctx.commands`; these names are owned by the terminal surface.
4
+ * @module @dsh-cc/tui/slash
5
+ */
6
+ /** Slash names the TUI handles without calling `ctx.commands`. */
7
+ export declare const LOCAL_SLASH: readonly ["quit", "exit", "clear", "new", "reset", "tui-help", "resume", "model", "effort", "agents", "cost", "usage", "export-md", "copy", "provider"];
8
+ /** `/provider` subcommands (§4.1) — surfaced as the argument completer hints. */
9
+ export declare const PROVIDER_SUBCOMMANDS: readonly ["list", "add", "remove"];
10
+ export type LocalSlashName = (typeof LOCAL_SLASH)[number];
11
+ export interface LocalCommand {
12
+ readonly name: string;
13
+ readonly description: string;
14
+ readonly argumentHint?: string;
15
+ }
16
+ /**
17
+ * Catalog of TUI-owned slash commands, surfaced via {@link Driver.listCommands}
18
+ * and the composer autocomplete. Descriptions mirror runLocal's behavior so
19
+ * the suggestion list matches what each command actually does.
20
+ */
21
+ export declare const LOCAL_COMMANDS: readonly LocalCommand[];
22
+ export type ParsedSlash = {
23
+ kind: 'local';
24
+ name: string;
25
+ rawInput: string;
26
+ } | {
27
+ kind: 'harness';
28
+ line: string;
29
+ } | {
30
+ kind: 'none';
31
+ };
32
+ /** Publish the current plugin-command name table (lowercased for matching). */
33
+ export declare function setPluginSlashNames(names: readonly string[]): void;
34
+ /**
35
+ * Classify one composer line. Leading slash required; unknown names go to
36
+ * the harness catalog so preset commands (`/permissions`, `/status`, …) work.
37
+ * At submit, a harness-kind line the command registry does not match falls
38
+ * through to a user prompt — user-invocable skills load through that
39
+ * host-side gesture boundary, so a hand-typed `/skill-name` reaches the model
40
+ * the same way a menu pick would.
41
+ * @param line - the raw composer contents.
42
+ */
43
+ export declare function parseSlash(line: string): ParsedSlash;
44
+ //# sourceMappingURL=slash.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slash.d.ts","sourceRoot":"","sources":["../src/slash.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,kEAAkE;AAClE,eAAO,MAAM,WAAW,yJAEd,CAAA;AAEV,iFAAiF;AACjF,eAAO,MAAM,oBAAoB,oCAAqC,CAAA;AAEtE,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAA;AAEzD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAC/B;AAED;;;;GAIG;AACH,eAAO,MAAM,cAAc,EAAE,SAAS,YAAY,EAoBxC,CAAA;AAEV,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACjD;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AAapB,+EAA+E;AAC/E,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAElE;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAkBpD"}
package/lib/slash.js ADDED
@@ -0,0 +1,81 @@
1
+ /**
2
+ * TUI-local slash parsing. Harness commands still dispatch through
3
+ * `ctx.commands`; these names are owned by the terminal surface.
4
+ * @module @dsh-cc/tui/slash
5
+ */
6
+ /** Slash names the TUI handles without calling `ctx.commands`. */
7
+ export const LOCAL_SLASH = [
8
+ 'quit', 'exit', 'clear', 'new', 'reset', 'tui-help', 'resume', 'model', 'effort', 'agents', 'cost', 'usage', 'export-md', 'copy', 'provider',
9
+ ];
10
+ /** `/provider` subcommands (§4.1) — surfaced as the argument completer hints. */
11
+ export const PROVIDER_SUBCOMMANDS = ['list', 'add', 'remove'];
12
+ /**
13
+ * Catalog of TUI-owned slash commands, surfaced via {@link Driver.listCommands}
14
+ * and the composer autocomplete. Descriptions mirror runLocal's behavior so
15
+ * the suggestion list matches what each command actually does.
16
+ */
17
+ export const LOCAL_COMMANDS = [
18
+ { name: 'quit', description: 'Exit the TUI session' },
19
+ { name: 'exit', description: 'Exit the TUI session' },
20
+ { name: 'clear', description: 'Start a new conversation (empty context). Previous session stays resumable.' },
21
+ { name: 'new', description: 'Alias of /clear' },
22
+ { name: 'reset', description: 'Alias of /clear' },
23
+ { name: 'tui-help', description: 'Show TUI keyboard and command help' },
24
+ { name: 'resume', description: 'Switch to a resumed session (picker or /resume <id>)', argumentHint: '<sessionId>' },
25
+ { name: 'model', description: 'List or switch the active model', argumentHint: '<n|provider/id>' },
26
+ { name: 'effort', description: 'Set reasoning effort for the current model', argumentHint: '<level|default>' },
27
+ { name: 'agents', description: 'List, inspect, or stop background agents', argumentHint: '[<id>|stop <id>]' },
28
+ { name: 'cost', description: 'Show token usage' },
29
+ { name: 'usage', description: 'Open the live token and context usage panel' },
30
+ {
31
+ name: 'export-md',
32
+ description: 'Export the transcript to a Markdown file',
33
+ argumentHint: '<path>',
34
+ },
35
+ { name: 'copy', description: 'Copy the latest assistant reply to the clipboard' },
36
+ { name: 'provider', description: 'Manage LLM provider routes and API keys', argumentHint: '[list | add <preset-id> | remove <route>]' },
37
+ ];
38
+ /**
39
+ * Plugin-command names exposed by the cc-shell `ccPlugins` service in the
40
+ * colon form `plugin:command` (e.g. `codex:review`). The TUI treats them as
41
+ * local commands, so classification must see the live table — but slash.ts is
42
+ * a pure leaf with no service access, so the catalog section (which owns the
43
+ * service lookup) publishes the names here. Duck-typed optional consumption:
44
+ * an empty registry (no ccPlugins service, or none published yet) keeps the
45
+ * pre-plugin behavior untouched.
46
+ */
47
+ let pluginSlashNames = new Set();
48
+ /** Publish the current plugin-command name table (lowercased for matching). */
49
+ export function setPluginSlashNames(names) {
50
+ pluginSlashNames = new Set(names.map(name => name.toLowerCase()));
51
+ }
52
+ /**
53
+ * Classify one composer line. Leading slash required; unknown names go to
54
+ * the harness catalog so preset commands (`/permissions`, `/status`, …) work.
55
+ * At submit, a harness-kind line the command registry does not match falls
56
+ * through to a user prompt — user-invocable skills load through that
57
+ * host-side gesture boundary, so a hand-typed `/skill-name` reaches the model
58
+ * the same way a menu pick would.
59
+ * @param line - the raw composer contents.
60
+ */
61
+ export function parseSlash(line) {
62
+ const trimmed = line.trim();
63
+ if (!trimmed.startsWith('/'))
64
+ return { kind: 'none' };
65
+ const body = trimmed.slice(1);
66
+ const space = body.search(/\s/);
67
+ const name = (space === -1 ? body : body.slice(0, space)).toLowerCase();
68
+ const rawInput = space === -1 ? '' : body.slice(space).trim();
69
+ if (LOCAL_SLASH.includes(name)) {
70
+ return { kind: 'local', name, rawInput };
71
+ }
72
+ // Plugin commands (colon form, `plugin:command`) dispatch through the
73
+ // ccPlugins service in runLocal. A name NOT in the table keeps the harness
74
+ // fall-through — the skill-injection gesture boundary depends on it, so a
75
+ // colon name must never be hard-classified local on a miss.
76
+ if (pluginSlashNames.has(name)) {
77
+ return { kind: 'local', name, rawInput };
78
+ }
79
+ return { kind: 'harness', line: trimmed };
80
+ }
81
+ //# sourceMappingURL=slash.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slash.js","sourceRoot":"","sources":["../src/slash.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,kEAAkE;AAClE,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU;CACpI,CAAA;AAEV,iFAAiF;AACjF,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,QAAQ,CAAU,CAAA;AAUtE;;;;GAIG;AACH,MAAM,CAAC,MAAM,cAAc,GAA4B;IACrD,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,sBAAsB,EAAE;IACrD,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,sBAAsB,EAAE;IACrD,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,6EAA6E,EAAE;IAC7G,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE;IAC/C,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE;IACjD,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,oCAAoC,EAAE;IACvE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,sDAAsD,EAAE,YAAY,EAAE,aAAa,EAAE;IACpH,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,iCAAiC,EAAE,YAAY,EAAE,iBAAiB,EAAE;IAClG,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,4CAA4C,EAAE,YAAY,EAAE,iBAAiB,EAAE;IAC9G,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,0CAA0C,EAAE,YAAY,EAAE,kBAAkB,EAAE;IAC7G,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,kBAAkB,EAAE;IACjD,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,6CAA6C,EAAE;IAC7E;QACE,IAAI,EAAE,WAAW;QACjB,WAAW,EAAE,0CAA0C;QACvD,YAAY,EAAE,QAAQ;KACvB;IACD,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,kDAAkD,EAAE;IACjF,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,yCAAyC,EAAE,YAAY,EAAE,2CAA2C,EAAE;CAC/H,CAAA;AAOV;;;;;;;;GAQG;AACH,IAAI,gBAAgB,GAAwB,IAAI,GAAG,EAAE,CAAA;AAErD,+EAA+E;AAC/E,MAAM,UAAU,mBAAmB,CAAC,KAAwB;IAC1D,gBAAgB,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAA;AACnE,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAA;IAC3B,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAA;IACrD,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;IAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IAC/B,MAAM,IAAI,GAAG,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,WAAW,EAAE,CAAA;IACvE,MAAM,QAAQ,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAA;IAC7D,IAAK,WAAiC,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACtD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAA;IAC1C,CAAC;IACD,sEAAsE;IACtE,2EAA2E;IAC3E,0EAA0E;IAC1E,4DAA4D;IAC5D,IAAI,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/B,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAA;IAC1C,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,CAAA;AAC3C,CAAC"}