@oh-my-pi/pi-coding-agent 17.2.4 → 17.2.6

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 (348) hide show
  1. package/CHANGELOG.md +69 -0
  2. package/dist/{CHANGELOG-bpmhv26t.md → CHANGELOG-gs76k6wc.md} +69 -0
  3. package/dist/cli.js +4438 -3962
  4. package/dist/{template-8vdv6xb4.js → template-c2hyaytt.js} +8 -26
  5. package/dist/types/cli/args.d.ts +4 -1
  6. package/dist/types/cli/browser-relay-cli.d.ts +15 -0
  7. package/dist/types/cli/command-help.d.ts +99 -0
  8. package/dist/types/cli/gc-cli.d.ts +1 -0
  9. package/dist/types/cli/help-extra.d.ts +2 -0
  10. package/dist/types/cli/thinking-levels.d.ts +5 -0
  11. package/dist/types/cli/update-cli.d.ts +13 -0
  12. package/dist/types/commands/browser-relay.d.ts +38 -0
  13. package/dist/types/commands/commit.d.ts +3 -0
  14. package/dist/types/commands/complete.d.ts +1 -1
  15. package/dist/types/commands/completions.d.ts +6 -0
  16. package/dist/types/commands/grep.d.ts +3 -0
  17. package/dist/types/commands/join.d.ts +4 -0
  18. package/dist/types/commands/launch-help.d.ts +171 -0
  19. package/dist/types/commands/launch.d.ts +5 -1
  20. package/dist/types/commands/models.d.ts +3 -0
  21. package/dist/types/commands/say.d.ts +10 -0
  22. package/dist/types/commands/worktree.d.ts +3 -0
  23. package/dist/types/config/keybindings.d.ts +5 -0
  24. package/dist/types/config/model-discovery.d.ts +2 -2
  25. package/dist/types/config/models-config-schema-bundle.d.ts +3 -0
  26. package/dist/types/config/models-config-schema.d.ts +2 -0
  27. package/dist/types/config/models-config.d.ts +1 -0
  28. package/dist/types/config/service-tier.d.ts +2 -0
  29. package/dist/types/config/settings-schema.d.ts +69 -21
  30. package/dist/types/cursor-bridge-tools.d.ts +1 -1
  31. package/dist/types/cursor.d.ts +7 -4
  32. package/dist/types/edit/index.d.ts +3 -3
  33. package/dist/types/edit/modes/replace.d.ts +22 -15
  34. package/dist/types/edit/renderer.d.ts +1 -1
  35. package/dist/types/eval/py/kernel.d.ts +3 -1
  36. package/dist/types/eval/py/spawn-options.d.ts +12 -16
  37. package/dist/types/extensibility/legacy-pi-ai-shim.d.ts +8 -1
  38. package/dist/types/extensibility/legacy-pi-coding-agent-shim.d.ts +1 -1
  39. package/dist/types/extensibility/plugins/legacy-pi-compat.d.ts +2 -0
  40. package/dist/types/launch/broker.d.ts +1 -1
  41. package/dist/types/launch/client.d.ts +15 -4
  42. package/dist/types/launch/ensure.d.ts +8 -0
  43. package/dist/types/launch/paths.d.ts +1 -1
  44. package/dist/types/launch/protocol.d.ts +19 -2
  45. package/dist/types/lsp/client.d.ts +2 -0
  46. package/dist/types/lsp/mux/daemon.d.ts +15 -0
  47. package/dist/types/lsp/mux/protocol.d.ts +57 -0
  48. package/dist/types/lsp/mux/server.d.ts +18 -0
  49. package/dist/types/lsp/types.d.ts +22 -2
  50. package/dist/types/main.d.ts +2 -0
  51. package/dist/types/mnemopi/embed-client.d.ts +1 -1
  52. package/dist/types/mnemopi/state.d.ts +0 -23
  53. package/dist/types/modes/components/assistant-message.d.ts +2 -0
  54. package/dist/types/modes/components/btw-panel.d.ts +3 -0
  55. package/dist/types/modes/components/custom-editor.d.ts +2 -1
  56. package/dist/types/modes/components/read-tool-group.d.ts +2 -0
  57. package/dist/types/modes/components/stripped-tool-calls-placeholder.d.ts +12 -0
  58. package/dist/types/modes/components/tool-execution.d.ts +2 -0
  59. package/dist/types/modes/controllers/btw-controller.d.ts +2 -0
  60. package/dist/types/modes/controllers/command-controller.d.ts +1 -0
  61. package/dist/types/modes/controllers/input-controller.d.ts +1 -0
  62. package/dist/types/modes/interactive-mode.d.ts +5 -1
  63. package/dist/types/modes/types.d.ts +4 -1
  64. package/dist/types/modes/workflow.d.ts +2 -1
  65. package/dist/types/sdk.d.ts +3 -1
  66. package/dist/types/secrets/index.d.ts +1 -1
  67. package/dist/types/security/contracts/schemas.d.ts +405 -403
  68. package/dist/types/session/agent-session-types.d.ts +8 -1
  69. package/dist/types/session/agent-session.d.ts +26 -2
  70. package/dist/types/session/indexed-session-storage.d.ts +1 -0
  71. package/dist/types/session/launch-completion.d.ts +10 -0
  72. package/dist/types/session/session-advisors.d.ts +1 -1
  73. package/dist/types/session/session-context.d.ts +2 -1
  74. package/dist/types/session/session-entries.d.ts +15 -1
  75. package/dist/types/session/session-maintenance.d.ts +1 -0
  76. package/dist/types/session/session-manager.d.ts +23 -11
  77. package/dist/types/session/session-stats.d.ts +10 -0
  78. package/dist/types/session/session-storage.d.ts +15 -3
  79. package/dist/types/session/yield-queue.d.ts +6 -1
  80. package/dist/types/system-prompt.d.ts +4 -1
  81. package/dist/types/task/index.d.ts +2 -1
  82. package/dist/types/task/spawn-policy.d.ts +5 -0
  83. package/dist/types/thinking.d.ts +1 -7
  84. package/dist/types/tools/ast-grep.d.ts +1 -1
  85. package/dist/types/tools/browser/registry.d.ts +2 -1
  86. package/dist/types/tools/browser/relay/bridge.d.ts +35 -0
  87. package/dist/types/tools/browser/relay/daemon.d.ts +16 -0
  88. package/dist/types/tools/browser/relay/kind.d.ts +19 -0
  89. package/dist/types/tools/browser/relay/protocol.d.ts +97 -0
  90. package/dist/types/tools/browser/relay/server.d.ts +35 -0
  91. package/dist/types/tools/browser/render.d.ts +1 -0
  92. package/dist/types/tools/browser.d.ts +3 -0
  93. package/dist/types/tools/computer/exposure.d.ts +9 -7
  94. package/dist/types/tools/computer/protocol.d.ts +70 -17
  95. package/dist/types/tools/computer/supervisor.d.ts +23 -10
  96. package/dist/types/tools/computer/worker-entry.d.ts +1 -0
  97. package/dist/types/tools/computer/worker.d.ts +42 -7
  98. package/dist/types/tools/computer-renderer.d.ts +7 -5
  99. package/dist/types/tools/computer.d.ts +25 -44
  100. package/dist/types/tools/context.d.ts +3 -0
  101. package/dist/types/tools/glob.d.ts +1 -1
  102. package/dist/types/tools/grep.d.ts +1 -1
  103. package/dist/types/tools/index.d.ts +9 -0
  104. package/dist/types/tools/render-utils.d.ts +2 -0
  105. package/dist/types/tools/{browser/run-cancellation.d.ts → run-scope.d.ts} +8 -8
  106. package/dist/types/tools/tool-timeouts.d.ts +5 -0
  107. package/dist/types/tools/xdev.d.ts +8 -0
  108. package/dist/types/utils/clipboard.d.ts +2 -2
  109. package/dist/types/web/kagi.d.ts +1 -0
  110. package/dist/types/web/search/index.d.ts +1 -1
  111. package/dist/types/web/search/providers/anthropic.d.ts +1 -0
  112. package/dist/types/web/search/providers/base.d.ts +2 -0
  113. package/dist/types/web/search/providers/brave.d.ts +1 -0
  114. package/dist/types/web/search/providers/browser-page.d.ts +1 -0
  115. package/dist/types/web/search/providers/codex.d.ts +1 -0
  116. package/dist/types/web/search/providers/exa.d.ts +1 -0
  117. package/dist/types/web/search/providers/firecrawl.d.ts +1 -0
  118. package/dist/types/web/search/providers/gemini.d.ts +1 -0
  119. package/dist/types/web/search/providers/jina.d.ts +1 -0
  120. package/dist/types/web/search/providers/kagi.d.ts +1 -0
  121. package/dist/types/web/search/providers/kimi.d.ts +1 -0
  122. package/dist/types/web/search/providers/parallel.d.ts +1 -0
  123. package/dist/types/web/search/providers/perplexity.d.ts +1 -0
  124. package/dist/types/web/search/providers/searxng.d.ts +1 -0
  125. package/dist/types/web/search/providers/tavily.d.ts +1 -0
  126. package/dist/types/web/search/providers/tinyfish.d.ts +1 -0
  127. package/dist/types/web/search/providers/utils.d.ts +6 -9
  128. package/dist/types/web/search/providers/zai.d.ts +1 -0
  129. package/dist/types/web/search/types.d.ts +4 -0
  130. package/package.json +12 -12
  131. package/src/cli/args.ts +7 -87
  132. package/src/cli/browser-relay-cli.ts +119 -0
  133. package/src/cli/command-help.ts +103 -0
  134. package/src/cli/completion-gen.ts +5 -5
  135. package/src/cli/flag-tables.ts +9 -0
  136. package/src/cli/gc-cli.ts +641 -21
  137. package/src/cli/help-extra.ts +89 -0
  138. package/src/cli/setup-cli.ts +13 -21
  139. package/src/cli/thinking-levels.ts +7 -0
  140. package/src/cli/update-cli.ts +26 -7
  141. package/src/cli-commands.ts +170 -33
  142. package/src/cli.ts +17 -5
  143. package/src/commands/acp.ts +3 -1
  144. package/src/commands/agents.ts +3 -2
  145. package/src/commands/auth-broker.ts +3 -2
  146. package/src/commands/auth-gateway.ts +3 -2
  147. package/src/commands/bench.ts +2 -3
  148. package/src/commands/browser-relay.ts +53 -0
  149. package/src/commands/cleanse.ts +2 -2
  150. package/src/commands/commit.ts +3 -2
  151. package/src/commands/complete.ts +2 -1
  152. package/src/commands/completions.ts +3 -2
  153. package/src/commands/config.ts +3 -2
  154. package/src/commands/dry-balance.ts +2 -2
  155. package/src/commands/gallery.ts +3 -2
  156. package/src/commands/gc.ts +3 -2
  157. package/src/commands/grep.ts +3 -2
  158. package/src/commands/grievances.ts +3 -2
  159. package/src/commands/install.ts +2 -2
  160. package/src/commands/join.ts +3 -2
  161. package/src/commands/launch-help.ts +116 -0
  162. package/src/commands/launch.ts +7 -191
  163. package/src/commands/models.ts +3 -2
  164. package/src/commands/plugin.ts +3 -2
  165. package/src/commands/read.ts +3 -2
  166. package/src/commands/say.ts +3 -2
  167. package/src/commands/setup.ts +3 -2
  168. package/src/commands/shell.ts +3 -2
  169. package/src/commands/ssh.ts +3 -2
  170. package/src/commands/stats.ts +3 -2
  171. package/src/commands/tiny-models.ts +2 -2
  172. package/src/commands/token.ts +2 -2
  173. package/src/commands/ttsr.ts +2 -2
  174. package/src/commands/update.ts +3 -2
  175. package/src/commands/usage.ts +3 -2
  176. package/src/commands/web-search.ts +3 -2
  177. package/src/commands/worktree.ts +3 -2
  178. package/src/config/keybindings.ts +5 -0
  179. package/src/config/model-discovery.ts +44 -27
  180. package/src/config/model-registry.ts +19 -13
  181. package/src/config/models-config-schema-bundle.ts +9 -0
  182. package/src/config/resolve-config-value.ts +2 -1
  183. package/src/config/service-tier.ts +5 -0
  184. package/src/config/settings-schema.ts +72 -20
  185. package/src/config/settings.ts +1 -1
  186. package/src/cursor-bridge-tools.ts +1 -1
  187. package/src/cursor.ts +10 -14
  188. package/src/edit/diff.ts +17 -8
  189. package/src/edit/index.ts +20 -7
  190. package/src/edit/modes/replace.ts +93 -40
  191. package/src/edit/renderer.ts +1 -1
  192. package/src/edit/streaming.ts +14 -17
  193. package/src/eval/py/kernel.ts +2 -1
  194. package/src/eval/py/spawn-options.ts +24 -29
  195. package/src/export/html/index.ts +10 -3
  196. package/src/export/html/template.js +8 -26
  197. package/src/export/share.ts +4 -0
  198. package/src/extensibility/extensions/wrapper.ts +1 -0
  199. package/src/extensibility/legacy-pi-ai-shim.ts +22 -1
  200. package/src/extensibility/legacy-pi-coding-agent-shim.ts +7 -6
  201. package/src/extensibility/plugins/legacy-pi-compat.ts +124 -57
  202. package/src/extensibility/skills.ts +11 -0
  203. package/src/extensibility/utils.ts +10 -2
  204. package/src/launch/broker.ts +223 -7
  205. package/src/launch/client.ts +192 -21
  206. package/src/launch/ensure.ts +73 -0
  207. package/src/launch/paths.ts +1 -1
  208. package/src/launch/protocol.ts +54 -2
  209. package/src/lsp/client.ts +23 -2
  210. package/src/lsp/index.ts +8 -0
  211. package/src/lsp/mux/daemon.ts +348 -0
  212. package/src/lsp/mux/protocol.ts +96 -0
  213. package/src/lsp/mux/server.ts +797 -0
  214. package/src/lsp/types.ts +28 -2
  215. package/src/main.ts +20 -8
  216. package/src/mcp/config-writer.ts +1 -1
  217. package/src/mcp/oauth-flow.ts +11 -1
  218. package/src/mnemopi/embed-client.ts +49 -2
  219. package/src/mnemopi/state.ts +57 -23
  220. package/src/modes/components/assistant-message.ts +11 -0
  221. package/src/modes/components/btw-panel.ts +41 -4
  222. package/src/modes/components/chat-transcript-builder.ts +4 -0
  223. package/src/modes/components/custom-editor.ts +9 -0
  224. package/src/modes/components/read-tool-group.ts +10 -0
  225. package/src/modes/components/status-line/component.ts +1 -1
  226. package/src/modes/components/stripped-tool-calls-placeholder.ts +35 -0
  227. package/src/modes/components/tool-execution.ts +8 -0
  228. package/src/modes/components/tree-selector.ts +46 -48
  229. package/src/modes/controllers/btw-controller.ts +55 -7
  230. package/src/modes/controllers/command-controller.ts +31 -0
  231. package/src/modes/controllers/event-controller.ts +17 -0
  232. package/src/modes/controllers/input-controller.ts +63 -8
  233. package/src/modes/controllers/mcp-command-controller.ts +11 -5
  234. package/src/modes/controllers/selector-controller.ts +20 -0
  235. package/src/modes/interactive-mode.ts +18 -2
  236. package/src/modes/types.ts +9 -1
  237. package/src/modes/utils/hotkeys-markdown.ts +1 -0
  238. package/src/modes/utils/interactive-context-helpers.ts +1 -0
  239. package/src/modes/utils/ui-helpers.ts +6 -10
  240. package/src/modes/workflow.ts +8 -2
  241. package/src/prompts/agents/init.md +1 -1
  242. package/src/prompts/session/launch-completion.md +1 -0
  243. package/src/prompts/system/plan-mode-active.md +2 -2
  244. package/src/prompts/system/system-prompt.md +26 -52
  245. package/src/prompts/system/workflow-notice.md +3 -3
  246. package/src/prompts/tools/ast-grep.md +1 -1
  247. package/src/prompts/tools/bash.md +1 -1
  248. package/src/prompts/tools/browser.md +1 -0
  249. package/src/prompts/tools/computer.md +21 -21
  250. package/src/prompts/tools/glob.md +1 -1
  251. package/src/prompts/tools/grep.md +1 -1
  252. package/src/prompts/tools/replace.md +5 -4
  253. package/src/prompts/tools/task.md +4 -4
  254. package/src/sdk.ts +49 -6
  255. package/src/secrets/index.ts +1 -1
  256. package/src/security/contracts/schemas.ts +205 -183
  257. package/src/security/contracts/validation.ts +5 -1
  258. package/src/security/store.ts +2 -2
  259. package/src/session/agent-session-types.ts +9 -1
  260. package/src/session/agent-session.ts +204 -15
  261. package/src/session/indexed-session-storage.ts +9 -0
  262. package/src/session/launch-completion.ts +37 -0
  263. package/src/session/prewalk.ts +24 -2
  264. package/src/session/session-advisors.ts +2 -2
  265. package/src/session/session-context.ts +42 -12
  266. package/src/session/session-dump-format.ts +1 -1
  267. package/src/session/session-entries.ts +17 -1
  268. package/src/session/session-maintenance.ts +38 -4
  269. package/src/session/session-manager.ts +123 -67
  270. package/src/session/session-paths.ts +118 -55
  271. package/src/session/session-stats.ts +48 -3
  272. package/src/session/session-storage.ts +30 -22
  273. package/src/session/stream-guards.ts +1 -1
  274. package/src/session/yield-queue.ts +121 -16
  275. package/src/slash-commands/builtin-registry.ts +37 -24
  276. package/src/system-prompt.ts +8 -3
  277. package/src/task/index.ts +23 -8
  278. package/src/task/spawn-policy.ts +14 -0
  279. package/src/thinking.ts +2 -8
  280. package/src/tools/ast-grep.ts +10 -4
  281. package/src/tools/browser/cmux/cmux-tab.ts +97 -14
  282. package/src/tools/browser/cmux/rpc.ts +2 -8
  283. package/src/tools/browser/registry.ts +53 -2
  284. package/src/tools/browser/relay/bridge.ts +945 -0
  285. package/src/tools/browser/relay/daemon.ts +117 -0
  286. package/src/tools/browser/relay/extension-assets/background.js.txt +242 -0
  287. package/src/tools/browser/relay/extension-assets/manifest.json.txt +14 -0
  288. package/src/tools/browser/relay/extension-assets/options.html.txt +53 -0
  289. package/src/tools/browser/relay/extension-assets/options.js.txt +23 -0
  290. package/src/tools/browser/relay/kind.ts +41 -0
  291. package/src/tools/browser/relay/protocol.ts +54 -0
  292. package/src/tools/browser/relay/server.ts +141 -0
  293. package/src/tools/browser/render.ts +4 -1
  294. package/src/tools/browser/shared-daemon.ts +7 -58
  295. package/src/tools/browser/tab-supervisor.ts +5 -4
  296. package/src/tools/browser/tab-worker.ts +33 -12
  297. package/src/tools/browser.ts +26 -1
  298. package/src/tools/computer/exposure.ts +11 -35
  299. package/src/tools/computer/protocol.ts +51 -10
  300. package/src/tools/computer/supervisor.ts +227 -124
  301. package/src/tools/computer/worker-entry.ts +11 -6
  302. package/src/tools/computer/worker.ts +695 -81
  303. package/src/tools/computer-renderer.ts +104 -65
  304. package/src/tools/computer.ts +134 -428
  305. package/src/tools/context.ts +3 -0
  306. package/src/tools/glob.ts +9 -2
  307. package/src/tools/grep.ts +12 -6
  308. package/src/tools/hub/launch.ts +122 -6
  309. package/src/tools/index.ts +9 -0
  310. package/src/tools/inspect-image.ts +32 -6
  311. package/src/tools/render-utils.ts +2 -0
  312. package/src/tools/{browser/run-cancellation.ts → run-scope.ts} +11 -11
  313. package/src/tools/tool-timeouts.ts +1 -0
  314. package/src/tools/xdev.ts +29 -2
  315. package/src/utils/clipboard.ts +40 -14
  316. package/src/utils/command-args.ts +26 -28
  317. package/src/utils/tool-choice.ts +0 -13
  318. package/src/web/kagi.ts +2 -1
  319. package/src/web/search/index.ts +18 -2
  320. package/src/web/search/providers/anthropic.ts +4 -1
  321. package/src/web/search/providers/base.ts +2 -0
  322. package/src/web/search/providers/brave.ts +3 -1
  323. package/src/web/search/providers/browser-page.ts +6 -4
  324. package/src/web/search/providers/codex.ts +4 -1
  325. package/src/web/search/providers/duckduckgo.ts +2 -1
  326. package/src/web/search/providers/ecosia.ts +2 -1
  327. package/src/web/search/providers/exa.ts +4 -2
  328. package/src/web/search/providers/firecrawl.ts +3 -1
  329. package/src/web/search/providers/gemini.ts +8 -2
  330. package/src/web/search/providers/google.ts +2 -1
  331. package/src/web/search/providers/jina.ts +12 -2
  332. package/src/web/search/providers/kagi.ts +3 -0
  333. package/src/web/search/providers/kimi.ts +5 -1
  334. package/src/web/search/providers/mojeek.ts +2 -1
  335. package/src/web/search/providers/parallel.ts +5 -1
  336. package/src/web/search/providers/perplexity.ts +6 -3
  337. package/src/web/search/providers/public.ts +1 -1
  338. package/src/web/search/providers/searxng.ts +11 -5
  339. package/src/web/search/providers/startpage.ts +10 -4
  340. package/src/web/search/providers/synthetic.ts +11 -5
  341. package/src/web/search/providers/tavily.ts +3 -1
  342. package/src/web/search/providers/tinyfish.ts +3 -1
  343. package/src/web/search/providers/utils.ts +12 -10
  344. package/src/web/search/providers/xai.ts +2 -2
  345. package/src/web/search/providers/zai.ts +18 -3
  346. package/src/web/search/types.ts +6 -0
  347. package/dist/types/config/file-lock.d.ts +0 -29
  348. package/src/config/file-lock.ts +0 -164
