@oh-my-pi/pi-coding-agent 8.1.0 → 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 (402) hide show
  1. package/CHANGELOG.md +21 -1
  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 +51 -23
  38. package/scripts/format-prompts.ts +0 -1
  39. package/src/capability/context-file.ts +2 -3
  40. package/src/capability/extension-module.ts +2 -3
  41. package/src/capability/extension.ts +2 -3
  42. package/src/capability/fs.ts +20 -21
  43. package/src/capability/hook.ts +2 -3
  44. package/src/capability/index.ts +15 -16
  45. package/src/capability/instruction.ts +2 -3
  46. package/src/capability/mcp.ts +2 -3
  47. package/src/capability/prompt.ts +2 -3
  48. package/src/capability/rule.ts +2 -3
  49. package/src/capability/settings.ts +1 -2
  50. package/src/capability/skill.ts +2 -3
  51. package/src/capability/slash-command.ts +2 -3
  52. package/src/capability/ssh.ts +2 -3
  53. package/src/capability/system-prompt.ts +2 -3
  54. package/src/capability/tool.ts +2 -3
  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 -21
  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 +21 -23
  66. package/src/commit/agentic/fallback.ts +9 -9
  67. package/src/commit/agentic/index.ts +30 -38
  68. package/src/commit/agentic/state.ts +1 -6
  69. package/src/commit/agentic/tools/analyze-file.ts +15 -15
  70. package/src/commit/agentic/tools/git-file-diff.ts +3 -3
  71. package/src/commit/agentic/tools/git-hunk.ts +7 -7
  72. package/src/commit/agentic/tools/git-overview.ts +5 -5
  73. package/src/commit/agentic/tools/index.ts +14 -14
  74. package/src/commit/agentic/tools/propose-changelog.ts +6 -6
  75. package/src/commit/agentic/tools/propose-commit.ts +8 -8
  76. package/src/commit/agentic/tools/recent-commits.ts +2 -2
  77. package/src/commit/agentic/tools/split-commit.ts +19 -23
  78. package/src/commit/agentic/topo-sort.ts +1 -1
  79. package/src/commit/agentic/trivial.ts +3 -3
  80. package/src/commit/agentic/validation.ts +12 -12
  81. package/src/commit/analysis/conventional.ts +7 -11
  82. package/src/commit/analysis/index.ts +4 -4
  83. package/src/commit/analysis/scope.ts +4 -4
  84. package/src/commit/analysis/summary.ts +7 -9
  85. package/src/commit/analysis/validation.ts +1 -1
  86. package/src/commit/changelog/detect.ts +6 -6
  87. package/src/commit/changelog/generate.ts +7 -9
  88. package/src/commit/changelog/index.ts +13 -13
  89. package/src/commit/changelog/parse.ts +2 -2
  90. package/src/commit/cli.ts +1 -1
  91. package/src/commit/git/diff.ts +3 -3
  92. package/src/commit/git/index.ts +19 -24
  93. package/src/commit/index.ts +1 -1
  94. package/src/commit/map-reduce/index.ts +9 -9
  95. package/src/commit/map-reduce/map-phase.ts +19 -34
  96. package/src/commit/map-reduce/reduce-phase.ts +9 -11
  97. package/src/commit/message.ts +2 -2
  98. package/src/commit/model-selection.ts +3 -7
  99. package/src/commit/pipeline.ts +20 -22
  100. package/src/commit/utils/exclusions.ts +3 -3
  101. package/src/config/file-lock.ts +17 -7
  102. package/src/config/keybindings.ts +6 -8
  103. package/src/config/model-registry.ts +55 -37
  104. package/src/config/model-resolver.ts +18 -19
  105. package/src/config/prompt-templates.ts +11 -11
  106. package/src/config/settings-manager.ts +50 -34
  107. package/src/config.ts +60 -62
  108. package/src/cursor.ts +11 -9
  109. package/src/discovery/agents-md.ts +11 -12
  110. package/src/discovery/builtin.ts +68 -73
  111. package/src/discovery/claude.ts +41 -42
  112. package/src/discovery/cline.ts +11 -12
  113. package/src/discovery/codex.ts +52 -53
  114. package/src/discovery/cursor.ts +9 -10
  115. package/src/discovery/gemini.ts +17 -22
  116. package/src/discovery/github.ts +13 -14
  117. package/src/discovery/helpers.ts +35 -34
  118. package/src/discovery/index.ts +16 -18
  119. package/src/discovery/mcp-json.ts +8 -9
  120. package/src/discovery/ssh.ts +8 -9
  121. package/src/discovery/vscode.ts +4 -5
  122. package/src/discovery/windsurf.ts +6 -7
  123. package/src/exa/company.ts +1 -2
  124. package/src/exa/index.ts +2 -3
  125. package/src/exa/linkedin.ts +1 -2
  126. package/src/exa/mcp-client.ts +14 -16
  127. package/src/exa/render.ts +10 -11
  128. package/src/exa/researcher.ts +1 -2
  129. package/src/exa/search.ts +1 -2
  130. package/src/exa/types.ts +0 -1
  131. package/src/exa/websets.ts +1 -2
  132. package/src/exec/bash-executor.ts +3 -4
  133. package/src/exec/exec.ts +0 -1
  134. package/src/export/custom-share.ts +5 -6
  135. package/src/export/html/index.ts +24 -21
  136. package/src/export/ttsr.ts +2 -3
  137. package/src/extensibility/custom-commands/bundled/review/index.ts +7 -8
  138. package/src/extensibility/custom-commands/loader.ts +17 -14
  139. package/src/extensibility/custom-commands/types.ts +1 -2
  140. package/src/extensibility/custom-tools/loader.ts +10 -11
  141. package/src/extensibility/custom-tools/types.ts +6 -7
  142. package/src/extensibility/custom-tools/wrapper.ts +2 -3
  143. package/src/extensibility/extensions/loader.ts +75 -53
  144. package/src/extensibility/extensions/runner.ts +11 -12
  145. package/src/extensibility/extensions/types.ts +19 -26
  146. package/src/extensibility/extensions/wrapper.ts +3 -4
  147. package/src/extensibility/hooks/index.ts +1 -1
  148. package/src/extensibility/hooks/loader.ts +8 -9
  149. package/src/extensibility/hooks/runner.ts +7 -8
  150. package/src/extensibility/hooks/tool-wrapper.ts +0 -1
  151. package/src/extensibility/hooks/types.ts +10 -17
  152. package/src/extensibility/plugins/doctor.ts +3 -3
  153. package/src/extensibility/plugins/installer.ts +27 -27
  154. package/src/extensibility/plugins/loader.ts +59 -56
  155. package/src/extensibility/plugins/manager.ts +211 -171
  156. package/src/extensibility/plugins/parser.ts +1 -1
  157. package/src/extensibility/plugins/paths.ts +8 -8
  158. package/src/extensibility/skills.ts +63 -60
  159. package/src/extensibility/slash-commands.ts +10 -10
  160. package/src/index.ts +46 -46
  161. package/src/internal-urls/agent-protocol.ts +21 -11
  162. package/src/internal-urls/artifact-protocol.ts +17 -13
  163. package/src/internal-urls/router.ts +1 -2
  164. package/src/internal-urls/rule-protocol.ts +3 -4
  165. package/src/internal-urls/skill-protocol.ts +3 -4
  166. package/src/ipy/executor.ts +14 -10
  167. package/src/ipy/gateway-coordinator.ts +79 -90
  168. package/src/ipy/kernel.ts +32 -30
  169. package/src/ipy/modules.ts +13 -13
  170. package/src/lsp/client.ts +21 -10
  171. package/src/lsp/clients/biome-client.ts +1 -2
  172. package/src/lsp/clients/index.ts +3 -3
  173. package/src/lsp/clients/lsp-linter-client.ts +4 -5
  174. package/src/lsp/config.ts +15 -15
  175. package/src/lsp/edits.ts +4 -5
  176. package/src/lsp/index.ts +43 -44
  177. package/src/lsp/lspmux.ts +8 -8
  178. package/src/lsp/render.ts +10 -16
  179. package/src/lsp/utils.ts +3 -3
  180. package/src/main.ts +55 -34
  181. package/src/mcp/client.ts +2 -3
  182. package/src/mcp/config.ts +5 -6
  183. package/src/mcp/json-rpc.ts +0 -1
  184. package/src/mcp/loader.ts +3 -4
  185. package/src/mcp/manager.ts +17 -18
  186. package/src/mcp/tool-bridge.ts +4 -9
  187. package/src/mcp/tool-cache.ts +2 -3
  188. package/src/mcp/transports/http.ts +2 -4
  189. package/src/mcp/transports/stdio.ts +1 -2
  190. package/src/migrations.ts +60 -49
  191. package/src/modes/components/armin.ts +4 -5
  192. package/src/modes/components/assistant-message.ts +6 -6
  193. package/src/modes/components/bash-execution.ts +7 -8
  194. package/src/modes/components/bordered-loader.ts +3 -3
  195. package/src/modes/components/branch-summary-message.ts +3 -3
  196. package/src/modes/components/compaction-summary-message.ts +3 -3
  197. package/src/modes/components/countdown-timer.ts +0 -1
  198. package/src/modes/components/custom-message.ts +5 -5
  199. package/src/modes/components/diff.ts +1 -1
  200. package/src/modes/components/dynamic-border.ts +2 -2
  201. package/src/modes/components/extensions/extension-dashboard.ts +6 -7
  202. package/src/modes/components/extensions/extension-list.ts +2 -3
  203. package/src/modes/components/extensions/inspector-panel.ts +3 -4
  204. package/src/modes/components/extensions/state-manager.ts +25 -26
  205. package/src/modes/components/extensions/types.ts +1 -2
  206. package/src/modes/components/footer.ts +47 -43
  207. package/src/modes/components/history-search.ts +2 -2
  208. package/src/modes/components/hook-editor.ts +3 -4
  209. package/src/modes/components/hook-input.ts +2 -3
  210. package/src/modes/components/hook-message.ts +5 -5
  211. package/src/modes/components/hook-selector.ts +2 -3
  212. package/src/modes/components/keybinding-hints.ts +2 -3
  213. package/src/modes/components/login-dialog.ts +2 -2
  214. package/src/modes/components/model-selector.ts +12 -12
  215. package/src/modes/components/oauth-selector.ts +2 -2
  216. package/src/modes/components/plugin-settings.ts +20 -20
  217. package/src/modes/components/python-execution.ts +7 -8
  218. package/src/modes/components/queue-mode-selector.ts +3 -3
  219. package/src/modes/components/read-tool-group.ts +2 -2
  220. package/src/modes/components/session-selector.ts +4 -4
  221. package/src/modes/components/settings-defs.ts +77 -69
  222. package/src/modes/components/settings-selector.ts +16 -16
  223. package/src/modes/components/show-images-selector.ts +2 -2
  224. package/src/modes/components/status-line/segments.ts +4 -4
  225. package/src/modes/components/status-line/separators.ts +1 -1
  226. package/src/modes/components/status-line/types.ts +2 -2
  227. package/src/modes/components/status-line-segment-editor.ts +7 -8
  228. package/src/modes/components/status-line.ts +12 -12
  229. package/src/modes/components/theme-selector.ts +8 -7
  230. package/src/modes/components/thinking-selector.ts +4 -4
  231. package/src/modes/components/todo-display.ts +2 -2
  232. package/src/modes/components/todo-reminder.ts +4 -4
  233. package/src/modes/components/tool-execution.ts +11 -16
  234. package/src/modes/components/tree-selector.ts +11 -11
  235. package/src/modes/components/ttsr-notification.ts +5 -5
  236. package/src/modes/components/user-message-selector.ts +1 -1
  237. package/src/modes/components/user-message.ts +1 -1
  238. package/src/modes/components/visual-truncate.ts +0 -1
  239. package/src/modes/components/welcome.ts +4 -4
  240. package/src/modes/controllers/command-controller.ts +46 -47
  241. package/src/modes/controllers/event-controller.ts +16 -20
  242. package/src/modes/controllers/extension-ui-controller.ts +40 -46
  243. package/src/modes/controllers/input-controller.ts +17 -18
  244. package/src/modes/controllers/selector-controller.ts +103 -91
  245. package/src/modes/index.ts +3 -3
  246. package/src/modes/interactive-mode.ts +27 -29
  247. package/src/modes/print-mode.ts +12 -13
  248. package/src/modes/rpc/rpc-client.ts +7 -8
  249. package/src/modes/rpc/rpc-mode.ts +24 -25
  250. package/src/modes/rpc/rpc-types.ts +3 -4
  251. package/src/modes/theme/mermaid-cache.ts +2 -2
  252. package/src/modes/theme/theme.ts +128 -53
  253. package/src/modes/types.ts +10 -10
  254. package/src/modes/utils/ui-helpers.ts +17 -17
  255. package/src/patch/applicator.ts +18 -19
  256. package/src/patch/diff.ts +1 -2
  257. package/src/patch/fuzzy.ts +1 -2
  258. package/src/patch/index.ts +10 -11
  259. package/src/patch/normalize.ts +4 -4
  260. package/src/patch/normative.ts +1 -2
  261. package/src/patch/parser.ts +8 -9
  262. package/src/patch/shared.ts +12 -13
  263. package/src/sdk.ts +60 -63
  264. package/src/session/agent-session.ts +83 -84
  265. package/src/session/agent-storage.ts +11 -11
  266. package/src/session/artifacts.ts +8 -9
  267. package/src/session/auth-storage.ts +25 -29
  268. package/src/session/compaction/branch-summarization.ts +7 -10
  269. package/src/session/compaction/compaction.ts +8 -19
  270. package/src/session/compaction/utils.ts +6 -9
  271. package/src/session/history-storage.ts +10 -10
  272. package/src/session/messages.ts +4 -5
  273. package/src/session/session-manager.ts +76 -65
  274. package/src/session/session-storage.ts +57 -69
  275. package/src/session/storage-migration.ts +2 -3
  276. package/src/session/streaming-output.ts +2 -2
  277. package/src/ssh/connection-manager.ts +43 -50
  278. package/src/ssh/ssh-executor.ts +2 -2
  279. package/src/ssh/sshfs-mount.ts +11 -18
  280. package/src/system-prompt.ts +27 -34
  281. package/src/task/agents.ts +45 -30
  282. package/src/task/commands.ts +6 -7
  283. package/src/task/discovery.ts +39 -76
  284. package/src/task/executor.ts +14 -15
  285. package/src/task/index.ts +33 -36
  286. package/src/task/output-manager.ts +3 -4
  287. package/src/task/parallel.ts +0 -1
  288. package/src/task/render.ts +19 -20
  289. package/src/task/subprocess-tool-registry.ts +1 -2
  290. package/src/task/worker-protocol.ts +3 -3
  291. package/src/task/worker.ts +32 -38
  292. package/src/task/worktree.ts +19 -19
  293. package/src/tools/ask.ts +8 -9
  294. package/src/tools/bash-interceptor.ts +1 -5
  295. package/src/tools/bash.ts +19 -18
  296. package/src/tools/calculator.ts +12 -12
  297. package/src/tools/complete.ts +3 -4
  298. package/src/tools/context.ts +2 -2
  299. package/src/tools/fetch.ts +23 -26
  300. package/src/tools/find.ts +15 -16
  301. package/src/tools/gemini-image.ts +14 -14
  302. package/src/tools/grep.ts +27 -27
  303. package/src/tools/index.ts +78 -56
  304. package/src/tools/list-limit.ts +1 -1
  305. package/src/tools/ls.ts +7 -7
  306. package/src/tools/notebook.ts +5 -5
  307. package/src/tools/output-meta.ts +3 -4
  308. package/src/tools/output-utils.ts +1 -1
  309. package/src/tools/path-utils.ts +5 -5
  310. package/src/tools/python.ts +36 -37
  311. package/src/tools/read.ts +23 -23
  312. package/src/tools/render-utils.ts +8 -9
  313. package/src/tools/renderers.ts +6 -7
  314. package/src/tools/review.ts +8 -11
  315. package/src/tools/ssh.ts +31 -30
  316. package/src/tools/todo-write.ts +13 -13
  317. package/src/tools/tool-errors.ts +3 -3
  318. package/src/tools/tool-result.ts +3 -8
  319. package/src/tools/write.ts +11 -16
  320. package/src/tui/code-cell.ts +3 -9
  321. package/src/tui/file-list.ts +3 -4
  322. package/src/tui/output-block.ts +1 -2
  323. package/src/tui/status-line.ts +2 -3
  324. package/src/tui/tree-list.ts +2 -3
  325. package/src/tui/types.ts +1 -2
  326. package/src/tui/utils.ts +2 -3
  327. package/src/utils/changelog.ts +9 -10
  328. package/src/utils/clipboard.ts +11 -11
  329. package/src/utils/file-mentions.ts +4 -10
  330. package/src/utils/frontmatter.ts +6 -3
  331. package/src/utils/fuzzy.ts +2 -2
  332. package/src/utils/image-convert.ts +1 -1
  333. package/src/utils/image-resize.ts +1 -1
  334. package/src/utils/mime.ts +2 -2
  335. package/src/utils/shell-snapshot.ts +11 -13
  336. package/src/utils/shell.ts +4 -5
  337. package/src/utils/title-generator.ts +8 -9
  338. package/src/utils/tools-manager.ts +23 -23
  339. package/src/vendor/photon/index.js +1099 -1059
  340. package/src/vendor/photon/photon_rs_bg.wasm +0 -0
  341. package/src/web/scrapers/artifacthub.ts +1 -1
  342. package/src/web/scrapers/arxiv.ts +2 -2
  343. package/src/web/scrapers/bluesky.ts +2 -2
  344. package/src/web/scrapers/cheatsh.ts +1 -1
  345. package/src/web/scrapers/chocolatey.ts +2 -2
  346. package/src/web/scrapers/choosealicense.ts +5 -5
  347. package/src/web/scrapers/cisa-kev.ts +1 -1
  348. package/src/web/scrapers/crossref.ts +2 -2
  349. package/src/web/scrapers/devto.ts +3 -3
  350. package/src/web/scrapers/discogs.ts +3 -4
  351. package/src/web/scrapers/discourse.ts +1 -1
  352. package/src/web/scrapers/dockerhub.ts +1 -1
  353. package/src/web/scrapers/fdroid.ts +2 -2
  354. package/src/web/scrapers/firefox-addons.ts +3 -3
  355. package/src/web/scrapers/flathub.ts +1 -1
  356. package/src/web/scrapers/github.ts +3 -3
  357. package/src/web/scrapers/gitlab.ts +4 -4
  358. package/src/web/scrapers/hackernews.ts +2 -2
  359. package/src/web/scrapers/huggingface.ts +1 -1
  360. package/src/web/scrapers/iacr.ts +2 -2
  361. package/src/web/scrapers/index.ts +0 -1
  362. package/src/web/scrapers/jetbrains-marketplace.ts +1 -1
  363. package/src/web/scrapers/lemmy.ts +2 -2
  364. package/src/web/scrapers/maven.ts +2 -2
  365. package/src/web/scrapers/mdn.ts +2 -4
  366. package/src/web/scrapers/metacpan.ts +2 -2
  367. package/src/web/scrapers/musicbrainz.ts +1 -2
  368. package/src/web/scrapers/npm.ts +1 -1
  369. package/src/web/scrapers/nuget.ts +2 -2
  370. package/src/web/scrapers/nvd.ts +3 -3
  371. package/src/web/scrapers/ollama.ts +7 -9
  372. package/src/web/scrapers/opencorporates.ts +2 -2
  373. package/src/web/scrapers/openlibrary.ts +6 -6
  374. package/src/web/scrapers/orcid.ts +0 -1
  375. package/src/web/scrapers/osv.ts +2 -2
  376. package/src/web/scrapers/packagist.ts +1 -1
  377. package/src/web/scrapers/pubmed.ts +1 -2
  378. package/src/web/scrapers/rawg.ts +2 -2
  379. package/src/web/scrapers/readthedocs.ts +1 -2
  380. package/src/web/scrapers/repology.ts +2 -2
  381. package/src/web/scrapers/rfc.ts +1 -1
  382. package/src/web/scrapers/searchcode.ts +2 -2
  383. package/src/web/scrapers/semantic-scholar.ts +1 -1
  384. package/src/web/scrapers/snapcraft.ts +2 -2
  385. package/src/web/scrapers/sourcegraph.ts +1 -1
  386. package/src/web/scrapers/spdx.ts +3 -3
  387. package/src/web/scrapers/spotify.ts +0 -1
  388. package/src/web/scrapers/twitter.ts +1 -1
  389. package/src/web/scrapers/types.ts +1 -2
  390. package/src/web/scrapers/utils.ts +5 -5
  391. package/src/web/scrapers/wikidata.ts +3 -3
  392. package/src/web/scrapers/youtube.ts +9 -14
  393. package/src/web/search/auth.ts +4 -9
  394. package/src/web/search/index.ts +11 -21
  395. package/src/web/search/providers/anthropic.ts +3 -9
  396. package/src/web/search/providers/exa.ts +6 -10
  397. package/src/web/search/providers/perplexity.ts +5 -5
  398. package/src/web/search/render.ts +16 -18
  399. package/scripts/generate-wasm-b64.ts +0 -24
  400. package/src/commit/map-reduce/.map-phase.ts.kate-swp +0 -0
  401. package/src/task/.executor.ts.kate-swp +0 -0
  402. package/src/vendor/photon/photon_rs_bg.wasm.b64.js +0 -1
