@bastani/pi-ai 0.9.14 → 0.9.15

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 (113) hide show
  1. package/CHANGELOG.md +72 -0
  2. package/NOTICE.md +4 -5
  3. package/README.md +6 -4
  4. package/dist/api/anthropic-messages.d.ts.map +1 -1
  5. package/dist/api/anthropic-messages.js +55 -25
  6. package/dist/api/anthropic-messages.js.map +1 -1
  7. package/dist/api/azure-openai-responses.d.ts +2 -0
  8. package/dist/api/azure-openai-responses.d.ts.map +1 -1
  9. package/dist/api/azure-openai-responses.js +9 -2
  10. package/dist/api/azure-openai-responses.js.map +1 -1
  11. package/dist/api/bedrock-converse-stream.d.ts.map +1 -1
  12. package/dist/api/bedrock-converse-stream.js +132 -8
  13. package/dist/api/bedrock-converse-stream.js.map +1 -1
  14. package/dist/api/github-copilot-headers.d.ts +22 -1
  15. package/dist/api/github-copilot-headers.d.ts.map +1 -1
  16. package/dist/api/github-copilot-headers.js +30 -0
  17. package/dist/api/github-copilot-headers.js.map +1 -1
  18. package/dist/api/google-generative-ai.d.ts +2 -2
  19. package/dist/api/google-generative-ai.d.ts.map +1 -1
  20. package/dist/api/google-generative-ai.js +28 -18
  21. package/dist/api/google-generative-ai.js.map +1 -1
  22. package/dist/api/google-shared.d.ts +5 -2
  23. package/dist/api/google-shared.d.ts.map +1 -1
  24. package/dist/api/google-shared.js +16 -0
  25. package/dist/api/google-shared.js.map +1 -1
  26. package/dist/api/google-vertex.d.ts +2 -2
  27. package/dist/api/google-vertex.d.ts.map +1 -1
  28. package/dist/api/google-vertex.js +15 -11
  29. package/dist/api/google-vertex.js.map +1 -1
  30. package/dist/api/mistral-conversations.d.ts.map +1 -1
  31. package/dist/api/mistral-conversations.js +15 -5
  32. package/dist/api/mistral-conversations.js.map +1 -1
  33. package/dist/api/openai-codex-responses.d.ts.map +1 -1
  34. package/dist/api/openai-codex-responses.js +15 -6
  35. package/dist/api/openai-codex-responses.js.map +1 -1
  36. package/dist/api/openai-completions.d.ts +3 -2
  37. package/dist/api/openai-completions.d.ts.map +1 -1
  38. package/dist/api/openai-completions.js +142 -94
  39. package/dist/api/openai-completions.js.map +1 -1
  40. package/dist/api/openai-responses.d.ts.map +1 -1
  41. package/dist/api/openai-responses.js +20 -10
  42. package/dist/api/openai-responses.js.map +1 -1
  43. package/dist/api/pi-messages.d.ts.map +1 -1
  44. package/dist/api/pi-messages.js +23 -5
  45. package/dist/api/pi-messages.js.map +1 -1
  46. package/dist/api/simple-options.d.ts +4 -0
  47. package/dist/api/simple-options.d.ts.map +1 -1
  48. package/dist/api/simple-options.js +18 -10
  49. package/dist/api/simple-options.js.map +1 -1
  50. package/dist/auth/oauth/device-code.d.ts +1 -0
  51. package/dist/auth/oauth/device-code.d.ts.map +1 -1
  52. package/dist/auth/oauth/device-code.js +1 -1
  53. package/dist/auth/oauth/device-code.js.map +1 -1
  54. package/dist/auth/oauth/github-copilot.d.ts.map +1 -1
  55. package/dist/auth/oauth/github-copilot.js +98 -34
  56. package/dist/auth/oauth/github-copilot.js.map +1 -1
  57. package/dist/auth/oauth/kimi-coding.d.ts.map +1 -1
  58. package/dist/auth/oauth/kimi-coding.js +1 -14
  59. package/dist/auth/oauth/kimi-coding.js.map +1 -1
  60. package/dist/index.d.ts +2 -1
  61. package/dist/index.d.ts.map +1 -1
  62. package/dist/index.js +1 -0
  63. package/dist/index.js.map +1 -1
  64. package/dist/providers/data/.manifest.json +1 -1
  65. package/dist/providers/data/amazon-bedrock.json +1 -1
  66. package/dist/providers/data/anthropic.json +1 -1
  67. package/dist/providers/data/baseten.json +1 -1
  68. package/dist/providers/data/cerebras.json +1 -1
  69. package/dist/providers/data/cloudflare-ai-gateway.json +1 -1
  70. package/dist/providers/data/cloudflare-workers-ai.json +1 -1
  71. package/dist/providers/data/github-copilot.json +1 -1
  72. package/dist/providers/data/google-vertex.json +1 -1
  73. package/dist/providers/data/google.json +1 -1
  74. package/dist/providers/data/huggingface.json +1 -1
  75. package/dist/providers/data/nvidia.json +1 -1
  76. package/dist/providers/data/opencode-go.json +1 -1
  77. package/dist/providers/data/opencode.json +1 -1
  78. package/dist/providers/data/openrouter.json +1 -1
  79. package/dist/providers/data/qwen-token-plan-cn.json +1 -1
  80. package/dist/providers/data/qwen-token-plan-individual.json +1 -1
  81. package/dist/providers/data/qwen-token-plan.json +1 -1
  82. package/dist/providers/data/together.json +1 -1
  83. package/dist/providers/data/vercel-ai-gateway.json +1 -1
  84. package/dist/providers/data/xai.json +1 -1
  85. package/dist/providers/data/xiaomi-token-plan-ams.json +1 -1
  86. package/dist/providers/data/xiaomi-token-plan-cn.json +1 -1
  87. package/dist/providers/data/xiaomi-token-plan-sgp.json +1 -1
  88. package/dist/providers/data/xiaomi.json +1 -1
  89. package/dist/providers/data/zai-coding-cn.json +1 -1
  90. package/dist/providers/data/zai.json +1 -1
  91. package/dist/providers/github-copilot-env.d.ts +36 -0
  92. package/dist/providers/github-copilot-env.d.ts.map +1 -0
  93. package/dist/providers/github-copilot-env.js +94 -0
  94. package/dist/providers/github-copilot-env.js.map +1 -0
  95. package/dist/providers/xai.d.ts +1 -1
  96. package/dist/providers/xai.d.ts.map +1 -1
  97. package/dist/providers/xai.js +1 -5
  98. package/dist/providers/xai.js.map +1 -1
  99. package/dist/types.d.ts +43 -5
  100. package/dist/types.d.ts.map +1 -1
  101. package/dist/types.js.map +1 -1
  102. package/dist/utils/retry.d.ts.map +1 -1
  103. package/dist/utils/retry.js +14 -0
  104. package/dist/utils/retry.js.map +1 -1
  105. package/dist/utils/sleep.d.ts +2 -0
  106. package/dist/utils/sleep.d.ts.map +1 -0
  107. package/dist/utils/sleep.js +15 -0
  108. package/dist/utils/sleep.js.map +1 -0
  109. package/dist/utils/stream-deadline.d.ts +74 -0
  110. package/dist/utils/stream-deadline.d.ts.map +1 -0
  111. package/dist/utils/stream-deadline.js +196 -0
  112. package/dist/utils/stream-deadline.js.map +1 -0
  113. package/package.json +118 -120
