@oh-my-pi/pi-coding-agent 17.0.8 → 17.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (340) hide show
  1. package/CHANGELOG.md +87 -1
  2. package/README.md +1 -1
  3. package/dist/cli.js +5495 -5021
  4. package/dist/types/async/job-manager.d.ts +37 -1
  5. package/dist/types/cli/args.d.ts +2 -0
  6. package/dist/types/cli/bench-cli.d.ts +41 -0
  7. package/dist/types/commands/bench.d.ts +15 -3
  8. package/dist/types/commands/launch.d.ts +4 -0
  9. package/dist/types/config/__tests__/model-registry.test.d.ts +1 -0
  10. package/dist/types/config/model-registry.d.ts +30 -1
  11. package/dist/types/config/models-config-schema.d.ts +18 -6
  12. package/dist/types/config/models-config.d.ts +14 -5
  13. package/dist/types/config/provider-globals.d.ts +2 -2
  14. package/dist/types/config/service-tier.d.ts +5 -1
  15. package/dist/types/config/settings-schema.d.ts +350 -50
  16. package/dist/types/config/settings.d.ts +7 -0
  17. package/dist/types/dap/client.d.ts +20 -0
  18. package/dist/types/exec/bash-executor.d.ts +38 -0
  19. package/dist/types/exec/direnv.d.ts +33 -0
  20. package/dist/types/export/html/args.d.ts +15 -0
  21. package/dist/types/export/html/index.d.ts +11 -26
  22. package/dist/types/export/html/web-palette.d.ts +55 -116
  23. package/dist/types/extensibility/extensions/loader.d.ts +3 -0
  24. package/dist/types/extensibility/extensions/types.d.ts +17 -2
  25. package/dist/types/extensibility/legacy-pi-coding-agent-shim.d.ts +1 -0
  26. package/dist/types/extensibility/legacy-pi-tui-shim.d.ts +10 -0
  27. package/dist/types/extensibility/plugins/legacy-pi-compat.d.ts +14 -1
  28. package/dist/types/internal-urls/registry-helpers.d.ts +11 -0
  29. package/dist/types/live/controller.d.ts +40 -0
  30. package/dist/types/live/protocol.d.ts +85 -0
  31. package/dist/types/live/protocol.test.d.ts +1 -0
  32. package/dist/types/live/transport.d.ts +48 -0
  33. package/dist/types/live/visualizer.d.ts +33 -0
  34. package/dist/types/lsp/client.d.ts +18 -1
  35. package/dist/types/mcp/config-writer.test.d.ts +1 -0
  36. package/dist/types/mcp/manager.d.ts +6 -2
  37. package/dist/types/mcp/oauth-discovery.d.ts +2 -0
  38. package/dist/types/mcp/render.d.ts +2 -2
  39. package/dist/types/mcp/smithery-auth.d.ts +1 -1
  40. package/dist/types/mcp/smithery-auth.test.d.ts +1 -0
  41. package/dist/types/mcp/tool-bridge.d.ts +7 -3
  42. package/dist/types/mcp/types.d.ts +6 -0
  43. package/dist/types/memory-backend/tool-names.d.ts +2 -0
  44. package/dist/types/modes/components/login-dialog.d.ts +2 -2
  45. package/dist/types/modes/components/oauth-selector.d.ts +8 -0
  46. package/dist/types/modes/components/plan-review-overlay.d.ts +26 -0
  47. package/dist/types/modes/components/settings-defs.d.ts +8 -1
  48. package/dist/types/modes/components/status-line/component.jj-cache.test.d.ts +1 -0
  49. package/dist/types/modes/components/tool-execution.d.ts +9 -1
  50. package/dist/types/modes/controllers/command-controller.d.ts +1 -1
  51. package/dist/types/modes/controllers/event-controller.d.ts +6 -1
  52. package/dist/types/modes/controllers/live-command-controller.d.ts +14 -0
  53. package/dist/types/modes/controllers/mcp-command-controller.d.ts +3 -0
  54. package/dist/types/modes/interactive-mode.d.ts +5 -0
  55. package/dist/types/modes/rpc/rpc-client.d.ts +10 -1
  56. package/dist/types/modes/rpc/rpc-frame.d.ts +16 -0
  57. package/dist/types/modes/rpc/rpc-messages.d.ts +26 -0
  58. package/dist/types/modes/rpc/rpc-types.d.ts +40 -0
  59. package/dist/types/modes/setup-wizard/scenes/sign-in.d.ts +1 -1
  60. package/dist/types/modes/setup-wizard/scenes/types.d.ts +9 -1
  61. package/dist/types/modes/setup-wizard/scenes/web-search.d.ts +1 -1
  62. package/dist/types/modes/theme/theme.d.ts +1 -1
  63. package/dist/types/modes/types.d.ts +3 -1
  64. package/dist/types/modes/utils/context-usage.d.ts +12 -2
  65. package/dist/types/plan-mode/plan-files.d.ts +10 -0
  66. package/dist/types/registry/agent-lifecycle.d.ts +21 -9
  67. package/dist/types/registry/agent-registry.d.ts +11 -4
  68. package/dist/types/sdk.d.ts +15 -1
  69. package/dist/types/secrets/index.d.ts +15 -2
  70. package/dist/types/secrets/obfuscator.d.ts +113 -15
  71. package/dist/types/session/acp-permission-gate.d.ts +19 -0
  72. package/dist/types/session/agent-session-events.d.ts +84 -0
  73. package/dist/types/session/agent-session-types.d.ts +314 -0
  74. package/dist/types/session/agent-session.d.ts +120 -750
  75. package/dist/types/session/async-job-delivery.d.ts +28 -0
  76. package/dist/types/session/bash-runner.d.ts +75 -0
  77. package/dist/types/session/blob-store.d.ts +11 -1
  78. package/dist/types/session/blob-store.test.d.ts +1 -0
  79. package/dist/types/session/checkpoint-entries.d.ts +28 -0
  80. package/dist/types/session/eval-runner.d.ts +49 -0
  81. package/dist/types/session/irc-bridge.d.ts +46 -0
  82. package/dist/types/session/messages.d.ts +22 -0
  83. package/dist/types/session/model-controls.d.ts +180 -0
  84. package/dist/types/session/prewalk.d.ts +46 -0
  85. package/dist/types/session/queued-messages.d.ts +22 -0
  86. package/dist/types/session/redis-session-storage.d.ts +1 -0
  87. package/dist/types/session/retry-fallback-chains.d.ts +74 -0
  88. package/dist/types/session/role-models.d.ts +15 -0
  89. package/dist/types/session/session-advisors.d.ts +228 -0
  90. package/dist/types/session/session-entries.d.ts +8 -0
  91. package/dist/types/session/session-handoff.d.ts +70 -0
  92. package/dist/types/session/session-history-format.d.ts +6 -1
  93. package/dist/types/session/session-loader.d.ts +6 -4
  94. package/dist/types/session/session-maintenance.d.ts +246 -0
  95. package/dist/types/session/session-manager.d.ts +41 -0
  96. package/dist/types/session/session-memory.d.ts +56 -0
  97. package/dist/types/session/session-provider-boundary.d.ts +62 -0
  98. package/dist/types/session/session-stats.d.ts +48 -0
  99. package/dist/types/session/session-tools.d.ts +143 -0
  100. package/dist/types/session/session-workspace.d.ts +32 -0
  101. package/dist/types/session/stream-guards.d.ts +44 -0
  102. package/dist/types/session/todo-tracker.d.ts +56 -0
  103. package/dist/types/session/ttsr-coordinator.d.ts +51 -0
  104. package/dist/types/session/turn-recovery.d.ts +225 -0
  105. package/dist/types/system-prompt.d.ts +2 -0
  106. package/dist/types/task/executor.d.ts +4 -1
  107. package/dist/types/task/output-manager.d.ts +3 -1
  108. package/dist/types/task/types.d.ts +14 -0
  109. package/dist/types/tools/approval.d.ts +1 -0
  110. package/dist/types/tools/browser/launch.d.ts +5 -0
  111. package/dist/types/tools/hub/jobs.d.ts +1 -1
  112. package/dist/types/tools/image-gen.d.ts +4 -4
  113. package/dist/types/tools/image-providers.d.ts +38 -0
  114. package/dist/types/tools/index.d.ts +8 -0
  115. package/dist/types/tools/path-utils.d.ts +8 -0
  116. package/dist/types/tools/report-tool-issue.d.ts +24 -9
  117. package/dist/types/tools/todo.d.ts +10 -4
  118. package/dist/types/tools/xdev.d.ts +5 -1
  119. package/dist/types/tts/streaming-player.d.ts +14 -0
  120. package/dist/types/tts/vocalizer.d.ts +5 -0
  121. package/dist/types/utils/jj.d.ts +29 -0
  122. package/dist/types/utils/lang-from-path.d.ts +1 -0
  123. package/dist/types/utils/title-generator.d.ts +30 -0
  124. package/dist/types/vibe/runtime.d.ts +36 -8
  125. package/dist/types/web/search/index.d.ts +1 -1
  126. package/dist/types/web/search/provider.d.ts +15 -5
  127. package/dist/types/web/search/providers/firecrawl.d.ts +9 -0
  128. package/dist/types/web/search/types.d.ts +95 -1
  129. package/package.json +13 -12
  130. package/scripts/generate-share-viewer.ts +4 -6
  131. package/scripts/legacy-pi-virtual-module.ts +1 -1
  132. package/src/advisor/__tests__/advisor.test.ts +643 -0
  133. package/src/advisor/runtime.ts +144 -43
  134. package/src/async/job-manager.ts +90 -2
  135. package/src/cli/args.ts +2 -0
  136. package/src/cli/auth-gateway-cli.ts +18 -3
  137. package/src/cli/bench-cli.ts +395 -29
  138. package/src/cli/flag-tables.ts +3 -0
  139. package/src/cli/gc-cli.ts +2 -2
  140. package/src/cli/grievances-cli.ts +2 -2
  141. package/src/cli/usage-cli.ts +11 -2
  142. package/src/collab/host.ts +3 -2
  143. package/src/commands/bench.ts +18 -4
  144. package/src/commands/launch.ts +4 -0
  145. package/src/config/__tests__/model-registry.test.ts +147 -0
  146. package/src/config/model-registry.ts +50 -2
  147. package/src/config/model-resolver.ts +0 -1
  148. package/src/config/models-config-schema.ts +15 -4
  149. package/src/config/provider-globals.ts +9 -9
  150. package/src/config/service-tier.ts +26 -1
  151. package/src/config/settings-schema.ts +250 -54
  152. package/src/config/settings.ts +81 -2
  153. package/src/dap/client.ts +37 -4
  154. package/src/edit/index.ts +49 -12
  155. package/src/eval/py/executor.ts +103 -33
  156. package/src/exec/bash-executor.ts +89 -6
  157. package/src/exec/direnv.ts +145 -0
  158. package/src/export/html/args.ts +20 -0
  159. package/src/export/html/index.ts +45 -47
  160. package/src/export/html/template.css +19 -1
  161. package/src/export/html/template.html +6 -0
  162. package/src/export/html/template.js +21 -0
  163. package/src/export/html/tool-views.generated.js +31 -31
  164. package/src/export/html/web-palette.ts +116 -132
  165. package/src/export/share.ts +249 -49
  166. package/src/extensibility/extensions/loader.ts +29 -1
  167. package/src/extensibility/extensions/runner.ts +6 -0
  168. package/src/extensibility/extensions/types.ts +33 -2
  169. package/src/extensibility/legacy-pi-coding-agent-shim.ts +1 -0
  170. package/src/extensibility/legacy-pi-tui-shim.ts +10 -0
  171. package/src/extensibility/plugins/legacy-pi-compat.ts +870 -311
  172. package/src/hindsight/state.ts +64 -6
  173. package/src/internal-urls/local-protocol.ts +2 -1
  174. package/src/internal-urls/memory-protocol.ts +2 -2
  175. package/src/internal-urls/registry-helpers.ts +40 -0
  176. package/src/internal-urls/skill-protocol.ts +2 -2
  177. package/src/internal-urls/ssh-protocol.ts +2 -1
  178. package/src/internal-urls/vault-protocol.ts +2 -1
  179. package/src/live/audio-worklet.txt +59 -0
  180. package/src/live/browser-runtime.txt +221 -0
  181. package/src/live/controller.ts +464 -0
  182. package/src/live/prompts/agent-final-message.md +3 -0
  183. package/src/live/prompts/live-instructions.md +23 -0
  184. package/src/live/protocol.test.ts +140 -0
  185. package/src/live/protocol.ts +233 -0
  186. package/src/live/transport.ts +490 -0
  187. package/src/live/visualizer.ts +234 -0
  188. package/src/lsp/client.ts +52 -9
  189. package/src/lsp/clients/biome-client.ts +3 -4
  190. package/src/lsp/index.ts +44 -11
  191. package/src/main.ts +9 -1
  192. package/src/mcp/config-writer.test.ts +43 -0
  193. package/src/mcp/config-writer.ts +109 -82
  194. package/src/mcp/manager.ts +39 -8
  195. package/src/mcp/oauth-discovery.ts +10 -2
  196. package/src/mcp/render.ts +94 -35
  197. package/src/mcp/smithery-auth.test.ts +29 -0
  198. package/src/mcp/smithery-auth.ts +3 -2
  199. package/src/mcp/tool-bridge.ts +107 -11
  200. package/src/mcp/types.ts +7 -0
  201. package/src/memories/index.ts +40 -20
  202. package/src/memory-backend/tool-names.ts +2 -0
  203. package/src/mnemopi/backend.ts +24 -7
  204. package/src/modes/acp/acp-agent.ts +56 -10
  205. package/src/modes/acp/acp-event-mapper.ts +8 -1
  206. package/src/modes/components/agent-hub.ts +27 -10
  207. package/src/modes/components/login-dialog.ts +14 -4
  208. package/src/modes/components/oauth-selector.ts +24 -7
  209. package/src/modes/components/plan-review-overlay.ts +350 -35
  210. package/src/modes/components/settings-defs.ts +28 -3
  211. package/src/modes/components/settings-selector.ts +178 -6
  212. package/src/modes/components/status-line/component.jj-cache.test.ts +229 -0
  213. package/src/modes/components/status-line/component.ts +123 -2
  214. package/src/modes/components/tool-execution.test.ts +63 -2
  215. package/src/modes/components/tool-execution.ts +11 -2
  216. package/src/modes/controllers/command-controller.ts +70 -22
  217. package/src/modes/controllers/event-controller.ts +111 -16
  218. package/src/modes/controllers/extension-ui-controller.test.ts +1 -0
  219. package/src/modes/controllers/extension-ui-controller.ts +20 -4
  220. package/src/modes/controllers/live-command-controller.ts +178 -0
  221. package/src/modes/controllers/mcp-command-controller.ts +80 -41
  222. package/src/modes/controllers/omfg-controller.ts +44 -40
  223. package/src/modes/controllers/selector-controller.ts +18 -10
  224. package/src/modes/controllers/session-focus-controller.ts +6 -1
  225. package/src/modes/interactive-mode.ts +160 -38
  226. package/src/modes/rpc/rpc-client.ts +94 -3
  227. package/src/modes/rpc/rpc-frame.ts +164 -4
  228. package/src/modes/rpc/rpc-messages.ts +127 -0
  229. package/src/modes/rpc/rpc-mode.ts +79 -7
  230. package/src/modes/rpc/rpc-types.ts +34 -2
  231. package/src/modes/runtime-init.ts +2 -0
  232. package/src/modes/setup-wizard/scenes/model.ts +5 -7
  233. package/src/modes/setup-wizard/scenes/providers.ts +3 -2
  234. package/src/modes/setup-wizard/scenes/sign-in.ts +8 -2
  235. package/src/modes/setup-wizard/scenes/theme.ts +13 -3
  236. package/src/modes/setup-wizard/scenes/types.ts +9 -1
  237. package/src/modes/setup-wizard/scenes/web-search.ts +23 -10
  238. package/src/modes/setup-wizard/wizard-overlay.ts +1 -1
  239. package/src/modes/theme/theme.ts +1 -1
  240. package/src/modes/types.ts +3 -1
  241. package/src/modes/utils/context-usage.ts +23 -7
  242. package/src/modes/utils/ui-helpers.ts +10 -5
  243. package/src/plan-mode/plan-files.ts +40 -0
  244. package/src/prompts/bench/cache-prefix-chunk.md +1 -0
  245. package/src/prompts/bench/cache-prefix.md +3 -0
  246. package/src/prompts/bench/cache-suffix.md +1 -0
  247. package/src/prompts/goals/guided-goal-system.md +24 -3
  248. package/src/prompts/system/custom-system-prompt.md +1 -1
  249. package/src/prompts/system/project-prompt.md +8 -1
  250. package/src/prompts/system/subagent-async-pending.md +6 -0
  251. package/src/prompts/system/system-prompt.md +1 -1
  252. package/src/prompts/system/workflow-notice.md +48 -40
  253. package/src/prompts/system/xdev-mount-notice.md +4 -0
  254. package/src/prompts/tools/task.md +12 -2
  255. package/src/prompts/tools/todo.md +3 -1
  256. package/src/registry/agent-lifecycle.ts +116 -46
  257. package/src/registry/agent-registry.ts +35 -8
  258. package/src/registry/persisted-agents.ts +26 -2
  259. package/src/sdk.ts +255 -139
  260. package/src/secrets/index.ts +127 -4
  261. package/src/secrets/obfuscator.ts +2328 -105
  262. package/src/session/acp-permission-gate.ts +165 -0
  263. package/src/session/agent-session-error-log.test.ts +1 -1
  264. package/src/session/agent-session-events.ts +66 -0
  265. package/src/session/agent-session-types.ts +334 -0
  266. package/src/session/agent-session.ts +1910 -12213
  267. package/src/session/artifacts.ts +6 -5
  268. package/src/session/async-job-delivery.ts +74 -0
  269. package/src/session/bash-runner.ts +326 -0
  270. package/src/session/blob-store.test.ts +56 -0
  271. package/src/session/blob-store.ts +18 -2
  272. package/src/session/checkpoint-entries.ts +81 -0
  273. package/src/session/eval-runner.ts +212 -0
  274. package/src/session/indexed-session-storage.ts +9 -2
  275. package/src/session/irc-bridge.ts +203 -0
  276. package/src/session/messages.ts +263 -1
  277. package/src/session/model-controls.ts +714 -0
  278. package/src/session/prewalk.ts +252 -0
  279. package/src/session/queued-messages.ts +93 -0
  280. package/src/session/redis-session-storage.ts +51 -11
  281. package/src/session/retry-fallback-chains.ts +455 -0
  282. package/src/session/role-models.ts +85 -0
  283. package/src/session/session-advisors.ts +1679 -0
  284. package/src/session/session-context.test.ts +224 -1
  285. package/src/session/session-context.ts +47 -5
  286. package/src/session/session-entries.ts +8 -0
  287. package/src/session/session-handoff.ts +308 -0
  288. package/src/session/session-history-format.ts +20 -9
  289. package/src/session/session-loader.ts +10 -51
  290. package/src/session/session-maintenance.ts +2983 -0
  291. package/src/session/session-manager.ts +390 -30
  292. package/src/session/session-memory.ts +222 -0
  293. package/src/session/session-provider-boundary.ts +307 -0
  294. package/src/session/session-stats.ts +293 -0
  295. package/src/session/session-tools.ts +943 -0
  296. package/src/session/session-workspace.ts +53 -0
  297. package/src/session/stream-guards.ts +417 -0
  298. package/src/session/todo-tracker.ts +380 -0
  299. package/src/session/ttsr-coordinator.ts +496 -0
  300. package/src/session/turn-recovery.ts +1629 -0
  301. package/src/slash-commands/builtin-registry.ts +92 -11
  302. package/src/slash-commands/helpers/usage-report.ts +25 -4
  303. package/src/system-prompt.ts +41 -17
  304. package/src/task/executor.ts +288 -70
  305. package/src/task/index.ts +148 -111
  306. package/src/task/output-manager.ts +25 -3
  307. package/src/task/persisted-revive.ts +4 -3
  308. package/src/task/structured-subagent.ts +4 -1
  309. package/src/task/types.ts +16 -0
  310. package/src/tools/approval.ts +55 -10
  311. package/src/tools/bash-interactive.ts +26 -0
  312. package/src/tools/bash-skill-urls.ts +28 -2
  313. package/src/tools/bash.ts +339 -123
  314. package/src/tools/browser/launch.ts +9 -1
  315. package/src/tools/browser/tab-supervisor.ts +8 -5
  316. package/src/tools/browser.ts +94 -47
  317. package/src/tools/hub/index.ts +1 -1
  318. package/src/tools/hub/jobs.ts +67 -8
  319. package/src/tools/image-gen.ts +20 -28
  320. package/src/tools/image-providers.ts +50 -0
  321. package/src/tools/index.ts +12 -0
  322. package/src/tools/path-utils.ts +49 -2
  323. package/src/tools/read.ts +156 -88
  324. package/src/tools/renderers.ts +7 -1
  325. package/src/tools/report-tool-issue.ts +79 -28
  326. package/src/tools/todo.ts +101 -11
  327. package/src/tools/vibe.ts +1 -2
  328. package/src/tools/write.ts +51 -1
  329. package/src/tools/xdev.ts +67 -3
  330. package/src/tts/streaming-player.ts +62 -4
  331. package/src/tts/vocalizer.ts +18 -1
  332. package/src/utils/jj.ts +125 -4
  333. package/src/utils/lang-from-path.ts +7 -0
  334. package/src/utils/title-generator.ts +137 -1
  335. package/src/vibe/runtime.ts +852 -72
  336. package/src/web/search/index.ts +3 -6
  337. package/src/web/search/provider.ts +31 -16
  338. package/src/web/search/providers/firecrawl.ts +46 -13
  339. package/src/web/search/providers/xai.ts +7 -1
  340. package/src/web/search/types.ts +8 -1