@@ -1,6 +1,6 @@
1
- import { homedir } from "node:os";
2
- import { join } from "node:path";
3
- import { CONFIG_DIR_NAME, getConfigDirPaths } from "@oh-my-pi/pi-coding-agent/config";
1
+ import * as os from "node:os";
2
+ import * as path from "node:path";
3
+ import { CONFIG_DIR_NAME, getConfigDirPaths } from "../../config";
4
4
 
5
5
  // =============================================================================
6
6
  // Plugin Directory Paths
@@ -8,27 +8,27 @@ import { CONFIG_DIR_NAME, getConfigDirPaths } from "@oh-my-pi/pi-coding-agent/co
8
8
 
9
9
  /** Root plugin directory: ~/.omp/plugins (not under agent/) */
10
10
  export function getPluginsDir(): string {
11
- return join(homedir(), CONFIG_DIR_NAME, "plugins");
11
+ return path.join(os.homedir(), CONFIG_DIR_NAME, "plugins");
12
12
  }
13
13
 
14
14
  /** Where npm installs packages: ~/.omp/plugins/node_modules */
15
15
  export function getPluginsNodeModules(): string {
16
- return join(getPluginsDir(), "node_modules");
16
+ return path.join(getPluginsDir(), "node_modules");
17
17
  }
