@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/ipy/kernel.ts CHANGED
@@ -1,11 +1,12 @@
1
1
  import { createServer } from "node:net";
2
- import { delimiter, join } from "node:path";
3
- import { getShellConfig, killProcessTree } from "@oh-my-pi/pi-coding-agent/utils/shell";
4
- import { getOrCreateSnapshot } from "@oh-my-pi/pi-coding-agent/utils/shell-snapshot";
5
- import { htmlToBasicMarkdown } from "@oh-my-pi/pi-coding-agent/web/scrapers/types";
2
+ import * as path from "node:path";
6
3
  import { logger } from "@oh-my-pi/pi-utils";
7
4
  import { $, type Subprocess } from "bun";
8
5
  import { nanoid } from "nanoid";
6
+ import { getShellConfig, killProcessTree } from "../utils/shell";
7
+ import { getOrCreateSnapshot } from "../utils/shell-snapshot";
8
+ import { time } from "../utils/timings";
9
+ import { htmlToBasicMarkdown } from "../web/scrapers/types";
9
10
  import { acquireSharedGateway, releaseSharedGateway } from "./gateway-coordinator";
10
11
  import { loadPythonModules } from "./modules";
11
12
  import { PYTHON_PRELUDE } from "./prelude";
@@ -131,13 +132,13 @@ const BASE_ENV_ALLOWLIST = CASE_INSENSITIVE_ENV
131
132
  ? new Set([...DEFAULT_ENV_ALLOWLIST, ...WINDOWS_ENV_ALLOWLIST])
132
133
  : DEFAULT_ENV_ALLOWLIST;
133
134
  const NORMALIZED_ALLOWLIST = new Set(
134
- Array.from(BASE_ENV_ALLOWLIST, (key) => (CASE_INSENSITIVE_ENV ? key.toUpperCase() : key)),
135
+ Array.from(BASE_ENV_ALLOWLIST, key => (CASE_INSENSITIVE_ENV ? key.toUpperCase() : key)),
135
136
  );
136
137
  const NORMALIZED_DENYLIST = new Set(
137
- Array.from(DEFAULT_ENV_DENYLIST, (key) => (CASE_INSENSITIVE_ENV ? key.toUpperCase() : key)),
138
+ Array.from(DEFAULT_ENV_DENYLIST, key => (CASE_INSENSITIVE_ENV ? key.toUpperCase() : key)),
138
139
  );
139
140
  const NORMALIZED_ALLOW_PREFIXES = CASE_INSENSITIVE_ENV
140
- ? DEFAULT_ENV_ALLOW_PREFIXES.map((prefix) => prefix.toUpperCase())
141
+ ? DEFAULT_ENV_ALLOW_PREFIXES.map(prefix => prefix.toUpperCase())
141
142
  : DEFAULT_ENV_ALLOW_PREFIXES;
142
143
 
