@code-yeongyu/senpi 2026.9.12-3 → 2026.9.13-2

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 (270) hide show
  1. package/CHANGELOG.md +63 -0
  2. package/README.md +3 -1
  3. package/dist/bun/cli.js +2 -3
  4. package/dist/bun/cli.js.map +1 -1
  5. package/dist/bun/runtime-modules.d.ts +3 -0
  6. package/dist/bun/runtime-modules.d.ts.map +1 -0
  7. package/dist/bun/runtime-modules.js +17 -0
  8. package/dist/bun/runtime-modules.js.map +1 -0
  9. package/dist/bun/runtime-setup.js +2 -5
  10. package/dist/bun/runtime-setup.js.map +1 -1
  11. package/dist/core/agent-session.d.ts +2 -2
  12. package/dist/core/agent-session.d.ts.map +1 -1
  13. package/dist/core/agent-session.js +38 -30
  14. package/dist/core/agent-session.js.map +1 -1
  15. package/dist/core/discovered-resource-scope.d.ts +23 -0
  16. package/dist/core/discovered-resource-scope.d.ts.map +1 -0
  17. package/dist/core/discovered-resource-scope.js +44 -0
  18. package/dist/core/discovered-resource-scope.js.map +1 -0
  19. package/dist/core/extensions/builtin/ask-user/notify.d.ts +24 -0
  20. package/dist/core/extensions/builtin/ask-user/notify.d.ts.map +1 -0
  21. package/dist/core/extensions/builtin/ask-user/notify.js +11 -0
  22. package/dist/core/extensions/builtin/ask-user/notify.js.map +1 -0
  23. package/dist/core/extensions/builtin/ask-user/registry.d.ts +2 -0
  24. package/dist/core/extensions/builtin/ask-user/registry.d.ts.map +1 -1
  25. package/dist/core/extensions/builtin/ask-user/registry.js.map +1 -1
  26. package/dist/core/extensions/builtin/ask-user/resume.d.ts +1 -1
  27. package/dist/core/extensions/builtin/ask-user/resume.d.ts.map +1 -1
  28. package/dist/core/extensions/builtin/ask-user/resume.js +10 -20
  29. package/dist/core/extensions/builtin/ask-user/resume.js.map +1 -1
  30. package/dist/core/extensions/builtin/ask-user/tool.d.ts +5 -2
  31. package/dist/core/extensions/builtin/ask-user/tool.d.ts.map +1 -1
  32. package/dist/core/extensions/builtin/ask-user/tool.js +41 -6
  33. package/dist/core/extensions/builtin/ask-user/tool.js.map +1 -1
  34. package/dist/core/extensions/builtin/goal/channel-state-subscriptions.d.ts +2 -1
  35. package/dist/core/extensions/builtin/goal/channel-state-subscriptions.d.ts.map +1 -1
  36. package/dist/core/extensions/builtin/goal/channel-state-subscriptions.js +1 -1
  37. package/dist/core/extensions/builtin/goal/channel-state-subscriptions.js.map +1 -1
  38. package/dist/core/extensions/builtin/goal/monitor-continuation.d.ts.map +1 -1
  39. package/dist/core/extensions/builtin/goal/monitor-continuation.js +27 -13
  40. package/dist/core/extensions/builtin/goal/monitor-continuation.js.map +1 -1
  41. package/dist/core/extensions/builtin/hooks/config-loader.d.ts +2 -0
  42. package/dist/core/extensions/builtin/hooks/config-loader.d.ts.map +1 -1
  43. package/dist/core/extensions/builtin/hooks/config-loader.js +27 -0
  44. package/dist/core/extensions/builtin/hooks/config-loader.js.map +1 -1
  45. package/dist/core/extensions/builtin/hooks/dispatcher.js +1 -0
  46. package/dist/core/extensions/builtin/hooks/dispatcher.js.map +1 -1
  47. package/dist/core/extensions/builtin/hooks/index.d.ts.map +1 -1
  48. package/dist/core/extensions/builtin/hooks/index.js +51 -2
  49. package/dist/core/extensions/builtin/hooks/index.js.map +1 -1
  50. package/dist/core/extensions/builtin/hooks/lifecycle-adapter.d.ts +18 -1
  51. package/dist/core/extensions/builtin/hooks/lifecycle-adapter.d.ts.map +1 -1
  52. package/dist/core/extensions/builtin/hooks/lifecycle-adapter.js +36 -1
  53. package/dist/core/extensions/builtin/hooks/lifecycle-adapter.js.map +1 -1
  54. package/dist/core/extensions/builtin/hooks/matcher.js +1 -0
  55. package/dist/core/extensions/builtin/hooks/matcher.js.map +1 -1
  56. package/dist/core/extensions/builtin/hooks/output-parser.js +6 -0
  57. package/dist/core/extensions/builtin/hooks/output-parser.js.map +1 -1
  58. package/dist/core/extensions/builtin/hooks/trust-storage.d.ts +2 -0
  59. package/dist/core/extensions/builtin/hooks/trust-storage.d.ts.map +1 -1
  60. package/dist/core/extensions/builtin/hooks/trust-storage.js +13 -0
  61. package/dist/core/extensions/builtin/hooks/trust-storage.js.map +1 -1
  62. package/dist/core/extensions/builtin/hooks/types.d.ts +14 -2
  63. package/dist/core/extensions/builtin/hooks/types.d.ts.map +1 -1
  64. package/dist/core/extensions/builtin/hooks/types.js +1 -1
  65. package/dist/core/extensions/builtin/hooks/types.js.map +1 -1
  66. package/dist/core/extensions/builtin/monitor-state-event.d.ts +1 -0
  67. package/dist/core/extensions/builtin/monitor-state-event.d.ts.map +1 -1
  68. package/dist/core/extensions/builtin/monitor-state-event.js.map +1 -1
  69. package/dist/core/extensions/builtin/terminal/tools/bash.d.ts +1 -0
  70. package/dist/core/extensions/builtin/terminal/tools/bash.d.ts.map +1 -1
  71. package/dist/core/extensions/builtin/terminal/tools/bash.js +13 -2
  72. package/dist/core/extensions/builtin/terminal/tools/bash.js.map +1 -1
  73. package/dist/core/extensions/loader.d.ts.map +1 -1
  74. package/dist/core/extensions/loader.js +5 -1
  75. package/dist/core/extensions/loader.js.map +1 -1
  76. package/dist/core/extensions/runner.d.ts +5 -16
  77. package/dist/core/extensions/runner.d.ts.map +1 -1
  78. package/dist/core/extensions/runner.js +16 -5
  79. package/dist/core/extensions/runner.js.map +1 -1
  80. package/dist/core/extensions/types.d.ts +28 -5
  81. package/dist/core/extensions/types.d.ts.map +1 -1
  82. package/dist/core/extensions/types.js.map +1 -1
  83. package/dist/core/extensions/wrapper.d.ts +8 -3
  84. package/dist/core/extensions/wrapper.d.ts.map +1 -1
  85. package/dist/core/extensions/wrapper.js +12 -6
  86. package/dist/core/extensions/wrapper.js.map +1 -1
  87. package/dist/core/keybindings.d.ts +8 -1
  88. package/dist/core/keybindings.d.ts.map +1 -1
  89. package/dist/core/keybindings.js +7 -1
  90. package/dist/core/keybindings.js.map +1 -1
  91. package/dist/core/package-manager.d.ts +4 -2
  92. package/dist/core/package-manager.d.ts.map +1 -1
  93. package/dist/core/package-manager.js +7 -2
  94. package/dist/core/package-manager.js.map +1 -1
  95. package/dist/core/pi-manifest.d.ts +2 -0
  96. package/dist/core/pi-manifest.d.ts.map +1 -1
  97. package/dist/core/pi-manifest.js +3 -0
  98. package/dist/core/pi-manifest.js.map +1 -1
  99. package/dist/core/resource-loader.d.ts +9 -0
  100. package/dist/core/resource-loader.d.ts.map +1 -1
  101. package/dist/core/resource-loader.js +69 -21
  102. package/dist/core/resource-loader.js.map +1 -1
  103. package/dist/core/settings-manager.d.ts +1 -0
  104. package/dist/core/settings-manager.d.ts.map +1 -1
  105. package/dist/core/settings-manager.js +1 -0
  106. package/dist/core/settings-manager.js.map +1 -1
  107. package/dist/core/settings-shapes.d.ts +1 -0
  108. package/dist/core/settings-shapes.d.ts.map +1 -1
  109. package/dist/core/settings-shapes.js.map +1 -1
  110. package/dist/core/source-info.d.ts +5 -1
  111. package/dist/core/source-info.d.ts.map +1 -1
  112. package/dist/core/source-info.js.map +1 -1
  113. package/dist/core/tools/bash.d.ts.map +1 -1
  114. package/dist/core/tools/bash.js +5 -0
  115. package/dist/core/tools/bash.js.map +1 -1
  116. package/dist/modes/app-server/server/skills.d.ts.map +1 -1
  117. package/dist/modes/app-server/server/skills.js +1 -0
  118. package/dist/modes/app-server/server/skills.js.map +1 -1
  119. package/dist/modes/interactive/components/ask-user-answer-chip.d.ts +17 -0
  120. package/dist/modes/interactive/components/ask-user-answer-chip.d.ts.map +1 -0
  121. package/dist/modes/interactive/components/ask-user-answer-chip.js +86 -0
  122. package/dist/modes/interactive/components/ask-user-answer-chip.js.map +1 -0
  123. package/dist/modes/interactive/components/ask-user-answer-key.d.ts +3 -1
  124. package/dist/modes/interactive/components/ask-user-answer-key.d.ts.map +1 -1
  125. package/dist/modes/interactive/components/ask-user-answer-key.js +11 -1
  126. package/dist/modes/interactive/components/ask-user-answer-key.js.map +1 -1
  127. package/dist/modes/interactive/components/ask-user-async-widget.d.ts +5 -2
  128. package/dist/modes/interactive/components/ask-user-async-widget.d.ts.map +1 -1
  129. package/dist/modes/interactive/components/ask-user-async-widget.js +18 -12
  130. package/dist/modes/interactive/components/ask-user-async-widget.js.map +1 -1
  131. package/dist/modes/interactive/components/ask-user-countdown.d.ts +8 -0
  132. package/dist/modes/interactive/components/ask-user-countdown.d.ts.map +1 -0
  133. package/dist/modes/interactive/components/ask-user-countdown.js +23 -0
  134. package/dist/modes/interactive/components/ask-user-countdown.js.map +1 -0
  135. package/dist/modes/interactive/components/ask-user-question-keys.d.ts.map +1 -1
  136. package/dist/modes/interactive/components/ask-user-question-keys.js +85 -17
  137. package/dist/modes/interactive/components/ask-user-question-keys.js.map +1 -1
  138. package/dist/modes/interactive/components/ask-user-question-render.d.ts.map +1 -1
  139. package/dist/modes/interactive/components/ask-user-question-render.js +22 -7
  140. package/dist/modes/interactive/components/ask-user-question-render.js.map +1 -1
  141. package/dist/modes/interactive/components/ask-user-question-state.d.ts +15 -0
  142. package/dist/modes/interactive/components/ask-user-question-state.d.ts.map +1 -1
  143. package/dist/modes/interactive/components/ask-user-question-state.js +57 -13
  144. package/dist/modes/interactive/components/ask-user-question-state.js.map +1 -1
  145. package/dist/modes/interactive/components/ask-user-question.d.ts +8 -2
  146. package/dist/modes/interactive/components/ask-user-question.d.ts.map +1 -1
  147. package/dist/modes/interactive/components/ask-user-question.js +16 -8
  148. package/dist/modes/interactive/components/ask-user-question.js.map +1 -1
  149. package/dist/modes/interactive/components/config-selector.d.ts +2 -1
  150. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  151. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  152. package/dist/modes/interactive/components/custom-editor.d.ts +2 -0
  153. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  154. package/dist/modes/interactive/components/custom-editor.js +10 -1
  155. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  156. package/dist/modes/interactive/components/loaded-resource-section.d.ts +14 -0
  157. package/dist/modes/interactive/components/loaded-resource-section.d.ts.map +1 -0
  158. package/dist/modes/interactive/components/loaded-resource-section.js +25 -0
  159. package/dist/modes/interactive/components/loaded-resource-section.js.map +1 -0
  160. package/dist/modes/interactive/components/user-message.d.ts +2 -1
  161. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  162. package/dist/modes/interactive/components/user-message.js +12 -2
  163. package/dist/modes/interactive/components/user-message.js.map +1 -1
  164. package/dist/modes/interactive/interactive-mode.d.ts +14 -11
  165. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  166. package/dist/modes/interactive/interactive-mode.js +263 -165
  167. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  168. package/dist/modes/interactive/loaded-resource-scopes.d.ts +28 -0
  169. package/dist/modes/interactive/loaded-resource-scopes.d.ts.map +1 -0
  170. package/dist/modes/interactive/loaded-resource-scopes.js +107 -0
  171. package/dist/modes/interactive/loaded-resource-scopes.js.map +1 -0
  172. package/dist/modes/interactive/tips/catalog/input-tips.d.ts +1 -1
  173. package/dist/modes/interactive/tips/catalog/input-tips.js +2 -2
  174. package/dist/modes/interactive/tips/catalog/input-tips.js.map +1 -1
  175. package/dist/modes/rpc/host-lifecycle.d.ts.map +1 -1
  176. package/dist/modes/rpc/host-lifecycle.js +7 -0
  177. package/dist/modes/rpc/host-lifecycle.js.map +1 -1
  178. package/dist/modes/rpc/session-worker.js +5 -0
  179. package/dist/modes/rpc/session-worker.js.map +1 -1
  180. package/docs/environment-variables.md +5 -1
  181. package/docs/extensions.md +43 -5
  182. package/docs/keybindings.md +5 -2
  183. package/docs/packages.md +17 -0
  184. package/docs/rpc.md +6 -3
  185. package/docs/settings.md +5 -1
  186. package/docs/tui.md +15 -3
  187. package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +28 -0
  188. package/node_modules/@code-yeongyu/senpi-codemode/README.md +16 -4
  189. package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
  190. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/worker-core.js +2 -0
  191. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/session-env.ts +6 -0
  192. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/detached-cell-manager.ts +6 -1
  193. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/run-eval-cell.ts +31 -12
  194. package/node_modules/@earendil-works/chord/package.json +1 -1
  195. package/node_modules/@earendil-works/pi-agent-core/dist/harness/messages.d.ts +1 -1
  196. package/node_modules/@earendil-works/pi-agent-core/dist/harness/messages.d.ts.map +1 -1
  197. package/node_modules/@earendil-works/pi-agent-core/dist/harness/messages.js +1 -1
  198. package/node_modules/@earendil-works/pi-agent-core/dist/harness/messages.js.map +1 -1
  199. package/node_modules/@earendil-works/pi-agent-core/package.json +4 -4
  200. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent.lazy.d.ts +2 -0
  201. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent.lazy.d.ts.map +1 -1
  202. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent.lazy.js +6 -1
  203. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent.lazy.js.map +1 -1
  204. package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.d.ts.map +1 -1
  205. package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.js +55 -17
  206. package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.js.map +1 -1
  207. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses-shared.d.ts.map +1 -1
  208. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses-shared.js +2 -1
  209. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses-shared.js.map +1 -1
  210. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.d.ts +2 -1
  211. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.d.ts.map +1 -1
  212. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js +9 -0
  213. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js.map +1 -1
  214. package/node_modules/@earendil-works/pi-ai/dist/api/responses-completion-grace.d.ts +30 -0
  215. package/node_modules/@earendil-works/pi-ai/dist/api/responses-completion-grace.d.ts.map +1 -0
  216. package/node_modules/@earendil-works/pi-ai/dist/api/responses-completion-grace.js +94 -0
  217. package/node_modules/@earendil-works/pi-ai/dist/api/responses-completion-grace.js.map +1 -0
  218. package/node_modules/@earendil-works/pi-ai/dist/api/websocket-liveness.d.ts +48 -0
  219. package/node_modules/@earendil-works/pi-ai/dist/api/websocket-liveness.d.ts.map +1 -0
  220. package/node_modules/@earendil-works/pi-ai/dist/api/websocket-liveness.js +104 -0
  221. package/node_modules/@earendil-works/pi-ai/dist/api/websocket-liveness.js.map +1 -0
  222. package/node_modules/@earendil-works/pi-ai/dist/devin-provider.d.ts +6 -0
  223. package/node_modules/@earendil-works/pi-ai/dist/devin-provider.d.ts.map +1 -0
  224. package/node_modules/@earendil-works/pi-ai/dist/devin-provider.js +4 -0
  225. package/node_modules/@earendil-works/pi-ai/dist/devin-provider.js.map +1 -0
  226. package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
  227. package/node_modules/@earendil-works/pi-ai/dist/providers/data/nvidia.json +1 -1
  228. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
  229. package/node_modules/@earendil-works/pi-ai/dist/providers/data/together.json +1 -1
  230. package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
  231. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.d.ts.map +1 -1
  232. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js +7 -3
  233. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js.map +1 -1
  234. package/node_modules/@earendil-works/pi-ai/package.json +10 -2
  235. package/node_modules/@earendil-works/pi-pty/package.json +1 -1
  236. package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
  237. package/node_modules/@earendil-works/pi-tui/README.md +11 -3
  238. package/node_modules/@earendil-works/pi-tui/dist/index.d.ts +2 -1
  239. package/node_modules/@earendil-works/pi-tui/dist/index.d.ts.map +1 -1
  240. package/node_modules/@earendil-works/pi-tui/dist/index.js +1 -0
  241. package/node_modules/@earendil-works/pi-tui/dist/index.js.map +1 -1
  242. package/node_modules/@earendil-works/pi-tui/dist/mouse-input.d.ts +37 -0
  243. package/node_modules/@earendil-works/pi-tui/dist/mouse-input.d.ts.map +1 -0
  244. package/node_modules/@earendil-works/pi-tui/dist/mouse-input.js +97 -0
  245. package/node_modules/@earendil-works/pi-tui/dist/mouse-input.js.map +1 -0
  246. package/node_modules/@earendil-works/pi-tui/dist/stdin-buffer.d.ts +2 -0
  247. package/node_modules/@earendil-works/pi-tui/dist/stdin-buffer.d.ts.map +1 -1
  248. package/node_modules/@earendil-works/pi-tui/dist/stdin-buffer.js +38 -0
  249. package/node_modules/@earendil-works/pi-tui/dist/stdin-buffer.js.map +1 -1
  250. package/node_modules/@earendil-works/pi-tui/dist/terminal.d.ts +25 -1
  251. package/node_modules/@earendil-works/pi-tui/dist/terminal.d.ts.map +1 -1
  252. package/node_modules/@earendil-works/pi-tui/dist/terminal.js +110 -4
  253. package/node_modules/@earendil-works/pi-tui/dist/terminal.js.map +1 -1
  254. package/node_modules/@earendil-works/pi-tui/dist/tui-alt-screen.d.ts.map +1 -1
  255. package/node_modules/@earendil-works/pi-tui/dist/tui-alt-screen.js +5 -50
  256. package/node_modules/@earendil-works/pi-tui/dist/tui-alt-screen.js.map +1 -1
  257. package/node_modules/@earendil-works/pi-tui/dist/tui-main-screen.d.ts +12 -0
  258. package/node_modules/@earendil-works/pi-tui/dist/tui-main-screen.d.ts.map +1 -1
  259. package/node_modules/@earendil-works/pi-tui/dist/tui-main-screen.js +129 -3
  260. package/node_modules/@earendil-works/pi-tui/dist/tui-main-screen.js.map +1 -1
  261. package/node_modules/@earendil-works/pi-tui/dist/tui.d.ts +28 -0
  262. package/node_modules/@earendil-works/pi-tui/dist/tui.d.ts.map +1 -1
  263. package/node_modules/@earendil-works/pi-tui/dist/tui.js +160 -0
  264. package/node_modules/@earendil-works/pi-tui/dist/tui.js.map +1 -1
  265. package/node_modules/@earendil-works/pi-tui/package.json +1 -1
  266. package/package.json +13 -9
  267. package/dist/bun/register-cursor-agent.d.ts +0 -2
  268. package/dist/bun/register-cursor-agent.d.ts.map +0 -1
  269. package/dist/bun/register-cursor-agent.js +0 -4
  270. package/dist/bun/register-cursor-agent.js.map +0 -1
