@code-yeongyu/senpi 2026.9.10 → 2026.9.11

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 (337) hide show
  1. package/CHANGELOG.md +83 -0
  2. package/dist/core/agent-session.d.ts +57 -0
  3. package/dist/core/agent-session.d.ts.map +1 -1
  4. package/dist/core/agent-session.js +130 -20
  5. package/dist/core/agent-session.js.map +1 -1
  6. package/dist/core/auth-storage.d.ts +2 -0
  7. package/dist/core/auth-storage.d.ts.map +1 -1
  8. package/dist/core/auth-storage.js +49 -17
  9. package/dist/core/auth-storage.js.map +1 -1
  10. package/dist/core/brand.d.ts +5 -0
  11. package/dist/core/brand.d.ts.map +1 -1
  12. package/dist/core/brand.js +13 -0
  13. package/dist/core/brand.js.map +1 -1
  14. package/dist/core/changelog-source.d.ts +8 -0
  15. package/dist/core/changelog-source.d.ts.map +1 -0
  16. package/dist/core/changelog-source.js +19 -0
  17. package/dist/core/changelog-source.js.map +1 -0
  18. package/dist/core/credential-accounts.d.ts +3 -0
  19. package/dist/core/credential-accounts.d.ts.map +1 -1
  20. package/dist/core/credential-accounts.js +20 -1
  21. package/dist/core/credential-accounts.js.map +1 -1
  22. package/dist/core/credential-pool/classify.d.ts.map +1 -1
  23. package/dist/core/credential-pool/classify.js +8 -0
  24. package/dist/core/credential-pool/classify.js.map +1 -1
  25. package/dist/core/extensions/builtin/account/index.d.ts.map +1 -1
  26. package/dist/core/extensions/builtin/account/index.js +7 -3
  27. package/dist/core/extensions/builtin/account/index.js.map +1 -1
  28. package/dist/core/extensions/builtin/account-display-name.d.ts +7 -0
  29. package/dist/core/extensions/builtin/account-display-name.d.ts.map +1 -0
  30. package/dist/core/extensions/builtin/account-display-name.js +40 -0
  31. package/dist/core/extensions/builtin/account-display-name.js.map +1 -0
  32. package/dist/core/extensions/builtin/ask-user/format.d.ts.map +1 -1
  33. package/dist/core/extensions/builtin/ask-user/format.js +7 -2
  34. package/dist/core/extensions/builtin/ask-user/format.js.map +1 -1
  35. package/dist/core/extensions/builtin/ask-user/pending.d.ts.map +1 -1
  36. package/dist/core/extensions/builtin/ask-user/pending.js +3 -0
  37. package/dist/core/extensions/builtin/ask-user/pending.js.map +1 -1
  38. package/dist/core/extensions/builtin/claude-sdk-oauth/account-command.d.ts.map +1 -1
  39. package/dist/core/extensions/builtin/claude-sdk-oauth/account-command.js +21 -9
  40. package/dist/core/extensions/builtin/claude-sdk-oauth/account-command.js.map +1 -1
  41. package/dist/core/extensions/builtin/claude-sdk-oauth/account-management.d.ts +1 -0
  42. package/dist/core/extensions/builtin/claude-sdk-oauth/account-management.d.ts.map +1 -1
  43. package/dist/core/extensions/builtin/claude-sdk-oauth/account-management.js +11 -6
  44. package/dist/core/extensions/builtin/claude-sdk-oauth/account-management.js.map +1 -1
  45. package/dist/core/extensions/builtin/claude-sdk-oauth/accounts.d.ts +9 -0
  46. package/dist/core/extensions/builtin/claude-sdk-oauth/accounts.d.ts.map +1 -1
  47. package/dist/core/extensions/builtin/claude-sdk-oauth/accounts.js +10 -1
  48. package/dist/core/extensions/builtin/claude-sdk-oauth/accounts.js.map +1 -1
  49. package/dist/core/extensions/builtin/claude-sdk-oauth/session-binding.js +3 -0
  50. package/dist/core/extensions/builtin/claude-sdk-oauth/session-binding.js.map +1 -1
  51. package/dist/core/extensions/builtin/claude-sdk-oauth/session-reattach.d.ts.map +1 -1
  52. package/dist/core/extensions/builtin/claude-sdk-oauth/session-reattach.js +19 -10
  53. package/dist/core/extensions/builtin/claude-sdk-oauth/session-reattach.js.map +1 -1
  54. package/dist/core/extensions/builtin/claude-sdk-oauth/settings.d.ts.map +1 -1
  55. package/dist/core/extensions/builtin/claude-sdk-oauth/settings.js +3 -9
  56. package/dist/core/extensions/builtin/claude-sdk-oauth/settings.js.map +1 -1
  57. package/dist/core/extensions/builtin/config-reload/routine-settings.d.ts.map +1 -1
  58. package/dist/core/extensions/builtin/config-reload/routine-settings.js +1 -0
  59. package/dist/core/extensions/builtin/config-reload/routine-settings.js.map +1 -1
  60. package/dist/core/extensions/builtin/cursor-cli-oauth/account-command.d.ts.map +1 -1
  61. package/dist/core/extensions/builtin/cursor-cli-oauth/account-command.js +5 -3
  62. package/dist/core/extensions/builtin/cursor-cli-oauth/account-command.js.map +1 -1
  63. package/dist/core/extensions/builtin/cursor-cli-oauth/accounts.d.ts +1 -0
  64. package/dist/core/extensions/builtin/cursor-cli-oauth/accounts.d.ts.map +1 -1
  65. package/dist/core/extensions/builtin/cursor-cli-oauth/accounts.js.map +1 -1
  66. package/dist/core/extensions/builtin/cursor-cli-oauth/settings.d.ts.map +1 -1
  67. package/dist/core/extensions/builtin/cursor-cli-oauth/settings.js +3 -9
  68. package/dist/core/extensions/builtin/cursor-cli-oauth/settings.js.map +1 -1
  69. package/dist/core/extensions/builtin/goal/agent-end-continuation.d.ts.map +1 -1
  70. package/dist/core/extensions/builtin/goal/agent-end-continuation.js +13 -1
  71. package/dist/core/extensions/builtin/goal/agent-end-continuation.js.map +1 -1
  72. package/dist/core/extensions/builtin/goal/prompt.d.ts.map +1 -1
  73. package/dist/core/extensions/builtin/goal/prompt.js +11 -8
  74. package/dist/core/extensions/builtin/goal/prompt.js.map +1 -1
  75. package/dist/core/extensions/builtin/goal/terminal-provider-error.d.ts +1 -0
  76. package/dist/core/extensions/builtin/goal/terminal-provider-error.d.ts.map +1 -1
  77. package/dist/core/extensions/builtin/goal/terminal-provider-error.js +28 -0
  78. package/dist/core/extensions/builtin/goal/terminal-provider-error.js.map +1 -1
  79. package/dist/core/extensions/builtin/goal/todo-gate.js +2 -2
  80. package/dist/core/extensions/builtin/goal/todo-gate.js.map +1 -1
  81. package/dist/core/extensions/builtin/goal/tool-registration.js +2 -2
  82. package/dist/core/extensions/builtin/goal/tool-registration.js.map +1 -1
  83. package/dist/core/extensions/builtin/gpt-account.d.ts.map +1 -1
  84. package/dist/core/extensions/builtin/gpt-account.js +19 -8
  85. package/dist/core/extensions/builtin/gpt-account.js.map +1 -1
  86. package/dist/core/extensions/builtin/prompt-preset/deepseek-v4-1-flash.d.ts +3 -0
  87. package/dist/core/extensions/builtin/prompt-preset/deepseek-v4-1-flash.d.ts.map +1 -0
  88. package/dist/core/extensions/builtin/prompt-preset/deepseek-v4-1-flash.js +19 -0
  89. package/dist/core/extensions/builtin/prompt-preset/deepseek-v4-1-flash.js.map +1 -0
  90. package/dist/core/extensions/builtin/prompt-preset/gpt-6-astra.d.ts +6 -6
  91. package/dist/core/extensions/builtin/prompt-preset/gpt-6-astra.d.ts.map +1 -1
  92. package/dist/core/extensions/builtin/prompt-preset/gpt-6-astra.js +26 -7
  93. package/dist/core/extensions/builtin/prompt-preset/gpt-6-astra.js.map +1 -1
  94. package/dist/core/extensions/builtin/prompt-preset/presets.d.ts.map +1 -1
  95. package/dist/core/extensions/builtin/prompt-preset/presets.js +29 -0
  96. package/dist/core/extensions/builtin/prompt-preset/presets.js.map +1 -1
  97. package/dist/core/extensions/builtin/prompt-preset/settings.d.ts +1 -1
  98. package/dist/core/extensions/builtin/prompt-preset/settings.d.ts.map +1 -1
  99. package/dist/core/extensions/builtin/prompt-preset/settings.js +1 -0
  100. package/dist/core/extensions/builtin/prompt-preset/settings.js.map +1 -1
  101. package/dist/core/high-reasoning-warning.d.ts.map +1 -1
  102. package/dist/core/high-reasoning-warning.js +5 -1
  103. package/dist/core/high-reasoning-warning.js.map +1 -1
  104. package/dist/core/manual-continue.d.ts +14 -0
  105. package/dist/core/manual-continue.d.ts.map +1 -1
  106. package/dist/core/manual-continue.js +13 -0
  107. package/dist/core/manual-continue.js.map +1 -1
  108. package/dist/core/model-runtime.d.ts.map +1 -1
  109. package/dist/core/model-runtime.js +2 -2
  110. package/dist/core/model-runtime.js.map +1 -1
  111. package/dist/core/remote-catalog-merge.d.ts +16 -0
  112. package/dist/core/remote-catalog-merge.d.ts.map +1 -0
  113. package/dist/core/remote-catalog-merge.js +75 -0
  114. package/dist/core/remote-catalog-merge.js.map +1 -0
  115. package/dist/core/remote-catalog-provider.d.ts +3 -0
  116. package/dist/core/remote-catalog-provider.d.ts.map +1 -1
  117. package/dist/core/remote-catalog-provider.js +12 -40
  118. package/dist/core/remote-catalog-provider.js.map +1 -1
  119. package/dist/core/session-entry-materializer.d.ts +12 -0
  120. package/dist/core/session-entry-materializer.d.ts.map +1 -0
  121. package/dist/core/session-entry-materializer.js +26 -0
  122. package/dist/core/session-entry-materializer.js.map +1 -0
  123. package/dist/core/session-manager.d.ts +36 -1
  124. package/dist/core/session-manager.d.ts.map +1 -1
  125. package/dist/core/session-manager.js +38 -8
  126. package/dist/core/session-manager.js.map +1 -1
  127. package/dist/core/settings-manager.d.ts +3 -0
  128. package/dist/core/settings-manager.d.ts.map +1 -1
  129. package/dist/core/settings-manager.js +10 -0
  130. package/dist/core/settings-manager.js.map +1 -1
  131. package/dist/modes/app-server/daemon/process.d.ts +6 -1
  132. package/dist/modes/app-server/daemon/process.d.ts.map +1 -1
  133. package/dist/modes/app-server/daemon/process.js +23 -4
  134. package/dist/modes/app-server/daemon/process.js.map +1 -1
  135. package/dist/modes/app-server/protocol/account.d.ts +2 -0
  136. package/dist/modes/app-server/protocol/account.d.ts.map +1 -1
  137. package/dist/modes/app-server/protocol/account.js.map +1 -1
  138. package/dist/modes/interactive/components/ask-user-question-keys.d.ts +1 -1
  139. package/dist/modes/interactive/components/ask-user-question-keys.d.ts.map +1 -1
  140. package/dist/modes/interactive/components/ask-user-question-keys.js +65 -17
  141. package/dist/modes/interactive/components/ask-user-question-keys.js.map +1 -1
  142. package/dist/modes/interactive/components/ask-user-question-render.d.ts +2 -1
  143. package/dist/modes/interactive/components/ask-user-question-render.d.ts.map +1 -1
  144. package/dist/modes/interactive/components/ask-user-question-render.js +39 -9
  145. package/dist/modes/interactive/components/ask-user-question-render.js.map +1 -1
  146. package/dist/modes/interactive/components/ask-user-question-state.d.ts +14 -4
  147. package/dist/modes/interactive/components/ask-user-question-state.d.ts.map +1 -1
  148. package/dist/modes/interactive/components/ask-user-question-state.js +63 -6
  149. package/dist/modes/interactive/components/ask-user-question-state.js.map +1 -1
  150. package/dist/modes/interactive/components/ask-user-question.d.ts +2 -0
  151. package/dist/modes/interactive/components/ask-user-question.d.ts.map +1 -1
  152. package/dist/modes/interactive/components/ask-user-question.js +27 -14
  153. package/dist/modes/interactive/components/ask-user-question.js.map +1 -1
  154. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  155. package/dist/modes/interactive/components/footer.js +51 -19
  156. package/dist/modes/interactive/components/footer.js.map +1 -1
  157. package/dist/modes/interactive/components/login-dialog.d.ts +11 -0
  158. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  159. package/dist/modes/interactive/components/login-dialog.js +29 -9
  160. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  161. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  162. package/dist/modes/interactive/components/tree-selector.js +7 -0
  163. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  164. package/dist/modes/interactive/help-content.d.ts.map +1 -1
  165. package/dist/modes/interactive/help-content.js +4 -0
  166. package/dist/modes/interactive/help-content.js.map +1 -1
  167. package/dist/modes/interactive/interactive-mode.d.ts +13 -4
  168. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  169. package/dist/modes/interactive/interactive-mode.js +44 -15
  170. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  171. package/dist/modes/interactive/tips/catalog/input-tips.js +1 -1
  172. package/dist/modes/interactive/tips/catalog/input-tips.js.map +1 -1
  173. package/dist/modes/rpc/connection-handler.d.ts.map +1 -1
  174. package/dist/modes/rpc/connection-handler.js +3 -1
  175. package/dist/modes/rpc/connection-handler.js.map +1 -1
  176. package/dist/modes/rpc/connection-question-bridge.js +1 -1
  177. package/dist/modes/rpc/connection-question-bridge.js.map +1 -1
  178. package/dist/modes/rpc/host-ensure.d.ts.map +1 -1
  179. package/dist/modes/rpc/host-ensure.js +33 -11
  180. package/dist/modes/rpc/host-ensure.js.map +1 -1
  181. package/dist/modes/rpc/host-lifecycle.d.ts +14 -0
  182. package/dist/modes/rpc/host-lifecycle.d.ts.map +1 -1
  183. package/dist/modes/rpc/host-lifecycle.js +31 -5
  184. package/dist/modes/rpc/host-lifecycle.js.map +1 -1
  185. package/dist/modes/rpc/rpc-input-validation.d.ts.map +1 -1
  186. package/dist/modes/rpc/rpc-input-validation.js +2 -0
  187. package/dist/modes/rpc/rpc-input-validation.js.map +1 -1
  188. package/dist/modes/rpc/rpc-types.d.ts +2 -0
  189. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  190. package/dist/modes/rpc/rpc-types.js.map +1 -1
  191. package/dist/utils/changelog.d.ts +3 -1
  192. package/dist/utils/changelog.d.ts.map +1 -1
  193. package/dist/utils/changelog.js +89 -23
  194. package/dist/utils/changelog.js.map +1 -1
  195. package/dist/utils/paths.d.ts +5 -0
  196. package/dist/utils/paths.d.ts.map +1 -1
  197. package/dist/utils/paths.js +14 -1
  198. package/dist/utils/paths.js.map +1 -1
  199. package/docs/app-server.md +6 -0
  200. package/docs/extensions.md +19 -3
  201. package/docs/rpc.md +10 -0
  202. package/docs/settings.md +2 -1
  203. package/docs/tui.md +1 -1
  204. package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +28 -0
  205. package/node_modules/@code-yeongyu/senpi-codemode/README.md +5 -4
  206. package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
  207. package/node_modules/@code-yeongyu/senpi-codemode/src/output/streaming-output-buffer.ts +58 -0
  208. package/node_modules/@code-yeongyu/senpi-codemode/src/output/streaming-output.ts +9 -64
  209. package/node_modules/@code-yeongyu/senpi-codemode/src/prompt/eval-prompt-template.ts +1 -1
  210. package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
  211. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/discovery.d.ts +17 -0
  212. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/discovery.d.ts.map +1 -0
  213. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/discovery.js +90 -0
  214. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/discovery.js.map +1 -0
  215. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/frames.d.ts +23 -0
  216. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/frames.d.ts.map +1 -0
  217. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/frames.js +71 -0
  218. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/frames.js.map +1 -0
  219. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/gen/cascade_pb.d.ts +873 -0
  220. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/gen/cascade_pb.d.ts.map +1 -0
  221. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/gen/cascade_pb.js +303 -0
  222. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/gen/cascade_pb.js.map +1 -0
  223. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/metadata.d.ts +12 -0
  224. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/metadata.d.ts.map +1 -0
  225. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/metadata.js +35 -0
  226. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/metadata.js.map +1 -0
  227. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/paths.d.ts +23 -0
  228. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/paths.d.ts.map +1 -0
  229. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/paths.js +23 -0
  230. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/paths.js.map +1 -0
  231. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/request.d.ts +24 -0
  232. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/request.d.ts.map +1 -0
  233. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/request.js +116 -0
  234. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/request.js.map +1 -0
  235. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/stream-state.d.ts +20 -0
  236. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/stream-state.d.ts.map +1 -0
  237. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/stream-state.js +153 -0
  238. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/stream-state.js.map +1 -0
  239. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/types.d.ts +12 -0
  240. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/types.d.ts.map +1 -0
  241. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/types.js +3 -0
  242. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/types.js.map +1 -0
  243. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/wire.d.ts +6 -0
  244. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/wire.d.ts.map +1 -0
  245. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/wire.js +6 -0
  246. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/wire.js.map +1 -0
  247. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent.d.ts +14 -0
  248. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent.d.ts.map +1 -0
  249. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent.js +162 -0
  250. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent.js.map +1 -0
  251. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent.lazy.d.ts +5 -0
  252. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent.lazy.d.ts.map +1 -0
  253. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent.lazy.js +23 -0
  254. package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent.lazy.js.map +1 -0
  255. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/devin-callback.d.ts +25 -0
  256. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/devin-callback.d.ts.map +1 -0
  257. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/devin-callback.js +124 -0
  258. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/devin-callback.js.map +1 -0
  259. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/devin-token.d.ts +18 -0
  260. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/devin-token.d.ts.map +1 -0
  261. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/devin-token.js +101 -0
  262. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/devin-token.js.map +1 -0
  263. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/devin.d.ts +14 -0
  264. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/devin.d.ts.map +1 -0
  265. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/devin.js +111 -0
  266. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/devin.js.map +1 -0
  267. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/kimi-coding.d.ts.map +1 -1
  268. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/kimi-coding.js +5 -1
  269. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/kimi-coding.js.map +1 -1
  270. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/kimi-identity.d.ts +24 -0
  271. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/kimi-identity.d.ts.map +1 -0
  272. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/kimi-identity.js +86 -0
  273. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/kimi-identity.js.map +1 -0
  274. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/load.d.ts +2 -0
  275. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/load.d.ts.map +1 -1
  276. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/load.js +5 -0
  277. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/load.js.map +1 -1
  278. package/node_modules/@earendil-works/pi-ai/dist/auth/pool/slots.d.ts +51 -4
  279. package/node_modules/@earendil-works/pi-ai/dist/auth/pool/slots.d.ts.map +1 -1
  280. package/node_modules/@earendil-works/pi-ai/dist/auth/pool/slots.js +196 -7
  281. package/node_modules/@earendil-works/pi-ai/dist/auth/pool/slots.js.map +1 -1
  282. package/node_modules/@earendil-works/pi-ai/dist/auth/resolve.d.ts +8 -0
  283. package/node_modules/@earendil-works/pi-ai/dist/auth/resolve.d.ts.map +1 -1
  284. package/node_modules/@earendil-works/pi-ai/dist/auth/resolve.js +10 -0
  285. package/node_modules/@earendil-works/pi-ai/dist/auth/resolve.js.map +1 -1
  286. package/node_modules/@earendil-works/pi-ai/dist/auth/types.d.ts +9 -1
  287. package/node_modules/@earendil-works/pi-ai/dist/auth/types.d.ts.map +1 -1
  288. package/node_modules/@earendil-works/pi-ai/dist/auth/types.js.map +1 -1
  289. package/node_modules/@earendil-works/pi-ai/dist/bun-oauth.d.ts.map +1 -1
  290. package/node_modules/@earendil-works/pi-ai/dist/bun-oauth.js +2 -0
  291. package/node_modules/@earendil-works/pi-ai/dist/bun-oauth.js.map +1 -1
  292. package/node_modules/@earendil-works/pi-ai/dist/compat.d.ts +1 -0
  293. package/node_modules/@earendil-works/pi-ai/dist/compat.d.ts.map +1 -1
  294. package/node_modules/@earendil-works/pi-ai/dist/compat.js +3 -0
  295. package/node_modules/@earendil-works/pi-ai/dist/compat.js.map +1 -1
  296. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.js +4 -4
  297. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.js.map +1 -1
  298. package/node_modules/@earendil-works/pi-ai/dist/models.d.ts +1 -1
  299. package/node_modules/@earendil-works/pi-ai/dist/models.d.ts.map +1 -1
  300. package/node_modules/@earendil-works/pi-ai/dist/models.js +14 -5
  301. package/node_modules/@earendil-works/pi-ai/dist/models.js.map +1 -1
  302. package/node_modules/@earendil-works/pi-ai/dist/providers/all.d.ts.map +1 -1
  303. package/node_modules/@earendil-works/pi-ai/dist/providers/all.js +2 -0
  304. package/node_modules/@earendil-works/pi-ai/dist/providers/all.js.map +1 -1
  305. package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
  306. package/node_modules/@earendil-works/pi-ai/dist/providers/data/amazon-bedrock.json +1 -1
  307. package/node_modules/@earendil-works/pi-ai/dist/providers/data/baseten.json +1 -1
  308. package/node_modules/@earendil-works/pi-ai/dist/providers/data/fireworks.json +1 -1
  309. package/node_modules/@earendil-works/pi-ai/dist/providers/data/huggingface.json +1 -1
  310. package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode-go.json +1 -1
  311. package/node_modules/@earendil-works/pi-ai/dist/providers/data/opengateway.json +1 -1
  312. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
  313. package/node_modules/@earendil-works/pi-ai/dist/providers/data/venice.json +1 -1
  314. package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
  315. package/node_modules/@earendil-works/pi-ai/dist/providers/devin.d.ts +12 -0
  316. package/node_modules/@earendil-works/pi-ai/dist/providers/devin.d.ts.map +1 -0
  317. package/node_modules/@earendil-works/pi-ai/dist/providers/devin.js +62 -0
  318. package/node_modules/@earendil-works/pi-ai/dist/providers/devin.js.map +1 -0
  319. package/node_modules/@earendil-works/pi-ai/dist/providers/devin.models.d.ts +10 -0
  320. package/node_modules/@earendil-works/pi-ai/dist/providers/devin.models.d.ts.map +1 -0
  321. package/node_modules/@earendil-works/pi-ai/dist/providers/devin.models.js +28 -0
  322. package/node_modules/@earendil-works/pi-ai/dist/providers/devin.models.js.map +1 -0
  323. package/node_modules/@earendil-works/pi-ai/dist/types.d.ts +3 -1
  324. package/node_modules/@earendil-works/pi-ai/dist/types.d.ts.map +1 -1
  325. package/node_modules/@earendil-works/pi-ai/dist/types.js.map +1 -1
  326. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.d.ts.map +1 -1
  327. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js +4 -0
  328. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js.map +1 -1
  329. package/node_modules/@earendil-works/pi-ai/package.json +2 -2
  330. package/node_modules/@earendil-works/pi-pty/package.json +1 -1
  331. package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
  332. package/node_modules/@earendil-works/pi-tui/dist/dollar-invocation-autocomplete.d.ts +1 -1
  333. package/node_modules/@earendil-works/pi-tui/dist/dollar-invocation-autocomplete.d.ts.map +1 -1
  334. package/node_modules/@earendil-works/pi-tui/dist/dollar-invocation-autocomplete.js +55 -16
  335. package/node_modules/@earendil-works/pi-tui/dist/dollar-invocation-autocomplete.js.map +1 -1
  336. package/node_modules/@earendil-works/pi-tui/package.json +1 -1
  337. package/package.json +7 -7
