@oh-my-pi/pi-coding-agent 7.0.0 → 8.0.1

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 (503) hide show
  1. package/CHANGELOG.md +87 -0
  2. package/README.md +1 -1
  3. package/docs/hooks.md +2 -2
  4. package/docs/sdk.md +1 -1
  5. package/package.json +12 -11
  6. package/scripts/format-prompts.ts +143 -0
  7. package/scripts/generate-template.ts +1 -1
  8. package/src/cli/args.ts +3 -3
  9. package/src/cli/config-cli.ts +4 -4
  10. package/src/cli/file-processor.ts +3 -3
  11. package/src/cli/list-models.ts +2 -2
  12. package/src/cli/plugin-cli.ts +3 -3
  13. package/src/cli/session-picker.ts +2 -2
  14. package/src/cli/setup-cli.ts +2 -2
  15. package/src/cli/stats-cli.ts +1 -1
  16. package/src/cli/update-cli.ts +2 -2
  17. package/src/{core → config}/keybindings.ts +1 -1
  18. package/src/{core → config}/model-registry.ts +1 -1
  19. package/src/{core → config}/model-resolver.ts +3 -3
  20. package/src/{core → config}/prompt-templates.ts +2 -2
  21. package/src/{core → config}/settings-manager.ts +6 -6
  22. package/src/{core/cursor/exec-bridge.ts → cursor.ts} +4 -4
  23. package/src/discovery/agents-md.ts +4 -4
  24. package/src/discovery/builtin.ts +17 -17
  25. package/src/discovery/claude.ts +12 -12
  26. package/src/discovery/cline.ts +6 -6
  27. package/src/discovery/codex.ts +21 -21
  28. package/src/discovery/cursor.ts +9 -9
  29. package/src/discovery/gemini.ts +9 -9
  30. package/src/discovery/github.ts +6 -6
  31. package/src/discovery/helpers.ts +4 -4
  32. package/src/discovery/index.ts +16 -16
  33. package/src/discovery/mcp-json.ts +4 -4
  34. package/src/discovery/ssh.ts +4 -4
  35. package/src/discovery/vscode.ts +4 -4
  36. package/src/discovery/windsurf.ts +6 -6
  37. package/src/{core/tools/exa → exa}/company.ts +2 -3
  38. package/src/{core/tools/exa → exa}/index.ts +2 -2
  39. package/src/{core/tools/exa → exa}/linkedin.ts +2 -3
  40. package/src/{core/tools/exa → exa}/mcp-client.ts +2 -2
  41. package/src/{core/tools/exa → exa}/render.ts +3 -3
  42. package/src/{core/tools/exa → exa}/researcher.ts +1 -1
  43. package/src/{core/tools/exa → exa}/search.ts +2 -10
  44. package/src/{core/tools/exa → exa}/websets.ts +1 -1
  45. package/src/{core → exec}/bash-executor.ts +22 -6
  46. package/src/{core → export}/custom-share.ts +1 -1
  47. package/src/{core/export-html → export/html}/index.ts +3 -3
  48. package/src/{core → export}/ttsr.ts +2 -2
  49. package/src/{core → extensibility}/custom-commands/bundled/review/index.ts +4 -4
  50. package/src/{core → extensibility}/custom-commands/loader.ts +3 -3
  51. package/src/{core → extensibility}/custom-commands/types.ts +1 -1
  52. package/src/{core → extensibility}/custom-tools/loader.ts +9 -9
  53. package/src/{core → extensibility}/custom-tools/types.ts +6 -6
  54. package/src/{core → extensibility}/custom-tools/wrapper.ts +1 -1
  55. package/src/{core → extensibility}/extensions/loader.ts +8 -8
  56. package/src/{core → extensibility}/extensions/runner.ts +3 -3
  57. package/src/{core → extensibility}/extensions/types.ts +15 -15
  58. package/src/{core → extensibility}/extensions/wrapper.ts +1 -1
  59. package/src/{core → extensibility}/hooks/index.ts +1 -1
  60. package/src/{core → extensibility}/hooks/loader.ts +7 -7
  61. package/src/{core → extensibility}/hooks/runner.ts +4 -4
  62. package/src/{core → extensibility}/hooks/types.ts +9 -9
  63. package/src/{core → extensibility}/plugins/doctor.ts +1 -1
  64. package/src/{core → extensibility}/plugins/installer.ts +2 -3
  65. package/src/{core → extensibility}/plugins/paths.ts +1 -1
  66. package/src/{core → extensibility}/skills.ts +8 -48
  67. package/src/{core → extensibility}/slash-commands.ts +6 -6
  68. package/src/index.ts +127 -128
  69. package/src/internal-urls/agent-protocol.ts +126 -0
  70. package/src/internal-urls/artifact-protocol.ts +93 -0
  71. package/src/internal-urls/index.ts +28 -0
  72. package/src/internal-urls/json-query.ts +126 -0
  73. package/src/internal-urls/router.ts +69 -0
  74. package/src/internal-urls/rule-protocol.ts +56 -0
  75. package/src/internal-urls/skill-protocol.ts +112 -0
  76. package/src/internal-urls/types.ts +48 -0
  77. package/src/{core/python-executor.ts → ipy/executor.ts} +51 -11
  78. package/src/{core/python-gateway-coordinator.ts → ipy/gateway-coordinator.ts} +41 -325
  79. package/src/{core/python-kernel.ts → ipy/kernel.ts} +38 -10
  80. package/src/ipy/prelude.ts +3 -0
  81. package/src/{core/tools/lsp → lsp}/client.ts +7 -6
  82. package/src/{core/tools/lsp → lsp}/clients/biome-client.ts +1 -1
  83. package/src/{core/tools/lsp → lsp}/clients/index.ts +1 -1
  84. package/src/{core/tools/lsp → lsp}/clients/lsp-linter-client.ts +4 -4
  85. package/src/{core/tools/lsp → lsp}/config.ts +1 -1
  86. package/src/{core/tools/lsp → lsp}/index.ts +16 -15
  87. package/src/{core/tools/lsp → lsp}/render.ts +2 -2
  88. package/src/{core/tools/lsp → lsp}/types.ts +14 -16
  89. package/src/{core/tools/lsp → lsp}/utils.ts +1 -1
  90. package/src/main.ts +12 -12
  91. package/src/{core/mcp → mcp}/config.ts +8 -8
  92. package/src/{core/mcp → mcp}/loader.ts +5 -6
  93. package/src/{core/mcp → mcp}/manager.ts +2 -2
  94. package/src/{core/mcp → mcp}/tool-bridge.ts +35 -6
  95. package/src/{core/mcp → mcp}/tool-cache.ts +1 -1
  96. package/src/{core/mcp → mcp}/transports/http.ts +7 -1
  97. package/src/{core/mcp → mcp}/transports/stdio.ts +1 -1
  98. package/src/{core/mcp → mcp}/types.ts +1 -1
  99. package/src/migrations.ts +2 -2
  100. package/src/modes/{interactive/components → components}/armin.ts +1 -1
  101. package/src/modes/{interactive/components → components}/assistant-message.ts +1 -1
  102. package/src/modes/{interactive/components → components}/bash-execution.ts +37 -29
  103. package/src/modes/{interactive/components → components}/bordered-loader.ts +1 -1
  104. package/src/modes/{interactive/components → components}/branch-summary-message.ts +2 -2
  105. package/src/modes/{interactive/components → components}/compaction-summary-message.ts +2 -2
  106. package/src/modes/{interactive/components → components}/custom-message.ts +3 -3
  107. package/src/modes/{interactive/components → components}/diff.ts +1 -1
  108. package/src/modes/{interactive/components → components}/dynamic-border.ts +1 -1
  109. package/src/modes/{interactive/components → components}/extensions/extension-dashboard.ts +3 -3
  110. package/src/modes/{interactive/components → components}/extensions/extension-list.ts +2 -2
  111. package/src/modes/{interactive/components → components}/extensions/inspector-panel.ts +1 -1
  112. package/src/modes/{interactive/components → components}/extensions/state-manager.ts +11 -17
  113. package/src/modes/{interactive/components → components}/extensions/types.ts +1 -1
  114. package/src/modes/{interactive/components → components}/footer.ts +3 -3
  115. package/src/modes/{interactive/components → components}/history-search.ts +2 -2
  116. package/src/modes/{interactive/components → components}/hook-editor.ts +1 -1
  117. package/src/modes/{interactive/components → components}/hook-input.ts +1 -1
  118. package/src/modes/{interactive/components → components}/hook-message.ts +3 -3
  119. package/src/modes/{interactive/components → components}/hook-selector.ts +1 -1
  120. package/src/modes/{interactive/components → components}/keybinding-hints.ts +2 -2
  121. package/src/modes/{interactive/components → components}/login-dialog.ts +1 -1
  122. package/src/modes/{interactive/components → components}/model-selector.ts +5 -5
  123. package/src/modes/{interactive/components → components}/oauth-selector.ts +2 -2
  124. package/src/modes/{interactive/components → components}/plugin-settings.ts +3 -3
  125. package/src/modes/{interactive/components → components}/python-execution.ts +35 -24
  126. package/src/modes/{interactive/components → components}/queue-mode-selector.ts +1 -1
  127. package/src/modes/{interactive/components → components}/read-tool-group.ts +2 -2
  128. package/src/modes/{interactive/components → components}/session-selector.ts +3 -3
  129. package/src/modes/{interactive/components → components}/settings-defs.ts +2 -2
  130. package/src/modes/{interactive/components → components}/settings-selector.ts +2 -2
  131. package/src/modes/{interactive/components → components}/show-images-selector.ts +1 -1
  132. package/src/modes/{interactive/components → components}/status-line/segments.ts +2 -2
  133. package/src/modes/{interactive/components → components}/status-line/separators.ts +1 -1
  134. package/src/modes/{interactive/components → components}/status-line/types.ts +2 -2
  135. package/src/modes/{interactive/components → components}/status-line-segment-editor.ts +2 -2
  136. package/src/modes/{interactive/components → components}/status-line.ts +3 -3
  137. package/src/modes/{interactive/components → components}/theme-selector.ts +1 -1
  138. package/src/modes/{interactive/components → components}/thinking-selector.ts +1 -1
  139. package/src/modes/{interactive/components → components}/todo-display.ts +3 -4
  140. package/src/modes/{interactive/components → components}/todo-reminder.ts +2 -2
  141. package/src/modes/{interactive/components → components}/tool-execution.ts +8 -8
  142. package/src/modes/{interactive/components → components}/tree-selector.ts +3 -3
  143. package/src/modes/{interactive/components → components}/ttsr-notification.ts +2 -2
  144. package/src/modes/{interactive/components → components}/user-message-selector.ts +1 -1
  145. package/src/modes/{interactive/components → components}/user-message.ts +1 -1
  146. package/src/modes/{interactive/components → components}/welcome.ts +2 -2
  147. package/src/modes/{interactive/controllers → controllers}/command-controller.ts +32 -30
  148. package/src/modes/{interactive/controllers → controllers}/event-controller.ts +9 -9
  149. package/src/modes/{interactive/controllers → controllers}/extension-ui-controller.ts +8 -8
  150. package/src/modes/{interactive/controllers → controllers}/input-controller.ts +6 -6
  151. package/src/modes/{interactive/controllers → controllers}/selector-controller.ts +16 -16
  152. package/src/modes/index.ts +1 -1
  153. package/src/modes/{interactive/interactive-mode.ts → interactive-mode.ts} +14 -14
  154. package/src/modes/print-mode.ts +1 -1
  155. package/src/modes/rpc/rpc-client.ts +3 -3
  156. package/src/modes/rpc/rpc-mode.ts +3 -3
  157. package/src/modes/rpc/rpc-types.ts +3 -3
  158. package/src/modes/{interactive/theme → theme}/theme.ts +1 -1
  159. package/src/modes/{interactive/types.ts → types.ts} +8 -9
  160. package/src/modes/{interactive/utils → utils}/ui-helpers.ts +20 -27
  161. package/src/{core/tools/patch → patch}/applicator.ts +1 -1
  162. package/src/{core/tools/patch → patch}/diff.ts +1 -1
  163. package/src/{core/tools/patch → patch}/index.ts +31 -36
  164. package/src/{core/tools/patch → patch}/shared.ts +9 -6
  165. package/src/prompts/agents/explore.md +83 -46
  166. package/src/prompts/agents/init.md +9 -4
  167. package/src/prompts/agents/plan.md +8 -7
  168. package/src/prompts/agents/reviewer.md +36 -18
  169. package/src/prompts/agents/task.md +4 -4
  170. package/src/prompts/compaction/branch-summary-preamble.md +0 -1
  171. package/src/prompts/review-request.md +0 -1
  172. package/src/prompts/system/custom-system-prompt.md +2 -14
  173. package/src/prompts/system/file-operations.md +0 -2
  174. package/src/prompts/system/system-prompt.md +147 -138
  175. package/src/prompts/system/web-search.md +26 -0
  176. package/src/prompts/tools/ask.md +31 -24
  177. package/src/prompts/tools/bash.md +20 -17
  178. package/src/prompts/tools/calculator.md +9 -5
  179. package/src/prompts/tools/fetch.md +16 -0
  180. package/src/prompts/tools/find.md +15 -5
  181. package/src/prompts/tools/gemini-image.md +21 -6
  182. package/src/prompts/tools/grep.md +28 -12
  183. package/src/prompts/tools/lsp.md +35 -14
  184. package/src/prompts/tools/patch.md +39 -41
  185. package/src/prompts/tools/python.md +59 -76
  186. package/src/prompts/tools/read.md +23 -22
  187. package/src/prompts/tools/replace.md +19 -12
  188. package/src/prompts/tools/ssh.md +21 -28
  189. package/src/prompts/tools/task.md +54 -44
  190. package/src/prompts/tools/todo-write.md +52 -163
  191. package/src/prompts/tools/web-search.md +16 -9
  192. package/src/prompts/tools/write.md +13 -2
  193. package/src/{core/sdk.ts → sdk.ts} +65 -34
  194. package/src/{core → session}/agent-session.ts +45 -37
  195. package/src/{core → session}/agent-storage.ts +2 -2
  196. package/src/session/artifacts.ts +110 -0
  197. package/src/{core → session}/auth-storage.ts +1 -1
  198. package/src/{core → session}/compaction/branch-summarization.ts +5 -5
  199. package/src/{core → session}/compaction/compaction.ts +6 -6
  200. package/src/{core → session}/compaction/utils.ts +3 -3
  201. package/src/{core → session}/history-storage.ts +1 -1
  202. package/src/{core → session}/messages.ts +6 -8
  203. package/src/{core → session}/session-manager.ts +2 -2
  204. package/src/{core → session}/storage-migration.ts +2 -2
  205. package/src/session/streaming-output.ts +177 -0
  206. package/src/{core/ssh → ssh}/connection-manager.ts +1 -1
  207. package/src/{core/ssh → ssh}/ssh-executor.ts +19 -4
  208. package/src/{core/ssh → ssh}/sshfs-mount.ts +1 -1
  209. package/src/{core/system-prompt.ts → system-prompt.ts} +8 -37
  210. package/src/{core/tools/task → task}/agents.ts +8 -8
  211. package/src/{core/tools/task → task}/commands.ts +5 -6
  212. package/src/{core/tools/task → task}/discovery.ts +3 -3
  213. package/src/{core/tools/task → task}/executor.ts +34 -44
  214. package/src/{core/tools/task → task}/index.ts +206 -50
  215. package/src/{core/tools/task → task}/render.ts +80 -23
  216. package/src/{core/tools/task → task}/subprocess-tool-registry.ts +1 -1
  217. package/src/task/template.ts +47 -0
  218. package/src/{core/tools/task → task}/types.ts +19 -27
  219. package/src/{core/tools/task → task}/worker-protocol.ts +8 -4
  220. package/src/{core/tools/task → task}/worker.ts +34 -29
  221. package/src/task/worktree.ts +166 -0
  222. package/src/{core/tools → tools}/ask.ts +13 -21
  223. package/src/{core/tools → tools}/bash-interceptor.ts +1 -1
  224. package/src/{core/tools → tools}/bash.ts +61 -63
  225. package/src/{core/tools → tools}/calculator.ts +4 -4
  226. package/src/{core/tools → tools}/complete.ts +1 -1
  227. package/src/{core/tools → tools}/context.ts +2 -2
  228. package/src/{core/tools/web-fetch.ts → tools/fetch.ts} +97 -76
  229. package/src/{core/tools → tools}/find.ts +80 -104
  230. package/src/{core/tools → tools}/gemini-image.ts +420 -29
  231. package/src/{core/tools → tools}/grep.ts +155 -164
  232. package/src/{core/tools → tools}/index.ts +63 -56
  233. package/src/tools/list-limit.ts +40 -0
  234. package/src/{core/tools → tools}/ls.ts +44 -35
  235. package/src/{core/tools → tools}/notebook.ts +3 -3
  236. package/src/tools/output-meta.ts +443 -0
  237. package/src/tools/output-utils.ts +63 -0
  238. package/src/{core/tools → tools}/python.ts +105 -89
  239. package/src/tools/read.ts +882 -0
  240. package/src/{core/tools → tools}/render-utils.ts +1 -1
  241. package/src/{core/tools → tools}/renderers.ts +8 -10
  242. package/src/{core/tools → tools}/review.ts +2 -2
  243. package/src/{core/tools → tools}/ssh.ts +56 -59
  244. package/src/{core/tools → tools}/todo-write.ts +12 -23
  245. package/src/tools/tool-errors.ts +95 -0
  246. package/src/tools/tool-result.ts +92 -0
  247. package/src/{core/tools → tools}/truncate.ts +2 -2
  248. package/src/{core/tools → tools}/write.ts +15 -13
  249. package/src/utils/changelog.ts +1 -1
  250. package/src/{core → utils}/file-mentions.ts +4 -4
  251. package/src/utils/image-convert.ts +1 -1
  252. package/src/utils/image-resize.ts +1 -1
  253. package/src/utils/shell.ts +1 -1
  254. package/src/{core → utils}/title-generator.ts +4 -4
  255. package/src/utils/tools-manager.ts +1 -1
  256. package/src/{core/tools/web-scrapers → web/scrapers}/choosealicense.ts +1 -1
  257. package/src/{core/tools/web-scrapers → web/scrapers}/twitter.ts +3 -2
  258. package/src/{core/tools/web-scrapers → web/scrapers}/types.ts +4 -2
  259. package/src/{core/tools/web-scrapers → web/scrapers}/utils.ts +1 -1
  260. package/src/{core/tools/web-scrapers → web/scrapers}/youtube.ts +14 -13
  261. package/src/{core/tools/web-search → web/search}/auth.ts +4 -4
  262. package/src/{core/tools/web-search → web/search}/index.ts +22 -71
  263. package/src/{core/tools/web-search → web/search}/providers/anthropic.ts +7 -10
  264. package/src/{core/tools/web-search → web/search}/providers/exa.ts +2 -2
  265. package/src/{core/tools/web-search → web/search}/providers/perplexity.ts +4 -16
  266. package/src/{core/tools/web-search → web/search}/render.ts +3 -3
  267. package/tsconfig.json +25 -0
  268. package/scripts/migrate-sessions.sh +0 -93
  269. package/src/core/index.ts +0 -56
  270. package/src/core/python-prelude.ts +0 -3
  271. package/src/core/ssh-executor.ts +0 -5
  272. package/src/core/streaming-output.ts +0 -115
  273. package/src/core/tools/output.ts +0 -519
  274. package/src/core/tools/read.ts +0 -717
  275. package/src/core/tools/task/template.ts +0 -37
  276. package/src/prompts/tools/output.md +0 -47
  277. package/src/prompts/tools/web-fetch.md +0 -9
  278. package/src/vendor/photon/photon_rs_bg.wasm.b64.js +0 -1
  279. /package/src/{core/tools/exa → exa}/types.ts +0 -0
  280. /package/src/{core → exec}/exec.ts +0 -0
  281. /package/src/{core/export-html → export/html}/template.css +0 -0
  282. /package/src/{core/export-html → export/html}/template.generated.ts +0 -0
  283. /package/src/{core/export-html → export/html}/template.html +0 -0
  284. /package/src/{core/export-html → export/html}/template.js +0 -0
  285. /package/src/{core/export-html → export/html}/template.macro.ts +0 -0
  286. /package/src/{core/export-html → export/html}/vendor/highlight.min.js +0 -0
  287. /package/src/{core/export-html → export/html}/vendor/marked.min.js +0 -0
  288. /package/src/{core → extensibility}/custom-commands/index.ts +0 -0
  289. /package/src/{core → extensibility}/custom-tools/index.ts +0 -0
  290. /package/src/{core → extensibility}/extensions/index.ts +0 -0
  291. /package/src/{core → extensibility}/hooks/tool-wrapper.ts +0 -0
  292. /package/src/{core → extensibility}/plugins/index.ts +0 -0
  293. /package/src/{core → extensibility}/plugins/loader.ts +0 -0
  294. /package/src/{core → extensibility}/plugins/manager.ts +0 -0
  295. /package/src/{core → extensibility}/plugins/parser.ts +0 -0
  296. /package/src/{core → extensibility}/plugins/types.ts +0 -0
  297. /package/src/{core/python-modules.ts → ipy/modules.ts} +0 -0
  298. /package/src/{core/python-prelude.py → ipy/prelude.py} +0 -0
  299. /package/src/{core/tools/lsp → lsp}/defaults.json +0 -0
  300. /package/src/{core/tools/lsp → lsp}/edits.ts +0 -0
  301. /package/src/{core/tools/lsp → lsp}/lspmux.ts +0 -0
  302. /package/src/{core/tools/lsp → lsp}/rust-analyzer.ts +0 -0
  303. /package/src/{core/mcp → mcp}/client.ts +0 -0
  304. /package/src/{core/mcp → mcp}/index.ts +0 -0
  305. /package/src/{core/mcp → mcp}/json-rpc.ts +0 -0
  306. /package/src/{core/mcp → mcp}/transports/index.ts +0 -0
  307. /package/src/modes/{interactive/components → components}/countdown-timer.ts +0 -0
  308. /package/src/modes/{interactive/components → components}/custom-editor.ts +0 -0
  309. /package/src/modes/{interactive/components → components}/extensions/index.ts +0 -0
  310. /package/src/modes/{interactive/components → components}/index.ts +0 -0
  311. /package/src/modes/{interactive/components → components}/status-line/index.ts +0 -0
  312. /package/src/modes/{interactive/components → components}/status-line/presets.ts +0 -0
  313. /package/src/modes/{interactive/components → components}/visual-truncate.ts +0 -0
  314. /package/src/modes/{interactive/theme → theme}/dark.json +0 -0
  315. /package/src/modes/{interactive/theme → theme}/defaults/alabaster.json +0 -0
  316. /package/src/modes/{interactive/theme → theme}/defaults/amethyst.json +0 -0
  317. /package/src/modes/{interactive/theme → theme}/defaults/anthracite.json +0 -0
  318. /package/src/modes/{interactive/theme → theme}/defaults/basalt.json +0 -0
  319. /package/src/modes/{interactive/theme → theme}/defaults/birch.json +0 -0
  320. /package/src/modes/{interactive/theme → theme}/defaults/dark-abyss.json +0 -0
  321. /package/src/modes/{interactive/theme → theme}/defaults/dark-arctic.json +0 -0
  322. /package/src/modes/{interactive/theme → theme}/defaults/dark-aurora.json +0 -0
  323. /package/src/modes/{interactive/theme → theme}/defaults/dark-catppuccin.json +0 -0
  324. /package/src/modes/{interactive/theme → theme}/defaults/dark-cavern.json +0 -0
  325. /package/src/modes/{interactive/theme → theme}/defaults/dark-copper.json +0 -0
  326. /package/src/modes/{interactive/theme → theme}/defaults/dark-cosmos.json +0 -0
  327. /package/src/modes/{interactive/theme → theme}/defaults/dark-cyberpunk.json +0 -0
  328. /package/src/modes/{interactive/theme → theme}/defaults/dark-dracula.json +0 -0
  329. /package/src/modes/{interactive/theme → theme}/defaults/dark-eclipse.json +0 -0
  330. /package/src/modes/{interactive/theme → theme}/defaults/dark-ember.json +0 -0
  331. /package/src/modes/{interactive/theme → theme}/defaults/dark-equinox.json +0 -0
  332. /package/src/modes/{interactive/theme → theme}/defaults/dark-forest.json +0 -0
  333. /package/src/modes/{interactive/theme → theme}/defaults/dark-github.json +0 -0
  334. /package/src/modes/{interactive/theme → theme}/defaults/dark-gruvbox.json +0 -0
  335. /package/src/modes/{interactive/theme → theme}/defaults/dark-lavender.json +0 -0
  336. /package/src/modes/{interactive/theme → theme}/defaults/dark-lunar.json +0 -0
  337. /package/src/modes/{interactive/theme → theme}/defaults/dark-midnight.json +0 -0
  338. /package/src/modes/{interactive/theme → theme}/defaults/dark-monochrome.json +0 -0
  339. /package/src/modes/{interactive/theme → theme}/defaults/dark-monokai.json +0 -0
  340. /package/src/modes/{interactive/theme → theme}/defaults/dark-nebula.json +0 -0
  341. /package/src/modes/{interactive/theme → theme}/defaults/dark-nord.json +0 -0
  342. /package/src/modes/{interactive/theme → theme}/defaults/dark-ocean.json +0 -0
  343. /package/src/modes/{interactive/theme → theme}/defaults/dark-one.json +0 -0
  344. /package/src/modes/{interactive/theme → theme}/defaults/dark-rainforest.json +0 -0
  345. /package/src/modes/{interactive/theme → theme}/defaults/dark-reef.json +0 -0
  346. /package/src/modes/{interactive/theme → theme}/defaults/dark-retro.json +0 -0
  347. /package/src/modes/{interactive/theme → theme}/defaults/dark-rose-pine.json +0 -0
  348. /package/src/modes/{interactive/theme → theme}/defaults/dark-sakura.json +0 -0
  349. /package/src/modes/{interactive/theme → theme}/defaults/dark-slate.json +0 -0
  350. /package/src/modes/{interactive/theme → theme}/defaults/dark-solarized.json +0 -0
  351. /package/src/modes/{interactive/theme → theme}/defaults/dark-solstice.json +0 -0
  352. /package/src/modes/{interactive/theme → theme}/defaults/dark-starfall.json +0 -0
  353. /package/src/modes/{interactive/theme → theme}/defaults/dark-sunset.json +0 -0
  354. /package/src/modes/{interactive/theme → theme}/defaults/dark-swamp.json +0 -0
  355. /package/src/modes/{interactive/theme → theme}/defaults/dark-synthwave.json +0 -0
  356. /package/src/modes/{interactive/theme → theme}/defaults/dark-taiga.json +0 -0
  357. /package/src/modes/{interactive/theme → theme}/defaults/dark-terminal.json +0 -0
  358. /package/src/modes/{interactive/theme → theme}/defaults/dark-tokyo-night.json +0 -0
  359. /package/src/modes/{interactive/theme → theme}/defaults/dark-tundra.json +0 -0
  360. /package/src/modes/{interactive/theme → theme}/defaults/dark-twilight.json +0 -0
  361. /package/src/modes/{interactive/theme → theme}/defaults/dark-volcanic.json +0 -0
  362. /package/src/modes/{interactive/theme → theme}/defaults/graphite.json +0 -0
  363. /package/src/modes/{interactive/theme → theme}/defaults/index.ts +0 -0
  364. /package/src/modes/{interactive/theme → theme}/defaults/light-arctic.json +0 -0
  365. /package/src/modes/{interactive/theme → theme}/defaults/light-aurora-day.json +0 -0
  366. /package/src/modes/{interactive/theme → theme}/defaults/light-canyon.json +0 -0
  367. /package/src/modes/{interactive/theme → theme}/defaults/light-catppuccin.json +0 -0
  368. /package/src/modes/{interactive/theme → theme}/defaults/light-cirrus.json +0 -0
  369. /package/src/modes/{interactive/theme → theme}/defaults/light-coral.json +0 -0
  370. /package/src/modes/{interactive/theme → theme}/defaults/light-cyberpunk.json +0 -0
  371. /package/src/modes/{interactive/theme → theme}/defaults/light-dawn.json +0 -0
  372. /package/src/modes/{interactive/theme → theme}/defaults/light-dunes.json +0 -0
  373. /package/src/modes/{interactive/theme → theme}/defaults/light-eucalyptus.json +0 -0
  374. /package/src/modes/{interactive/theme → theme}/defaults/light-forest.json +0 -0
  375. /package/src/modes/{interactive/theme → theme}/defaults/light-frost.json +0 -0
  376. /package/src/modes/{interactive/theme → theme}/defaults/light-github.json +0 -0
  377. /package/src/modes/{interactive/theme → theme}/defaults/light-glacier.json +0 -0
  378. /package/src/modes/{interactive/theme → theme}/defaults/light-gruvbox.json +0 -0
  379. /package/src/modes/{interactive/theme → theme}/defaults/light-haze.json +0 -0
  380. /package/src/modes/{interactive/theme → theme}/defaults/light-honeycomb.json +0 -0
  381. /package/src/modes/{interactive/theme → theme}/defaults/light-lagoon.json +0 -0
  382. /package/src/modes/{interactive/theme → theme}/defaults/light-lavender.json +0 -0
  383. /package/src/modes/{interactive/theme → theme}/defaults/light-meadow.json +0 -0
  384. /package/src/modes/{interactive/theme → theme}/defaults/light-mint.json +0 -0
  385. /package/src/modes/{interactive/theme → theme}/defaults/light-monochrome.json +0 -0
  386. /package/src/modes/{interactive/theme → theme}/defaults/light-ocean.json +0 -0
  387. /package/src/modes/{interactive/theme → theme}/defaults/light-one.json +0 -0
  388. /package/src/modes/{interactive/theme → theme}/defaults/light-opal.json +0 -0
  389. /package/src/modes/{interactive/theme → theme}/defaults/light-orchard.json +0 -0
  390. /package/src/modes/{interactive/theme → theme}/defaults/light-paper.json +0 -0
  391. /package/src/modes/{interactive/theme → theme}/defaults/light-prism.json +0 -0
  392. /package/src/modes/{interactive/theme → theme}/defaults/light-retro.json +0 -0
  393. /package/src/modes/{interactive/theme → theme}/defaults/light-sand.json +0 -0
  394. /package/src/modes/{interactive/theme → theme}/defaults/light-savanna.json +0 -0
  395. /package/src/modes/{interactive/theme → theme}/defaults/light-solarized.json +0 -0
  396. /package/src/modes/{interactive/theme → theme}/defaults/light-soleil.json +0 -0
  397. /package/src/modes/{interactive/theme → theme}/defaults/light-sunset.json +0 -0
  398. /package/src/modes/{interactive/theme → theme}/defaults/light-synthwave.json +0 -0
  399. /package/src/modes/{interactive/theme → theme}/defaults/light-tokyo-night.json +0 -0
  400. /package/src/modes/{interactive/theme → theme}/defaults/light-wetland.json +0 -0
  401. /package/src/modes/{interactive/theme → theme}/defaults/light-zenith.json +0 -0
  402. /package/src/modes/{interactive/theme → theme}/defaults/limestone.json +0 -0
  403. /package/src/modes/{interactive/theme → theme}/defaults/mahogany.json +0 -0
  404. /package/src/modes/{interactive/theme → theme}/defaults/marble.json +0 -0
  405. /package/src/modes/{interactive/theme → theme}/defaults/obsidian.json +0 -0
  406. /package/src/modes/{interactive/theme → theme}/defaults/onyx.json +0 -0
  407. /package/src/modes/{interactive/theme → theme}/defaults/pearl.json +0 -0
  408. /package/src/modes/{interactive/theme → theme}/defaults/porcelain.json +0 -0
  409. /package/src/modes/{interactive/theme → theme}/defaults/quartz.json +0 -0
  410. /package/src/modes/{interactive/theme → theme}/defaults/sandstone.json +0 -0
  411. /package/src/modes/{interactive/theme → theme}/defaults/titanium.json +0 -0
  412. /package/src/modes/{interactive/theme → theme}/light.json +0 -0
  413. /package/src/modes/{interactive/theme → theme}/theme-schema.json +0 -0
  414. /package/src/{core/tools/patch → patch}/fuzzy.ts +0 -0
  415. /package/src/{core/tools/patch → patch}/normalize.ts +0 -0
  416. /package/src/{core/tools/patch → patch}/normative.ts +0 -0
  417. /package/src/{core/tools/patch → patch}/parser.ts +0 -0
  418. /package/src/{core/tools/patch → patch}/types.ts +0 -0
  419. /package/src/{core → session}/compaction/index.ts +0 -0
  420. /package/src/{core → session}/session-storage.ts +0 -0
  421. /package/src/{core/tools/task → task}/name-generator.ts +0 -0
  422. /package/src/{core/tools/task → task}/omp-command.ts +0 -0
  423. /package/src/{core/tools/task → task}/parallel.ts +0 -0
  424. /package/src/{core/tools → tools}/jtd-to-json-schema.ts +0 -0
  425. /package/src/{core/tools → tools}/path-utils.ts +0 -0
  426. /package/src/{core → utils}/event-bus.ts +0 -0
  427. /package/src/{core → utils}/frontmatter.ts +0 -0
  428. /package/src/{core → utils}/terminal-notify.ts +0 -0
  429. /package/src/{core → utils}/timings.ts +0 -0
  430. /package/src/{core → utils}/utils.ts +0 -0
  431. /package/src/{core/tools/web-scrapers → web/scrapers}/artifacthub.ts +0 -0
  432. /package/src/{core/tools/web-scrapers → web/scrapers}/arxiv.ts +0 -0
  433. /package/src/{core/tools/web-scrapers → web/scrapers}/aur.ts +0 -0
  434. /package/src/{core/tools/web-scrapers → web/scrapers}/biorxiv.ts +0 -0
  435. /package/src/{core/tools/web-scrapers → web/scrapers}/bluesky.ts +0 -0
  436. /package/src/{core/tools/web-scrapers → web/scrapers}/brew.ts +0 -0
  437. /package/src/{core/tools/web-scrapers → web/scrapers}/cheatsh.ts +0 -0
  438. /package/src/{core/tools/web-scrapers → web/scrapers}/chocolatey.ts +0 -0
  439. /package/src/{core/tools/web-scrapers → web/scrapers}/cisa-kev.ts +0 -0
  440. /package/src/{core/tools/web-scrapers → web/scrapers}/clojars.ts +0 -0
  441. /package/src/{core/tools/web-scrapers → web/scrapers}/coingecko.ts +0 -0
  442. /package/src/{core/tools/web-scrapers → web/scrapers}/crates-io.ts +0 -0
  443. /package/src/{core/tools/web-scrapers → web/scrapers}/crossref.ts +0 -0
  444. /package/src/{core/tools/web-scrapers → web/scrapers}/devto.ts +0 -0
  445. /package/src/{core/tools/web-scrapers → web/scrapers}/discogs.ts +0 -0
  446. /package/src/{core/tools/web-scrapers → web/scrapers}/discourse.ts +0 -0
  447. /package/src/{core/tools/web-scrapers → web/scrapers}/dockerhub.ts +0 -0
  448. /package/src/{core/tools/web-scrapers → web/scrapers}/fdroid.ts +0 -0
  449. /package/src/{core/tools/web-scrapers → web/scrapers}/firefox-addons.ts +0 -0
  450. /package/src/{core/tools/web-scrapers → web/scrapers}/flathub.ts +0 -0
  451. /package/src/{core/tools/web-scrapers → web/scrapers}/github-gist.ts +0 -0
  452. /package/src/{core/tools/web-scrapers → web/scrapers}/github.ts +0 -0
  453. /package/src/{core/tools/web-scrapers → web/scrapers}/gitlab.ts +0 -0
  454. /package/src/{core/tools/web-scrapers → web/scrapers}/go-pkg.ts +0 -0
  455. /package/src/{core/tools/web-scrapers → web/scrapers}/hackage.ts +0 -0
  456. /package/src/{core/tools/web-scrapers → web/scrapers}/hackernews.ts +0 -0
  457. /package/src/{core/tools/web-scrapers → web/scrapers}/hex.ts +0 -0
  458. /package/src/{core/tools/web-scrapers → web/scrapers}/huggingface.ts +0 -0
  459. /package/src/{core/tools/web-scrapers → web/scrapers}/iacr.ts +0 -0
  460. /package/src/{core/tools/web-scrapers → web/scrapers}/index.ts +0 -0
  461. /package/src/{core/tools/web-scrapers → web/scrapers}/jetbrains-marketplace.ts +0 -0
  462. /package/src/{core/tools/web-scrapers → web/scrapers}/lemmy.ts +0 -0
  463. /package/src/{core/tools/web-scrapers → web/scrapers}/lobsters.ts +0 -0
  464. /package/src/{core/tools/web-scrapers → web/scrapers}/mastodon.ts +0 -0
  465. /package/src/{core/tools/web-scrapers → web/scrapers}/maven.ts +0 -0
  466. /package/src/{core/tools/web-scrapers → web/scrapers}/mdn.ts +0 -0
  467. /package/src/{core/tools/web-scrapers → web/scrapers}/metacpan.ts +0 -0
  468. /package/src/{core/tools/web-scrapers → web/scrapers}/musicbrainz.ts +0 -0
  469. /package/src/{core/tools/web-scrapers → web/scrapers}/npm.ts +0 -0
  470. /package/src/{core/tools/web-scrapers → web/scrapers}/nuget.ts +0 -0
  471. /package/src/{core/tools/web-scrapers → web/scrapers}/nvd.ts +0 -0
  472. /package/src/{core/tools/web-scrapers → web/scrapers}/ollama.ts +0 -0
  473. /package/src/{core/tools/web-scrapers → web/scrapers}/open-vsx.ts +0 -0
  474. /package/src/{core/tools/web-scrapers → web/scrapers}/opencorporates.ts +0 -0
  475. /package/src/{core/tools/web-scrapers → web/scrapers}/openlibrary.ts +0 -0
  476. /package/src/{core/tools/web-scrapers → web/scrapers}/orcid.ts +0 -0
  477. /package/src/{core/tools/web-scrapers → web/scrapers}/osv.ts +0 -0
  478. /package/src/{core/tools/web-scrapers → web/scrapers}/packagist.ts +0 -0
  479. /package/src/{core/tools/web-scrapers → web/scrapers}/pub-dev.ts +0 -0
  480. /package/src/{core/tools/web-scrapers → web/scrapers}/pubmed.ts +0 -0
  481. /package/src/{core/tools/web-scrapers → web/scrapers}/pypi.ts +0 -0
  482. /package/src/{core/tools/web-scrapers → web/scrapers}/rawg.ts +0 -0
  483. /package/src/{core/tools/web-scrapers → web/scrapers}/readthedocs.ts +0 -0
  484. /package/src/{core/tools/web-scrapers → web/scrapers}/reddit.ts +0 -0
  485. /package/src/{core/tools/web-scrapers → web/scrapers}/repology.ts +0 -0
  486. /package/src/{core/tools/web-scrapers → web/scrapers}/rfc.ts +0 -0
  487. /package/src/{core/tools/web-scrapers → web/scrapers}/rubygems.ts +0 -0
  488. /package/src/{core/tools/web-scrapers → web/scrapers}/searchcode.ts +0 -0
  489. /package/src/{core/tools/web-scrapers → web/scrapers}/sec-edgar.ts +0 -0
  490. /package/src/{core/tools/web-scrapers → web/scrapers}/semantic-scholar.ts +0 -0
  491. /package/src/{core/tools/web-scrapers → web/scrapers}/snapcraft.ts +0 -0
  492. /package/src/{core/tools/web-scrapers → web/scrapers}/sourcegraph.ts +0 -0
  493. /package/src/{core/tools/web-scrapers → web/scrapers}/spdx.ts +0 -0
  494. /package/src/{core/tools/web-scrapers → web/scrapers}/spotify.ts +0 -0
  495. /package/src/{core/tools/web-scrapers → web/scrapers}/stackoverflow.ts +0 -0
  496. /package/src/{core/tools/web-scrapers → web/scrapers}/terraform.ts +0 -0
  497. /package/src/{core/tools/web-scrapers → web/scrapers}/tldr.ts +0 -0
  498. /package/src/{core/tools/web-scrapers → web/scrapers}/vimeo.ts +0 -0
  499. /package/src/{core/tools/web-scrapers → web/scrapers}/vscode-marketplace.ts +0 -0
  500. /package/src/{core/tools/web-scrapers → web/scrapers}/w3c.ts +0 -0
  501. /package/src/{core/tools/web-scrapers → web/scrapers}/wikidata.ts +0 -0
  502. /package/src/{core/tools/web-scrapers → web/scrapers}/wikipedia.ts +0 -0
  503. /package/src/{core/tools/web-search → web/search}/types.ts +0 -0
