@astralyn/pi 1.4.4 → 1.4.6

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 (230) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/README.md +1 -0
  3. package/dist/bundle/chunks/chunk-5M3YJ54Z.js +82 -0
  4. package/dist/bundle/chunks/chunk-6QGV3IWD.js +6 -0
  5. package/dist/bundle/chunks/chunk-ALHAFUHP.js +7 -0
  6. package/dist/bundle/chunks/chunk-AXFWZIHH.js +4 -0
  7. package/dist/bundle/chunks/chunk-EYKC6ESU.js +2 -0
  8. package/dist/bundle/chunks/chunk-KDO6L76C.js +230 -0
  9. package/dist/bundle/chunks/chunk-RBTJBQWX.js +1500 -0
  10. package/dist/bundle/chunks/chunk-RLNMABLM.js +9 -0
  11. package/dist/bundle/chunks/cli-FH77R7JR.js +51 -0
  12. package/dist/bundle/chunks/execute-5ZQUS52M.js +505 -0
  13. package/dist/bundle/chunks/runtime-R5CMHJ5P.js +2 -0
  14. package/dist/bundle/chunks/virtual-modules-KCQU7LOC.js +2 -0
  15. package/dist/bundle/cli.js +1 -1
  16. package/dist/bundle/index.js +1 -1
  17. package/dist/bundle/rpc-entry.js +1 -1
  18. package/dist/core/agent-session.d.ts.map +1 -1
  19. package/dist/core/agent-session.js +2 -0
  20. package/dist/core/agent-session.js.map +1 -1
  21. package/dist/core/extensions/index.d.ts +1 -1
  22. package/dist/core/extensions/index.d.ts.map +1 -1
  23. package/dist/core/extensions/index.js.map +1 -1
  24. package/dist/core/extensions/runner.d.ts +2 -0
  25. package/dist/core/extensions/runner.d.ts.map +1 -1
  26. package/dist/core/extensions/runner.js +18 -0
  27. package/dist/core/extensions/runner.js.map +1 -1
  28. package/dist/core/extensions/types.d.ts +6 -0
  29. package/dist/core/extensions/types.d.ts.map +1 -1
  30. package/dist/core/extensions/types.js.map +1 -1
  31. package/dist/core/isolated-session.d.ts +23 -0
  32. package/dist/core/isolated-session.d.ts.map +1 -0
  33. package/dist/core/isolated-session.js +55 -0
  34. package/dist/core/isolated-session.js.map +1 -0
  35. package/dist/core/model-config.d.ts +1 -3
  36. package/dist/core/model-config.d.ts.map +1 -1
  37. package/dist/core/model-config.js +1 -3
  38. package/dist/core/model-config.js.map +1 -1
  39. package/dist/core/settings-manager.d.ts +4 -0
  40. package/dist/core/settings-manager.d.ts.map +1 -1
  41. package/dist/core/settings-manager.js +38 -0
  42. package/dist/core/settings-manager.js.map +1 -1
  43. package/dist/core/settings-schema.d.ts +1 -0
  44. package/dist/core/settings-schema.d.ts.map +1 -1
  45. package/dist/core/settings-schema.js +3 -0
  46. package/dist/core/settings-schema.js.map +1 -1
  47. package/dist/core/tasks/codec.d.ts +12 -0
  48. package/dist/core/tasks/codec.d.ts.map +1 -0
  49. package/dist/core/tasks/codec.js +139 -0
  50. package/dist/core/tasks/codec.js.map +1 -0
  51. package/dist/core/tasks/execution.d.ts +64 -0
  52. package/dist/core/tasks/execution.d.ts.map +1 -0
  53. package/dist/core/tasks/execution.js +272 -0
  54. package/dist/core/tasks/execution.js.map +1 -0
  55. package/dist/core/tasks/output.d.ts +12 -5
  56. package/dist/core/tasks/output.d.ts.map +1 -1
  57. package/dist/core/tasks/output.js +38 -37
  58. package/dist/core/tasks/output.js.map +1 -1
  59. package/dist/core/tasks/presentation.d.ts +14 -5
  60. package/dist/core/tasks/presentation.d.ts.map +1 -1
  61. package/dist/core/tasks/presentation.js +56 -185
  62. package/dist/core/tasks/presentation.js.map +1 -1
  63. package/dist/core/tasks/runtime.d.ts +9 -9
  64. package/dist/core/tasks/runtime.d.ts.map +1 -1
  65. package/dist/core/tasks/runtime.js +63 -252
  66. package/dist/core/tasks/runtime.js.map +1 -1
  67. package/dist/core/tasks/scheduler.d.ts +16 -0
  68. package/dist/core/tasks/scheduler.d.ts.map +1 -0
  69. package/dist/core/tasks/scheduler.js +42 -0
  70. package/dist/core/tasks/scheduler.js.map +1 -0
  71. package/dist/core/tasks/session.d.ts +1 -0
  72. package/dist/core/tasks/session.d.ts.map +1 -1
  73. package/dist/core/tasks/session.js +15 -27
  74. package/dist/core/tasks/session.js.map +1 -1
  75. package/dist/core/tasks/store.js +4 -4
  76. package/dist/core/tasks/store.js.map +1 -1
  77. package/dist/core/tasks/types.d.ts +63 -49
  78. package/dist/core/tasks/types.d.ts.map +1 -1
  79. package/dist/core/tasks/types.js +3 -9
  80. package/dist/core/tasks/types.js.map +1 -1
  81. package/dist/core/tools/render-utils.d.ts +6 -4
  82. package/dist/core/tools/render-utils.d.ts.map +1 -1
  83. package/dist/core/tools/render-utils.js +34 -14
  84. package/dist/core/tools/render-utils.js.map +1 -1
  85. package/dist/core/tools/shell-execution.js +4 -4
  86. package/dist/core/tools/shell-execution.js.map +1 -1
  87. package/dist/core/tools/shell-tool.d.ts.map +1 -1
  88. package/dist/core/tools/shell-tool.js +23 -30
  89. package/dist/core/tools/shell-tool.js.map +1 -1
  90. package/dist/core/usage-totals.d.ts +1 -3
  91. package/dist/core/usage-totals.d.ts.map +1 -1
  92. package/dist/core/usage-totals.js +17 -8
  93. package/dist/core/usage-totals.js.map +1 -1
  94. package/dist/extensions/agent/activity.d.ts +13 -0
  95. package/dist/extensions/agent/activity.d.ts.map +1 -0
  96. package/dist/extensions/agent/activity.js +75 -0
  97. package/dist/extensions/agent/activity.js.map +1 -0
  98. package/dist/extensions/agent/index.d.ts +4 -0
  99. package/dist/extensions/agent/index.d.ts.map +1 -0
  100. package/dist/extensions/agent/index.js +11 -0
  101. package/dist/extensions/agent/index.js.map +1 -0
  102. package/dist/extensions/agent/progress.d.ts +31 -0
  103. package/dist/extensions/agent/progress.d.ts.map +1 -0
  104. package/dist/extensions/agent/progress.js +145 -0
  105. package/dist/extensions/agent/progress.js.map +1 -0
  106. package/dist/extensions/agent/render.d.ts +6 -0
  107. package/dist/extensions/agent/render.d.ts.map +1 -0
  108. package/dist/extensions/agent/render.js +120 -0
  109. package/dist/extensions/agent/render.js.map +1 -0
  110. package/dist/extensions/agent/report.d.ts +9 -0
  111. package/dist/extensions/agent/report.d.ts.map +1 -0
  112. package/dist/extensions/agent/report.js +40 -0
  113. package/dist/extensions/agent/report.js.map +1 -0
  114. package/dist/extensions/agent/settings-panel.d.ts +43 -0
  115. package/dist/extensions/agent/settings-panel.d.ts.map +1 -0
  116. package/dist/extensions/agent/settings-panel.js +125 -0
  117. package/dist/extensions/agent/settings-panel.js.map +1 -0
  118. package/dist/extensions/agent/settings.d.ts +15 -0
  119. package/dist/extensions/agent/settings.d.ts.map +1 -0
  120. package/dist/extensions/agent/settings.js +201 -0
  121. package/dist/extensions/agent/settings.js.map +1 -0
  122. package/dist/extensions/agent/tool.d.ts +13 -0
  123. package/dist/extensions/agent/tool.d.ts.map +1 -0
  124. package/dist/extensions/agent/tool.js +84 -0
  125. package/dist/extensions/agent/tool.js.map +1 -0
  126. package/dist/extensions/agent/types.d.ts +43 -0
  127. package/dist/extensions/agent/types.d.ts.map +1 -0
  128. package/dist/extensions/agent/types.js +6 -0
  129. package/dist/extensions/agent/types.js.map +1 -0
  130. package/dist/extensions/agent/worker.d.ts +16 -0
  131. package/dist/extensions/agent/worker.d.ts.map +1 -0
  132. package/dist/extensions/agent/worker.js +68 -0
  133. package/dist/extensions/agent/worker.js.map +1 -0
  134. package/dist/extensions/codemode/execute.js +1 -1
  135. package/dist/extensions/codemode/execute.js.map +1 -1
  136. package/dist/extensions/codemode/execute.lazy.d.ts +2 -2
  137. package/dist/extensions/codemode/execute.lazy.d.ts.map +1 -1
  138. package/dist/extensions/codemode/execute.lazy.js +2 -2
  139. package/dist/extensions/codemode/execute.lazy.js.map +1 -1
  140. package/dist/extensions/index.d.ts.map +1 -1
  141. package/dist/extensions/index.js +2 -0
  142. package/dist/extensions/index.js.map +1 -1
  143. package/dist/extensions/mcp/cli.lazy.d.ts +2 -2
  144. package/dist/extensions/mcp/cli.lazy.d.ts.map +1 -1
  145. package/dist/extensions/mcp/cli.lazy.js +2 -2
  146. package/dist/extensions/mcp/cli.lazy.js.map +1 -1
  147. package/dist/extensions/mcp/index.d.ts.map +1 -1
  148. package/dist/extensions/mcp/index.js +2 -2
  149. package/dist/extensions/mcp/index.js.map +1 -1
  150. package/dist/extensions/mcp/runtime.lazy.d.ts +2 -2
  151. package/dist/extensions/mcp/runtime.lazy.d.ts.map +1 -1
  152. package/dist/extensions/mcp/runtime.lazy.js +2 -2
  153. package/dist/extensions/mcp/runtime.lazy.js.map +1 -1
  154. package/dist/extensions/provider/compat-fields.js +1 -1
  155. package/dist/extensions/provider/compat-fields.js.map +1 -1
  156. package/dist/extensions/tasks/tool/actions.d.ts.map +1 -1
  157. package/dist/extensions/tasks/tool/actions.js +1 -9
  158. package/dist/extensions/tasks/tool/actions.js.map +1 -1
  159. package/dist/extensions/tasks/tool/schema.js +1 -1
  160. package/dist/extensions/tasks/tool/schema.js.map +1 -1
  161. package/dist/extensions/tasks/tool/types.d.ts +2 -8
  162. package/dist/extensions/tasks/tool/types.d.ts.map +1 -1
  163. package/dist/extensions/tasks/tool/types.js +0 -2
  164. package/dist/extensions/tasks/tool/types.js.map +1 -1
  165. package/dist/extensions/tasks/ui/completion-render.d.ts.map +1 -1
  166. package/dist/extensions/tasks/ui/completion-render.js +27 -26
  167. package/dist/extensions/tasks/ui/completion-render.js.map +1 -1
  168. package/dist/extensions/tasks/ui/inspector.d.ts +5 -3
  169. package/dist/extensions/tasks/ui/inspector.d.ts.map +1 -1
  170. package/dist/extensions/tasks/ui/inspector.js +18 -6
  171. package/dist/extensions/tasks/ui/inspector.js.map +1 -1
  172. package/dist/extensions/tasks/ui/layout.d.ts.map +1 -1
  173. package/dist/extensions/tasks/ui/layout.js +111 -75
  174. package/dist/extensions/tasks/ui/layout.js.map +1 -1
  175. package/dist/extensions/tasks/ui/list.d.ts.map +1 -1
  176. package/dist/extensions/tasks/ui/list.js +43 -28
  177. package/dist/extensions/tasks/ui/list.js.map +1 -1
  178. package/dist/extensions/tasks/ui/manager.d.ts.map +1 -1
  179. package/dist/extensions/tasks/ui/manager.js +8 -2
  180. package/dist/extensions/tasks/ui/manager.js.map +1 -1
  181. package/dist/extensions/tasks/ui/model.d.ts +4 -0
  182. package/dist/extensions/tasks/ui/model.d.ts.map +1 -1
  183. package/dist/extensions/tasks/ui/model.js +12 -1
  184. package/dist/extensions/tasks/ui/model.js.map +1 -1
  185. package/dist/extensions/tasks/ui/render.js +3 -4
  186. package/dist/extensions/tasks/ui/render.js.map +1 -1
  187. package/dist/extensions/tasks/ui/task-view.d.ts +0 -5
  188. package/dist/extensions/tasks/ui/task-view.d.ts.map +1 -1
  189. package/dist/extensions/tasks/ui/task-view.js +0 -7
  190. package/dist/extensions/tasks/ui/task-view.js.map +1 -1
  191. package/dist/extensions/tasks/ui/tree.js +1 -1
  192. package/dist/extensions/tasks/ui/tree.js.map +1 -1
  193. package/dist/extensions/tasks/ui/views.d.ts +10 -6
  194. package/dist/extensions/tasks/ui/views.d.ts.map +1 -1
  195. package/dist/extensions/tasks/ui/views.js +64 -28
  196. package/dist/extensions/tasks/ui/views.js.map +1 -1
  197. package/dist/index.d.ts +2 -1
  198. package/dist/index.d.ts.map +1 -1
  199. package/dist/index.js.map +1 -1
  200. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
  201. package/dist/modes/interactive/components/keybinding-hints.js +2 -1
  202. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
  203. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  204. package/dist/modes/interactive/components/model-selector.js +7 -4
  205. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  206. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  207. package/dist/modes/interactive/components/thinking-selector.js +10 -3
  208. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  209. package/docs/bundled/README.md +1 -0
  210. package/docs/bundled/extensions/agent.md +68 -0
  211. package/docs/bundled/extensions/statusline.md +1 -1
  212. package/docs/bundled/tasks.md +15 -14
  213. package/docs/docs.json +4 -0
  214. package/docs/extensions.md +33 -6
  215. package/docs/sdk.md +2 -2
  216. package/docs/session-format.md +27 -23
  217. package/npm-shrinkwrap.json +2 -2
  218. package/package.json +1 -1
  219. package/schemas/settings.schema.json +12 -0
  220. package/dist/bundle/chunks/chunk-SBVVM3NV.js +0 -2361
  221. package/dist/bundle/chunks/chunk-VGSZTBVJ.js +0 -2
  222. package/dist/bundle/chunks/virtual-modules-ETYFHSUG.js +0 -2
  223. package/dist/core/tasks/history.d.ts +0 -4
  224. package/dist/core/tasks/history.d.ts.map +0 -1
  225. package/dist/core/tasks/history.js +0 -121
  226. package/dist/core/tasks/history.js.map +0 -1
  227. package/dist/extensions/codemode/search.d.ts +0 -33
  228. package/dist/extensions/codemode/search.d.ts.map +0 -1
  229. package/dist/extensions/codemode/search.js +0 -117
  230. package/dist/extensions/codemode/search.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"completion-render.js","sourceRoot":"","sources":["../../../../src/extensions/tasks/ui/completion-render.ts"],"names":[],"mappings":"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","sourcesContent":["/** Human-facing completion cards. The persisted context message remains untouched. */\nimport { type Component, stripTerminalSequences, truncateToWidth, wrapTextWithAnsi } from \"@earendil-works/pi-tui\";\nimport type { MessageRenderOptions } from \"../../../core/extensions/types.ts\";\nimport type { CustomMessage } from \"../../../core/messages.ts\";\nimport { runtimeLabel } from \"../../../core/tasks/format.ts\";\nimport { readTaskCompletion } from \"../../../core/tasks/presentation.ts\";\nimport type { TaskTerminalStatus } from \"../../../core/tasks/types.ts\";\nimport { type StatusMarkerColor, statusMarker } from \"../../../modes/interactive/components/status-marker.ts\";\nimport type { Theme } from \"../../../modes/interactive/theme/theme.ts\";\nimport { FramedComponent } from \"../../../modes/interactive/tool-view/style.ts\";\nimport { sanitizeBinaryOutput } from \"../../../utils/shell.ts\";\nimport { statusName } from \"./task-view.ts\";\n\nconst SOURCE_LIMIT = 64 * 1024;\nconst CARD_ROWS = 128;\nconst OUTPUT_ROWS = 20;\nconst SHELL_NAMES: Record<string, string> = { bash: \"Bash\", powershell: \"PowerShell\" };\n\ninterface CompletionView {\n\ttitle?: string;\n\tduration?: string;\n\texitCode?: number | null;\n\tkind?: string;\n\tstatus?: TaskTerminalStatus;\n\tid?: string;\n\tcommand?: string;\n\tcwd?: string;\n\tpath?: string;\n\tdiagnostic?: string;\n\t/** Undefined for an unreadable message, whose saved content is shown instead. */\n\toutput?: string;\n\tbody: string;\n\ttruncated: boolean;\n}\n\nfunction clean(text: string): string {\n\treturn sanitizeBinaryOutput(stripTerminalSequences(text)).replace(/\\r\\n?/g, \"\\n\");\n}\n\nfunction savedText(message: CustomMessage<unknown>): { text: string; clipped: boolean } {\n\t// 64K is a UTF-16 code-unit display budget, not a UTF-8 byte promise; the block\n\t// cap bounds iteration itself so many empty/non-text blocks cannot spin here.\n\tconst MAX_SOURCE_BLOCKS = 256;\n\tconst content = message.content;\n\tlet text = \"\";\n\tlet clipped = false;\n\tif (typeof content === \"string\") {\n\t\ttext = content.slice(0, SOURCE_LIMIT);\n\t\tclipped = content.length > SOURCE_LIMIT;\n\t} else if (Array.isArray(content)) {\n\t\tlet visited = 0;\n\t\tfor (const block of content) {\n\t\t\tif (++visited > MAX_SOURCE_BLOCKS) {\n\t\t\t\tclipped = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (!block || block.type !== \"text\" || typeof block.text !== \"string\") continue;\n\t\t\tconst next = `${text ? \"\\n\" : \"\"}${block.text.slice(0, SOURCE_LIMIT + 1)}`;\n\t\t\tconst remaining = SOURCE_LIMIT - text.length;\n\t\t\ttext += next.slice(0, remaining);\n\t\t\tif (next.length > remaining || block.text.length > SOURCE_LIMIT) {\n\t\t\t\tclipped = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\treturn { text: clean(text), clipped };\n}\n\nfunction completionView(message: CustomMessage<unknown>): CompletionView {\n\tconst snapshot = readTaskCompletion(message.details);\n\tif (!snapshot) {\n\t\tconst { text, clipped } = savedText(message);\n\t\treturn { body: text, truncated: clipped };\n\t}\n\treturn {\n\t\ttitle: clean(snapshot.title),\n\t\tduration: runtimeLabel(snapshot),\n\t\tkind: snapshot.kind,\n\t\tstatus: snapshot.status,\n\t\tid: clean(snapshot.taskId),\n\t\texitCode: snapshot.exitCode,\n\t\tcommand: snapshot.command === undefined ? undefined : clean(snapshot.command.text),\n\t\tcwd: snapshot.cwd === undefined ? undefined : clean(snapshot.cwd),\n\t\tpath: snapshot.outputPath === undefined ? undefined : clean(snapshot.outputPath),\n\t\tdiagnostic: snapshot.error === undefined ? undefined : clean(snapshot.error),\n\t\toutput: clean(snapshot.output.text),\n\t\tbody: \"\",\n\t\ttruncated: snapshot.output.truncated || snapshot.command?.truncated === true,\n\t};\n}\n\nfunction color(status: string | undefined): StatusMarkerColor {\n\treturn status === undefined ? \"muted\" : statusMarker(status).color;\n}\nfunction shortId(id: string): string {\n\treturn id.replace(/^(.+)-([0-9a-f]{8})-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i, \"$1-$2\");\n}\n\nclass CompletionCard implements Component {\n\tprivate readonly view: CompletionView;\n\tprivate readonly options: MessageRenderOptions;\n\tprivate readonly theme: Theme;\n\tconstructor(view: CompletionView, options: MessageRenderOptions, theme: Theme) {\n\t\tthis.view = view;\n\t\tthis.options = options;\n\t\tthis.theme = theme;\n\t}\n\tinvalidate(): void {}\n\trender(width: number): string[] {\n\t\tif (width < 1) return [];\n\t\tconst chrome = new FramedComponent(\n\t\t\t{ render: (contentWidth) => this.renderContent(contentWidth), invalidate() {} },\n\t\t\t\"header\",\n\t\t\t() => color(this.view.status),\n\t\t);\n\t\t// The gutter reserves its own cells; clip defensively for one-cell terminals.\n\t\treturn chrome.render(width).map((line) => truncateToWidth(line, width, \"\"));\n\t}\n\tprivate renderContent(width: number): string[] {\n\t\t// The chrome clamps to ≥1 already; keep the padding arithmetic safe regardless.\n\t\tif (!Number.isFinite(width) || width < 1) return [];\n\t\tconst view = this.view;\n\t\tconst theme = this.theme;\n\t\tconst options = this.options;\n\t\t// The native dot/rail replaces the default one-cell custom-message inset.\n\t\t// Additional configured padding stays inside the chrome, never shifting the dot.\n\t\tconst padding = Math.min(Math.max(0, Math.floor(options.outputPad || 0) - 1), Math.floor((width - 1) / 2));\n\t\tconst inner = width - padding * 2;\n\t\tconst indent = inner >= 3 ? \" \" : \"\";\n\t\tconst bodyWidth = Math.max(1, inner - indent.length);\n\t\tconst lines: string[] = [];\n\t\tconst status = view.status ? statusName(view.status) : \"Result received\";\n\t\tconst kind = view.kind === undefined ? \"Notification\" : (SHELL_NAMES[view.kind] ?? view.kind);\n\t\tlines.push(\n\t\t\t`${theme.fg(\"toolTitle\", theme.bold(kind))}${theme.fg(\"muted\", ` · Background ${status.toLowerCase()}${view.duration ? ` · ${view.duration}` : \"\"}`)}${view.id ? theme.fg(\"dim\", ` · ${shortId(view.id)}`) : \"\"}`,\n\t\t);\n\t\tconst summary = view.command ? `$ ${view.command.split(\"\\n\")[0]}` : view.title;\n\t\tif (!options.expanded) {\n\t\t\tif (summary) lines.push(theme.fg(\"toolOutput\", summary));\n\t\t\tif (view.diagnostic) lines.push(theme.fg(color(view.status), view.diagnostic));\n\t\t} else {\n\t\t\tif (view.truncated) {\n\t\t\t\tlines.push(theme.fg(\"warning\", \"The saved result is truncated; this is not the complete original output.\"));\n\t\t\t}\n\t\t\tconst section = (title: string, text: string, limit: number, tail = false, error = false) => {\n\t\t\t\tlines.push(\"\", theme.fg(\"muted\", theme.bold(title)));\n\t\t\t\tconst rendered = wrapTextWithAnsi(text, bodyWidth).map((line) =>\n\t\t\t\t\ttheme.fg(error ? \"error\" : \"toolOutput\", line),\n\t\t\t\t);\n\t\t\t\tconst omitted = Math.max(0, rendered.length - limit);\n\t\t\t\tconst selected = tail ? rendered.slice(-limit) : rendered.slice(0, limit);\n\t\t\t\tif (tail && omitted) lines.push(theme.fg(\"dim\", `${indent}… ${omitted} earlier display lines omitted`));\n\t\t\t\tfor (const line of selected) lines.push(indent + line);\n\t\t\t\tif (!tail && omitted) lines.push(theme.fg(\"dim\", `${indent}… ${omitted} more display lines omitted`));\n\t\t\t};\n\t\t\tif (view.output === undefined) section(\"Details\", view.body || \"No text result.\", 36);\n\t\t\telse {\n\t\t\t\tif (view.command) section(\"Command\", view.command, 8);\n\t\t\t\telse if (view.title) section(\"Task\", view.title, 4);\n\t\t\t\tif (view.cwd) section(\"Directory\", view.cwd, 2);\n\t\t\t\tsection(\n\t\t\t\t\tview.status === \"failed\" || view.status === \"timeout\" ? \"Error\" : \"Result\",\n\t\t\t\t\t`${view.diagnostic ?? status}${view.exitCode !== undefined ? ` · ${view.exitCode === null ? \"terminated by signal\" : `exit ${view.exitCode}`}` : \"\"}`,\n\t\t\t\t\t4,\n\t\t\t\t\tfalse,\n\t\t\t\t\tview.status === \"failed\",\n\t\t\t\t);\n\t\t\t\tsection(\"Output\", !view.output.trim() ? \"No output.\" : view.output, OUTPUT_ROWS, true);\n\t\t\t\tif (view.path) section(\"Log\", view.path, 4);\n\t\t\t}\n\t\t\tif (view.id) {\n\t\t\t\tlines.push(\"\", ...wrapTextWithAnsi(`Task ID: ${view.id}`, inner).map((line) => theme.fg(\"dim\", line)));\n\t\t\t}\n\t\t\tlines.push(theme.fg(\"dim\", \"Preview of the saved result.\"));\n\t\t}\n\t\tconst bounded =\n\t\t\tlines.length > CARD_ROWS\n\t\t\t\t? [\n\t\t\t\t\t\t...lines.slice(0, CARD_ROWS - 1),\n\t\t\t\t\t\ttheme.fg(\"dim\", \"… card shortened; use tasks read for retained output\"),\n\t\t\t\t\t]\n\t\t\t\t: lines;\n\t\treturn bounded.map((line) => \" \".repeat(padding) + truncateToWidth(line, inner, \"…\") + \" \".repeat(padding));\n\t}\n}\n\n/** Always return a compact, replay-safe component, including for unknown historical formats. */\nexport function renderTaskCompletion(\n\tmessage: CustomMessage<unknown>,\n\toptions: MessageRenderOptions,\n\ttheme: Theme,\n): Component {\n\tlet view: CompletionView;\n\ttry {\n\t\tview = completionView(message);\n\t} catch {\n\t\tview = {\n\t\t\tbody: \"The saved notification could not be interpreted. Its original message remains in session history.\",\n\t\t\ttruncated: false,\n\t\t};\n\t}\n\treturn new CompletionCard(view, options, theme);\n}\n"]}