@@ -1,13 +1,14 @@
1
1
  /**
2
2
  * View usage statistics dashboard.
3
3
  */
4
+
4
5
  import { Command, Flags } from "@oh-my-pi/pi-utils/cli";
6
+ import { statsHelp as commandHelp } from "../cli/command-help";
5
7
  import { runStatsCommand, type StatsCommandArgs } from "../cli/stats-cli";
6
8
  import { initTheme } from "../modes/theme/theme";
7
9
 
8
10
  export default class Stats extends Command {
9
- static description = "View usage statistics";
10
-
11
+ static description = commandHelp.description;
11
12
  static flags = {
12
13
  port: Flags.integer({ char: "p", description: "Port for the dashboard server", default: 3847 }),
13
14
  json: Flags.boolean({ char: "j", description: "Output stats as JSON", default: false }),
@@ -1,11 +1,11 @@
1
1
  import { Args, Command, Flags } from "@oh-my-pi/pi-utils/cli";
2
+ import { tinyModelsHelp as commandHelp } from "../cli/command-help";
2
3
  import { runTinyModelsCommand, type TinyModelsAction, type TinyModelsCommandArgs } from "../cli/tiny-models-cli";
3
4
 
4
5
  const ACTIONS: TinyModelsAction[] = ["download", "list"];
5
6
 
6
7
  export default class TinyModels extends Command {
7
- static description = "Download tiny local models (session titles + memory)";
8
-
8
+ static description = commandHelp.description;
9
9
  static args = {
10
10
  action: Args.string({
11
11
  description: "Action to perform",
@@ -5,13 +5,13 @@
5
5
  import { PROVIDER_REGISTRY } from "@oh-my-pi/pi-ai";
6
6
  import { Args, Command, Flags } from "@oh-my-pi/pi-utils/cli";
7
7
  import chalk from "chalk";
8
+ import { tokenHelp as commandHelp } from "../cli/command-help";
8
9
  import { isAuthenticated, ModelRegistry } from "../config/model-registry";
9
10
  import { discoverAuthStorage } from "../sdk";
10
11
  import { getAvailableAuthMethods } from "../web/search/providers/perplexity-auth";
11
12
 
12
13
  export default class Token extends Command {
13
- static description = "Get the API key or OAuth token for a provider";
14
-
14
+ static description = commandHelp.description;
15
15
  static args = {
16
16
  provider: Args.string({
17
17
  description: "Provider ID (e.g. anthropic, openai)",
@@ -8,6 +8,7 @@ import * as path from "node:path";
8
8
  * shows every TTSR-registered rule the current project/user config would load.
9
9
  */
10
10
  import { Args, Command, Flags } from "@oh-my-pi/pi-utils/cli";
11
+ import { ttsrHelp as commandHelp } from "../cli/command-help";
11
12
  import {
12
13
  runTtsrCommand,
13
14
  TTSR_ACTIONS,
@@ -19,8 +20,7 @@ import {
19
20
  import type { TtsrMatchSource } from "../export/ttsr";
20
21
 
21
22
  export default class Ttsr extends Command {
22
- static description = "Inspect and test Time-Traveling Stream Rules (TTSR)";
23
-
23
+ static description = commandHelp.description;
24
24
  static args = {
25
25
  action: Args.string({
26
26
  description: "TTSR action",
@@ -1,14 +1,15 @@
1
1
  /**
2
2
  * Check for and install updates.
3
3
  */
4
+
4
5
  import { Command, Flags } from "@oh-my-pi/pi-utils/cli";
6
+ import { updateHelp as commandHelp } from "../cli/command-help";
5
7
  import * as pluginCli from "../cli/plugin-cli";
6
8
  import * as updateCli from "../cli/update-cli";
7
9
  import { initTheme } from "../modes/theme/theme";
8
10
 
9
11
  export default class Update extends Command {
10
- static description = "Check for and install updates";
11
-
12
+ static description = commandHelp.description;
12
13
  static flags = {
13
14
  force: Flags.boolean({ char: "f", description: "Force update", default: false }),
14
15
  check: Flags.boolean({ char: "c", description: "Check for updates without installing", default: false }),
@@ -1,12 +1,13 @@
1
1
  /**
2
2
  * Show provider usage limits for every authenticated account.
3
3
  */
4
+
4
5
  import { Args, Command, Flags } from "@oh-my-pi/pi-utils/cli";
6
+ import { usageHelp as commandHelp } from "../cli/command-help";
5
7
  import { runUsageCommand } from "../cli/usage-cli";
6
8
 
7
9
  export default class Usage extends Command {
8
- static description = "Show provider usage limits for every authenticated account";
9
-
10
+ static description = commandHelp.description;
10
11
  static args = {
11
12
  action: Args.string({
12
13
  description: "Optional subcommand to execute",
@@ -1,7 +1,9 @@
1
1
  /**
2
2
  * Test web search providers.
3
3
  */
4
+
4
5
  import { Args, Command, Flags } from "@oh-my-pi/pi-utils/cli";
6
+ import { searchHelp as commandHelp } from "../cli/command-help";
5
7
  import { runSearchCommand, type SearchCommandArgs } from "../cli/web-search-cli";
6
8
  import { SEARCH_PROVIDER_ORDER } from "../web/search/provider";
7
9
 
@@ -10,8 +12,7 @@ const PROVIDERS: Array<string> = ["auto", ...SEARCH_PROVIDER_ORDER];
10
12
  const RECENCY: NonNullable<SearchCommandArgs["recency"]>[] = ["day", "week", "month", "year"];
11
13
 
12
14
  export default class Search extends Command {
13
- static description = "Test web search providers";
14
-
15
+ static description = commandHelp.description;
15
16
  static aliases = ["q"];
16
17
 
17
18
  static args = {
@@ -1,14 +1,15 @@
1
1
  /**
2
2
  * List and clean up agent-managed git worktrees under `~/.omp/wt`.
3
3
  */
4
+
4
5
  import { getProjectDir } from "@oh-my-pi/pi-utils";
5
6
  import { Args, Command, Flags } from "@oh-my-pi/pi-utils/cli";
7
+ import { worktreeHelp as commandHelp } from "../cli/command-help";
6
8
  import { clearWorktrees, listWorktrees } from "../cli/worktree-cli";
7
9
  import { Settings } from "../config/settings";
8
10
 
9
11
  export default class Worktree extends Command {
10
- static description = "List or clear agent-managed git worktrees (~/.omp/wt)";
11
-
12
+ static description = commandHelp.description;
12
13
  static aliases = ["wt"];
13
14
 
14
15
  static args = {
@@ -29,6 +29,7 @@ interface AppKeybindings {
29
29
  "app.model.select": true;
30
30
  "app.model.selectTemporary": true;
31
31
  "app.tools.expand": true;
32
+ "app.tools.toggleVisibility": true;
32
33
  "app.editor.external": true;
33
34
  "app.message.followUp": true;
34
35
  "app.retry": true;
@@ -124,6 +125,10 @@ export const KEYBINDINGS = {
124
125
  defaultKeys: "ctrl+o",
125
126
  description: "Expand tools",
126
127
  },
128
+ "app.tools.toggleVisibility": {
129
+ defaultKeys: "ctrl+shift+o",
130
+ description: "Show or hide tool activity",
131
+ },
127
132
  "app.editor.external": {
128
133
  defaultKeys: "ctrl+g",
129
134
  description: "Open external editor",
@@ -38,25 +38,25 @@ export const DISCOVERY_DEFAULT_CONTEXT_WINDOW = OPENAI_COMPAT_DISCOVERY_DEFAULT_
38
38
  export const DISCOVERY_DEFAULT_MAX_TOKENS = OPENAI_COMPAT_DISCOVERY_DEFAULT_MAX_TOKENS;
39
39
 
40
40
  /**
41
- * Run `fn` with an abort signal that fires after `timeoutMs`, clearing the
42
- * backing timer the instant the operation settles.
41
+ * Run `fn` with a hard deadline while also signalling cooperative transports
42
+ * to abort. The independent rejection keeps discovery bounded when a runtime
43
+ * leaves its fetch promise pending after `AbortSignal.abort()` (observed with
44
+ * Windows localhost probes).
43
45
  *
44
- * Unlike the built-in abort-signal timeout API, the timer never outlives the
45
- * request: on the success path it is cancelled before `fn` resolves, so the
46
- * signal is never aborted and no pending callback lingers on the heap. A leaked
47
- * abort-signal timeout (e.g. discovery against a mocked fetch that resolves
48
- * instantly) fires seconds later and sets its abort `reason` — which crashed
49
- * Bun's concurrent GC while it marked the signal's wrapped reason during an
50
- * unrelated allocation (`JSAbortSignal::visitAdditionalChildren`).
46
+ * The backing timer is cleared as soon as `fn` settles, unlike
47
+ * `AbortSignal.timeout()`, whose delayed reason previously crashed Bun's
48
+ * concurrent GC during an unrelated allocation.
51
49
  */
52
50
  async function withTimeoutSignal<T>(timeoutMs: number, fn: (signal: AbortSignal) => Promise<T>): Promise<T> {
53
51
  const controller = new AbortController();
54
- const timer = setTimeout(
55
- () => controller.abort(new DOMException("The operation timed out.", "TimeoutError")),
56
- timeoutMs,
57
- );
52
+ const timeout = Promise.withResolvers<never>();
53
+ const timer = setTimeout(() => {
54
+ const error = new DOMException("The operation timed out.", "TimeoutError");
55
+ controller.abort(error);
56
+ timeout.reject(error);
57
+ }, timeoutMs);
58
58
  try {
59
- return await fn(controller.signal);
59
+ return await Promise.race([fn(controller.signal), timeout.promise]);
60
60
  } finally {
61
61
  clearTimeout(timer);
62
62
  }
@@ -76,7 +76,10 @@ const REMOTE_DISCOVERY_TIMEOUT_MS = 10_000;
76
76
  * empty (issue #7087). Anything that is not strictly loopback therefore gets
77
77
  * {@link REMOTE_DISCOVERY_TIMEOUT_MS}.
78
78
  */
79
- export function discoveryProbeTimeoutMs(baseUrl: string, loopbackMs: number): number {
79
+ export function discoveryProbeTimeoutMs(baseUrl: string, loopbackMs: number, customTimeoutMs?: number): number {
80
+ if (typeof customTimeoutMs === "number" && customTimeoutMs > 0 && Number.isFinite(customTimeoutMs)) {
81
+ return customTimeoutMs;
82
+ }
80
83
  let hostname: string;
81
84
  try {
82
85
  hostname = new URL(baseUrl).hostname;
@@ -415,10 +418,11 @@ async function discoverOllamaModelMetadata(
415
418
  endpoint: string,
416
419
  modelId: string,
417
420
  headers: Record<string, string> | undefined,
421
+ customTimeoutMs?: number,
418
422
  ): Promise<OllamaDiscoveredModelMetadata | null> {
419
423
  const showUrl = `${endpoint}/api/show`;
420
424
  try {
421
- const payload = await withTimeoutSignal(discoveryProbeTimeoutMs(endpoint, 150), async signal => {
425
+ const payload = await withTimeoutSignal(discoveryProbeTimeoutMs(endpoint, 150, customTimeoutMs), async signal => {
422
426
  const response = await ctx.fetch(showUrl, {
423
427
  method: "POST",
424
428
  headers: { ...(headers ?? {}), "Content-Type": "application/json" },
@@ -471,7 +475,8 @@ export async function discoverOllamaModels(
471
475
  const endpoint = normalizeOllamaBaseUrl(providerConfig.baseUrl);
472
476
  const tagsUrl = `${endpoint}/api/tags`;
473
477
  const headers = { ...(providerConfig.headers ?? {}) };
474
- const payload = await withTimeoutSignal(discoveryProbeTimeoutMs(endpoint, 250), async signal => {
478
+ const customTimeoutMs = providerConfig.discovery.timeoutMs;
479
+ const payload = await withTimeoutSignal(discoveryProbeTimeoutMs(endpoint, 250, customTimeoutMs), async signal => {
475
480
  const response = await ctx.fetch(tagsUrl, {
476
481
  headers,
477
482
  signal,
@@ -488,7 +493,11 @@ export async function discoverOllamaModels(
488
493
  const metadataById = new Map(
489
494
  await Promise.all(
490
495
  entries.map(
491
- async entry => [entry.id, await discoverOllamaModelMetadata(ctx, endpoint, entry.id, headers)] as const,
496
+ async entry =>
497
+ [
498
+ entry.id,
499
+ await discoverOllamaModelMetadata(ctx, endpoint, entry.id, headers, customTimeoutMs),
500
+ ] as const,
492
501
  ),
493
502
  ),
494
503
  );
@@ -515,10 +524,11 @@ async function discoverLlamaCppServerMetadata(
515
524
  ctx: DiscoveryContext,
516
525
  baseUrl: string,
517
526
  headers: Record<string, string> | undefined,
527
+ customTimeoutMs?: number,
518
528
  ): Promise<LlamaCppDiscoveredServerMetadata | null> {
519
529
  const propsUrl = `${toLlamaCppNativeBaseUrl(baseUrl)}/props`;
520
530
  try {
521
- const payload = await withTimeoutSignal(discoveryProbeTimeoutMs(baseUrl, 150), async signal => {
531
+ const payload = await withTimeoutSignal(discoveryProbeTimeoutMs(baseUrl, 150, customTimeoutMs), async signal => {
522
532
  const response = await ctx.fetch(propsUrl, {
523
533
  headers,
524
534
  signal,
@@ -592,9 +602,10 @@ export async function discoverLlamaCppModels(
592
602
 
593
603
  const baseHeaders: Record<string, string> = { ...(providerConfig.headers ?? {}) };
594
604
  let headers = baseHeaders;
605
+ const customTimeoutMs = providerConfig.discovery.timeoutMs;
595
606
  const attempt = async (h: Record<string, string>) => {
596
607
  const [payload, metadata] = await Promise.all([
597
- withTimeoutSignal(discoveryProbeTimeoutMs(baseUrl, 250), async signal => {
608
+ withTimeoutSignal(discoveryProbeTimeoutMs(baseUrl, 250, customTimeoutMs), async signal => {
598
609
  const response = await ctx.fetch(modelsUrl, {
599
610
  headers: h,
600
611
  signal,
@@ -605,7 +616,7 @@ export async function discoverLlamaCppModels(
605
616
  headers = h;
606
617
  return (await response.json()) as unknown;
607
618
  }),
608
- discoverLlamaCppServerMetadata(ctx, baseUrl, h),
619
+ discoverLlamaCppServerMetadata(ctx, baseUrl, h, customTimeoutMs),
609
620
  ]);
610
621
  return [payload, metadata] as const;
611
622
  };
@@ -657,6 +668,7 @@ export async function discoverLlamaCppModels(
657
668
  export async function discoverLlamaCppModelRuntimeMetadata(
658
669
  model: Pick<Model<Api>, "provider" | "id" | "baseUrl" | "headers">,
659
670
  ctx: DiscoveryContext,
671
+ customTimeoutMs?: number,
660
672
  ): Promise<LlamaCppDiscoveredModelRuntimeMetadata | undefined> {
661
673
  const baseUrl = normalizeLlamaCppBaseUrl(model.baseUrl);
662
674
  // Probe the native `/models` endpoint (not the OpenAI-compatible `/v1/models`)
@@ -668,7 +680,7 @@ export async function discoverLlamaCppModelRuntimeMetadata(
668
680
  const baseHeaders: Record<string, string> = { ...(model.headers ?? {}) };
669
681
  const attempt = async (headers: Record<string, string>) => {
670
682
  const [entries, serverMetadata] = await Promise.all([
671
- withTimeoutSignal(discoveryProbeTimeoutMs(nativeBaseUrl, 250), async signal => {
683
+ withTimeoutSignal(discoveryProbeTimeoutMs(nativeBaseUrl, 250, customTimeoutMs), async signal => {
672
684
  const response = await ctx.fetch(modelsUrl, {
673
685
  headers,
674
686
  signal,
@@ -678,7 +690,7 @@ export async function discoverLlamaCppModelRuntimeMetadata(
678
690
  }
679
691
  return parseLlamaCppModelList(await response.json());
680
692
  }),
681
- discoverLlamaCppServerMetadata(ctx, nativeBaseUrl, headers),
693
+ discoverLlamaCppServerMetadata(ctx, nativeBaseUrl, headers, customTimeoutMs),
682
694
  ]);
683
695
  if (!entries) {
684
696
  return undefined;
@@ -721,13 +733,16 @@ export async function discoverOpenAIModelsList(
721
733
 
722
734
  const baseHeaders: Record<string, string> = { ...(providerConfig.headers ?? {}) };
723
735
  let headers = baseHeaders;
736
+ const timeoutMs = providerConfig.discovery.timeoutMs ?? 10_000;
724
737
  const attempt = async (h: Record<string, string>) => {
725
738
  const nativeMetadataPromise =
726
739
  providerConfig.discovery.type === "lm-studio"
727
- ? fetchLmStudioNativeModelMetadata(baseUrl, ctx.fetch, { headers: h })
740
+ ? withTimeoutSignal(timeoutMs, signal =>
741
+ fetchLmStudioNativeModelMetadata(baseUrl, ctx.fetch, { headers: h, signal }),
742
+ )
728
743
  : Promise.resolve(null);
729
744
  const [payload, nativeMetadata] = await Promise.all([
730
- withTimeoutSignal(10_000, async signal => {
745
+ withTimeoutSignal(timeoutMs, async signal => {
731
746
  const res = await ctx.fetch(modelsUrl, {
732
747
  headers: h,
733
748
  signal,
@@ -819,6 +834,7 @@ export async function discoverLiteLLMModels(
819
834
  const resolveReference = (id: string) => resolveModelReference(id, references) as ModelSpec<Api> | undefined;
820
835
  const baseHeaders: Record<string, string> = { ...(providerConfig.headers ?? {}) };
821
836
  let headers = baseHeaders;
837
+ const timeoutMs = providerConfig.discovery.timeoutMs ?? 10_000;
822
838
  const attempt = async (h: Record<string, string>) => {
823
839
  headers = h;
824
840
  let authError: (Error & { status: number }) | undefined;
@@ -830,7 +846,7 @@ export async function discoverLiteLLMModels(
830
846
  }
831
847
  return response;
832
848
  };
833
- const models = await withTimeoutSignal(10_000, signal =>
849
+ const models = await withTimeoutSignal(timeoutMs, signal =>
834
850
  fetchLiteLLMRichModels({
835
851
  api: providerConfig.api,
836
852
  provider: providerConfig.provider,
@@ -889,8 +905,9 @@ export async function discoverProxyModels(
889
905
 
890
906
  const baseHeaders: Record<string, string> = { ...(providerConfig.headers ?? {}) };
891
907
  let headers = baseHeaders;
908
+ const timeoutMs = providerConfig.discovery.timeoutMs ?? 10_000;
892
909
  const attempt = async (h: Record<string, string>) =>
893
- withTimeoutSignal(10_000, async signal => {
910
+ withTimeoutSignal(timeoutMs, async signal => {
894
911
  const res = await ctx.fetch(modelsUrl, {
895
912
  headers: h,
896
913
  signal,
@@ -68,12 +68,13 @@ import type { ApiKeyResolver, FetchImpl } from "@oh-my-pi/pi-ai";
68
68
  import { registerOAuthProvider, unregisterOAuthProviders } from "@oh-my-pi/pi-ai/oauth";
69
69
  import type { OAuthCredentials, OAuthLoginCallbacks } from "@oh-my-pi/pi-ai/oauth/types";
70
70
  import { setCodexAttestationProvider } from "@oh-my-pi/pi-ai/providers/openai-codex-responses";
71
+ import { getProviderDefinition } from "@oh-my-pi/pi-ai/registry";
71
72
  import {
72
73
  getBundledModelReferenceIndex,
73
74
  inheritReferenceThinking,
74
75
  resolveModelReference,
75
76
  } from "@oh-my-pi/pi-catalog/identity";
76
- import { isBunTestRuntime, isRecord, logger, wrapFetchForExtraCa } from "@oh-my-pi/pi-utils";
77
+ import { $envExact, isBunTestRuntime, isRecord, logger, wrapFetchForExtraCa } from "@oh-my-pi/pi-utils";
77
78
  import { parseModelString, resolveProviderModelReference } from "../config/model-resolver";
78
79
  import { generateCodexAttestation } from "../live/attestation";
79
80
  import type { AuthStorage, OAuthCredential } from "../session/auth-storage";
@@ -329,7 +330,7 @@ interface CommandApiKeyResolution {
329
330
  */
330
331
  function resolveConfigValue(valueConfig: string): string | undefined {
331
332
  if (valueConfig.startsWith("!")) return resolveCommandConfig(valueConfig.slice(1).trim());
332
- const envValue = Bun.env[valueConfig];
333
+ const envValue = $envExact(valueConfig);
333
334
  if (envValue) return envValue;
334
335
  return valueConfig;
335
336
  }
@@ -972,14 +973,18 @@ export class ModelRegistry {
972
973
  * Refresh dynamic metadata that can appear only after a local model loads.
973
974
  */
974
975
  async refreshSelectedModelMetadata(model: Model<Api>): Promise<Model<Api>> {
975
- const isLlamaCppDiscovery = this.#discoverableProviders.some(
976
+ const llamaCppDiscoveryConfig = this.#discoverableProviders.find(
976
977
  providerConfig => providerConfig.provider === model.provider && providerConfig.discovery.type === "llama.cpp",
977
978
  );
978
- if (!isLlamaCppDiscovery) {
979
+ if (!llamaCppDiscoveryConfig) {
979
980
  return model;
980
981
  }
981
982
  this.#ensureFullSnapshot();
982
- const runtimeMetadata = await discoverLlamaCppModelRuntimeMetadata(model, this.#nonResolvingDiscoveryContext());
983
+ const runtimeMetadata = await discoverLlamaCppModelRuntimeMetadata(
984
+ model,
985
+ this.#nonResolvingDiscoveryContext(),
986
+ llamaCppDiscoveryConfig.discovery.timeoutMs,
987
+ );
983
988
  if (runtimeMetadata === undefined) {
984
989
  return this.find(model.provider, model.id) ?? model;
985
990
  }
@@ -2007,14 +2012,15 @@ export class ModelRegistry {
2007
2012
  this.#providerOverrides.has(descriptor.providerId) ||
2008
2013
  this.#keylessProviders.has(descriptor.providerId));
2009
2014
  if (isAuthenticated(apiKey) || descriptor.allowUnauthenticated || hasExplicitVllmConfig) {
2010
- const discoveryBaseUrl = this.#descriptorBaseUrl(descriptor.providerId);
2011
- options.push(
2012
- descriptor.createModelManagerOptions({
2013
- apiKey: isDiscoveryBearerApiKey(apiKey) ? apiKey : undefined,
2014
- baseUrl: discoveryBaseUrl,
2015
- fetch: this.#fetch,
2016
- }),
2017
- );
2015
+ const discoveryConfig = {
2016
+ apiKey: isDiscoveryBearerApiKey(apiKey) ? apiKey : undefined,
2017
+ baseUrl: this.#descriptorBaseUrl(descriptor.providerId),
2018
+ fetch: this.#fetch,
2019
+ };
2020
+ const preparedConfig =
2021
+ getProviderDefinition(descriptor.providerId)?.prepareModelDiscovery?.(discoveryConfig) ??
2022
+ discoveryConfig;
2023
+ options.push(descriptor.createModelManagerOptions(preparedConfig));
2018
2024
  }
2019
2025
  }
2020
2026
 
@@ -262,6 +262,15 @@ export const getModelsConfigSchemaBundle = once(() => {
262
262
 
263
263
  const ProviderDiscoverySchema = type({
264
264
  type: '"ollama" | "llama.cpp" | "lm-studio" | "openai-models-list" | "proxy" | "litellm"',
265
+ "timeoutMs?": "number",
266
+ }).narrow((value, ctx) => {
267
+ if (
268
+ value.timeoutMs !== undefined &&
269
+ (typeof value.timeoutMs !== "number" || value.timeoutMs <= 0 || !Number.isFinite(value.timeoutMs))
270
+ ) {
271
+ return ctx.mustBe("timeoutMs a positive finite number");
272
+ }
273
+ return true;
265
274
  });
266
275
 
267
276
  const ProviderAuthSchema = type('"apiKey" | "none" | "oauth"');
@@ -5,6 +5,7 @@
5
5
  */
6
6
 
7
7
  import { executeShell } from "@oh-my-pi/pi-natives";
8
+ import { $envExact } from "@oh-my-pi/pi-utils";
8
9
 
9
10
  /** Cache for successful shell command results (persists for process lifetime). */
10
11
  const commandResultCache = new Map<string, string>();
@@ -21,7 +22,7 @@ export async function resolveConfigValue(config: string): Promise<string | undef
21
22
  if (config.startsWith("!")) {
22
23
  return await executeCommand(config);
23
24
  }
24
- const envValue = process.env[config];
25
+ const envValue = $envExact(config);
25
26
  return envValue || config;
26
27
  }
27
28
 
@@ -16,6 +16,11 @@ export type ServiceTierOpenAISettingValue = (typeof SERVICE_TIER_OPENAI_VALUES)[
16
16
  export type ServiceTierAnthropicSettingValue = (typeof SERVICE_TIER_ANTHROPIC_VALUES)[number];
17
17
  export type ServiceTierGoogleSettingValue = (typeof SERVICE_TIER_GOOGLE_VALUES)[number];
18
18
 
19
+ /** Whether a runtime value is a supported OpenAI service-tier setting. */
20
+ export function isServiceTierOpenAISettingValue(value: string): value is ServiceTierOpenAISettingValue {
21
+ return SERVICE_TIER_OPENAI_VALUES.some(tier => tier === value);
22
+ }
23
+
19
24
  /** Whether a runtime value names a provider family with an independent service-tier knob. */
20
25
  export function isServiceTierFamily(value: unknown): value is ServiceTierFamily {
21
26
  return value === "openai" || value === "anthropic" || value === "google";
@@ -37,7 +37,12 @@ import {
37
37
  TTS_LOCAL_VOICE_VALUES,
38
38
  } from "../tts/models";
39
39
  import { EDIT_MODES } from "../utils/edit-mode";
40
- import { SEARCH_PROVIDER_CHOICES, type SearchProviderId } from "../web/search/types";
40
+ import {
41
+ DEFAULT_WEB_SEARCH_TIMEOUT_SECONDS,
42
+ MAX_WEB_SEARCH_TIMEOUT_SECONDS,
43
+ SEARCH_PROVIDER_CHOICES,
44
+ type SearchProviderId,
45
+ } from "../web/search/types";
41
46
  import {
42
47
  SERVICE_TIER_ANTHROPIC_OPTIONS,
43
48
  SERVICE_TIER_ANTHROPIC_VALUES,
@@ -1013,6 +1018,17 @@ export const SETTINGS_SCHEMA = {
1013
1018
  },
1014
1019
  },
1015
1020
 
1021
+ "display.hideToolActivity": {
1022
+ type: "boolean",
1023
+ default: false,
1024
+ ui: {
1025
+ tab: "appearance",
1026
+ group: "Display",
1027
+ label: "Hide Tool Activity",
1028
+ description: "Hide model-initiated tool calls and results from the transcript",
1029
+ },
1030
+ },
1031
+
1016
1032
  "display.showTokenUsage": {
1017
1033
  type: "boolean",
1018
1034
  default: false,
@@ -3382,6 +3398,18 @@ export const SETTINGS_SCHEMA = {
3382
3398
  },
3383
3399
  },
3384
3400
 
3401
+ "lsp.shared": {
3402
+ type: "boolean",
3403
+ default: true,
3404
+ ui: {
3405
+ tab: "files",
3406
+ group: "LSP",
3407
+ label: "Shared Language Servers",
3408
+ description:
3409
+ "Share one language server per project across omp instances via the daemon broker (falls back to private servers when unavailable)",
3410
+ },
3411
+ },
3412
+
3385
3413
  "lsp.formatOnWrite": {
3386
3414
  type: "boolean",
3387
3415
  default: false,
@@ -3897,23 +3925,7 @@ export const SETTINGS_SCHEMA = {
3897
3925
  tab: "tools",
3898
3926
  group: "Available Tools",
3899
3927
  label: "Computer",
3900
- description: "Enable native host-desktop screenshots and input for OpenAI computer use",
3901
- },
3902
- },
3903
-
3904
- "computer.backend": {
3905
- type: "enum",
3906
- values: ["auto", "native"] as const,
3907
- default: "auto",
3908
- ui: {
3909
- tab: "tools",
3910
- group: "Computer",
3911
- label: "Computer Backend",
3912
- description: "Select automatic or explicit platform-native desktop capture and input",
3913
- options: [
3914
- { value: "auto", label: "Auto" },
3915
- { value: "native", label: "Native" },
3916
- ],
3928
+ description: "Enable the scriptable host-desktop control tool (screenshots, input, accessibility)",
3917
3929
  },
3918
3930
  },
3919
3931
 
@@ -3930,7 +3942,7 @@ export const SETTINGS_SCHEMA = {
3930
3942
 
3931
3943
  "computer.maxWidth": {
3932
3944
  type: "number",
3933
- default: 1920,
3945
+ default: 3840,
3934
3946
  ui: {
3935
3947
  tab: "tools",
3936
3948
  group: "Computer",
@@ -3941,7 +3953,7 @@ export const SETTINGS_SCHEMA = {
3941
3953
 
3942
3954
  "computer.maxHeight": {
3943
3955
  type: "number",
3944
- default: 1200,
3956
+ default: 2400,
3945
3957
  ui: {
3946
3958
  tab: "tools",
3947
3959
  group: "Computer",
@@ -4108,6 +4120,29 @@ export const SETTINGS_SCHEMA = {
4108
4120
  },
4109
4121
  },
4110
4122
 
4123
+ "browser.relay": {
4124
+ type: "boolean",
4125
+ default: false,
4126
+ ui: {
4127
+ tab: "tools",
4128
+ group: "Grep & Browser",
4129
+ label: "Browser Relay",
4130
+ description:
4131
+ "Drive your own Chrome tabs through the omp browser relay. Install the extension once (`omp browser-relay install`); the relay server auto-starts when the browser tool needs it. Takes precedence over Browser CDP URL; set PI_BROWSER_RELAY=0 or PI_BROWSER_RELAY=1 to override.",
4132
+ },
4133
+ },
4134
+
4135
+ "browser.relayUrl": {
4136
+ type: "string",
4137
+ default: undefined,
4138
+ ui: {
4139
+ tab: "tools",
4140
+ group: "Grep & Browser",
4141
+ label: "Browser Relay URL",
4142
+ description: "omp browser relay endpoint (default http://127.0.0.1:9224).",
4143
+ },
4144
+ },
4145
+
4111
4146
  "browser.headless": {
4112
4147
  type: "boolean",
4113
4148
  default: true,
@@ -4869,6 +4904,23 @@ export const SETTINGS_SCHEMA = {
4869
4904
  options: SEARCH_PROVIDER_CHOICES,
4870
4905
  },
4871
4906
  },
4907
+ "providers.webSearchTimeoutSeconds": {
4908
+ type: "number",
4909
+ default: DEFAULT_WEB_SEARCH_TIMEOUT_SECONDS,
4910
+ ui: {
4911
+ tab: "providers",
4912
+ group: "Services",
4913
+ label: "Web Search Timeout",
4914
+ description: `Hard timeout for each provider's search transport before web_search advances to the next fallback, in seconds (maximum ${MAX_WEB_SEARCH_TIMEOUT_SECONDS})`,
4915
+ options: [
4916
+ { value: "30", label: "30 seconds" },
4917
+ { value: "60", label: "1 minute" },
4918
+ { value: "120", label: "2 minutes" },
4919
+ { value: "180", label: "3 minutes" },
4920
+ { value: "300", label: "5 minutes" },
4921
+ ],
4922
+ },
4923
+ },
4872
4924
  "providers.webSearchGeminiModel": {
4873
4925
  type: "string",
4874
4926
  default: undefined,
@@ -30,6 +30,7 @@ import {
30
30
  setWorktreesDir,
31
31
  toError,
32
32
  } from "@oh-my-pi/pi-utils";
33
+ import { withFileLock } from "@oh-my-pi/pi-utils/file-lock";
33
34
  import { JSONC, YAML } from "bun";
34
35
  import { invalidate as invalidateCapabilityFsCache } from "../capability/fs";
35
36
  import { type Settings as SettingsCapabilityItem, settingsCapability } from "../capability/settings";
@@ -41,7 +42,6 @@ import { AUTO_IMAGE_PROVIDER_ORDER, isImageProviderId } from "../tools/image-pro
41
42
  import { type EditMode, normalizeEditMode } from "../utils/edit-mode";
42
43
  import { INSPECT_IMAGE_MODES } from "../utils/inspect-image-mode";
43
44
  import { isSearchProviderId, SEARCH_PROVIDER_ORDER } from "../web/search/types";
44
- import { withFileLock } from "./file-lock";
45
45
  import {
46
46
  type BashInterceptorRule,
47
47
  type GroupPrefix,
@@ -39,7 +39,7 @@ export function createBridgeGrepFactory(
39
39
  /**
40
40
  * Build the `replace`-mode `edit` the bridge answers `pi_edit` with.
41
41
  *
42
- * `PiEditExecArgs` carries `old_text`/`new_text` pairs, which is exactly
42
+ * `PiEditExecArgs` carries `old_string`/`new_string` replacements, which is exactly
43
43
  * `replace`'s schema and nothing else's. The session's own instance follows the
44
44
  * configured `edit.mode` — `hashline` by default, whose schema is a single
45
45
  * `input` string — so a frame handed that instance fails validation instead of