143
144
  function normalizeEnvKey(key: string): string {
@@ -146,7 +147,7 @@ function normalizeEnvKey(key: string): string {
146
147
 
147
148
  function resolvePathKey(env: Record<string, string | undefined>): string {
148
149
  if (!CASE_INSENSITIVE_ENV) return "PATH";
149
- const match = Object.keys(env).find((candidate) => candidate.toLowerCase() === "path");
150
+ const match = Object.keys(env).find(candidate => candidate.toLowerCase() === "path");
150
151
  return match ?? "PATH";
151
152
  }
152
153
 
@@ -230,7 +231,7 @@ function filterEnv(env: Record<string, string | undefined>): Record<string, stri
230
231
  filtered[destKey] = value;
231
232
  continue;
232
233
  }
233
- if (NORMALIZED_ALLOW_PREFIXES.some((prefix) => normalizedKey.startsWith(prefix))) {
234
+ if (NORMALIZED_ALLOW_PREFIXES.some(prefix => normalizedKey.startsWith(prefix))) {
234
235
  filtered[key] = value;
235
236
  }
236
237
  }
@@ -239,7 +240,7 @@ function filterEnv(env: Record<string, string | undefined>): Record<string, stri
239
240
 
240
241
  async function resolveVenvPath(cwd: string): Promise<string | null> {
241
242
  if (process.env.VIRTUAL_ENV) return process.env.VIRTUAL_ENV;
242
- const candidates = [join(cwd, ".venv"), join(cwd, "venv")];
243
+ const candidates = [path.join(cwd, ".venv"), path.join(cwd, "venv")];
243
244
  for (const candidate of candidates) {
244
245
  if (await Bun.file(candidate).exists()) {
245
246
  return candidate;
@@ -253,12 +254,12 @@ async function resolvePythonRuntime(cwd: string, baseEnv: Record<string, string
253
254
  const venvPath = env.VIRTUAL_ENV ?? (await resolveVenvPath(cwd));
254
255
  if (venvPath) {
255
256
  env.VIRTUAL_ENV = venvPath;
256
- const binDir = process.platform === "win32" ? join(venvPath, "Scripts") : join(venvPath, "bin");
257
- const pythonCandidate = join(binDir, process.platform === "win32" ? "python.exe" : "python");
257
+ const binDir = process.platform === "win32" ? path.join(venvPath, "Scripts") : path.join(venvPath, "bin");
258
+ const pythonCandidate = path.join(binDir, process.platform === "win32" ? "python.exe" : "python");
258
259
  if (await Bun.file(pythonCandidate).exists()) {
259
260
  const pathKey = resolvePathKey(env);
260
261
  const currentPath = env[pathKey];
261
- env[pathKey] = currentPath ? `${binDir}${delimiter}${currentPath}` : binDir;
262
+ env[pathKey] = currentPath ? `${binDir}${path.delimiter}${currentPath}` : binDir;
262
263
  return { pythonPath: pythonCandidate, env };
263
264
  }
264
265
  }
@@ -309,13 +310,11 @@ async function checkExternalGatewayAvailability(config: ExternalGatewayConfig):
309
310
  }
310
311
 
311
312
  const controller = new AbortController();
312
- const timeout = setTimeout(() => controller.abort(), 5000);
313
313
 
314
314
  const response = await fetch(`${config.url}/api/kernelspecs`, {
315
315
  headers,
316
- signal: controller.signal,
316
+ signal: AbortSignal.any([controller.signal, AbortSignal.timeout(5000)]),
317
317
  });
318
- clearTimeout(timeout);
319
318
 
320
319
  if (response.ok) {
321
320
  return { ok: true };
@@ -505,6 +504,7 @@ export class PythonKernel {
505
504
 
506
505
  static async start(options: KernelStartOptions): Promise<PythonKernel> {
507
506
  const availability = await checkPythonKernelAvailability(options.cwd);
507
+ time("PythonKernel.start:availabilityCheck");
508
508
  if (!availability.ok) {
509
509
  throw new Error(availability.reason ?? "Python kernel unavailable");
510
510
  }
@@ -518,8 +518,11 @@ export class PythonKernel {
518
518
  if (options.useSharedGateway !== false) {
519
519
  try {
520
520
  const sharedResult = await acquireSharedGateway(options.cwd);
521
+ time("PythonKernel.start:acquireSharedGateway");
521
522
  if (sharedResult) {
522
- return PythonKernel.startWithSharedGateway(sharedResult.url, options.cwd, options.env);
523
+ const kernel = await PythonKernel.startWithSharedGateway(sharedResult.url, options.cwd, options.env);
524
+ time("PythonKernel.start:startWithSharedGateway");
525
+ return kernel;
523
526
  }
524
527
  } catch (err) {
525
528
  logger.warn("Failed to acquire shared gateway, falling back to local", {
@@ -582,6 +585,7 @@ export class PythonKernel {
582
585
  headers: { "Content-Type": "application/json" },
583
586
  body: JSON.stringify({ name: "python3" }),
584
587
  });
588
+ time("startWithSharedGateway:createKernel");
585
589
 
586
590
  if (!createResponse.ok) {
587
591
  await releaseSharedGateway();
@@ -595,13 +599,17 @@ export class PythonKernel {
595
599
 
596
600
  try {
597
601
  await kernel.connectWebSocket();
602
+ time("startWithSharedGateway:connectWS");
598
603
  await kernel.initializeKernelEnvironment(cwd, env);
604
+ time("startWithSharedGateway:initEnv");
599
605
  kernel.startHeartbeat();
600
606
  const preludeResult = await kernel.execute(PYTHON_PRELUDE, { silent: true, storeHistory: false });
607
+ time("startWithSharedGateway:prelude");
601
608
  if (preludeResult.cancelled || preludeResult.status === "error") {
602
609
  throw new Error("Failed to initialize Python kernel prelude");
603
610
  }
604
611
  await loadPythonModules(kernel, { cwd });
612
+ time("startWithSharedGateway:loadModules");
605
613
  return kernel;
606
614
  } catch (err: unknown) {
607
615
  await kernel.shutdown();
@@ -627,7 +635,7 @@ export class PythonKernel {
627
635
  OMP_SHELL_SNAPSHOT: snapshotPath ?? undefined,
628
636
  };
629
637
 
630
- const pythonPathParts = [options.cwd, kernelEnv.PYTHONPATH].filter(Boolean).join(delimiter);
638
+ const pythonPathParts = [options.cwd, kernelEnv.PYTHONPATH].filter(Boolean).join(path.delimiter);
631
639
  if (pythonPathParts) {
632
640
  kernelEnv.PYTHONPATH = pythonPathParts;
633
641
  }
@@ -754,7 +762,7 @@ export class PythonKernel {
754
762
  resolve();
755
763
  };
756
764
 
757
- ws.onerror = (event) => {
765
+ ws.onerror = event => {
758
766
  const error = new Error(`WebSocket error: ${event}`);
759
767
  if (!settled) {
760
768
  settled = true;
@@ -779,7 +787,7 @@ export class PythonKernel {
779
787
  this.abortPendingExecutions("WebSocket closed");
780
788
  };
781
789
 
782
- ws.onmessage = (event) => {
790
+ ws.onmessage = event => {
783
791
  let msg: JupyterMessage | null = null;
784
792
  if (event.data instanceof ArrayBuffer) {
785
793
  msg = deserializeWebSocketMessage(event.data);
@@ -950,7 +958,7 @@ export class PythonKernel {
950
958
  return promise;
951
959
  }
952
960
 
953
- this.#messageHandlers.set(msgId, async (response) => {
961
+ this.#messageHandlers.set(msgId, async response => {
954
962
  switch (response.header.msg_type) {
955
963
  case "execute_reply": {
956
964
  replyReceived = true;
@@ -1045,7 +1053,7 @@ export class PythonKernel {
1045
1053
  const result = await this.execute(PRELUDE_INTROSPECTION_SNIPPET, {
1046
1054
  silent: false,
1047
1055
  storeHistory: false,
1048
- onChunk: (text) => {
1056
+ onChunk: text => {
1049
1057
  output += text;
1050
1058
  },
1051
1059
  });
@@ -1064,14 +1072,11 @@ export class PythonKernel {
1064
1072
 
1065
1073
  async interrupt(): Promise<void> {
1066
1074
  try {
1067
- const controller = new AbortController();
1068
- const timeout = setTimeout(() => controller.abort(), 2000);
1069
1075
  await fetch(`${this.gatewayUrl}/api/kernels/${this.kernelId}/interrupt`, {
1070
1076
  method: "POST",
1071
1077
  headers: this.#authHeaders(),
1072
- signal: controller.signal,
1078
+ signal: AbortSignal.timeout(2000),
1073
1079
  });
1074
- clearTimeout(timeout);
1075
1080
  } catch (err: unknown) {
1076
1081
  logger.warn("Failed to interrupt kernel via API", { error: err instanceof Error ? err.message : String(err) });
1077
1082
  }
@@ -1138,13 +1143,10 @@ export class PythonKernel {
1138
1143
  async ping(timeoutMs: number = HEARTBEAT_TIMEOUT_MS): Promise<boolean> {
1139
1144
  if (!this.isAlive()) return false;
1140
1145
  try {
1141
- const controller = new AbortController();
1142
- const timeout = setTimeout(() => controller.abort(), timeoutMs);
1143
1146
  const response = await fetch(`${this.gatewayUrl}/api/kernels/${this.kernelId}`, {
1144
- signal: controller.signal,
1147
+ signal: AbortSignal.timeout(timeoutMs),
1145
1148
  headers: this.#authHeaders(),
1146
1149
  });
1147
- clearTimeout(timeout);
1148
1150
  if (response.ok) {
1149
1151
  this.#heartbeatFailures = 0;
1150
1152
  return true;
@@ -1,6 +1,6 @@
1
- import { readdir } from "node:fs/promises";
2
- import { homedir } from "node:os";
3
- import { join, resolve } from "node:path";
1
+ import * as fs from "node:fs/promises";
2
+ import * as os from "node:os";
3
+ import * as path from "node:path";
4
4
 
5
5
  export type PythonModuleSource = "user" | "project";
6
6
 
@@ -38,12 +38,12 @@ interface ModuleCandidate {
38
38
 
39
39
  async function listModuleCandidates(dir: string, source: PythonModuleSource): Promise<ModuleCandidate[]> {
40
40
  try {
41
- const entries = await readdir(dir, { withFileTypes: true });
41
+ const entries = await fs.readdir(dir, { withFileTypes: true });
42
42
  return entries
43
- .filter((entry) => entry.isFile() && entry.name.endsWith(".py"))
44
- .map((entry) => ({
43
+ .filter(entry => entry.isFile() && entry.name.endsWith(".py"))
44
+ .map(entry => ({
45
45
  name: entry.name,
46
- path: resolve(dir, entry.name),
46
+ path: path.resolve(dir, entry.name),
47
47
  source,
48
48
  }));
49
49
  } catch {
@@ -66,13 +66,13 @@ async function readModuleContent(candidate: ModuleCandidate): Promise<PythonModu
66
66
  */
67
67
  export async function discoverPythonModules(options: DiscoverPythonModulesOptions = {}): Promise<PythonModuleEntry[]> {
68
68
  const cwd = options.cwd ?? process.cwd();
69
- const homeDir = options.homeDir ?? homedir();
69
+ const homeDir = options.homeDir ?? os.homedir();
70
70
 
71
- const userDirs = [join(homeDir, ".omp", "agent", "modules"), join(homeDir, ".pi", "agent", "modules")];
72
- const projectDirs = [resolve(cwd, ".omp", "modules"), resolve(cwd, ".pi", "modules")];
71
+ const userDirs = [path.join(homeDir, ".omp", "agent", "modules"), path.join(homeDir, ".pi", "agent", "modules")];
72
+ const projectDirs = [path.resolve(cwd, ".omp", "modules"), path.resolve(cwd, ".pi", "modules")];
73
73
 
74
- const userCandidates = (await Promise.all(userDirs.map((dir) => listModuleCandidates(dir, "user")))).flat();
75
- const projectCandidates = (await Promise.all(projectDirs.map((dir) => listModuleCandidates(dir, "project")))).flat();
74
+ const userCandidates = (await Promise.all(userDirs.map(dir => listModuleCandidates(dir, "user")))).flat();
75
+ const projectCandidates = (await Promise.all(projectDirs.map(dir => listModuleCandidates(dir, "project")))).flat();
76
76
 
77
77
  const byName = new Map<string, ModuleCandidate>();
78
78
  for (const candidate of userCandidates) {
@@ -88,7 +88,7 @@ export async function discoverPythonModules(options: DiscoverPythonModulesOption
88
88
  }
89
89
 
90
90
  const sorted = Array.from(byName.values()).sort((a, b) => a.name.localeCompare(b.name));
91
- return Promise.all(sorted.map((candidate) => readModuleContent(candidate)));
91
+ return Promise.all(sorted.map(candidate => readModuleContent(candidate)));
92
92
  }
93
93
 
94
94
  /**
package/src/lsp/client.ts CHANGED
@@ -1,6 +1,5 @@
1
- import * as fs from "node:fs";
2
- import { ToolAbortError, throwIfAborted } from "@oh-my-pi/pi-coding-agent/tools/tool-errors";
3
- import { logger } from "@oh-my-pi/pi-utils";
1
+ import { isEnoent, logger } from "@oh-my-pi/pi-utils";
2
+ import { ToolAbortError, throwIfAborted } from "../tools/tool-errors";
4
3
  import { applyWorkspaceEdit } from "./edits";
5
4
  import { getLspmuxCommand, isLspmuxSupported } from "./lspmux";
6
5
  import type {
@@ -298,7 +297,7 @@ async function handleConfigurationRequest(client: LspClient, message: LspJsonRpc
298
297
  if (typeof message.id !== "number") return;
299
298
  const params = message.params as { items?: Array<{ section?: string }> };
300
299
  const items = params?.items ?? [];
301
- const result = items.map((item) => {
300
+ const result = items.map(item => {
302
301
  const section = item.section ?? "";
303
302
  return client.config.settings?.[section] ?? {};
304
303
  });
@@ -512,7 +511,13 @@ export async function ensureFileOpen(client: LspClient, filePath: string): Promi
512
511
  return;
513
512
  }
514
513
 
515
- const content = fs.readFileSync(filePath, "utf-8");
514
+ let content: string;
515
+ try {
516
+ content = await Bun.file(filePath).text();
517
+ } catch (err) {
518
+ if (isEnoent(err)) return;
519
+ throw err;
520
+ }
516
521
  const languageId = detectLanguageId(filePath);
517
522
 
518
523
  await sendNotification(client, "textDocument/didOpen", {
@@ -634,7 +639,13 @@ export async function refreshFile(client: LspClient, filePath: string): Promise<
634
639
  return;
635
640
  }
636
641
 
637
- const content = fs.readFileSync(filePath, "utf-8");
642
+ let content: string;
643
+ try {
644
+ content = await Bun.file(filePath).text();
645
+ } catch (err) {
646
+ if (isEnoent(err)) return;
647
+ throw err;
648
+ }
638
649
  const version = ++info.version;
639
650
 
640
651
  await sendNotification(client, "textDocument/didChange", {
@@ -748,12 +759,12 @@ export async function sendRequest(
748
759
 
749
760
  // Register pending request with timeout wrapper
750
761
  client.pendingRequests.set(id, {
751
- resolve: (result) => {
762
+ resolve: result => {
752
763
  if (timeout) clearTimeout(timeout);
753
764
  cleanup();
754
765
  resolve(result);
755
766
  },
756
- reject: (err) => {
767
+ reject: err => {
757
768
  if (timeout) clearTimeout(timeout);
758
769
  cleanup();
759
770
  reject(err);
@@ -762,7 +773,7 @@ export async function sendRequest(
762
773
  });
763
774
 
764
775
  // Write request
765
- writeMessage(client.process.stdin as import("bun").FileSink, request).catch((err) => {
776
+ writeMessage(client.process.stdin as import("bun").FileSink, request).catch(err => {
766
777
  if (timeout) clearTimeout(timeout);
767
778
  client.pendingRequests.delete(id);
768
779
  cleanup();
@@ -816,7 +827,7 @@ export interface LspServerStatus {
816
827
  * Get status of all active LSP clients.
817
828
  */
818
829
  export function getActiveClients(): LspServerStatus[] {
819
- return Array.from(clients.values()).map((client) => ({
830
+ return Array.from(clients.values()).map(client => ({
820
831
  name: client.config.command,
821
832
  status: "ready" as const,
822
833
  fileTypes: client.config.fileTypes,
@@ -2,9 +2,8 @@
2
2
  * Biome CLI-based linter client.
3
3
  * Uses Biome's CLI with JSON output instead of LSP (which has stale diagnostics issues).
4
4
  */
5
-
6
5
  import path from "node:path";
7
- import type { Diagnostic, DiagnosticSeverity, LinterClient, ServerConfig } from "@oh-my-pi/pi-coding-agent/lsp/types";
6
+ import type { Diagnostic, DiagnosticSeverity, LinterClient, ServerConfig } from "../../lsp/types";
8
7
 
9
8
  // =============================================================================
10
9
  // Biome JSON Output Types
@@ -1,3 +1,6 @@
1
+ import type { LinterClient, ServerConfig } from "../../lsp/types";
2
+ import { LspLinterClient } from "./lsp-linter-client";
3
+
1
4
  /**
2
5
  * Linter client implementations.
3
6
  *
@@ -8,9 +11,6 @@
8
11
  export { BiomeClient } from "./biome-client";
9
12
  export { LspLinterClient } from "./lsp-linter-client";
10
13
 
11
- import type { LinterClient, ServerConfig } from "@oh-my-pi/pi-coding-agent/lsp/types";
12
- import { LspLinterClient } from "./lsp-linter-client";
13
-
14
14
  // Cache of linter clients by server name + cwd
15
15
  const clientCache = new Map<string, LinterClient>();
16
16
 
@@ -2,11 +2,10 @@
2
2
  * LSP-based linter client.
3
3
  * Uses the Language Server Protocol for formatting and diagnostics.
4
4
  */
5
-
6
- import { getOrCreateClient, notifySaved, sendRequest, syncContent } from "@oh-my-pi/pi-coding-agent/lsp/client";
7
- import { applyTextEditsToString } from "@oh-my-pi/pi-coding-agent/lsp/edits";
8
- import type { Diagnostic, LinterClient, LspClient, ServerConfig, TextEdit } from "@oh-my-pi/pi-coding-agent/lsp/types";
9
- import { fileToUri } from "@oh-my-pi/pi-coding-agent/lsp/utils";
5
+ import { getOrCreateClient, notifySaved, sendRequest, syncContent } from "../../lsp/client";
6
+ import { applyTextEditsToString } from "../../lsp/edits";
7
+ import type { Diagnostic, LinterClient, LspClient, ServerConfig, TextEdit } from "../../lsp/types";
8
+ import { fileToUri } from "../../lsp/utils";
10
9
 
11
10
  /** Default formatting options for LSP */
12
11
  const DEFAULT_FORMAT_OPTIONS = {
package/src/lsp/config.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { homedir } from "node:os";
2
- import { basename, extname, join } from "node:path";
3
- import { getConfigDirPaths } from "@oh-my-pi/pi-coding-agent/config";
1
+ import * as os from "node:os";
2
+ import * as path from "node:path";
4
3
  import { logger } from "@oh-my-pi/pi-utils";
5
4
  import { YAML } from "bun";
6
5
  import { globSync } from "glob";
6
+ import { getConfigDirPaths } from "../config";
7
7
  import { BiomeClient } from "./clients/biome-client";
8
8
  import DEFAULTS from "./defaults.json" with { type: "json" };
9
9
  import type { ServerConfig } from "./types";
@@ -30,7 +30,7 @@ function isRecord(value: unknown): value is Record<string, unknown> {
30
30
  }
31
31
 
32
32
  function parseConfigContent(content: string, filePath: string): unknown {
33
- const extension = extname(filePath).toLowerCase();
33
+ const extension = path.extname(filePath).toLowerCase();
34
34
  if (extension === ".yaml" || extension === ".yml") {
35
35
  return YAML.parse(content) as unknown;
36
36
  }
@@ -141,7 +141,7 @@ function applyRuntimeDefaults(servers: Record<string, ServerConfig>): Record<str
141
141
  }
142
142
 
143
143
  if (updated.omnisharp?.args) {
144
- const args = updated.omnisharp.args.map((arg) => (arg === PID_TOKEN ? String(process.pid) : arg));
144
+ const args = updated.omnisharp.args.map(arg => (arg === PID_TOKEN ? String(process.pid) : arg));
145
145
  updated.omnisharp = { ...updated.omnisharp, args };
146
146
  }
147
147
 
@@ -160,7 +160,7 @@ export async function hasRootMarkers(cwd: string, markers: string[]): Promise<bo
160
160
  // Handle glob-like patterns (e.g., "*.cabal")
161
161
  if (marker.includes("*")) {
162
162
  try {
163
- const matches = globSync(join(cwd, marker));
163
+ const matches = globSync(path.join(cwd, marker));
164
164
  if (matches.length > 0) {
165
165
  return true;
166
166
  }
@@ -169,7 +169,7 @@ export async function hasRootMarkers(cwd: string, markers: string[]): Promise<bo
169
169
  }
170
170
  continue;
171
171
  }
172
- const filePath = join(cwd, marker);
172
+ const filePath = path.join(cwd, marker);
173
173
  if (await Bun.file(filePath).exists()) {
174
174
  return true;
175
175
  }
@@ -211,7 +211,7 @@ export async function resolveCommand(command: string, cwd: string): Promise<stri
211
211
  // Check local bin directories based on project markers
212
212
  for (const { markers, binDir } of LOCAL_BIN_PATHS) {
213
213
  if (await hasRootMarkers(cwd, markers)) {
214
- const localPath = join(cwd, binDir, command);
214
+ const localPath = path.join(cwd, binDir, command);
215
215
  if (await Bun.file(localPath).exists()) {
216
216
  return localPath;
217
217
  }
@@ -232,14 +232,14 @@ function getConfigPaths(cwd: string): string[] {
232
232
 
233
233
  // Project root files (highest priority)
234
234
  for (const filename of filenames) {
235
- paths.push(join(cwd, filename));
235
+ paths.push(path.join(cwd, filename));
236
236
  }
237
237
 
238
238
  // Project config directories (.omp/, .pi/, .claude/)
239
239
  const projectDirs = getConfigDirPaths("", { user: false, project: true, cwd });
240
240
  for (const dir of projectDirs) {
241
241
  for (const filename of filenames) {
242
- paths.push(join(dir, filename));
242
+ paths.push(path.join(dir, filename));
243
243
  }
244
244
  }
245
245
 
@@ -247,13 +247,13 @@ function getConfigPaths(cwd: string): string[] {
247
247
  const userDirs = getConfigDirPaths("", { user: true, project: false });
248
248
  for (const dir of userDirs) {
249
249
  for (const filename of filenames) {
250
- paths.push(join(dir, filename));
250
+ paths.push(path.join(dir, filename));
251
251
  }
252
252
  }
253
253
 
254
254
  // User home root files (lowest priority fallback)
255
255
  for (const filename of filenames) {
256
- paths.push(join(homedir(), filename));
256
+ paths.push(path.join(os.homedir(), filename));
257
257
  }
258
258
 
259
259
  return paths;
@@ -352,12 +352,12 @@ export async function loadConfig(cwd: string): Promise<LspConfig> {
352
352
  * Returns servers sorted with primary (non-linter) servers first.
353
353
  */
354
354
  export function getServersForFile(config: LspConfig, filePath: string): Array<[string, ServerConfig]> {
355
- const ext = extname(filePath).toLowerCase();
356
- const fileName = basename(filePath).toLowerCase();
355
+ const ext = path.extname(filePath).toLowerCase();
356
+ const fileName = path.basename(filePath).toLowerCase();
357
357
  const matches: Array<[string, ServerConfig]> = [];
358
358
 
359
359
  for (const [name, serverConfig] of Object.entries(config.servers)) {
360
- const supportsFile = serverConfig.fileTypes.some((fileType) => {
360
+ const supportsFile = serverConfig.fileTypes.some(fileType => {
361
361
  const normalized = fileType.toLowerCase();
362
362
  return normalized === ext || normalized === fileName;
363
363
  });
package/src/lsp/edits.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { mkdir, rename, rm } from "node:fs/promises";
1
+ import * as fs from "node:fs/promises";
2
2
  import path from "node:path";
3
3
  import type { CreateFile, DeleteFile, RenameFile, TextDocumentEdit, TextEdit, WorkspaceEdit } from "./types";
4
4
  import { uriToFile } from "./utils";
@@ -86,20 +86,19 @@ export async function applyWorkspaceEdit(edit: WorkspaceEdit, cwd: string): Prom
86
86
  if (change.kind === "create") {
87
87
  const createOp = change as CreateFile;
88
88
  const filePath = uriToFile(createOp.uri);
89
- await mkdir(path.dirname(filePath), { recursive: true });
90
89
  await Bun.write(filePath, "");
91
90
  applied.push(`Created ${path.relative(cwd, filePath)}`);
92
91
  } else if (change.kind === "rename") {
93
92
  const renameOp = change as RenameFile;
94
93
  const oldPath = uriToFile(renameOp.oldUri);
95
94
  const newPath = uriToFile(renameOp.newUri);
96
- await mkdir(path.dirname(newPath), { recursive: true });
97
- await rename(oldPath, newPath);
95
+ await fs.mkdir(path.dirname(newPath), { recursive: true });
96
+ await fs.rename(oldPath, newPath);
98
97
  applied.push(`Renamed ${path.relative(cwd, oldPath)} → ${path.relative(cwd, newPath)}`);
99
98
  } else if (change.kind === "delete") {
100
99
  const deleteOp = change as DeleteFile;
101
100
  const filePath = uriToFile(deleteOp.uri);
102
- await rm(filePath, { recursive: true });
101
+ await fs.rm(filePath, { recursive: true });
103
102
  applied.push(`Deleted ${path.relative(cwd, filePath)}`);
104
103
  }
105
104
  }