@@ -135,11 +135,9 @@ async function executeSearch(
135
135
  let candidates: SearchProviderCandidate[];
136
136
  if (explicitProvider && explicitProvider !== "auto") {
137
137
  candidates = [{ id: explicitProvider, explicit: true }];
138
- } else if (explicitProvider === "auto") {
139
- // Explicit `--provider auto` bypasses the configured preferred provider
140
- // for this invocation; exclusions still apply.
141
- candidates = resolveProviderCandidates("auto");
142
138
  } else {
139
+ // `--provider auto` and the default both walk the configured chain;
140
+ // exclusions still apply.
143
141
  candidates = resolveProviderCandidates();
144
142
  }
145
143
 
@@ -216,7 +214,6 @@ async function executeSearch(
216
214
  // summary error), masking the cancellation.
217
215
  throwIfAborted(signal);
218
216
  failures.push({ provider: provider ?? providerMeta, error });
219
- if (candidate.explicit) break;
220
217
  }
221
218
  }
222
219
 
@@ -351,6 +348,6 @@ export function getSearchTools(): CustomTool<any, any>[] {
351
348
  return [webSearchCustomTool];
352
349
  }
353
350
 
354
- export { getSearchProvider, setExcludedSearchProviders, setPreferredSearchProvider } from "./provider";
351
+ export { getSearchProvider, setExcludedSearchProviders, setSearchProviderOrder } from "./provider";
355
352
  export type { SearchProviderId as SearchProvider, SearchResponse } from "./types";
