@oh-my-pi/pi-coding-agent 8.0.20 → 8.2.0

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 (421) hide show
  1. package/CHANGELOG.md +125 -0
  2. package/docs/session.md +111 -46
  3. package/examples/custom-tools/hello/index.ts +1 -1
  4. package/examples/custom-tools/todo/index.ts +3 -4
  5. package/examples/extensions/api-demo.ts +0 -1
  6. package/examples/extensions/chalk-logger.ts +2 -3
  7. package/examples/extensions/hello.ts +0 -1
  8. package/examples/extensions/pirate.ts +0 -1
  9. package/examples/extensions/plan-mode.ts +15 -16
  10. package/examples/extensions/todo.ts +3 -4
  11. package/examples/extensions/tools.ts +1 -2
  12. package/examples/extensions/with-deps/index.ts +0 -1
  13. package/examples/hooks/auto-commit-on-exit.ts +1 -2
  14. package/examples/hooks/confirm-destructive.ts +0 -1
  15. package/examples/hooks/custom-compaction.ts +1 -2
  16. package/examples/hooks/dirty-repo-guard.ts +0 -1
  17. package/examples/hooks/file-trigger.ts +3 -4
  18. package/examples/hooks/git-checkpoint.ts +0 -1
  19. package/examples/hooks/handoff.ts +3 -4
  20. package/examples/hooks/permission-gate.ts +1 -2
  21. package/examples/hooks/protected-paths.ts +1 -2
  22. package/examples/hooks/qna.ts +2 -3
  23. package/examples/hooks/snake.ts +4 -5
  24. package/examples/hooks/status-line.ts +0 -1
  25. package/examples/sdk/01-minimal.ts +2 -3
  26. package/examples/sdk/02-custom-model.ts +2 -3
  27. package/examples/sdk/03-custom-prompt.ts +3 -4
  28. package/examples/sdk/04-skills.ts +2 -3
  29. package/examples/sdk/06-extensions.ts +1 -2
  30. package/examples/sdk/06-hooks.ts +6 -7
  31. package/examples/sdk/07-context-files.ts +0 -1
  32. package/examples/sdk/08-prompt-templates.ts +0 -1
  33. package/examples/sdk/08-slash-commands.ts +0 -1
  34. package/examples/sdk/09-api-keys-and-oauth.ts +0 -1
  35. package/examples/sdk/10-settings.ts +0 -1
  36. package/examples/sdk/11-sessions.ts +0 -1
  37. package/package.json +54 -23
  38. package/scripts/format-prompts.ts +0 -1
  39. package/src/capability/context-file.ts +3 -4
  40. package/src/capability/extension-module.ts +3 -4
  41. package/src/capability/extension.ts +3 -4
  42. package/src/capability/fs.ts +20 -21
  43. package/src/capability/hook.ts +3 -4
  44. package/src/capability/index.ts +15 -16
  45. package/src/capability/instruction.ts +3 -4
  46. package/src/capability/mcp.ts +3 -4
  47. package/src/capability/prompt.ts +3 -4
  48. package/src/capability/rule.ts +3 -4
  49. package/src/capability/settings.ts +2 -3
  50. package/src/capability/skill.ts +3 -4
  51. package/src/capability/slash-command.ts +3 -4
  52. package/src/capability/ssh.ts +3 -4
  53. package/src/capability/system-prompt.ts +3 -4
  54. package/src/capability/tool.ts +3 -4
  55. package/src/cli/args.ts +5 -6
  56. package/src/cli/config-cli.ts +6 -7
  57. package/src/cli/file-processor.ts +19 -17
  58. package/src/cli/jupyter-cli.ts +105 -0
  59. package/src/cli/list-models.ts +10 -11
  60. package/src/cli/plugin-cli.ts +20 -25
  61. package/src/cli/session-picker.ts +2 -3
  62. package/src/cli/setup-cli.ts +2 -3
  63. package/src/cli/stats-cli.ts +2 -3
  64. package/src/cli/update-cli.ts +25 -22
  65. package/src/commit/agentic/agent.ts +307 -0
  66. package/src/commit/agentic/fallback.ts +96 -0
  67. package/src/commit/agentic/index.ts +351 -0
  68. package/src/commit/agentic/prompts/analyze-file.md +22 -0
  69. package/src/commit/agentic/prompts/session-user.md +26 -0
  70. package/src/commit/agentic/prompts/split-confirm.md +1 -0
  71. package/src/commit/agentic/prompts/system.md +40 -0
  72. package/src/commit/agentic/state.ts +69 -0
  73. package/src/commit/agentic/tools/analyze-file.ts +131 -0
  74. package/src/commit/agentic/tools/git-file-diff.ts +194 -0
  75. package/src/commit/agentic/tools/git-hunk.ts +50 -0
  76. package/src/commit/agentic/tools/git-overview.ts +84 -0
  77. package/src/commit/agentic/tools/index.ts +56 -0
  78. package/src/commit/agentic/tools/propose-changelog.ts +128 -0
  79. package/src/commit/agentic/tools/propose-commit.ts +154 -0
  80. package/src/commit/agentic/tools/recent-commits.ts +81 -0
  81. package/src/commit/agentic/tools/split-commit.ts +280 -0
  82. package/src/commit/agentic/topo-sort.ts +44 -0
  83. package/src/commit/agentic/trivial.ts +51 -0
  84. package/src/commit/agentic/validation.ts +200 -0
  85. package/src/commit/analysis/conventional.ts +165 -0
  86. package/src/commit/analysis/index.ts +4 -0
  87. package/src/commit/analysis/scope.ts +242 -0
  88. package/src/commit/analysis/summary.ts +112 -0
  89. package/src/commit/analysis/validation.ts +66 -0
  90. package/src/commit/changelog/detect.ts +36 -0
  91. package/src/commit/changelog/generate.ts +110 -0
  92. package/src/commit/changelog/index.ts +233 -0
  93. package/src/commit/changelog/parse.ts +44 -0
  94. package/src/commit/cli.ts +93 -0
  95. package/src/commit/git/diff.ts +148 -0
  96. package/src/commit/git/errors.ts +11 -0
  97. package/src/commit/git/index.ts +212 -0
  98. package/src/commit/git/operations.ts +53 -0
  99. package/src/commit/index.ts +5 -0
  100. package/src/commit/map-reduce/index.ts +63 -0
  101. package/src/commit/map-reduce/map-phase.ts +178 -0
  102. package/src/commit/map-reduce/reduce-phase.ts +145 -0
  103. package/src/commit/map-reduce/utils.ts +9 -0
  104. package/src/commit/message.ts +11 -0
  105. package/src/commit/model-selection.ts +80 -0
  106. package/src/commit/pipeline.ts +240 -0
  107. package/src/commit/prompts/analysis-system.md +155 -0
  108. package/src/commit/prompts/analysis-user.md +41 -0
  109. package/src/commit/prompts/changelog-system.md +56 -0
  110. package/src/commit/prompts/changelog-user.md +19 -0
  111. package/src/commit/prompts/file-observer-system.md +26 -0
  112. package/src/commit/prompts/file-observer-user.md +9 -0
  113. package/src/commit/prompts/reduce-system.md +60 -0
  114. package/src/commit/prompts/reduce-user.md +17 -0
  115. package/src/commit/prompts/summary-retry.md +4 -0
  116. package/src/commit/prompts/summary-system.md +52 -0
  117. package/src/commit/prompts/summary-user.md +13 -0
  118. package/src/commit/prompts/types-description.md +2 -0
  119. package/src/commit/types.ts +109 -0
  120. package/src/commit/utils/exclusions.ts +42 -0
  121. package/src/config/file-lock.ts +121 -0
  122. package/src/config/keybindings.ts +6 -8
  123. package/src/config/model-registry.ts +65 -38
  124. package/src/config/model-resolver.ts +18 -19
  125. package/src/config/prompt-templates.ts +11 -11
  126. package/src/config/settings-manager.ts +141 -50
  127. package/src/config.ts +64 -66
  128. package/src/cursor.ts +11 -9
  129. package/src/discovery/agents-md.ts +11 -12
  130. package/src/discovery/builtin.ts +68 -73
  131. package/src/discovery/claude.ts +41 -42
  132. package/src/discovery/cline.ts +11 -12
  133. package/src/discovery/codex.ts +52 -53
  134. package/src/discovery/cursor.ts +9 -10
  135. package/src/discovery/gemini.ts +17 -22
  136. package/src/discovery/github.ts +13 -14
  137. package/src/discovery/helpers.ts +35 -34
  138. package/src/discovery/index.ts +22 -24
  139. package/src/discovery/mcp-json.ts +8 -9
  140. package/src/discovery/ssh.ts +8 -9
  141. package/src/discovery/vscode.ts +4 -5
  142. package/src/discovery/windsurf.ts +6 -7
  143. package/src/exa/company.ts +1 -2
  144. package/src/exa/index.ts +2 -3
  145. package/src/exa/linkedin.ts +1 -2
  146. package/src/exa/mcp-client.ts +14 -16
  147. package/src/exa/render.ts +10 -11
  148. package/src/exa/researcher.ts +1 -2
  149. package/src/exa/search.ts +1 -2
  150. package/src/exa/types.ts +0 -1
  151. package/src/exa/websets.ts +1 -2
  152. package/src/exec/bash-executor.ts +3 -4
  153. package/src/exec/exec.ts +0 -1
  154. package/src/export/custom-share.ts +5 -6
  155. package/src/export/html/index.ts +24 -21
  156. package/src/export/ttsr.ts +2 -3
  157. package/src/extensibility/custom-commands/bundled/review/index.ts +7 -8
  158. package/src/extensibility/custom-commands/loader.ts +18 -15
  159. package/src/extensibility/custom-commands/types.ts +2 -3
  160. package/src/extensibility/custom-tools/loader.ts +11 -12
  161. package/src/extensibility/custom-tools/types.ts +7 -8
  162. package/src/extensibility/custom-tools/wrapper.ts +2 -3
  163. package/src/extensibility/extensions/loader.ts +76 -54
  164. package/src/extensibility/extensions/runner.ts +11 -12
  165. package/src/extensibility/extensions/types.ts +20 -27
  166. package/src/extensibility/extensions/wrapper.ts +3 -4
  167. package/src/extensibility/hooks/index.ts +1 -1
  168. package/src/extensibility/hooks/loader.ts +9 -10
  169. package/src/extensibility/hooks/runner.ts +7 -8
  170. package/src/extensibility/hooks/tool-wrapper.ts +0 -1
  171. package/src/extensibility/hooks/types.ts +11 -18
  172. package/src/extensibility/plugins/doctor.ts +3 -3
  173. package/src/extensibility/plugins/installer.ts +27 -27
  174. package/src/extensibility/plugins/loader.ts +59 -56
  175. package/src/extensibility/plugins/manager.ts +211 -171
  176. package/src/extensibility/plugins/parser.ts +1 -1
  177. package/src/extensibility/plugins/paths.ts +8 -8
  178. package/src/extensibility/skills.ts +63 -60
  179. package/src/extensibility/slash-commands.ts +10 -10
  180. package/src/index.ts +54 -54
  181. package/src/internal-urls/agent-protocol.ts +21 -11
  182. package/src/internal-urls/artifact-protocol.ts +17 -13
  183. package/src/internal-urls/router.ts +1 -2
  184. package/src/internal-urls/rule-protocol.ts +3 -4
  185. package/src/internal-urls/skill-protocol.ts +3 -4
  186. package/src/ipy/executor.ts +109 -9
  187. package/src/ipy/gateway-coordinator.ts +79 -90
  188. package/src/ipy/kernel.ts +32 -30
  189. package/src/ipy/modules.ts +13 -13
  190. package/src/lsp/client.ts +21 -10
  191. package/src/lsp/clients/biome-client.ts +1 -2
  192. package/src/lsp/clients/index.ts +3 -3
  193. package/src/lsp/clients/lsp-linter-client.ts +4 -5
  194. package/src/lsp/config.ts +15 -15
  195. package/src/lsp/edits.ts +4 -5
  196. package/src/lsp/index.ts +43 -44
  197. package/src/lsp/lspmux.ts +8 -8
  198. package/src/lsp/render.ts +99 -61
  199. package/src/lsp/utils.ts +3 -3
  200. package/src/main.ts +71 -37
  201. package/src/mcp/client.ts +2 -3
  202. package/src/mcp/config.ts +5 -6
  203. package/src/mcp/json-rpc.ts +0 -1
  204. package/src/mcp/loader.ts +6 -7
  205. package/src/mcp/manager.ts +17 -18
  206. package/src/mcp/tool-bridge.ts +4 -9
  207. package/src/mcp/tool-cache.ts +2 -3
  208. package/src/mcp/transports/http.ts +2 -4
  209. package/src/mcp/transports/stdio.ts +1 -2
  210. package/src/migrations.ts +63 -52
  211. package/src/modes/components/armin.ts +4 -5
  212. package/src/modes/components/assistant-message.ts +33 -5
  213. package/src/modes/components/bash-execution.ts +7 -8
  214. package/src/modes/components/bordered-loader.ts +3 -3
  215. package/src/modes/components/branch-summary-message.ts +3 -3
  216. package/src/modes/components/compaction-summary-message.ts +3 -3
  217. package/src/modes/components/countdown-timer.ts +0 -1
  218. package/src/modes/components/custom-message.ts +5 -5
  219. package/src/modes/components/diff.ts +1 -1
  220. package/src/modes/components/dynamic-border.ts +2 -2
  221. package/src/modes/components/extensions/extension-dashboard.ts +6 -7
  222. package/src/modes/components/extensions/extension-list.ts +2 -3
  223. package/src/modes/components/extensions/inspector-panel.ts +3 -4
  224. package/src/modes/components/extensions/state-manager.ts +25 -26
  225. package/src/modes/components/extensions/types.ts +1 -2
  226. package/src/modes/components/footer.ts +47 -43
  227. package/src/modes/components/history-search.ts +2 -2
  228. package/src/modes/components/hook-editor.ts +3 -4
  229. package/src/modes/components/hook-input.ts +2 -3
  230. package/src/modes/components/hook-message.ts +5 -5
  231. package/src/modes/components/hook-selector.ts +2 -3
  232. package/src/modes/components/keybinding-hints.ts +2 -3
  233. package/src/modes/components/login-dialog.ts +2 -2
  234. package/src/modes/components/model-selector.ts +12 -12
  235. package/src/modes/components/oauth-selector.ts +2 -2
  236. package/src/modes/components/plugin-settings.ts +20 -20
  237. package/src/modes/components/python-execution.ts +7 -8
  238. package/src/modes/components/queue-mode-selector.ts +3 -3
  239. package/src/modes/components/read-tool-group.ts +2 -2
  240. package/src/modes/components/session-selector.ts +4 -4
  241. package/src/modes/components/settings-defs.ts +77 -69
  242. package/src/modes/components/settings-selector.ts +16 -16
  243. package/src/modes/components/show-images-selector.ts +2 -2
  244. package/src/modes/components/status-line/segments.ts +4 -4
  245. package/src/modes/components/status-line/separators.ts +1 -1
  246. package/src/modes/components/status-line/types.ts +2 -2
  247. package/src/modes/components/status-line-segment-editor.ts +7 -8
  248. package/src/modes/components/status-line.ts +12 -12
  249. package/src/modes/components/theme-selector.ts +8 -7
  250. package/src/modes/components/thinking-selector.ts +4 -4
  251. package/src/modes/components/todo-display.ts +2 -2
  252. package/src/modes/components/todo-reminder.ts +4 -4
  253. package/src/modes/components/tool-execution.ts +16 -19
  254. package/src/modes/components/tree-selector.ts +12 -12
  255. package/src/modes/components/ttsr-notification.ts +5 -5
  256. package/src/modes/components/user-message-selector.ts +1 -1
  257. package/src/modes/components/user-message.ts +1 -1
  258. package/src/modes/components/visual-truncate.ts +0 -1
  259. package/src/modes/components/welcome.ts +4 -4
  260. package/src/modes/controllers/command-controller.ts +46 -47
  261. package/src/modes/controllers/event-controller.ts +16 -20
  262. package/src/modes/controllers/extension-ui-controller.ts +40 -46
  263. package/src/modes/controllers/input-controller.ts +17 -18
  264. package/src/modes/controllers/selector-controller.ts +103 -91
  265. package/src/modes/index.ts +3 -3
  266. package/src/modes/interactive-mode.ts +31 -31
  267. package/src/modes/print-mode.ts +12 -13
  268. package/src/modes/rpc/rpc-client.ts +7 -8
  269. package/src/modes/rpc/rpc-mode.ts +24 -28
  270. package/src/modes/rpc/rpc-types.ts +3 -4
  271. package/src/modes/theme/mermaid-cache.ts +89 -0
  272. package/src/modes/theme/theme.ts +130 -53
  273. package/src/modes/types.ts +10 -10
  274. package/src/modes/utils/ui-helpers.ts +17 -17
  275. package/src/patch/applicator.ts +18 -19
  276. package/src/patch/diff.ts +1 -2
  277. package/src/patch/fuzzy.ts +1 -2
  278. package/src/patch/index.ts +11 -18
  279. package/src/patch/normalize.ts +4 -4
  280. package/src/patch/normative.ts +1 -2
  281. package/src/patch/parser.ts +8 -9
  282. package/src/patch/shared.ts +43 -16
  283. package/src/prompts/tools/task.md +2 -0
  284. package/src/sdk.ts +100 -65
  285. package/src/session/agent-session.ts +84 -85
  286. package/src/session/agent-storage.ts +43 -39
  287. package/src/session/artifacts.ts +32 -10
  288. package/src/session/auth-storage.ts +50 -39
  289. package/src/session/compaction/branch-summarization.ts +7 -10
  290. package/src/session/compaction/compaction.ts +8 -19
  291. package/src/session/compaction/utils.ts +6 -9
  292. package/src/session/history-storage.ts +10 -10
  293. package/src/session/messages.ts +4 -5
  294. package/src/session/session-manager.ts +76 -65
  295. package/src/session/session-storage.ts +57 -69
  296. package/src/session/storage-migration.ts +14 -56
  297. package/src/session/streaming-output.ts +2 -2
  298. package/src/ssh/connection-manager.ts +43 -50
  299. package/src/ssh/ssh-executor.ts +2 -2
  300. package/src/ssh/sshfs-mount.ts +11 -18
  301. package/src/system-prompt.ts +28 -35
  302. package/src/task/agents.ts +45 -30
  303. package/src/task/commands.ts +6 -7
  304. package/src/task/discovery.ts +39 -76
  305. package/src/task/executor.ts +14 -15
  306. package/src/task/index.ts +40 -34
  307. package/src/task/output-manager.ts +93 -0
  308. package/src/task/parallel.ts +0 -1
  309. package/src/task/render.ts +24 -30
  310. package/src/task/subprocess-tool-registry.ts +1 -2
  311. package/src/task/worker-protocol.ts +3 -3
  312. package/src/task/worker.ts +33 -39
  313. package/src/task/worktree.ts +19 -19
  314. package/src/tools/ask.ts +41 -20
  315. package/src/tools/bash-interceptor.ts +1 -5
  316. package/src/tools/bash.ts +91 -97
  317. package/src/tools/calculator.ts +49 -47
  318. package/src/tools/complete.ts +4 -5
  319. package/src/tools/context.ts +2 -2
  320. package/src/tools/fetch.ts +84 -124
  321. package/src/tools/find.ts +94 -98
  322. package/src/tools/gemini-image.ts +14 -14
  323. package/src/tools/grep.ts +100 -116
  324. package/src/tools/index.ts +80 -55
  325. package/src/tools/list-limit.ts +1 -1
  326. package/src/tools/ls.ts +44 -70
  327. package/src/tools/notebook.ts +51 -67
  328. package/src/tools/output-meta.ts +3 -4
  329. package/src/tools/output-utils.ts +2 -2
  330. package/src/tools/path-utils.ts +5 -5
  331. package/src/tools/python.ts +104 -217
  332. package/src/tools/read.ts +92 -33
  333. package/src/tools/render-utils.ts +8 -23
  334. package/src/tools/renderers.ts +6 -7
  335. package/src/tools/review.ts +8 -11
  336. package/src/tools/ssh.ts +69 -49
  337. package/src/tools/todo-write.ts +37 -25
  338. package/src/tools/tool-errors.ts +3 -3
  339. package/src/tools/tool-result.ts +3 -8
  340. package/src/tools/write.ts +99 -75
  341. package/src/tui/code-cell.ts +109 -0
  342. package/src/tui/file-list.ts +47 -0
  343. package/src/tui/index.ts +11 -0
  344. package/src/tui/output-block.ts +72 -0
  345. package/src/tui/status-line.ts +39 -0
  346. package/src/tui/tree-list.ts +55 -0
  347. package/src/tui/types.ts +16 -0
  348. package/src/tui/utils.ts +48 -0
  349. package/src/utils/changelog.ts +9 -10
  350. package/src/utils/clipboard.ts +11 -11
  351. package/src/utils/file-mentions.ts +4 -10
  352. package/src/utils/frontmatter.ts +6 -3
  353. package/src/utils/fuzzy.ts +2 -2
  354. package/src/utils/image-convert.ts +1 -1
  355. package/src/utils/image-resize.ts +1 -1
  356. package/src/utils/mime.ts +2 -2
  357. package/src/utils/shell-snapshot.ts +11 -13
  358. package/src/utils/shell.ts +4 -5
  359. package/src/utils/title-generator.ts +8 -9
  360. package/src/utils/tools-manager.ts +23 -23
  361. package/src/vendor/photon/index.js +1099 -1059
  362. package/src/vendor/photon/photon_rs_bg.wasm +0 -0
  363. package/src/web/scrapers/artifacthub.ts +1 -1
  364. package/src/web/scrapers/arxiv.ts +2 -2
  365. package/src/web/scrapers/bluesky.ts +2 -2
  366. package/src/web/scrapers/cheatsh.ts +1 -1
  367. package/src/web/scrapers/chocolatey.ts +2 -2
  368. package/src/web/scrapers/choosealicense.ts +5 -5
  369. package/src/web/scrapers/cisa-kev.ts +1 -1
  370. package/src/web/scrapers/crossref.ts +2 -2
  371. package/src/web/scrapers/devto.ts +3 -3
  372. package/src/web/scrapers/discogs.ts +3 -4
  373. package/src/web/scrapers/discourse.ts +1 -1
  374. package/src/web/scrapers/dockerhub.ts +1 -1
  375. package/src/web/scrapers/fdroid.ts +2 -2
  376. package/src/web/scrapers/firefox-addons.ts +3 -3
  377. package/src/web/scrapers/flathub.ts +1 -1
  378. package/src/web/scrapers/github.ts +3 -3
  379. package/src/web/scrapers/gitlab.ts +4 -4
  380. package/src/web/scrapers/hackernews.ts +2 -2
  381. package/src/web/scrapers/huggingface.ts +1 -1
  382. package/src/web/scrapers/iacr.ts +2 -2
  383. package/src/web/scrapers/index.ts +0 -1
  384. package/src/web/scrapers/jetbrains-marketplace.ts +1 -1
  385. package/src/web/scrapers/lemmy.ts +2 -2
  386. package/src/web/scrapers/maven.ts +2 -2
  387. package/src/web/scrapers/mdn.ts +2 -4
  388. package/src/web/scrapers/metacpan.ts +2 -2
  389. package/src/web/scrapers/musicbrainz.ts +1 -2
  390. package/src/web/scrapers/npm.ts +1 -1
  391. package/src/web/scrapers/nuget.ts +2 -2
  392. package/src/web/scrapers/nvd.ts +3 -3
  393. package/src/web/scrapers/ollama.ts +7 -9
  394. package/src/web/scrapers/opencorporates.ts +2 -2
  395. package/src/web/scrapers/openlibrary.ts +6 -6
  396. package/src/web/scrapers/orcid.ts +0 -1
  397. package/src/web/scrapers/osv.ts +2 -2
  398. package/src/web/scrapers/packagist.ts +1 -1
  399. package/src/web/scrapers/pubmed.ts +1 -2
  400. package/src/web/scrapers/rawg.ts +2 -2
  401. package/src/web/scrapers/readthedocs.ts +1 -2
  402. package/src/web/scrapers/repology.ts +2 -2
  403. package/src/web/scrapers/rfc.ts +1 -1
  404. package/src/web/scrapers/searchcode.ts +2 -2
  405. package/src/web/scrapers/semantic-scholar.ts +1 -1
  406. package/src/web/scrapers/snapcraft.ts +2 -2
  407. package/src/web/scrapers/sourcegraph.ts +1 -1
  408. package/src/web/scrapers/spdx.ts +3 -3
  409. package/src/web/scrapers/spotify.ts +0 -1
  410. package/src/web/scrapers/twitter.ts +1 -1
  411. package/src/web/scrapers/types.ts +1 -2
  412. package/src/web/scrapers/utils.ts +5 -5
  413. package/src/web/scrapers/wikidata.ts +3 -3
  414. package/src/web/scrapers/youtube.ts +9 -14
  415. package/src/web/search/auth.ts +5 -10
  416. package/src/web/search/index.ts +11 -21
  417. package/src/web/search/providers/anthropic.ts +3 -9
  418. package/src/web/search/providers/exa.ts +6 -10
  419. package/src/web/search/providers/perplexity.ts +5 -5
  420. package/src/web/search/render.ts +129 -175
  421. package/tsconfig.json +0 -42
