@oh-my-pi/pi-coding-agent 17.2.3 → 17.2.5

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 (375) hide show
  1. package/CHANGELOG.md +92 -0
  2. package/dist/{CHANGELOG-c5hpqt9r.md → CHANGELOG-q2w43aw3.md} +92 -0
  3. package/dist/cli.js +3979 -3548
  4. package/dist/{template-8vdv6xb4.js → template-c2hyaytt.js} +8 -26
  5. package/dist/types/advisor/advise-tool.d.ts +6 -0
  6. package/dist/types/advisor/runtime.d.ts +4 -4
  7. package/dist/types/capability/mcp.d.ts +9 -0
  8. package/dist/types/cli/args.d.ts +4 -1
  9. package/dist/types/cli/browser-relay-cli.d.ts +15 -0
  10. package/dist/types/cli/command-help.d.ts +99 -0
  11. package/dist/types/cli/help-extra.d.ts +2 -0
  12. package/dist/types/cli/models-cli.d.ts +1 -1
  13. package/dist/types/cli/thinking-levels.d.ts +5 -0
  14. package/dist/types/cli/update-cli.d.ts +13 -0
  15. package/dist/types/commands/browser-relay.d.ts +38 -0
  16. package/dist/types/commands/commit.d.ts +3 -0
  17. package/dist/types/commands/complete.d.ts +1 -1
  18. package/dist/types/commands/completions.d.ts +6 -0
  19. package/dist/types/commands/grep.d.ts +3 -0
  20. package/dist/types/commands/join.d.ts +4 -0
  21. package/dist/types/commands/launch-help.d.ts +171 -0
  22. package/dist/types/commands/launch.d.ts +5 -1
  23. package/dist/types/commands/models.d.ts +3 -0
  24. package/dist/types/commands/say.d.ts +10 -0
  25. package/dist/types/commands/worktree.d.ts +3 -0
  26. package/dist/types/config/keybindings.d.ts +6 -1
  27. package/dist/types/config/model-discovery.d.ts +2 -2
  28. package/dist/types/config/models-config-schema-bundle.d.ts +3 -0
  29. package/dist/types/config/models-config-schema.d.ts +2 -0
  30. package/dist/types/config/models-config.d.ts +1 -0
  31. package/dist/types/config/service-tier.d.ts +2 -0
  32. package/dist/types/config/settings-schema.d.ts +70 -22
  33. package/dist/types/cursor-bridge-tools.d.ts +1 -1
  34. package/dist/types/cursor.d.ts +7 -4
  35. package/dist/types/discovery/helpers.d.ts +6 -0
  36. package/dist/types/discovery/omp-extension-roots.d.ts +21 -2
  37. package/dist/types/edit/index.d.ts +3 -3
  38. package/dist/types/edit/modes/replace.d.ts +22 -15
  39. package/dist/types/edit/renderer.d.ts +1 -1
  40. package/dist/types/eval/py/kernel.d.ts +3 -1
  41. package/dist/types/eval/py/spawn-options.d.ts +12 -16
  42. package/dist/types/extensibility/extensions/loader.d.ts +6 -2
  43. package/dist/types/extensibility/legacy-pi-ai-shim.d.ts +8 -1
  44. package/dist/types/extensibility/legacy-pi-coding-agent-shim.d.ts +1 -1
  45. package/dist/types/extensibility/plugins/legacy-pi-compat.d.ts +2 -0
  46. package/dist/types/extensibility/plugins/marketplace/registry.d.ts +2 -2
  47. package/dist/types/launch/broker.d.ts +1 -1
  48. package/dist/types/launch/client.d.ts +6 -3
  49. package/dist/types/launch/ensure.d.ts +8 -0
  50. package/dist/types/launch/paths.d.ts +3 -2
  51. package/dist/types/launch/protocol.d.ts +2 -2
  52. package/dist/types/lsp/client.d.ts +2 -0
  53. package/dist/types/lsp/mux/daemon.d.ts +15 -0
  54. package/dist/types/lsp/mux/protocol.d.ts +57 -0
  55. package/dist/types/lsp/mux/server.d.ts +18 -0
  56. package/dist/types/lsp/types.d.ts +22 -2
  57. package/dist/types/main.d.ts +2 -0
  58. package/dist/types/mcp/request-id.d.ts +19 -0
  59. package/dist/types/mcp/types.d.ts +14 -0
  60. package/dist/types/memory-backend/index.d.ts +1 -0
  61. package/dist/types/memory-backend/messages.d.ts +15 -0
  62. package/dist/types/mnemopi/embed-client.d.ts +1 -1
  63. package/dist/types/mnemopi/state.d.ts +0 -23
  64. package/dist/types/modes/components/assistant-message.d.ts +2 -0
  65. package/dist/types/modes/components/custom-editor.d.ts +2 -1
  66. package/dist/types/modes/components/model-browser.d.ts +7 -5
  67. package/dist/types/modes/components/model-picker.d.ts +9 -3
  68. package/dist/types/modes/components/read-tool-group.d.ts +11 -0
  69. package/dist/types/modes/components/stripped-tool-calls-placeholder.d.ts +12 -0
  70. package/dist/types/modes/components/tool-execution.d.ts +2 -0
  71. package/dist/types/modes/controllers/input-controller.d.ts +1 -0
  72. package/dist/types/modes/interactive-mode.d.ts +1 -0
  73. package/dist/types/modes/types.d.ts +2 -1
  74. package/dist/types/modes/workflow.d.ts +2 -1
  75. package/dist/types/registry/agent-lifecycle.d.ts +14 -5
  76. package/dist/types/registry/agent-registry.d.ts +4 -3
  77. package/dist/types/sdk.d.ts +4 -2
  78. package/dist/types/secrets/index.d.ts +7 -9
  79. package/dist/types/session/agent-session-types.d.ts +3 -1
  80. package/dist/types/session/agent-session.d.ts +6 -1
  81. package/dist/types/session/indexed-session-storage.d.ts +1 -0
  82. package/dist/types/session/model-controls.d.ts +0 -1
  83. package/dist/types/session/session-advisors.d.ts +8 -1
  84. package/dist/types/session/session-context.d.ts +2 -1
  85. package/dist/types/session/session-maintenance.d.ts +2 -0
  86. package/dist/types/session/session-manager.d.ts +16 -5
  87. package/dist/types/session/session-stats.d.ts +10 -0
  88. package/dist/types/session/session-storage.d.ts +15 -3
  89. package/dist/types/system-prompt.d.ts +6 -1
  90. package/dist/types/task/index.d.ts +2 -1
  91. package/dist/types/task/spawn-policy.d.ts +5 -0
  92. package/dist/types/thinking.d.ts +1 -7
  93. package/dist/types/tools/ast-grep.d.ts +1 -1
  94. package/dist/types/tools/browser/registry.d.ts +2 -1
  95. package/dist/types/tools/browser/relay/bridge.d.ts +35 -0
  96. package/dist/types/tools/browser/relay/daemon.d.ts +16 -0
  97. package/dist/types/tools/browser/relay/kind.d.ts +19 -0
  98. package/dist/types/tools/browser/relay/protocol.d.ts +97 -0
  99. package/dist/types/tools/browser/relay/server.d.ts +35 -0
  100. package/dist/types/tools/browser/render.d.ts +1 -0
  101. package/dist/types/tools/browser.d.ts +3 -0
  102. package/dist/types/tools/computer/exposure.d.ts +9 -7
  103. package/dist/types/tools/computer/protocol.d.ts +70 -17
  104. package/dist/types/tools/computer/supervisor.d.ts +23 -10
  105. package/dist/types/tools/computer/worker-entry.d.ts +1 -0
  106. package/dist/types/tools/computer/worker.d.ts +42 -7
  107. package/dist/types/tools/computer-renderer.d.ts +7 -5
  108. package/dist/types/tools/computer.d.ts +25 -44
  109. package/dist/types/tools/context.d.ts +3 -0
  110. package/dist/types/tools/default-renderer.d.ts +3 -0
  111. package/dist/types/tools/glob.d.ts +1 -1
  112. package/dist/types/tools/grep.d.ts +1 -1
  113. package/dist/types/tools/render-utils.d.ts +2 -0
  114. package/dist/types/tools/{browser/run-cancellation.d.ts → run-scope.d.ts} +8 -8
  115. package/dist/types/tools/tool-timeouts.d.ts +5 -0
  116. package/dist/types/tools/xdev.d.ts +8 -0
  117. package/dist/types/utils/clipboard.d.ts +2 -2
  118. package/dist/types/web/kagi.d.ts +1 -0
  119. package/dist/types/web/search/index.d.ts +1 -1
  120. package/dist/types/web/search/providers/anthropic.d.ts +1 -0
  121. package/dist/types/web/search/providers/base.d.ts +2 -0
  122. package/dist/types/web/search/providers/brave.d.ts +1 -0
  123. package/dist/types/web/search/providers/browser-page.d.ts +1 -0
  124. package/dist/types/web/search/providers/codex.d.ts +1 -0
  125. package/dist/types/web/search/providers/exa.d.ts +1 -0
  126. package/dist/types/web/search/providers/firecrawl.d.ts +1 -0
  127. package/dist/types/web/search/providers/gemini.d.ts +1 -0
  128. package/dist/types/web/search/providers/jina.d.ts +1 -0
  129. package/dist/types/web/search/providers/kagi.d.ts +1 -0
  130. package/dist/types/web/search/providers/kimi.d.ts +1 -0
  131. package/dist/types/web/search/providers/parallel.d.ts +1 -0
  132. package/dist/types/web/search/providers/perplexity.d.ts +1 -0
  133. package/dist/types/web/search/providers/searxng.d.ts +1 -0
  134. package/dist/types/web/search/providers/tavily.d.ts +1 -0
  135. package/dist/types/web/search/providers/tinyfish.d.ts +1 -0
  136. package/dist/types/web/search/providers/utils.d.ts +6 -9
  137. package/dist/types/web/search/providers/zai.d.ts +1 -0
  138. package/dist/types/web/search/types.d.ts +4 -0
  139. package/package.json +12 -12
  140. package/scripts/legacy-pi-virtual-module.ts +12 -2
  141. package/src/advisor/advise-tool.ts +18 -0
  142. package/src/advisor/runtime.ts +6 -6
  143. package/src/capability/mcp.ts +7 -0
  144. package/src/cli/args.ts +7 -87
  145. package/src/cli/browser-relay-cli.ts +119 -0
  146. package/src/cli/command-help.ts +103 -0
  147. package/src/cli/completion-gen.ts +5 -5
  148. package/src/cli/flag-tables.ts +9 -0
  149. package/src/cli/help-extra.ts +89 -0
  150. package/src/cli/models-cli.ts +13 -16
  151. package/src/cli/setup-cli.ts +13 -21
  152. package/src/cli/thinking-levels.ts +7 -0
  153. package/src/cli/update-cli.ts +26 -7
  154. package/src/cli-commands.ts +170 -33
  155. package/src/cli.ts +17 -5
  156. package/src/collab/host.ts +1 -1
  157. package/src/commands/acp.ts +3 -1
  158. package/src/commands/agents.ts +3 -2
  159. package/src/commands/auth-broker.ts +3 -2
  160. package/src/commands/auth-gateway.ts +3 -2
  161. package/src/commands/bench.ts +2 -3
  162. package/src/commands/browser-relay.ts +53 -0
  163. package/src/commands/cleanse.ts +2 -2
  164. package/src/commands/commit.ts +3 -2
  165. package/src/commands/complete.ts +2 -1
  166. package/src/commands/completions.ts +3 -2
  167. package/src/commands/config.ts +3 -2
  168. package/src/commands/dry-balance.ts +2 -2
  169. package/src/commands/gallery.ts +3 -2
  170. package/src/commands/gc.ts +3 -2
  171. package/src/commands/grep.ts +3 -2
  172. package/src/commands/grievances.ts +3 -2
  173. package/src/commands/install.ts +2 -2
  174. package/src/commands/join.ts +3 -2
  175. package/src/commands/launch-help.ts +116 -0
  176. package/src/commands/launch.ts +7 -191
  177. package/src/commands/models.ts +3 -2
  178. package/src/commands/plugin.ts +3 -2
  179. package/src/commands/read.ts +3 -2
  180. package/src/commands/say.ts +3 -2
  181. package/src/commands/setup.ts +3 -2
  182. package/src/commands/shell.ts +3 -2
  183. package/src/commands/ssh.ts +3 -2
  184. package/src/commands/stats.ts +3 -2
  185. package/src/commands/tiny-models.ts +2 -2
  186. package/src/commands/token.ts +2 -2
  187. package/src/commands/ttsr.ts +2 -2
  188. package/src/commands/update.ts +3 -2
  189. package/src/commands/usage.ts +3 -2
  190. package/src/commands/web-search.ts +3 -2
  191. package/src/commands/worktree.ts +3 -2
  192. package/src/config/keybindings.ts +19 -9
  193. package/src/config/mcp-schema.json +5 -0
  194. package/src/config/model-discovery.ts +30 -13
  195. package/src/config/model-registry.ts +16 -6
  196. package/src/config/models-config-schema-bundle.ts +9 -0
  197. package/src/config/resolve-config-value.ts +2 -1
  198. package/src/config/service-tier.ts +5 -0
  199. package/src/config/settings-schema.ts +73 -21
  200. package/src/cursor-bridge-tools.ts +1 -1
  201. package/src/cursor.ts +10 -14
  202. package/src/discovery/builtin.ts +10 -0
  203. package/src/discovery/helpers.ts +10 -0
  204. package/src/discovery/mcp-json.ts +11 -1
  205. package/src/discovery/omp-extension-roots.ts +79 -20
  206. package/src/discovery/omp-plugins.ts +10 -1
  207. package/src/edit/diff.ts +17 -8
  208. package/src/edit/index.ts +20 -7
  209. package/src/edit/modes/replace.ts +93 -40
  210. package/src/edit/renderer.ts +1 -1
  211. package/src/edit/streaming.ts +14 -17
  212. package/src/eval/py/kernel.ts +2 -1
  213. package/src/eval/py/spawn-options.ts +24 -29
  214. package/src/export/html/template.js +8 -26
  215. package/src/extensibility/extensions/loader.ts +66 -28
  216. package/src/extensibility/extensions/wrapper.ts +1 -0
  217. package/src/extensibility/legacy-pi-ai-shim.ts +22 -1
  218. package/src/extensibility/legacy-pi-coding-agent-shim.ts +7 -6
  219. package/src/extensibility/plugins/legacy-pi-compat.ts +124 -57
  220. package/src/extensibility/plugins/marketplace/registry.ts +4 -8
  221. package/src/extensibility/skills.ts +11 -0
  222. package/src/extensibility/utils.ts +10 -2
  223. package/src/launch/broker.ts +1 -1
  224. package/src/launch/client.ts +32 -13
  225. package/src/launch/ensure.ts +73 -0
  226. package/src/launch/paths.ts +3 -6
  227. package/src/launch/protocol.ts +2 -2
  228. package/src/lsp/client.ts +23 -2
  229. package/src/lsp/index.ts +8 -0
  230. package/src/lsp/mux/daemon.ts +348 -0
  231. package/src/lsp/mux/protocol.ts +96 -0
  232. package/src/lsp/mux/server.ts +797 -0
  233. package/src/lsp/types.ts +28 -2
  234. package/src/main.ts +31 -24
  235. package/src/mcp/config.ts +1 -0
  236. package/src/mcp/oauth-flow.ts +11 -1
  237. package/src/mcp/request-id.ts +24 -0
  238. package/src/mcp/transports/http.ts +4 -2
  239. package/src/mcp/transports/sse.ts +4 -2
  240. package/src/mcp/transports/stdio.ts +4 -2
  241. package/src/mcp/types.ts +15 -0
  242. package/src/memory-backend/index.ts +1 -0
  243. package/src/memory-backend/messages.ts +19 -0
  244. package/src/mnemopi/embed-client.ts +49 -2
  245. package/src/mnemopi/state.ts +57 -23
  246. package/src/modes/components/agent-hub.ts +1 -1
  247. package/src/modes/components/assistant-message.ts +11 -0
  248. package/src/modes/components/chat-transcript-builder.ts +4 -0
  249. package/src/modes/components/custom-editor.ts +10 -1
  250. package/src/modes/components/model-browser.ts +25 -17
  251. package/src/modes/components/model-picker.ts +10 -6
  252. package/src/modes/components/read-tool-group.ts +36 -0
  253. package/src/modes/components/status-line/component.ts +1 -1
  254. package/src/modes/components/stripped-tool-calls-placeholder.ts +35 -0
  255. package/src/modes/components/tool-execution.ts +85 -20
  256. package/src/modes/components/tree-selector.ts +46 -48
  257. package/src/modes/controllers/command-controller.ts +2 -2
  258. package/src/modes/controllers/event-controller.ts +199 -10
  259. package/src/modes/controllers/input-controller.ts +39 -1
  260. package/src/modes/controllers/mcp-command-controller.ts +11 -5
  261. package/src/modes/controllers/selector-controller.ts +47 -6
  262. package/src/modes/interactive-mode.ts +2 -0
  263. package/src/modes/types.ts +6 -1
  264. package/src/modes/utils/hotkeys-markdown.ts +1 -0
  265. package/src/modes/utils/interactive-context-helpers.ts +1 -0
  266. package/src/modes/utils/ui-helpers.ts +6 -10
  267. package/src/modes/workflow.ts +8 -2
  268. package/src/prompts/agents/init.md +1 -1
  269. package/src/prompts/system/plan-mode-active.md +2 -2
  270. package/src/prompts/system/system-prompt.md +26 -52
  271. package/src/prompts/system/workflow-notice.md +3 -3
  272. package/src/prompts/tools/ast-grep.md +1 -1
  273. package/src/prompts/tools/bash.md +1 -1
  274. package/src/prompts/tools/browser.md +1 -0
  275. package/src/prompts/tools/computer.md +21 -21
  276. package/src/prompts/tools/glob.md +1 -1
  277. package/src/prompts/tools/grep.md +1 -1
  278. package/src/prompts/tools/replace.md +5 -4
  279. package/src/prompts/tools/task.md +4 -4
  280. package/src/registry/agent-lifecycle.ts +36 -11
  281. package/src/registry/agent-registry.ts +12 -5
  282. package/src/sdk.ts +102 -35
  283. package/src/secrets/index.ts +16 -18
  284. package/src/session/agent-session-types.ts +3 -1
  285. package/src/session/agent-session.ts +23 -2
  286. package/src/session/agent-storage.ts +6 -4
  287. package/src/session/history-storage.ts +4 -2
  288. package/src/session/indexed-session-storage.ts +9 -0
  289. package/src/session/messages.ts +31 -7
  290. package/src/session/model-controls.ts +0 -1
  291. package/src/session/prewalk.ts +24 -2
  292. package/src/session/session-advisors.ts +21 -3
  293. package/src/session/session-context.ts +16 -12
  294. package/src/session/session-dump-format.ts +1 -1
  295. package/src/session/session-maintenance.ts +41 -4
  296. package/src/session/session-manager.ts +181 -94
  297. package/src/session/session-paths.ts +118 -55
  298. package/src/session/session-stats.ts +48 -3
  299. package/src/session/session-storage.ts +30 -22
  300. package/src/session/session-tools.ts +25 -23
  301. package/src/session/stream-guards.ts +1 -1
  302. package/src/slash-commands/builtin-registry.ts +29 -26
  303. package/src/system-prompt.ts +14 -4
  304. package/src/task/executor.ts +8 -1
  305. package/src/task/index.ts +23 -8
  306. package/src/task/spawn-policy.ts +14 -0
  307. package/src/thinking.ts +2 -8
  308. package/src/tiny/text.ts +12 -0
  309. package/src/tools/ast-grep.ts +10 -4
  310. package/src/tools/browser/cmux/cmux-tab.ts +5 -10
  311. package/src/tools/browser/cmux/rpc.ts +2 -8
  312. package/src/tools/browser/registry.ts +53 -2
  313. package/src/tools/browser/relay/bridge.ts +945 -0
  314. package/src/tools/browser/relay/daemon.ts +117 -0
  315. package/src/tools/browser/relay/extension-assets/background.js.txt +242 -0
  316. package/src/tools/browser/relay/extension-assets/manifest.json.txt +14 -0
  317. package/src/tools/browser/relay/extension-assets/options.html.txt +53 -0
  318. package/src/tools/browser/relay/extension-assets/options.js.txt +23 -0
  319. package/src/tools/browser/relay/kind.ts +41 -0
  320. package/src/tools/browser/relay/protocol.ts +54 -0
  321. package/src/tools/browser/relay/server.ts +141 -0
  322. package/src/tools/browser/render.ts +4 -1
  323. package/src/tools/browser/shared-daemon.ts +7 -58
  324. package/src/tools/browser/tab-supervisor.ts +5 -4
  325. package/src/tools/browser/tab-worker.ts +33 -12
  326. package/src/tools/browser.ts +26 -1
  327. package/src/tools/computer/exposure.ts +11 -35
  328. package/src/tools/computer/protocol.ts +51 -10
  329. package/src/tools/computer/supervisor.ts +227 -124
  330. package/src/tools/computer/worker-entry.ts +11 -6
  331. package/src/tools/computer/worker.ts +695 -81
  332. package/src/tools/computer-renderer.ts +104 -65
  333. package/src/tools/computer.ts +134 -428
  334. package/src/tools/context.ts +3 -0
  335. package/src/tools/default-renderer.ts +19 -4
  336. package/src/tools/glob.ts +9 -2
  337. package/src/tools/grep.ts +12 -6
  338. package/src/tools/index.ts +10 -6
  339. package/src/tools/inspect-image.ts +32 -6
  340. package/src/tools/render-utils.ts +2 -0
  341. package/src/tools/{browser/run-cancellation.ts → run-scope.ts} +11 -11
  342. package/src/tools/tool-timeouts.ts +1 -0
  343. package/src/tools/xdev.ts +29 -2
  344. package/src/utils/clipboard.ts +40 -14
  345. package/src/utils/command-args.ts +26 -28
  346. package/src/utils/tool-choice.ts +0 -13
  347. package/src/web/kagi.ts +2 -1
  348. package/src/web/search/index.ts +18 -2
  349. package/src/web/search/providers/anthropic.ts +7 -2
  350. package/src/web/search/providers/base.ts +2 -0
  351. package/src/web/search/providers/brave.ts +3 -1
  352. package/src/web/search/providers/browser-page.ts +6 -4
  353. package/src/web/search/providers/codex.ts +4 -1
  354. package/src/web/search/providers/duckduckgo.ts +2 -1
  355. package/src/web/search/providers/ecosia.ts +2 -1
  356. package/src/web/search/providers/exa.ts +4 -2
  357. package/src/web/search/providers/firecrawl.ts +3 -1
  358. package/src/web/search/providers/gemini.ts +8 -2
  359. package/src/web/search/providers/google.ts +2 -1
  360. package/src/web/search/providers/jina.ts +12 -2
  361. package/src/web/search/providers/kagi.ts +3 -0
  362. package/src/web/search/providers/kimi.ts +5 -1
  363. package/src/web/search/providers/mojeek.ts +2 -1
  364. package/src/web/search/providers/parallel.ts +5 -1
  365. package/src/web/search/providers/perplexity.ts +6 -3
  366. package/src/web/search/providers/public.ts +1 -1
  367. package/src/web/search/providers/searxng.ts +11 -5
  368. package/src/web/search/providers/startpage.ts +10 -4
  369. package/src/web/search/providers/synthetic.ts +11 -5
  370. package/src/web/search/providers/tavily.ts +3 -1
  371. package/src/web/search/providers/tinyfish.ts +3 -1
  372. package/src/web/search/providers/utils.ts +12 -10
  373. package/src/web/search/providers/xai.ts +2 -2
  374. package/src/web/search/providers/zai.ts +18 -3
  375. package/src/web/search/types.ts +6 -0
