@oh-my-pi/pi-coding-agent 15.10.10 → 15.10.12

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 (415) hide show
  1. package/CHANGELOG.md +142 -7
  2. package/dist/cli.js +23108 -0
  3. package/dist/tokenizers.linux-x64-gnu-xcjh3jwk.node +0 -0
  4. package/dist/types/async/job-manager.d.ts +18 -0
  5. package/dist/types/cli/args.d.ts +2 -1
  6. package/dist/types/cli/dry-balance-cli.d.ts +1 -1
  7. package/dist/types/cli/gallery-cli.d.ts +1 -1
  8. package/dist/types/cli/gallery-fixtures/types.d.ts +1 -1
  9. package/dist/types/cli/usage-cli.d.ts +72 -0
  10. package/dist/types/cli-commands.d.ts +12 -0
  11. package/dist/types/commands/launch.d.ts +5 -1
  12. package/dist/types/commands/read.d.ts +1 -1
  13. package/dist/types/commands/usage.d.ts +25 -0
  14. package/dist/types/config/api-key-resolver.d.ts +3 -0
  15. package/dist/types/config/append-only-context-mode.d.ts +2 -1
  16. package/dist/types/config/model-discovery.d.ts +55 -0
  17. package/dist/types/config/model-registry.d.ts +8 -219
  18. package/dist/types/config/model-resolver.d.ts +34 -10
  19. package/dist/types/config/model-roles.d.ts +28 -0
  20. package/dist/types/config/models-config-schema.d.ts +523 -42
  21. package/dist/types/config/models-config.d.ts +385 -0
  22. package/dist/types/config/settings-schema.d.ts +41 -8
  23. package/dist/types/config/settings.d.ts +8 -1
  24. package/dist/types/debug/log-viewer.d.ts +1 -1
  25. package/dist/types/debug/raw-sse.d.ts +1 -1
  26. package/dist/types/edit/hashline/noop-loop-guard.d.ts +72 -0
  27. package/dist/types/eval/backend.d.ts +0 -2
  28. package/dist/types/eval/idle-timeout.d.ts +0 -4
  29. package/dist/types/eval/js/shared/rewrite-imports.d.ts +6 -6
  30. package/dist/types/eval/py/executor.d.ts +5 -0
  31. package/dist/types/eval/py/kernel.d.ts +6 -1
  32. package/dist/types/eval/py/runtime.d.ts +9 -0
  33. package/dist/types/exec/bash-executor.d.ts +2 -0
  34. package/dist/types/export/html/template.generated.d.ts +1 -1
  35. package/dist/types/extensibility/extensions/runner.d.ts +3 -2
  36. package/dist/types/extensibility/extensions/types.d.ts +6 -3
  37. package/dist/types/hindsight/mental-models.d.ts +17 -8
  38. package/dist/types/internal-urls/artifact-protocol.d.ts +2 -2
  39. package/dist/types/internal-urls/types.d.ts +1 -1
  40. package/dist/types/lsp/edits.d.ts +9 -0
  41. package/dist/types/lsp/index.d.ts +2 -2
  42. package/dist/types/lsp/types.d.ts +2 -0
  43. package/dist/types/lsp/utils.d.ts +3 -0
  44. package/dist/types/mcp/json-rpc.d.ts +5 -0
  45. package/dist/types/memory-backend/index.d.ts +1 -0
  46. package/dist/types/memory-backend/runtime.d.ts +4 -0
  47. package/dist/types/memory-backend/types.d.ts +66 -1
  48. package/dist/types/mnemopi/state.d.ts +11 -1
  49. package/dist/types/modes/components/agent-dashboard.d.ts +1 -1
  50. package/dist/types/modes/components/assistant-message.d.ts +3 -1
  51. package/dist/types/modes/components/bash-execution.d.ts +1 -1
  52. package/dist/types/modes/components/copy-selector.d.ts +1 -1
  53. package/dist/types/modes/components/dynamic-border.d.ts +1 -1
  54. package/dist/types/modes/components/extensions/extension-dashboard.d.ts +1 -1
  55. package/dist/types/modes/components/extensions/extension-list.d.ts +1 -1
  56. package/dist/types/modes/components/extensions/inspector-panel.d.ts +1 -1
  57. package/dist/types/modes/components/footer.d.ts +1 -1
  58. package/dist/types/modes/components/hook-editor.d.ts +5 -0
  59. package/dist/types/modes/components/hook-input.d.ts +4 -0
  60. package/dist/types/modes/components/hook-selector.d.ts +1 -1
  61. package/dist/types/modes/components/model-selector.d.ts +1 -1
  62. package/dist/types/modes/components/plan-review-overlay.d.ts +1 -1
  63. package/dist/types/modes/components/session-observer-overlay.d.ts +1 -1
  64. package/dist/types/modes/components/session-selector.d.ts +1 -1
  65. package/dist/types/modes/components/status-line/component.d.ts +1 -1
  66. package/dist/types/modes/components/tiny-title-download-progress.d.ts +1 -1
  67. package/dist/types/modes/components/transcript-container.d.ts +25 -6
  68. package/dist/types/modes/components/tree-selector.d.ts +1 -1
  69. package/dist/types/modes/components/user-message-selector.d.ts +1 -1
  70. package/dist/types/modes/components/user-message.d.ts +2 -1
  71. package/dist/types/modes/components/visual-truncate.d.ts +1 -1
  72. package/dist/types/modes/components/welcome.d.ts +19 -3
  73. package/dist/types/modes/controllers/mcp-command-controller.d.ts +1 -1
  74. package/dist/types/modes/controllers/streaming-reveal.d.ts +1 -1
  75. package/dist/types/modes/index.d.ts +3 -3
  76. package/dist/types/modes/interactive-mode.d.ts +8 -3
  77. package/dist/types/modes/oauth-manual-input.d.ts +7 -0
  78. package/dist/types/modes/rpc/rpc-client.d.ts +39 -2
  79. package/dist/types/modes/rpc/rpc-mode.d.ts +31 -2
  80. package/dist/types/modes/rpc/rpc-subagents.d.ts +24 -0
  81. package/dist/types/modes/rpc/rpc-types.d.ts +75 -1
  82. package/dist/types/modes/setup-wizard/index.d.ts +5 -1
  83. package/dist/types/modes/setup-wizard/lazy.d.ts +2 -0
  84. package/dist/types/modes/setup-wizard/scenes/sign-in.d.ts +1 -1
  85. package/dist/types/modes/setup-wizard/scenes/types.d.ts +1 -1
  86. package/dist/types/modes/setup-wizard/scenes/web-search.d.ts +1 -1
  87. package/dist/types/modes/setup-wizard/wizard-overlay.d.ts +1 -1
  88. package/dist/types/modes/types.d.ts +4 -1
  89. package/dist/types/secrets/index.d.ts +1 -1
  90. package/dist/types/secrets/obfuscator.d.ts +8 -2
  91. package/dist/types/session/agent-session.d.ts +15 -3
  92. package/dist/types/session/auth-broker-config.d.ts +4 -0
  93. package/dist/types/session/session-manager.d.ts +1 -1
  94. package/dist/types/session/streaming-output.d.ts +23 -0
  95. package/dist/types/slash-commands/acp-builtins.d.ts +16 -0
  96. package/dist/types/slash-commands/builtin-registry.d.ts +1 -0
  97. package/dist/types/slash-commands/helpers/stats-dashboard.d.ts +13 -0
  98. package/dist/types/slash-commands/types.d.ts +1 -1
  99. package/dist/types/ssh/connection-manager.d.ts +8 -0
  100. package/dist/types/system-prompt.d.ts +2 -0
  101. package/dist/types/task/executor.d.ts +1 -0
  102. package/dist/types/task/index.d.ts +2 -2
  103. package/dist/types/task/parallel.d.ts +2 -2
  104. package/dist/types/task/types.d.ts +8 -0
  105. package/dist/types/task/worktree.d.ts +2 -0
  106. package/dist/types/thinking.d.ts +4 -0
  107. package/dist/types/tiny/title-client.d.ts +11 -0
  108. package/dist/types/tiny/title-protocol.d.ts +1 -0
  109. package/dist/types/tools/ask.d.ts +4 -0
  110. package/dist/types/tools/conflict-detect.d.ts +16 -0
  111. package/dist/types/tools/github-cache.d.ts +7 -0
  112. package/dist/types/tools/index.d.ts +6 -0
  113. package/dist/types/tools/sqlite-reader.d.ts +3 -0
  114. package/dist/types/tui/output-block.d.ts +3 -3
  115. package/dist/types/utils/changelog.d.ts +8 -0
  116. package/dist/types/utils/git.d.ts +15 -2
  117. package/dist/types/utils/title-generator.d.ts +3 -2
  118. package/dist/types/web/scrapers/readthedocs.d.ts +3 -0
  119. package/dist/types/web/scrapers/types.d.ts +12 -0
  120. package/dist/types/web/search/providers/codex.d.ts +1 -1
  121. package/dist/types/web/search/providers/gemini.d.ts +1 -1
  122. package/examples/extensions/tools.ts +5 -4
  123. package/package.json +14 -11
  124. package/scripts/build-binary.ts +18 -23
  125. package/scripts/bundle-dist.ts +81 -0
  126. package/scripts/{dev-launch → omp} +1 -1
  127. package/scripts/{dev-launch-preload.ts → omp.ts} +1 -1
  128. package/src/async/job-manager.ts +57 -3
  129. package/src/auto-thinking/classifier.ts +1 -0
  130. package/src/autoresearch/dashboard.ts +1 -1
  131. package/src/autoresearch/prompt-setup.md +6 -6
  132. package/src/autoresearch/prompt.md +6 -6
  133. package/src/capability/fs.ts +10 -0
  134. package/src/cli/args.ts +4 -1
  135. package/src/cli/auth-gateway-cli.ts +1 -3
  136. package/src/cli/dry-balance-cli.ts +1 -1
  137. package/src/cli/gallery-cli.ts +1 -1
  138. package/src/cli/gallery-fixtures/fs.ts +1 -1
  139. package/src/cli/gallery-fixtures/types.ts +5 -1
  140. package/src/cli/list-models.ts +2 -1
  141. package/src/cli/usage-cli.ts +603 -0
  142. package/src/cli-commands.ts +30 -0
  143. package/src/cli.ts +76 -13
  144. package/src/commands/complete.ts +1 -1
  145. package/src/commands/launch.ts +5 -1
  146. package/src/commands/read.ts +6 -3
  147. package/src/commands/usage.ts +35 -0
  148. package/src/commit/agentic/agent.ts +1 -1
  149. package/src/commit/model-selection.ts +4 -3
  150. package/src/config/api-key-resolver.ts +8 -6
  151. package/src/config/append-only-context-mode.ts +6 -12
  152. package/src/config/model-discovery.ts +554 -0
  153. package/src/config/model-registry.ts +320 -1041
  154. package/src/config/model-resolver.ts +173 -156
  155. package/src/config/model-roles.ts +74 -0
  156. package/src/config/models-config-schema.ts +57 -8
  157. package/src/config/models-config.ts +129 -0
  158. package/src/config/settings-schema.ts +61 -19
  159. package/src/config/settings.ts +98 -4
  160. package/src/dap/client.ts +124 -37
  161. package/src/dap/session.ts +259 -158
  162. package/src/debug/log-viewer.ts +1 -1
  163. package/src/debug/raw-sse.ts +1 -1
  164. package/src/edit/diff.ts +47 -3
  165. package/src/edit/hashline/block-resolver.ts +20 -1
  166. package/src/edit/hashline/diff.ts +36 -1
  167. package/src/edit/hashline/execute.ts +47 -4
  168. package/src/edit/hashline/noop-loop-guard.ts +99 -0
  169. package/src/edit/index.ts +16 -1
  170. package/src/edit/modes/patch.ts +52 -0
  171. package/src/edit/modes/replace.ts +56 -22
  172. package/src/edit/notebook.ts +22 -2
  173. package/src/edit/renderer.ts +36 -10
  174. package/src/eval/__tests__/completion-bridge.test.ts +1 -1
  175. package/src/eval/backend.ts +0 -2
  176. package/src/eval/completion-bridge.ts +3 -1
  177. package/src/eval/idle-timeout.ts +2 -9
  178. package/src/eval/js/context-manager.ts +6 -8
  179. package/src/eval/js/executor.ts +6 -2
  180. package/src/eval/js/index.ts +0 -2
  181. package/src/eval/js/shared/helpers.ts +5 -6
  182. package/src/eval/js/shared/local-module-loader.ts +1 -1
  183. package/src/eval/js/shared/prelude.txt +62 -1
  184. package/src/eval/js/shared/rewrite-imports.ts +40 -22
  185. package/src/eval/js/shared/runtime.ts +1 -1
  186. package/src/eval/py/executor.ts +29 -7
  187. package/src/eval/py/index.ts +6 -3
  188. package/src/eval/py/kernel.ts +43 -4
  189. package/src/eval/py/runner.py +107 -3
  190. package/src/eval/py/runtime.ts +37 -0
  191. package/src/exec/bash-executor.ts +85 -4
  192. package/src/export/html/template.generated.ts +1 -1
  193. package/src/export/html/template.js +3 -1
  194. package/src/extensibility/extensions/get-commands-handler.ts +2 -1
  195. package/src/extensibility/extensions/runner.ts +6 -1
  196. package/src/extensibility/extensions/types.ts +6 -2
  197. package/src/extensibility/plugins/legacy-pi-compat.ts +20 -3
  198. package/src/hindsight/bank.ts +17 -2
  199. package/src/hindsight/mental-models.ts +59 -12
  200. package/src/hindsight/state.ts +6 -1
  201. package/src/internal-urls/artifact-protocol.ts +11 -2
  202. package/src/internal-urls/docs-index.generated.ts +11 -11
  203. package/src/internal-urls/issue-pr-protocol.ts +12 -5
  204. package/src/internal-urls/router.ts +1 -1
  205. package/src/internal-urls/types.ts +1 -1
  206. package/src/lib/xai-http.ts +1 -1
  207. package/src/lsp/client.ts +118 -38
  208. package/src/lsp/clients/biome-client.ts +101 -39
  209. package/src/lsp/edits.ts +143 -95
  210. package/src/lsp/index.ts +31 -22
  211. package/src/lsp/render.ts +1 -1
  212. package/src/lsp/types.ts +2 -0
  213. package/src/lsp/utils.ts +28 -10
  214. package/src/main.ts +183 -23
  215. package/src/mcp/json-rpc.ts +35 -5
  216. package/src/mcp/transports/stdio.ts +7 -1
  217. package/src/memories/index.ts +4 -1
  218. package/src/memory-backend/index.ts +1 -0
  219. package/src/memory-backend/local-backend.ts +9 -0
  220. package/src/memory-backend/off-backend.ts +9 -0
  221. package/src/memory-backend/runtime.ts +66 -0
  222. package/src/memory-backend/types.ts +81 -1
  223. package/src/mnemopi/backend.ts +176 -7
  224. package/src/mnemopi/state.ts +38 -2
  225. package/src/modes/acp/acp-agent.ts +119 -11
  226. package/src/modes/components/agent-dashboard.ts +10 -7
  227. package/src/modes/components/assistant-message.ts +32 -28
  228. package/src/modes/components/bash-execution.ts +1 -1
  229. package/src/modes/components/copy-selector.ts +1 -1
  230. package/src/modes/components/diff.ts +13 -2
  231. package/src/modes/components/dynamic-border.ts +12 -3
  232. package/src/modes/components/extensions/extension-dashboard.ts +8 -5
  233. package/src/modes/components/extensions/extension-list.ts +1 -1
  234. package/src/modes/components/extensions/inspector-panel.ts +1 -1
  235. package/src/modes/components/footer.ts +4 -2
  236. package/src/modes/components/history-search.ts +1 -1
  237. package/src/modes/components/hook-editor.ts +8 -0
  238. package/src/modes/components/hook-input.ts +8 -0
  239. package/src/modes/components/hook-selector.ts +2 -2
  240. package/src/modes/components/model-selector.ts +4 -2
  241. package/src/modes/components/plan-review-overlay.ts +1 -1
  242. package/src/modes/components/session-observer-overlay.ts +2 -2
  243. package/src/modes/components/session-selector.ts +1 -1
  244. package/src/modes/components/settings-selector.ts +5 -1
  245. package/src/modes/components/status-line/component.ts +119 -35
  246. package/src/modes/components/tiny-title-download-progress.ts +1 -1
  247. package/src/modes/components/transcript-container.ts +258 -53
  248. package/src/modes/components/tree-selector.ts +3 -3
  249. package/src/modes/components/user-message-selector.ts +1 -1
  250. package/src/modes/components/user-message.ts +17 -5
  251. package/src/modes/components/visual-truncate.ts +1 -1
  252. package/src/modes/components/welcome.ts +108 -26
  253. package/src/modes/controllers/command-controller.ts +11 -4
  254. package/src/modes/controllers/event-controller.ts +73 -4
  255. package/src/modes/controllers/input-controller.ts +2 -1
  256. package/src/modes/controllers/mcp-command-controller.ts +39 -4
  257. package/src/modes/controllers/selector-controller.ts +1 -1
  258. package/src/modes/controllers/streaming-reveal.ts +85 -18
  259. package/src/modes/index.ts +3 -21
  260. package/src/modes/interactive-mode.ts +42 -18
  261. package/src/modes/oauth-manual-input.ts +30 -3
  262. package/src/modes/rpc/rpc-client.ts +154 -3
  263. package/src/modes/rpc/rpc-mode.ts +97 -12
  264. package/src/modes/rpc/rpc-subagents.ts +265 -0
  265. package/src/modes/rpc/rpc-types.ts +81 -1
  266. package/src/modes/setup-wizard/index.ts +12 -2
  267. package/src/modes/setup-wizard/lazy.ts +16 -0
  268. package/src/modes/setup-wizard/scenes/glyph.ts +1 -1
  269. package/src/modes/setup-wizard/scenes/providers.ts +1 -1
  270. package/src/modes/setup-wizard/scenes/sign-in.ts +1 -1
  271. package/src/modes/setup-wizard/scenes/theme.ts +1 -1
  272. package/src/modes/setup-wizard/scenes/types.ts +1 -1
  273. package/src/modes/setup-wizard/scenes/web-search.ts +1 -1
  274. package/src/modes/setup-wizard/wizard-overlay.ts +1 -1
  275. package/src/modes/types.ts +4 -1
  276. package/src/prompts/agents/explore.md +2 -2
  277. package/src/prompts/agents/librarian.md +1 -2
  278. package/src/prompts/agents/oracle.md +1 -1
  279. package/src/prompts/agents/plan.md +5 -5
  280. package/src/prompts/agents/task.md +5 -5
  281. package/src/prompts/ci-green-request.md +5 -7
  282. package/src/prompts/goals/goal-budget-limit.md +2 -2
  283. package/src/prompts/goals/goal-continuation.md +4 -4
  284. package/src/prompts/goals/goal-mode-active.md +1 -1
  285. package/src/prompts/memories/read-path.md +1 -1
  286. package/src/prompts/memories/stage_one_system.md +2 -2
  287. package/src/prompts/review-custom-request.md +1 -1
  288. package/src/prompts/system/agent-creation-architect.md +2 -2
  289. package/src/prompts/system/auto-continue.md +1 -1
  290. package/src/prompts/system/background-tan-dispatch.md +1 -1
  291. package/src/prompts/system/btw-user.md +2 -2
  292. package/src/prompts/system/commit-message-system.md +13 -1
  293. package/src/prompts/system/custom-system-prompt.md +1 -1
  294. package/src/prompts/system/eager-todo.md +2 -2
  295. package/src/prompts/system/irc-incoming.md +1 -1
  296. package/src/prompts/system/manual-continue.md +1 -1
  297. package/src/prompts/system/omfg-user.md +3 -4
  298. package/src/prompts/system/orchestrate-notice.md +9 -9
  299. package/src/prompts/system/plan-mode-active.md +4 -4
  300. package/src/prompts/system/plan-mode-subagent.md +4 -5
  301. package/src/prompts/system/plan-mode-tool-decision-reminder.md +1 -1
  302. package/src/prompts/system/project-prompt.md +2 -2
  303. package/src/prompts/system/subagent-system-prompt.md +4 -4
  304. package/src/prompts/system/system-prompt.md +13 -24
  305. package/src/prompts/system/title-system.md +2 -2
  306. package/src/prompts/system/ttsr-tool-reminder.md +1 -1
  307. package/src/prompts/system/workflow-notice.md +1 -1
  308. package/src/prompts/tools/ast-edit.md +1 -1
  309. package/src/prompts/tools/ast-grep.md +2 -2
  310. package/src/prompts/tools/bash.md +5 -7
  311. package/src/prompts/tools/browser.md +7 -7
  312. package/src/prompts/tools/debug.md +1 -1
  313. package/src/prompts/tools/eval.md +3 -3
  314. package/src/prompts/tools/find.md +0 -1
  315. package/src/prompts/tools/github.md +8 -7
  316. package/src/prompts/tools/goal.md +1 -1
  317. package/src/prompts/tools/image-gen.md +1 -1
  318. package/src/prompts/tools/inspect-image-system.md +1 -1
  319. package/src/prompts/tools/irc.md +15 -15
  320. package/src/prompts/tools/lsp.md +2 -2
  321. package/src/prompts/tools/patch.md +2 -2
  322. package/src/prompts/tools/read.md +3 -4
  323. package/src/prompts/tools/recall.md +1 -1
  324. package/src/prompts/tools/reflect.md +1 -1
  325. package/src/prompts/tools/render-mermaid.md +2 -2
  326. package/src/prompts/tools/replace.md +4 -10
  327. package/src/prompts/tools/rewind.md +2 -2
  328. package/src/prompts/tools/search-tool-bm25.md +1 -9
  329. package/src/prompts/tools/search.md +0 -1
  330. package/src/prompts/tools/ssh.md +0 -4
  331. package/src/prompts/tools/task.md +2 -3
  332. package/src/prompts/tools/todo.md +1 -1
  333. package/src/sdk.ts +31 -11
  334. package/src/secrets/index.ts +8 -1
  335. package/src/secrets/obfuscator.ts +39 -18
  336. package/src/session/agent-session.ts +223 -64
  337. package/src/session/auth-broker-config.ts +30 -1
  338. package/src/session/session-manager.ts +2 -2
  339. package/src/session/streaming-output.ts +188 -11
  340. package/src/slash-commands/acp-builtins.ts +24 -0
  341. package/src/slash-commands/builtin-registry.ts +40 -0
  342. package/src/slash-commands/helpers/stats-dashboard.ts +85 -0
  343. package/src/slash-commands/types.ts +1 -1
  344. package/src/ssh/connection-manager.ts +27 -0
  345. package/src/system-prompt.ts +14 -0
  346. package/src/task/commands.ts +2 -1
  347. package/src/task/executor.ts +74 -65
  348. package/src/task/index.ts +146 -68
  349. package/src/task/parallel.ts +3 -3
  350. package/src/task/render.ts +20 -5
  351. package/src/task/types.ts +9 -0
  352. package/src/task/worktree.ts +64 -56
  353. package/src/thinking.ts +9 -1
  354. package/src/tiny/title-client.ts +60 -16
  355. package/src/tiny/title-protocol.ts +1 -1
  356. package/src/tiny/worker.ts +6 -4
  357. package/src/tools/archive-reader.ts +30 -2
  358. package/src/tools/ask.ts +104 -21
  359. package/src/tools/ast-edit.ts +25 -5
  360. package/src/tools/auto-generated-guard.ts +20 -3
  361. package/src/tools/bash-interactive.ts +27 -7
  362. package/src/tools/bash.ts +100 -18
  363. package/src/tools/browser/launch.ts +11 -2
  364. package/src/tools/browser/readable.ts +19 -2
  365. package/src/tools/browser/registry.ts +4 -1
  366. package/src/tools/browser/render.ts +2 -2
  367. package/src/tools/browser/tab-supervisor.ts +55 -16
  368. package/src/tools/conflict-detect.ts +50 -4
  369. package/src/tools/debug.ts +1 -1
  370. package/src/tools/eval-render.ts +5 -5
  371. package/src/tools/eval.ts +0 -2
  372. package/src/tools/fetch.ts +33 -10
  373. package/src/tools/gh-cache-invalidation.ts +63 -8
  374. package/src/tools/gh-renderer.ts +1 -1
  375. package/src/tools/gh.ts +172 -29
  376. package/src/tools/github-cache.ts +70 -6
  377. package/src/tools/image-gen.ts +14 -13
  378. package/src/tools/index.ts +13 -1
  379. package/src/tools/inspect-image.ts +1 -0
  380. package/src/tools/irc.ts +5 -1
  381. package/src/tools/job.ts +1 -1
  382. package/src/tools/read.ts +202 -61
  383. package/src/tools/render-utils.ts +3 -3
  384. package/src/tools/resolve.ts +1 -1
  385. package/src/tools/search.ts +92 -29
  386. package/src/tools/sqlite-reader.ts +17 -5
  387. package/src/tools/ssh.ts +8 -8
  388. package/src/tools/todo.ts +38 -8
  389. package/src/tools/write.ts +118 -18
  390. package/src/tui/output-block.ts +4 -4
  391. package/src/utils/changelog.ts +27 -1
  392. package/src/utils/commit-message-generator.ts +1 -0
  393. package/src/utils/file-mentions.ts +2 -1
  394. package/src/utils/git.ts +267 -13
  395. package/src/utils/title-generator.ts +24 -5
  396. package/src/web/scrapers/arxiv.ts +1 -1
  397. package/src/web/scrapers/go-pkg.ts +1 -1
  398. package/src/web/scrapers/iacr.ts +1 -1
  399. package/src/web/scrapers/readthedocs.ts +1 -1
  400. package/src/web/scrapers/twitter.ts +2 -1
  401. package/src/web/scrapers/types.ts +87 -8
  402. package/src/web/scrapers/wikipedia.ts +1 -1
  403. package/src/web/scrapers/youtube.ts +6 -1
  404. package/src/web/search/index.ts +1 -1
  405. package/src/web/search/providers/codex.ts +2 -1
  406. package/src/web/search/providers/gemini.ts +2 -3
  407. package/src/web/search/render.ts +8 -6
  408. package/dist/types/config/model-equivalence.d.ts +0 -24
  409. package/dist/types/config/model-id-affixes.d.ts +0 -12
  410. package/dist/types/config/model-provider-priority.d.ts +0 -1
  411. package/dist/types/exec/idle-timeout-watchdog.d.ts +0 -18
  412. package/src/config/model-equivalence.ts +0 -875
  413. package/src/config/model-id-affixes.ts +0 -81
  414. package/src/config/model-provider-priority.ts +0 -56
  415. package/src/exec/idle-timeout-watchdog.ts +0 -126
