@oh-my-pi/pi-ai 18.1.4 → 18.1.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 (288) hide show
  1. package/CHANGELOG.md +52 -9
  2. package/README.md +8 -33
  3. package/dist/types/dialect/thinking.d.ts +9 -0
  4. package/dist/types/dialect/types.d.ts +10 -0
  5. package/dist/types/error/flags.d.ts +0 -7
  6. package/dist/types/error/retryable.d.ts +3 -10
  7. package/dist/types/index.d.ts +0 -1
  8. package/dist/types/providers/amazon-bedrock.d.ts +7 -0
  9. package/dist/types/providers/anthropic.d.ts +1 -8
  10. package/dist/types/providers/cursor.d.ts +3 -1
  11. package/dist/types/providers/inference-headers.d.ts +24 -0
  12. package/dist/types/providers/openai-codex/request-transformer.d.ts +7 -10
  13. package/dist/types/providers/openai-codex-responses.d.ts +3 -7
  14. package/dist/types/providers/openai-shared.d.ts +1 -1
  15. package/dist/types/registry/amazon-bedrock.d.ts +3 -10
  16. package/dist/types/registry/bedrock-mantle.d.ts +3 -22
  17. package/dist/types/registry/build.d.ts +11 -0
  18. package/dist/types/registry/cloudflare-ai-gateway.d.ts +3 -13
  19. package/dist/types/registry/engine/api-key.d.ts +8 -0
  20. package/dist/types/registry/engine/common.d.ts +55 -0
  21. package/dist/types/registry/engine/device-code.d.ts +9 -0
  22. package/dist/types/registry/engine/oauth-code.d.ts +27 -0
  23. package/dist/types/registry/engine/refresh.d.ts +11 -0
  24. package/dist/types/registry/hooks/api-key.d.ts +8 -0
  25. package/dist/types/registry/hooks/custom.d.ts +7 -0
  26. package/dist/types/registry/hooks/device-code.d.ts +8 -0
  27. package/dist/types/registry/hooks/env.d.ts +2 -0
  28. package/dist/types/registry/hooks/index.d.ts +3 -0
  29. package/dist/types/registry/hooks/oauth-code.d.ts +8 -0
  30. package/dist/types/registry/hooks/types.d.ts +44 -0
  31. package/dist/types/registry/oauth/alibaba-coding-plan.d.ts +2 -0
  32. package/dist/types/registry/{alibaba-token-plan.d.ts → oauth/alibaba-token-plan.d.ts} +1 -6
  33. package/dist/types/registry/oauth/anthropic.d.ts +24 -16
  34. package/dist/types/registry/oauth/cloudflare-ai-gateway.d.ts +3 -0
  35. package/dist/types/registry/oauth/coreweave.d.ts +1 -0
  36. package/dist/types/registry/oauth/cursor.d.ts +3 -1
  37. package/dist/types/registry/oauth/github-copilot.d.ts +5 -2
  38. package/dist/types/registry/oauth/gitlab-duo.d.ts +3 -3
  39. package/dist/types/registry/oauth/google-antigravity.d.ts +3 -7
  40. package/dist/types/registry/oauth/google-gemini-cli.d.ts +3 -6
  41. package/dist/types/registry/oauth/google-oauth-shared.d.ts +0 -24
  42. package/dist/types/registry/oauth/kilo.d.ts +2 -0
  43. package/dist/types/registry/oauth/kimi.d.ts +0 -9
  44. package/dist/types/registry/oauth/openai-codex.d.ts +6 -13
  45. package/dist/types/registry/oauth/xai-oauth.d.ts +5 -10
  46. package/dist/types/registry/oauth/xiaomi.d.ts +2 -10
  47. package/dist/types/registry/oauth/zai.d.ts +3 -15
  48. package/dist/types/registry/registry.d.ts +9 -386
  49. package/dist/types/registry/types.d.ts +12 -9
  50. package/dist/types/types.d.ts +9 -0
  51. package/dist/types/usage.d.ts +12 -0
  52. package/dist/types/utils/http-inspector.d.ts +3 -4
  53. package/dist/types/utils/leaked-thinking-stream.d.ts +6 -0
  54. package/dist/types/utils/thinking-loop.d.ts +1 -1
  55. package/dist/types/utils.d.ts +7 -0
  56. package/package.json +5 -5
  57. package/src/auth-gateway/server.ts +7 -2
  58. package/src/auth-storage.ts +315 -78
  59. package/src/dialect/owned-stream.ts +3 -0
  60. package/src/dialect/thinking.ts +44 -7
  61. package/src/dialect/types.ts +8 -0
  62. package/src/error/flags.ts +0 -45
  63. package/src/error/rate-limit.ts +9 -1
  64. package/src/error/retryable.ts +3 -12
  65. package/src/index.ts +0 -1
  66. package/src/providers/amazon-bedrock.ts +72 -5
  67. package/src/providers/anthropic.ts +96 -49
  68. package/src/providers/cursor-external-tool-handoff.md +1 -0
  69. package/src/providers/cursor.ts +32 -1
  70. package/src/providers/github-copilot-headers.ts +7 -2
  71. package/src/providers/google-shared.ts +11 -9
  72. package/src/providers/google.ts +6 -0
  73. package/src/providers/inference-headers.ts +79 -0
  74. package/src/providers/openai-codex/request-transformer.ts +9 -15
  75. package/src/providers/openai-codex-responses.ts +6 -12
  76. package/src/providers/openai-completions.ts +5 -6
  77. package/src/providers/openai-responses.ts +35 -42
  78. package/src/providers/openai-shared.ts +8 -13
  79. package/src/providers/pi-native-server.ts +1 -0
  80. package/src/registry/amazon-bedrock.ts +5 -8
  81. package/src/registry/bedrock-mantle.ts +5 -8
  82. package/src/registry/build.ts +73 -0
  83. package/src/registry/cloudflare-ai-gateway.ts +4 -44
  84. package/src/registry/engine/api-key.ts +109 -0
  85. package/src/registry/engine/common.ts +306 -0
  86. package/src/registry/engine/device-code.ts +131 -0
  87. package/src/registry/engine/oauth-code.ts +227 -0
  88. package/src/registry/engine/refresh.ts +105 -0
  89. package/src/registry/hooks/api-key.ts +19 -0
  90. package/src/registry/hooks/custom.ts +15 -0
  91. package/src/registry/hooks/device-code.ts +13 -0
  92. package/src/registry/hooks/env.ts +42 -0
  93. package/src/registry/hooks/index.ts +21 -0
  94. package/src/registry/hooks/oauth-code.ts +18 -0
  95. package/src/registry/hooks/types.ts +53 -0
  96. package/src/registry/{alibaba-coding-plan.ts → oauth/alibaba-coding-plan.ts} +3 -11
  97. package/src/registry/{alibaba-token-plan.ts → oauth/alibaba-token-plan.ts} +3 -10
  98. package/src/registry/oauth/anthropic.ts +39 -272
  99. package/src/registry/oauth/cloudflare-ai-gateway.ts +39 -0
  100. package/src/registry/oauth/coreweave.ts +16 -0
  101. package/src/registry/oauth/cursor.ts +12 -1
  102. package/src/registry/oauth/github-copilot.ts +37 -21
  103. package/src/registry/oauth/gitlab-duo.ts +6 -219
  104. package/src/registry/oauth/google-antigravity.ts +32 -66
  105. package/src/registry/oauth/google-gemini-cli.ts +31 -65
  106. package/src/registry/oauth/google-oauth-shared.ts +0 -143
  107. package/src/registry/oauth/index.ts +28 -39
  108. package/src/registry/{kilo.ts → oauth/kilo.ts} +2 -9
  109. package/src/registry/oauth/kimi.ts +1 -246
  110. package/src/registry/oauth/openai-codex.ts +28 -109
  111. package/src/registry/oauth/xai-oauth.ts +7 -327
  112. package/src/registry/oauth/xiaomi.ts +9 -60
  113. package/src/registry/oauth/zai.ts +6 -100
  114. package/src/registry/registry.ts +32 -173
  115. package/src/registry/types.ts +12 -9
  116. package/src/stream.ts +52 -8
  117. package/src/types.ts +9 -0
  118. package/src/usage/github-copilot.ts +2 -2
  119. package/src/usage/google-antigravity.ts +279 -44
  120. package/src/usage.ts +9 -0
  121. package/src/utils/empty-completion-retry.ts +0 -1
  122. package/src/utils/http-inspector.ts +3 -8
  123. package/src/utils/leaked-thinking-stream.ts +37 -7
  124. package/src/utils/stream-markup-healing.ts +1 -0
  125. package/src/utils/thinking-loop.ts +1 -1
  126. package/src/utils.ts +18 -0
  127. package/dist/types/registry/aiand.d.ts +0 -7
  128. package/dist/types/registry/aimlapi.d.ts +0 -4
  129. package/dist/types/registry/alibaba-coding-plan.d.ts +0 -8
  130. package/dist/types/registry/anthropic.d.ts +0 -10
  131. package/dist/types/registry/api-key-login.d.ts +0 -48
  132. package/dist/types/registry/azure.d.ts +0 -4
  133. package/dist/types/registry/baseten.d.ts +0 -7
  134. package/dist/types/registry/cerebras.d.ts +0 -7
  135. package/dist/types/registry/cline-pass.d.ts +0 -7
  136. package/dist/types/registry/coreweave.d.ts +0 -7
  137. package/dist/types/registry/cursor.d.ts +0 -7
  138. package/dist/types/registry/deepinfra.d.ts +0 -6
  139. package/dist/types/registry/deepseek.d.ts +0 -8
  140. package/dist/types/registry/devin.d.ts +0 -8
  141. package/dist/types/registry/exa.d.ts +0 -8
  142. package/dist/types/registry/firepass.d.ts +0 -16
  143. package/dist/types/registry/fireworks.d.ts +0 -7
  144. package/dist/types/registry/github-copilot.d.ts +0 -7
  145. package/dist/types/registry/gitlab-duo-workflow.d.ts +0 -10
  146. package/dist/types/registry/gitlab-duo.d.ts +0 -9
  147. package/dist/types/registry/gmi-cloud.d.ts +0 -7
  148. package/dist/types/registry/google-antigravity.d.ts +0 -9
  149. package/dist/types/registry/google-gemini-cli.d.ts +0 -9
  150. package/dist/types/registry/google-vertex.d.ts +0 -5
  151. package/dist/types/registry/google.d.ts +0 -4
  152. package/dist/types/registry/groq.d.ts +0 -4
  153. package/dist/types/registry/huggingface.d.ts +0 -7
  154. package/dist/types/registry/kagi.d.ts +0 -14
  155. package/dist/types/registry/kilo.d.ts +0 -7
  156. package/dist/types/registry/kimi-code.d.ts +0 -7
  157. package/dist/types/registry/litellm.d.ts +0 -13
  158. package/dist/types/registry/llama-cpp.d.ts +0 -8
  159. package/dist/types/registry/lm-studio.d.ts +0 -8
  160. package/dist/types/registry/meta.d.ts +0 -7
  161. package/dist/types/registry/minimax-code-cn.d.ts +0 -6
  162. package/dist/types/registry/minimax-code.d.ts +0 -6
  163. package/dist/types/registry/minimax.d.ts +0 -4
  164. package/dist/types/registry/mistral.d.ts +0 -4
  165. package/dist/types/registry/moonshot.d.ts +0 -7
  166. package/dist/types/registry/nanogpt.d.ts +0 -7
  167. package/dist/types/registry/novita.d.ts +0 -6
  168. package/dist/types/registry/nvidia.d.ts +0 -7
  169. package/dist/types/registry/oauth/devin.d.ts +0 -5
  170. package/dist/types/registry/oauth/gitlab-duo-workflow.d.ts +0 -6
  171. package/dist/types/registry/oauth/minimax-code.d.ts +0 -27
  172. package/dist/types/registry/oauth/opencode.d.ts +0 -25
  173. package/dist/types/registry/oauth/openrouter.d.ts +0 -36
  174. package/dist/types/registry/oauth/wafer.d.ts +0 -1
  175. package/dist/types/registry/ollama-cloud.d.ts +0 -7
  176. package/dist/types/registry/ollama.d.ts +0 -12
  177. package/dist/types/registry/openai-codex-device.d.ts +0 -8
  178. package/dist/types/registry/openai-codex.d.ts +0 -9
  179. package/dist/types/registry/openai.d.ts +0 -4
  180. package/dist/types/registry/opencode-go.d.ts +0 -6
  181. package/dist/types/registry/opencode-zen.d.ts +0 -6
  182. package/dist/types/registry/openrouter.d.ts +0 -14
  183. package/dist/types/registry/parallel.d.ts +0 -14
  184. package/dist/types/registry/perplexity.d.ts +0 -7
  185. package/dist/types/registry/qianfan.d.ts +0 -7
  186. package/dist/types/registry/qwen-portal.d.ts +0 -7
  187. package/dist/types/registry/sakana.d.ts +0 -7
  188. package/dist/types/registry/siliconflow-cn.d.ts +0 -7
  189. package/dist/types/registry/siliconflow.d.ts +0 -7
  190. package/dist/types/registry/synthetic.d.ts +0 -6
  191. package/dist/types/registry/tavily.d.ts +0 -14
  192. package/dist/types/registry/together.d.ts +0 -6
  193. package/dist/types/registry/umans.d.ts +0 -7
  194. package/dist/types/registry/venice.d.ts +0 -13
  195. package/dist/types/registry/vercel-ai-gateway.d.ts +0 -7
  196. package/dist/types/registry/vllm.d.ts +0 -7
  197. package/dist/types/registry/wafer-serverless.d.ts +0 -6
  198. package/dist/types/registry/xai-oauth.d.ts +0 -7
  199. package/dist/types/registry/xai.d.ts +0 -7
  200. package/dist/types/registry/xiaomi-token-plan-ams.d.ts +0 -6
  201. package/dist/types/registry/xiaomi-token-plan-cn.d.ts +0 -6
  202. package/dist/types/registry/xiaomi-token-plan-sgp.d.ts +0 -6
  203. package/dist/types/registry/xiaomi.d.ts +0 -6
  204. package/dist/types/registry/yolo-auto.d.ts +0 -15
  205. package/dist/types/registry/zai.d.ts +0 -15
  206. package/dist/types/registry/zenmux.d.ts +0 -7
  207. package/dist/types/registry/zhipu-coding-plan.d.ts +0 -7
  208. package/dist/types/utils/retry.d.ts +0 -14
  209. package/src/registry/aiand.ts +0 -22
  210. package/src/registry/aimlapi.ts +0 -6
  211. package/src/registry/anthropic.ts +0 -26
  212. package/src/registry/api-key-login.ts +0 -135
  213. package/src/registry/azure.ts +0 -6
  214. package/src/registry/baseten.ts +0 -22
  215. package/src/registry/cerebras.ts +0 -23
  216. package/src/registry/cline-pass.ts +0 -27
  217. package/src/registry/coreweave.ts +0 -40
  218. package/src/registry/cursor.ts +0 -20
  219. package/src/registry/deepinfra.ts +0 -24
  220. package/src/registry/deepseek.ts +0 -46
  221. package/src/registry/devin.ts +0 -15
  222. package/src/registry/exa.ts +0 -19
  223. package/src/registry/firepass.ts +0 -32
  224. package/src/registry/fireworks.ts +0 -28
  225. package/src/registry/github-copilot.ts +0 -22
  226. package/src/registry/gitlab-duo-workflow.ts +0 -20
  227. package/src/registry/gitlab-duo.ts +0 -19
  228. package/src/registry/gmi-cloud.ts +0 -22
  229. package/src/registry/google-antigravity.ts +0 -22
  230. package/src/registry/google-gemini-cli.ts +0 -22
  231. package/src/registry/google-vertex.ts +0 -38
  232. package/src/registry/google.ts +0 -6
  233. package/src/registry/groq.ts +0 -6
  234. package/src/registry/huggingface.ts +0 -29
  235. package/src/registry/kagi.ts +0 -28
  236. package/src/registry/kimi-code.ts +0 -17
  237. package/src/registry/litellm.ts +0 -27
  238. package/src/registry/llama-cpp.ts +0 -25
  239. package/src/registry/lm-studio.ts +0 -20
  240. package/src/registry/meta.ts +0 -22
  241. package/src/registry/minimax-code-cn.ts +0 -12
  242. package/src/registry/minimax-code.ts +0 -12
  243. package/src/registry/minimax.ts +0 -6
  244. package/src/registry/mistral.ts +0 -6
  245. package/src/registry/moonshot.ts +0 -28
  246. package/src/registry/nanogpt.ts +0 -22
  247. package/src/registry/novita.ts +0 -25
  248. package/src/registry/nvidia.ts +0 -61
  249. package/src/registry/oauth/devin.ts +0 -124
  250. package/src/registry/oauth/gitlab-duo-workflow.ts +0 -146
  251. package/src/registry/oauth/minimax-code.ts +0 -53
  252. package/src/registry/oauth/opencode.ts +0 -64
  253. package/src/registry/oauth/openrouter.ts +0 -120
  254. package/src/registry/oauth/wafer.ts +0 -24
  255. package/src/registry/ollama-cloud.ts +0 -36
  256. package/src/registry/ollama.ts +0 -43
  257. package/src/registry/openai-codex-device.ts +0 -18
  258. package/src/registry/openai-codex.ts +0 -19
  259. package/src/registry/openai.ts +0 -6
  260. package/src/registry/opencode-go.ts +0 -12
  261. package/src/registry/opencode-zen.ts +0 -12
  262. package/src/registry/openrouter.ts +0 -24
  263. package/src/registry/parallel.ts +0 -27
  264. package/src/registry/perplexity.ts +0 -13
  265. package/src/registry/qianfan.ts +0 -28
  266. package/src/registry/qwen-portal.ts +0 -50
  267. package/src/registry/sakana.ts +0 -22
  268. package/src/registry/siliconflow-cn.ts +0 -22
  269. package/src/registry/siliconflow.ts +0 -22
  270. package/src/registry/synthetic.ts +0 -21
  271. package/src/registry/tavily.ts +0 -27
  272. package/src/registry/together.ts +0 -26
  273. package/src/registry/umans.ts +0 -23
  274. package/src/registry/venice.ts +0 -33
  275. package/src/registry/vercel-ai-gateway.ts +0 -20
  276. package/src/registry/vllm.ts +0 -24
  277. package/src/registry/wafer-serverless.ts +0 -12
  278. package/src/registry/xai-oauth.ts +0 -17
  279. package/src/registry/xai.ts +0 -22
  280. package/src/registry/xiaomi-token-plan-ams.ts +0 -12
  281. package/src/registry/xiaomi-token-plan-cn.ts +0 -12
  282. package/src/registry/xiaomi-token-plan-sgp.ts +0 -12
  283. package/src/registry/xiaomi.ts +0 -12
  284. package/src/registry/yolo-auto.ts +0 -30
  285. package/src/registry/zai.ts +0 -41
  286. package/src/registry/zenmux.ts +0 -22
  287. package/src/registry/zhipu-coding-plan.ts +0 -27
  288. package/src/utils/retry.ts +0 -77
package/CHANGELOG.md CHANGED
@@ -2,6 +2,49 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [18.1.6] - 2026-09-03
6
+
7
+ ### Breaking Changes
8
+
9
+ - Renamed `claudeCodeSessionId` to `sessionId` in `AnthropicClientOptionsArgs`.
10
+ - Renamed `openAISessionId` to `sessionId` in `OpenAIRequestSetupOptions`.
11
+
12
+ ### Added
13
+
14
+ - Added Amazon Bedrock `requestMetadata` support for cost and usage attribution in AWS invocation logs.
15
+
16
+ ### Changed
17
+
18
+ - Codex GPT-5.6 requests now use full Responses by default, enabling independent tool calls to run in parallel; provider-native compaction continues to use catalog-selected Responses Lite.
19
+ - Inference requests now identify as omp by default while preserving explicit provider and OAuth User-Agent fingerprints. Amazon Bedrock requests use an `omp/<version>` User-Agent by default and honor configured `User-Agent` overrides.
20
+
21
+ ### Fixed
22
+
23
+ - Fixed Antigravity usage reporting to match the official client's five-hour and weekly quota buckets.
24
+ - Anthropic and OpenRouter credit-exhaustion errors now automatically switch to a sibling account instead of stopping the turn with a retry hint.
25
+ - Fixed OpenCode Go and Zen requests by including the required stable per-conversation session identification.
26
+ - Improved Anthropic prompt caching so explicit cache breakpoints preserve reusable tools and system prompts when the message tail changes.
27
+
28
+ ## [18.1.5] - 2026-09-03
29
+
30
+ ### Added
31
+
32
+ - Added `/login abliteration` with API key validation against `/v1/models`, supporting the `ABLITERATION_API_KEY` and `ABLIT_KEY` environment variables.
33
+
34
+ ### Changed
35
+
36
+ - Modernized provider authentication and token refresh across the catalog, with shared support for API-key, authorization-code, and device-code sign-in flows and clearer sign-in progress messages for OpenRouter, Kimi, and xAI.
37
+
38
+ ### Fixed
39
+
40
+ - GitHub Copilot now uses the official Copilot CLI identity and OAuth application for requests and new sign-ins, restoring access to client-gated models while preserving existing credentials.
41
+ - GitHub Copilot now reports `model_not_supported` responses immediately instead of repeatedly retrying unsupported models.
42
+ - Improved account recovery after Google rate limits are lifted earlier than the reported reset time.
43
+ - Fixed unmetered autocomplete models being reported as exhausted when quota is limited.
44
+ - Fixed Gemini 3 cross-model sessions in Cloud Code Assist when replaying tool calls without a thought signature.
45
+ - Fixed Cursor models behind an authentication gateway incorrectly retrying valid client-declared tool calls.
46
+ - Fixed reasoning from models that prefill `<think>` (including DeepSeek-R1 and hosted Qwen3-Thinking) being shown in the response instead of as a separate thinking block.
47
+
5
48
  ## [18.1.3] - 2026-09-02
6
49
 
7
50
  ### Fixed
@@ -163,7 +206,7 @@
163
206
  - Fixed Codex continuations, retries, and compaction replacing or dropping the turn-scoped sticky-routing token ([#9277](https://github.com/can1357/oh-my-pi/issues/9277)).
164
207
  - Fixed Codex Responses append chains falling back to full-context replay when replay-sanitized assistant items differ only by output-only IDs or lifecycle status.
165
208
  - Fixed Cursor usage reporting “no usage data” for plans without a numeric legacy request cap.
166
- - Fixed DeepSeek models rejecting requests with HTTP 400 `unknown variant \`image_url\`, expected \`text\`` when screenshots or image-producing tool results are present in conversation history or when `model.input` claims vision capability; `convertMessages` in `openai-completions` now strips `image_url` content parts and injects non-vision image placeholders for all DeepSeek endpoints.
209
+ - Fixed DeepSeek models rejecting requests with HTTP 400 `unknown variant \`image_url\`, expected \`text\``when screenshots or image-producing tool results are present in conversation history or when`model.input`claims vision capability;`convertMessages`in`openai-completions`now strips`image_url` content parts and injects non-vision image placeholders for all DeepSeek endpoints.
167
210
  - Fixed `PI_PROXY` covering only provider streams: OAuth token refresh and login, usage probes, and model discovery went out through the bare global `fetch` and ignored it, so a region-blocked token endpoint answered `403 Request not allowed` (Anthropic `/v1/oauth/token`) and disabled the credential while the proxied stream itself worked. `installGlobalProxyFetch()` now routes the process-wide `fetch` through `PI_PROXY`; a per-request proxy such as `PI_PROXY_<PROVIDER>` still wins, and loopback / private-range / `NO_PROXY` targets stay direct.
168
211
  - Fixed Anthropic inference ignoring every proxy setting. `coworkFetch` runs on `node:https`, whose Bun shim discards both `agent.createConnection` and `options.createConnection`: the CONNECT tunnel to `PI_PROXY` was built, TLS-negotiated, then abandoned, and the request dialed `api.anthropic.com` on the default route (measured at the proxy: 581 bytes of handshake, zero request bytes). On a region-blocked egress that returned `403 {"type":"forbidden","message":"Request not allowed"}` with the proxy apparently configured. Proxied requests now go through Bun's own `fetch`, which honors `init.proxy`, trading the Cowork TLS/header profile for a proxy that actually carries the traffic; the dead tunnel plumbing is gone from the transport. `node:http2` (Cursor) does honor `createConnection` and is unaffected.
169
212
  - Fixed `cowork-fetch` capturing `globalThis.fetch` at module load, so a proxy wrapper installed later in startup was ignored on its fallback path.
@@ -233,7 +276,7 @@
233
276
 
234
277
  ### Changed
235
278
 
236
- - Fixed Gemini thought summaries occasionally leaking a raw `` ```thinking `` / `` ``````thinking `` fence delimiter into the reasoning block, so it no longer shows up as fence spam in the thinking display or persisted transcripts ([#8719](https://github.com/can1357/oh-my-pi/issues/8719)).
279
+ - Fixed Gemini thought summaries occasionally leaking a raw ` ```thinking ` / ` ``````thinking ` fence delimiter into the reasoning block, so it no longer shows up as fence spam in the thinking display or persisted transcripts ([#8719](https://github.com/can1357/oh-my-pi/issues/8719)).
237
280
  - Fixed the OpenCode Go login prompting for an "OpenCode Zen API key": the shared login flow now names the provider you selected, so connecting OpenCode Go asks for an OpenCode Go key (the `opencode.ai/auth` console is still shared, as documented upstream) ([#8738](https://github.com/can1357/oh-my-pi/issues/8738)).
238
281
  - Fixed Anthropic-compatible endpoints with strict prompt validation (e.g. Z.AI GLM `api.z.ai/api/anthropic`, which rejects the whole request with `400 code 1213 "The prompt parameter was not received normally"`) failing sessions once a tool returned empty output on a vision-capable model: empty successful `tool_result` blocks now encode as `content: ""` instead of `content: []`, which both the official API and strict compatible endpoints accept.
239
282
  - Fixed `retry.usageReservePct` (Reserve Margin) ignoring Claude Fable/Mythos weekly tier usage until it hit 100%, so a Fable model kept serving turns past the configured reserve; reserve health now honors the mapped tier row while credential-wide hard blocks still require confirmed exhaustion ([#8773](https://github.com/can1357/oh-my-pi/issues/8773)).
@@ -1285,7 +1328,7 @@
1285
1328
 
1286
1329
  - Added a third streaming thinking-loop detection heuristic to catch "progress-lexicon stalls" where models endlessly reshuffle motivational filler without introducing new vocabulary or concrete technical references
1287
1330
  - Added branded wordmark and logo animation to authentication flow
1288
- - Added a third streaming thinking-loop detection shape — a *progress-lexicon stall* — alongside verbatim tail repetition and near-duplicate (trigram) segments. It catches reasoning-summarizer loops that reshuffle the same motivational filler ("just doing it, pushing ahead, maintaining momentum") into fresh word order every paragraph: word-trigrams never cluster, but a run of substantial segments that recycle the recent vocabulary and introduce no *new* concrete reference (path / identifier / code-span) trips the guard. Summarizer title/heading lines (`**Bold Title**`, `## Heading`) are stripped before analysis so their ever-changing wording cannot mask the stall by inflating novelty. Calibrated against 537k real non-Gemini reasoning blocks (zero false positives at novelty floor 0.2 / run length 8; the real loop sustains runs of 10+).
1331
+ - Added a third streaming thinking-loop detection shape — a _progress-lexicon stall_ — alongside verbatim tail repetition and near-duplicate (trigram) segments. It catches reasoning-summarizer loops that reshuffle the same motivational filler ("just doing it, pushing ahead, maintaining momentum") into fresh word order every paragraph: word-trigrams never cluster, but a run of substantial segments that recycle the recent vocabulary and introduce no _new_ concrete reference (path / identifier / code-span) trips the guard. Summarizer title/heading lines (`**Bold Title**`, `## Heading`) are stripped before analysis so their ever-changing wording cannot mask the stall by inflating novelty. Calibrated against 537k real non-Gemini reasoning blocks (zero false positives at novelty floor 0.2 / run length 8; the real loop sustains runs of 10+).
1289
1332
  - Added CoreWeave Serverless Inference provider login support via `COREWEAVE_API_KEY` and `WANDB_API_KEY` fallback.
1290
1333
 
1291
1334
  ### Changed
@@ -1429,7 +1472,7 @@
1429
1472
  - Fixed tool call ID normalization for Anthropic-compatible models
1430
1473
  - Fixed Anthropic Messages replay sanitizing malformed tool-call IDs, including aborted native tool calls with empty IDs, so retries no longer send invalid `tool_use.id` / `tool_result.tool_use_id` pairs.
1431
1474
  - Fixed the Codex Responses WebSocket transport attributing a prior turn's output to the current one on a reused connection: a trailing/duplicate frame from a cleanly-completed previous response that slipped past the queue drain could be consumed as this request's terminal (ending the turn with empty output) or as a stale tool call. Frames are now keyed by `response.id` — a frame carrying the previous response's id is dropped, and one carrying a third id (or a regressed `sequence_number`) fails closed so the turn retries instead of mixing two responses' streams. Idless frames (deltas, the rate-limit/metadata preamble, `response.created`-less streams) still pass through, matching upstream codex-rs.
1432
- - Fixed `transformMessages` pulling an earlier, orphaned tool result onto a later tool call that reused the same id (left behind when compaction folded the originating `tool_use` into a summary). The pending-call flush now pairs each call with a result positioned *after* its assistant turn, so a reused id surfaces its own output rather than a prior turn's.
1475
+ - Fixed `transformMessages` pulling an earlier, orphaned tool result onto a later tool call that reused the same id (left behind when compaction folded the originating `tool_use` into a summary). The pending-call flush now pairs each call with a result positioned _after_ its assistant turn, so a reused id surfaces its own output rather than a prior turn's.
1433
1476
  - Fixed DashScope 429 rate-limit messages that mention authorization being classified as credential failures, preventing valid API keys from being invalidated after throttling. ([#3172](https://github.com/can1357/oh-my-pi/issues/3172))
1434
1477
  - Fixed OpenCode Go `401 Insufficient balance` quota errors being treated as unknown failures instead of usage-limit errors, restoring credential rotation and fallback chains. ([#3169](https://github.com/can1357/oh-my-pi/issues/3169))
1435
1478
 
@@ -1705,7 +1748,7 @@
1705
1748
  - Added `wrapInbandToolStream` function to process streaming responses with in-band tool call parsing
1706
1749
  - Added `ThinkingInbandScanner` for parsing thinking/reasoning blocks across dialects
1707
1750
  - Added `OwnedStream` class for managing dialect-aware streaming with tool call events
1708
- - Added in-band thinking channels to every dialect that was missing one: `gemini` (a ```` ```thinking ```` fence mirroring ```` ```tool_code ````), `gemma` (its native `<|channel>thought…<channel|>` reasoning channel), `kimi` (`<think>…</think>`), and `pi` (`<thinking>…</thinking>`). Each scanner now parses reasoning into thinking events instead of leaking chain-of-thought into the visible reply, and every dialect's `renderThinking` is a real channel that round-trips back through its scanner (no passthrough renderers).
1751
+ - Added in-band thinking channels to every dialect that was missing one: `gemini` (a ` ```thinking ` fence mirroring ` ```tool_code `), `gemma` (its native `<|channel>thought…<channel|>` reasoning channel), `kimi` (`<think>…</think>`), and `pi` (`<thinking>…</thinking>`). Each scanner now parses reasoning into thinking events instead of leaking chain-of-thought into the visible reply, and every dialect's `renderThinking` is a real channel that round-trips back through its scanner (no passthrough renderers).
1709
1752
 
1710
1753
  ### Changed
1711
1754
 
@@ -1729,7 +1772,7 @@
1729
1772
 
1730
1773
  ### Added
1731
1774
 
1732
- - Added the `gemini` in-band tool-call syntax with Python-style ```tool_code``` blocks and `default_api` invocations
1775
+ - Added the `gemini` in-band tool-call syntax with Python-style `tool_code` blocks and `default_api` invocations
1733
1776
  - Added the `gemma` token-delimited in-band tool-call syntax using `<|tool_call>` and `<|tool_response>` blocks
1734
1777
  - Added `gemini` and `gemma` to owned stream tool-result token detection so their tool responses are recognized
1735
1778
  - Fixed truncated Gemini and Gemma tool blocks from being emitted as plain text during streaming
@@ -1774,7 +1817,7 @@
1774
1817
  - Fixed Harmony leak handling support by adding `recoverHarmonyToolCall` plus leak-detection workflows for contaminated assistant messages so recoverable tool-call arguments can be safely truncated and retried
1775
1818
  - Fixed false-positive gating in Harmony leak heuristics using signal-based checks so unrelated text containing `to=functions...` is not treated as leaked tool-call markup
1776
1819
  - Routed Kimi, DeepSeek DSML, and plain thinking markup healing through the shared in-band scanners so provider leak repair and owned tool calling parse the same wire formats.
1777
- - Fixed Cursor provider (`cursor-agent` API) streaming dropping large MCP tool-call arguments — most visibly the built-in `task` tool's `tasks` array on multi-subagent dispatches, which failed downstream schema validation with `tasks: Invalid input: expected array, received undefined`. Two upstream behaviors were fighting the stream handler in `packages/ai/src/providers/cursor.ts`: (1) `args_text_delta` carries the *cumulative* args text so far per `agent.proto`, but the handler concatenated each snapshot onto the buffer, garbling the JSON; (2) `tool_call_completed` carries an `McpArgs` map that omits oversized parameters entirely and downgrades unparsable values to their raw string fallback, but the handler unconditionally overwrote the streamed args with that map. The handler now strips the already-buffered prefix from each `args_text_delta` snapshot (falling back to append when the snapshot doesn't extend the buffer) and merges the decoded `McpArgs` map into the streamed args — preserving streamed keys the completion frame omits and the structured value when the completion frame downgrades to a string. ([#2615](https://github.com/can1357/oh-my-pi/issues/2615))
1820
+ - Fixed Cursor provider (`cursor-agent` API) streaming dropping large MCP tool-call arguments — most visibly the built-in `task` tool's `tasks` array on multi-subagent dispatches, which failed downstream schema validation with `tasks: Invalid input: expected array, received undefined`. Two upstream behaviors were fighting the stream handler in `packages/ai/src/providers/cursor.ts`: (1) `args_text_delta` carries the _cumulative_ args text so far per `agent.proto`, but the handler concatenated each snapshot onto the buffer, garbling the JSON; (2) `tool_call_completed` carries an `McpArgs` map that omits oversized parameters entirely and downgrades unparsable values to their raw string fallback, but the handler unconditionally overwrote the streamed args with that map. The handler now strips the already-buffered prefix from each `args_text_delta` snapshot (falling back to append when the snapshot doesn't extend the buffer) and merges the decoded `McpArgs` map into the streamed args — preserving streamed keys the completion frame omits and the structured value when the completion frame downgrades to a string. ([#2615](https://github.com/can1357/oh-my-pi/issues/2615))
1778
1821
  - Fixed Codex Responses stream mis-routing interleaved `function_call_arguments.delta` events when more than one tool call was open concurrently. The runtime tracked a singleton `currentItem`/`currentBlock`, so every delta — regardless of `item_id` — was appended to whichever item was most recently added, and `output_item.done` for the earlier call then overwrote a sibling's stored arguments (visible as `tasks: Invalid input: expected array, received undefined` on the `task` tool). Open items are now keyed by `item_id` with `output_index` fallback; deltas/done events route to the matching block, late deltas whose item already closed are dropped instead of corrupting a sibling, and `toolcall_*` stream events emit the right `contentIndex` per call ([#2619](https://github.com/can1357/oh-my-pi/issues/2619)).
1779
1822
 
1780
1823
  ## [15.13.1] - 2026-06-15
@@ -1983,7 +2026,7 @@
1983
2026
 
1984
2027
  ### Breaking Changes
1985
2028
 
1986
- - The model catalog moved to the new `@oh-my-pi/pi-catalog` package. Deep subpath exports `@oh-my-pi/pi-ai/models.json`, `/models`, `/model-cache`, `/model-manager`, `/model-thinking`, `/effort`, `/provider-models*`, `/utils/discovery*`, `/providers/openai-codex/constants`, `/providers/google-gemini-headers`, and `/providers/openai-completions-compat` are gone — import the `@oh-my-pi/pi-catalog` equivalents (`/models.json`, `/models`, `/model-cache`, `/model-manager`, `/model-thinking`, `/effort`, `/provider-models*`, `/discovery*`, `/wire/codex`, `/wire/gemini-headers`, `/compat/openai`). The pi-ai root barrel re-exports only the model/effort *types* its own signatures use (`Model`, `Api`, `ThinkingConfig`, `Effort`, `Usage`, compat interfaces) — catalog *values* (`getBundledModel(s)`, `calculateCost`, `modelsAreEqual`, `clampThinkingLevelForModel`, `DEFAULT_MODEL_PER_PROVIDER`, …) must be imported from `@oh-my-pi/pi-catalog`.
2029
+ - The model catalog moved to the new `@oh-my-pi/pi-catalog` package. Deep subpath exports `@oh-my-pi/pi-ai/models.json`, `/models`, `/model-cache`, `/model-manager`, `/model-thinking`, `/effort`, `/provider-models*`, `/utils/discovery*`, `/providers/openai-codex/constants`, `/providers/google-gemini-headers`, and `/providers/openai-completions-compat` are gone — import the `@oh-my-pi/pi-catalog` equivalents (`/models.json`, `/models`, `/model-cache`, `/model-manager`, `/model-thinking`, `/effort`, `/provider-models*`, `/discovery*`, `/wire/codex`, `/wire/gemini-headers`, `/compat/openai`). The pi-ai root barrel re-exports only the model/effort _types_ its own signatures use (`Model`, `Api`, `ThinkingConfig`, `Effort`, `Usage`, compat interfaces) — catalog _values_ (`getBundledModel(s)`, `calculateCost`, `modelsAreEqual`, `clampThinkingLevelForModel`, `DEFAULT_MODEL_PER_PROVIDER`, …) must be imported from `@oh-my-pi/pi-catalog`.
1987
2030
  - `ProviderDefinition` is now auth-only: `defaultModel`, `createModelManagerOptions`, `catalogDiscovery`, `dynamicModelsAuthoritative`, `allowUnauthenticated`, and `specialModelManager` moved to pi-catalog's `CATALOG_PROVIDERS` table, and `KnownProviderId` was replaced by pi-catalog's `KnownProvider` (registry completeness is enforced by a compile-time check against that union). The pure GitHub Copilot key/endpoint helpers moved from `registry/oauth/github-copilot` to `@oh-my-pi/pi-catalog/wire/github-copilot`.
1988
2031
 
1989
2032
  ### Added
@@ -2072,7 +2115,7 @@
2072
2115
  - Fixed `AnthropicMessagesClient` spreading `fetchOptions` after the core request fields, letting a caller-supplied `signal`/`method`/`body` silently disconnect the timeout controller or corrupt the request. Transport extras (TLS) still pass through; core fields now always win.
2073
2116
  - Fixed Foundry mTLS/CA material being cached for the process lifetime when the env vars point at files: the cache key now folds in the file mtime so on-disk certificate rotation takes effect.
2074
2117
  - Fixed the Claude Code fingerprint version drifting across surfaces: the usage endpoint (`claude-cli/2.1.160`) and OAuth bootstrap (`claude-code/2.1.160`) pinned a stale version while `/v1/messages` reported 2.1.165; both now derive from `claudeCodeVersion`.
2075
- - Fixed a system prompt that merely *mentions* `x-anthropic-billing-header:` mid-text suppressing the entire Claude Code system-block injection (billing header, instruction, and cch attestation); the resumed-session guard now anchors with `startsWith`.
2118
+ - Fixed a system prompt that merely _mentions_ `x-anthropic-billing-header:` mid-text suppressing the entire Claude Code system-block injection (billing header, instruction, and cch attestation); the resumed-session guard now anchors with `startsWith`.
2076
2119
  - Fixed lone surrogates in cross-API tool-call arguments reaching Anthropic's strict UTF-8 validation: replayed OpenAI/Google-origin `tool_use.input` string leaves are now deep-sanitized with `toWellFormed()`, while same-API Anthropic arguments stay byte-identical to keep prompt-cache prefixes stable.
2077
2120
  - Bounded the many-image resize fan-out to 4 concurrent decodes (it previously decoded every oversized image at once, two encode pipelines each — multi-GB transient memory at the 20+-image threshold that activates the feature).
2078
2121
  - Fixed `mergeHeaders` merging case-sensitively on the Copilot/client-options path, where a miscased user-configured header (e.g. `authorization` next to the synthesized `Authorization`) survived as two keys that the `Headers` constructor joins comma-separated on the wire.
package/README.md CHANGED
@@ -1090,56 +1090,31 @@ For the current API-key onboarding flows, the library covers Together, Moonshot,
1090
1090
 
1091
1091
  ### Programmatic OAuth
1092
1092
 
1093
- The library provides login and token refresh functions. Credential storage is the caller's responsibility.
1093
+ Provider login and refresh behavior is exposed through the registry. Credential storage is the caller's responsibility.
1094
1094
 
1095
1095
  ```typescript
1096
1096
  import {
1097
- // Login functions (return credentials, do not store)
1098
- loginAnthropic,
1099
- loginOpenAICodex,
1100
- loginGitHubCopilot,
1101
- loginGeminiCli,
1102
- loginAntigravity,
1103
- loginCloudflareAiGateway,
1104
- loginHuggingface,
1105
- loginLiteLLM,
1106
- loginMoonshot,
1107
- loginNvidia,
1108
- loginNanoGPT,
1109
- loginQianfan,
1110
- loginQwenPortal,
1111
- loginTogether,
1112
- loginVenice,
1113
- loginVllm,
1114
- loginXiaomi,
1115
-
1116
- // Token management
1097
+ getProviderDefinition,
1117
1098
  refreshOAuthToken, // (provider, credentials) => new credentials
1118
1099
  getOAuthApiKey, // (provider, credentialsMap) => { newCredentials, apiKey } | null
1119
-
1120
- // Types
1121
- type OAuthProvider, // includes 'anthropic', 'openai-codex', 'github-copilot', 'google-gemini-cli', 'google-antigravity', 'together', 'moonshot', 'qianfan', 'nvidia', 'nanogpt', 'novita', 'huggingface', 'venice', 'xiaomi', 'vllm', 'litellm', 'cloudflare-ai-gateway', 'qwen-portal', ...
1100
+ type OAuthProvider,
1122
1101
  type OAuthCredentials,
1123
1102
  } from "@oh-my-pi/pi-ai";
1124
- ```
1125
1103
 
1126
- `loginOpenAICodex` accepts an optional `originator` value used in the OAuth flow:
1127
-
1128
- ```typescript
1129
- await loginOpenAICodex({
1104
+ const provider = getProviderDefinition("openai-codex");
1105
+ const credentials = await provider?.login?.({
1130
1106
  onAuth: ({ url }) => console.log(url),
1131
- originator: "my-cli",
1132
1107
  });
1133
1108
  ```
1134
1109
 
1135
1110
  ### Login Flow Example
1136
1111
 
1137
1112
  ```typescript
1138
- import { loginGitHubCopilot } from "@oh-my-pi/pi-ai";
1113
+ import { getProviderDefinition } from "@oh-my-pi/pi-ai";
1139
1114
  import * as fs from "node:fs";
1140
1115
 
1141
- const credentials = await loginGitHubCopilot({
1142
- onAuth: (url, instructions) => {
1116
+ const credentials = await getProviderDefinition("github-copilot")?.login?.({
1117
+ onAuth: ({ url, instructions }) => {
1143
1118
  console.log(`Open: ${url}`);
1144
1119
  if (instructions) console.log(instructions);
1145
1120
  },
@@ -1,6 +1,15 @@
1
1
  import type { InbandScanEvent, InbandScanner } from "./types.js";
2
+ export interface ThinkingInbandScannerOptions {
3
+ /**
4
+ * Report a bare reasoning close tag (no open seen) as an `impliedThinkingEnd`
5
+ * event instead of passing it through as text. Off by default: only a
6
+ * consumer that owns the whole message can reclassify the text before it.
7
+ */
8
+ readonly impliedOpen?: boolean;
9
+ }
2
10
  export declare class ThinkingInbandScanner implements InbandScanner {
3
11
  #private;
12
+ constructor(options?: ThinkingInbandScannerOptions);
4
13
  feed(text: string): InbandScanEvent[];
5
14
  flush(): InbandScanEvent[];
6
15
  }
@@ -12,6 +12,16 @@ export type InbandScanEvent = {
12
12
  } | {
13
13
  type: "thinkingEnd";
14
14
  thinking: string;
15
+ }
16
+ /**
17
+ * A reasoning close tag with no open in this stream. Chat templates that
18
+ * prefill the opener into the prompt (DeepSeek-R1, Qwen3-Thinking) make the
19
+ * model stream only the close, so everything emitted as `text` before this
20
+ * event was reasoning. Only {@link ThinkingInbandScanner} with `impliedOpen`
21
+ * emits it.
22
+ */
23
+ | {
24
+ type: "impliedThinkingEnd";
15
25
  } | {
16
26
  type: "toolStart";
17
27
  id: string;
@@ -87,13 +87,6 @@ export declare function isFastModeUnsupported(error: unknown): boolean;
87
87
  * fail identically) nor surface as an auth failure.
88
88
  */
89
89
  export declare function isClinePassSurfaceGateMessage(errorMessage: string | undefined): boolean;
90
- /**
91
- * GitHub Copilot 400 `model_not_supported` response for a model advertised by
92
- * `/models` — transient fleet skew, not a malformed request. Reads the
93
- * structural `code` through the SDK/body envelopes, then falls back to the
94
- * stringified body both SDK families put in `message`.
95
- */
96
- export declare function isCopilotTransientModelError(error: unknown): boolean;
97
90
  export declare function classifyMessage(message: {
98
91
  api?: Api;
99
92
  provider?: string;
@@ -7,13 +7,6 @@
7
7
  * may match more. Use this when you only have a `status: number`.
8
8
  */
9
9
  export declare function isTransientStatus(status: number | undefined): boolean;
10
- /** Hook for provider-specific transient detection that the error module must not import directly. */
11
- export interface ProviderRetryableHooks {
12
- /** Provider id of the failing request, used to gate provider-specific checks. */
13
- provider?: string;
14
- /** Provider-specific transient predicate (e.g. Copilot model-availability 400s). */
15
- isProviderTransient?: (error: Error) => boolean;
16
- }
17
10
  /**
18
11
  * Whether a provider stream error should be retried against the same credential.
19
12
  *
@@ -21,7 +14,7 @@ export interface ProviderRetryableHooks {
21
14
  * here — they are owned by the credential-rotation layer (auth-gateway /
22
15
  * `streamSimple` a/b/c policy), not this seconds-scale provider backoff.
23
16
  *
24
- * Provider-specific transient cases are injected via {@link ProviderRetryableHooks}
25
- * so this stays free of provider imports.
17
+ * Every 4xx other than 408/429 is terminal: a request the provider rejected
18
+ * as malformed, unauthorized, or unentitled fails identically on replay.
26
19
  */
27
- export declare function isProviderRetryableError(error: unknown, hooks?: ProviderRetryableHooks): boolean;
20
+ export declare function isProviderRetryableError(error: unknown): boolean;
@@ -46,7 +46,6 @@ export * from "./utils/anthropic-auth.js";
46
46
  export * from "./utils/event-stream.js";
47
47
  export * from "./utils/glyph-codec.js";
48
48
  export * from "./utils/openrouter-headers.js";
49
- export * from "./utils/retry.js";
50
49
  export * from "./utils/schema/index.js";
51
50
  export * from "./utils/thinking-loop.js";
52
51
  export * from "./utils/tool-call-loop-guard.js";
@@ -47,5 +47,12 @@ export interface BedrockOptions extends StreamOptions {
47
47
  * we omit it for them.
48
48
  */
49
49
  thinkingDisplay?: BedrockThinkingDisplay;
50
+ /**
51
+ * Per-request Bedrock invocation-log tags. Merged over `model.requestMetadata`
52
+ * (per-call entries win on key collision). AWS caps the result at 16 entries;
53
+ * keys 1-256 chars, values 0-256 chars, both limited to
54
+ * `[a-zA-Z0-9\s:_@$#=/+,-.]`. Entries outside those limits are dropped.
55
+ */
56
+ requestMetadata?: Record<string, string>;
50
57
  }
51
58
  export declare const streamBedrock: StreamFunction<"bedrock-converse-stream">;
@@ -164,7 +164,7 @@ export type AnthropicClientOptionsArgs = {
164
164
  disableStrictTools?: boolean;
165
165
  fetch?: FetchImpl;
166
166
  maxRetryDelayMs?: number;
167
- claudeCodeSessionId?: string;
167
+ sessionId?: string;
168
168
  };
169
169
  export type AnthropicClientOptionsResult = {
170
170
  isOAuthToken: boolean;
@@ -188,13 +188,6 @@ export type AnthropicClientOptionsResult = {
188
188
  * omitted there.
189
189
  */
190
190
  export declare function resolveAnthropicCustomHeadersForBaseUrl(baseUrl: string | undefined): Record<string, string> | undefined;
191
- /**
192
- * Whether an Anthropic (or Copilot-over-Anthropic) stream error should be
193
- * retried. The classification lives in {@link AIError.isProviderRetryableError};
194
- * this wrapper injects the Copilot-specific model-availability transient check,
195
- * which the error module must not import directly.
196
- */
197
- export declare function isProviderRetryableError(error: unknown, provider?: string): boolean;
198
191
  export type AnthropicUsageLike = {
199
192
  cache_creation?: {
200
193
  ephemeral_5m_input_tokens?: number | null;
@@ -12,6 +12,8 @@ export interface CursorOptions extends StreamOptions {
12
12
  conversationId?: string;
13
13
  execHandlers?: CursorExecHandlers;
14
14
  onToolResult?: CursorToolResultHandler;
15
+ /** Treat unhandled MCP calls as accepted handoffs to an external executor. */
16
+ externalToolExecutor?: boolean;
15
17
  /** Wire model id selected after thinking-effort routing (`resolveWireModelId`). */
16
18
  wireModelId?: string;
17
19
  }
@@ -104,7 +106,7 @@ export interface UsageState {
104
106
  sawTokenDelta: boolean;
105
107
  }
106
108
  /** Exported for tests: drives one Cursor server message through the stream (exec waits mark the stream busy). */
107
- export declare function handleServerMessage(msg: AgentServerMessage, output: AssistantMessage, stream: AssistantMessageEventStream, state: BlockState, blobStore: Map<string, Uint8Array>, h2Request: http2.ClientHttp2Stream, execHandlers: CursorExecHandlers | undefined, onToolResult: CursorToolResultHandler | undefined, usageState: UsageState, requestContextTools: McpToolDefinition[], requestContextRules?: CursorRule[], onConversationCheckpoint?: (checkpoint: ConversationStateStructure) => void): Promise<void>;
109
+ export declare function handleServerMessage(msg: AgentServerMessage, output: AssistantMessage, stream: AssistantMessageEventStream, state: BlockState, blobStore: Map<string, Uint8Array>, h2Request: http2.ClientHttp2Stream, execHandlers: CursorExecHandlers | undefined, onToolResult: CursorToolResultHandler | undefined, usageState: UsageState, requestContextTools: McpToolDefinition[], requestContextRules?: CursorRule[], onConversationCheckpoint?: (checkpoint: ConversationStateStructure) => void, externalToolExecutor?: boolean): Promise<void>;
108
110
  /**
109
111
  * Exported for tests: verifies handler is invoked with correct `this` when passed as bound.
110
112
  *
@@ -0,0 +1,24 @@
1
+ /** Shared inference request identity headers. */
2
+ import type { FetchImpl } from "../types.js";
3
+ /** Options controlling provider and protocol inference headers. */
4
+ export interface InferenceHeaderOptions {
5
+ provider: string;
6
+ protocol: "anthropic" | "google" | "openai";
7
+ sessionId?: string;
8
+ }
9
+ /** Set a header unless the map already contains that field under any casing. */
10
+ export declare function setHeaderIfAbsent(headers: Record<string, string>, name: string, value: string): void;
11
+ /**
12
+ * Project omp's identity and authoritative conversation id onto the headers
13
+ * understood by the active inference protocol and host.
14
+ */
15
+ export declare function applyInferenceHeaders(headers: Record<string, string>, options: InferenceHeaderOptions): void;
16
+ /**
17
+ * Apply omp's process-wide inference User-Agent default. Any explicit header,
18
+ * including Anthropic and Codex OAuth fingerprints, remains authoritative.
19
+ *
20
+ * Plain-object headers stay plain objects: custom `fetch` implementations
21
+ * (proxies, tests) index `init.headers` by name and must not be handed a
22
+ * `Headers` instance instead.
23
+ */
24
+ export declare function withInferenceUserAgent(fetchImpl: FetchImpl): FetchImpl;
@@ -21,10 +21,8 @@ export interface CodexRequestOptions {
21
21
  textVerbosity?: "low" | "medium" | "high";
22
22
  include?: string[];
23
23
  /**
24
- * Responses Lite transport override; defaults to the model's
25
- * `useResponsesLite`. Lite moves instructions/tools into input items,
26
- * strips image detail, and disables parallel tool calling (codex-rs
27
- * `use_responses_lite`).
24
+ * Responses Lite transport opt-in. Normal inference defaults to full
25
+ * Responses so the model can emit independent tool calls in parallel.
28
26
  */
29
27
  responsesLite?: boolean;
30
28
  }
@@ -70,13 +68,12 @@ export interface RequestBody {
70
68
  [key: string]: unknown;
71
69
  }
72
70
  /**
73
- * Resolve whether a Codex request uses the Responses Lite transport: an
74
- * explicit option wins, then the `PI_CODEX_RESPONSES_LITE` env override
75
- * (`1`/`true` forces Lite, `0`/`false` forces the full Responses body),
76
- * otherwise the model's catalog flag (codex-rs `model_info.use_responses_lite`)
77
- * decides.
71
+ * Resolve whether a Codex request explicitly opts into Responses Lite.
72
+ *
73
+ * Provider-native compaction passes the model's `useResponsesLite` flag as an
74
+ * explicit option; normal inference defaults to the full Responses contract.
78
75
  */
79
- export declare function resolveCodexResponsesLite(model: Model<"openai-codex-responses">, requested: boolean | undefined): boolean;
76
+ export declare function resolveCodexResponsesLite(requested: boolean | undefined): boolean;
80
77
  /**
81
78
  * Structural view of a Responses-style body mutated by the Lite rewrite.
82
79
  * Loose (`unknown`) property types let the turn transformer (`RequestBody`)
@@ -12,13 +12,9 @@ export interface OpenAICodexResponsesOptions extends StreamOptions {
12
12
  preferWebsockets?: boolean;
13
13
  serviceTier?: ServiceTier;
14
14
  /**
15
- * Responses Lite transport override; defaults to the model's catalog
16
- * `useResponsesLite` flag (codex-rs `use_responses_lite`). Sends
17
- * `x-openai-internal-codex-responses-lite: true` on HTTP requests and on the
18
- * WebSocket upgrade (the marker is connection-scoped there, so lite and
19
- * non-lite turns never share a pooled socket), moves instructions/tools
20
- * into input items, strips image detail, and disables parallel tool
21
- * calling — mirroring codex-rs.
15
+ * Responses Lite transport opt-in. Normal inference defaults to full
16
+ * Responses; provider-native compaction explicitly follows the model's
17
+ * `useResponsesLite` flag.
22
18
  */
23
19
  responsesLite?: boolean;
24
20
  /**
@@ -56,7 +56,7 @@ export interface OpenAIRequestSetupOptions {
56
56
  apiVersion: string;
57
57
  deploymentName: string;
58
58
  };
59
- openAISessionId?: string;
59
+ sessionId?: string;
60
60
  promptCacheSessionId?: string;
61
61
  }
62
62
  export interface OpenAIRequestSetup {
@@ -1,10 +1,3 @@
1
- export declare const amazonBedrockProvider: {
2
- readonly id: "amazon-bedrock";
3
- readonly name: "Amazon Bedrock";
4
- readonly envKeys: () => string | undefined;
5
- readonly mapSimpleOptions: (options: import("../index.js").SimpleStreamOptions) => {
6
- region: string | undefined;
7
- profile: string | undefined;
8
- bearerToken: string | undefined;
9
- };
10
- };
1
+ import type { ProviderTransport } from "./build.js";
2
+ /** Amazon Bedrock request shaping; auth policy lives in `rules/auth/amazon-bedrock.kdl`. */
3
+ export declare const amazonBedrockTransport: ProviderTransport;
@@ -1,22 +1,3 @@
1
- import type { Model } from "../types.js";
2
- import { resolveAwsRegistryApiKey } from "./aws.js";
3
- export declare const bedrockMantleProvider: {
4
- readonly id: "bedrock-mantle";
5
- readonly name: "Amazon Bedrock Mantle";
6
- readonly envKeys: typeof resolveAwsRegistryApiKey;
7
- readonly allowsMissingApiKey: true;
8
- readonly prepareRequest: (model: Model<import("@oh-my-pi/pi-catalog").Api>, options: import("../index.js").StreamOptions) => import("../providers/bedrock-mantle.js").PreparedBedrockMantleRequest;
9
- readonly mapSimpleOptions: (options: import("../index.js").SimpleStreamOptions) => {
10
- providerOptions: Readonly<Record<string, unknown>> | undefined;
11
- };
12
- readonly prepareModelDiscovery: (config: import("./types.js").ProviderModelDiscoveryConfig) => {
13
- baseUrl?: string;
14
- fetch?: import("@oh-my-pi/pi-utils").FetchImpl;
15
- apiKey: undefined;
16
- authenticated: false;
17
- } | {
18
- authenticated: true;
19
- baseUrl: string;
20
- fetch: import("@oh-my-pi/pi-utils").FetchImpl;
21
- };
22
- };
1
+ import type { ProviderTransport } from "./build.js";
2
+ /** Bedrock Mantle request/discovery shaping; auth policy lives in `rules/auth/bedrock-mantle.kdl`. */
3
+ export declare const bedrockMantleTransport: ProviderTransport;
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Projects one compiled auth policy (`rules/auth/<id>.kdl`) plus the
3
+ * provider's optional TypeScript transport hooks into the
4
+ * {@link ProviderDefinition} the rest of `@oh-my-pi/pi-ai` consumes.
5
+ */
6
+ import type { CompiledAuthProvider } from "@oh-my-pi/pi-catalog/compat/types";
7
+ import type { ProviderDefinition } from "./types.js";
8
+ /** Request/model shaping a provider implements in TypeScript beside its KDL auth policy. */
9
+ export type ProviderTransport = Pick<ProviderDefinition, "prepareModel" | "prepareRequest" | "mapSimpleOptions" | "prepareModelDiscovery">;
10
+ /** Materializes the registry definition for one compiled policy. */
11
+ export declare function buildProviderDefinition(policy: CompiledAuthProvider, transport?: ProviderTransport): ProviderDefinition;
@@ -1,13 +1,3 @@
1
- import type { OAuthController, OAuthLoginCallbacks } from "./oauth/types.js";
2
- /** Collect the gateway credential used by CLI, setup-wizard, and TUI login callers. */
3
- export declare function loginCloudflareAiGateway(options: OAuthController): Promise<string>;
4
- export declare const cloudflareAiGatewayProvider: {
5
- readonly id: "cloudflare-ai-gateway";
6
- readonly name: "Cloudflare AI Gateway";
7
- readonly prepareModel: (model: import("@oh-my-pi/pi-catalog").Model<import("@oh-my-pi/pi-catalog").Api>) => import("@oh-my-pi/pi-catalog").Model<import("@oh-my-pi/pi-catalog").Api>;
8
- readonly prepareRequest: (model: import("@oh-my-pi/pi-catalog").Model<import("@oh-my-pi/pi-catalog").Api>, options: import("../index.js").StreamOptions) => {
9
- model: import("@oh-my-pi/pi-catalog").Model<import("@oh-my-pi/pi-catalog").Api>;
10
- options: import("../index.js").StreamOptions;
11
- };
12
- readonly login: (cb: OAuthLoginCallbacks) => Promise<string>;
13
- };
1
+ import type { ProviderTransport } from "./build.js";
2
+ /** Cloudflare AI Gateway model/request shaping; login lives in `oauth/cloudflare-ai-gateway.ts` + its auth rule. */
3
+ export declare const cloudflareAiGatewayTransport: ProviderTransport;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * `login "api-key"` engine: open the provider's key page, prompt for a paste,
3
+ * optionally validate the key against a declared probe, return the key.
4
+ */
5
+ import type { CompiledApiKeyLogin } from "@oh-my-pi/pi-catalog/compat/types";
6
+ import type { OAuthController } from "../oauth/types.js";
7
+ /** Builds the login function for one `login "api-key"` rule; `label` is the provider display name. */
8
+ export declare function createApiKeyLogin(rule: CompiledApiKeyLogin, label: string): (options: OAuthController) => Promise<string>;
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Shared machinery for the declarative login engines: resolving KDL values
3
+ * (env overrides, obfuscation, hooks), `{placeholder}` templating, token
4
+ * endpoint requests and token-response → `OAuthCredentials` projection.
5
+ */
6
+ import type { CompiledAuthValue, CompiledCredentialMap, CompiledOAuthRequest, CompiledUserinfo } from "@oh-my-pi/pi-catalog/compat/types";
7
+ import type { FetchImpl } from "../../types.js";
8
+ import type { AfterExchangeHook, ExchangeContext, HeadersHook, LoginHook, RefreshHook } from "../hooks/types.js";
9
+ import type { OAuthCredentials } from "../oauth/types.js";
10
+ /** Far-future epoch ms: credentials that never expire (durable minted keys, session JWTs). */
11
+ export declare const NEVER_EXPIRES = 8640000000000000;
12
+ /** Substitution values available to `{placeholder}` templates in KDL params/URLs. */
13
+ export type TemplateVars = Record<string, string | undefined>;
14
+ export declare function loadLoginHook(name: string): Promise<LoginHook>;
15
+ export declare function loadRefreshHook(name: string): Promise<RefreshHook>;
16
+ export declare function loadAfterExchangeHook(name: string): Promise<AfterExchangeHook>;
17
+ export declare function loadHeadersHook(name: string): Promise<HeadersHook>;
18
+ /** Resolves a KDL value node: env overrides first, then the (possibly encoded) literal or hook. */
19
+ export declare function resolveValue(value: CompiledAuthValue, signal?: AbortSignal): Promise<string>;
20
+ /** Replaces `{name}` placeholders; unknown or undefined placeholders resolve to the empty string. */
21
+ export declare function template(text: string, vars: TemplateVars): string;
22
+ /** Reads a dot path (`data.user.email`) from a parsed JSON body. */
23
+ export declare function jsonPath(body: unknown, path: string): unknown;
24
+ /** Decodes a JWT payload without verification; `null` for malformed tokens. */
25
+ export declare function decodeJwtPayload(token: string): Record<string, unknown> | null;
26
+ /** Epoch ms of a JWT `exp` claim minus `skewMs`, or undefined when absent. */
27
+ export declare function jwtExpiryMs(token: string, skewMs: number): number | undefined;
28
+ /**
29
+ * Projects a token response onto `OAuthCredentials` per the rule's
30
+ * `credential` map. A missing refresh token keeps `previous.refresh` (refresh
31
+ * grants that do not rotate) or falls back to the empty string.
32
+ */
33
+ export declare function mapCredentials(map: CompiledCredentialMap, body: unknown, provider: string, previous?: OAuthCredentials): OAuthCredentials;
34
+ export interface RequestContext {
35
+ provider: string;
36
+ fetch: FetchImpl;
37
+ signal?: AbortSignal;
38
+ /** Extra headers merged under the rule's declared headers. */
39
+ headers?: Record<string, string>;
40
+ }
41
+ /**
42
+ * Performs one declared token-style POST. `standardParams` are the grant's
43
+ * baseline (included when the rule keeps `standard=#true`), `params` the
44
+ * rule's declared extras; both are templated with `vars`.
45
+ */
46
+ export declare function postTokenRequest(request: CompiledOAuthRequest, standardParams: Record<string, string | undefined>, vars: TemplateVars, context: RequestContext, errorKind: "token-exchange" | "token-refresh" | "device-auth"): Promise<{
47
+ body: unknown;
48
+ response: Response;
49
+ }>;
50
+ /** Bearer GET declared by `userinfo`; failures leave identity fields unset. */
51
+ export declare function applyUserinfo(userinfo: CompiledUserinfo | undefined, credentials: OAuthCredentials, context: RequestContext): Promise<OAuthCredentials>;
52
+ /** Runs the rule's after-exchange / after-refresh hook, if declared. */
53
+ export declare function applyAfterExchange(hook: string | undefined, credentials: OAuthCredentials, context: ExchangeContext): Promise<OAuthCredentials>;
54
+ export declare function describeError(error: unknown): string;
55
+ export declare function throwIfCancelled(signal: AbortSignal | undefined): void;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * `login "device-code"` engine: RFC 8628 device authorization — request a
3
+ * user code, show the verification URL, poll the token endpoint until the
4
+ * grant completes, then project / enrich the credentials.
5
+ */
6
+ import type { CompiledDeviceCodeLogin } from "@oh-my-pi/pi-catalog/compat/types";
7
+ import type { OAuthController, OAuthCredentials } from "../oauth/types.js";
8
+ /** Builds the login function for one `login "device-code"` rule. */
9
+ export declare function createDeviceCodeLogin(rule: CompiledDeviceCodeLogin, provider: string): (ctrl: OAuthController) => Promise<OAuthCredentials>;
@@ -0,0 +1,27 @@
1
+ /**
2
+ * `login "oauth-code"` engine: authorization-code grant (optionally PKCE)
3
+ * through the loopback callback server, followed by the declared token
4
+ * exchange, credential projection, userinfo enrichment and after-exchange hook.
5
+ */
6
+ import type { CompiledAuthProvider, CompiledCallback, CompiledOAuthCodeLogin } from "@oh-my-pi/pi-catalog/compat/types";
7
+ import { OAuthCallbackFlow, type OAuthCallbackFlowOptions } from "../oauth/callback-server.js";
8
+ import type { OAuthController, OAuthCredentials } from "../oauth/types.js";
9
+ /**
10
+ * Callback-server options for a rule. A `redirect-uri-env` override is
11
+ * advertised verbatim with random-port fallback disabled; HTTP loopback
12
+ * overrides also bind the listener to the URI's host/port/path.
13
+ */
14
+ export declare function resolveCallbackOptions(callback: CompiledCallback, provider: string, signal?: AbortSignal): Promise<OAuthCallbackFlowOptions>;
15
+ /** Generic authorization-code flow driven by one compiled rule. */
16
+ export declare class DeclarativeOAuthCodeFlow extends OAuthCallbackFlow {
17
+ #private;
18
+ constructor(ctrl: OAuthController, rule: CompiledOAuthCodeLogin, policy: CompiledAuthProvider, options: OAuthCallbackFlowOptions);
19
+ generateState(): string;
20
+ generateAuthUrl(state: string, redirectUri: string): Promise<{
21
+ url: string;
22
+ instructions?: string;
23
+ }>;
24
+ exchangeToken(code: string, state: string, redirectUri: string): Promise<OAuthCredentials>;
25
+ }
26
+ /** Builds the login function for one `login "oauth-code"` rule. */
27
+ export declare function createOAuthCodeLogin(rule: CompiledOAuthCodeLogin, policy: CompiledAuthProvider): (ctrl: OAuthController) => Promise<OAuthCredentials>;