@@ -30,7 +30,6 @@ import { computeEditDiff, type DiffError, type DiffResult } from "./diff";
30
30
  import { computeHashlineDiff, computeHashlineSectionDiff } from "./hashline/diff";
31
31
  import { type ApplyPatchEntry, expandApplyPatchToEntries, expandApplyPatchToPreviewEntries } from "./modes/apply-patch";
32
32
  import { computePatchDiff, type PatchEditEntry } from "./modes/patch";
33
- import type { ReplaceEditEntry } from "./modes/replace";
34
33
 
35
34
  export interface PerFileDiffPreview {
36
35
  path: string;
@@ -333,27 +332,32 @@ function splitApplyPatchPerFile(input: string): EditMatcherEntry[] {
333
332
 
334
333
  interface ReplaceArgs {
335
334
  path?: string;
336
- edits?: ReplaceEditEntry[];
335
+ old_string?: string;
336
+ new_string?: string;
337
+ replace_all?: boolean;
337
338
  __partialJson?: string;
338
339
  }
339
340
 
340
341
  const replaceStrategy: EditStreamingStrategy<ReplaceArgs> = {
341
342
  extractCompleteEdits(args, partialJson) {
342
- if (!args?.edits) return args;
343
- return { ...args, edits: dropIncompleteLastEdit(args.edits, partialJson, "edits") };
343
+ // While args are still streaming, `old_string` is only trustworthy once
344
+ // the parser has moved past it — i.e. the `new_string` key has appeared.
345
+ // Previewing a half-streamed `old_string` would flash a bogus
346
+ // "no match" diff error until the rest of the value arrives.
347
+ if (!partialJson || partialJson.includes('"new_string"')) return args;
348
+ return { ...args, old_string: undefined, new_string: undefined };
344
349
  },
345
350
  async computeDiffPreview(args, ctx) {
346
351
  if (!args.path) return null;
347
- const first = args.edits?.[0];
348
- if (!first || first.old_text === undefined || first.new_text === undefined) return null;
352
+ if (args.old_string === undefined || args.new_string === undefined) return null;
349
353
  ctx.signal.throwIfAborted();
350
354
  const result = await computeEditDiff(
351
355
  args.path,
352
- first.old_text,
353
- first.new_text,
356
+ args.old_string,
357
+ args.new_string,
354
358
  ctx.cwd,
355
359
  ctx.allowFuzzy ?? true,
356
- first.all,
360
+ args.replace_all,
357
361
  ctx.fuzzyThreshold,
358
362
  );
359
363
  ctx.signal.throwIfAborted();
@@ -363,14 +367,7 @@ const replaceStrategy: EditStreamingStrategy<ReplaceArgs> = {
363
367
  return "";
364
368
  },
365
369
  matcherDigest(args) {
366
- const edits = args?.edits;
367
- if (!Array.isArray(edits)) return undefined;
368
- let digest: string | undefined;
369
- for (const edit of edits) {
370
- if (typeof edit?.new_text !== "string") continue;
371
- digest = digest === undefined ? edit.new_text : `${digest}\n${edit.new_text}`;
372
- }
373
- return digest;
370
+ return typeof args?.new_string === "string" ? args.new_string : undefined;
374
371
  },
375
372
  matcherPaths(args) {
376
373
  return typeof args?.path === "string" && args.path.length > 0 ? [args.path] : undefined;
@@ -82,8 +82,9 @@ const availabilityCache = new Map<string, Promise<PythonKernelAvailability>>();
82
82
  export async function checkPythonKernelAvailability(
83
83
  cwd: string,
84
84
  interpreter?: string,
85
+ options?: { forceProbe?: boolean },
85
86
  ): Promise<PythonKernelAvailability> {
86
- if (isBunTestRuntime() || $flag("PI_PYTHON_SKIP_CHECK")) {
87
+ if (!options?.forceProbe && (isBunTestRuntime() || $flag("PI_PYTHON_SKIP_CHECK"))) {
87
88
  return { ok: true };
88
89
  }
89
90
  const resolvedCwd = path.resolve(cwd);
@@ -1,10 +1,10 @@
1
1
  /**
2
2
  * Subprocess spawn-option helpers for the Python kernel.
3
3
  *
4
- * Pure helpers (`shouldHideKernelWindow`, `consoleAttachedViaTTY`) live here
5
- * so they can be unit-tested without dragging in the kernel's runtime
6
- * dependencies. The effectful `hostHasInheritableConsole` wraps a Win32 FFI
7
- * probe with a TTY fallback and is the function `kernel.ts` actually calls.
4
+ * Pure helpers (`shouldHideKernelWindow`, `consoleAttached`) live here so they
5
+ * can be unit-tested without dragging in the kernel's runtime dependencies.
6
+ * The effectful `hostHasInheritableConsole` combines a Win32 FFI probe with
7
+ * TTY evidence and is the function `kernel.ts` actually calls.
8
8
  */
9
9
  import { dlopen, FFIType } from "bun:ffi";
10
10
 
@@ -54,20 +54,21 @@ export function shouldDetachKernel(platform: NodeJS.Platform): boolean {
54
54
  }
55
55
 
56
56
  /**
57
- * TTY-based fallback used when the Win32 console probe is unavailable.
57
+ * Combine native Win32 and stdio TTY evidence of an inheritable console.
58
58
  *
59
- * Returns `true` if any of stdin/stdout/stderr is currently a TTY. This
60
- * correctly detects the common interactive launches and the partial-
61
- * redirection cases (`omp -p > out.txt`, `< in.txt`, `2> err.log`) where at
62
- * least one stream stays bound to the terminal. The all-stdio-redirected
63
- * case (`< in > out 2> err` from a console) is the reason we prefer the
64
- * Win32 probe over this fallback whenever possible.
59
+ * `GetConsoleWindow()` detects classic consoles even when every stdio stream
60
+ * is redirected. TTY detection covers ConPTY-backed terminals, where compiled
61
+ * hosts can receive a null HWND despite being attached to Windows Terminal.
62
+ * Either signal must preserve console inheritance: `CREATE_NO_WINDOW` can
63
+ * deadlock NumPy native-extension loading in the Python child.
65
64
  */
66
- export function consoleAttachedViaTTY(opts: {
65
+ export function consoleAttached(opts: {
66
+ nativeConsole?: boolean | null;
67
67
  stdinIsTTY: boolean;
68
68
  stdoutIsTTY: boolean;
69
69
  stderrIsTTY: boolean;
70
70
  }): boolean {
71
+ if (opts.nativeConsole === true) return true;
71
72
  return opts.stdinIsTTY || opts.stdoutIsTTY || opts.stderrIsTTY;
72
73
  }
73
74
 
@@ -75,10 +76,10 @@ export function consoleAttachedViaTTY(opts: {
75
76
  * Probe `kernel32.dll!GetConsoleWindow()` to detect whether the current
76
77
  * Windows process owns a console window.
77
78
  *
78
- * Returns `true` for a non-NULL HWND, `false` when NULL (no console true
79
- * service / `DETACHED_PROCESS` / GUI parent), and `null` when the probe
80
- * itself fails (off-Windows, FFI disabled, or unexpected kernel32 layout).
81
- * A `null` return means "don't trust me, use the TTY fallback".
79
+ * Returns `true` for a non-NULL HWND, `false` when NULL, and `null` when the
80
+ * probe itself fails (off-Windows, FFI disabled, or unexpected kernel32
81
+ * layout). A false result is not conclusive for ConPTY-backed terminals, so
82
+ * callers must also inspect the stdio TTY signals.
82
83
  *
83
84
  * Cached on first call because in practice the console attachment of a
84
85
  * long-lived OMP host never changes for the lifetime of the process, and
@@ -117,21 +118,15 @@ export function __resetWindowsConsoleProbeCache(): void {
117
118
  /**
118
119
  * Whether the host process owns a console its children can inherit.
119
120
  *
120
- * - On Windows, the authoritative signal is `GetConsoleWindow()`. It returns
121
- * a non-NULL HWND whenever the process has a console attached, regardless
122
- * of how the standard streams are redirected so an `omp -p ... < in.txt
123
- * > out.txt 2> err.log` launched from a real Windows Terminal session is
124
- * correctly classified as console-attached and the kernel keeps its
125
- * inheritable console.
126
- * - On any other platform, or if the FFI probe fails, fall back to the
127
- * TTY-OR heuristic. That still catches the common interactive cases.
121
+ * On Windows, `GetConsoleWindow()` detects classic consoles and all-stdio-
122
+ * redirected launches while stdio TTYs detect ConPTY-backed terminals. Either
123
+ * signal is sufficient. Other platforms use the same TTY evidence, although
124
+ * `windowsHide` is a no-op there.
128
125
  */
129
126
  export function hostHasInheritableConsole(): boolean {
130
- if (process.platform === "win32") {
131
- const native = probeWindowsConsoleWindow();
132
- if (native !== null) return native;
133
- }
134
- return consoleAttachedViaTTY({
127
+ const nativeConsole = process.platform === "win32" ? probeWindowsConsoleWindow() : null;
128
+ return consoleAttached({
129
+ nativeConsole,
135
130
  stdinIsTTY: !!process.stdin.isTTY,
136
131
  stdoutIsTTY: !!process.stdout.isTTY,
137
132
  stderrIsTTY: !!process.stderr.isTTY,
@@ -204,7 +204,7 @@
204
204
  containsActive.set(node, has);
205
205
  }
206
206
 
207
- // Stack: [node, indent, justBranched, showConnector, isLast, gutters, isVirtualRootChild]
207
+ // Stack: [node, indent, showConnector, isLast, gutters, isVirtualRootChild]
208
208
  const stack = [];
209
209
 
210
210
  // Add roots (prioritize branch containing active leaf)
@@ -213,11 +213,11 @@
213
213
  );
214
214
  for (let i = orderedRoots.length - 1; i >= 0; i--) {
215
215
  const isLast = i === orderedRoots.length - 1;
216
- stack.push([orderedRoots[i], multipleRoots ? 1 : 0, multipleRoots, multipleRoots, isLast, [], multipleRoots]);
216
+ stack.push([orderedRoots[i], multipleRoots ? 1 : 0, multipleRoots, isLast, [], multipleRoots]);
217
217
  }
218
218
 
219
219
  while (stack.length > 0) {
220
- const [node, indent, justBranched, showConnector, isLast, gutters, isVirtualRootChild] = stack.pop();
220
+ const [node, indent, showConnector, isLast, gutters, isVirtualRootChild] = stack.pop();
221
221
 
222
222
  result.push({ node, indent, showConnector, isLast, gutters, isVirtualRootChild, multipleRoots });
223
223
 
@@ -229,18 +229,10 @@
229
229
  Number(containsActive.get(b)) - Number(containsActive.get(a))
230
230
  );
231
231
 
232
- // Calculate child indent (matches tree-selector.ts)
233
- let childIndent;
234
- if (multipleChildren) {
235
- // Parent branches: children get +1
236
- childIndent = indent + 1;
237
- } else if (justBranched && indent > 0) {
238
- // First generation after a branch: +1 for visual grouping
239
- childIndent = indent + 1;
240
- } else {
241
- // Single-child chain: stay flat
242
- childIndent = indent;
243
- }
232
+ // Real branch points add visual depth, and a virtual root's direct
233
+ // children (the session roots) nest one level under the shared
234
+ // column-0 root. Linear continuations otherwise stay aligned.
235
+ const childIndent = multipleChildren || isVirtualRootChild ? indent + 1 : indent;
244
236
 
245
237
  // Build gutters for children
246
238
  const connectorDisplayed = showConnector && !isVirtualRootChild;
@@ -253,7 +245,7 @@
253
245
  // Add children in reverse order for stack
254
246
  for (let i = orderedChildren.length - 1; i >= 0; i--) {
255
247
  const childIsLast = i === orderedChildren.length - 1;
256
- stack.push([orderedChildren[i], childIndent, multipleChildren, multipleChildren, childIsLast, childGutters, false]);
248
+ stack.push([orderedChildren[i], childIndent, multipleChildren, childIsLast, childGutters, false]);
257
249
  }
258
250
  }
259
251
 
@@ -268,13 +260,6 @@
268
260
  const displayIndent = multipleRoots ? Math.max(0, indent - 1) : indent;
269
261
  const connector = showConnector && !isVirtualRootChild ? (isLast ? '└─ ' : '├─ ') : '';
270
262
  const connectorPosition = connector ? displayIndent - 1 : -1;
271
- // Chain rows (no connector of their own) under a last-sibling (`└─`)
272
- // branch stay anchored by a vertical drawn one level right of the
273
- // suppressed gutter — below the branch head's content — never in the
274
- // `└─` corner column itself (#2298, #2325). Chains under `├─` heads
275
- // are already anchored by the sibling line (`show: true` gutter).
276
- const nearestGutter = !connector ? gutters[gutters.length - 1] : undefined;
277
- const chainAnchorLevel = nearestGutter && !nearestGutter.show ? nearestGutter.position + 1 : -1;
278
263
 
279
264
  const totalChars = displayIndent * 3;
280
265
  const prefixChars = [];
@@ -287,9 +272,6 @@
287
272
  // Standard tree semantics: `│` only while more siblings continue
288
273
  // below (`show`), space below a `└─`.
289
274
  prefixChars.push(posInLevel === 0 && gutter.show ? '│' : ' ');
290
- } else if (level === chainAnchorLevel) {
291
- // Chain anchor for rows under a `└─` branch head.
292
- prefixChars.push(posInLevel === 0 ? '│' : ' ');
293
275
  } else if (connector && level === connectorPosition) {
294
276
  if (posInLevel === 0) {
295
277
  prefixChars.push(isLast ? '└' : '├');
@@ -509,6 +509,26 @@ async function discoverExtensionsInDir(dir: string): Promise<string[]> {
509
509
 
510
510
  return discovered;
511
511
  }
512
+ async function discoverHooksInPackageRoot(root: string): Promise<string[]> {
513
+ const hooks: string[] = [];
514
+ for (const hookType of ["pre", "post"]) {
515
+ const hookDir = path.join(root, "hooks", hookType);
516
+ let entries: fs1.Dirent[];
517
+ try {
518
+ entries = await fs.readdir(hookDir, { withFileTypes: true });
519
+ } catch (err) {
520
+ if (isEnoent(err) || isEacces(err) || hasFsCode(err, "ENOTDIR") || hasFsCode(err, "EPERM")) continue;
521
+ throw err;
522
+ }
523
+ for (const entry of entries) {
524
+ if ((entry.isFile() || entry.isSymbolicLink()) && isExtensionFile(entry.name)) {
525
+ hooks.push(path.join(hookDir, entry.name));
526
+ }
527
+ }
528
+ }
529
+ return hooks;
530
+ }
531
+
512
532
  /**
513
533
  * Discover absolute paths of extensions to load, without importing or
514
534
  * binding factories. Hot path on session startup — the scan walks native
@@ -522,10 +542,16 @@ async function discoverExtensionsInDir(dir: string): Promise<string[]> {
522
542
  * `LoadExtensionsResult` directly would reuse handlers/tools/commands that
523
543
  * closed over the parent's `cwd` and event bus.
524
544
  */
545
+ export interface DiscoverExtensionPathOptions {
546
+ /** Include ambient native extensions, hooks, and installed plugins. */
547
+ ambient?: boolean;
548
+ }
549
+
525
550
  export async function discoverExtensionPaths(
526
551
  configuredPaths: string[],
527
552
  cwd: string,
528
553
  disabledExtensionIds?: string[],
554
+ options: DiscoverExtensionPathOptions = {},
529
555
  ): Promise<string[]> {
530
556
  const allPaths: string[] = [];
531
557
  const seen = new Set<string>();
@@ -549,33 +575,44 @@ export async function discoverExtensionPaths(
549
575
  }
550
576
  };
551
577
 
552
- // 1. Discover extension modules via capability API (native .omp/.pi only).
553
- // Scope the load to the native provider — the extension-module capability
554
- // also has claude/codex/gemini/opencode providers, and their items were
555
- // discarded here anyway (see #4198). The provider filter skips the walk
556
- // entirely instead of running four foreign directory scans and dropping
557
- // the results.
558
- const discovered = await loadCapability<ExtensionModule>(extensionModuleCapability.id, {
559
- ...loadOptions,
560
- providers: ["native"],
561
- });
562
- for (const ext of discovered.items) {
563
- addPath(ext.path);
564
- }
565
-
566
- // 2. Discover JS/TS hook factories from hookCapability and bind them through
567
- // the extension runner, which owns the current runtime event bus. Hook
568
- // capability loading already applies hook-specific disabled ids; do not also
569
- // filter them through extension-module names.
570
- const hooks = await loadCapability<Hook>(hookCapability.id, loadOptions);
571
- for (const hookPath of hooks.items
572
- .map(hook => hook.path)
573
- .filter(hookPath => isExtensionFile(path.basename(hookPath)))) {
574
- addPath(hookPath);
575
- }
576
-
577
- // 3. Discover extension entry points from installed plugins
578
- addPaths(await getAllPluginExtensionPaths(cwd));
578
+ const ambient = options.ambient !== false;
579
+ if (ambient) {
580
+ // 1. Discover extension modules via capability API (native .omp/.pi only).
581
+ // Scope the load to the native provider the extension-module capability
582
+ // also has claude/codex/gemini/opencode providers, and their items were
583
+ // discarded here anyway (see #4198). The provider filter skips the walk
584
+ // entirely instead of running four foreign directory scans and dropping
585
+ // the results.
586
+ const discovered = await loadCapability<ExtensionModule>(extensionModuleCapability.id, {
587
+ ...loadOptions,
588
+ providers: ["native"],
589
+ });
590
+ for (const ext of discovered.items) {
591
+ addPath(ext.path);
592
+ }
593
+ }
594
+
595
+ // 2. Discover JS/TS hook factories and bind them through the extension
596
+ // runner, which owns the current runtime event bus. Non-ambient discovery
597
+ // scans only this invocation's configured package roots; it must not consult
598
+ // settings, installed packages, or process-global CLI injection state.
599
+ if (ambient) {
600
+ const hooks = await loadCapability<Hook>(hookCapability.id, loadOptions);
601
+ for (const hookPath of hooks.items
602
+ .map(hook => hook.path)
603
+ .filter(hookPath => isExtensionFile(path.basename(hookPath)))) {
604
+ addPath(hookPath);
605
+ }
606
+ } else {
607
+ for (const configuredPath of configuredPaths) {
608
+ addPaths(await discoverHooksInPackageRoot(resolvePath(configuredPath, cwd)));
609
+ }
610
+ }
611
+
612
+ // 3. Discover extension entry points from installed plugins.
613
+ if (ambient) {
614
+ addPaths(await getAllPluginExtensionPaths(cwd));
615
+ }
579
616
 
580
617
  // 4. Explicitly configured paths
581
618
  for (const configuredPath of configuredPaths) {
@@ -618,7 +655,8 @@ export async function discoverAndLoadExtensions(
618
655
  cwd: string,
619
656
  eventBus?: EventBus,
620
657
  disabledExtensionIds?: string[],
658
+ options: DiscoverExtensionPathOptions = {},
621
659
  ): Promise<LoadExtensionsResult> {
622
- const paths = await discoverExtensionPaths(configuredPaths, cwd, disabledExtensionIds);
660
+ const paths = await discoverExtensionPaths(configuredPaths, cwd, disabledExtensionIds, options);
623
661
  return loadExtensions(paths, cwd, eventBus);
624
662
  }
@@ -239,6 +239,7 @@ export class ExtensionToolWrapper<TParameters extends TSchema = TSchema, TDetail
239
239
  // short-circuit above.
240
240
  const resolvedArgs = approvalArgs(effectiveParams, context);
241
241
  const resolved = resolveApproval(this.tool, resolvedArgs, approvalMode, userPolicies);
242
+ context?.xdevTierResolved?.(resolved.tier);
242
243
  if (resolved.policy === "deny") {
243
244
  throw new Error(
244
245
  `Tool "${this.tool.name}" is blocked by user policy.\n` +
@@ -19,7 +19,15 @@
19
19
  * `types.ts` via the `export *` below — pi-ai still exports both as types,
20
20
  * only the runtime `Type` builder and `StringEnum()` helper were removed.
21
21
  */
22
- import type { Api, AssistantMessage, Model } from "@oh-my-pi/pi-ai";
22
+ import {
23
+ type Api,
24
+ type AssistantMessage,
25
+ type AssistantMessageEventStream,
26
+ type Context,
27
+ type Model,
28
+ type SimpleStreamOptions,
29
+ streamSimple,
30
+ } from "@oh-my-pi/pi-ai";
23
31
  import type { Effort } from "@oh-my-pi/pi-catalog/effort";
24
32
  import { clampThinkingLevelForModel } from "@oh-my-pi/pi-catalog/model-thinking";
25
33
  import {
@@ -121,6 +129,19 @@ export { calculateCost, getBundledModel, getBundledModels, getBundledProviders,
121
129
  export const getModel = getBundledModel;
122
130
  export const getModels = getBundledModels;
123
131
 
132
+ /**
133
+ * Stream OpenAI Responses through the historical simple-options contract.
134
+ *
135
+ * Legacy `/compat` callers pass {@link SimpleStreamOptions}; routing through
136
+ * `streamSimple` preserves option normalization before provider dispatch.
137
+ */
138
+ export function streamSimpleOpenAIResponses(
139
+ model: Model<"openai-responses">,
140
+ context: Context,
141
+ options?: SimpleStreamOptions,
142
+ ): AssistantMessageEventStream {
143
+ return streamSimple(model, context, options);
144
+ }
124
145
  /**
125
146
  * Compatibility re-exports for runtime helpers that upstream
126
147
  * `@earendil-works/pi-ai` exposed from its package root but omp's
@@ -1415,12 +1415,13 @@ export function getPackageDir(): string {
1415
1415
  return getOmpPackageDir() ?? (isCompiledBinary() ? path.dirname(process.execPath) : process.cwd());
1416
1416
  }
1417
1417
 
1418
- // Legacy pi's `@earendil-works/pi-coding-agent` re-exported `estimateTokens`
1419
- // and `compact` from its package root (via `./core/compaction/index.ts`). In
1420
- // omp both live in `@oh-my-pi/pi-agent-core/compaction`, and the coding-agent
1421
- // barrel below does not forward them, so legacy extensions importing either
1422
- // fail Bun's static export check during validation (issues #6583, #7174).
1423
- export { compact, estimateTokens } from "@oh-my-pi/pi-agent-core/compaction";
1418
+ // Legacy pi's `@earendil-works/pi-coding-agent` re-exported `estimateTokens`,
1419
+ // `compact`, and `serializeConversation` from its package root (via
1420
+ // `./core/compaction/index.ts`). In omp they live in
1421
+ // `@oh-my-pi/pi-agent-core/compaction`, and the coding-agent barrel below does
1422
+ // not forward them, so legacy extensions importing them fail Bun's static
1423
+ // export check during validation (issues #6583, #7174, #7403).
1424
+ export { compact, estimateTokens, serializeConversation } from "@oh-my-pi/pi-agent-core/compaction";
1424
1425
 
1425
1426
  // Same barrel gap for two more legacy package-root exports: pi re-exported the
1426
1427
  // `CONFIG_DIR_NAME` constant and the CLI parser `parseArgs`. In omp