@astralyn/pi 1.4.6 → 1.4.7

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 (242) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/bundle/chunks/{chunk-KDO6L76C.js → chunk-FODCTZXW.js} +4 -4
  3. package/dist/bundle/chunks/{chunk-EYKC6ESU.js → chunk-FYKNSJG6.js} +1 -1
  4. package/dist/bundle/chunks/{chunk-AXFWZIHH.js → chunk-MG5XDTXV.js} +1 -1
  5. package/dist/bundle/chunks/{chunk-ALHAFUHP.js → chunk-PU2IWWXV.js} +1 -1
  6. package/dist/bundle/chunks/{chunk-5M3YJ54Z.js → chunk-RO2VH6UZ.js} +1 -1
  7. package/dist/bundle/chunks/{chunk-RBTJBQWX.js → chunk-YJTSOLP2.js} +73 -74
  8. package/dist/bundle/chunks/{cli-FH77R7JR.js → cli-MEL7SGJD.js} +1 -1
  9. package/dist/bundle/chunks/{execute-5ZQUS52M.js → execute-4CWRNHPO.js} +1 -1
  10. package/dist/bundle/chunks/{runtime-R5CMHJ5P.js → runtime-R3X67XMR.js} +1 -1
  11. package/dist/bundle/chunks/{virtual-modules-KCQU7LOC.js → virtual-modules-PKEOKGYI.js} +1 -1
  12. package/dist/bundle/cli.js +1 -1
  13. package/dist/bundle/index.js +1 -1
  14. package/dist/bundle/rpc-entry.js +1 -1
  15. package/dist/core/agent-session.d.ts +0 -3
  16. package/dist/core/agent-session.d.ts.map +1 -1
  17. package/dist/core/agent-session.js +0 -4
  18. package/dist/core/agent-session.js.map +1 -1
  19. package/dist/core/extensions/index.d.ts +1 -1
  20. package/dist/core/extensions/index.d.ts.map +1 -1
  21. package/dist/core/extensions/index.js.map +1 -1
  22. package/dist/core/package-manager.d.ts +7 -1
  23. package/dist/core/package-manager.d.ts.map +1 -1
  24. package/dist/core/package-manager.js +72 -1
  25. package/dist/core/package-manager.js.map +1 -1
  26. package/dist/core/resource-loader.d.ts +1 -0
  27. package/dist/core/resource-loader.d.ts.map +1 -1
  28. package/dist/core/resource-loader.js +23 -7
  29. package/dist/core/resource-loader.js.map +1 -1
  30. package/dist/core/settings-manager.d.ts +4 -2
  31. package/dist/core/settings-manager.d.ts.map +1 -1
  32. package/dist/core/settings-manager.js +11 -0
  33. package/dist/core/settings-manager.js.map +1 -1
  34. package/dist/core/settings-schema.d.ts +7 -0
  35. package/dist/core/settings-schema.d.ts.map +1 -1
  36. package/dist/core/settings-schema.js +6 -0
  37. package/dist/core/settings-schema.js.map +1 -1
  38. package/dist/core/skills.d.ts +10 -0
  39. package/dist/core/skills.d.ts.map +1 -1
  40. package/dist/core/skills.js +23 -0
  41. package/dist/core/skills.js.map +1 -1
  42. package/dist/core/tasks/delivery.d.ts +11 -4
  43. package/dist/core/tasks/delivery.d.ts.map +1 -1
  44. package/dist/core/tasks/delivery.js +9 -9
  45. package/dist/core/tasks/delivery.js.map +1 -1
  46. package/dist/core/tasks/execution.d.ts +10 -3
  47. package/dist/core/tasks/execution.d.ts.map +1 -1
  48. package/dist/core/tasks/execution.js +72 -52
  49. package/dist/core/tasks/execution.js.map +1 -1
  50. package/dist/core/tasks/format.d.ts +0 -2
  51. package/dist/core/tasks/format.d.ts.map +1 -1
  52. package/dist/core/tasks/format.js +1 -16
  53. package/dist/core/tasks/format.js.map +1 -1
  54. package/dist/core/tasks/limits.d.ts +12 -1
  55. package/dist/core/tasks/limits.d.ts.map +1 -1
  56. package/dist/core/tasks/limits.js +20 -1
  57. package/dist/core/tasks/limits.js.map +1 -1
  58. package/dist/core/tasks/output.d.ts +6 -12
  59. package/dist/core/tasks/output.d.ts.map +1 -1
  60. package/dist/core/tasks/output.js +35 -32
  61. package/dist/core/tasks/output.js.map +1 -1
  62. package/dist/core/tasks/record.d.ts +45 -0
  63. package/dist/core/tasks/record.d.ts.map +1 -0
  64. package/dist/core/tasks/record.js +80 -0
  65. package/dist/core/tasks/record.js.map +1 -0
  66. package/dist/core/tasks/runtime.d.ts +14 -14
  67. package/dist/core/tasks/runtime.d.ts.map +1 -1
  68. package/dist/core/tasks/runtime.js +111 -93
  69. package/dist/core/tasks/runtime.js.map +1 -1
  70. package/dist/core/tasks/session.d.ts +0 -1
  71. package/dist/core/tasks/session.d.ts.map +1 -1
  72. package/dist/core/tasks/session.js +7 -8
  73. package/dist/core/tasks/session.js.map +1 -1
  74. package/dist/core/tasks/store.d.ts +18 -25
  75. package/dist/core/tasks/store.d.ts.map +1 -1
  76. package/dist/core/tasks/store.js +42 -40
  77. package/dist/core/tasks/store.js.map +1 -1
  78. package/dist/core/tasks/types.d.ts +96 -17
  79. package/dist/core/tasks/types.d.ts.map +1 -1
  80. package/dist/core/tasks/types.js.map +1 -1
  81. package/dist/core/tools/shell-execution.d.ts +8 -7
  82. package/dist/core/tools/shell-execution.d.ts.map +1 -1
  83. package/dist/core/tools/shell-execution.js +18 -26
  84. package/dist/core/tools/shell-execution.js.map +1 -1
  85. package/dist/core/tools/shell-tool.d.ts.map +1 -1
  86. package/dist/core/tools/shell-tool.js +31 -29
  87. package/dist/core/tools/shell-tool.js.map +1 -1
  88. package/dist/core/usage-totals.d.ts +3 -0
  89. package/dist/core/usage-totals.d.ts.map +1 -1
  90. package/dist/core/usage-totals.js +15 -0
  91. package/dist/core/usage-totals.js.map +1 -1
  92. package/dist/extensions/agent/progress.d.ts.map +1 -1
  93. package/dist/extensions/agent/progress.js +1 -11
  94. package/dist/extensions/agent/progress.js.map +1 -1
  95. package/dist/extensions/agent/tool.d.ts.map +1 -1
  96. package/dist/extensions/agent/tool.js +9 -5
  97. package/dist/extensions/agent/tool.js.map +1 -1
  98. package/dist/extensions/agent/worker.d.ts.map +1 -1
  99. package/dist/extensions/agent/worker.js +3 -5
  100. package/dist/extensions/agent/worker.js.map +1 -1
  101. package/dist/extensions/btw/agent.d.ts +1 -1
  102. package/dist/extensions/btw/agent.d.ts.map +1 -1
  103. package/dist/extensions/btw/agent.js +3 -20
  104. package/dist/extensions/btw/agent.js.map +1 -1
  105. package/dist/extensions/cached-compaction/index.d.ts.map +1 -1
  106. package/dist/extensions/cached-compaction/index.js +3 -22
  107. package/dist/extensions/cached-compaction/index.js.map +1 -1
  108. package/dist/extensions/cached-compaction/render.d.ts +1 -0
  109. package/dist/extensions/cached-compaction/render.d.ts.map +1 -1
  110. package/dist/extensions/cached-compaction/render.js +42 -14
  111. package/dist/extensions/cached-compaction/render.js.map +1 -1
  112. package/dist/extensions/deepwiki/client.d.ts.map +1 -1
  113. package/dist/extensions/deepwiki/client.js +6 -78
  114. package/dist/extensions/deepwiki/client.js.map +1 -1
  115. package/dist/extensions/deepwiki/transport.d.ts +3 -0
  116. package/dist/extensions/deepwiki/transport.d.ts.map +1 -0
  117. package/dist/extensions/deepwiki/transport.js +96 -0
  118. package/dist/extensions/deepwiki/transport.js.map +1 -0
  119. package/dist/extensions/provider/ui/builtin-data.d.ts +3 -3
  120. package/dist/extensions/provider/ui/builtin-data.d.ts.map +1 -1
  121. package/dist/extensions/provider/ui/builtin-data.js.map +1 -1
  122. package/dist/extensions/provider/ui/compat.d.ts +3 -3
  123. package/dist/extensions/provider/ui/compat.d.ts.map +1 -1
  124. package/dist/extensions/provider/ui/compat.js.map +1 -1
  125. package/dist/extensions/provider/ui/controls.d.ts +2 -2
  126. package/dist/extensions/provider/ui/controls.d.ts.map +1 -1
  127. package/dist/extensions/provider/ui/controls.js.map +1 -1
  128. package/dist/extensions/provider/ui/dialogs.d.ts +3 -3
  129. package/dist/extensions/provider/ui/dialogs.d.ts.map +1 -1
  130. package/dist/extensions/provider/ui/dialogs.js.map +1 -1
  131. package/dist/extensions/provider/ui/dictionary.d.ts +2 -2
  132. package/dist/extensions/provider/ui/dictionary.d.ts.map +1 -1
  133. package/dist/extensions/provider/ui/dictionary.js.map +1 -1
  134. package/dist/extensions/provider/ui/editor.d.ts.map +1 -1
  135. package/dist/extensions/provider/ui/editor.js +1 -3
  136. package/dist/extensions/provider/ui/editor.js.map +1 -1
  137. package/dist/extensions/provider/ui/fetch-models.d.ts +2 -2
  138. package/dist/extensions/provider/ui/fetch-models.d.ts.map +1 -1
  139. package/dist/extensions/provider/ui/fetch-models.js.map +1 -1
  140. package/dist/extensions/provider/ui/model-fields.d.ts +2 -2
  141. package/dist/extensions/provider/ui/model-fields.d.ts.map +1 -1
  142. package/dist/extensions/provider/ui/model-fields.js.map +1 -1
  143. package/dist/extensions/provider/ui/model-options.d.ts +6 -6
  144. package/dist/extensions/provider/ui/model-options.d.ts.map +1 -1
  145. package/dist/extensions/provider/ui/model-options.js.map +1 -1
  146. package/dist/extensions/provider/ui/pane.d.ts +21 -12
  147. package/dist/extensions/provider/ui/pane.d.ts.map +1 -1
  148. package/dist/extensions/provider/ui/pane.js.map +1 -1
  149. package/dist/extensions/provider/ui/provider-fields.d.ts +3 -3
  150. package/dist/extensions/provider/ui/provider-fields.d.ts.map +1 -1
  151. package/dist/extensions/provider/ui/provider-fields.js.map +1 -1
  152. package/dist/extensions/provider/ui/thinking-map.d.ts +2 -2
  153. package/dist/extensions/provider/ui/thinking-map.d.ts.map +1 -1
  154. package/dist/extensions/provider/ui/thinking-map.js.map +1 -1
  155. package/dist/extensions/run-summary/format.js +1 -1
  156. package/dist/extensions/run-summary/format.js.map +1 -1
  157. package/dist/extensions/statusline/usage.d.ts.map +1 -1
  158. package/dist/extensions/statusline/usage.js +2 -6
  159. package/dist/extensions/statusline/usage.js.map +1 -1
  160. package/dist/extensions/tasks/tool/actions.d.ts +1 -1
  161. package/dist/extensions/tasks/tool/actions.d.ts.map +1 -1
  162. package/dist/extensions/tasks/tool/actions.js +49 -106
  163. package/dist/extensions/tasks/tool/actions.js.map +1 -1
  164. package/dist/extensions/tasks/tool/constants.d.ts +1 -6
  165. package/dist/extensions/tasks/tool/constants.d.ts.map +1 -1
  166. package/dist/extensions/tasks/tool/constants.js +1 -6
  167. package/dist/extensions/tasks/tool/constants.js.map +1 -1
  168. package/dist/extensions/tasks/tool/schema.d.ts +0 -3
  169. package/dist/extensions/tasks/tool/schema.d.ts.map +1 -1
  170. package/dist/extensions/tasks/tool/schema.js +4 -13
  171. package/dist/extensions/tasks/tool/schema.js.map +1 -1
  172. package/dist/extensions/tasks/tool.d.ts.map +1 -1
  173. package/dist/extensions/tasks/tool.js +2 -2
  174. package/dist/extensions/tasks/tool.js.map +1 -1
  175. package/dist/extensions/tasks/ui/completion-render.d.ts.map +1 -1
  176. package/dist/extensions/tasks/ui/completion-render.js +31 -33
  177. package/dist/extensions/tasks/ui/completion-render.js.map +1 -1
  178. package/dist/extensions/tasks/ui/layout.d.ts +7 -7
  179. package/dist/extensions/tasks/ui/layout.d.ts.map +1 -1
  180. package/dist/extensions/tasks/ui/layout.js +17 -19
  181. package/dist/extensions/tasks/ui/layout.js.map +1 -1
  182. package/dist/extensions/tasks/ui/list.d.ts.map +1 -1
  183. package/dist/extensions/tasks/ui/list.js +2 -3
  184. package/dist/extensions/tasks/ui/list.js.map +1 -1
  185. package/dist/extensions/tasks/ui/manager.d.ts +16 -7
  186. package/dist/extensions/tasks/ui/manager.d.ts.map +1 -1
  187. package/dist/extensions/tasks/ui/manager.js +163 -131
  188. package/dist/extensions/tasks/ui/manager.js.map +1 -1
  189. package/dist/extensions/tasks/ui/model.d.ts +25 -0
  190. package/dist/extensions/tasks/ui/model.d.ts.map +1 -1
  191. package/dist/extensions/tasks/ui/model.js +4 -0
  192. package/dist/extensions/tasks/ui/model.js.map +1 -1
  193. package/dist/extensions/tasks/ui/render.d.ts +1 -1
  194. package/dist/extensions/tasks/ui/render.d.ts.map +1 -1
  195. package/dist/extensions/tasks/ui/render.js +11 -7
  196. package/dist/extensions/tasks/ui/render.js.map +1 -1
  197. package/dist/extensions/tasks/ui/status.d.ts +15 -0
  198. package/dist/extensions/tasks/ui/status.d.ts.map +1 -0
  199. package/dist/extensions/tasks/ui/status.js +16 -0
  200. package/dist/extensions/tasks/ui/status.js.map +1 -0
  201. package/dist/index.d.ts +1 -1
  202. package/dist/index.d.ts.map +1 -1
  203. package/dist/index.js.map +1 -1
  204. package/dist/modes/interactive/components/config-selector.d.ts +14 -1
  205. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  206. package/dist/modes/interactive/components/config-selector.js +258 -7
  207. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  208. package/dist/modes/interactive/components/status-marker.d.ts +2 -1
  209. package/dist/modes/interactive/components/status-marker.d.ts.map +1 -1
  210. package/dist/modes/interactive/components/status-marker.js +0 -1
  211. package/dist/modes/interactive/components/status-marker.js.map +1 -1
  212. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  213. package/dist/modes/interactive/interactive-mode.js +7 -1
  214. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  215. package/dist/utils/duration.d.ts +3 -0
  216. package/dist/utils/duration.d.ts.map +1 -0
  217. package/dist/utils/duration.js +17 -0
  218. package/dist/utils/duration.js.map +1 -0
  219. package/dist/utils/number.d.ts +3 -0
  220. package/dist/utils/number.d.ts.map +1 -0
  221. package/dist/utils/number.js +5 -0
  222. package/dist/utils/number.js.map +1 -0
  223. package/docs/bundled/extensions/agent.md +3 -3
  224. package/docs/bundled/extensions/cached-compaction.md +13 -4
  225. package/docs/bundled/extensions/deepwiki.md +3 -1
  226. package/docs/extensions.md +5 -5
  227. package/docs/packages.md +5 -3
  228. package/docs/sdk.md +1 -1
  229. package/docs/session-format.md +1 -1
  230. package/docs/settings.md +11 -0
  231. package/docs/skills.md +23 -0
  232. package/npm-shrinkwrap.json +2 -2
  233. package/package.json +1 -1
  234. package/schemas/settings.schema.json +36 -0
  235. package/dist/extensions/deepwiki/http.d.ts +0 -13
  236. package/dist/extensions/deepwiki/http.d.ts.map +0 -1
  237. package/dist/extensions/deepwiki/http.js +0 -88
  238. package/dist/extensions/deepwiki/http.js.map +0 -1
  239. package/dist/extensions/tasks/ui/task-view.d.ts +0 -8
  240. package/dist/extensions/tasks/ui/task-view.d.ts.map +0 -1
  241. package/dist/extensions/tasks/ui/task-view.js +0 -13
  242. package/dist/extensions/tasks/ui/task-view.js.map +0 -1