@@ -6,12 +6,11 @@
6
6
  *
7
7
  * Priority: 5 (low, as this is a fallback after tool-specific providers)
8
8
  */
9
-
10
- import { join } from "node:path";
11
- import { readFile } from "@oh-my-pi/pi-coding-agent/capability/fs";
12
- import { registerProvider } from "@oh-my-pi/pi-coding-agent/capability/index";
13
- import { type MCPServer, mcpCapability } from "@oh-my-pi/pi-coding-agent/capability/mcp";
14
- import type { LoadContext, LoadResult, SourceMeta } from "@oh-my-pi/pi-coding-agent/capability/types";
9
+ import * as path from "node:path";
10
+ import { registerProvider } from "../capability";
11
+ import { readFile } from "../capability/fs";
12
+ import { type MCPServer, mcpCapability } from "../capability/mcp";
13
+ import type { LoadContext, LoadResult, SourceMeta } from "../capability/types";
15
14
  import { createSourceMeta, expandEnvVarsDeep, parseJSON } from "./helpers";
16
15
 
17
16
  const PROVIDER_ID = "mcp-json";
@@ -102,11 +101,11 @@ async function loadMCPJsonFile(
102
101
  async function load(ctx: LoadContext): Promise<LoadResult<MCPServer>> {
103
102
  const filenames = ["mcp.json", ".mcp.json"];
104
103
  const results = await Promise.all(
105
- filenames.map((filename) => loadMCPJsonFile(ctx, join(ctx.cwd, filename), "project")),
104
+ filenames.map(filename => loadMCPJsonFile(ctx, path.join(ctx.cwd, filename), "project")),
106
105
  );
107
106
 
108
- const allItems = results.flatMap((r) => r.items);
109
- const allWarnings = results.flatMap((r) => r.warnings ?? []);
107
+ const allItems = results.flatMap(r => r.items);
108
+ const allWarnings = results.flatMap(r => r.warnings ?? []);
110
109
 
111
110
  return {
112
111
  items: allItems,
@@ -4,12 +4,11 @@
4
4
  * Discovers SSH hosts from ssh.json or .ssh.json in the project root.
5
5
  * Priority: 5 (low, project-level only)
6
6
  */
7
-
8
- import { join } from "node:path";
9
- import { readFile } from "@oh-my-pi/pi-coding-agent/capability/fs";
10
- import { registerProvider } from "@oh-my-pi/pi-coding-agent/capability/index";
11
- import { type SSHHost, sshCapability } from "@oh-my-pi/pi-coding-agent/capability/ssh";
12
- import type { LoadContext, LoadResult, SourceMeta } from "@oh-my-pi/pi-coding-agent/capability/types";
7
+ import * as path from "node:path";
8
+ import { registerProvider } from "../capability";
9
+ import { readFile } from "../capability/fs";
10
+ import { type SSHHost, sshCapability } from "../capability/ssh";
11
+ import type { LoadContext, LoadResult, SourceMeta } from "../capability/types";
13
12
  import { createSourceMeta, expandEnvVarsDeep, parseJSON } from "./helpers";
14
13
 
15
14
  const PROVIDER_ID = "ssh-json";
@@ -134,10 +133,10 @@ async function loadSshJsonFile(_ctx: LoadContext, path: string): Promise<LoadRes
134
133
 
135
134
  async function load(ctx: LoadContext): Promise<LoadResult<SSHHost>> {
136
135
  const filenames = ["ssh.json", ".ssh.json"];
137
- const results = await Promise.all(filenames.map((filename) => loadSshJsonFile(ctx, join(ctx.cwd, filename))));
136
+ const results = await Promise.all(filenames.map(filename => loadSshJsonFile(ctx, path.join(ctx.cwd, filename))));
138
137
 
139
- const allItems = results.flatMap((r) => r.items);
140
- const allWarnings = results.flatMap((r) => r.warnings ?? []);
138
+ const allItems = results.flatMap(r => r.items);
139
+ const allWarnings = results.flatMap(r => r.warnings ?? []);
141
140
 
142
141
  return {
143
142
  items: allItems,
@@ -4,11 +4,10 @@
4
4
  * Loads config from `.vscode` directory (project-only).
5
5
  * Supports MCP server discovery from `mcp.json` with nested `mcp.servers` structure.
6
6
  */
7
-
8
- import { readFile } from "@oh-my-pi/pi-coding-agent/capability/fs";
9
- import { registerProvider } from "@oh-my-pi/pi-coding-agent/capability/index";
10
- import { type MCPServer, mcpCapability } from "@oh-my-pi/pi-coding-agent/capability/mcp";
11
- import type { LoadContext, LoadResult } from "@oh-my-pi/pi-coding-agent/capability/types";
7
+ import { registerProvider } from "../capability";
8
+ import { readFile } from "../capability/fs";
9
+ import { type MCPServer, mcpCapability } from "../capability/mcp";
10
+ import type { LoadContext, LoadResult } from "../capability/types";
12
11
  import { createSourceMeta, expandEnvVarsDeep, getProjectPath, parseJSON } from "./helpers";
13
12
 
14
13
  const PROVIDER_ID = "vscode";
@@ -10,13 +10,12 @@
10
10
  * - Rules from .windsurf/rules/*.md and ~/.codeium/windsurf/memories/global_rules.md
11
11
  * - Legacy .windsurfrules file
12
12
  */
13
-
14
- import { readFile } from "@oh-my-pi/pi-coding-agent/capability/fs";
15
- import { registerProvider } from "@oh-my-pi/pi-coding-agent/capability/index";
16
- import { type MCPServer, mcpCapability } from "@oh-my-pi/pi-coding-agent/capability/mcp";
17
- import { type Rule, ruleCapability } from "@oh-my-pi/pi-coding-agent/capability/rule";
18
- import type { LoadContext, LoadResult } from "@oh-my-pi/pi-coding-agent/capability/types";
19
- import { parseFrontmatter } from "@oh-my-pi/pi-coding-agent/utils/frontmatter";
13
+ import { registerProvider } from "../capability";
14
+ import { readFile } from "../capability/fs";
15
+ import { type MCPServer, mcpCapability } from "../capability/mcp";
16
+ import { type Rule, ruleCapability } from "../capability/rule";
17
+ import type { LoadContext, LoadResult } from "../capability/types";
18
+ import { parseFrontmatter } from "../utils/frontmatter";
20
19
  import {
21
20
  createSourceMeta,
22
21
  expandEnvVarsDeep,
@@ -3,9 +3,8 @@
3
3
  *
4
4
  * Research companies using Exa's comprehensive data sources.
5
5
  */
6
-
7
- import type { CustomTool } from "@oh-my-pi/pi-coding-agent/extensibility/custom-tools/types";
8
6
  import { Type } from "@sinclair/typebox";
7
+ import type { CustomTool } from "../extensibility/custom-tools/types";
9
8
  import { callExaTool, findApiKey, formatSearchResults, isSearchResponse } from "./mcp-client";
10
9
  import type { ExaRenderDetails } from "./types";
11
10
 
package/src/exa/index.ts CHANGED
@@ -8,9 +8,8 @@
8
8
  * - 2 researcher tools (start, poll)
9
9
  * - 14 websets tools (CRUD, items, search, enrichment, monitor)
10
10
  */
11
-
12
- import type { ExaSettings } from "@oh-my-pi/pi-coding-agent/config/settings-manager";
13
- import type { CustomTool } from "@oh-my-pi/pi-coding-agent/extensibility/custom-tools/types";
11
+ import type { ExaSettings } from "../config/settings-manager";
12
+ import type { CustomTool } from "../extensibility/custom-tools/types";
14
13
  import { companyTool } from "./company";
15
14
  import { linkedinTool } from "./linkedin";
16
15
  import { researcherTools } from "./researcher";
@@ -3,9 +3,8 @@
3
3
  *
4
4
  * Search LinkedIn for people, companies, and professional content.
5
5
  */
6
-
7
- import type { CustomTool } from "@oh-my-pi/pi-coding-agent/extensibility/custom-tools/types";
8
6
  import { Type } from "@sinclair/typebox";
7
+ import type { CustomTool } from "../extensibility/custom-tools/types";
9
8
  import { callExaTool, findApiKey, formatSearchResults, isSearchResponse } from "./mcp-client";
10
9
  import type { ExaRenderDetails } from "./types";
11
10
 
@@ -3,13 +3,11 @@
3
3
  *
4
4
  * Client for interacting with Exa MCP servers.
5
5
  */
6
-
7
- import { existsSync, readFileSync } from "node:fs";
8
- import { homedir } from "node:os";
9
- import type { CustomTool, CustomToolResult } from "@oh-my-pi/pi-coding-agent/extensibility/custom-tools/types";
10
- import { callMCP } from "@oh-my-pi/pi-coding-agent/mcp/json-rpc";
11
- import { logger } from "@oh-my-pi/pi-utils";
6
+ import * as os from "node:os";
7
+ import { isEnoent, logger } from "@oh-my-pi/pi-utils";
12
8
  import type { TSchema } from "@sinclair/typebox";
9
+ import type { CustomTool, CustomToolResult } from "../extensibility/custom-tools/types";
10
+ import { callMCP } from "../mcp/json-rpc";
13
11
  import type {
14
12
  ExaRenderDetails,
15
13
  ExaSearchResponse,
@@ -29,20 +27,20 @@ export async function findApiKey(): Promise<string | null> {
29
27
 
30
28
  // Try loading from .env files in cwd and home
31
29
  const cwd = process.cwd();
32
- const home = homedir();
30
+ const home = os.homedir();
33
31
 
34
32
  for (const dir of [cwd, home]) {
35
33
  const envPath = `${dir}/.env`;
36
34
  try {
37
- if (existsSync(envPath)) {
38
- const content = readFileSync(envPath, "utf-8");
39
- const match = content.match(/^EXA_API_KEY=(.+)$/m);
40
- if (match?.[1]) {
41
- return match[1].trim().replace(/^["']|["']$/g, "");
42
- }
35
+ const content = await Bun.file(envPath).text();
36
+ const match = content.match(/^EXA_API_KEY=(.+)$/m);
37
+ if (match?.[1]) {
38
+ return match[1].trim().replace(/^["']|["']$/g, "");
39
+ }
40
+ } catch (err) {
41
+ if (!isEnoent(err)) {
42
+ logger.debug("Error reading .env file", { path: envPath, error: String(err) });
43
43
  }
44
- } catch {
45
- // Ignore read errors
46
44
  }
47
45
  }
48
46
 
@@ -231,7 +229,7 @@ export async function fetchMCPToolSchema(
231
229
 
232
230
  try {
233
231
  const tools = isWebsetsTool ? await fetchWebsetsTools(apiKey) : await fetchExaTools(apiKey, [mcpToolName]);
234
- const tool = tools.find((t) => t.name === mcpToolName);
232
+ const tool = tools.find(t => t.name === mcpToolName);
235
233
  if (tool) {
236
234
  mcpSchemaCache.set(cacheKey, tool);
237
235
  return tool;
package/src/exa/render.ts CHANGED
@@ -3,9 +3,11 @@
3
3
  *
4
4
  * Tree-based rendering with collapsed/expanded states for Exa search results.
5
5
  */
6
-
7
- import type { RenderResultOptions } from "@oh-my-pi/pi-coding-agent/extensibility/custom-tools/types";
8
- import type { Theme } from "@oh-my-pi/pi-coding-agent/modes/theme/theme";
6
+ import type { Component } from "@oh-my-pi/pi-tui";
7
+ import { Text } from "@oh-my-pi/pi-tui";
8
+ import { logger } from "@oh-my-pi/pi-utils";
9
+ import type { RenderResultOptions } from "../extensibility/custom-tools/types";
10
+ import type { Theme } from "../modes/theme/theme";
9
11
  import {
10
12
  formatCount,
11
13
  formatExpandHint,
@@ -16,10 +18,7 @@ import {
16
18
  PREVIEW_LIMITS,
17
19
  TRUNCATE_LENGTHS,
18
20
  truncate,
19
- } from "@oh-my-pi/pi-coding-agent/tools/render-utils";
20
- import type { Component } from "@oh-my-pi/pi-tui";
21
- import { Text } from "@oh-my-pi/pi-tui";
22
- import { logger } from "@oh-my-pi/pi-utils";
21
+ } from "../tools/render-utils";
23
22
  import type { ExaRenderDetails } from "./types";
24
23
 
25
24
  const COLLAPSED_PREVIEW_LINES = PREVIEW_LIMITS.COLLAPSED_LINES;
@@ -60,7 +59,7 @@ export function renderExaResult(
60
59
  if (!response) {
61
60
  if (details?.raw) {
62
61
  const rawText = typeof details.raw === "string" ? details.raw : JSON.stringify(details.raw, null, 2);
63
- const rawLines = rawText.split("\n").filter((l) => l.trim());
62
+ const rawLines = rawText.split("\n").filter(l => l.trim());
64
63
  const maxLines = expanded ? rawLines.length : Math.min(rawLines.length, COLLAPSED_PREVIEW_LINES);
65
64
  const displayLines = rawLines.slice(0, maxLines);
66
65
  const remaining = rawLines.length - maxLines;
@@ -104,7 +103,7 @@ export function renderExaResult(
104
103
  let hasMorePreview = false;
105
104
  if (!expanded && resultCount > 0) {
106
105
  const previewText = results[0].text ?? results[0].title ?? "";
107
- const totalLines = previewText.split("\n").filter((l) => l.trim()).length;
106
+ const totalLines = previewText.split("\n").filter(l => l.trim()).length;
108
107
  hasMorePreview = totalLines > COLLAPSED_PREVIEW_LINES || resultCount > 1;
109
108
  }
110
109
  const expandHint = formatExpandHint(uiTheme, expanded, hasMorePreview);
@@ -123,7 +122,7 @@ export function renderExaResult(
123
122
  ? getPreviewLines(previewText, COLLAPSED_PREVIEW_LINES, COLLAPSED_PREVIEW_LINE_LEN, uiTheme.format.ellipsis)
124
123
  : [];
125
124
  const safePreviewLines = previewLines.length > 0 ? previewLines : ["No preview text"];
126
- const totalLines = previewText.split("\n").filter((l) => l.trim()).length;
125
+ const totalLines = previewText.split("\n").filter(l => l.trim()).length;
127
126
  const remainingLines = Math.max(0, totalLines - previewLines.length);
128
127
  const extraItems: string[] = [];
129
128
  if (remainingLines > 0) {
@@ -189,7 +188,7 @@ export function renderExaResult(
189
188
  }
190
189
 
191
190
  if (res.text) {
192
- const textLines = res.text.split("\n").filter((l) => l.trim());
191
+ const textLines = res.text.split("\n").filter(l => l.trim());
193
192
  const displayLines = textLines.slice(0, EXPANDED_TEXT_LINES);
194
193
  for (const line of displayLines) {
195
194
  text += `\n ${uiTheme.fg("dim", cont)} ${uiTheme.fg("dim", uiTheme.tree.hook)} ${uiTheme.fg(
@@ -3,9 +3,8 @@
3
3
  *
4
4
  * Async research tasks with polling for completion.
5
5
  */
6
-
7
- import type { CustomTool } from "@oh-my-pi/pi-coding-agent/extensibility/custom-tools/types";
8
6
  import { Type } from "@sinclair/typebox";
7
+ import type { CustomTool } from "../extensibility/custom-tools/types";
9
8
  import { callExaTool, findApiKey } from "./mcp-client";
10
9
  import type { ExaRenderDetails } from "./types";
11
10
 
package/src/exa/search.ts CHANGED
@@ -3,10 +3,9 @@
3
3
  *
4
4
  * Basic neural/keyword search, deep research, code search, and URL crawling.
5
5
  */
6
-
7
6
  import { StringEnum } from "@oh-my-pi/pi-ai";
8
- import type { CustomTool } from "@oh-my-pi/pi-coding-agent/extensibility/custom-tools/types";
9
7
  import { Type } from "@sinclair/typebox";
8
+ import type { CustomTool } from "../extensibility/custom-tools/types";
10
9
  import { callExaTool, findApiKey, formatSearchResults, isSearchResponse } from "./mcp-client";
11
10
  import type { ExaRenderDetails } from "./types";
12
11
 
package/src/exa/types.ts CHANGED
@@ -3,7 +3,6 @@
3
3
  *
4
4
  * Types for the Exa MCP client and tool implementations.
5
5
  */
6
-
7
6
  import type { TSchema } from "@sinclair/typebox";
8
7
 
9
8
  /** MCP endpoint URLs */
@@ -3,9 +3,8 @@
3
3
  *
4
4
  * CRUD operations for websets, items, searches, enrichments, and monitoring.
5
5
  */
6
-
7
- import type { CustomTool } from "@oh-my-pi/pi-coding-agent/extensibility/custom-tools/types";
8
6
  import { Type } from "@sinclair/typebox";
7
+ import type { CustomTool } from "../extensibility/custom-tools/types";
9
8
  import { callWebsetsTool, findApiKey } from "./mcp-client";
10
9
  import type { ExaRenderDetails } from "./types";
11
10
 
@@ -3,11 +3,10 @@
3
3
  *
4
4
  * Provides unified bash execution for AgentSession.executeBash() and direct calls.
5
5
  */
6
-
7
- import { OutputSink } from "@oh-my-pi/pi-coding-agent/session/streaming-output";
8
- import { getShellConfig } from "@oh-my-pi/pi-coding-agent/utils/shell";
9
- import { getOrCreateSnapshot, getSnapshotSourceCommand } from "@oh-my-pi/pi-coding-agent/utils/shell-snapshot";
10
6
  import { cspawn, Exception, ptree } from "@oh-my-pi/pi-utils";
7
+ import { OutputSink } from "../session/streaming-output";
8
+ import { getShellConfig } from "../utils/shell";
9
+ import { getOrCreateSnapshot, getSnapshotSourceCommand } from "../utils/shell-snapshot";
11
10
 
12
11
  export interface BashExecutorOptions {
13
12
  cwd?: string;
package/src/exec/exec.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  /**
2
2
  * Shared command execution utilities for hooks and custom tools.
3
3
  */
4
-
5
4
  import { ptree } from "@oh-my-pi/pi-utils";
6
5
 
7
6
  /**
@@ -4,10 +4,9 @@
4
4
  * Allows users to define a custom share handler at ~/.omp/agent/share.ts
5
5
  * that will be used instead of the default GitHub Gist sharing.
6
6
  */
7
-
8
- import { existsSync } from "node:fs";
9
- import { join } from "node:path";
10
- import { getAgentDir } from "@oh-my-pi/pi-coding-agent/config";
7
+ import * as fs from "node:fs";
8
+ import * as path from "node:path";
9
+ import { getAgentDir } from "../config";
11
10
 
12
11
  export interface CustomShareResult {
13
12
  /** URL to display/open (optional - script may handle everything itself) */
@@ -32,8 +31,8 @@ export function getCustomSharePath(): string | null {
32
31
  const agentDir = getAgentDir();
33
32
 
34
33
  for (const candidate of SHARE_SCRIPT_CANDIDATES) {
35
- const scriptPath = join(agentDir, candidate);
36
- if (existsSync(scriptPath)) {
34
+ const scriptPath = path.join(agentDir, candidate);
35
+ if (fs.existsSync(scriptPath)) {
37
36
  return scriptPath;
38
37
  }
39
38
  }
@@ -1,10 +1,9 @@
1
- import { existsSync, writeFileSync } from "node:fs";
2
- import { basename } from "node:path";
1
+ import * as path from "node:path";
3
2
  import type { AgentState } from "@oh-my-pi/pi-agent-core";
4
- import { APP_NAME } from "@oh-my-pi/pi-coding-agent/config";
5
- import { getResolvedThemeColors, getThemeExportColors } from "@oh-my-pi/pi-coding-agent/modes/theme/theme";
6
- import { SessionManager } from "@oh-my-pi/pi-coding-agent/session/session-manager";
7
-
3
+ import { isEnoent } from "@oh-my-pi/pi-utils";
4
+ import { APP_NAME } from "../../config";
5
+ import { getResolvedThemeColors, getThemeExportColors } from "../../modes/theme/theme";
6
+ import { SessionManager } from "../../session/session-manager";
8
7
  // Pre-generated template (created by scripts/generate-template.ts at publish time)
9
8
  import { TEMPLATE } from "./template.generated";
10
9
 
@@ -74,14 +73,14 @@ function deriveExportColors(baseColor: string): { pageBg: string; cardBg: string
74
73
  }
75
74
 
76
75
  /** Generate CSS custom properties for theme. */
77
- function generateThemeVars(themeName?: string): string {
78
- const colors = getResolvedThemeColors(themeName);
76
+ async function generateThemeVars(themeName?: string): Promise<string> {
77
+ const colors = await getResolvedThemeColors(themeName);
79
78
  const lines: string[] = [];
80
79
  for (const [key, value] of Object.entries(colors)) {
81
80
  lines.push(`--${key}: ${value};`);
82
81
  }
83
82
 
84
- const themeExport = getThemeExportColors(themeName);
83
+ const themeExport = await getThemeExportColors(themeName);
85
84
  const userMessageBg = colors.userMessageBg || "#343541";
86
85
  const derived = deriveExportColors(userMessageBg);
87
86
 
@@ -101,8 +100,8 @@ interface SessionData {
101
100
  }
102
101
 
103
102
  /** Generate HTML from bundled template with runtime substitutions. */
104
- function generateHtml(sessionData: SessionData, themeName?: string): string {
105
- const themeVars = generateThemeVars(themeName);
103
+ async function generateHtml(sessionData: SessionData, themeName?: string): Promise<string> {
104
+ const themeVars = await generateThemeVars(themeName);
106
105
  const sessionDataBase64 = Buffer.from(JSON.stringify(sessionData)).toString("base64");
107
106
 
108
107
  return TEMPLATE.replace("<theme-vars/>", `<style>:root { ${themeVars} }</style>`).replace(
@@ -121,20 +120,19 @@ export async function exportSessionToHtml(
121
120
 
122
121
  const sessionFile = sm.getSessionFile();
123
122
  if (!sessionFile) throw new Error("Cannot export in-memory session to HTML");
124
- if (!existsSync(sessionFile)) throw new Error("Nothing to export yet - start a conversation first");
125
123
 
126
124
  const sessionData: SessionData = {
127
125
  header: sm.getHeader(),
128
126
  entries: sm.getEntries(),
129
127
  leafId: sm.getLeafId(),
130
128
  systemPrompt: state?.systemPrompt,
131
- tools: state?.tools?.map((t) => ({ name: t.name, description: t.description })),
129
+ tools: state?.tools?.map(t => ({ name: t.name, description: t.description })),
132
130
  };
133
131
 
134
- const html = generateHtml(sessionData, opts.themeName);
135
- const outputPath = opts.outputPath || `${APP_NAME}-session-${basename(sessionFile, ".jsonl")}.html`;
132
+ const html = await generateHtml(sessionData, opts.themeName);
133
+ const outputPath = opts.outputPath || `${APP_NAME}-session-${path.basename(sessionFile, ".jsonl")}.html`;
136
134
 
137
- writeFileSync(outputPath, html, "utf8");
135
+ await Bun.write(outputPath, html);
138
136
  return outputPath;
139
137
  }
140
138
 
@@ -142,18 +140,23 @@ export async function exportSessionToHtml(
142
140
  export async function exportFromFile(inputPath: string, options?: ExportOptions | string): Promise<string> {
143
141
  const opts: ExportOptions = typeof options === "string" ? { outputPath: options } : options || {};
144
142
 
145
- if (!existsSync(inputPath)) throw new Error(`File not found: ${inputPath}`);
143
+ let sm: SessionManager;
144
+ try {
145
+ sm = await SessionManager.open(inputPath);
146
+ } catch (err) {
147
+ if (isEnoent(err)) throw new Error(`File not found: ${inputPath}`);
148
+ throw err;
149
+ }
146
150
 
147
- const sm = await SessionManager.open(inputPath);
148
151
  const sessionData: SessionData = {
149
152
  header: sm.getHeader(),
150
153
  entries: sm.getEntries(),
151
154
  leafId: sm.getLeafId(),
152
155
  };
153
156
 
154
- const html = generateHtml(sessionData, opts.themeName);
155
- const outputPath = opts.outputPath || `${APP_NAME}-session-${basename(inputPath, ".jsonl")}.html`;
157
+ const html = await generateHtml(sessionData, opts.themeName);
158
+ const outputPath = opts.outputPath || `${APP_NAME}-session-${path.basename(inputPath, ".jsonl")}.html`;
156
159
 
157
- writeFileSync(outputPath, html, "utf8");
160
+ await Bun.write(outputPath, html);
158
161
  return outputPath;
159
162
  }
@@ -5,10 +5,9 @@
5
5
  * the agent's output. When a match occurs, the stream is aborted, the rule is
6
6
  * injected as a system reminder, and the request is retried.
7
7
  */
8
-
9
- import type { Rule } from "@oh-my-pi/pi-coding-agent/capability/rule";
10
- import type { TtsrSettings } from "@oh-my-pi/pi-coding-agent/config/settings-manager";
11
8
  import { logger } from "@oh-my-pi/pi-utils";
9
+ import type { Rule } from "../capability/rule";
10
+ import type { TtsrSettings } from "../config/settings-manager";
12
11
 
13
12
  interface TtsrEntry {
14
13
  rule: Rule;
@@ -11,11 +11,10 @@
11
11
  * rich context for the orchestrating agent to distribute work across
12
12
  * multiple reviewer agents based on diff weight and locality.
13
13
  */
14
-
15
- import { renderPromptTemplate } from "@oh-my-pi/pi-coding-agent/config/prompt-templates";
16
- import type { CustomCommand, CustomCommandAPI } from "@oh-my-pi/pi-coding-agent/extensibility/custom-commands/types";
17
- import type { HookCommandContext } from "@oh-my-pi/pi-coding-agent/extensibility/hooks/types";
18
- import reviewRequestTemplate from "@oh-my-pi/pi-coding-agent/prompts/review-request.md" with { type: "text" };
14
+ import { renderPromptTemplate } from "../../../../config/prompt-templates";
15
+ import type { CustomCommand, CustomCommandAPI } from "../../../../extensibility/custom-commands/types";
16
+ import type { HookCommandContext } from "../../../../extensibility/hooks/types";
17
+ import reviewRequestTemplate from "../../../../prompts/review-request.md" with { type: "text" };
19
18
 
20
19
  // ─────────────────────────────────────────────────────────────────────────────
21
20
  // Types
@@ -203,7 +202,7 @@ function buildReviewPrompt(mode: string, stats: DiffStats, rawDiff: string): str
203
202
  const totalLines = stats.totalAdded + stats.totalRemoved;
204
203
  const linesPerFile = skipDiff ? Math.max(5, Math.floor(100 / stats.files.length)) : 0;
205
204
 
206
- const filesWithExt = stats.files.map((f) => ({
205
+ const filesWithExt = stats.files.map(f => ({
207
206
  ...f,
208
207
  ext: getFileExt(f.path),
209
208
  hunksPreview: skipDiff ? getDiffPreview(f.hunks, linesPerFile) : "",
@@ -393,7 +392,7 @@ async function getGitBranches(api: CustomCommandAPI): Promise<string[]> {
393
392
  if (result.code !== 0) return [];
394
393
  return result.stdout
395
394
  .split("\n")
396
- .map((b) => b.trim())
395
+ .map(b => b.trim())
397
396
  .filter(Boolean);
398
397
  } catch {
399
398
  return [];
@@ -424,7 +423,7 @@ async function getRecentCommits(api: CustomCommandAPI, count: number): Promise<s
424
423
  if (result.code !== 0) return [];
425
424
  return result.stdout
426
425
  .split("\n")
427
- .map((c) => c.trim())
426
+ .map(c => c.trim())
428
427
  .filter(Boolean);
429
428
  } catch {
430
429
  return [];
@@ -4,14 +4,13 @@
4
4
  * Dependencies (@sinclair/typebox and pi-coding-agent) are injected via the CustomCommandAPI
5
5
  * to avoid import resolution issues with custom commands loaded from user directories.
6
6
  */
7
-
8
- import { type Dirent, existsSync, readdirSync } from "node:fs";
7
+ import * as fs from "node:fs";
9
8
  import * as path from "node:path";
10
- import { getAgentDir, getConfigDirs } from "@oh-my-pi/pi-coding-agent/config";
11
- import { execCommand } from "@oh-my-pi/pi-coding-agent/exec/exec";
12
- import * as piCodingAgent from "@oh-my-pi/pi-coding-agent/index";
13
- import { logger } from "@oh-my-pi/pi-utils";
9
+ import * as piCodingAgent from "@oh-my-pi/pi-coding-agent";
10
+ import { isEnoent, logger } from "@oh-my-pi/pi-utils";
14
11
  import * as typebox from "@sinclair/typebox";
12
+ import { getAgentDir, getConfigDirs } from "../../config";
13
+ import { execCommand } from "../../exec/exec";
15
14
  import { ReviewCommand } from "./bundled/review";
16
15
  import type {
17
16
  CustomCommand,
@@ -77,7 +76,9 @@ export interface DiscoverCustomCommandsResult {
77
76
  * Discover custom command modules (TypeScript slash commands).
78
77
  * Markdown slash commands are handled by core/slash-commands.ts.
79
78
  */
80
- export function discoverCustomCommands(options: DiscoverCustomCommandsOptions = {}): DiscoverCustomCommandsResult {
79
+ export async function discoverCustomCommands(
80
+ options: DiscoverCustomCommandsOptions = {},
81
+ ): Promise<DiscoverCustomCommandsResult> {
81
82
  const cwd = options.cwd ?? process.cwd();
82
83
  const agentDir = options.agentDir ?? getAgentDir();
83
84
  const paths: Array<{ path: string; source: CustomCommandSource }> = [];
@@ -93,25 +94,27 @@ export function discoverCustomCommands(options: DiscoverCustomCommandsOptions =
93
94
  const commandDirs: Array<{ path: string; source: CustomCommandSource }> = [];
94
95
  if (agentDir) {
95
96
  const userCommandsDir = path.join(agentDir, "commands");
96
- if (existsSync(userCommandsDir)) {
97
+ if (fs.existsSync(userCommandsDir)) {
97
98
  commandDirs.push({ path: userCommandsDir, source: "user" });
98
99
  }
99
100
  }
100
101
 
101
102
  for (const entry of getConfigDirs("commands", { cwd, existingOnly: true })) {
102
103
  const source = entry.level === "user" ? "user" : "project";
103
- if (!commandDirs.some((d) => d.path === entry.path)) {
104
+ if (!commandDirs.some(d => d.path === entry.path)) {
104
105
  commandDirs.push({ path: entry.path, source });
105
106
  }
106
107
  }
107
108
 
108
109
  const indexCandidates = ["index.ts", "index.js", "index.mjs", "index.cjs"];
109
110
  for (const { path: commandsDir, source } of commandDirs) {
110
- let entries: Dirent[];
111
+ let entries: fs.Dirent[];
111
112
  try {
112
- entries = readdirSync(commandsDir, { withFileTypes: true });
113
+ entries = await fs.promises.readdir(commandsDir, { withFileTypes: true });
113
114
  } catch (error) {
114
- logger.warn("Failed to read custom commands directory", { path: commandsDir, error: String(error) });
115
+ if (!isEnoent(error)) {
116
+ logger.warn("Failed to read custom commands directory", { path: commandsDir, error: String(error) });
117
+ }
115
118
  continue;
116
119
  }
117
120
  for (const entry of entries) {
@@ -120,7 +123,7 @@ export function discoverCustomCommands(options: DiscoverCustomCommandsOptions =
120
123
 
121
124
  for (const filename of indexCandidates) {
122
125
  const candidate = path.join(commandDir, filename);
123
- if (existsSync(candidate)) {
126
+ if (fs.existsSync(candidate)) {
124
127
  addPath(candidate, source);
125
128
  break;
126
129
  }
@@ -162,7 +165,7 @@ export async function loadCustomCommands(options: LoadCustomCommandsOptions = {}
162
165
  const cwd = options.cwd ?? process.cwd();
163
166
  const agentDir = options.agentDir ?? getAgentDir();
164
167
 
165
- const { paths } = discoverCustomCommands({ cwd, agentDir });
168
+ const { paths } = await discoverCustomCommands({ cwd, agentDir });
166
169
 
167
170
  const commands: LoadedCustomCommand[] = [];
168
171
  const errors: Array<{ path: string; error: string }> = [];
@@ -195,7 +198,7 @@ export async function loadCustomCommands(options: LoadCustomCommandsOptions = {}
195
198
  if (loadedCommands) {
196
199
  for (const command of loadedCommands) {
197
200
  // Allow overriding bundled commands, but not user/project conflicts
198
- const existingIdx = commands.findIndex((c) => c.command.name === command.name);
201
+ const existingIdx = commands.findIndex(c => c.command.name === command.name);
199
202
  if (existingIdx !== -1) {
200
203
  const existing = commands[existingIdx];
201
204
  if (existing.source === "bundled") {
@@ -5,8 +5,7 @@
5
5
  * Unlike markdown commands which expand to prompts, custom commands can execute
6
6
  * arbitrary logic with full access to the hook context.
7
7
  */
8
-
9
- import type { ExecOptions, ExecResult, HookCommandContext } from "@oh-my-pi/pi-coding-agent/extensibility/hooks/types";
8
+ import type { ExecOptions, ExecResult, HookCommandContext } from "../../extensibility/hooks/types";
10
9
 
11
10
  // Re-export for custom commands to use
12
11
  export type { ExecOptions, ExecResult, HookCommandContext };
@@ -23,7 +22,7 @@ export interface CustomCommandAPI {
23
22
  /** Injected @sinclair/typebox module */
24
23
  typebox: typeof import("@sinclair/typebox");
25
24
  /** Injected pi-coding-agent exports */
26
- pi: typeof import("../../index");
25
+ pi: typeof import("../..");
27
26
  }
28
27
 
29
28
  /**