18
18
 
19
19
  /** Plugin manifest: ~/.omp/plugins/package.json */
20
20
  export function getPluginsPackageJson(): string {
21
- return join(getPluginsDir(), "package.json");
21
+ return path.join(getPluginsDir(), "package.json");
22
22
  }
23
23
 
24
24
  /** Plugin lock file: ~/.omp/plugins/omp-plugins.lock.json */
25
25
  export function getPluginsLockfile(): string {
26
- return join(getPluginsDir(), "omp-plugins.lock.json");
26
+ return path.join(getPluginsDir(), "omp-plugins.lock.json");
27
27
  }
28
28
 
29
29
  /** Project-local plugin overrides: .omp/plugin-overrides.json (primary) */
30
30
  export function getProjectPluginOverrides(cwd: string): string {
31
- return join(cwd, CONFIG_DIR_NAME, "plugin-overrides.json");
31
+ return path.join(cwd, CONFIG_DIR_NAME, "plugin-overrides.json");
32
32
  }
33
33
 
34
34
  /** All possible project plugin override paths (primary + legacy) */
@@ -1,16 +1,12 @@
1
- import { readdirSync, readFileSync, statSync } from "node:fs";
2
- import { realpath } from "node:fs/promises";
3
- import { basename, join } from "node:path";
4
- import { skillCapability } from "@oh-my-pi/pi-coding-agent/capability/skill";
5
- import type { SourceMeta } from "@oh-my-pi/pi-coding-agent/capability/types";
6
- import type { SkillsSettings } from "@oh-my-pi/pi-coding-agent/config/settings-manager";
7
- import type {
8
- Skill as CapabilitySkill,
9
- SkillFrontmatter as ImportedSkillFrontmatter,
10
- } from "@oh-my-pi/pi-coding-agent/discovery";
11
- import { loadCapability } from "@oh-my-pi/pi-coding-agent/discovery";
12
- import { parseFrontmatter } from "@oh-my-pi/pi-coding-agent/utils/frontmatter";
1
+ import * as fs from "node:fs/promises";
2
+ import * as path from "node:path";
13
3
  import { logger } from "@oh-my-pi/pi-utils";