@@ -8,11 +8,11 @@
8
8
  */
9
9
  import { Container, Text, TruncatedText } from "@earendil-works/pi-tui";
10
10
  import { theme } from "../theme/theme.js";
11
- import { ASK_USER_ANSWER_KEYBINDING } from "./ask-user-answer-key.js";
11
+ import { askUserAnswerKeyHint } from "./ask-user-answer-key.js";
12
+ import { AskUserCountdown } from "./ask-user-countdown.js";
12
13
  import { formatCountdownLabel } from "./ask-user-question-state.js";
13
- import { CountdownTimer } from "./countdown-timer.js";
14
14
  import { keyText } from "./keybinding-hints.js";
15
- /** Widget slot key used with `setWidget`; one pending async question at a time. */
15
+ /** Host-owned widget slot displaying one request from the pending queue. */
16
16
  export const ASK_USER_WIDGET_KEY = "ask-user";
17
17
  const INDENT = " ";
18
18
  function hasAnswer(answer) {
@@ -46,9 +46,11 @@ export function buildTimedOutResponse(request, draft, autoResolvedAfterMs) {
46
46
  autoResolvedAfterMs,
47
47
  };
48
48
  }
49
- export function renderStatusLine(unanswered, countdownLabel) {
49
+ export function renderStatusLine(unanswered, countdownLabel, pendingCount = 1) {
50
50
  const countdown = countdownLabel === "" ? "" : theme.fg("muted", ` · ${countdownLabel}`);
51
- return (theme.fg("accent", theme.bold("?")) + theme.fg("text", ` Question pending (${unanswered} unanswered)`) + countdown);
51
+ return (theme.fg("accent", theme.bold("?")) +
52
+ theme.fg("text", pendingCount > 1 ? ` ${pendingCount} questions pending` : ` Question pending (${unanswered} unanswered)`) +
53
+ countdown);
52
54
  }
53
55
  export function renderQuestionLine(question) {
54
56
  return (INDENT +
@@ -65,7 +67,7 @@ export function renderOptionsLine(question, remaining) {
65
67
  }
66
68
  /** Hint naming every way into the pending question; the shortcut segment follows the effective binding. */
67
69
  export function renderAnswerHint() {
68
- const shortcut = keyText(ASK_USER_ANSWER_KEYBINDING);
70
+ const shortcut = askUserAnswerKeyHint();
69
71
  const keys = shortcut === "" ? "enter" : `enter or ${shortcut}`;
70
72
  return [
71
73
  theme.fg("dim", keys) + theme.fg("muted", " to answer"),
@@ -79,11 +81,12 @@ export class AskUserAsyncWidget extends Container {
79
81
  this.countdownLabel = "";
80
82
  this.request = options.request;
81
83
  this.draft = options.draft;
82
- if (options.timeoutMs > 0) {
83
- this.countdown = new CountdownTimer(options.timeoutMs, options.tui, (seconds) => {
84
- this.countdownLabel = formatCountdownLabel(seconds * 1000);
84
+ this.pendingCount = options.pendingCount ?? 1;
85
+ if (options.timeoutMs > 0 || options.getDeadlineAtMs) {
86
+ this.countdown = new AskUserCountdown(options.timeoutMs, options.tui, (remainingMs) => {
87
+ this.countdownLabel = formatCountdownLabel(remainingMs);
85
88
  this.update();
86
- }, options.onExpire);
89
+ }, options.onExpire, options.getDeadlineAtMs);
87
90
  }
88
91
  this.update();
89
92
  }
@@ -95,12 +98,15 @@ export class AskUserAsyncWidget extends Container {
95
98
  const pending = unansweredIds(this.request, this.draft);
96
99
  const shown = this.request.questions.find((question) => question.id === pending[0]);
97
100
  this.clear();
98
- this.addChild(new Text(renderStatusLine(pending.length, this.countdownLabel), 1, 0));
101
+ this.addChild(new Text(renderStatusLine(pending.length, this.countdownLabel, this.pendingCount), 1, 0));
99
102
  if (shown) {
100
103
  this.addChild(new TruncatedText(renderQuestionLine(shown), 1, 0));
101
104
  this.addChild(new TruncatedText(renderOptionsLine(shown, pending.length - 1), 1, 0));
102
105
  }
103
- this.addChild(new Text(INDENT + renderAnswerHint(), 1, 0));
106
+ const nextHint = this.pendingCount > 1
107
+ ? theme.fg("muted", ` · +${this.pendingCount - 1} more · ${keyText("app.question.next")} next question`)
108
+ : "";
109
+ this.addChild(new Text(INDENT + renderAnswerHint() + nextHint, 1, 0));
104
110
  }
105
111
  }
106
112
  //# sourceMappingURL=ask-user-async-widget.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ask-user-async-widget.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/ask-user-async-widget.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Collapsed widget for a pending async (waitForAnswer=false) question: it\n * sits above the editor and shows the unanswered count with the idle\n * countdown, the first unanswered question with its options, and every way\n * into the full AskUserQuestionComponent. The response-building helpers here\n * are pure so interactive-mode can turn ordinary composer text into the\n * comment answer.\n */\n\nimport { Container, Text, TruncatedText, type TUI } from \"@earendil-works/pi-tui\";\nimport type { QuestionRequest, QuestionResponse } from \"../../../core/extensions/types.ts\";\nimport { theme } from \"../theme/theme.ts\";\nimport { ASK_USER_ANSWER_KEYBINDING } from \"./ask-user-answer-key.ts\";\nimport { formatCountdownLabel, type QuestionDraft } from \"./ask-user-question-state.ts\";\nimport { CountdownTimer } from \"./countdown-timer.ts\";\nimport { keyText } from \"./keybinding-hints.ts\";\n\n/** Widget slot key used with `setWidget`; one pending async question at a time. */\nexport const ASK_USER_WIDGET_KEY = \"ask-user\";\n\ntype Question = QuestionRequest[\"questions\"][number];\n\nconst INDENT = \" \";\n\nfunction hasAnswer(answer: QuestionResponse[\"answers\"][string] | undefined): boolean {\n\tif (!answer) return false;\n\tif (answer.selected.length > 0) return true;\n\treturn (answer.text ?? \"\").trim() !== \"\";\n}\n\n/** Question ids the draft has not answered yet. */\nexport function unansweredIds(request: QuestionRequest, draft: QuestionDraft): string[] {\n\treturn request.questions.filter((question) => !hasAnswer(draft.answers?.[question.id])).map((q) => q.id);\n}\n\n/** Response for composer text typed while the question is pending: the text is the comment. */\nexport function buildCommentResponse(\n\trequest: QuestionRequest,\n\tdraft: QuestionDraft,\n\tcomment: string,\n): QuestionResponse {\n\treturn {\n\t\tstatus: \"comment-submitted\",\n\t\tanswers: draft.answers ?? {},\n\t\tcomment,\n\t\tunanswered: unansweredIds(request, draft),\n\t};\n}\n\n/** Response for an idle countdown that expired while the widget was collapsed. */\nexport function buildTimedOutResponse(\n\trequest: QuestionRequest,\n\tdraft: QuestionDraft,\n\tautoResolvedAfterMs: number,\n): QuestionResponse {\n\tconst comment = draft.comment?.trim();\n\treturn {\n\t\tstatus: \"timed_out\",\n\t\tanswers: draft.answers ?? {},\n\t\t...(comment ? { comment } : {}),\n\t\tunanswered: unansweredIds(request, draft),\n\t\tautoResolvedAfterMs,\n\t};\n}\n\nexport function renderStatusLine(unanswered: number, countdownLabel: string): string {\n\tconst countdown = countdownLabel === \"\" ? \"\" : theme.fg(\"muted\", ` · ${countdownLabel}`);\n\treturn (\n\t\ttheme.fg(\"accent\", theme.bold(\"?\")) + theme.fg(\"text\", ` Question pending (${unanswered} unanswered)`) + countdown\n\t);\n}\n\nexport function renderQuestionLine(question: Question): string {\n\treturn (\n\t\tINDENT +\n\t\ttheme.fg(\"text\", theme.bold(question.header)) +\n\t\ttheme.fg(\"muted\", \" — \") +\n\t\ttheme.fg(\"text\", question.question)\n\t);\n}\n\nexport function renderOptionsLine(question: Question, remaining: number): string {\n\tconst parts = question.options.map(\n\t\t(option, index) => theme.fg(\"dim\", `${index + 1}`) + theme.fg(\"muted\", ` ${option.label}`),\n\t);\n\tparts.push(theme.fg(\"muted\", \"own answer\"));\n\tif (remaining > 0) parts.push(theme.fg(\"muted\", `+${remaining} more question${remaining === 1 ? \"\" : \"s\"}`));\n\treturn INDENT + parts.join(theme.fg(\"muted\", \" · \"));\n}\n\n/** Hint naming every way into the pending question; the shortcut segment follows the effective binding. */\nexport function renderAnswerHint(): string {\n\tconst shortcut = keyText(ASK_USER_ANSWER_KEYBINDING);\n\tconst keys = shortcut === \"\" ? \"enter\" : `enter or ${shortcut}`;\n\treturn [\n\t\ttheme.fg(\"dim\", keys) + theme.fg(\"muted\", \" to answer\"),\n\t\ttheme.fg(\"dim\", \"/answer\"),\n\t\ttheme.fg(\"muted\", \"or just type your reply\"),\n\t].join(theme.fg(\"muted\", \" · \"));\n}\n\nexport interface AskUserAsyncWidgetOptions {\n\trequest: QuestionRequest;\n\tdraft: QuestionDraft;\n\t/** Idle countdown shown in the line; 0 disables it. */\n\ttimeoutMs: number;\n\ttui?: TUI;\n\tonExpire: () => void;\n}\n\nexport class AskUserAsyncWidget extends Container {\n\tprivate readonly request: QuestionRequest;\n\tprivate readonly draft: QuestionDraft;\n\tprivate readonly countdown: CountdownTimer | undefined;\n\tprivate countdownLabel = \"\";\n\n\tconstructor(options: AskUserAsyncWidgetOptions) {\n\t\tsuper();\n\t\tthis.request = options.request;\n\t\tthis.draft = options.draft;\n\t\tif (options.timeoutMs > 0) {\n\t\t\tthis.countdown = new CountdownTimer(\n\t\t\t\toptions.timeoutMs,\n\t\t\t\toptions.tui,\n\t\t\t\t(seconds) => {\n\t\t\t\t\tthis.countdownLabel = formatCountdownLabel(seconds * 1000);\n\t\t\t\t\tthis.update();\n\t\t\t\t},\n\t\t\t\toptions.onExpire,\n\t\t\t);\n\t\t}\n\t\tthis.update();\n\t}\n\n\tdispose(): void {\n\t\tthis.countdown?.dispose();\n\t\tsuper.dispose();\n\t}\n\n\tprivate update(): void {\n\t\tconst pending = unansweredIds(this.request, this.draft);\n\t\tconst shown = this.request.questions.find((question) => question.id === pending[0]);\n\t\tthis.clear();\n\t\tthis.addChild(new Text(renderStatusLine(pending.length, this.countdownLabel), 1, 0));\n\t\tif (shown) {\n\t\t\tthis.addChild(new TruncatedText(renderQuestionLine(shown), 1, 0));\n\t\t\tthis.addChild(new TruncatedText(renderOptionsLine(shown, pending.length - 1), 1, 0));\n\t\t}\n\t\tthis.addChild(new Text(INDENT + renderAnswerHint(), 1, 0));\n\t}\n}\n"]}
1
+ {"version":3,"file":"ask-user-async-widget.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/ask-user-async-widget.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Collapsed widget for a pending async (waitForAnswer=false) question: it\n * sits above the editor and shows the unanswered count with the idle\n * countdown, the first unanswered question with its options, and every way\n * into the full AskUserQuestionComponent. The response-building helpers here\n * are pure so interactive-mode can turn ordinary composer text into the\n * comment answer.\n */\n\nimport { Container, Text, TruncatedText, type TUI } from \"@earendil-works/pi-tui\";\nimport type { QuestionRequest, QuestionResponse } from \"../../../core/extensions/types.ts\";\nimport { theme } from \"../theme/theme.ts\";\nimport { askUserAnswerKeyHint } from \"./ask-user-answer-key.ts\";\nimport { AskUserCountdown } from \"./ask-user-countdown.ts\";\nimport { formatCountdownLabel, type QuestionDraft } from \"./ask-user-question-state.ts\";\nimport { keyText } from \"./keybinding-hints.ts\";\n\n/** Host-owned widget slot displaying one request from the pending queue. */\nexport const ASK_USER_WIDGET_KEY = \"ask-user\";\n\ntype Question = QuestionRequest[\"questions\"][number];\n\nconst INDENT = \" \";\n\nfunction hasAnswer(answer: QuestionResponse[\"answers\"][string] | undefined): boolean {\n\tif (!answer) return false;\n\tif (answer.selected.length > 0) return true;\n\treturn (answer.text ?? \"\").trim() !== \"\";\n}\n\n/** Question ids the draft has not answered yet. */\nexport function unansweredIds(request: QuestionRequest, draft: QuestionDraft): string[] {\n\treturn request.questions.filter((question) => !hasAnswer(draft.answers?.[question.id])).map((q) => q.id);\n}\n\n/** Response for composer text typed while the question is pending: the text is the comment. */\nexport function buildCommentResponse(\n\trequest: QuestionRequest,\n\tdraft: QuestionDraft,\n\tcomment: string,\n): QuestionResponse {\n\treturn {\n\t\tstatus: \"comment-submitted\",\n\t\tanswers: draft.answers ?? {},\n\t\tcomment,\n\t\tunanswered: unansweredIds(request, draft),\n\t};\n}\n\n/** Response for an idle countdown that expired while the widget was collapsed. */\nexport function buildTimedOutResponse(\n\trequest: QuestionRequest,\n\tdraft: QuestionDraft,\n\tautoResolvedAfterMs: number,\n): QuestionResponse {\n\tconst comment = draft.comment?.trim();\n\treturn {\n\t\tstatus: \"timed_out\",\n\t\tanswers: draft.answers ?? {},\n\t\t...(comment ? { comment } : {}),\n\t\tunanswered: unansweredIds(request, draft),\n\t\tautoResolvedAfterMs,\n\t};\n}\n\nexport function renderStatusLine(unanswered: number, countdownLabel: string, pendingCount = 1): string {\n\tconst countdown = countdownLabel === \"\" ? \"\" : theme.fg(\"muted\", ` · ${countdownLabel}`);\n\treturn (\n\t\ttheme.fg(\"accent\", theme.bold(\"?\")) +\n\t\ttheme.fg(\n\t\t\t\"text\",\n\t\t\tpendingCount > 1 ? ` ${pendingCount} questions pending` : ` Question pending (${unanswered} unanswered)`,\n\t\t) +\n\t\tcountdown\n\t);\n}\n\nexport function renderQuestionLine(question: Question): string {\n\treturn (\n\t\tINDENT +\n\t\ttheme.fg(\"text\", theme.bold(question.header)) +\n\t\ttheme.fg(\"muted\", \" — \") +\n\t\ttheme.fg(\"text\", question.question)\n\t);\n}\n\nexport function renderOptionsLine(question: Question, remaining: number): string {\n\tconst parts = question.options.map(\n\t\t(option, index) => theme.fg(\"dim\", `${index + 1}`) + theme.fg(\"muted\", ` ${option.label}`),\n\t);\n\tparts.push(theme.fg(\"muted\", \"own answer\"));\n\tif (remaining > 0) parts.push(theme.fg(\"muted\", `+${remaining} more question${remaining === 1 ? \"\" : \"s\"}`));\n\treturn INDENT + parts.join(theme.fg(\"muted\", \" · \"));\n}\n\n/** Hint naming every way into the pending question; the shortcut segment follows the effective binding. */\nexport function renderAnswerHint(): string {\n\tconst shortcut = askUserAnswerKeyHint();\n\tconst keys = shortcut === \"\" ? \"enter\" : `enter or ${shortcut}`;\n\treturn [\n\t\ttheme.fg(\"dim\", keys) + theme.fg(\"muted\", \" to answer\"),\n\t\ttheme.fg(\"dim\", \"/answer\"),\n\t\ttheme.fg(\"muted\", \"or just type your reply\"),\n\t].join(theme.fg(\"muted\", \" · \"));\n}\n\nexport interface AskUserAsyncWidgetOptions {\n\trequest: QuestionRequest;\n\tdraft: QuestionDraft;\n\t/** Idle countdown shown in the line; 0 disables it. */\n\ttimeoutMs: number;\n\tgetDeadlineAtMs?: () => number;\n\tpendingCount?: number;\n\ttui?: TUI;\n\tonExpire: () => void;\n}\n\nexport class AskUserAsyncWidget extends Container {\n\tprivate readonly request: QuestionRequest;\n\tprivate readonly draft: QuestionDraft;\n\tprivate readonly countdown: AskUserCountdown | undefined;\n\tprivate readonly pendingCount: number;\n\tprivate countdownLabel = \"\";\n\n\tconstructor(options: AskUserAsyncWidgetOptions) {\n\t\tsuper();\n\t\tthis.request = options.request;\n\t\tthis.draft = options.draft;\n\t\tthis.pendingCount = options.pendingCount ?? 1;\n\t\tif (options.timeoutMs > 0 || options.getDeadlineAtMs) {\n\t\t\tthis.countdown = new AskUserCountdown(\n\t\t\t\toptions.timeoutMs,\n\t\t\t\toptions.tui,\n\t\t\t\t(remainingMs) => {\n\t\t\t\t\tthis.countdownLabel = formatCountdownLabel(remainingMs);\n\t\t\t\t\tthis.update();\n\t\t\t\t},\n\t\t\t\toptions.onExpire,\n\t\t\t\toptions.getDeadlineAtMs,\n\t\t\t);\n\t\t}\n\t\tthis.update();\n\t}\n\n\tdispose(): void {\n\t\tthis.countdown?.dispose();\n\t\tsuper.dispose();\n\t}\n\n\tprivate update(): void {\n\t\tconst pending = unansweredIds(this.request, this.draft);\n\t\tconst shown = this.request.questions.find((question) => question.id === pending[0]);\n\t\tthis.clear();\n\t\tthis.addChild(new Text(renderStatusLine(pending.length, this.countdownLabel, this.pendingCount), 1, 0));\n\t\tif (shown) {\n\t\t\tthis.addChild(new TruncatedText(renderQuestionLine(shown), 1, 0));\n\t\t\tthis.addChild(new TruncatedText(renderOptionsLine(shown, pending.length - 1), 1, 0));\n\t\t}\n\t\tconst nextHint =\n\t\t\tthis.pendingCount > 1\n\t\t\t\t? theme.fg(\"muted\", ` · +${this.pendingCount - 1} more · ${keyText(\"app.question.next\")} next question`)\n\t\t\t\t: \"\";\n\t\tthis.addChild(new Text(INDENT + renderAnswerHint() + nextHint, 1, 0));\n\t}\n}\n"]}
@@ -0,0 +1,8 @@
1
+ import type { TUI } from "@earendil-works/pi-tui";
2
+ /** Absolute question countdown. An external deadline is display-only; its owner settles the request. */
3
+ export declare class AskUserCountdown {
4
+ private timer;
5
+ constructor(timeoutMs: number, tui: TUI | undefined, onTick: (remainingMs: number) => void, onExpire: () => void, getDeadlineAtMs?: () => number);
6
+ dispose(): void;
7
+ }
8
+ //# sourceMappingURL=ask-user-countdown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ask-user-countdown.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/ask-user-countdown.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,wBAAwB,CAAC;AAElD,wGAAwG;AACxG,qBAAa,gBAAgB;IAC5B,OAAO,CAAC,KAAK,CAA6C;IAE1D,YACC,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,GAAG,GAAG,SAAS,EACpB,MAAM,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,EACrC,QAAQ,EAAE,MAAM,IAAI,EACpB,eAAe,CAAC,EAAE,MAAM,MAAM,EAe9B;IAED,OAAO,IAAI,IAAI,CAGd;CACD"}
@@ -0,0 +1,23 @@
1
+ /** Absolute question countdown. An external deadline is display-only; its owner settles the request. */
2
+ export class AskUserCountdown {
3
+ constructor(timeoutMs, tui, onTick, onExpire, getDeadlineAtMs) {
4
+ const deadline = Date.now() + timeoutMs;
5
+ const tick = () => {
6
+ const remaining = Math.max(0, (getDeadlineAtMs?.() ?? deadline) - Date.now());
7
+ onTick(remaining);
8
+ tui?.requestRender();
9
+ if (remaining === 0 && !getDeadlineAtMs) {
10
+ this.dispose();
11
+ onExpire();
12
+ }
13
+ };
14
+ this.timer = setInterval(tick, 1_000);
15
+ this.timer.unref();
16
+ tick();
17
+ }
18
+ dispose() {
19
+ clearInterval(this.timer);
20
+ this.timer = undefined;
21
+ }
22
+ }
23
+ //# sourceMappingURL=ask-user-countdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ask-user-countdown.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/ask-user-countdown.ts"],"names":[],"mappings":"AAEA,wGAAwG;AACxG,MAAM,OAAO,gBAAgB;IAG5B,YACC,SAAiB,EACjB,GAAoB,EACpB,MAAqC,EACrC,QAAoB,EACpB,eAA8B;QAE9B,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;QACxC,MAAM,IAAI,GAAG,GAAG,EAAE;YACjB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,eAAe,EAAE,EAAE,IAAI,QAAQ,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;YAC9E,MAAM,CAAC,SAAS,CAAC,CAAC;YAClB,GAAG,EAAE,aAAa,EAAE,CAAC;YACrB,IAAI,SAAS,KAAK,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC;gBACzC,IAAI,CAAC,OAAO,EAAE,CAAC;gBACf,QAAQ,EAAE,CAAC;YACZ,CAAC;QACF,CAAC,CAAC;QACF,IAAI,CAAC,KAAK,GAAG,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACtC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACnB,IAAI,EAAE,CAAC;IACR,CAAC;IAED,OAAO;QACN,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1B,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC;IACxB,CAAC;CACD","sourcesContent":["import type { TUI } from \"@earendil-works/pi-tui\";\n\n/** Absolute question countdown. An external deadline is display-only; its owner settles the request. */\nexport class AskUserCountdown {\n\tprivate timer: ReturnType<typeof setInterval> | undefined;\n\n\tconstructor(\n\t\ttimeoutMs: number,\n\t\ttui: TUI | undefined,\n\t\tonTick: (remainingMs: number) => void,\n\t\tonExpire: () => void,\n\t\tgetDeadlineAtMs?: () => number,\n\t) {\n\t\tconst deadline = Date.now() + timeoutMs;\n\t\tconst tick = () => {\n\t\t\tconst remaining = Math.max(0, (getDeadlineAtMs?.() ?? deadline) - Date.now());\n\t\t\tonTick(remaining);\n\t\t\ttui?.requestRender();\n\t\t\tif (remaining === 0 && !getDeadlineAtMs) {\n\t\t\t\tthis.dispose();\n\t\t\t\tonExpire();\n\t\t\t}\n\t\t};\n\t\tthis.timer = setInterval(tick, 1_000);\n\t\tthis.timer.unref();\n\t\ttick();\n\t}\n\n\tdispose(): void {\n\t\tclearInterval(this.timer);\n\t\tthis.timer = undefined;\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"ask-user-question-keys.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/ask-user-question-keys.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAkB,KAAK,KAAK,EAAc,MAAM,wBAAwB,CAAC;AAChF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAC1E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAEzE,MAAM,WAAW,wBAAwB;IACxC,KAAK,EAAE,oBAAoB,CAAC;IAC5B,cAAc,EAAE,KAAK,CAAC;IACtB,YAAY,EAAE,KAAK,CAAC;IACpB,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,QAAQ,CAAC,EAAE,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/E,aAAa,IAAI,IAAI,CAAC;IACtB,aAAa,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1C,eAAe,IAAI,IAAI,CAAC;IACxB,YAAY,IAAI,IAAI,CAAC;IACrB,SAAS,IAAI,IAAI,CAAC;CAClB;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,wBAAwB,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAevF"}
1
+ {"version":3,"file":"ask-user-question-keys.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/ask-user-question-keys.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAkB,KAAK,KAAK,EAAc,MAAM,wBAAwB,CAAC;AAChF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAC1E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAEzE,MAAM,WAAW,wBAAwB;IACxC,KAAK,EAAE,oBAAoB,CAAC;IAC5B,cAAc,EAAE,KAAK,CAAC;IACtB,YAAY,EAAE,KAAK,CAAC;IACpB,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,QAAQ,CAAC,EAAE,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/E,aAAa,IAAI,IAAI,CAAC;IACtB,aAAa,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1C,eAAe,IAAI,IAAI,CAAC;IACxB,YAAY,IAAI,IAAI,CAAC;IACrB,SAAS,IAAI,IAAI,CAAC;CAClB;AAUD,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,wBAAwB,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAevF"}
@@ -4,6 +4,10 @@
4
4
  * the component's Inputs via an explicit context.
5
5
  */
6
6
  import { getKeybindings, matchesKey } from "@earendil-works/pi-tui";
7
+ const DEL = "\x7f";
8
+ function isPrintable(data) {
9
+ return data.length === 1 && data >= " " && data !== DEL;
10
+ }
7
11
  export function handleAskUserKeyInput(ctx, data) {
8
12
  const kb = getKeybindings();
9
13
  if (matchesKey(data, "ctrl+c")) {
@@ -20,7 +24,15 @@ export function handleAskUserKeyInput(ctx, data) {
20
24
  }
21
25
  handleOptionsKey(ctx, data, kb);
22
26
  }
27
+ /** Navigation out of the editor saves typed text but never wipes an existing answer with an empty editor. */
28
+ function saveTypedOwnAnswer(ctx) {
29
+ if (ctx.ownAnswerInput.getValue().trim() !== "")
30
+ ctx.commitOwnAnswer();
31
+ else
32
+ ctx.ownAnswerInput.setValue("");
33
+ }
23
34
  function handleOwnAnswerKey(ctx, data, kb) {
35
+ const state = ctx.state;
24
36
  if (matchesKey(data, "ctrl+enter")) {
25
37
  ctx.commitOwnAnswer();
26
38
  ctx.attemptSubmit();
@@ -28,15 +40,36 @@ function handleOwnAnswerKey(ctx, data, kb) {
28
40
  }
29
41
  if (kb.matches(data, "tui.select.confirm") || data === "\n") {
30
42
  ctx.commitOwnAnswer();
31
- ctx.state.advance();
43
+ state.advance();
32
44
  ctx.updateAll();
33
45
  return;
34
46
  }
35
47
  if (kb.matches(data, "tui.select.cancel")) {
36
- if (ctx.state.request.waitForAnswer)
37
- ctx.state.returnToOptions();
38
- else
39
- ctx.finish("cancelled");
48
+ ctx.ownAnswerInput.setValue("");
49
+ state.leaveOwnAnswer(state.ownAnswerRowIndex);
50
+ ctx.updateAll();
51
+ return;
52
+ }
53
+ if (kb.matches(data, "tui.select.up")) {
54
+ saveTypedOwnAnswer(ctx);
55
+ state.leaveOwnAnswer(state.ownAnswerRowIndex - 1);
56
+ ctx.updateAll();
57
+ return;
58
+ }
59
+ if (kb.matches(data, "tui.select.down")) {
60
+ saveTypedOwnAnswer(ctx);
61
+ state.leaveOwnAnswer(state.ownAnswerRowIndex);
62
+ ctx.updateAll();
63
+ return;
64
+ }
65
+ if (matchesKey(data, "tab") || matchesKey(data, "shift+tab")) {
66
+ saveTypedOwnAnswer(ctx);
67
+ state.switchTab(matchesKey(data, "tab") ? 1 : -1);
68
+ ctx.updateAll();
69
+ return;
70
+ }
71
+ if (matchesKey(data, "backspace") && ctx.ownAnswerInput.getValue() === "") {
72
+ state.leaveOwnAnswer(state.ownAnswerRowIndex);
40
73
  ctx.updateAll();
41
74
  return;
42
75
  }
@@ -44,30 +77,59 @@ function handleOwnAnswerKey(ctx, data, kb) {
44
77
  ctx.emitProgress();
45
78
  }
46
79
  function handleSubmitKey(ctx, data, kb) {
47
- if (matchesKey(data, "ctrl+enter") || kb.matches(data, "tui.input.submit") || data === "\n") {
80
+ const state = ctx.state;
81
+ if (matchesKey(data, "ctrl+enter")) {
48
82
  ctx.attemptSubmit();
49
83
  return;
50
84
  }
85
+ if (kb.matches(data, "tui.input.submit") || data === "\n") {
86
+ if (state.isCommentFocused)
87
+ ctx.attemptSubmit();
88
+ else {
89
+ state.jumpToQuestion(state.submitRowIndex);
90
+ ctx.updateAll();
91
+ }
92
+ return;
93
+ }
51
94
  if (kb.matches(data, "tui.select.cancel")) {
52
- if (ctx.state.request.waitForAnswer)
53
- ctx.state.returnToOptions();
95
+ if (state.request.waitForAnswer)
96
+ state.returnToOptions();
54
97
  else
55
98
  ctx.finish("cancelled");
56
99
  ctx.updateAll();
57
100
  return;
58
101
  }
59
- if (matchesKey(data, "shift+tab") || matchesKey(data, "left")) {
60
- ctx.state.switchTab(-1);
102
+ if (kb.matches(data, "tui.select.up") || kb.matches(data, "tui.select.down")) {
103
+ state.moveSubmitRow(kb.matches(data, "tui.select.up") ? -1 : 1);
61
104
  ctx.updateAll();
62
105
  return;
63
106
  }
64
- if (matchesKey(data, "tab") || matchesKey(data, "right")) {
65
- ctx.state.switchTab(1);
107
+ if (matchesKey(data, "shift+tab") || matchesKey(data, "tab")) {
108
+ state.switchTab(matchesKey(data, "tab") ? 1 : -1);
66
109
  ctx.updateAll();
67
110
  return;
68
111
  }
112
+ const commentHasText = ctx.commentInput.getValue() !== "";
113
+ if (matchesKey(data, "left") || matchesKey(data, "right")) {
114
+ if (!state.isCommentFocused || !commentHasText) {
115
+ state.switchTab(matchesKey(data, "right") ? 1 : -1);
116
+ ctx.updateAll();
117
+ return;
118
+ }
119
+ }
120
+ if (matchesKey(data, "backspace") && state.isCommentFocused && !commentHasText) {
121
+ state.moveSubmitRow(-1);
122
+ ctx.updateAll();
123
+ return;
124
+ }
125
+ if (!state.isCommentFocused) {
126
+ if (!isPrintable(data))
127
+ return;
128
+ state.focusComment();
129
+ }
69
130
  ctx.commentInput.handleInput(data);
70
- ctx.state.comment = ctx.commentInput.getValue();
131
+ state.comment = ctx.commentInput.getValue();
132
+ ctx.updateAll();
71
133
  ctx.emitProgress();
72
134
  }
73
135
  function handleOptionsKey(ctx, data, kb) {
@@ -103,13 +165,19 @@ function handleOptionsKey(ctx, data, kb) {
103
165
  ctx.updateAll();
104
166
  return;
105
167
  }
168
+ if (matchesKey(data, "backspace")) {
169
+ state.clearAnswer(state.activeQuestion.id);
170
+ ctx.emitProgress();
171
+ ctx.updateAll();
172
+ return;
173
+ }
106
174
  if (data.length === 1 && data >= "1" && data <= "9") {
107
175
  const option = state.activeQuestion.options[Number(data) - 1];
108
176
  if (option) {
109
177
  state.activateOption(state.activeQuestion.id, option.label);
110
178
  ctx.emitProgress();
111
179
  if (!state.activeQuestion.multiSelect) {
112
- if (state.request.waitForAnswer && state.request.questions.length === 1)
180
+ if (state.request.questions.length === 1)
113
181
  ctx.attemptSubmit();
114
182
  else
115
183
  state.advance();
@@ -127,11 +195,11 @@ function handleOptionsKey(ctx, data, kb) {
127
195
  return;
128
196
  }
129
197
  if (data === "c") {
130
- state.focus = "submit";
198
+ state.enterSubmit();
131
199
  ctx.updateAll();
132
200
  return;
133
201
  }
134
- if (data.length === 1 && data >= " " && data !== "c") {
202
+ if (isPrintable(data)) {
135
203
  ctx.openOwnAnswer(data);
136
204
  ctx.updateAll();
137
205
  }
@@ -151,7 +219,7 @@ function activateHighlighted(ctx, confirm) {
151
219
  ctx.emitProgress();
152
220
  ctx.updateAll();
153
221
  if (confirm) {
154
- if (!state.activeQuestion.multiSelect && state.request.waitForAnswer && state.request.questions.length === 1) {
222
+ if (!state.activeQuestion.multiSelect && state.request.questions.length === 1) {
155
223
  ctx.attemptSubmit();
156
224
  }
157
225
  else {
@@ -1 +1 @@
1
- {"version":3,"file":"ask-user-question-keys.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/ask-user-question-keys.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Key dispatch for the ask-user question overlay. Split from the component to\n * keep every sibling under 250 LOC; handlers operate on the shared state and\n * the component's Inputs via an explicit context.\n */\n\nimport { getKeybindings, type Input, matchesKey } from \"@earendil-works/pi-tui\";\nimport type { QuestionResponse } from \"../../../core/extensions/types.ts\";\nimport type { AskUserQuestionState } from \"./ask-user-question-state.ts\";\n\nexport interface AskUserKeyHandlerContext {\n\tstate: AskUserQuestionState;\n\townAnswerInput: Input;\n\tcommentInput: Input;\n\tfinish(status: QuestionResponse[\"status\"], autoResolvedAfterMs?: number): void;\n\tattemptSubmit(): void;\n\topenOwnAnswer(initialText?: string): void;\n\tcommitOwnAnswer(): void;\n\temitProgress(): void;\n\tupdateAll(): void;\n}\n\nexport function handleAskUserKeyInput(ctx: AskUserKeyHandlerContext, data: string): void {\n\tconst kb = getKeybindings();\n\tif (matchesKey(data, \"ctrl+c\")) {\n\t\tctx.finish(\"cancelled\");\n\t\treturn;\n\t}\n\tif (ctx.state.focus === \"own-answer\") {\n\t\thandleOwnAnswerKey(ctx, data, kb);\n\t\treturn;\n\t}\n\tif (ctx.state.focus === \"submit\") {\n\t\thandleSubmitKey(ctx, data, kb);\n\t\treturn;\n\t}\n\thandleOptionsKey(ctx, data, kb);\n}\n\nfunction handleOwnAnswerKey(ctx: AskUserKeyHandlerContext, data: string, kb: ReturnType<typeof getKeybindings>): void {\n\tif (matchesKey(data, \"ctrl+enter\")) {\n\t\tctx.commitOwnAnswer();\n\t\tctx.attemptSubmit();\n\t\treturn;\n\t}\n\tif (kb.matches(data, \"tui.select.confirm\") || data === \"\\n\") {\n\t\tctx.commitOwnAnswer();\n\t\tctx.state.advance();\n\t\tctx.updateAll();\n\t\treturn;\n\t}\n\tif (kb.matches(data, \"tui.select.cancel\")) {\n\t\tif (ctx.state.request.waitForAnswer) ctx.state.returnToOptions();\n\t\telse ctx.finish(\"cancelled\");\n\t\tctx.updateAll();\n\t\treturn;\n\t}\n\tctx.ownAnswerInput.handleInput(data);\n\tctx.emitProgress();\n}\n\nfunction handleSubmitKey(ctx: AskUserKeyHandlerContext, data: string, kb: ReturnType<typeof getKeybindings>): void {\n\tif (matchesKey(data, \"ctrl+enter\") || kb.matches(data, \"tui.input.submit\") || data === \"\\n\") {\n\t\tctx.attemptSubmit();\n\t\treturn;\n\t}\n\tif (kb.matches(data, \"tui.select.cancel\")) {\n\t\tif (ctx.state.request.waitForAnswer) ctx.state.returnToOptions();\n\t\telse ctx.finish(\"cancelled\");\n\t\tctx.updateAll();\n\t\treturn;\n\t}\n\tif (matchesKey(data, \"shift+tab\") || matchesKey(data, \"left\")) {\n\t\tctx.state.switchTab(-1);\n\t\tctx.updateAll();\n\t\treturn;\n\t}\n\tif (matchesKey(data, \"tab\") || matchesKey(data, \"right\")) {\n\t\tctx.state.switchTab(1);\n\t\tctx.updateAll();\n\t\treturn;\n\t}\n\tctx.commentInput.handleInput(data);\n\tctx.state.comment = ctx.commentInput.getValue();\n\tctx.emitProgress();\n}\n\nfunction handleOptionsKey(ctx: AskUserKeyHandlerContext, data: string, kb: ReturnType<typeof getKeybindings>): void {\n\tconst state = ctx.state;\n\tif (matchesKey(data, \"ctrl+enter\")) {\n\t\tctx.attemptSubmit();\n\t\treturn;\n\t}\n\tif (kb.matches(data, \"tui.select.cancel\")) {\n\t\tif (!state.request.waitForAnswer || state.requestDismiss() === \"cancel\") ctx.finish(\"cancelled\");\n\t\telse ctx.updateAll();\n\t\treturn;\n\t}\n\tif (matchesKey(data, \"tab\") || matchesKey(data, \"right\")) {\n\t\tstate.switchTab(1);\n\t\tctx.updateAll();\n\t\treturn;\n\t}\n\tif (matchesKey(data, \"shift+tab\") || matchesKey(data, \"left\")) {\n\t\tstate.switchTab(-1);\n\t\tctx.updateAll();\n\t\treturn;\n\t}\n\tif (kb.matches(data, \"tui.select.up\") || data === \"k\") {\n\t\tstate.highlightIndex = Math.max(0, state.highlightIndex - 1);\n\t\tctx.updateAll();\n\t\treturn;\n\t}\n\tif (kb.matches(data, \"tui.select.down\") || data === \"j\") {\n\t\tstate.highlightIndex = Math.min(state.ownAnswerRowIndex, state.highlightIndex + 1);\n\t\tctx.updateAll();\n\t\treturn;\n\t}\n\tif (data.length === 1 && data >= \"1\" && data <= \"9\") {\n\t\tconst option = state.activeQuestion.options[Number(data) - 1];\n\t\tif (option) {\n\t\t\tstate.activateOption(state.activeQuestion.id, option.label);\n\t\t\tctx.emitProgress();\n\t\t\tif (!state.activeQuestion.multiSelect) {\n\t\t\t\tif (state.request.waitForAnswer && state.request.questions.length === 1) ctx.attemptSubmit();\n\t\t\t\telse state.advance();\n\t\t\t}\n\t\t\tctx.updateAll();\n\t\t}\n\t\treturn;\n\t}\n\tif (matchesKey(data, \"space\")) {\n\t\tactivateHighlighted(ctx, false);\n\t\treturn;\n\t}\n\tif (kb.matches(data, \"tui.select.confirm\") || data === \"\\n\") {\n\t\tactivateHighlighted(ctx, true);\n\t\treturn;\n\t}\n\tif (data === \"c\") {\n\t\tstate.focus = \"submit\";\n\t\tctx.updateAll();\n\t\treturn;\n\t}\n\tif (data.length === 1 && data >= \" \" && data !== \"c\") {\n\t\tctx.openOwnAnswer(data);\n\t\tctx.updateAll();\n\t}\n}\n\nfunction activateHighlighted(ctx: AskUserKeyHandlerContext, confirm: boolean): void {\n\tconst state = ctx.state;\n\tif (state.highlightIndex === state.ownAnswerRowIndex) {\n\t\tctx.openOwnAnswer();\n\t\treturn;\n\t}\n\tconst option = state.activeQuestion.options[state.highlightIndex];\n\tif (!option) return;\n\tif (!confirm || !state.activeQuestion.multiSelect) {\n\t\tstate.activateOption(state.activeQuestion.id, option.label);\n\t}\n\tctx.emitProgress();\n\tctx.updateAll();\n\tif (confirm) {\n\t\tif (!state.activeQuestion.multiSelect && state.request.waitForAnswer && state.request.questions.length === 1) {\n\t\t\tctx.attemptSubmit();\n\t\t} else {\n\t\t\tstate.advance();\n\t\t\tctx.updateAll();\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"ask-user-question-keys.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/ask-user-question-keys.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Key dispatch for the ask-user question overlay. Split from the component to\n * keep every sibling under 250 LOC; handlers operate on the shared state and\n * the component's Inputs via an explicit context.\n */\n\nimport { getKeybindings, type Input, matchesKey } from \"@earendil-works/pi-tui\";\nimport type { QuestionResponse } from \"../../../core/extensions/types.ts\";\nimport type { AskUserQuestionState } from \"./ask-user-question-state.ts\";\n\nexport interface AskUserKeyHandlerContext {\n\tstate: AskUserQuestionState;\n\townAnswerInput: Input;\n\tcommentInput: Input;\n\tfinish(status: QuestionResponse[\"status\"], autoResolvedAfterMs?: number): void;\n\tattemptSubmit(): void;\n\topenOwnAnswer(initialText?: string): void;\n\tcommitOwnAnswer(): void;\n\temitProgress(): void;\n\tupdateAll(): void;\n}\n\ntype Keybindings = ReturnType<typeof getKeybindings>;\n\nconst DEL = \"\\x7f\";\n\nfunction isPrintable(data: string): boolean {\n\treturn data.length === 1 && data >= \" \" && data !== DEL;\n}\n\nexport function handleAskUserKeyInput(ctx: AskUserKeyHandlerContext, data: string): void {\n\tconst kb = getKeybindings();\n\tif (matchesKey(data, \"ctrl+c\")) {\n\t\tctx.finish(\"cancelled\");\n\t\treturn;\n\t}\n\tif (ctx.state.focus === \"own-answer\") {\n\t\thandleOwnAnswerKey(ctx, data, kb);\n\t\treturn;\n\t}\n\tif (ctx.state.focus === \"submit\") {\n\t\thandleSubmitKey(ctx, data, kb);\n\t\treturn;\n\t}\n\thandleOptionsKey(ctx, data, kb);\n}\n\n/** Navigation out of the editor saves typed text but never wipes an existing answer with an empty editor. */\nfunction saveTypedOwnAnswer(ctx: AskUserKeyHandlerContext): void {\n\tif (ctx.ownAnswerInput.getValue().trim() !== \"\") ctx.commitOwnAnswer();\n\telse ctx.ownAnswerInput.setValue(\"\");\n}\n\nfunction handleOwnAnswerKey(ctx: AskUserKeyHandlerContext, data: string, kb: Keybindings): void {\n\tconst state = ctx.state;\n\tif (matchesKey(data, \"ctrl+enter\")) {\n\t\tctx.commitOwnAnswer();\n\t\tctx.attemptSubmit();\n\t\treturn;\n\t}\n\tif (kb.matches(data, \"tui.select.confirm\") || data === \"\\n\") {\n\t\tctx.commitOwnAnswer();\n\t\tstate.advance();\n\t\tctx.updateAll();\n\t\treturn;\n\t}\n\tif (kb.matches(data, \"tui.select.cancel\")) {\n\t\tctx.ownAnswerInput.setValue(\"\");\n\t\tstate.leaveOwnAnswer(state.ownAnswerRowIndex);\n\t\tctx.updateAll();\n\t\treturn;\n\t}\n\tif (kb.matches(data, \"tui.select.up\")) {\n\t\tsaveTypedOwnAnswer(ctx);\n\t\tstate.leaveOwnAnswer(state.ownAnswerRowIndex - 1);\n\t\tctx.updateAll();\n\t\treturn;\n\t}\n\tif (kb.matches(data, \"tui.select.down\")) {\n\t\tsaveTypedOwnAnswer(ctx);\n\t\tstate.leaveOwnAnswer(state.ownAnswerRowIndex);\n\t\tctx.updateAll();\n\t\treturn;\n\t}\n\tif (matchesKey(data, \"tab\") || matchesKey(data, \"shift+tab\")) {\n\t\tsaveTypedOwnAnswer(ctx);\n\t\tstate.switchTab(matchesKey(data, \"tab\") ? 1 : -1);\n\t\tctx.updateAll();\n\t\treturn;\n\t}\n\tif (matchesKey(data, \"backspace\") && ctx.ownAnswerInput.getValue() === \"\") {\n\t\tstate.leaveOwnAnswer(state.ownAnswerRowIndex);\n\t\tctx.updateAll();\n\t\treturn;\n\t}\n\tctx.ownAnswerInput.handleInput(data);\n\tctx.emitProgress();\n}\n\nfunction handleSubmitKey(ctx: AskUserKeyHandlerContext, data: string, kb: Keybindings): void {\n\tconst state = ctx.state;\n\tif (matchesKey(data, \"ctrl+enter\")) {\n\t\tctx.attemptSubmit();\n\t\treturn;\n\t}\n\tif (kb.matches(data, \"tui.input.submit\") || data === \"\\n\") {\n\t\tif (state.isCommentFocused) ctx.attemptSubmit();\n\t\telse {\n\t\t\tstate.jumpToQuestion(state.submitRowIndex);\n\t\t\tctx.updateAll();\n\t\t}\n\t\treturn;\n\t}\n\tif (kb.matches(data, \"tui.select.cancel\")) {\n\t\tif (state.request.waitForAnswer) state.returnToOptions();\n\t\telse ctx.finish(\"cancelled\");\n\t\tctx.updateAll();\n\t\treturn;\n\t}\n\tif (kb.matches(data, \"tui.select.up\") || kb.matches(data, \"tui.select.down\")) {\n\t\tstate.moveSubmitRow(kb.matches(data, \"tui.select.up\") ? -1 : 1);\n\t\tctx.updateAll();\n\t\treturn;\n\t}\n\tif (matchesKey(data, \"shift+tab\") || matchesKey(data, \"tab\")) {\n\t\tstate.switchTab(matchesKey(data, \"tab\") ? 1 : -1);\n\t\tctx.updateAll();\n\t\treturn;\n\t}\n\tconst commentHasText = ctx.commentInput.getValue() !== \"\";\n\tif (matchesKey(data, \"left\") || matchesKey(data, \"right\")) {\n\t\tif (!state.isCommentFocused || !commentHasText) {\n\t\t\tstate.switchTab(matchesKey(data, \"right\") ? 1 : -1);\n\t\t\tctx.updateAll();\n\t\t\treturn;\n\t\t}\n\t}\n\tif (matchesKey(data, \"backspace\") && state.isCommentFocused && !commentHasText) {\n\t\tstate.moveSubmitRow(-1);\n\t\tctx.updateAll();\n\t\treturn;\n\t}\n\tif (!state.isCommentFocused) {\n\t\tif (!isPrintable(data)) return;\n\t\tstate.focusComment();\n\t}\n\tctx.commentInput.handleInput(data);\n\tstate.comment = ctx.commentInput.getValue();\n\tctx.updateAll();\n\tctx.emitProgress();\n}\n\nfunction handleOptionsKey(ctx: AskUserKeyHandlerContext, data: string, kb: Keybindings): void {\n\tconst state = ctx.state;\n\tif (matchesKey(data, \"ctrl+enter\")) {\n\t\tctx.attemptSubmit();\n\t\treturn;\n\t}\n\tif (kb.matches(data, \"tui.select.cancel\")) {\n\t\tif (!state.request.waitForAnswer || state.requestDismiss() === \"cancel\") ctx.finish(\"cancelled\");\n\t\telse ctx.updateAll();\n\t\treturn;\n\t}\n\tif (matchesKey(data, \"tab\") || matchesKey(data, \"right\")) {\n\t\tstate.switchTab(1);\n\t\tctx.updateAll();\n\t\treturn;\n\t}\n\tif (matchesKey(data, \"shift+tab\") || matchesKey(data, \"left\")) {\n\t\tstate.switchTab(-1);\n\t\tctx.updateAll();\n\t\treturn;\n\t}\n\tif (kb.matches(data, \"tui.select.up\") || data === \"k\") {\n\t\tstate.highlightIndex = Math.max(0, state.highlightIndex - 1);\n\t\tctx.updateAll();\n\t\treturn;\n\t}\n\tif (kb.matches(data, \"tui.select.down\") || data === \"j\") {\n\t\tstate.highlightIndex = Math.min(state.ownAnswerRowIndex, state.highlightIndex + 1);\n\t\tctx.updateAll();\n\t\treturn;\n\t}\n\tif (matchesKey(data, \"backspace\")) {\n\t\tstate.clearAnswer(state.activeQuestion.id);\n\t\tctx.emitProgress();\n\t\tctx.updateAll();\n\t\treturn;\n\t}\n\tif (data.length === 1 && data >= \"1\" && data <= \"9\") {\n\t\tconst option = state.activeQuestion.options[Number(data) - 1];\n\t\tif (option) {\n\t\t\tstate.activateOption(state.activeQuestion.id, option.label);\n\t\t\tctx.emitProgress();\n\t\t\tif (!state.activeQuestion.multiSelect) {\n\t\t\t\tif (state.request.questions.length === 1) ctx.attemptSubmit();\n\t\t\t\telse state.advance();\n\t\t\t}\n\t\t\tctx.updateAll();\n\t\t}\n\t\treturn;\n\t}\n\tif (matchesKey(data, \"space\")) {\n\t\tactivateHighlighted(ctx, false);\n\t\treturn;\n\t}\n\tif (kb.matches(data, \"tui.select.confirm\") || data === \"\\n\") {\n\t\tactivateHighlighted(ctx, true);\n\t\treturn;\n\t}\n\tif (data === \"c\") {\n\t\tstate.enterSubmit();\n\t\tctx.updateAll();\n\t\treturn;\n\t}\n\tif (isPrintable(data)) {\n\t\tctx.openOwnAnswer(data);\n\t\tctx.updateAll();\n\t}\n}\n\nfunction activateHighlighted(ctx: AskUserKeyHandlerContext, confirm: boolean): void {\n\tconst state = ctx.state;\n\tif (state.highlightIndex === state.ownAnswerRowIndex) {\n\t\tctx.openOwnAnswer();\n\t\treturn;\n\t}\n\tconst option = state.activeQuestion.options[state.highlightIndex];\n\tif (!option) return;\n\tif (!confirm || !state.activeQuestion.multiSelect) {\n\t\tstate.activateOption(state.activeQuestion.id, option.label);\n\t}\n\tctx.emitProgress();\n\tctx.updateAll();\n\tif (confirm) {\n\t\tif (!state.activeQuestion.multiSelect && state.request.questions.length === 1) {\n\t\t\tctx.attemptSubmit();\n\t\t} else {\n\t\t\tstate.advance();\n\t\t\tctx.updateAll();\n\t\t}\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"ask-user-question-render.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/ask-user-question-render.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAEzE,OAAO,EAAE,KAAK,oBAAoB,EAAmC,MAAM,8BAA8B,CAAC;AAG1G,wBAAgB,WAAW,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAG1D;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,oBAAoB,GAAG,MAAM,CAahE;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,eAAe,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,GAAG,MAAM,CAEzF;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,oBAAoB,GAAG,MAAM,EAAE,CAkBxE;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,oBAAoB,GAAG,MAAM,EAAE,CAOzE;AAED,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAE/D;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,oBAAoB,GAAG,MAAM,CASpE;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,GAAG,MAAM,CAoCnE"}
1
+ {"version":3,"file":"ask-user-question-render.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/ask-user-question-render.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAEzE,OAAO,EAAE,KAAK,oBAAoB,EAAmC,MAAM,8BAA8B,CAAC;AAG1G,wBAAgB,WAAW,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAG1D;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,oBAAoB,GAAG,MAAM,CAahE;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,eAAe,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,GAAG,MAAM,CAEzF;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,oBAAoB,GAAG,MAAM,EAAE,CAkBxE;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,oBAAoB,GAAG,MAAM,EAAE,CASzE;AAED,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAE/D;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,oBAAoB,GAAG,MAAM,CASpE;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,GAAG,MAAM,CAmDnE"}
@@ -46,16 +46,18 @@ export function renderQuestionList(state) {
46
46
  return lines;
47
47
  }
48
48
  export function renderSubmitSummary(state) {
49
- return state.request.questions.map((question) => {
49
+ return state.request.questions.map((question, index) => {
50
+ const highlighted = state.focus === "submit" && state.submitRowIndex === index;
51
+ const prefix = highlighted ? theme.fg("accent", "→ ") : " ";
50
52
  const answer = state.answers()[question.id];
51
53
  if (!answer)
52
- return theme.fg("warning", `${question.header}: unanswered`);
54
+ return `${prefix}${theme.fg("warning", `${question.header}: unanswered`)}`;
53
55
  const value = answer.selected.length > 0 ? answer.selected.join(", ") : (answer.text ?? "");
54
- return `${question.header}: ${value}`;
56
+ return `${prefix}${question.header}: ${value}`;
55
57
  });
56
58
  }
57
59
  export function renderOwnAnswerLabel() {
58
- return theme.fg("muted", "Your answer (enter to save, esc to discard)");
60
+ return theme.fg("muted", "Your answer (enter to save, ↑↓ back to options, esc to discard)");
59
61
  }
60
62
  export function renderCommentLabel() {
61
63
  return theme.fg("muted", COMMENT_LABEL);
@@ -73,9 +75,20 @@ export function renderSubmitLine(state) {
73
75
  }
74
76
  export function renderHintsLine(state) {
75
77
  if (state.focus === "submit") {
78
+ if (!state.isCommentFocused) {
79
+ return (rawKeyHint("enter", "edit answer") +
80
+ " " +
81
+ rawKeyHint("↑↓", "move") +
82
+ " " +
83
+ rawKeyHint("tab", "next question") +
84
+ " " +
85
+ rawKeyHint("esc", "back"));
86
+ }
76
87
  return (rawKeyHint("enter", "submit") +
77
88
  " " +
78
- rawKeyHint("←/shift+tab", "back") +
89
+ rawKeyHint("↑", "review answers") +
90
+ " " +
91
+ rawKeyHint("shift+tab", "back") +
79
92
  " " +
80
93
  rawKeyHint("tab", "next question") +
81
94
  " " +
@@ -84,9 +97,11 @@ export function renderHintsLine(state) {
84
97
  if (state.focus === "own-answer") {
85
98
  return (rawKeyHint("enter", "save and next") +
86
99
  " " +
87
- rawKeyHint("esc", "discard") +
100
+ rawKeyHint("↑↓", "back to options") +
101
+ " " +
102
+ rawKeyHint("tab", "next question") +
88
103
  " " +
89
- rawKeyHint("shift+enter", "new line"));
104
+ rawKeyHint("esc", "discard"));
90
105
  }
91
106
  return (rawKeyHint("↑↓", "move") +
92
107
  " " +
@@ -1 +1 @@
1
- {"version":3,"file":"ask-user-question-render.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/ask-user-question-render.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Line builders for the ask-user question overlay. Kept separate from the\n * component so the layout rules stay under the 250-LOC sibling limit; the\n * component owns focus, key decoding and the inline Inputs.\n */\n\nimport type { QuestionRequest } from \"../../../core/extensions/types.ts\";\nimport { theme } from \"../theme/theme.ts\";\nimport { type AskUserQuestionState, COMMENT_LABEL, OWN_ANSWER_LABEL } from \"./ask-user-question-state.ts\";\nimport { rawKeyHint } from \"./keybinding-hints.ts\";\n\nexport function renderTitle(countdownLabel: string): string {\n\tconst suffix = countdownLabel === \"\" ? \"\" : theme.fg(\"muted\", ` · ${countdownLabel}`);\n\treturn theme.fg(\"accent\", theme.bold(\"Ask user\")) + suffix;\n}\n\nexport function renderTabBar(state: AskUserQuestionState): string {\n\tconst tabs = state.request.questions.map((question, index) => {\n\t\tconst answered = state.isAnswered(question.id) ? theme.fg(\"success\", \" ✓\") : \"\";\n\t\tconst label = `${question.header}${answered}`;\n\t\treturn index === state.activeTabIndex\n\t\t\t? theme.fg(\"accent\", theme.bold(`→ ${label}`))\n\t\t\t: theme.fg(\"muted\", ` ${label}`);\n\t});\n\tconst submit =\n\t\tstate.activeTabIndex === state.request.questions.length\n\t\t\t? theme.fg(\"accent\", theme.bold(\"→ Submit\"))\n\t\t\t: theme.fg(\"muted\", \" Submit\");\n\treturn [...tabs, submit].join(\" \");\n}\n\nexport function renderQuestionLine(question: QuestionRequest[\"questions\"][number]): string {\n\treturn theme.fg(\"text\", question.question);\n}\n\nexport function renderQuestionList(state: AskUserQuestionState): string[] {\n\tconst lines: string[] = [];\n\tconst active = state.activeQuestion;\n\tactive.options.forEach((option, index) => {\n\t\tconst highlighted = index === state.highlightIndex && state.focus === \"options\";\n\t\tconst marker = state.isSelected(active.id, option.label) ? theme.fg(\"success\", \" ✓\") : \"\";\n\t\tconst prefix = highlighted ? theme.fg(\"accent\", \"→ \") : \" \";\n\t\tlines.push(`${prefix}${index + 1}. ${theme.fg(\"text\", option.label)}${marker}`);\n\t\tif (option.description) {\n\t\t\tlines.push(theme.fg(\"muted\", ` ${option.description}`));\n\t\t}\n\t});\n\tconst ownText = state.textFor(active.id);\n\tconst ownSuffix = ownText !== undefined ? theme.fg(\"text\", `: ${ownText}`) : \"\";\n\tconst ownHighlighted = state.highlightIndex === state.ownAnswerRowIndex && state.focus === \"options\";\n\tconst ownPrefix = ownHighlighted ? theme.fg(\"accent\", \"→ \") : \" \";\n\tlines.push(`${ownPrefix}${theme.fg(\"muted\", OWN_ANSWER_LABEL)}${ownSuffix}`);\n\treturn lines;\n}\n\nexport function renderSubmitSummary(state: AskUserQuestionState): string[] {\n\treturn state.request.questions.map((question) => {\n\t\tconst answer = state.answers()[question.id];\n\t\tif (!answer) return theme.fg(\"warning\", `${question.header}: unanswered`);\n\t\tconst value = answer.selected.length > 0 ? answer.selected.join(\", \") : (answer.text ?? \"\");\n\t\treturn `${question.header}: ${value}`;\n\t});\n}\n\nexport function renderOwnAnswerLabel(): string {\n\treturn theme.fg(\"muted\", \"Your answer (enter to save, esc to discard)\");\n}\n\nexport function renderCommentLabel(): string {\n\treturn theme.fg(\"muted\", COMMENT_LABEL);\n}\n\nexport function renderNotice(notice: string | undefined): string {\n\treturn notice === undefined ? \"\" : theme.fg(\"warning\", `! ${notice}`);\n}\n\nexport function renderSubmitLine(state: AskUserQuestionState): string {\n\tconst answered = state.answeredCount();\n\tconst total = state.request.questions.length;\n\tif (state.focus === \"submit\") {\n\t\treturn theme.fg(\"accent\", theme.bold(`Submit (${answered}/${total} answered)`));\n\t}\n\treturn (\n\t\ttheme.fg(\"accent\", theme.bold(`Submit (${answered}/${total} answered)`)) + theme.fg(\"muted\", \" — Enter advances\")\n\t);\n}\n\nexport function renderHintsLine(state: AskUserQuestionState): string {\n\tif (state.focus === \"submit\") {\n\t\treturn (\n\t\t\trawKeyHint(\"enter\", \"submit\") +\n\t\t\t\" \" +\n\t\t\trawKeyHint(\"←/shift+tab\", \"back\") +\n\t\t\t\" \" +\n\t\t\trawKeyHint(\"tab\", \"next question\") +\n\t\t\t\" \" +\n\t\t\trawKeyHint(\"esc\", \"back\")\n\t\t);\n\t}\n\tif (state.focus === \"own-answer\") {\n\t\treturn (\n\t\t\trawKeyHint(\"enter\", \"save and next\") +\n\t\t\t\" \" +\n\t\t\trawKeyHint(\"esc\", \"discard\") +\n\t\t\t\" \" +\n\t\t\trawKeyHint(\"shift+enter\", \"new line\")\n\t\t);\n\t}\n\treturn (\n\t\trawKeyHint(\"↑↓\", \"move\") +\n\t\t\" \" +\n\t\trawKeyHint(\"1-9\", \"select\") +\n\t\t\" \" +\n\t\trawKeyHint(\"space\", state.activeQuestion.multiSelect ? \"toggle\" : \"select\") +\n\t\t\" \" +\n\t\trawKeyHint(\"enter\", \"next\") +\n\t\t\" \" +\n\t\trawKeyHint(\"tab\", \"next question\") +\n\t\t\" \" +\n\t\trawKeyHint(\"c\", \"comment\") +\n\t\t\" \" +\n\t\trawKeyHint(\"esc\", \"cancel\")\n\t);\n}\n"]}
1
+ {"version":3,"file":"ask-user-question-render.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/ask-user-question-render.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Line builders for the ask-user question overlay. Kept separate from the\n * component so the layout rules stay under the 250-LOC sibling limit; the\n * component owns focus, key decoding and the inline Inputs.\n */\n\nimport type { QuestionRequest } from \"../../../core/extensions/types.ts\";\nimport { theme } from \"../theme/theme.ts\";\nimport { type AskUserQuestionState, COMMENT_LABEL, OWN_ANSWER_LABEL } from \"./ask-user-question-state.ts\";\nimport { rawKeyHint } from \"./keybinding-hints.ts\";\n\nexport function renderTitle(countdownLabel: string): string {\n\tconst suffix = countdownLabel === \"\" ? \"\" : theme.fg(\"muted\", ` · ${countdownLabel}`);\n\treturn theme.fg(\"accent\", theme.bold(\"Ask user\")) + suffix;\n}\n\nexport function renderTabBar(state: AskUserQuestionState): string {\n\tconst tabs = state.request.questions.map((question, index) => {\n\t\tconst answered = state.isAnswered(question.id) ? theme.fg(\"success\", \" ✓\") : \"\";\n\t\tconst label = `${question.header}${answered}`;\n\t\treturn index === state.activeTabIndex\n\t\t\t? theme.fg(\"accent\", theme.bold(`→ ${label}`))\n\t\t\t: theme.fg(\"muted\", ` ${label}`);\n\t});\n\tconst submit =\n\t\tstate.activeTabIndex === state.request.questions.length\n\t\t\t? theme.fg(\"accent\", theme.bold(\"→ Submit\"))\n\t\t\t: theme.fg(\"muted\", \" Submit\");\n\treturn [...tabs, submit].join(\" \");\n}\n\nexport function renderQuestionLine(question: QuestionRequest[\"questions\"][number]): string {\n\treturn theme.fg(\"text\", question.question);\n}\n\nexport function renderQuestionList(state: AskUserQuestionState): string[] {\n\tconst lines: string[] = [];\n\tconst active = state.activeQuestion;\n\tactive.options.forEach((option, index) => {\n\t\tconst highlighted = index === state.highlightIndex && state.focus === \"options\";\n\t\tconst marker = state.isSelected(active.id, option.label) ? theme.fg(\"success\", \" ✓\") : \"\";\n\t\tconst prefix = highlighted ? theme.fg(\"accent\", \"→ \") : \" \";\n\t\tlines.push(`${prefix}${index + 1}. ${theme.fg(\"text\", option.label)}${marker}`);\n\t\tif (option.description) {\n\t\t\tlines.push(theme.fg(\"muted\", ` ${option.description}`));\n\t\t}\n\t});\n\tconst ownText = state.textFor(active.id);\n\tconst ownSuffix = ownText !== undefined ? theme.fg(\"text\", `: ${ownText}`) : \"\";\n\tconst ownHighlighted = state.highlightIndex === state.ownAnswerRowIndex && state.focus === \"options\";\n\tconst ownPrefix = ownHighlighted ? theme.fg(\"accent\", \"→ \") : \" \";\n\tlines.push(`${ownPrefix}${theme.fg(\"muted\", OWN_ANSWER_LABEL)}${ownSuffix}`);\n\treturn lines;\n}\n\nexport function renderSubmitSummary(state: AskUserQuestionState): string[] {\n\treturn state.request.questions.map((question, index) => {\n\t\tconst highlighted = state.focus === \"submit\" && state.submitRowIndex === index;\n\t\tconst prefix = highlighted ? theme.fg(\"accent\", \"→ \") : \" \";\n\t\tconst answer = state.answers()[question.id];\n\t\tif (!answer) return `${prefix}${theme.fg(\"warning\", `${question.header}: unanswered`)}`;\n\t\tconst value = answer.selected.length > 0 ? answer.selected.join(\", \") : (answer.text ?? \"\");\n\t\treturn `${prefix}${question.header}: ${value}`;\n\t});\n}\n\nexport function renderOwnAnswerLabel(): string {\n\treturn theme.fg(\"muted\", \"Your answer (enter to save, ↑↓ back to options, esc to discard)\");\n}\n\nexport function renderCommentLabel(): string {\n\treturn theme.fg(\"muted\", COMMENT_LABEL);\n}\n\nexport function renderNotice(notice: string | undefined): string {\n\treturn notice === undefined ? \"\" : theme.fg(\"warning\", `! ${notice}`);\n}\n\nexport function renderSubmitLine(state: AskUserQuestionState): string {\n\tconst answered = state.answeredCount();\n\tconst total = state.request.questions.length;\n\tif (state.focus === \"submit\") {\n\t\treturn theme.fg(\"accent\", theme.bold(`Submit (${answered}/${total} answered)`));\n\t}\n\treturn (\n\t\ttheme.fg(\"accent\", theme.bold(`Submit (${answered}/${total} answered)`)) + theme.fg(\"muted\", \" — Enter advances\")\n\t);\n}\n\nexport function renderHintsLine(state: AskUserQuestionState): string {\n\tif (state.focus === \"submit\") {\n\t\tif (!state.isCommentFocused) {\n\t\t\treturn (\n\t\t\t\trawKeyHint(\"enter\", \"edit answer\") +\n\t\t\t\t\" \" +\n\t\t\t\trawKeyHint(\"↑↓\", \"move\") +\n\t\t\t\t\" \" +\n\t\t\t\trawKeyHint(\"tab\", \"next question\") +\n\t\t\t\t\" \" +\n\t\t\t\trawKeyHint(\"esc\", \"back\")\n\t\t\t);\n\t\t}\n\t\treturn (\n\t\t\trawKeyHint(\"enter\", \"submit\") +\n\t\t\t\" \" +\n\t\t\trawKeyHint(\"↑\", \"review answers\") +\n\t\t\t\" \" +\n\t\t\trawKeyHint(\"shift+tab\", \"back\") +\n\t\t\t\" \" +\n\t\t\trawKeyHint(\"tab\", \"next question\") +\n\t\t\t\" \" +\n\t\t\trawKeyHint(\"esc\", \"back\")\n\t\t);\n\t}\n\tif (state.focus === \"own-answer\") {\n\t\treturn (\n\t\t\trawKeyHint(\"enter\", \"save and next\") +\n\t\t\t\" \" +\n\t\t\trawKeyHint(\"↑↓\", \"back to options\") +\n\t\t\t\" \" +\n\t\t\trawKeyHint(\"tab\", \"next question\") +\n\t\t\t\" \" +\n\t\t\trawKeyHint(\"esc\", \"discard\")\n\t\t);\n\t}\n\treturn (\n\t\trawKeyHint(\"↑↓\", \"move\") +\n\t\t\" \" +\n\t\trawKeyHint(\"1-9\", \"select\") +\n\t\t\" \" +\n\t\trawKeyHint(\"space\", state.activeQuestion.multiSelect ? \"toggle\" : \"select\") +\n\t\t\" \" +\n\t\trawKeyHint(\"enter\", \"next\") +\n\t\t\" \" +\n\t\trawKeyHint(\"tab\", \"next question\") +\n\t\t\" \" +\n\t\trawKeyHint(\"c\", \"comment\") +\n\t\t\" \" +\n\t\trawKeyHint(\"esc\", \"cancel\")\n\t);\n}\n"]}
@@ -25,6 +25,8 @@ export declare class AskUserQuestionState {
25
25
  activeIndex: number;
26
26
  highlightIndex: number;
27
27
  focus: QuestionFocus;
28
+ /** Highlighted row on the Submit tab: a review row per question, then the comment editor. */
29
+ submitRowIndex: number;
28
30
  notice: string | undefined;
29
31
  comment: string | undefined;
30
32
  private dismissPending;
@@ -36,10 +38,20 @@ export declare class AskUserQuestionState {
36
38
  get ownAnswerRowIndex(): number;
37
39
  get rowCount(): number;
38
40
  get activeTabIndex(): number;
41
+ get commentRowIndex(): number;
42
+ get isCommentFocused(): boolean;
39
43
  switchQuestion(delta: number): void;
40
44
  switchTab(delta: number): void;
41
45
  advance(): void;
46
+ jumpToQuestion(index: number): void;
47
+ enterSubmit(): void;
42
48
  returnToOptions(): void;
49
+ /** Close the own-answer editor and highlight `row` of the active question. */
50
+ leaveOwnAnswer(row: number): void;
51
+ /** Move the Submit-tab highlight by `delta`, clamped to the review rows and the comment editor. */
52
+ moveSubmitRow(delta: number): void;
53
+ focusComment(): void;
54
+ private clearTransient;
43
55
  requestDismiss(): "confirm" | "cancel";
44
56
  acceptPartialSubmit(): void;
45
57
  private hasDraft;
@@ -52,6 +64,9 @@ export declare class AskUserQuestionState {
52
64
  activateOption(questionId: string, label: string): void;
53
65
  /** Replace the question's answer with typed text; empty text clears it. */
54
66
  setOwnAnswer(questionId: string, text: string): void;
67
+ clearAnswer(questionId: string): void;
68
+ /** Seed selections, own texts and the comment from a previously captured draft. */
69
+ restoreDraft(draft: QuestionDraft): void;
55
70
  answers(): QuestionAnswers;
56
71
  unanswered(): string[];
57
72
  /** Submit outcome: comment wins, then answers; undefined means stay open. */
@@ -1 +1 @@
1
- {"version":3,"file":"ask-user-question-state.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/ask-user-question-state.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAE3F,MAAM,MAAM,eAAe,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC;AAC1D,MAAM,MAAM,aAAa,GAAG;IAAE,OAAO,CAAC,EAAE,eAAe,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAC5E,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,YAAY,GAAG,QAAQ,CAAC;AAEhE,eAAO,MAAM,aAAa,0DAA0D,CAAC;AACrF,eAAO,MAAM,gBAAgB,4BAA4B,CAAC;AAC1D,eAAO,MAAM,mBAAmB,wCAAwC,CAAC;AACzE,eAAO,MAAM,cAAc,2DAA2D,CAAC;AACvF,eAAO,MAAM,qBAAqB,0DAA0D,CAAC;AAE7F,2EAA2E;AAC3E,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAMhE;AAED,qBAAa,oBAAoB;IAChC,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;IAClC,WAAW,SAAK;IAChB,cAAc,SAAK;IACnB,KAAK,EAAE,aAAa,CAAa;IACjC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA+B;IACxD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA6B;IAEnD,YAAY,OAAO,EAAE,eAAe,EAEnC;IAED,IAAI,cAAc,IAAI,eAAe,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,CAEzD;IAED,mFAAmF;IACnF,IAAI,iBAAiB,IAAI,MAAM,CAE9B;IAED,IAAI,QAAQ,IAAI,MAAM,CAErB;IAED,IAAI,cAAc,IAAI,MAAM,CAE3B;IAED,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAElC;IAED,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAY7B;IAED,OAAO,IAAI,IAAI,CAYd;IAED,eAAe,IAAI,IAAI,CAKtB;IAED,cAAc,IAAI,SAAS,GAAG,QAAQ,CAQrC;IAED,mBAAmB,IAAI,IAAI,CAG1B;IAED,OAAO,CAAC,QAAQ;IAKhB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAExC;IAED,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAE9C;IAED,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAErD;IAED,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAGtC;IAED,aAAa,IAAI,MAAM,CAEtB;IAED,0EAA0E;IAC1E,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAatD;IAED,2EAA2E;IAC3E,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAMnD;IAED,OAAO,IAAI,eAAe,CASzB;IAED,UAAU,IAAI,MAAM,EAAE,CAErB;IAED,6EAA6E;IAC7E,aAAa,CAAC,YAAY,UAAQ,GAAG,UAAU,GAAG,mBAAmB,GAAG,SAAS,CAMhF;IAED,aAAa,CAAC,MAAM,EAAE,gBAAgB,CAAC,QAAQ,CAAC,EAAE,mBAAmB,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAShG;IAED,YAAY,IAAI,aAAa,CAM5B;CACD"}
1
+ {"version":3,"file":"ask-user-question-state.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/ask-user-question-state.ts"],"names":[],"mappings":"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"}