@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
@@ -13,7 +13,7 @@
13
13
  * Modes use this class and add their own I/O layer on top.
14
14
  */
15
15
 
16
- import { existsSync, readFileSync } from "node:fs";
16
+ import * as fs from "node:fs";
17
17
  import type { Agent, AgentEvent, AgentMessage, AgentState, AgentTool, ThinkingLevel } from "@oh-my-pi/pi-agent-core";
18
18
  import type {
19
19
  AssistantMessage,
@@ -26,21 +26,23 @@ import type {
26
26
  UsageReport,
27
27
  } from "@oh-my-pi/pi-ai";
28
28
  import { isContextOverflow, modelsAreEqual, supportsXhigh } from "@oh-my-pi/pi-ai";
29
- import type { Rule } from "@oh-my-pi/pi-coding-agent/capability/rule";
30
- import { getAgentDbPath } from "@oh-my-pi/pi-coding-agent/config";
31
- import type { ModelRegistry } from "@oh-my-pi/pi-coding-agent/config/model-registry";
32
- import { parseModelString } from "@oh-my-pi/pi-coding-agent/config/model-resolver";
29
+ import { abortableSleep, isEnoent, logger } from "@oh-my-pi/pi-utils";
30
+ import { YAML } from "bun";
31
+ import type { Rule } from "../capability/rule";
32
+ import { getAgentDbPath } from "../config";
33
+ import type { ModelRegistry } from "../config/model-registry";
34
+ import { parseModelString } from "../config/model-resolver";
33
35
  import {
34
36
  expandPromptTemplate,
35
37
  type PromptTemplate,
36
38
  parseCommandArgs,
37
39
  renderPromptTemplate,
38
- } from "@oh-my-pi/pi-coding-agent/config/prompt-templates";
39
- import type { SettingsManager, SkillsSettings } from "@oh-my-pi/pi-coding-agent/config/settings-manager";
40
- import { type BashResult, executeBash as executeBashCommand } from "@oh-my-pi/pi-coding-agent/exec/bash-executor";
41
- import { exportSessionToHtml } from "@oh-my-pi/pi-coding-agent/export/html";
42
- import type { TtsrManager } from "@oh-my-pi/pi-coding-agent/export/ttsr";
43
- import type { LoadedCustomCommand } from "@oh-my-pi/pi-coding-agent/extensibility/custom-commands";
40
+ } from "../config/prompt-templates";
41
+ import type { SettingsManager, SkillsSettings } from "../config/settings-manager";
42
+ import { type BashResult, executeBash as executeBashCommand } from "../exec/bash-executor";
43
+ import { exportSessionToHtml } from "../export/html";
44
+ import type { TtsrManager } from "../export/ttsr";
45
+ import type { LoadedCustomCommand } from "../extensibility/custom-commands";
44
46
  import type {
45
47
  ExtensionCommandContext,
46
48
  ExtensionRunner,
@@ -52,23 +54,21 @@ import type {
52
54
  TreePreparation,
53
55
  TurnEndEvent,
54
56
  TurnStartEvent,
55
- } from "@oh-my-pi/pi-coding-agent/extensibility/extensions";
56
- import type { CompactOptions, ContextUsage } from "@oh-my-pi/pi-coding-agent/extensibility/extensions/types";
57
- import type { HookCommandContext } from "@oh-my-pi/pi-coding-agent/extensibility/hooks/types";
58
- import type { Skill, SkillWarning } from "@oh-my-pi/pi-coding-agent/extensibility/skills";
59
- import { expandSlashCommand, type FileSlashCommand } from "@oh-my-pi/pi-coding-agent/extensibility/slash-commands";
60
- import { executePython as executePythonCommand, type PythonResult } from "@oh-my-pi/pi-coding-agent/ipy/executor";
61
- import { theme } from "@oh-my-pi/pi-coding-agent/modes/theme/theme";
62
- import { normalizeDiff, normalizeToLF, ParseError, previewPatch, stripBom } from "@oh-my-pi/pi-coding-agent/patch";
63
- import ttsrInterruptTemplate from "@oh-my-pi/pi-coding-agent/prompts/system/ttsr-interrupt.md" with { type: "text" };
64
- import { closeAllConnections } from "@oh-my-pi/pi-coding-agent/ssh/connection-manager";
65
- import { unmountAll } from "@oh-my-pi/pi-coding-agent/ssh/sshfs-mount";
66
- import { outputMeta } from "@oh-my-pi/pi-coding-agent/tools/output-meta";
67
- import { resolveToCwd } from "@oh-my-pi/pi-coding-agent/tools/path-utils";
68
- import type { TodoItem } from "@oh-my-pi/pi-coding-agent/tools/todo-write";
69
- import { extractFileMentions, generateFileMentionMessages } from "@oh-my-pi/pi-coding-agent/utils/file-mentions";
70
- import { abortableSleep, logger } from "@oh-my-pi/pi-utils";
71
- import { YAML } from "bun";
57
+ } from "../extensibility/extensions";
58
+ import type { CompactOptions, ContextUsage } from "../extensibility/extensions/types";
59
+ import type { HookCommandContext } from "../extensibility/hooks/types";
60
+ import type { Skill, SkillWarning } from "../extensibility/skills";
61
+ import { expandSlashCommand, type FileSlashCommand } from "../extensibility/slash-commands";
62
+ import { executePython as executePythonCommand, type PythonResult } from "../ipy/executor";
63
+ import { theme } from "../modes/theme/theme";
64
+ import { normalizeDiff, normalizeToLF, ParseError, previewPatch, stripBom } from "../patch";
65
+ import ttsrInterruptTemplate from "../prompts/system/ttsr-interrupt.md" with { type: "text" };
66
+ import { closeAllConnections } from "../ssh/connection-manager";
67
+ import { unmountAll } from "../ssh/sshfs-mount";
68
+ import { outputMeta } from "../tools/output-meta";
69
+ import { resolveToCwd } from "../tools/path-utils";
70
+ import type { TodoItem } from "../tools/todo-write";
71
+ import { extractFileMentions, generateFileMentionMessages } from "../utils/file-mentions";
72
72
  import {
73
73
  type CompactionResult,
74
74
  calculateContextTokens,
@@ -214,9 +214,9 @@ const noOpUIContext: ExtensionUIContext = {
214
214
  get theme() {
215
215
  return theme;
216
216
  },
217
- getAllThemes: () => [],
218
- getTheme: () => undefined,
219
- setTheme: (_theme) => ({ success: false, error: "UI not available" }),
217
+ getAllThemes: () => Promise.resolve([]),
218
+ getTheme: () => Promise.resolve(undefined),
219
+ setTheme: _theme => Promise.resolve({ success: false, error: "UI not available" }),
220
220
  setFooter: () => {},
221
221
  setHeader: () => {},
222
222
  setEditorComponent: () => {},
@@ -542,7 +542,7 @@ export class AgentSession {
542
542
  private _getTtsrInjectionContent(): string | undefined {
543
543
  if (this._pendingTtsrInjections.length === 0) return undefined;
544
544
  const content = this._pendingTtsrInjections
545
- .map((r) => renderPromptTemplate(ttsrInterruptTemplate, { name: r.name, path: r.path, content: r.content }))
545
+ .map(r => renderPromptTemplate(ttsrInterruptTemplate, { name: r.name, path: r.path, content: r.content }))
546
546
  .join("\n\n");
547
547
  this._pendingTtsrInjections = [];
548
548
  return content;
@@ -553,10 +553,10 @@ export class AgentSession {
553
553
  if (message.role !== "user") return "";
554
554
  const content = message.content;
555
555
  if (typeof content === "string") return content;
556
- const textBlocks = content.filter((c) => c.type === "text");
557
- const text = textBlocks.map((c) => (c as TextContent).text).join("");
556
+ const textBlocks = content.filter(c => c.type === "text");
557
+ const text = textBlocks.map(c => (c as TextContent).text).join("");
558
558
  if (text.length > 0) return text;
559
- const hasImages = content.some((c) => c.type === "image");
559
+ const hasImages = content.some(c => c.type === "image");
560
560
  return hasImages ? "[Image]" : "";
561
561
  }
562
562
 
@@ -578,7 +578,7 @@ export class AgentSession {
578
578
  this._streamingEditFileCache.clear();
579
579
  }
580
580
 
581
- private _preCacheStreamingEditFile(event: AgentEvent): void {
581
+ private async _preCacheStreamingEditFile(event: AgentEvent): Promise<void> {
582
582
  if (!this.settingsManager.getEditStreamingAbort()) return;
583
583
  if (event.type !== "message_update") return;
584
584
  const assistantEvent = event.assistantMessageEvent;
@@ -606,13 +606,11 @@ export class AgentSession {
606
606
  if (this._streamingEditFileCache.has(resolvedPath)) return;
607
607
 
608
608
  try {
609
- if (existsSync(resolvedPath)) {
610
- const rawText = readFileSync(resolvedPath, "utf8");
611
- const { text } = stripBom(rawText);
612
- this._streamingEditFileCache.set(resolvedPath, normalizeToLF(text));
613
- }
609
+ const rawText = fs.readFileSync(resolvedPath, "utf-8");
610
+ const { text } = stripBom(rawText);
611
+ this._streamingEditFileCache.set(resolvedPath, normalizeToLF(text));
614
612
  } catch {
615
- // Don't cache on read errors - let the edit tool handle them
613
+ // Don't cache on read errors (including ENOENT) - let the edit tool handle them
616
614
  }
617
615
  }
618
616
 
@@ -655,7 +653,7 @@ export class AgentSession {
655
653
  const normalizedDiff = normalizeDiff(diffForCheck.replace(/\r/g, ""));
656
654
  if (!normalizedDiff) return;
657
655
  const lines = normalizedDiff.split("\n");
658
- const hasChangeLine = lines.some((line) => line.startsWith("+") || line.startsWith("-"));
656
+ const hasChangeLine = lines.some(line => line.startsWith("+") || line.startsWith("-"));
659
657
  if (!hasChangeLine) return;
660
658
 
661
659
  const lineCount = lines.length;
@@ -666,13 +664,13 @@ export class AgentSession {
666
664
  const rename = typeof args.rename === "string" ? args.rename : undefined;
667
665
 
668
666
  const removedLines = lines
669
- .filter((line) => line.startsWith("-") && !line.startsWith("--- "))
670
- .map((line) => line.slice(1));
667
+ .filter(line => line.startsWith("-") && !line.startsWith("--- "))
668
+ .map(line => line.slice(1));
671
669
  if (removedLines.length > 0) {
672
670
  const resolvedPath = resolveToCwd(path, this.sessionManager.getCwd());
673
671
  const cachedContent = this._streamingEditFileCache.get(resolvedPath);
674
672
  if (cachedContent !== undefined) {
675
- const missing = removedLines.find((line) => !cachedContent.includes(normalizeToLF(line)));
673
+ const missing = removedLines.find(line => !cachedContent.includes(normalizeToLF(line)));
676
674
  if (missing) {
677
675
  this._streamingEditAbortTriggered = true;
678
676
  logger.warn("Streaming edit aborted due to patch preview failure", {
@@ -701,10 +699,9 @@ export class AgentSession {
701
699
  ): Promise<void> {
702
700
  if (this._streamingEditAbortTriggered) return;
703
701
  try {
704
- if (!(await Bun.file(resolvedPath).exists())) return;
705
702
  const { text } = stripBom(await Bun.file(resolvedPath).text());
706
703
  const normalizedContent = normalizeToLF(text);
707
- const missing = removedLines.find((line) => !normalizedContent.includes(normalizeToLF(line)));
704
+ const missing = removedLines.find(line => !normalizedContent.includes(normalizeToLF(line)));
708
705
  if (missing) {
709
706
  this._streamingEditAbortTriggered = true;
710
707
  logger.warn("Streaming edit aborted due to patch preview failure", {
@@ -714,8 +711,12 @@ export class AgentSession {
714
711
  });
715
712
  this.agent.abort();
716
713
  }
717
- } catch {
718
- // Ignore errors during async fallback
714
+ } catch (err) {
715
+ // Ignore ENOENT (file not found) - let the edit tool handle missing files
716
+ // Also ignore other errors during async fallback
717
+ if (!isEnoent(err)) {
718
+ // Log unexpected errors but don't abort
719
+ }
719
720
  }
720
721
  }
721
722
 
@@ -885,7 +886,7 @@ export class AgentSession {
885
886
  * Returns the names of tools currently set on the agent.
886
887
  */
887
888
  getActiveToolNames(): string[] {
888
- return this.agent.state.tools.map((t) => t.name);
889
+ return this.agent.state.tools.map(t => t.name);
889
890
  }
890
891
 
891
892
  /**
@@ -1178,7 +1179,7 @@ export class AgentSession {
1178
1179
  hasQueuedMessages: () => this.queuedMessageCount > 0,
1179
1180
  getContextUsage: () => this.getContextUsage(),
1180
1181
  waitForIdle: () => this.agent.waitForIdle(),
1181
- newSession: async (options) => {
1182
+ newSession: async options => {
1182
1183
  const success = await this.newSession({ parentSession: options?.parentSession });
1183
1184
  if (!success) {
1184
1185
  return { cancelled: true };
@@ -1188,7 +1189,7 @@ export class AgentSession {
1188
1189
  }
1189
1190
  return { cancelled: false };
1190
1191
  },
1191
- branch: async (entryId) => {
1192
+ branch: async entryId => {
1192
1193
  const result = await this.branch(entryId);
1193
1194
  return { cancelled: result.cancelled };
1194
1195
  },
@@ -1196,7 +1197,7 @@ export class AgentSession {
1196
1197
  const result = await this.navigateTree(targetId, { summarize: options?.summarize });
1197
1198
  return { cancelled: result.cancelled };
1198
1199
  },
1199
- compact: async (instructionsOrOptions) => {
1200
+ compact: async instructionsOrOptions => {
1200
1201
  const instructions = typeof instructionsOrOptions === "string" ? instructionsOrOptions : undefined;
1201
1202
  const options =
1202
1203
  instructionsOrOptions && typeof instructionsOrOptions === "object" ? instructionsOrOptions : undefined;
@@ -1218,7 +1219,7 @@ export class AgentSession {
1218
1219
  const argsString = spaceIndex === -1 ? "" : text.slice(spaceIndex + 1);
1219
1220
 
1220
1221
  // Find matching command
1221
- const loaded = this._customCommands.find((c) => c.command.name === commandName);
1222
+ const loaded = this._customCommands.find(c => c.command.name === commandName);
1222
1223
  if (!loaded) return null;
1223
1224
 
1224
1225
  // Get command context from extension runner (includes session control methods)
@@ -1605,10 +1606,10 @@ export class AgentSession {
1605
1606
  const parsed = parseModelString(roleModelStr);
1606
1607
  let match: Model<any> | undefined;
1607
1608
  if (parsed) {
1608
- match = availableModels.find((m) => m.provider === parsed.provider && m.id === parsed.id);
1609
+ match = availableModels.find(m => m.provider === parsed.provider && m.id === parsed.id);
1609
1610
  }
1610
1611
  if (!match) {
1611
- match = availableModels.find((m) => m.id.toLowerCase() === roleModelStr.toLowerCase());
1612
+ match = availableModels.find(m => m.id.toLowerCase() === roleModelStr.toLowerCase());
1612
1613
  }
1613
1614
  if (!match) continue;
1614
1615
 
@@ -1619,8 +1620,8 @@ export class AgentSession {
1619
1620
 
1620
1621
  const lastRole = this.sessionManager.getLastModelChangeRole();
1621
1622
  let currentIndex = lastRole
1622
- ? roleModels.findIndex((entry) => entry.role === lastRole)
1623
- : roleModels.findIndex((entry) => modelsAreEqual(entry.model, currentModel));
1623
+ ? roleModels.findIndex(entry => entry.role === lastRole)
1624
+ : roleModels.findIndex(entry => modelsAreEqual(entry.model, currentModel));
1624
1625
  if (currentIndex === -1) currentIndex = 0;
1625
1626
 
1626
1627
  const nextIndex = (currentIndex + 1) % roleModels.length;
@@ -1639,7 +1640,7 @@ export class AgentSession {
1639
1640
  if (this._scopedModels.length <= 1) return undefined;
1640
1641
 
1641
1642
  const currentModel = this.model;
1642
- let currentIndex = this._scopedModels.findIndex((sm) => modelsAreEqual(sm.model, currentModel));
1643
+ let currentIndex = this._scopedModels.findIndex(sm => modelsAreEqual(sm.model, currentModel));
1643
1644
 
1644
1645
  if (currentIndex === -1) currentIndex = 0;
1645
1646
  const len = this._scopedModels.length;
@@ -1668,7 +1669,7 @@ export class AgentSession {
1668
1669
  if (availableModels.length <= 1) return undefined;
1669
1670
 
1670
1671
  const currentModel = this.model;
1671
- let currentIndex = availableModels.findIndex((m) => modelsAreEqual(m, currentModel));
1672
+ let currentIndex = availableModels.findIndex(m => modelsAreEqual(m, currentModel));
1672
1673
 
1673
1674
  if (currentIndex === -1) currentIndex = 0;
1674
1675
  const len = availableModels.length;
@@ -1898,7 +1899,7 @@ export class AgentSession {
1898
1899
  this.agent.replaceMessages(sessionContext.messages);
1899
1900
 
1900
1901
  // Get the saved compaction entry for the hook
1901
- const savedCompactionEntry = newEntries.find((e) => e.type === "compaction" && e.summary === summary) as
1902
+ const savedCompactionEntry = newEntries.find(e => e.type === "compaction" && e.summary === summary) as
1902
1903
  | CompactionEntry
1903
1904
  | undefined;
1904
1905
 
@@ -1975,7 +1976,7 @@ export class AgentSession {
1975
1976
  // The error shouldn't trigger another compaction since we already compacted.
1976
1977
  // Example: opus fails → switch to codex → compact → switch back to opus → opus error
1977
1978
  // is still in context but shouldn't trigger compaction again.
1978
- const compactionEntry = this.sessionManager.getBranch().find((e) => e.type === "compaction");
1979
+ const compactionEntry = this.sessionManager.getBranch().find(e => e.type === "compaction");
1979
1980
  const errorIsFromBeforeCompaction =
1980
1981
  compactionEntry && assistantMessage.timestamp < new Date(compactionEntry.timestamp).getTime();
1981
1982
 
@@ -2022,22 +2023,20 @@ export class AgentSession {
2022
2023
  if (!sessionFile) return;
2023
2024
 
2024
2025
  const todoPath = `${sessionFile.slice(0, -6)}/todos.json`;
2025
- const file = Bun.file(todoPath);
2026
- if (!(await file.exists())) {
2027
- this._todoReminderCount = 0;
2028
- return;
2029
- }
2030
2026
 
2031
2027
  let todos: TodoItem[];
2032
2028
  try {
2033
- const data = await file.json();
2029
+ const data = await Bun.file(todoPath).json();
2034
2030
  todos = data?.todos ?? [];
2035
- } catch {
2031
+ } catch (err) {
2032
+ if (isEnoent(err)) {
2033
+ this._todoReminderCount = 0;
2034
+ }
2036
2035
  return;
2037
2036
  }
2038
2037
 
2039
2038
  // Check for incomplete todos
2040
- const incomplete = todos.filter((t) => t.status !== "completed");
2039
+ const incomplete = todos.filter(t => t.status !== "completed");
2041
2040
  if (incomplete.length === 0) {
2042
2041
  this._todoReminderCount = 0;
2043
2042
  return;
@@ -2045,7 +2044,7 @@ export class AgentSession {
2045
2044
 
2046
2045
  // Build reminder message
2047
2046
  this._todoReminderCount++;
2048
- const todoList = incomplete.map((t) => `- ${t.content}`).join("\n");
2047
+ const todoList = incomplete.map(t => `- ${t.content}`).join("\n");
2049
2048
  const reminder =
2050
2049
  `<system_reminder>\n` +
2051
2050
  `You stopped with ${incomplete.length} incomplete todo item(s):\n${todoList}\n\n` +
@@ -2094,10 +2093,10 @@ export class AgentSession {
2094
2093
 
2095
2094
  const parsed = parseModelString(roleModelStr);
2096
2095
  if (parsed) {
2097
- return availableModels.find((m) => m.provider === parsed.provider && m.id === parsed.id);
2096
+ return availableModels.find(m => m.provider === parsed.provider && m.id === parsed.id);
2098
2097
  }
2099
2098
  const roleLower = roleModelStr.toLowerCase();
2100
- return availableModels.find((m) => m.id.toLowerCase() === roleLower);
2099
+ return availableModels.find(m => m.id.toLowerCase() === roleLower);
2101
2100
  }
2102
2101
 
2103
2102
  private _getCompactionModelCandidates(availableModels: Model<any>[]): Model<any>[] {
@@ -2295,7 +2294,7 @@ export class AgentSession {
2295
2294
  this.agent.replaceMessages(sessionContext.messages);
2296
2295
 
2297
2296
  // Get the saved compaction entry for the hook
2298
- const savedCompactionEntry = newEntries.find((e) => e.type === "compaction" && e.summary === summary) as
2297
+ const savedCompactionEntry = newEntries.find(e => e.type === "compaction" && e.summary === summary) as
2299
2298
  | CompactionEntry
2300
2299
  | undefined;
2301
2300
 
@@ -2822,7 +2821,7 @@ export class AgentSession {
2822
2821
  const provider = defaultModelStr.slice(0, slashIdx);
2823
2822
  const modelId = defaultModelStr.slice(slashIdx + 1);
2824
2823
  const availableModels = this._modelRegistry.getAvailable();
2825
- const match = availableModels.find((m) => m.provider === provider && m.id === modelId);
2824
+ const match = availableModels.find(m => m.provider === provider && m.id === modelId);
2826
2825
  if (match) {
2827
2826
  this.agent.setModel(match);
2828
2827
  }
@@ -3026,7 +3025,7 @@ export class AgentSession {
3026
3025
  ? targetEntry.content
3027
3026
  : targetEntry.content
3028
3027
  .filter((c): c is { type: "text"; text: string } => c.type === "text")
3029
- .map((c) => c.text)
3028
+ .map(c => c.text)
3030
3029
  .join("");
3031
3030
  } else {
3032
3031
  // Non-user message: leaf = selected node
@@ -3092,7 +3091,7 @@ export class AgentSession {
3092
3091
  if (Array.isArray(content)) {
3093
3092
  return content
3094
3093
  .filter((c): c is { type: "text"; text: string } => c.type === "text")
3095
- .map((c) => c.text)
3094
+ .map(c => c.text)
3096
3095
  .join("");
3097
3096
  }
3098
3097
  return "";
@@ -3103,9 +3102,9 @@ export class AgentSession {
3103
3102
  */
3104
3103
  getSessionStats(): SessionStats {
3105
3104
  const state = this.state;
3106
- const userMessages = state.messages.filter((m) => m.role === "user").length;
3107
- const assistantMessages = state.messages.filter((m) => m.role === "assistant").length;
3108
- const toolResults = state.messages.filter((m) => m.role === "toolResult").length;
3105
+ const userMessages = state.messages.filter(m => m.role === "user").length;
3106
+ const assistantMessages = state.messages.filter(m => m.role === "assistant").length;
3107
+ const toolResults = state.messages.filter(m => m.role === "toolResult").length;
3109
3108
 
3110
3109
  let toolCalls = 0;
3111
3110
  let totalInput = 0;
@@ -3125,7 +3124,7 @@ export class AgentSession {
3125
3124
  for (const message of state.messages) {
3126
3125
  if (message.role === "assistant") {
3127
3126
  const assistantMsg = message as AssistantMessage;
3128
- toolCalls += assistantMsg.content.filter((c) => c.type === "toolCall").length;
3127
+ toolCalls += assistantMsg.content.filter(c => c.type === "toolCall").length;
3129
3128
  totalInput += assistantMsg.usage.input;
3130
3129
  totalOutput += assistantMsg.usage.output;
3131
3130
  totalCacheRead += assistantMsg.usage.cacheRead;
@@ -3193,7 +3192,7 @@ export class AgentSession {
3193
3192
  const authStorage = this._modelRegistry.authStorage;
3194
3193
  if (!authStorage.fetchUsageReports) return null;
3195
3194
  return authStorage.fetchUsageReports({
3196
- baseUrlResolver: (provider) => this._modelRegistry.getProviderBaseUrl?.(provider),
3195
+ baseUrlResolver: provider => this._modelRegistry.getProviderBaseUrl?.(provider),
3197
3196
  });
3198
3197
  }
3199
3198
 
@@ -3274,7 +3273,7 @@ export class AgentSession {
3274
3273
  const lastAssistant = this.messages
3275
3274
  .slice()
3276
3275
  .reverse()
3277
- .find((m) => {
3276
+ .find(m => {
3278
3277
  if (m.role !== "assistant") return false;
3279
3278
  const msg = m as AssistantMessage;
3280
3279
  // Skip aborted messages with no content
@@ -1,9 +1,9 @@
1
1
  import { Database } from "bun:sqlite";
2
- import { chmodSync, existsSync, mkdirSync } from "node:fs";
3
- import { dirname } from "node:path";
4
- import { getAgentDbPath } from "@oh-my-pi/pi-coding-agent/config";
5
- import type { Settings } from "@oh-my-pi/pi-coding-agent/config/settings-manager";
2
+ import * as fs from "node:fs";
3
+ import * as path from "node:path";
6
4
  import { logger } from "@oh-my-pi/pi-utils";
5
+ import { getAgentDbPath } from "../config";
6
+ import type { Settings } from "../config/settings-manager";
7
7
  import type { AuthCredential } from "./auth-storage";
8
8
 
9
9
  /** Prepared SQLite statement type from bun:sqlite */
@@ -191,8 +191,8 @@ CREATE TABLE IF NOT EXISTS schema_version (version INTEGER PRIMARY KEY);
191
191
 
192
192
  const settingsInfo = this.db.prepare("PRAGMA table_info(settings)").all() as Array<{ name?: string }>;
193
193
  const hasSettingsTable = settingsInfo.length > 0;
194
- const hasKey = settingsInfo.some((column) => column.name === "key");
195
- const hasValue = settingsInfo.some((column) => column.name === "value");
194
+ const hasKey = settingsInfo.some(column => column.name === "key");
195
+ const hasValue = settingsInfo.some(column => column.name === "value");
196
196
 
197
197
  if (!hasSettingsTable) {
198
198
  this.db.exec(`
@@ -484,20 +484,20 @@ CREATE TABLE settings (
484
484
  * @param dbPath - Path to the database file
485
485
  */
486
486
  private ensureDir(dbPath: string): void {
487
- mkdirSync(dirname(dbPath), { recursive: true });
487
+ fs.mkdirSync(path.dirname(dbPath), { recursive: true });
488
488
  }
489
489
 
490
490
  private hardenPermissions(dbPath: string): void {
491
- const dir = dirname(dbPath);
491
+ const dir = path.dirname(dbPath);
492
492
  try {
493
- chmodSync(dir, 0o700);
493
+ fs.chmodSync(dir, 0o700);
494
494
  } catch (error) {
495
495
  logger.warn("AgentStorage failed to chmod agent dir", { path: dir, error: String(error) });
496
496
  }
497
497
 
498
- if (!existsSync(dbPath)) return;
498
+ if (!fs.existsSync(dbPath)) return;
499
499
  try {
500
- chmodSync(dbPath, 0o600);
500
+ fs.chmodSync(dbPath, 0o600);
501
501
  } catch (error) {
502
502
  logger.warn("AgentStorage failed to chmod db file", { path: dbPath, error: String(error) });
503
503
  }
@@ -4,9 +4,8 @@
4
4
  * Artifacts are stored in a directory alongside the session file,
5
5
  * accessible via artifact:// URLs or the $ARTIFACTS environment variable.
6
6
  */
7
-
8
- import { mkdir, readdir } from "node:fs/promises";
9
- import { join } from "node:path";
7
+ import * as fs from "node:fs/promises";
8
+ import * as path from "node:path";
10
9
 
11
10
  /**
12
11
  * Manages artifact storage for a session.
@@ -38,7 +37,7 @@ export class ArtifactManager {
38
37
 
39
38
  async #ensureDir(): Promise<void> {
40
39
  if (!this.#dirCreated) {
41
- await mkdir(this.#dir, { recursive: true });
40
+ await fs.mkdir(this.#dir, { recursive: true });
42
41
  this.#dirCreated = true;
43
42
  }
44
43
  if (!this.#initialized) {
@@ -82,7 +81,7 @@ export class ArtifactManager {
82
81
  await this.#ensureDir();
83
82
  const id = String(this.allocateId());
84
83
  const filename = `${id}.${toolType}.log`;
85
- return { id, path: join(this.#dir, filename) };
84
+ return { id, path: path.join(this.#dir, filename) };
86
85
  }
87
86
 
88
87
  /**
@@ -104,7 +103,7 @@ export class ArtifactManager {
104
103
  */
105
104
  async exists(id: string): Promise<boolean> {
106
105
  const files = await this.listFiles();
107
- return files.some((f) => f.startsWith(`${id}.`));
106
+ return files.some(f => f.startsWith(`${id}.`));
108
107
  }
109
108
 
110
109
  /**
@@ -113,7 +112,7 @@ export class ArtifactManager {
113
112
  */
114
113
  async listFiles(): Promise<string[]> {
115
114
  try {
116
- return await readdir(this.#dir);
115
+ return await fs.readdir(this.#dir);
117
116
  } catch {
118
117
  return [];
119
118
  }
@@ -127,7 +126,7 @@ export class ArtifactManager {
127
126
  */
128
127
  async getPath(id: string): Promise<string | null> {
129
128
  const files = await this.listFiles();
130
- const match = files.find((f) => f.startsWith(`${id}.`));
131
- return match ? join(this.#dir, match) : null;
129
+ const match = files.find(f => f.startsWith(`${id}.`));
130
+ return match ? path.join(this.#dir, match) : null;
132
131
  }
133
132
  }