@linxiraos/pi-ai 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (639) hide show
  1. package/CHANGELOG.md +5066 -0
  2. package/README.md +1195 -0
  3. package/dist/types/api-registry.d.ts +30 -0
  4. package/dist/types/auth/sqlite-credential-store.d.ts +117 -0
  5. package/dist/types/auth-broker/client.d.ts +93 -0
  6. package/dist/types/auth-broker/discover.d.ts +39 -0
  7. package/dist/types/auth-broker/index.d.ts +7 -0
  8. package/dist/types/auth-broker/refresher.d.ts +25 -0
  9. package/dist/types/auth-broker/remote-store.d.ts +136 -0
  10. package/dist/types/auth-broker/server.d.ts +48 -0
  11. package/dist/types/auth-broker/snapshot-cache.d.ts +17 -0
  12. package/dist/types/auth-broker/types.d.ts +152 -0
  13. package/dist/types/auth-broker/wire-schema-resource.d.ts +53 -0
  14. package/dist/types/auth-broker/wire-schemas.d.ts +5 -0
  15. package/dist/types/auth-gateway/http.d.ts +56 -0
  16. package/dist/types/auth-gateway/index.d.ts +3 -0
  17. package/dist/types/auth-gateway/server.d.ts +36 -0
  18. package/dist/types/auth-gateway/types.d.ts +127 -0
  19. package/dist/types/auth-retry.d.ts +150 -0
  20. package/dist/types/auth-storage.d.ts +1258 -0
  21. package/dist/types/dialect/anthropic.d.ts +15 -0
  22. package/dist/types/dialect/catalog.d.ts +3 -0
  23. package/dist/types/dialect/coercion.d.ts +23 -0
  24. package/dist/types/dialect/deepseek.d.ts +14 -0
  25. package/dist/types/dialect/demotion.d.ts +30 -0
  26. package/dist/types/dialect/examples.d.ts +18 -0
  27. package/dist/types/dialect/factory.d.ts +3 -0
  28. package/dist/types/dialect/fenced-thinking.d.ts +53 -0
  29. package/dist/types/dialect/gemini.d.ts +17 -0
  30. package/dist/types/dialect/gemma.d.ts +15 -0
  31. package/dist/types/dialect/glm.d.ts +9 -0
  32. package/dist/types/dialect/harmony.d.ts +8 -0
  33. package/dist/types/dialect/hermes.d.ts +9 -0
  34. package/dist/types/dialect/history.d.ts +3 -0
  35. package/dist/types/dialect/index.d.ts +11 -0
  36. package/dist/types/dialect/inventory.d.ts +9 -0
  37. package/dist/types/dialect/kimi.d.ts +14 -0
  38. package/dist/types/dialect/minimax.d.ts +3 -0
  39. package/dist/types/dialect/owned-stream.d.ts +4 -0
  40. package/dist/types/dialect/qwen3.d.ts +9 -0
  41. package/dist/types/dialect/rendering.d.ts +54 -0
  42. package/dist/types/dialect/thinking.d.ts +6 -0
  43. package/dist/types/dialect/types.d.ts +68 -0
  44. package/dist/types/dialect/xml.d.ts +9 -0
  45. package/dist/types/error/abort.d.ts +14 -0
  46. package/dist/types/error/auth-classify.d.ts +20 -0
  47. package/dist/types/error/auth.d.ts +27 -0
  48. package/dist/types/error/aws.d.ts +27 -0
  49. package/dist/types/error/classes.d.ts +106 -0
  50. package/dist/types/error/finalize.d.ts +39 -0
  51. package/dist/types/error/flags.d.ts +94 -0
  52. package/dist/types/error/format.d.ts +20 -0
  53. package/dist/types/error/gateway.d.ts +20 -0
  54. package/dist/types/error/index.d.ts +14 -0
  55. package/dist/types/error/oauth.d.ts +43 -0
  56. package/dist/types/error/provider.d.ts +42 -0
  57. package/dist/types/error/rate-limit.d.ts +80 -0
  58. package/dist/types/error/retryable.d.ts +27 -0
  59. package/dist/types/error/validation.d.ts +32 -0
  60. package/dist/types/index.d.ts +51 -0
  61. package/dist/types/provider-details.d.ts +24 -0
  62. package/dist/types/providers/amazon-bedrock.d.ts +39 -0
  63. package/dist/types/providers/anthropic-client.d.ts +106 -0
  64. package/dist/types/providers/anthropic-messages-server-schema.d.ts +937 -0
  65. package/dist/types/providers/anthropic-messages-server.d.ts +17 -0
  66. package/dist/types/providers/anthropic-wire.d.ts +345 -0
  67. package/dist/types/providers/anthropic.d.ts +261 -0
  68. package/dist/types/providers/aws-credentials.d.ts +48 -0
  69. package/dist/types/providers/aws-eventstream.d.ts +39 -0
  70. package/dist/types/providers/aws-sigv4.d.ts +55 -0
  71. package/dist/types/providers/azure-openai-responses.d.ts +16 -0
  72. package/dist/types/providers/bedrock-mantle.d.ts +13 -0
  73. package/dist/types/providers/claude-code-fingerprint.d.ts +19 -0
  74. package/dist/types/providers/cowork-fetch.d.ts +3 -0
  75. package/dist/types/providers/cursor/exec-modern.d.ts +98 -0
  76. package/dist/types/providers/cursor-pi-args.d.ts +105 -0
  77. package/dist/types/providers/cursor.d.ts +221 -0
  78. package/dist/types/providers/devin.d.ts +12 -0
  79. package/dist/types/providers/error-message.d.ts +25 -0
  80. package/dist/types/providers/github-copilot-headers.d.ts +40 -0
  81. package/dist/types/providers/gitlab-duo-workflow.d.ts +254 -0
  82. package/dist/types/providers/gitlab-duo.d.ts +27 -0
  83. package/dist/types/providers/google-auth.d.ts +24 -0
  84. package/dist/types/providers/google-gemini-cli.d.ts +120 -0
  85. package/dist/types/providers/google-shared.d.ts +203 -0
  86. package/dist/types/providers/google-types.d.ts +155 -0
  87. package/dist/types/providers/google-vertex.d.ts +7 -0
  88. package/dist/types/providers/google.d.ts +4 -0
  89. package/dist/types/providers/grammar.d.ts +1 -0
  90. package/dist/types/providers/kimi.d.ts +27 -0
  91. package/dist/types/providers/mock.d.ts +179 -0
  92. package/dist/types/providers/ollama.d.ts +8 -0
  93. package/dist/types/providers/openai-anthropic-shim.d.ts +35 -0
  94. package/dist/types/providers/openai-chat-server-schema.d.ts +1311 -0
  95. package/dist/types/providers/openai-chat-server.d.ts +16 -0
  96. package/dist/types/providers/openai-chat-wire.d.ts +669 -0
  97. package/dist/types/providers/openai-codex/request-transformer.d.ts +109 -0
  98. package/dist/types/providers/openai-codex/response-handler.d.ts +26 -0
  99. package/dist/types/providers/openai-codex-responses.d.ts +238 -0
  100. package/dist/types/providers/openai-completions.d.ts +48 -0
  101. package/dist/types/providers/openai-reasoning-fallback.d.ts +25 -0
  102. package/dist/types/providers/openai-responses-server-schema.d.ts +1314 -0
  103. package/dist/types/providers/openai-responses-server.d.ts +17 -0
  104. package/dist/types/providers/openai-responses-wire.d.ts +6099 -0
  105. package/dist/types/providers/openai-responses.d.ts +131 -0
  106. package/dist/types/providers/openai-shared.d.ts +624 -0
  107. package/dist/types/providers/pi-native-client.d.ts +13 -0
  108. package/dist/types/providers/pi-native-server.d.ts +69 -0
  109. package/dist/types/providers/register-builtins.d.ts +37 -0
  110. package/dist/types/providers/synthetic.d.ts +26 -0
  111. package/dist/types/providers/transform-messages.d.ts +32 -0
  112. package/dist/types/providers/vision-guard.d.ts +20 -0
  113. package/dist/types/registry/aiand.d.ts +7 -0
  114. package/dist/types/registry/aimlapi.d.ts +4 -0
  115. package/dist/types/registry/alibaba-coding-plan.d.ts +8 -0
  116. package/dist/types/registry/alibaba-token-plan.d.ts +18 -0
  117. package/dist/types/registry/amazon-bedrock.d.ts +5 -0
  118. package/dist/types/registry/anthropic.d.ts +10 -0
  119. package/dist/types/registry/api-key-login.d.ts +42 -0
  120. package/dist/types/registry/api-key-validation.d.ts +43 -0
  121. package/dist/types/registry/aws.d.ts +13 -0
  122. package/dist/types/registry/azure.d.ts +4 -0
  123. package/dist/types/registry/baseten.d.ts +7 -0
  124. package/dist/types/registry/bedrock-mantle.d.ts +22 -0
  125. package/dist/types/registry/cerebras.d.ts +7 -0
  126. package/dist/types/registry/cloudflare-ai-gateway.d.ts +13 -0
  127. package/dist/types/registry/coreweave.d.ts +7 -0
  128. package/dist/types/registry/cursor.d.ts +7 -0
  129. package/dist/types/registry/deepseek.d.ts +8 -0
  130. package/dist/types/registry/derived.d.ts +5 -0
  131. package/dist/types/registry/devin.d.ts +8 -0
  132. package/dist/types/registry/exa.d.ts +8 -0
  133. package/dist/types/registry/firepass.d.ts +16 -0
  134. package/dist/types/registry/fireworks.d.ts +7 -0
  135. package/dist/types/registry/github-copilot.d.ts +7 -0
  136. package/dist/types/registry/gitlab-duo-workflow.d.ts +10 -0
  137. package/dist/types/registry/gitlab-duo.d.ts +9 -0
  138. package/dist/types/registry/gmi-cloud.d.ts +7 -0
  139. package/dist/types/registry/google-antigravity.d.ts +9 -0
  140. package/dist/types/registry/google-gemini-cli.d.ts +9 -0
  141. package/dist/types/registry/google-vertex.d.ts +5 -0
  142. package/dist/types/registry/google.d.ts +4 -0
  143. package/dist/types/registry/groq.d.ts +4 -0
  144. package/dist/types/registry/huggingface.d.ts +7 -0
  145. package/dist/types/registry/index.d.ts +4 -0
  146. package/dist/types/registry/kagi.d.ts +14 -0
  147. package/dist/types/registry/kilo.d.ts +7 -0
  148. package/dist/types/registry/kimi-code.d.ts +7 -0
  149. package/dist/types/registry/litellm.d.ts +13 -0
  150. package/dist/types/registry/llama-cpp.d.ts +8 -0
  151. package/dist/types/registry/lm-studio.d.ts +8 -0
  152. package/dist/types/registry/meta.d.ts +7 -0
  153. package/dist/types/registry/minimax-code-cn.d.ts +6 -0
  154. package/dist/types/registry/minimax-code.d.ts +6 -0
  155. package/dist/types/registry/minimax.d.ts +4 -0
  156. package/dist/types/registry/mistral.d.ts +4 -0
  157. package/dist/types/registry/moonshot.d.ts +7 -0
  158. package/dist/types/registry/nanogpt.d.ts +7 -0
  159. package/dist/types/registry/novita.d.ts +6 -0
  160. package/dist/types/registry/nvidia.d.ts +7 -0
  161. package/dist/types/registry/oauth/anthropic-constants.d.ts +12 -0
  162. package/dist/types/registry/oauth/anthropic.d.ts +24 -0
  163. package/dist/types/registry/oauth/callback-server.d.ts +74 -0
  164. package/dist/types/registry/oauth/cursor.d.ts +16 -0
  165. package/dist/types/registry/oauth/device-code.d.ts +25 -0
  166. package/dist/types/registry/oauth/devin.d.ts +5 -0
  167. package/dist/types/registry/oauth/github-copilot.d.ts +30 -0
  168. package/dist/types/registry/oauth/gitlab-duo-workflow.d.ts +6 -0
  169. package/dist/types/registry/oauth/gitlab-duo.d.ts +3 -0
  170. package/dist/types/registry/oauth/google-antigravity.d.ts +11 -0
  171. package/dist/types/registry/oauth/google-gemini-cli.d.ts +22 -0
  172. package/dist/types/registry/oauth/google-oauth-shared.d.ts +56 -0
  173. package/dist/types/registry/oauth/index.d.ts +45 -0
  174. package/dist/types/registry/oauth/kimi.d.ts +21 -0
  175. package/dist/types/registry/oauth/minimax-code.d.ts +27 -0
  176. package/dist/types/registry/oauth/openai-codex.d.ts +33 -0
  177. package/dist/types/registry/oauth/opencode.d.ts +18 -0
  178. package/dist/types/registry/oauth/perplexity.d.ts +9 -0
  179. package/dist/types/registry/oauth/pkce.d.ts +8 -0
  180. package/dist/types/registry/oauth/types.d.ts +87 -0
  181. package/dist/types/registry/oauth/wafer.d.ts +1 -0
  182. package/dist/types/registry/oauth/xai-oauth.d.ts +46 -0
  183. package/dist/types/registry/oauth/xiaomi.d.ts +25 -0
  184. package/dist/types/registry/oauth/zai.d.ts +25 -0
  185. package/dist/types/registry/ollama-cloud.d.ts +7 -0
  186. package/dist/types/registry/ollama.d.ts +12 -0
  187. package/dist/types/registry/openai-codex-device.d.ts +8 -0
  188. package/dist/types/registry/openai-codex.d.ts +9 -0
  189. package/dist/types/registry/openai.d.ts +4 -0
  190. package/dist/types/registry/opencode-go.d.ts +6 -0
  191. package/dist/types/registry/opencode-zen.d.ts +6 -0
  192. package/dist/types/registry/openrouter.d.ts +13 -0
  193. package/dist/types/registry/parallel.d.ts +14 -0
  194. package/dist/types/registry/perplexity.d.ts +7 -0
  195. package/dist/types/registry/qianfan.d.ts +7 -0
  196. package/dist/types/registry/qwen-portal.d.ts +7 -0
  197. package/dist/types/registry/registry.d.ts +367 -0
  198. package/dist/types/registry/sakana.d.ts +7 -0
  199. package/dist/types/registry/siliconflow-cn.d.ts +7 -0
  200. package/dist/types/registry/siliconflow.d.ts +7 -0
  201. package/dist/types/registry/synthetic.d.ts +6 -0
  202. package/dist/types/registry/tavily.d.ts +14 -0
  203. package/dist/types/registry/together.d.ts +6 -0
  204. package/dist/types/registry/types.d.ts +75 -0
  205. package/dist/types/registry/umans.d.ts +7 -0
  206. package/dist/types/registry/venice.d.ts +13 -0
  207. package/dist/types/registry/vercel-ai-gateway.d.ts +7 -0
  208. package/dist/types/registry/vllm.d.ts +7 -0
  209. package/dist/types/registry/wafer-serverless.d.ts +6 -0
  210. package/dist/types/registry/xai-oauth.d.ts +7 -0
  211. package/dist/types/registry/xai.d.ts +7 -0
  212. package/dist/types/registry/xiaomi-token-plan-ams.d.ts +6 -0
  213. package/dist/types/registry/xiaomi-token-plan-cn.d.ts +6 -0
  214. package/dist/types/registry/xiaomi-token-plan-sgp.d.ts +6 -0
  215. package/dist/types/registry/xiaomi.d.ts +6 -0
  216. package/dist/types/registry/zai.d.ts +15 -0
  217. package/dist/types/registry/zenmux.d.ts +7 -0
  218. package/dist/types/registry/zhipu-coding-plan.d.ts +7 -0
  219. package/dist/types/stream.d.ts +46 -0
  220. package/dist/types/types.d.ts +1064 -0
  221. package/dist/types/usage/alibaba-token-plan.d.ts +3 -0
  222. package/dist/types/usage/claude.d.ts +4 -0
  223. package/dist/types/usage/cursor.d.ts +4 -0
  224. package/dist/types/usage/gemini.d.ts +2 -0
  225. package/dist/types/usage/github-copilot.d.ts +7 -0
  226. package/dist/types/usage/google-antigravity.d.ts +15 -0
  227. package/dist/types/usage/kimi.d.ts +2 -0
  228. package/dist/types/usage/minimax-code.d.ts +3 -0
  229. package/dist/types/usage/ollama.d.ts +5 -0
  230. package/dist/types/usage/openai-codex-base-url.d.ts +18 -0
  231. package/dist/types/usage/openai-codex-reset.d.ts +88 -0
  232. package/dist/types/usage/openai-codex.d.ts +10 -0
  233. package/dist/types/usage/opencode-go.d.ts +2 -0
  234. package/dist/types/usage/shared.d.ts +1 -0
  235. package/dist/types/usage/synthetic.d.ts +2 -0
  236. package/dist/types/usage/umans.d.ts +2 -0
  237. package/dist/types/usage/xai-oauth.d.ts +12 -0
  238. package/dist/types/usage/zai.d.ts +3 -0
  239. package/dist/types/usage.d.ts +527 -0
  240. package/dist/types/utils/abort.d.ts +25 -0
  241. package/dist/types/utils/anthropic-auth.d.ts +35 -0
  242. package/dist/types/utils/aws-profile.d.ts +17 -0
  243. package/dist/types/utils/block-symbols.d.ts +62 -0
  244. package/dist/types/utils/deterministic-id.d.ts +16 -0
  245. package/dist/types/utils/empty-completion-retry.d.ts +21 -0
  246. package/dist/types/utils/event-stream.d.ts +39 -0
  247. package/dist/types/utils/foundry.d.ts +1 -0
  248. package/dist/types/utils/google-validation.d.ts +2 -0
  249. package/dist/types/utils/harmony-leak.d.ts +135 -0
  250. package/dist/types/utils/http-inspector.d.ts +49 -0
  251. package/dist/types/utils/idle-iterator.d.ts +149 -0
  252. package/dist/types/utils/leaked-thinking-stream.d.ts +33 -0
  253. package/dist/types/utils/openai-http.d.ts +48 -0
  254. package/dist/types/utils/openrouter-headers.d.ts +1 -0
  255. package/dist/types/utils/parse-bind.d.ts +23 -0
  256. package/dist/types/utils/provider-response.d.ts +3 -0
  257. package/dist/types/utils/proxy.d.ts +39 -0
  258. package/dist/types/utils/request-debug.d.ts +29 -0
  259. package/dist/types/utils/retry-after.d.ts +4 -0
  260. package/dist/types/utils/retry.d.ts +14 -0
  261. package/dist/types/utils/schema/adapt.d.ts +24 -0
  262. package/dist/types/utils/schema/compatibility.d.ts +30 -0
  263. package/dist/types/utils/schema/dereference.d.ts +11 -0
  264. package/dist/types/utils/schema/draft.d.ts +10 -0
  265. package/dist/types/utils/schema/equality.d.ts +4 -0
  266. package/dist/types/utils/schema/fields.d.ts +54 -0
  267. package/dist/types/utils/schema/index.d.ts +14 -0
  268. package/dist/types/utils/schema/json-schema-validator.d.ts +20 -0
  269. package/dist/types/utils/schema/meta-validator.d.ts +2 -0
  270. package/dist/types/utils/schema/normalize.d.ts +153 -0
  271. package/dist/types/utils/schema/spill.d.ts +8 -0
  272. package/dist/types/utils/schema/stamps.d.ts +17 -0
  273. package/dist/types/utils/schema/strict-tool-validation.d.ts +16 -0
  274. package/dist/types/utils/schema/types.d.ts +4 -0
  275. package/dist/types/utils/schema/typescript.d.ts +24 -0
  276. package/dist/types/utils/schema/wire.d.ts +52 -0
  277. package/dist/types/utils/sdk-stream-timeout.d.ts +33 -0
  278. package/dist/types/utils/sse-debug.d.ts +5 -0
  279. package/dist/types/utils/stream-markup-healing.d.ts +87 -0
  280. package/dist/types/utils/thinking-loop.d.ts +102 -0
  281. package/dist/types/utils/tool-call-loop-guard.d.ts +26 -0
  282. package/dist/types/utils/tool-choice.d.ts +52 -0
  283. package/dist/types/utils/validation.d.ts +28 -0
  284. package/dist/types/utils.d.ts +57 -0
  285. package/package.json +138 -0
  286. package/src/api-registry.ts +109 -0
  287. package/src/auth/sqlite-credential-store.ts +2066 -0
  288. package/src/auth-broker/client.ts +471 -0
  289. package/src/auth-broker/discover.ts +310 -0
  290. package/src/auth-broker/index.ts +7 -0
  291. package/src/auth-broker/refresher.ts +117 -0
  292. package/src/auth-broker/remote-store.ts +1332 -0
  293. package/src/auth-broker/server.ts +898 -0
  294. package/src/auth-broker/snapshot-cache.ts +200 -0
  295. package/src/auth-broker/types.ts +193 -0
  296. package/src/auth-broker/wire-schema-resource.ts +487 -0
  297. package/src/auth-broker/wire-schemas.ts +43 -0
  298. package/src/auth-gateway/http.ts +227 -0
  299. package/src/auth-gateway/index.ts +3 -0
  300. package/src/auth-gateway/server.ts +836 -0
  301. package/src/auth-gateway/types.ts +153 -0
  302. package/src/auth-retry.ts +401 -0
  303. package/src/auth-storage.ts +6540 -0
  304. package/src/dialect/anthropic.md +31 -0
  305. package/src/dialect/anthropic.ts +608 -0
  306. package/src/dialect/catalog.ts +29 -0
  307. package/src/dialect/coercion.ts +136 -0
  308. package/src/dialect/deepseek.md +24 -0
  309. package/src/dialect/deepseek.ts +609 -0
  310. package/src/dialect/demotion.ts +40 -0
  311. package/src/dialect/examples.ts +71 -0
  312. package/src/dialect/factory.ts +34 -0
  313. package/src/dialect/fenced-thinking.ts +184 -0
  314. package/src/dialect/gemini.md +44 -0
  315. package/src/dialect/gemini.ts +583 -0
  316. package/src/dialect/gemma.md +33 -0
  317. package/src/dialect/gemma.ts +387 -0
  318. package/src/dialect/glm.md +32 -0
  319. package/src/dialect/glm.ts +579 -0
  320. package/src/dialect/harmony.md +31 -0
  321. package/src/dialect/harmony.ts +345 -0
  322. package/src/dialect/hermes.md +25 -0
  323. package/src/dialect/hermes.ts +206 -0
  324. package/src/dialect/history.ts +81 -0
  325. package/src/dialect/index.ts +15 -0
  326. package/src/dialect/inventory.ts +30 -0
  327. package/src/dialect/kimi.md +24 -0
  328. package/src/dialect/kimi.ts +340 -0
  329. package/src/dialect/minimax.md +31 -0
  330. package/src/dialect/minimax.ts +95 -0
  331. package/src/dialect/owned-stream.ts +481 -0
  332. package/src/dialect/prompt-template.md +12 -0
  333. package/src/dialect/qwen3.md +28 -0
  334. package/src/dialect/qwen3.ts +240 -0
  335. package/src/dialect/rendering.ts +304 -0
  336. package/src/dialect/thinking.ts +292 -0
  337. package/src/dialect/types.ts +56 -0
  338. package/src/dialect/xml.md +22 -0
  339. package/src/dialect/xml.ts +90 -0
  340. package/src/error/abort.ts +18 -0
  341. package/src/error/auth-classify.ts +47 -0
  342. package/src/error/auth.ts +48 -0
  343. package/src/error/aws.ts +35 -0
  344. package/src/error/classes.ts +281 -0
  345. package/src/error/finalize.ts +69 -0
  346. package/src/error/flags.ts +602 -0
  347. package/src/error/format.ts +45 -0
  348. package/src/error/gateway.ts +96 -0
  349. package/src/error/index.ts +14 -0
  350. package/src/error/oauth.ts +58 -0
  351. package/src/error/provider.ts +63 -0
  352. package/src/error/rate-limit.ts +303 -0
  353. package/src/error/retryable.ts +70 -0
  354. package/src/error/validation.ts +44 -0
  355. package/src/index.ts +51 -0
  356. package/src/provider-details.ts +90 -0
  357. package/src/providers/amazon-bedrock.ts +1064 -0
  358. package/src/providers/anthropic-client.ts +317 -0
  359. package/src/providers/anthropic-messages-server-schema.ts +252 -0
  360. package/src/providers/anthropic-messages-server.ts +818 -0
  361. package/src/providers/anthropic-wire.ts +359 -0
  362. package/src/providers/anthropic.ts +4539 -0
  363. package/src/providers/aws-credentials.ts +772 -0
  364. package/src/providers/aws-eventstream.ts +181 -0
  365. package/src/providers/aws-sigv4.ts +218 -0
  366. package/src/providers/azure-openai-responses.ts +438 -0
  367. package/src/providers/bedrock-mantle.ts +110 -0
  368. package/src/providers/claude-code-fingerprint.ts +20 -0
  369. package/src/providers/cowork-fetch.ts +201 -0
  370. package/src/providers/cursor/exec-modern.ts +496 -0
  371. package/src/providers/cursor/proto/agent.proto +4533 -0
  372. package/src/providers/cursor/proto/buf.gen.yaml +6 -0
  373. package/src/providers/cursor/proto/buf.yaml +17 -0
  374. package/src/providers/cursor-pi-args.ts +165 -0
  375. package/src/providers/cursor.ts +4689 -0
  376. package/src/providers/devin/proto/buf/validate/validate.proto +468 -0
  377. package/src/providers/devin/proto/buf.gen.yaml +33 -0
  378. package/src/providers/devin/proto/buf.yaml +17 -0
  379. package/src/providers/devin/proto/cel/expr/checked.proto +103 -0
  380. package/src/providers/devin/proto/cel/expr/eval.proto +38 -0
  381. package/src/providers/devin/proto/cel/expr/explain.proto +15 -0
  382. package/src/providers/devin/proto/cel/expr/syntax.proto +113 -0
  383. package/src/providers/devin/proto/cel/expr/value.proto +41 -0
  384. package/src/providers/devin/proto/connectext/grpc/status/v1/status.proto +11 -0
  385. package/src/providers/devin/proto/errorspb/errors.proto +56 -0
  386. package/src/providers/devin/proto/errorspb/hintdetail.proto +7 -0
  387. package/src/providers/devin/proto/errorspb/markers.proto +10 -0
  388. package/src/providers/devin/proto/errorspb/tags.proto +12 -0
  389. package/src/providers/devin/proto/errorspb/testing.proto +6 -0
  390. package/src/providers/devin/proto/exa/analytics_pb/analytics.proto +188 -0
  391. package/src/providers/devin/proto/exa/api_server_pb/api_server.proto +2461 -0
  392. package/src/providers/devin/proto/exa/auth_pb/auth.proto +19 -0
  393. package/src/providers/devin/proto/exa/auto_cascade_common_pb/auto_cascade_common.proto +79 -0
  394. package/src/providers/devin/proto/exa/browser_preview_pb/browser_preview.proto +32 -0
  395. package/src/providers/devin/proto/exa/bug_checker_pb/bug_checker.proto +22 -0
  396. package/src/providers/devin/proto/exa/cascade_plugins_pb/cascade_plugins.proto +262 -0
  397. package/src/providers/devin/proto/exa/chat_client_server_pb/chat_client_server.proto +57 -0
  398. package/src/providers/devin/proto/exa/chat_pb/chat.proto +449 -0
  399. package/src/providers/devin/proto/exa/code_edit/code_edit_pb/code_edit.proto +186 -0
  400. package/src/providers/devin/proto/exa/codeium_common_pb/codeium_common.proto +4157 -0
  401. package/src/providers/devin/proto/exa/context_module_pb/context_module.proto +175 -0
  402. package/src/providers/devin/proto/exa/cortex_pb/cortex.proto +3268 -0
  403. package/src/providers/devin/proto/exa/dev_pb/dev.proto +26 -0
  404. package/src/providers/devin/proto/exa/diff_action_pb/diff_action.proto +75 -0
  405. package/src/providers/devin/proto/exa/eval/pr_eval/datasets_pb/datasets.proto +103 -0
  406. package/src/providers/devin/proto/exa/eval_pb/eval.proto +1315 -0
  407. package/src/providers/devin/proto/exa/extension_server_pb/extension_server.proto +556 -0
  408. package/src/providers/devin/proto/exa/file_system_provider_pb/file_system_provider.proto +75 -0
  409. package/src/providers/devin/proto/exa/index_pb/index.proto +461 -0
  410. package/src/providers/devin/proto/exa/knowledge_base_pb/knowledge_base.proto +144 -0
  411. package/src/providers/devin/proto/exa/language_server_pb/language_server.proto +2385 -0
  412. package/src/providers/devin/proto/exa/model_management_pb/model_management.proto +186 -0
  413. package/src/providers/devin/proto/exa/opensearch_clients_pb/opensearch_clients.proto +503 -0
  414. package/src/providers/devin/proto/exa/product_analytics_pb/product_analytics.proto +37 -0
  415. package/src/providers/devin/proto/exa/prompt_pb/prompt.proto +92 -0
  416. package/src/providers/devin/proto/exa/reactive_component_pb/reactive_component.proto +96 -0
  417. package/src/providers/devin/proto/exa/seat_management_pb/seat_management.proto +2680 -0
  418. package/src/providers/devin/proto/exa/tokenizer_pb/tokenizer.proto +37 -0
  419. package/src/providers/devin/proto/exa/trainer_pb/config.proto +647 -0
  420. package/src/providers/devin/proto/exa/tree_sitter/language_data_pb/language_data.proto +14 -0
  421. package/src/providers/devin/proto/exa/trust_pb/trust.proto +157 -0
  422. package/src/providers/devin/proto/exa/user_analytics_pb/user_analytics.proto +519 -0
  423. package/src/providers/devin/proto/google.golang.org/appengine/internal/base/api_base.proto +28 -0
  424. package/src/providers/devin/proto/google.golang.org/appengine/internal/datastore/datastore_v3.proto +484 -0
  425. package/src/providers/devin/proto/google.golang.org/appengine/internal/log/log_service.proto +136 -0
  426. package/src/providers/devin/proto/google.golang.org/appengine/internal/remote_api/remote_api.proto +42 -0
  427. package/src/providers/devin/proto/google.golang.org/appengine/internal/urlfetch/urlfetch_service.proto +61 -0
  428. package/src/providers/devin/proto/grpc/binlog/v1/binarylog.proto +84 -0
  429. package/src/providers/devin/proto/io/prometheus/client/metrics.proto +98 -0
  430. package/src/providers/devin.ts +679 -0
  431. package/src/providers/error-message.ts +23 -0
  432. package/src/providers/github-copilot-headers.ts +141 -0
  433. package/src/providers/gitlab-duo-workflow-chatml-note.md +1 -0
  434. package/src/providers/gitlab-duo-workflow.ts +3135 -0
  435. package/src/providers/gitlab-duo.ts +399 -0
  436. package/src/providers/google-auth.ts +330 -0
  437. package/src/providers/google-gemini-cli.ts +1370 -0
  438. package/src/providers/google-shared.ts +1122 -0
  439. package/src/providers/google-types.ts +180 -0
  440. package/src/providers/google-vertex.ts +135 -0
  441. package/src/providers/google.ts +47 -0
  442. package/src/providers/grammar.ts +70 -0
  443. package/src/providers/kimi.ts +51 -0
  444. package/src/providers/mock.ts +514 -0
  445. package/src/providers/ollama.ts +776 -0
  446. package/src/providers/openai-anthropic-shim.ts +166 -0
  447. package/src/providers/openai-chat-server-schema.ts +243 -0
  448. package/src/providers/openai-chat-server.ts +752 -0
  449. package/src/providers/openai-chat-wire.ts +859 -0
  450. package/src/providers/openai-codex/request-transformer.ts +491 -0
  451. package/src/providers/openai-codex/response-handler.ts +102 -0
  452. package/src/providers/openai-codex-responses.ts +4716 -0
  453. package/src/providers/openai-completions.ts +2389 -0
  454. package/src/providers/openai-reasoning-fallback.ts +269 -0
  455. package/src/providers/openai-responses-server-schema.ts +397 -0
  456. package/src/providers/openai-responses-server.ts +1466 -0
  457. package/src/providers/openai-responses-wire.ts +6416 -0
  458. package/src/providers/openai-responses.ts +1393 -0
  459. package/src/providers/openai-shared.ts +3500 -0
  460. package/src/providers/pi-native-client.ts +275 -0
  461. package/src/providers/pi-native-server.ts +245 -0
  462. package/src/providers/register-builtins.ts +503 -0
  463. package/src/providers/synthetic.ts +50 -0
  464. package/src/providers/transform-messages.ts +1083 -0
  465. package/src/providers/vision-guard.ts +54 -0
  466. package/src/registry/aiand.ts +22 -0
  467. package/src/registry/aimlapi.ts +6 -0
  468. package/src/registry/alibaba-coding-plan.ts +104 -0
  469. package/src/registry/alibaba-token-plan.ts +125 -0
  470. package/src/registry/amazon-bedrock.ts +22 -0
  471. package/src/registry/anthropic.ts +26 -0
  472. package/src/registry/api-key-login.ts +115 -0
  473. package/src/registry/api-key-validation.ts +145 -0
  474. package/src/registry/aws.ts +57 -0
  475. package/src/registry/azure.ts +6 -0
  476. package/src/registry/baseten.ts +22 -0
  477. package/src/registry/bedrock-mantle.ts +34 -0
  478. package/src/registry/cerebras.ts +23 -0
  479. package/src/registry/cloudflare-ai-gateway.ts +45 -0
  480. package/src/registry/coreweave.ts +40 -0
  481. package/src/registry/cursor.ts +20 -0
  482. package/src/registry/deepseek.ts +46 -0
  483. package/src/registry/derived.ts +9 -0
  484. package/src/registry/devin.ts +15 -0
  485. package/src/registry/exa.ts +19 -0
  486. package/src/registry/firepass.ts +32 -0
  487. package/src/registry/fireworks.ts +28 -0
  488. package/src/registry/github-copilot.ts +22 -0
  489. package/src/registry/gitlab-duo-workflow.ts +20 -0
  490. package/src/registry/gitlab-duo.ts +19 -0
  491. package/src/registry/gmi-cloud.ts +22 -0
  492. package/src/registry/google-antigravity.ts +22 -0
  493. package/src/registry/google-gemini-cli.ts +22 -0
  494. package/src/registry/google-vertex.ts +38 -0
  495. package/src/registry/google.ts +6 -0
  496. package/src/registry/groq.ts +6 -0
  497. package/src/registry/huggingface.ts +29 -0
  498. package/src/registry/index.ts +4 -0
  499. package/src/registry/kagi.ts +46 -0
  500. package/src/registry/kilo.ts +114 -0
  501. package/src/registry/kimi-code.ts +17 -0
  502. package/src/registry/litellm.ts +45 -0
  503. package/src/registry/llama-cpp.ts +35 -0
  504. package/src/registry/lm-studio.ts +31 -0
  505. package/src/registry/meta.ts +22 -0
  506. package/src/registry/minimax-code-cn.ts +12 -0
  507. package/src/registry/minimax-code.ts +12 -0
  508. package/src/registry/minimax.ts +6 -0
  509. package/src/registry/mistral.ts +6 -0
  510. package/src/registry/moonshot.ts +28 -0
  511. package/src/registry/nanogpt.ts +22 -0
  512. package/src/registry/novita.ts +25 -0
  513. package/src/registry/nvidia.ts +61 -0
  514. package/src/registry/oauth/anthropic-constants.ts +12 -0
  515. package/src/registry/oauth/anthropic.ts +346 -0
  516. package/src/registry/oauth/callback-server.ts +438 -0
  517. package/src/registry/oauth/cursor.ts +187 -0
  518. package/src/registry/oauth/device-code.ts +92 -0
  519. package/src/registry/oauth/devin.ts +124 -0
  520. package/src/registry/oauth/github-copilot.ts +369 -0
  521. package/src/registry/oauth/gitlab-duo-workflow.ts +146 -0
  522. package/src/registry/oauth/gitlab-duo.ts +222 -0
  523. package/src/registry/oauth/google-antigravity.ts +225 -0
  524. package/src/registry/oauth/google-gemini-cli.ts +297 -0
  525. package/src/registry/oauth/google-oauth-shared.ts +211 -0
  526. package/src/registry/oauth/index.ts +187 -0
  527. package/src/registry/oauth/kimi.ts +297 -0
  528. package/src/registry/oauth/minimax-code.ts +53 -0
  529. package/src/registry/oauth/oauth.html +317 -0
  530. package/src/registry/oauth/openai-codex.ts +384 -0
  531. package/src/registry/oauth/opencode.ts +50 -0
  532. package/src/registry/oauth/perplexity.ts +228 -0
  533. package/src/registry/oauth/pkce.ts +18 -0
  534. package/src/registry/oauth/types.ts +96 -0
  535. package/src/registry/oauth/wafer.ts +24 -0
  536. package/src/registry/oauth/xai-oauth.ts +559 -0
  537. package/src/registry/oauth/xiaomi.ts +211 -0
  538. package/src/registry/oauth/zai.ts +285 -0
  539. package/src/registry/ollama-cloud.ts +36 -0
  540. package/src/registry/ollama.ts +43 -0
  541. package/src/registry/openai-codex-device.ts +18 -0
  542. package/src/registry/openai-codex.ts +19 -0
  543. package/src/registry/openai.ts +6 -0
  544. package/src/registry/opencode-go.ts +12 -0
  545. package/src/registry/opencode-zen.ts +12 -0
  546. package/src/registry/openrouter.ts +28 -0
  547. package/src/registry/parallel.ts +45 -0
  548. package/src/registry/perplexity.ts +13 -0
  549. package/src/registry/qianfan.ts +27 -0
  550. package/src/registry/qwen-portal.ts +50 -0
  551. package/src/registry/registry.ts +182 -0
  552. package/src/registry/sakana.ts +22 -0
  553. package/src/registry/siliconflow-cn.ts +22 -0
  554. package/src/registry/siliconflow.ts +22 -0
  555. package/src/registry/synthetic.ts +21 -0
  556. package/src/registry/tavily.ts +45 -0
  557. package/src/registry/together.ts +22 -0
  558. package/src/registry/types.ts +86 -0
  559. package/src/registry/umans.ts +23 -0
  560. package/src/registry/venice.ts +33 -0
  561. package/src/registry/vercel-ai-gateway.ts +38 -0
  562. package/src/registry/vllm.ts +34 -0
  563. package/src/registry/wafer-serverless.ts +12 -0
  564. package/src/registry/xai-oauth.ts +17 -0
  565. package/src/registry/xai.ts +22 -0
  566. package/src/registry/xiaomi-token-plan-ams.ts +12 -0
  567. package/src/registry/xiaomi-token-plan-cn.ts +12 -0
  568. package/src/registry/xiaomi-token-plan-sgp.ts +12 -0
  569. package/src/registry/xiaomi.ts +12 -0
  570. package/src/registry/zai.ts +41 -0
  571. package/src/registry/zenmux.ts +22 -0
  572. package/src/registry/zhipu-coding-plan.ts +27 -0
  573. package/src/stream.ts +1944 -0
  574. package/src/types.ts +1243 -0
  575. package/src/usage/alibaba-token-plan.ts +230 -0
  576. package/src/usage/claude.ts +830 -0
  577. package/src/usage/cursor.ts +335 -0
  578. package/src/usage/gemini.ts +258 -0
  579. package/src/usage/github-copilot.ts +424 -0
  580. package/src/usage/google-antigravity.ts +497 -0
  581. package/src/usage/kimi.ts +277 -0
  582. package/src/usage/minimax-code.ts +291 -0
  583. package/src/usage/ollama.ts +41 -0
  584. package/src/usage/openai-codex-base-url.ts +35 -0
  585. package/src/usage/openai-codex-reset.ts +205 -0
  586. package/src/usage/openai-codex.ts +627 -0
  587. package/src/usage/opencode-go.ts +89 -0
  588. package/src/usage/shared.ts +10 -0
  589. package/src/usage/synthetic.ts +180 -0
  590. package/src/usage/umans.ts +192 -0
  591. package/src/usage/xai-oauth.ts +414 -0
  592. package/src/usage/zai.ts +370 -0
  593. package/src/usage.ts +411 -0
  594. package/src/utils/abort.ts +67 -0
  595. package/src/utils/anthropic-auth.ts +93 -0
  596. package/src/utils/aws-profile.ts +88 -0
  597. package/src/utils/block-symbols.ts +78 -0
  598. package/src/utils/deterministic-id.ts +20 -0
  599. package/src/utils/empty-completion-retry.ts +161 -0
  600. package/src/utils/event-stream.ts +202 -0
  601. package/src/utils/foundry.ts +8 -0
  602. package/src/utils/google-validation.ts +25 -0
  603. package/src/utils/harmony-leak.ts +500 -0
  604. package/src/utils/http-inspector.ts +196 -0
  605. package/src/utils/idle-iterator.ts +531 -0
  606. package/src/utils/leaked-thinking-stream.ts +483 -0
  607. package/src/utils/openai-http.ts +119 -0
  608. package/src/utils/openrouter-headers.ts +12 -0
  609. package/src/utils/parse-bind.ts +56 -0
  610. package/src/utils/provider-response.ts +30 -0
  611. package/src/utils/proxy.ts +314 -0
  612. package/src/utils/request-debug.ts +351 -0
  613. package/src/utils/retry-after.ts +121 -0
  614. package/src/utils/retry.ts +77 -0
  615. package/src/utils/schema/CONSTRAINTS.md +168 -0
  616. package/src/utils/schema/adapt.ts +36 -0
  617. package/src/utils/schema/compatibility.ts +435 -0
  618. package/src/utils/schema/dereference.ts +98 -0
  619. package/src/utils/schema/draft.ts +341 -0
  620. package/src/utils/schema/equality.ts +97 -0
  621. package/src/utils/schema/fields.ts +210 -0
  622. package/src/utils/schema/index.ts +14 -0
  623. package/src/utils/schema/json-schema-validator.ts +595 -0
  624. package/src/utils/schema/meta-validator.ts +167 -0
  625. package/src/utils/schema/normalize.ts +2314 -0
  626. package/src/utils/schema/spill.ts +43 -0
  627. package/src/utils/schema/stamps.ts +109 -0
  628. package/src/utils/schema/strict-tool-validation.ts +117 -0
  629. package/src/utils/schema/types.ts +10 -0
  630. package/src/utils/schema/typescript.ts +212 -0
  631. package/src/utils/schema/wire.ts +662 -0
  632. package/src/utils/sdk-stream-timeout.ts +43 -0
  633. package/src/utils/sse-debug.ts +18 -0
  634. package/src/utils/stream-markup-healing.ts +247 -0
  635. package/src/utils/thinking-loop.ts +552 -0
  636. package/src/utils/tool-call-loop-guard.ts +107 -0
  637. package/src/utils/tool-choice.ts +101 -0
  638. package/src/utils/validation.ts +1932 -0
  639. package/src/utils.ts +492 -0