1
+ {"version":3,"file":"completion-render.js","sourceRoot":"","sources":["../../../../src/extensions/tasks/ui/completion-render.ts"],"names":[],"mappings":"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","sourcesContent":["/** Human-facing completion cards. The persisted context message remains untouched. */\nimport { type Component, stripTerminalSequences, truncateToWidth, wrapTextWithAnsi } from \"@earendil-works/pi-tui\";\nimport type { MessageRenderOptions } from \"../../../core/extensions/types.ts\";\nimport type { CustomMessage } from \"../../../core/messages.ts\";\nimport { readVersionedTask } from \"../../../core/tasks/codec.ts\";\nimport { runtimeLabel } from \"../../../core/tasks/format.ts\";\nimport type { TaskFact, TaskStatus } from \"../../../core/tasks/types.ts\";\nimport { type StatusMarkerColor, statusMarker } from \"../../../modes/interactive/components/status-marker.ts\";\nimport type { Theme } from \"../../../modes/interactive/theme/theme.ts\";\nimport { FramedComponent } from \"../../../modes/interactive/tool-view/style.ts\";\nimport { sanitizeBinaryOutput } from \"../../../utils/shell.ts\";\nimport { statusName } from \"./task-view.ts\";\n\nconst SOURCE_LIMIT = 64 * 1024;\nconst CARD_ROWS = 128;\nconst OUTPUT_ROWS = 20;\ninterface CompletionView {\n\tlabel?: string;\n\ttitle?: string;\n\tduration?: string;\n\tstatus?: TaskStatus;\n\tid?: string;\n\tinput?: { label: string; text: string };\n\tfacts: TaskFact[];\n\tpath?: string;\n\tdiagnostic?: string;\n\t/** Undefined for an unreadable message, whose saved content is shown instead. */\n\toutput?: string;\n\t/** A report previews its beginning; a log previews its end. */\n\treport?: boolean;\n\tbody: string;\n\ttruncated: boolean;\n}\n\nfunction clean(text: string): string {\n\treturn sanitizeBinaryOutput(stripTerminalSequences(text)).replace(/\\r\\n?/g, \"\\n\");\n}\n\nfunction savedText(message: CustomMessage<unknown>): { text: string; clipped: boolean } {\n\t// 64K is a UTF-16 code-unit display budget, not a UTF-8 byte promise; the block\n\t// cap bounds iteration itself so many empty/non-text blocks cannot spin here.\n\tconst MAX_SOURCE_BLOCKS = 256;\n\tconst content = message.content;\n\tlet text = \"\";\n\tlet clipped = false;\n\tif (typeof content === \"string\") {\n\t\ttext = content.slice(0, SOURCE_LIMIT);\n\t\tclipped = content.length > SOURCE_LIMIT;\n\t} else if (Array.isArray(content)) {\n\t\tlet visited = 0;\n\t\tfor (const block of content) {\n\t\t\tif (++visited > MAX_SOURCE_BLOCKS) {\n\t\t\t\tclipped = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (!block || block.type !== \"text\" || typeof block.text !== \"string\") continue;\n\t\t\tconst next = `${text ? \"\\n\" : \"\"}${block.text.slice(0, SOURCE_LIMIT + 1)}`;\n\t\t\tconst remaining = SOURCE_LIMIT - text.length;\n\t\t\ttext += next.slice(0, remaining);\n\t\t\tif (next.length > remaining || block.text.length > SOURCE_LIMIT) {\n\t\t\t\tclipped = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\treturn { text: clean(text), clipped };\n}\n\nfunction completionView(message: CustomMessage<unknown>): CompletionView {\n\tconst task = readVersionedTask(message.details);\n\tif (!task) {\n\t\tconst { text, clipped } = savedText(message);\n\t\treturn { body: text, truncated: clipped, facts: [] };\n\t}\n\treturn {\n\t\tlabel: clean(task.label),\n\t\ttitle: clean(task.title),\n\t\tduration: runtimeLabel(task),\n\t\tstatus: task.status,\n\t\tid: clean(task.id),\n\t\tinput: task.input && { label: clean(task.input.label), text: clean(task.input.text) },\n\t\tfacts: (task.facts ?? []).map(([label, value]) => [clean(label), clean(value)]),\n\t\tpath: task.outputPath === undefined ? undefined : clean(task.outputPath),\n\t\tdiagnostic: task.error === undefined ? undefined : clean(task.error),\n\t\toutput: clean(task.result?.text ?? \"\"),\n\t\treport: task.output === \"report\",\n\t\tbody: \"\",\n\t\ttruncated: task.result?.truncated === true || task.input?.truncated === true,\n\t};\n}\n\nfunction color(status: string | undefined): StatusMarkerColor {\n\treturn status === undefined ? \"muted\" : statusMarker(status).color;\n}\nfunction shortId(id: string): string {\n\treturn id.replace(/^(.+)-([0-9a-f]{8})-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i, \"$1-$2\");\n}\n\nclass CompletionCard implements Component {\n\tprivate readonly view: CompletionView;\n\tprivate readonly options: MessageRenderOptions;\n\tprivate readonly theme: Theme;\n\tconstructor(view: CompletionView, options: MessageRenderOptions, theme: Theme) {\n\t\tthis.view = view;\n\t\tthis.options = options;\n\t\tthis.theme = theme;\n\t}\n\tinvalidate(): void {}\n\trender(width: number): string[] {\n\t\tif (width < 1) return [];\n\t\tconst chrome = new FramedComponent(\n\t\t\t{ render: (contentWidth) => this.renderContent(contentWidth), invalidate() {} },\n\t\t\t\"header\",\n\t\t\t() => color(this.view.status),\n\t\t);\n\t\t// The gutter reserves its own cells; clip defensively for one-cell terminals.\n\t\treturn chrome.render(width).map((line) => truncateToWidth(line, width, \"\"));\n\t}\n\tprivate renderContent(width: number): string[] {\n\t\t// The chrome clamps to ≥1 already; keep the padding arithmetic safe regardless.\n\t\tif (!Number.isFinite(width) || width < 1) return [];\n\t\tconst view = this.view;\n\t\tconst theme = this.theme;\n\t\tconst options = this.options;\n\t\t// The native dot/rail replaces the default one-cell custom-message inset.\n\t\t// Additional configured padding stays inside the chrome, never shifting the dot.\n\t\tconst padding = Math.min(Math.max(0, Math.floor(options.outputPad || 0) - 1), Math.floor((width - 1) / 2));\n\t\tconst inner = width - padding * 2;\n\t\tconst indent = inner >= 3 ? \" \" : \"\";\n\t\tconst bodyWidth = Math.max(1, inner - indent.length);\n\t\tconst lines: string[] = [];\n\t\tconst status = view.status ? statusName(view.status) : \"Result received\";\n\t\tlines.push(\n\t\t\t`${theme.fg(\"toolTitle\", theme.bold(view.label ?? \"Notification\"))}${theme.fg(\"muted\", ` · Background ${status.toLowerCase()}${view.duration ? ` · ${view.duration}` : \"\"}`)}${view.id ? theme.fg(\"dim\", ` · ${shortId(view.id)}`) : \"\"}`,\n\t\t);\n\t\tconst summary = view.title?.split(\"\\n\").find((line) => line.trim()) ?? view.title;\n\t\tif (!options.expanded) {\n\t\t\tif (summary) lines.push(theme.fg(\"toolOutput\", summary));\n\t\t\tif (view.diagnostic) lines.push(theme.fg(color(view.status), view.diagnostic));\n\t\t} else {\n\t\t\tif (view.truncated) {\n\t\t\t\tlines.push(theme.fg(\"warning\", \"The saved result is truncated; this is not the complete original output.\"));\n\t\t\t}\n\t\t\tconst section = (title: string, text: string, limit: number, tail = false, error = false) => {\n\t\t\t\tlines.push(\"\", theme.fg(\"muted\", theme.bold(title)));\n\t\t\t\tconst rendered = wrapTextWithAnsi(text, bodyWidth).map((line) =>\n\t\t\t\t\ttheme.fg(error ? \"error\" : \"toolOutput\", line),\n\t\t\t\t);\n\t\t\t\tconst omitted = Math.max(0, rendered.length - limit);\n\t\t\t\tconst selected = tail ? rendered.slice(-limit) : rendered.slice(0, limit);\n\t\t\t\tif (tail && omitted) lines.push(theme.fg(\"dim\", `${indent}… ${omitted} earlier display lines omitted`));\n\t\t\t\tfor (const line of selected) lines.push(indent + line);\n\t\t\t\tif (!tail && omitted) lines.push(theme.fg(\"dim\", `${indent}… ${omitted} more display lines omitted`));\n\t\t\t};\n\t\t\tif (view.output === undefined) section(\"Details\", view.body || \"No text result.\", 36);\n\t\t\telse {\n\t\t\t\tif (view.input) section(view.input.label, view.input.text, 8);\n\t\t\t\telse if (view.title) section(\"Task\", view.title, 4);\n\t\t\t\tif (view.facts.length) {\n\t\t\t\t\tconst width = Math.max(...view.facts.map(([label]) => label.length)) + 1;\n\t\t\t\t\tsection(\"Details\", view.facts.map(([label, value]) => `${label.padEnd(width)}${value}`).join(\"\\n\"), 8);\n\t\t\t\t}\n\t\t\t\tsection(\n\t\t\t\t\tview.status === \"failed\" || view.status === \"timeout\" ? \"Error\" : \"Result\",\n\t\t\t\t\tview.diagnostic ?? status,\n\t\t\t\t\t4,\n\t\t\t\t\tfalse,\n\t\t\t\t\tview.status === \"failed\",\n\t\t\t\t);\n\t\t\t\tsection(\"Output\", !view.output.trim() ? \"No output.\" : view.output, OUTPUT_ROWS, !view.report);\n\t\t\t\tif (view.path) section(\"Log\", view.path, 4);\n\t\t\t}\n\t\t\tif (view.id) {\n\t\t\t\tlines.push(\"\", ...wrapTextWithAnsi(`Task ID: ${view.id}`, inner).map((line) => theme.fg(\"dim\", line)));\n\t\t\t}\n\t\t\tlines.push(theme.fg(\"dim\", \"Preview of the saved result.\"));\n\t\t}\n\t\tconst bounded =\n\t\t\tlines.length > CARD_ROWS\n\t\t\t\t? [\n\t\t\t\t\t\t...lines.slice(0, CARD_ROWS - 1),\n\t\t\t\t\t\ttheme.fg(\"dim\", \"… card shortened; use tasks read for retained output\"),\n\t\t\t\t\t]\n\t\t\t\t: lines;\n\t\treturn bounded.map((line) => \" \".repeat(padding) + truncateToWidth(line, inner, \"…\") + \" \".repeat(padding));\n\t}\n}\n\n/** Always return a compact, replay-safe component, including for unknown historical formats. */\nexport function renderTaskCompletion(\n\tmessage: CustomMessage<unknown>,\n\toptions: MessageRenderOptions,\n\ttheme: Theme,\n): Component {\n\tlet view: CompletionView;\n\ttry {\n\t\tview = completionView(message);\n\t} catch {\n\t\tview = {\n\t\t\tbody: \"The saved notification could not be interpreted. Its original message remains in session history.\",\n\t\t\ttruncated: false,\n\t\t\tfacts: [],\n\t\t};\n\t}\n\treturn new CompletionCard(view, options, theme);\n}\n"]}
@@ -1,6 +1,5 @@
1
1
  import type { TaskRead, TaskSnapshot, TasksContext } from "../../../core/tasks/types.ts";