@@ -1 +1 @@
1
- {"openai-completions":{"mimo-v2-pro":{"id":"mimo-v2-pro","name":"MiMo-V2-Pro","api":"openai-completions","provider":"xiaomi-token-plan-cn","baseUrl":"https://token-plan-cn.xiaomimimo.com/v1","compat":{"requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},"reasoning":true,"input":["text"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":1048576,"maxTokens":131072},"mimo-v2.5":{"id":"mimo-v2.5","name":"MiMo-V2.5","api":"openai-completions","provider":"xiaomi-token-plan-cn","baseUrl":"https://token-plan-cn.xiaomimimo.com/v1","compat":{"requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},"reasoning":true,"input":["text","image"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":1048576,"maxTokens":131072},"mimo-v2.5-pro":{"id":"mimo-v2.5-pro","name":"MiMo-V2.5-Pro","api":"openai-completions","provider":"xiaomi-token-plan-cn","baseUrl":"https://token-plan-cn.xiaomimimo.com/v1","compat":{"requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},"reasoning":true,"input":["text"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":1048576,"maxTokens":131072}}}
1
+ {"openai-completions":{"mimo-v2.5":{"id":"mimo-v2.5","name":"MiMo-V2.5","api":"openai-completions","provider":"xiaomi-token-plan-cn","baseUrl":"https://token-plan-cn.xiaomimimo.com/v1","compat":{"requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},"reasoning":true,"input":["text","image"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":1048576,"maxTokens":131072},"mimo-v2.5-pro":{"id":"mimo-v2.5-pro","name":"MiMo-V2.5-Pro","api":"openai-completions","provider":"xiaomi-token-plan-cn","baseUrl":"https://token-plan-cn.xiaomimimo.com/v1","compat":{"requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},"reasoning":true,"input":["text"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":1048576,"maxTokens":131072}}}
@@ -1 +1 @@
1
- {"openai-completions":{"mimo-v2-pro":{"id":"mimo-v2-pro","name":"MiMo-V2-Pro","api":"openai-completions","provider":"xiaomi-token-plan-sgp","baseUrl":"https://token-plan-sgp.xiaomimimo.com/v1","compat":{"requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},"reasoning":true,"input":["text"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":1048576,"maxTokens":131072},"mimo-v2.5":{"id":"mimo-v2.5","name":"MiMo-V2.5","api":"openai-completions","provider":"xiaomi-token-plan-sgp","baseUrl":"https://token-plan-sgp.xiaomimimo.com/v1","compat":{"requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},"reasoning":true,"input":["text","image"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":1048576,"maxTokens":131072},"mimo-v2.5-pro":{"id":"mimo-v2.5-pro","name":"MiMo-V2.5-Pro","api":"openai-completions","provider":"xiaomi-token-plan-sgp","baseUrl":"https://token-plan-sgp.xiaomimimo.com/v1","compat":{"requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},"reasoning":true,"input":["text"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":1048576,"maxTokens":131072}}}
1
+ {"openai-completions":{"mimo-v2.5":{"id":"mimo-v2.5","name":"MiMo-V2.5","api":"openai-completions","provider":"xiaomi-token-plan-sgp","baseUrl":"https://token-plan-sgp.xiaomimimo.com/v1","compat":{"requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},"reasoning":true,"input":["text","image"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":1048576,"maxTokens":131072},"mimo-v2.5-pro":{"id":"mimo-v2.5-pro","name":"MiMo-V2.5-Pro","api":"openai-completions","provider":"xiaomi-token-plan-sgp","baseUrl":"https://token-plan-sgp.xiaomimimo.com/v1","compat":{"requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},"reasoning":true,"input":["text"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":1048576,"maxTokens":131072}}}
@@ -1 +1 @@
1
- {"openai-completions":{"mimo-v2-flash":{"id":"mimo-v2-flash","name":"MiMo-V2-Flash","api":"openai-completions","provider":"xiaomi","baseUrl":"https://api.xiaomimimo.com/v1","compat":{"requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},"reasoning":true,"input":["text"],"cost":{"input":0.14,"output":0.28,"cacheRead":0.0028,"cacheWrite":0},"contextWindow":262144,"maxTokens":65536},"mimo-v2-omni":{"id":"mimo-v2-omni","name":"MiMo-V2-Omni","api":"openai-completions","provider":"xiaomi","baseUrl":"https://api.xiaomimimo.com/v1","compat":{"requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},"reasoning":true,"input":["text","image"],"cost":{"input":0.14,"output":0.28,"cacheRead":0.0028,"cacheWrite":0},"contextWindow":262144,"maxTokens":131072},"mimo-v2-pro":{"id":"mimo-v2-pro","name":"MiMo-V2-Pro","api":"openai-completions","provider":"xiaomi","baseUrl":"https://api.xiaomimimo.com/v1","compat":{"requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},"reasoning":true,"input":["text"],"cost":{"input":0.435,"output":0.87,"cacheRead":0.0036,"cacheWrite":0},"contextWindow":1048576,"maxTokens":131072},"mimo-v2.5":{"id":"mimo-v2.5","name":"MiMo-V2.5","api":"openai-completions","provider":"xiaomi","baseUrl":"https://api.xiaomimimo.com/v1","compat":{"requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},"reasoning":true,"input":["text","image"],"cost":{"input":0.14,"output":0.28,"cacheRead":0.0028,"cacheWrite":0},"contextWindow":1048576,"maxTokens":131072},"mimo-v2.5-pro":{"id":"mimo-v2.5-pro","name":"MiMo-V2.5-Pro","api":"openai-completions","provider":"xiaomi","baseUrl":"https://api.xiaomimimo.com/v1","compat":{"requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},"reasoning":true,"input":["text"],"cost":{"input":0.435,"output":0.87,"cacheRead":0.0036,"cacheWrite":0},"contextWindow":1048576,"maxTokens":131072},"mimo-v2.5-pro-ultraspeed":{"id":"mimo-v2.5-pro-ultraspeed","name":"MiMo-V2.5-Pro-UltraSpeed","api":"openai-completions","provider":"xiaomi","baseUrl":"https://api.xiaomimimo.com/v1","compat":{"requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},"reasoning":true,"input":["text"],"cost":{"input":1.305,"output":2.61,"cacheRead":0.0108,"cacheWrite":0},"contextWindow":1048576,"maxTokens":131072}}}
1
+ {"openai-completions":{"mimo-v2.5":{"id":"mimo-v2.5","name":"MiMo-V2.5","api":"openai-completions","provider":"xiaomi","baseUrl":"https://api.xiaomimimo.com/v1","compat":{"requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},"reasoning":true,"input":["text","image"],"cost":{"input":0.14,"output":0.28,"cacheRead":0.0028,"cacheWrite":0},"contextWindow":1048576,"maxTokens":131072},"mimo-v2.5-pro":{"id":"mimo-v2.5-pro","name":"MiMo-V2.5-Pro","api":"openai-completions","provider":"xiaomi","baseUrl":"https://api.xiaomimimo.com/v1","compat":{"requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},"reasoning":true,"input":["text"],"cost":{"input":0.435,"output":0.87,"cacheRead":0.0036,"cacheWrite":0},"contextWindow":1048576,"maxTokens":131072},"mimo-v2.5-pro-ultraspeed":{"id":"mimo-v2.5-pro-ultraspeed","name":"MiMo-V2.5-Pro-UltraSpeed","api":"openai-completions","provider":"xiaomi","baseUrl":"https://api.xiaomimimo.com/v1","compat":{"requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},"reasoning":true,"input":["text"],"cost":{"input":1.305,"output":2.61,"cacheRead":0.0108,"cacheWrite":0},"contextWindow":1048576,"maxTokens":131072}}}
@@ -1 +1 @@
1
- {"openai-completions":{"glm-4.7":{"id":"glm-4.7","name":"GLM-4.7","api":"openai-completions","provider":"zai-coding-cn","baseUrl":"https://open.bigmodel.cn/api/coding/paas/v4","reasoning":true,"input":["text"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","thinkingFormat":"zai","zaiToolStream":true},"contextWindow":204800,"maxTokens":131072},"glm-5-turbo":{"id":"glm-5-turbo","name":"GLM-5-Turbo","api":"openai-completions","provider":"zai-coding-cn","baseUrl":"https://open.bigmodel.cn/api/coding/paas/v4","reasoning":true,"input":["text"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","thinkingFormat":"zai","zaiToolStream":true},"contextWindow":200000,"maxTokens":131072},"glm-5.2":{"id":"glm-5.2","name":"GLM-5.2","api":"openai-completions","provider":"zai-coding-cn","baseUrl":"https://open.bigmodel.cn/api/coding/paas/v4","reasoning":true,"thinkingLevelMap":{"minimal":null,"low":"high","medium":"high","high":"high","max":"max"},"input":["text"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":true,"maxTokensField":"max_tokens","thinkingFormat":"zai","zaiToolStream":true},"contextWindow":1000000,"maxTokens":131072},"glm-5.2-highspeed":{"id":"glm-5.2-highspeed","name":"GLM-5.2 Highspeed","api":"openai-completions","provider":"zai-coding-cn","baseUrl":"https://open.bigmodel.cn/api/coding/paas/v4","reasoning":true,"input":["text"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","thinkingFormat":"zai","zaiToolStream":true},"contextWindow":1000000,"maxTokens":131072},"glm-5.3":{"id":"glm-5.3","name":"GLM-5.3","api":"openai-completions","provider":"zai-coding-cn","baseUrl":"https://open.bigmodel.cn/api/coding/paas/v4","reasoning":true,"input":["text"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","thinkingFormat":"zai","zaiToolStream":true},"contextWindow":1000000,"maxTokens":131072}}}
1
+ {"openai-completions":{"glm-4.6v":{"id":"glm-4.6v","name":"GLM-4.6V","api":"openai-completions","provider":"zai-coding-cn","baseUrl":"https://open.bigmodel.cn/api/coding/paas/v4","reasoning":true,"input":["text","image"],"cost":{"input":0.3,"output":0.9,"cacheRead":0,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","thinkingFormat":"zai","zaiToolStream":true},"contextWindow":128000,"maxTokens":32768},"glm-4.7":{"id":"glm-4.7","name":"GLM-4.7","api":"openai-completions","provider":"zai-coding-cn","baseUrl":"https://open.bigmodel.cn/api/coding/paas/v4","reasoning":true,"input":["text"],"cost":{"input":0.6,"output":2.2,"cacheRead":0.11,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","thinkingFormat":"zai","zaiToolStream":true},"contextWindow":204800,"maxTokens":131072},"glm-5-turbo":{"id":"glm-5-turbo","name":"GLM-5-Turbo","api":"openai-completions","provider":"zai-coding-cn","baseUrl":"https://open.bigmodel.cn/api/coding/paas/v4","reasoning":true,"input":["text"],"cost":{"input":1.2,"output":4,"cacheRead":0.24,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","thinkingFormat":"zai","zaiToolStream":true},"contextWindow":200000,"maxTokens":131072},"glm-5.1":{"id":"glm-5.1","name":"GLM-5.1","api":"openai-completions","provider":"zai-coding-cn","baseUrl":"https://open.bigmodel.cn/api/coding/paas/v4","reasoning":true,"input":["text"],"cost":{"input":1.4,"output":4.4,"cacheRead":0.26,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","thinkingFormat":"zai","zaiToolStream":true},"contextWindow":200000,"maxTokens":131072},"glm-5.2":{"id":"glm-5.2","name":"GLM-5.2","api":"openai-completions","provider":"zai-coding-cn","baseUrl":"https://open.bigmodel.cn/api/coding/paas/v4","reasoning":true,"thinkingLevelMap":{"off":"none","minimal":null,"low":null,"medium":null,"high":"high","xhigh":null,"max":"max"},"input":["text"],"cost":{"input":1.4,"output":4.4,"cacheRead":0.26,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":true,"maxTokensField":"max_tokens","thinkingFormat":"zai","zaiToolStream":true},"contextWindow":1000000,"maxTokens":131072},"glm-5.2-highspeed":{"id":"glm-5.2-highspeed","name":"GLM-5.2 Highspeed","api":"openai-completions","provider":"zai-coding-cn","baseUrl":"https://open.bigmodel.cn/api/coding/paas/v4","reasoning":true,"thinkingLevelMap":{"off":"none","minimal":null,"low":null,"medium":null,"high":"high","xhigh":null,"max":"max"},"input":["text"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":true,"maxTokensField":"max_tokens","thinkingFormat":"zai","zaiToolStream":true},"contextWindow":1000000,"maxTokens":131072},"glm-5.3":{"id":"glm-5.3","name":"GLM-5.3","api":"openai-completions","provider":"zai-coding-cn","baseUrl":"https://open.bigmodel.cn/api/coding/paas/v4","reasoning":true,"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":null,"high":"high","xhigh":null,"max":"max"},"input":["text"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":true,"maxTokensField":"max_tokens","thinkingFormat":"zai","zaiToolStream":true},"contextWindow":1000000,"maxTokens":131072},"glm-5v-turbo":{"id":"glm-5v-turbo","name":"GLM-5V-Turbo","api":"openai-completions","provider":"zai-coding-cn","baseUrl":"https://open.bigmodel.cn/api/coding/paas/v4","reasoning":true,"input":["text","image"],"cost":{"input":1.2,"output":4,"cacheRead":0.24,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","thinkingFormat":"zai","zaiToolStream":true},"contextWindow":200000,"maxTokens":131072}}}
@@ -1 +1 @@
1
- {"openai-completions":{"glm-4.7":{"id":"glm-4.7","name":"GLM-4.7","api":"openai-completions","provider":"zai","baseUrl":"https://api.z.ai/api/coding/paas/v4","reasoning":true,"input":["text"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","thinkingFormat":"zai","zaiToolStream":true},"contextWindow":204800,"maxTokens":131072},"glm-5-turbo":{"id":"glm-5-turbo","name":"GLM-5-Turbo","api":"openai-completions","provider":"zai","baseUrl":"https://api.z.ai/api/coding/paas/v4","reasoning":true,"input":["text"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","thinkingFormat":"zai","zaiToolStream":true},"contextWindow":200000,"maxTokens":131072},"glm-5.2":{"id":"glm-5.2","name":"GLM-5.2","api":"openai-completions","provider":"zai","baseUrl":"https://api.z.ai/api/coding/paas/v4","reasoning":true,"thinkingLevelMap":{"minimal":null,"low":"high","medium":"high","high":"high","max":"max"},"input":["text"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":true,"maxTokensField":"max_tokens","thinkingFormat":"zai","zaiToolStream":true},"contextWindow":1000000,"maxTokens":131072},"glm-5.2-highspeed":{"id":"glm-5.2-highspeed","name":"GLM-5.2 Highspeed","api":"openai-completions","provider":"zai","baseUrl":"https://api.z.ai/api/coding/paas/v4","reasoning":true,"input":["text"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","thinkingFormat":"zai","zaiToolStream":true},"contextWindow":1000000,"maxTokens":131072},"glm-5.3":{"id":"glm-5.3","name":"GLM-5.3","api":"openai-completions","provider":"zai","baseUrl":"https://api.z.ai/api/coding/paas/v4","reasoning":true,"input":["text"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","thinkingFormat":"zai","zaiToolStream":true},"contextWindow":1000000,"maxTokens":131072}}}
1
+ {"openai-completions":{"glm-4.7":{"id":"glm-4.7","name":"GLM-4.7","api":"openai-completions","provider":"zai","baseUrl":"https://api.z.ai/api/coding/paas/v4","reasoning":true,"input":["text"],"cost":{"input":0.6,"output":2.2,"cacheRead":0.11,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","thinkingFormat":"zai","zaiToolStream":true},"contextWindow":204800,"maxTokens":131072},"glm-5-turbo":{"id":"glm-5-turbo","name":"GLM-5-Turbo","api":"openai-completions","provider":"zai","baseUrl":"https://api.z.ai/api/coding/paas/v4","reasoning":true,"input":["text"],"cost":{"input":1.2,"output":4,"cacheRead":0.24,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","thinkingFormat":"zai","zaiToolStream":true},"contextWindow":200000,"maxTokens":131072},"glm-5.2":{"id":"glm-5.2","name":"GLM-5.2","api":"openai-completions","provider":"zai","baseUrl":"https://api.z.ai/api/coding/paas/v4","reasoning":true,"thinkingLevelMap":{"off":"none","minimal":null,"low":null,"medium":null,"high":"high","xhigh":null,"max":"max"},"input":["text"],"cost":{"input":1.4,"output":4.4,"cacheRead":0.26,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":true,"maxTokensField":"max_tokens","thinkingFormat":"zai","zaiToolStream":true},"contextWindow":1000000,"maxTokens":131072},"glm-5.2-highspeed":{"id":"glm-5.2-highspeed","name":"GLM-5.2 Highspeed","api":"openai-completions","provider":"zai","baseUrl":"https://api.z.ai/api/coding/paas/v4","reasoning":true,"thinkingLevelMap":{"off":"none","minimal":null,"low":null,"medium":null,"high":"high","xhigh":null,"max":"max"},"input":["text"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":true,"maxTokensField":"max_tokens","thinkingFormat":"zai","zaiToolStream":true},"contextWindow":1000000,"maxTokens":131072},"glm-5.3":{"id":"glm-5.3","name":"GLM-5.3","api":"openai-completions","provider":"zai","baseUrl":"https://api.z.ai/api/coding/paas/v4","reasoning":true,"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":null,"high":"high","xhigh":null,"max":"max"},"input":["text"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":true,"maxTokensField":"max_tokens","thinkingFormat":"zai","zaiToolStream":true},"contextWindow":1000000,"maxTokens":131072}}}
@@ -0,0 +1,36 @@
1
+ import type { Provider } from "../models.ts";
2
+ /**
3
+ * GitHub Copilot host routing for `COPILOT_GITHUB_TOKEN` (PAT) auth.
4
+ *
5
+ * Upstream pi pins `github-copilot` to `https://api.individual.githubcopilot.com`
6
+ * and only derives a per-tenant host inside the OAuth loader, which returns an
7
+ * `auth.baseUrl` from the token's `proxy-ep` segment. `envApiKeyAuth` resolves
8
+ * `COPILOT_GITHUB_TOKEN` without a base URL, so business/enterprise tokens are
9
+ * sent to the individual CAPI host and GitHub answers `421 Misdirected Request`.
10
+ *
11
+ * This module restores the routing precedence for the env-token path only; the
12
+ * OAuth path stays exactly upstream. A `models.json` provider `baseUrl` still
13
+ * wins, because it is applied as a later overlay in `applyModelsJson`.
14
+ */
15
+ export type CopilotRoutingEnv = Readonly<Record<string, string | undefined>>;
16
+ /**
17
+ * Resolve the Copilot API base URL for env-token auth, highest precedence first:
18
+ *
19
+ * 1. `COPILOT_API_TARGET` / `GITHUB_COPILOT_BASE_URL` explicit override
20
+ * 2. the `proxy-ep` segment embedded in `COPILOT_GITHUB_TOKEN`
21
+ * 3. an explicit `enterpriseDomain`
22
+ * 4. `GITHUB_SERVER_URL` (`*.ghe.com` tenant host, else the enterprise host)
23
+ * 5. the public Copilot routing hub when `COPILOT_GITHUB_TOKEN` is set
24
+ *
25
+ * Returns `undefined` when nothing applies, leaving pi's individual-host default.
26
+ */
27
+ export declare function resolveCopilotEnvBaseUrl(env: CopilotRoutingEnv, enterpriseDomain?: string): string | undefined;
28
+ /**
29
+ * Rewrite the builtin Copilot provider's host when `COPILOT_GITHUB_TOKEN` is set.
30
+ *
31
+ * Applied to the builtin layer so a `models.json` `baseUrl` override, which is
32
+ * composed afterwards, still takes precedence. Providers without the env token
33
+ * are returned untouched so OAuth logins keep pi's exact behavior.
34
+ */
35
+ export declare function withCopilotEnvBaseUrl(provider: Provider, env: CopilotRoutingEnv): Provider;
36
+ //# sourceMappingURL=github-copilot-env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github-copilot-env.d.ts","sourceRoot":"","sources":["../../src/providers/github-copilot-env.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAG7C;;;;;;;;;;;;GAYG;AAEH,MAAM,MAAM,iBAAiB,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;AAyC7E;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,iBAAiB,EAAE,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAoB9G;AAMD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,QAAQ,EAAE,GAAG,EAAE,iBAAiB,GAAG,QAAQ,CAU1F","sourcesContent":["import type { Provider } from \"../models.ts\";\nimport type { Api, Model } from \"../types.ts\";\n\n/**\n * GitHub Copilot host routing for `COPILOT_GITHUB_TOKEN` (PAT) auth.\n *\n * Upstream pi pins `github-copilot` to `https://api.individual.githubcopilot.com`\n * and only derives a per-tenant host inside the OAuth loader, which returns an\n * `auth.baseUrl` from the token's `proxy-ep` segment. `envApiKeyAuth` resolves\n * `COPILOT_GITHUB_TOKEN` without a base URL, so business/enterprise tokens are\n * sent to the individual CAPI host and GitHub answers `421 Misdirected Request`.\n *\n * This module restores the routing precedence for the env-token path only; the\n * OAuth path stays exactly upstream. A `models.json` provider `baseUrl` still\n * wins, because it is applied as a later overlay in `applyModelsJson`.\n */\n\nexport type CopilotRoutingEnv = Readonly<Record<string, string | undefined>>;\n\nconst COPILOT_PROVIDER_ID = \"github-copilot\";\n/** Public routing hub: resolves the caller's plan-specific CAPI host server-side. */\nconst PUBLIC_COPILOT_HUB = \"https://api.githubcopilot.com\";\nconst ENTERPRISE_COPILOT_HOST = \"https://api.enterprise.githubcopilot.com\";\n\nfunction normalizeBaseUrl(value: string): string {\n\tconst trimmed = value.trim().replace(/\\/+$/u, \"\");\n\tif (!trimmed) return \"\";\n\treturn /^https?:\\/\\//u.test(trimmed) ? trimmed : `https://${trimmed}`;\n}\n\n/** `tid=...;exp=...;proxy-ep=proxy.business.githubcopilot.com;...` -> API host. */\nfunction baseUrlFromToken(token: string): string | undefined {\n\tconst match = token.match(/proxy-ep=([^;]+)/u);\n\tif (!match?.[1]) return undefined;\n\tconst host = match[1].trim().replace(/^proxy\\./u, \"api.\");\n\treturn host ? normalizeBaseUrl(host) : undefined;\n}\n\nfunction hostFromServerUrl(serverUrl: string): string | undefined {\n\ttry {\n\t\treturn new URL(normalizeBaseUrl(serverUrl)).hostname.toLowerCase() || undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction baseUrlFromServerHost(host: string): string | undefined {\n\tif (host === \"github.com\" || host.endsWith(\".github.com\")) return undefined;\n\t// Tenant-scoped GHE.com: octocorp.ghe.com -> copilot-api.octocorp.ghe.com\n\tif (host.endsWith(\".ghe.com\")) {\n\t\tconst tenant = host.slice(0, -\".ghe.com\".length).split(\".\").pop();\n\t\treturn tenant ? `https://copilot-api.${tenant}.ghe.com` : ENTERPRISE_COPILOT_HOST;\n\t}\n\t// GitHub Enterprise Server on a self-hosted domain routes through the\n\t// enterprise CAPI host rather than a per-appliance Copilot endpoint.\n\treturn ENTERPRISE_COPILOT_HOST;\n}\n\n/**\n * Resolve the Copilot API base URL for env-token auth, highest precedence first:\n *\n * 1. `COPILOT_API_TARGET` / `GITHUB_COPILOT_BASE_URL` explicit override\n * 2. the `proxy-ep` segment embedded in `COPILOT_GITHUB_TOKEN`\n * 3. an explicit `enterpriseDomain`\n * 4. `GITHUB_SERVER_URL` (`*.ghe.com` tenant host, else the enterprise host)\n * 5. the public Copilot routing hub when `COPILOT_GITHUB_TOKEN` is set\n *\n * Returns `undefined` when nothing applies, leaving pi's individual-host default.\n */\nexport function resolveCopilotEnvBaseUrl(env: CopilotRoutingEnv, enterpriseDomain?: string): string | undefined {\n\tconst override = env.COPILOT_API_TARGET?.trim() || env.GITHUB_COPILOT_BASE_URL?.trim();\n\tif (override) return normalizeBaseUrl(override);\n\n\tconst token = env.COPILOT_GITHUB_TOKEN?.trim();\n\tif (token) {\n\t\tconst fromToken = baseUrlFromToken(token);\n\t\tif (fromToken) return fromToken;\n\t}\n\n\tif (enterpriseDomain?.trim()) return `https://copilot-api.${enterpriseDomain.trim()}`;\n\n\tconst serverUrl = env.GITHUB_SERVER_URL?.trim();\n\tif (serverUrl) {\n\t\tconst host = hostFromServerUrl(serverUrl);\n\t\tconst fromServer = host ? baseUrlFromServerHost(host) : undefined;\n\t\tif (fromServer) return fromServer;\n\t}\n\n\treturn token ? PUBLIC_COPILOT_HUB : undefined;\n}\n\nfunction withModelBaseUrl<TApi extends Api>(models: readonly Model<TApi>[], baseUrl: string): Model<TApi>[] {\n\treturn models.map((model) => ({ ...model, baseUrl }));\n}\n\n/**\n * Rewrite the builtin Copilot provider's host when `COPILOT_GITHUB_TOKEN` is set.\n *\n * Applied to the builtin layer so a `models.json` `baseUrl` override, which is\n * composed afterwards, still takes precedence. Providers without the env token\n * are returned untouched so OAuth logins keep pi's exact behavior.\n */\nexport function withCopilotEnvBaseUrl(provider: Provider, env: CopilotRoutingEnv): Provider {\n\tif (provider.id !== COPILOT_PROVIDER_ID || !env.COPILOT_GITHUB_TOKEN?.trim()) return provider;\n\tconst baseUrl = resolveCopilotEnvBaseUrl(env);\n\tif (!baseUrl || baseUrl === provider.baseUrl) return provider;\n\treturn {\n\t\t...provider,\n\t\tbaseUrl,\n\t\t// Wrap the getter so dynamically refreshed models are routed too.\n\t\tgetModels: () => withModelBaseUrl(provider.getModels(), baseUrl),\n\t};\n}\n"]}
@@ -0,0 +1,94 @@
1
+ const COPILOT_PROVIDER_ID = "github-copilot";
2
+ /** Public routing hub: resolves the caller's plan-specific CAPI host server-side. */
3
+ const PUBLIC_COPILOT_HUB = "https://api.githubcopilot.com";
4
+ const ENTERPRISE_COPILOT_HOST = "https://api.enterprise.githubcopilot.com";
5
+ function normalizeBaseUrl(value) {
6
+ const trimmed = value.trim().replace(/\/+$/u, "");
7
+ if (!trimmed)
8
+ return "";
9
+ return /^https?:\/\//u.test(trimmed) ? trimmed : `https://${trimmed}`;
10
+ }
11
+ /** `tid=...;exp=...;proxy-ep=proxy.business.githubcopilot.com;...` -> API host. */
12
+ function baseUrlFromToken(token) {
13
+ const match = token.match(/proxy-ep=([^;]+)/u);
14
+ if (!match?.[1])
15
+ return undefined;
16
+ const host = match[1].trim().replace(/^proxy\./u, "api.");
17
+ return host ? normalizeBaseUrl(host) : undefined;
18
+ }
19
+ function hostFromServerUrl(serverUrl) {
20
+ try {
21
+ return new URL(normalizeBaseUrl(serverUrl)).hostname.toLowerCase() || undefined;
22
+ }
23
+ catch {
24
+ return undefined;
25
+ }
26
+ }
27
+ function baseUrlFromServerHost(host) {
28
+ if (host === "github.com" || host.endsWith(".github.com"))
29
+ return undefined;
30
+ // Tenant-scoped GHE.com: octocorp.ghe.com -> copilot-api.octocorp.ghe.com
31
+ if (host.endsWith(".ghe.com")) {
32
+ const tenant = host.slice(0, -".ghe.com".length).split(".").pop();
33
+ return tenant ? `https://copilot-api.${tenant}.ghe.com` : ENTERPRISE_COPILOT_HOST;
34
+ }
35
+ // GitHub Enterprise Server on a self-hosted domain routes through the
36
+ // enterprise CAPI host rather than a per-appliance Copilot endpoint.
37
+ return ENTERPRISE_COPILOT_HOST;
38
+ }
39
+ /**
40
+ * Resolve the Copilot API base URL for env-token auth, highest precedence first:
41
+ *
42
+ * 1. `COPILOT_API_TARGET` / `GITHUB_COPILOT_BASE_URL` explicit override
43
+ * 2. the `proxy-ep` segment embedded in `COPILOT_GITHUB_TOKEN`
44
+ * 3. an explicit `enterpriseDomain`
45
+ * 4. `GITHUB_SERVER_URL` (`*.ghe.com` tenant host, else the enterprise host)
46
+ * 5. the public Copilot routing hub when `COPILOT_GITHUB_TOKEN` is set
47
+ *
48
+ * Returns `undefined` when nothing applies, leaving pi's individual-host default.
49
+ */
50
+ export function resolveCopilotEnvBaseUrl(env, enterpriseDomain) {
51
+ const override = env.COPILOT_API_TARGET?.trim() || env.GITHUB_COPILOT_BASE_URL?.trim();
52
+ if (override)
53
+ return normalizeBaseUrl(override);
54
+ const token = env.COPILOT_GITHUB_TOKEN?.trim();
55
+ if (token) {
56
+ const fromToken = baseUrlFromToken(token);
57
+ if (fromToken)
58
+ return fromToken;
59
+ }
60
+ if (enterpriseDomain?.trim())
61
+ return `https://copilot-api.${enterpriseDomain.trim()}`;
62
+ const serverUrl = env.GITHUB_SERVER_URL?.trim();
63
+ if (serverUrl) {
64
+ const host = hostFromServerUrl(serverUrl);
65
+ const fromServer = host ? baseUrlFromServerHost(host) : undefined;
66
+ if (fromServer)
67
+ return fromServer;
68
+ }
69
+ return token ? PUBLIC_COPILOT_HUB : undefined;
70
+ }
71
+ function withModelBaseUrl(models, baseUrl) {
72
+ return models.map((model) => ({ ...model, baseUrl }));
73
+ }
74
+ /**
75
+ * Rewrite the builtin Copilot provider's host when `COPILOT_GITHUB_TOKEN` is set.
76
+ *
77
+ * Applied to the builtin layer so a `models.json` `baseUrl` override, which is
78
+ * composed afterwards, still takes precedence. Providers without the env token
79
+ * are returned untouched so OAuth logins keep pi's exact behavior.
80
+ */
81
+ export function withCopilotEnvBaseUrl(provider, env) {
82
+ if (provider.id !== COPILOT_PROVIDER_ID || !env.COPILOT_GITHUB_TOKEN?.trim())
83
+ return provider;
84
+ const baseUrl = resolveCopilotEnvBaseUrl(env);
85
+ if (!baseUrl || baseUrl === provider.baseUrl)
86
+ return provider;
87
+ return {
88
+ ...provider,
89
+ baseUrl,
90
+ // Wrap the getter so dynamically refreshed models are routed too.
91
+ getModels: () => withModelBaseUrl(provider.getModels(), baseUrl),
92
+ };
93
+ }
94
+ //# sourceMappingURL=github-copilot-env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github-copilot-env.js","sourceRoot":"","sources":["../../src/providers/github-copilot-env.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Provider } from \"../models.ts\";\nimport type { Api, Model } from \"../types.ts\";\n\n/**\n * GitHub Copilot host routing for `COPILOT_GITHUB_TOKEN` (PAT) auth.\n *\n * Upstream pi pins `github-copilot` to `https://api.individual.githubcopilot.com`\n * and only derives a per-tenant host inside the OAuth loader, which returns an\n * `auth.baseUrl` from the token's `proxy-ep` segment. `envApiKeyAuth` resolves\n * `COPILOT_GITHUB_TOKEN` without a base URL, so business/enterprise tokens are\n * sent to the individual CAPI host and GitHub answers `421 Misdirected Request`.\n *\n * This module restores the routing precedence for the env-token path only; the\n * OAuth path stays exactly upstream. A `models.json` provider `baseUrl` still\n * wins, because it is applied as a later overlay in `applyModelsJson`.\n */\n\nexport type CopilotRoutingEnv = Readonly<Record<string, string | undefined>>;\n\nconst COPILOT_PROVIDER_ID = \"github-copilot\";\n/** Public routing hub: resolves the caller's plan-specific CAPI host server-side. */\nconst PUBLIC_COPILOT_HUB = \"https://api.githubcopilot.com\";\nconst ENTERPRISE_COPILOT_HOST = \"https://api.enterprise.githubcopilot.com\";\n\nfunction normalizeBaseUrl(value: string): string {\n\tconst trimmed = value.trim().replace(/\\/+$/u, \"\");\n\tif (!trimmed) return \"\";\n\treturn /^https?:\\/\\//u.test(trimmed) ? trimmed : `https://${trimmed}`;\n}\n\n/** `tid=...;exp=...;proxy-ep=proxy.business.githubcopilot.com;...` -> API host. */\nfunction baseUrlFromToken(token: string): string | undefined {\n\tconst match = token.match(/proxy-ep=([^;]+)/u);\n\tif (!match?.[1]) return undefined;\n\tconst host = match[1].trim().replace(/^proxy\\./u, \"api.\");\n\treturn host ? normalizeBaseUrl(host) : undefined;\n}\n\nfunction hostFromServerUrl(serverUrl: string): string | undefined {\n\ttry {\n\t\treturn new URL(normalizeBaseUrl(serverUrl)).hostname.toLowerCase() || undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction baseUrlFromServerHost(host: string): string | undefined {\n\tif (host === \"github.com\" || host.endsWith(\".github.com\")) return undefined;\n\t// Tenant-scoped GHE.com: octocorp.ghe.com -> copilot-api.octocorp.ghe.com\n\tif (host.endsWith(\".ghe.com\")) {\n\t\tconst tenant = host.slice(0, -\".ghe.com\".length).split(\".\").pop();\n\t\treturn tenant ? `https://copilot-api.${tenant}.ghe.com` : ENTERPRISE_COPILOT_HOST;\n\t}\n\t// GitHub Enterprise Server on a self-hosted domain routes through the\n\t// enterprise CAPI host rather than a per-appliance Copilot endpoint.\n\treturn ENTERPRISE_COPILOT_HOST;\n}\n\n/**\n * Resolve the Copilot API base URL for env-token auth, highest precedence first:\n *\n * 1. `COPILOT_API_TARGET` / `GITHUB_COPILOT_BASE_URL` explicit override\n * 2. the `proxy-ep` segment embedded in `COPILOT_GITHUB_TOKEN`\n * 3. an explicit `enterpriseDomain`\n * 4. `GITHUB_SERVER_URL` (`*.ghe.com` tenant host, else the enterprise host)\n * 5. the public Copilot routing hub when `COPILOT_GITHUB_TOKEN` is set\n *\n * Returns `undefined` when nothing applies, leaving pi's individual-host default.\n */\nexport function resolveCopilotEnvBaseUrl(env: CopilotRoutingEnv, enterpriseDomain?: string): string | undefined {\n\tconst override = env.COPILOT_API_TARGET?.trim() || env.GITHUB_COPILOT_BASE_URL?.trim();\n\tif (override) return normalizeBaseUrl(override);\n\n\tconst token = env.COPILOT_GITHUB_TOKEN?.trim();\n\tif (token) {\n\t\tconst fromToken = baseUrlFromToken(token);\n\t\tif (fromToken) return fromToken;\n\t}\n\n\tif (enterpriseDomain?.trim()) return `https://copilot-api.${enterpriseDomain.trim()}`;\n\n\tconst serverUrl = env.GITHUB_SERVER_URL?.trim();\n\tif (serverUrl) {\n\t\tconst host = hostFromServerUrl(serverUrl);\n\t\tconst fromServer = host ? baseUrlFromServerHost(host) : undefined;\n\t\tif (fromServer) return fromServer;\n\t}\n\n\treturn token ? PUBLIC_COPILOT_HUB : undefined;\n}\n\nfunction withModelBaseUrl<TApi extends Api>(models: readonly Model<TApi>[], baseUrl: string): Model<TApi>[] {\n\treturn models.map((model) => ({ ...model, baseUrl }));\n}\n\n/**\n * Rewrite the builtin Copilot provider's host when `COPILOT_GITHUB_TOKEN` is set.\n *\n * Applied to the builtin layer so a `models.json` `baseUrl` override, which is\n * composed afterwards, still takes precedence. Providers without the env token\n * are returned untouched so OAuth logins keep pi's exact behavior.\n */\nexport function withCopilotEnvBaseUrl(provider: Provider, env: CopilotRoutingEnv): Provider {\n\tif (provider.id !== COPILOT_PROVIDER_ID || !env.COPILOT_GITHUB_TOKEN?.trim()) return provider;\n\tconst baseUrl = resolveCopilotEnvBaseUrl(env);\n\tif (!baseUrl || baseUrl === provider.baseUrl) return provider;\n\treturn {\n\t\t...provider,\n\t\tbaseUrl,\n\t\t// Wrap the getter so dynamically refreshed models are routed too.\n\t\tgetModels: () => withModelBaseUrl(provider.getModels(), baseUrl),\n\t};\n}\n"]}
@@ -1,3 +1,3 @@
1
1
  import { type Provider } from "../models.ts";
2
- export declare function xaiProvider(): Provider<"openai-completions" | "openai-responses">;
2
+ export declare function xaiProvider(): Provider<"openai-responses">;
3
3
  //# sourceMappingURL=xai.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"xai.d.ts","sourceRoot":"","sources":["../../src/providers/xai.ts"],"names":[],"mappings":"AAIA,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,cAAc,CAAC;AAG7D,wBAAgB,WAAW,IAAI,QAAQ,CAAC,oBAAoB,GAAG,kBAAkB,CAAC,CAoBjF","sourcesContent":["import { openAICompletionsApi } from \"../api/openai-completions.lazy.ts\";\nimport { openAIResponsesApi } from \"../api/openai-responses.lazy.ts\";\nimport { envApiKeyAuth, lazyOAuth } from \"../auth/helpers.ts\";\nimport { loadXaiOAuth } from \"../auth/oauth/load.ts\";\nimport { createProvider, type Provider } from \"../models.ts\";\nimport { XAI_MODELS } from \"./xai.models.ts\";\n\nexport function xaiProvider(): Provider<\"openai-completions\" | \"openai-responses\"> {\n\treturn createProvider({\n\t\tid: \"xai\",\n\t\tname: \"xAI\",\n\t\tbaseUrl: \"https://api.x.ai/v1\",\n\t\tauth: {\n\t\t\tapiKey: envApiKeyAuth(\"xAI API key\", [\"XAI_API_KEY\"]),\n\t\t\toauth: lazyOAuth({\n\t\t\t\tname: \"xAI (Grok/X subscription)\",\n\t\t\t\tisSubscription: true,\n\t\t\t\tloginLabel: \"Sign in with SuperGrok or X Premium\",\n\t\t\t\tload: loadXaiOAuth,\n\t\t\t}),\n\t\t},\n\t\tmodels: Object.values(XAI_MODELS),\n\t\tapi: {\n\t\t\t\"openai-completions\": openAICompletionsApi(),\n\t\t\t\"openai-responses\": openAIResponsesApi(),\n\t\t},\n\t});\n}\n"]}
1
+ {"version":3,"file":"xai.d.ts","sourceRoot":"","sources":["../../src/providers/xai.ts"],"names":[],"mappings":"AAGA,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,cAAc,CAAC;AAG7D,wBAAgB,WAAW,IAAI,QAAQ,CAAC,kBAAkB,CAAC,CAiB1D","sourcesContent":["import { openAIResponsesApi } from \"../api/openai-responses.lazy.ts\";\nimport { envApiKeyAuth, lazyOAuth } from \"../auth/helpers.ts\";\nimport { loadXaiOAuth } from \"../auth/oauth/load.ts\";\nimport { createProvider, type Provider } from \"../models.ts\";\nimport { XAI_MODELS } from \"./xai.models.ts\";\n\nexport function xaiProvider(): Provider<\"openai-responses\"> {\n\treturn createProvider({\n\t\tid: \"xai\",\n\t\tname: \"xAI\",\n\t\tbaseUrl: \"https://api.x.ai/v1\",\n\t\tauth: {\n\t\t\tapiKey: envApiKeyAuth(\"xAI API key\", [\"XAI_API_KEY\"]),\n\t\t\toauth: lazyOAuth({\n\t\t\t\tname: \"xAI (Grok/X subscription)\",\n\t\t\t\tisSubscription: true,\n\t\t\t\tloginLabel: \"Sign in with SuperGrok or X Premium\",\n\t\t\t\tload: loadXaiOAuth,\n\t\t\t}),\n\t\t},\n\t\tmodels: Object.values(XAI_MODELS),\n\t\tapi: openAIResponsesApi(),\n\t});\n}\n"]}
@@ -1,4 +1,3 @@
1
- import { openAICompletionsApi } from "../api/openai-completions.lazy.js";
2
1
  import { openAIResponsesApi } from "../api/openai-responses.lazy.js";
3
2
  import { envApiKeyAuth, lazyOAuth } from "../auth/helpers.js";
4
3
  import { loadXaiOAuth } from "../auth/oauth/load.js";
@@ -19,10 +18,7 @@ export function xaiProvider() {
19
18
  }),
20
19
  },
21
20
  models: Object.values(XAI_MODELS),
22
- api: {
23
- "openai-completions": openAICompletionsApi(),
24
- "openai-responses": openAIResponsesApi(),
25
- },
21
+ api: openAIResponsesApi(),
26
22
  });
27
23
  }
28
24
  //# sourceMappingURL=xai.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"xai.js","sourceRoot":"","sources":["../../src/providers/xai.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAiB,MAAM,cAAc,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,MAAM,UAAU,WAAW,GAAwD;IAClF,OAAO,cAAc,CAAC;QACrB,EAAE,EAAE,KAAK;QACT,IAAI,EAAE,KAAK;QACX,OAAO,EAAE,qBAAqB;QAC9B,IAAI,EAAE;YACL,MAAM,EAAE,aAAa,CAAC,aAAa,EAAE,CAAC,aAAa,CAAC,CAAC;YACrD,KAAK,EAAE,SAAS,CAAC;gBAChB,IAAI,EAAE,2BAA2B;gBACjC,cAAc,EAAE,IAAI;gBACpB,UAAU,EAAE,qCAAqC;gBACjD,IAAI,EAAE,YAAY;aAClB,CAAC;SACF;QACD,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC;QACjC,GAAG,EAAE;YACJ,oBAAoB,EAAE,oBAAoB,EAAE;YAC5C,kBAAkB,EAAE,kBAAkB,EAAE;SACxC;KACD,CAAC,CAAC;AAAA,CACH","sourcesContent":["import { openAICompletionsApi } from \"../api/openai-completions.lazy.ts\";\nimport { openAIResponsesApi } from \"../api/openai-responses.lazy.ts\";\nimport { envApiKeyAuth, lazyOAuth } from \"../auth/helpers.ts\";\nimport { loadXaiOAuth } from \"../auth/oauth/load.ts\";\nimport { createProvider, type Provider } from \"../models.ts\";\nimport { XAI_MODELS } from \"./xai.models.ts\";\n\nexport function xaiProvider(): Provider<\"openai-completions\" | \"openai-responses\"> {\n\treturn createProvider({\n\t\tid: \"xai\",\n\t\tname: \"xAI\",\n\t\tbaseUrl: \"https://api.x.ai/v1\",\n\t\tauth: {\n\t\t\tapiKey: envApiKeyAuth(\"xAI API key\", [\"XAI_API_KEY\"]),\n\t\t\toauth: lazyOAuth({\n\t\t\t\tname: \"xAI (Grok/X subscription)\",\n\t\t\t\tisSubscription: true,\n\t\t\t\tloginLabel: \"Sign in with SuperGrok or X Premium\",\n\t\t\t\tload: loadXaiOAuth,\n\t\t\t}),\n\t\t},\n\t\tmodels: Object.values(XAI_MODELS),\n\t\tapi: {\n\t\t\t\"openai-completions\": openAICompletionsApi(),\n\t\t\t\"openai-responses\": openAIResponsesApi(),\n\t\t},\n\t});\n}\n"]}
1
+ {"version":3,"file":"xai.js","sourceRoot":"","sources":["../../src/providers/xai.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAiB,MAAM,cAAc,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,MAAM,UAAU,WAAW,GAAiC;IAC3D,OAAO,cAAc,CAAC;QACrB,EAAE,EAAE,KAAK;QACT,IAAI,EAAE,KAAK;QACX,OAAO,EAAE,qBAAqB;QAC9B,IAAI,EAAE;YACL,MAAM,EAAE,aAAa,CAAC,aAAa,EAAE,CAAC,aAAa,CAAC,CAAC;YACrD,KAAK,EAAE,SAAS,CAAC;gBAChB,IAAI,EAAE,2BAA2B;gBACjC,cAAc,EAAE,IAAI;gBACpB,UAAU,EAAE,qCAAqC;gBACjD,IAAI,EAAE,YAAY;aAClB,CAAC;SACF;QACD,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC;QACjC,GAAG,EAAE,kBAAkB,EAAE;KACzB,CAAC,CAAC;AAAA,CACH","sourcesContent":["import { openAIResponsesApi } from \"../api/openai-responses.lazy.ts\";\nimport { envApiKeyAuth, lazyOAuth } from \"../auth/helpers.ts\";\nimport { loadXaiOAuth } from \"../auth/oauth/load.ts\";\nimport { createProvider, type Provider } from \"../models.ts\";\nimport { XAI_MODELS } from \"./xai.models.ts\";\n\nexport function xaiProvider(): Provider<\"openai-responses\"> {\n\treturn createProvider({\n\t\tid: \"xai\",\n\t\tname: \"xAI\",\n\t\tbaseUrl: \"https://api.x.ai/v1\",\n\t\tauth: {\n\t\t\tapiKey: envApiKeyAuth(\"xAI API key\", [\"XAI_API_KEY\"]),\n\t\t\toauth: lazyOAuth({\n\t\t\t\tname: \"xAI (Grok/X subscription)\",\n\t\t\t\tisSubscription: true,\n\t\t\t\tloginLabel: \"Sign in with SuperGrok or X Premium\",\n\t\t\t\tload: loadXaiOAuth,\n\t\t\t}),\n\t\t},\n\t\tmodels: Object.values(XAI_MODELS),\n\t\tapi: openAIResponsesApi(),\n\t});\n}\n"]}
package/dist/types.d.ts CHANGED
@@ -20,13 +20,16 @@ export type KnownProvider = "amazon-bedrock" | "ant-ling" | "anthropic" | "googl
20
20
  export type ProviderId = KnownProvider | string;
21
21
  export type KnownImagesProvider = "openrouter";
22
22
  export type ImagesProviderId = KnownImagesProvider | string;
23
+ export type ToolChoice = "auto" | "none";
23
24
  export type ThinkingLevel = "minimal" | "low" | "medium" | "high" | "xhigh" | "max";
24
25
  export type ModelThinkingLevel = "off" | ThinkingLevel;
25
26
  export type ThinkingLevelMap = Partial<Record<ModelThinkingLevel, string | null>>;
26
27
  export type ChatTemplateKwargValue = string | number | boolean | null | {
27
- $var: "thinking.enabled" | "thinking.effort";
28
+ $var: "thinking.enabled" | "thinking.effort" | "thinking.budget";
28
29
  omitWhenOff?: boolean;
29
30
  };
31
+ /** Top-level request field used to cap reasoning tokens on OpenAI-compatible servers. */
32
+ export type ThinkingTokenBudgetField = "thinking_token_budget" | "thinking_budget" | "thinking_budget_tokens";
30
33
  /** Token budgets for each thinking level (token-based providers only) */
31
34
  export interface ThinkingBudgets {
32
35
  minimal?: number;
@@ -135,9 +138,22 @@ export interface StreamOptions extends ProviderRequestOptions<Model<Api>> {
135
138
  /**
136
139
  * WebSocket connect timeout in milliseconds for providers that support
137
140
  * WebSocket transports. This covers the connection/open handshake only;
138
- * stream idleness after connection uses timeoutMs.
141
+ * HTTP/SDK idleness uses `timeoutMs`, while gaps between decoded provider
142
+ * stream events use `streamDeadlineMs`.
139
143
  */
140
144
  websocketConnectTimeoutMs?: number;
145
+ /**
146
+ * Maximum idle gap in milliseconds between two provider stream events.
147
+ *
148
+ * Enforced below the HTTP layer, so a response body that stalls without ever
149
+ * rejecting the adapter's async iterator (for example a decompression failure
150
+ * that destroys the stream silently, #2553) still settles the attempt as a
151
+ * retryable transport error instead of hanging forever. The timer restarts on
152
+ * every event, so it never caps total stream duration.
153
+ *
154
+ * Defaults to 300000 ms. `0` (or any non-positive value) disables it.
155
+ */
156
+ streamDeadlineMs?: number;
141
157
  /**
142
158
  * Optional metadata to include in API requests.
143
159
  * Providers extract the fields they understand and ignore the rest.
@@ -208,7 +224,14 @@ export interface ImagesOptions extends ProviderRequestOptions<ImagesModel<Images
208
224
  metadata?: Record<string, unknown>;
209
225
  }
210
226
  export type ProviderImagesOptions = ImagesOptions & Record<string, unknown>;
227
+ export interface AnthropicAllowedFallbackModel {
228
+ provider: ProviderId;
229
+ model: string;
230
+ cost: ModelCost;
231
+ }
211
232
  export interface SimpleStreamOptions extends StreamOptions {
233
+ /** Provider-neutral tool selection for simple requests. Default: "auto". */
234
+ toolChoice?: ToolChoice;
212
235
  reasoning?: ThinkingLevel;
213
236
  /** Ask a capable provider to return a durable handle and continue the request asynchronously. */
214
237
  deferred?: boolean | {
@@ -468,9 +491,9 @@ export interface OpenAICompletionsCompat {
468
491
  requiresReasoningContentOnAssistantMessages?: boolean;
469
492
  /** Format for reasoning/thinking parameter. "openai" uses reasoning_effort, "openrouter" uses reasoning: { effort }, "deepseek" uses thinking: { type } plus reasoning_effort when supported, "together" uses reasoning: { enabled } plus reasoning_effort when supported, "baseten" uses configurable chat_template_args plus reasoning_effort when supported, "zai" uses thinking: { type }, "qwen" uses top-level enable_thinking: boolean, "qwen-chat-template" uses chat_template_kwargs.enable_thinking and preserve_thinking, "chat-template" uses configurable chat_template_kwargs, "string-thinking" uses top-level thinking: string, and "ant-ling" uses reasoning: { effort } only when the mapped effort is non-null. Default: "openai". */
470
493
  thinkingFormat?: "openai" | "openrouter" | "deepseek" | "together" | "baseten" | "zai" | "qwen" | "chat-template" | "qwen-chat-template" | "string-thinking" | "ant-ling";
471
- /** Kwargs to send as `chat_template_kwargs` when `thinkingFormat` is `chat-template`. Use `{ "$var": "thinking.enabled" }` or `{ "$var": "thinking.effort" }` for pi-controlled thinking values. */
494
+ /** Kwargs to send as `chat_template_kwargs` when `thinkingFormat` is `chat-template`. Use `{ "$var": "thinking.enabled" }`, `{ "$var": "thinking.effort" }`, or `{ "$var": "thinking.budget" }` for pi-controlled thinking values. */
472
495
  chatTemplateKwargs?: Record<string, ChatTemplateKwargValue>;
473
- /** Arguments to send as `chat_template_args` when `thinkingFormat` is `baseten`. Use `{ "$var": "thinking.enabled" }` or `{ "$var": "thinking.effort" }` for pi-controlled thinking values. */
496
+ /** Arguments to send as `chat_template_args` when `thinkingFormat` is `baseten`. Use `{ "$var": "thinking.enabled" }`, `{ "$var": "thinking.effort" }`, or `{ "$var": "thinking.budget" }` for pi-controlled thinking values. */
474
497
  chatTemplateArgs?: Record<string, ChatTemplateKwargValue>;
475
498
  /** OpenRouter-compatible routing preferences sent as the `provider` request field. */
476
499
  openRouterRouting?: OpenRouterRouting;
@@ -478,7 +501,15 @@ export interface OpenAICompletionsCompat {
478
501
  vercelGatewayRouting?: VercelGatewayRouting;
479
502
  /** Whether z.ai supports top-level `tool_stream: true` for streaming tool call deltas. Default: false. */
480
503
  zaiToolStream?: boolean;
481
- /** Whether the provider supports top-level `thinking_token_budget` to cap reasoning tokens (vLLM). Reasoning and the answer share `max_tokens` on these endpoints, so without a budget a reasoning-heavy turn can consume the whole response and emit no answer. Default: false. */
504
+ /**
505
+ * Top-level request field used to cap reasoning tokens from `thinkingBudgets`.
506
+ * Reasoning and the answer share `max_tokens` on these endpoints, so without a budget a
507
+ * reasoning-heavy turn can consume the whole response and emit no answer.
508
+ * `"thinking_token_budget"` is vLLM, `"thinking_budget"` is Qwen/DashScope/SGLang,
509
+ * `"thinking_budget_tokens"` is llama.cpp. Off by default; not set on the generated catalog.
510
+ */
511
+ thinkingTokenBudgetField?: ThinkingTokenBudgetField;
512
+ /** Alias for `thinkingTokenBudgetField: "thinking_token_budget"` (vLLM). Prefer `thinkingTokenBudgetField`. Default: false. */
482
513
  supportsThinkingTokenBudget?: boolean;
483
514
  /** Whether the provider supports OpenAI custom tools with Lark/regex grammar formats. When false, grammar-constrained tools fall back to normal function tools. Default: false; the generated model catalog enables it for capable models. */
484
515
  supportsOpenAIGrammarTools?: boolean;
@@ -562,6 +593,13 @@ export interface AnthropicMessagesCompat {
562
593
  allowEmptySignature?: boolean;
563
594
  /** Whether the provider supports Anthropic strict tool schemas. Default: false; generated Anthropic models enable it explicitly. */
564
595
  supportsStrictTools?: boolean;
596
+ /**
597
+ * Models Anthropic accepts in `fallbacks` for server-side refusal fallback,
598
+ * with local pricing metadata for returned fallback responses. When absent or
599
+ * empty, callers must omit `fallbacks`; Anthropic rejects the field for models
600
+ * with no permitted fallback targets.
601
+ */
602
+ allowedFallbackModels?: AnthropicAllowedFallbackModel[];
565
603
  /**
566
604
  * Whether the provider supports deferred tools loaded by `tool_reference`
567
605
  * blocks in tool results. Default: true for first-party Anthropic models