@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
package/src/migrations.ts CHANGED
@@ -1,32 +1,31 @@
1
1
  /**
2
2
  * One-time migrations that run on startup.
3
3
  */
4
-
5
- import { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
6
- import { join } from "node:path";
7
- import { AgentStorage } from "@oh-my-pi/pi-coding-agent/session/agent-storage";
8
- import type { AuthCredential } from "@oh-my-pi/pi-coding-agent/session/auth-storage";
9
- import { logger } from "@oh-my-pi/pi-utils";
4
+ import * as fs from "node:fs";
5
+ import * as path from "node:path";
6
+ import { isEnoent, logger } from "@oh-my-pi/pi-utils";
10
7
  import chalk from "chalk";
11
8
  import { getAgentDbPath, getAgentDir, getBinDir } from "./config";
9
+ import { AgentStorage } from "./session/agent-storage";
10
+ import type { AuthCredential } from "./session/auth-storage";
12
11
 
13
12
  /**
14
13
  * Migrate legacy oauth.json and settings.json apiKeys to agent.db.
15
14
  *
16
15
  * @returns Array of provider names that were migrated
17
16
  */
18
- export function migrateAuthToAgentDb(): string[] {
17
+ export async function migrateAuthToAgentDb(): Promise<string[]> {
19
18
  const agentDir = getAgentDir();
20
- const oauthPath = join(agentDir, "oauth.json");
21
- const settingsPath = join(agentDir, "settings.json");
22
- const storage = AgentStorage.open(getAgentDbPath(agentDir));
19
+ const oauthPath = path.join(agentDir, "oauth.json");
20
+ const settingsPath = path.join(agentDir, "settings.json");
21
+ const storage = await AgentStorage.open(getAgentDbPath(agentDir));
23
22
 
24
23
  const migrated: Record<string, AuthCredential[]> = {};
25
24
  const providers: string[] = [];
26
25
 
27
- if (existsSync(oauthPath)) {
26
+ try {
27
+ const oauth = await Bun.file(oauthPath).json();
28
28
  try {
29
- const oauth = JSON.parse(readFileSync(oauthPath, "utf-8"));
30
29
  for (const [provider, cred] of Object.entries(oauth)) {
31
30
  if (storage.listAuthCredentials(provider).length > 0) {
32
31
  continue;
@@ -34,16 +33,19 @@ export function migrateAuthToAgentDb(): string[] {
34
33
  migrated[provider] = [{ type: "oauth", ...(cred as object) } as AuthCredential];
35
34
  providers.push(provider);
36
35
  }
37
- renameSync(oauthPath, `${oauthPath}.migrated`);
36
+ await fs.promises.rename(oauthPath, `${oauthPath}.migrated`);
38
37
  } catch (error) {
39
38
  logger.warn("Failed to migrate oauth.json", { path: oauthPath, error: String(error) });
40
39
  }
40
+ } catch (err) {
41
+ if (!isEnoent(err)) {
42
+ logger.warn("Failed to read oauth.json", { path: oauthPath, error: String(err) });
43
+ }
41
44
  }
42
45
 
43
- if (existsSync(settingsPath)) {
46
+ try {
47
+ const settings = await Bun.file(settingsPath).json();
44
48
  try {
45
- const content = readFileSync(settingsPath, "utf-8");
46
- const settings = JSON.parse(content);
47
49
  if (settings.apiKeys && typeof settings.apiKeys === "object") {
48
50
  for (const [provider, key] of Object.entries(settings.apiKeys)) {
49
51
  if (typeof key !== "string") continue;
@@ -53,11 +55,15 @@ export function migrateAuthToAgentDb(): string[] {
53
55
  providers.push(provider);
54
56
  }
55
57
  delete settings.apiKeys;
56
- writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
58
+ await Bun.write(settingsPath, JSON.stringify(settings, null, 2));
57
59
  }
58
60
  } catch (error) {
59
61
  logger.warn("Failed to migrate settings.json apiKeys", { path: settingsPath, error: String(error) });
60
62
  }
63
+ } catch (err) {
64
+ if (!isEnoent(err)) {
65
+ logger.warn("Failed to read settings.json", { path: settingsPath, error: String(err) });
66
+ }
61
67
  }
62
68
 
63
69
  for (const [provider, credentials] of Object.entries(migrated)) {
@@ -76,15 +82,14 @@ export function migrateAuthToAgentDb(): string[] {
76
82
  *
77
83
  * See: https://github.com/badlogic/pi-mono/issues/320
78
84
  */
79
- export function migrateSessionsFromAgentRoot(): void {
85
+ export async function migrateSessionsFromAgentRoot(): Promise<void> {
80
86
  const agentDir = getAgentDir();
81
87
 
82
88
  // Find all .jsonl files directly in agentDir (not in subdirectories)
83
89
  let files: string[];
84
90
  try {
85
- files = readdirSync(agentDir)
86
- .filter((f) => f.endsWith(".jsonl"))
87
- .map((f) => join(agentDir, f));
91
+ const entries = await fs.promises.readdir(agentDir);
92
+ files = entries.filter(f => f.endsWith(".jsonl")).map(f => path.join(agentDir, f));
88
93
  } catch (error) {
89
94
  logger.warn("Failed to read agent directory for session migration", { path: agentDir, error: String(error) });
90
95
  return;
@@ -95,7 +100,13 @@ export function migrateSessionsFromAgentRoot(): void {
95
100
  for (const file of files) {
96
101
  try {
97
102
  // Read first line to get session header
98
- const content = readFileSync(file, "utf8");
103
+ let content: string;
104
+ try {
105
+ content = await Bun.file(file).text();
106
+ } catch (err) {
107
+ if (isEnoent(err)) continue;
108
+ throw err;
109
+ }
99
110
  const firstLine = content.split("\n")[0];
100
111
  if (!firstLine?.trim()) continue;
101
112
 
@@ -106,18 +117,18 @@ export function migrateSessionsFromAgentRoot(): void {
106
117
 
107
118
  // Compute the correct session directory (same encoding as session-manager.ts)
108
119
  const safePath = `--${cwd.replace(/^[/\\]/, "").replace(/[/\\:]/g, "-")}--`;
109
- const correctDir = join(agentDir, "sessions", safePath);
120
+ const correctDir = path.join(agentDir, "sessions", safePath);
110
121
 
111
122
  // Create directory if needed
112
- mkdirSync(correctDir, { recursive: true });
123
+ await fs.promises.mkdir(correctDir, { recursive: true });
113
124
 
114
125
  // Move the file
115
126
  const fileName = file.split("/").pop() || file.split("\\").pop();
116
- const newPath = join(correctDir, fileName!);
127
+ const newPath = path.join(correctDir, fileName!);
117
128
 
118
- if (existsSync(newPath)) continue; // Skip if target exists
129
+ if (fs.existsSync(newPath)) continue; // Skip if target exists
119
130
 
120
- renameSync(file, newPath);
131
+ await fs.promises.rename(file, newPath);
121
132
  } catch (error) {
122
133
  logger.warn("Failed to migrate session file", { path: file, error: String(error) });
123
134
  }
@@ -127,38 +138,38 @@ export function migrateSessionsFromAgentRoot(): void {
127
138
  /**
128
139
  * Move fd/rg binaries from tools/ to bin/ if they exist.
129
140
  */
130
- function migrateToolsToBin(): void {
141
+ async function migrateToolsToBin(): Promise<void> {
131
142
  const agentDir = getAgentDir();
132
- const toolsDir = join(agentDir, "tools");
143
+ const toolsDir = path.join(agentDir, "tools");
133
144
  const binDir = getBinDir();
134
145
 
135
- if (!existsSync(toolsDir)) return;
146
+ if (!fs.existsSync(toolsDir)) return;
136
147
 
137
148
  const binaries = ["fd", "rg", "fd.exe", "rg.exe"];
138
149
  let movedAny = false;
139
150
 
140
151
  for (const bin of binaries) {
141
- const oldPath = join(toolsDir, bin);
142
- const newPath = join(binDir, bin);
152
+ const oldPath = path.join(toolsDir, bin);
153
+ const newPath = path.join(binDir, bin);
154
+ if (!fs.existsSync(oldPath)) continue;
155
+
156
+ if (!fs.existsSync(binDir)) {
157
+ await fs.promises.mkdir(binDir, { recursive: true });
158
+ }
143
159
 
144
- if (existsSync(oldPath)) {
145
- if (!existsSync(binDir)) {
146
- mkdirSync(binDir, { recursive: true });
160
+ if (!fs.existsSync(newPath)) {
161
+ try {
162
+ await fs.promises.rename(oldPath, newPath);
163
+ movedAny = true;
164
+ } catch (error) {
165
+ logger.warn("Failed to migrate binary", { from: oldPath, to: newPath, error: String(error) });
147
166
  }
148
- if (!existsSync(newPath)) {
149
- try {
150
- renameSync(oldPath, newPath);
151
- movedAny = true;
152
- } catch (error) {
153
- logger.warn("Failed to migrate binary", { from: oldPath, to: newPath, error: String(error) });
154
- }
155
- } else {
156
- // Target exists, just delete the old one
157
- try {
158
- rmSync(oldPath, { force: true });
159
- } catch {
160
- // Ignore
161
- }
167
+ } else {
168
+ // Target exists, just delete the old one
169
+ try {
170
+ await fs.promises.rm(oldPath, { force: true });
171
+ } catch {
172
+ // Ignore
162
173
  }
163
174
  }
164
175
  }
@@ -179,9 +190,9 @@ export async function runMigrations(_cwd: string): Promise<{
179
190
  deprecationWarnings: string[];
180
191
  }> {
181
192
  // Then: run data migrations
182
- const migratedAuthProviders = migrateAuthToAgentDb();
183
- migrateSessionsFromAgentRoot();
184
- migrateToolsToBin();
193
+ const migratedAuthProviders = await migrateAuthToAgentDb();
194
+ await migrateSessionsFromAgentRoot();
195
+ await migrateToolsToBin();
185
196
 
186
197
  return { migratedAuthProviders, deprecationWarnings: [] };
187
198
  }
@@ -1,9 +1,8 @@
1
1
  /**
2
2
  * Armin says hi! A fun easter egg with animated XBM art.
3
3
  */
4
-
5
- import { theme } from "@oh-my-pi/pi-coding-agent/modes/theme/theme";
6
4
  import type { Component, TUI } from "@oh-my-pi/pi-tui";
5
+ import { theme } from "../../modes/theme/theme";
7
6
 
8
7
  // XBM image: 31x36 pixels, LSB first, 1=background, 0=foreground
9
8
  const WIDTH = 31;
@@ -91,7 +90,7 @@ export class ArminComponent implements Component {
91
90
  const padding = 1;
92
91
  const availableWidth = width - padding;
93
92
 
94
- this.cachedLines = this.currentGrid.map((row) => {
93
+ this.cachedLines = this.currentGrid.map(row => {
95
94
  // Clip row to available width before applying color
96
95
  const clipped = row.slice(0, availableWidth).join("");
97
96
  const padRight = Math.max(0, width - padding - clipped.length);
@@ -332,7 +331,7 @@ export class ArminComponent implements Component {
332
331
 
333
332
  if (state.phase < state.glitchFrames) {
334
333
  // Glitch phase: show corrupted version
335
- this.currentGrid = this.finalGrid.map((row) => {
334
+ this.currentGrid = this.finalGrid.map(row => {
336
335
  const offset = Math.floor(Math.random() * 7) - 3;
337
336
  const glitchRow = [...row];
338
337
 
@@ -355,7 +354,7 @@ export class ArminComponent implements Component {
355
354
  }
356
355
 
357
356
  // Final frame: show clean image
358
- this.currentGrid = this.finalGrid.map((row) => [...row]);
357
+ this.currentGrid = this.finalGrid.map(row => [...row]);
359
358
  return true;
360
359
  }
361
360
 
@@ -1,6 +1,7 @@
1
1
  import type { AssistantMessage } from "@oh-my-pi/pi-ai";
2
- import { getMarkdownTheme, theme } from "@oh-my-pi/pi-coding-agent/modes/theme/theme";
3
- import { Container, Markdown, Spacer, Text } from "@oh-my-pi/pi-tui";
2
+ import { Container, getCapabilities, Markdown, Spacer, Text } from "@oh-my-pi/pi-tui";
3
+ import { hasPendingMermaid, prerenderMermaid } from "../../modes/theme/mermaid-cache";
4
+ import { getMarkdownTheme, theme } from "../../modes/theme/theme";
4
5
 
5
6
  /**
6
7
  * Component that renders a complete assistant message
@@ -9,6 +10,7 @@ export class AssistantMessageComponent extends Container {
9
10
  private contentContainer: Container;
10
11
  private hideThinkingBlock: boolean;
11
12
  private lastMessage?: AssistantMessage;
13
+ private prerenderInFlight = false;
12
14
 
13
15
  constructor(message?: AssistantMessage, hideThinkingBlock = false) {
14
16
  super();
@@ -35,14 +37,40 @@ export class AssistantMessageComponent extends Container {
35
37
  this.hideThinkingBlock = hide;
36
38
  }
37
39
 
40
+ private triggerMermaidPrerender(message: AssistantMessage): void {
41
+ const caps = getCapabilities();
42
+ if (!caps.images || this.prerenderInFlight) return;
43
+
44
+ // Check if any text content has pending mermaid blocks
45
+ const hasPending = message.content.some(c => c.type === "text" && c.text.trim() && hasPendingMermaid(c.text));
46
+ if (!hasPending) return;
47
+
48
+ this.prerenderInFlight = true;
49
+
50
+ // Fire off background prerender
51
+ (async () => {
52
+ for (const content of message.content) {
53
+ if (content.type === "text" && content.text.trim() && hasPendingMermaid(content.text)) {
54
+ await prerenderMermaid(content.text);
55
+ }
56
+ }
57
+ this.prerenderInFlight = false;
58
+ // Invalidate to re-render with cached images
59
+ this.invalidate();
60
+ })();
61
+ }
62
+
38
63
  updateContent(message: AssistantMessage): void {
39
64
  this.lastMessage = message;
40
65
 
41
66
  // Clear content container
42
67
  this.contentContainer.clear();
43
68
 
69
+ // Trigger background mermaid pre-rendering if needed
70
+ this.triggerMermaidPrerender(message);
71
+
44
72
  const hasVisibleContent = message.content.some(
45
- (c) => (c.type === "text" && c.text.trim()) || (c.type === "thinking" && c.thinking.trim()),
73
+ c => (c.type === "text" && c.text.trim()) || (c.type === "thinking" && c.thinking.trim()),
46
74
  );
47
75
 
48
76
  if (hasVisibleContent) {
@@ -58,7 +86,7 @@ export class AssistantMessageComponent extends Container {
58
86
  this.contentContainer.addChild(new Markdown(content.text.trim(), 1, 0, getMarkdownTheme()));
59
87
  } else if (content.type === "thinking" && content.thinking.trim()) {
60
88
  // Check if there's text content after this thinking block
61
- const hasTextAfter = message.content.slice(i + 1).some((c) => c.type === "text" && c.text.trim());
89
+ const hasTextAfter = message.content.slice(i + 1).some(c => c.type === "text" && c.text.trim());
62
90
 
63
91
  if (this.hideThinkingBlock) {
64
92
  // Show static "Thinking..." label when hidden
@@ -81,7 +109,7 @@ export class AssistantMessageComponent extends Container {
81
109
 
82
110
  // Check if aborted - show after partial content
83
111
  // But only if there are no tool calls (tool execution components will show the error)
84
- const hasToolCalls = message.content.some((c) => c.type === "toolCall");
112
+ const hasToolCalls = message.content.some(c => c.type === "toolCall");
85
113
  if (!hasToolCalls) {
86
114
  if (message.stopReason === "aborted") {
87
115
  const abortMessage =
@@ -1,12 +1,11 @@
1
1
  /**
2
2
  * Component for displaying bash command execution with streaming output.
3
3
  */
4
-
5
- import { getSymbolTheme, theme } from "@oh-my-pi/pi-coding-agent/modes/theme/theme";
6
- import type { TruncationMeta } from "@oh-my-pi/pi-coding-agent/tools/output-meta";
7
- import { formatSize } from "@oh-my-pi/pi-coding-agent/tools/truncate";
8
4
  import { Container, Loader, Spacer, Text, type TUI } from "@oh-my-pi/pi-tui";
9
5
  import stripAnsi from "strip-ansi";
6
+ import { getSymbolTheme, theme } from "../../modes/theme/theme";
7
+ import type { TruncationMeta } from "../../tools/output-meta";
8
+ import { formatSize } from "../../tools/truncate";
10
9
  import { DynamicBorder } from "./dynamic-border";
11
10
  import { truncateToVisualLines } from "./visual-truncate";
12
11
 
@@ -48,8 +47,8 @@ export class BashExecutionComponent extends Container {
48
47
  // Loader
49
48
  this.loader = new Loader(
50
49
  ui,
51
- (spinner) => theme.fg(colorKey, spinner),
52
- (text) => theme.fg("muted", text),
50
+ spinner => theme.fg(colorKey, spinner),
51
+ text => theme.fg("muted", text),
53
52
  `Running${theme.format.ellipsis} (esc to cancel)`,
54
53
  getSymbolTheme().spinnerFrames,
55
54
  );
@@ -128,11 +127,11 @@ export class BashExecutionComponent extends Container {
128
127
  if (availableLines.length > 0) {
129
128
  if (this.expanded) {
130
129
  // Show all lines
131
- const displayText = availableLines.map((line) => theme.fg("muted", line)).join("\n");
130
+ const displayText = availableLines.map(line => theme.fg("muted", line)).join("\n");
132
131
  this.contentContainer.addChild(new Text(`\n${displayText}`, 1, 0));
133
132
  } else {
134
133
  // Use shared visual truncation utility, recomputed per render width
135
- const styledOutput = previewLogicalLines.map((line) => theme.fg("muted", line)).join("\n");
134
+ const styledOutput = previewLogicalLines.map(line => theme.fg("muted", line)).join("\n");
136
135
  const previewText = `\n${styledOutput}`;
137
136
  this.contentContainer.addChild({
138
137
  render: (width: number) => {
@@ -1,5 +1,5 @@
1
- import type { Theme } from "@oh-my-pi/pi-coding-agent/modes/theme/theme";
2
1
  import { CancellableLoader, Container, Spacer, Text, type TUI } from "@oh-my-pi/pi-tui";
2
+ import type { Theme } from "../../modes/theme/theme";
3
3
  import { DynamicBorder } from "./dynamic-border";
4
4
 
5
5
  /** Loader wrapped with borders for hook UI */
@@ -12,8 +12,8 @@ export class BorderedLoader extends Container {
12
12
  this.addChild(new DynamicBorder(borderColor));
13
13
  this.loader = new CancellableLoader(
14
14
  tui,
15
- (s) => theme.fg("accent", s),
16
- (s) => theme.fg("muted", s),
15
+ s => theme.fg("accent", s),
16
+ s => theme.fg("muted", s),
17
17
  message,
18
18
  );
19
19
  this.addChild(this.loader);
@@ -1,6 +1,6 @@
1
- import { getMarkdownTheme, theme } from "@oh-my-pi/pi-coding-agent/modes/theme/theme";
2
- import type { BranchSummaryMessage } from "@oh-my-pi/pi-coding-agent/session/messages";
3
1
  import { Box, Markdown, Spacer, Text } from "@oh-my-pi/pi-tui";
2
+ import { getMarkdownTheme, theme } from "../../modes/theme/theme";
3
+ import type { BranchSummaryMessage } from "../../session/messages";
4
4
 
5
5
  /**
6
6
  * Component that renders a branch summary message with collapsed/expanded state.
@@ -11,7 +11,7 @@ export class BranchSummaryMessageComponent extends Box {
11
11
  private message: BranchSummaryMessage;
12
12
 
13
13
  constructor(message: BranchSummaryMessage) {
14
- super(1, 1, (t) => theme.bg("customMessageBg", t));
14
+ super(1, 1, t => theme.bg("customMessageBg", t));
15
15
  this.message = message;
16
16
  this.updateDisplay();
17
17
  }
@@ -1,6 +1,6 @@
1
- import { getMarkdownTheme, theme } from "@oh-my-pi/pi-coding-agent/modes/theme/theme";
2
- import type { CompactionSummaryMessage } from "@oh-my-pi/pi-coding-agent/session/messages";
3
1
  import { Box, Markdown, Spacer, Text } from "@oh-my-pi/pi-tui";
2
+ import { getMarkdownTheme, theme } from "../../modes/theme/theme";
3
+ import type { CompactionSummaryMessage } from "../../session/messages";
4
4
 
5
5
  /**
6
6
  * Component that renders a compaction message with collapsed/expanded state.
@@ -11,7 +11,7 @@ export class CompactionSummaryMessageComponent extends Box {
11
11
  private message: CompactionSummaryMessage;
12
12
 
13
13
  constructor(message: CompactionSummaryMessage) {
14
- super(1, 1, (t) => theme.bg("customMessageBg", t));
14
+ super(1, 1, t => theme.bg("customMessageBg", t));
15
15
  this.message = message;
16
16
  this.updateDisplay();
17
17
  }
@@ -1,7 +1,6 @@
1
1
  /**
2
2
  * Reusable countdown timer for dialog components.
3
3
  */
4
-
5
4
  import type { TUI } from "@oh-my-pi/pi-tui";
6
5
 
7
6
  export class CountdownTimer {
@@ -1,9 +1,9 @@
1
1
  import type { TextContent } from "@oh-my-pi/pi-ai";
2
- import type { MessageRenderer } from "@oh-my-pi/pi-coding-agent/extensibility/extensions/types";
3
- import { getMarkdownTheme, theme } from "@oh-my-pi/pi-coding-agent/modes/theme/theme";
4
- import type { CustomMessage } from "@oh-my-pi/pi-coding-agent/session/messages";
5
2
  import type { Component } from "@oh-my-pi/pi-tui";
6
3
  import { Box, Container, Markdown, Spacer, Text } from "@oh-my-pi/pi-tui";
4
+ import type { MessageRenderer } from "../../extensibility/extensions/types";
5
+ import { getMarkdownTheme, theme } from "../../modes/theme/theme";
6
+ import type { CustomMessage } from "../../session/messages";
7
7
 
8
8
  /**
9
9
  * Component that renders a custom message entry from extensions.
@@ -24,7 +24,7 @@ export class CustomMessageComponent extends Container {
24
24
  this.addChild(new Spacer(1));
25
25
 
26
26
  // Create box with custom background (used for default rendering)
27
- this.box = new Box(1, 1, (t) => theme.bg("customMessageBg", t));
27
+ this.box = new Box(1, 1, t => theme.bg("customMessageBg", t));
28
28
 
29
29
  this.rebuild();
30
30
  }
@@ -79,7 +79,7 @@ export class CustomMessageComponent extends Container {
79
79
  } else {
80
80
  text = this.message.content
81
81
  .filter((c): c is TextContent => c.type === "text")
82
- .map((c) => c.text)
82
+ .map(c => c.text)
83
83
  .join("\n");
84
84
  }
85
85
 
@@ -1,5 +1,5 @@
1
- import { theme } from "@oh-my-pi/pi-coding-agent/modes/theme/theme";
2
1
  import * as Diff from "diff";
2
+ import { theme } from "../../modes/theme/theme";
3
3
 
4
4
  /**
5
5
  * Parse diff line to extract prefix, line number, and content.
@@ -1,5 +1,5 @@
1
- import { theme } from "@oh-my-pi/pi-coding-agent/modes/theme/theme";
2
1
  import type { Component } from "@oh-my-pi/pi-tui";
2
+ import { theme } from "../../modes/theme/theme";
3
3
 
4
4
  /**
5
5
  * Dynamic border component that adjusts to viewport width.
@@ -11,7 +11,7 @@ import type { Component } from "@oh-my-pi/pi-tui";
11
11
  export class DynamicBorder implements Component {
12
12
  private color: (str: string) => string;
13
13
 
14
- constructor(color: (str: string) => string = (str) => theme.fg("border", str)) {
14
+ constructor(color: (str: string) => string = str => theme.fg("border", str)) {
15
15
  this.color = color;
16
16
  }
17
17
 
@@ -11,11 +11,10 @@
11
11
  * - Space: Toggle selected item (or master switch)
12
12
  * - Esc: Close dashboard (clears search first if active)
13
13
  */
14
-
15
- import type { SettingsManager } from "@oh-my-pi/pi-coding-agent/config/settings-manager";
16
- import { DynamicBorder } from "@oh-my-pi/pi-coding-agent/modes/components/dynamic-border";
17
- import { theme } from "@oh-my-pi/pi-coding-agent/modes/theme/theme";
18
14
  import { type Component, Container, matchesKey, Spacer, Text, truncateToWidth, visibleWidth } from "@oh-my-pi/pi-tui";
15
+ import type { SettingsManager } from "../../../config/settings-manager";
16
+ import { DynamicBorder } from "../../../modes/components/dynamic-border";
17
+ import { theme } from "../../../modes/theme/theme";
19
18
  import { ExtensionList } from "./extension-list";
20
19
  import { InspectorPanel } from "./inspector-panel";
21
20
  import { applyFilter, createInitialState, filterByProvider, refreshState, toggleProvider } from "./state-manager";
@@ -60,14 +59,14 @@ export class ExtensionDashboard extends Container {
60
59
  this.mainList = new ExtensionList(
61
60
  this.state.searchFiltered,
62
61
  {
63
- onSelectionChange: (ext) => {
62
+ onSelectionChange: ext => {
64
63
  this.state.selected = ext;
65
64
  this.inspector.setExtension(ext);
66
65
  },
67
66
  onToggle: (extensionId, enabled) => {
68
67
  this.handleExtensionToggle(extensionId, enabled);
69
68
  },
70
- onMasterToggle: (providerId) => {
69
+ onMasterToggle: providerId => {
71
70
  this.handleProviderToggle(providerId);
72
71
  },
73
72
  masterSwitchProvider: this.getActiveProviderId(),
@@ -176,7 +175,7 @@ export class ExtensionDashboard extends Container {
176
175
 
177
176
  // Find the same tab in the new (re-sorted) list
178
177
  if (currentTabId) {
179
- const newIndex = this.state.tabs.findIndex((t) => t.id === currentTabId);
178
+ const newIndex = this.state.tabs.findIndex(t => t.id === currentTabId);
180
179
  if (newIndex >= 0) {
181
180
  this.state.activeTabIndex = newIndex;
182
181
  }
@@ -5,10 +5,9 @@
5
5
  * that toggles the entire provider. All items below are dimmed when the
6
6
  * master switch is off.
7
7
  */
8
-
9
- import { isProviderEnabled } from "@oh-my-pi/pi-coding-agent/discovery";
10
- import { theme } from "@oh-my-pi/pi-coding-agent/modes/theme/theme";
11
8
  import { type Component, matchesKey, truncateToWidth, visibleWidth } from "@oh-my-pi/pi-tui";
9
+ import { isProviderEnabled } from "../../../discovery";
10
+ import { theme } from "../../../modes/theme/theme";
12
11
  import { applyFilter } from "./state-manager";
13
12
  import type { Extension, ExtensionKind, ExtensionState } from "./types";
14
13
 
@@ -3,10 +3,9 @@
3
3
  *
4
4
  * Shows name, description, origin, status, and kind-specific preview.
5
5
  */
6
-
7
- import { homedir } from "node:os";
8
- import { theme } from "@oh-my-pi/pi-coding-agent/modes/theme/theme";
6
+ import * as os from "node:os";
9
7
  import { type Component, truncateToWidth, wrapTextWithAnsi } from "@oh-my-pi/pi-tui";
8
+ import { theme } from "../../../modes/theme/theme";
10
9
  import type { Extension, ExtensionState } from "./types";
11
10
 
12
11
  export class InspectorPanel implements Component {
@@ -304,7 +303,7 @@ export class InspectorPanel implements Component {
304
303
  }
305
304
 
306
305
  private shortenPath(path: string): string {
307
- const home = homedir();
306
+ const home = os.homedir();
308
307
  if (home && path.startsWith(home)) {
309
308
  return `~${path.slice(home.length)}`;
310
309
  }