2
2
  import type { Theme } from "../../../modes/interactive/theme/theme.ts";
3
- import type { TasksTab } from "./model.ts";
4
3
  import { TaskViewport } from "./viewport.ts";
5
4
  interface ReadingPosition {
6
5
  info: TaskViewport;
@@ -21,14 +20,17 @@ export declare class TaskInspector {
21
20
  private reading;
22
21
  private disposed;
23
22
  /** Snapshots are immutable, so identity tells when the lines must be rebuilt. */
24
- private cache?;
23
+ private outputCache?;
24
+ private detailCache?;
25
25
  constructor(options: InspectorOptions);
26
26
  get position(): ReadingPosition;
27
27
  select(task: TaskSnapshot | undefined): void;
28
28
  prune(ids: ReadonlySet<string>): void;
29
29
  invalidate(): void;
30
30
  refresh(): Promise<void>;
31
- lines(tab: TasksTab): string[];
31
+ output(width: number): string[];
32
+ /** `status` carries the runtime, so Details rebuild at most once per displayed tick. */
33
+ details(status: string): string[];
32
34
  dispose(): void;
33
35
  }
34
36
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"inspector.d.ts","sourceRoot":"","sources":["../../../../src/extensions/tasks/ui/inspector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAEzF,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,2CAA2C,CAAC;AACvE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAG7C,UAAU,eAAe;IACxB,IAAI,EAAE,YAAY,CAAC;IACnB,MAAM,EAAE,YAAY,CAAC;IACrB,IAAI,CAAC,EAAE,QAAQ,CAAC;CAChB;AACD,UAAU,gBAAgB;IACzB,IAAI,EAAE,IAAI,CAAC,YAAY,EAAE,MAAM,GAAG,QAAQ,CAAC,CAAC;IAC5C,KAAK,EAAE,KAAK,CAAC;IACb,aAAa,IAAI,IAAI,CAAC;CACtB;AAED,8FAA8F;AAC9F,qBAAa,aAAa;IACzB,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAmB;IAC3C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAsC;IAChE,OAAO,CAAC,OAAO,CAAC,CAAa;IAC7B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAS;IACzB,iFAAiF;IACjF,OAAO,CAAC,KAAK,CAAC,CAA4D;gBAC9D,OAAO,EAAE,gBAAgB;IAGrC,IAAI,QAAQ,IAAI,eAAe,CAQ9B;IACD,MAAM,CAAC,IAAI,EAAE,YAAY,GAAG,SAAS,GAAG,IAAI;IAU5C,KAAK,CAAC,GAAG,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,IAAI;IAGrC,UAAU,IAAI,IAAI;IAGZ,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IA0B9B,KAAK,CAAC,GAAG,EAAE,QAAQ,GAAG,MAAM,EAAE;IAQ9B,OAAO,IAAI,IAAI;CAOf"}
1
+ {"version":3,"file":"inspector.d.ts","sourceRoot":"","sources":["../../../../src/extensions/tasks/ui/inspector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAEzF,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,2CAA2C,CAAC;AAEvE,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAG7C,UAAU,eAAe;IACxB,IAAI,EAAE,YAAY,CAAC;IACnB,MAAM,EAAE,YAAY,CAAC;IACrB,IAAI,CAAC,EAAE,QAAQ,CAAC;CAChB;AACD,UAAU,gBAAgB;IACzB,IAAI,EAAE,IAAI,CAAC,YAAY,EAAE,MAAM,GAAG,QAAQ,CAAC,CAAC;IAC5C,KAAK,EAAE,KAAK,CAAC;IACb,aAAa,IAAI,IAAI,CAAC;CACtB;AAED,8FAA8F;AAC9F,qBAAa,aAAa;IACzB,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAmB;IAC3C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAsC;IAChE,OAAO,CAAC,OAAO,CAAC,CAAa;IAC7B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAS;IACzB,iFAAiF;IACjF,OAAO,CAAC,WAAW,CAAC,CAA0E;IAC9F,OAAO,CAAC,WAAW,CAAC,CAA0D;gBAClE,OAAO,EAAE,gBAAgB;IAGrC,IAAI,QAAQ,IAAI,eAAe,CAQ9B;IACD,MAAM,CAAC,IAAI,EAAE,YAAY,GAAG,SAAS,GAAG,IAAI;IAU5C,KAAK,CAAC,GAAG,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,IAAI;IAGrC,UAAU,IAAI,IAAI;IAIZ,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IA0B9B,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IAS/B,wFAAwF;IACxF,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE;IAQjC,OAAO,IAAI,IAAI;CAOf"}
@@ -1,7 +1,7 @@
1
1
  import { isTaskTerminal } from "../../../core/tasks/types.js";
2
2
  import { cleanTaskText } from "./text.js";
3
3
  import { TaskViewport } from "./viewport.js";
4
- import { taskLines } from "./views.js";
4
+ import { detailLines, outputLines } from "./views.js";
5
5
  /** Owns the selected task's bounded reads. Reading never acknowledges completion delivery. */
6
6
  export class TaskInspector {
7
7
  constructor(options) {
@@ -37,7 +37,8 @@ export class TaskInspector {
37
37
  this.positions.delete(id);
38
38
  }
39
39
  invalidate() {
40
- this.cache = undefined;
40
+ this.outputCache = undefined;
41
+ this.detailCache = undefined;
41
42
  }
42
43
  async refresh() {
43
44
  const task = this.task;
@@ -72,14 +73,25 @@ export class TaskInspector {
72
73
  await this.refresh();
73
74
  }
74
75
  }
75
- lines(tab) {
76
+ output(width) {
76
77
  const task = this.task;
77
78
  if (!task)
78
79
  return [];
79
80
  const read = this.position.read;
80
- if (this.cache?.task !== task || this.cache.read !== read)
81
- this.cache = { task, read, lines: taskLines(task, read, this.options.theme) };
82
- return this.cache.lines[tab];
81
+ const cache = this.outputCache;
82
+ if (cache?.task !== task || cache.read !== read || cache.width !== width)
83
+ this.outputCache = { task, read, width, lines: outputLines(task, read, this.options.theme, width) };
84
+ return this.outputCache.lines;
85
+ }
86
+ /** `status` carries the runtime, so Details rebuild at most once per displayed tick. */
87
+ details(status) {
88
+ const task = this.task;
89
+ if (!task)
90
+ return [];
91
+ const cache = this.detailCache;
92
+ if (cache?.task !== task || cache.status !== status)
93
+ this.detailCache = { task, status, lines: detailLines(task, status, this.options.theme) };
94
+ return this.detailCache.lines;
83
95
  }
84
96
  dispose() {
85
97
  if (this.disposed)
@@ -1 +1 @@
1
- {"version":3,"file":"inspector.js","sourceRoot":"","sources":["../../../../src/extensions/tasks/ui/inspector.ts"],"names":[],"mappings":"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","sourcesContent":["import type { TaskRead, TaskSnapshot, TasksContext } from \"../../../core/tasks/types.ts\";\nimport { isTaskTerminal } from \"../../../core/tasks/types.ts\";\nimport type { Theme } from \"../../../modes/interactive/theme/theme.ts\";\nimport type { TasksTab } from \"./model.ts\";\nimport { cleanTaskText } from \"./text.ts\";\nimport { TaskViewport } from \"./viewport.ts\";\nimport { type TaskLines, taskLines } from \"./views.ts\";\n\ninterface ReadingPosition {\n\tinfo: TaskViewport;\n\toutput: TaskViewport;\n\tread?: TaskRead;\n}\ninterface InspectorOptions {\n\thost: Pick<TasksContext, \"read\" | \"retain\">;\n\ttheme: Theme;\n\trequestRender(): void;\n}\n\n/** Owns the selected task's bounded reads. Reading never acknowledges completion delivery. */\nexport class TaskInspector {\n\ttask?: TaskSnapshot;\n\tprivate readonly options: InspectorOptions;\n\tprivate readonly positions = new Map<string, ReadingPosition>();\n\tprivate release?: () => void;\n\tprivate reading = false;\n\tprivate disposed = false;\n\t/** Snapshots are immutable, so identity tells when the lines must be rebuilt. */\n\tprivate cache?: { task: TaskSnapshot; read?: TaskRead; lines: TaskLines };\n\tconstructor(options: InspectorOptions) {\n\t\tthis.options = options;\n\t}\n\tget position(): ReadingPosition {\n\t\tconst id = this.task?.id;\n\t\tlet position = id ? this.positions.get(id) : undefined;\n\t\tif (!position) {\n\t\t\tposition = { info: new TaskViewport(), output: new TaskViewport(true) };\n\t\t\tif (id) this.positions.set(id, position);\n\t\t}\n\t\treturn position;\n\t}\n\tselect(task: TaskSnapshot | undefined): void {\n\t\tif (this.disposed) return;\n\t\tif (this.task?.id !== task?.id) {\n\t\t\tconst release = task ? this.options.host.retain(task.id) : undefined;\n\t\t\tconst previous = this.release;\n\t\t\tthis.release = release;\n\t\t\tprevious?.();\n\t\t}\n\t\tthis.task = task;\n\t}\n\tprune(ids: ReadonlySet<string>): void {\n\t\tfor (const id of this.positions.keys()) if (!ids.has(id)) this.positions.delete(id);\n\t}\n\tinvalidate(): void {\n\t\tthis.cache = undefined;\n\t}\n\tasync refresh(): Promise<void> {\n\t\tconst task = this.task;\n\t\tif (this.disposed || !task || this.reading) return;\n\t\tconst position = this.position;\n\t\tif (position.read && (!position.output.follow || isTaskTerminal(position.read.task.status))) return;\n\t\tthis.reading = true;\n\t\ttry {\n\t\t\tconst read = await this.options.host.read(task.id, { mode: \"tail\", bytes: 48 * 1024 });\n\t\t\tif (this.disposed || this.task?.id !== task.id || (!position.output.follow && position.read)) return;\n\t\t\tposition.read = read;\n\t\t} catch (error) {\n\t\t\tif (!this.disposed && this.task?.id === task.id && (position.output.follow || !position.read)) {\n\t\t\t\tposition.read = {\n\t\t\t\t\ttask,\n\t\t\t\t\ttext: \"\",\n\t\t\t\t\treadError: `Cannot read output: ${cleanTaskText(String(error))}`,\n\t\t\t\t\ttotalBytes: 0,\n\t\t\t\t\ttruncated: false,\n\t\t\t\t};\n\t\t\t}\n\t\t} finally {\n\t\t\tthis.reading = false;\n\t\t\tif (!this.disposed) this.options.requestRender();\n\t\t\tif (!this.disposed && this.task?.id !== task.id) await this.refresh();\n\t\t}\n\t}\n\tlines(tab: TasksTab): string[] {\n\t\tconst task = this.task;\n\t\tif (!task) return [];\n\t\tconst read = this.position.read;\n\t\tif (this.cache?.task !== task || this.cache.read !== read)\n\t\t\tthis.cache = { task, read, lines: taskLines(task, read, this.options.theme) };\n\t\treturn this.cache.lines[tab];\n\t}\n\tdispose(): void {\n\t\tif (this.disposed) return;\n\t\tthis.disposed = true;\n\t\tthis.release?.();\n\t\tthis.release = undefined;\n\t\tthis.positions.clear();\n\t}\n}\n"]}
1
+ {"version":3,"file":"inspector.js","sourceRoot":"","sources":["../../../../src/extensions/tasks/ui/inspector.ts"],"names":[],"mappings":"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","sourcesContent":["import type { TaskRead, TaskSnapshot, TasksContext } from \"../../../core/tasks/types.ts\";\nimport { isTaskTerminal } from \"../../../core/tasks/types.ts\";\nimport type { Theme } from \"../../../modes/interactive/theme/theme.ts\";\nimport { cleanTaskText } from \"./text.ts\";\nimport { TaskViewport } from \"./viewport.ts\";\nimport { detailLines, outputLines } from \"./views.ts\";\n\ninterface ReadingPosition {\n\tinfo: TaskViewport;\n\toutput: TaskViewport;\n\tread?: TaskRead;\n}\ninterface InspectorOptions {\n\thost: Pick<TasksContext, \"read\" | \"retain\">;\n\ttheme: Theme;\n\trequestRender(): void;\n}\n\n/** Owns the selected task's bounded reads. Reading never acknowledges completion delivery. */\nexport class TaskInspector {\n\ttask?: TaskSnapshot;\n\tprivate readonly options: InspectorOptions;\n\tprivate readonly positions = new Map<string, ReadingPosition>();\n\tprivate release?: () => void;\n\tprivate reading = false;\n\tprivate disposed = false;\n\t/** Snapshots are immutable, so identity tells when the lines must be rebuilt. */\n\tprivate outputCache?: { task: TaskSnapshot; read?: TaskRead; width: number; lines: string[] };\n\tprivate detailCache?: { task: TaskSnapshot; status: string; lines: string[] };\n\tconstructor(options: InspectorOptions) {\n\t\tthis.options = options;\n\t}\n\tget position(): ReadingPosition {\n\t\tconst id = this.task?.id;\n\t\tlet position = id ? this.positions.get(id) : undefined;\n\t\tif (!position) {\n\t\t\tposition = { info: new TaskViewport(), output: new TaskViewport(true) };\n\t\t\tif (id) this.positions.set(id, position);\n\t\t}\n\t\treturn position;\n\t}\n\tselect(task: TaskSnapshot | undefined): void {\n\t\tif (this.disposed) return;\n\t\tif (this.task?.id !== task?.id) {\n\t\t\tconst release = task ? this.options.host.retain(task.id) : undefined;\n\t\t\tconst previous = this.release;\n\t\t\tthis.release = release;\n\t\t\tprevious?.();\n\t\t}\n\t\tthis.task = task;\n\t}\n\tprune(ids: ReadonlySet<string>): void {\n\t\tfor (const id of this.positions.keys()) if (!ids.has(id)) this.positions.delete(id);\n\t}\n\tinvalidate(): void {\n\t\tthis.outputCache = undefined;\n\t\tthis.detailCache = undefined;\n\t}\n\tasync refresh(): Promise<void> {\n\t\tconst task = this.task;\n\t\tif (this.disposed || !task || this.reading) return;\n\t\tconst position = this.position;\n\t\tif (position.read && (!position.output.follow || isTaskTerminal(position.read.task.status))) return;\n\t\tthis.reading = true;\n\t\ttry {\n\t\t\tconst read = await this.options.host.read(task.id, { mode: \"tail\", bytes: 48 * 1024 });\n\t\t\tif (this.disposed || this.task?.id !== task.id || (!position.output.follow && position.read)) return;\n\t\t\tposition.read = read;\n\t\t} catch (error) {\n\t\t\tif (!this.disposed && this.task?.id === task.id && (position.output.follow || !position.read)) {\n\t\t\t\tposition.read = {\n\t\t\t\t\ttask,\n\t\t\t\t\ttext: \"\",\n\t\t\t\t\treadError: `Cannot read output: ${cleanTaskText(String(error))}`,\n\t\t\t\t\ttotalBytes: 0,\n\t\t\t\t\ttruncated: false,\n\t\t\t\t};\n\t\t\t}\n\t\t} finally {\n\t\t\tthis.reading = false;\n\t\t\tif (!this.disposed) this.options.requestRender();\n\t\t\tif (!this.disposed && this.task?.id !== task.id) await this.refresh();\n\t\t}\n\t}\n\toutput(width: number): string[] {\n\t\tconst task = this.task;\n\t\tif (!task) return [];\n\t\tconst read = this.position.read;\n\t\tconst cache = this.outputCache;\n\t\tif (cache?.task !== task || cache.read !== read || cache.width !== width)\n\t\t\tthis.outputCache = { task, read, width, lines: outputLines(task, read, this.options.theme, width) };\n\t\treturn this.outputCache!.lines;\n\t}\n\t/** `status` carries the runtime, so Details rebuild at most once per displayed tick. */\n\tdetails(status: string): string[] {\n\t\tconst task = this.task;\n\t\tif (!task) return [];\n\t\tconst cache = this.detailCache;\n\t\tif (cache?.task !== task || cache.status !== status)\n\t\t\tthis.detailCache = { task, status, lines: detailLines(task, status, this.options.theme) };\n\t\treturn this.detailCache!.lines;\n\t}\n\tdispose(): void {\n\t\tif (this.disposed) return;\n\t\tthis.disposed = true;\n\t\tthis.release?.();\n\t\tthis.release = undefined;\n\t\tthis.positions.clear();\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../../../src/extensions/tasks/ui/layout.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAc,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAKlG,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,2CAA2C,CAAC;AACvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAG1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,MAAM,WAAW,OAAO;IACvB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,aAAa,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,QAAQ,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;CACjB;AACD,MAAM,WAAW,WAAW;IAC3B,IAAI,EAAE,OAAO,EAAE,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,2FAA2F;IAC3F,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB;AACD,UAAU,aAAa;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,KAAK,CAAC;IACb,WAAW,EAAE,IAAI,CAAC,kBAAkB,EAAE,SAAS,CAAC,CAAC;IACjD,SAAS,EAAE,aAAa,CAAC;IACzB,SAAS,EAAE,aAAa,CAAC;IACzB,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,MAAM,GAAG,WAAW,CAAC;IAC5B,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACvC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;CACnB;AAGD,6FAA6F;AAC7F,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,aAAa,GAAG,WAAW,CA0NrE"}
1
+ {"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../../../src/extensions/tasks/ui/layout.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAc,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAMlG,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,2CAA2C,CAAC;AACvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAG1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,MAAM,WAAW,OAAO;IACvB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,aAAa,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,QAAQ,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;CACjB;AACD,MAAM,WAAW,WAAW;IAC3B,IAAI,EAAE,OAAO,EAAE,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,2FAA2F;IAC3F,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB;AACD,UAAU,aAAa;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,KAAK,CAAC;IACb,WAAW,EAAE,IAAI,CAAC,kBAAkB,EAAE,SAAS,CAAC,CAAC;IACjD,SAAS,EAAE,aAAa,CAAC;IACzB,SAAS,EAAE,aAAa,CAAC;IACzB,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,MAAM,GAAG,WAAW,CAAC;IAC5B,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACvC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;CACnB;AAKD,6FAA6F;AAC7F,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,aAAa,GAAG,WAAW,CAoMrE"}
@@ -3,9 +3,12 @@ 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";
6
7
  import { statusName } from "./task-view.js";
7
8
  import { cleanTaskText, firstCommandLine } from "./text.js";
8
9
  const pad = (text, width) => truncateToWidth(text, Math.max(1, width), "…", true);
10
+ /** Visible width of "Output Details". */
11
+ const TABS_WIDTH = 15;
9
12
  /** Cell geometry and mouse targets are produced together, so resize cannot separate them. */
10
13
  export function renderTasksLayout(options) {
11
14
  const { width, height, theme, selection, inspector, list, focus, keybindings } = options;
@@ -20,7 +23,8 @@ export function renderTasksLayout(options) {
20
23
  const bodyHeight = height - 5;
21
24
  const hits = result.hits;
22
25
  result.listWidth = listWidth;
23
- result.listPageSize = Math.max(1, Math.floor((bodyHeight - 1) / 2));
26
+ // One row per task, less the group headings.
27
+ result.listPageSize = Math.max(1, bodyHeight - 2);
24
28
  const pane = (lines, size, active) => {
25
29
  const border = (text) => theme.fg(wide && active ? "borderAccent" : "borderMuted", text);
26
30
  return [
@@ -85,45 +89,57 @@ export function renderTasksLayout(options) {
85
89
  const task = inspector.task;
86
90
  const tab = selection.state.tab;
87
91
  const tabLabel = (id, label) => theme.style(label, { fg: "text", underline: tab === id });
88
- const right = [`${tabLabel("output", "Output")} ${tabLabel("info", "Details")}`];
92
+ // One header row in every layout: the selected task's source and status, with the tabs on the right.
93
+ const tabsX = rightWidth - 2 - TABS_WIDTH;
94
+ const marker = task ? statusMarker(task.status) : undefined;
95
+ const summary = task && marker
96
+ ? [
97
+ theme.fg("muted", cleanTaskText(task.label)),
98
+ theme.fg(marker.color, statusName(task.status)),
99
+ theme.fg("muted", runtimeLabel(task)),
100
+ ].join(theme.fg("dim", " · "))
101
+ : "";
102
+ const shownSummary = truncateToWidth(summary, Math.max(0, tabsX - 1), "…");
103
+ const right = [
104
+ `${shownSummary}${" ".repeat(tabsX - visibleWidth(shownSummary))}${tabLabel("output", "Output")} ${tabLabel("info", "Details")}`,
105
+ ];
89
106
  if (wide || focus === "inspector")
90
- hits.push({ x: rightX + 1, y: 1, width: 6, tab: "output" }, { x: rightX + 9, y: 1, width: 7, tab: "info" });
107
+ hits.push({ x: rightX + 1 + tabsX, y: 1, width: 6, tab: "output" }, { x: rightX + 9 + tabsX, y: 1, width: 7, tab: "info" });
91
108
  const content = [];
92
109
  let reading = "";
93
110
  if (task) {
111
+ // Without the list beside it, the inspector names the task it shows.
94
112
  if (!wide)
95
- content.push(theme.fg("text", cleanTaskText(firstCommandLine(task.command ?? task.title))), theme.fg("muted", `${statusName(task.status)} · ${runtimeLabel(task)}`));
96
- const lines = inspector.lines(tab);
113
+ content.push(theme.fg("text", cleanTaskText(firstCommandLine(task.title))));
97
114
  const position = inspector.position;
98
115
  const read = position.read;
116
+ const terminal = isTaskTerminal(task.status);
99
117
  const diagnostics = [task.error, read?.readError].filter((text) => !!text).map(cleanTaskText);
100
118
  if (tab === "output" && diagnostics.length)
101
119
  content.push(theme.fg("warning", diagnostics.join(" · ").replace(/\n/g, " ")));
102
120
  const source = tab === "info"
103
- ? [
104
- `Task ID ${task.id}`,
105
- `Status ${statusName(task.status)} · ${statusName(task.mode)} · ${runtimeLabel(task)}`,
106
- ...diagnostics,
107
- ...lines,
108
- ]
109
- : lines;
121
+ ? inspector.details(`${statusName(task.status)} · ${statusName(task.mode)} · ${runtimeLabel(task)}`)
122
+ : inspector.output(rightWidth - 2);
110
123
  content.push(...position[tab].layout(source, rightWidth - 2, bodyHeight - content.length));
111
124
  if (tab === "output") {
112
- reading = position.output.follow
113
- ? isTaskTerminal(task.status)
114
- ? "Finished"
115
- : "Live"
116
- : isTaskTerminal(task.status)
117
- ? `Finished · ${hint("app.tasks.follow")} load final output`
118
- : `Browsing · ${hint("app.tasks.follow")} follow output`;
119
- if (!position.output.follow && (wide || focus === "inspector"))
125
+ // Only a log holds a browsed snapshot; other output is always the current result.
126
+ const settled = terminal && task.outputPath === undefined;
127
+ reading =
128
+ position.output.follow || settled
129
+ ? terminal
130
+ ? "Finished"
131
+ : "Live"
132
+ : terminal
133
+ ? `Finished · ${hint("app.tasks.follow")} load final output`
134
+ : `Browsing · ${hint("app.tasks.follow")} follow output`;
135
+ if (!position.output.follow && !settled && (wide || focus === "inspector"))
120
136
  hits.push({
121
137
  x: rightX + 1,
122
138
  y: height - 3,
123
139
  width: Math.min(rightWidth - 2, visibleWidth(reading)),
124
140
  key: "app.tasks.follow",
125
141
  });
126
- if (read?.truncated)
142
+ if (task.outputPath !== undefined && read?.truncated)
127
143
  reading += ` · Tail preview: ${formatSize(Buffer.byteLength(read.text))} of ${formatSize(read.totalBytes)}`;
128
144
  }
129
145
  else if (tab === "info")
@@ -146,58 +162,26 @@ export function renderTasksLayout(options) {
146
162
  if (target)
147
163
  hits.push({ x, y: height - 1, width: visibleWidth(text), ...target });
148
164
  };
149
- if (options.help || options.pendingKill) {
165
+ if (options.help) {
150
166
  hits.length = 0;
151
- let body;
152
- if (options.help) {
153
- const controls = [
154
- ["app.tasks.nextFocus", "Switch task list / inspector"],
155
- ["app.tasks.previousFocus", "Switch inspector / task list"],
156
- ["app.tasks.previousTab", "Output (inspector only)"],
157
- ["app.tasks.nextTab", "Details (inspector only)"],
158
- ["tui.select.up", "Previous task / scroll up"],
159
- ["tui.select.down", "Next task / scroll down"],
160
- ["tui.select.pageUp", "Page up in task list"],
161
- ["tui.select.pageDown", "Page down in task list"],
162
- ["tui.editor.pageUp", "Page up in inspector"],
163
- ["tui.editor.pageDown", "Page down in inspector"],
164
- ["app.tasks.top", "Top of list / content"],
165
- ["app.tasks.bottom", "Bottom of list / content"],
166
- ["app.tasks.search", "Locate a retained task; Enter chooses, Escape restores selection"],
167
- ["app.tasks.follow", "Follow latest / final output (Output only)"],
168
- ["app.tasks.detach", "Move every eligible foreground execution to the background"],
169
- ["app.tasks.detachSelected", "Move selected foreground task to background"],
170
- ["app.tasks.kill", "Request stop of selected whole task"],
171
- ["app.tasks.confirmStop", "Confirm stop"],
172
- ["tui.select.cancel", "Close current search, help or confirmation; otherwise close panel"],
173
- ];
174
- body = [
175
- theme.fg("text", "Task controls"),
176
- ...options.help.layout(controls.map(([key, label]) => hint(key).padEnd(14) + label), width - 2, height - 5),
177
- "",
178
- ];
179
- addHint("tui.select.up", `/ ${hint("tui.select.down")} scroll`);
180
- addHint("tui.select.cancel", "back", { cancel: true });
181
- }
182
- else {
183
- const target = selection.all.find((task) => task.id === options.pendingKill);
184
- const command = wrapTextWithAnsi(cleanTaskText(target?.command ?? target?.title ?? options.pendingKill), width - 2);
185
- const preview = command.slice(0, height - 8);
186
- if (preview.length < command.length)
187
- preview[preview.length - 1] = "… Full command in Details.";
188
- body = [
189
- theme.fg("text", "Stop task?"),
190
- "Stops the whole task, including its active work.",
191
- `Task ID: ${options.pendingKill}`,
192
- "",
193
- ...preview,
194
- ];
195
- addHint("app.tasks.confirmStop", "confirm", { key: "app.tasks.confirmStop" });
196
- addHint("tui.select.cancel", "cancel", { cancel: true });
197
- }
198
- while (body.length < height - 3)
199
- body.push("");
200
- panels = pane(body, width, false);
167
+ panels = pane(helpLines(options.help, hint, theme, width, height), width, false);
168
+ addHint("tui.select.up", `/ ${hint("tui.select.down")} scroll`);
169
+ addHint("tui.select.cancel", "back", { cancel: true });
170
+ }
171
+ else if (options.pendingKill) {
172
+ // The question borrows only the footer row, so the task stays in view while confirming.
173
+ hits.length = 0;
174
+ const target = selection.all.find((task) => task.id === options.pendingKill);
175
+ const source = cleanTaskText(target?.label ?? "task");
176
+ const confirm = `${hint("app.tasks.confirmStop")} stop`;
177
+ const cancel = `${hint("tui.select.cancel")} cancel`;
178
+ const actions = `${confirm} · ${cancel}`;
179
+ const room = width - visibleWidth(`Stop ${source} ""? ${actions}`);
180
+ const title = cleanTaskText(firstCommandLine(target?.title ?? options.pendingKill));
181
+ const question = room >= 4 ? `Stop ${source} "${truncateToWidth(title, room, "…")}"? ` : `Stop ${source}? `;
182
+ footer = question + actions;
183
+ const x = visibleWidth(question);
184
+ 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 });
201
185
  }
202
186
  else if (options.searchLine) {
203
187
  // Only search candidates and cancellation are clickable while locating a task.
@@ -210,9 +194,10 @@ export function renderTasksLayout(options) {
210
194
  }
211
195
  else {
212
196
  addHint("tui.select.up", `/ ${hint("tui.select.down")}${focus === "list" ? " tasks" : " scroll"}`);
213
- addHint("app.tasks.nextFocus", focus === "list" ? (tab === "output" ? "output" : "details") : "tasks", {
214
- key: "app.tasks.nextFocus",
215
- });
197
+ if (focus === "list")
198
+ addHint("tui.select.confirm", "open", { tab });
199
+ else
200
+ addHint("app.tasks.nextFocus", "tasks", { key: "app.tasks.nextFocus" });
216
201
  addHint("tui.select.cancel", "close", { cancel: true });
217
202
  if (focus === "list")
218
203
  addHint("app.tasks.search", "find", { key: "app.tasks.search" });
@@ -234,4 +219,55 @@ export function renderTasksLayout(options) {
234
219
  result.lines = [...panels, theme.fg(options.pendingKill ? "warning" : "dim", pad(footer, width))];
235
220
  return result;
236
221
  }
222
+ /** Controls grouped by purpose; actions sharing a key, such as list and inspector paging, share a row. */
223
+ function helpLines(help, hint, theme, width, height) {
224
+ const keys = (...bindings) => [...new Set(bindings.map(hint).filter(Boolean))].join(" / ");
225
+ const listPage = keys("tui.select.pageUp", "tui.select.pageDown");
226
+ const inspectorPage = keys("tui.editor.pageUp", "tui.editor.pageDown");
227
+ const paging = listPage === inspectorPage
228
+ ? [[listPage, "Page the list or inspector"]]
229
+ : [
230
+ [listPage, "Page the list"],
231
+ [inspectorPage, "Page the inspector"],
232
+ ];
233
+ const sections = [
234
+ [
235
+ "Navigate",
236
+ [
237
+ [keys("tui.select.up", "tui.select.down"), "Select a task, or scroll the inspector"],
238
+ ...paging,
239
+ [keys("app.tasks.top", "app.tasks.bottom"), "Top or bottom"],
240
+ [hint("tui.select.confirm"), "Open the selected task"],
241
+ [keys("app.tasks.nextFocus", "app.tasks.previousFocus"), "Switch between list and inspector"],
242
+ ],
243
+ ],
244
+ [
245
+ "View",
246
+ [
247
+ [keys("app.tasks.previousTab", "app.tasks.nextTab"), "Output or Details, in the inspector"],
248
+ [hint("app.tasks.follow"), "Follow the latest output, or load the final output"],
249
+ [hint("app.tasks.search"), "Find a task; Enter locates it, Esc restores the selection"],
250
+ ],
251
+ ],
252
+ [
253
+ "Act",
254
+ [
255
+ [hint("app.tasks.kill"), `Stop the selected task; ${hint("app.tasks.confirmStop")} confirms`],
256
+ [hint("app.tasks.detachSelected"), "Move the selected foreground task to the background"],
257
+ [hint("app.tasks.detach"), "Move every foreground execution to the background"],
258
+ [hint("tui.select.cancel"), "Close search, help or confirmation; otherwise the panel"],
259
+ ],
260
+ ],
261
+ ];
262
+ const keyWidth = Math.max(...sections.flatMap(([, rows]) => rows.map(([key]) => visibleWidth(key)))) + 2;
263
+ const rows = sections.flatMap(([title, entries], index) => [
264
+ ...(index ? [""] : []),
265
+ theme.fg("accent", title),
266
+ ...entries.map(([key, label]) => ` ${key}${" ".repeat(keyWidth - visibleWidth(key))}${label}`),
267
+ ]);
268
+ const body = [theme.fg("text", "Task controls"), ...help.layout(rows, width - 2, height - 5), ""];
269
+ while (body.length < height - 3)
270
+ body.push("");
271
+ return body;
272
+ }
237
273
  //# sourceMappingURL=layout.js.map