package/src/utils/git.ts CHANGED
@@ -27,6 +27,7 @@ export interface GitRepository {
27
27
  gitEntryPath: string;
28
28
  headPath: string;
29
29
  repoRoot: string;
30
+ isReftable?: boolean;
30
31
  }
31
32
 
32
33
  export interface GitStatusSummary {
@@ -476,6 +477,31 @@ async function resolveCommonDir(gitDir: string): Promise<string> {
476
477
  if (!relative) return gitDir;
477
478
  return path.resolve(gitDir, relative);
478
479
  }
480
+ function isLinkedWorktree(repository: GitRepository): boolean {
481
+ return (
482
+ repository.gitDir !== repository.commonDir &&
483
+ getEntryTypeSync(path.join(repository.gitDir, "commondir")) === "file"
484
+ );
485
+ }
486
+
487
+ async function isLinkedWorktreeAsync(repository: GitRepository): Promise<boolean> {
488
+ return (
489
+ repository.gitDir !== repository.commonDir &&
490
+ (await getEntryType(path.join(repository.gitDir, "commondir"))) === "file"
491
+ );
492
+ }
493
+
494
+ function primaryRootFromRepositorySync(repository: GitRepository): string {
495
+ if (path.basename(repository.commonDir) === ".git") return path.dirname(repository.commonDir);
496
+ if (isLinkedWorktree(repository)) return repository.commonDir;
497
+ return repository.repoRoot;
498
+ }
499
+
500
+ async function primaryRootFromRepository(repository: GitRepository): Promise<string> {
501
+ if (path.basename(repository.commonDir) === ".git") return path.dirname(repository.commonDir);
502
+ if (await isLinkedWorktreeAsync(repository)) return repository.commonDir;
503
+ return repository.repoRoot;
504
+ }
479
505
 
480
506
  function resolveRepoFromEntrySync(repoRoot: string, gitEntryPath: string, entryType: EntryType): GitRepository | null {
481
507
  const gitDir = resolveGitDirSync(gitEntryPath, entryType);
@@ -560,7 +586,174 @@ function parsePackedRefs(content: string | null, targetRef: string): string | nu
560
586
  return null;
561
587
  }
562
588
 
589
+ function stripGitConfigComments(line: string): string {
590
+ let clean = "";
591
+ let inQuotes = false;
592
+ for (let i = 0; i < line.length; i++) {
593
+ const char = line[i];
594
+ if (char === '"') {
595
+ inQuotes = !inQuotes;
596
+ clean += char;
597
+ } else if (!inQuotes && (char === ";" || char === "#")) {
598
+ break;
599
+ } else {
600
+ clean += char;
601
+ }
602
+ }
603
+ return clean.trim();
604
+ }
605
+
606
+ function parseGitConfigHasReftable(content: string): boolean {
607
+ let inExtensions = false;
608
+ for (const line of content.split("\n")) {
609
+ const trimmed = stripGitConfigComments(line);
610
+ if (trimmed.startsWith("[") && trimmed.endsWith("]")) {
611
+ const section = trimmed.slice(1, -1).trim().toLowerCase();
612
+ inExtensions = section === "extensions";
613
+ } else if (inExtensions) {
614
+ const eqIndex = trimmed.indexOf("=");
615
+ if (eqIndex !== -1) {
616
+ const key = trimmed.slice(0, eqIndex).trim().toLowerCase();
617
+ let value = trimmed.slice(eqIndex + 1).trim();
618
+ if (key === "refstorage") {
619
+ if (value.startsWith('"') && value.endsWith('"')) {
620
+ value = value.slice(1, -1).trim();
621
+ }
622
+ const lowerValue = value.toLowerCase();
623
+ if (lowerValue === "reftable" || lowerValue.startsWith("reftable:")) {
624
+ return true;
625
+ }
626
+ }
627
+ }
628
+ }
629
+ }
630
+ return false;
631
+ }
632
+
633
+ function isReftableRepoSync(repository: GitRepository): boolean {
634
+ if (repository.isReftable !== undefined) return repository.isReftable;
635
+ const configPath = path.join(repository.commonDir, "config");
636
+ const content = readOptionalTextSync(configPath);
637
+ repository.isReftable = content ? parseGitConfigHasReftable(content) : false;
638
+ return repository.isReftable;
639
+ }
640
+
641
+ async function isReftableRepo(repository: GitRepository): Promise<boolean> {
642
+ if (repository.isReftable !== undefined) return repository.isReftable;
643
+ const configPath = path.join(repository.commonDir, "config");
644
+ const content = await readOptionalText(configPath);
645
+ repository.isReftable = content ? parseGitConfigHasReftable(content) : false;
646
+ return repository.isReftable;
647
+ }
648
+
649
+ async function resolveHeadStateReftable(repository: GitRepository, signal?: AbortSignal): Promise<GitHeadState | null> {
650
+ throwIfAborted(signal);
651
+ const symResult = await git(repository.repoRoot, ["symbolic-ref", "HEAD"], { readOnly: true, signal }).catch(err => {
652
+ if (signal?.aborted || (err instanceof Error && (err.name === "AbortError" || err.name === "ToolAbortError"))) {
653
+ throw err;
654
+ }
655
+ return null;
656
+ });
657
+ throwIfAborted(signal);
658
+ const revResult = await git(repository.repoRoot, ["rev-parse", "--verify", "HEAD"], {
659
+ readOnly: true,
660
+ signal,
661
+ }).catch(err => {
662
+ if (signal?.aborted || (err instanceof Error && (err.name === "AbortError" || err.name === "ToolAbortError"))) {
663
+ throw err;
664
+ }
665
+ return null;
666
+ });
667
+ const commit = revResult && revResult.exitCode === 0 ? revResult.stdout.trim() || null : null;
668
+
669
+ if (symResult && symResult.exitCode === 0) {
670
+ const ref = symResult.stdout.trim();
671
+ const branchName = ref.startsWith(LOCAL_BRANCH_PREFIX) ? ref.slice(LOCAL_BRANCH_PREFIX.length) : null;
672
+ return {
673
+ ...repository,
674
+ kind: "ref",
675
+ ref,
676
+ branchName,
677
+ commit,
678
+ headContent: `${HEAD_REF_PREFIX} ${ref}`,
679
+ };
680
+ }
681
+
682
+ return {
683
+ ...repository,
684
+ kind: "detached",
685
+ commit,
686
+ headContent: commit || "",
687
+ };
688
+ }
689
+
690
+ function resolveHeadStateReftableSync(repository: GitRepository): GitHeadState | null {
691
+ ensureAvailable();
692
+ const symArgs = withShortLivedGitConfig(withNoOptionalLocks(["symbolic-ref", "HEAD"]));
693
+ const symResult = Bun.spawnSync(["git", ...symArgs], {
694
+ cwd: repository.repoRoot,
695
+ stdout: "pipe",
696
+ stderr: "pipe",
697
+ windowsHide: true,
698
+ });
699
+
700
+ const revArgs = withShortLivedGitConfig(withNoOptionalLocks(["rev-parse", "--verify", "HEAD"]));
701
+ const revResult = Bun.spawnSync(["git", ...revArgs], {
702
+ cwd: repository.repoRoot,
703
+ stdout: "pipe",
704
+ stderr: "pipe",
705
+ windowsHide: true,
706
+ });
707
+ const commit = revResult.exitCode === 0 ? new TextDecoder().decode(revResult.stdout).trim() || null : null;
708
+
709
+ if (symResult.exitCode === 0) {
710
+ const ref = new TextDecoder().decode(symResult.stdout).trim();
711
+ const branchName = ref.startsWith(LOCAL_BRANCH_PREFIX) ? ref.slice(LOCAL_BRANCH_PREFIX.length) : null;
712
+ return {
713
+ ...repository,
714
+ kind: "ref",
715
+ ref,
716
+ branchName,
717
+ commit,
718
+ headContent: `${HEAD_REF_PREFIX} ${ref}`,
719
+ };
720
+ }
721
+
722
+ return {
723
+ ...repository,
724
+ kind: "detached",
725
+ commit,
726
+ headContent: commit || "",
727
+ };
728
+ }
729
+
563
730
  function readRefSync(repository: GitRepository, targetRef: string): string | null {
731
+ if (isReftableRepoSync(repository)) {
732
+ ensureAvailable();
733
+ const symArgs = withShortLivedGitConfig(withNoOptionalLocks(["symbolic-ref", targetRef]));
734
+ const symResult = Bun.spawnSync(["git", ...symArgs], {
735
+ cwd: repository.repoRoot,
736
+ stdout: "pipe",
737
+ stderr: "pipe",
738
+ windowsHide: true,
739
+ });
740
+ if (symResult.exitCode === 0) {
741
+ const stdoutText = new TextDecoder().decode(symResult.stdout).trim();
742
+ return `${HEAD_REF_PREFIX} ${stdoutText}`;
743
+ }
744
+ const revArgs = withShortLivedGitConfig(withNoOptionalLocks(["rev-parse", "--verify", targetRef]));
745
+ const revResult = Bun.spawnSync(["git", ...revArgs], {
746
+ cwd: repository.repoRoot,
747
+ stdout: "pipe",
748
+ stderr: "pipe",
749
+ windowsHide: true,
750
+ });
751
+ if (revResult.exitCode === 0) {
752
+ return new TextDecoder().decode(revResult.stdout).trim() || null;
753
+ }
754
+ return null;
755
+ }
756
+
564
757
  for (const dir of getRefLookupDirs(repository)) {
565
758
  const value = normalizeRefValue(readOptionalTextSync(path.join(dir, targetRef)));
566
759
  if (value) return value;
@@ -572,7 +765,42 @@ function readRefSync(repository: GitRepository, targetRef: string): string | nul
572
765
  return null;
573
766
  }
574
767
 
575
- async function readRef(repository: GitRepository, targetRef: string): Promise<string | null> {
768
+ async function readRef(repository: GitRepository, targetRef: string, signal?: AbortSignal): Promise<string | null> {
769
+ if (await isReftableRepo(repository)) {
770
+ throwIfAborted(signal);
771
+ const symResult = await git(repository.repoRoot, ["symbolic-ref", targetRef], { readOnly: true, signal }).catch(
772
+ err => {
773
+ if (
774
+ signal?.aborted ||
775
+ (err instanceof Error && (err.name === "AbortError" || err.name === "ToolAbortError"))
776
+ ) {
777
+ throw err;
778
+ }
779
+ return null;
780
+ },
781
+ );
782
+ if (symResult && symResult.exitCode === 0) {
783
+ return `${HEAD_REF_PREFIX} ${symResult.stdout.trim()}`;
784
+ }
785
+ throwIfAborted(signal);
786
+ const revResult = await git(repository.repoRoot, ["rev-parse", "--verify", targetRef], {
787
+ readOnly: true,
788
+ signal,
789
+ }).catch(err => {
790
+ if (
791
+ signal?.aborted ||
792
+ (err instanceof Error && (err.name === "AbortError" || err.name === "ToolAbortError"))
793
+ ) {
794
+ throw err;
795
+ }
796
+ return null;
797
+ });
798
+ if (revResult && revResult.exitCode === 0) {
799
+ return revResult.stdout.trim() || null;
800
+ }
801
+ return null;
802
+ }
803
+
576
804
  for (const dir of getRefLookupDirs(repository)) {
577
805
  const value = normalizeRefValue(await readOptionalText(path.join(dir, targetRef)));
578
806
  if (value) return value;
@@ -997,7 +1225,7 @@ export const branch = {
997
1225
  const repository = await resolveRepository(cwd);
998
1226
  if (repository) {
999
1227
  for (const refPath of DEFAULT_BRANCH_REFS) {
1000
- const target = await readRef(repository, refPath);
1228
+ const target = await readRef(repository, refPath, signal);
1001
1229
  const branchName = parseDefaultBranchRef(refPath, target);
1002
1230
  if (branchName) return branchName;
1003
1231
  }
@@ -1095,7 +1323,7 @@ export const ref = {
1095
1323
  async exists(cwd: string, refName: string, signal?: AbortSignal): Promise<boolean> {
1096
1324
  if (refName === "HEAD") return (await head.sha(cwd, signal)) !== null;
1097
1325
  const repository = await resolveRepository(cwd);
1098
- if (repository && refName.startsWith("refs/")) return (await readRef(repository, refName)) !== null;
1326
+ if (repository && refName.startsWith("refs/")) return (await readRef(repository, refName, signal)) !== null;
1099
1327
  const result = await git(cwd, ["show-ref", "--verify", "--quiet", refName], { readOnly: true, signal });
1100
1328
  return result.exitCode === 0;
1101
1329
  },
@@ -1104,7 +1332,7 @@ export const ref = {
1104
1332
  async resolve(cwd: string, refName: string, signal?: AbortSignal): Promise<string | null> {
1105
1333
  if (refName === "HEAD") return head.sha(cwd, signal);
1106
1334
  const repository = await resolveRepository(cwd);
1107
- if (repository && refName.startsWith("refs/")) return readRef(repository, refName);
1335
+ if (repository && refName.startsWith("refs/")) return readRef(repository, refName, signal);
1108
1336
  const result = await git(cwd, ["rev-parse", refName], { readOnly: true, signal });
1109
1337
  if (result.exitCode !== 0) return null;
1110
1338
  return result.stdout.trim() || null;
@@ -1397,9 +1625,12 @@ export const ls = {
1397
1625
 
1398
1626
  export const head = {
1399
1627
  /** Full HEAD state (branch, commit, repo info). */
1400
- async resolve(cwd: string): Promise<GitHeadState | null> {
1628
+ async resolve(cwd: string, signal?: AbortSignal): Promise<GitHeadState | null> {
1401
1629
  const repository = await resolveRepository(cwd);
1402
1630
  if (!repository) return null;
1631
+ if (await isReftableRepo(repository)) {
1632
+ return resolveHeadStateReftable(repository, signal);
1633
+ }
1403
1634
  const content = await readOptionalText(repository.headPath);
1404
1635
  if (content === null) return null;
1405
1636
  return parseHeadState(repository, content);
@@ -1409,6 +1640,9 @@ export const head = {
1409
1640
  resolveSync(cwd: string): GitHeadState | null {
1410
1641
  const repository = resolveRepositorySync(cwd);
1411
1642
  if (!repository) return null;
1643
+ if (isReftableRepoSync(repository)) {
1644
+ return resolveHeadStateReftableSync(repository);
1645
+ }
1412
1646
  const content = readOptionalTextSync(repository.headPath);
1413
1647
  if (content === null) return null;
1414
1648
  return parseHeadStateSync(repository, content);
@@ -1416,7 +1650,7 @@ export const head = {
1416
1650
 
1417
1651
  /** Current HEAD commit SHA. */
1418
1652
  async sha(cwd: string, signal?: AbortSignal): Promise<string | null> {
1419
- const headState = await head.resolve(cwd);
1653
+ const headState = await head.resolve(cwd, signal);
1420
1654
  if (headState?.commit) return headState.commit;
1421
1655
  const result = await git(cwd, ["rev-parse", "HEAD"], { readOnly: true, signal });
1422
1656
  if (result.exitCode !== 0) return null;
@@ -1445,13 +1679,10 @@ export const repo = {
1445
1679
  return result.stdout.trim() || null;
1446
1680
  },
1447
1681
 
1448
- /** Resolve the primary repository root (not a worktree the main checkout). */
1682
+ /** Resolve the primary checkout root, or the shared common dir for bare-repo worktrees. */
1449
1683
  async primaryRoot(cwd: string, signal?: AbortSignal): Promise<string | null> {
1450
1684
  const repository = await resolveRepository(cwd);
1451
- if (repository) {
1452
- if (path.basename(repository.commonDir) === ".git") return path.dirname(repository.commonDir);
1453
- return repository.repoRoot;
1454
- }
1685
+ if (repository) return primaryRootFromRepository(repository);
1455
1686
  const repoRoot = await repo.root(cwd, signal);
1456
1687
  if (!repoRoot) return null;
1457
1688
  const commonDir = await runText(repoRoot, ["rev-parse", "--path-format=absolute", "--git-common-dir"], {
@@ -1462,6 +1693,19 @@ export const repo = {
1462
1693
  return repoRoot;
1463
1694
  },
1464
1695
 
1696
+ /**
1697
+ * Sync sibling of {@link primaryRoot}. Resolves only via on-disk `.git`/
1698
+ * `commondir` walking — no subprocess fallback — so it stays usable from
1699
+ * paths where async I/O is impractical (e.g. `computeBankScope`). Returns
1700
+ * `null` when `cwd` is outside a repository. Bare-repo worktrees resolve to
1701
+ * the shared common dir (`foo.git`) because they have no primary checkout.
1702
+ */
1703
+ primaryRootSync(cwd: string): string | null {
1704
+ const repository = resolveRepositorySync(cwd);
1705
+ if (!repository) return null;
1706
+ return primaryRootFromRepositorySync(repository);
1707
+ },
1708
+
1465
1709
  /** Full GitRepository metadata (sync). */
1466
1710
  resolveSync(cwd: string): GitRepository | null {
1467
1711
  return resolveRepositorySync(cwd);
@@ -1471,11 +1715,21 @@ export const repo = {
1471
1715
  resolve(cwd: string): Promise<GitRepository | null> {
1472
1716
  return resolveRepository(cwd);
1473
1717
  },
1718
+
1719
+ /** Check if the repository uses the reftable reference storage format (sync). */
1720
+ isReftableSync(repository: GitRepository): boolean {
1721
+ return isReftableRepoSync(repository);
1722
+ },
1723
+
1724
+ /** Check if the repository uses the reftable reference storage format. */
1725
+ isReftable(repository: GitRepository): Promise<boolean> {
1726
+ return isReftableRepo(repository);
1727
+ },
1474
1728
  };
1475
1729
 
1476
1730
  // Helper used during head resolution — defined here to reference `head` namespace.
1477
- async function resolveHead(cwd: string): Promise<GitHeadState | null> {
1478
- return head.resolve(cwd);
1731
+ async function resolveHead(cwd: string, signal?: AbortSignal): Promise<GitHeadState | null> {
1732
+ return head.resolve(cwd, signal);
1479
1733
  }
1480
1734
 
1481
1735
  // ════════════════════════════════════════════════════════════════════════════
@@ -33,7 +33,7 @@ const setTitleTool: Tool = {
33
33
  title: {
34
34
  type: "string",
35
35
  description:
36
- 'A concise, sentence-case 3-7 word title for the session (capitalize only the first word and proper nouns), or exactly "none" when the message carries no concrete task yet (greeting, small talk, vague).',
36
+ 'The generated session title, or exactly "none" when the message carries no concrete task yet.',
37
37
  },
38
38
  },
39
39
  required: ["title"],
@@ -137,6 +137,7 @@ export async function raceFirstNonNull<T>(
137
137
  * to produce request metadata (e.g. user_id for session attribution). Using a
138
138
  * resolver instead of a pre-evaluated value ensures the metadata's account_uuid
139
139
  * reflects the credential actually selected for this request.
140
+ * @param customSystemPrompt Optional title-specific system prompt override
140
141
  */
141
142
  export async function generateSessionTitle(
142
143
  firstMessage: string,
@@ -145,6 +146,7 @@ export async function generateSessionTitle(
145
146
  sessionId?: string,
146
147
  currentModel?: Model<Api>,
147
148
  metadataResolver?: (provider: string) => Record<string, unknown> | undefined,
149
+ customSystemPrompt?: string,
148
150
  ): Promise<string | null> {
149
151
  // Defer titling for greetings / acknowledgements / empty input. The default
150
152
  // tiny title model can't reliably decline trivial input, so this happens
@@ -155,13 +157,26 @@ export async function generateSessionTitle(
155
157
  return null;
156
158
  }
157
159
 
160
+ const titleSystemPrompt = customSystemPrompt?.trim() || undefined;
158
161
  const tinyModel = settings.get("providers.tinyModel");
159
162
  if (tinyModel === ONLINE_TINY_TITLE_MODEL_KEY) {
160
- return generateTitleOnline(firstMessage, registry, settings, sessionId, currentModel, metadataResolver);
163
+ return generateTitleOnline(
164
+ firstMessage,
165
+ registry,
166
+ settings,
167
+ sessionId,
168
+ currentModel,
169
+ metadataResolver,
170
+ undefined,
171
+ titleSystemPrompt,
172
+ );
161
173
  }
162
174
 
163
175
  const onlineAbortController = new AbortController();
164
- const localTitle = tinyTitleClient.generate(tinyModel, firstMessage).then(
176
+ const localTitlePromise = titleSystemPrompt
177
+ ? tinyTitleClient.generate(tinyModel, firstMessage, { systemPrompt: titleSystemPrompt })
178
+ : tinyTitleClient.generate(tinyModel, firstMessage);
179
+ const localTitle = localTitlePromise.then(
165
180
  title => title || null,
166
181
  err => {
167
182
  logger.warn("title-generator: local model error", {
@@ -181,6 +196,7 @@ export async function generateSessionTitle(
181
196
  currentModel,
182
197
  metadataResolver,
183
198
  onlineAbortController.signal,
199
+ titleSystemPrompt,
184
200
  );
185
201
 
186
202
  return raceFirstNonNull(localTitle, startOnline, TITLE_LOCAL_FALLBACK_DELAY_MS, () => {
@@ -196,6 +212,7 @@ export async function generateTitleOnline(
196
212
  currentModel?: Model<Api>,
197
213
  metadataResolver?: (provider: string) => Record<string, unknown> | undefined,
198
214
  signal?: AbortSignal,
215
+ customSystemPrompt?: string,
199
216
  ): Promise<string | null> {
200
217
  const model = getTitleModel(registry, settings, currentModel);
201
218
  if (!model) {
@@ -203,6 +220,8 @@ export async function generateTitleOnline(
203
220
  return null;
204
221
  }
205
222
 
223
+ const titleSystemPrompt = customSystemPrompt?.trim() || undefined;
224
+ const systemPrompt = titleSystemPrompt ?? TITLE_SYSTEM_PROMPT;
206
225
  const userMessage = formatTitleUserMessage(firstMessage);
207
226
  const modelName = `${model.provider}/${model.id}`;
208
227
  const modelContext = {
@@ -234,12 +253,12 @@ export async function generateTitleOnline(
234
253
  const response = await completeSimple(
235
254
  model,
236
255
  {
237
- systemPrompt: [TITLE_SYSTEM_PROMPT],
256
+ systemPrompt: [systemPrompt],
238
257
  messages: [{ role: "user", content: userMessage, timestamp: Date.now() }],
239
258
  tools: [setTitleTool],
240
259
  },
241
260
  {
242
- apiKey: registry.resolver(model.provider, { sessionId, baseUrl: model.baseUrl }),
261
+ apiKey: registry.resolver(model.provider, { sessionId, baseUrl: model.baseUrl, modelId: model.id }),
243
262
  maxTokens,
244
263
  disableReasoning: true,
245
264
  toolChoice: { type: "tool", name: SET_TITLE_TOOL_NAME },
@@ -1,4 +1,3 @@
1
- import { parseHTML } from "linkedom";
2
1
  import type { RenderResult, SpecialHandler } from "./types";
3
2
  import { buildResult, loadPage } from "./types";
4
3
  import { convertWithMarkit, fetchBinary } from "./utils";
@@ -31,6 +30,7 @@ export const handleArxiv: SpecialHandler = async (
31
30
  if (!result.ok) return null;
32
31
 
33
32
  // Parse the Atom feed response
33
+ const { parseHTML } = await import("linkedom");
34
34
  const doc = parseHTML(result.content).document;
35
35
  const entry = doc.querySelector("entry");
36
36
 
@@ -1,5 +1,4 @@
1
1
  import { tryParseJson } from "@oh-my-pi/pi-utils";
2
- import { parseHTML } from "linkedom";
3
2
  import type { RenderResult, SpecialHandler } from "./types";
4
3
  import { buildResult, htmlToBasicMarkdown, loadPage } from "./types";
5
4
 
@@ -97,6 +96,7 @@ export const handleGoPkg: SpecialHandler = async (
97
96
  });
98
97
  }
99
98
 
99
+ const { parseHTML } = await import("linkedom");
100
100
  const doc = parseHTML(pageResult.content).document;
101
101
 
102
102
  // Extract actual module path from breadcrumb or header
@@ -1,4 +1,3 @@
1
- import { parseHTML } from "linkedom";
2
1
  import type { RenderResult, SpecialHandler } from "./types";
3
2
  import { buildResult, loadPage } from "./types";
4
3
  import { convertWithMarkit, fetchBinary } from "./utils";
@@ -30,6 +29,7 @@ export const handleIacr: SpecialHandler = async (
30
29
 
31
30
  if (!result.ok) return null;
32
31
 
32
+ const { parseHTML } = await import("linkedom");
33
33
  const doc = parseHTML(result.content).document;
34
34
 
35
35
  // Extract metadata from the page
@@ -1,7 +1,6 @@
1
1
  /**
2
2
  * Read the Docs handler for web-fetch
3
3
  */
4
- import { parseHTML } from "linkedom";
5
4
  import { buildResult, htmlToBasicMarkdown, loadPage, type RenderResult, type SpecialHandler } from "./types";
6
5
 
7
6
  export const handleReadTheDocs: SpecialHandler = async (
@@ -39,6 +38,7 @@ export const handleReadTheDocs: SpecialHandler = async (
39
38
  }
40
39
 
41
40
  // Parse HTML
41
+ const { parseHTML } = await import("linkedom");
42
42
  const root = parseHTML(result.content).document;
43
43
 
44
44
  // Extract main content from common Read the Docs selectors
@@ -1,4 +1,4 @@
1
- import { type HTMLElement, parseHTML } from "linkedom";
1
+ import type { HTMLElement } from "linkedom";
2
2
  import { ToolAbortError } from "../../tools/tool-errors";
3
3
  import type { RenderResult, SpecialHandler } from "./types";
4
4
  import { buildResult, loadPage } from "./types";
@@ -33,6 +33,7 @@ export const handleTwitter: SpecialHandler = async (
33
33
 
34
34
  if (result.ok && result.content.length > 500) {
35
35
  // Parse the Nitter HTML
36
+ const { parseHTML } = await import("linkedom");
36
37
  const doc = parseHTML(result.content).document;
37
38
 
38
39
  // Extract tweet content