@@ -1,6 +1,11 @@
1
1
  export interface DaemonPidFile {
2
2
  readonly pid: number;
3
- readonly processStartTime: string;
3
+ /**
4
+ * Identity guard for the recorded pid. `null` means the host was registered while its
5
+ * identity probe was starved: the pid is known, ownership is not provable, and no caller
6
+ * may signal it on that record.
7
+ */
8
+ readonly processStartTime: string | null;
4
9
  }
5
10
  export declare function parseDaemonPidFile(text: string): DaemonPidFile | undefined;
6
11
  export type ProcessIdentityResult = {
@@ -1 +1 @@
1
- {"version":3,"file":"process.d.ts","sourceRoot":"","sources":["../../../../src/modes/app-server/daemon/process.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,aAAa;IAC7B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;CAClC;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAe1E;AAED,MAAM,MAAM,qBAAqB,GAC9B;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACvD;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,GAC3B;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAC;AAEvD,sFAAsF;AACtF,qBAAa,8BAA+B,SAAQ,KAAK;IACxD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,SAAkB,KAAK,EAAE,OAAO,CAAC;IAEjC,YAAY,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAQxD;CACD;AAED,MAAM,WAAW,kBAAkB;IAClC,sEAAsE;IACtE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,kDAAkD;IAClD,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CAC1C,OAAO,EAAE,aAAa,EACtB,aAAa,GAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAwB,EAClF,MAAM,GAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAuB,EAChD,KAAK,GAAE,kBAAuB,GAC5B,OAAO,CAAC,OAAO,CAAC,CAelB;AAED,wBAAsB,mBAAmB,CACxC,GAAG,EAAE,MAAM,EACX,QAAQ,GAAE,MAAM,CAAC,QAA2B,EAC5C,SAAS,CAAC,EAAE,MAAM,EAClB,MAAM,GAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAuB,GAC9C,OAAO,CAAC,qBAAqB,CAAC,CAwChC;AAED,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CASpG;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAO7F;AAED,wBAAsB,oBAAoB,CACzC,GAAG,EAAE,MAAM,EACX,QAAQ,GAAE,MAAM,CAAC,QAA2B,EAC5C,SAAS,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAK7B;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CASlD;AAED;;;;;;;;;GASG;AACH,wBAAsB,gBAAgB,CACrC,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,MAAM,EACjB,aAAa,GAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAwB,EAClF,MAAM,GAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAuB,GAC9C,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAgB7B"}
1
+ {"version":3,"file":"process.d.ts","sourceRoot":"","sources":["../../../../src/modes/app-server/daemon/process.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,aAAa;IAC7B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,QAAQ,CAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;CACzC;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAoB1E;AAED,MAAM,MAAM,qBAAqB,GAC9B;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACvD;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,GAC3B;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAC;AAEvD,sFAAsF;AACtF,qBAAa,8BAA+B,SAAQ,KAAK;IACxD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,SAAkB,KAAK,EAAE,OAAO,CAAC;IAEjC,YAAY,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAQxD;CACD;AAED,MAAM,WAAW,kBAAkB;IAClC,sEAAsE;IACtE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,kDAAkD;IAClD,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CAC1C,OAAO,EAAE,aAAa,EACtB,aAAa,GAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAwB,EAClF,MAAM,GAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAuB,EAChD,KAAK,GAAE,kBAAuB,GAC5B,OAAO,CAAC,OAAO,CAAC,CAwBlB;AAED,wBAAsB,mBAAmB,CACxC,GAAG,EAAE,MAAM,EACX,QAAQ,GAAE,MAAM,CAAC,QAA2B,EAC5C,SAAS,CAAC,EAAE,MAAM,EAClB,MAAM,GAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAuB,GAC9C,OAAO,CAAC,qBAAqB,CAAC,CAwChC;AAED,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CASpG;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAO7F;AAED,wBAAsB,oBAAoB,CACzC,GAAG,EAAE,MAAM,EACX,QAAQ,GAAE,MAAM,CAAC,QAA2B,EAC5C,SAAS,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAK7B;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CASlD;AAED;;;;;;;;;GASG;AACH,wBAAsB,gBAAgB,CACrC,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,MAAM,EACjB,aAAa,GAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAwB,EAClF,MAAM,GAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAuB,GAC9C,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAgB7B"}
@@ -9,12 +9,18 @@ export function parseDaemonPidFile(text) {
9
9
  return undefined;
10
10
  throw error;
11
11
  }
12
- if (!isRecord(parsed) || typeof parsed.pid !== "number" || typeof parsed.processStartTime !== "string") {
12
+ const unguarded = parsed !== null && isRecord(parsed) && parsed.processStartTime === null;
13
+ if (!isRecord(parsed) ||
14
+ typeof parsed.pid !== "number" ||
15
+ (!unguarded && typeof parsed.processStartTime !== "string")) {
13
16
  return undefined;
14
17
  }
15
- if (!Number.isInteger(parsed.pid) || parsed.pid <= 0 || parsed.processStartTime.trim() === "") {
18
+ if (!Number.isInteger(parsed.pid) || parsed.pid <= 0)
19
+ return undefined;
20
+ if (unguarded)
21
+ return { pid: parsed.pid, processStartTime: null };
22
+ if (typeof parsed.processStartTime !== "string" || parsed.processStartTime.trim() === "")
16
23
  return undefined;
17
- }
18
24
  return { pid: parsed.pid, processStartTime: parsed.processStartTime };
19
25
  }
20
26
  /** Thrown when a live process refuses to yield an identity after the retry budget. */
@@ -35,13 +41,26 @@ export class ProcessIdentityUnreadableError extends Error {
35
41
  * ProcessIdentityUnreadableError. It never leaks the raw probe error as a verdict.
36
42
  */
37
43
  export async function processMatchesPidFile(pidFile, readStartTime = readProcessStartTime, isLive = processIsLive, retry = {}) {
44
+ // A record without an identity guard answers only the liveness half of the question: a pid
45
+ // that is gone is gone, and a live one stays unknown so it is never claimed or signalled.
46
+ if (pidFile.processStartTime === null) {
47
+ if (!isLive(pidFile.pid))
48
+ return false;
49
+ throw new ProcessIdentityUnreadableError(pidFile.pid, 0, new Error("pidfile carries no process identity guard"));
50
+ }
38
51
  const attempts = Math.max(1, retry.attempts ?? 5);
39
52
  const delayMs = retry.delayMs ?? 200;
40
53
  let lastError;
41
54
  for (let attempt = 1; attempt <= attempts; attempt++) {
42
55
  try {
43
56
  const current = await readStartTime(pidFile.pid);
44
- return current === pidFile.processStartTime;
57
+ if (current !== undefined)
58
+ return current === pidFile.processStartTime;
59
+ if (!isLive(pidFile.pid))
60
+ return false;
61
+ lastError = new Error("process identity probe returned no identity for a live process");
62
+ if (attempt < attempts)
63
+ await new Promise((resolve) => setTimeout(resolve, delayMs));
45
64
  }
46
65
  catch (error) {
47
66
  if (!isLive(pidFile.pid))
@@ -1 +1 @@
1
- {"version":3,"file":"process.js","sourceRoot":"","sources":["../../../../src/modes/app-server/daemon/process.ts"],"names":[],"mappings":"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","sourcesContent":["import { execFile } from \"node:child_process\";\n\nexport interface DaemonPidFile {\n\treadonly pid: number;\n\treadonly processStartTime: string;\n}\n\nexport function parseDaemonPidFile(text: string): DaemonPidFile | undefined {\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(text);\n\t} catch (error: unknown) {\n\t\tif (error instanceof SyntaxError) return undefined;\n\t\tthrow error;\n\t}\n\tif (!isRecord(parsed) || typeof parsed.pid !== \"number\" || typeof parsed.processStartTime !== \"string\") {\n\t\treturn undefined;\n\t}\n\tif (!Number.isInteger(parsed.pid) || parsed.pid <= 0 || parsed.processStartTime.trim() === \"\") {\n\t\treturn undefined;\n\t}\n\treturn { pid: parsed.pid, processStartTime: parsed.processStartTime };\n}\n\nexport type ProcessIdentityResult =\n\t| { readonly kind: \"present\"; readonly identity: string }\n\t| { readonly kind: \"absent\" }\n\t| { readonly kind: \"error\"; readonly error: unknown };\n\n/** Thrown when a live process refuses to yield an identity after the retry budget. */\nexport class ProcessIdentityUnreadableError extends Error {\n\treadonly pid: number;\n\treadonly attempts: number;\n\toverride readonly cause: unknown;\n\n\tconstructor(pid: number, attempts: number, cause: unknown) {\n\t\tsuper(\n\t\t\t`process identity for live pid ${pid} stayed unreadable after ${attempts} probe attempt(s): ${cause instanceof Error ? cause.message : String(cause)}`,\n\t\t);\n\t\tthis.name = \"ProcessIdentityUnreadableError\";\n\t\tthis.pid = pid;\n\t\tthis.attempts = attempts;\n\t\tthis.cause = cause;\n\t}\n}\n\nexport interface IdentityProbeRetry {\n\t/** Probe attempts against a live pid before giving up (default 5). */\n\treadonly attempts?: number;\n\t/** Pause between attempts in ms (default 200). */\n\treadonly delayMs?: number;\n}\n\n/**\n * True when the pidfile still describes the running process. A probe FAILURE is not\n * an answer: on a pid that is no longer live it means \"gone\" (false); on a live pid it\n * is an observation gap — the platform query was starved or exited non-zero — so the\n * probe is retried within a bounded budget and only then surfaces as\n * ProcessIdentityUnreadableError. It never leaks the raw probe error as a verdict.\n */\nexport async function processMatchesPidFile(\n\tpidFile: DaemonPidFile,\n\treadStartTime: (pid: number) => Promise<string | undefined> = readProcessStartTime,\n\tisLive: (pid: number) => boolean = processIsLive,\n\tretry: IdentityProbeRetry = {},\n): Promise<boolean> {\n\tconst attempts = Math.max(1, retry.attempts ?? 5);\n\tconst delayMs = retry.delayMs ?? 200;\n\tlet lastError: unknown;\n\tfor (let attempt = 1; attempt <= attempts; attempt++) {\n\t\ttry {\n\t\t\tconst current = await readStartTime(pidFile.pid);\n\t\t\treturn current === pidFile.processStartTime;\n\t\t} catch (error: unknown) {\n\t\t\tif (!isLive(pidFile.pid)) return false;\n\t\t\tlastError = error;\n\t\t\tif (attempt < attempts) await new Promise<void>((resolve) => setTimeout(resolve, delayMs));\n\t\t}\n\t}\n\tthrow new ProcessIdentityUnreadableError(pidFile.pid, attempts, lastError);\n}\n\nexport async function readProcessIdentity(\n\tpid: number,\n\tplatform: NodeJS.Platform = process.platform,\n\ttimeoutMs?: number,\n\tisLive: (pid: number) => boolean = processIsLive,\n): Promise<ProcessIdentityResult> {\n\tconst command =\n\t\tplatform === \"win32\"\n\t\t\t? {\n\t\t\t\t\texecutable: \"powershell.exe\",\n\t\t\t\t\targs: [\n\t\t\t\t\t\t\"-NoProfile\",\n\t\t\t\t\t\t\"-NonInteractive\",\n\t\t\t\t\t\t\"-Command\",\n\t\t\t\t\t\t`$process = Get-CimInstance Win32_Process -Filter \"ProcessId=${String(pid)}\" -ErrorAction Stop; if ($null -eq $process) { Write-Output '__SENPI_ABSENT__'; exit 0 }; $process.CreationDate.ToFileTimeUtc().ToString(\"D\", [Globalization.CultureInfo]::InvariantCulture)`,\n\t\t\t\t\t],\n\t\t\t\t}\n\t\t\t: { executable: \"ps\", args: [\"-o\", \"lstart=\", \"-p\", String(pid)] };\n\treturn new Promise((resolve) => {\n\t\tconst effectiveTimeoutMs = timeoutMs ?? (platform === \"win32\" ? 1_000 : undefined);\n\t\texecFile(\n\t\t\tcommand.executable,\n\t\t\tcommand.args,\n\t\t\t{ windowsHide: true, ...(effectiveTimeoutMs === undefined ? {} : { timeout: effectiveTimeoutMs }) },\n\t\t\t(error, stdout) => {\n\t\t\t\tif (error) {\n\t\t\t\t\tconst code = \"code\" in error ? error.code : undefined;\n\t\t\t\t\t// ps exits 1 for an unknown pid; on every platform a query that fails against a\n\t\t\t\t\t// pid that is no longer live has answered the question. Only a failure against a\n\t\t\t\t\t// LIVE pid is an observation error the caller must treat as unknown.\n\t\t\t\t\tif ((platform !== \"win32\" && code === 1) || !isLive(pid)) {\n\t\t\t\t\t\tresolve({ kind: \"absent\" });\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tresolve({ kind: \"error\", error });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst output = stdout.trim();\n\t\t\t\tif (output === \"__SENPI_ABSENT__\") return resolve({ kind: \"absent\" });\n\t\t\t\tif (!output || (platform === \"win32\" && !/^\\d+$/.test(output)))\n\t\t\t\t\treturn resolve({ kind: \"error\", error: new Error(\"invalid process identity output\") });\n\t\t\t\tresolve({ kind: \"present\", identity: output });\n\t\t\t},\n\t\t).once(\"error\", (error) => resolve({ kind: \"error\", error }));\n\t});\n}\n\nexport async function stopValidatedPid(pidFile: DaemonPidFile, signal: NodeJS.Signals): Promise<void> {\n\tif (!(await processMatchesPidFile(pidFile))) return;\n\ttry {\n\t\tprocess.kill(pidFile.pid, signal);\n\t} catch (error: unknown) {\n\t\tif (!isNodeErrorCode(error, \"ESRCH\")) throw error;\n\t}\n\tif (signal === \"SIGTERM\") await waitForGone(pidFile, 10_000);\n\tif (signal === \"SIGKILL\") await waitForGone(pidFile, 2_000);\n}\n\nexport async function waitForGone(pidFile: DaemonPidFile, timeoutMs: number): Promise<boolean> {\n\tconst deadline = Date.now() + timeoutMs;\n\twhile (Date.now() <= deadline) {\n\t\tif (!(await processMatchesPidFile(pidFile))) return true;\n\t\tawait delay(100);\n\t}\n\treturn !(await processMatchesPidFile(pidFile));\n}\n\nexport async function readProcessStartTime(\n\tpid: number,\n\tplatform: NodeJS.Platform = process.platform,\n\ttimeoutMs?: number,\n): Promise<string | undefined> {\n\treturn readProcessIdentity(pid, platform, timeoutMs).then((result) => {\n\t\tif (result.kind === \"error\") throw result.error;\n\t\treturn result.kind === \"present\" ? result.identity : undefined;\n\t});\n}\n\nexport function processIsLive(pid: number): boolean {\n\ttry {\n\t\tprocess.kill(pid, 0);\n\t\treturn true;\n\t} catch (error: unknown) {\n\t\tif (isNodeErrorCode(error, \"ESRCH\")) return false;\n\t\tif (isNodeErrorCode(error, \"EPERM\")) return true;\n\t\tthrow error;\n\t}\n}\n\n/**\n * Wait for a spawned pid's process identity.\n *\n * Returns `undefined` (UNKNOWN) when the budget is exhausted but the process is still alive:\n * budget exhaustion is an OBSERVABILITY failure, not evidence the child failed to start. On a\n * loaded Windows runner every `Get-CimInstance` probe can outlive `readProcessIdentity`'s 1s win32\n * default, so all ~9 attempts inside a 10s budget time out and throw while the process runs\n * normally (PR #1351/#1352 CI, runs 33839093178 / 33842155236). Only a pid that is really gone is\n * a startup failure, so callers can distinguish \"no identity yet\" from \"child died\".\n */\nexport async function waitForStartTime(\n\tpid: number,\n\ttimeoutMs: number,\n\treadStartTime: (pid: number) => Promise<string | undefined> = readProcessStartTime,\n\tisLive: (pid: number) => boolean = processIsLive,\n): Promise<string | undefined> {\n\tconst deadline = Date.now() + timeoutMs;\n\twhile (Date.now() <= deadline) {\n\t\tlet startTime: string | undefined;\n\t\ttry {\n\t\t\tstartTime = await readStartTime(pid);\n\t\t} catch {\n\t\t\t// Process identity queries can fail transiently while a Windows process is\n\t\t\t// entering the CIM table. Keep the bounded startup wait alive so callers do\n\t\t\t// not mistake an observability failure for a child startup failure.\n\t\t}\n\t\tif (startTime) return startTime;\n\t\tawait delay(20);\n\t}\n\tif (isLive(pid)) return undefined;\n\tthrow new Error(`spawned daemon pid ${pid} had no process start time`);\n}\n\nfunction delay(ms: number): Promise<void> {\n\treturn new Promise((resolveDelay) => setTimeout(resolveDelay, ms));\n}\n\nfunction isRecord(value: unknown): value is Readonly<Record<string, unknown>> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isNodeErrorCode(error: unknown, code: string): boolean {\n\treturn error instanceof Error && \"code\" in error && error.code === code;\n}\n"]}
1
+ {"version":3,"file":"process.js","sourceRoot":"","sources":["../../../../src/modes/app-server/daemon/process.ts"],"names":[],"mappings":"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","sourcesContent":["import { execFile } from \"node:child_process\";\n\nexport interface DaemonPidFile {\n\treadonly pid: number;\n\t/**\n\t * Identity guard for the recorded pid. `null` means the host was registered while its\n\t * identity probe was starved: the pid is known, ownership is not provable, and no caller\n\t * may signal it on that record.\n\t */\n\treadonly processStartTime: string | null;\n}\n\nexport function parseDaemonPidFile(text: string): DaemonPidFile | undefined {\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(text);\n\t} catch (error: unknown) {\n\t\tif (error instanceof SyntaxError) return undefined;\n\t\tthrow error;\n\t}\n\tconst unguarded = parsed !== null && isRecord(parsed) && parsed.processStartTime === null;\n\tif (\n\t\t!isRecord(parsed) ||\n\t\ttypeof parsed.pid !== \"number\" ||\n\t\t(!unguarded && typeof parsed.processStartTime !== \"string\")\n\t) {\n\t\treturn undefined;\n\t}\n\tif (!Number.isInteger(parsed.pid) || parsed.pid <= 0) return undefined;\n\tif (unguarded) return { pid: parsed.pid, processStartTime: null };\n\tif (typeof parsed.processStartTime !== \"string\" || parsed.processStartTime.trim() === \"\") return undefined;\n\treturn { pid: parsed.pid, processStartTime: parsed.processStartTime };\n}\n\nexport type ProcessIdentityResult =\n\t| { readonly kind: \"present\"; readonly identity: string }\n\t| { readonly kind: \"absent\" }\n\t| { readonly kind: \"error\"; readonly error: unknown };\n\n/** Thrown when a live process refuses to yield an identity after the retry budget. */\nexport class ProcessIdentityUnreadableError extends Error {\n\treadonly pid: number;\n\treadonly attempts: number;\n\toverride readonly cause: unknown;\n\n\tconstructor(pid: number, attempts: number, cause: unknown) {\n\t\tsuper(\n\t\t\t`process identity for live pid ${pid} stayed unreadable after ${attempts} probe attempt(s): ${cause instanceof Error ? cause.message : String(cause)}`,\n\t\t);\n\t\tthis.name = \"ProcessIdentityUnreadableError\";\n\t\tthis.pid = pid;\n\t\tthis.attempts = attempts;\n\t\tthis.cause = cause;\n\t}\n}\n\nexport interface IdentityProbeRetry {\n\t/** Probe attempts against a live pid before giving up (default 5). */\n\treadonly attempts?: number;\n\t/** Pause between attempts in ms (default 200). */\n\treadonly delayMs?: number;\n}\n\n/**\n * True when the pidfile still describes the running process. A probe FAILURE is not\n * an answer: on a pid that is no longer live it means \"gone\" (false); on a live pid it\n * is an observation gap — the platform query was starved or exited non-zero — so the\n * probe is retried within a bounded budget and only then surfaces as\n * ProcessIdentityUnreadableError. It never leaks the raw probe error as a verdict.\n */\nexport async function processMatchesPidFile(\n\tpidFile: DaemonPidFile,\n\treadStartTime: (pid: number) => Promise<string | undefined> = readProcessStartTime,\n\tisLive: (pid: number) => boolean = processIsLive,\n\tretry: IdentityProbeRetry = {},\n): Promise<boolean> {\n\t// A record without an identity guard answers only the liveness half of the question: a pid\n\t// that is gone is gone, and a live one stays unknown so it is never claimed or signalled.\n\tif (pidFile.processStartTime === null) {\n\t\tif (!isLive(pidFile.pid)) return false;\n\t\tthrow new ProcessIdentityUnreadableError(pidFile.pid, 0, new Error(\"pidfile carries no process identity guard\"));\n\t}\n\tconst attempts = Math.max(1, retry.attempts ?? 5);\n\tconst delayMs = retry.delayMs ?? 200;\n\tlet lastError: unknown;\n\tfor (let attempt = 1; attempt <= attempts; attempt++) {\n\t\ttry {\n\t\t\tconst current = await readStartTime(pidFile.pid);\n\t\t\tif (current !== undefined) return current === pidFile.processStartTime;\n\t\t\tif (!isLive(pidFile.pid)) return false;\n\t\t\tlastError = new Error(\"process identity probe returned no identity for a live process\");\n\t\t\tif (attempt < attempts) await new Promise<void>((resolve) => setTimeout(resolve, delayMs));\n\t\t} catch (error: unknown) {\n\t\t\tif (!isLive(pidFile.pid)) return false;\n\t\t\tlastError = error;\n\t\t\tif (attempt < attempts) await new Promise<void>((resolve) => setTimeout(resolve, delayMs));\n\t\t}\n\t}\n\tthrow new ProcessIdentityUnreadableError(pidFile.pid, attempts, lastError);\n}\n\nexport async function readProcessIdentity(\n\tpid: number,\n\tplatform: NodeJS.Platform = process.platform,\n\ttimeoutMs?: number,\n\tisLive: (pid: number) => boolean = processIsLive,\n): Promise<ProcessIdentityResult> {\n\tconst command =\n\t\tplatform === \"win32\"\n\t\t\t? {\n\t\t\t\t\texecutable: \"powershell.exe\",\n\t\t\t\t\targs: [\n\t\t\t\t\t\t\"-NoProfile\",\n\t\t\t\t\t\t\"-NonInteractive\",\n\t\t\t\t\t\t\"-Command\",\n\t\t\t\t\t\t`$process = Get-CimInstance Win32_Process -Filter \"ProcessId=${String(pid)}\" -ErrorAction Stop; if ($null -eq $process) { Write-Output '__SENPI_ABSENT__'; exit 0 }; $process.CreationDate.ToFileTimeUtc().ToString(\"D\", [Globalization.CultureInfo]::InvariantCulture)`,\n\t\t\t\t\t],\n\t\t\t\t}\n\t\t\t: { executable: \"ps\", args: [\"-o\", \"lstart=\", \"-p\", String(pid)] };\n\treturn new Promise((resolve) => {\n\t\tconst effectiveTimeoutMs = timeoutMs ?? (platform === \"win32\" ? 1_000 : undefined);\n\t\texecFile(\n\t\t\tcommand.executable,\n\t\t\tcommand.args,\n\t\t\t{ windowsHide: true, ...(effectiveTimeoutMs === undefined ? {} : { timeout: effectiveTimeoutMs }) },\n\t\t\t(error, stdout) => {\n\t\t\t\tif (error) {\n\t\t\t\t\tconst code = \"code\" in error ? error.code : undefined;\n\t\t\t\t\t// ps exits 1 for an unknown pid; on every platform a query that fails against a\n\t\t\t\t\t// pid that is no longer live has answered the question. Only a failure against a\n\t\t\t\t\t// LIVE pid is an observation error the caller must treat as unknown.\n\t\t\t\t\tif ((platform !== \"win32\" && code === 1) || !isLive(pid)) {\n\t\t\t\t\t\tresolve({ kind: \"absent\" });\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tresolve({ kind: \"error\", error });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst output = stdout.trim();\n\t\t\t\tif (output === \"__SENPI_ABSENT__\") return resolve({ kind: \"absent\" });\n\t\t\t\tif (!output || (platform === \"win32\" && !/^\\d+$/.test(output)))\n\t\t\t\t\treturn resolve({ kind: \"error\", error: new Error(\"invalid process identity output\") });\n\t\t\t\tresolve({ kind: \"present\", identity: output });\n\t\t\t},\n\t\t).once(\"error\", (error) => resolve({ kind: \"error\", error }));\n\t});\n}\n\nexport async function stopValidatedPid(pidFile: DaemonPidFile, signal: NodeJS.Signals): Promise<void> {\n\tif (!(await processMatchesPidFile(pidFile))) return;\n\ttry {\n\t\tprocess.kill(pidFile.pid, signal);\n\t} catch (error: unknown) {\n\t\tif (!isNodeErrorCode(error, \"ESRCH\")) throw error;\n\t}\n\tif (signal === \"SIGTERM\") await waitForGone(pidFile, 10_000);\n\tif (signal === \"SIGKILL\") await waitForGone(pidFile, 2_000);\n}\n\nexport async function waitForGone(pidFile: DaemonPidFile, timeoutMs: number): Promise<boolean> {\n\tconst deadline = Date.now() + timeoutMs;\n\twhile (Date.now() <= deadline) {\n\t\tif (!(await processMatchesPidFile(pidFile))) return true;\n\t\tawait delay(100);\n\t}\n\treturn !(await processMatchesPidFile(pidFile));\n}\n\nexport async function readProcessStartTime(\n\tpid: number,\n\tplatform: NodeJS.Platform = process.platform,\n\ttimeoutMs?: number,\n): Promise<string | undefined> {\n\treturn readProcessIdentity(pid, platform, timeoutMs).then((result) => {\n\t\tif (result.kind === \"error\") throw result.error;\n\t\treturn result.kind === \"present\" ? result.identity : undefined;\n\t});\n}\n\nexport function processIsLive(pid: number): boolean {\n\ttry {\n\t\tprocess.kill(pid, 0);\n\t\treturn true;\n\t} catch (error: unknown) {\n\t\tif (isNodeErrorCode(error, \"ESRCH\")) return false;\n\t\tif (isNodeErrorCode(error, \"EPERM\")) return true;\n\t\tthrow error;\n\t}\n}\n\n/**\n * Wait for a spawned pid's process identity.\n *\n * Returns `undefined` (UNKNOWN) when the budget is exhausted but the process is still alive:\n * budget exhaustion is an OBSERVABILITY failure, not evidence the child failed to start. On a\n * loaded Windows runner every `Get-CimInstance` probe can outlive `readProcessIdentity`'s 1s win32\n * default, so all ~9 attempts inside a 10s budget time out and throw while the process runs\n * normally (PR #1351/#1352 CI, runs 33839093178 / 33842155236). Only a pid that is really gone is\n * a startup failure, so callers can distinguish \"no identity yet\" from \"child died\".\n */\nexport async function waitForStartTime(\n\tpid: number,\n\ttimeoutMs: number,\n\treadStartTime: (pid: number) => Promise<string | undefined> = readProcessStartTime,\n\tisLive: (pid: number) => boolean = processIsLive,\n): Promise<string | undefined> {\n\tconst deadline = Date.now() + timeoutMs;\n\twhile (Date.now() <= deadline) {\n\t\tlet startTime: string | undefined;\n\t\ttry {\n\t\t\tstartTime = await readStartTime(pid);\n\t\t} catch {\n\t\t\t// Process identity queries can fail transiently while a Windows process is\n\t\t\t// entering the CIM table. Keep the bounded startup wait alive so callers do\n\t\t\t// not mistake an observability failure for a child startup failure.\n\t\t}\n\t\tif (startTime) return startTime;\n\t\tawait delay(20);\n\t}\n\tif (isLive(pid)) return undefined;\n\tthrow new Error(`spawned daemon pid ${pid} had no process start time`);\n}\n\nfunction delay(ms: number): Promise<void> {\n\treturn new Promise((resolveDelay) => setTimeout(resolveDelay, ms));\n}\n\nfunction isRecord(value: unknown): value is Readonly<Record<string, unknown>> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isNodeErrorCode(error: unknown, code: string): boolean {\n\treturn error instanceof Error && \"code\" in error && error.code === code;\n}\n"]}
@@ -19,7 +19,9 @@ export type AccountReadResponse = {
19
19
  /** Additive Senpi provider-account surface; desktop consumers update separately. */
20
20
  export type ProviderAccountSource = "login" | "import" | "env";
21
21
  export type ProviderAccount = {
22
+ /** Immutable selector ID; render displayName (name) when metadata is present. */
22
23
  readonly name: string;
24
+ readonly displayName?: string;
23
25
  readonly source: ProviderAccountSource;
24
26
  readonly blocked: boolean;
25
27
  readonly pinned: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"account.d.ts","sourceRoot":"","sources":["../../../../src/modes/app-server/protocol/account.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GACjB,MAAM,GACN,IAAI,GACJ,MAAM,GACN,KAAK,GACL,SAAS,GACT,MAAM,GACN,iCAAiC,GACjC,UAAU,GACV,4BAA4B,GAC5B,YAAY,GACZ,KAAK,GACL,SAAS,CAAC;AAEb,MAAM,MAAM,OAAO,GAChB;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,GAC3B;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;CAAE,GACxF;IAAE,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAAC,QAAQ,CAAC,2BAA2B,EAAE,OAAO,CAAA;CAAE,CAAC;AAErF,MAAM,MAAM,iBAAiB,GAAG;IAAE,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AACpE,MAAM,MAAM,mBAAmB,GAAG;IACjC,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACjC,QAAQ,CAAC,kBAAkB,EAAE,OAAO,CAAC;CACrC,CAAC;AAEF,oFAAoF;AACpF,MAAM,MAAM,qBAAqB,GAAG,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;AAC/D,MAAM,MAAM,eAAe,GAAG;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,qBAAqB,CAAC;IACvC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CACzB,CAAC;AACF,MAAM,MAAM,0BAA0B,GAAG;IAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AACvE,MAAM,MAAM,4BAA4B,GAAG;IAC1C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,SAAS,eAAe,EAAE,CAAC;CAC9C,CAAC;AACF,MAAM,MAAM,yBAAyB,GAAG;IAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC;AACpG,MAAM,MAAM,4BAA4B,GAAG;IAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAChG,MAAM,MAAM,mCAAmC,GAAG;IAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAChF,MAAM,MAAM,mCAAmC,GAAG;IACjD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3C,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC,CAAC;AACF,MAAM,MAAM,eAAe,GAAG;IAC7B,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC,CAAC;AACF,MAAM,MAAM,yBAAyB,GAAG;IACvC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC1B,CAAC;AACF,MAAM,MAAM,oBAAoB,GAC7B,oBAAoB,GACpB,kCAAkC,GAClC,mCAAmC,GACnC,qCAAqC,GACrC,sCAAsC,CAAC;AAC1C,MAAM,MAAM,iBAAiB,GAAG;IAC/B,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI,CAAC;IACzC,QAAQ,CAAC,SAAS,EAAE,eAAe,GAAG,IAAI,CAAC;IAC3C,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI,CAAC;IACzC,QAAQ,CAAC,eAAe,EAAE,yBAAyB,GAAG,IAAI,CAAC;IAC3D,QAAQ,CAAC,mBAAmB,EAAE,OAAO,GAAG,IAAI,CAAC;IAC7C,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAC;IACnC,QAAQ,CAAC,oBAAoB,EAAE,oBAAoB,GAAG,IAAI,CAAC;CAC3D,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,iBAAiB,GAAG,SAAS,CAAC;AAC/D,MAAM,MAAM,0BAA0B,GAAG,WAAW,GAAG,WAAW,GAAG,UAAU,GAAG,SAAS,CAAC;AAC5F,MAAM,MAAM,oBAAoB,GAAG;IAClC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,SAAS,EAAE,kBAAkB,CAAC;IACvC,QAAQ,CAAC,MAAM,EAAE,0BAA0B,CAAC;IAC5C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CACpC,CAAC;AACF,MAAM,MAAM,4BAA4B,GAAG;IAC1C,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,OAAO,EAAE,SAAS,oBAAoB,EAAE,GAAG,IAAI,CAAC;CACzD,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG,SAAS,CAAC;AACpD,MAAM,MAAM,6BAA6B,GAAG;IAC3C,QAAQ,CAAC,UAAU,EAAE,iBAAiB,CAAC;IACvC,QAAQ,CAAC,mBAAmB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,iBAAiB,GAAG,SAAS,CAAC,CAAC,GAAG,IAAI,CAAC;IAC7F,QAAQ,CAAC,qBAAqB,EAAE,4BAA4B,GAAG,IAAI,CAAC;CACpE,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACtC,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,QAAQ,CAAC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IACxC,QAAQ,CAAC,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9C,QAAQ,CAAC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1C,QAAQ,CAAC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1C,CAAC;AACF,MAAM,MAAM,4BAA4B,GAAG;IAC1C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACxB,CAAC;AACF,MAAM,MAAM,sBAAsB,GAAG,SAAS,CAAC;AAC/C,MAAM,MAAM,wBAAwB,GAAG;IACtC,QAAQ,CAAC,OAAO,EAAE,wBAAwB,CAAC;IAC3C,QAAQ,CAAC,iBAAiB,EAAE,SAAS,4BAA4B,EAAE,GAAG,IAAI,CAAC;CAC3E,CAAC"}
1
+ {"version":3,"file":"account.d.ts","sourceRoot":"","sources":["../../../../src/modes/app-server/protocol/account.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"account.js","sourceRoot":"","sources":["../../../../src/modes/app-server/protocol/account.ts"],"names":[],"mappings":"","sourcesContent":["export type PlanType =\n\t| \"free\"\n\t| \"go\"\n\t| \"plus\"\n\t| \"pro\"\n\t| \"prolite\"\n\t| \"team\"\n\t| \"self_serve_business_usage_based\"\n\t| \"business\"\n\t| \"enterprise_cbp_usage_based\"\n\t| \"enterprise\"\n\t| \"edu\"\n\t| \"unknown\";\n\nexport type Account =\n\t| { readonly type: \"apiKey\" }\n\t| { readonly type: \"chatgpt\"; readonly email: string | null; readonly planType: PlanType }\n\t| { readonly type: \"amazonBedrock\"; readonly usesCodexManagedCredentials: boolean };\n\nexport type AccountReadParams = { readonly refreshToken?: boolean };\nexport type AccountReadResponse = {\n\treadonly account: Account | null;\n\treadonly requiresOpenaiAuth: boolean;\n};\n\n/** Additive Senpi provider-account surface; desktop consumers update separately. */\nexport type ProviderAccountSource = \"login\" | \"import\" | \"env\";\nexport type ProviderAccount = {\n\treadonly name: string;\n\treadonly source: ProviderAccountSource;\n\treadonly blocked: boolean;\n\treadonly pinned: boolean;\n};\nexport type ProviderAccountsReadParams = { readonly provider: string };\nexport type ProviderAccountsReadResponse = {\n\treadonly provider: string;\n\treadonly accounts: readonly ProviderAccount[];\n};\nexport type ProviderAccountsPinParams = { readonly provider: string; readonly name: string | null };\nexport type ProviderAccountsRemoveParams = { readonly provider: string; readonly name: string };\nexport type ProviderAccountsUpdatedNotification = { readonly provider: string };\nexport type ProviderAccountFailoverNotification = {\n\treadonly provider: string;\n\treadonly from: string;\n\treadonly to: string;\n\treadonly reason: string;\n};\n\nexport type RateLimitWindow = {\n\treadonly usedPercent: number;\n\treadonly windowDurationMins: number | null;\n\treadonly resetsAt: number | null;\n};\nexport type CreditsSnapshot = {\n\treadonly hasCredits: boolean;\n\treadonly unlimited: boolean;\n\treadonly balance: string | null;\n};\nexport type SpendControlLimitSnapshot = {\n\treadonly limit: string;\n\treadonly used: string;\n\treadonly remainingPercent: number;\n\treadonly resetsAt: number;\n};\nexport type RateLimitReachedType =\n\t| \"rate_limit_reached\"\n\t| \"workspace_owner_credits_depleted\"\n\t| \"workspace_member_credits_depleted\"\n\t| \"workspace_owner_usage_limit_reached\"\n\t| \"workspace_member_usage_limit_reached\";\nexport type RateLimitSnapshot = {\n\treadonly limitId: string | null;\n\treadonly limitName: string | null;\n\treadonly primary: RateLimitWindow | null;\n\treadonly secondary: RateLimitWindow | null;\n\treadonly credits: CreditsSnapshot | null;\n\treadonly individualLimit: SpendControlLimitSnapshot | null;\n\treadonly spendControlReached: boolean | null;\n\treadonly planType: PlanType | null;\n\treadonly rateLimitReachedType: RateLimitReachedType | null;\n};\n\nexport type RateLimitResetType = \"codexRateLimits\" | \"unknown\";\nexport type RateLimitResetCreditStatus = \"available\" | \"redeeming\" | \"redeemed\" | \"unknown\";\nexport type RateLimitResetCredit = {\n\treadonly id: string;\n\treadonly resetType: RateLimitResetType;\n\treadonly status: RateLimitResetCreditStatus;\n\treadonly grantedAt: number;\n\treadonly expiresAt: number | null;\n\treadonly title: string | null;\n\treadonly description: string | null;\n};\nexport type RateLimitResetCreditsSummary = {\n\treadonly availableCount: number;\n\treadonly credits: readonly RateLimitResetCredit[] | null;\n};\n\nexport type AccountRateLimitsReadParams = undefined;\nexport type AccountRateLimitsReadResponse = {\n\treadonly rateLimits: RateLimitSnapshot;\n\treadonly rateLimitsByLimitId: Readonly<Record<string, RateLimitSnapshot | undefined>> | null;\n\treadonly rateLimitResetCredits: RateLimitResetCreditsSummary | null;\n};\n\nexport type AccountTokenUsageSummary = {\n\treadonly lifetimeTokens: number | null;\n\treadonly peakDailyTokens: number | null;\n\treadonly longestRunningTurnSec: number | null;\n\treadonly currentStreakDays: number | null;\n\treadonly longestStreakDays: number | null;\n};\nexport type AccountTokenUsageDailyBucket = {\n\treadonly startDate: string;\n\treadonly tokens: number;\n};\nexport type AccountUsageReadParams = undefined;\nexport type AccountUsageReadResponse = {\n\treadonly summary: AccountTokenUsageSummary;\n\treadonly dailyUsageBuckets: readonly AccountTokenUsageDailyBucket[] | null;\n};\n"]}
1
+ {"version":3,"file":"account.js","sourceRoot":"","sources":["../../../../src/modes/app-server/protocol/account.ts"],"names":[],"mappings":"","sourcesContent":["export type PlanType =\n\t| \"free\"\n\t| \"go\"\n\t| \"plus\"\n\t| \"pro\"\n\t| \"prolite\"\n\t| \"team\"\n\t| \"self_serve_business_usage_based\"\n\t| \"business\"\n\t| \"enterprise_cbp_usage_based\"\n\t| \"enterprise\"\n\t| \"edu\"\n\t| \"unknown\";\n\nexport type Account =\n\t| { readonly type: \"apiKey\" }\n\t| { readonly type: \"chatgpt\"; readonly email: string | null; readonly planType: PlanType }\n\t| { readonly type: \"amazonBedrock\"; readonly usesCodexManagedCredentials: boolean };\n\nexport type AccountReadParams = { readonly refreshToken?: boolean };\nexport type AccountReadResponse = {\n\treadonly account: Account | null;\n\treadonly requiresOpenaiAuth: boolean;\n};\n\n/** Additive Senpi provider-account surface; desktop consumers update separately. */\nexport type ProviderAccountSource = \"login\" | \"import\" | \"env\";\nexport type ProviderAccount = {\n\t/** Immutable selector ID; render displayName (name) when metadata is present. */\n\treadonly name: string;\n\treadonly displayName?: string;\n\treadonly source: ProviderAccountSource;\n\treadonly blocked: boolean;\n\treadonly pinned: boolean;\n};\nexport type ProviderAccountsReadParams = { readonly provider: string };\nexport type ProviderAccountsReadResponse = {\n\treadonly provider: string;\n\treadonly accounts: readonly ProviderAccount[];\n};\nexport type ProviderAccountsPinParams = { readonly provider: string; readonly name: string | null };\nexport type ProviderAccountsRemoveParams = { readonly provider: string; readonly name: string };\nexport type ProviderAccountsUpdatedNotification = { readonly provider: string };\nexport type ProviderAccountFailoverNotification = {\n\treadonly provider: string;\n\treadonly from: string;\n\treadonly to: string;\n\treadonly reason: string;\n};\n\nexport type RateLimitWindow = {\n\treadonly usedPercent: number;\n\treadonly windowDurationMins: number | null;\n\treadonly resetsAt: number | null;\n};\nexport type CreditsSnapshot = {\n\treadonly hasCredits: boolean;\n\treadonly unlimited: boolean;\n\treadonly balance: string | null;\n};\nexport type SpendControlLimitSnapshot = {\n\treadonly limit: string;\n\treadonly used: string;\n\treadonly remainingPercent: number;\n\treadonly resetsAt: number;\n};\nexport type RateLimitReachedType =\n\t| \"rate_limit_reached\"\n\t| \"workspace_owner_credits_depleted\"\n\t| \"workspace_member_credits_depleted\"\n\t| \"workspace_owner_usage_limit_reached\"\n\t| \"workspace_member_usage_limit_reached\";\nexport type RateLimitSnapshot = {\n\treadonly limitId: string | null;\n\treadonly limitName: string | null;\n\treadonly primary: RateLimitWindow | null;\n\treadonly secondary: RateLimitWindow | null;\n\treadonly credits: CreditsSnapshot | null;\n\treadonly individualLimit: SpendControlLimitSnapshot | null;\n\treadonly spendControlReached: boolean | null;\n\treadonly planType: PlanType | null;\n\treadonly rateLimitReachedType: RateLimitReachedType | null;\n};\n\nexport type RateLimitResetType = \"codexRateLimits\" | \"unknown\";\nexport type RateLimitResetCreditStatus = \"available\" | \"redeeming\" | \"redeemed\" | \"unknown\";\nexport type RateLimitResetCredit = {\n\treadonly id: string;\n\treadonly resetType: RateLimitResetType;\n\treadonly status: RateLimitResetCreditStatus;\n\treadonly grantedAt: number;\n\treadonly expiresAt: number | null;\n\treadonly title: string | null;\n\treadonly description: string | null;\n};\nexport type RateLimitResetCreditsSummary = {\n\treadonly availableCount: number;\n\treadonly credits: readonly RateLimitResetCredit[] | null;\n};\n\nexport type AccountRateLimitsReadParams = undefined;\nexport type AccountRateLimitsReadResponse = {\n\treadonly rateLimits: RateLimitSnapshot;\n\treadonly rateLimitsByLimitId: Readonly<Record<string, RateLimitSnapshot | undefined>> | null;\n\treadonly rateLimitResetCredits: RateLimitResetCreditsSummary | null;\n};\n\nexport type AccountTokenUsageSummary = {\n\treadonly lifetimeTokens: number | null;\n\treadonly peakDailyTokens: number | null;\n\treadonly longestRunningTurnSec: number | null;\n\treadonly currentStreakDays: number | null;\n\treadonly longestStreakDays: number | null;\n};\nexport type AccountTokenUsageDailyBucket = {\n\treadonly startDate: string;\n\treadonly tokens: number;\n};\nexport type AccountUsageReadParams = undefined;\nexport type AccountUsageReadResponse = {\n\treadonly summary: AccountTokenUsageSummary;\n\treadonly dailyUsageBuckets: readonly AccountTokenUsageDailyBucket[] | null;\n};\n"]}
@@ -12,7 +12,7 @@ export interface AskUserKeyHandlerContext {
12
12
  commentInput: Input;
13
13
  finish(status: QuestionResponse["status"], autoResolvedAfterMs?: number): void;
14
14
  attemptSubmit(): void;
15
- openOwnAnswer(): void;
15
+ openOwnAnswer(initialText?: string): void;
16
16
  commitOwnAnswer(): void;
17
17
  emitProgress(): void;
18
18
  updateAll(): void;
@@ -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,IAAI,IAAI,CAAC;IACtB,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,CAWvF"}
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"}
@@ -6,12 +6,16 @@
6
6
  import { getKeybindings, matchesKey } from "@earendil-works/pi-tui";
7
7
  export function handleAskUserKeyInput(ctx, data) {
8
8
  const kb = getKeybindings();
9
+ if (matchesKey(data, "ctrl+c")) {
10
+ ctx.finish("cancelled");
11
+ return;
12
+ }
9
13
  if (ctx.state.focus === "own-answer") {
10
14
  handleOwnAnswerKey(ctx, data, kb);
11
15
  return;
12
16
  }
13
- if (ctx.state.focus === "comment") {
14
- handleCommentKey(ctx, data, kb);
17
+ if (ctx.state.focus === "submit") {
18
+ handleSubmitKey(ctx, data, kb);
15
19
  return;
16
20
  }
17
21
  handleOptionsKey(ctx, data, kb);
@@ -24,23 +28,41 @@ function handleOwnAnswerKey(ctx, data, kb) {
24
28
  }
25
29
  if (kb.matches(data, "tui.select.confirm") || data === "\n") {
26
30
  ctx.commitOwnAnswer();
31
+ ctx.state.advance();
32
+ ctx.updateAll();
27
33
  return;
28
34
  }
29
35
  if (kb.matches(data, "tui.select.cancel")) {
30
- ctx.state.focus = "options";
36
+ if (ctx.state.request.waitForAnswer)
37
+ ctx.state.returnToOptions();
38
+ else
39
+ ctx.finish("cancelled");
31
40
  ctx.updateAll();
32
41
  return;
33
42
  }
34
43
  ctx.ownAnswerInput.handleInput(data);
35
44
  ctx.emitProgress();
36
45
  }
37
- function handleCommentKey(ctx, data, kb) {
46
+ function handleSubmitKey(ctx, data, kb) {
38
47
  if (matchesKey(data, "ctrl+enter") || kb.matches(data, "tui.input.submit") || data === "\n") {
39
48
  ctx.attemptSubmit();
40
49
  return;
41
50
  }
42
51
  if (kb.matches(data, "tui.select.cancel")) {
43
- ctx.state.focus = "options";
52
+ if (ctx.state.request.waitForAnswer)
53
+ ctx.state.returnToOptions();
54
+ else
55
+ ctx.finish("cancelled");
56
+ ctx.updateAll();
57
+ return;
58
+ }
59
+ if (matchesKey(data, "shift+tab") || matchesKey(data, "left")) {
60
+ ctx.state.switchTab(-1);
61
+ ctx.updateAll();
62
+ return;
63
+ }
64
+ if (matchesKey(data, "tab") || matchesKey(data, "right")) {
65
+ ctx.state.switchTab(1);
44
66
  ctx.updateAll();
45
67
  return;
46
68
  }
@@ -55,16 +77,19 @@ function handleOptionsKey(ctx, data, kb) {
55
77
  return;
56
78
  }
57
79
  if (kb.matches(data, "tui.select.cancel")) {
58
- ctx.finish("cancelled");
80
+ if (!state.request.waitForAnswer || state.requestDismiss() === "cancel")
81
+ ctx.finish("cancelled");
82
+ else
83
+ ctx.updateAll();
59
84
  return;
60
85
  }
61
86
  if (matchesKey(data, "tab") || matchesKey(data, "right")) {
62
- state.switchQuestion(1);
87
+ state.switchTab(1);
63
88
  ctx.updateAll();
64
89
  return;
65
90
  }
66
91
  if (matchesKey(data, "shift+tab") || matchesKey(data, "left")) {
67
- state.switchQuestion(-1);
92
+ state.switchTab(-1);
68
93
  ctx.updateAll();
69
94
  return;
70
95
  }
@@ -74,10 +99,7 @@ function handleOptionsKey(ctx, data, kb) {
74
99
  return;
75
100
  }
76
101
  if (kb.matches(data, "tui.select.down") || data === "j") {
77
- if (state.highlightIndex >= state.ownAnswerRowIndex)
78
- state.focus = "comment";
79
- else
80
- state.highlightIndex += 1;
102
+ state.highlightIndex = Math.min(state.ownAnswerRowIndex, state.highlightIndex + 1);
81
103
  ctx.updateAll();
82
104
  return;
83
105
  }
@@ -86,20 +108,35 @@ function handleOptionsKey(ctx, data, kb) {
86
108
  if (option) {
87
109
  state.activateOption(state.activeQuestion.id, option.label);
88
110
  ctx.emitProgress();
111
+ if (!state.activeQuestion.multiSelect) {
112
+ if (state.request.waitForAnswer && state.request.questions.length === 1)
113
+ ctx.attemptSubmit();
114
+ else
115
+ state.advance();
116
+ }
89
117
  ctx.updateAll();
90
118
  }
91
119
  return;
92
120
  }
93
- if (matchesKey(data, "space") || kb.matches(data, "tui.select.confirm") || data === "\n") {
94
- activateHighlighted(ctx);
121
+ if (matchesKey(data, "space")) {
122
+ activateHighlighted(ctx, false);
123
+ return;
124
+ }
125
+ if (kb.matches(data, "tui.select.confirm") || data === "\n") {
126
+ activateHighlighted(ctx, true);
95
127
  return;
96
128
  }
97
129
  if (data === "c") {
98
- state.focus = "comment";
130
+ state.focus = "submit";
131
+ ctx.updateAll();
132
+ return;
133
+ }
134
+ if (data.length === 1 && data >= " " && data !== "c") {
135
+ ctx.openOwnAnswer(data);
99
136
  ctx.updateAll();
100
137
  }
101
138
  }
102
- function activateHighlighted(ctx) {
139
+ function activateHighlighted(ctx, confirm) {
103
140
  const state = ctx.state;
104
141
  if (state.highlightIndex === state.ownAnswerRowIndex) {
105
142
  ctx.openOwnAnswer();
@@ -108,8 +145,19 @@ function activateHighlighted(ctx) {
108
145
  const option = state.activeQuestion.options[state.highlightIndex];
109
146
  if (!option)
110
147
  return;
111
- state.activateOption(state.activeQuestion.id, option.label);
148
+ if (!confirm || !state.activeQuestion.multiSelect) {
149
+ state.activateOption(state.activeQuestion.id, option.label);
150
+ }
112
151
  ctx.emitProgress();
113
152
  ctx.updateAll();
153
+ if (confirm) {
154
+ if (!state.activeQuestion.multiSelect && state.request.waitForAnswer && state.request.questions.length === 1) {
155
+ ctx.attemptSubmit();
156
+ }
157
+ else {
158
+ state.advance();
159
+ ctx.updateAll();
160
+ }
161
+ }
114
162
  }
115
163
  //# sourceMappingURL=ask-user-question-keys.js.map
@@ -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(): 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 (ctx.state.focus === \"own-answer\") {\n\t\thandleOwnAnswerKey(ctx, data, kb);\n\t\treturn;\n\t}\n\tif (ctx.state.focus === \"comment\") {\n\t\thandleCommentKey(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\treturn;\n\t}\n\tif (kb.matches(data, \"tui.select.cancel\")) {\n\t\tctx.state.focus = \"options\";\n\t\tctx.updateAll();\n\t\treturn;\n\t}\n\tctx.ownAnswerInput.handleInput(data);\n\tctx.emitProgress();\n}\n\nfunction handleCommentKey(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\tctx.state.focus = \"options\";\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\tctx.finish(\"cancelled\");\n\t\treturn;\n\t}\n\tif (matchesKey(data, \"tab\") || matchesKey(data, \"right\")) {\n\t\tstate.switchQuestion(1);\n\t\tctx.updateAll();\n\t\treturn;\n\t}\n\tif (matchesKey(data, \"shift+tab\") || matchesKey(data, \"left\")) {\n\t\tstate.switchQuestion(-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\tif (state.highlightIndex >= state.ownAnswerRowIndex) state.focus = \"comment\";\n\t\telse 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\tctx.updateAll();\n\t\t}\n\t\treturn;\n\t}\n\tif (matchesKey(data, \"space\") || kb.matches(data, \"tui.select.confirm\") || data === \"\\n\") {\n\t\tactivateHighlighted(ctx);\n\t\treturn;\n\t}\n\tif (data === \"c\") {\n\t\tstate.focus = \"comment\";\n\t\tctx.updateAll();\n\t}\n}\n\nfunction activateHighlighted(ctx: AskUserKeyHandlerContext): 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\tstate.activateOption(state.activeQuestion.id, option.label);\n\tctx.emitProgress();\n\tctx.updateAll();\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\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"]}
@@ -9,9 +9,10 @@ export declare function renderTitle(countdownLabel: string): string;
9
9
  export declare function renderTabBar(state: AskUserQuestionState): string;
10
10
  export declare function renderQuestionLine(question: QuestionRequest["questions"][number]): string;
11
11
  export declare function renderQuestionList(state: AskUserQuestionState): string[];
12
+ export declare function renderSubmitSummary(state: AskUserQuestionState): string[];
12
13
  export declare function renderOwnAnswerLabel(): string;
13
14
  export declare function renderCommentLabel(): string;
14
15
  export declare function renderNotice(notice: string | undefined): string;
15
16
  export declare function renderSubmitLine(state: AskUserQuestionState): string;
16
- export declare function renderHintsLine(): string;
17
+ export declare function renderHintsLine(state: AskUserQuestionState): string;
17
18
  //# sourceMappingURL=ask-user-question-render.d.ts.map
@@ -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,CAShE;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,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,CAOpE;AAED,wBAAgB,eAAe,IAAI,MAAM,CAgBxC"}
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"}
@@ -5,7 +5,7 @@
5
5
  */
6
6
  import { theme } from "../theme/theme.js";
7
7
  import { COMMENT_LABEL, OWN_ANSWER_LABEL } from "./ask-user-question-state.js";
8
- import { keyHint, rawKeyHint } from "./keybinding-hints.js";
8
+ import { rawKeyHint } from "./keybinding-hints.js";
9
9
  export function renderTitle(countdownLabel) {
10
10
  const suffix = countdownLabel === "" ? "" : theme.fg("muted", ` · ${countdownLabel}`);
11
11
  return theme.fg("accent", theme.bold("Ask user")) + suffix;
@@ -14,11 +14,14 @@ export function renderTabBar(state) {
14
14
  const tabs = state.request.questions.map((question, index) => {
15
15
  const answered = state.isAnswered(question.id) ? theme.fg("success", " ✓") : "";
16
16
  const label = `${question.header}${answered}`;
17
- return index === state.activeIndex
17
+ return index === state.activeTabIndex
18
18
  ? theme.fg("accent", theme.bold(`→ ${label}`))
19
19
  : theme.fg("muted", ` ${label}`);
20
20
  });
21
- return tabs.join(" ");
21
+ const submit = state.activeTabIndex === state.request.questions.length
22
+ ? theme.fg("accent", theme.bold("→ Submit"))
23
+ : theme.fg("muted", " Submit");
24
+ return [...tabs, submit].join(" ");
22
25
  }
23
26
  export function renderQuestionLine(question) {
24
27
  return theme.fg("text", question.question);
@@ -42,6 +45,15 @@ export function renderQuestionList(state) {
42
45
  lines.push(`${ownPrefix}${theme.fg("muted", OWN_ANSWER_LABEL)}${ownSuffix}`);
43
46
  return lines;
44
47
  }
48
+ export function renderSubmitSummary(state) {
49
+ return state.request.questions.map((question) => {
50
+ const answer = state.answers()[question.id];
51
+ if (!answer)
52
+ return theme.fg("warning", `${question.header}: unanswered`);
53
+ const value = answer.selected.length > 0 ? answer.selected.join(", ") : (answer.text ?? "");
54
+ return `${question.header}: ${value}`;
55
+ });
56
+ }
45
57
  export function renderOwnAnswerLabel() {
46
58
  return theme.fg("muted", "Your answer (enter to save, esc to discard)");
47
59
  }
@@ -54,22 +66,40 @@ export function renderNotice(notice) {
54
66
  export function renderSubmitLine(state) {
55
67
  const answered = state.answeredCount();
56
68
  const total = state.request.questions.length;
57
- return (theme.fg("accent", theme.bold(`Submit (${answered}/${total} answered)`)) +
58
- theme.fg("muted", " ctrl+enter or enter in comment"));
69
+ if (state.focus === "submit") {
70
+ return theme.fg("accent", theme.bold(`Submit (${answered}/${total} answered)`));
71
+ }
72
+ return (theme.fg("accent", theme.bold(`Submit (${answered}/${total} answered)`)) + theme.fg("muted", " — Enter advances"));
59
73
  }
60
- export function renderHintsLine() {
74
+ export function renderHintsLine(state) {
75
+ if (state.focus === "submit") {
76
+ return (rawKeyHint("enter", "submit") +
77
+ " " +
78
+ rawKeyHint("←/shift+tab", "back") +
79
+ " " +
80
+ rawKeyHint("tab", "next question") +
81
+ " " +
82
+ rawKeyHint("esc", "back"));
83
+ }
84
+ if (state.focus === "own-answer") {
85
+ return (rawKeyHint("enter", "save and next") +
86
+ " " +
87
+ rawKeyHint("esc", "discard") +
88
+ " " +
89
+ rawKeyHint("shift+enter", "new line"));
90
+ }
61
91
  return (rawKeyHint("↑↓", "move") +
62
92
  " " +
63
93
  rawKeyHint("1-9", "select") +
64
94
  " " +
65
- rawKeyHint("space", "toggle") +
95
+ rawKeyHint("space", state.activeQuestion.multiSelect ? "toggle" : "select") +
66
96
  " " +
67
- keyHint("tui.select.confirm", "select") +
97
+ rawKeyHint("enter", "next") +
68
98
  " " +
69
99
  rawKeyHint("tab", "next question") +
70
100
  " " +
71
101
  rawKeyHint("c", "comment") +
72
102
  " " +
73
- keyHint("tui.select.cancel", "cancel"));
103
+ rawKeyHint("esc", "cancel"));
74
104
  }
75
105
  //# sourceMappingURL=ask-user-question-render.js.map
@@ -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 { keyHint, 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.activeIndex\n\t\t\t? theme.fg(\"accent\", theme.bold(`→ ${label}`))\n\t\t\t: theme.fg(\"muted\", ` ${label}`);\n\t});\n\treturn tabs.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 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\treturn (\n\t\ttheme.fg(\"accent\", theme.bold(`Submit (${answered}/${total} answered)`)) +\n\t\ttheme.fg(\"muted\", \" — ctrl+enter or enter in comment\")\n\t);\n}\n\nexport function renderHintsLine(): string {\n\treturn (\n\t\trawKeyHint(\"↑↓\", \"move\") +\n\t\t\" \" +\n\t\trawKeyHint(\"1-9\", \"select\") +\n\t\t\" \" +\n\t\trawKeyHint(\"space\", \"toggle\") +\n\t\t\" \" +\n\t\tkeyHint(\"tui.select.confirm\", \"select\") +\n\t\t\" \" +\n\t\trawKeyHint(\"tab\", \"next question\") +\n\t\t\" \" +\n\t\trawKeyHint(\"c\", \"comment\") +\n\t\t\" \" +\n\t\tkeyHint(\"tui.select.cancel\", \"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) => {\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"]}