@@ -6,9 +6,10 @@ import { STATUS_SPINNER_INTERVAL_MS } from "../../../modes/interactive/component
6
6
  import { TaskInspector } from "./inspector.js";
7
7
  import { renderTasksLayout } from "./layout.js";
8
8
  import { TaskList } from "./list.js";
9
- import { TaskSelection } from "./model.js";
9
+ import { isStoppable, TaskSelection } from "./model.js";
10
10
  import { cleanTaskText } from "./text.js";
11
11
  import { TaskViewport } from "./viewport.js";
12
+ const BROWSE = { kind: "browse" };
12
13
  const actions = [
13
14
  "app.tasks.search",
14
15
  "app.tasks.kill",
@@ -26,8 +27,8 @@ export class TasksMenu {
26
27
  constructor(options) {
27
28
  this.focused = false;
28
29
  this.list = new TaskList();
30
+ this.mode = BROWSE;
29
31
  this.focus = "list";
30
- this.searching = false;
31
32
  this.dirty = true;
32
33
  this.tickQueued = false;
33
34
  this.refreshQueued = false;
@@ -69,8 +70,8 @@ export class TasksMenu {
69
70
  const selected = this.selection.selected;
70
71
  if (selected && isTaskTerminal(selected.status) && previous && !isTaskTerminal(previous.status))
71
72
  this.feedback = undefined;
72
- if (this.pendingKill && (this.pendingKill !== selected?.id || (selected && isTaskTerminal(selected.status))))
73
- this.clearKill();
73
+ if (this.mode.kind === "confirmStop" && (this.mode.taskId !== selected?.id || isTaskTerminal(selected.status)))
74
+ this.setMode(BROWSE);
74
75
  const animates = this.selection.all.some((task) => task.status === "running");
75
76
  if (animates && !this.animationTimer) {
76
77
  this.animationTimer = setInterval(() => this.options.tui.requestRender(), STATUS_SPINNER_INTERVAL_MS);
@@ -106,50 +107,76 @@ export class TasksMenu {
106
107
  invalidate() {
107
108
  this.inspector.invalidate();
108
109
  }
109
- clearKill() {
110
- this.pendingKill = undefined;
110
+ /** The one place the mode changes; the search input is focused exactly while searching. */
111
+ setMode(next) {
112
+ this.mode = next;
113
+ this.search.focused = next.kind === "search";
114
+ }
115
+ /** Unwinds exactly one transient layer; from plain browsing it closes the panel. */
116
+ cancel() {
117
+ switch (this.mode.kind) {
118
+ case "search":
119
+ this.finishSearch(true);
120
+ break;
121
+ case "help":
122
+ case "confirmStop":
123
+ this.setMode(BROWSE);
124
+ break;
125
+ case "browse":
126
+ this.close();
127
+ break;
128
+ }
129
+ }
130
+ close() {
131
+ this.dispose();
132
+ this.options.onClose();
111
133
  }
112
134
  selectedChanged() {
113
- this.clearKill();
135
+ if (this.mode.kind === "confirmStop")
136
+ this.setMode(BROWSE);
114
137
  this.list.showSelection();
115
138
  this.inspector.select(this.selection.selected);
116
139
  this.queueTick(true);
117
140
  }
118
- stop(confirm = false) {
141
+ requestStop() {
119
142
  const task = this.selection.selected;
120
- if (confirm) {
121
- const id = this.pendingKill;
122
- this.clearKill();
123
- if (!id || id !== task?.id || isTaskTerminal(task.status))
124
- return;
125
- this.feedback = this.options.host.kill(id)
126
- ? "Cancellation requested; waiting for cleanup."
127
- : "No new cancellation requested.";
128
- }
129
- else if (task && !isTaskTerminal(task.status) && task.status !== "stopping") {
130
- this.pendingKill = task.id;
131
- }
143
+ if (task && isStoppable(task))
144
+ this.setMode({ kind: "confirmStop", taskId: task.id });
145
+ }
146
+ confirmStop() {
147
+ const mode = this.mode;
148
+ if (mode.kind !== "confirmStop")
149
+ return;
150
+ this.setMode(BROWSE);
151
+ const task = this.selection.selected;
152
+ if (mode.taskId !== task?.id || isTaskTerminal(task.status))
153
+ return;
154
+ this.feedback = this.options.host.kill(mode.taskId)
155
+ ? "Cancellation requested; waiting for cleanup."
156
+ : "No new cancellation requested.";
157
+ }
158
+ startSearch() {
159
+ this.setMode({ kind: "search", restore: { id: this.selection.state.selectedId, focus: this.focus } });
160
+ this.focus = "list";
161
+ this.search.setValue("");
132
162
  }
133
163
  finishSearch(cancel) {
134
- const id = cancel ? this.beforeSearch?.id : this.selection.state.selectedId;
164
+ const mode = this.mode;
165
+ if (mode.kind !== "search")
166
+ return;
167
+ const id = cancel ? mode.restore.id : this.selection.state.selectedId;
135
168
  if (!cancel && !id)
136
169
  return;
137
- this.focus = cancel ? (this.beforeSearch?.focus ?? "list") : "list";
138
- this.searching = false;
139
- this.search.focused = false;
170
+ this.focus = cancel ? mode.restore.focus : "list";
171
+ this.setMode(BROWSE);
140
172
  this.selection.query = "";
141
173
  this.selection.select(id);
142
- this.beforeSearch = undefined;
143
174
  this.selectedChanged();
144
175
  }
145
176
  action(key) {
146
177
  switch (key) {
147
178
  case "app.tasks.search":
148
- this.beforeSearch = { id: this.selection.state.selectedId, focus: this.focus };
149
- this.focus = "list";
150
- this.searching = true;
151
- this.search.focused = true;
152
- this.search.setValue("");
179
+ this.startSearch();
153
180
  break;
154
181
  case "app.tasks.previousTab":
155
182
  case "app.tasks.nextTab":
@@ -176,31 +203,29 @@ export class TasksMenu {
176
203
  this.inspector.position[this.selection.state.tab].jump(key === "app.tasks.bottom", this.selection.state.tab === "output");
177
204
  break;
178
205
  case "app.tasks.kill":
179
- this.stop();
206
+ this.requestStop();
180
207
  break;
181
208
  case "app.tasks.confirmStop":
182
- this.stop(true);
209
+ this.confirmStop();
183
210
  break;
184
211
  case "app.tasks.detachSelected": {
185
212
  const task = this.selection.selected;
186
- if (task?.mode === "foreground" &&
187
- !isTaskTerminal(task.status) &&
188
- task.status !== "stopping" &&
189
- this.options.host.enabled !== false) {
190
- this.feedback = this.options.host.detach?.(task.id)
213
+ // The core decides; a full background lane throws its own explanation, shown as feedback.
214
+ if (task?.mode === "foreground" && isStoppable(task)) {
215
+ this.feedback = this.options.host.detach(task.id)
191
216
  ? "Selected task moved to background; execution continues."
192
217
  : "This task cannot move to background.";
193
218
  }
194
219
  break;
195
220
  }
196
221
  case "app.tasks.help":
197
- this.help = this.help ? undefined : new TaskViewport();
222
+ this.setMode({ kind: "help", viewport: new TaskViewport() });
198
223
  break;
199
224
  }
200
225
  }
201
226
  move(direction, page = false) {
202
- if (this.help) {
203
- this.help.move(direction, page, false);
227
+ if (this.mode.kind === "help") {
228
+ this.mode.viewport.move(direction, page, false);
204
229
  return;
205
230
  }
206
231
  if (this.focus === "list") {
@@ -222,87 +247,95 @@ export class TasksMenu {
222
247
  return;
223
248
  this.sync();
224
249
  this.render(this.width);
225
- const kb = this.options.keybindings;
226
250
  this.feedback = undefined;
227
251
  try {
228
252
  if (this.layout?.tooSmall) {
229
253
  // The resize notice owns the screen; keys must not act on the hidden panel.
230
- // Cancel unwinds one transient state at a time, then closes.
231
- if (kb.matches(data, "tui.select.cancel")) {
232
- if (this.help)
233
- this.help = undefined;
234
- else if (this.searching)
235
- this.finishSearch(true);
236
- else if (this.pendingKill)
237
- this.clearKill();
238
- else {
239
- this.dispose();
240
- this.options.onClose();
241
- return;
242
- }
243
- }
244
- }
245
- else if (this.help) {
246
- if (kb.matches(data, "tui.select.cancel") || kb.matches(data, "app.tasks.help"))
247
- this.help = undefined;
248
- else if (kb.matches(data, "app.tasks.top") || kb.matches(data, "app.tasks.bottom"))
249
- this.help.jump(kb.matches(data, "app.tasks.bottom"), false);
250
- else if (kb.matches(data, "tui.select.up") || kb.matches(data, "tui.editor.pageUp"))
251
- this.help.move(-1, kb.matches(data, "tui.editor.pageUp"), false);
252
- else if (kb.matches(data, "tui.select.down") || kb.matches(data, "tui.editor.pageDown"))
253
- this.help.move(1, kb.matches(data, "tui.editor.pageDown"), false);
254
- }
255
- else if (this.searching) {
256
- if (kb.matches(data, "tui.select.cancel"))
257
- this.finishSearch(true);
258
- else if (kb.matches(data, "tui.select.confirm"))
259
- this.finishSearch(false);
260
- else if (kb.matches(data, "tui.select.up") || kb.matches(data, "tui.select.pageUp"))
261
- this.move(-1, kb.matches(data, "tui.select.pageUp"));
262
- else if (kb.matches(data, "tui.select.down") || kb.matches(data, "tui.select.pageDown"))
263
- this.move(1, kb.matches(data, "tui.select.pageDown"));
264
- else {
265
- this.search.handleInput(data);
266
- this.selection.query = this.search.getValue().slice(0, 512);
267
- this.selection.refresh();
268
- this.selectedChanged();
269
- }
270
- }
271
- else if (this.pendingKill) {
272
- if (kb.matches(data, "app.tasks.confirmStop"))
273
- this.stop(true);
274
- else if (kb.matches(data, "tui.select.cancel"))
275
- this.clearKill();
276
- }
277
- else if (kb.matches(data, "tui.select.cancel")) {
278
- this.dispose();
279
- this.options.onClose();
280
- return;
254
+ if (this.options.keybindings.matches(data, "tui.select.cancel"))
255
+ this.cancel();
281
256
  }
282
257
  else {
283
- const pageUp = kb.matches(data, this.focus === "list" ? "tui.select.pageUp" : "tui.editor.pageUp");
284
- const pageDown = kb.matches(data, this.focus === "list" ? "tui.select.pageDown" : "tui.editor.pageDown");
285
- if (pageUp || kb.matches(data, "tui.select.up"))
286
- this.move(-1, pageUp);
287
- else if (pageDown || kb.matches(data, "tui.select.down"))
288
- this.move(1, pageDown);
289
- else if (kb.matches(data, "tui.select.confirm")) {
290
- if (this.focus === "list" && this.selection.selected)
291
- this.focus = "inspector";
292
- }
293
- else {
294
- const key = actions.find((key) => kb.matches(data, key));
295
- if (key)
296
- this.action(key);
258
+ switch (this.mode.kind) {
259
+ case "help":
260
+ this.helpInput(this.mode.viewport, data);
261
+ break;
262
+ case "search":
263
+ this.searchInput(data);
264
+ break;
265
+ case "confirmStop":
266
+ this.confirmInput(data);
267
+ break;
268
+ case "browse":
269
+ this.browseInput(data);
270
+ break;
297
271
  }
298
272
  }
299
273
  }
300
274
  catch (error) {
301
275
  this.feedback = cleanTaskText(error instanceof Error ? error.message : String(error));
302
276
  }
277
+ if (this.disposed)
278
+ return;
303
279
  this.queueTick(true);
304
280
  this.options.tui.requestRender();
305
281
  }
282
+ helpInput(viewport, data) {
283
+ const kb = this.options.keybindings;
284
+ if (kb.matches(data, "tui.select.cancel") || kb.matches(data, "app.tasks.help"))
285
+ this.setMode(BROWSE);
286
+ else if (kb.matches(data, "app.tasks.top") || kb.matches(data, "app.tasks.bottom"))
287
+ viewport.jump(kb.matches(data, "app.tasks.bottom"), false);
288
+ else if (kb.matches(data, "tui.select.up") || kb.matches(data, "tui.editor.pageUp"))
289
+ viewport.move(-1, kb.matches(data, "tui.editor.pageUp"), false);
290
+ else if (kb.matches(data, "tui.select.down") || kb.matches(data, "tui.editor.pageDown"))
291
+ viewport.move(1, kb.matches(data, "tui.editor.pageDown"), false);
292
+ }
293
+ searchInput(data) {
294
+ const kb = this.options.keybindings;
295
+ if (kb.matches(data, "tui.select.cancel"))
296
+ this.cancel();
297
+ else if (kb.matches(data, "tui.select.confirm"))
298
+ this.finishSearch(false);
299
+ else if (kb.matches(data, "tui.select.up") || kb.matches(data, "tui.select.pageUp"))
300
+ this.move(-1, kb.matches(data, "tui.select.pageUp"));
301
+ else if (kb.matches(data, "tui.select.down") || kb.matches(data, "tui.select.pageDown"))
302
+ this.move(1, kb.matches(data, "tui.select.pageDown"));
303
+ else {
304
+ this.search.handleInput(data);
305
+ this.selection.query = this.search.getValue().slice(0, 512);
306
+ this.selection.refresh();
307
+ this.selectedChanged();
308
+ }
309
+ }
310
+ confirmInput(data) {
311
+ const kb = this.options.keybindings;
312
+ if (kb.matches(data, "app.tasks.confirmStop"))
313
+ this.confirmStop();
314
+ else if (kb.matches(data, "tui.select.cancel"))
315
+ this.cancel();
316
+ }
317
+ browseInput(data) {
318
+ const kb = this.options.keybindings;
319
+ if (kb.matches(data, "tui.select.cancel")) {
320
+ this.cancel();
321
+ return;
322
+ }
323
+ const pageUp = kb.matches(data, this.focus === "list" ? "tui.select.pageUp" : "tui.editor.pageUp");
324
+ const pageDown = kb.matches(data, this.focus === "list" ? "tui.select.pageDown" : "tui.editor.pageDown");
325
+ if (pageUp || kb.matches(data, "tui.select.up"))
326
+ this.move(-1, pageUp);
327
+ else if (pageDown || kb.matches(data, "tui.select.down"))
328
+ this.move(1, pageDown);
329
+ else if (kb.matches(data, "tui.select.confirm")) {
330
+ if (this.focus === "list" && this.selection.selected)
331
+ this.focus = "inspector";
332
+ }
333
+ else {
334
+ const key = actions.find((key) => kb.matches(data, key));
335
+ if (key)
336
+ this.action(key);
337
+ }
338
+ }
306
339
  handleMouse(event) {
307
340
  if (this.disposed || event.ctrl || event.alt || event.shift)
308
341
  return;
@@ -310,38 +343,32 @@ export class TasksMenu {
310
343
  this.feedback = undefined;
311
344
  this.render(event.width);
312
345
  const layout = this.layout;
346
+ const mode = this.mode;
313
347
  if (event.type === "wheel" && event.wheelDelta) {
314
- if (!this.pendingKill && !layout.tooSmall && event.y >= 2 && event.y < this.options.tui.terminal.rows - 3) {
348
+ if (mode.kind !== "confirmStop" &&
349
+ !layout.tooSmall &&
350
+ event.y >= 2 &&
351
+ event.y < this.options.tui.terminal.rows - 3) {
315
352
  const delta = Math.sign(event.wheelDelta) * Math.min(20, Math.abs(event.wheelDelta));
316
353
  const region = this.width >= 100 ? (event.x < layout.listWidth ? "list" : "inspector") : this.focus;
317
- if (this.help)
318
- this.help.move(delta, false, false);
354
+ if (mode.kind === "help")
355
+ mode.viewport.move(delta, false, false);
319
356
  else if (region === "list")
320
357
  this.list.scroll(delta);
321
- else if (!this.searching)
358
+ else if (mode.kind !== "search")
322
359
  this.inspector.position[this.selection.state.tab].move(delta, false, this.selection.state.tab === "output");
323
360
  }
324
361
  }
325
362
  else if (event.type === "click" && event.button === "left") {
326
363
  const hit = layout.hits.find((hit) => hit.y === event.y && event.x >= hit.x && event.x < hit.x + hit.width);
327
364
  try {
328
- if (hit?.cancel) {
329
- if (this.searching)
330
- this.finishSearch(true);
331
- else if (this.help)
332
- this.help = undefined;
333
- else if (this.pendingKill)
334
- this.clearKill();
335
- else {
336
- this.dispose();
337
- this.options.onClose();
338
- }
339
- }
365
+ if (hit?.cancel)
366
+ this.cancel();
340
367
  else if (hit?.taskId) {
341
368
  this.selection.select(hit.taskId);
342
369
  this.selectedChanged();
343
370
  this.focus = "list";
344
- if (this.searching)
371
+ if (mode.kind === "search")
345
372
  this.finishSearch(false);
346
373
  }
347
374
  else if (hit?.tab) {
@@ -353,9 +380,7 @@ export class TasksMenu {
353
380
  this.focus = "inspector";
354
381
  this.action(hit.key);
355
382
  }
356
- else if (!this.pendingKill &&
357
- !this.searching &&
358
- !this.help &&
383
+ else if (mode.kind === "browse" &&
359
384
  !layout.tooSmall &&
360
385
  event.y >= 1 &&
361
386
  event.y < this.options.tui.terminal.rows - 2 &&
@@ -384,14 +409,22 @@ export class TasksMenu {
384
409
  inspector: this.inspector,
385
410
  list: this.list,
386
411
  focus: this.focus,
387
- searchLine: this.searching ? (width) => this.search.render(width).join("") : undefined,
388
- pendingKill: this.pendingKill,
412
+ mode: this.mode,
413
+ searchLine: (width) => this.search.render(width).join(""),
389
414
  feedback: this.feedback,
390
- help: this.help,
391
- canDetach: this.options.host.enabled !== false && !!this.options.host.detach,
415
+ canDetach: (id) => this.canDetach(id),
392
416
  });
393
417
  return this.layout.lines;
394
418
  }
419
+ /** The panel's selection can lag the runtime by a notification; a task that is gone cannot move. */
420
+ canDetach(id) {
421
+ try {
422
+ return this.options.host.canDetach(id);
423
+ }
424
+ catch {
425
+ return false;
426
+ }
427
+ }
395
428
  dispose() {
396
429
  if (this.disposed)
397
430
  return;
@@ -399,7 +432,6 @@ export class TasksMenu {
399
432
  this.selection.state.closedAt = Date.now();
400
433
  clearInterval(this.pollTimer);
401
434
  clearInterval(this.animationTimer);
402
- this.clearKill();
403
435
  this.unsubscribe();
404
436
  this.inspector.dispose();
405
437
  }
@@ -1 +1 @@
1
- {"version":3,"file":"manager.js","sourceRoot":"","sources":["../../../../src/extensions/tasks/ui/manager.ts"],"names":[],"mappings":"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","sourcesContent":["/** Panel lifecycle and input routing; selection, output ownership and layout have separate owners. */\nimport \"../keybindings.ts\";\nimport {\n\ttype Component,\n\ttype Focusable,\n\tInput,\n\ttype TuiMouseEvent,\n\ttype TuiMouseEventResult,\n} from \"@earendil-works/pi-tui\";\nimport type { AppKeybinding, KeybindingsManager } from \"../../../core/keybindings.ts\";\nimport { isTaskTerminal, type TasksContext } from \"../../../core/tasks/types.ts\";\nimport { STATUS_SPINNER_INTERVAL_MS } from \"../../../modes/interactive/components/status-marker.ts\";\nimport type { Theme } from \"../../../modes/interactive/theme/theme.ts\";\nimport { TaskInspector } from \"./inspector.ts\";\nimport { renderTasksLayout, type TasksLayout } from \"./layout.ts\";\nimport { TaskList } from \"./list.ts\";\nimport { TaskSelection, type TasksPanelState } from \"./model.ts\";\nimport { cleanTaskText } from \"./text.ts\";\nimport { TaskViewport } from \"./viewport.ts\";\n\nexport type TasksManagerHost = Pick<TasksContext, \"list\" | \"read\" | \"kill\" | \"subscribe\" | \"retain\"> &\n\tPartial<Pick<TasksContext, \"detach\" | \"enabled\">>;\nexport interface TasksMenuOptions {\n\ttui: { requestRender(): void; terminal: { rows: number; columns: number } };\n\ttheme: Theme;\n\tkeybindings: Pick<KeybindingsManager, \"matches\" | \"getKeys\">;\n\thost: TasksManagerHost;\n\tstate?: TasksPanelState;\n\tonClose(): void;\n\tpollIntervalMs?: number;\n}\n\nconst actions: AppKeybinding[] = [\n\t\"app.tasks.search\",\n\t\"app.tasks.kill\",\n\t\"app.tasks.detachSelected\",\n\t\"app.tasks.previousTab\",\n\t\"app.tasks.nextTab\",\n\t\"app.tasks.follow\",\n\t\"app.tasks.top\",\n\t\"app.tasks.bottom\",\n\t\"app.tasks.nextFocus\",\n\t\"app.tasks.previousFocus\",\n\t\"app.tasks.help\",\n];\n\nexport class TasksMenu implements Component, Focusable {\n\tfocused = false;\n\tprivate readonly options: TasksMenuOptions;\n\tprivate readonly selection: TaskSelection;\n\tprivate readonly inspector: TaskInspector;\n\tprivate readonly list = new TaskList();\n\tprivate readonly search: Input;\n\tprivate readonly unsubscribe: () => void;\n\tprivate readonly pollTimer: ReturnType<typeof setInterval>;\n\tprivate animationTimer?: ReturnType<typeof setInterval>;\n\tprivate pendingKill?: string;\n\tprivate feedback?: string;\n\tprivate focus: \"list\" | \"inspector\" = \"list\";\n\tprivate searching = false;\n\tprivate beforeSearch?: { id?: string; focus: \"list\" | \"inspector\" };\n\tprivate help?: TaskViewport;\n\tprivate dirty = true;\n\tprivate tickQueued = false;\n\tprivate refreshQueued = false;\n\tprivate disposed = false;\n\tprivate width: number;\n\tprivate layout?: TasksLayout;\n\tconstructor(options: TasksMenuOptions) {\n\t\tthis.options = options;\n\t\tthis.width = options.tui.terminal.columns;\n\t\tthis.selection = new TaskSelection(options.state ?? { tab: \"output\" });\n\t\tthis.inspector = new TaskInspector({\n\t\t\thost: options.host,\n\t\t\ttheme: options.theme,\n\t\t\trequestRender: () => options.tui.requestRender(),\n\t\t});\n\t\tthis.search = new Input({ prompt: \"Find task: \", placeholder: \"title, command, kind or ID\" });\n\t\tthis.sync();\n\t\tthis.selection.selectStartedSinceClose();\n\t\tthis.inspector.select(this.selection.selected);\n\t\tthis.list.showSelection();\n\t\tthis.unsubscribe = options.host.subscribe(() => {\n\t\t\tthis.dirty = true;\n\t\t\tthis.queueTick();\n\t\t\toptions.tui.requestRender();\n\t\t});\n\t\tthis.pollTimer = setInterval(() => {\n\t\t\tthis.queueTick(true);\n\t\t\tif (this.selection.activeCount) options.tui.requestRender();\n\t\t}, options.pollIntervalMs ?? 1000);\n\t\tthis.pollTimer.unref?.();\n\t\tthis.queueTick(true);\n\t}\n\tprivate sync(): void {\n\t\tif (this.disposed || !this.dirty) return;\n\t\tthis.dirty = false;\n\t\tconst previous = this.selection.selected;\n\t\tthis.selection.sync(this.options.host.list());\n\t\tthis.inspector.select(this.selection.selected);\n\t\tthis.inspector.prune(new Set(this.selection.all.map((task) => task.id)));\n\t\tconst selected = this.selection.selected;\n\t\tif (selected && isTaskTerminal(selected.status) && previous && !isTaskTerminal(previous.status))\n\t\t\tthis.feedback = undefined;\n\t\tif (this.pendingKill && (this.pendingKill !== selected?.id || (selected && isTaskTerminal(selected.status))))\n\t\t\tthis.clearKill();\n\t\tconst animates = this.selection.all.some((task) => task.status === \"running\");\n\t\tif (animates && !this.animationTimer) {\n\t\t\tthis.animationTimer = setInterval(() => this.options.tui.requestRender(), STATUS_SPINNER_INTERVAL_MS);\n\t\t\tthis.animationTimer.unref?.();\n\t\t} else if (!animates) {\n\t\t\tclearInterval(this.animationTimer);\n\t\t\tthis.animationTimer = undefined;\n\t\t}\n\t}\n\tprivate queueTick(refresh = false): void {\n\t\tif (this.disposed) return;\n\t\tthis.refreshQueued ||= refresh;\n\t\tif (this.tickQueued) return;\n\t\tthis.tickQueued = true;\n\t\tvoid Promise.resolve()\n\t\t\t.then(async () => {\n\t\t\t\tthis.tickQueued = false;\n\t\t\t\tif (this.disposed) return;\n\t\t\t\tconst refresh = this.refreshQueued;\n\t\t\t\tthis.refreshQueued = false;\n\t\t\t\tthis.sync();\n\t\t\t\tif (refresh || (this.inspector.task && isTaskTerminal(this.inspector.task.status)))\n\t\t\t\t\tawait this.inspector.refresh();\n\t\t\t})\n\t\t\t.catch(() => {\n\t\t\t\t/* Task observers cannot reject execution. */\n\t\t\t});\n\t}\n\tinvalidate(): void {\n\t\tthis.inspector.invalidate();\n\t}\n\tprivate clearKill(): void {\n\t\tthis.pendingKill = undefined;\n\t}\n\tprivate selectedChanged(): void {\n\t\tthis.clearKill();\n\t\tthis.list.showSelection();\n\t\tthis.inspector.select(this.selection.selected);\n\t\tthis.queueTick(true);\n\t}\n\tprivate stop(confirm = false): void {\n\t\tconst task = this.selection.selected;\n\t\tif (confirm) {\n\t\t\tconst id = this.pendingKill;\n\t\t\tthis.clearKill();\n\t\t\tif (!id || id !== task?.id || isTaskTerminal(task.status)) return;\n\t\t\tthis.feedback = this.options.host.kill(id)\n\t\t\t\t? \"Cancellation requested; waiting for cleanup.\"\n\t\t\t\t: \"No new cancellation requested.\";\n\t\t} else if (task && !isTaskTerminal(task.status) && task.status !== \"stopping\") {\n\t\t\tthis.pendingKill = task.id;\n\t\t}\n\t}\n\tprivate finishSearch(cancel: boolean): void {\n\t\tconst id = cancel ? this.beforeSearch?.id : this.selection.state.selectedId;\n\t\tif (!cancel && !id) return;\n\t\tthis.focus = cancel ? (this.beforeSearch?.focus ?? \"list\") : \"list\";\n\t\tthis.searching = false;\n\t\tthis.search.focused = false;\n\t\tthis.selection.query = \"\";\n\t\tthis.selection.select(id);\n\t\tthis.beforeSearch = undefined;\n\t\tthis.selectedChanged();\n\t}\n\tprivate action(key: AppKeybinding): void {\n\t\tswitch (key) {\n\t\t\tcase \"app.tasks.search\":\n\t\t\t\tthis.beforeSearch = { id: this.selection.state.selectedId, focus: this.focus };\n\t\t\t\tthis.focus = \"list\";\n\t\t\t\tthis.searching = true;\n\t\t\t\tthis.search.focused = true;\n\t\t\t\tthis.search.setValue(\"\");\n\t\t\t\tbreak;\n\t\t\tcase \"app.tasks.previousTab\":\n\t\t\tcase \"app.tasks.nextTab\":\n\t\t\t\tif (this.focus === \"inspector\")\n\t\t\t\t\tthis.selection.state.tab = key === \"app.tasks.previousTab\" ? \"output\" : \"info\";\n\t\t\t\tbreak;\n\t\t\tcase \"app.tasks.nextFocus\":\n\t\t\tcase \"app.tasks.previousFocus\":\n\t\t\t\tthis.focus = this.focus === \"list\" ? \"inspector\" : \"list\";\n\t\t\t\tbreak;\n\t\t\tcase \"app.tasks.follow\":\n\t\t\t\tif (this.focus === \"inspector\" && this.selection.state.tab === \"output\") {\n\t\t\t\t\tthis.inspector.position.output.jump(true, true);\n\t\t\t\t\tthis.queueTick(true);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"app.tasks.top\":\n\t\t\tcase \"app.tasks.bottom\":\n\t\t\t\tif (this.focus === \"list\") {\n\t\t\t\t\tthis.selection.select(\n\t\t\t\t\t\tkey === \"app.tasks.top\" ? this.selection.rows[0]?.id : this.selection.rows.at(-1)?.id,\n\t\t\t\t\t);\n\t\t\t\t\tthis.selectedChanged();\n\t\t\t\t} else\n\t\t\t\t\tthis.inspector.position[this.selection.state.tab].jump(\n\t\t\t\t\t\tkey === \"app.tasks.bottom\",\n\t\t\t\t\t\tthis.selection.state.tab === \"output\",\n\t\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"app.tasks.kill\":\n\t\t\t\tthis.stop();\n\t\t\t\tbreak;\n\t\t\tcase \"app.tasks.confirmStop\":\n\t\t\t\tthis.stop(true);\n\t\t\t\tbreak;\n\t\t\tcase \"app.tasks.detachSelected\": {\n\t\t\t\tconst task = this.selection.selected;\n\t\t\t\tif (\n\t\t\t\t\ttask?.mode === \"foreground\" &&\n\t\t\t\t\t!isTaskTerminal(task.status) &&\n\t\t\t\t\ttask.status !== \"stopping\" &&\n\t\t\t\t\tthis.options.host.enabled !== false\n\t\t\t\t) {\n\t\t\t\t\tthis.feedback = this.options.host.detach?.(task.id)\n\t\t\t\t\t\t? \"Selected task moved to background; execution continues.\"\n\t\t\t\t\t\t: \"This task cannot move to background.\";\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"app.tasks.help\":\n\t\t\t\tthis.help = this.help ? undefined : new TaskViewport();\n\t\t\t\tbreak;\n\t\t}\n\t}\n\tprivate move(direction: number, page = false): void {\n\t\tif (this.help) {\n\t\t\tthis.help.move(direction, page, false);\n\t\t\treturn;\n\t\t}\n\t\tif (this.focus === \"list\") {\n\t\t\tconst rows = this.selection.rows;\n\t\t\tif (!rows.length) return;\n\t\t\tconst index = rows.findIndex((task) => task.id === this.selection.state.selectedId);\n\t\t\tconst next = page\n\t\t\t\t? Math.max(0, Math.min(rows.length - 1, index + direction * (this.layout?.listPageSize ?? 1)))\n\t\t\t\t: (index + direction + rows.length) % rows.length;\n\t\t\tthis.selection.select(rows[next]?.id);\n\t\t\tthis.selectedChanged();\n\t\t} else\n\t\t\tthis.inspector.position[this.selection.state.tab].move(direction, page, this.selection.state.tab === \"output\");\n\t}\n\thandleInput(data: string): void {\n\t\tif (this.disposed) return;\n\t\tthis.sync();\n\t\tthis.render(this.width);\n\t\tconst kb = this.options.keybindings;\n\t\tthis.feedback = undefined;\n\t\ttry {\n\t\t\tif (this.layout?.tooSmall) {\n\t\t\t\t// The resize notice owns the screen; keys must not act on the hidden panel.\n\t\t\t\t// Cancel unwinds one transient state at a time, then closes.\n\t\t\t\tif (kb.matches(data, \"tui.select.cancel\")) {\n\t\t\t\t\tif (this.help) this.help = undefined;\n\t\t\t\t\telse if (this.searching) this.finishSearch(true);\n\t\t\t\t\telse if (this.pendingKill) this.clearKill();\n\t\t\t\t\telse {\n\t\t\t\t\t\tthis.dispose();\n\t\t\t\t\t\tthis.options.onClose();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (this.help) {\n\t\t\t\tif (kb.matches(data, \"tui.select.cancel\") || kb.matches(data, \"app.tasks.help\")) this.help = undefined;\n\t\t\t\telse if (kb.matches(data, \"app.tasks.top\") || kb.matches(data, \"app.tasks.bottom\"))\n\t\t\t\t\tthis.help.jump(kb.matches(data, \"app.tasks.bottom\"), false);\n\t\t\t\telse if (kb.matches(data, \"tui.select.up\") || kb.matches(data, \"tui.editor.pageUp\"))\n\t\t\t\t\tthis.help.move(-1, kb.matches(data, \"tui.editor.pageUp\"), false);\n\t\t\t\telse if (kb.matches(data, \"tui.select.down\") || kb.matches(data, \"tui.editor.pageDown\"))\n\t\t\t\t\tthis.help.move(1, kb.matches(data, \"tui.editor.pageDown\"), false);\n\t\t\t} else if (this.searching) {\n\t\t\t\tif (kb.matches(data, \"tui.select.cancel\")) this.finishSearch(true);\n\t\t\t\telse if (kb.matches(data, \"tui.select.confirm\")) this.finishSearch(false);\n\t\t\t\telse if (kb.matches(data, \"tui.select.up\") || kb.matches(data, \"tui.select.pageUp\"))\n\t\t\t\t\tthis.move(-1, kb.matches(data, \"tui.select.pageUp\"));\n\t\t\t\telse if (kb.matches(data, \"tui.select.down\") || kb.matches(data, \"tui.select.pageDown\"))\n\t\t\t\t\tthis.move(1, kb.matches(data, \"tui.select.pageDown\"));\n\t\t\t\telse {\n\t\t\t\t\tthis.search.handleInput(data);\n\t\t\t\t\tthis.selection.query = this.search.getValue().slice(0, 512);\n\t\t\t\t\tthis.selection.refresh();\n\t\t\t\t\tthis.selectedChanged();\n\t\t\t\t}\n\t\t\t} else if (this.pendingKill) {\n\t\t\t\tif (kb.matches(data, \"app.tasks.confirmStop\")) this.stop(true);\n\t\t\t\telse if (kb.matches(data, \"tui.select.cancel\")) this.clearKill();\n\t\t\t} else if (kb.matches(data, \"tui.select.cancel\")) {\n\t\t\t\tthis.dispose();\n\t\t\t\tthis.options.onClose();\n\t\t\t\treturn;\n\t\t\t} else {\n\t\t\t\tconst pageUp = kb.matches(data, this.focus === \"list\" ? \"tui.select.pageUp\" : \"tui.editor.pageUp\");\n\t\t\t\tconst pageDown = kb.matches(data, this.focus === \"list\" ? \"tui.select.pageDown\" : \"tui.editor.pageDown\");\n\t\t\t\tif (pageUp || kb.matches(data, \"tui.select.up\")) this.move(-1, pageUp);\n\t\t\t\telse if (pageDown || kb.matches(data, \"tui.select.down\")) this.move(1, pageDown);\n\t\t\t\telse if (kb.matches(data, \"tui.select.confirm\")) {\n\t\t\t\t\tif (this.focus === \"list\" && this.selection.selected) this.focus = \"inspector\";\n\t\t\t\t} else {\n\t\t\t\t\tconst key = actions.find((key) => kb.matches(data, key));\n\t\t\t\t\tif (key) this.action(key);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tthis.feedback = cleanTaskText(error instanceof Error ? error.message : String(error));\n\t\t}\n\t\tthis.queueTick(true);\n\t\tthis.options.tui.requestRender();\n\t}\n\thandleMouse(event: TuiMouseEvent): TuiMouseEventResult | undefined {\n\t\tif (this.disposed || event.ctrl || event.alt || event.shift) return;\n\t\t// Feedback is transient: a click retracts it and acts, exactly like a keypress does.\n\t\tthis.feedback = undefined;\n\t\tthis.render(event.width);\n\t\tconst layout = this.layout!;\n\t\tif (event.type === \"wheel\" && event.wheelDelta) {\n\t\t\tif (!this.pendingKill && !layout.tooSmall && event.y >= 2 && event.y < this.options.tui.terminal.rows - 3) {\n\t\t\t\tconst delta = Math.sign(event.wheelDelta) * Math.min(20, Math.abs(event.wheelDelta));\n\t\t\t\tconst region = this.width >= 100 ? (event.x < layout.listWidth ? \"list\" : \"inspector\") : this.focus;\n\t\t\t\tif (this.help) this.help.move(delta, false, false);\n\t\t\t\telse if (region === \"list\") this.list.scroll(delta);\n\t\t\t\telse if (!this.searching)\n\t\t\t\t\tthis.inspector.position[this.selection.state.tab].move(\n\t\t\t\t\t\tdelta,\n\t\t\t\t\t\tfalse,\n\t\t\t\t\t\tthis.selection.state.tab === \"output\",\n\t\t\t\t\t);\n\t\t\t}\n\t\t} else if (event.type === \"click\" && event.button === \"left\") {\n\t\t\tconst hit = layout.hits.find((hit) => hit.y === event.y && event.x >= hit.x && event.x < hit.x + hit.width);\n\t\t\ttry {\n\t\t\t\tif (hit?.cancel) {\n\t\t\t\t\tif (this.searching) this.finishSearch(true);\n\t\t\t\t\telse if (this.help) this.help = undefined;\n\t\t\t\t\telse if (this.pendingKill) this.clearKill();\n\t\t\t\t\telse {\n\t\t\t\t\t\tthis.dispose();\n\t\t\t\t\t\tthis.options.onClose();\n\t\t\t\t\t}\n\t\t\t\t} else if (hit?.taskId) {\n\t\t\t\t\tthis.selection.select(hit.taskId);\n\t\t\t\t\tthis.selectedChanged();\n\t\t\t\t\tthis.focus = \"list\";\n\t\t\t\t\tif (this.searching) this.finishSearch(false);\n\t\t\t\t} else if (hit?.tab) {\n\t\t\t\t\tthis.focus = \"inspector\";\n\t\t\t\t\tthis.selection.state.tab = hit.tab;\n\t\t\t\t} else if (hit?.key) {\n\t\t\t\t\tif (hit.key === \"app.tasks.follow\") this.focus = \"inspector\";\n\t\t\t\t\tthis.action(hit.key);\n\t\t\t\t} else if (\n\t\t\t\t\t!this.pendingKill &&\n\t\t\t\t\t!this.searching &&\n\t\t\t\t\t!this.help &&\n\t\t\t\t\t!layout.tooSmall &&\n\t\t\t\t\tevent.y >= 1 &&\n\t\t\t\t\tevent.y < this.options.tui.terminal.rows - 2 &&\n\t\t\t\t\tthis.width >= 100\n\t\t\t\t)\n\t\t\t\t\tthis.focus = event.x < layout.listWidth ? \"list\" : \"inspector\";\n\t\t\t} catch (error) {\n\t\t\t\tthis.feedback = cleanTaskText(error instanceof Error ? error.message : String(error));\n\t\t\t}\n\t\t} else return;\n\t\tthis.queueTick(true);\n\t\tthis.options.tui.requestRender();\n\t\treturn { handled: true, focus: event.type === \"click\" };\n\t}\n\trender(width: number): string[] {\n\t\tthis.width = width;\n\t\tthis.sync();\n\t\tthis.layout = renderTasksLayout({\n\t\t\twidth,\n\t\t\theight: this.options.tui.terminal.rows,\n\t\t\ttheme: this.options.theme,\n\t\t\tkeybindings: this.options.keybindings,\n\t\t\tselection: this.selection,\n\t\t\tinspector: this.inspector,\n\t\t\tlist: this.list,\n\t\t\tfocus: this.focus,\n\t\t\tsearchLine: this.searching ? (width) => this.search.render(width).join(\"\") : undefined,\n\t\t\tpendingKill: this.pendingKill,\n\t\t\tfeedback: this.feedback,\n\t\t\thelp: this.help,\n\t\t\tcanDetach: this.options.host.enabled !== false && !!this.options.host.detach,\n\t\t});\n\t\treturn this.layout.lines;\n\t}\n\tdispose(): void {\n\t\tif (this.disposed) return;\n\t\tthis.disposed = true;\n\t\tthis.selection.state.closedAt = Date.now();\n\t\tclearInterval(this.pollTimer);\n\t\tclearInterval(this.animationTimer);\n\t\tthis.clearKill();\n\t\tthis.unsubscribe();\n\t\tthis.inspector.dispose();\n\t}\n}\n"]}
1
+ {"version":3,"file":"manager.js","sourceRoot":"","sources":["../../../../src/extensions/tasks/ui/manager.ts"],"names":[],"mappings":"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","sourcesContent":["/** Panel lifecycle and input routing; selection, output ownership and layout have separate owners. */\nimport \"../keybindings.ts\";\nimport {\n\ttype Component,\n\ttype Focusable,\n\tInput,\n\ttype TuiMouseEvent,\n\ttype TuiMouseEventResult,\n} from \"@earendil-works/pi-tui\";\nimport type { AppKeybinding, KeybindingsManager } from \"../../../core/keybindings.ts\";\nimport { isTaskTerminal, type TasksContext } from \"../../../core/tasks/types.ts\";\nimport { STATUS_SPINNER_INTERVAL_MS } from \"../../../modes/interactive/components/status-marker.ts\";\nimport type { Theme } from \"../../../modes/interactive/theme/theme.ts\";\nimport { TaskInspector } from \"./inspector.ts\";\nimport { renderTasksLayout, type TasksLayout } from \"./layout.ts\";\nimport { TaskList } from \"./list.ts\";\nimport { isStoppable, type PanelFocus, type PanelMode, TaskSelection, type TasksPanelState } from \"./model.ts\";\nimport { cleanTaskText } from \"./text.ts\";\nimport { TaskViewport } from \"./viewport.ts\";\n\nexport type TasksManagerHost = Pick<\n\tTasksContext,\n\t\"list\" | \"read\" | \"kill\" | \"subscribe\" | \"retain\" | \"canDetach\" | \"detach\"\n>;\nexport interface TasksMenuOptions {\n\ttui: { requestRender(): void; terminal: { rows: number; columns: number } };\n\ttheme: Theme;\n\tkeybindings: Pick<KeybindingsManager, \"matches\" | \"getKeys\">;\n\thost: TasksManagerHost;\n\tstate?: TasksPanelState;\n\tonClose(): void;\n\tpollIntervalMs?: number;\n}\n\nconst BROWSE: PanelMode = { kind: \"browse\" };\nconst actions: AppKeybinding[] = [\n\t\"app.tasks.search\",\n\t\"app.tasks.kill\",\n\t\"app.tasks.detachSelected\",\n\t\"app.tasks.previousTab\",\n\t\"app.tasks.nextTab\",\n\t\"app.tasks.follow\",\n\t\"app.tasks.top\",\n\t\"app.tasks.bottom\",\n\t\"app.tasks.nextFocus\",\n\t\"app.tasks.previousFocus\",\n\t\"app.tasks.help\",\n];\n\nexport class TasksMenu implements Component, Focusable {\n\tfocused = false;\n\tprivate readonly options: TasksMenuOptions;\n\tprivate readonly selection: TaskSelection;\n\tprivate readonly inspector: TaskInspector;\n\tprivate readonly list = new TaskList();\n\tprivate readonly search: Input;\n\tprivate readonly unsubscribe: () => void;\n\tprivate readonly pollTimer: ReturnType<typeof setInterval>;\n\tprivate animationTimer?: ReturnType<typeof setInterval>;\n\tprivate mode: PanelMode = BROWSE;\n\tprivate feedback?: string;\n\tprivate focus: PanelFocus = \"list\";\n\tprivate dirty = true;\n\tprivate tickQueued = false;\n\tprivate refreshQueued = false;\n\tprivate disposed = false;\n\tprivate width: number;\n\tprivate layout?: TasksLayout;\n\tconstructor(options: TasksMenuOptions) {\n\t\tthis.options = options;\n\t\tthis.width = options.tui.terminal.columns;\n\t\tthis.selection = new TaskSelection(options.state ?? { tab: \"output\" });\n\t\tthis.inspector = new TaskInspector({\n\t\t\thost: options.host,\n\t\t\ttheme: options.theme,\n\t\t\trequestRender: () => options.tui.requestRender(),\n\t\t});\n\t\tthis.search = new Input({ prompt: \"Find task: \", placeholder: \"title, command, kind or ID\" });\n\t\tthis.sync();\n\t\tthis.selection.selectStartedSinceClose();\n\t\tthis.inspector.select(this.selection.selected);\n\t\tthis.list.showSelection();\n\t\tthis.unsubscribe = options.host.subscribe(() => {\n\t\t\tthis.dirty = true;\n\t\t\tthis.queueTick();\n\t\t\toptions.tui.requestRender();\n\t\t});\n\t\tthis.pollTimer = setInterval(() => {\n\t\t\tthis.queueTick(true);\n\t\t\tif (this.selection.activeCount) options.tui.requestRender();\n\t\t}, options.pollIntervalMs ?? 1000);\n\t\tthis.pollTimer.unref?.();\n\t\tthis.queueTick(true);\n\t}\n\tprivate sync(): void {\n\t\tif (this.disposed || !this.dirty) return;\n\t\tthis.dirty = false;\n\t\tconst previous = this.selection.selected;\n\t\tthis.selection.sync(this.options.host.list());\n\t\tthis.inspector.select(this.selection.selected);\n\t\tthis.inspector.prune(new Set(this.selection.all.map((task) => task.id)));\n\t\tconst selected = this.selection.selected;\n\t\tif (selected && isTaskTerminal(selected.status) && previous && !isTaskTerminal(previous.status))\n\t\t\tthis.feedback = undefined;\n\t\tif (this.mode.kind === \"confirmStop\" && (this.mode.taskId !== selected?.id || isTaskTerminal(selected.status)))\n\t\t\tthis.setMode(BROWSE);\n\t\tconst animates = this.selection.all.some((task) => task.status === \"running\");\n\t\tif (animates && !this.animationTimer) {\n\t\t\tthis.animationTimer = setInterval(() => this.options.tui.requestRender(), STATUS_SPINNER_INTERVAL_MS);\n\t\t\tthis.animationTimer.unref?.();\n\t\t} else if (!animates) {\n\t\t\tclearInterval(this.animationTimer);\n\t\t\tthis.animationTimer = undefined;\n\t\t}\n\t}\n\tprivate queueTick(refresh = false): void {\n\t\tif (this.disposed) return;\n\t\tthis.refreshQueued ||= refresh;\n\t\tif (this.tickQueued) return;\n\t\tthis.tickQueued = true;\n\t\tvoid Promise.resolve()\n\t\t\t.then(async () => {\n\t\t\t\tthis.tickQueued = false;\n\t\t\t\tif (this.disposed) return;\n\t\t\t\tconst refresh = this.refreshQueued;\n\t\t\t\tthis.refreshQueued = false;\n\t\t\t\tthis.sync();\n\t\t\t\tif (refresh || (this.inspector.task && isTaskTerminal(this.inspector.task.status)))\n\t\t\t\t\tawait this.inspector.refresh();\n\t\t\t})\n\t\t\t.catch(() => {\n\t\t\t\t/* Task observers cannot reject execution. */\n\t\t\t});\n\t}\n\tinvalidate(): void {\n\t\tthis.inspector.invalidate();\n\t}\n\t/** The one place the mode changes; the search input is focused exactly while searching. */\n\tprivate setMode(next: PanelMode): void {\n\t\tthis.mode = next;\n\t\tthis.search.focused = next.kind === \"search\";\n\t}\n\t/** Unwinds exactly one transient layer; from plain browsing it closes the panel. */\n\tprivate cancel(): void {\n\t\tswitch (this.mode.kind) {\n\t\t\tcase \"search\":\n\t\t\t\tthis.finishSearch(true);\n\t\t\t\tbreak;\n\t\t\tcase \"help\":\n\t\t\tcase \"confirmStop\":\n\t\t\t\tthis.setMode(BROWSE);\n\t\t\t\tbreak;\n\t\t\tcase \"browse\":\n\t\t\t\tthis.close();\n\t\t\t\tbreak;\n\t\t}\n\t}\n\tprivate close(): void {\n\t\tthis.dispose();\n\t\tthis.options.onClose();\n\t}\n\tprivate selectedChanged(): void {\n\t\tif (this.mode.kind === \"confirmStop\") this.setMode(BROWSE);\n\t\tthis.list.showSelection();\n\t\tthis.inspector.select(this.selection.selected);\n\t\tthis.queueTick(true);\n\t}\n\tprivate requestStop(): void {\n\t\tconst task = this.selection.selected;\n\t\tif (task && isStoppable(task)) this.setMode({ kind: \"confirmStop\", taskId: task.id });\n\t}\n\tprivate confirmStop(): void {\n\t\tconst mode = this.mode;\n\t\tif (mode.kind !== \"confirmStop\") return;\n\t\tthis.setMode(BROWSE);\n\t\tconst task = this.selection.selected;\n\t\tif (mode.taskId !== task?.id || isTaskTerminal(task.status)) return;\n\t\tthis.feedback = this.options.host.kill(mode.taskId)\n\t\t\t? \"Cancellation requested; waiting for cleanup.\"\n\t\t\t: \"No new cancellation requested.\";\n\t}\n\tprivate startSearch(): void {\n\t\tthis.setMode({ kind: \"search\", restore: { id: this.selection.state.selectedId, focus: this.focus } });\n\t\tthis.focus = \"list\";\n\t\tthis.search.setValue(\"\");\n\t}\n\tprivate finishSearch(cancel: boolean): void {\n\t\tconst mode = this.mode;\n\t\tif (mode.kind !== \"search\") return;\n\t\tconst id = cancel ? mode.restore.id : this.selection.state.selectedId;\n\t\tif (!cancel && !id) return;\n\t\tthis.focus = cancel ? mode.restore.focus : \"list\";\n\t\tthis.setMode(BROWSE);\n\t\tthis.selection.query = \"\";\n\t\tthis.selection.select(id);\n\t\tthis.selectedChanged();\n\t}\n\tprivate action(key: AppKeybinding): void {\n\t\tswitch (key) {\n\t\t\tcase \"app.tasks.search\":\n\t\t\t\tthis.startSearch();\n\t\t\t\tbreak;\n\t\t\tcase \"app.tasks.previousTab\":\n\t\t\tcase \"app.tasks.nextTab\":\n\t\t\t\tif (this.focus === \"inspector\")\n\t\t\t\t\tthis.selection.state.tab = key === \"app.tasks.previousTab\" ? \"output\" : \"info\";\n\t\t\t\tbreak;\n\t\t\tcase \"app.tasks.nextFocus\":\n\t\t\tcase \"app.tasks.previousFocus\":\n\t\t\t\tthis.focus = this.focus === \"list\" ? \"inspector\" : \"list\";\n\t\t\t\tbreak;\n\t\t\tcase \"app.tasks.follow\":\n\t\t\t\tif (this.focus === \"inspector\" && this.selection.state.tab === \"output\") {\n\t\t\t\t\tthis.inspector.position.output.jump(true, true);\n\t\t\t\t\tthis.queueTick(true);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"app.tasks.top\":\n\t\t\tcase \"app.tasks.bottom\":\n\t\t\t\tif (this.focus === \"list\") {\n\t\t\t\t\tthis.selection.select(\n\t\t\t\t\t\tkey === \"app.tasks.top\" ? this.selection.rows[0]?.id : this.selection.rows.at(-1)?.id,\n\t\t\t\t\t);\n\t\t\t\t\tthis.selectedChanged();\n\t\t\t\t} else\n\t\t\t\t\tthis.inspector.position[this.selection.state.tab].jump(\n\t\t\t\t\t\tkey === \"app.tasks.bottom\",\n\t\t\t\t\t\tthis.selection.state.tab === \"output\",\n\t\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"app.tasks.kill\":\n\t\t\t\tthis.requestStop();\n\t\t\t\tbreak;\n\t\t\tcase \"app.tasks.confirmStop\":\n\t\t\t\tthis.confirmStop();\n\t\t\t\tbreak;\n\t\t\tcase \"app.tasks.detachSelected\": {\n\t\t\t\tconst task = this.selection.selected;\n\t\t\t\t// The core decides; a full background lane throws its own explanation, shown as feedback.\n\t\t\t\tif (task?.mode === \"foreground\" && isStoppable(task)) {\n\t\t\t\t\tthis.feedback = this.options.host.detach(task.id)\n\t\t\t\t\t\t? \"Selected task moved to background; execution continues.\"\n\t\t\t\t\t\t: \"This task cannot move to background.\";\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"app.tasks.help\":\n\t\t\t\tthis.setMode({ kind: \"help\", viewport: new TaskViewport() });\n\t\t\t\tbreak;\n\t\t}\n\t}\n\tprivate move(direction: number, page = false): void {\n\t\tif (this.mode.kind === \"help\") {\n\t\t\tthis.mode.viewport.move(direction, page, false);\n\t\t\treturn;\n\t\t}\n\t\tif (this.focus === \"list\") {\n\t\t\tconst rows = this.selection.rows;\n\t\t\tif (!rows.length) return;\n\t\t\tconst index = rows.findIndex((task) => task.id === this.selection.state.selectedId);\n\t\t\tconst next = page\n\t\t\t\t? Math.max(0, Math.min(rows.length - 1, index + direction * (this.layout?.listPageSize ?? 1)))\n\t\t\t\t: (index + direction + rows.length) % rows.length;\n\t\t\tthis.selection.select(rows[next]?.id);\n\t\t\tthis.selectedChanged();\n\t\t} else\n\t\t\tthis.inspector.position[this.selection.state.tab].move(direction, page, this.selection.state.tab === \"output\");\n\t}\n\thandleInput(data: string): void {\n\t\tif (this.disposed) return;\n\t\tthis.sync();\n\t\tthis.render(this.width);\n\t\tthis.feedback = undefined;\n\t\ttry {\n\t\t\tif (this.layout?.tooSmall) {\n\t\t\t\t// The resize notice owns the screen; keys must not act on the hidden panel.\n\t\t\t\tif (this.options.keybindings.matches(data, \"tui.select.cancel\")) this.cancel();\n\t\t\t} else {\n\t\t\t\tswitch (this.mode.kind) {\n\t\t\t\t\tcase \"help\":\n\t\t\t\t\t\tthis.helpInput(this.mode.viewport, data);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"search\":\n\t\t\t\t\t\tthis.searchInput(data);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"confirmStop\":\n\t\t\t\t\t\tthis.confirmInput(data);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"browse\":\n\t\t\t\t\t\tthis.browseInput(data);\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tthis.feedback = cleanTaskText(error instanceof Error ? error.message : String(error));\n\t\t}\n\t\tif (this.disposed) return;\n\t\tthis.queueTick(true);\n\t\tthis.options.tui.requestRender();\n\t}\n\tprivate helpInput(viewport: TaskViewport, data: string): void {\n\t\tconst kb = this.options.keybindings;\n\t\tif (kb.matches(data, \"tui.select.cancel\") || kb.matches(data, \"app.tasks.help\")) this.setMode(BROWSE);\n\t\telse if (kb.matches(data, \"app.tasks.top\") || kb.matches(data, \"app.tasks.bottom\"))\n\t\t\tviewport.jump(kb.matches(data, \"app.tasks.bottom\"), false);\n\t\telse if (kb.matches(data, \"tui.select.up\") || kb.matches(data, \"tui.editor.pageUp\"))\n\t\t\tviewport.move(-1, kb.matches(data, \"tui.editor.pageUp\"), false);\n\t\telse if (kb.matches(data, \"tui.select.down\") || kb.matches(data, \"tui.editor.pageDown\"))\n\t\t\tviewport.move(1, kb.matches(data, \"tui.editor.pageDown\"), false);\n\t}\n\tprivate searchInput(data: string): void {\n\t\tconst kb = this.options.keybindings;\n\t\tif (kb.matches(data, \"tui.select.cancel\")) this.cancel();\n\t\telse if (kb.matches(data, \"tui.select.confirm\")) this.finishSearch(false);\n\t\telse if (kb.matches(data, \"tui.select.up\") || kb.matches(data, \"tui.select.pageUp\"))\n\t\t\tthis.move(-1, kb.matches(data, \"tui.select.pageUp\"));\n\t\telse if (kb.matches(data, \"tui.select.down\") || kb.matches(data, \"tui.select.pageDown\"))\n\t\t\tthis.move(1, kb.matches(data, \"tui.select.pageDown\"));\n\t\telse {\n\t\t\tthis.search.handleInput(data);\n\t\t\tthis.selection.query = this.search.getValue().slice(0, 512);\n\t\t\tthis.selection.refresh();\n\t\t\tthis.selectedChanged();\n\t\t}\n\t}\n\tprivate confirmInput(data: string): void {\n\t\tconst kb = this.options.keybindings;\n\t\tif (kb.matches(data, \"app.tasks.confirmStop\")) this.confirmStop();\n\t\telse if (kb.matches(data, \"tui.select.cancel\")) this.cancel();\n\t}\n\tprivate browseInput(data: string): void {\n\t\tconst kb = this.options.keybindings;\n\t\tif (kb.matches(data, \"tui.select.cancel\")) {\n\t\t\tthis.cancel();\n\t\t\treturn;\n\t\t}\n\t\tconst pageUp = kb.matches(data, this.focus === \"list\" ? \"tui.select.pageUp\" : \"tui.editor.pageUp\");\n\t\tconst pageDown = kb.matches(data, this.focus === \"list\" ? \"tui.select.pageDown\" : \"tui.editor.pageDown\");\n\t\tif (pageUp || kb.matches(data, \"tui.select.up\")) this.move(-1, pageUp);\n\t\telse if (pageDown || kb.matches(data, \"tui.select.down\")) this.move(1, pageDown);\n\t\telse if (kb.matches(data, \"tui.select.confirm\")) {\n\t\t\tif (this.focus === \"list\" && this.selection.selected) this.focus = \"inspector\";\n\t\t} else {\n\t\t\tconst key = actions.find((key) => kb.matches(data, key));\n\t\t\tif (key) this.action(key);\n\t\t}\n\t}\n\thandleMouse(event: TuiMouseEvent): TuiMouseEventResult | undefined {\n\t\tif (this.disposed || event.ctrl || event.alt || event.shift) return;\n\t\t// Feedback is transient: a click retracts it and acts, exactly like a keypress does.\n\t\tthis.feedback = undefined;\n\t\tthis.render(event.width);\n\t\tconst layout = this.layout!;\n\t\tconst mode = this.mode;\n\t\tif (event.type === \"wheel\" && event.wheelDelta) {\n\t\t\tif (\n\t\t\t\tmode.kind !== \"confirmStop\" &&\n\t\t\t\t!layout.tooSmall &&\n\t\t\t\tevent.y >= 2 &&\n\t\t\t\tevent.y < this.options.tui.terminal.rows - 3\n\t\t\t) {\n\t\t\t\tconst delta = Math.sign(event.wheelDelta) * Math.min(20, Math.abs(event.wheelDelta));\n\t\t\t\tconst region = this.width >= 100 ? (event.x < layout.listWidth ? \"list\" : \"inspector\") : this.focus;\n\t\t\t\tif (mode.kind === \"help\") mode.viewport.move(delta, false, false);\n\t\t\t\telse if (region === \"list\") this.list.scroll(delta);\n\t\t\t\telse if (mode.kind !== \"search\")\n\t\t\t\t\tthis.inspector.position[this.selection.state.tab].move(\n\t\t\t\t\t\tdelta,\n\t\t\t\t\t\tfalse,\n\t\t\t\t\t\tthis.selection.state.tab === \"output\",\n\t\t\t\t\t);\n\t\t\t}\n\t\t} else if (event.type === \"click\" && event.button === \"left\") {\n\t\t\tconst hit = layout.hits.find((hit) => hit.y === event.y && event.x >= hit.x && event.x < hit.x + hit.width);\n\t\t\ttry {\n\t\t\t\tif (hit?.cancel) this.cancel();\n\t\t\t\telse if (hit?.taskId) {\n\t\t\t\t\tthis.selection.select(hit.taskId);\n\t\t\t\t\tthis.selectedChanged();\n\t\t\t\t\tthis.focus = \"list\";\n\t\t\t\t\tif (mode.kind === \"search\") this.finishSearch(false);\n\t\t\t\t} else if (hit?.tab) {\n\t\t\t\t\tthis.focus = \"inspector\";\n\t\t\t\t\tthis.selection.state.tab = hit.tab;\n\t\t\t\t} else if (hit?.key) {\n\t\t\t\t\tif (hit.key === \"app.tasks.follow\") this.focus = \"inspector\";\n\t\t\t\t\tthis.action(hit.key);\n\t\t\t\t} else if (\n\t\t\t\t\tmode.kind === \"browse\" &&\n\t\t\t\t\t!layout.tooSmall &&\n\t\t\t\t\tevent.y >= 1 &&\n\t\t\t\t\tevent.y < this.options.tui.terminal.rows - 2 &&\n\t\t\t\t\tthis.width >= 100\n\t\t\t\t)\n\t\t\t\t\tthis.focus = event.x < layout.listWidth ? \"list\" : \"inspector\";\n\t\t\t} catch (error) {\n\t\t\t\tthis.feedback = cleanTaskText(error instanceof Error ? error.message : String(error));\n\t\t\t}\n\t\t} else return;\n\t\tthis.queueTick(true);\n\t\tthis.options.tui.requestRender();\n\t\treturn { handled: true, focus: event.type === \"click\" };\n\t}\n\trender(width: number): string[] {\n\t\tthis.width = width;\n\t\tthis.sync();\n\t\tthis.layout = renderTasksLayout({\n\t\t\twidth,\n\t\t\theight: this.options.tui.terminal.rows,\n\t\t\ttheme: this.options.theme,\n\t\t\tkeybindings: this.options.keybindings,\n\t\t\tselection: this.selection,\n\t\t\tinspector: this.inspector,\n\t\t\tlist: this.list,\n\t\t\tfocus: this.focus,\n\t\t\tmode: this.mode,\n\t\t\tsearchLine: (width) => this.search.render(width).join(\"\"),\n\t\t\tfeedback: this.feedback,\n\t\t\tcanDetach: (id) => this.canDetach(id),\n\t\t});\n\t\treturn this.layout.lines;\n\t}\n\t/** The panel's selection can lag the runtime by a notification; a task that is gone cannot move. */\n\tprivate canDetach(id: string): boolean {\n\t\ttry {\n\t\t\treturn this.options.host.canDetach(id);\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n\tdispose(): void {\n\t\tif (this.disposed) return;\n\t\tthis.disposed = true;\n\t\tthis.selection.state.closedAt = Date.now();\n\t\tclearInterval(this.pollTimer);\n\t\tclearInterval(this.animationTimer);\n\t\tthis.unsubscribe();\n\t\tthis.inspector.dispose();\n\t}\n}\n"]}
@@ -1,5 +1,30 @@
1
1
  import { type TaskSnapshot } from "../../../core/tasks/types.ts";
2
+ import type { TaskViewport } from "./viewport.ts";
2
3
  export type TasksTab = "output" | "info";
4
+ export type PanelFocus = "list" | "inspector";
5
+ /**
6
+ * The one transient layer over the browsing panel. Each layer owns its data, so a stale
7
+ * combination (help over a confirmation, a restore point without a search) cannot exist.
8
+ */
9
+ export type PanelMode = {
10
+ kind: "browse";
11
+ }
12
+ /** Searching moves focus to the list; `restore` is where Esc returns to. */
13
+ | {
14
+ kind: "search";
15
+ restore: {
16
+ id?: string;
17
+ focus: PanelFocus;
18
+ };
19
+ } | {
20
+ kind: "confirmStop";
21
+ taskId: string;
22
+ } | {
23
+ kind: "help";
24
+ viewport: TaskViewport;
25
+ };
26
+ /** A task can be asked to stop while it is neither settled nor already stopping. */
27
+ export declare function isStoppable(task: Pick<TaskSnapshot, "status">): boolean;
3
28
  /** Remember navigation within one runtime, without retaining output or execution handles. */
4
29
  export interface TasksPanelState {
5
30
  tab: TasksTab;
@@ -1 +1 @@
1
- {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../../../src/extensions/tasks/ui/model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAEjF,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEzC,6FAA6F;AAC7F,MAAM,WAAW,eAAe;IAC/B,GAAG,EAAE,QAAQ,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,8FAA8F;AAC9F,qBAAa,aAAa;IACzB,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC;IAChC,GAAG,EAAE,YAAY,EAAE,CAAM;IACzB,IAAI,EAAE,YAAY,EAAE,CAAM;IAC1B,KAAK,SAAM;gBACC,KAAK,EAAE,eAAe;IAGlC,IAAI,QAAQ,IAAI,YAAY,GAAG,SAAS,CAEvC;IACD,IAAI,WAAW,IAAI,MAAM,CAExB;IACD,IAAI,CAAC,GAAG,EAAE,YAAY,EAAE,GAAG,IAAI;IAI/B,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;IAIpC,gGAAgG;IAChG,uBAAuB,IAAI,IAAI;IAM/B,OAAO,IAAI,IAAI;CAmBf"}
1
+ {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../../../src/extensions/tasks/ui/model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,8BAA8B,CAAC;AACjF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;AACzC,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,WAAW,CAAC;AAE9C;;;GAGG;AACH,MAAM,MAAM,SAAS,GAClB;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE;AACpB,4EAA4E;GAC1E;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE;QAAE,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,UAAU,CAAA;KAAE,CAAA;CAAE,GAC/D;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACvC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,YAAY,CAAA;CAAE,CAAC;AAE5C,oFAAoF;AACpF,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,GAAG,OAAO,CAEvE;AAED,6FAA6F;AAC7F,MAAM,WAAW,eAAe;IAC/B,GAAG,EAAE,QAAQ,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,8FAA8F;AAC9F,qBAAa,aAAa;IACzB,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC;IAChC,GAAG,EAAE,YAAY,EAAE,CAAM;IACzB,IAAI,EAAE,YAAY,EAAE,CAAM;IAC1B,KAAK,SAAM;gBACC,KAAK,EAAE,eAAe;IAGlC,IAAI,QAAQ,IAAI,YAAY,GAAG,SAAS,CAEvC;IACD,IAAI,WAAW,IAAI,MAAM,CAExB;IACD,IAAI,CAAC,GAAG,EAAE,YAAY,EAAE,GAAG,IAAI;IAI/B,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;IAIpC,gGAAgG;IAChG,uBAAuB,IAAI,IAAI;IAM/B,OAAO,IAAI,IAAI;CAmBf"}