package/README.md ADDED
@@ -0,0 +1,1195 @@
1
+ # @linxiraos/pi-ai
2
+
3
+ Unified LLM API with automatic model discovery, provider configuration, token and cost tracking, and simple context persistence and hand-off to other models mid-session.
4
+
5
+ **Note**: This library only includes models that support tool calling (function calling), as this is essential for agentic workflows.
6
+
7
+ ## Table of Contents
8
+
9
+ - [Supported Providers](#supported-providers)
10
+ - [Installation](#installation)
11
+ - [Quick Start](#quick-start)
12
+ - [Tools](#tools)
13
+ - [Defining Tools](#defining-tools)
14
+ - [Handling Tool Calls](#handling-tool-calls)
15
+ - [Streaming Tool Calls with Partial JSON](#streaming-tool-calls-with-partial-json)
16
+ - [Validating Tool Arguments](#validating-tool-arguments)
17
+ - [Complete Event Reference](#complete-event-reference)
18
+ - [Image Input](#image-input)
19
+ - [Thinking/Reasoning](#thinkingreasoning)
20
+ - [Unified Interface](#unified-interface-streamsimplecompletesimple)
21
+ - [Provider-Specific Options](#provider-specific-options-streamcomplete)
22
+ - [Streaming Thinking Content](#streaming-thinking-content)
23
+ - [Stop Reasons](#stop-reasons)
24
+ - [Error Handling](#error-handling)
25
+ - [Aborting Requests](#aborting-requests)
26
+ - [Continuing After Abort](#continuing-after-abort)
27
+ - [APIs, Models, and Providers](#apis-models-and-providers)
28
+ - [Providers and Models](#providers-and-models)
29
+ - [Querying Providers and Models](#querying-providers-and-models)
30
+ - [Custom Models](#custom-models)
31
+ - [OpenAI Compatibility Settings](#openai-compatibility-settings)
32
+ - [Type Safety](#type-safety)
33
+ - [Cross-Provider Handoffs](#cross-provider-handoffs)
34
+ - [Context Serialization](#context-serialization)
35
+ - [Browser Usage](#browser-usage)
36
+ - [Environment Variables](#environment-variables-nodejs-only)
37
+ - [Checking Environment Variables](#checking-environment-variables)
38
+ - [OAuth Providers](#oauth-providers)
39
+ - [Vertex AI (ADC)](#vertex-ai-adc)
40
+ - [CLI Login](#cli-login)
41
+ - [Programmatic OAuth](#programmatic-oauth)
42
+ - [Login Flow Example](#login-flow-example)
43
+ - [Using OAuth Tokens](#using-oauth-tokens)
44
+ - [Provider Notes](#provider-notes)
45
+ - [License](#license)
46
+
47
+ ## Supported Providers
48
+
49
+ - **OpenAI**
50
+ - **OpenAI Codex** (ChatGPT Plus/Pro subscription, requires OAuth, see below)
51
+ - **Anthropic**
52
+ - **Google**
53
+ - **Vertex AI** (Gemini via Vertex AI)
54
+ - **Mistral**
55
+ - **Groq**
56
+ - **Cerebras**
57
+ - **Together**
58
+ - **Moonshot** (requires `MOONSHOT_API_KEY`)
59
+ - **Qianfan** (requires `QIANFAN_API_KEY`)
60
+ - **NVIDIA** (requires `NVIDIA_API_KEY`)
61
+ - **NanoGPT** (requires `NANO_GPT_API_KEY`)
62
+ - **Novita** (requires `NOVITA_API_KEY`)
63
+ - **Hugging Face Inference**
64
+ - **xAI**
65
+ - **Venice** (requires `VENICE_API_KEY`)
66
+ - **Wafer Serverless** (requires `WAFER_SERVERLESS_API_KEY`; pay-as-you-go)
67
+ - **OpenRouter**
68
+ - **Kilo Gateway** (supports OAuth `/login kilo` or `KILO_API_KEY`)
69
+ - **LiteLLM** (requires `LITELLM_API_KEY`)
70
+ - **zAI** (requires `ZAI_API_KEY`)
71
+ - **Umans AI Coding Plan** (supports `/login umans` or `UMANS_AI_CODING_PLAN_API_KEY`)
72
+ - **MiniMax Token Plan** (requires `MINIMAX_CODE_API_KEY` or `MINIMAX_CODE_CN_API_KEY`)
73
+ - **Xiaomi MiMo** (requires `XIAOMI_API_KEY`)
74
+ - **ZenMux** (requires `ZENMUX_API_KEY`)
75
+ - **Qwen Portal** (supports `QWEN_OAUTH_TOKEN` or `QWEN_PORTAL_API_KEY`)
76
+ - **QwenCloud Token Plan** (supports `/login alibaba-token-plan`, `ALIBABA_TOKEN_PLAN_API_KEY`, or `BAILIAN_TOKEN_PLAN_API_KEY`; interactive login first selects a region — International (Singapore, default), China (Beijing) for 百炼 Token Plan keys, or a custom base URL — since region keys are non-interchangeable, then optionally stores a `home.qwencloud.com` Cookie request header for best-effort 5-hour and 7-day quota reporting)
77
+ To enable quota reporting, sign in to the Token Plan dashboard, copy the `Cookie` request-header value from a `home.qwencloud.com` request in browser developer tools, and paste it at the second login prompt. Press Enter to skip; the Cookie is sensitive and session-lived, so rerun login when it expires.
78
+ - **Cloudflare AI Gateway** (requires `CLOUDFLARE_AI_GATEWAY_API_KEY` and provider-specific gateway base URL)
79
+ - **Ollama** (local OpenAI-compatible runtime; optional `OLLAMA_API_KEY`)
80
+ - **Ollama Cloud** (hosted native Ollama API; requires `OLLAMA_CLOUD_API_KEY`)
81
+ - **llama.cpp** (local OpenAI and Anthropic compatible inference server)
82
+ - **vLLM** (OpenAI-compatible server; `VLLM_API_KEY` for secured deployments)
83
+ - **GitHub Copilot** (requires OAuth, see below)
84
+ - **Google Gemini CLI** (requires OAuth, see below)
85
+ - **Antigravity** (requires OAuth, see below)
86
+ - **Any OpenAI-compatible API**: LM Studio, custom proxies, etc.
87
+
88
+ ## Installation
89
+
90
+ ```bash
91
+ npm install @linxiraos/pi-ai
92
+ ```
93
+
94
+ ## Quick Start
95
+
96
+ ```typescript
97
+ import { getModel, stream, complete, Context, Tool, type } from "@linxiraos/pi-ai";
98
+
99
+ // Fully typed with auto-complete support for both providers and models
100
+ const model = getModel("openai", "gpt-4o-mini");
101
+
102
+ // Define tools with omptype schemas for type safety and validation
103
+ const tools: Tool[] = [
104
+ {
105
+ name: "get_time",
106
+ description: "Get the current time",
107
+ parameters: type({
108
+ "timezone?": type("string").describe("Optional timezone (e.g., America/New_York)"),
109
+ }),
110
+ },
111
+ ];
112
+
113
+ // Build a conversation context (easily serializable and transferable between models)
114
+ const context: Context = {
115
+ systemPrompt: ["You are a helpful assistant."],
116
+ messages: [{ role: "user", content: "What time is it?" }],
117
+ tools,
118
+ };
119
+
120
+ // Option 1: Streaming with all event types
121
+ const s = stream(model, context);
122
+
123
+ for await (const event of s) {
124
+ switch (event.type) {
125
+ case "start":
126
+ console.log(`Starting with ${event.partial.model}`);
127
+ break;
128
+ case "text_start":
129
+ console.log("\n[Text started]");
130
+ break;
131
+ case "text_delta":
132
+ process.stdout.write(event.delta);
133
+ break;
134
+ case "text_end":
135
+ console.log("\n[Text ended]");
136
+ break;
137
+ case "thinking_start":
138
+ console.log("[Model is thinking...]");
139
+ break;
140
+ case "thinking_delta":
141
+ process.stdout.write(event.delta);
142
+ break;
143
+ case "thinking_end":
144
+ console.log("[Thinking complete]");
145
+ break;
146
+ case "toolcall_start":
147
+ console.log(`\n[Tool call started: index ${event.contentIndex}]`);
148
+ break;
149
+ case "toolcall_delta":
150
+ // Partial tool arguments are being streamed
151
+ const partialCall = event.partial.content[event.contentIndex];
152
+ if (partialCall.type === "toolCall") {
153
+ console.log(`[Streaming args for ${partialCall.name}]`);
154
+ }
155
+ break;
156
+ case "toolcall_end":
157
+ console.log(`\nTool called: ${event.toolCall.name}`);
158
+ console.log(`Arguments: ${JSON.stringify(event.toolCall.arguments)}`);
159
+ break;
160
+ case "done":
161
+ console.log(`\nFinished: ${event.reason}`);
162
+ break;
163
+ case "error":
164
+ console.error(`Error: ${event.error}`);
165
+ break;
166
+ }
167
+ }
168
+
169
+ // Get the final message after streaming, add it to the context
170
+ const finalMessage = await s.result();
171
+ context.messages.push(finalMessage);
172
+
173
+ // Handle tool calls if any
174
+ const toolCalls = finalMessage.content.filter((b) => b.type === "toolCall");
175
+ for (const call of toolCalls) {
176
+ // Execute the tool
177
+ const result =
178
+ call.name === "get_time"
179
+ ? new Date().toLocaleString("en-US", {
180
+ timeZone: call.arguments.timezone || "UTC",
181
+ dateStyle: "full",
182
+ timeStyle: "long",
183
+ })
184
+ : "Unknown tool";
185
+
186
+ // Add tool result to context (supports text and images)
187
+ context.messages.push({
188
+ role: "toolResult",
189
+ toolCallId: call.id,
190
+ toolName: call.name,
191
+ content: [{ type: "text", text: result }],
192
+ isError: false,
193
+ timestamp: Date.now(),
194
+ });
195
+ }
196
+
197
+ // Continue if there were tool calls
198
+ if (toolCalls.length > 0) {
199
+ const continuation = await complete(model, context);
200
+ context.messages.push(continuation);
201
+ console.log("After tool execution:", continuation.content);
202
+ }
203
+
204
+ console.log(`Total tokens: ${finalMessage.usage.input} in, ${finalMessage.usage.output} out`);
205
+ console.log(`Cost: $${finalMessage.usage.cost.total.toFixed(4)}`);
206
+
207
+ // Option 2: Get complete response without streaming
208
+ const response = await complete(model, context);
209
+
210
+ for (const block of response.content) {
211
+ if (block.type === "text") {
212
+ console.log(block.text);
213
+ } else if (block.type === "toolCall") {
214
+ console.log(`Tool: ${block.name}(${JSON.stringify(block.arguments)})`);
215
+ }
216
+ }
217
+ ```
218
+
219
+ ## Tools
220
+
221
+ Tools enable LLMs to interact with external systems. Omptype schemas provide type-safe definitions, runtime validation, and JSON Schema conversion for providers.
222
+
223
+ ### Defining Tools
224
+
225
+ ```typescript
226
+ import { type Tool, type } from "@linxiraos/pi-ai";
227
+
228
+ const weatherTool: Tool = {
229
+ name: "get_weather",
230
+ description: "Get current weather for a location",
231
+ parameters: type({
232
+ location: type("string").describe("City name or coordinates"),
233
+ units: type.enumerated("celsius", "fahrenheit").default("celsius"),
234
+ }),
235
+ };
236
+
237
+ const bookMeetingTool: Tool = {
238
+ name: "book_meeting",
239
+ description: "Schedule a meeting",
240
+ parameters: type({
241
+ title: type("string").atLeastLength(1),
242
+ startTime: type("string").describe("ISO 8601 date-time"),
243
+ endTime: type("string").describe("ISO 8601 date-time"),
244
+ attendees: type("string.email").array().atLeastLength(1),
245
+ }),
246
+ };
247
+ ```
248
+
249
+ ### Handling Tool Calls
250
+
251
+ Tool results use content blocks and can include both text and images:
252
+
253
+ ```typescript
254
+ import * as fs from "node:fs";
255
+
256
+ const context: Context = {
257
+ messages: [{ role: "user", content: "What is the weather in London?" }],
258
+ tools: [weatherTool],
259
+ };
260
+
261
+ const response = await complete(model, context);
262
+
263
+ // Check for tool calls in the response
264
+ for (const block of response.content) {
265
+ if (block.type === "toolCall") {
266
+ // Execute your tool with the arguments
267
+ // See "Validating Tool Arguments" section for validation
268
+ const result = await executeWeatherApi(block.arguments);
269
+
270
+ // Add tool result with text content
271
+ context.messages.push({
272
+ role: "toolResult",
273
+ toolCallId: block.id,
274
+ toolName: block.name,
275
+ content: [{ type: "text", text: JSON.stringify(result) }],
276
+ isError: false,
277
+ timestamp: Date.now(),
278
+ });
279
+ }
280
+ }
281
+
282
+ // Tool results can also include images (for vision-capable models)
283
+ const imageBuffer = fs.readFileSync("chart.png");
284
+ context.messages.push({
285
+ role: "toolResult",
286
+ toolCallId: "tool_xyz",
287
+ toolName: "generate_chart",
288
+ content: [
289
+ { type: "text", text: "Generated chart showing temperature trends" },
290
+ { type: "image", data: imageBuffer.toBase64(), mimeType: "image/png" },
291
+ ],
292
+ isError: false,
293
+ timestamp: Date.now(),
294
+ });
295
+ ```
296
+
297
+ ### Streaming Tool Calls with Partial JSON
298
+
299
+ During streaming, tool call arguments are progressively parsed as they arrive. This enables real-time UI updates before the complete arguments are available:
300
+
301
+ ```typescript
302
+ const s = stream(model, context);
303
+
304
+ for await (const event of s) {
305
+ if (event.type === "toolcall_delta") {
306
+ const toolCall = event.partial.content[event.contentIndex];
307
+
308
+ // toolCall.arguments contains partially parsed JSON during streaming
309
+ // This allows for progressive UI updates
310
+ if (toolCall.type === "toolCall" && toolCall.arguments) {
311
+ // BE DEFENSIVE: arguments may be incomplete
312
+ // Example: Show file path being written even before content is complete
313
+ if (toolCall.name === "write_file" && toolCall.arguments.path) {
314
+ console.log(`Writing to: ${toolCall.arguments.path}`);
315
+
316
+ // Content might be partial or missing
317
+ if (toolCall.arguments.content) {
318
+ console.log(`Content preview: ${toolCall.arguments.content.substring(0, 100)}...`);
319
+ }
320
+ }
321
+ }
322
+ }
323
+
324
+ if (event.type === "toolcall_end") {
325
+ // Here toolCall.arguments is complete (but not yet validated)
326
+ const toolCall = event.toolCall;
327
+ console.log(`Tool completed: ${toolCall.name}`, toolCall.arguments);
328
+ }
329
+ }
330
+ ```
331
+
332
+ **Important notes about partial tool arguments:**
333
+
334
+ - During `toolcall_delta` events, `arguments` contains the best-effort parse of partial JSON
335
+ - Fields may be missing or incomplete - always check for existence before use
336
+ - String values may be truncated mid-word
337
+ - Arrays may be incomplete
338
+ - Nested objects may be partially populated
339
+ - At minimum, `arguments` will be an empty object `{}`, never `undefined`
340
+ - The Google provider does not support function call streaming. Instead, you will receive a single `toolcall_delta` event with the full arguments.
341
+
342
+ ### Validating Tool Arguments
343
+
344
+ When using `agentLoop`, tool arguments are automatically validated against their omptype schemas before execution. Validation failures are returned to the model as tool results so it can retry.
345
+
346
+ When implementing your own tool execution loop with `stream()` or `complete()`, use `validateToolCall` to validate arguments before passing them to your tools:
347
+
348
+ ```typescript
349
+ import { stream, validateToolCall, Tool } from "@linxiraos/pi-ai";
350
+
351
+ const tools: Tool[] = [weatherTool, calculatorTool];
352
+ const s = stream(model, { messages, tools });
353
+
354
+ for await (const event of s) {
355
+ if (event.type === "toolcall_end") {
356
+ const toolCall = event.toolCall;
357
+
358
+ try {
359
+ // Validate arguments against the tool's schema (throws on invalid args)
360
+ const validatedArgs = validateToolCall(tools, toolCall);
361
+ const result = await executeMyTool(toolCall.name, validatedArgs);
362
+ // ... add tool result to context
363
+ } catch (error) {
364
+ // Validation failed - return error as tool result so model can retry
365
+ context.messages.push({
366
+ role: "toolResult",
367
+ toolCallId: toolCall.id,
368
+ toolName: toolCall.name,
369
+ content: [{ type: "text", text: error.message }],
370
+ isError: true,
371
+ timestamp: Date.now(),
372
+ });
373
+ }
374
+ }
375
+ }
376
+ ```
377
+
378
+ ### Complete Event Reference
379
+
380
+ All streaming events emitted during assistant message generation:
381
+
382
+ | Event Type | Description | Key Properties |
383
+ | ---------------- | ------------------------ | ------------------------------------------------------------------------------------------- |
384
+ | `start` | Stream begins | `partial`: Initial assistant message structure |
385
+ | `text_start` | Text block starts | `contentIndex`: Position in content array |
386
+ | `text_delta` | Text chunk received | `delta`: New text, `contentIndex`: Position |
387
+ | `text_end` | Text block complete | `content`: Full text, `contentIndex`: Position |
388
+ | `thinking_start` | Thinking block starts | `contentIndex`: Position in content array |
389
+ | `thinking_delta` | Thinking chunk received | `delta`: New text, `contentIndex`: Position |
390
+ | `thinking_end` | Thinking block complete | `content`: Full thinking, `contentIndex`: Position |
391
+ | `toolcall_start` | Tool call begins | `contentIndex`: Position in content array |
392
+ | `toolcall_delta` | Tool arguments streaming | `delta`: JSON chunk, `partial.content[contentIndex].arguments`: Partial parsed args |
393
+ | `toolcall_end` | Tool call complete | `toolCall`: Complete validated tool call with `id`, `name`, `arguments` |
394
+ | `done` | Stream complete | `reason`: Stop reason ("stop", "length", "toolUse"), `message`: Final assistant message |
395
+ | `error` | Error occurred | `reason`: Error type ("error" or "aborted"), `error`: AssistantMessage with partial content |
396
+
397
+ ## Image Input
398
+
399
+ Models with vision capabilities can process images. You can check if a model supports images via the `input` property. If you pass images to a non-vision model, they are silently ignored.
400
+
401
+ ```typescript
402
+ import * as fs from "node:fs";
403
+ import { getModel, complete } from "@linxiraos/pi-ai";
404
+
405
+ const model = getModel("openai", "gpt-4o-mini");
406
+
407
+ // Check if model supports images
408
+ if (model.input.includes("image")) {
409
+ console.log("Model supports vision");
410
+ }
411
+
412
+ const imageBuffer = fs.readFileSync("image.png");
413
+ const base64Image = imageBuffer.toBase64();
414
+
415
+ const response = await complete(model, {
416
+ messages: [
417
+ {
418
+ role: "user",
419
+ content: [
420
+ { type: "text", text: "What is in this image?" },
421
+ { type: "image", data: base64Image, mimeType: "image/png" },
422
+ ],
423
+ },
424
+ ],
425
+ });
426
+
427
+ // Access the response
428
+ for (const block of response.content) {
429
+ if (block.type === "text") {
430
+ console.log(block.text);
431
+ }
432
+ }
433
+ ```
434
+
435
+ ## Thinking/Reasoning
436
+
437
+ Many models support thinking/reasoning capabilities where they can show their internal thought process. You can check if a model supports reasoning via the `reasoning` property. If you pass reasoning options to a non-reasoning model, they are silently ignored.
438
+
439
+ ### Unified Interface (streamSimple/completeSimple)
440
+
441
+ ```typescript
442
+ import { getModel, streamSimple, completeSimple } from "@linxiraos/pi-ai";
443
+
444
+ // Many models across providers support thinking/reasoning
445
+ const model = getModel("anthropic", "claude-sonnet-4-20250514");
446
+ // or getModel('openai', 'gpt-5-mini');
447
+ // or getModel('google', 'gemini-2.5-flash');
448
+ // or getModel('xai', 'grok-code-fast-1');
449
+ // or getModel('groq', 'openai/gpt-oss-20b');
450
+ // or getModel('cerebras', 'gpt-oss-120b');
451
+ // or getModel('openrouter', 'z-ai/glm-4.5v');
452
+
453
+ // Check if model supports reasoning
454
+ if (model.reasoning) {
455
+ console.log("Model supports reasoning/thinking");
456
+ }
457
+
458
+ // Use the simplified reasoning option
459
+ const response = await completeSimple(
460
+ model,
461
+ {
462
+ messages: [{ role: "user", content: "Solve: 2x + 5 = 13" }],
463
+ },
464
+ {
465
+ reasoning: "medium", // 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' (xhigh maps to high on non-OpenAI providers)
466
+ }
467
+ );
468
+
469
+ // Access thinking and text blocks
470
+ for (const block of response.content) {
471
+ if (block.type === "thinking") {
472
+ console.log("Thinking:", block.thinking);
473
+ } else if (block.type === "text") {
474
+ console.log("Response:", block.text);
475
+ }
476
+ }
477
+ ```
478
+
479
+ ### Provider-Specific Options (stream/complete)
480
+
481
+ For fine-grained control, use the provider-specific options:
482
+
483
+ ```typescript
484
+ import { getModel, complete } from "@linxiraos/pi-ai";
485
+
486
+ // OpenAI Reasoning (o1, o3, gpt-5)
487
+ const openaiModel = getModel("openai", "gpt-5-mini");
488
+ await complete(openaiModel, context, {
489
+ reasoningEffort: "medium",
490
+ reasoningSummary: "detailed", // OpenAI Responses API only
491
+ });
492
+
493
+ // Anthropic Thinking (Claude Sonnet 4)
494
+ const anthropicModel = getModel("anthropic", "claude-sonnet-4-20250514");
495
+ await complete(anthropicModel, context, {
496
+ thinkingEnabled: true,
497
+ thinkingBudgetTokens: 8192, // Optional token limit
498
+ });
499
+
500
+ // Google Gemini Thinking
501
+ const googleModel = getModel("google", "gemini-2.5-flash");
502
+ await complete(googleModel, context, {
503
+ thinking: {
504
+ enabled: true,
505
+ budgetTokens: 8192, // -1 for dynamic, 0 to disable
506
+ },
507
+ });
508
+ ```
509
+
510
+ ### Streaming Thinking Content
511
+
512
+ When streaming, thinking content is delivered through specific events:
513
+
514
+ ```typescript
515
+ const s = streamSimple(model, context, { reasoning: "high" });
516
+
517
+ for await (const event of s) {
518
+ switch (event.type) {
519
+ case "thinking_start":
520
+ console.log("[Model started thinking]");
521
+ break;
522
+ case "thinking_delta":
523
+ process.stdout.write(event.delta); // Stream thinking content
524
+ break;
525
+ case "thinking_end":
526
+ console.log("\n[Thinking complete]");
527
+ break;
528
+ }
529
+ }
530
+ ```
531
+
532
+ ## Stop Reasons
533
+
534
+ Every `AssistantMessage` includes a `stopReason` field that indicates how the generation ended:
535
+
536
+ - `"stop"` - Normal completion, the model finished its response
537
+ - `"length"` - Output hit the maximum token limit
538
+ - `"toolUse"` - Model is calling tools and expects tool results
539
+ - `"error"` - An error occurred during generation
540
+ - `"aborted"` - Request was cancelled via abort signal
541
+
542
+ ## Error Handling
543
+
544
+ When a request ends with an error (including aborts and tool call validation errors), the streaming API emits an error event:
545
+
546
+ ```typescript
547
+ // In streaming
548
+ for await (const event of stream) {
549
+ if (event.type === "error") {
550
+ // event.reason is either "error" or "aborted"
551
+ // event.error is the AssistantMessage with partial content
552
+ console.error(`Error (${event.reason}):`, event.error.errorMessage);
553
+ console.log("Partial content:", event.error.content);
554
+ }
555
+ }
556
+
557
+ // The final message will have the error details
558
+ const message = await stream.result();
559
+ if (message.stopReason === "error" || message.stopReason === "aborted") {
560
+ console.error("Request failed:", message.errorMessage);
561
+ // message.content contains any partial content received before the error
562
+ // message.usage contains partial token counts and costs
563
+ }
564
+ ```
565
+
566
+ ### Aborting Requests
567
+
568
+ The abort signal allows you to cancel in-progress requests. Aborted requests have `stopReason === 'aborted'`:
569
+
570
+ ```typescript
571
+ import { getModel, stream } from "@linxiraos/pi-ai";
572
+
573
+ const model = getModel("openai", "gpt-4o-mini");
574
+
575
+ // Abort after 2 seconds
576
+ const signal = AbortSignal.timeout(2000);
577
+
578
+ const s = stream(
579
+ model,
580
+ {
581
+ messages: [{ role: "user", content: "Write a long story" }],
582
+ },
583
+ {
584
+ signal,
585
+ }
586
+ );
587
+
588
+ for await (const event of s) {
589
+ if (event.type === "text_delta") {
590
+ process.stdout.write(event.delta);
591
+ } else if (event.type === "error") {
592
+ // event.reason tells you if it was "error" or "aborted"
593
+ console.log(`${event.reason === "aborted" ? "Aborted" : "Error"}:`, event.error.errorMessage);
594
+ }
595
+ }
596
+
597
+ // Get results (may be partial if aborted)
598
+ const response = await s.result();
599
+ if (response.stopReason === "aborted") {
600
+ console.log("Request was aborted:", response.errorMessage);
601
+ console.log("Partial content received:", response.content);
602
+ console.log("Tokens used:", response.usage);
603
+ }
604
+ ```
605
+
606
+ ### Continuing After Abort
607
+
608
+ Aborted messages can be added to the conversation context and continued in subsequent requests:
609
+
610
+ ```typescript
611
+ const context = {
612
+ messages: [{ role: "user", content: "Explain quantum computing in detail" }],
613
+ };
614
+
615
+ // First request gets aborted after 2 seconds
616
+ const controller1 = new AbortController();
617
+ setTimeout(() => controller1.abort(), 2000);
618
+
619
+ const partial = await complete(model, context, { signal: controller1.signal });
620
+
621
+ // Add the partial response to context
622
+ context.messages.push(partial);
623
+ context.messages.push({ role: "user", content: "Please continue" });
624
+
625
+ // Continue the conversation
626
+ const continuation = await complete(model, context);
627
+ ```
628
+
629
+ ### Common Stream Options
630
+
631
+ All providers accept the base `StreamOptions` (in addition to provider-specific options):
632
+
633
+ - `apiKey`: Override the provider API key
634
+ - `headers`: Extra request headers merged on top of model-defined headers
635
+ - `sessionId`: Provider-specific session identifier (prompt caching/routing)
636
+ - `signal`: Abort in-flight requests
637
+ - `onPayload`: Callback invoked with the provider request payload just before sending
638
+
639
+ Example:
640
+
641
+ ```typescript
642
+ const response = await complete(model, context, {
643
+ apiKey: "sk-live",
644
+ headers: { "X-Debug-Trace": "true" },
645
+ onPayload: (payload) => {
646
+ console.log("request payload", payload);
647
+ },
648
+ });
649
+ ```
650
+
651
+ ## APIs, Models, and Providers
652
+
653
+ The library implements 4 API interfaces, each with its own streaming function and options:
654
+
655
+ - **`anthropic-messages`**: Anthropic's Messages API (`streamAnthropic`, `AnthropicOptions`)
656
+ - **`google-generative-ai`**: Google's Generative AI API (`streamGoogle`, `GoogleOptions`)
657
+ - **`openai-completions`**: OpenAI's Chat Completions API (`streamOpenAICompletions`, `OpenAICompletionsOptions`)
658
+ - **`openai-responses`**: OpenAI's Responses API (`streamOpenAIResponses`, `OpenAIResponsesOptions`)
659
+
660
+ ### Providers and Models
661
+
662
+ A **provider** offers models through a specific API. For example:
663
+
664
+ - **Anthropic** models use the `anthropic-messages` API
665
+ - **Google** models use the `google-generative-ai` API
666
+ - **OpenAI** models use the `openai-responses` API
667
+ - **Mistral, xAI, Cerebras, Groq, etc.** models use the `openai-completions` API (OpenAI-compatible)
668
+
669
+ ### Querying Providers and Models
670
+
671
+ ```typescript
672
+ import { getProviders, getModels, getModel } from "@linxiraos/pi-ai";
673
+
674
+ // Get all available providers
675
+ const providers = getProviders();
676
+ console.log(providers); // ['openai', 'anthropic', 'google', 'xai', 'groq', ...]
677
+
678
+ // Get all models from a provider (fully typed)
679
+ const anthropicModels = getModels("anthropic");
680
+ for (const model of anthropicModels) {
681
+ console.log(`${model.id}: ${model.name}`);
682
+ console.log(` API: ${model.api}`); // 'anthropic-messages'
683
+ console.log(` Context: ${model.contextWindow} tokens`);
684
+ console.log(` Vision: ${model.input.includes("image")}`);
685
+ console.log(` Reasoning: ${model.reasoning}`);
686
+ }
687
+
688
+ // Get a specific model (both provider and model ID are auto-completed in IDEs)
689
+ const model = getModel("openai", "gpt-4o-mini");
690
+ console.log(`Using ${model.name} via ${model.api} API`);
691
+ ```
692
+
693
+ ### Custom Models
694
+
695
+ You can create custom models for local inference servers or custom endpoints.
696
+
697
+ For local Ollama, `OLLAMA_API_KEY` is optional and mainly needed for authenticated/self-hosted gateways. `ollama` remains the local OpenAI-compatible runtime integration.
698
+
699
+ ```typescript
700
+ import { Model, stream } from "@linxiraos/pi-ai";
701
+
702
+ // Example: local Ollama using the OpenAI-compatible API
703
+ const ollamaModel: Model<"openai-completions"> = {
704
+ id: "llama-3.1-8b",
705
+ name: "Llama 3.1 8B (Ollama)",
706
+ api: "openai-completions",
707
+ provider: "ollama",
708
+ baseUrl: "http://localhost:11434/v1",
709
+ reasoning: false,
710
+ input: ["text"],
711
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
712
+ contextWindow: 128000,
713
+ maxTokens: 32000,
714
+ };
715
+
716
+ const localResponse = await stream(ollamaModel, context, {
717
+ apiKey: process.env.OLLAMA_API_KEY, // Optional; local Ollama usually runs without auth
718
+ });
719
+
720
+ // Example: Ollama Cloud using the native /api/chat transport
721
+ const ollamaCloudModel: Model<"ollama-chat"> = {
722
+ id: "gpt-oss:120b",
723
+ name: "GPT OSS 120B (Ollama Cloud)",
724
+ api: "ollama-chat",
725
+ provider: "ollama-cloud",
726
+ baseUrl: "https://ollama.com",
727
+ reasoning: true,
728
+ input: ["text", "image"],
729
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
730
+ contextWindow: 262144,
731
+ maxTokens: 8192,
732
+ };
733
+
734
+ const cloudResponse = await stream(ollamaCloudModel, context, {
735
+ apiKey: process.env.OLLAMA_CLOUD_API_KEY,
736
+ });
737
+
738
+ // Example: LiteLLM proxy with explicit compat settings
739
+ const litellmModel: Model<"openai-completions"> = {
740
+ id: "gpt-4o",
741
+ name: "GPT-4o (via LiteLLM)",
742
+ api: "openai-completions",
743
+ provider: "litellm",
744
+ baseUrl: "http://localhost:4000/v1",
745
+ reasoning: false,
746
+ input: ["text", "image"],
747
+ cost: { input: 2.5, output: 10, cacheRead: 0, cacheWrite: 0 },
748
+ contextWindow: 128000,
749
+ maxTokens: 16384,
750
+ compat: {
751
+ supportsStore: false, // LiteLLM doesn't support the store field
752
+ },
753
+ };
754
+
755
+ // Example: Custom endpoint with headers (bypassing Cloudflare bot detection)
756
+ const proxyModel: Model<"anthropic-messages"> = {
757
+ id: "claude-sonnet-4",
758
+ name: "Claude Sonnet 4 (Proxied)",
759
+ api: "anthropic-messages",
760
+ provider: "custom-proxy",
761
+ baseUrl: "https://proxy.example.com/v1",
762
+ reasoning: true,
763
+ input: ["text", "image"],
764
+ cost: { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
765
+ contextWindow: 200000,
766
+ maxTokens: 8192,
767
+ headers: {
768
+ "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36",
769
+ "X-Custom-Auth": "bearer-token-here",
770
+ },
771
+ };
772
+ ```
773
+
774
+ ### OpenAI Compatibility Settings
775
+
776
+ The `openai-completions` API is implemented by many providers with minor differences. By default, the library auto-detects compatibility settings based on `baseUrl` for known providers (Cerebras, xAI, Mistral, Chutes, etc.). For custom proxies or unknown endpoints, you can override these settings via the `compat` field:
777
+
778
+ ```typescript
779
+ interface OpenAICompat {
780
+ supportsStore?: boolean; // Whether provider supports the `store` field (default: true)
781
+ supportsDeveloperRole?: boolean; // Whether provider supports `developer` role vs `system` (default: true)
782
+ supportsReasoningEffort?: boolean; // Whether provider supports `reasoning_effort` (default: true)
783
+ maxTokensField?: "max_completion_tokens" | "max_tokens"; // Which field name to use (default: max_completion_tokens)
784
+ extraBody?: Record<string, unknown>; // Extra request-body fields for custom proxy routing or provider-specific options
785
+ }
786
+ ```
787
+
788
+ If `compat` is not set, the library falls back to URL-based detection. If `compat` is partially set, unspecified fields use the detected defaults. This is useful for:
789
+
790
+ - **LiteLLM proxies**: May not support `store` field
791
+ - **Custom inference servers**: May use non-standard field names
792
+ - **Self-hosted endpoints**: May have different feature support
793
+
794
+ ### Type Safety
795
+
796
+ Models are typed by their API, ensuring type-safe options:
797
+
798
+ ```typescript
799
+ // TypeScript knows this is an Anthropic model
800
+ const claude = getModel("anthropic", "claude-sonnet-4-20250514");
801
+
802
+ // So these options are type-checked for AnthropicOptions
803
+ await stream(claude, context, {
804
+ thinkingEnabled: true, // ✓ Valid for anthropic-messages
805
+ thinkingBudgetTokens: 2048, // ✓ Valid for anthropic-messages
806
+ // reasoningEffort: 'high' // ✗ TypeScript error: not valid for anthropic-messages
807
+ });
808
+ ```
809
+
810
+ ## Cross-Provider Handoffs
811
+
812
+ The library supports seamless handoffs between different LLM providers within the same conversation. This allows you to switch models mid-conversation while preserving context, including thinking blocks, tool calls, and tool results.
813
+
814
+ ### How It Works
815
+
816
+ When messages from one provider are sent to a different provider, the library automatically transforms them for compatibility:
817
+
818
+ - **User and tool result messages** are passed through unchanged
819
+ - **Assistant messages from the same provider/API** are preserved as-is
820
+ - **Assistant messages from different providers** have their thinking blocks converted to text with `<thinking>` tags
821
+ - **Tool calls and regular text** are preserved unchanged
822
+
823
+ ### Example: Multi-Provider Conversation
824
+
825
+ ```typescript
826
+ import { getModel, complete, Context } from "@linxiraos/pi-ai";
827
+
828
+ // Start with Claude
829
+ const claude = getModel("anthropic", "claude-sonnet-4-20250514");
830
+ const context: Context = {
831
+ messages: [],
832
+ };
833
+
834
+ context.messages.push({ role: "user", content: "What is 25 * 18?" });
835
+ const claudeResponse = await complete(claude, context, {
836
+ thinkingEnabled: true,
837
+ });
838
+ context.messages.push(claudeResponse);
839
+
840
+ // Switch to GPT-5 - it will see Claude's thinking as <thinking> tagged text
841
+ const gpt5 = getModel("openai", "gpt-5-mini");
842
+ context.messages.push({ role: "user", content: "Is that calculation correct?" });
843
+ const gptResponse = await complete(gpt5, context);
844
+ context.messages.push(gptResponse);
845
+
846
+ // Switch to Gemini
847
+ const gemini = getModel("google", "gemini-2.5-flash");
848
+ context.messages.push({ role: "user", content: "What was the original question?" });
849
+ const geminiResponse = await complete(gemini, context);
850
+ ```
851
+
852
+ ### Provider Compatibility
853
+
854
+ All providers can handle messages from other providers, including:
855
+
856
+ - Text content
857
+ - Tool calls and tool results (including images in tool results)
858
+ - Thinking/reasoning blocks (transformed to tagged text for cross-provider compatibility)
859
+ - Aborted messages with partial content
860
+
861
+ This enables flexible workflows where you can:
862
+
863
+ - Start with a fast model for initial responses
864
+ - Switch to a more capable model for complex reasoning
865
+ - Use specialized models for specific tasks
866
+ - Maintain conversation continuity across provider outages
867
+
868
+ ## Context Serialization
869
+
870
+ The `Context` object can be easily serialized and deserialized using standard JSON methods, making it simple to persist conversations, implement chat history, or transfer contexts between services:
871
+
872
+ ```typescript
873
+ import { Context, getModel, complete } from "@linxiraos/pi-ai";
874
+
875
+ // Create and use a context
876
+ const context: Context = {
877
+ systemPrompt: ["You are a helpful assistant."],
878
+ messages: [{ role: "user", content: "What is TypeScript?" }],
879
+ };
880
+
881
+ const model = getModel("openai", "gpt-4o-mini");
882
+ const response = await complete(model, context);
883
+ context.messages.push(response);
884
+
885
+ // Serialize the entire context
886
+ const serialized = JSON.stringify(context);
887
+ console.log("Serialized context size:", serialized.length, "bytes");
888
+
889
+ // Save to database, localStorage, file, etc.
890
+ localStorage.setItem("conversation", serialized);
891
+
892
+ // Later: deserialize and continue the conversation
893
+ const restored: Context = JSON.parse(localStorage.getItem("conversation")!);
894
+ restored.messages.push({ role: "user", content: "Tell me more about its type system" });
895
+
896
+ // Continue with any model
897
+ const newModel = getModel("anthropic", "claude-haiku-4-5-20251001");
898
+ const continuation = await complete(newModel, restored);
899
+ ```
900
+
901
+ > **Note**: If the context contains images (encoded as base64 as shown in the Image Input section), those will also be serialized.
902
+
903
+ ## Browser Usage
904
+
905
+ The library supports browser environments. You must pass the API key explicitly since environment variables are not available in browsers:
906
+
907
+ ```typescript
908
+ import { getModel, complete } from "@linxiraos/pi-ai";
909
+
910
+ // API key must be passed explicitly in browser
911
+ const model = getModel("anthropic", "claude-haiku-4-5-20251001");
912
+
913
+ const response = await complete(
914
+ model,
915
+ {
916
+ messages: [{ role: "user", content: "Hello!" }],
917
+ },
918
+ {
919
+ apiKey: "your-api-key",
920
+ }
921
+ );
922
+ ```
923
+
924
+ > **Security Warning**: Exposing API keys in frontend code is dangerous. Anyone can extract and abuse your keys. Only use this approach for internal tools or demos. For production applications, use a backend proxy that keeps your API keys secure.
925
+
926
+ ### Environment Variables (Node.js only)
927
+
928
+ In Node.js environments, you can set environment variables to avoid passing API keys:
929
+
930
+ | Provider | Environment Variable(s) |
931
+ | -------------- | ---------------------------------------------------------------------------- |
932
+ | OpenAI | `OPENAI_API_KEY` |
933
+ | Anthropic | `ANTHROPIC_API_KEY` or `ANTHROPIC_OAUTH_TOKEN` (or `ANTHROPIC_FOUNDRY_API_KEY` when `CLAUDE_CODE_USE_FOUNDRY=true`) |
934
+ | Google | `GEMINI_API_KEY` |
935
+ | Vertex AI | `GOOGLE_CLOUD_PROJECT` (or `GCLOUD_PROJECT`) + `GOOGLE_CLOUD_LOCATION` + ADC |
936
+ | Mistral | `MISTRAL_API_KEY` |
937
+ | Groq | `GROQ_API_KEY` |
938
+ | Cerebras | `CEREBRAS_API_KEY` |
939
+ | Together | `TOGETHER_API_KEY` |
940
+ | Qianfan | `QIANFAN_API_KEY` |
941
+ | Hugging Face | `HUGGINGFACE_HUB_TOKEN` or `HF_TOKEN` |
942
+ | Synthetic | `SYNTHETIC_API_KEY` |
943
+ | NVIDIA | `NVIDIA_API_KEY` |
944
+ | NanoGPT | `NANO_GPT_API_KEY` |
945
+ | Novita | `NOVITA_API_KEY` |
946
+ | Venice | `VENICE_API_KEY` |
947
+ | Moonshot | `MOONSHOT_API_KEY` |
948
+ | xAI | `XAI_API_KEY` |
949
+ | OpenRouter | `OPENROUTER_API_KEY` |
950
+ | LiteLLM | `LITELLM_API_KEY` |
951
+ | Ollama | `OLLAMA_API_KEY` (optional for local deployments) |
952
+ | Ollama Cloud | `OLLAMA_CLOUD_API_KEY` |
953
+ | Qwen Portal | `QWEN_OAUTH_TOKEN` or `QWEN_PORTAL_API_KEY` |
954
+ | QwenCloud Token Plan | `ALIBABA_TOKEN_PLAN_API_KEY` or `BAILIAN_TOKEN_PLAN_API_KEY` |
955
+ | zAI | `ZAI_API_KEY` |
956
+ | Umans AI Coding Plan | `UMANS_AI_CODING_PLAN_API_KEY` |
957
+ | MiniMax Code | `MINIMAX_CODE_API_KEY` (international) or `MINIMAX_CODE_CN_API_KEY` (China) |
958
+ | Xiaomi MiMo | `XIAOMI_API_KEY` |
959
+ | ZenMux | `ZENMUX_API_KEY` |
960
+ | vLLM | `VLLM_API_KEY` |
961
+ | Cloudflare AI Gateway | `CLOUDFLARE_AI_GATEWAY_API_KEY` |
962
+ | GitHub Copilot | `COPILOT_GITHUB_TOKEN` or `GH_TOKEN` or `GITHUB_TOKEN` |
963
+
964
+ For Cloudflare AI Gateway models, use provider base URL format
965
+ `https://gateway.ai.cloudflare.com/v1/<account>/<gateway>/anthropic`.
966
+
967
+ For Anthropic Foundry routing, set `CLAUDE_CODE_USE_FOUNDRY=true` plus:
968
+ `FOUNDRY_BASE_URL`, `ANTHROPIC_FOUNDRY_API_KEY`, optional `ANTHROPIC_CUSTOM_HEADERS`,
969
+ and optional mTLS material (`CLAUDE_CODE_CLIENT_CERT`, `CLAUDE_CODE_CLIENT_KEY`).
970
+
971
+ `NODE_EXTRA_CA_CERTS` (PEM file path or inline PEM, mirroring Node's contract)
972
+ is honoured on every provider fetch — OpenAI-compatible, Codex, Ollama, Azure
973
+ Responses, Google, and Anthropic alike — for corporate relays or private CA
974
+ bundles. Bun's `fetch` does not consume the env var natively, so omp injects
975
+ the bundle into `RequestInit.tls.ca` and seeds the system root store
976
+ alongside it.
977
+
978
+ Provider endpoint defaults for the current OpenAI-compatible integrations:
979
+
980
+ - Together: `https://api.together.xyz/v1`
981
+ - Moonshot: `https://api.moonshot.ai/v1`
982
+ - Qianfan: `https://qianfan.baidubce.com/v2`
983
+ - NVIDIA: `https://integrate.api.nvidia.com/v1`
984
+ - NanoGPT: `https://nano-gpt.com/api/v1`
985
+ - Novita: `https://api.novita.ai/openai/v1`
986
+ - Hugging Face Inference: `https://router.huggingface.co/v1`
987
+ - Venice: `https://api.venice.ai/api/v1`
988
+ - Xiaomi MiMo: `https://api.xiaomimimo.com/anthropic`
989
+ - ZenMux (OpenAI): `https://zenmux.ai/api/v1`
990
+ - ZenMux (Anthropic models): `https://zenmux.ai/api/anthropic`
991
+ - Umans AI Coding Plan: `https://api.code.umans.ai`
992
+ - vLLM: `http://127.0.0.1:8000/v1`
993
+ - Ollama: local OpenAI-compatible runtime (`http://127.0.0.1:11434/v1`)
994
+ - Ollama Cloud: native Ollama API host (`https://ollama.com/api`, configured here as base URL `https://ollama.com`)
995
+ - LiteLLM: `http://localhost:4000/v1`
996
+ - Cloudflare AI Gateway: `https://gateway.ai.cloudflare.com/v1/<account>/<gateway>/anthropic`
997
+ - Qwen Portal: `https://portal.qwen.ai/v1`
998
+ When set, the library automatically uses these keys:
999
+
1000
+ ```typescript
1001
+ // Uses OPENAI_API_KEY from environment
1002
+ const model = getModel("openai", "gpt-4o-mini");
1003
+ const response = await complete(model, context);
1004
+
1005
+ // Or override with explicit key
1006
+ const response = await complete(model, context, {
1007
+ apiKey: "sk-different-key",
1008
+ });
1009
+ ```
1010
+
1011
+ ### Checking Environment Variables
1012
+
1013
+ ```typescript
1014
+ import { getEnvApiKey } from "@linxiraos/pi-ai";
1015
+
1016
+ // Check if an API key is set in environment variables
1017
+ const key = getEnvApiKey("openai"); // checks OPENAI_API_KEY
1018
+ ```
1019
+
1020
+ ## OAuth Providers
1021
+
1022
+ Several providers support OAuth authentication (some also support static API keys):
1023
+
1024
+ - **Anthropic** (Claude Pro/Max subscription)
1025
+ - **OpenAI Codex** (ChatGPT Plus/Pro subscription, access to GPT-5.x Codex models)
1026
+ - **GitHub Copilot** (Copilot subscription)
1027
+ - **Google Gemini CLI** (Gemini 2.0/2.5 via Google Cloud Code Assist; free tier or paid subscription)
1028
+ - **Antigravity** (Free Gemini 3, Claude, GPT-OSS via Google Cloud)
1029
+ - **Qwen Portal** (Qwen OAuth token or API key)
1030
+
1031
+ For paid Cloud Code Assist subscriptions, set `GOOGLE_CLOUD_PROJECT` or `GOOGLE_CLOUD_PROJECT_ID` to your project ID.
1032
+
1033
+ ### Vertex AI (ADC)
1034
+
1035
+ Vertex AI models use Application Default Credentials (ADC):
1036
+
1037
+ - **Local development**: Run `gcloud auth application-default login`
1038
+ - **CI/Production**: Set `GOOGLE_APPLICATION_CREDENTIALS` to point to a service account JSON key file
1039
+
1040
+ Also set `GOOGLE_CLOUD_PROJECT` (or `GCLOUD_PROJECT`) and `GOOGLE_CLOUD_LOCATION`. You can also pass `project`/`location` in the call options.
1041
+
1042
+ Example:
1043
+
1044
+ ```bash
1045
+ # Local (uses your user credentials)
1046
+ gcloud auth application-default login
1047
+ export GOOGLE_CLOUD_PROJECT="my-project"
1048
+ export GOOGLE_CLOUD_LOCATION="us-central1"
1049
+
1050
+ # CI/Production (service account key file)
1051
+ export GOOGLE_APPLICATION_CREDENTIALS="/path/to/service-account.json"
1052
+ ```
1053
+
1054
+ ```typescript
1055
+ import { getModel, complete } from "@linxiraos/pi-ai";
1056
+
1057
+ (async () => {
1058
+ const model = getModel("google-vertex", "gemini-2.5-flash");
1059
+ const response = await complete(model, {
1060
+ messages: [{ role: "user", content: "Hello from Vertex AI" }],
1061
+ });
1062
+
1063
+ for (const block of response.content) {
1064
+ if (block.type === "text") console.log(block.text);
1065
+ }
1066
+ })().catch(console.error);
1067
+ ```
1068
+
1069
+ Official docs: [Application Default Credentials](https://cloud.google.com/docs/authentication/application-default-credentials)
1070
+
1071
+ ### CLI Login
1072
+
1073
+ Authenticate via the [`omp`](https://omp.sh) coding-agent CLI, which drives this library's OAuth/API-key flows in-process and persists into `agent.db`:
1074
+
1075
+ ```bash
1076
+ omp auth-broker login # interactive provider selection
1077
+ omp auth-broker login anthropic # login to a specific provider
1078
+ omp auth-broker login vllm # store vLLM API key (or placeholder for local no-auth)
1079
+ omp auth-broker list # list supported providers
1080
+ omp auth-broker logout # interactive — pick a stored credential to remove
1081
+ ```
1082
+
1083
+ Credentials are saved to `agent.db` in the agent directory. `/login qianfan` opens the Qianfan console and stores the pasted API key.
1084
+
1085
+ `login` supports OAuth providers (Anthropic, OpenAI Codex, GitHub Copilot, Gemini CLI, Antigravity) and API-key onboarding flows.
1086
+
1087
+ For the current API-key onboarding flows, the library covers Together, Moonshot, Qianfan, NVIDIA, NanoGPT, Novita, Hugging Face, Venice, Xiaomi, vLLM, LiteLLM, Cloudflare AI Gateway, Qwen Portal, and Ollama Cloud. Ollama remains the local runtime integration; set `OLLAMA_API_KEY` only when your local or self-hosted deployment enforces bearer auth.
1088
+
1089
+ ### Programmatic OAuth
1090
+
1091
+ The library provides login and token refresh functions. Credential storage is the caller's responsibility.
1092
+
1093
+ ```typescript
1094
+ import {
1095
+ // Login functions (return credentials, do not store)
1096
+ loginAnthropic,
1097
+ loginOpenAICodex,
1098
+ loginGitHubCopilot,
1099
+ loginGeminiCli,
1100
+ loginAntigravity,
1101
+ loginCloudflareAiGateway,
1102
+ loginHuggingface,
1103
+ loginLiteLLM,
1104
+ loginMoonshot,
1105
+ loginNvidia,
1106
+ loginNanoGPT,
1107
+ loginQianfan,
1108
+ loginQwenPortal,
1109
+ loginTogether,
1110
+ loginVenice,
1111
+ loginVllm,
1112
+ loginXiaomi,
1113
+
1114
+ // Token management
1115
+ refreshOAuthToken, // (provider, credentials) => new credentials
1116
+ getOAuthApiKey, // (provider, credentialsMap) => { newCredentials, apiKey } | null
1117
+
1118
+ // Types
1119
+ 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', ...
1120
+ type OAuthCredentials,
1121
+ } from "@linxiraos/pi-ai";
1122
+ ```
1123
+
1124
+ `loginOpenAICodex` accepts an optional `originator` value used in the OAuth flow:
1125
+
1126
+ ```typescript
1127
+ await loginOpenAICodex({
1128
+ onAuth: ({ url }) => console.log(url),
1129
+ originator: "my-cli",
1130
+ });
1131
+ ```
1132
+
1133
+ ### Login Flow Example
1134
+
1135
+ ```typescript
1136
+ import { loginGitHubCopilot } from "@linxiraos/pi-ai";
1137
+ import * as fs from "node:fs";
1138
+
1139
+ const credentials = await loginGitHubCopilot({
1140
+ onAuth: (url, instructions) => {
1141
+ console.log(`Open: ${url}`);
1142
+ if (instructions) console.log(instructions);
1143
+ },
1144
+ onPrompt: async (prompt) => {
1145
+ return await getUserInput(prompt.message);
1146
+ },
1147
+ onProgress: (message) => console.log(message),
1148
+ });
1149
+
1150
+ // Store credentials yourself
1151
+ const auth = { "github-copilot": { type: "oauth", ...credentials } };
1152
+ fs.writeFileSync("credentials.json", JSON.stringify(auth, null, 2));
1153
+ ```
1154
+
1155
+ ### Using OAuth Tokens
1156
+
1157
+ Use `getOAuthApiKey()` to get an API key, automatically refreshing if expired:
1158
+
1159
+ ```typescript
1160
+ import { getModel, complete, getOAuthApiKey } from "@linxiraos/pi-ai";
1161
+ import * as fs from "node:fs";
1162
+
1163
+ // Load your stored credentials
1164
+ const auth = JSON.parse(fs.readFileSync("credentials.json", "utf-8"));
1165
+
1166
+ // Get API key (refreshes if expired)
1167
+ const result = await getOAuthApiKey("github-copilot", auth);
1168
+ if (!result) throw new Error("Not logged in");
1169
+
1170
+ // Save refreshed credentials
1171
+ auth["github-copilot"] = { type: "oauth", ...result.newCredentials };
1172
+ fs.writeFileSync("credentials.json", JSON.stringify(auth, null, 2));
1173
+
1174
+ // Use the API key
1175
+ const model = getModel("github-copilot", "gpt-4o");
1176
+ const response = await complete(
1177
+ model,
1178
+ {
1179
+ messages: [{ role: "user", content: "Hello!" }],
1180
+ },
1181
+ { apiKey: result.apiKey }
1182
+ );
1183
+ ```
1184
+
1185
+ ### Provider Notes
1186
+
1187
+ **OpenAI Codex**: Requires a ChatGPT Plus or Pro subscription. Provides access to GPT-5.x Codex models with extended context windows and reasoning capabilities. The library automatically handles session-based prompt caching when `sessionId` is provided in stream options.
1188
+
1189
+ **GitHub Copilot**: If you get "The requested model is not supported" error, enable the model manually in VS Code: open Copilot Chat, click the model selector, select the model (warning icon), and click "Enable".
1190
+
1191
+ **Google Gemini CLI / Antigravity**: These use Google Cloud OAuth. The `apiKey` returned by `getOAuthApiKey()` is a JSON string containing both the token and project ID, which the library handles automatically.
1192
+
1193
+ ## License
1194
+
1195
+ MIT