@astralyn/pi 1.4.5 → 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 (324) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/dist/bundle/chunks/chunk-FODCTZXW.js +230 -0
  3. package/dist/bundle/chunks/{chunk-I5S7H7GA.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-YJTSOLP2.js +1499 -0
  8. package/dist/bundle/chunks/{cli-FH77R7JR.js → cli-MEL7SGJD.js} +1 -1
  9. package/dist/bundle/chunks/{execute-GMFGC27P.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-6FUV7ZDV.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/isolated-session.d.ts +23 -0
  23. package/dist/core/isolated-session.d.ts.map +1 -0
  24. package/dist/core/isolated-session.js +55 -0
  25. package/dist/core/isolated-session.js.map +1 -0
  26. package/dist/core/package-manager.d.ts +7 -1
  27. package/dist/core/package-manager.d.ts.map +1 -1
  28. package/dist/core/package-manager.js +72 -1
  29. package/dist/core/package-manager.js.map +1 -1
  30. package/dist/core/resource-loader.d.ts +1 -0
  31. package/dist/core/resource-loader.d.ts.map +1 -1
  32. package/dist/core/resource-loader.js +23 -7
  33. package/dist/core/resource-loader.js.map +1 -1
  34. package/dist/core/settings-manager.d.ts +4 -2
  35. package/dist/core/settings-manager.d.ts.map +1 -1
  36. package/dist/core/settings-manager.js +11 -0
  37. package/dist/core/settings-manager.js.map +1 -1
  38. package/dist/core/settings-schema.d.ts +7 -0
  39. package/dist/core/settings-schema.d.ts.map +1 -1
  40. package/dist/core/settings-schema.js +6 -0
  41. package/dist/core/settings-schema.js.map +1 -1
  42. package/dist/core/skills.d.ts +10 -0
  43. package/dist/core/skills.d.ts.map +1 -1
  44. package/dist/core/skills.js +23 -0
  45. package/dist/core/skills.js.map +1 -1
  46. package/dist/core/tasks/codec.d.ts +12 -0
  47. package/dist/core/tasks/codec.d.ts.map +1 -0
  48. package/dist/core/tasks/codec.js +139 -0
  49. package/dist/core/tasks/codec.js.map +1 -0
  50. package/dist/core/tasks/delivery.d.ts +11 -4
  51. package/dist/core/tasks/delivery.d.ts.map +1 -1
  52. package/dist/core/tasks/delivery.js +9 -9
  53. package/dist/core/tasks/delivery.js.map +1 -1
  54. package/dist/core/tasks/execution.d.ts +71 -0
  55. package/dist/core/tasks/execution.d.ts.map +1 -0
  56. package/dist/core/tasks/execution.js +292 -0
  57. package/dist/core/tasks/execution.js.map +1 -0
  58. package/dist/core/tasks/format.d.ts +0 -2
  59. package/dist/core/tasks/format.d.ts.map +1 -1
  60. package/dist/core/tasks/format.js +1 -16
  61. package/dist/core/tasks/format.js.map +1 -1
  62. package/dist/core/tasks/limits.d.ts +12 -1
  63. package/dist/core/tasks/limits.d.ts.map +1 -1
  64. package/dist/core/tasks/limits.js +20 -1
  65. package/dist/core/tasks/limits.js.map +1 -1
  66. package/dist/core/tasks/output.d.ts +17 -17
  67. package/dist/core/tasks/output.d.ts.map +1 -1
  68. package/dist/core/tasks/output.js +72 -69
  69. package/dist/core/tasks/output.js.map +1 -1
  70. package/dist/core/tasks/presentation.d.ts +14 -5
  71. package/dist/core/tasks/presentation.d.ts.map +1 -1
  72. package/dist/core/tasks/presentation.js +56 -185
  73. package/dist/core/tasks/presentation.js.map +1 -1
  74. package/dist/core/tasks/record.d.ts +45 -0
  75. package/dist/core/tasks/record.d.ts.map +1 -0
  76. package/dist/core/tasks/record.js +80 -0
  77. package/dist/core/tasks/record.js.map +1 -0
  78. package/dist/core/tasks/runtime.d.ts +22 -22
  79. package/dist/core/tasks/runtime.d.ts.map +1 -1
  80. package/dist/core/tasks/runtime.js +170 -343
  81. package/dist/core/tasks/runtime.js.map +1 -1
  82. package/dist/core/tasks/scheduler.d.ts +16 -0
  83. package/dist/core/tasks/scheduler.d.ts.map +1 -0
  84. package/dist/core/tasks/scheduler.js +42 -0
  85. package/dist/core/tasks/scheduler.js.map +1 -0
  86. package/dist/core/tasks/session.d.ts +1 -1
  87. package/dist/core/tasks/session.d.ts.map +1 -1
  88. package/dist/core/tasks/session.js +22 -35
  89. package/dist/core/tasks/session.js.map +1 -1
  90. package/dist/core/tasks/store.d.ts +18 -25
  91. package/dist/core/tasks/store.d.ts.map +1 -1
  92. package/dist/core/tasks/store.js +45 -43
  93. package/dist/core/tasks/store.js.map +1 -1
  94. package/dist/core/tasks/types.d.ts +159 -70
  95. package/dist/core/tasks/types.d.ts.map +1 -1
  96. package/dist/core/tasks/types.js +3 -9
  97. package/dist/core/tasks/types.js.map +1 -1
  98. package/dist/core/tools/shell-execution.d.ts +8 -7
  99. package/dist/core/tools/shell-execution.d.ts.map +1 -1
  100. package/dist/core/tools/shell-execution.js +19 -27
  101. package/dist/core/tools/shell-execution.js.map +1 -1
  102. package/dist/core/tools/shell-tool.d.ts.map +1 -1
  103. package/dist/core/tools/shell-tool.js +42 -47
  104. package/dist/core/tools/shell-tool.js.map +1 -1
  105. package/dist/core/usage-totals.d.ts +4 -3
  106. package/dist/core/usage-totals.d.ts.map +1 -1
  107. package/dist/core/usage-totals.js +32 -8
  108. package/dist/core/usage-totals.js.map +1 -1
  109. package/dist/extensions/agent/activity.d.ts +4 -4
  110. package/dist/extensions/agent/activity.d.ts.map +1 -1
  111. package/dist/extensions/agent/activity.js +15 -24
  112. package/dist/extensions/agent/activity.js.map +1 -1
  113. package/dist/extensions/agent/index.d.ts +2 -11
  114. package/dist/extensions/agent/index.d.ts.map +1 -1
  115. package/dist/extensions/agent/index.js +3 -88
  116. package/dist/extensions/agent/index.js.map +1 -1
  117. package/dist/extensions/agent/progress.d.ts +31 -0
  118. package/dist/extensions/agent/progress.d.ts.map +1 -0
  119. package/dist/extensions/agent/progress.js +135 -0
  120. package/dist/extensions/agent/progress.js.map +1 -0
  121. package/dist/extensions/agent/render.d.ts.map +1 -1
  122. package/dist/extensions/agent/render.js +8 -17
  123. package/dist/extensions/agent/render.js.map +1 -1
  124. package/dist/extensions/agent/report.d.ts +9 -0
  125. package/dist/extensions/agent/report.d.ts.map +1 -0
  126. package/dist/extensions/agent/report.js +40 -0
  127. package/dist/extensions/agent/report.js.map +1 -0
  128. package/dist/extensions/agent/settings-panel.d.ts +43 -0
  129. package/dist/extensions/agent/settings-panel.d.ts.map +1 -0
  130. package/dist/extensions/agent/settings-panel.js +125 -0
  131. package/dist/extensions/agent/settings-panel.js.map +1 -0
  132. package/dist/extensions/agent/settings.d.ts +1 -1
  133. package/dist/extensions/agent/settings.d.ts.map +1 -1
  134. package/dist/extensions/agent/settings.js +101 -83
  135. package/dist/extensions/agent/settings.js.map +1 -1
  136. package/dist/extensions/agent/tool.d.ts +13 -0
  137. package/dist/extensions/agent/tool.d.ts.map +1 -0
  138. package/dist/extensions/agent/tool.js +88 -0
  139. package/dist/extensions/agent/tool.js.map +1 -0
  140. package/dist/extensions/agent/types.d.ts +19 -21
  141. package/dist/extensions/agent/types.d.ts.map +1 -1
  142. package/dist/extensions/agent/types.js +2 -10
  143. package/dist/extensions/agent/types.js.map +1 -1
  144. package/dist/extensions/agent/worker.d.ts +16 -0
  145. package/dist/extensions/agent/worker.d.ts.map +1 -0
  146. package/dist/extensions/agent/worker.js +66 -0
  147. package/dist/extensions/agent/worker.js.map +1 -0
  148. package/dist/extensions/btw/agent.d.ts +1 -1
  149. package/dist/extensions/btw/agent.d.ts.map +1 -1
  150. package/dist/extensions/btw/agent.js +3 -20
  151. package/dist/extensions/btw/agent.js.map +1 -1
  152. package/dist/extensions/cached-compaction/index.d.ts.map +1 -1
  153. package/dist/extensions/cached-compaction/index.js +3 -22
  154. package/dist/extensions/cached-compaction/index.js.map +1 -1
  155. package/dist/extensions/cached-compaction/render.d.ts +1 -0
  156. package/dist/extensions/cached-compaction/render.d.ts.map +1 -1
  157. package/dist/extensions/cached-compaction/render.js +42 -14
  158. package/dist/extensions/cached-compaction/render.js.map +1 -1
  159. package/dist/extensions/deepwiki/client.d.ts.map +1 -1
  160. package/dist/extensions/deepwiki/client.js +6 -78
  161. package/dist/extensions/deepwiki/client.js.map +1 -1
  162. package/dist/extensions/deepwiki/transport.d.ts +3 -0
  163. package/dist/extensions/deepwiki/transport.d.ts.map +1 -0
  164. package/dist/extensions/deepwiki/transport.js +96 -0
  165. package/dist/extensions/deepwiki/transport.js.map +1 -0
  166. package/dist/extensions/provider/ui/builtin-data.d.ts +3 -3
  167. package/dist/extensions/provider/ui/builtin-data.d.ts.map +1 -1
  168. package/dist/extensions/provider/ui/builtin-data.js.map +1 -1
  169. package/dist/extensions/provider/ui/compat.d.ts +3 -3
  170. package/dist/extensions/provider/ui/compat.d.ts.map +1 -1
  171. package/dist/extensions/provider/ui/compat.js.map +1 -1
  172. package/dist/extensions/provider/ui/controls.d.ts +2 -2
  173. package/dist/extensions/provider/ui/controls.d.ts.map +1 -1
  174. package/dist/extensions/provider/ui/controls.js.map +1 -1
  175. package/dist/extensions/provider/ui/dialogs.d.ts +3 -3
  176. package/dist/extensions/provider/ui/dialogs.d.ts.map +1 -1
  177. package/dist/extensions/provider/ui/dialogs.js.map +1 -1
  178. package/dist/extensions/provider/ui/dictionary.d.ts +2 -2
  179. package/dist/extensions/provider/ui/dictionary.d.ts.map +1 -1
  180. package/dist/extensions/provider/ui/dictionary.js.map +1 -1
  181. package/dist/extensions/provider/ui/editor.d.ts.map +1 -1
  182. package/dist/extensions/provider/ui/editor.js +1 -3
  183. package/dist/extensions/provider/ui/editor.js.map +1 -1
  184. package/dist/extensions/provider/ui/fetch-models.d.ts +2 -2
  185. package/dist/extensions/provider/ui/fetch-models.d.ts.map +1 -1
  186. package/dist/extensions/provider/ui/fetch-models.js.map +1 -1
  187. package/dist/extensions/provider/ui/model-fields.d.ts +2 -2
  188. package/dist/extensions/provider/ui/model-fields.d.ts.map +1 -1
  189. package/dist/extensions/provider/ui/model-fields.js.map +1 -1
  190. package/dist/extensions/provider/ui/model-options.d.ts +6 -6
  191. package/dist/extensions/provider/ui/model-options.d.ts.map +1 -1
  192. package/dist/extensions/provider/ui/model-options.js.map +1 -1
  193. package/dist/extensions/provider/ui/pane.d.ts +21 -12
  194. package/dist/extensions/provider/ui/pane.d.ts.map +1 -1
  195. package/dist/extensions/provider/ui/pane.js.map +1 -1
  196. package/dist/extensions/provider/ui/provider-fields.d.ts +3 -3
  197. package/dist/extensions/provider/ui/provider-fields.d.ts.map +1 -1
  198. package/dist/extensions/provider/ui/provider-fields.js.map +1 -1
  199. package/dist/extensions/provider/ui/thinking-map.d.ts +2 -2
  200. package/dist/extensions/provider/ui/thinking-map.d.ts.map +1 -1
  201. package/dist/extensions/provider/ui/thinking-map.js.map +1 -1
  202. package/dist/extensions/run-summary/format.js +1 -1
  203. package/dist/extensions/run-summary/format.js.map +1 -1
  204. package/dist/extensions/statusline/usage.d.ts.map +1 -1
  205. package/dist/extensions/statusline/usage.js +2 -6
  206. package/dist/extensions/statusline/usage.js.map +1 -1
  207. package/dist/extensions/tasks/tool/actions.d.ts +1 -1
  208. package/dist/extensions/tasks/tool/actions.d.ts.map +1 -1
  209. package/dist/extensions/tasks/tool/actions.js +50 -115
  210. package/dist/extensions/tasks/tool/actions.js.map +1 -1
  211. package/dist/extensions/tasks/tool/constants.d.ts +1 -6
  212. package/dist/extensions/tasks/tool/constants.d.ts.map +1 -1
  213. package/dist/extensions/tasks/tool/constants.js +1 -6
  214. package/dist/extensions/tasks/tool/constants.js.map +1 -1
  215. package/dist/extensions/tasks/tool/schema.d.ts +0 -3
  216. package/dist/extensions/tasks/tool/schema.d.ts.map +1 -1
  217. package/dist/extensions/tasks/tool/schema.js +5 -14
  218. package/dist/extensions/tasks/tool/schema.js.map +1 -1
  219. package/dist/extensions/tasks/tool/types.d.ts +2 -8
  220. package/dist/extensions/tasks/tool/types.d.ts.map +1 -1
  221. package/dist/extensions/tasks/tool/types.js +0 -2
  222. package/dist/extensions/tasks/tool/types.js.map +1 -1
  223. package/dist/extensions/tasks/tool.d.ts.map +1 -1
  224. package/dist/extensions/tasks/tool.js +2 -2
  225. package/dist/extensions/tasks/tool.js.map +1 -1
  226. package/dist/extensions/tasks/ui/completion-render.d.ts.map +1 -1
  227. package/dist/extensions/tasks/ui/completion-render.js +46 -47
  228. package/dist/extensions/tasks/ui/completion-render.js.map +1 -1
  229. package/dist/extensions/tasks/ui/inspector.d.ts +5 -3
  230. package/dist/extensions/tasks/ui/inspector.d.ts.map +1 -1
  231. package/dist/extensions/tasks/ui/inspector.js +18 -6
  232. package/dist/extensions/tasks/ui/inspector.js.map +1 -1
  233. package/dist/extensions/tasks/ui/layout.d.ts +7 -7
  234. package/dist/extensions/tasks/ui/layout.d.ts.map +1 -1
  235. package/dist/extensions/tasks/ui/layout.js +118 -84
  236. package/dist/extensions/tasks/ui/layout.js.map +1 -1
  237. package/dist/extensions/tasks/ui/list.d.ts.map +1 -1
  238. package/dist/extensions/tasks/ui/list.js +45 -31
  239. package/dist/extensions/tasks/ui/list.js.map +1 -1
  240. package/dist/extensions/tasks/ui/manager.d.ts +16 -7
  241. package/dist/extensions/tasks/ui/manager.d.ts.map +1 -1
  242. package/dist/extensions/tasks/ui/manager.js +167 -129
  243. package/dist/extensions/tasks/ui/manager.js.map +1 -1
  244. package/dist/extensions/tasks/ui/model.d.ts +29 -0
  245. package/dist/extensions/tasks/ui/model.d.ts.map +1 -1
  246. package/dist/extensions/tasks/ui/model.js +16 -1
  247. package/dist/extensions/tasks/ui/model.js.map +1 -1
  248. package/dist/extensions/tasks/ui/render.d.ts +1 -1
  249. package/dist/extensions/tasks/ui/render.d.ts.map +1 -1
  250. package/dist/extensions/tasks/ui/render.js +12 -9
  251. package/dist/extensions/tasks/ui/render.js.map +1 -1
  252. package/dist/extensions/tasks/ui/status.d.ts +15 -0
  253. package/dist/extensions/tasks/ui/status.d.ts.map +1 -0
  254. package/dist/extensions/tasks/ui/status.js +16 -0
  255. package/dist/extensions/tasks/ui/status.js.map +1 -0
  256. package/dist/extensions/tasks/ui/tree.js +1 -1
  257. package/dist/extensions/tasks/ui/tree.js.map +1 -1
  258. package/dist/extensions/tasks/ui/views.d.ts +10 -5
  259. package/dist/extensions/tasks/ui/views.d.ts.map +1 -1
  260. package/dist/extensions/tasks/ui/views.js +61 -36
  261. package/dist/extensions/tasks/ui/views.js.map +1 -1
  262. package/dist/index.d.ts +2 -1
  263. package/dist/index.d.ts.map +1 -1
  264. package/dist/index.js.map +1 -1
  265. package/dist/modes/interactive/components/config-selector.d.ts +14 -1
  266. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  267. package/dist/modes/interactive/components/config-selector.js +258 -7
  268. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  269. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
  270. package/dist/modes/interactive/components/keybinding-hints.js +2 -1
  271. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
  272. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  273. package/dist/modes/interactive/components/model-selector.js +7 -4
  274. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  275. package/dist/modes/interactive/components/status-marker.d.ts +2 -1
  276. package/dist/modes/interactive/components/status-marker.d.ts.map +1 -1
  277. package/dist/modes/interactive/components/status-marker.js +0 -1
  278. package/dist/modes/interactive/components/status-marker.js.map +1 -1
  279. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  280. package/dist/modes/interactive/components/thinking-selector.js +10 -3
  281. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  282. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  283. package/dist/modes/interactive/interactive-mode.js +7 -1
  284. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  285. package/dist/utils/duration.d.ts +3 -0
  286. package/dist/utils/duration.d.ts.map +1 -0
  287. package/dist/utils/duration.js +17 -0
  288. package/dist/utils/duration.js.map +1 -0
  289. package/dist/utils/number.d.ts +3 -0
  290. package/dist/utils/number.d.ts.map +1 -0
  291. package/dist/utils/number.js +5 -0
  292. package/dist/utils/number.js.map +1 -0
  293. package/docs/bundled/extensions/agent.md +14 -12
  294. package/docs/bundled/extensions/cached-compaction.md +13 -4
  295. package/docs/bundled/extensions/deepwiki.md +3 -1
  296. package/docs/bundled/extensions/statusline.md +1 -1
  297. package/docs/bundled/tasks.md +15 -14
  298. package/docs/extensions.md +26 -10
  299. package/docs/packages.md +5 -3
  300. package/docs/sdk.md +3 -3
  301. package/docs/session-format.md +28 -24
  302. package/docs/settings.md +11 -0
  303. package/docs/skills.md +23 -0
  304. package/npm-shrinkwrap.json +2 -2
  305. package/package.json +1 -1
  306. package/schemas/settings.schema.json +36 -0
  307. package/dist/bundle/chunks/chunk-FSJ45CRP.js +0 -229
  308. package/dist/bundle/chunks/chunk-W3FIUMGM.js +0 -1501
  309. package/dist/core/tasks/history.d.ts +0 -4
  310. package/dist/core/tasks/history.d.ts.map +0 -1
  311. package/dist/core/tasks/history.js +0 -131
  312. package/dist/core/tasks/history.js.map +0 -1
  313. package/dist/extensions/agent/runner.d.ts +0 -24
  314. package/dist/extensions/agent/runner.d.ts.map +0 -1
  315. package/dist/extensions/agent/runner.js +0 -274
  316. package/dist/extensions/agent/runner.js.map +0 -1
  317. package/dist/extensions/deepwiki/http.d.ts +0 -13
  318. package/dist/extensions/deepwiki/http.d.ts.map +0 -1
  319. package/dist/extensions/deepwiki/http.js +0 -88
  320. package/dist/extensions/deepwiki/http.js.map +0 -1
  321. package/dist/extensions/tasks/ui/task-view.d.ts +0 -13
  322. package/dist/extensions/tasks/ui/task-view.d.ts.map +0 -1
  323. package/dist/extensions/tasks/ui/task-view.js +0 -20
  324. package/dist/extensions/tasks/ui/task-view.js.map +0 -1
@@ -0,0 +1,3 @@
1
+ /** Compact elapsed time shared by tool responses and interactive views. */
2
+ export declare function formatDuration(ms: number): string;
3
+ //# sourceMappingURL=duration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"duration.d.ts","sourceRoot":"","sources":["../../src/utils/duration.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAYjD"}
@@ -0,0 +1,17 @@
1
+ /** Compact elapsed time shared by tool responses and interactive views. */
2
+ export function formatDuration(ms) {
3
+ if (ms < 500)
4
+ return "<1s";
5
+ const seconds = Math.round(ms / 1000);
6
+ if (seconds < 60)
7
+ return `${seconds}s`;
8
+ const minutes = Math.floor(seconds / 60);
9
+ if (minutes < 60) {
10
+ const remainder = seconds % 60;
11
+ return remainder === 0 ? `${minutes}m` : `${minutes}m ${remainder}s`;
12
+ }
13
+ const hours = Math.floor(minutes / 60);
14
+ const remainder = minutes % 60;
15
+ return remainder === 0 ? `${hours}h` : `${hours}h ${remainder}m`;
16
+ }
17
+ //# sourceMappingURL=duration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"duration.js","sourceRoot":"","sources":["../../src/utils/duration.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,MAAM,UAAU,cAAc,CAAC,EAAU;IACxC,IAAI,EAAE,GAAG,GAAG;QAAE,OAAO,KAAK,CAAC;IAC3B,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;IACtC,IAAI,OAAO,GAAG,EAAE;QAAE,OAAO,GAAG,OAAO,GAAG,CAAC;IACvC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;IACzC,IAAI,OAAO,GAAG,EAAE,EAAE,CAAC;QAClB,MAAM,SAAS,GAAG,OAAO,GAAG,EAAE,CAAC;QAC/B,OAAO,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,GAAG,CAAC,CAAC,CAAC,GAAG,OAAO,KAAK,SAAS,GAAG,CAAC;IACtE,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;IACvC,MAAM,SAAS,GAAG,OAAO,GAAG,EAAE,CAAC;IAC/B,OAAO,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,KAAK,SAAS,GAAG,CAAC;AAClE,CAAC","sourcesContent":["/** Compact elapsed time shared by tool responses and interactive views. */\nexport function formatDuration(ms: number): string {\n\tif (ms < 500) return \"<1s\";\n\tconst seconds = Math.round(ms / 1000);\n\tif (seconds < 60) return `${seconds}s`;\n\tconst minutes = Math.floor(seconds / 60);\n\tif (minutes < 60) {\n\t\tconst remainder = seconds % 60;\n\t\treturn remainder === 0 ? `${minutes}m` : `${minutes}m ${remainder}s`;\n\t}\n\tconst hours = Math.floor(minutes / 60);\n\tconst remainder = minutes % 60;\n\treturn remainder === 0 ? `${hours}h` : `${hours}h ${remainder}m`;\n}\n"]}
@@ -0,0 +1,3 @@
1
+ /** A non-negative integer limit: `fallback` for a missing or non-finite value, otherwise floored and capped at `ceiling`. */
2
+ export declare function finiteLimit(value: number | undefined, fallback: number, ceiling: number): number;
3
+ //# sourceMappingURL=number.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"number.d.ts","sourceRoot":"","sources":["../../src/utils/number.ts"],"names":[],"mappings":"AAAA,6HAA6H;AAC7H,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAEhG"}
@@ -0,0 +1,5 @@
1
+ /** A non-negative integer limit: `fallback` for a missing or non-finite value, otherwise floored and capped at `ceiling`. */
2
+ export function finiteLimit(value, fallback, ceiling) {
3
+ return value === undefined || !Number.isFinite(value) ? fallback : Math.max(0, Math.min(ceiling, Math.floor(value)));
4
+ }
5
+ //# sourceMappingURL=number.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"number.js","sourceRoot":"","sources":["../../src/utils/number.ts"],"names":[],"mappings":"AAAA,6HAA6H;AAC7H,MAAM,UAAU,WAAW,CAAC,KAAyB,EAAE,QAAgB,EAAE,OAAe;IACvF,OAAO,KAAK,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACtH,CAAC","sourcesContent":["/** A non-negative integer limit: `fallback` for a missing or non-finite value, otherwise floored and capped at `ceiling`. */\nexport function finiteLimit(value: number | undefined, fallback: number, ceiling: number): number {\n\treturn value === undefined || !Number.isFinite(value) ? fallback : Math.max(0, Math.min(ceiling, Math.floor(value)));\n}\n"]}
@@ -1,22 +1,22 @@
1
1
  # Agent — lightweight delegation
2
2
 
3
- The bundled `Agent` extension adds the `Agent` tool and `/agent` settings command. One call delegates one self-contained task to a temporary Agent and returns its final report. Use it sparingly for independent work that clearly benefits from separate context or parallel execution. There are no General/Explore profiles, batch arrays, persistent worker identities, or chain modes.
3
+ The bundled `Agent` extension adds the `Agent` tool and `/agent` settings command. One call delegates one self-contained task to a temporary Agent and returns its final report; the Agent does not converse with its parent while it runs. Use it when independent work clearly benefits from separate context or parallel execution. Keep design and substantial coding in the main session; Agents are primarily for independent research, verification, and well-specified, self-contained implementation. Handle known-path reads and small edits directly. There are no General/Explore profiles, batch arrays, persistent worker identities, chain modes, or mid-run messaging and steering.
4
4
 
5
5
  ## Tool contract
6
6
 
7
7
  ```json
8
8
  {
9
9
  "description": "Inspect Tasks persistence",
10
- "prompt": "Trace task-result restoration and report the relevant paths and invariants. Do not edit files.",
10
+ "prompt": "Trace task-record restoration and report the relevant paths and invariants. Do not edit files.",
11
11
  "background": false
12
12
  }
13
13
  ```
14
14
 
15
- - `prompt` is required, must be self-contained, and is limited to 16 KiB. The Agent cannot see the parent conversation.
16
- - `description` is an optional short label for the Transcript and `/tasks`; otherwise Pi derives one from the prompt.
17
- - `background` is optional. Foreground waits for the report; `true` returns a Task ID after initialization and delivers the report automatically. Interactive **Ctrl+B** can detach a foreground call without restarting it.
15
+ - `prompt` is required, must be self-contained, and is limited to 16 KiB. The Agent cannot see the parent conversation. Include the goal and rationale, prior findings, relevant paths and constraints, whether to investigate or edit, and expected verification. For open investigations, hand over the question rather than a fragile step-by-step procedure.
16
+ - `description` is an optional short (3–5 word) label for the Transcript and `/tasks`; otherwise Pi derives one from the prompt.
17
+ - `background` is optional. Foreground waits for the report; `true` returns a Task ID once the Agent has initialized, or at once while it waits for a slot, and delivers the report automatically. Interactive **Ctrl+B** can detach a foreground call without restarting it.
18
18
 
19
- Issue parallel `Agent` calls for independent work. Each call is a separate Transcript row and Task, including its own completion notification; there is no aggregate batch view. At most four Agents run concurrently in one extension runtime, with additional calls queued visibly in Tasks. Parallel tasks must not perform overlapping writes.
19
+ Issue parallel `Agent` calls for independent work. Each call is a separate Transcript row and Task, including its own completion notification; there is no aggregate batch view. At most four Agents run at once in a session; additional calls wait as queued Tasks and start when a slot frees. A queued background call returns its Task ID immediately, and **Ctrl+B** can move a queued foreground call to the background before it starts. Parallel tasks must not perform overlapping writes.
20
20
 
21
21
  Agents use the parent's working directory and share its canonical model/authentication runtime. Their isolated in-memory sessions have `read`, `bash`, `edit`, and `write`, with shell commands covering file discovery and search. They load applicable repository instructions and do not load extensions, skills, prompt templates, or themes. They cannot recursively delegate or start managed background work. The full child conversation is not persisted separately.
22
22
 
@@ -24,7 +24,9 @@ Resource discovery preserves the parent's project-trust decision. Declining trus
24
24
 
25
25
  ## Model and thinking settings
26
26
 
27
- Run `/agent` to choose **Model** or **Thinking**. The model picker is searchable; either setting can follow the current session. Choices apply only to future Agents and never switch the parent session or change running work.
27
+ Run `/agent` to choose **Model** or **Effort**, reusing the searchable `/model` and `/thinking` selectors. The compact panel shows the full `provider/model-id` and current effort on aligned single lines. An unset field adds `· Follow current session`; when the requested effort is unsupported, the panel shows the requested and effective levels, such as `max → high · Follow current session`. Fixed overrides also show a conversion when necessary, without the inheritance suffix. Choices apply only to future Agents and never switch the parent session or change running work.
28
+
29
+ **Reset to follow current session** is always available and clears both Agent overrides in one save, preserving unrelated settings. Resetting fields that already inherit is a no-op. Choosing a specific model or effort makes that field fixed, even when it equals the inherited value. Picker confirmation never changes global model or thinking defaults.
28
30
 
29
31
  Settings are stored in the global `settings.json`:
30
32
 
@@ -41,7 +43,7 @@ Settings are stored in the global `settings.json`:
41
43
 
42
44
  Omit either field to inherit it. Thinking is clamped to the effective model's supported levels. A configured model that no longer exists or has no authentication fails explicitly instead of silently selecting another model.
43
45
 
44
- Malformed model or thinking fields are marked `[invalid]` in `/agent`, where you can replace them or explicitly reset each field to follow the current session. Escape leaves settings unchanged, and repairs preserve the other fields and extension namespaces. Invalid JSON or a malformed namespace object must be repaired in `settings.json`; Pi does not overwrite that damaged configuration automatically.
46
+ Malformed model or thinking fields are marked `[invalid]` in `/agent`, where you can replace them through their native picker or explicitly reset both fields to follow the current session. A missing model is marked `[unavailable]`, and effort stays `[unresolved]` rather than using the parent model's capabilities. Cancelling a picker leaves its setting unchanged; closing the panel retains earlier confirmed saves. Repairs preserve the other fields and extension namespaces. Invalid JSON or a malformed namespace object must be repaired in `settings.json`; Pi does not overwrite that damaged configuration automatically.
45
47
 
46
48
  ## Transcript and Tasks
47
49
 
@@ -54,13 +56,13 @@ The Transcript only describes status and current work. It never includes the Pro
54
56
  | Completed | One duration and `/tasks` status line | Identical |
55
57
  | Failed or cancelled | One short diagnostic or cancellation line | Identical |
56
58
 
57
- Shell activity shows only the first non-empty command line and retains the actual tool name. Tasks Output holds bounded argument summaries and tool-failure excerpts while the Agent runs; successful intermediate tool output is not retained in the parent Tasks record. The final report replaces live activity.
59
+ Shell activity shows only the first non-empty command line and retains the actual tool name. The human-only Tasks display holds bounded argument summaries and tool-failure excerpts; successful intermediate tool output is not retained in the parent Tasks record. While running, model-facing `tasks read` returns one status line, such as `Agent running · 3 tool calls · latest: bash npm test`; after settlement it returns the final report. Intermediate assistant text and Tool calls never reach the parent model. To change direction, kill the Agent and delegate again with a better briefing.
58
60
 
59
61
  In `/tasks`, each Agent remains an independent row:
60
62
 
61
- - **Output** shows actual tool activity while running and the final report with Markdown formatting after successful completion. Oversized reports remain available through their managed output file.
63
+ - **Output** shows the status line and compact Tool calls while running, written like the expanded Transcript: `✓ read README.md · 4ms`. A successful final report uses Markdown formatting, followed by the retained Tool calls. Oversized reports remain available through their managed output file.
62
64
  - **Details** shows the full Prompt, working directory, model, and thinking level.
63
65
 
64
- Use `tasks read`, `tasks wait`, or `tasks kill` with the Task ID. Selection, scrolling, cancellation, foreground detach, history, and completion delivery are owned by the shared Tasks implementation. Parent cancellation stops foreground-owned work, including cancellation received during startup; detached work continues until it finishes or is killed. Reload, session replacement, and shutdown cancel active Agents.
66
+ Use `tasks read`, `tasks wait`, or `tasks kill` with the Task ID. Reading requires no view options: the status line or report is the model projection, while the `/tasks` panel adds the human-only Tool-call display. Selection, scrolling, cancellation, foreground detach, history, and completion delivery are owned by the shared Tasks implementation. Parent cancellation stops foreground-owned work, including cancellation received during startup; detached work continues until it finishes or is killed. Reload, session replacement, and shutdown cancel active Agents.
65
67
 
66
- Inline reports are bounded to 24 KiB. Longer reports are written in full to a managed temporary Markdown file, and the tool result includes a bash-style `Full output: <path>` notice. Use `read` on that path or `tasks read` for retained output; a failure to save the file falls back to a bounded report without changing the Agent's outcome. Activity history is limited to the latest 50 tool calls, and published task results use the shared Tasks limits. Inline report previews, static Details, usage, and completion state restore through the parent session branch. Managed output files follow the Tasks lifecycle and never survive restart; live execution never resumes either.
68
+ Inline reports are bounded to 24 KiB. Longer reports are written in full to a managed temporary Markdown file, and the tool result includes a bash-style `Full output: <path>` notice. Use `read` on that path or `tasks read` for retained output; a failure to save the file falls back to a bounded report without changing the Agent's outcome. Activity history is limited to the latest 50 tool calls, and published task results use the shared Tasks limits. A background completion delivers the report from its beginning, whole when it fits the notification budget, so the parent reads the same report a foreground call would have returned. Inline report previews, Details, usage, and completion state restore through the parent session branch. Managed output files follow the Tasks lifecycle and never survive restart; live execution never resumes either.
@@ -23,13 +23,22 @@ Native compaction accepts the same native file-list shape in extension-provided
23
23
 
24
24
  ## Result card
25
25
 
26
- A successful cached-path compaction adds a persistent display-only card after the summary:
26
+ A successful cached-path compaction adds a persistent display-only card, a one-line footnote under the compaction summary:
27
27
 
28
28
  ```text
29
- Cached compaction · manual
30
- Cache 641.2k/648.8k (98.8%) · output 2.8k · 18.4s
29
+ From cache · CH 98.8% · ↓2.8k · 18s
31
30
  ```
32
31
 
33
- Automatic compaction is labelled `automatic`. The cache figures are the response's actual `cacheRead` divided by `input + cacheRead + cacheWrite`; the card also shows output tokens and elapsed time. It contains no cost estimate and never enters model context. Native fallback adds no card.
32
+ Automatic compaction adds `auto` after `From cache`. `CH` is the summary request's cache hit rate, its actual `cacheRead` divided by `input + cacheRead + cacheWrite`, written with the same `↑ ↓ R W CH` units as the footer; it is green from 80%, a warning color below 50%, and omitted when the provider reported no cache activity. The card then shows output tokens and elapsed time.
33
+
34
+ Expanding tool output (Ctrl+O) expands the card with the summary, adding the reason and the prompt broken down by billing:
35
+
36
+ ```text
37
+ From cache · manual · CH 98.8% · 18s
38
+ Prompt 649k = R641k cached + W4.5k written + ↑3.1k uncached
39
+ Output ↓2.8k
40
+ ```
41
+
42
+ The card contains no cost estimate and never enters model context. Native fallback adds no card.
34
43
 
35
44
  The extension registers no commands or settings.
@@ -52,11 +52,13 @@ Avoid DeepWiki when the authoritative source is local or time-sensitive:
52
52
 
53
53
  - A repository may not be indexed. DeepWiki can return that as normal text, so the extension treats repository-not-found messages as tool errors.
54
54
  - All model-facing responses are capped at 120,000 characters. `contents` prefers `# Page:` boundaries (whole pages kept in order; at least the first page survives, cut mid-page if it alone exceeds the budget). Its trailing notice reports shown/total pages, the full length, up to 20 omitted page titles, and points at `page` reads and `action: "question"` for the rest. `structure` and `question` append a focused-request truncation notice. Details carry `shownPages` / `truncatedChars` when applicable; `outputLength` always reflects the full cached response. Single-page reads set `requestedPage` / `pageIndex` and share the same hard budget.
55
- - Each transport response is streamed with an 8 MiB byte limit before JSON/SSE parsing; oversized, failed, aborted, and timed-out responses never enter the cache. Network attempts time out after 45 seconds and surface as Pi tool errors.
55
+ - Each transport response is streamed with an 8 MiB byte limit before JSON/SSE parsing; oversized, failed, aborted, and timed-out responses never enter the cache. Network failures and transient HTTP statuses (408, 425, 429, 500, 502, 503, 504) are retried up to twice without delay; caller cancellation and timeouts are not retried. The whole call, retries included, times out after 45 seconds and surfaces as a Pi tool error.
56
56
  - Use local Pi tools (`read`, `grep`, `find`, `ls`) for workspace state. DeepWiki answers describe repository snapshots indexed by DeepWiki, not local uncommitted files.
57
57
 
58
58
  ## Implementation notes
59
59
 
60
+ Each uncached call is one stateless JSON-RPC `tools/call` POST: DeepWiki's endpoint issues no MCP session, so the extension skips the initialize handshake that `McpClient` would add to every call. It validates the response with `@earendil-works/pi-mcp`'s JSON-RPC parser and reads either a JSON or an SSE body.
61
+
60
62
  DeepWiki's public MCP endpoint exposes exactly three operations: list a wiki's page titles, return the whole generated wiki as one document, and answer a question. There is no per-page fetch upstream — `page` is implemented by this extension: it fetches the full wiki (or reuses the 10-minute cache) and slices out the requested page locally. The first `contents` call for a repo pays the network cost; subsequent page reads within the cache window are instant and free.
61
63
 
62
64
  DeepWiki may return generated explanations with source-file citations and "related pages" links. The TUI uses a local renderer (`render.ts`) rather than Pi's generic fallback, which would dump the full (often large) `content` text. Call questions, page names, and result titles are whitespace-normalized into bounded one-line summaries. Collapsed result text uses the quieter tool-output color and keeps the configured expand hint on the same logical line; expanding renders the complete response as Markdown. Historical malformed titles, requested pages, and error messages are bounded and fall back safely instead of breaking transcript rendering.
@@ -42,7 +42,7 @@ CTX 2.1%/1.0M ↑13k ↓13k R440k CH99.4% $0.074
42
42
 
43
43
  - Extension status text from `ctx.ui.setStatus()` is sorted by key and pinned to the center of the line — anchored to the absolute line center so it does not drift as the usage cluster grows, falling back to balancing the free space when the side zones collide with the center anchor. When space runs out it is dropped so CTX and usage stay readable. Plain text is muted; strings that already carry ANSI color are left unchanged.
44
44
 
45
- Background billing uses the first valid `task-usage` record per execution ID; managed foreground results omit duplicate `usage`. Opening `/tasks`, detaching, or repeating `tasks read`/`wait` does not add billing. Accrued worker retry, cancellation, failure, and provider-supplied compaction usage is included when settled; missing usage is not fabricated. Quarantined late settlements are excluded from active totals. This does not change the footer's active-branch scope (session-wide statistics can include other branches), parent CTX estimate, or latest-parent-request `CH`. See the [persisted record format](../../session-format.md#background-records).
45
+ Background billing uses the first valid task usage settlement per execution ID, from a `task-record` or a released session's `task-usage` entry; managed foreground results omit duplicate `usage`. Opening `/tasks`, detaching, or repeating `tasks read`/`wait` does not add billing. Accrued worker retry, cancellation, failure, and provider-supplied compaction usage is included when settled; missing usage is not fabricated. Quarantined late settlements are excluded from active totals. This does not change the footer's active-branch scope (session-wide statistics can include other branches), parent CTX estimate, or latest-parent-request `CH`. See the [persisted record format](../../session-format.md#background-records).
46
46
 
47
47
  The built-in Tasks UI can supply centered status text such as `tasks 2 active · 1 finished`. These counts cover backgrounded executions; worker rows are not separate groups. The old prompt-stall watchdog and `waiting for input` counts are no longer generated.
48
48
 
@@ -27,7 +27,7 @@ Hosts can prohibit background execution with `backgroundAllowed: false`. This re
27
27
  | Action | Parameters | Behavior |
28
28
  |---|---|---|
29
29
  | `list` | — | Lists active and up to five retained finished records, at most 100 rows; foreground executions are omitted with a count (they deliver inline in the transcript) |
30
- | `read` | `taskId`, optional `mode`, `bytes` | Reads bounded output/report while running or after completion |
30
+ | `read` | `taskId`, optional `mode`, `bytes` | Reads bounded model-readable output/report while running or after completion; running Agents return a one-line status without Tool calls |
31
31
  | `wait` | optional `taskId`, `waitMs`, `sinceBytes` | Waits for one task, or for any task running at call time when `taskId` is omitted |
32
32
  | `kill` | `taskId` | Requests cancellation of the selected task |
33
33
 
@@ -37,7 +37,7 @@ Use the execution ID returned by the native tool or `tasks list`. An unknown or
37
37
  { "action": "read", "taskId": "<execution-id>", "mode": "tail", "bytes": 8192 }
38
38
  ```
39
39
 
40
- Reads default to an 8KB tail. `bytes` clamps between 256 bytes and 48KB; `mode` can be `head` or `tail`. A Bash output path is included when available. Tasks without a log return their bounded published result. Every read and settled wait reports its byte range and where to continue, for example `bytes 92160–100352 of 100352 · next sinceBytes 100352`. Use a returned offset with that task's ID; waitAny does not accept a cross-task offset.
40
+ Reads default to an 8KB tail. `bytes` clamps between 256 bytes and 48KB; `mode` can be `head` or `tail`. A Bash output path is included when available. Tasks without a log return their bounded published result. Executors can separately attach human-only display text: `/tasks` shows it, while `tasks read`, settled waits, and completion context exclude it. Agent Tool calls use this display channel, so no read-view parameter is needed. Every read and settled wait reports its byte range and where to continue, for example `bytes 92160–100352 of 100352 · next sinceBytes 100352`. Use a returned offset with that task's ID; waitAny does not accept a cross-task offset.
41
41
 
42
42
  ```json
43
43
  { "action": "wait", "taskId": "<execution-id>", "waitMs": 20000, "sinceBytes": 4096 }
@@ -63,32 +63,33 @@ All model-facing management responses, including listings and error messages, ar
63
63
 
64
64
  ## `/tasks` panel
65
65
 
66
- The fullscreen panel has one scrollable list. **Active** groups queued, running and stopping work; **Finished** groups all retained results on the selected branch, including foreground shell results, newest first. Empty groups are hidden. Task summaries show status and elapsed time; foreground/background mode is available in Details. Durations omit zero components and separate remaining units (`8s`, `1m`, `1m 5s`, `1h 5m`). The background action is offered only when the selected task can move.
66
+ The fullscreen panel has one scrollable list. **Active** groups queued, running and stopping work; **Finished** groups all retained results on the selected branch, including foreground shell results, newest first. Empty groups are hidden. Each task is one row: its status glyph, its source label such as Bash or Agent in an aligned dim column, the title, and right-aligned metadata. The metadata shows elapsed time, the status name for every status except running, completed and failed, whose glyphs are unambiguous, and an ID suffix when two titles are identical. Foreground/background mode is available in Details. Durations omit zero components and separate remaining units (`8s`, `1m`, `1m 5s`, `1h 5m`). The background action is offered only when the selected task can move.
67
67
 
68
- Selection follows the task when it finishes; new work does not steal focus or replace browsed output. The list preserves the selected row's screen position where space permits. Reopening remembers the selected ID and right-hand tab while the runtime remains available. Runtime replacement resets these preferences, and branch navigation removes results outside the visible branch. History remains bounded by the retention limits below.
68
+ Selection follows the task when it finishes; new work does not steal focus or replace browsed output. The list preserves the selected row's screen position where space permits. Reopening selects the newest task started since the panel last closed; when nothing new started, it keeps the remembered selection. The right-hand tab is remembered as well, while the runtime remains available. Runtime replacement resets these preferences, and branch navigation removes results outside the visible branch. History remains bounded by the retention limits below.
69
69
 
70
- At 100 columns or more, the task list sits beside an inspector. **Output** shows the result directly; **Details** holds the full command, directory, task ID, log location and executor-specific details. Each task and tab keeps its reading position for the lifetime of the panel. Tab switches between the two panes, preserving the right-hand tab. Left/Right switch Output/Details only when the inspector has focus.
70
+ At 100 columns or more, the task list sits beside an inspector. The inspector's first row names the selected task — `Bash · Running · 12s` — with the **Output** and **Details** tabs at its right. **Output** shows the result directly; **Details** starts with the source, task ID and status, then holds what the executor declared — its input such as the full command or prompt, and facts such as the directory, model or exit code — plus the log location. Each task and tab keeps its reading position for the lifetime of the panel. Tab switches between the two panes, preserving the right-hand tab. Left/Right switch Output/Details only when the inspector has focus.
71
71
 
72
72
  The focused pane has a highlighted border. Task selection uses a persistent row background, and the selected right-hand tab uses an underline; neither changes when focus moves. When the system theme has no background colors, the selected row uses inverse text. There are no focus arrows or extra title colors. Narrow terminals show one pane at full width with the same Tab navigation and no focus highlight. The inspector includes task context when the list is hidden. Escape closes the panel from either pane. The minimum supported size is 60 columns by 14 rows; below it, a centered dialog asks for a larger window and covers the screen, because the panel keeps input focus while open.
73
73
 
74
- Bash and PowerShell show live plain-text output. Other executors show their published result, and a task without a command is labeled by its title. Completed Agent reports use the native Markdown renderer; running Agent activity and other executor output remain literal text. An executor can also supply bounded static `info` text: Output remains the published result while Details shows that executor-owned context instead of the generic command fields. Missing logs fall back to the saved result. Task status, failure reasons and output-read errors remain distinct.
74
+ Every executor is presented the same way, from data it declares: a label such as Bash or Agent, an input, labelled facts, and whether its output is a log or a report. Logs show live plain-text output; other executors show their published result plus any human-only display suffix, updated as soon as the executor publishes rather than on the log poll. A completed report, such as an Agent's, uses the native Markdown renderer while its retained activity remains literal text. Agent Output combines its status line or report with compact Tool calls, written as in the transcript: `✓ read README.md · 4ms`. A task without an input shows its title in Details. Missing logs fall back to the saved result. Task status, failure reasons and output-read errors remain distinct.
75
75
 
76
76
  | Default key | Action |
77
77
  |---|---|
78
- | `/` | Locate any retained task by title, command, kind or ID; Up/Down choose a candidate, Enter or clicking locates it and restores the full list, Escape restores the prior selection and focus |
78
+ | `/` | Locate any retained task by title, input, label, kind or ID; Up/Down choose a candidate, Enter or clicking locates it and restores the full list, Escape restores the prior selection and focus |
79
79
  | Left / Right | Output / Details, only while the inspector has focus |
80
80
  | Tab / Shift+Tab | Switch between list and inspector, preserving the current tab |
81
81
  | Up / Down | Select a task or scroll the focused region |
82
+ | Enter | Open the selected task: focus the inspector, or show it full width in a narrow terminal |
82
83
  | Page Up / Page Down | Page the focused list or region |
83
84
  | Home / End | Top / bottom of the list or bounded preview |
84
85
  | `f` | Follow the latest output, or load the final output after completion, while Output has focus |
85
86
  | `b` | Move only the selected eligible foreground task to the background |
86
- | `k`, then Enter | Request cancellation of the selected whole task; Escape cancels confirmation. Confirmation has no time limit and closes if its target finishes |
87
- | `?` | Show configurable controls; Up/Down scroll the help |
87
+ | `k`, then Enter | Request cancellation of the selected whole task. The footer asks `Stop Bash "npm test"?` while the list and inspector stay visible; Escape cancels. Confirmation has no time limit and closes if its target finishes |
88
+ | `?` | Show configurable controls, grouped into Navigate, View and Act; Up/Down scroll the help |
88
89
  | Escape | Close the current search, help or confirmation first; otherwise close the panel |
89
90
  | Ctrl+B | Detach **all** eligible foreground executions through the host |
90
91
 
91
- Click a pane to focus it, a task row to select it, or a tab label to display it. The mouse wheel scrolls the pane under the pointer without changing keyboard focus or task selection. Footer hints are clickable as well, including while a transient confirmation owns that row: the click dismisses it and performs the hint's action. Search, help and confirmation consume their own input without activating the panel behind them.
92
+ Click a pane to focus it, a task row to select it, or a tab label to display it. The mouse wheel scrolls the pane under the pointer without changing keyboard focus or task selection. Footer hints are clickable as well, including while transient feedback owns that row: the click dismisses it and performs the hint's action. While a stop question owns the footer, only its stop and cancel actions respond. Search, help and confirmation consume their own input without activating the panel behind them.
92
93
 
93
94
  Shell output initially follows the tail, marked **Live** next to the output. Scrolling up enters **Browsing**, which holds a bounded output snapshot while status continues updating. In Output, press `f`, End, or scroll down to the bottom to resume following. If the task finishes while browsing, the panel offers to load its final output. Closing or scrolling never pauses, restarts or cancels execution.
94
95
 
@@ -102,11 +103,11 @@ The statusline counts only queued, running and stopping background tasks: `1 bac
102
103
 
103
104
  ## Completion notifications
104
105
 
105
- Interactive `task-completion` messages have a compact collapsed summary: outcome, execution kind, duration, short ID, and the command or, without one, the task title. Failures retain a short reason; log paths, output and worker reports stay out of the collapsed view. In fullscreen mode, left-click the notification to expand or collapse that message independently. The blank spacer above it is not a click target. The configured tool-output expansion binding (default Ctrl+O) remains available for toggling output expansion across the transcript.
106
+ Interactive `task-completion` messages have a compact collapsed summary: the executor's label, outcome, duration, short ID, and the task title. Failures retain a short reason; log paths, output and worker reports stay out of the collapsed view. In fullscreen mode, left-click the notification to expand or collapse that message independently. The blank spacer above it is not a click target. The configured tool-output expansion binding (default Ctrl+O) remains available for toggling output expansion across the transcript.
106
107
 
107
- Expanded notifications separate **Command** (or **Task** for a titled task), **Directory**, **Result** or **Error** with the recorded exit code, a bounded plain-text **Output** tail, **Log** and the full execution ID. The saved output keeps the end of the result, where the outcome is, and carries an explicit truncation flag. Screen line limits are independent of source truncation. These are previews of the saved bounded completion.
108
+ Expanded notifications separate the input under its own label, such as **Command** or **Prompt** (or **Task** without one), **Details** with the declared facts such as directory and exit code, **Result** or **Error**, a bounded plain-text **Output** preview, **Log** and the full execution ID. A log's saved output keeps its end, where the outcome is; a report's keeps its beginning, where the conclusion is. Both carry an explicit truncation flag. Screen line limits are independent of source truncation. These are previews of the saved bounded completion.
108
109
 
109
- Rendering reads the self-contained `TaskCompletionSnapshot` in message `details`, so `/reload`, history eviction, expired logs and restart do not require a live task lookup. The session generates model-facing `content` from the same facts; `details` never enters model context or usage accounting. Replay details retain a 40 KiB output tail, while the automatic model-facing notification includes only an 8 KiB tail plus the log path and truncation guidance for `tasks read`. Commands containing `Output:` and literal truncation notices remain ordinary data. See the [snapshot contract](../session-format.md#background-records).
110
+ Rendering reads the self-contained terminal snapshot in message `details`, so `/reload`, history eviction, expired logs and restart do not require a live task lookup. The session generates model-facing `content` from the same facts; `details` never enters model context or usage accounting. Replay details retain up to 40 KiB of output. The automatic model-facing notification includes only an 8 KiB tail of a log, plus the log path and truncation guidance for `tasks read`; a report arrives from its beginning, whole when it fits the 48 KiB budget, as its foreground result would. Commands containing `Output:` and literal truncation notices remain ordinary data. See the [snapshot contract](../session-format.md#background-records).
110
111
 
111
112
  Only the current structured completion format (version 2) is specialized. Older completions, including version-1 shell and report completions, and malformed details receive a bounded plain **Details** view of their saved message; no text reconstruction or migration is performed. Legacy `background-task` notifications show as plain messages. HTML export and `/tree` selector labels continue to display the saved message content.
112
113
 
@@ -122,7 +123,7 @@ Managed shell output is collected continuously from startup, including before de
122
123
 
123
124
  Managed logs are ephemeral: they are retained with the runtime record and cleaned up when that record is evicted or the runtime shuts down. Save needed output elsewhere before then. The core defaults to eight concurrent background executions and two independent terminal histories: 32 background results plus 32 foreground results. Foreground work of any kind can only evict older foreground records. Pending delivery, pins, active reads and cleanup use a separate allowance within the bounded total; pins temporarily defer history eviction, not runtime shutdown. These are service limits, not new user settings.
124
125
 
125
- Terminal snapshots persist as version-2 `task-result` custom entries; usage remains in independent version-1 `task-usage` entries. A foreground snapshot omits its output, which the transcript already saves in the tool result, and restoration reads it back from there. The runtime restores version-2 terminal history from the selected branch for programmatic reads and the panel's Finished group, selecting the newest records independently for each history. Older result records are left in the session file and are not migrated or restored. Live execution never resumes after restart, and restoration does not replay accounting or completion events. Restored records drop their log path: logs never outlive the runtime that wrote them. See [session format](../session-format.md#background-records).
126
+ Each settlement appends one version-3 `task-record` custom entry holding the terminal snapshot and its usage. A foreground snapshot omits its output, which the transcript already saves in the tool result, and restoration reads it back from there. The runtime restores version-3 terminal history from the selected branch for programmatic reads and the panel's Finished group, selecting the newest records independently for each history. Older `task-result` records are left in the session file and are not migrated or restored; usage from released sessions still counts. Live execution never resumes after restart, and restoration does not replay accounting or completion events. Restored records drop their log path: logs never outlive the runtime that wrote them. See [session format](../session-format.md#background-records).
126
127
 
127
128
  Delivered history outside the selected branch can be released and restored on return, so it does not fill the new branch's history budget. Undelivered completions stay protected while their branch is hidden. Pending delivery, pins and active reads use a separate allowance within the total runtime retention cap; restoration respects the same cap.
128
129
 
@@ -554,6 +554,7 @@ pi.on("session_compact", async (event, ctx) => {
554
554
  // event.fromExtension - whether extension provided it
555
555
  // event.reason - "manual" (/compact), "threshold", or "overflow"
556
556
  // event.willRetry - whether overflow recovery will actually retry after retained-context verification
557
+ // Entries appended here with pi.appendEntry() render after the compaction summary.
557
558
  });
558
559
 
559
560
  pi.on("session_compact_failed", async (event, ctx) => {
@@ -1256,30 +1257,45 @@ Session-bound `TasksContext` supervises native and extension-owned execution. Fo
1256
1257
 
1257
1258
  | Method | Contract |
1258
1259
  |---|---|
1259
- | `execute<T>(execution)` | Returns `{ kind: "result", result, status?, error? }` or `{ kind: "background", task }` |
1260
+ | `execute<T>(execution)` | Returns `{ kind: "result", result, status, error? }` or `{ kind: "background", task }` |
1260
1261
  | `list()` / `get(id)` | Bounded, read-only (frozen) retained snapshots; IDs support unique prefixes |
1261
- | `read(id, options?)` | Bounded head, tail, or byte-offset output |
1262
- | `wait(id, timeoutMs?, signal?, interruptSignal?)` | Observation only; timeout, cancellation, or `interruptSignal` ends the wait, not execution |
1263
- | `waitAny(timeoutMs?, signal?, interruptSignal?)` | Observes the first task running at call time to settle; returns `undefined` for an empty cohort, timeout, interruption, or closed host. Later tasks are excluded |
1262
+ | `read(id, options?)` | Bounded head, tail, or byte-offset model-readable output; excludes human-only display text |
1263
+ | `wait(id, options?)` | One observation of one task. `options`: `timeoutMs`, `signal`, `toolCallId`, and `read: { bytes?, sinceBytes? }`. Returns `{ outcome, waitedMs, task, read? }` where `outcome` is `settled`, `timed_out`, `interrupted` (host steering), or `closed` (host shut down; state unconfirmed). Timeout, cancellation, or interruption ends the wait, not execution |
1264
+ | `waitAny(options?)` | Observes the first task running at call time to settle, with `timeoutMs`, `signal`, `toolCallId`, and `read: { bytes? }`. Returns `{ outcome, waitedMs, task?, read?, running }`; `outcome` adds `no_tasks` for an empty cohort. Later tasks are excluded |
1264
1265
  | `kill(id)` | Requests cancellation; `stopping` is not a terminal status |
1265
1266
  | `detach(id)` / `detachForeground()` | Hands off one task, or eligible foreground tasks oldest first while background slots remain, without restarting them; throws when every background slot is taken |
1266
1267
  | `canDetach(id)` | Reports whether an execution can move now, including host policy and available background slots; does not change the execution |
1267
1268
  | `subscribe(listener)` | Observes task state and progress |
1268
1269
  | `retain(id)` | Returns an idempotent release function protecting retained data, without delaying notifications |
1269
- | `holdDelivery(id)` | Explicitly retains data and delays automatic delivery until released |
1270
1270
 
1271
- `TaskExecution<T>` supplies `kind`, `title`, `toolCallId`, `run(control)`, optional `command`, `cwd`, `info`, `background`, `signal`, and `onUpdate`. Bounded static `info` text appears in the panel's Details tab; Output continues to show published results. It restores with terminal task history but never enters model context. `kind` is an executor-owned source label matching `[a-z][a-z0-9-]{0,63}`; the runtime never dispatches on it. At most eight background executions run at once; foreground executions are not limited by them. Foreground and background results have separate history quotas.
1271
+ `TaskExecution<T>` supplies `kind`, `title`, `toolCallId`, and `run(control)`, plus optional fields:
1272
1272
 
1273
- `run` returns `TaskCompletion<T>`: `{ result, status?, error?, exitCode?, usage? }`. The original tool result is returned to a foreground caller; private `result.details` is not copied into task history. Explicit terminal statuses are `completed`, `partial`, `failed`, `cancelled`, and `timeout`. Usage is settled by the host once; managed foreground results omit usage to avoid billing it twice.
1273
+ | Field | Contract |
1274
+ |---|---|
1275
+ | `label` | Human source name for the panel and completion card, such as `Bash` or `Agent`; defaults to `kind` |
1276
+ | `output` | `"log"` (default) or `"report"`. A log's outcome is at its end, so a background completion gives the model an 8 KiB tail. A report leads with its conclusion, so it arrives from its beginning, whole when it fits the 48 KiB context budget, as its foreground result would; a completed report renders as Markdown in `/tasks` |
1277
+ | `input` | `{ label, text, truncated, language? }`: what the task was asked to do, such as a command or briefing. Shown in Details and the expanded completion card, highlighted when `language` is set |
1278
+ | `facts` | Up to 16 labelled `[label, value]` Details rows, such as `["Directory", cwd]` |
1279
+ | `concurrency` | `{ key, limit }`: at most `limit` executions sharing `key` run at once. Later ones wait as `queued` tasks and `run` starts when a slot frees |
1280
+ | `background`, `signal`, `onUpdate` | Requested handoff, parent cancellation, and foreground progress forwarding |
1281
+
1282
+ `kind` is an executor-owned source label matching `[a-z][a-z0-9-]{0,63}`; the runtime never dispatches on it. Presentation is declared data: the panel and completion card render `label`, `input`, `facts`, and `output` the same way for every executor. Input and facts restore with terminal task history; facts also appear in the completion notification. At most eight background executions, queued ones included, are retained as active at once; foreground executions are not limited by them. Foreground and background results have separate history quotas.
1283
+
1284
+ A caller can be handed off to the background while its task is queued, before `run` starts, or after `run` calls `accept()`. A queued task becomes `running` when its `run` starts; cancelling it settles it as `cancelled` without starting it.
1285
+
1286
+ `run` returns `TaskCompletion<T>`: `{ result, status?, display?, error?, facts?, usage? }`. The original tool result is returned to a foreground caller; task history keeps only its bounded text. Optional `display` is bounded human-only Output suffix text, excluded from `tasks read`, settled waits, and completion context. Terminal `facts` replace launch facts with the same label, as the shell does with `["Exit", "42"]`. Explicit terminal statuses are `completed`, `partial`, `failed`, `cancelled`, and `timeout`. The host settles usage once, preferring `usage`, then `result.usage`, then the latest published usage; managed foreground results omit usage to avoid billing it twice.
1274
1287
 
1275
- `TaskControl<T>` exposes `id`, `signal`, `mode`, `accept()`, `publish(result)`, `setOutputPath(path, cleanup?)`, `onModeChange(listener)`, and `requestCancel()`. `publish` replaces the task's bounded text result, which the `/tasks` panel, `tasks read`, and the completion notification show; a task with an output path is read from that log instead. Call `accept()` after whole-invocation preflight, before allowing a background handoff. Use the control's signal throughout execution. Parent-call cancellation is disconnected after handoff, while runtime shutdown still cancels the task. Mode subscriptions concern only this task; executors do not need the global registry to observe their own handoff or cancel themselves.
1288
+ `TaskControl<T>` exposes `id`, `signal`, `mode`, `onModeChange(listener)`, `accept()`, `publish(update)`, `attachOutput(path, cleanup?)`, and `cancel()`. `publish({ result, display?, usage? })` replaces the bounded model-readable result and optionally the human-only Output suffix and cumulative usage; `/tasks` combines result and display, while model reads and completion notifications use only the result. A task with an attached output file is read from that file instead. Call `accept()` after whole-invocation preflight, before allowing a background handoff. Use the control's signal throughout execution. Parent-call cancellation is disconnected after handoff, while runtime shutdown still cancels the task. Mode subscriptions concern only this task; executors do not need the global registry to observe their own handoff or cancel themselves.
1276
1289
 
1277
- Completion messages store a self-contained `TaskCompletionSnapshot`; only their bounded `content` enters model context, with an 8 KiB output tail while replay details retain 40 KiB. Built-in `tasks wait` binds delivery to the actual tool call, and the host confirms it after successful persistence; a settled waitAny binds only its winning task. Ordinary extension reads/waits, including `waitAny`, do not acknowledge delivery, and arbitrary tool-result detail fields cannot acknowledge a task.
1290
+ Completion messages store `{ version: 3, task }` in `details`, a bounded terminal `TaskSnapshot`; only their bounded `content` enters model context. Built-in `tasks wait` binds delivery to the actual tool call, and the host confirms it after successful persistence; a settled waitAny binds only its winning task. Reads and waits without a `toolCallId`, including `waitAny`, do not acknowledge delivery, and arbitrary tool-result detail fields cannot acknowledge a task.
1278
1291
 
1279
1292
  ```typescript
1280
1293
  const outcome = await ctx.tasks.execute({
1281
1294
  kind: "report-job",
1295
+ label: "Review",
1282
1296
  title: "Inspect project",
1297
+ output: "report",
1298
+ facts: [["Directory", ctx.cwd]],
1283
1299
  toolCallId,
1284
1300
  signal,
1285
1301
  background: params.background,
@@ -1293,7 +1309,7 @@ if (outcome.kind === "result") return outcome.result;
1293
1309
  return { content: [{ type: "text", text: `Task ${outcome.task.id} continues in the background.` }], details: undefined };
1294
1310
  ```
1295
1311
 
1296
- When Pi attaches the runtime to its durable session lifecycle, `ctx.tasks.session` exposes the small host integration used by management products: `waitInterruptSignal`, `prepareWait(toolCallId, taskId)`, and `stoppedByTreeNavigation(targetId)`. Standalone runtimes omit it, leaving waits observational. This bridge lets the bundled `tasks` extension coordinate persisted wait receipts and branch confirmations without importing `TaskSession` or interactive internals.
1312
+ When Pi attaches the runtime to its durable session lifecycle, `ctx.tasks.session` exposes `stoppedByTreeNavigation(targetId)`, which lists running tasks that navigating to an entry would cancel. Standalone runtimes omit it. Wait receipts and steering interruption are not extension concerns: the runtime applies them inside `wait()` and `waitAny()`. In a session host, passing the tool call's `toolCallId` keeps a settled background task out of automatic notifications from before the wait until that tool result is persisted, so the persisted result acknowledges it exactly once; without a `toolCallId`, or in a standalone runtime, a wait is purely observational.
1297
1313
 
1298
1314
  `TaskRuntime`, `TaskRuntimeOptions`, and the public `Task*`/`TasksContext`/`TasksSessionContext` types are exported from `@astralyn/pi`. Captured capabilities close with their runtime; obtain the replacement from the new session context after reload or session replacement.
1299
1315
 
package/docs/packages.md CHANGED
@@ -199,9 +199,10 @@ Filter what a package loads using the object form in settings:
199
199
  {
200
200
  "source": "npm:my-package",
201
201
  "extensions": ["extensions/*.ts", "!extensions/legacy.ts"],
202
- "skills": [],
202
+ "skills": ["skills"],
203
203
  "prompts": ["prompts/review.md"],
204
- "themes": ["+themes/legacy.json"]
204
+ "themes": ["+themes/legacy.json"],
205
+ "skillInvocationOverrides": { "skills/pdf": "user-only" }
205
206
  }
206
207
  ]
207
208
  }
@@ -215,10 +216,11 @@ Filter what a package loads using the object form in settings:
215
216
  - `+path` force-includes an exact path.
216
217
  - `-path` force-excludes an exact path.
217
218
  - Filters layer on top of the manifest. They narrow down what is already allowed.
219
+ - `skillInvocationOverrides` uses package-relative skill files or directories and accepts `"model-and-user"` or `"user-only"`. It controls model visibility, not resource loading.
218
220
 
219
221
  ## Enable and Disable Resources
220
222
 
221
- Use `pi config` to enable or disable extensions, skills, prompt templates, and themes from installed packages and local directories. `pi config` starts in global settings (`~/.pi/agent/settings.json`); press Tab to switch between global and project-local modes. Use `pi config -l` to start in project overrides (`.pi/settings.json`) with inherited global resources dimmed.
223
+ Use `pi config` to enable or disable extensions, prompt templates, and themes, and to switch skills between On, User only, and Off. User-only skills remain available as `/skill:name` but are omitted from the model's system prompt. `pi config` starts in global settings (`~/.pi/agent/settings.json`); press Tab to switch between global and project-local modes. Use `pi config -l` to start in project overrides (`.pi/settings.json`) with inherited global resources dimmed.
222
224
 
223
225
  ## Scope and Deduplication
224
226
 
package/docs/sdk.md CHANGED
@@ -254,7 +254,7 @@ The host must choose:
254
254
 
255
255
  - **Lifetime and cancellation:** a settled main-agent turn is not the end of background work. `session.abort()` cancels foreground-owned work, not detached work. Use `session.tasks.kill(id)` for a whole execution, or `await session.tasks.shutdown(graceMs?)` to close admission, cancel all owned work and drain within a bounded grace period (default 2 seconds, maximum 60 seconds). A non-cooperating executor can outlive that grace period.
256
256
  - **Result-driven turns and cost:** automatic completions join the host's prompt queue, so a running turn receives them as steering and an idle session starts a completion turn. Use the nestable `session.pauseTaskNotifications()` to defer delivery; its returned release function is idempotent. Pausing does not stop execution or its costs. Budget worker activity and completion-triggered turns explicitly.
257
- - **Observation and delivery:** `session.tasks` exposes the [public supervision methods](extensions.md#ctxtasks). `read()`, `wait()`, and `waitAny()` observe; a terminal snapshot alone does not acknowledge model delivery. `waitAny()` covers only tasks running at call time and returns `undefined` for an empty cohort, timeout, interruption, or closed host. The optional `interruptSignal` ends only a wait. The built-in `tasks wait` tool binds a delivery receipt to its tool-call ID; the host confirms it only after persisting the result, even if extensions rewrite its details. A direct SDK waiter that consumes the result outside model history can explicitly call `session.tasks.markDelivered(task.id)` after successful consumption. A timeout or cancelled wait does not stop the execution. Failed notification delivery leaves the result available for inspection; after fixing the host failure, call `session.retryTaskNotifications()` explicitly. Pi does not retry a failed delivery forever on a timer.
257
+ - **Observation and delivery:** `session.tasks` exposes the [public supervision methods](extensions.md#ctxtasks). `read()`, `wait()`, and `waitAny()` observe; a terminal snapshot alone does not acknowledge model delivery. `waitAny()` covers only tasks running at call time and reports `no_tasks` for an empty cohort. Both return a typed `outcome` (`settled`, `timed_out`, `interrupted`, or `closed`), and steering interrupts only waits, never execution. The built-in `tasks wait` tool passes its tool-call ID as `toolCallId`, so the runtime holds the observed result back from notifications and the host confirms it only after persisting that tool result, even if extensions rewrite its details. A direct SDK waiter that consumes the result outside model history omits `toolCallId` and can explicitly call `session.tasks.markDelivered(task.id)` after successful consumption. A timeout or cancelled wait does not stop the execution. Failed notification delivery leaves the result available for inspection; after fixing the host failure, call `session.retryTaskNotifications()` explicitly. Pi does not retry a failed delivery forever on a timer.
258
258
  - **Shutdown:** `await runtime.dispose()` handles background shutdown and extension lifecycle when using the runtime API. For a directly owned session, drain Background, abort the main agent, then dispose; synchronous `session.dispose()` alone is not an awaited drain.
259
259
 
260
260
  A deliberately single-turn embedding can suppress completion-triggered turns and cancel leftover work on exit:
@@ -280,7 +280,7 @@ try {
280
280
 
281
281
  For a longer-lived embedding, keep the host alive, subscribe to snapshots and choose bounded waits or release notification delivery according to your model-turn policy. Do not use a panel or repeated reads as the billing or cleanup mechanism.
282
282
 
283
- Automatic completion messages carry a version-2 `TaskCompletionSnapshot` in `details`, with the command, a 40 KiB output tail, diagnostics and explicit truncation flags. This snapshot is self-contained for transcript replay and is not sent to the model; `content` contains separately bounded prose with an 8 KiB output tail. After compaction, one request-local reminder lists still-active background tasks to prevent duplicate work; it is not persisted and does not start a turn. Current terminal history uses version-2 `task-result` records, with no migration of earlier result records. The usage ledger remains independent. See [Background records](session-format.md#background-records).
283
+ Automatic completion messages carry `{ version: 3, task }` in `details`: the bounded terminal snapshot with its input, facts, diagnostics, up to 40 KiB of output and explicit truncation flags. This snapshot is self-contained for transcript replay and is not sent to the model. `content` is separately bounded prose: a log contributes an 8 KiB tail, while a report arrives from its beginning, whole when it fits the 48 KiB budget. After compaction, one request-local reminder lists still-active background tasks to prevent duplicate work; it is not persisted and does not start a turn. Each settlement appends one version-3 `task-record` holding the terminal snapshot and its usage, with no migration of earlier result records. See [Background records](session-format.md#background-records).
284
284
 
285
285
  `backgroundAllowed: false` on `createAgentSession()` is a host capability ceiling, independent of task kind. It prevents enabling background execution through `bindExtensions` or direct runtime activation, including after reload. Requests for `background: true` are rejected before startup; foreground execution remains available. Omitting this option permits host opt-in but does not enable background execution by itself. This capability restriction is not an OS sandbox.
286
286
 
@@ -292,7 +292,7 @@ An executor that ignores abort and settles after its originating runtime/branch
292
292
 
293
293
  `session.getSessionStats()` returns `sessionFile`, `sessionId`, `userMessages`, `assistantMessages`, `toolCalls`, `toolResults`, `totalMessages`, `tokens`, `cost`, and optional `contextUsage`. `tokens` contains `input`, `output`, `cacheRead`, `cacheWrite`, and `total` (the sum of those four categories); `cost` is accumulated reported cost.
294
294
 
295
- Usage totals cover all session entries, including other branches and compacted history: assistant requests, usage-bearing tool results, compaction/branch summaries, and the first valid `task-usage` record per execution ID. Managed foreground results omit duplicate usage. Background records do not increment message/tool counts, and reads, waits, handoff and history restoration do not add billing. Worker retry, failure, cancellation and compaction usage is included when supplied; missing provider usage is not fabricated. Quarantined late settlements are excluded.
295
+ Usage totals cover all session entries, including other branches and compacted history: assistant requests, usage-bearing tool results, compaction/branch summaries, and the first valid task usage settlement per execution ID, from a `task-record` or a released session's `task-usage` entry. Managed foreground results omit duplicate usage. Background records do not increment message/tool counts, and reads, waits, handoff and history restoration do not add billing. Worker retry, failure, cancellation and compaction usage is included when supplied; missing provider usage is not fabricated. Quarantined late settlements are excluded.
296
296
 
297
297
  This differs from the bundled Statusline's active-branch totals. Neither accumulated worker usage nor Background billing changes the parent context-occupancy estimate or the latest parent request's cache-hit ratio.
298
298
 
@@ -336,48 +336,52 @@ Use `customType` to identify your extension's entries on reload. Interactive mod
336
336
 
337
337
  ### Background records
338
338
 
339
- Managed execution uses ordinary version-3 custom entries; it does not add a new session-file version or persist live execution handles. Every managed execution — including a foreground one — appends its own bounded terminal snapshot. A foreground snapshot omits `result`: its tool result already holds the output, and restoration reads it from the tool result with the same `toolCallId` on the branch.
339
+ Managed execution uses ordinary version-3 custom entries; it does not add a new session-file version or persist live execution handles. Every managed execution — including a foreground one — appends exactly one record when it settles, holding its bounded terminal snapshot and the usage settled for it. A foreground snapshot omits `result`: its tool result already holds the output, and restoration reads it from the tool result with the same `toolCallId` on the branch.
340
340
 
341
341
  | `customType` | `data` | Purpose |
342
342
  |---|---|---|
343
- | `task-usage` | `{ version: 1, taskId, usage }` | Independent settlement of provider-reported nested usage |
344
- | `task-result` | `{ version: 2, task }` | Bounded terminal `TaskSnapshot` |
343
+ | `task-record` | `{ version: 3, task, usage? }` | Bounded terminal `TaskSnapshot` and its settlement of provider-reported nested usage |
345
344
 
346
- `taskId` is the execution/group ID, not a worker display number. `usage` has the `Usage` shape above. Consumers count only the first valid usage record per ID within the entries they aggregate; malformed records, unsupported versions, blank IDs, and non-finite or negative usage/cost values are ignored. A later valid duplicate is not an adjustment. Do not create these host-owned entries yourself or bill again from a result/read/notification.
345
+ `task.id` is the execution ID, not a worker display number. `usage` has the `Usage` shape above and is absent when the executor reported none. Consumers count only the first valid usage settlement per ID within the entries they aggregate; malformed records, unsupported versions, blank IDs, and non-finite or negative usage/cost values are ignored. A later valid duplicate is not an adjustment. Do not create these host-owned entries yourself or bill again from a result/read/notification.
347
346
 
348
- A `TaskSnapshot` has `id`, `kind` (executor-owned source label, such as `bash`, `powershell`, or an extension-defined label), `title`, `toolCallId`, `anchorId`, `mode`, `status`, and numeric millisecond `startedAt`; optional fields include `endedAt`, `command`, `commandTruncated`, `cwd`, `info`, `exitCode`, `outputPath`, `result`, `resultTruncated`, and `error`. `info` is bounded executor-owned Details text with the same `{ text, truncated }` shape used elsewhere; it is display data, not model context. Truncation flags record clipping at the producing/retention boundary. Mode (`foreground` or `background`) is independent of status. Persisted terminal statuses are `completed`, `partial`, `failed`, `cancelled`, or `timeout`; live snapshots can also be `queued`, `running`, or `stopping`.
347
+ A `TaskSnapshot` has `id`, `kind` (executor-owned source label, such as `bash`, `powershell`, or an extension-defined label), `label` (human source name, such as `Bash` or `Agent`), `title`, `output` (`log` or `report`), `toolCallId`, `anchorId`, `mode`, `status`, and numeric millisecond `startedAt`; optional fields include `endedAt`, `input`, `facts`, `display`, `outputPath`, `result`, and `error`. `input` is `{ label, text, truncated, language? }`, what the task was asked to do; `facts` are up to 16 `[label, value]` Details rows, such as `["Exit", "1"]`. `result` is the bounded model-readable text and `display` is bounded human-only Output suffix text; both use `{ text, truncated }`. Only the result, error and facts reach model context. Truncation flags record clipping at the producing/retention boundary. Mode (`foreground` or `background`) is independent of status. Persisted terminal statuses are `completed`, `partial`, `failed`, `cancelled`, or `timeout`; live snapshots can also be `queued`, `running`, or `stopping`.
349
348
 
350
- The retained tool result contains bounded text (up to 48 KiB) and no executor-private details; images are replaced with a text omission marker. Source truncation is explicit; the reader never recognizes truncation by matching output text. `outputPath`, if present, points to an ephemeral executor-owned file which may already have been removed on eviction or runtime shutdown; restored records drop it. Save important output separately.
349
+ The retained result text is bounded (up to 48 KiB) and carries no executor-private details; images are replaced with a text omission marker. Source truncation is explicit; the reader never recognizes truncation by matching output text. `outputPath`, if present, points to an ephemeral executor-owned file which may already have been removed on eviction or runtime shutdown; restored records drop it. Save important output separately.
351
350
 
352
- Terminal history is restored only from the selected branch's valid version-2 result records; older fields such as `format` and `projection` are ignored. Version-1 result records are ignored without migration; their independent usage entries still participate in accounting. This is read-only history: no processes or workers are restarted or reattached, and restoration does not replay usage settlement or completion events. Forks can carry historical entries on their copied path, never live execution handles.
351
+ Terminal history is restored only from the selected branch's valid version-3 records. Released sessions also contain `task-result` records (versions 1 and 2) and separate version-1 `task-usage` entries, `{ version: 1, taskId, usage }`. Those results are ignored without migration, while their usage entries still count toward session totals. This is read-only history: no processes or workers are restarted or reattached, and restoration does not replay usage settlement or completion events. Forks can carry historical entries on their copied path, never live execution handles.
353
352
 
354
- These `custom` entries do not enter model context. Automatic delivery creates a `custom_message` with `customType: "task-completion"`, `display: true`, and a self-contained `TaskCompletionSnapshot` in `details`. The session formats `content` from the same snapshot, with a total limit of 48 KiB and 2,000 lines, keeping only an 8 KiB output tail for the automatic model turn. Only `content` is sent to the model.
353
+ These `custom` entries do not enter model context. Automatic terminal delivery creates a `custom_message` with `customType: "task-completion"`, `display: true`, and `{ version: 3, task }` in `details`. The session formats `content` from the same snapshot, with a total limit of 48 KiB and 2,000 lines. A `log` task contributes only an 8 KiB output tail to the automatic model turn; a `report` task contributes its beginning, whole when it fits. Only `content` is sent to the model.
355
354
 
356
- Completion details use one format, `version: 2`, bounded to 120 KiB of serialized JSON including escaping. It has `version`, `kind`, `taskId`, `title`, terminal `status`, numeric millisecond `startedAt` and `endedAt`, and `output: { text, truncated }`, plus optional `error`, `command: { text, truncated }`, `cwd`, `outputPath`, and `exitCode` (a number, or `null` when signal-reaped).
357
-
358
- `output` is the end of the final result text, bounded to 40 KiB including JSON escaping for replay and expanded rendering; the smaller model-facing projection does not change this stored field. Source flags survive further clipping. Missing shell metadata is left unspecified. The renderer sanitizes terminal control sequences and applies separate display row limits.
355
+ Completion details are bounded to 120 KiB of serialized JSON including escaping. `task` is the terminal snapshot without `display`. Its `input` is clipped to 8 KiB, and its `result` keeps the end of a log or the beginning of a report, up to 40 KiB for replay and expanded rendering. The smaller model-facing projection does not change these stored fields. Source flags survive further clipping. The renderer sanitizes terminal control sequences and applies separate display row limits.
359
356
 
360
357
  A shell completion's `details` can look like this:
361
358
 
362
359
  ```json
363
360
  {
364
- "version": 2,
365
- "taskId": "bash-12345678-abcd-4321-abcd-123456789012",
366
- "kind": "bash",
367
- "title": "npm run build",
368
- "status": "completed",
369
- "startedAt": 1733234400000,
370
- "endedAt": 1733234405000,
371
- "command": { "text": "npm run build", "truncated": false },
372
- "cwd": "/project",
373
- "outputPath": "/tmp/pi-bash-example.log",
374
- "output": { "text": "Build finished", "truncated": false }
361
+ "version": 3,
362
+ "task": {
363
+ "id": "bash-12345678-abcd-4321-abcd-123456789012",
364
+ "kind": "bash",
365
+ "label": "Bash",
366
+ "title": "npm run build",
367
+ "output": "log",
368
+ "input": { "label": "Command", "text": "npm run build", "truncated": false, "language": "bash" },
369
+ "facts": [["Directory", "/project"], ["Exit", "0"]],
370
+ "toolCallId": "call_1",
371
+ "anchorId": "a1b2c3d4",
372
+ "mode": "background",
373
+ "status": "completed",
374
+ "startedAt": 1733234400000,
375
+ "endedAt": 1733234405000,
376
+ "outputPath": "/tmp/pi-bash-example.log",
377
+ "result": { "text": "Build finished", "truncated": false }
378
+ }
375
379
  }
376
380
  ```
377
381
 
378
- The message carries everything needed for replay after `/reload`, branch navigation, history eviction or restart; rendering does not open the saved log or query a live task. Unsupported or malformed completion details, including version 1, use bounded plain message text. There is no legacy text parser, dual-format reconstruction or migration.
382
+ The message carries everything needed for replay after `/reload`, branch navigation, history eviction or restart; rendering does not open the saved log or query a live task. Unsupported or malformed completion details, including versions 1 and 2, use bounded plain message text. There is no legacy text parser, dual-format reconstruction or migration.
379
383
 
380
- A completion is acknowledged only after its message is persisted. A terminal `tasks wait` binds a host-owned receipt to the tool-call ID. Only persisting that tool result acknowledges delivery, even if its details were rewritten; aborting during an output read cannot consume a notification. Direct `TasksContext.wait()` is observational. Snapshots and repeated reads do not create more usage. Historical extension-owned `background-task` notifications and old `bg create` tool results remain transcript history shown as saved text, not new runnable tasks.
384
+ A completion is acknowledged only after its message is persisted. A terminal `tasks wait` binds a host-owned receipt to the tool-call ID. Only persisting that tool result acknowledges delivery, even if its details were rewritten; aborting during an output read cannot consume a notification. Direct `TasksContext.wait()` and `waitAny()` are observational unless given a `toolCallId` in a session host. Snapshots and repeated reads do not create more usage. Historical extension-owned `background-task` notifications and old `bg create` tool results remain transcript history shown as saved text, not new runnable tasks.
381
385
 
382
386
  Session-wide statistics aggregate the ledger across all entries; the bundled Statusline uses the active branch. Accrued retries, failures, cancellations and worker compaction count when usage is reported. No usage is invented for a provider that does not expose it, and worker billing does not occupy the parent's context window. See [SDK session statistics](sdk.md#session-statistics).
383
387
 
package/docs/settings.md CHANGED
@@ -346,12 +346,23 @@ Paths in `~/.pi/agent/settings.json` resolve relative to `~/.pi/agent`. Paths in
346
346
  | `packages` | array | `[]` | npm/git packages to load resources from |
347
347
  | `extensions` | string[] | `[]` | Local extension file paths or directories |
348
348
  | `skills` | string[] | `[]` | Local skill file paths or directories |
349
+ | `skillInvocationOverrides` | object | `{}` | Per-skill invocation policy: `"model-and-user"` or `"user-only"` |
349
350
  | `prompts` | string[] | `[]` | Local prompt template paths or directories |
350
351
  | `themes` | string[] | `[]` | Local theme file paths or directories |
351
352
  | `enableSkillCommands` | boolean | `true` | Register skills as `/skill:name` commands |
352
353
 
353
354
  Arrays support glob patterns and exclusions. Use `!pattern` to exclude. Use `+path` to force-include an exact path and `-path` to force-exclude an exact path.
354
355
 
356
+ `skillInvocationOverrides` uses exact skill file or directory paths as keys. It changes model visibility without changing whether the skill loads; user-only skills remain available as `/skill:name`. Project values override global values. With no override, the skill's `disable-model-invocation` frontmatter applies.
357
+
358
+ ```json
359
+ {
360
+ "skillInvocationOverrides": {
361
+ "skills/pdf/SKILL.md": "user-only"
362
+ }
363
+ }
364
+ ```
365
+
355
366
  #### packages
356
367
 
357
368
  String form loads all resources from a package: