lsd-pi 1.2.4 → 1.3.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 (357) hide show
  1. package/README.md +22 -16
  2. package/dist/app-paths.d.ts +4 -0
  3. package/dist/app-paths.js +4 -0
  4. package/dist/bedrock-auth.d.ts +4 -0
  5. package/dist/bedrock-auth.js +4 -0
  6. package/dist/bundled-extension-paths.d.ts +4 -0
  7. package/dist/bundled-extension-paths.js +4 -0
  8. package/dist/cli-theme.d.ts +2 -2
  9. package/dist/cli-theme.js +13 -14
  10. package/dist/cli.js +43 -3
  11. package/dist/codex-rotate-settings.d.ts +4 -0
  12. package/dist/codex-rotate-settings.js +4 -0
  13. package/dist/help-text.d.ts +4 -0
  14. package/dist/help-text.js +4 -0
  15. package/dist/lsd-brand.d.ts +4 -0
  16. package/dist/lsd-brand.js +4 -0
  17. package/dist/onboarding-llm.d.ts +5 -0
  18. package/dist/onboarding-llm.js +5 -0
  19. package/dist/project-sessions.d.ts +4 -0
  20. package/dist/project-sessions.js +4 -0
  21. package/dist/resources/agents/generic.md +1 -0
  22. package/dist/resources/agents/scout.md +8 -1
  23. package/dist/resources/agents/worker.md +1 -0
  24. package/dist/resources/extensions/ask-user-questions.js +70 -0
  25. package/dist/resources/extensions/bg-shell/bg-shell-tool.js +6 -16
  26. package/dist/resources/extensions/browser-tools/tools/codegen.js +5 -5
  27. package/dist/resources/extensions/browser-tools/tools/navigation.js +107 -178
  28. package/dist/resources/extensions/browser-tools/tools/network-mock.js +112 -167
  29. package/dist/resources/extensions/browser-tools/tools/pages.js +182 -234
  30. package/dist/resources/extensions/browser-tools/tools/refs.js +202 -461
  31. package/dist/resources/extensions/browser-tools/tools/session.js +176 -323
  32. package/dist/resources/extensions/browser-tools/tools/state-persistence.js +91 -154
  33. package/dist/resources/extensions/browser-tools/utils.js +1 -1
  34. package/dist/resources/extensions/mac-tools/index.js +19 -34
  35. package/dist/resources/extensions/memory/index.js +20 -2
  36. package/dist/resources/extensions/shared/interview-ui.js +103 -20
  37. package/dist/resources/extensions/slash-commands/extension-manifest.json +2 -2
  38. package/dist/resources/extensions/slash-commands/fast.js +73 -0
  39. package/dist/resources/extensions/slash-commands/index.js +2 -0
  40. package/dist/resources/extensions/slash-commands/plan.js +54 -28
  41. package/dist/resources/extensions/slash-commands/tools.js +40 -4
  42. package/dist/resources/extensions/subagent/agent-switcher-component.js +208 -0
  43. package/dist/resources/extensions/subagent/agent-switcher-model.js +107 -0
  44. package/dist/resources/extensions/subagent/background-job-manager.js +24 -6
  45. package/dist/resources/extensions/subagent/background-runner.js +4 -0
  46. package/dist/resources/extensions/subagent/in-process-runner.js +387 -0
  47. package/dist/resources/extensions/subagent/index.js +715 -370
  48. package/dist/resources/extensions/subagent/launch-helpers.js +19 -5
  49. package/dist/resources/extensions/subagent/legacy-runner.js +503 -0
  50. package/dist/resources/extensions/voice/index.js +96 -36
  51. package/dist/resources/extensions/voice/push-to-talk.js +26 -0
  52. package/dist/shared-paths.d.ts +4 -0
  53. package/dist/shared-paths.js +4 -0
  54. package/dist/shared-preferences.d.ts +4 -0
  55. package/dist/shared-preferences.js +4 -0
  56. package/dist/startup-model-validation.d.ts +1 -1
  57. package/dist/startup-timings.d.ts +4 -0
  58. package/dist/startup-timings.js +4 -0
  59. package/dist/update-check.d.ts +4 -0
  60. package/dist/update-check.js +4 -0
  61. package/dist/update-cmd.d.ts +4 -0
  62. package/dist/update-cmd.js +4 -0
  63. package/dist/welcome-screen.js +4 -4
  64. package/dist/wizard.d.ts +4 -0
  65. package/dist/wizard.js +4 -0
  66. package/package.json +1 -1
  67. package/packages/pi-agent-core/dist/agent.d.ts +28 -0
  68. package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
  69. package/packages/pi-agent-core/dist/agent.js +105 -5
  70. package/packages/pi-agent-core/dist/agent.js.map +1 -1
  71. package/packages/pi-agent-core/dist/types.d.ts +13 -2
  72. package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
  73. package/packages/pi-agent-core/dist/types.js.map +1 -1
  74. package/packages/pi-agent-core/src/agent.ts +142 -6
  75. package/packages/pi-agent-core/src/types.ts +12 -3
  76. package/packages/pi-ai/dist/adaptive/classifier.d.ts +29 -0
  77. package/packages/pi-ai/dist/adaptive/classifier.d.ts.map +1 -0
  78. package/packages/pi-ai/dist/adaptive/classifier.js +72 -0
  79. package/packages/pi-ai/dist/adaptive/classifier.js.map +1 -0
  80. package/packages/pi-ai/dist/adaptive/classifier.test.d.ts +2 -0
  81. package/packages/pi-ai/dist/adaptive/classifier.test.d.ts.map +1 -0
  82. package/packages/pi-ai/dist/adaptive/classifier.test.js +32 -0
  83. package/packages/pi-ai/dist/adaptive/classifier.test.js.map +1 -0
  84. package/packages/pi-ai/dist/index.d.ts +1 -0
  85. package/packages/pi-ai/dist/index.d.ts.map +1 -1
  86. package/packages/pi-ai/dist/index.js +1 -0
  87. package/packages/pi-ai/dist/index.js.map +1 -1
  88. package/packages/pi-ai/dist/providers/amazon-bedrock.js +0 -2
  89. package/packages/pi-ai/dist/providers/amazon-bedrock.js.map +1 -1
  90. package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
  91. package/packages/pi-ai/dist/providers/anthropic-shared.js +0 -2
  92. package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
  93. package/packages/pi-ai/dist/providers/azure-openai-responses.d.ts +1 -1
  94. package/packages/pi-ai/dist/providers/azure-openai-responses.d.ts.map +1 -1
  95. package/packages/pi-ai/dist/providers/azure-openai-responses.js.map +1 -1
  96. package/packages/pi-ai/dist/providers/google-gemini-cli.d.ts.map +1 -1
  97. package/packages/pi-ai/dist/providers/google-gemini-cli.js +0 -4
  98. package/packages/pi-ai/dist/providers/google-gemini-cli.js.map +1 -1
  99. package/packages/pi-ai/dist/providers/google-vertex.js +0 -5
  100. package/packages/pi-ai/dist/providers/google-vertex.js.map +1 -1
  101. package/packages/pi-ai/dist/providers/google.js +0 -5
  102. package/packages/pi-ai/dist/providers/google.js.map +1 -1
  103. package/packages/pi-ai/dist/providers/openai-codex-responses.d.ts +35 -2
  104. package/packages/pi-ai/dist/providers/openai-codex-responses.d.ts.map +1 -1
  105. package/packages/pi-ai/dist/providers/openai-codex-responses.js +32 -6
  106. package/packages/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
  107. package/packages/pi-ai/dist/providers/openai-codex-responses.test.js +127 -16
  108. package/packages/pi-ai/dist/providers/openai-codex-responses.test.js.map +1 -1
  109. package/packages/pi-ai/dist/providers/openai-completions.d.ts +1 -1
  110. package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
  111. package/packages/pi-ai/dist/providers/openai-completions.js +0 -1
  112. package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
  113. package/packages/pi-ai/dist/providers/openai-responses.d.ts +9 -2
  114. package/packages/pi-ai/dist/providers/openai-responses.d.ts.map +1 -1
  115. package/packages/pi-ai/dist/providers/openai-responses.fast-mode.test.d.ts +2 -0
  116. package/packages/pi-ai/dist/providers/openai-responses.fast-mode.test.d.ts.map +1 -0
  117. package/packages/pi-ai/dist/providers/openai-responses.fast-mode.test.js +67 -0
  118. package/packages/pi-ai/dist/providers/openai-responses.fast-mode.test.js.map +1 -0
  119. package/packages/pi-ai/dist/providers/openai-responses.js +21 -3
  120. package/packages/pi-ai/dist/providers/openai-responses.js.map +1 -1
  121. package/packages/pi-ai/dist/providers/openai-shared.d.ts +0 -1
  122. package/packages/pi-ai/dist/providers/openai-shared.d.ts.map +1 -1
  123. package/packages/pi-ai/dist/providers/openai-shared.js +0 -4
  124. package/packages/pi-ai/dist/providers/openai-shared.js.map +1 -1
  125. package/packages/pi-ai/dist/providers/simple-options.d.ts.map +1 -1
  126. package/packages/pi-ai/dist/providers/simple-options.js +2 -1
  127. package/packages/pi-ai/dist/providers/simple-options.js.map +1 -1
  128. package/packages/pi-ai/dist/types.d.ts +6 -2
  129. package/packages/pi-ai/dist/types.d.ts.map +1 -1
  130. package/packages/pi-ai/dist/types.js.map +1 -1
  131. package/packages/pi-ai/src/adaptive/classifier.test.ts +38 -0
  132. package/packages/pi-ai/src/adaptive/classifier.ts +107 -0
  133. package/packages/pi-ai/src/index.ts +1 -0
  134. package/packages/pi-ai/src/providers/amazon-bedrock.ts +0 -2
  135. package/packages/pi-ai/src/providers/anthropic-shared.ts +0 -2
  136. package/packages/pi-ai/src/providers/azure-openai-responses.ts +1 -1
  137. package/packages/pi-ai/src/providers/google-gemini-cli.ts +0 -4
  138. package/packages/pi-ai/src/providers/google-vertex.ts +0 -5
  139. package/packages/pi-ai/src/providers/google.ts +0 -5
  140. package/packages/pi-ai/src/providers/openai-codex-responses.test.ts +143 -20
  141. package/packages/pi-ai/src/providers/openai-codex-responses.ts +48 -7
  142. package/packages/pi-ai/src/providers/openai-completions.ts +1 -2
  143. package/packages/pi-ai/src/providers/openai-responses.fast-mode.test.ts +73 -0
  144. package/packages/pi-ai/src/providers/openai-responses.ts +27 -4
  145. package/packages/pi-ai/src/providers/openai-shared.ts +0 -3
  146. package/packages/pi-ai/src/providers/simple-options.ts +2 -1
  147. package/packages/pi-ai/src/types.ts +6 -2
  148. package/packages/pi-coding-agent/dist/cli/args.js +2 -2
  149. package/packages/pi-coding-agent/dist/cli/args.js.map +1 -1
  150. package/packages/pi-coding-agent/dist/core/agent-session.d.ts +7 -2
  151. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  152. package/packages/pi-coding-agent/dist/core/agent-session.js +53 -20
  153. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  154. package/packages/pi-coding-agent/dist/core/keybindings.d.ts +1 -1
  155. package/packages/pi-coding-agent/dist/core/keybindings.d.ts.map +1 -1
  156. package/packages/pi-coding-agent/dist/core/keybindings.js +2 -0
  157. package/packages/pi-coding-agent/dist/core/keybindings.js.map +1 -1
  158. package/packages/pi-coding-agent/dist/core/lsp/lsp.md +3 -1
  159. package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
  160. package/packages/pi-coding-agent/dist/core/sdk.js +36 -8
  161. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  162. package/packages/pi-coding-agent/dist/core/sdk.test.js +37 -0
  163. package/packages/pi-coding-agent/dist/core/sdk.test.js.map +1 -1
  164. package/packages/pi-coding-agent/dist/core/session-manager.d.ts +8 -0
  165. package/packages/pi-coding-agent/dist/core/session-manager.d.ts.map +1 -1
  166. package/packages/pi-coding-agent/dist/core/session-manager.js +4 -0
  167. package/packages/pi-coding-agent/dist/core/session-manager.js.map +1 -1
  168. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +18 -7
  169. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  170. package/packages/pi-coding-agent/dist/core/settings-manager.fast-mode.test.d.ts +2 -0
  171. package/packages/pi-coding-agent/dist/core/settings-manager.fast-mode.test.d.ts.map +1 -0
  172. package/packages/pi-coding-agent/dist/core/settings-manager.fast-mode.test.js +35 -0
  173. package/packages/pi-coding-agent/dist/core/settings-manager.fast-mode.test.js.map +1 -0
  174. package/packages/pi-coding-agent/dist/core/settings-manager.js +32 -2
  175. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  176. package/packages/pi-coding-agent/dist/core/skills.d.ts.map +1 -1
  177. package/packages/pi-coding-agent/dist/core/skills.js +4 -1
  178. package/packages/pi-coding-agent/dist/core/skills.js.map +1 -1
  179. package/packages/pi-coding-agent/dist/core/slash-commands.d.ts.map +1 -1
  180. package/packages/pi-coding-agent/dist/core/slash-commands.js +2 -1
  181. package/packages/pi-coding-agent/dist/core/slash-commands.js.map +1 -1
  182. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
  183. package/packages/pi-coding-agent/dist/core/system-prompt.js +12 -3
  184. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  185. package/packages/pi-coding-agent/dist/core/tool-priority.d.ts +4 -0
  186. package/packages/pi-coding-agent/dist/core/tool-priority.d.ts.map +1 -0
  187. package/packages/pi-coding-agent/dist/core/tool-priority.js +18 -0
  188. package/packages/pi-coding-agent/dist/core/tool-priority.js.map +1 -0
  189. package/packages/pi-coding-agent/dist/core/tool-priority.test.d.ts +2 -0
  190. package/packages/pi-coding-agent/dist/core/tool-priority.test.d.ts.map +1 -0
  191. package/packages/pi-coding-agent/dist/core/tool-priority.test.js +27 -0
  192. package/packages/pi-coding-agent/dist/core/tool-priority.test.js.map +1 -0
  193. package/packages/pi-coding-agent/dist/core/tools/grep.js +1 -1
  194. package/packages/pi-coding-agent/dist/core/tools/grep.js.map +1 -1
  195. package/packages/pi-coding-agent/dist/core/tools/index.d.ts +2 -0
  196. package/packages/pi-coding-agent/dist/core/tools/index.d.ts.map +1 -1
  197. package/packages/pi-coding-agent/dist/core/tools/index.js +2 -0
  198. package/packages/pi-coding-agent/dist/core/tools/index.js.map +1 -1
  199. package/packages/pi-coding-agent/dist/core/tools/pty.d.ts +10 -1
  200. package/packages/pi-coding-agent/dist/core/tools/pty.d.ts.map +1 -1
  201. package/packages/pi-coding-agent/dist/core/tools/pty.js +29 -3
  202. package/packages/pi-coding-agent/dist/core/tools/pty.js.map +1 -1
  203. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-summary-line.test.d.ts +2 -0
  204. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-summary-line.test.d.ts.map +1 -0
  205. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-summary-line.test.js +26 -0
  206. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-summary-line.test.js.map +1 -0
  207. package/packages/pi-coding-agent/dist/modes/interactive/components/btw-overlay.d.ts +45 -0
  208. package/packages/pi-coding-agent/dist/modes/interactive/components/btw-overlay.d.ts.map +1 -0
  209. package/packages/pi-coding-agent/dist/modes/interactive/components/btw-overlay.js +314 -0
  210. package/packages/pi-coding-agent/dist/modes/interactive/components/btw-overlay.js.map +1 -0
  211. package/packages/pi-coding-agent/dist/modes/interactive/components/btw-overlay.test.d.ts +2 -0
  212. package/packages/pi-coding-agent/dist/modes/interactive/components/btw-overlay.test.d.ts.map +1 -0
  213. package/packages/pi-coding-agent/dist/modes/interactive/components/btw-overlay.test.js +122 -0
  214. package/packages/pi-coding-agent/dist/modes/interactive/components/btw-overlay.test.js.map +1 -0
  215. package/packages/pi-coding-agent/dist/modes/interactive/components/embedded-terminal.js +1 -1
  216. package/packages/pi-coding-agent/dist/modes/interactive/components/embedded-terminal.js.map +1 -1
  217. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts +2 -0
  218. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
  219. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +19 -2
  220. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
  221. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts +11 -2
  222. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  223. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js +49 -6
  224. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js.map +1 -1
  225. package/packages/pi-coding-agent/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  226. package/packages/pi-coding-agent/dist/modes/interactive/components/thinking-selector.js +1 -2
  227. package/packages/pi-coding-agent/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  228. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +6 -0
  229. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  230. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +18 -4
  231. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  232. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-summary-line.d.ts +13 -0
  233. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-summary-line.d.ts.map +1 -0
  234. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-summary-line.js +49 -0
  235. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-summary-line.js.map +1 -0
  236. package/packages/pi-coding-agent/dist/modes/interactive/controllers/__tests__/chat-controller.collapsed-tool-summary.test.d.ts +2 -0
  237. package/packages/pi-coding-agent/dist/modes/interactive/controllers/__tests__/chat-controller.collapsed-tool-summary.test.d.ts.map +1 -0
  238. package/packages/pi-coding-agent/dist/modes/interactive/controllers/__tests__/chat-controller.collapsed-tool-summary.test.js +197 -0
  239. package/packages/pi-coding-agent/dist/modes/interactive/controllers/__tests__/chat-controller.collapsed-tool-summary.test.js.map +1 -0
  240. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  241. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +106 -0
  242. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  243. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
  244. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +7 -0
  245. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  246. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts +3 -0
  247. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
  248. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.js.map +1 -1
  249. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +4 -0
  250. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  251. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +88 -2
  252. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  253. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.d.ts.map +1 -1
  254. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js +41 -0
  255. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js.map +1 -1
  256. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts +2 -2
  257. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  258. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js +10 -6
  259. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js.map +1 -1
  260. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js +1 -1
  261. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js.map +1 -1
  262. package/packages/pi-coding-agent/dist/modes/print-mode.d.ts.map +1 -1
  263. package/packages/pi-coding-agent/dist/modes/print-mode.js +6 -0
  264. package/packages/pi-coding-agent/dist/modes/print-mode.js.map +1 -1
  265. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  266. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js +20 -0
  267. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js.map +1 -1
  268. package/packages/pi-coding-agent/dist/tests/path-display.test.js +15 -0
  269. package/packages/pi-coding-agent/dist/tests/path-display.test.js.map +1 -1
  270. package/packages/pi-coding-agent/package.json +1 -1
  271. package/packages/pi-coding-agent/src/cli/args.ts +2 -2
  272. package/packages/pi-coding-agent/src/core/agent-session.ts +58 -21
  273. package/packages/pi-coding-agent/src/core/keybindings.ts +4 -1
  274. package/packages/pi-coding-agent/src/core/lsp/lsp.md +3 -1
  275. package/packages/pi-coding-agent/src/core/sdk.test.ts +45 -0
  276. package/packages/pi-coding-agent/src/core/sdk.ts +39 -8
  277. package/packages/pi-coding-agent/src/core/session-manager.ts +12 -0
  278. package/packages/pi-coding-agent/src/core/settings-manager.fast-mode.test.ts +46 -0
  279. package/packages/pi-coding-agent/src/core/settings-manager.ts +50 -9
  280. package/packages/pi-coding-agent/src/core/skills.ts +4 -1
  281. package/packages/pi-coding-agent/src/core/slash-commands.ts +2 -1
  282. package/packages/pi-coding-agent/src/core/system-prompt.ts +14 -3
  283. package/packages/pi-coding-agent/src/core/tool-priority.test.ts +30 -0
  284. package/packages/pi-coding-agent/src/core/tool-priority.ts +17 -0
  285. package/packages/pi-coding-agent/src/core/tools/grep.ts +1 -1
  286. package/packages/pi-coding-agent/src/core/tools/index.ts +3 -0
  287. package/packages/pi-coding-agent/src/core/tools/pty.ts +45 -6
  288. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-summary-line.test.ts +31 -0
  289. package/packages/pi-coding-agent/src/modes/interactive/components/btw-overlay.test.ts +172 -0
  290. package/packages/pi-coding-agent/src/modes/interactive/components/btw-overlay.ts +402 -0
  291. package/packages/pi-coding-agent/src/modes/interactive/components/embedded-terminal.ts +1 -1
  292. package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +18 -2
  293. package/packages/pi-coding-agent/src/modes/interactive/components/settings-selector.ts +63 -9
  294. package/packages/pi-coding-agent/src/modes/interactive/components/thinking-selector.ts +1 -2
  295. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +1154 -1136
  296. package/packages/pi-coding-agent/src/modes/interactive/components/tool-summary-line.ts +64 -0
  297. package/packages/pi-coding-agent/src/modes/interactive/controllers/__tests__/chat-controller.collapsed-tool-summary.test.ts +228 -0
  298. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +494 -389
  299. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +7 -0
  300. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-state.ts +3 -0
  301. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +103 -3
  302. package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.ts +60 -1
  303. package/packages/pi-coding-agent/src/modes/interactive/theme/theme.ts +11 -7
  304. package/packages/pi-coding-agent/src/modes/interactive/theme/themes.ts +1 -1
  305. package/packages/pi-coding-agent/src/modes/print-mode.ts +6 -0
  306. package/packages/pi-coding-agent/src/modes/rpc/rpc-mode.ts +29 -0
  307. package/packages/pi-coding-agent/src/tests/path-display.test.ts +17 -0
  308. package/packages/pi-tui/dist/components/loader.d.ts +5 -2
  309. package/packages/pi-tui/dist/components/loader.d.ts.map +1 -1
  310. package/packages/pi-tui/dist/components/loader.js +33 -3
  311. package/packages/pi-tui/dist/components/loader.js.map +1 -1
  312. package/packages/pi-tui/src/components/loader.ts +31 -3
  313. package/packages/rpc-client/src/index.ts +1 -1
  314. package/packages/rpc-client/src/rpc-client.ts +29 -0
  315. package/packages/rpc-client/src/rpc-types.ts +1 -1
  316. package/pkg/dist/modes/interactive/theme/theme.d.ts +2 -2
  317. package/pkg/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  318. package/pkg/dist/modes/interactive/theme/theme.js +10 -6
  319. package/pkg/dist/modes/interactive/theme/theme.js.map +1 -1
  320. package/pkg/dist/modes/interactive/theme/themes.js +1 -1
  321. package/pkg/dist/modes/interactive/theme/themes.js.map +1 -1
  322. package/pkg/package.json +1 -1
  323. package/src/resources/agents/generic.md +1 -0
  324. package/src/resources/agents/scout.md +8 -1
  325. package/src/resources/agents/worker.md +1 -0
  326. package/src/resources/extensions/ask-user-questions.ts +88 -0
  327. package/src/resources/extensions/bg-shell/bg-shell-tool.ts +6 -16
  328. package/src/resources/extensions/browser-tools/tools/codegen.ts +5 -5
  329. package/src/resources/extensions/browser-tools/tools/navigation.ts +118 -196
  330. package/src/resources/extensions/browser-tools/tools/network-mock.ts +114 -205
  331. package/src/resources/extensions/browser-tools/tools/pages.ts +183 -237
  332. package/src/resources/extensions/browser-tools/tools/refs.ts +193 -507
  333. package/src/resources/extensions/browser-tools/tools/session.ts +182 -321
  334. package/src/resources/extensions/browser-tools/tools/state-persistence.ts +94 -172
  335. package/src/resources/extensions/browser-tools/utils.ts +1 -1
  336. package/src/resources/extensions/mac-tools/index.ts +19 -34
  337. package/src/resources/extensions/memory/index.ts +22 -2
  338. package/src/resources/extensions/shared/interview-ui.ts +108 -15
  339. package/src/resources/extensions/shared/tests/ask-user-freetext.test.ts +61 -0
  340. package/src/resources/extensions/shared/tests/custom-ui-fallbacks.test.ts +46 -0
  341. package/src/resources/extensions/slash-commands/extension-manifest.json +2 -2
  342. package/src/resources/extensions/slash-commands/fast.ts +89 -0
  343. package/src/resources/extensions/slash-commands/index.ts +2 -0
  344. package/src/resources/extensions/slash-commands/plan.ts +59 -30
  345. package/src/resources/extensions/slash-commands/tools.ts +43 -4
  346. package/src/resources/extensions/subagent/agent-switcher-component.ts +228 -0
  347. package/src/resources/extensions/subagent/agent-switcher-model.ts +160 -0
  348. package/src/resources/extensions/subagent/background-job-manager.ts +57 -6
  349. package/src/resources/extensions/subagent/background-runner.ts +8 -0
  350. package/src/resources/extensions/subagent/background-types.ts +4 -0
  351. package/src/resources/extensions/subagent/in-process-runner.ts +534 -0
  352. package/src/resources/extensions/subagent/index.ts +998 -493
  353. package/src/resources/extensions/subagent/launch-helpers.ts +15 -4
  354. package/src/resources/extensions/subagent/legacy-runner.ts +607 -0
  355. package/src/resources/extensions/voice/index.ts +308 -238
  356. package/src/resources/extensions/voice/push-to-talk.ts +42 -0
  357. package/src/resources/extensions/voice/tests/push-to-talk.test.ts +109 -0
@@ -447,7 +447,6 @@ function getGemini3ThinkingLevel(
447
447
  ): GoogleThinkingLevel {
448
448
  if (isGemini3ProModel(model)) {
449
449
  switch (effort) {
450
- case "minimal":
451
450
  case "low":
452
451
  return "LOW";
453
452
  case "medium":
@@ -456,8 +455,6 @@ function getGemini3ThinkingLevel(
456
455
  }
457
456
  }
458
457
  switch (effort) {
459
- case "minimal":
460
- return "MINIMAL";
461
458
  case "low":
462
459
  return "LOW";
463
460
  case "medium":
@@ -480,7 +477,6 @@ function getGoogleBudget(
480
477
 
481
478
  if (model.id.includes("2.5-pro")) {
482
479
  const budgets: Record<ClampedThinkingLevel, number> = {
483
- minimal: 128,
484
480
  low: 2048,
485
481
  medium: 8192,
486
482
  high: 32768,
@@ -490,7 +486,6 @@ function getGoogleBudget(
490
486
 
491
487
  if (model.id.includes("2.5-flash")) {
492
488
  const budgets: Record<ClampedThinkingLevel, number> = {
493
- minimal: 128,
494
489
  low: 2048,
495
490
  medium: 8192,
496
491
  high: 24576,
@@ -414,7 +414,6 @@ function getGemini3ThinkingLevel(
414
414
  ): GoogleThinkingLevel {
415
415
  if (isGemini3ProModel(model)) {
416
416
  switch (effort) {
417
- case "minimal":
418
417
  case "low":
419
418
  return "LOW";
420
419
  case "medium":
@@ -423,8 +422,6 @@ function getGemini3ThinkingLevel(
423
422
  }
424
423
  }
425
424
  switch (effort) {
426
- case "minimal":
427
- return "MINIMAL";
428
425
  case "low":
429
426
  return "LOW";
430
427
  case "medium":
@@ -447,7 +444,6 @@ function getGoogleBudget(
447
444
 
448
445
  if (model.id.includes("2.5-pro")) {
449
446
  const budgets: Record<ClampedThinkingLevel, number> = {
450
- minimal: 128,
451
447
  low: 2048,
452
448
  medium: 8192,
453
449
  high: 32768,
@@ -457,7 +453,6 @@ function getGoogleBudget(
457
453
 
458
454
  if (model.id.includes("2.5-flash")) {
459
455
  const budgets: Record<ClampedThinkingLevel, number> = {
460
- minimal: 128,
461
456
  low: 2048,
462
457
  medium: 8192,
463
458
  high: 24576,
@@ -1,7 +1,7 @@
1
1
  import assert from "node:assert/strict";
2
2
  import test from "node:test";
3
3
 
4
- import { streamSimpleOpenAICodexResponses } from "./openai-codex-responses.js";
4
+ import { __testing, streamSimpleOpenAICodexResponses } from "./openai-codex-responses.js";
5
5
 
6
6
  function makeJwt(accountId: string): string {
7
7
  const header = Buffer.from(JSON.stringify({ alg: "none", typ: "JWT" })).toString("base64url");
@@ -11,6 +11,24 @@ function makeJwt(accountId: string): string {
11
11
  return `${header}.${payload}.sig`;
12
12
  }
13
13
 
14
+ const codexModel = {
15
+ id: "gpt-5.4",
16
+ name: "gpt-5.4",
17
+ api: "openai-codex-responses",
18
+ provider: "openai-codex",
19
+ baseUrl: "https://chatgpt.com/backend-api",
20
+ reasoning: true,
21
+ input: ["text"],
22
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
23
+ contextWindow: 128000,
24
+ maxTokens: 16384,
25
+ } as any;
26
+
27
+ const simpleContext = {
28
+ systemPrompt: "",
29
+ messages: [{ role: "user", content: [{ type: "text", text: "hi" }] }],
30
+ } as any;
31
+
14
32
  test("codex provider does not internally retry ChatGPT usage-plan 429s", async () => {
15
33
  const originalFetch = globalThis.fetch;
16
34
  let fetchCalls = 0;
@@ -31,25 +49,10 @@ test("codex provider does not internally retry ChatGPT usage-plan 429s", async (
31
49
  }) as typeof fetch;
32
50
 
33
51
  try {
34
- const stream = streamSimpleOpenAICodexResponses(
35
- {
36
- id: "gpt-5.4",
37
- name: "gpt-5.4",
38
- api: "openai-codex-responses",
39
- provider: "openai-codex",
40
- baseUrl: "https://chatgpt.com/backend-api",
41
- reasoning: true,
42
- input: ["text"],
43
- cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
44
- contextWindow: 128000,
45
- maxTokens: 16384,
46
- } as any,
47
- {
48
- systemPrompt: "",
49
- messages: [{ role: "user", content: [{ type: "text", text: "hi" }] }],
50
- } as any,
51
- { apiKey: makeJwt("acct_123"), transport: "sse" } as any,
52
- );
52
+ const stream = streamSimpleOpenAICodexResponses(codexModel, simpleContext, {
53
+ apiKey: makeJwt("acct_123"),
54
+ transport: "sse",
55
+ } as any);
53
56
 
54
57
  let finalError = "";
55
58
  for await (const event of stream) {
@@ -64,3 +67,123 @@ test("codex provider does not internally retry ChatGPT usage-plan 429s", async (
64
67
  globalThis.fetch = originalFetch;
65
68
  }
66
69
  });
70
+
71
+ test("codex request body maps fast mode to service_tier=priority and omits when off", () => {
72
+ const onBody = __testing.buildRequestBody(codexModel, simpleContext, { fastMode: true } as any);
73
+ assert.equal(onBody.service_tier, "priority");
74
+
75
+ const offBody = __testing.buildRequestBody(codexModel, simpleContext, { fastMode: false } as any);
76
+ assert.equal("service_tier" in offBody, false);
77
+ });
78
+
79
+ test("codex SSE payload includes priority when fast mode is on and omits when off", async () => {
80
+ const originalFetch = globalThis.fetch;
81
+ const bodies: any[] = [];
82
+
83
+ globalThis.fetch = (async (_url, init) => {
84
+ const rawBody = typeof init?.body === "string" ? init.body : "{}";
85
+ bodies.push(JSON.parse(rawBody));
86
+ const sse = [
87
+ 'data: {"type":"response.completed","response":{"status":"completed","usage":{"input_tokens":0,"output_tokens":0,"total_tokens":0}}}',
88
+ "",
89
+ ].join("\n");
90
+ return new Response(sse, { status: 200, headers: { "content-type": "text/event-stream" } });
91
+ }) as typeof fetch;
92
+
93
+ try {
94
+ for (const fastMode of [true, false]) {
95
+ const stream = streamSimpleOpenAICodexResponses(codexModel, simpleContext, {
96
+ apiKey: makeJwt("acct_sse"),
97
+ transport: "sse",
98
+ fastMode,
99
+ } as any);
100
+ await stream.result();
101
+ }
102
+
103
+ assert.equal(bodies[0]?.service_tier, "priority");
104
+ assert.equal("service_tier" in bodies[1], false);
105
+ } finally {
106
+ globalThis.fetch = originalFetch;
107
+ }
108
+ });
109
+
110
+ test("codex websocket cache resets when fast mode changes on same session", async () => {
111
+ const originalWebSocket = (globalThis as any).WebSocket;
112
+ const originalFetch = globalThis.fetch;
113
+ const sentPayloads: any[] = [];
114
+ let constructorCalls = 0;
115
+
116
+ class MockWebSocket {
117
+ public readyState = 0;
118
+ private listeners = new Map<string, Set<(event: any) => void>>();
119
+
120
+ constructor(_url: string, _options?: unknown) {
121
+ constructorCalls++;
122
+ queueMicrotask(() => {
123
+ this.readyState = 1;
124
+ this.emit("open", {});
125
+ });
126
+ }
127
+
128
+ send(data: string): void {
129
+ sentPayloads.push(JSON.parse(data));
130
+ queueMicrotask(() => {
131
+ this.emit("message", {
132
+ data: JSON.stringify({
133
+ type: "response.completed",
134
+ response: {
135
+ status: "completed",
136
+ usage: { input_tokens: 0, output_tokens: 0, total_tokens: 0 },
137
+ },
138
+ }),
139
+ });
140
+ });
141
+ }
142
+
143
+ close(): void {
144
+ this.readyState = 3;
145
+ this.emit("close", { code: 1000, reason: "closed" });
146
+ }
147
+
148
+ addEventListener(type: string, listener: (event: any) => void): void {
149
+ if (!this.listeners.has(type)) this.listeners.set(type, new Set());
150
+ this.listeners.get(type)!.add(listener);
151
+ }
152
+
153
+ removeEventListener(type: string, listener: (event: any) => void): void {
154
+ this.listeners.get(type)?.delete(listener);
155
+ }
156
+
157
+ private emit(type: string, event: any): void {
158
+ for (const listener of this.listeners.get(type) ?? []) {
159
+ listener(event);
160
+ }
161
+ }
162
+ }
163
+
164
+ (globalThis as any).WebSocket = MockWebSocket as any;
165
+ globalThis.fetch = (async () => {
166
+ throw new Error("fetch should not be used in websocket transport test");
167
+ }) as any;
168
+
169
+ try {
170
+ __testing.clearWebSocketSessionCache();
171
+ for (const fastMode of [true, false]) {
172
+ const stream = streamSimpleOpenAICodexResponses(codexModel, simpleContext, {
173
+ apiKey: makeJwt("acct_ws"),
174
+ transport: "websocket",
175
+ sessionId: "session-fast-toggle",
176
+ fastMode,
177
+ } as any);
178
+ await stream.result();
179
+ }
180
+
181
+ assert.equal(constructorCalls, 2, "websocket should reconnect when service tier state changes");
182
+ assert.equal(sentPayloads[0]?.service_tier, "priority");
183
+ assert.equal("service_tier" in sentPayloads[1], false);
184
+ } finally {
185
+ __testing.clearWebSocketSessionCache();
186
+ (globalThis as any).WebSocket = originalWebSocket;
187
+ globalThis.fetch = originalFetch;
188
+ }
189
+ });
@@ -1,5 +1,5 @@
1
1
  import type * as NodeOs from "node:os";
2
- import type { Tool as OpenAITool, ResponseInput, ResponseStreamEvent } from "openai/resources/responses/responses.js";
2
+ import type { Tool as OpenAITool, ResponseCreateParamsStreaming, ResponseInput, ResponseStreamEvent } from "openai/resources/responses/responses.js";
3
3
 
4
4
  // NEVER convert to top-level runtime imports - breaks browser/Vite builds (web-ui)
5
5
  let _os: typeof NodeOs | null = null;
@@ -54,9 +54,10 @@ const CODEX_RESPONSE_STATUSES = new Set<CodexResponseStatus>([
54
54
  // ============================================================================
55
55
 
56
56
  export interface OpenAICodexResponsesOptions extends StreamOptions {
57
- reasoningEffort?: "none" | "minimal" | "low" | "medium" | "high" | "xhigh";
57
+ reasoningEffort?: "none" | "low" | "medium" | "high" | "xhigh";
58
58
  reasoningSummary?: "auto" | "concise" | "detailed" | "off" | "on" | null;
59
59
  textVerbosity?: "low" | "medium" | "high";
60
+ serviceTier?: ResponseCreateParamsStreaming["service_tier"];
60
61
  }
61
62
 
62
63
  type CodexResponseStatus = "completed" | "incomplete" | "failed" | "cancelled" | "queued" | "in_progress";
@@ -73,6 +74,7 @@ interface RequestBody {
73
74
  temperature?: number;
74
75
  reasoning?: { effort?: string; summary?: string };
75
76
  text?: { verbosity?: string };
77
+ service_tier?: ResponseCreateParamsStreaming["service_tier"];
76
78
  include?: string[];
77
79
  prompt_cache_key?: string;
78
80
  [key: string]: unknown;
@@ -294,6 +296,13 @@ export const streamSimpleOpenAICodexResponses: StreamFunction<"openai-codex-resp
294
296
  // Request Building
295
297
  // ============================================================================
296
298
 
299
+ function resolveCodexServiceTier(options?: OpenAICodexResponsesOptions): ResponseCreateParamsStreaming["service_tier"] | undefined {
300
+ if (options?.serviceTier !== undefined) {
301
+ return options.serviceTier;
302
+ }
303
+ return options?.fastMode ? "priority" : undefined;
304
+ }
305
+
297
306
  function buildRequestBody(
298
307
  model: Model<"openai-codex-responses">,
299
308
  context: Context,
@@ -320,6 +329,11 @@ function buildRequestBody(
320
329
  body.temperature = options.temperature;
321
330
  }
322
331
 
332
+ const resolvedServiceTier = resolveCodexServiceTier(options);
333
+ if (resolvedServiceTier !== undefined) {
334
+ body.service_tier = resolvedServiceTier;
335
+ }
336
+
323
337
  if (context.tools) {
324
338
  body.tools = convertResponsesTools(context.tools, { strict: null });
325
339
  }
@@ -336,8 +350,6 @@ function buildRequestBody(
336
350
 
337
351
  function clampReasoningEffort(modelId: string, effort: string): string {
338
352
  const id = modelId.includes("/") ? modelId.split("/").pop()! : modelId;
339
- if ((id.startsWith("gpt-5.2") || id.startsWith("gpt-5.3") || id.startsWith("gpt-5.4")) && effort === "minimal")
340
- return "low";
341
353
  if (id === "gpt-5.1" && effort === "xhigh") return "high";
342
354
  if (id === "gpt-5.1-codex-mini") return effort === "high" || effort === "xhigh" ? "high" : "medium";
343
355
  return effort;
@@ -476,6 +488,7 @@ interface CachedWebSocketConnection {
476
488
  socket: WebSocketLike;
477
489
  busy: boolean;
478
490
  idleTimer?: ReturnType<typeof setTimeout>;
491
+ serviceTier?: ResponseCreateParamsStreaming["service_tier"];
479
492
  }
480
493
 
481
494
  const websocketSessionCache = new Map<string, CachedWebSocketConnection>();
@@ -591,6 +604,7 @@ async function acquireWebSocket(
591
604
  url: string,
592
605
  headers: Headers,
593
606
  sessionId: string | undefined,
607
+ serviceTier: ResponseCreateParamsStreaming["service_tier"] | undefined,
594
608
  signal?: AbortSignal,
595
609
  ): Promise<{ socket: WebSocketLike; release: (options?: { keep?: boolean }) => void }> {
596
610
  if (!sessionId) {
@@ -613,7 +627,8 @@ async function acquireWebSocket(
613
627
  clearTimeout(cached.idleTimer);
614
628
  cached.idleTimer = undefined;
615
629
  }
616
- if (!cached.busy && isWebSocketReusable(cached.socket)) {
630
+
631
+ if (!cached.busy && isWebSocketReusable(cached.socket) && cached.serviceTier === serviceTier) {
617
632
  cached.busy = true;
618
633
  return {
619
634
  socket: cached.socket,
@@ -628,6 +643,10 @@ async function acquireWebSocket(
628
643
  },
629
644
  };
630
645
  }
646
+ if (!cached.busy && isWebSocketReusable(cached.socket) && cached.serviceTier !== serviceTier) {
647
+ closeWebSocketSilently(cached.socket, 1000, "service_tier_changed");
648
+ websocketSessionCache.delete(sessionId);
649
+ }
631
650
  if (cached.busy) {
632
651
  const socket = await connectWebSocket(url, headers, signal);
633
652
  return {
@@ -644,7 +663,7 @@ async function acquireWebSocket(
644
663
  }
645
664
 
646
665
  const socket = await connectWebSocket(url, headers, signal);
647
- const entry: CachedWebSocketConnection = { socket, busy: true };
666
+ const entry: CachedWebSocketConnection = { socket, busy: true, serviceTier };
648
667
 
649
668
  // Evict the oldest entry if the cache is at capacity (LRU eviction).
650
669
  if (websocketSessionCache.size >= MAX_WEBSOCKET_CACHE_SIZE) {
@@ -832,7 +851,13 @@ async function processWebSocketStream(
832
851
  onStart: () => void,
833
852
  options?: OpenAICodexResponsesOptions,
834
853
  ): Promise<void> {
835
- const { socket, release } = await acquireWebSocket(url, headers, options?.sessionId, options?.signal);
854
+ const { socket, release } = await acquireWebSocket(
855
+ url,
856
+ headers,
857
+ options?.sessionId,
858
+ body.service_tier,
859
+ options?.signal,
860
+ );
836
861
  let keepConnection = true;
837
862
  try {
838
863
  socket.send(JSON.stringify({ type: "response.create", ...body }));
@@ -924,3 +949,19 @@ function buildHeaders(
924
949
 
925
950
  return headers;
926
951
  }
952
+
953
+ function clearWebSocketSessionCache(): void {
954
+ for (const [, entry] of websocketSessionCache) {
955
+ if (entry.idleTimer) {
956
+ clearTimeout(entry.idleTimer);
957
+ }
958
+ closeWebSocketSilently(entry.socket);
959
+ }
960
+ websocketSessionCache.clear();
961
+ }
962
+
963
+ export const __testing = {
964
+ buildRequestBody,
965
+ resolveCodexServiceTier,
966
+ clearWebSocketSessionCache,
967
+ };
@@ -62,7 +62,7 @@ function hasToolHistory(messages: Message[]): boolean {
62
62
 
63
63
  export interface OpenAICompletionsOptions extends StreamOptions {
64
64
  toolChoice?: "auto" | "none" | "required" | { type: "function"; function: { name: string } };
65
- reasoningEffort?: "minimal" | "low" | "medium" | "high" | "xhigh";
65
+ reasoningEffort?: "low" | "medium" | "high" | "xhigh";
66
66
  }
67
67
 
68
68
  export const streamOpenAICompletions: StreamFunction<"openai-completions", OpenAICompletionsOptions> = (
@@ -718,7 +718,6 @@ function detectCompat(model: Model<"openai-completions">): Required<OpenAIComple
718
718
  const reasoningEffortMap =
719
719
  isGroq && model.id === "qwen/qwen3-32b"
720
720
  ? {
721
- minimal: "default",
722
721
  low: "default",
723
722
  medium: "default",
724
723
  high: "default",
@@ -0,0 +1,73 @@
1
+ import assert from "node:assert/strict";
2
+ import test from "node:test";
3
+
4
+ import { __testing } from "./openai-responses.js";
5
+
6
+ test("openai-responses fast mode maps to service_tier=priority for supported models", () => {
7
+ const model = {
8
+ id: "gpt-5.4",
9
+ name: "gpt-5.4",
10
+ api: "openai-responses",
11
+ provider: "openai",
12
+ baseUrl: "https://api.openai.com/v1",
13
+ reasoning: true,
14
+ input: ["text"],
15
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
16
+ contextWindow: 200000,
17
+ maxTokens: 32768,
18
+ capabilities: { supportsServiceTier: true },
19
+ } as any;
20
+ const context = {
21
+ systemPrompt: "",
22
+ messages: [{ role: "user", content: [{ type: "text", text: "hi" }] }],
23
+ } as any;
24
+
25
+ const params = __testing.buildParams(model, context, { fastMode: true });
26
+ assert.equal(params.service_tier, "priority");
27
+ });
28
+
29
+ test("openai-responses fast mode off omits service_tier", () => {
30
+ const model = {
31
+ id: "gpt-5.4",
32
+ name: "gpt-5.4",
33
+ api: "openai-responses",
34
+ provider: "openai",
35
+ baseUrl: "https://api.openai.com/v1",
36
+ reasoning: true,
37
+ input: ["text"],
38
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
39
+ contextWindow: 200000,
40
+ maxTokens: 32768,
41
+ capabilities: { supportsServiceTier: true },
42
+ } as any;
43
+ const context = {
44
+ systemPrompt: "",
45
+ messages: [{ role: "user", content: [{ type: "text", text: "hi" }] }],
46
+ } as any;
47
+
48
+ const params = __testing.buildParams(model, context, { fastMode: false });
49
+ assert.equal("service_tier" in params, false);
50
+ });
51
+
52
+ test("openai-responses fast mode is scoped to provider=openai", () => {
53
+ const model = {
54
+ id: "gpt-5.4",
55
+ name: "gpt-5.4",
56
+ api: "openai-responses",
57
+ provider: "openrouter",
58
+ baseUrl: "https://openrouter.ai/api/v1",
59
+ reasoning: true,
60
+ input: ["text"],
61
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
62
+ contextWindow: 200000,
63
+ maxTokens: 32768,
64
+ capabilities: { supportsServiceTier: true },
65
+ } as any;
66
+ const context = {
67
+ systemPrompt: "",
68
+ messages: [{ role: "user", content: [{ type: "text", text: "hi" }] }],
69
+ } as any;
70
+
71
+ const params = __testing.buildParams(model, context, { fastMode: true });
72
+ assert.equal("service_tier" in params, false);
73
+ });
@@ -56,7 +56,7 @@ function getPromptCacheRetention(baseUrl: string, cacheRetention: CacheRetention
56
56
 
57
57
  // OpenAI Responses-specific options
58
58
  export interface OpenAIResponsesOptions extends StreamOptions {
59
- reasoningEffort?: "minimal" | "low" | "medium" | "high" | "xhigh";
59
+ reasoningEffort?: "low" | "medium" | "high" | "xhigh";
60
60
  reasoningSummary?: "auto" | "detailed" | "concise" | null;
61
61
  serviceTier?: ResponseCreateParamsStreaming["service_tier"];
62
62
  }
@@ -86,6 +86,7 @@ export const streamOpenAIResponses: StreamFunction<"openai-responses", OpenAIRes
86
86
  if (nextParams !== undefined) {
87
87
  params = nextParams as ResponseCreateParamsStreaming;
88
88
  }
89
+ const resolvedServiceTier = resolveOpenAIServiceTier(model, options);
89
90
  const openaiStream = await client.responses.create(
90
91
  params,
91
92
  options?.signal ? { signal: options.signal } : undefined,
@@ -93,7 +94,7 @@ export const streamOpenAIResponses: StreamFunction<"openai-responses", OpenAIRes
93
94
  stream.push({ type: "start", partial: output });
94
95
 
95
96
  await processResponsesStream(openaiStream, output, stream, model, {
96
- serviceTier: options?.serviceTier,
97
+ serviceTier: resolvedServiceTier,
97
98
  applyServiceTierPricing,
98
99
  });
99
100
 
@@ -127,8 +128,25 @@ export const streamSimpleOpenAIResponses: StreamFunction<"openai-responses", Sim
127
128
  } satisfies OpenAIResponsesOptions);
128
129
  };
129
130
 
131
+ function resolveOpenAIServiceTier(
132
+ model: Model<"openai-responses">,
133
+ options?: OpenAIResponsesOptions,
134
+ ): ResponseCreateParamsStreaming["service_tier"] | undefined {
135
+ if (options?.serviceTier !== undefined) {
136
+ return options.serviceTier;
137
+ }
138
+ if (options?.fastMode !== true) {
139
+ return undefined;
140
+ }
141
+ if (model.provider !== "openai") {
142
+ return undefined;
143
+ }
144
+ return model.capabilities?.supportsServiceTier ? "priority" : undefined;
145
+ }
146
+
130
147
  function buildParams(model: Model<"openai-responses">, context: Context, options?: OpenAIResponsesOptions) {
131
148
  const messages = convertResponsesMessages(model, context, OPENAI_TOOL_CALL_PROVIDERS);
149
+ const resolvedServiceTier = resolveOpenAIServiceTier(model, options);
132
150
 
133
151
  const cacheRetention = resolveCacheRetention(options?.cacheRetention);
134
152
  const params: ResponseCreateParamsStreaming = {
@@ -148,8 +166,8 @@ function buildParams(model: Model<"openai-responses">, context: Context, options
148
166
  params.temperature = options?.temperature;
149
167
  }
150
168
 
151
- if (options?.serviceTier !== undefined) {
152
- params.service_tier = options.serviceTier;
169
+ if (resolvedServiceTier !== undefined) {
170
+ params.service_tier = resolvedServiceTier;
153
171
  }
154
172
 
155
173
  if (context.tools) {
@@ -204,3 +222,8 @@ function applyServiceTierPricing(usage: Usage, serviceTier: ResponseCreateParams
204
222
  usage.cost.cacheWrite *= multiplier;
205
223
  usage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;
206
224
  }
225
+
226
+ export const __testing = {
227
+ buildParams,
228
+ resolveOpenAIServiceTier,
229
+ };
@@ -182,12 +182,9 @@ export function handleStreamError(
182
182
 
183
183
  /**
184
184
  * Clamp reasoning effort for models that don't support all levels.
185
- * gpt-5.x models don't support "minimal" -- map to "low".
186
185
  *
187
186
  * Used by both openai-responses.ts and azure-openai-responses.ts.
188
187
  */
189
188
  export function clampReasoningForModel(modelName: string, effort: string): string {
190
- const name = modelName.includes("/") ? modelName.split("/").pop()! : modelName;
191
- if (name.startsWith("gpt-5") && effort === "minimal") return "low";
192
189
  return effort;
193
190
  }
@@ -6,6 +6,8 @@ export function buildBaseOptions(model: Model<Api>, options?: SimpleStreamOption
6
6
  maxTokens: options?.maxTokens || Math.min(model.maxTokens, 32000),
7
7
  signal: options?.signal,
8
8
  apiKey: apiKey || options?.apiKey,
9
+ transport: options?.transport,
10
+ fastMode: options?.fastMode,
9
11
  cacheRetention: options?.cacheRetention,
10
12
  sessionId: options?.sessionId,
11
13
  headers: options?.headers,
@@ -28,7 +30,6 @@ export function adjustMaxTokensForThinking(
28
30
  customBudgets?: ThinkingBudgets,
29
31
  ): { maxTokens: number; thinkingBudget: number } {
30
32
  const defaultBudgets: ThinkingBudgets = {
31
- minimal: 1024,
32
33
  low: 2048,
33
34
  medium: 8192,
34
35
  high: 16384,
@@ -46,11 +46,10 @@ export type KnownProvider =
46
46
  | "ollama-cloud";
47
47
  export type Provider = KnownProvider | string;
48
48
 
49
- export type ThinkingLevel = "minimal" | "low" | "medium" | "high" | "xhigh" | "adaptive";
49
+ export type ThinkingLevel = "low" | "medium" | "high" | "xhigh" | "adaptive";
50
50
 
51
51
  /** Token budgets for each thinking level (token-based providers only) */
52
52
  export interface ThinkingBudgets {
53
- minimal?: number;
54
53
  low?: number;
55
54
  medium?: number;
56
55
  high?: number;
@@ -66,6 +65,11 @@ export interface StreamOptions {
66
65
  maxTokens?: number;
67
66
  signal?: AbortSignal;
68
67
  apiKey?: string;
68
+ /**
69
+ * Enable fast mode for providers/models that support OpenAI service tiers.
70
+ * For OpenAI/Codex Responses, this maps to service_tier="priority".
71
+ */
72
+ fastMode?: boolean;
69
73
  /**
70
74
  * Preferred transport for providers that support multiple transports.
71
75
  * Providers that do not support this option ignore it.
@@ -4,7 +4,7 @@
4
4
  import chalk from "chalk";
5
5
  import { APP_NAME, CONFIG_DIR_NAME, ENV_AGENT_DIR } from "../config.js";
6
6
  import { allTools } from "../core/tools/index.js";
7
- const VALID_THINKING_LEVELS = ["off", "minimal", "low", "medium", "high", "xhigh", "adaptive"];
7
+ const VALID_THINKING_LEVELS = ["off", "low", "medium", "high", "xhigh", "adaptive"];
8
8
  export function isValidThinkingLevel(level) {
9
9
  return VALID_THINKING_LEVELS.includes(level);
10
10
  }
@@ -210,7 +210,7 @@ ${chalk.bold("Options:")}
210
210
  --no-tools Disable all built-in tools
211
211
  --tools <tools> Comma-separated list of tools to enable (default: read,bash,edit,write)
212
212
  Available: read, bash, edit, write, lsp, grep, find, ls
213
- --thinking <level> Set thinking level: off, minimal, low, medium, high, xhigh
213
+ --thinking <level> Set thinking level: off, low, medium, high, xhigh
214
214
  --extension, -e <path> Load an extension file (can be used multiple times)
215
215
  --no-extensions, -ne Disable extension discovery (explicit -e paths still work)
216
216
  --skill <path> Load a skill file or directory (can be used multiple times)