@astralyn/pi 1.4.4 → 1.4.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (230) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/README.md +1 -0
  3. package/dist/bundle/chunks/chunk-5M3YJ54Z.js +82 -0
  4. package/dist/bundle/chunks/chunk-6QGV3IWD.js +6 -0
  5. package/dist/bundle/chunks/chunk-ALHAFUHP.js +7 -0
  6. package/dist/bundle/chunks/chunk-AXFWZIHH.js +4 -0
  7. package/dist/bundle/chunks/chunk-EYKC6ESU.js +2 -0
  8. package/dist/bundle/chunks/chunk-KDO6L76C.js +230 -0
  9. package/dist/bundle/chunks/chunk-RBTJBQWX.js +1500 -0
  10. package/dist/bundle/chunks/chunk-RLNMABLM.js +9 -0
  11. package/dist/bundle/chunks/cli-FH77R7JR.js +51 -0
  12. package/dist/bundle/chunks/execute-5ZQUS52M.js +505 -0
  13. package/dist/bundle/chunks/runtime-R5CMHJ5P.js +2 -0
  14. package/dist/bundle/chunks/virtual-modules-KCQU7LOC.js +2 -0
  15. package/dist/bundle/cli.js +1 -1
  16. package/dist/bundle/index.js +1 -1
  17. package/dist/bundle/rpc-entry.js +1 -1
  18. package/dist/core/agent-session.d.ts.map +1 -1
  19. package/dist/core/agent-session.js +2 -0
  20. package/dist/core/agent-session.js.map +1 -1
  21. package/dist/core/extensions/index.d.ts +1 -1
  22. package/dist/core/extensions/index.d.ts.map +1 -1
  23. package/dist/core/extensions/index.js.map +1 -1
  24. package/dist/core/extensions/runner.d.ts +2 -0
  25. package/dist/core/extensions/runner.d.ts.map +1 -1
  26. package/dist/core/extensions/runner.js +18 -0
  27. package/dist/core/extensions/runner.js.map +1 -1
  28. package/dist/core/extensions/types.d.ts +6 -0
  29. package/dist/core/extensions/types.d.ts.map +1 -1
  30. package/dist/core/extensions/types.js.map +1 -1
  31. package/dist/core/isolated-session.d.ts +23 -0
  32. package/dist/core/isolated-session.d.ts.map +1 -0
  33. package/dist/core/isolated-session.js +55 -0
  34. package/dist/core/isolated-session.js.map +1 -0
  35. package/dist/core/model-config.d.ts +1 -3
  36. package/dist/core/model-config.d.ts.map +1 -1
  37. package/dist/core/model-config.js +1 -3
  38. package/dist/core/model-config.js.map +1 -1
  39. package/dist/core/settings-manager.d.ts +4 -0
  40. package/dist/core/settings-manager.d.ts.map +1 -1
  41. package/dist/core/settings-manager.js +38 -0
  42. package/dist/core/settings-manager.js.map +1 -1
  43. package/dist/core/settings-schema.d.ts +1 -0
  44. package/dist/core/settings-schema.d.ts.map +1 -1
  45. package/dist/core/settings-schema.js +3 -0
  46. package/dist/core/settings-schema.js.map +1 -1
  47. package/dist/core/tasks/codec.d.ts +12 -0
  48. package/dist/core/tasks/codec.d.ts.map +1 -0
  49. package/dist/core/tasks/codec.js +139 -0
  50. package/dist/core/tasks/codec.js.map +1 -0
  51. package/dist/core/tasks/execution.d.ts +64 -0
  52. package/dist/core/tasks/execution.d.ts.map +1 -0
  53. package/dist/core/tasks/execution.js +272 -0
  54. package/dist/core/tasks/execution.js.map +1 -0
  55. package/dist/core/tasks/output.d.ts +12 -5
  56. package/dist/core/tasks/output.d.ts.map +1 -1
  57. package/dist/core/tasks/output.js +38 -37
  58. package/dist/core/tasks/output.js.map +1 -1
  59. package/dist/core/tasks/presentation.d.ts +14 -5
  60. package/dist/core/tasks/presentation.d.ts.map +1 -1
  61. package/dist/core/tasks/presentation.js +56 -185
  62. package/dist/core/tasks/presentation.js.map +1 -1
  63. package/dist/core/tasks/runtime.d.ts +9 -9
  64. package/dist/core/tasks/runtime.d.ts.map +1 -1
  65. package/dist/core/tasks/runtime.js +63 -252
  66. package/dist/core/tasks/runtime.js.map +1 -1
  67. package/dist/core/tasks/scheduler.d.ts +16 -0
  68. package/dist/core/tasks/scheduler.d.ts.map +1 -0
  69. package/dist/core/tasks/scheduler.js +42 -0
  70. package/dist/core/tasks/scheduler.js.map +1 -0
  71. package/dist/core/tasks/session.d.ts +1 -0
  72. package/dist/core/tasks/session.d.ts.map +1 -1
  73. package/dist/core/tasks/session.js +15 -27
  74. package/dist/core/tasks/session.js.map +1 -1
  75. package/dist/core/tasks/store.js +4 -4
  76. package/dist/core/tasks/store.js.map +1 -1
  77. package/dist/core/tasks/types.d.ts +63 -49
  78. package/dist/core/tasks/types.d.ts.map +1 -1
  79. package/dist/core/tasks/types.js +3 -9
  80. package/dist/core/tasks/types.js.map +1 -1
  81. package/dist/core/tools/render-utils.d.ts +6 -4
  82. package/dist/core/tools/render-utils.d.ts.map +1 -1
  83. package/dist/core/tools/render-utils.js +34 -14
  84. package/dist/core/tools/render-utils.js.map +1 -1
  85. package/dist/core/tools/shell-execution.js +4 -4
  86. package/dist/core/tools/shell-execution.js.map +1 -1
  87. package/dist/core/tools/shell-tool.d.ts.map +1 -1
  88. package/dist/core/tools/shell-tool.js +23 -30
  89. package/dist/core/tools/shell-tool.js.map +1 -1
  90. package/dist/core/usage-totals.d.ts +1 -3
  91. package/dist/core/usage-totals.d.ts.map +1 -1
  92. package/dist/core/usage-totals.js +17 -8
  93. package/dist/core/usage-totals.js.map +1 -1
  94. package/dist/extensions/agent/activity.d.ts +13 -0
  95. package/dist/extensions/agent/activity.d.ts.map +1 -0
  96. package/dist/extensions/agent/activity.js +75 -0
  97. package/dist/extensions/agent/activity.js.map +1 -0
  98. package/dist/extensions/agent/index.d.ts +4 -0
  99. package/dist/extensions/agent/index.d.ts.map +1 -0
  100. package/dist/extensions/agent/index.js +11 -0
  101. package/dist/extensions/agent/index.js.map +1 -0
  102. package/dist/extensions/agent/progress.d.ts +31 -0
  103. package/dist/extensions/agent/progress.d.ts.map +1 -0
  104. package/dist/extensions/agent/progress.js +145 -0
  105. package/dist/extensions/agent/progress.js.map +1 -0
  106. package/dist/extensions/agent/render.d.ts +6 -0
  107. package/dist/extensions/agent/render.d.ts.map +1 -0
  108. package/dist/extensions/agent/render.js +120 -0
  109. package/dist/extensions/agent/render.js.map +1 -0
  110. package/dist/extensions/agent/report.d.ts +9 -0
  111. package/dist/extensions/agent/report.d.ts.map +1 -0
  112. package/dist/extensions/agent/report.js +40 -0
  113. package/dist/extensions/agent/report.js.map +1 -0
  114. package/dist/extensions/agent/settings-panel.d.ts +43 -0
  115. package/dist/extensions/agent/settings-panel.d.ts.map +1 -0
  116. package/dist/extensions/agent/settings-panel.js +125 -0
  117. package/dist/extensions/agent/settings-panel.js.map +1 -0
  118. package/dist/extensions/agent/settings.d.ts +15 -0
  119. package/dist/extensions/agent/settings.d.ts.map +1 -0
  120. package/dist/extensions/agent/settings.js +201 -0
  121. package/dist/extensions/agent/settings.js.map +1 -0
  122. package/dist/extensions/agent/tool.d.ts +13 -0
  123. package/dist/extensions/agent/tool.d.ts.map +1 -0
  124. package/dist/extensions/agent/tool.js +84 -0
  125. package/dist/extensions/agent/tool.js.map +1 -0
  126. package/dist/extensions/agent/types.d.ts +43 -0
  127. package/dist/extensions/agent/types.d.ts.map +1 -0
  128. package/dist/extensions/agent/types.js +6 -0
  129. package/dist/extensions/agent/types.js.map +1 -0
  130. package/dist/extensions/agent/worker.d.ts +16 -0
  131. package/dist/extensions/agent/worker.d.ts.map +1 -0
  132. package/dist/extensions/agent/worker.js +68 -0
  133. package/dist/extensions/agent/worker.js.map +1 -0
  134. package/dist/extensions/codemode/execute.js +1 -1
  135. package/dist/extensions/codemode/execute.js.map +1 -1
  136. package/dist/extensions/codemode/execute.lazy.d.ts +2 -2
  137. package/dist/extensions/codemode/execute.lazy.d.ts.map +1 -1
  138. package/dist/extensions/codemode/execute.lazy.js +2 -2
  139. package/dist/extensions/codemode/execute.lazy.js.map +1 -1
  140. package/dist/extensions/index.d.ts.map +1 -1
  141. package/dist/extensions/index.js +2 -0
  142. package/dist/extensions/index.js.map +1 -1
  143. package/dist/extensions/mcp/cli.lazy.d.ts +2 -2
  144. package/dist/extensions/mcp/cli.lazy.d.ts.map +1 -1
  145. package/dist/extensions/mcp/cli.lazy.js +2 -2
  146. package/dist/extensions/mcp/cli.lazy.js.map +1 -1
  147. package/dist/extensions/mcp/index.d.ts.map +1 -1
  148. package/dist/extensions/mcp/index.js +2 -2
  149. package/dist/extensions/mcp/index.js.map +1 -1
  150. package/dist/extensions/mcp/runtime.lazy.d.ts +2 -2
  151. package/dist/extensions/mcp/runtime.lazy.d.ts.map +1 -1
  152. package/dist/extensions/mcp/runtime.lazy.js +2 -2
  153. package/dist/extensions/mcp/runtime.lazy.js.map +1 -1
  154. package/dist/extensions/provider/compat-fields.js +1 -1
  155. package/dist/extensions/provider/compat-fields.js.map +1 -1
  156. package/dist/extensions/tasks/tool/actions.d.ts.map +1 -1
  157. package/dist/extensions/tasks/tool/actions.js +1 -9
  158. package/dist/extensions/tasks/tool/actions.js.map +1 -1
  159. package/dist/extensions/tasks/tool/schema.js +1 -1
  160. package/dist/extensions/tasks/tool/schema.js.map +1 -1
  161. package/dist/extensions/tasks/tool/types.d.ts +2 -8
  162. package/dist/extensions/tasks/tool/types.d.ts.map +1 -1
  163. package/dist/extensions/tasks/tool/types.js +0 -2
  164. package/dist/extensions/tasks/tool/types.js.map +1 -1
  165. package/dist/extensions/tasks/ui/completion-render.d.ts.map +1 -1
  166. package/dist/extensions/tasks/ui/completion-render.js +27 -26
  167. package/dist/extensions/tasks/ui/completion-render.js.map +1 -1
  168. package/dist/extensions/tasks/ui/inspector.d.ts +5 -3
  169. package/dist/extensions/tasks/ui/inspector.d.ts.map +1 -1
  170. package/dist/extensions/tasks/ui/inspector.js +18 -6
  171. package/dist/extensions/tasks/ui/inspector.js.map +1 -1
  172. package/dist/extensions/tasks/ui/layout.d.ts.map +1 -1
  173. package/dist/extensions/tasks/ui/layout.js +111 -75
  174. package/dist/extensions/tasks/ui/layout.js.map +1 -1
  175. package/dist/extensions/tasks/ui/list.d.ts.map +1 -1
  176. package/dist/extensions/tasks/ui/list.js +43 -28
  177. package/dist/extensions/tasks/ui/list.js.map +1 -1
  178. package/dist/extensions/tasks/ui/manager.d.ts.map +1 -1
  179. package/dist/extensions/tasks/ui/manager.js +8 -2
  180. package/dist/extensions/tasks/ui/manager.js.map +1 -1
  181. package/dist/extensions/tasks/ui/model.d.ts +4 -0
  182. package/dist/extensions/tasks/ui/model.d.ts.map +1 -1
  183. package/dist/extensions/tasks/ui/model.js +12 -1
  184. package/dist/extensions/tasks/ui/model.js.map +1 -1
  185. package/dist/extensions/tasks/ui/render.js +3 -4
  186. package/dist/extensions/tasks/ui/render.js.map +1 -1
  187. package/dist/extensions/tasks/ui/task-view.d.ts +0 -5
  188. package/dist/extensions/tasks/ui/task-view.d.ts.map +1 -1
  189. package/dist/extensions/tasks/ui/task-view.js +0 -7
  190. package/dist/extensions/tasks/ui/task-view.js.map +1 -1
  191. package/dist/extensions/tasks/ui/tree.js +1 -1
  192. package/dist/extensions/tasks/ui/tree.js.map +1 -1
  193. package/dist/extensions/tasks/ui/views.d.ts +10 -6
  194. package/dist/extensions/tasks/ui/views.d.ts.map +1 -1
  195. package/dist/extensions/tasks/ui/views.js +64 -28
  196. package/dist/extensions/tasks/ui/views.js.map +1 -1
  197. package/dist/index.d.ts +2 -1
  198. package/dist/index.d.ts.map +1 -1
  199. package/dist/index.js.map +1 -1
  200. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
  201. package/dist/modes/interactive/components/keybinding-hints.js +2 -1
  202. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
  203. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  204. package/dist/modes/interactive/components/model-selector.js +7 -4
  205. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  206. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  207. package/dist/modes/interactive/components/thinking-selector.js +10 -3
  208. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  209. package/docs/bundled/README.md +1 -0
  210. package/docs/bundled/extensions/agent.md +68 -0
  211. package/docs/bundled/extensions/statusline.md +1 -1
  212. package/docs/bundled/tasks.md +15 -14
  213. package/docs/docs.json +4 -0
  214. package/docs/extensions.md +33 -6
  215. package/docs/sdk.md +2 -2
  216. package/docs/session-format.md +27 -23
  217. package/npm-shrinkwrap.json +2 -2
  218. package/package.json +1 -1
  219. package/schemas/settings.schema.json +12 -0
  220. package/dist/bundle/chunks/chunk-SBVVM3NV.js +0 -2361
  221. package/dist/bundle/chunks/chunk-VGSZTBVJ.js +0 -2
  222. package/dist/bundle/chunks/virtual-modules-ETYFHSUG.js +0 -2
  223. package/dist/core/tasks/history.d.ts +0 -4
  224. package/dist/core/tasks/history.d.ts.map +0 -1
  225. package/dist/core/tasks/history.js +0 -121
  226. package/dist/core/tasks/history.js.map +0 -1
  227. package/dist/extensions/codemode/search.d.ts +0 -33
  228. package/dist/extensions/codemode/search.d.ts.map +0 -1
  229. package/dist/extensions/codemode/search.js +0 -117
  230. package/dist/extensions/codemode/search.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"usage-totals.js","sourceRoot":"","sources":["../../src/core/usage-totals.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Usage } from \"@earendil-works/pi-ai/compat\";\nimport type { SessionEntry } from \"./session-manager.ts\";\n\nexport interface UsageTotals {\n\tinput: number;\n\toutput: number;\n\tcacheRead: number;\n\tcacheWrite: number;\n\tcost: number;\n}\n\nexport function createUsageTotals(): UsageTotals {\n\treturn {\n\t\tinput: 0,\n\t\toutput: 0,\n\t\tcacheRead: 0,\n\t\tcacheWrite: 0,\n\t\tcost: 0,\n\t};\n}\n\nexport function addUsageToTotals(totals: UsageTotals, usage: Usage): void {\n\ttotals.input += usage.input;\n\ttotals.output += usage.output;\n\ttotals.cacheRead += usage.cacheRead;\n\ttotals.cacheWrite += usage.cacheWrite;\n\ttotals.cost += usage.cost.total;\n}\n\n/** Sum of two usages, keeping the optional token splits when either side reports them. */\nexport function combineUsage(first: Usage, second: Usage): Usage {\n\treturn {\n\t\tinput: first.input + second.input,\n\t\toutput: first.output + second.output,\n\t\tcacheRead: first.cacheRead + second.cacheRead,\n\t\tcacheWrite: first.cacheWrite + second.cacheWrite,\n\t\t...(first.cacheWrite1h !== undefined || second.cacheWrite1h !== undefined\n\t\t\t? { cacheWrite1h: (first.cacheWrite1h ?? 0) + (second.cacheWrite1h ?? 0) }\n\t\t\t: {}),\n\t\t...(first.reasoning !== undefined || second.reasoning !== undefined\n\t\t\t? { reasoning: (first.reasoning ?? 0) + (second.reasoning ?? 0) }\n\t\t\t: {}),\n\t\ttotalTokens: first.totalTokens + second.totalTokens,\n\t\tcost: {\n\t\t\tinput: first.cost.input + second.cost.input,\n\t\t\toutput: first.cost.output + second.cost.output,\n\t\t\tcacheRead: first.cost.cacheRead + second.cost.cacheRead,\n\t\t\tcacheWrite: first.cost.cacheWrite + second.cost.cacheWrite,\n\t\t\ttotal: first.cost.total + second.cost.total,\n\t\t},\n\t};\n}\n\nexport interface UsageCostBreakdownEntry {\n\tkey: string;\n\tcost: number;\n\ttokens: number;\n}\n\nexport const TASK_USAGE_TYPE = \"task-usage\";\n\nexport interface TaskUsageRecord {\n\tversion: 1;\n\ttaskId: string;\n\tusage: Usage;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isUsageValue(value: unknown): value is number {\n\treturn typeof value === \"number\" && Number.isFinite(value) && value >= 0;\n}\n\n/** Validate persisted ledger data and return only its serializable accounting fields. */\nexport function getTaskUsageRecord(entry: SessionEntry): TaskUsageRecord | undefined {\n\tif (entry.type !== \"custom\" || entry.customType !== TASK_USAGE_TYPE) return undefined;\n\tconst data = entry.data;\n\tif (!isRecord(data) || data.version !== 1 || typeof data.taskId !== \"string\" || !data.taskId.trim()) {\n\t\treturn undefined;\n\t}\n\tconst usage = data.usage;\n\tif (!isRecord(usage) || !isRecord(usage.cost)) return undefined;\n\tconst { input, output, cacheRead, cacheWrite, totalTokens, reasoning, cacheWrite1h } = usage;\n\tconst cost = usage.cost;\n\tif (\n\t\t!isUsageValue(input) ||\n\t\t!isUsageValue(output) ||\n\t\t!isUsageValue(cacheRead) ||\n\t\t!isUsageValue(cacheWrite) ||\n\t\t!isUsageValue(totalTokens) ||\n\t\t!isUsageValue(cost.input) ||\n\t\t!isUsageValue(cost.output) ||\n\t\t!isUsageValue(cost.cacheRead) ||\n\t\t!isUsageValue(cost.cacheWrite) ||\n\t\t!isUsageValue(cost.total) ||\n\t\t(reasoning !== undefined && !isUsageValue(reasoning)) ||\n\t\t(cacheWrite1h !== undefined && !isUsageValue(cacheWrite1h))\n\t)\n\t\treturn undefined;\n\treturn {\n\t\tversion: 1,\n\t\ttaskId: data.taskId,\n\t\tusage: {\n\t\t\tinput,\n\t\t\toutput,\n\t\t\tcacheRead,\n\t\t\tcacheWrite,\n\t\t\ttotalTokens,\n\t\t\t...(reasoning === undefined ? {} : { reasoning }),\n\t\t\t...(cacheWrite1h === undefined ? {} : { cacheWrite1h }),\n\t\t\tcost: {\n\t\t\t\tinput: cost.input,\n\t\t\t\toutput: cost.output,\n\t\t\t\tcacheRead: cost.cacheRead,\n\t\t\t\tcacheWrite: cost.cacheWrite,\n\t\t\t\ttotal: cost.total,\n\t\t\t},\n\t\t},\n\t};\n}\n\nfunction* accountedUsageEntries(entries: readonly SessionEntry[]): Generator<{ key: string; usage: Usage }> {\n\tconst backgroundTasks = new Set<string>();\n\tfor (const entry of entries) {\n\t\tif (entry.type === \"message\" && entry.message.role === \"assistant\") {\n\t\t\tyield {\n\t\t\t\tkey: `${entry.message.provider}/${entry.message.responseModel ?? entry.message.model}`,\n\t\t\t\tusage: entry.message.usage,\n\t\t\t};\n\t\t} else if (entry.type === \"usage\") {\n\t\t\tyield { key: `${entry.provider}/${entry.model}`, usage: entry.usage };\n\t\t} else if (entry.type === \"message\" && entry.message.role === \"toolResult\" && entry.message.usage) {\n\t\t\tyield { key: \"Tools/summaries\", usage: entry.message.usage };\n\t\t} else if ((entry.type === \"branch_summary\" || entry.type === \"compaction\") && entry.usage) {\n\t\t\tyield { key: \"Tools/summaries\", usage: entry.usage };\n\t\t} else {\n\t\t\tconst record = getTaskUsageRecord(entry);\n\t\t\tif (!record || backgroundTasks.has(record.taskId)) continue;\n\t\t\tbackgroundTasks.add(record.taskId);\n\t\t\tyield { key: \"Tools/summaries\", usage: record.usage };\n\t\t}\n\t}\n}\n\n/** Legacy usage plus the first valid ledger record per task. Managed results omit usage. */\nexport function getAccountedUsages(entries: readonly SessionEntry[]): Usage[] {\n\treturn Array.from(accountedUsageEntries(entries), ({ usage }) => usage);\n}\n\n/** Group model-attributed usage by model and all other usage into a separate bucket. */\nexport function getUsageCostBreakdown(entries: readonly SessionEntry[]): UsageCostBreakdownEntry[] {\n\tconst totalsByKey = new Map<string, UsageTotals>();\n\n\tfor (const { key, usage } of accountedUsageEntries(entries)) {\n\t\tlet totals = totalsByKey.get(key);\n\t\tif (!totals) {\n\t\t\ttotals = createUsageTotals();\n\t\t\ttotalsByKey.set(key, totals);\n\t\t}\n\t\taddUsageToTotals(totals, usage);\n\t}\n\n\treturn Array.from(totalsByKey, ([key, totals]) => ({\n\t\tkey,\n\t\tcost: totals.cost,\n\t\ttokens: totals.input + totals.output + totals.cacheRead + totals.cacheWrite,\n\t}))\n\t\t.filter((entry) => entry.cost > 0 || entry.tokens > 0)\n\t\t.sort((a, b) => b.cost - a.cost);\n}\n"]}