@@ -28,23 +28,21 @@ import type {
28
28
  import { isContextOverflow, modelsAreEqual, supportsXhigh } from "@oh-my-pi/pi-ai";
29
29
  import { abortableSleep, logger } from "@oh-my-pi/pi-utils";
30
30
  import { YAML } from "bun";
31
- import type { Rule } from "../capability/rule";
32
- import { getAgentDbPath } from "../config";
33
- import { theme } from "../modes/interactive/theme/theme";
34
- import ttsrInterruptTemplate from "../prompts/system/ttsr-interrupt.md" with { type: "text" };
35
- import { type BashResult, executeBash as executeBashCommand } from "./bash-executor";
31
+ import type { Rule } from "$c/capability/rule";
32
+ import { getAgentDbPath } from "$c/config";
33
+ import type { ModelRegistry } from "$c/config/model-registry";
34
+ import { parseModelString } from "$c/config/model-resolver";
36
35
  import {
37
- type CompactionResult,
38
- calculateContextTokens,
39
- collectEntriesForBranchSummary,
40
- compact,
41
- estimateTokens,
42
- generateBranchSummary,
43
- prepareCompaction,
44
- shouldCompact,
45
- } from "./compaction/index";
46
- import type { LoadedCustomCommand } from "./custom-commands/index";
47
- import { exportSessionToHtml } from "./export-html/index";
36
+ expandPromptTemplate,
37
+ type PromptTemplate,
38
+ parseCommandArgs,
39
+ renderPromptTemplate,
40
+ } from "$c/config/prompt-templates";
41
+ import type { SettingsManager, SkillsSettings } from "$c/config/settings-manager";
42
+ import { type BashResult, executeBash as executeBashCommand } from "$c/exec/bash-executor";
43
+ import { exportSessionToHtml } from "$c/export/html/index";
44
+ import type { TtsrManager } from "$c/export/ttsr";
45
+ import type { LoadedCustomCommand } from "$c/extensibility/custom-commands/index";
48
46
  import type {
49
47
  ExtensionCommandContext,
50
48
  ExtensionRunner,
@@ -56,10 +54,31 @@ import type {
56
54
  TreePreparation,
57
55
  TurnEndEvent,
58
56
  TurnStartEvent,
59
- } from "./extensions";
60
- import type { CompactOptions, ContextUsage } from "./extensions/types";
61
- import { extractFileMentions, generateFileMentionMessages } from "./file-mentions";
62
- import type { HookCommandContext } from "./hooks/types";
57
+ } from "$c/extensibility/extensions";
58
+ import type { CompactOptions, ContextUsage } from "$c/extensibility/extensions/types";
59
+ import type { HookCommandContext } from "$c/extensibility/hooks/types";
60
+ import type { Skill, SkillWarning } from "$c/extensibility/skills";
61
+ import { expandSlashCommand, type FileSlashCommand } from "$c/extensibility/slash-commands";
62
+ import { executePython as executePythonCommand, type PythonResult } from "$c/ipy/executor";
63
+ import { theme } from "$c/modes/theme/theme";
64
+ import { normalizeDiff, normalizeToLF, ParseError, previewPatch, stripBom } from "$c/patch";
65
+ import ttsrInterruptTemplate from "$c/prompts/system/ttsr-interrupt.md" with { type: "text" };
66
+ import { closeAllConnections } from "$c/ssh/connection-manager";
67
+ import { unmountAll } from "$c/ssh/sshfs-mount";
68
+ import { outputMeta } from "$c/tools/output-meta";
69
+ import { resolveToCwd } from "$c/tools/path-utils";
70
+ import type { TodoItem } from "$c/tools/todo-write";
71
+ import { extractFileMentions, generateFileMentionMessages } from "$c/utils/file-mentions";
72
+ import {
73
+ type CompactionResult,
74
+ calculateContextTokens,
75
+ collectEntriesForBranchSummary,
76
+ compact,
77
+ estimateTokens,
78
+ generateBranchSummary,
79
+ prepareCompaction,
80
+ shouldCompact,
81
+ } from "./compaction/index";
63
82
  import {
64
83
  type BashExecutionMessage,
65
84
  type BranchSummaryMessage,
@@ -71,20 +90,7 @@ import {
71
90
  type PythonExecutionMessage,
72
91
  pythonExecutionToText,
73
92
  } from "./messages";
74
- import type { ModelRegistry } from "./model-registry";
75
- import { parseModelString } from "./model-resolver";
76
- import { expandPromptTemplate, type PromptTemplate, parseCommandArgs, renderPromptTemplate } from "./prompt-templates";
77
- import { executePython as executePythonCommand, type PythonResult } from "./python-executor";
78
93
  import type { BranchSummaryEntry, CompactionEntry, NewSessionOptions, SessionManager } from "./session-manager";
79
- import type { SettingsManager, SkillsSettings } from "./settings-manager";
80
- import type { Skill, SkillWarning } from "./skills";
81
- import { expandSlashCommand, type FileSlashCommand } from "./slash-commands";
82
- import { closeAllConnections } from "./ssh/connection-manager";
83
- import { unmountAll } from "./ssh/sshfs-mount";
84
- import { normalizeDiff, normalizeToLF, ParseError, previewPatch, stripBom } from "./tools/patch";
85
- import { resolveToCwd } from "./tools/path-utils";
86
- import type { TodoItem } from "./tools/todo-write";
87
- import type { TtsrManager } from "./ttsr";
88
94
 
89
95
  /** Session-specific events that extend the core AgentEvent */
90
96
  export type AgentSessionEvent =
@@ -587,7 +593,7 @@ export class AgentSession {
587
593
 
588
594
  const args = toolCall.arguments;
589
595
  if (!args || typeof args !== "object" || Array.isArray(args)) return;
590
- if ("oldText" in args || "newText" in args) return;
596
+ if ("old_text" in args || "new_text" in args) return;
591
597
 
592
598
  const path = typeof args.path === "string" ? args.path : undefined;
593
599
  if (!path) return;
@@ -632,7 +638,7 @@ export class AgentSession {
632
638
 
633
639
  const args = toolCall.arguments;
634
640
  if (!args || typeof args !== "object" || Array.isArray(args)) return;
635
- if ("oldText" in args || "newText" in args) return;
641
+ if ("old_text" in args || "new_text" in args) return;
636
642
 
637
643
  const path = typeof args.path === "string" ? args.path : undefined;
638
644
  const diff = typeof args.diff === "string" ? args.diff : undefined;
@@ -2597,6 +2603,7 @@ export class AgentSession {
2597
2603
  * Used by executeBash and by extensions that handle bash execution themselves.
2598
2604
  */
2599
2605
  recordBashResult(command: string, result: BashResult, options?: { excludeFromContext?: boolean }): void {
2606
+ const meta = outputMeta().truncationFromSummary(result, { direction: "tail" }).get();
2600
2607
  const bashMessage: BashExecutionMessage = {
2601
2608
  role: "bashExecution",
2602
2609
  command,
@@ -2604,7 +2611,7 @@ export class AgentSession {
2604
2611
  exitCode: result.exitCode,
2605
2612
  cancelled: result.cancelled,
2606
2613
  truncated: result.truncated,
2607
- fullOutputPath: result.fullOutputPath,
2614
+ meta,
2608
2615
  timestamp: Date.now(),
2609
2616
  excludeFromContext: options?.excludeFromContext,
2610
2617
  };
@@ -2701,6 +2708,7 @@ export class AgentSession {
2701
2708
  * Record a Python execution result in session history.
2702
2709
  */
2703
2710
  recordPythonResult(code: string, result: PythonResult, options?: { excludeFromContext?: boolean }): void {
2711
+ const meta = outputMeta().truncationFromSummary(result, { direction: "tail" }).get();
2704
2712
  const pythonMessage: PythonExecutionMessage = {
2705
2713
  role: "pythonExecution",
2706
2714
  code,
@@ -2708,7 +2716,7 @@ export class AgentSession {
2708
2716
  exitCode: result.exitCode,
2709
2717
  cancelled: result.cancelled,
2710
2718
  truncated: result.truncated,
2711
- fullOutputPath: result.fullOutputPath,
2719
+ meta,
2712
2720
  timestamp: Date.now(),
2713
2721
  excludeFromContext: options?.excludeFromContext,
2714
2722
  };
@@ -2,9 +2,9 @@ import { Database } from "bun:sqlite";
2
2
  import { chmodSync, existsSync, mkdirSync } from "node:fs";
3
3
  import { dirname } from "node:path";
4
4
  import { logger } from "@oh-my-pi/pi-utils";
5
- import { getAgentDbPath } from "../config";
5
+ import { getAgentDbPath } from "$c/config";
6
+ import type { Settings } from "$c/config/settings-manager";
6
7
  import type { AuthCredential } from "./auth-storage";
7
- import type { Settings } from "./settings-manager";
8
8
 
9
9
  /** Prepared SQLite statement type from bun:sqlite */
10
10
  type Statement = ReturnType<Database["prepare"]>;
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Session-scoped artifact storage for truncated tool outputs.
3
+ *
4
+ * Artifacts are stored in a directory alongside the session file,
5
+ * accessible via artifact:// URLs or the $ARTIFACTS environment variable.
6
+ */
7
+
8
+ import { mkdir, readdir } from "node:fs/promises";
9
+ import { join } from "node:path";
10
+
11
+ /**
12
+ * Manages artifact storage for a session.
13
+ *
14
+ * Artifacts are stored with sequential IDs in the session's artifact directory.
15
+ * The directory is created lazily on first write.
16
+ */
17
+ export class ArtifactManager {
18
+ #nextId = 0;
19
+ readonly #dir: string;
20
+ #dirCreated = false;
21
+
22
+ /**
23
+ * @param sessionFile Path to the session .jsonl file
24
+ */
25
+ constructor(sessionFile: string) {
26
+ // Artifact directory is session file path without .jsonl extension
27
+ this.#dir = sessionFile.slice(0, -6);
28
+ }
29
+
30
+ /**
31
+ * Artifact directory path.
32
+ * Directory may not exist until first artifact is saved.
33
+ */
34
+ get dir(): string {
35
+ return this.#dir;
36
+ }
37
+
38
+ async #ensureDir(): Promise<void> {
39
+ if (!this.#dirCreated) {
40
+ await mkdir(this.#dir, { recursive: true });
41
+ this.#dirCreated = true;
42
+ }
43
+ }
44
+
45
+ /**
46
+ * Atomically allocate next artifact ID.
47
+ * IDs are sequential within the session.
48
+ */
49
+ allocateId(): number {
50
+ return this.#nextId++;
51
+ }
52
+
53
+ /**
54
+ * Allocate a new artifact path and ID without writing content.
55
+ *
56
+ * @param toolType Tool name for file extension (e.g., "bash", "fetch")
57
+ */
58
+ async allocatePath(toolType: string): Promise<{ id: string; path: string }> {
59
+ await this.#ensureDir();
60
+ const id = String(this.allocateId());
61
+ const filename = `${id}.${toolType}.txt`;
62
+ return { id, path: join(this.#dir, filename) };
63
+ }
64
+
65
+ /**
66
+ * Save content as an artifact and return the artifact ID.
67
+ *
68
+ * @param content Full content to save
69
+ * @param toolType Tool name for file extension (e.g., "bash", "fetch")
70
+ * @returns Artifact ID (numeric string)
71
+ */
72
+ async save(content: string, toolType: string): Promise<string> {
73
+ const { id, path } = await this.allocatePath(toolType);
74
+ await Bun.write(path, content);
75
+ return id;
76
+ }
77
+
78
+ /**
79
+ * Check if an artifact exists.
80
+ * @param id Artifact ID (numeric string)
81
+ */
82
+ async exists(id: string): Promise<boolean> {
83
+ const files = await this.listFiles();
84
+ return files.some((f) => f.startsWith(`${id}.`));
85
+ }
86
+
87
+ /**
88
+ * List all artifact files in the directory.
89
+ * Returns empty array if directory doesn't exist.
90
+ */
91
+ async listFiles(): Promise<string[]> {
92
+ try {
93
+ return await readdir(this.#dir);
94
+ } catch {
95
+ return [];
96
+ }
97
+ }
98
+
99
+ /**
100
+ * Get the full path to an artifact file.
101
+ * Returns null if artifact doesn't exist.
102
+ *
103
+ * @param id Artifact ID (numeric string)
104
+ */
105
+ async getPath(id: string): Promise<string | null> {
106
+ const files = await this.listFiles();
107
+ const match = files.find((f) => f.startsWith(`${id}.`));
108
+ return match ? join(this.#dir, match) : null;
109
+ }
110
+ }
@@ -33,7 +33,7 @@ import {
33
33
  zaiUsageProvider,
34
34
  } from "@oh-my-pi/pi-ai";
35
35
  import { logger } from "@oh-my-pi/pi-utils";
36
- import { getAgentDbPath, getAuthPath } from "../config";
36
+ import { getAgentDbPath, getAuthPath } from "$c/config";
37
37
  import { AgentStorage } from "./agent-storage";
38
38
  import { migrateJsonStorage } from "./storage-migration";
39
39
 
@@ -8,16 +8,16 @@
8
8
  import type { AgentMessage } from "@oh-my-pi/pi-agent-core";
9
9
  import type { Model } from "@oh-my-pi/pi-ai";
10
10
  import { completeSimple } from "@oh-my-pi/pi-ai";
11
- import branchSummaryPrompt from "../../prompts/compaction/branch-summary.md" with { type: "text" };
12
- import branchSummaryPreamble from "../../prompts/compaction/branch-summary-preamble.md" with { type: "text" };
11
+ import { renderPromptTemplate } from "$c/config/prompt-templates";
12
+ import branchSummaryPrompt from "$c/prompts/compaction/branch-summary.md" with { type: "text" };
13
+ import branchSummaryPreamble from "$c/prompts/compaction/branch-summary-preamble.md" with { type: "text" };
13
14
  import {
14
15
  convertToLlm,
15
16
  createBranchSummaryMessage,
16
17
  createCompactionSummaryMessage,
17
18
  createCustomMessage,
18
- } from "../messages";
19
- import { renderPromptTemplate } from "../prompt-templates";
20
- import type { ReadonlySessionManager, SessionEntry } from "../session-manager";
19
+ } from "$c/session/messages";
20
+ import type { ReadonlySessionManager, SessionEntry } from "$c/session/session-manager";
21
21
  import { estimateTokens } from "./compaction";
22
22
  import {
23
23
  computeFileLists,
@@ -8,12 +8,12 @@
8
8
  import type { AgentMessage } from "@oh-my-pi/pi-agent-core";
9
9
  import type { AssistantMessage, Model, Usage } from "@oh-my-pi/pi-ai";
10
10
  import { completeSimple } from "@oh-my-pi/pi-ai";
11
- import compactionSummaryPrompt from "../../prompts/compaction/compaction-summary.md" with { type: "text" };
12
- import compactionTurnPrefixPrompt from "../../prompts/compaction/compaction-turn-prefix.md" with { type: "text" };
13
- import compactionUpdateSummaryPrompt from "../../prompts/compaction/compaction-update-summary.md" with { type: "text" };
14
- import { convertToLlm, createBranchSummaryMessage, createCustomMessage } from "../messages";
15
- import { renderPromptTemplate } from "../prompt-templates";
16
- import type { CompactionEntry, SessionEntry } from "../session-manager";
11
+ import { renderPromptTemplate } from "$c/config/prompt-templates";
12
+ import compactionSummaryPrompt from "$c/prompts/compaction/compaction-summary.md" with { type: "text" };
13
+ import compactionTurnPrefixPrompt from "$c/prompts/compaction/compaction-turn-prefix.md" with { type: "text" };
14
+ import compactionUpdateSummaryPrompt from "$c/prompts/compaction/compaction-update-summary.md" with { type: "text" };
15
+ import { convertToLlm, createBranchSummaryMessage, createCustomMessage } from "$c/session/messages";
16
+ import type { CompactionEntry, SessionEntry } from "$c/session/session-manager";
17
17
  import {
18
18
  computeFileLists,
19
19
  createFileOps,
@@ -4,9 +4,9 @@
4
4
 
5
5
  import type { AgentMessage } from "@oh-my-pi/pi-agent-core";
6
6
  import type { Message } from "@oh-my-pi/pi-ai";
7
- import fileOperationsTemplate from "../../prompts/system/file-operations.md" with { type: "text" };
8
- import summarizationSystemPrompt from "../../prompts/system/summarization-system.md" with { type: "text" };
9
- import { renderPromptTemplate } from "../prompt-templates";
7
+ import { renderPromptTemplate } from "$c/config/prompt-templates";
8
+ import fileOperationsTemplate from "$c/prompts/system/file-operations.md" with { type: "text" };
9
+ import summarizationSystemPrompt from "$c/prompts/system/summarization-system.md" with { type: "text" };
10
10
 
11
11
  // ============================================================================
12
12
  // File Operation Tracking
@@ -2,7 +2,7 @@ import { Database } from "bun:sqlite";
2
2
  import { mkdirSync } from "node:fs";
3
3
  import { dirname, join } from "node:path";
4
4
  import { logger } from "@oh-my-pi/pi-utils";
5
- import { getAgentDir } from "../config";
5
+ import { getAgentDir } from "$c/config";
6
6
 
7
7
  export interface HistoryEntry {
8
8
  id: number;
@@ -7,6 +7,8 @@
7
7
 
8
8
  import type { AgentMessage } from "@oh-my-pi/pi-agent-core";
9
9
  import type { ImageContent, Message, TextContent } from "@oh-my-pi/pi-ai";
10
+ import type { OutputMeta } from "$c/tools/output-meta";
11
+ import { formatOutputNotice } from "$c/tools/output-meta";
10
12
 
11
13
  export const COMPACTION_SUMMARY_PREFIX = `The conversation history before this point was compacted into the following summary:
12
14
 
@@ -33,7 +35,7 @@ export interface BashExecutionMessage {
33
35
  exitCode: number | undefined;
34
36
  cancelled: boolean;
35
37
  truncated: boolean;
36
- fullOutputPath?: string;
38
+ meta?: OutputMeta;
37
39
  timestamp: number;
38
40
  /** If true, this message is excluded from LLM context (!! prefix) */
39
41
  excludeFromContext?: boolean;
@@ -50,7 +52,7 @@ export interface PythonExecutionMessage {
50
52
  exitCode: number | undefined;
51
53
  cancelled: boolean;
52
54
  truncated: boolean;
53
- fullOutputPath?: string;
55
+ meta?: OutputMeta;
54
56
  timestamp: number;
55
57
  /** If true, this message is excluded from LLM context ($$ prefix) */
56
58
  excludeFromContext?: boolean;
@@ -136,9 +138,7 @@ export function bashExecutionToText(msg: BashExecutionMessage): string {
136
138
  } else if (msg.exitCode !== null && msg.exitCode !== undefined && msg.exitCode !== 0) {
137
139
  text += `\n\nCommand exited with code ${msg.exitCode}`;
138
140
  }
139
- if (msg.truncated && msg.fullOutputPath) {
140
- text += `\n\n[Output truncated. Full output: ${msg.fullOutputPath}]`;
141
- }
141
+ text += formatOutputNotice(msg.meta);
142
142
  return text;
143
143
  }
144
144
 
@@ -157,9 +157,7 @@ export function pythonExecutionToText(msg: PythonExecutionMessage): string {
157
157
  } else if (msg.exitCode !== null && msg.exitCode !== undefined && msg.exitCode !== 0) {
158
158
  text += `\n\nExecution failed with code ${msg.exitCode}`;
159
159
  }
160
- if (msg.truncated && msg.fullOutputPath) {
161
- text += `\n\n[Output truncated. Full output: ${msg.fullOutputPath}]`;
162
- }
160
+ text += formatOutputNotice(msg.meta);
163
161
  return text;
164
162
  }
165
163
 
@@ -3,8 +3,8 @@ import type { AgentMessage } from "@oh-my-pi/pi-agent-core";
3
3
  import type { ImageContent, Message, TextContent, Usage } from "@oh-my-pi/pi-ai";
4
4
  import { logger } from "@oh-my-pi/pi-utils";
5
5
  import { nanoid } from "nanoid";
6
- import { getAgentDir as getDefaultAgentDir } from "../config";
7
- import { resizeImage } from "../utils/image-resize";
6
+ import { getAgentDir as getDefaultAgentDir } from "$c/config";
7
+ import { resizeImage } from "$c/utils/image-resize";
8
8
  import {
9
9
  type BashExecutionMessage,
10
10
  type CustomMessage,
@@ -5,10 +5,10 @@
5
5
  */
6
6
 
7
7
  import { logger } from "@oh-my-pi/pi-utils";
8
- import { getAgentDbPath } from "../config";
8
+ import { getAgentDbPath } from "$c/config";
9
+ import type { Settings } from "$c/config/settings-manager";
9
10
  import { AgentStorage } from "./agent-storage";
10
11
  import type { AuthCredential, AuthCredentialEntry, AuthStorageData } from "./auth-storage";
11
- import type { Settings } from "./settings-manager";
12
12
 
13
13
  /** Paths configuration for the storage migration process. */
14
14
  type MigrationPaths = {
@@ -0,0 +1,177 @@
1
+ import { sanitizeText } from "@oh-my-pi/pi-utils";
2
+ import { DEFAULT_MAX_BYTES } from "$c/tools/truncate";
3
+
4
+ export interface OutputSummary {
5
+ output: string;
6
+ truncated: boolean;
7
+ totalLines: number;
8
+ totalBytes: number;
9
+ outputLines: number;
10
+ outputBytes: number;
11
+ /** Artifact ID for internal URL access (artifact://<id>) when truncated */
12
+ artifactId?: string;
13
+ }
14
+
15
+ export interface OutputSinkOptions {
16
+ artifactPath?: string;
17
+ artifactId?: string;
18
+ spillThreshold?: number;
19
+ onChunk?: (chunk: string) => void;
20
+ }
21
+
22
+ function countNewlines(text: string): number {
23
+ let count = 0;
24
+ for (let i = 0; i < text.length; i++) {
25
+ if (text.charCodeAt(i) === 10) count += 1;
26
+ }
27
+ return count;
28
+ }
29
+
30
+ function countLines(text: string): number {
31
+ if (text.length === 0) return 0;
32
+ return countNewlines(text) + 1;
33
+ }
34
+
35
+ function truncateStringToBytesFromEnd(text: string, maxBytes: number): { text: string; bytes: number } {
36
+ const buf = Buffer.from(text, "utf-8");
37
+ if (buf.length <= maxBytes) {
38
+ return { text, bytes: buf.length };
39
+ }
40
+
41
+ let start = buf.length - maxBytes;
42
+ while (start < buf.length && (buf[start] & 0xc0) === 0x80) {
43
+ start++;
44
+ }
45
+
46
+ const sliced = buf.subarray(start).toString("utf-8");
47
+ return { text: sliced, bytes: Buffer.byteLength(sliced, "utf-8") };
48
+ }
49
+
50
+ /**
51
+ * Line-buffered output sink with file spill support.
52
+ *
53
+ * Uses a single string buffer with line position tracking.
54
+ * When memory limit exceeded, spills ~half to file in one batch operation.
55
+ */
56
+ export class OutputSink {
57
+ #buffer = "";
58
+ #bufferBytes = 0;
59
+ #totalLines = 0;
60
+ #totalBytes = 0;
61
+ #sawData = false;
62
+ #truncated = false;
63
+ #file?: {
64
+ path: string;
65
+ artifactId?: string;
66
+ sink: Bun.FileSink;
67
+ };
68
+ readonly #artifactPath?: string;
69
+ readonly #artifactId?: string;
70
+ readonly #spillThreshold: number;
71
+ readonly #onChunk?: (chunk: string) => void;
72
+
73
+ constructor(options?: OutputSinkOptions) {
74
+ const { artifactPath, artifactId, spillThreshold = DEFAULT_MAX_BYTES, onChunk } = options ?? {};
75
+
76
+ this.#artifactPath = artifactPath;
77
+ this.#artifactId = artifactId;
78
+ this.#spillThreshold = spillThreshold;
79
+ this.#onChunk = onChunk;
80
+ }
81
+
82
+ async #pushSanitized(data: string): Promise<void> {
83
+ this.#onChunk?.(data);
84
+
85
+ const dataBytes = Buffer.byteLength(data, "utf-8");
86
+ this.#totalBytes += dataBytes;
87
+ if (data.length > 0) {
88
+ this.#sawData = true;
89
+ this.#totalLines += countNewlines(data);
90
+ }
91
+
92
+ const bufferOverflow = this.#bufferBytes + dataBytes > this.#spillThreshold;
93
+ const overflow = this.#file || bufferOverflow;
94
+ const sink = overflow ? await this.#fileSink() : null;
95
+
96
+ this.#buffer += data;
97
+ this.#bufferBytes += dataBytes;
98
+ await sink?.write(data);
99
+
100
+ if (bufferOverflow) {
101
+ this.#truncated = true;
102
+ const trimmed = truncateStringToBytesFromEnd(this.#buffer, this.#spillThreshold);
103
+ this.#buffer = trimmed.text;
104
+ this.#bufferBytes = trimmed.bytes;
105
+ }
106
+ if (this.#file) {
107
+ this.#truncated = true;
108
+ }
109
+ }
110
+
111
+ async #fileSink(): Promise<Bun.FileSink | null> {
112
+ if (!this.#artifactPath) return null;
113
+ if (!this.#file) {
114
+ try {
115
+ this.#file = {
116
+ path: this.#artifactPath,
117
+ artifactId: this.#artifactId,
118
+ sink: Bun.file(this.#artifactPath).writer(),
119
+ };
120
+ await this.#file.sink.write(this.#buffer);
121
+ } catch {
122
+ try {
123
+ await this.#file?.sink?.end();
124
+ } catch {}
125
+ this.#file = undefined;
126
+ return null;
127
+ }
128
+ }
129
+ return this.#file.sink;
130
+ }
131
+
132
+ async push(chunk: string): Promise<void> {
133
+ chunk = sanitizeText(chunk);
134
+ await this.#pushSanitized(chunk);
135
+ }
136
+
137
+ createInput(): WritableStream<Uint8Array | string> {
138
+ const dec = new TextDecoder("utf-8", { ignoreBOM: true });
139
+ const finalize = async () => {
140
+ await this.push(dec.decode());
141
+ };
142
+
143
+ return new WritableStream<Uint8Array | string>({
144
+ write: async (chunk) => {
145
+ if (typeof chunk === "string") {
146
+ await this.push(chunk);
147
+ } else {
148
+ await this.push(dec.decode(chunk, { stream: true }));
149
+ }
150
+ },
151
+ close: finalize,
152
+ abort: finalize,
153
+ });
154
+ }
155
+
156
+ async dump(notice?: string): Promise<OutputSummary> {
157
+ const noticeLine = notice ? `[${notice}]\n` : "";
158
+ const outputLines = countLines(this.#buffer);
159
+ const outputBytes = this.#bufferBytes;
160
+ const totalLines = this.#sawData ? this.#totalLines + 1 : 0;
161
+ const totalBytes = this.#totalBytes;
162
+
163
+ if (this.#file) {
164
+ await this.#file.sink.end();
165
+ }
166
+
167
+ return {
168
+ output: `${noticeLine}${this.#buffer}`,
169
+ truncated: this.#truncated,
170
+ totalLines,
171
+ totalBytes,
172
+ outputLines,
173
+ outputBytes,
174
+ artifactId: this.#file?.artifactId,
175
+ };
176
+ }
177
+ }
@@ -3,7 +3,7 @@ import { homedir } from "node:os";
3
3
  import { join } from "node:path";
4
4
  import { logger } from "@oh-my-pi/pi-utils";
5
5
  import { $ } from "bun";
6
- import { CONFIG_DIR_NAME } from "../../config";
6
+ import { CONFIG_DIR_NAME } from "$c/config";
7
7
 
8
8
  export interface SSHConnectionTarget {
9
9
  name: string;
@@ -1,5 +1,5 @@
1
1
  import { cspawn, logger, ptree } from "@oh-my-pi/pi-utils";
2
- import { OutputSink } from "../streaming-output";
2
+ import { OutputSink } from "$c/session/streaming-output";
3
3
  import { buildRemoteCommand, ensureConnection, ensureHostInfo, type SSHConnectionTarget } from "./connection-manager";
4
4
  import { hasSshfs, mountRemote } from "./sshfs-mount";
5
5
 
@@ -14,6 +14,9 @@ export interface SSHExecutorOptions {
14
14
  remotePath?: string;
15
15
  /** Wrap commands in a POSIX shell for compat mode */
16
16
  compatEnabled?: boolean;
17
+ /** Artifact path/id for full output storage */
18
+ artifactPath?: string;
19
+ artifactId?: string;
17
20
  }
18
21
 
19
22
  export interface SSHResult {
@@ -25,8 +28,16 @@ export interface SSHResult {
25
28
  cancelled: boolean;
26
29
  /** Whether the output was truncated */
27
30
  truncated: boolean;
28
- /** Path to temp file containing full output (if output exceeded truncation threshold) */
29
- fullOutputPath?: string;
31
+ /** Total number of lines in the output stream */
32
+ totalLines: number;
33
+ /** Total number of bytes in the output stream */
34
+ totalBytes: number;
35
+ /** Number of lines included in the output text */
36
+ outputLines: number;
37
+ /** Number of bytes included in the output text */
38
+ outputBytes: number;
39
+ /** Artifact ID if full output was saved to artifact storage */
40
+ artifactId?: string;
30
41
  }
31
42
 
32
43
  function quoteForCompatShell(command: string): string {
@@ -70,7 +81,11 @@ export async function executeSSH(
70
81
  timeout: options?.timeout,
71
82
  });
72
83
 
73
- const sink = new OutputSink({ onChunk: options?.onChunk });
84
+ const sink = new OutputSink({
85
+ onChunk: options?.onChunk,
86
+ artifactPath: options?.artifactPath,
87
+ artifactId: options?.artifactId,
88
+ });
74
89
 
75
90
  await Promise.allSettled([child.stdout.pipeTo(sink.createInput()), child.stderr.pipeTo(sink.createInput())]).catch(
76
91
  () => {},
@@ -3,7 +3,7 @@ import { homedir } from "node:os";
3
3
  import { join } from "node:path";
4
4
  import { logger } from "@oh-my-pi/pi-utils";
5
5
  import { $ } from "bun";
6
- import { CONFIG_DIR_NAME } from "../../config";
6
+ import { CONFIG_DIR_NAME } from "$c/config";
7
7
  import { getControlDir, getControlPathTemplate, type SSHConnectionTarget } from "./connection-manager";
8
8
 
9
9
  const REMOTE_DIR = join(homedir(), CONFIG_DIR_NAME, "remote");