@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
@@ -3,15 +3,15 @@ import { runtimeLabel } from "../../../core/tasks/format.js";
3
3
  import { isTaskTerminal } from "../../../core/tasks/types.js";
4
4
  import { formatSize } from "../../../core/tools/truncate.js";
5
5
  import { keyLabel } from "../../../modes/interactive/components/keybinding-hints.js";
6
- import { statusMarker } from "../../../modes/interactive/components/status-marker.js";
7
- import { statusName } from "./task-view.js";
6
+ import { isStoppable } from "./model.js";
7
+ import { modeName, statusName, statusView } from "./status.js";
8
8
  import { cleanTaskText, firstCommandLine } from "./text.js";
9
9
  const pad = (text, width) => truncateToWidth(text, Math.max(1, width), "…", true);
10
10
  /** Visible width of "Output Details". */
11
11
  const TABS_WIDTH = 15;
12
12
  /** Cell geometry and mouse targets are produced together, so resize cannot separate them. */
13
13
  export function renderTasksLayout(options) {
14
- const { width, height, theme, selection, inspector, list, focus, keybindings } = options;
14
+ const { width, height, theme, selection, inspector, list, focus, keybindings, mode } = options;
15
15
  const hint = (key) => keyLabel(key, { keybindings });
16
16
  const result = { hits: [], listWidth: 0, listPageSize: 1, lines: [] };
17
17
  if (width < 1 || height < 1)
@@ -68,7 +68,7 @@ export function renderTasksLayout(options) {
68
68
  const visible = list.render(selection, theme, listWidth - 2, bodyHeight);
69
69
  let listHeader = theme.fg("text", "Tasks");
70
70
  const searchLabel = `${hint("app.tasks.search")} find`;
71
- if (options.searchLine)
71
+ if (mode.kind === "search")
72
72
  listHeader = options.searchLine(listWidth - 2);
73
73
  else {
74
74
  const x = Math.max(6, listWidth - 2 - visibleWidth(searchLabel));
@@ -91,11 +91,10 @@ export function renderTasksLayout(options) {
91
91
  const tabLabel = (id, label) => theme.style(label, { fg: "text", underline: tab === id });
92
92
  // One header row in every layout: the selected task's source and status, with the tabs on the right.
93
93
  const tabsX = rightWidth - 2 - TABS_WIDTH;
94
- const marker = task ? statusMarker(task.status) : undefined;
95
- const summary = task && marker
94
+ const summary = task
96
95
  ? [
97
96
  theme.fg("muted", cleanTaskText(task.label)),
98
- theme.fg(marker.color, statusName(task.status)),
97
+ theme.fg(statusView(task.status).color, statusName(task.status)),
99
98
  theme.fg("muted", runtimeLabel(task)),
100
99
  ].join(theme.fg("dim", " · "))
101
100
  : "";
@@ -118,7 +117,7 @@ export function renderTasksLayout(options) {
118
117
  if (tab === "output" && diagnostics.length)
119
118
  content.push(theme.fg("warning", diagnostics.join(" · ").replace(/\n/g, " ")));
120
119
  const source = tab === "info"
121
- ? inspector.details(`${statusName(task.status)} · ${statusName(task.mode)} · ${runtimeLabel(task)}`)
120
+ ? inspector.details(`${statusName(task.status)} · ${modeName(task.mode)} · ${runtimeLabel(task)}`)
122
121
  : inspector.output(rightWidth - 2);
123
122
  content.push(...position[tab].layout(source, rightWidth - 2, bodyHeight - content.length));
124
123
  if (tab === "output") {
@@ -162,28 +161,28 @@ export function renderTasksLayout(options) {
162
161
  if (target)
163
162
  hits.push({ x, y: height - 1, width: visibleWidth(text), ...target });
164
163
  };
165
- if (options.help) {
164
+ if (mode.kind === "help") {
166
165
  hits.length = 0;
167
- panels = pane(helpLines(options.help, hint, theme, width, height), width, false);
166
+ panels = pane(helpLines(mode.viewport, hint, theme, width, height), width, false);
168
167
  addHint("tui.select.up", `/ ${hint("tui.select.down")} scroll`);
169
168
  addHint("tui.select.cancel", "back", { cancel: true });
170
169
  }
171
- else if (options.pendingKill) {
170
+ else if (mode.kind === "confirmStop") {
172
171
  // The question borrows only the footer row, so the task stays in view while confirming.
173
172
  hits.length = 0;
174
- const target = selection.all.find((task) => task.id === options.pendingKill);
173
+ const target = selection.all.find((task) => task.id === mode.taskId);
175
174
  const source = cleanTaskText(target?.label ?? "task");
176
175
  const confirm = `${hint("app.tasks.confirmStop")} stop`;
177
176
  const cancel = `${hint("tui.select.cancel")} cancel`;
178
177
  const actions = `${confirm} · ${cancel}`;
179
178
  const room = width - visibleWidth(`Stop ${source} ""? ${actions}`);
180
- const title = cleanTaskText(firstCommandLine(target?.title ?? options.pendingKill));
179
+ const title = cleanTaskText(firstCommandLine(target?.title ?? mode.taskId));
181
180
  const question = room >= 4 ? `Stop ${source} "${truncateToWidth(title, room, "…")}"? ` : `Stop ${source}? `;
182
181
  footer = question + actions;
183
182
  const x = visibleWidth(question);
184
183
  hits.push({ x, y: height - 1, width: visibleWidth(confirm), key: "app.tasks.confirmStop" }, { x: x + visibleWidth(confirm) + 3, y: height - 1, width: visibleWidth(cancel), cancel: true });
185
184
  }
186
- else if (options.searchLine) {
185
+ else if (mode.kind === "search") {
187
186
  // Only search candidates and cancellation are clickable while locating a task.
188
187
  for (let i = hits.length - 1; i >= 0; i--)
189
188
  if (!hits[i].taskId)
@@ -205,18 +204,17 @@ export function renderTasksLayout(options) {
205
204
  addHint("app.tasks.previousTab", "output", { tab: "output" });
206
205
  addHint("app.tasks.nextTab", "details", { tab: "info" });
207
206
  }
208
- if (task && !isTaskTerminal(task.status) && task.status !== "stopping") {
207
+ if (task && isStoppable(task))
209
208
  addHint("app.tasks.kill", "stop", { key: "app.tasks.kill" });
210
- if (task.mode === "foreground" && options.canDetach)
211
- addHint("app.tasks.detachSelected", "background", { key: "app.tasks.detachSelected" });
212
- }
209
+ if (task && options.canDetach(task.id))
210
+ addHint("app.tasks.detachSelected", "background", { key: "app.tasks.detachSelected" });
213
211
  addHint("app.tasks.help", "keys", { key: "app.tasks.help" });
214
212
  // Feedback borrows the hint row, so the hint hit targets stay live and the click that
215
213
  // dismisses it can act in the same gesture.
216
214
  if (options.feedback)
217
215
  footer = options.feedback;
218
216
  }
219
- result.lines = [...panels, theme.fg(options.pendingKill ? "warning" : "dim", pad(footer, width))];
217
+ result.lines = [...panels, theme.fg(mode.kind === "confirmStop" ? "warning" : "dim", pad(footer, width))];
220
218
  return result;
221
219
  }
222
220
  /** Controls grouped by purpose; actions sharing a key, such as list and inspector paging, share a row. */
@@ -1 +1 @@
1
- {"version":3,"file":"layout.js","sourceRoot":"","sources":["../../../../src/extensions/tasks/ui/layout.ts"],"names":[],"mappings":"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","sourcesContent":["import { truncateToWidth, visibleWidth, wrapTextWithAnsi } from \"@earendil-works/pi-tui\";\nimport type { AppKeybinding, Keybinding, KeybindingsManager } from \"../../../core/keybindings.ts\";\nimport { runtimeLabel } from \"../../../core/tasks/format.ts\";\nimport { isTaskTerminal } from \"../../../core/tasks/types.ts\";\nimport { formatSize } from \"../../../core/tools/truncate.ts\";\nimport { keyLabel } from \"../../../modes/interactive/components/keybinding-hints.ts\";\nimport { statusMarker } from \"../../../modes/interactive/components/status-marker.ts\";\nimport type { Theme } from \"../../../modes/interactive/theme/theme.ts\";\nimport type { TaskInspector } from \"./inspector.ts\";\nimport type { TaskList } from \"./list.ts\";\nimport type { TaskSelection, TasksTab } from \"./model.ts\";\nimport { statusName } from \"./task-view.ts\";\nimport { cleanTaskText, firstCommandLine } from \"./text.ts\";\nimport type { TaskViewport } from \"./viewport.ts\";\n\nexport interface TaskHit {\n\tx: number;\n\ty: number;\n\twidth: number;\n\tkey?: AppKeybinding;\n\ttaskId?: string;\n\ttab?: TasksTab;\n\tcancel?: boolean;\n}\nexport interface TasksLayout {\n\thits: TaskHit[];\n\tlistWidth: number;\n\tlistPageSize: number;\n\tlines: string[];\n\t/** The terminal is below the supported size; only a full-screen resize notice is shown. */\n\ttooSmall?: boolean;\n}\ninterface LayoutOptions {\n\twidth: number;\n\theight: number;\n\ttheme: Theme;\n\tkeybindings: Pick<KeybindingsManager, \"getKeys\">;\n\tselection: TaskSelection;\n\tinspector: TaskInspector;\n\tlist: TaskList;\n\tfocus: \"list\" | \"inspector\";\n\tsearchLine?: (width: number) => string;\n\tpendingKill?: string;\n\tfeedback?: string;\n\thelp?: TaskViewport;\n\tcanDetach: boolean;\n}\nconst pad = (text: string, width: number) => truncateToWidth(text, Math.max(1, width), \"…\", true);\n/** Visible width of \"Output Details\". */\nconst TABS_WIDTH = 15;\n\n/** Cell geometry and mouse targets are produced together, so resize cannot separate them. */\nexport function renderTasksLayout(options: LayoutOptions): TasksLayout {\n\tconst { width, height, theme, selection, inspector, list, focus, keybindings } = options;\n\tconst hint = (key: Keybinding) => keyLabel(key, { keybindings });\n\tconst result: TasksLayout = { hits: [], listWidth: 0, listPageSize: 1, lines: [] };\n\tif (width < 1 || height < 1) return result;\n\tconst wide = width >= 100;\n\tconst listWidth = wide ? Math.min(42, Math.max(32, Math.floor(width * 0.32))) : width;\n\tconst rightWidth = wide ? width - listWidth - 1 : width;\n\tconst rightX = wide ? listWidth + 1 : 0;\n\tconst bodyHeight = height - 5;\n\tconst hits = result.hits;\n\tresult.listWidth = listWidth;\n\t// One row per task, less the group headings.\n\tresult.listPageSize = Math.max(1, bodyHeight - 2);\n\tconst pane = (lines: string[], size: number, active: boolean): string[] => {\n\t\tconst border = (text: string) => theme.fg(wide && active ? \"borderAccent\" : \"borderMuted\", text);\n\t\treturn [\n\t\t\tborder(`┌${\"─\".repeat(size - 2)}┐`),\n\t\t\t...lines.map((line) => border(\"│\") + pad(line, size - 2) + border(\"│\")),\n\t\t\tborder(`└${\"─\".repeat(size - 2)}┘`),\n\t\t];\n\t};\n\tif (width < 60 || height < 14) {\n\t\t// The panel is modal: a floating notice would leave the transcript visible yet\n\t\t// unscrollable, so the notice owns every row as a centered dialog. Only a truly\n\t\t// tiny terminal, where even the dialog does not fit, gets bare covering lines.\n\t\tresult.tooSmall = true;\n\t\tconst message = \"Terminal too small for /tasks. Enlarge the window to continue.\";\n\t\tconst close = `${hint(\"tui.select.cancel\")} close`;\n\t\tconst boxWidth = Math.min(width, 46);\n\t\tconst inner = boxWidth - 2;\n\t\tconst wrapped = wrapTextWithAnsi(message, inner).map((line) => theme.fg(\"warning\", line));\n\t\tconst spacious = [theme.fg(\"text\", \"Tasks\"), \"\", ...wrapped, \"\", theme.fg(\"dim\", close)];\n\t\tconst tight = [theme.fg(\"text\", \"Tasks\"), ...wrapped, theme.fg(\"dim\", close)];\n\t\tconst body = height >= spacious.length + 2 ? spacious : tight;\n\t\tif (inner >= 16 && height >= body.length + 2) {\n\t\t\tconst box = pane(body, boxWidth, false);\n\t\t\tconst left = Math.floor((width - boxWidth) / 2);\n\t\t\tconst top = Math.max(0, Math.floor((height - box.length) / 2));\n\t\t\tconst blank = \" \".repeat(width);\n\t\t\tresult.lines = [\n\t\t\t\t...Array.from({ length: top }, () => blank),\n\t\t\t\t...box.map((line) => \" \".repeat(left) + line + \" \".repeat(width - left - boxWidth)),\n\t\t\t\t...Array.from({ length: height - top - box.length }, () => blank),\n\t\t\t];\n\t\t\thits.push({ x: left + 1, y: top + body.length, width: visibleWidth(close), cancel: true });\n\t\t} else {\n\t\t\tresult.lines = [\"Tasks\", message, close].slice(0, height).map((line) => pad(line, width));\n\t\t\twhile (result.lines.length < height) result.lines.push(\" \".repeat(width));\n\t\t}\n\t\treturn result;\n\t}\n\tconst visible = list.render(selection, theme, listWidth - 2, bodyHeight);\n\tlet listHeader = theme.fg(\"text\", \"Tasks\");\n\tconst searchLabel = `${hint(\"app.tasks.search\")} find`;\n\tif (options.searchLine) listHeader = options.searchLine(listWidth - 2);\n\telse {\n\t\tconst x = Math.max(6, listWidth - 2 - visibleWidth(searchLabel));\n\t\tlistHeader += \" \".repeat(x - 5) + theme.fg(\"dim\", searchLabel);\n\t\tif (wide || focus === \"list\")\n\t\t\thits.push({ x: x + 1, y: 1, width: visibleWidth(searchLabel), key: \"app.tasks.search\" });\n\t}\n\tif (wide || focus === \"list\")\n\t\tvisible.forEach((row, index) => {\n\t\t\tif (row.taskId) hits.push({ x: 1, y: 2 + index, width: listWidth - 2, taskId: row.taskId });\n\t\t});\n\tconst left = [\n\t\tlistHeader,\n\t\t...Array.from({ length: bodyHeight }, (_, i) => visible[i]?.text ?? \"\"),\n\t\ttheme.fg(\"dim\", list.range),\n\t];\n\tconst task = inspector.task;\n\tconst tab = selection.state.tab;\n\tconst tabLabel = (id: TasksTab, label: string) => theme.style(label, { fg: \"text\", underline: tab === id });\n\t// One header row in every layout: the selected task's source and status, with the tabs on the right.\n\tconst tabsX = rightWidth - 2 - TABS_WIDTH;\n\tconst marker = task ? statusMarker(task.status) : undefined;\n\tconst summary =\n\t\ttask && marker\n\t\t\t? [\n\t\t\t\t\ttheme.fg(\"muted\", cleanTaskText(task.label)),\n\t\t\t\t\ttheme.fg(marker.color, statusName(task.status)),\n\t\t\t\t\ttheme.fg(\"muted\", runtimeLabel(task)),\n\t\t\t\t].join(theme.fg(\"dim\", \" · \"))\n\t\t\t: \"\";\n\tconst shownSummary = truncateToWidth(summary, Math.max(0, tabsX - 1), \"…\");\n\tconst right = [\n\t\t`${shownSummary}${\" \".repeat(tabsX - visibleWidth(shownSummary))}${tabLabel(\"output\", \"Output\")} ${tabLabel(\"info\", \"Details\")}`,\n\t];\n\tif (wide || focus === \"inspector\")\n\t\thits.push(\n\t\t\t{ x: rightX + 1 + tabsX, y: 1, width: 6, tab: \"output\" },\n\t\t\t{ x: rightX + 9 + tabsX, y: 1, width: 7, tab: \"info\" },\n\t\t);\n\tconst content: string[] = [];\n\tlet reading = \"\";\n\tif (task) {\n\t\t// Without the list beside it, the inspector names the task it shows.\n\t\tif (!wide) content.push(theme.fg(\"text\", cleanTaskText(firstCommandLine(task.title))));\n\t\tconst position = inspector.position;\n\t\tconst read = position.read;\n\t\tconst terminal = isTaskTerminal(task.status);\n\t\tconst diagnostics = [task.error, read?.readError].filter((text): text is string => !!text).map(cleanTaskText);\n\t\tif (tab === \"output\" && diagnostics.length)\n\t\t\tcontent.push(theme.fg(\"warning\", diagnostics.join(\" · \").replace(/\\n/g, \" \")));\n\t\tconst source =\n\t\t\ttab === \"info\"\n\t\t\t\t? inspector.details(`${statusName(task.status)} · ${statusName(task.mode)} · ${runtimeLabel(task)}`)\n\t\t\t\t: inspector.output(rightWidth - 2);\n\t\tcontent.push(...position[tab].layout(source, rightWidth - 2, bodyHeight - content.length));\n\t\tif (tab === \"output\") {\n\t\t\t// Only a log holds a browsed snapshot; other output is always the current result.\n\t\t\tconst settled = terminal && task.outputPath === undefined;\n\t\t\treading =\n\t\t\t\tposition.output.follow || settled\n\t\t\t\t\t? terminal\n\t\t\t\t\t\t? \"Finished\"\n\t\t\t\t\t\t: \"Live\"\n\t\t\t\t\t: terminal\n\t\t\t\t\t\t? `Finished · ${hint(\"app.tasks.follow\")} load final output`\n\t\t\t\t\t\t: `Browsing · ${hint(\"app.tasks.follow\")} follow output`;\n\t\t\tif (!position.output.follow && !settled && (wide || focus === \"inspector\"))\n\t\t\t\thits.push({\n\t\t\t\t\tx: rightX + 1,\n\t\t\t\t\ty: height - 3,\n\t\t\t\t\twidth: Math.min(rightWidth - 2, visibleWidth(reading)),\n\t\t\t\t\tkey: \"app.tasks.follow\",\n\t\t\t\t});\n\t\t\tif (task.outputPath !== undefined && read?.truncated)\n\t\t\t\treading += ` · Tail preview: ${formatSize(Buffer.byteLength(read.text))} of ${formatSize(read.totalBytes)}`;\n\t\t} else if (tab === \"info\") reading = `Details ${position.info.range}`;\n\t} else content.push(theme.fg(\"muted\", \"Select a task to inspect its result.\"));\n\tright.push(...Array.from({ length: bodyHeight }, (_, i) => content[i] ?? \"\"), theme.fg(\"dim\", reading));\n\tconst rightPane = pane(right, rightWidth, focus === \"inspector\");\n\tlet panels = wide\n\t\t? pane(left, listWidth, focus === \"list\").map((line, i) => `${line} ${rightPane[i]}`)\n\t\t: pane(focus === \"list\" ? left : right, width, false);\n\n\tlet footer = \"\";\n\tconst addHint = (key: Keybinding, label: string, target?: Omit<TaskHit, \"x\" | \"y\" | \"width\">) => {\n\t\tconst text = `${hint(key)} ${label}`;\n\t\tconst x = visibleWidth(footer) + (footer ? 3 : 0);\n\t\tif (x + visibleWidth(text) > width) return;\n\t\tfooter += (footer ? \" · \" : \"\") + text;\n\t\tif (target) hits.push({ x, y: height - 1, width: visibleWidth(text), ...target });\n\t};\n\tif (options.help) {\n\t\thits.length = 0;\n\t\tpanels = pane(helpLines(options.help, hint, theme, width, height), width, false);\n\t\taddHint(\"tui.select.up\", `/ ${hint(\"tui.select.down\")} scroll`);\n\t\taddHint(\"tui.select.cancel\", \"back\", { cancel: true });\n\t} else if (options.pendingKill) {\n\t\t// The question borrows only the footer row, so the task stays in view while confirming.\n\t\thits.length = 0;\n\t\tconst target = selection.all.find((task) => task.id === options.pendingKill);\n\t\tconst source = cleanTaskText(target?.label ?? \"task\");\n\t\tconst confirm = `${hint(\"app.tasks.confirmStop\")} stop`;\n\t\tconst cancel = `${hint(\"tui.select.cancel\")} cancel`;\n\t\tconst actions = `${confirm} · ${cancel}`;\n\t\tconst room = width - visibleWidth(`Stop ${source} \"\"? ${actions}`);\n\t\tconst title = cleanTaskText(firstCommandLine(target?.title ?? options.pendingKill));\n\t\tconst question = room >= 4 ? `Stop ${source} \"${truncateToWidth(title, room, \"…\")}\"? ` : `Stop ${source}? `;\n\t\tfooter = question + actions;\n\t\tconst x = visibleWidth(question);\n\t\thits.push(\n\t\t\t{ x, y: height - 1, width: visibleWidth(confirm), key: \"app.tasks.confirmStop\" },\n\t\t\t{ x: x + visibleWidth(confirm) + 3, y: height - 1, width: visibleWidth(cancel), cancel: true },\n\t\t);\n\t} else if (options.searchLine) {\n\t\t// Only search candidates and cancellation are clickable while locating a task.\n\t\tfor (let i = hits.length - 1; i >= 0; i--) if (!hits[i]!.taskId) hits.splice(i, 1);\n\t\taddHint(\"tui.select.up\", `/ ${hint(\"tui.select.down\")} choose`);\n\t\taddHint(\"tui.select.confirm\", \"locate\");\n\t\taddHint(\"tui.select.cancel\", \"cancel\", { cancel: true });\n\t} else {\n\t\taddHint(\"tui.select.up\", `/ ${hint(\"tui.select.down\")}${focus === \"list\" ? \" tasks\" : \" scroll\"}`);\n\t\tif (focus === \"list\") addHint(\"tui.select.confirm\", \"open\", { tab });\n\t\telse addHint(\"app.tasks.nextFocus\", \"tasks\", { key: \"app.tasks.nextFocus\" });\n\t\taddHint(\"tui.select.cancel\", \"close\", { cancel: true });\n\t\tif (focus === \"list\") addHint(\"app.tasks.search\", \"find\", { key: \"app.tasks.search\" });\n\t\telse {\n\t\t\taddHint(\"app.tasks.previousTab\", \"output\", { tab: \"output\" });\n\t\t\taddHint(\"app.tasks.nextTab\", \"details\", { tab: \"info\" });\n\t\t}\n\t\tif (task && !isTaskTerminal(task.status) && task.status !== \"stopping\") {\n\t\t\taddHint(\"app.tasks.kill\", \"stop\", { key: \"app.tasks.kill\" });\n\t\t\tif (task.mode === \"foreground\" && options.canDetach)\n\t\t\t\taddHint(\"app.tasks.detachSelected\", \"background\", { key: \"app.tasks.detachSelected\" });\n\t\t}\n\t\taddHint(\"app.tasks.help\", \"keys\", { key: \"app.tasks.help\" });\n\t\t// Feedback borrows the hint row, so the hint hit targets stay live and the click that\n\t\t// dismisses it can act in the same gesture.\n\t\tif (options.feedback) footer = options.feedback;\n\t}\n\tresult.lines = [...panels, theme.fg(options.pendingKill ? \"warning\" : \"dim\", pad(footer, width))];\n\treturn result;\n}\n\n/** Controls grouped by purpose; actions sharing a key, such as list and inspector paging, share a row. */\nfunction helpLines(\n\thelp: TaskViewport,\n\thint: (key: Keybinding) => string,\n\ttheme: Theme,\n\twidth: number,\n\theight: number,\n): string[] {\n\tconst keys = (...bindings: Keybinding[]) => [...new Set(bindings.map(hint).filter(Boolean))].join(\" / \");\n\tconst listPage = keys(\"tui.select.pageUp\", \"tui.select.pageDown\");\n\tconst inspectorPage = keys(\"tui.editor.pageUp\", \"tui.editor.pageDown\");\n\tconst paging: Array<[string, string]> =\n\t\tlistPage === inspectorPage\n\t\t\t? [[listPage, \"Page the list or inspector\"]]\n\t\t\t: [\n\t\t\t\t\t[listPage, \"Page the list\"],\n\t\t\t\t\t[inspectorPage, \"Page the inspector\"],\n\t\t\t\t];\n\tconst sections: Array<[string, Array<[string, string]>]> = [\n\t\t[\n\t\t\t\"Navigate\",\n\t\t\t[\n\t\t\t\t[keys(\"tui.select.up\", \"tui.select.down\"), \"Select a task, or scroll the inspector\"],\n\t\t\t\t...paging,\n\t\t\t\t[keys(\"app.tasks.top\", \"app.tasks.bottom\"), \"Top or bottom\"],\n\t\t\t\t[hint(\"tui.select.confirm\"), \"Open the selected task\"],\n\t\t\t\t[keys(\"app.tasks.nextFocus\", \"app.tasks.previousFocus\"), \"Switch between list and inspector\"],\n\t\t\t],\n\t\t],\n\t\t[\n\t\t\t\"View\",\n\t\t\t[\n\t\t\t\t[keys(\"app.tasks.previousTab\", \"app.tasks.nextTab\"), \"Output or Details, in the inspector\"],\n\t\t\t\t[hint(\"app.tasks.follow\"), \"Follow the latest output, or load the final output\"],\n\t\t\t\t[hint(\"app.tasks.search\"), \"Find a task; Enter locates it, Esc restores the selection\"],\n\t\t\t],\n\t\t],\n\t\t[\n\t\t\t\"Act\",\n\t\t\t[\n\t\t\t\t[hint(\"app.tasks.kill\"), `Stop the selected task; ${hint(\"app.tasks.confirmStop\")} confirms`],\n\t\t\t\t[hint(\"app.tasks.detachSelected\"), \"Move the selected foreground task to the background\"],\n\t\t\t\t[hint(\"app.tasks.detach\"), \"Move every foreground execution to the background\"],\n\t\t\t\t[hint(\"tui.select.cancel\"), \"Close search, help or confirmation; otherwise the panel\"],\n\t\t\t],\n\t\t],\n\t];\n\tconst keyWidth = Math.max(...sections.flatMap(([, rows]) => rows.map(([key]) => visibleWidth(key)))) + 2;\n\tconst rows = sections.flatMap(([title, entries], index) => [\n\t\t...(index ? [\"\"] : []),\n\t\ttheme.fg(\"accent\", title),\n\t\t...entries.map(([key, label]) => ` ${key}${\" \".repeat(keyWidth - visibleWidth(key))}${label}`),\n\t]);\n\tconst body = [theme.fg(\"text\", \"Task controls\"), ...help.layout(rows, width - 2, height - 5), \"\"];\n\twhile (body.length < height - 3) body.push(\"\");\n\treturn body;\n}\n"]}
1
+ {"version":3,"file":"layout.js","sourceRoot":"","sources":["../../../../src/extensions/tasks/ui/layout.ts"],"names":[],"mappings":"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","sourcesContent":["import { truncateToWidth, visibleWidth, wrapTextWithAnsi } from \"@earendil-works/pi-tui\";\nimport type { AppKeybinding, Keybinding, KeybindingsManager } from \"../../../core/keybindings.ts\";\nimport { runtimeLabel } from \"../../../core/tasks/format.ts\";\nimport { isTaskTerminal } from \"../../../core/tasks/types.ts\";\nimport { formatSize } from \"../../../core/tools/truncate.ts\";\nimport { keyLabel } from \"../../../modes/interactive/components/keybinding-hints.ts\";\nimport type { Theme } from \"../../../modes/interactive/theme/theme.ts\";\nimport type { TaskInspector } from \"./inspector.ts\";\nimport type { TaskList } from \"./list.ts\";\nimport { isStoppable, type PanelFocus, type PanelMode, type TaskSelection, type TasksTab } from \"./model.ts\";\nimport { modeName, statusName, statusView } from \"./status.ts\";\nimport { cleanTaskText, firstCommandLine } from \"./text.ts\";\nimport type { TaskViewport } from \"./viewport.ts\";\n\nexport interface TaskHit {\n\tx: number;\n\ty: number;\n\twidth: number;\n\tkey?: AppKeybinding;\n\ttaskId?: string;\n\ttab?: TasksTab;\n\tcancel?: boolean;\n}\nexport interface TasksLayout {\n\thits: TaskHit[];\n\tlistWidth: number;\n\tlistPageSize: number;\n\tlines: string[];\n\t/** The terminal is below the supported size; only a full-screen resize notice is shown. */\n\ttooSmall?: boolean;\n}\ninterface LayoutOptions {\n\twidth: number;\n\theight: number;\n\ttheme: Theme;\n\tkeybindings: Pick<KeybindingsManager, \"getKeys\">;\n\tselection: TaskSelection;\n\tinspector: TaskInspector;\n\tlist: TaskList;\n\tfocus: PanelFocus;\n\tmode: PanelMode;\n\t/** Renders the search input line; shown only in search mode. */\n\tsearchLine: (width: number) => string;\n\tfeedback?: string;\n\t/** Whether the host would move this task to the background now. */\n\tcanDetach: (id: string) => boolean;\n}\nconst pad = (text: string, width: number) => truncateToWidth(text, Math.max(1, width), \"…\", true);\n/** Visible width of \"Output Details\". */\nconst TABS_WIDTH = 15;\n\n/** Cell geometry and mouse targets are produced together, so resize cannot separate them. */\nexport function renderTasksLayout(options: LayoutOptions): TasksLayout {\n\tconst { width, height, theme, selection, inspector, list, focus, keybindings, mode } = options;\n\tconst hint = (key: Keybinding) => keyLabel(key, { keybindings });\n\tconst result: TasksLayout = { hits: [], listWidth: 0, listPageSize: 1, lines: [] };\n\tif (width < 1 || height < 1) return result;\n\tconst wide = width >= 100;\n\tconst listWidth = wide ? Math.min(42, Math.max(32, Math.floor(width * 0.32))) : width;\n\tconst rightWidth = wide ? width - listWidth - 1 : width;\n\tconst rightX = wide ? listWidth + 1 : 0;\n\tconst bodyHeight = height - 5;\n\tconst hits = result.hits;\n\tresult.listWidth = listWidth;\n\t// One row per task, less the group headings.\n\tresult.listPageSize = Math.max(1, bodyHeight - 2);\n\tconst pane = (lines: string[], size: number, active: boolean): string[] => {\n\t\tconst border = (text: string) => theme.fg(wide && active ? \"borderAccent\" : \"borderMuted\", text);\n\t\treturn [\n\t\t\tborder(`┌${\"─\".repeat(size - 2)}┐`),\n\t\t\t...lines.map((line) => border(\"│\") + pad(line, size - 2) + border(\"│\")),\n\t\t\tborder(`└${\"─\".repeat(size - 2)}┘`),\n\t\t];\n\t};\n\tif (width < 60 || height < 14) {\n\t\t// The panel is modal: a floating notice would leave the transcript visible yet\n\t\t// unscrollable, so the notice owns every row as a centered dialog. Only a truly\n\t\t// tiny terminal, where even the dialog does not fit, gets bare covering lines.\n\t\tresult.tooSmall = true;\n\t\tconst message = \"Terminal too small for /tasks. Enlarge the window to continue.\";\n\t\tconst close = `${hint(\"tui.select.cancel\")} close`;\n\t\tconst boxWidth = Math.min(width, 46);\n\t\tconst inner = boxWidth - 2;\n\t\tconst wrapped = wrapTextWithAnsi(message, inner).map((line) => theme.fg(\"warning\", line));\n\t\tconst spacious = [theme.fg(\"text\", \"Tasks\"), \"\", ...wrapped, \"\", theme.fg(\"dim\", close)];\n\t\tconst tight = [theme.fg(\"text\", \"Tasks\"), ...wrapped, theme.fg(\"dim\", close)];\n\t\tconst body = height >= spacious.length + 2 ? spacious : tight;\n\t\tif (inner >= 16 && height >= body.length + 2) {\n\t\t\tconst box = pane(body, boxWidth, false);\n\t\t\tconst left = Math.floor((width - boxWidth) / 2);\n\t\t\tconst top = Math.max(0, Math.floor((height - box.length) / 2));\n\t\t\tconst blank = \" \".repeat(width);\n\t\t\tresult.lines = [\n\t\t\t\t...Array.from({ length: top }, () => blank),\n\t\t\t\t...box.map((line) => \" \".repeat(left) + line + \" \".repeat(width - left - boxWidth)),\n\t\t\t\t...Array.from({ length: height - top - box.length }, () => blank),\n\t\t\t];\n\t\t\thits.push({ x: left + 1, y: top + body.length, width: visibleWidth(close), cancel: true });\n\t\t} else {\n\t\t\tresult.lines = [\"Tasks\", message, close].slice(0, height).map((line) => pad(line, width));\n\t\t\twhile (result.lines.length < height) result.lines.push(\" \".repeat(width));\n\t\t}\n\t\treturn result;\n\t}\n\tconst visible = list.render(selection, theme, listWidth - 2, bodyHeight);\n\tlet listHeader = theme.fg(\"text\", \"Tasks\");\n\tconst searchLabel = `${hint(\"app.tasks.search\")} find`;\n\tif (mode.kind === \"search\") listHeader = options.searchLine(listWidth - 2);\n\telse {\n\t\tconst x = Math.max(6, listWidth - 2 - visibleWidth(searchLabel));\n\t\tlistHeader += \" \".repeat(x - 5) + theme.fg(\"dim\", searchLabel);\n\t\tif (wide || focus === \"list\")\n\t\t\thits.push({ x: x + 1, y: 1, width: visibleWidth(searchLabel), key: \"app.tasks.search\" });\n\t}\n\tif (wide || focus === \"list\")\n\t\tvisible.forEach((row, index) => {\n\t\t\tif (row.taskId) hits.push({ x: 1, y: 2 + index, width: listWidth - 2, taskId: row.taskId });\n\t\t});\n\tconst left = [\n\t\tlistHeader,\n\t\t...Array.from({ length: bodyHeight }, (_, i) => visible[i]?.text ?? \"\"),\n\t\ttheme.fg(\"dim\", list.range),\n\t];\n\tconst task = inspector.task;\n\tconst tab = selection.state.tab;\n\tconst tabLabel = (id: TasksTab, label: string) => theme.style(label, { fg: \"text\", underline: tab === id });\n\t// One header row in every layout: the selected task's source and status, with the tabs on the right.\n\tconst tabsX = rightWidth - 2 - TABS_WIDTH;\n\tconst summary = task\n\t\t? [\n\t\t\t\ttheme.fg(\"muted\", cleanTaskText(task.label)),\n\t\t\t\ttheme.fg(statusView(task.status).color, statusName(task.status)),\n\t\t\t\ttheme.fg(\"muted\", runtimeLabel(task)),\n\t\t\t].join(theme.fg(\"dim\", \" · \"))\n\t\t: \"\";\n\tconst shownSummary = truncateToWidth(summary, Math.max(0, tabsX - 1), \"…\");\n\tconst right = [\n\t\t`${shownSummary}${\" \".repeat(tabsX - visibleWidth(shownSummary))}${tabLabel(\"output\", \"Output\")} ${tabLabel(\"info\", \"Details\")}`,\n\t];\n\tif (wide || focus === \"inspector\")\n\t\thits.push(\n\t\t\t{ x: rightX + 1 + tabsX, y: 1, width: 6, tab: \"output\" },\n\t\t\t{ x: rightX + 9 + tabsX, y: 1, width: 7, tab: \"info\" },\n\t\t);\n\tconst content: string[] = [];\n\tlet reading = \"\";\n\tif (task) {\n\t\t// Without the list beside it, the inspector names the task it shows.\n\t\tif (!wide) content.push(theme.fg(\"text\", cleanTaskText(firstCommandLine(task.title))));\n\t\tconst position = inspector.position;\n\t\tconst read = position.read;\n\t\tconst terminal = isTaskTerminal(task.status);\n\t\tconst diagnostics = [task.error, read?.readError].filter((text): text is string => !!text).map(cleanTaskText);\n\t\tif (tab === \"output\" && diagnostics.length)\n\t\t\tcontent.push(theme.fg(\"warning\", diagnostics.join(\" · \").replace(/\\n/g, \" \")));\n\t\tconst source =\n\t\t\ttab === \"info\"\n\t\t\t\t? inspector.details(`${statusName(task.status)} · ${modeName(task.mode)} · ${runtimeLabel(task)}`)\n\t\t\t\t: inspector.output(rightWidth - 2);\n\t\tcontent.push(...position[tab].layout(source, rightWidth - 2, bodyHeight - content.length));\n\t\tif (tab === \"output\") {\n\t\t\t// Only a log holds a browsed snapshot; other output is always the current result.\n\t\t\tconst settled = terminal && task.outputPath === undefined;\n\t\t\treading =\n\t\t\t\tposition.output.follow || settled\n\t\t\t\t\t? terminal\n\t\t\t\t\t\t? \"Finished\"\n\t\t\t\t\t\t: \"Live\"\n\t\t\t\t\t: terminal\n\t\t\t\t\t\t? `Finished · ${hint(\"app.tasks.follow\")} load final output`\n\t\t\t\t\t\t: `Browsing · ${hint(\"app.tasks.follow\")} follow output`;\n\t\t\tif (!position.output.follow && !settled && (wide || focus === \"inspector\"))\n\t\t\t\thits.push({\n\t\t\t\t\tx: rightX + 1,\n\t\t\t\t\ty: height - 3,\n\t\t\t\t\twidth: Math.min(rightWidth - 2, visibleWidth(reading)),\n\t\t\t\t\tkey: \"app.tasks.follow\",\n\t\t\t\t});\n\t\t\tif (task.outputPath !== undefined && read?.truncated)\n\t\t\t\treading += ` · Tail preview: ${formatSize(Buffer.byteLength(read.text))} of ${formatSize(read.totalBytes)}`;\n\t\t} else if (tab === \"info\") reading = `Details ${position.info.range}`;\n\t} else content.push(theme.fg(\"muted\", \"Select a task to inspect its result.\"));\n\tright.push(...Array.from({ length: bodyHeight }, (_, i) => content[i] ?? \"\"), theme.fg(\"dim\", reading));\n\tconst rightPane = pane(right, rightWidth, focus === \"inspector\");\n\tlet panels = wide\n\t\t? pane(left, listWidth, focus === \"list\").map((line, i) => `${line} ${rightPane[i]}`)\n\t\t: pane(focus === \"list\" ? left : right, width, false);\n\n\tlet footer = \"\";\n\tconst addHint = (key: Keybinding, label: string, target?: Omit<TaskHit, \"x\" | \"y\" | \"width\">) => {\n\t\tconst text = `${hint(key)} ${label}`;\n\t\tconst x = visibleWidth(footer) + (footer ? 3 : 0);\n\t\tif (x + visibleWidth(text) > width) return;\n\t\tfooter += (footer ? \" · \" : \"\") + text;\n\t\tif (target) hits.push({ x, y: height - 1, width: visibleWidth(text), ...target });\n\t};\n\tif (mode.kind === \"help\") {\n\t\thits.length = 0;\n\t\tpanels = pane(helpLines(mode.viewport, hint, theme, width, height), width, false);\n\t\taddHint(\"tui.select.up\", `/ ${hint(\"tui.select.down\")} scroll`);\n\t\taddHint(\"tui.select.cancel\", \"back\", { cancel: true });\n\t} else if (mode.kind === \"confirmStop\") {\n\t\t// The question borrows only the footer row, so the task stays in view while confirming.\n\t\thits.length = 0;\n\t\tconst target = selection.all.find((task) => task.id === mode.taskId);\n\t\tconst source = cleanTaskText(target?.label ?? \"task\");\n\t\tconst confirm = `${hint(\"app.tasks.confirmStop\")} stop`;\n\t\tconst cancel = `${hint(\"tui.select.cancel\")} cancel`;\n\t\tconst actions = `${confirm} · ${cancel}`;\n\t\tconst room = width - visibleWidth(`Stop ${source} \"\"? ${actions}`);\n\t\tconst title = cleanTaskText(firstCommandLine(target?.title ?? mode.taskId));\n\t\tconst question = room >= 4 ? `Stop ${source} \"${truncateToWidth(title, room, \"…\")}\"? ` : `Stop ${source}? `;\n\t\tfooter = question + actions;\n\t\tconst x = visibleWidth(question);\n\t\thits.push(\n\t\t\t{ x, y: height - 1, width: visibleWidth(confirm), key: \"app.tasks.confirmStop\" },\n\t\t\t{ x: x + visibleWidth(confirm) + 3, y: height - 1, width: visibleWidth(cancel), cancel: true },\n\t\t);\n\t} else if (mode.kind === \"search\") {\n\t\t// Only search candidates and cancellation are clickable while locating a task.\n\t\tfor (let i = hits.length - 1; i >= 0; i--) if (!hits[i]!.taskId) hits.splice(i, 1);\n\t\taddHint(\"tui.select.up\", `/ ${hint(\"tui.select.down\")} choose`);\n\t\taddHint(\"tui.select.confirm\", \"locate\");\n\t\taddHint(\"tui.select.cancel\", \"cancel\", { cancel: true });\n\t} else {\n\t\taddHint(\"tui.select.up\", `/ ${hint(\"tui.select.down\")}${focus === \"list\" ? \" tasks\" : \" scroll\"}`);\n\t\tif (focus === \"list\") addHint(\"tui.select.confirm\", \"open\", { tab });\n\t\telse addHint(\"app.tasks.nextFocus\", \"tasks\", { key: \"app.tasks.nextFocus\" });\n\t\taddHint(\"tui.select.cancel\", \"close\", { cancel: true });\n\t\tif (focus === \"list\") addHint(\"app.tasks.search\", \"find\", { key: \"app.tasks.search\" });\n\t\telse {\n\t\t\taddHint(\"app.tasks.previousTab\", \"output\", { tab: \"output\" });\n\t\t\taddHint(\"app.tasks.nextTab\", \"details\", { tab: \"info\" });\n\t\t}\n\t\tif (task && isStoppable(task)) addHint(\"app.tasks.kill\", \"stop\", { key: \"app.tasks.kill\" });\n\t\tif (task && options.canDetach(task.id))\n\t\t\taddHint(\"app.tasks.detachSelected\", \"background\", { key: \"app.tasks.detachSelected\" });\n\t\taddHint(\"app.tasks.help\", \"keys\", { key: \"app.tasks.help\" });\n\t\t// Feedback borrows the hint row, so the hint hit targets stay live and the click that\n\t\t// dismisses it can act in the same gesture.\n\t\tif (options.feedback) footer = options.feedback;\n\t}\n\tresult.lines = [...panels, theme.fg(mode.kind === \"confirmStop\" ? \"warning\" : \"dim\", pad(footer, width))];\n\treturn result;\n}\n\n/** Controls grouped by purpose; actions sharing a key, such as list and inspector paging, share a row. */\nfunction helpLines(\n\thelp: TaskViewport,\n\thint: (key: Keybinding) => string,\n\ttheme: Theme,\n\twidth: number,\n\theight: number,\n): string[] {\n\tconst keys = (...bindings: Keybinding[]) => [...new Set(bindings.map(hint).filter(Boolean))].join(\" / \");\n\tconst listPage = keys(\"tui.select.pageUp\", \"tui.select.pageDown\");\n\tconst inspectorPage = keys(\"tui.editor.pageUp\", \"tui.editor.pageDown\");\n\tconst paging: Array<[string, string]> =\n\t\tlistPage === inspectorPage\n\t\t\t? [[listPage, \"Page the list or inspector\"]]\n\t\t\t: [\n\t\t\t\t\t[listPage, \"Page the list\"],\n\t\t\t\t\t[inspectorPage, \"Page the inspector\"],\n\t\t\t\t];\n\tconst sections: Array<[string, Array<[string, string]>]> = [\n\t\t[\n\t\t\t\"Navigate\",\n\t\t\t[\n\t\t\t\t[keys(\"tui.select.up\", \"tui.select.down\"), \"Select a task, or scroll the inspector\"],\n\t\t\t\t...paging,\n\t\t\t\t[keys(\"app.tasks.top\", \"app.tasks.bottom\"), \"Top or bottom\"],\n\t\t\t\t[hint(\"tui.select.confirm\"), \"Open the selected task\"],\n\t\t\t\t[keys(\"app.tasks.nextFocus\", \"app.tasks.previousFocus\"), \"Switch between list and inspector\"],\n\t\t\t],\n\t\t],\n\t\t[\n\t\t\t\"View\",\n\t\t\t[\n\t\t\t\t[keys(\"app.tasks.previousTab\", \"app.tasks.nextTab\"), \"Output or Details, in the inspector\"],\n\t\t\t\t[hint(\"app.tasks.follow\"), \"Follow the latest output, or load the final output\"],\n\t\t\t\t[hint(\"app.tasks.search\"), \"Find a task; Enter locates it, Esc restores the selection\"],\n\t\t\t],\n\t\t],\n\t\t[\n\t\t\t\"Act\",\n\t\t\t[\n\t\t\t\t[hint(\"app.tasks.kill\"), `Stop the selected task; ${hint(\"app.tasks.confirmStop\")} confirms`],\n\t\t\t\t[hint(\"app.tasks.detachSelected\"), \"Move the selected foreground task to the background\"],\n\t\t\t\t[hint(\"app.tasks.detach\"), \"Move every foreground execution to the background\"],\n\t\t\t\t[hint(\"tui.select.cancel\"), \"Close search, help or confirmation; otherwise the panel\"],\n\t\t\t],\n\t\t],\n\t];\n\tconst keyWidth = Math.max(...sections.flatMap(([, rows]) => rows.map(([key]) => visibleWidth(key)))) + 2;\n\tconst rows = sections.flatMap(([title, entries], index) => [\n\t\t...(index ? [\"\"] : []),\n\t\ttheme.fg(\"accent\", title),\n\t\t...entries.map(([key, label]) => ` ${key}${\" \".repeat(keyWidth - visibleWidth(key))}${label}`),\n\t]);\n\tconst body = [theme.fg(\"text\", \"Task controls\"), ...help.layout(rows, width - 2, height - 5), \"\"];\n\twhile (body.length < height - 3) body.push(\"\");\n\treturn body;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../../src/extensions/tasks/ui/list.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,2CAA2C,CAAC;AACvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAIhD,UAAU,OAAO;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAgBD,4FAA4F;AAC5F,qBAAa,QAAQ;IACpB,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,IAAI,CAAiB;IAC7B,OAAO,CAAC,UAAU,CAAC,CAAS;IAC5B,OAAO,CAAC,YAAY,CAAM;IAC1B,OAAO,CAAC,MAAM,CAAS;IACvB,aAAa,IAAI,IAAI;IAGrB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAG3B,MAAM,CAAC,SAAS,EAAE,aAAa,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,EAAE;IAgExF,IAAI,KAAK,IAAI,MAAM,CAOlB;CACD"}
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../../src/extensions/tasks/ui/list.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,2CAA2C,CAAC;AACvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAIhD,UAAU,OAAO;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAgBD,4FAA4F;AAC5F,qBAAa,QAAQ;IACpB,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,IAAI,CAAiB;IAC7B,OAAO,CAAC,UAAU,CAAC,CAAS;IAC5B,OAAO,CAAC,YAAY,CAAM;IAC1B,OAAO,CAAC,MAAM,CAAS;IACvB,aAAa,IAAI,IAAI;IAGrB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAG3B,MAAM,CAAC,SAAS,EAAE,aAAa,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,EAAE;IAgExF,IAAI,KAAK,IAAI,MAAM,CAOlB;CACD"}
@@ -1,8 +1,7 @@
1
1
  import { stripTerminalSequences, truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
2
2
  import { runtimeLabel } from "../../../core/tasks/format.js";
3
3
  import { isTaskTerminal } from "../../../core/tasks/types.js";
4
- import { statusMarker } from "../../../modes/interactive/components/status-marker.js";
5
- import { statusName } from "./task-view.js";
4
+ import { statusName, statusView } from "./status.js";
6
5
  import { cleanTaskText, firstCommandLine } from "./text.js";
7
6
  /** Spinner, ✓ and the error × are unique; every other status also needs its name. */
8
7
  const SELF_EVIDENT = new Set(["running", "completed", "failed"]);
@@ -46,7 +45,7 @@ export class TaskList {
46
45
  const selected = task.id === selection.state.selectedId;
47
46
  if (selected)
48
47
  selectedLine = rows.length;
49
- const marker = statusMarker(task.status, { now: Date.now() });
48
+ const marker = statusView(task.status, { now: Date.now() });
50
49
  const label = labels[index];
51
50
  const duplicate = titles.some((title, other) => other !== index && title === titles[index]);
52
51
  const meta = rowMeta(task, duplicate);
@@ -1 +1 @@
1
- {"version":3,"file":"list.js","sourceRoot":"","sources":["../../../../src/extensions/tasks/ui/list.ts"],"names":[],"mappings":"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","sourcesContent":["import { stripTerminalSequences, truncateToWidth, visibleWidth } from \"@earendil-works/pi-tui\";\nimport { runtimeLabel } from \"../../../core/tasks/format.ts\";\nimport { isTaskTerminal, type TaskSnapshot } from \"../../../core/tasks/types.ts\";\nimport { statusMarker } from \"../../../modes/interactive/components/status-marker.ts\";\nimport type { Theme } from \"../../../modes/interactive/theme/theme.ts\";\nimport type { TaskSelection } from \"./model.ts\";\nimport { statusName } from \"./task-view.ts\";\nimport { cleanTaskText, firstCommandLine } from \"./text.ts\";\n\ninterface ListRow {\n\ttext: string;\n\ttaskId?: string;\n}\n\n/** Spinner, ✓ and the error × are unique; every other status also needs its name. */\nconst SELF_EVIDENT = new Set([\"running\", \"completed\", \"failed\"]);\n\n/** Right-aligned row metadata: the status name when the glyph is ambiguous, a disambiguating ID, and runtime. */\nfunction rowMeta(task: TaskSnapshot, duplicate: boolean): string {\n\treturn [\n\t\tSELF_EVIDENT.has(task.status) ? \"\" : statusName(task.status),\n\t\tduplicate ? task.id.slice(-8) : \"\",\n\t\truntimeLabel(task),\n\t]\n\t\t.filter(Boolean)\n\t\t.join(\" · \");\n}\n\n/** Keeps list scrolling independent of selection, with an identity anchor on reordering. */\nexport class TaskList {\n\tprivate start = 0;\n\tprivate height = 1;\n\tprivate rows: ListRow[] = [];\n\tprivate selectedId?: string;\n\tprivate selectedLine = -1;\n\tprivate reveal = false;\n\tshowSelection(): void {\n\t\tthis.reveal = true;\n\t}\n\tscroll(delta: number): void {\n\t\tthis.start = Math.max(0, Math.min(Math.max(0, this.rows.length - this.height), this.start + delta));\n\t}\n\trender(selection: TaskSelection, theme: Theme, width: number, height: number): ListRow[] {\n\t\tconst rows: ListRow[] = [];\n\t\tconst labels = selection.rows.map((task) => cleanTaskText(task.label));\n\t\tconst labelWidth = Math.max(0, ...labels.map((label) => visibleWidth(label)));\n\t\tconst titles = selection.rows.map((task) => cleanTaskText(firstCommandLine(task.title)));\n\t\tlet group = \"\",\n\t\t\tselectedLine = -1;\n\t\tfor (const [index, task] of selection.rows.entries()) {\n\t\t\tconst nextGroup = isTaskTerminal(task.status) ? \"Finished\" : \"Active\";\n\t\t\tif (nextGroup !== group) {\n\t\t\t\trows.push({ text: theme.fg(\"dim\", nextGroup) });\n\t\t\t\tgroup = nextGroup;\n\t\t\t}\n\t\t\tconst selected = task.id === selection.state.selectedId;\n\t\t\tif (selected) selectedLine = rows.length;\n\t\t\tconst marker = statusMarker(task.status, { now: Date.now() });\n\t\t\tconst label = labels[index]!;\n\t\t\tconst duplicate = titles.some((title, other) => other !== index && title === titles[index]);\n\t\t\tconst meta = rowMeta(task, duplicate);\n\t\t\t// Labels form an aligned source column so titles start together.\n\t\t\tconst source = labelWidth ? `${label}${\" \".repeat(labelWidth - visibleWidth(label))} ` : \"\";\n\t\t\tconst head = visibleWidth(marker.glyph) + 1 + visibleWidth(source);\n\t\t\tconst title = truncateToWidth(titles[index]!, Math.max(1, width - head - visibleWidth(meta) - 1), \"…\");\n\t\t\tconst gap = Math.max(1, width - head - visibleWidth(title) - visibleWidth(meta));\n\t\t\tconst text = `${theme.fg(marker.color, marker.glyph)} ${theme.fg(\"dim\", source)}${theme.fg(\"text\", title)}${\" \".repeat(gap)}${theme.fg(\"muted\", meta)}`;\n\t\t\tconst padded = truncateToWidth(text, width, \"…\", true);\n\t\t\t// The system theme has no panel backgrounds until the terminal reports its colors.\n\t\t\trows.push({\n\t\t\t\ttext: !selected\n\t\t\t\t\t? padded\n\t\t\t\t\t: theme.getBgAnsi(\"selectedBg\") === \"\\x1b[49m\"\n\t\t\t\t\t\t? theme.style(stripTerminalSequences(padded), { inverse: true })\n\t\t\t\t\t\t: theme.bg(\"selectedBg\", padded),\n\t\t\t\ttaskId: task.id,\n\t\t\t});\n\t\t}\n\t\tif (!rows.length)\n\t\t\trows.push({ text: theme.fg(\"muted\", selection.query ? \"No matching tasks.\" : \"No retained tasks.\") });\n\t\tconst sameSelection = this.selectedId === selection.state.selectedId;\n\t\tconst selectedWasVisible =\n\t\t\tsameSelection &&\n\t\t\tthis.selectedLine >= this.start &&\n\t\t\tthis.selectedLine < this.start + this.height &&\n\t\t\tselectedLine >= 0;\n\t\tif (selectedWasVisible) this.start += selectedLine - this.selectedLine;\n\t\telse {\n\t\t\tconst anchor = this.rows[this.start]?.taskId;\n\t\t\tconst next = anchor ? rows.findIndex((row) => row.taskId === anchor) : -1;\n\t\t\tif (next >= 0) this.start = next;\n\t\t}\n\t\tif (selectedLine >= 0 && (!sameSelection || this.reveal || selectedWasVisible)) {\n\t\t\t// Revealing the first task of a group keeps its heading in view.\n\t\t\tconst top = rows[selectedLine - 1]?.taskId === undefined ? selectedLine - 1 : selectedLine;\n\t\t\tif (top < this.start) this.start = Math.max(0, top);\n\t\t\telse if (selectedLine >= this.start + height) this.start = selectedLine + 1 - height;\n\t\t}\n\t\tthis.start = Math.max(0, Math.min(Math.max(0, rows.length - height), this.start));\n\t\tthis.rows = rows;\n\t\tthis.height = height;\n\t\tthis.selectedId = selection.state.selectedId;\n\t\tthis.selectedLine = selectedLine;\n\t\tthis.reveal = false;\n\t\treturn rows.slice(this.start, this.start + height);\n\t}\n\tget range(): string {\n\t\tif (this.rows.length <= this.height) return \"\";\n\t\tconst ids = this.rows.flatMap((row) => (row.taskId ? [row.taskId] : []));\n\t\tconst visible = this.rows\n\t\t\t.slice(this.start, this.start + this.height)\n\t\t\t.flatMap((row) => (row.taskId ? [row.taskId] : []));\n\t\treturn `Tasks ${ids.indexOf(visible[0]!) + 1}-${ids.indexOf(visible.at(-1)!) + 1} of ${ids.length}`;\n\t}\n}\n"]}
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../../../src/extensions/tasks/ui/list.ts"],"names":[],"mappings":"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","sourcesContent":["import { stripTerminalSequences, truncateToWidth, visibleWidth } from \"@earendil-works/pi-tui\";\nimport { runtimeLabel } from \"../../../core/tasks/format.ts\";\nimport { isTaskTerminal, type TaskSnapshot, type TaskStatus } from \"../../../core/tasks/types.ts\";\nimport type { Theme } from \"../../../modes/interactive/theme/theme.ts\";\nimport type { TaskSelection } from \"./model.ts\";\nimport { statusName, statusView } from \"./status.ts\";\nimport { cleanTaskText, firstCommandLine } from \"./text.ts\";\n\ninterface ListRow {\n\ttext: string;\n\ttaskId?: string;\n}\n\n/** Spinner, ✓ and the error × are unique; every other status also needs its name. */\nconst SELF_EVIDENT = new Set<TaskStatus>([\"running\", \"completed\", \"failed\"]);\n\n/** Right-aligned row metadata: the status name when the glyph is ambiguous, a disambiguating ID, and runtime. */\nfunction rowMeta(task: TaskSnapshot, duplicate: boolean): string {\n\treturn [\n\t\tSELF_EVIDENT.has(task.status) ? \"\" : statusName(task.status),\n\t\tduplicate ? task.id.slice(-8) : \"\",\n\t\truntimeLabel(task),\n\t]\n\t\t.filter(Boolean)\n\t\t.join(\" · \");\n}\n\n/** Keeps list scrolling independent of selection, with an identity anchor on reordering. */\nexport class TaskList {\n\tprivate start = 0;\n\tprivate height = 1;\n\tprivate rows: ListRow[] = [];\n\tprivate selectedId?: string;\n\tprivate selectedLine = -1;\n\tprivate reveal = false;\n\tshowSelection(): void {\n\t\tthis.reveal = true;\n\t}\n\tscroll(delta: number): void {\n\t\tthis.start = Math.max(0, Math.min(Math.max(0, this.rows.length - this.height), this.start + delta));\n\t}\n\trender(selection: TaskSelection, theme: Theme, width: number, height: number): ListRow[] {\n\t\tconst rows: ListRow[] = [];\n\t\tconst labels = selection.rows.map((task) => cleanTaskText(task.label));\n\t\tconst labelWidth = Math.max(0, ...labels.map((label) => visibleWidth(label)));\n\t\tconst titles = selection.rows.map((task) => cleanTaskText(firstCommandLine(task.title)));\n\t\tlet group = \"\",\n\t\t\tselectedLine = -1;\n\t\tfor (const [index, task] of selection.rows.entries()) {\n\t\t\tconst nextGroup = isTaskTerminal(task.status) ? \"Finished\" : \"Active\";\n\t\t\tif (nextGroup !== group) {\n\t\t\t\trows.push({ text: theme.fg(\"dim\", nextGroup) });\n\t\t\t\tgroup = nextGroup;\n\t\t\t}\n\t\t\tconst selected = task.id === selection.state.selectedId;\n\t\t\tif (selected) selectedLine = rows.length;\n\t\t\tconst marker = statusView(task.status, { now: Date.now() });\n\t\t\tconst label = labels[index]!;\n\t\t\tconst duplicate = titles.some((title, other) => other !== index && title === titles[index]);\n\t\t\tconst meta = rowMeta(task, duplicate);\n\t\t\t// Labels form an aligned source column so titles start together.\n\t\t\tconst source = labelWidth ? `${label}${\" \".repeat(labelWidth - visibleWidth(label))} ` : \"\";\n\t\t\tconst head = visibleWidth(marker.glyph) + 1 + visibleWidth(source);\n\t\t\tconst title = truncateToWidth(titles[index]!, Math.max(1, width - head - visibleWidth(meta) - 1), \"…\");\n\t\t\tconst gap = Math.max(1, width - head - visibleWidth(title) - visibleWidth(meta));\n\t\t\tconst text = `${theme.fg(marker.color, marker.glyph)} ${theme.fg(\"dim\", source)}${theme.fg(\"text\", title)}${\" \".repeat(gap)}${theme.fg(\"muted\", meta)}`;\n\t\t\tconst padded = truncateToWidth(text, width, \"…\", true);\n\t\t\t// The system theme has no panel backgrounds until the terminal reports its colors.\n\t\t\trows.push({\n\t\t\t\ttext: !selected\n\t\t\t\t\t? padded\n\t\t\t\t\t: theme.getBgAnsi(\"selectedBg\") === \"\\x1b[49m\"\n\t\t\t\t\t\t? theme.style(stripTerminalSequences(padded), { inverse: true })\n\t\t\t\t\t\t: theme.bg(\"selectedBg\", padded),\n\t\t\t\ttaskId: task.id,\n\t\t\t});\n\t\t}\n\t\tif (!rows.length)\n\t\t\trows.push({ text: theme.fg(\"muted\", selection.query ? \"No matching tasks.\" : \"No retained tasks.\") });\n\t\tconst sameSelection = this.selectedId === selection.state.selectedId;\n\t\tconst selectedWasVisible =\n\t\t\tsameSelection &&\n\t\t\tthis.selectedLine >= this.start &&\n\t\t\tthis.selectedLine < this.start + this.height &&\n\t\t\tselectedLine >= 0;\n\t\tif (selectedWasVisible) this.start += selectedLine - this.selectedLine;\n\t\telse {\n\t\t\tconst anchor = this.rows[this.start]?.taskId;\n\t\t\tconst next = anchor ? rows.findIndex((row) => row.taskId === anchor) : -1;\n\t\t\tif (next >= 0) this.start = next;\n\t\t}\n\t\tif (selectedLine >= 0 && (!sameSelection || this.reveal || selectedWasVisible)) {\n\t\t\t// Revealing the first task of a group keeps its heading in view.\n\t\t\tconst top = rows[selectedLine - 1]?.taskId === undefined ? selectedLine - 1 : selectedLine;\n\t\t\tif (top < this.start) this.start = Math.max(0, top);\n\t\t\telse if (selectedLine >= this.start + height) this.start = selectedLine + 1 - height;\n\t\t}\n\t\tthis.start = Math.max(0, Math.min(Math.max(0, rows.length - height), this.start));\n\t\tthis.rows = rows;\n\t\tthis.height = height;\n\t\tthis.selectedId = selection.state.selectedId;\n\t\tthis.selectedLine = selectedLine;\n\t\tthis.reveal = false;\n\t\treturn rows.slice(this.start, this.start + height);\n\t}\n\tget range(): string {\n\t\tif (this.rows.length <= this.height) return \"\";\n\t\tconst ids = this.rows.flatMap((row) => (row.taskId ? [row.taskId] : []));\n\t\tconst visible = this.rows\n\t\t\t.slice(this.start, this.start + this.height)\n\t\t\t.flatMap((row) => (row.taskId ? [row.taskId] : []));\n\t\treturn `Tasks ${ids.indexOf(visible[0]!) + 1}-${ids.indexOf(visible.at(-1)!) + 1} of ${ids.length}`;\n\t}\n}\n"]}
@@ -5,7 +5,7 @@ import type { KeybindingsManager } from "../../../core/keybindings.ts";
5
5
  import { type TasksContext } from "../../../core/tasks/types.ts";
6
6
  import type { Theme } from "../../../modes/interactive/theme/theme.ts";
7
7
  import { type TasksPanelState } from "./model.ts";
8
- export type TasksManagerHost = Pick<TasksContext, "list" | "read" | "kill" | "subscribe" | "retain"> & Partial<Pick<TasksContext, "detach" | "enabled">>;
8
+ export type TasksManagerHost = Pick<TasksContext, "list" | "read" | "kill" | "subscribe" | "retain" | "canDetach" | "detach">;
9
9
  export interface TasksMenuOptions {
10
10
  tui: {
11
11
  requestRender(): void;
@@ -31,12 +31,9 @@ export declare class TasksMenu implements Component, Focusable {
31
31
  private readonly unsubscribe;
32
32
  private readonly pollTimer;
33
33
  private animationTimer?;
34
- private pendingKill?;
34
+ private mode;
35
35
  private feedback?;
36
36
  private focus;
37
- private searching;
38
- private beforeSearch?;
39
- private help?;
40
37
  private dirty;
41
38
  private tickQueued;
42
39
  private refreshQueued;
@@ -47,15 +44,27 @@ export declare class TasksMenu implements Component, Focusable {
47
44
  private sync;
48
45
  private queueTick;
49
46
  invalidate(): void;
50
- private clearKill;
47
+ /** The one place the mode changes; the search input is focused exactly while searching. */
48
+ private setMode;
49
+ /** Unwinds exactly one transient layer; from plain browsing it closes the panel. */
50
+ private cancel;
51
+ private close;
51
52
  private selectedChanged;
52
- private stop;
53
+ private requestStop;
54
+ private confirmStop;
55
+ private startSearch;
53
56
  private finishSearch;
54
57
  private action;
55
58
  private move;
56
59
  handleInput(data: string): void;
60
+ private helpInput;
61
+ private searchInput;
62
+ private confirmInput;
63
+ private browseInput;
57
64
  handleMouse(event: TuiMouseEvent): TuiMouseEventResult | undefined;
58
65
  render(width: number): string[];
66
+ /** The panel's selection can lag the runtime by a notification; a task that is gone cannot move. */
67
+ private canDetach;
59
68
  dispose(): void;
60
69
  }
61
70
  //# sourceMappingURL=manager.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../../../src/extensions/tasks/ui/manager.ts"],"names":[],"mappings":"AAAA,sGAAsG;AACtG,OAAO,mBAAmB,CAAC;AAC3B,OAAO,EACN,KAAK,SAAS,EACd,KAAK,SAAS,EAEd,KAAK,aAAa,EAClB,KAAK,mBAAmB,EACxB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAiB,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AACtF,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAEjF,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,2CAA2C,CAAC;AAIvE,OAAO,EAAiB,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAIjE,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAC,GACnG,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAC;AACnD,MAAM,WAAW,gBAAgB;IAChC,GAAG,EAAE;QAAE,aAAa,IAAI,IAAI,CAAC;QAAC,QAAQ,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC;IAC5E,KAAK,EAAE,KAAK,CAAC;IACb,WAAW,EAAE,IAAI,CAAC,kBAAkB,EAAE,SAAS,GAAG,SAAS,CAAC,CAAC;IAC7D,IAAI,EAAE,gBAAgB,CAAC;IACvB,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,OAAO,IAAI,IAAI,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AAgBD,qBAAa,SAAU,YAAW,SAAS,EAAE,SAAS;IACrD,OAAO,UAAS;IAChB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAmB;IAC3C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAgB;IAC1C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAgB;IAC1C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAkB;IACvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAQ;IAC/B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAa;IACzC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAiC;IAC3D,OAAO,CAAC,cAAc,CAAC,CAAiC;IACxD,OAAO,CAAC,WAAW,CAAC,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,CAAS;IAC1B,OAAO,CAAC,KAAK,CAAgC;IAC7C,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,YAAY,CAAC,CAA+C;IACpE,OAAO,CAAC,IAAI,CAAC,CAAe;IAC5B,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,MAAM,CAAC,CAAc;gBACjB,OAAO,EAAE,gBAAgB;IA0BrC,OAAO,CAAC,IAAI;IAqBZ,OAAO,CAAC,SAAS;IAmBjB,UAAU,IAAI,IAAI;IAGlB,OAAO,CAAC,SAAS;IAGjB,OAAO,CAAC,eAAe;IAMvB,OAAO,CAAC,IAAI;IAaZ,OAAO,CAAC,YAAY;IAWpB,OAAO,CAAC,MAAM;IA8Dd,OAAO,CAAC,IAAI;IAiBZ,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAkE/B,WAAW,CAAC,KAAK,EAAE,aAAa,GAAG,mBAAmB,GAAG,SAAS;IA2DlE,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IAoB/B,OAAO,IAAI,IAAI;CAUf"}
1
+ {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../../../src/extensions/tasks/ui/manager.ts"],"names":[],"mappings":"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"}