1
+ {"version":3,"file":"usage-totals.js","sourceRoot":"","sources":["../../src/core/usage-totals.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Usage } from \"@earendil-works/pi-ai/compat\";\nimport type { SessionEntry } from \"./session-manager.ts\";\nimport { TASK_RECORD_TYPE, TASK_SNAPSHOT_VERSION } from \"./tasks/codec.ts\";\n\nexport interface UsageTotals {\n\tinput: number;\n\toutput: number;\n\tcacheRead: number;\n\tcacheWrite: number;\n\tcost: number;\n}\n\nexport function createUsageTotals(): UsageTotals {\n\treturn {\n\t\tinput: 0,\n\t\toutput: 0,\n\t\tcacheRead: 0,\n\t\tcacheWrite: 0,\n\t\tcost: 0,\n\t};\n}\n\nexport function addUsageToTotals(totals: UsageTotals, usage: Usage): void {\n\ttotals.input += usage.input;\n\ttotals.output += usage.output;\n\ttotals.cacheRead += usage.cacheRead;\n\ttotals.cacheWrite += usage.cacheWrite;\n\ttotals.cost += usage.cost.total;\n}\n\n/** Sum of two usages, keeping the optional token splits when either side reports them. */\nexport function combineUsage(first: Usage, second: Usage): Usage {\n\treturn {\n\t\tinput: first.input + second.input,\n\t\toutput: first.output + second.output,\n\t\tcacheRead: first.cacheRead + second.cacheRead,\n\t\tcacheWrite: first.cacheWrite + second.cacheWrite,\n\t\t...(first.cacheWrite1h !== undefined || second.cacheWrite1h !== undefined\n\t\t\t? { cacheWrite1h: (first.cacheWrite1h ?? 0) + (second.cacheWrite1h ?? 0) }\n\t\t\t: {}),\n\t\t...(first.reasoning !== undefined || second.reasoning !== undefined\n\t\t\t? { reasoning: (first.reasoning ?? 0) + (second.reasoning ?? 0) }\n\t\t\t: {}),\n\t\ttotalTokens: first.totalTokens + second.totalTokens,\n\t\tcost: {\n\t\t\tinput: first.cost.input + second.cost.input,\n\t\t\toutput: first.cost.output + second.cost.output,\n\t\t\tcacheRead: first.cost.cacheRead + second.cost.cacheRead,\n\t\t\tcacheWrite: first.cost.cacheWrite + second.cost.cacheWrite,\n\t\t\ttotal: first.cost.total + second.cost.total,\n\t\t},\n\t};\n}\n\nexport interface UsageCostBreakdownEntry {\n\tkey: string;\n\tcost: number;\n\ttokens: number;\n}\n\nexport interface TaskUsageRecord {\n\ttaskId: string;\n\tusage: Usage;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isUsageValue(value: unknown): value is number {\n\treturn typeof value === \"number\" && Number.isFinite(value) && value >= 0;\n}\n\n/** Released sessions settled usage in separate entries; their billing still counts. */\nconst LEGACY_TASK_USAGE_TYPE = \"task-usage\";\n\nfunction settledTaskId(entry: SessionEntry): unknown {\n\tif (entry.type !== \"custom\" || !isRecord(entry.data)) return undefined;\n\tconst data = entry.data;\n\tif (entry.customType === TASK_RECORD_TYPE)\n\t\treturn data.version === TASK_SNAPSHOT_VERSION && isRecord(data.task) ? data.task.id : undefined;\n\tif (entry.customType === LEGACY_TASK_USAGE_TYPE) return data.version === 1 ? data.taskId : undefined;\n\treturn undefined;\n}\n\n/** Validate a task record's usage settlement and return only its serializable accounting fields. */\nexport function getTaskUsageRecord(entry: SessionEntry): TaskUsageRecord | undefined {\n\tconst taskId = settledTaskId(entry);\n\tif (typeof taskId !== \"string\" || !taskId.trim() || entry.type !== \"custom\") return undefined;\n\tconst data = entry.data as Record<string, unknown>;\n\tconst usage = data.usage;\n\tif (!isRecord(usage) || !isRecord(usage.cost)) return undefined;\n\tconst { input, output, cacheRead, cacheWrite, totalTokens, reasoning, cacheWrite1h } = usage;\n\tconst cost = usage.cost;\n\tif (\n\t\t!isUsageValue(input) ||\n\t\t!isUsageValue(output) ||\n\t\t!isUsageValue(cacheRead) ||\n\t\t!isUsageValue(cacheWrite) ||\n\t\t!isUsageValue(totalTokens) ||\n\t\t!isUsageValue(cost.input) ||\n\t\t!isUsageValue(cost.output) ||\n\t\t!isUsageValue(cost.cacheRead) ||\n\t\t!isUsageValue(cost.cacheWrite) ||\n\t\t!isUsageValue(cost.total) ||\n\t\t(reasoning !== undefined && !isUsageValue(reasoning)) ||\n\t\t(cacheWrite1h !== undefined && !isUsageValue(cacheWrite1h))\n\t)\n\t\treturn undefined;\n\treturn {\n\t\ttaskId,\n\t\tusage: {\n\t\t\tinput,\n\t\t\toutput,\n\t\t\tcacheRead,\n\t\t\tcacheWrite,\n\t\t\ttotalTokens,\n\t\t\t...(reasoning === undefined ? {} : { reasoning }),\n\t\t\t...(cacheWrite1h === undefined ? {} : { cacheWrite1h }),\n\t\t\tcost: {\n\t\t\t\tinput: cost.input,\n\t\t\t\toutput: cost.output,\n\t\t\t\tcacheRead: cost.cacheRead,\n\t\t\t\tcacheWrite: cost.cacheWrite,\n\t\t\t\ttotal: cost.total,\n\t\t\t},\n\t\t},\n\t};\n}\n\nfunction* accountedUsageEntries(entries: readonly SessionEntry[]): Generator<{ key: string; usage: Usage }> {\n\tconst backgroundTasks = new Set<string>();\n\tfor (const entry of entries) {\n\t\tif (entry.type === \"message\" && entry.message.role === \"assistant\") {\n\t\t\tyield {\n\t\t\t\tkey: `${entry.message.provider}/${entry.message.responseModel ?? entry.message.model}`,\n\t\t\t\tusage: entry.message.usage,\n\t\t\t};\n\t\t} else if (entry.type === \"usage\") {\n\t\t\tyield { key: `${entry.provider}/${entry.model}`, usage: entry.usage };\n\t\t} else if (entry.type === \"message\" && entry.message.role === \"toolResult\" && entry.message.usage) {\n\t\t\tyield { key: \"Tools/summaries\", usage: entry.message.usage };\n\t\t} else if ((entry.type === \"branch_summary\" || entry.type === \"compaction\") && entry.usage) {\n\t\t\tyield { key: \"Tools/summaries\", usage: entry.usage };\n\t\t} else {\n\t\t\tconst record = getTaskUsageRecord(entry);\n\t\t\tif (!record || backgroundTasks.has(record.taskId)) continue;\n\t\t\tbackgroundTasks.add(record.taskId);\n\t\t\tyield { key: \"Tools/summaries\", usage: record.usage };\n\t\t}\n\t}\n}\n\n/** Legacy usage plus the first valid ledger record per task. Managed results omit usage. */\nexport function getAccountedUsages(entries: readonly SessionEntry[]): Usage[] {\n\treturn Array.from(accountedUsageEntries(entries), ({ usage }) => usage);\n}\n\n/** Group model-attributed usage by model and all other usage into a separate bucket. */\nexport function getUsageCostBreakdown(entries: readonly SessionEntry[]): UsageCostBreakdownEntry[] {\n\tconst totalsByKey = new Map<string, UsageTotals>();\n\n\tfor (const { key, usage } of accountedUsageEntries(entries)) {\n\t\tlet totals = totalsByKey.get(key);\n\t\tif (!totals) {\n\t\t\ttotals = createUsageTotals();\n\t\t\ttotalsByKey.set(key, totals);\n\t\t}\n\t\taddUsageToTotals(totals, usage);\n\t}\n\n\treturn Array.from(totalsByKey, ([key, totals]) => ({\n\t\tkey,\n\t\tcost: totals.cost,\n\t\ttokens: totals.input + totals.output + totals.cacheRead + totals.cacheWrite,\n\t}))\n\t\t.filter((entry) => entry.cost > 0 || entry.tokens > 0)\n\t\t.sort((a, b) => b.cost - a.cost);\n}\n"]}
@@ -0,0 +1,13 @@
1
+ import type { AgentActivity } from "./types.ts";
2
+ export declare function clipText(text: string, bytes: number): string;
3
+ export declare function compactArguments(args: unknown): string;
4
+ /** A short display target; full arguments remain available in Tasks Output. */
5
+ export declare function activityTarget(name: string, args: unknown): string;
6
+ /** The stored display target, or one derived from the bounded arguments. */
7
+ export declare function targetOf(activity: AgentActivity): string;
8
+ export declare function formatActivityDuration(ms: number | undefined): string;
9
+ export declare function activityGlyph(status: AgentActivity["status"]): string;
10
+ /** The Transcript's `glyph tool target · duration` form, plus an indented failure excerpt. */
11
+ export declare function activityText(activity: AgentActivity, includeError?: boolean): string;
12
+ export declare function activitiesText(activities: readonly AgentActivity[]): string;
13
+ //# sourceMappingURL=activity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"activity.d.ts","sourceRoot":"","sources":["../../../src/extensions/agent/activity.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAG5D;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAMtD;AAED,+EAA+E;AAC/E,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,MAAM,CAgBlE;AAED,4EAA4E;AAC5E,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,aAAa,GAAG,MAAM,CAOxD;AAED,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAGrE;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,aAAa,CAAC,QAAQ,CAAC,GAAG,MAAM,CAWrE;AAED,8FAA8F;AAC9F,wBAAgB,YAAY,CAAC,QAAQ,EAAE,aAAa,EAAE,YAAY,UAAO,GAAG,MAAM,CAOjF;AAED,wBAAgB,cAAc,CAAC,UAAU,EAAE,SAAS,aAAa,EAAE,GAAG,MAAM,CAE3E"}
@@ -0,0 +1,75 @@
1
+ /** Compact, bounded formatting of an Agent's tool-call activity, shared by the Transcript and /tasks. */
2
+ import { boundText } from "../../core/tasks/output.js";
3
+ export function clipText(text, bytes) {
4
+ if (Buffer.byteLength(text) <= bytes)
5
+ return text;
6
+ return `${boundText(text, Math.max(1, bytes - 1))}…`;
7
+ }
8
+ export function compactArguments(args) {
9
+ try {
10
+ return clipText(JSON.stringify(args) ?? String(args), 512).replace(/\s+/gu, " ");
11
+ }
12
+ catch {
13
+ return "{…}";
14
+ }
15
+ }
16
+ /** A short display target; full arguments remain available in Tasks Output. */
17
+ export function activityTarget(name, args) {
18
+ if (!args || typeof args !== "object" || Array.isArray(args))
19
+ return compactArguments(args);
20
+ const record = args;
21
+ const keys = name === "bash" || name === "powershell"
22
+ ? ["command"]
23
+ : name === "grep" || name === "find"
24
+ ? ["pattern", "path"]
25
+ : ["path", "pattern", "command"];
26
+ for (const key of keys) {
27
+ const value = record[key];
28
+ if (typeof value !== "string" || !value.trim())
29
+ continue;
30
+ const first = key === "command" ? value.split(/\r?\n/).find((line) => line.trim()) : value;
31
+ return clipText((first ?? value).trim().replace(/[ \t]+/gu, " "), 160);
32
+ }
33
+ return compactArguments(args);
34
+ }
35
+ /** The stored display target, or one derived from the bounded arguments. */
36
+ export function targetOf(activity) {
37
+ if (activity.target)
38
+ return activity.target;
39
+ try {
40
+ return activityTarget(activity.name, JSON.parse(activity.args));
41
+ }
42
+ catch {
43
+ return activity.args;
44
+ }
45
+ }
46
+ export function formatActivityDuration(ms) {
47
+ if (ms === undefined)
48
+ return "";
49
+ return ms < 1000 ? `${Math.round(ms)}ms` : `${(ms / 1000).toFixed(1)}s`;
50
+ }
51
+ export function activityGlyph(status) {
52
+ switch (status) {
53
+ case "running":
54
+ return "…";
55
+ case "ok":
56
+ return "✓";
57
+ case "error":
58
+ return "✗";
59
+ case "cancelled":
60
+ return "⊘";
61
+ }
62
+ }
63
+ /** The Transcript's `glyph tool target · duration` form, plus an indented failure excerpt. */
64
+ export function activityText(activity, includeError = true) {
65
+ const target = targetOf(activity);
66
+ const duration = formatActivityDuration(activity.durationMs);
67
+ const line = `${activityGlyph(activity.status)} ${activity.name}${target ? ` ${target}` : ""}${duration ? ` · ${duration}` : ""}`;
68
+ return includeError && activity.error
69
+ ? `${line}\n ${clipText(activity.error, 1000).replaceAll("\n", "\n ")}`
70
+ : line;
71
+ }
72
+ export function activitiesText(activities) {
73
+ return activities.map((activity) => activityText(activity)).join("\n");
74
+ }
75
+ //# sourceMappingURL=activity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"activity.js","sourceRoot":"","sources":["../../../src/extensions/agent/activity.ts"],"names":[],"mappings":"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","sourcesContent":["/** Compact, bounded formatting of an Agent's tool-call activity, shared by the Transcript and /tasks. */\nimport { boundText } from \"../../core/tasks/output.ts\";\nimport type { AgentActivity } from \"./types.ts\";\n\nexport function clipText(text: string, bytes: number): string {\n\tif (Buffer.byteLength(text) <= bytes) return text;\n\treturn `${boundText(text, Math.max(1, bytes - 1))}…`;\n}\n\nexport function compactArguments(args: unknown): string {\n\ttry {\n\t\treturn clipText(JSON.stringify(args) ?? String(args), 512).replace(/\\s+/gu, \" \");\n\t} catch {\n\t\treturn \"{…}\";\n\t}\n}\n\n/** A short display target; full arguments remain available in Tasks Output. */\nexport function activityTarget(name: string, args: unknown): string {\n\tif (!args || typeof args !== \"object\" || Array.isArray(args)) return compactArguments(args);\n\tconst record = args as Record<string, unknown>;\n\tconst keys =\n\t\tname === \"bash\" || name === \"powershell\"\n\t\t\t? [\"command\"]\n\t\t\t: name === \"grep\" || name === \"find\"\n\t\t\t\t? [\"pattern\", \"path\"]\n\t\t\t\t: [\"path\", \"pattern\", \"command\"];\n\tfor (const key of keys) {\n\t\tconst value = record[key];\n\t\tif (typeof value !== \"string\" || !value.trim()) continue;\n\t\tconst first = key === \"command\" ? value.split(/\\r?\\n/).find((line) => line.trim()) : value;\n\t\treturn clipText((first ?? value).trim().replace(/[ \\t]+/gu, \" \"), 160);\n\t}\n\treturn compactArguments(args);\n}\n\n/** The stored display target, or one derived from the bounded arguments. */\nexport function targetOf(activity: AgentActivity): string {\n\tif (activity.target) return activity.target;\n\ttry {\n\t\treturn activityTarget(activity.name, JSON.parse(activity.args));\n\t} catch {\n\t\treturn activity.args;\n\t}\n}\n\nexport function formatActivityDuration(ms: number | undefined): string {\n\tif (ms === undefined) return \"\";\n\treturn ms < 1000 ? `${Math.round(ms)}ms` : `${(ms / 1000).toFixed(1)}s`;\n}\n\nexport function activityGlyph(status: AgentActivity[\"status\"]): string {\n\tswitch (status) {\n\t\tcase \"running\":\n\t\t\treturn \"…\";\n\t\tcase \"ok\":\n\t\t\treturn \"✓\";\n\t\tcase \"error\":\n\t\t\treturn \"✗\";\n\t\tcase \"cancelled\":\n\t\t\treturn \"⊘\";\n\t}\n}\n\n/** The Transcript's `glyph tool target · duration` form, plus an indented failure excerpt. */\nexport function activityText(activity: AgentActivity, includeError = true): string {\n\tconst target = targetOf(activity);\n\tconst duration = formatActivityDuration(activity.durationMs);\n\tconst line = `${activityGlyph(activity.status)} ${activity.name}${target ? ` ${target}` : \"\"}${duration ? ` · ${duration}` : \"\"}`;\n\treturn includeError && activity.error\n\t\t? `${line}\\n ${clipText(activity.error, 1000).replaceAll(\"\\n\", \"\\n \")}`\n\t\t: line;\n}\n\nexport function activitiesText(activities: readonly AgentActivity[]): string {\n\treturn activities.map((activity) => activityText(activity)).join(\"\\n\");\n}\n"]}
@@ -0,0 +1,4 @@
1
+ import type { ExtensionAPI } from "../../core/extensions/types.ts";
2
+ export { createAgentTool } from "./tool.ts";
3
+ export default function agentExtension(pi: ExtensionAPI): void;
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/extensions/agent/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAInE,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAE5C,MAAM,CAAC,OAAO,UAAU,cAAc,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CAM7D"}
@@ -0,0 +1,11 @@
1
+ import { openAgentSettings } from "./settings.js";
2
+ import { createAgentTool } from "./tool.js";
3
+ export { createAgentTool } from "./tool.js";
4
+ export default function agentExtension(pi) {
5
+ pi.registerTool(createAgentTool());
6
+ pi.registerCommand("agent", {
7
+ description: "Choose the model and thinking level for future Agents",
8
+ handler: async (_args, ctx) => openAgentSettings(ctx),
9
+ });
10
+ }
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/extensions/agent/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAE5C,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAE5C,MAAM,CAAC,OAAO,UAAU,cAAc,CAAC,EAAgB;IACtD,EAAE,CAAC,YAAY,CAAC,eAAe,EAAE,CAAC,CAAC;IACnC,EAAE,CAAC,eAAe,CAAC,OAAO,EAAE;QAC3B,WAAW,EAAE,uDAAuD;QACpE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,iBAAiB,CAAC,GAAG,CAAC;KACrD,CAAC,CAAC;AACJ,CAAC","sourcesContent":["import type { ExtensionAPI } from \"../../core/extensions/types.ts\";\nimport { openAgentSettings } from \"./settings.ts\";\nimport { createAgentTool } from \"./tool.ts\";\n\nexport { createAgentTool } from \"./tool.ts\";\n\nexport default function agentExtension(pi: ExtensionAPI): void {\n\tpi.registerTool(createAgentTool());\n\tpi.registerCommand(\"agent\", {\n\t\tdescription: \"Choose the model and thinking level for future Agents\",\n\t\thandler: async (_args, ctx) => openAgentSettings(ctx),\n\t});\n}\n"]}
@@ -0,0 +1,31 @@
1
+ import type { AgentMessage } from "@earendil-works/pi-agent-core";
2
+ import type { AgentSessionEvent } from "../../core/agent-session.ts";
3
+ import type { TaskCompletion, TaskControl, TaskTerminalStatus } from "../../core/tasks/types.ts";
4
+ import { type AgentToolDetails } from "./types.ts";
5
+ export declare function finalAssistantText(messages: readonly AgentMessage[]): string;
6
+ /**
7
+ * One worker session translated into task progress: a one-line status for the model,
8
+ * tool activity for humans, and cumulative usage for the ledger.
9
+ */
10
+ export declare class AgentProgress {
11
+ private readonly control;
12
+ private readonly activities;
13
+ private readonly counted;
14
+ private calls;
15
+ private usage;
16
+ private last?;
17
+ constructor(control: TaskControl<AgentToolDetails>);
18
+ handle(event: AgentSessionEvent): void;
19
+ publish(): void;
20
+ /** Classify a finished run from its last assistant message. */
21
+ outcome(): {
22
+ status: TaskTerminalStatus;
23
+ error?: string;
24
+ };
25
+ complete(status: TaskTerminalStatus, error: string | undefined, report: string): TaskCompletion<AgentToolDetails>;
26
+ /** Model-readable progress: the report is the contract, so intermediate text never leaves the worker. */
27
+ private status;
28
+ /** Human-only Output: compact tool calls, never sent to the model. */
29
+ private display;
30
+ }
31
+ //# sourceMappingURL=progress.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress.d.ts","sourceRoot":"","sources":["../../../src/extensions/agent/progress.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAElE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAGjG,OAAO,EAA4C,KAAK,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAuB7F,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,GAAG,MAAM,CAM5E;AAWD;;;GAGG;AACH,qBAAa,aAAa;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgC;IACxD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAuB;IAClD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA+B;IACvD,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,IAAI,CAAC,CAAmB;gBAEpB,OAAO,EAAE,WAAW,CAAC,gBAAgB,CAAC;IAIlD,MAAM,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI;IAsCtC,OAAO,IAAI,IAAI;IAgBf,+DAA+D;IAC/D,OAAO,IAAI;QAAE,MAAM,EAAE,kBAAkB,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE;IAYzD,QAAQ,CAAC,MAAM,EAAE,kBAAkB,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,cAAc,CAAC,gBAAgB,CAAC;IAcjH,yGAAyG;IACzG,OAAO,CAAC,MAAM;IAOd,sEAAsE;IACtE,OAAO,CAAC,OAAO;CAGf"}
@@ -0,0 +1,145 @@
1
+ import { combineUsage } from "../../core/usage-totals.js";
2
+ import { activitiesText, activityTarget, clipText, compactArguments } from "./activity.js";
3
+ import { AGENT_MAX_ACTIVITIES } from "./types.js";
4
+ function emptyUsage() {
5
+ return {
6
+ input: 0,
7
+ output: 0,
8
+ cacheRead: 0,
9
+ cacheWrite: 0,
10
+ totalTokens: 0,
11
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
12
+ };
13
+ }
14
+ function assistantText(message) {
15
+ if (message.role !== "assistant")
16
+ return "";
17
+ return message.content
18
+ .filter((block) => block.type === "text")
19
+ .map((block) => block.text)
20
+ .join("\n");
21
+ }
22
+ export function finalAssistantText(messages) {
23
+ for (let index = messages.length - 1; index >= 0; index--) {
24
+ const text = assistantText(messages[index]);
25
+ if (text.trim())
26
+ return text;
27
+ }
28
+ return "";
29
+ }
30
+ function toolErrorText(result) {
31
+ const content = result.content;
32
+ const text = content
33
+ ?.filter((block) => block.type === "text")
34
+ .map((block) => block.text ?? "")
35
+ .join("\n");
36
+ return clipText(text || "Tool call failed.", 1000);
37
+ }
38
+ /**
39
+ * One worker session translated into task progress: a one-line status for the model,
40
+ * tool activity for humans, and cumulative usage for the ledger.
41
+ */
42
+ export class AgentProgress {
43
+ constructor(control) {
44
+ this.activities = [];
45
+ this.counted = new WeakSet();
46
+ this.calls = 0;
47
+ this.usage = emptyUsage();
48
+ this.control = control;
49
+ }
50
+ handle(event) {
51
+ switch (event.type) {
52
+ case "message_end":
53
+ if (event.message.role !== "assistant")
54
+ return;
55
+ this.last = event.message;
56
+ if (!this.counted.has(event.message)) {
57
+ this.counted.add(event.message);
58
+ this.usage = combineUsage(this.usage, event.message.usage);
59
+ }
60
+ return;
61
+ case "compaction_end":
62
+ if (event.result?.usage)
63
+ this.usage = combineUsage(this.usage, event.result.usage);
64
+ return;
65
+ case "tool_execution_start":
66
+ this.calls++;
67
+ this.activities.push({
68
+ id: event.toolCallId,
69
+ name: event.toolName,
70
+ args: compactArguments(event.args),
71
+ target: activityTarget(event.toolName, event.args),
72
+ status: "running",
73
+ });
74
+ if (this.activities.length > AGENT_MAX_ACTIVITIES)
75
+ this.activities.shift();
76
+ break;
77
+ case "tool_execution_end": {
78
+ const activity = this.activities.findLast((item) => item.id === event.toolCallId);
79
+ if (!activity)
80
+ return;
81
+ activity.status = this.control.signal.aborted ? "cancelled" : event.isError ? "error" : "ok";
82
+ activity.durationMs = event.durationMs;
83
+ if (event.isError)
84
+ activity.error = toolErrorText(event.result);
85
+ break;
86
+ }
87
+ default:
88
+ return;
89
+ }
90
+ this.publish();
91
+ }
92
+ publish() {
93
+ this.control.publish({
94
+ result: {
95
+ content: [{ type: "text", text: this.status() }],
96
+ details: {
97
+ version: 2,
98
+ state: "running",
99
+ taskId: this.control.id,
100
+ activities: structuredClone(this.activities),
101
+ },
102
+ },
103
+ display: this.display(),
104
+ usage: this.usage,
105
+ });
106
+ }
107
+ /** Classify a finished run from its last assistant message. */
108
+ outcome() {
109
+ const last = this.last;
110
+ if (this.control.signal.aborted || last?.stopReason === "aborted")
111
+ return { status: "cancelled", error: "Agent cancelled." };
112
+ if (!last || last.stopReason === "error" || last.stopReason === "length")
113
+ return {
114
+ status: "failed",
115
+ error: clipText(last?.errorMessage || "Agent ended without a complete report.", 4096),
116
+ };
117
+ return { status: "completed" };
118
+ }
119
+ complete(status, error, report) {
120
+ return {
121
+ status,
122
+ error,
123
+ usage: this.usage,
124
+ display: this.display(),
125
+ result: {
126
+ content: [{ type: "text", text: report }],
127
+ details: { version: 2, state: status, taskId: this.control.id, ...(error ? { error } : {}) },
128
+ ...(status === "completed" ? {} : { isError: true }),
129
+ },
130
+ };
131
+ }
132
+ /** Model-readable progress: the report is the contract, so intermediate text never leaves the worker. */
133
+ status() {
134
+ const latest = this.activities.at(-1);
135
+ if (!latest)
136
+ return "Agent running; no tool calls yet.";
137
+ const calls = `${this.calls} tool ${this.calls === 1 ? "call" : "calls"}`;
138
+ return `Agent running · ${calls} · latest: ${latest.name}${latest.target ? ` ${latest.target}` : ""}`;
139
+ }
140
+ /** Human-only Output: compact tool calls, never sent to the model. */
141
+ display() {
142
+ return this.activities.length ? `Tool calls\n${activitiesText(this.activities)}` : "";
143
+ }
144
+ }
145
+ //# sourceMappingURL=progress.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress.js","sourceRoot":"","sources":["../../../src/extensions/agent/progress.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport type { Usage } from \"@earendil-works/pi-ai/compat\";\nimport type { AgentSessionEvent } from \"../../core/agent-session.ts\";\nimport type { TaskCompletion, TaskControl, TaskTerminalStatus } from \"../../core/tasks/types.ts\";\nimport { combineUsage } from \"../../core/usage-totals.ts\";\nimport { activitiesText, activityTarget, clipText, compactArguments } from \"./activity.ts\";\nimport { AGENT_MAX_ACTIVITIES, type AgentActivity, type AgentToolDetails } from \"./types.ts\";\n\ntype AssistantMessage = Extract<AgentMessage, { role: \"assistant\" }>;\n\nfunction emptyUsage(): Usage {\n\treturn {\n\t\tinput: 0,\n\t\toutput: 0,\n\t\tcacheRead: 0,\n\t\tcacheWrite: 0,\n\t\ttotalTokens: 0,\n\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t};\n}\n\nfunction assistantText(message: AgentMessage): string {\n\tif (message.role !== \"assistant\") return \"\";\n\treturn message.content\n\t\t.filter((block) => block.type === \"text\")\n\t\t.map((block) => block.text)\n\t\t.join(\"\\n\");\n}\n\nexport function finalAssistantText(messages: readonly AgentMessage[]): string {\n\tfor (let index = messages.length - 1; index >= 0; index--) {\n\t\tconst text = assistantText(messages[index]!);\n\t\tif (text.trim()) return text;\n\t}\n\treturn \"\";\n}\n\nfunction toolErrorText(result: unknown): string {\n\tconst content = (result as { content?: Array<{ type: string; text?: string }> }).content;\n\tconst text = content\n\t\t?.filter((block) => block.type === \"text\")\n\t\t.map((block) => block.text ?? \"\")\n\t\t.join(\"\\n\");\n\treturn clipText(text || \"Tool call failed.\", 1000);\n}\n\n/**\n * One worker session translated into task progress: a one-line status for the model,\n * tool activity for humans, and cumulative usage for the ledger.\n */\nexport class AgentProgress {\n\tprivate readonly control: TaskControl<AgentToolDetails>;\n\tprivate readonly activities: AgentActivity[] = [];\n\tprivate readonly counted = new WeakSet<AgentMessage>();\n\tprivate calls = 0;\n\tprivate usage: Usage = emptyUsage();\n\tprivate last?: AssistantMessage;\n\n\tconstructor(control: TaskControl<AgentToolDetails>) {\n\t\tthis.control = control;\n\t}\n\n\thandle(event: AgentSessionEvent): void {\n\t\tswitch (event.type) {\n\t\t\tcase \"message_end\":\n\t\t\t\tif (event.message.role !== \"assistant\") return;\n\t\t\t\tthis.last = event.message;\n\t\t\t\tif (!this.counted.has(event.message)) {\n\t\t\t\t\tthis.counted.add(event.message);\n\t\t\t\t\tthis.usage = combineUsage(this.usage, event.message.usage);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\tcase \"compaction_end\":\n\t\t\t\tif (event.result?.usage) this.usage = combineUsage(this.usage, event.result.usage);\n\t\t\t\treturn;\n\t\t\tcase \"tool_execution_start\":\n\t\t\t\tthis.calls++;\n\t\t\t\tthis.activities.push({\n\t\t\t\t\tid: event.toolCallId,\n\t\t\t\t\tname: event.toolName,\n\t\t\t\t\targs: compactArguments(event.args),\n\t\t\t\t\ttarget: activityTarget(event.toolName, event.args),\n\t\t\t\t\tstatus: \"running\",\n\t\t\t\t});\n\t\t\t\tif (this.activities.length > AGENT_MAX_ACTIVITIES) this.activities.shift();\n\t\t\t\tbreak;\n\t\t\tcase \"tool_execution_end\": {\n\t\t\t\tconst activity = this.activities.findLast((item) => item.id === event.toolCallId);\n\t\t\t\tif (!activity) return;\n\t\t\t\tactivity.status = this.control.signal.aborted ? \"cancelled\" : event.isError ? \"error\" : \"ok\";\n\t\t\t\tactivity.durationMs = event.durationMs;\n\t\t\t\tif (event.isError) activity.error = toolErrorText(event.result);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\treturn;\n\t\t}\n\t\tthis.publish();\n\t}\n\n\tpublish(): void {\n\t\tthis.control.publish({\n\t\t\tresult: {\n\t\t\t\tcontent: [{ type: \"text\", text: this.status() }],\n\t\t\t\tdetails: {\n\t\t\t\t\tversion: 2,\n\t\t\t\t\tstate: \"running\",\n\t\t\t\t\ttaskId: this.control.id,\n\t\t\t\t\tactivities: structuredClone(this.activities),\n\t\t\t\t},\n\t\t\t},\n\t\t\tdisplay: this.display(),\n\t\t\tusage: this.usage,\n\t\t});\n\t}\n\n\t/** Classify a finished run from its last assistant message. */\n\toutcome(): { status: TaskTerminalStatus; error?: string } {\n\t\tconst last = this.last;\n\t\tif (this.control.signal.aborted || last?.stopReason === \"aborted\")\n\t\t\treturn { status: \"cancelled\", error: \"Agent cancelled.\" };\n\t\tif (!last || last.stopReason === \"error\" || last.stopReason === \"length\")\n\t\t\treturn {\n\t\t\t\tstatus: \"failed\",\n\t\t\t\terror: clipText(last?.errorMessage || \"Agent ended without a complete report.\", 4096),\n\t\t\t};\n\t\treturn { status: \"completed\" };\n\t}\n\n\tcomplete(status: TaskTerminalStatus, error: string | undefined, report: string): TaskCompletion<AgentToolDetails> {\n\t\treturn {\n\t\t\tstatus,\n\t\t\terror,\n\t\t\tusage: this.usage,\n\t\t\tdisplay: this.display(),\n\t\t\tresult: {\n\t\t\t\tcontent: [{ type: \"text\", text: report }],\n\t\t\t\tdetails: { version: 2, state: status, taskId: this.control.id, ...(error ? { error } : {}) },\n\t\t\t\t...(status === \"completed\" ? {} : { isError: true }),\n\t\t\t},\n\t\t};\n\t}\n\n\t/** Model-readable progress: the report is the contract, so intermediate text never leaves the worker. */\n\tprivate status(): string {\n\t\tconst latest = this.activities.at(-1);\n\t\tif (!latest) return \"Agent running; no tool calls yet.\";\n\t\tconst calls = `${this.calls} tool ${this.calls === 1 ? \"call\" : \"calls\"}`;\n\t\treturn `Agent running · ${calls} · latest: ${latest.name}${latest.target ? ` ${latest.target}` : \"\"}`;\n\t}\n\n\t/** Human-only Output: compact tool calls, never sent to the model. */\n\tprivate display(): string {\n\t\treturn this.activities.length ? `Tool calls\\n${activitiesText(this.activities)}` : \"\";\n\t}\n}\n"]}
@@ -0,0 +1,6 @@
1
+ import type { ToolDefinition } from "../../core/extensions/types.ts";
2
+ import type { AgentToolDetails } from "./types.ts";
3
+ type AgentRenderer = Required<Pick<ToolDefinition<any, AgentToolDetails>, "renderCall" | "renderResult">>;
4
+ export declare const agentRenderers: AgentRenderer;
5
+ export {};
6
+ //# sourceMappingURL=render.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../../src/extensions/agent/render.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAmB,cAAc,EAAqB,MAAM,gCAAgC,CAAC;AAIzG,OAAO,KAAK,EAAiB,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAIlE,KAAK,aAAa,GAAG,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,GAAG,EAAE,gBAAgB,CAAC,EAAE,YAAY,GAAG,cAAc,CAAC,CAAC,CAAC;AAiH1G,eAAO,MAAM,cAAc,EAAE,aA0B5B,CAAC"}
@@ -0,0 +1,120 @@
1
+ import { Container, TruncatedText, truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
2
+ import { getTextOutput, startToolTimer, toolTimerText } from "../../core/tools/render-utils.js";
3
+ import { activityGlyph, clipText, formatActivityDuration, targetOf } from "./activity.js";
4
+ const EXPANDED_ACTIVITIES = 5;
5
+ class AgentCallComponent {
6
+ constructor(theme) {
7
+ this.title = "";
8
+ this.parts = {};
9
+ this.theme = theme;
10
+ }
11
+ update(theme, title, parts) {
12
+ this.theme = theme;
13
+ this.title = singleLine(title, 160);
14
+ this.parts = parts;
15
+ }
16
+ render(width) {
17
+ if (width <= 0)
18
+ return [];
19
+ const heading = this.theme.fg("toolTitle", this.theme.bold("Agent"));
20
+ const available = width - visibleWidth(heading) - 1;
21
+ if (available <= 0)
22
+ return [truncateToWidth(heading, width, "")];
23
+ // Tasks access and time are fixed; diagnostics take precedence over the task label.
24
+ const { diagnostic, duration, tasks } = this.parts;
25
+ const fullSuffix = [duration, tasks].filter(Boolean).join(" · ");
26
+ const suffix = truncateToWidth(visibleWidth(fullSuffix) <= available ? fullSuffix : (tasks ?? duration ?? ""), available, "…");
27
+ const contentWidth = Math.max(0, available - visibleWidth(suffix) - (suffix ? 3 : 0));
28
+ const shownDiagnostic = truncateToWidth(diagnostic ?? "", contentWidth, "…");
29
+ const titleWidth = Math.max(0, contentWidth - visibleWidth(shownDiagnostic) - (shownDiagnostic ? 3 : 0));
30
+ const title = truncateToWidth(this.title, titleWidth, "…");
31
+ const parts = [
32
+ title ? this.theme.fg("muted", title) : undefined,
33
+ shownDiagnostic ? this.theme.fg("dim", shownDiagnostic) : undefined,
34
+ suffix ? this.theme.fg("dim", suffix) : undefined,
35
+ ].filter(Boolean);
36
+ return [heading + (parts.length ? ` ${parts.join(this.theme.fg("dim", " · "))}` : "")];
37
+ }
38
+ invalidate() { }
39
+ }
40
+ function activityColor(status) {
41
+ switch (status) {
42
+ case "running":
43
+ return "warning";
44
+ case "ok":
45
+ return "success";
46
+ case "error":
47
+ return "error";
48
+ case "cancelled":
49
+ return "muted";
50
+ }
51
+ }
52
+ function renderActivity(activity, theme) {
53
+ const target = targetOf(activity);
54
+ const duration = formatActivityDuration(activity.durationMs);
55
+ return [
56
+ `${theme.fg(activityColor(activity.status), activityGlyph(activity.status))} ${theme.fg("toolTitle", activity.name)}${target ? theme.fg("muted", ` ${target}`) : ""}`,
57
+ ...(duration ? [theme.fg("dim", duration)] : []),
58
+ ].join(theme.fg("dim", " · "));
59
+ }
60
+ function detailsOf(result) {
61
+ const details = result?.details;
62
+ return details?.version === 2 && typeof details.state === "string" ? details : undefined;
63
+ }
64
+ function singleLine(text, bytes = 120) {
65
+ return clipText(text.replace(/\s+/gu, " ").trim(), bytes);
66
+ }
67
+ function errorOf(result, details) {
68
+ if (details && "error" in details && details.error)
69
+ return singleLine(details.error, 240);
70
+ const output = result ? getTextOutput(result, false).trim() : "";
71
+ const marker = output.lastIndexOf("Error:");
72
+ return singleLine(marker >= 0 ? output.slice(marker + 6) : output.split("\n")[0] || "Failed", 240);
73
+ }
74
+ function statusParts(context, details) {
75
+ const status = details?.state;
76
+ if (status === "background") {
77
+ toolTimerText(context, false);
78
+ return { diagnostic: "Background", tasks: "/tasks" };
79
+ }
80
+ const timer = toolTimerText(context, context.isPartial);
81
+ const duration = timer?.replace(/^(?:Took|Elapsed) /, "");
82
+ const tasks = details?.taskId ? "/tasks" : undefined;
83
+ if (context.isPartial || status === "running") {
84
+ const latest = details?.state === "running" ? details.activities.at(-1) : undefined;
85
+ const activity = latest ? `${latest.name}${targetOf(latest) ? ` ${targetOf(latest)}` : ""}` : "Starting…";
86
+ return { diagnostic: context.expanded ? undefined : activity, duration };
87
+ }
88
+ if (status === "cancelled")
89
+ return { diagnostic: "Cancelled", duration, tasks };
90
+ if (status === "failed" || status === "timeout" || context.isError)
91
+ return { diagnostic: errorOf(context.result, details), duration, tasks };
92
+ return { duration, tasks };
93
+ }
94
+ export const agentRenderers = {
95
+ renderCall(args, theme, context) {
96
+ startToolTimer(context);
97
+ const input = args;
98
+ const title = typeof input.description === "string" && input.description.trim()
99
+ ? input.description
100
+ : typeof input.prompt === "string"
101
+ ? input.prompt
102
+ : "Delegated task";
103
+ const parts = statusParts(context, detailsOf(context.result));
104
+ const component = context.lastComponent instanceof AgentCallComponent ? context.lastComponent : new AgentCallComponent(theme);
105
+ component.update(theme, title, parts);
106
+ return component;
107
+ },
108
+ renderResult(result, options, theme, context) {
109
+ const component = context.lastComponent ?? new Container();
110
+ component.clear();
111
+ const details = detailsOf(result);
112
+ // Only live progress carries activities; settled rows stay one line.
113
+ if (details?.state !== "running" || !options.expanded)
114
+ return component;
115
+ for (const activity of details.activities.slice(-EXPANDED_ACTIVITIES))
116
+ component.addChild(new TruncatedText(renderActivity(activity, theme), 0, 0));
117
+ return component;
118
+ },
119
+ };
120
+ //# sourceMappingURL=render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.js","sourceRoot":"","sources":["../../../src/extensions/agent/render.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Component, Container, TruncatedText, truncateToWidth, visibleWidth } from \"@earendil-works/pi-tui\";\nimport type { AgentToolResult, ToolDefinition, ToolRenderContext } from \"../../core/extensions/types.ts\";\nimport { getTextOutput, startToolTimer, toolTimerText } from \"../../core/tools/render-utils.ts\";\nimport type { Theme } from \"../../modes/interactive/theme/theme.ts\";\nimport { activityGlyph, clipText, formatActivityDuration, targetOf } from \"./activity.ts\";\nimport type { AgentActivity, AgentToolDetails } from \"./types.ts\";\n\nconst EXPANDED_ACTIVITIES = 5;\n\ntype AgentRenderer = Required<Pick<ToolDefinition<any, AgentToolDetails>, \"renderCall\" | \"renderResult\">>;\n\ninterface StatusParts {\n\tdiagnostic?: string;\n\tduration?: string;\n\ttasks?: string;\n}\n\nclass AgentCallComponent implements Component {\n\tprivate title = \"\";\n\tprivate parts: StatusParts = {};\n\tprivate theme: Theme;\n\n\tconstructor(theme: Theme) {\n\t\tthis.theme = theme;\n\t}\n\n\tupdate(theme: Theme, title: string, parts: StatusParts): void {\n\t\tthis.theme = theme;\n\t\tthis.title = singleLine(title, 160);\n\t\tthis.parts = parts;\n\t}\n\n\trender(width: number): string[] {\n\t\tif (width <= 0) return [];\n\t\tconst heading = this.theme.fg(\"toolTitle\", this.theme.bold(\"Agent\"));\n\t\tconst available = width - visibleWidth(heading) - 1;\n\t\tif (available <= 0) return [truncateToWidth(heading, width, \"\")];\n\n\t\t// Tasks access and time are fixed; diagnostics take precedence over the task label.\n\t\tconst { diagnostic, duration, tasks } = this.parts;\n\t\tconst fullSuffix = [duration, tasks].filter(Boolean).join(\" · \");\n\t\tconst suffix = truncateToWidth(\n\t\t\tvisibleWidth(fullSuffix) <= available ? fullSuffix : (tasks ?? duration ?? \"\"),\n\t\t\tavailable,\n\t\t\t\"…\",\n\t\t);\n\t\tconst contentWidth = Math.max(0, available - visibleWidth(suffix) - (suffix ? 3 : 0));\n\t\tconst shownDiagnostic = truncateToWidth(diagnostic ?? \"\", contentWidth, \"…\");\n\t\tconst titleWidth = Math.max(0, contentWidth - visibleWidth(shownDiagnostic) - (shownDiagnostic ? 3 : 0));\n\t\tconst title = truncateToWidth(this.title, titleWidth, \"…\");\n\t\tconst parts = [\n\t\t\ttitle ? this.theme.fg(\"muted\", title) : undefined,\n\t\t\tshownDiagnostic ? this.theme.fg(\"dim\", shownDiagnostic) : undefined,\n\t\t\tsuffix ? this.theme.fg(\"dim\", suffix) : undefined,\n\t\t].filter(Boolean);\n\t\treturn [heading + (parts.length ? ` ${parts.join(this.theme.fg(\"dim\", \" · \"))}` : \"\")];\n\t}\n\n\tinvalidate(): void {}\n}\n\nfunction activityColor(status: AgentActivity[\"status\"]): \"warning\" | \"success\" | \"error\" | \"muted\" {\n\tswitch (status) {\n\t\tcase \"running\":\n\t\t\treturn \"warning\";\n\t\tcase \"ok\":\n\t\t\treturn \"success\";\n\t\tcase \"error\":\n\t\t\treturn \"error\";\n\t\tcase \"cancelled\":\n\t\t\treturn \"muted\";\n\t}\n}\n\nfunction renderActivity(activity: AgentActivity, theme: Theme): string {\n\tconst target = targetOf(activity);\n\tconst duration = formatActivityDuration(activity.durationMs);\n\treturn [\n\t\t`${theme.fg(activityColor(activity.status), activityGlyph(activity.status))} ${theme.fg(\"toolTitle\", activity.name)}${target ? theme.fg(\"muted\", ` ${target}`) : \"\"}`,\n\t\t...(duration ? [theme.fg(\"dim\", duration)] : []),\n\t].join(theme.fg(\"dim\", \" · \"));\n}\n\nfunction detailsOf(result: AgentToolResult<AgentToolDetails> | undefined): AgentToolDetails | undefined {\n\tconst details = result?.details;\n\treturn details?.version === 2 && typeof details.state === \"string\" ? details : undefined;\n}\n\nfunction singleLine(text: string, bytes = 120): string {\n\treturn clipText(text.replace(/\\s+/gu, \" \").trim(), bytes);\n}\n\nfunction errorOf(result: AgentToolResult<AgentToolDetails> | undefined, details: AgentToolDetails | undefined): string {\n\tif (details && \"error\" in details && details.error) return singleLine(details.error, 240);\n\tconst output = result ? getTextOutput(result, false).trim() : \"\";\n\tconst marker = output.lastIndexOf(\"Error:\");\n\treturn singleLine(marker >= 0 ? output.slice(marker + 6) : output.split(\"\\n\")[0] || \"Failed\", 240);\n}\n\nfunction statusParts(\n\tcontext: ToolRenderContext<any, any, AgentToolDetails>,\n\tdetails: AgentToolDetails | undefined,\n): StatusParts {\n\tconst status = details?.state;\n\tif (status === \"background\") {\n\t\ttoolTimerText(context, false);\n\t\treturn { diagnostic: \"Background\", tasks: \"/tasks\" };\n\t}\n\tconst timer = toolTimerText(context, context.isPartial);\n\tconst duration = timer?.replace(/^(?:Took|Elapsed) /, \"\");\n\tconst tasks = details?.taskId ? \"/tasks\" : undefined;\n\tif (context.isPartial || status === \"running\") {\n\t\tconst latest = details?.state === \"running\" ? details.activities.at(-1) : undefined;\n\t\tconst activity = latest ? `${latest.name}${targetOf(latest) ? ` ${targetOf(latest)}` : \"\"}` : \"Starting…\";\n\t\treturn { diagnostic: context.expanded ? undefined : activity, duration };\n\t}\n\tif (status === \"cancelled\") return { diagnostic: \"Cancelled\", duration, tasks };\n\tif (status === \"failed\" || status === \"timeout\" || context.isError)\n\t\treturn { diagnostic: errorOf(context.result, details), duration, tasks };\n\treturn { duration, tasks };\n}\n\nexport const agentRenderers: AgentRenderer = {\n\trenderCall(args, theme, context) {\n\t\tstartToolTimer(context);\n\t\tconst input = args as { description?: unknown; prompt?: unknown };\n\t\tconst title =\n\t\t\ttypeof input.description === \"string\" && input.description.trim()\n\t\t\t\t? input.description\n\t\t\t\t: typeof input.prompt === \"string\"\n\t\t\t\t\t? input.prompt\n\t\t\t\t\t: \"Delegated task\";\n\t\tconst parts = statusParts(context, detailsOf(context.result));\n\t\tconst component =\n\t\t\tcontext.lastComponent instanceof AgentCallComponent ? context.lastComponent : new AgentCallComponent(theme);\n\t\tcomponent.update(theme, title, parts);\n\t\treturn component;\n\t},\n\trenderResult(result, options, theme, context) {\n\t\tconst component = (context.lastComponent as Container | undefined) ?? new Container();\n\t\tcomponent.clear();\n\t\tconst details = detailsOf(result);\n\t\t// Only live progress carries activities; settled rows stay one line.\n\t\tif (details?.state !== \"running\" || !options.expanded) return component;\n\t\tfor (const activity of details.activities.slice(-EXPANDED_ACTIVITIES))\n\t\t\tcomponent.addChild(new TruncatedText(renderActivity(activity, theme), 0, 0));\n\t\treturn component;\n\t},\n};\n"]}
@@ -0,0 +1,9 @@
1
+ import type { TaskControl } from "../../core/tasks/types.ts";
2
+ import { type AgentToolDetails } from "./types.ts";
3
+ export declare function boundedReport(text: string, fullOutputPath?: string): string;
4
+ /**
5
+ * The model-facing report. An oversized report keeps its beginning and names a managed
6
+ * Markdown file with the complete text, which the task owns and cleans up.
7
+ */
8
+ export declare function finalReport(control: TaskControl<AgentToolDetails>, report: string, error: string | undefined): Promise<string>;
9
+ //# sourceMappingURL=report.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../../src/extensions/agent/report.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAE7D,OAAO,EAAsB,KAAK,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEvE,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,MAAM,CAM3E;AAQD;;;GAGG;AACH,wBAAsB,WAAW,CAChC,OAAO,EAAE,WAAW,CAAC,gBAAgB,CAAC,EACtC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GAAG,SAAS,GACvB,OAAO,CAAC,MAAM,CAAC,CAajB"}
@@ -0,0 +1,40 @@
1
+ import { unlink } from "node:fs/promises";
2
+ import { boundText } from "../../core/tasks/output.js";
3
+ import { writeOutputFile } from "../../utils/output-files.js";
4
+ import { AGENT_REPORT_BYTES } from "./types.js";
5
+ export function boundedReport(text, fullOutputPath) {
6
+ if (Buffer.byteLength(text) <= AGENT_REPORT_BYTES)
7
+ return text;
8
+ const notice = fullOutputPath
9
+ ? `\n\n[Agent output truncated. Full output: ${fullOutputPath}]`
10
+ : "\n\n[Agent output truncated. Full output unavailable.]";
11
+ return boundText(text, AGENT_REPORT_BYTES - Buffer.byteLength(notice)) + notice;
12
+ }
13
+ async function removeOutputFile(path) {
14
+ await unlink(path).catch((error) => {
15
+ if (error.code !== "ENOENT")
16
+ throw error;
17
+ });
18
+ }
19
+ /**
20
+ * The model-facing report. An oversized report keeps its beginning and names a managed
21
+ * Markdown file with the complete text, which the task owns and cleans up.
22
+ */
23
+ export async function finalReport(control, report, error) {
24
+ const text = !report ? (error ?? "No report returned.") : error ? `${report}\n\nError: ${error}` : report;
25
+ if (Buffer.byteLength(text) <= AGENT_REPORT_BYTES)
26
+ return text;
27
+ let path;
28
+ try {
29
+ path = await writeOutputFile("pi-agent", ".md", text);
30
+ const saved = path;
31
+ control.attachOutput(saved, () => removeOutputFile(saved));
32
+ return boundedReport(text, saved);
33
+ }
34
+ catch {
35
+ if (path)
36
+ await removeOutputFile(path).catch(() => { });
37
+ return boundedReport(text);
38
+ }
39
+ }
40
+ //# sourceMappingURL=report.js.map