4
+ import { skillCapability } from "../capability/skill";
5
+ import type { SourceMeta } from "../capability/types";
6
+ import type { SkillsSettings } from "../config/settings-manager";
7
+ import type { Skill as CapabilitySkill, SkillFrontmatter as ImportedSkillFrontmatter } from "../discovery";
8
+ import { loadCapability } from "../discovery";
9
+ import { parseFrontmatter } from "../utils/frontmatter";
14
10
 
15
11
  // Re-export SkillFrontmatter for backward compatibility
16
12
  export type { ImportedSkillFrontmatter as SkillFrontmatter };
@@ -45,17 +41,16 @@ export interface LoadSkillsFromDirOptions {
45
41
  /**
46
42
  * Load skills from a directory recursively.
47
43
  * Skills are directories containing a SKILL.md file with frontmatter including a description.
48
- * @deprecated Use loadSync("skills") from discovery API instead
49
44
  */
50
- export function loadSkillsFromDir(options: LoadSkillsFromDirOptions): LoadSkillsResult {
45
+ export async function loadSkillsFromDir(options: LoadSkillsFromDirOptions): Promise<LoadSkillsResult> {
51
46
  const skills: Skill[] = [];
52
47
  const warnings: SkillWarning[] = [];
53
48
  const seenPaths = new Set<string>();
54
49
 
55
- function addSkill(skillFile: string, skillDir: string, dirName: string) {
50
+ async function addSkill(skillFile: string, skillDir: string, dirName: string): Promise<void> {
56
51
  if (seenPaths.has(skillFile)) return;
57
52
  try {
58
- const content = readFileSync(skillFile, "utf-8");
53
+ const content = await fs.readFile(skillFile, "utf-8");
59
54
  const { frontmatter } = parseFrontmatter(content, { source: skillFile });
60
55
  const name = (frontmatter.name as string) || dirName;
61
56
  const description = frontmatter.description as string;
@@ -75,26 +70,30 @@ export function loadSkillsFromDir(options: LoadSkillsFromDirOptions): LoadSkills
75
70
  }
76
71
  }
77
72
 
78
- function scanDir(dir: string) {
73
+ async function scanDir(dir: string): Promise<void> {
79
74
  try {
80
- const entries = readdirSync(dir, { withFileTypes: true });
75
+ // First check if this directory itself is a skill
76
+ const selfSkillFile = path.join(dir, "SKILL.md");
77
+ try {
78
+ const s = await fs.stat(selfSkillFile);
79
+ if (s.isFile()) {
80
+ await addSkill(selfSkillFile, dir, path.basename(dir));
81
+ // This directory is a skill, don't recurse
82
+ return;
83
+ }
84
+ } catch {
85
+ // No SKILL.md in this directory
86
+ }
87
+
88
+ // Recurse into subdirectories
89
+ const entries = await fs.readdir(dir, { withFileTypes: true });
90
+
81
91
  for (const entry of entries) {
82
92
  if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
83
93
 
84
- const fullPath = join(dir, entry.name);
94
+ const fullPath = path.join(dir, entry.name);
85
95
  if (entry.isDirectory()) {
86
- const skillFile = join(fullPath, "SKILL.md");
87
- try {
88
- const stat = statSync(skillFile);
89
- if (stat.isFile()) {
90
- addSkill(skillFile, fullPath, entry.name);
91
- }
92
- } catch {
93
- // No SKILL.md in this directory
94
- }
95
- scanDir(fullPath);
96
- } else if (entry.isFile() && entry.name === "SKILL.md") {
97
- addSkill(fullPath, dir, basename(dir));
96
+ await scanDir(fullPath);
98
97
  }
99
98
  }
100
99
  } catch (err) {
@@ -102,7 +101,7 @@ export function loadSkillsFromDir(options: LoadSkillsFromDirOptions): LoadSkills
102
101
  }
103
102
  }
104
103
 
105
- scanDir(options.dir);
104
+ await scanDir(options.dir);
106
105
 
107
106
  return { skills, warnings };
108
107
  }
@@ -111,15 +110,15 @@ export function loadSkillsFromDir(options: LoadSkillsFromDirOptions): LoadSkills
111
110
  * Scan a directory for SKILL.md files recursively.
112
111
  * Used internally by loadSkills for custom directories.
113
112
  */
114
- function scanDirectoryForSkills(dir: string): LoadSkillsResult {
113
+ async function scanDirectoryForSkills(dir: string): Promise<LoadSkillsResult> {
115
114
  const skills: Skill[] = [];
116
115
  const warnings: SkillWarning[] = [];
117
116
  const seenPaths = new Set<string>();
118
117
 
119
- function addSkill(skillFile: string, skillDir: string, dirName: string) {
118
+ async function addSkill(skillFile: string, skillDir: string, dirName: string): Promise<void> {
120
119
  if (seenPaths.has(skillFile)) return;
121
120
  try {
122
- const content = readFileSync(skillFile, "utf-8");
121
+ const content = await fs.readFile(skillFile, "utf-8");
123
122
  const { frontmatter } = parseFrontmatter(content, { source: skillFile });
124
123
  const name = (frontmatter.name as string) || dirName;
125
124
  const description = frontmatter.description as string;
@@ -139,26 +138,30 @@ function scanDirectoryForSkills(dir: string): LoadSkillsResult {
139
138
  }
140
139
  }
141
140
 
142
- function scanDir(currentDir: string) {
141
+ async function scanDir(currentDir: string): Promise<void> {
143
142
  try {
144
- const entries = readdirSync(currentDir, { withFileTypes: true });
143
+ // First check if this directory itself is a skill
144
+ const selfSkillFile = path.join(currentDir, "SKILL.md");
145
+ try {
146
+ const s = await fs.stat(selfSkillFile);
147
+ if (s.isFile()) {
148
+ await addSkill(selfSkillFile, currentDir, path.basename(currentDir));
149
+ // This directory is a skill, don't recurse
150
+ return;
151
+ }
152
+ } catch {
153
+ // No SKILL.md in this directory
154
+ }
155
+
156
+ // Recurse into subdirectories
157
+ const entries = await fs.readdir(currentDir, { withFileTypes: true });
158
+
145
159
  for (const entry of entries) {
146
160
  if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
147
161
 
148
- const fullPath = join(currentDir, entry.name);
162
+ const fullPath = path.join(currentDir, entry.name);
149
163
  if (entry.isDirectory()) {
150
- const skillFile = join(fullPath, "SKILL.md");
151
- try {
152
- const stat = statSync(skillFile);
153
- if (stat.isFile()) {
154
- addSkill(skillFile, fullPath, entry.name);
155
- }
156
- } catch {
157
- // No SKILL.md in this directory
158
- }
159
- scanDir(fullPath);
160
- } else if (entry.isFile() && entry.name === "SKILL.md") {
161
- addSkill(fullPath, currentDir, basename(currentDir));
164
+ await scanDir(fullPath);
162
165
  }
163
166
  }
164
167
  } catch (err) {
@@ -166,7 +169,7 @@ function scanDirectoryForSkills(dir: string): LoadSkillsResult {
166
169
  }
167
170
  }
168
171
 
169
- scanDir(dir);
172
+ await scanDir(dir);
170
173
 
171
174
  return { skills, warnings };
172
175
  }
@@ -221,17 +224,17 @@ export async function loadSkills(options: LoadSkillsOptions = {}): Promise<LoadS
221
224
  // Check if skill name matches any of the include patterns
222
225
  function matchesIncludePatterns(name: string): boolean {
223
226
  if (includeSkills.length === 0) return true;
224
- return includeSkills.some((pattern) => new Bun.Glob(pattern).match(name));
227
+ return includeSkills.some(pattern => new Bun.Glob(pattern).match(name));
225
228
  }
226
229
 
227
230
  // Check if skill name matches any of the ignore patterns
228
231
  function matchesIgnorePatterns(name: string): boolean {
229
232
  if (ignoredSkills.length === 0) return false;
230
- return ignoredSkills.some((pattern) => new Bun.Glob(pattern).match(name));
233
+ return ignoredSkills.some(pattern => new Bun.Glob(pattern).match(name));
231
234
  }
232
235
 
233
236
  // Filter skills by source and patterns first
234
- const filteredSkills = result.items.filter((capSkill) => {
237
+ const filteredSkills = result.items.filter(capSkill => {
235
238
  if (!isSourceEnabled(capSkill._source)) return false;
236
239
  if (matchesIgnorePatterns(capSkill.name)) return false;
237
240
  if (!matchesIncludePatterns(capSkill.name)) return false;
@@ -240,9 +243,9 @@ export async function loadSkills(options: LoadSkillsOptions = {}): Promise<LoadS
240
243
 
241
244
  // Batch resolve all real paths in parallel
242
245
  const realPaths = await Promise.all(
243
- filteredSkills.map(async (capSkill) => {
246
+ filteredSkills.map(async capSkill => {
244
247
  try {
245
- return await realpath(capSkill.path);
248
+ return await fs.realpath(capSkill.path);
246
249
  } catch {
247
250
  return capSkill.path;
248
251
  }
@@ -282,8 +285,8 @@ export async function loadSkills(options: LoadSkillsOptions = {}): Promise<LoadS
282
285
 
283
286
  // Process custom directories - scan directly without using full provider system
284
287
  const allCustomSkills: Array<{ skill: Skill; path: string }> = [];
285
- for (const dir of customDirectories) {
286
- const customSkills = scanDirectoryForSkills(dir);
288
+ const customScanResults = await Promise.all(customDirectories.map(dir => scanDirectoryForSkills(dir)));
289
+ for (const customSkills of customScanResults) {
287
290
  for (const s of customSkills.skills) {
288
291
  if (matchesIgnorePatterns(s.name)) continue;
289
292
  if (!matchesIncludePatterns(s.name)) continue;
@@ -306,7 +309,7 @@ export async function loadSkills(options: LoadSkillsOptions = {}): Promise<LoadS
306
309
  const customRealPaths = await Promise.all(
307
310
  allCustomSkills.map(async ({ path }) => {
308
311
  try {
309
- return await realpath(path);
312
+ return await fs.realpath(path);
310
313
  } catch {
311
314
  return path;
312
315
  }
@@ -332,6 +335,6 @@ export async function loadSkills(options: LoadSkillsOptions = {}): Promise<LoadS
332
335
 
333
336
  return {
334
337
  skills: Array.from(skillMap.values()),
335
- warnings: [...result.warnings.map((w) => ({ skillPath: "", message: w })), ...collisionWarnings],
338
+ warnings: [...result.warnings.map(w => ({ skillPath: "", message: w })), ...collisionWarnings],
336
339
  };
337
340
  }
@@ -1,9 +1,9 @@
1
- import { slashCommandCapability } from "@oh-my-pi/pi-coding-agent/capability/slash-command";
2
- import { renderPromptTemplate } from "@oh-my-pi/pi-coding-agent/config/prompt-templates";
3
- import type { SlashCommand } from "@oh-my-pi/pi-coding-agent/discovery";
4
- import { loadCapability } from "@oh-my-pi/pi-coding-agent/discovery";
5
- import { EMBEDDED_COMMAND_TEMPLATES } from "@oh-my-pi/pi-coding-agent/task/commands";
6
- import { parseFrontmatter } from "@oh-my-pi/pi-coding-agent/utils/frontmatter";
1
+ import { slashCommandCapability } from "../capability/slash-command";
2
+ import { renderPromptTemplate } from "../config/prompt-templates";
3
+ import type { SlashCommand } from "../discovery";
4
+ import { loadCapability } from "../discovery";
5
+ import { EMBEDDED_COMMAND_TEMPLATES } from "../task/commands";
6
+ import { parseFrontmatter } from "../utils/frontmatter";
7
7
 
8
8
  /**
9
9
  * Represents a custom slash command loaded from a file
@@ -29,7 +29,7 @@ function parseCommandTemplate(
29
29
  // Get description from frontmatter or first non-empty line
30
30
  let description = frontmatterDesc;
31
31
  if (!description) {
32
- const firstLine = body.split("\n").find((line) => line.trim());
32
+ const firstLine = body.split("\n").find(line => line.trim());
33
33
  if (firstLine) {
34
34
  description = firstLine.slice(0, 60);
35
35
  if (firstLine.length > 60) description += "...";
@@ -114,7 +114,7 @@ export interface LoadSlashCommandsOptions {
114
114
  export async function loadSlashCommands(options: LoadSlashCommandsOptions = {}): Promise<FileSlashCommand[]> {
115
115
  const result = await loadCapability<SlashCommand>(slashCommandCapability.id, { cwd: options.cwd });
116
116
 
117
- const fileCommands: FileSlashCommand[] = result.items.map((cmd) => {
117
+ const fileCommands: FileSlashCommand[] = result.items.map(cmd => {
118
118
  const { description, body } = parseCommandTemplate(cmd.content, {
119
119
  source: cmd.path ?? `slash-command:${cmd.name}`,
120
120
  level: cmd.level === "native" ? "fatal" : "warn",
@@ -133,7 +133,7 @@ export async function loadSlashCommands(options: LoadSlashCommandsOptions = {}):
133
133
  };
134
134
  });
135
135
 
136
- const seenNames = new Set(fileCommands.map((cmd) => cmd.name));
136
+ const seenNames = new Set(fileCommands.map(cmd => cmd.name));
137
137
  for (const cmd of EMBEDDED_SLASH_COMMANDS) {
138
138
  const name = cmd.name.replace(/\.md$/, "");
139
139
  if (seenNames.has(name)) continue;
@@ -165,7 +165,7 @@ export function expandSlashCommand(text: string, fileCommands: FileSlashCommand[
165
165
  const commandName = spaceIndex === -1 ? text.slice(1) : text.slice(1, spaceIndex);
166
166
  const argsString = spaceIndex === -1 ? "" : text.slice(spaceIndex + 1);
167
167
 
168
- const fileCommand = fileCommands.find((cmd) => cmd.name === commandName);
168
+ const fileCommand = fileCommands.find(cmd => cmd.name === commandName);
169
169
  if (fileCommand) {
170
170
  const args = parseCommandArgs(argsString);
171
171
  const argsText = args.join(" ");
package/src/index.ts CHANGED
@@ -3,52 +3,6 @@
3
3
  // TypeBox helper for string enums (convenience for custom tools)
4
4
  // Re-export from pi-ai which uses the correct enum-based schema format
5
5
  export { StringEnum } from "@oh-my-pi/pi-ai";
6
- export type { FileDiagnosticsResult } from "@oh-my-pi/pi-coding-agent/lsp";
7
- // UI components for extensions
8
- export {
9
- ArminComponent,
10
- AssistantMessageComponent,
11
- BashExecutionComponent,
12
- BorderedLoader,
13
- BranchSummaryMessageComponent,
14
- CompactionSummaryMessageComponent,
15
- CustomEditor,
16
- CustomMessageComponent,
17
- DynamicBorder,
18
- FooterComponent,
19
- HookEditorComponent as ExtensionEditorComponent,
20
- HookInputComponent as ExtensionInputComponent,
21
- HookSelectorComponent as ExtensionSelectorComponent,
22
- LoginDialogComponent,
23
- ModelSelectorComponent,
24
- OAuthSelectorComponent,
25
- type RenderDiffOptions,
26
- renderDiff,
27
- SessionSelectorComponent,
28
- type SettingsCallbacks,
29
- SettingsSelectorComponent,
30
- ShowImagesSelectorComponent,
31
- ThemeSelectorComponent,
32
- ThinkingSelectorComponent,
33
- ToolExecutionComponent,
34
- type ToolExecutionOptions,
35
- TreeSelectorComponent,
36
- truncateToVisualLines,
37
- UserMessageComponent,
38
- UserMessageSelectorComponent,
39
- type VisualTruncateResult,
40
- } from "@oh-my-pi/pi-coding-agent/modes/components";
41
- // Theme utilities for custom tools
42
- export {
43
- getLanguageFromPath,
44
- getMarkdownTheme,
45
- getSelectListTheme,
46
- getSettingsListTheme,
47
- highlightCode,
48
- initTheme,
49
- Theme,
50
- type ThemeColor,
51
- } from "@oh-my-pi/pi-coding-agent/modes/theme/theme";
52
6
  // Re-export TUI components for custom tool rendering
53
7
  export { Container, Markdown, Spacer, Text } from "@oh-my-pi/pi-tui";
54
8
  // Logging
@@ -150,6 +104,7 @@ export {
150
104
  } from "./extensibility/skills";
151
105
  // Slash commands
152
106
  export { type FileSlashCommand, loadSlashCommands as discoverSlashCommands } from "./extensibility/slash-commands";
107
+ export type { FileDiagnosticsResult } from "./lsp";
153
108
  // Main entry point
154
109
  export { main } from "./main";
155
110
  // Run modes for programmatic SDK usage
@@ -163,6 +118,51 @@ export {
163
118
  runPrintMode,
164
119
  runRpcMode,
165
120
  } from "./modes";
121
+ // UI components for extensions
122
+ export {
123
+ ArminComponent,
124
+ AssistantMessageComponent,
125
+ BashExecutionComponent,
126
+ BorderedLoader,
127
+ BranchSummaryMessageComponent,
128
+ CompactionSummaryMessageComponent,
129
+ CustomEditor,
130
+ CustomMessageComponent,
131
+ DynamicBorder,
132
+ FooterComponent,
133
+ HookEditorComponent as ExtensionEditorComponent,
134
+ HookInputComponent as ExtensionInputComponent,
135
+ HookSelectorComponent as ExtensionSelectorComponent,
136
+ LoginDialogComponent,
137
+ ModelSelectorComponent,
138
+ OAuthSelectorComponent,
139
+ type RenderDiffOptions,
140
+ renderDiff,
141
+ SessionSelectorComponent,
142
+ type SettingsCallbacks,
143
+ SettingsSelectorComponent,
144
+ ShowImagesSelectorComponent,
145
+ ThemeSelectorComponent,
146
+ ThinkingSelectorComponent,
147
+ ToolExecutionComponent,
148
+ type ToolExecutionOptions,
149
+ TreeSelectorComponent,
150
+ truncateToVisualLines,
151
+ UserMessageComponent,
152
+ UserMessageSelectorComponent,
153
+ type VisualTruncateResult,
154
+ } from "./modes/components";
155
+ // Theme utilities for custom tools
156
+ export {
157
+ getLanguageFromPath,
158
+ getMarkdownTheme,
159
+ getSelectListTheme,
160
+ getSettingsListTheme,
161
+ highlightCode,
162
+ initTheme,
163
+ Theme,
164
+ type ThemeColor,
165
+ } from "./modes/theme/theme";
166
166
  // SDK for programmatic usage
167
167
  export {
168
168
  // Factory
@@ -8,9 +8,9 @@
8
8
  * - agent://<id>/<path> - JSON extraction via path form
9
9
  * - agent://<id>?q=<query> - JSON extraction via query form
10
10
  */
11
-
12
- import * as fs from "node:fs";
11
+ import * as fs from "node:fs/promises";
13
12
  import * as path from "node:path";
13
+ import { isEnoent } from "@oh-my-pi/pi-utils";
14
14
  import { applyQuery, pathToQuery } from "./json-query";
15
15
  import type { InternalResource, InternalUrl, ProtocolHandler } from "./types";
16
16
 
@@ -25,10 +25,10 @@ export interface AgentProtocolOptions {
25
25
  /**
26
26
  * List available output IDs in artifacts directory.
27
27
  */
28
- function listAvailableOutputs(artifactsDir: string): string[] {
28
+ async function listAvailableOutputs(artifactsDir: string): Promise<string[]> {
29
29
  try {
30
- const files = fs.readdirSync(artifactsDir);
31
- return files.filter((f) => f.endsWith(".md")).map((f) => f.replace(".md", ""));
30
+ const files = await fs.readdir(artifactsDir);
31
+ return files.filter(f => f.endsWith(".md")).map(f => f.replace(".md", ""));
32
32
  } catch {
33
33
  return [];
34
34
  }
@@ -51,8 +51,13 @@ export class AgentProtocolHandler implements ProtocolHandler {
51
51
  throw new Error("No session - agent outputs unavailable");
52
52
  }
53
53
 
54
- if (!fs.existsSync(artifactsDir)) {
55
- throw new Error("No artifacts directory found");
54
+ try {
55
+ await fs.stat(artifactsDir);
56
+ } catch (err) {
57
+ if (isEnoent(err)) {
58
+ throw new Error("No artifacts directory found");
59
+ }
60
+ throw err;
56
61
  }
57
62
 
58
63
  // Extract output ID from host
@@ -73,10 +78,15 @@ export class AgentProtocolHandler implements ProtocolHandler {
73
78
 
74
79
  // Load the output file
75
80
  const outputPath = path.join(artifactsDir, `${outputId}.md`);
76
- if (!fs.existsSync(outputPath)) {
77
- const available = listAvailableOutputs(artifactsDir);
78
- const availableStr = available.length > 0 ? available.join(", ") : "none";
79
- throw new Error(`Not found: ${outputId}\nAvailable: ${availableStr}`);
81
+ try {
82
+ await fs.stat(outputPath);
83
+ } catch (err) {
84
+ if (isEnoent(err)) {
85
+ const available = await listAvailableOutputs(artifactsDir);
86
+ const availableStr = available.length > 0 ? available.join(", ") : "none";
87
+ throw new Error(`Not found: ${outputId}\nAvailable: ${availableStr}`);
88
+ }
89
+ throw err;
80
90
  }
81
91
 
82
92
  const rawContent = await Bun.file(outputPath).text();
@@ -9,9 +9,9 @@
9
9
  *
10
10
  * Pagination is handled by the read tool via offset/limit parameters.
11
11
  */
12
-
13
- import * as fs from "node:fs";
12
+ import * as fs from "node:fs/promises";
14
13
  import * as path from "node:path";
14
+ import { isEnoent } from "@oh-my-pi/pi-utils";
15
15
  import type { InternalResource, InternalUrl, ProtocolHandler } from "./types";
16
16
 
17
17
  export interface ArtifactProtocolOptions {
@@ -24,12 +24,12 @@ export interface ArtifactProtocolOptions {
24
24
  /**
25
25
  * List available artifact IDs in the directory.
26
26
  */
27
- function listAvailableArtifacts(artifactsDir: string): string[] {
27
+ async function listAvailableArtifacts(artifactsDir: string): Promise<string[]> {
28
28
  try {
29
- const files = fs.readdirSync(artifactsDir);
29
+ const files = await fs.readdir(artifactsDir);
30
30
  return files
31
- .filter((f) => /^\d+\./.test(f))
32
- .map((f) => f.split(".")[0])
31
+ .filter(f => /^\d+\./.test(f))
32
+ .map(f => f.split(".")[0])
33
33
  .sort((a, b) => Number(a) - Number(b));
34
34
  } catch {
35
35
  return [];
@@ -64,17 +64,21 @@ export class ArtifactProtocolHandler implements ProtocolHandler {
64
64
  throw new Error(`artifact:// ID must be numeric, got: ${id}`);
65
65
  }
66
66
 
67
- // Check directory exists
68
- if (!fs.existsSync(artifactsDir)) {
69
- throw new Error("No artifacts directory found");
67
+ // Check directory exists and find file matching ID prefix
68
+ let files: string[];
69
+ try {
70
+ files = await fs.readdir(artifactsDir);
71
+ } catch (err) {
72
+ if (isEnoent(err)) {
73
+ throw new Error("No artifacts directory found");
74
+ }
75
+ throw err;
70
76
  }
71
77
 
72
- // Find file matching ID prefix
73
- const files = fs.readdirSync(artifactsDir);
74
- const match = files.find((f) => f.startsWith(`${id}.`));
78
+ const match = files.find(f => f.startsWith(`${id}.`));
75
79
 
76
80
  if (!match) {
77
- const available = listAvailableArtifacts(artifactsDir);
81
+ const available = await listAvailableArtifacts(artifactsDir);
78
82
  const availableStr = available.length > 0 ? available.join(", ") : "none";
79
83
  throw new Error(`Artifact ${id} not found. Available: ${availableStr}`);
80
84
  }
@@ -1,7 +1,6 @@
1
1
  /**
2
2
  * Internal URL router for resolving agent:// and skill:// URLs.
3
3
  */
4
-
5
4
  import type { InternalResource, InternalUrl, ProtocolHandler } from "./types";
6
5
 
7
6
  /**
@@ -59,7 +58,7 @@ export class InternalUrlRouter {
59
58
 
60
59
  if (!handler) {
61
60
  const available = Array.from(this.handlers.keys())
62
- .map((s) => `${s}://`)
61
+ .map(s => `${s}://`)
63
62
  .join(", ");
64
63
  throw new Error(`Unknown protocol: ${scheme}://\nSupported: ${available || "none"}`);
65
64
  }
@@ -6,8 +6,7 @@
6
6
  * URL forms:
7
7
  * - rule://<name> - Reads rule content
8
8
  */
9
-
10
- import type { Rule } from "@oh-my-pi/pi-coding-agent/capability/rule";
9
+ import type { Rule } from "../capability/rule";
11
10
  import type { InternalResource, InternalUrl, ProtocolHandler } from "./types";
12
11
 
13
12
  export interface RuleProtocolOptions {
@@ -37,9 +36,9 @@ export class RuleProtocolHandler implements ProtocolHandler {
37
36
  }
38
37
 
39
38
  // Find the rule
40
- const rule = rules.find((r) => r.name === ruleName);
39
+ const rule = rules.find(r => r.name === ruleName);
41
40
  if (!rule) {
42
- const available = rules.map((r) => r.name);
41
+ const available = rules.map(r => r.name);
43
42
  const availableStr = available.length > 0 ? available.join(", ") : "none";
44
43
  throw new Error(`Unknown rule: ${ruleName}\nAvailable: ${availableStr}`);
45
44
  }
@@ -7,9 +7,8 @@
7
7
  * - skill://<name> - Reads SKILL.md
8
8
  * - skill://<name>/<path> - Reads relative path within skill's baseDir
9
9
  */
10
-
11
10
  import * as path from "node:path";
12
- import type { Skill } from "@oh-my-pi/pi-coding-agent/extensibility/skills";
11
+ import type { Skill } from "../extensibility/skills";
13
12
  import type { InternalResource, InternalUrl, ProtocolHandler } from "./types";
14
13
 
15
14
  export interface SkillProtocolOptions {
@@ -62,9 +61,9 @@ export class SkillProtocolHandler implements ProtocolHandler {
62
61
  }
63
62
 
64
63
  // Find the skill
65
- const skill = skills.find((s) => s.name === skillName);
64
+ const skill = skills.find(s => s.name === skillName);
66
65
  if (!skill) {
67
- const available = skills.map((s) => s.name);
66
+ const available = skills.map(s => s.name);
68
67
  const availableStr = available.length > 0 ? available.join(", ") : "none";
69
68
  throw new Error(`Unknown skill: ${skillName}\nAvailable: ${availableStr}`);
70
69
  }