@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
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * Shared types and utilities for web-fetch handlers
3
3
  */
4
+ import { scheduler } from "node:timers/promises";
4
5
  import { ptree } from "@oh-my-pi/pi-utils";
5
6
  import type TurndownService from "turndown";
6
7
 
@@ -70,6 +71,12 @@ export interface LoadPageOptions {
70
71
  body?: string;
71
72
  maxBytes?: number;
72
73
  signal?: AbortSignal;
74
+ /**
75
+ * Return true to skip reading the response body for this content type
76
+ * (lowercased mime, no params). The caller is expected to re-fetch the
77
+ * payload as binary; this avoids streaming + decoding huge binaries twice.
78
+ */
79
+ skipBodyForContentType?: (contentType: string) => boolean;
73
80
  }
74
81
 
75
82
  export interface LoadPageResult {
@@ -78,6 +85,51 @@ export interface LoadPageResult {
78
85
  finalUrl: string;
79
86
  ok: boolean;
80
87
  status?: number;
88
+ /** True when the body was cut mid-stream at maxBytes. */
89
+ truncated?: boolean;
90
+ /** Last transport-level error message when ok is false. */
91
+ error?: string;
92
+ /** True when the body read was skipped via skipBodyForContentType. */
93
+ bodySkipped?: boolean;
94
+ }
95
+
96
+ const RETRY_AFTER_MAX_MS = 10_000;
97
+
98
+ /** Parse a Retry-After header (seconds or HTTP-date) into a bounded delay. */
99
+ function parseRetryAfterMs(value: string | null): number {
100
+ if (!value) return 1_000;
101
+ const seconds = Number(value);
102
+ if (Number.isFinite(seconds)) return Math.min(Math.max(seconds, 0) * 1000, RETRY_AFTER_MAX_MS);
103
+ const date = Date.parse(value);
104
+ if (!Number.isNaN(date)) return Math.min(Math.max(date - Date.now(), 0), RETRY_AFTER_MAX_MS);
105
+ return 1_000;
106
+ }
107
+
108
+ function charsetFromContentType(header: string): string | undefined {
109
+ return /charset\s*=\s*"?([\w-]+)"?/i.exec(header)?.[1];
110
+ }
111
+
112
+ /**
113
+ * Decode a response body honoring the declared charset (Content-Type header,
114
+ * then a cheap <meta charset> sniff), falling back to UTF-8.
115
+ */
116
+ function decodeBody(bytes: Buffer, contentTypeHeader: string): string {
117
+ let label = charsetFromContentType(contentTypeHeader);
118
+ if (!label) {
119
+ // All charsets we can decode are ASCII-compatible in the prefix, so a
120
+ // latin1 view of the first 2KB is enough to find a <meta charset>.
121
+ label = /<meta[^>]+charset\s*=\s*["']?([\w-]+)/i.exec(bytes.subarray(0, 2048).toString("latin1"))?.[1];
122
+ }
123
+ if (label && !/^utf-?8$/i.test(label)) {
124
+ try {
125
+ // Bun.Encoding's union is narrower than the runtime, which accepts
126
+ // WHATWG labels (shift_jis, euc-kr, gbk, big5, …); unknowns throw here.
127
+ return new TextDecoder(label as Bun.Encoding).decode(bytes);
128
+ } catch {
129
+ // Unknown/unsupported label — fall back to UTF-8.
130
+ }
131
+ }
132
+ return bytes.toString("utf-8");
81
133
  }
82
134
 
83
135
  /**
@@ -86,6 +138,8 @@ export interface LoadPageResult {
86
138
  export async function loadPage(url: string, options: LoadPageOptions = {}): Promise<LoadPageResult> {
87
139
  const { timeout = 20, headers = {}, maxBytes = MAX_BYTES, signal, method = "GET", body } = options;
88
140
 
141
+ let lastError: string | undefined;
142
+ let retried429 = false;
89
143
  for (let attempt = 0; attempt < USER_AGENTS.length; attempt++) {
90
144
  if (signal?.aborted) {
91
145
  throw new ToolAbortError();
@@ -114,9 +168,31 @@ export async function loadPage(url: string, options: LoadPageOptions = {}): Prom
114
168
 
115
169
  const response = await fetch(url, requestInit);
116
170
 
117
- const contentType = response.headers.get("content-type")?.split(";")[0]?.trim().toLowerCase() ?? "";
171
+ const rawContentType = response.headers.get("content-type") ?? "";
172
+ const contentType = rawContentType.split(";")[0]?.trim().toLowerCase() ?? "";
118
173
  const finalUrl = response.url;
119
174
 
175
+ if (response.status === 429 && !retried429) {
176
+ // Rate limited: retry once, honoring a bounded Retry-After. The
177
+ // wait observes the caller's signal so an Esc during the backoff
178
+ // does not stall for up to the full delay.
179
+ retried429 = true;
180
+ const delayMs = parseRetryAfterMs(response.headers.get("retry-after"));
181
+ void response.body?.cancel().catch(() => {});
182
+ try {
183
+ await scheduler.wait(delayMs, { signal });
184
+ } catch {
185
+ throw new ToolAbortError();
186
+ }
187
+ attempt--; // Reuse the same user agent for the retry.
188
+ continue;
189
+ }
190
+
191
+ if (response.ok && options.skipBodyForContentType?.(contentType)) {
192
+ void response.body?.cancel().catch(() => {});
193
+ return { content: "", contentType, finalUrl, ok: true, status: response.status, bodySkipped: true };
194
+ }
195
+
120
196
  const reader = response.body?.getReader();
121
197
  if (!reader) {
122
198
  return { content: "", contentType, finalUrl, ok: false, status: response.status };
@@ -124,6 +200,7 @@ export async function loadPage(url: string, options: LoadPageOptions = {}): Prom
124
200
 
125
201
  const chunks: Uint8Array[] = [];
126
202
  let totalSize = 0;
203
+ let truncated = false;
127
204
 
128
205
  while (true) {
129
206
  const { done, value } = await reader.read();
@@ -133,32 +210,34 @@ export async function loadPage(url: string, options: LoadPageOptions = {}): Prom
133
210
  totalSize += value.length;
134
211
 
135
212
  if (totalSize > maxBytes) {
136
- reader.cancel();
213
+ truncated = true;
214
+ void reader.cancel().catch(() => {});
137
215
  break;
138
216
  }
139
217
  }
140
218
 
141
- const content = Buffer.concat(chunks).toString("utf-8");
219
+ const content = decodeBody(Buffer.concat(chunks), rawContentType);
142
220
  if (isBotBlocked(response.status, content) && attempt < USER_AGENTS.length - 1) {
143
221
  continue;
144
222
  }
145
223
 
146
224
  if (!response.ok) {
147
- return { content, contentType, finalUrl, ok: false, status: response.status };
225
+ return { content, contentType, finalUrl, ok: false, status: response.status, truncated };
148
226
  }
149
227
 
150
- return { content, contentType, finalUrl, ok: true, status: response.status };
151
- } catch {
228
+ return { content, contentType, finalUrl, ok: true, status: response.status, truncated };
229
+ } catch (error) {
152
230
  if (signal?.aborted) {
153
231
  throw new ToolAbortError();
154
232
  }
233
+ lastError = error instanceof Error ? error.message : String(error);
155
234
  if (attempt === USER_AGENTS.length - 1) {
156
- return { content: "", contentType: "", finalUrl: url, ok: false };
235
+ return { content: "", contentType: "", finalUrl: url, ok: false, error: lastError };
157
236
  }
158
237
  }
159
238
  }
160
239
 
161
- return { content: "", contentType: "", finalUrl: url, ok: false };
240
+ return { content: "", contentType: "", finalUrl: url, ok: false, error: lastError };
162
241
  }
163
242
 
164
243
  /** Module-level Turndown instance — built lazily on first use. */
@@ -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
 
@@ -45,6 +44,7 @@ export const handleWikipedia: SpecialHandler = async (
45
44
  const contentResult = await loadPage(contentUrl, { timeout, signal });
46
45
 
47
46
  if (contentResult.ok) {
47
+ const { parseHTML } = await import("linkedom");
48
48
  const doc = parseHTML(contentResult.content).document;
49
49
 
50
50
  // Extract main content sections
@@ -288,12 +288,17 @@ export const handleYouTube: SpecialHandler = async (
288
288
  }
289
289
  }
290
290
  } finally {
291
- throwIfAborted(signal);
292
291
  // Cleanup temp files (fire-and-forget with error suppression)
293
292
  Array.fromAsync(new Bun.Glob(`${tmpBase}*`).scan({ absolute: true }))
294
293
  .then(tmpFiles => Promise.all(tmpFiles.map(f => fs.unlink(f).catch(() => {}))))
295
294
  .catch(() => {});
296
295
  }
296
+ // Only a user-initiated abort is fatal; the per-fetch time budget expiring
297
+ // just means partial metadata/transcript, which we surface as a note.
298
+ throwIfAborted(userSignal);
299
+ if (signal?.aborted) {
300
+ notes.push("Fetch time budget exhausted; metadata/transcript may be incomplete");
301
+ }
297
302
 
298
303
  // Build markdown output
299
304
  let md = `# ${title}\n\n`;
@@ -150,7 +150,7 @@ async function executeSearch(
150
150
  lastProvider = provider;
151
151
  try {
152
152
  const response = await provider.search({
153
- query: params.query.replace(/202\d/g, String(new Date().getFullYear())), // LUL
153
+ query: params.query,
154
154
  limit: params.limit,
155
155
  recency: params.recency,
156
156
  systemPrompt: webSearchSystemPrompt,
@@ -7,8 +7,9 @@
7
7
  * SQLite store, never POSTs the broker sentinel to an OpenAI token endpoint.
8
8
  */
9
9
  import * as os from "node:os";
10
- import { type AuthStorage, type FetchImpl, getBundledModels } from "@oh-my-pi/pi-ai";
10
+ import type { AuthStorage, FetchImpl } from "@oh-my-pi/pi-ai";
11
11
  import { decodeJwt } from "@oh-my-pi/pi-ai/oauth/openai-codex";
12
+ import { getBundledModels } from "@oh-my-pi/pi-catalog/models";
12
13
  import { $env, readSseJson } from "@oh-my-pi/pi-utils";
13
14
  import packageJson from "../../../../package.json" with { type: "json" };
14
15
  import type { SearchResponse, SearchSource } from "../../../web/search/types";
@@ -8,13 +8,12 @@
8
8
  * sibling SQLite store and never POSTs the broker sentinel to a Google token
9
9
  * endpoint.
10
10
  */
11
+ import type { AuthStorage, FetchImpl } from "@oh-my-pi/pi-ai";
11
12
  import {
12
13
  ANTIGRAVITY_SYSTEM_INSTRUCTION,
13
- type AuthStorage,
14
- type FetchImpl,
15
14
  getAntigravityUserAgent,
16
15
  getGeminiCliHeaders,
17
- } from "@oh-my-pi/pi-ai";
16
+ } from "@oh-my-pi/pi-catalog/wire/gemini-headers";
18
17
  import { fetchWithRetry } from "@oh-my-pi/pi-utils";
19
18
 
20
19
  import type { SearchCitation, SearchResponse, SearchSource } from "../../../web/search/types";
@@ -65,7 +65,7 @@ function renderSearchErrorPanel(message: string, providerLabel: string | undefin
65
65
  const body = theme.fg("error", `Error: ${replaceTabs(message)}`);
66
66
  const outputBlock = new CachedOutputBlock();
67
67
  return markFramedBlockComponent({
68
- render(width: number): string[] {
68
+ render(width: number): readonly string[] {
69
69
  return outputBlock.render({ header, state: "error", sections: [{ lines: [body] }], width }, theme);
70
70
  },
71
71
  invalidate() {
@@ -154,23 +154,25 @@ export function renderSearchResult(
154
154
  const outputBlock = new CachedOutputBlock();
155
155
 
156
156
  return markFramedBlockComponent({
157
- render(width: number): string[] {
157
+ render(width: number): readonly string[] {
158
158
  // Read mutable state at render time
159
159
  const { expanded } = options;
160
160
 
161
161
  // Answer lines: full markdown when expanded, capped markdown preview when collapsed.
162
162
  const answerWidth = Math.max(20, width - 3);
163
163
  const renderedAnswer = answerMarkdown ? answerMarkdown.render(answerWidth) : [];
164
- let answerLines: string[];
164
+ let answerLines: readonly string[];
165
165
  if (renderedAnswer.length === 0) {
166
166
  answerLines = [theme.fg("muted", "No answer text returned")];
167
167
  } else if (args?.maxAnswerLines !== undefined && !expanded) {
168
168
  // CLI compact mode (`omp q`) caps the answer; the TUI passes no cap and shows it in full.
169
- answerLines = renderedAnswer.slice(0, args.maxAnswerLines);
170
- const remaining = renderedAnswer.length - answerLines.length;
169
+ // `renderedAnswer` is the Markdown component's shared cache — slice copies before appending.
170
+ const capped = renderedAnswer.slice(0, args.maxAnswerLines);
171
+ const remaining = renderedAnswer.length - capped.length;
171
172
  if (remaining > 0) {
172
- answerLines.push(theme.fg("muted", formatMoreItems(remaining, "line")));
173
+ capped.push(theme.fg("muted", formatMoreItems(remaining, "line")));
173
174
  }
175
+ answerLines = capped;
174
176
  } else {
175
177
  answerLines = renderedAnswer;
176
178
  }
@@ -1,24 +0,0 @@
1
- import { type Api, type Model } from "@oh-my-pi/pi-ai";
2
- export type CanonicalModelSource = "override" | "bundled" | "heuristic" | "fallback";
3
- export interface ModelEquivalenceConfig {
4
- overrides?: Record<string, string>;
5
- exclude?: string[];
6
- }
7
- export interface CanonicalModelVariant {
8
- canonicalId: string;
9
- selector: string;
10
- model: Model<Api>;
11
- source: CanonicalModelSource;
12
- }
13
- export interface CanonicalModelRecord {
14
- id: string;
15
- name: string;
16
- variants: CanonicalModelVariant[];
17
- }
18
- export interface CanonicalModelIndex {
19
- records: CanonicalModelRecord[];
20
- byId: Map<string, CanonicalModelRecord>;
21
- bySelector: Map<string, string>;
22
- }
23
- export declare function formatCanonicalVariantSelector(model: Model<Api>): string;
24
- export declare function buildCanonicalModelIndex(models: readonly Model<Api>[], equivalence?: ModelEquivalenceConfig): CanonicalModelIndex;
@@ -1,12 +0,0 @@
1
- export declare function getModelLikeIdSegments(modelId: string): string[];
2
- export declare function getLongestModelLikeIdSegment(modelId: string): string | undefined;
3
- /**
4
- * Strip reseller / wrapper tags that are injected as bracketed affixes around an
5
- * upstream model id, e.g.
6
- * "[Kiro] claude-opus-4-8" -> "claude-opus-4-8"
7
- * "[gcli转] gemini-3.1-pro-preview [假流]" -> "gemini-3.1-pro-preview"
8
- *
9
- * Candidates are returned most-stripped first: both ends, then leading-only, then trailing-only.
10
- */
11
- export declare function getBracketStrippedModelIdCandidates(modelId: string): string[];
12
- export declare function stripBracketedModelIdAffixes(modelId: string): string | undefined;
@@ -1 +0,0 @@
1
- export declare function buildModelProviderPriorityRank(configuredProviderOrder?: readonly string[]): Map<string, number>;
@@ -1,18 +0,0 @@
1
- export type ExecutionAbortReason = "idle-timeout" | "signal";
2
- export interface IdleTimeoutWatchdogOptions {
3
- timeoutMs?: number;
4
- signal?: AbortSignal;
5
- hardTimeoutGraceMs: number;
6
- onAbort?: (reason: ExecutionAbortReason) => void;
7
- }
8
- export declare class IdleTimeoutWatchdog {
9
- #private;
10
- constructor(options: IdleTimeoutWatchdogOptions);
11
- get abortedBySignal(): boolean;
12
- get hardTimeoutPromise(): Promise<"hard-timeout">;
13
- get signal(): AbortSignal;
14
- get timedOut(): boolean;
15
- touch(): void;
16
- dispose(): void;
17
- }
18
- export declare function formatIdleTimeoutMessage(timeoutMs?: number): string;