356
353
  export { isSearchProviderId, isSearchProviderPreference } from "./types";
@@ -189,12 +189,25 @@ export async function getSearchProvider(id: SearchProviderId): Promise<SearchPro
189
189
  return provider;
190
190
  }
191
191
 
192
- /** Preferred provider set via settings (default: auto) */
193
- let preferredProvId: SearchProviderId | "auto" = "auto";
192
+ /** Provider fallback order set via settings (default: built-in order). */
193
+ let orderedProvIds: readonly SearchProviderId[] = SEARCH_PROVIDER_ORDER;
194
+ /** Providers the user explicitly listed in `providers.webSearchOrder`. */
195
+ let explicitProvIds = new Set<SearchProviderId>();
194
196
 
195
- /** Set the preferred web search provider from settings */
196
- export function setPreferredSearchProvider(provider: SearchProviderId | "auto"): void {
197
- preferredProvId = provider;
197
+ /**
198
+ * Prioritize configured providers while retaining every unlisted provider in
199
+ * its built-in relative order. Invalid IDs are ignored defensively. Listed
200
+ * providers are treated as explicit selections: they resolve through
201
+ * `isExplicitlyAvailable`, so e.g. a hand-listed Perplexity may fall back to
202
+ * anonymous search exactly like the retired single-preference setting did.
203
+ */
204
+ export function setSearchProviderOrder(providers: readonly SearchProviderId[]): void {
205
+ const prioritized = new Set(providers.filter(id => SEARCH_PROVIDER_ORDER.includes(id)));
206
+ explicitProvIds = prioritized;
207
+ orderedProvIds =
208
+ prioritized.size === 0
209
+ ? SEARCH_PROVIDER_ORDER
210
+ : [...prioritized, ...SEARCH_PROVIDER_ORDER.filter(id => !prioritized.has(id))];
198
211
  }
199
212
 
200
213
  /** Providers excluded from web search resolution via settings. */
@@ -215,19 +228,21 @@ export interface SearchProviderCandidate {
215
228
  explicit: boolean;
216
229
  }
217
230
 
218
- /** Return provider candidates in fallback order without loading their modules. */
219
- export function resolveProviderCandidates(
220
- preferredProvider: SearchProviderId | "auto" = preferredProvId,
221
- ): SearchProviderCandidate[] {
231
+ /**
232
+ * Return provider candidates in fallback order without loading their modules.
233
+ * `forcedProvider` (a per-request `provider` argument) is terminal-first and
234
+ * bypasses exclusion; configured-order entries carry `explicit: true`.
235
+ */
236
+ export function resolveProviderCandidates(forcedProvider?: SearchProviderId): SearchProviderCandidate[] {
222
237
  const candidates: SearchProviderCandidate[] = [];
223
238
 
224
- if (preferredProvider !== "auto" && !isSearchProviderExcluded(preferredProvider)) {
225
- candidates.push({ id: preferredProvider, explicit: true });
239
+ if (forcedProvider !== undefined && !isSearchProviderExcluded(forcedProvider)) {
240
+ candidates.push({ id: forcedProvider, explicit: true });
226
241
  }
227
242
 
228
- for (const id of SEARCH_PROVIDER_ORDER) {
229
- if (id === preferredProvider || isSearchProviderExcluded(id)) continue;
230
- candidates.push({ id, explicit: false });
243
+ for (const id of orderedProvIds) {
244
+ if (id === forcedProvider || isSearchProviderExcluded(id)) continue;
245
+ candidates.push({ id, explicit: explicitProvIds.has(id) });
231
246
  }
232
247
 
233
248
  return candidates;
@@ -241,11 +256,11 @@ export function resolveProviderCandidates(
241
256
  */
242
257
  export async function resolveProviderChain(
243
258
  authStorage: AuthStorage,
244
- preferredProvider: SearchProviderId | "auto" = preferredProvId,
259
+ forcedProvider?: SearchProviderId,
245
260
  ): Promise<SearchProvider[]> {
246
261
  const providers: SearchProvider[] = [];
247
262
 
248
- for (const candidate of resolveProviderCandidates(preferredProvider)) {
263
+ for (const candidate of resolveProviderCandidates(forcedProvider)) {
249
264
  const provider = await getSearchProvider(candidate.id);
250
265
  const available = candidate.explicit
251
266
  ? await provider.isExplicitlyAvailable(authStorage)
@@ -4,7 +4,14 @@
4
4
  * Calls Firecrawl's search API and maps web results into the unified
5
5
  * SearchResponse shape used by the web search tool.
6
6
  */
7
- import { type ApiKey, type AuthStorage, type FetchImpl, getEnvApiKey, withAuth } from "@oh-my-pi/pi-ai";
7
+ import {
8
+ type AuthStorage,
9
+ type FetchImpl,
10
+ getEnvApiKey,
11
+ resolveApiKeyOnce,
12
+ seedApiKeyResolver,
13
+ withAuth,
14
+ } from "@oh-my-pi/pi-ai";
8
15
  import type { SearchResponse, SearchSource } from "../../../web/search/types";
9
16
  import { SearchProviderError } from "../../../web/search/types";
10
17
  import { clampNumResults } from "../utils";
@@ -66,13 +73,19 @@ function buildRequestBody(params: FirecrawlSearchParams): Record<string, unknown
66
73
  return body;
67
74
  }
68
75
 
69
- async function callFirecrawlSearch(apiKey: string, params: FirecrawlSearchParams): Promise<FirecrawlSearchResponse> {
76
+ async function callFirecrawlSearch(
77
+ apiKey: string | undefined,
78
+ params: FirecrawlSearchParams,
79
+ ): Promise<FirecrawlSearchResponse> {
80
+ const headers: Record<string, string> = {
81
+ "Content-Type": "application/json",
82
+ };
83
+ if (apiKey) {
84
+ headers.Authorization = `Bearer ${apiKey}`;
85
+ }
70
86
  const response = await (params.fetch ?? fetch)(FIRECRAWL_SEARCH_URL, {
71
87
  method: "POST",
72
- headers: {
73
- "Content-Type": "application/json",
74
- Authorization: `Bearer ${apiKey}`,
75
- },
88
+ headers,
76
89
  body: JSON.stringify(buildRequestBody(params)),
77
90
  signal: withHardTimeout(params.signal),
78
91
  });
@@ -100,16 +113,24 @@ export async function searchFirecrawl(params: SearchParams): Promise<SearchRespo
100
113
  signal: params.signal,
101
114
  fetch: params.fetch,
102
115
  };
103
- const keyOrResolver: ApiKey = params.authStorage.resolver("firecrawl", {
116
+ const keyResolver = params.authStorage.resolver("firecrawl", {
104
117
  sessionId: params.sessionId,
105
118
  });
106
119
  const numResults = clampNumResults(firecrawlParams.num_results, DEFAULT_NUM_RESULTS, MAX_NUM_RESULTS);
107
120
 
108
- const data = await withAuth(keyOrResolver, key => callFirecrawlSearch(key, firecrawlParams), {
109
- signal: params.signal,
110
- missingKeyMessage:
111
- 'Firecrawl credentials not found. Set FIRECRAWL_API_KEY or configure an API key for provider "firecrawl".',
112
- });
121
+ const resolvedKey = await resolveApiKeyOnce(keyResolver, params.signal);
122
+ let data: FirecrawlSearchResponse;
123
+ if (resolvedKey) {
124
+ // Reuse the preflight credential for the initial authenticated attempt.
125
+ const seededResolver = seedApiKeyResolver(resolvedKey, keyResolver);
126
+ data = await withAuth(seededResolver, key => callFirecrawlSearch(key, firecrawlParams), {
127
+ signal: params.signal,
128
+ });
129
+ } else {
130
+ // Keyless mode — omit Authorization header
131
+ data = await callFirecrawlSearch(undefined, firecrawlParams);
132
+ }
133
+
113
134
  const sources: SearchSource[] = [];
114
135
 
115
136
  for (const result of data.data?.web ?? []) {
@@ -125,7 +146,7 @@ export async function searchFirecrawl(params: SearchParams): Promise<SearchRespo
125
146
  provider: "firecrawl",
126
147
  sources: sources.slice(0, numResults),
127
148
  requestId: data.id ?? undefined,
128
- authMode: "api_key",
149
+ authMode: resolvedKey ? "api_key" : "keyless",
129
150
  };
130
151
  }
131
152
 
@@ -134,10 +155,22 @@ export class FirecrawlProvider extends SearchProvider {
134
155
  readonly id = "firecrawl";
135
156
  readonly label = "Firecrawl";
136
157
 
158
+ /**
159
+ * Auto-chain admission: requires a credential so an unconfigured Firecrawl
160
+ * doesn't displace other providers that the user has set up with API keys.
161
+ */
137
162
  isAvailable(authStorage: AuthStorage): boolean {
138
163
  return authStorage.hasAuth("firecrawl") || !!getEnvApiKey("firecrawl");
139
164
  }
140
165
 
166
+ /**
167
+ * Firecrawl supports keyless mode, so an explicit user selection
168
+ * (`webSearch: firecrawl`) works without any credential configured.
169
+ */
170
+ isExplicitlyAvailable(_authStorage: AuthStorage): boolean {
171
+ return true;
172
+ }
173
+
141
174
  search(params: SearchParams): Promise<SearchResponse> {
142
175
  return searchFirecrawl(params);
143
176
  }
@@ -9,7 +9,12 @@ import { SearchProvider } from "./base";
9
9
  import { classifyProviderHttpError, withHardTimeout } from "./utils";
10
10
 
11
11
  const XAI_DEFAULT_BASE_URL = "https://api.x.ai/v1";
12
- const XAI_WEB_SEARCH_MODEL = "grok-4.3";
12
+ const XAI_WEB_SEARCH_MODEL = "grok-4.5";
13
+ // grok-4.5 defaults reasoning.effort to "high"; xAI documents "low" for
14
+ // latency-sensitive agentic use and simple tool calling
15
+ // (docs.x.ai/developers/model-capabilities/text/reasoning). Web search is
16
+ // exactly that and runs under a 60s hard timeout, so pin the search calls low.
17
+ const XAI_WEB_SEARCH_REASONING_EFFORT = "low";
13
18
  const DEFAULT_NUM_RESULTS = 10;
14
19
  const MAX_NUM_RESULTS = 30;
15
20
 
@@ -60,6 +65,7 @@ function buildRequestBody(params: SearchParams): Record<string, unknown> {
60
65
  { role: "user", content: params.query },
61
66
  ],
62
67
  tools: [{ type: "web_search" }],
68
+ reasoning: { effort: XAI_WEB_SEARCH_REASONING_EFFORT },
63
69
  };
64
70
 
65
71
  if (params.maxOutputTokens !== undefined) {
@@ -37,7 +37,11 @@ export const SEARCH_PROVIDER_OPTIONS = [
37
37
  { value: "jina", label: "Jina", description: "Requires JINA_API_KEY" },
38
38
  { value: "kagi", label: "Kagi", description: "Requires KAGI_API_KEY and Kagi Search API beta access" },
39
39
  { value: "tavily", label: "Tavily", description: "Requires TAVILY_API_KEY" },
40
- { value: "firecrawl", label: "Firecrawl", description: "Requires FIRECRAWL_API_KEY" },
40
+ {
41
+ value: "firecrawl",
42
+ label: "Firecrawl",
43
+ description: "Uses Firecrawl API when FIRECRAWL_API_KEY is set; falls back to keyless mode",
44
+ },
41
45
  { value: "brave", label: "Brave", description: "Requires BRAVE_API_KEY" },
42
46
  {
43
47
  value: "kimi",
@@ -92,6 +96,9 @@ export const SEARCH_PROVIDER_ORDER: readonly SearchProviderId[] = SEARCH_PROVIDE
92
96
  option.value === "auto" ? [] : [option.value],
93
97
  );
94
98
 
99
+ /** Concrete provider choices (no `auto` sentinel) — for list-valued settings like order/exclude. */
100
+ export const SEARCH_PROVIDER_CHOICES = SEARCH_PROVIDER_OPTIONS.filter(option => option.value !== "auto");
101
+
95
102
  export const SEARCH_PROVIDER_PREFERENCES = ["auto", ...SEARCH_PROVIDER_ORDER] as const;
96
103
 
97
104
  /** Display labels, derived from {@link SEARCH_PROVIDER_OPTIONS}. */