@earendil-works/pi-ai 0.85.1 → 0.86.1

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 (177) hide show
  1. package/README.md +50 -6
  2. package/dist/api/anthropic-messages.d.ts.map +1 -1
  3. package/dist/api/anthropic-messages.js +130 -86
  4. package/dist/api/anthropic-messages.js.map +1 -1
  5. package/dist/api/azure-openai-responses.d.ts.map +1 -1
  6. package/dist/api/azure-openai-responses.js +17 -5
  7. package/dist/api/azure-openai-responses.js.map +1 -1
  8. package/dist/api/bedrock-converse-stream.d.ts.map +1 -1
  9. package/dist/api/bedrock-converse-stream.js +13 -12
  10. package/dist/api/bedrock-converse-stream.js.map +1 -1
  11. package/dist/api/google-generative-ai.d.ts.map +1 -1
  12. package/dist/api/google-generative-ai.js +21 -73
  13. package/dist/api/google-generative-ai.js.map +1 -1
  14. package/dist/api/google-shared.d.ts +13 -4
  15. package/dist/api/google-shared.d.ts.map +1 -1
  16. package/dist/api/google-shared.js +55 -4
  17. package/dist/api/google-shared.js.map +1 -1
  18. package/dist/api/google-vertex.d.ts.map +1 -1
  19. package/dist/api/google-vertex.js +25 -65
  20. package/dist/api/google-vertex.js.map +1 -1
  21. package/dist/api/mistral-conversations.d.ts.map +1 -1
  22. package/dist/api/mistral-conversations.js +19 -12
  23. package/dist/api/mistral-conversations.js.map +1 -1
  24. package/dist/api/openai-codex-responses.d.ts.map +1 -1
  25. package/dist/api/openai-codex-responses.js +26 -23
  26. package/dist/api/openai-codex-responses.js.map +1 -1
  27. package/dist/api/openai-completions.d.ts +6 -4
  28. package/dist/api/openai-completions.d.ts.map +1 -1
  29. package/dist/api/openai-completions.js +40 -58
  30. package/dist/api/openai-completions.js.map +1 -1
  31. package/dist/api/openai-responses-shared.d.ts +7 -5
  32. package/dist/api/openai-responses-shared.d.ts.map +1 -1
  33. package/dist/api/openai-responses-shared.js +56 -56
  34. package/dist/api/openai-responses-shared.js.map +1 -1
  35. package/dist/api/openai-responses.d.ts.map +1 -1
  36. package/dist/api/openai-responses.js +14 -19
  37. package/dist/api/openai-responses.js.map +1 -1
  38. package/dist/api/pi-messages.d.ts +3 -3
  39. package/dist/api/pi-messages.d.ts.map +1 -1
  40. package/dist/api/pi-messages.js +2 -2
  41. package/dist/api/pi-messages.js.map +1 -1
  42. package/dist/api/simple-options.d.ts +3 -3
  43. package/dist/api/simple-options.d.ts.map +1 -1
  44. package/dist/api/simple-options.js.map +1 -1
  45. package/dist/api/transform-messages.d.ts.map +1 -1
  46. package/dist/api/transform-messages.js +21 -7
  47. package/dist/api/transform-messages.js.map +1 -1
  48. package/dist/auth/oauth/load.d.ts +2 -0
  49. package/dist/auth/oauth/load.d.ts.map +1 -1
  50. package/dist/auth/oauth/load.js +5 -0
  51. package/dist/auth/oauth/load.js.map +1 -1
  52. package/dist/auth/oauth/meta.d.ts +17 -0
  53. package/dist/auth/oauth/meta.d.ts.map +1 -0
  54. package/dist/auth/oauth/meta.js +190 -0
  55. package/dist/auth/oauth/meta.js.map +1 -0
  56. package/dist/bun-oauth.d.ts.map +1 -1
  57. package/dist/bun-oauth.js +2 -0
  58. package/dist/bun-oauth.js.map +1 -1
  59. package/dist/compat.d.ts +3 -3
  60. package/dist/compat.d.ts.map +1 -1
  61. package/dist/compat.js +9 -6
  62. package/dist/compat.js.map +1 -1
  63. package/dist/env-api-keys.d.ts.map +1 -1
  64. package/dist/env-api-keys.js +1 -0
  65. package/dist/env-api-keys.js.map +1 -1
  66. package/dist/image-models.generated.d.ts +30 -0
  67. package/dist/image-models.generated.d.ts.map +1 -1
  68. package/dist/image-models.generated.js +34 -4
  69. package/dist/image-models.generated.js.map +1 -1
  70. package/dist/index.d.ts +2 -1
  71. package/dist/index.d.ts.map +1 -1
  72. package/dist/index.js +2 -1
  73. package/dist/index.js.map +1 -1
  74. package/dist/models.d.ts +4 -3
  75. package/dist/models.d.ts.map +1 -1
  76. package/dist/models.generated.d.ts +4 -0
  77. package/dist/models.generated.d.ts.map +1 -1
  78. package/dist/models.generated.js +4 -0
  79. package/dist/models.generated.js.map +1 -1
  80. package/dist/models.js +5 -2
  81. package/dist/models.js.map +1 -1
  82. package/dist/providers/all.d.ts.map +1 -1
  83. package/dist/providers/all.js +2 -0
  84. package/dist/providers/all.js.map +1 -1
  85. package/dist/providers/data/.manifest.json +1 -1
  86. package/dist/providers/data/amazon-bedrock.json +1 -1
  87. package/dist/providers/data/anthropic.json +1 -1
  88. package/dist/providers/data/baseten.json +1 -1
  89. package/dist/providers/data/cerebras.json +1 -1
  90. package/dist/providers/data/cloudflare-ai-gateway.json +1 -1
  91. package/dist/providers/data/deepseek.json +1 -1
  92. package/dist/providers/data/fireworks.json +1 -1
  93. package/dist/providers/data/github-copilot.json +1 -1
  94. package/dist/providers/data/google-vertex.json +1 -1
  95. package/dist/providers/data/google.json +1 -1
  96. package/dist/providers/data/huggingface.json +1 -1
  97. package/dist/providers/data/kimi-coding.json +1 -1
  98. package/dist/providers/data/meta.json +1 -0
  99. package/dist/providers/data/mistral.json +1 -1
  100. package/dist/providers/data/moonshotai-cn.json +1 -1
  101. package/dist/providers/data/moonshotai.json +1 -1
  102. package/dist/providers/data/nvidia.json +1 -1
  103. package/dist/providers/data/openai-codex.json +1 -1
  104. package/dist/providers/data/openai.json +1 -1
  105. package/dist/providers/data/opencode-go.json +1 -1
  106. package/dist/providers/data/opencode.json +1 -1
  107. package/dist/providers/data/openrouter.json +1 -1
  108. package/dist/providers/data/qwen-token-plan-cn.json +1 -1
  109. package/dist/providers/data/qwen-token-plan.json +1 -1
  110. package/dist/providers/data/radius.json +1 -0
  111. package/dist/providers/data/together.json +1 -1
  112. package/dist/providers/data/vercel-ai-gateway.json +1 -1
  113. package/dist/providers/data/zai-coding-cn.json +1 -1
  114. package/dist/providers/data/zai.json +1 -1
  115. package/dist/providers/faux.d.ts +2 -2
  116. package/dist/providers/faux.d.ts.map +1 -1
  117. package/dist/providers/faux.js +11 -11
  118. package/dist/providers/faux.js.map +1 -1
  119. package/dist/providers/meta.d.ts +3 -0
  120. package/dist/providers/meta.d.ts.map +1 -0
  121. package/dist/providers/meta.js +24 -0
  122. package/dist/providers/meta.js.map +1 -0
  123. package/dist/providers/meta.models.d.ts +4 -0
  124. package/dist/providers/meta.models.d.ts.map +1 -0
  125. package/dist/providers/meta.models.js +6 -0
  126. package/dist/providers/meta.models.js.map +1 -0
  127. package/dist/providers/opencode-go.d.ts.map +1 -1
  128. package/dist/providers/opencode-go.js +4 -3
  129. package/dist/providers/opencode-go.js.map +1 -1
  130. package/dist/providers/opencode-headers.d.ts +4 -0
  131. package/dist/providers/opencode-headers.d.ts.map +1 -0
  132. package/dist/providers/opencode-headers.js +22 -0
  133. package/dist/providers/opencode-headers.js.map +1 -0
  134. package/dist/providers/opencode.d.ts.map +1 -1
  135. package/dist/providers/opencode.js +5 -4
  136. package/dist/providers/opencode.js.map +1 -1
  137. package/dist/providers/radius.d.ts.map +1 -1
  138. package/dist/providers/radius.js +19 -5
  139. package/dist/providers/radius.js.map +1 -1
  140. package/dist/providers/radius.models.d.ts +4 -0
  141. package/dist/providers/radius.models.d.ts.map +1 -0
  142. package/dist/providers/radius.models.js +6 -0
  143. package/dist/providers/radius.models.js.map +1 -0
  144. package/dist/types.d.ts +98 -27
  145. package/dist/types.d.ts.map +1 -1
  146. package/dist/types.js.map +1 -1
  147. package/dist/utils/diagnostics.d.ts +3 -2
  148. package/dist/utils/diagnostics.d.ts.map +1 -1
  149. package/dist/utils/diagnostics.js.map +1 -1
  150. package/dist/utils/estimate.d.ts +2 -2
  151. package/dist/utils/estimate.d.ts.map +1 -1
  152. package/dist/utils/estimate.js +8 -29
  153. package/dist/utils/estimate.js.map +1 -1
  154. package/dist/utils/event-stream.d.ts.map +1 -1
  155. package/dist/utils/event-stream.js +25 -7
  156. package/dist/utils/event-stream.js.map +1 -1
  157. package/dist/utils/overflow.d.ts +1 -0
  158. package/dist/utils/overflow.d.ts.map +1 -1
  159. package/dist/utils/overflow.js +11 -5
  160. package/dist/utils/overflow.js.map +1 -1
  161. package/dist/utils/retry.d.ts +6 -1
  162. package/dist/utils/retry.d.ts.map +1 -1
  163. package/dist/utils/retry.js +9 -1
  164. package/dist/utils/retry.js.map +1 -1
  165. package/dist/utils/text.d.ts +9 -1
  166. package/dist/utils/text.d.ts.map +1 -1
  167. package/dist/utils/text.js +26 -0
  168. package/dist/utils/text.js.map +1 -1
  169. package/dist/utils/transcript.d.ts +84 -0
  170. package/dist/utils/transcript.d.ts.map +1 -0
  171. package/dist/utils/transcript.js +204 -0
  172. package/dist/utils/transcript.js.map +1 -0
  173. package/package.json +9 -9
  174. package/dist/utils/deferred-tools.d.ts +0 -9
  175. package/dist/utils/deferred-tools.d.ts.map +0 -1
  176. package/dist/utils/deferred-tools.js +0 -36
  177. package/dist/utils/deferred-tools.js.map +0 -1
@@ -0,0 +1,22 @@
1
+ const OPENCODE_SESSION_HEADER = "x-opencode-session";
2
+ function hasHeader(headers, name) {
3
+ const expected = name.toLowerCase();
4
+ return Object.keys(headers ?? {}).some((key) => key.toLowerCase() === expected);
5
+ }
6
+ function withSessionHeader(options) {
7
+ if (!options?.sessionId || hasHeader(options.headers, OPENCODE_SESSION_HEADER))
8
+ return options;
9
+ return {
10
+ ...options,
11
+ headers: { ...options.headers, [OPENCODE_SESSION_HEADER]: options.sessionId },
12
+ };
13
+ }
14
+ /** Adds OpenCode's required per-conversation routing header before API dispatch. */
15
+ export function withOpenCodeSessionHeader(streams) {
16
+ return {
17
+ ...streams,
18
+ stream: (model, context, options) => streams.stream(model, context, withSessionHeader(options)),
19
+ streamSimple: (model, context, options) => streams.streamSimple(model, context, withSessionHeader(options)),
20
+ };
21
+ }
22
+ //# sourceMappingURL=opencode-headers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opencode-headers.js","sourceRoot":"","sources":["../../src/providers/opencode-headers.ts"],"names":[],"mappings":"AAEA,MAAM,uBAAuB,GAAG,oBAAoB,CAAC;AAErD,SAAS,SAAS,CAAC,OAAoC,EAAE,IAAY,EAAW;IAC/E,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IACpC,OAAO,MAAM,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,QAAQ,CAAC,CAAC;AAAA,CAChF;AAED,SAAS,iBAAiB,CAAiC,OAA6B,EAAwB;IAC/G,IAAI,CAAC,OAAO,EAAE,SAAS,IAAI,SAAS,CAAC,OAAO,CAAC,OAAO,EAAE,uBAAuB,CAAC;QAAE,OAAO,OAAO,CAAC;IAC/F,OAAO;QACN,GAAG,OAAO;QACV,OAAO,EAAE,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,uBAAuB,CAAC,EAAE,OAAO,CAAC,SAAS,EAAE;KAC7E,CAAC;AAAA,CACF;AAED,oFAAoF;AACpF,MAAM,UAAU,yBAAyB,CAAC,OAAwB,EAAmB;IACpF,OAAO;QACN,GAAG,OAAO;QACV,MAAM,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,iBAAiB,CAAC,OAAO,CAAC,CAAC;QAC/F,YAAY,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,iBAAiB,CAAC,OAAO,CAAC,CAAC;KAC3G,CAAC;AAAA,CACF","sourcesContent":["import type { ProviderHeaders, ProviderStreams, StreamOptions } from \"../types.ts\";\n\nconst OPENCODE_SESSION_HEADER = \"x-opencode-session\";\n\nfunction hasHeader(headers: ProviderHeaders | undefined, name: string): boolean {\n\tconst expected = name.toLowerCase();\n\treturn Object.keys(headers ?? {}).some((key) => key.toLowerCase() === expected);\n}\n\nfunction withSessionHeader<TOptions extends StreamOptions>(options: TOptions | undefined): TOptions | undefined {\n\tif (!options?.sessionId || hasHeader(options.headers, OPENCODE_SESSION_HEADER)) return options;\n\treturn {\n\t\t...options,\n\t\theaders: { ...options.headers, [OPENCODE_SESSION_HEADER]: options.sessionId },\n\t};\n}\n\n/** Adds OpenCode's required per-conversation routing header before API dispatch. */\nexport function withOpenCodeSessionHeader(streams: ProviderStreams): ProviderStreams {\n\treturn {\n\t\t...streams,\n\t\tstream: (model, context, options) => streams.stream(model, context, withSessionHeader(options)),\n\t\tstreamSimple: (model, context, options) => streams.streamSimple(model, context, withSessionHeader(options)),\n\t};\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"opencode.d.ts","sourceRoot":"","sources":["../../src/providers/opencode.ts"],"names":[],"mappings":"AAKA,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,cAAc,CAAC;AAG7D,wBAAgB,gBAAgB,IAAI,QAAQ,CAC3C,oBAAoB,GAAG,sBAAsB,GAAG,oBAAoB,GAAG,kBAAkB,CACzF,CAaA","sourcesContent":["import { anthropicMessagesApi } from \"../api/anthropic-messages.lazy.ts\";\nimport { googleGenerativeAIApi } from \"../api/google-generative-ai.lazy.ts\";\nimport { openAICompletionsApi } from \"../api/openai-completions.lazy.ts\";\nimport { openAIResponsesApi } from \"../api/openai-responses.lazy.ts\";\nimport { envApiKeyAuth } from \"../auth/helpers.ts\";\nimport { createProvider, type Provider } from \"../models.ts\";\nimport { OPENCODE_MODELS } from \"./opencode.models.ts\";\n\nexport function opencodeProvider(): Provider<\n\t\"anthropic-messages\" | \"google-generative-ai\" | \"openai-completions\" | \"openai-responses\"\n> {\n\treturn createProvider({\n\t\tid: \"opencode\",\n\t\tname: \"OpenCode Zen\",\n\t\tauth: { apiKey: envApiKeyAuth(\"OpenCode API key\", [\"OPENCODE_API_KEY\"]) },\n\t\tmodels: Object.values(OPENCODE_MODELS),\n\t\tapi: {\n\t\t\t\"anthropic-messages\": anthropicMessagesApi(),\n\t\t\t\"google-generative-ai\": googleGenerativeAIApi(),\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":"opencode.d.ts","sourceRoot":"","sources":["../../src/providers/opencode.ts"],"names":[],"mappings":"AAKA,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,cAAc,CAAC;AAI7D,wBAAgB,gBAAgB,IAAI,QAAQ,CAC3C,oBAAoB,GAAG,sBAAsB,GAAG,oBAAoB,GAAG,kBAAkB,CACzF,CAaA","sourcesContent":["import { anthropicMessagesApi } from \"../api/anthropic-messages.lazy.ts\";\nimport { googleGenerativeAIApi } from \"../api/google-generative-ai.lazy.ts\";\nimport { openAICompletionsApi } from \"../api/openai-completions.lazy.ts\";\nimport { openAIResponsesApi } from \"../api/openai-responses.lazy.ts\";\nimport { envApiKeyAuth } from \"../auth/helpers.ts\";\nimport { createProvider, type Provider } from \"../models.ts\";\nimport { OPENCODE_MODELS } from \"./opencode.models.ts\";\nimport { withOpenCodeSessionHeader } from \"./opencode-headers.ts\";\n\nexport function opencodeProvider(): Provider<\n\t\"anthropic-messages\" | \"google-generative-ai\" | \"openai-completions\" | \"openai-responses\"\n> {\n\treturn createProvider({\n\t\tid: \"opencode\",\n\t\tname: \"OpenCode Zen\",\n\t\tauth: { apiKey: envApiKeyAuth(\"OpenCode API key\", [\"OPENCODE_API_KEY\"]) },\n\t\tmodels: Object.values(OPENCODE_MODELS),\n\t\tapi: {\n\t\t\t\"anthropic-messages\": withOpenCodeSessionHeader(anthropicMessagesApi()),\n\t\t\t\"google-generative-ai\": withOpenCodeSessionHeader(googleGenerativeAIApi()),\n\t\t\t\"openai-completions\": withOpenCodeSessionHeader(openAICompletionsApi()),\n\t\t\t\"openai-responses\": withOpenCodeSessionHeader(openAIResponsesApi()),\n\t\t},\n\t});\n}\n"]}
@@ -5,6 +5,7 @@ import { openAIResponsesApi } from "../api/openai-responses.lazy.js";
5
5
  import { envApiKeyAuth } from "../auth/helpers.js";
6
6
  import { createProvider } from "../models.js";
7
7
  import { OPENCODE_MODELS } from "./opencode.models.js";
8
+ import { withOpenCodeSessionHeader } from "./opencode-headers.js";
8
9
  export function opencodeProvider() {
9
10
  return createProvider({
10
11
  id: "opencode",
@@ -12,10 +13,10 @@ export function opencodeProvider() {
12
13
  auth: { apiKey: envApiKeyAuth("OpenCode API key", ["OPENCODE_API_KEY"]) },
13
14
  models: Object.values(OPENCODE_MODELS),
14
15
  api: {
15
- "anthropic-messages": anthropicMessagesApi(),
16
- "google-generative-ai": googleGenerativeAIApi(),
17
- "openai-completions": openAICompletionsApi(),
18
- "openai-responses": openAIResponsesApi(),
16
+ "anthropic-messages": withOpenCodeSessionHeader(anthropicMessagesApi()),
17
+ "google-generative-ai": withOpenCodeSessionHeader(googleGenerativeAIApi()),
18
+ "openai-completions": withOpenCodeSessionHeader(openAICompletionsApi()),
19
+ "openai-responses": withOpenCodeSessionHeader(openAIResponsesApi()),
19
20
  },
20
21
  });
21
22
  }
@@ -1 +1 @@
1
- {"version":3,"file":"opencode.js","sourceRoot":"","sources":["../../src/providers/opencode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAC5E,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAiB,MAAM,cAAc,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,MAAM,UAAU,gBAAgB,GAE9B;IACD,OAAO,cAAc,CAAC;QACrB,EAAE,EAAE,UAAU;QACd,IAAI,EAAE,cAAc;QACpB,IAAI,EAAE,EAAE,MAAM,EAAE,aAAa,CAAC,kBAAkB,EAAE,CAAC,kBAAkB,CAAC,CAAC,EAAE;QACzE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC;QACtC,GAAG,EAAE;YACJ,oBAAoB,EAAE,oBAAoB,EAAE;YAC5C,sBAAsB,EAAE,qBAAqB,EAAE;YAC/C,oBAAoB,EAAE,oBAAoB,EAAE;YAC5C,kBAAkB,EAAE,kBAAkB,EAAE;SACxC;KACD,CAAC,CAAC;AAAA,CACH","sourcesContent":["import { anthropicMessagesApi } from \"../api/anthropic-messages.lazy.ts\";\nimport { googleGenerativeAIApi } from \"../api/google-generative-ai.lazy.ts\";\nimport { openAICompletionsApi } from \"../api/openai-completions.lazy.ts\";\nimport { openAIResponsesApi } from \"../api/openai-responses.lazy.ts\";\nimport { envApiKeyAuth } from \"../auth/helpers.ts\";\nimport { createProvider, type Provider } from \"../models.ts\";\nimport { OPENCODE_MODELS } from \"./opencode.models.ts\";\n\nexport function opencodeProvider(): Provider<\n\t\"anthropic-messages\" | \"google-generative-ai\" | \"openai-completions\" | \"openai-responses\"\n> {\n\treturn createProvider({\n\t\tid: \"opencode\",\n\t\tname: \"OpenCode Zen\",\n\t\tauth: { apiKey: envApiKeyAuth(\"OpenCode API key\", [\"OPENCODE_API_KEY\"]) },\n\t\tmodels: Object.values(OPENCODE_MODELS),\n\t\tapi: {\n\t\t\t\"anthropic-messages\": anthropicMessagesApi(),\n\t\t\t\"google-generative-ai\": googleGenerativeAIApi(),\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":"opencode.js","sourceRoot":"","sources":["../../src/providers/opencode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAC5E,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAiB,MAAM,cAAc,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAElE,MAAM,UAAU,gBAAgB,GAE9B;IACD,OAAO,cAAc,CAAC;QACrB,EAAE,EAAE,UAAU;QACd,IAAI,EAAE,cAAc;QACpB,IAAI,EAAE,EAAE,MAAM,EAAE,aAAa,CAAC,kBAAkB,EAAE,CAAC,kBAAkB,CAAC,CAAC,EAAE;QACzE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC;QACtC,GAAG,EAAE;YACJ,oBAAoB,EAAE,yBAAyB,CAAC,oBAAoB,EAAE,CAAC;YACvE,sBAAsB,EAAE,yBAAyB,CAAC,qBAAqB,EAAE,CAAC;YAC1E,oBAAoB,EAAE,yBAAyB,CAAC,oBAAoB,EAAE,CAAC;YACvE,kBAAkB,EAAE,yBAAyB,CAAC,kBAAkB,EAAE,CAAC;SACnE;KACD,CAAC,CAAC;AAAA,CACH","sourcesContent":["import { anthropicMessagesApi } from \"../api/anthropic-messages.lazy.ts\";\nimport { googleGenerativeAIApi } from \"../api/google-generative-ai.lazy.ts\";\nimport { openAICompletionsApi } from \"../api/openai-completions.lazy.ts\";\nimport { openAIResponsesApi } from \"../api/openai-responses.lazy.ts\";\nimport { envApiKeyAuth } from \"../auth/helpers.ts\";\nimport { createProvider, type Provider } from \"../models.ts\";\nimport { OPENCODE_MODELS } from \"./opencode.models.ts\";\nimport { withOpenCodeSessionHeader } from \"./opencode-headers.ts\";\n\nexport function opencodeProvider(): Provider<\n\t\"anthropic-messages\" | \"google-generative-ai\" | \"openai-completions\" | \"openai-responses\"\n> {\n\treturn createProvider({\n\t\tid: \"opencode\",\n\t\tname: \"OpenCode Zen\",\n\t\tauth: { apiKey: envApiKeyAuth(\"OpenCode API key\", [\"OPENCODE_API_KEY\"]) },\n\t\tmodels: Object.values(OPENCODE_MODELS),\n\t\tapi: {\n\t\t\t\"anthropic-messages\": withOpenCodeSessionHeader(anthropicMessagesApi()),\n\t\t\t\"google-generative-ai\": withOpenCodeSessionHeader(googleGenerativeAIApi()),\n\t\t\t\"openai-completions\": withOpenCodeSessionHeader(openAICompletionsApi()),\n\t\t\t\"openai-responses\": withOpenCodeSessionHeader(openAIResponsesApi()),\n\t\t},\n\t});\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"radius.d.ts","sourceRoot":"","sources":["../../src/providers/radius.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAS7C,MAAM,WAAW,qBAAqB;IACrC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,+EAA+E;AAC/E,wBAAgB,cAAc,CAAC,OAAO,GAAE,qBAA0B,GAAG,QAAQ,CAAC,aAAa,CAAC,CA8D3F","sourcesContent":["import { piMessagesApi } from \"../api/pi-messages.lazy.ts\";\nimport { envApiKeyAuth, lazyOAuth } from \"../auth/helpers.ts\";\nimport { loadRadiusOAuth } from \"../auth/oauth/load.ts\";\nimport type { Provider } from \"../models.ts\";\nimport {\n\tDEFAULT_RADIUS_GATEWAY,\n\tgetRadiusModels,\n\tgetRadiusModelsFromConfig,\n\tloadRadiusGatewayConfig,\n\tnormalizeRadiusGatewayUrl,\n} from \"./radius-config.ts\";\n\nexport interface RadiusProviderOptions {\n\tid?: string;\n\tname?: string;\n\tgateway?: string;\n}\n\n/** Radius gateway provider with a persisted, dynamically refreshed catalog. */\nexport function radiusProvider(options: RadiusProviderOptions = {}): Provider<\"pi-messages\"> {\n\tconst id = options.id ?? \"radius\";\n\tconst name = options.name ?? \"Radius\";\n\tconst gateway = normalizeRadiusGatewayUrl(options.gateway ?? DEFAULT_RADIUS_GATEWAY);\n\tlet models = getRadiusModels(id, undefined);\n\tconst streams = piMessagesApi();\n\n\treturn {\n\t\tid,\n\t\tname,\n\t\tauth: {\n\t\t\tapiKey: envApiKeyAuth(\"Radius API key\", [\"RADIUS_API_KEY\"]),\n\t\t\toauth: lazyOAuth({ name, load: () => loadRadiusOAuth({ name, gateway }) }),\n\t\t},\n\t\tgetModels: () => models,\n\t\trefreshModels: async (context) => {\n\t\t\tconst stored = context.stored;\n\t\t\tif (stored) {\n\t\t\t\tconst restored = stored.models.filter((model) => model.provider === id) as typeof models;\n\t\t\t\tif (\n\t\t\t\t\t!(await context.publish({\n\t\t\t\t\t\tupdate: () => {\n\t\t\t\t\t\t\tmodels = restored;\n\t\t\t\t\t\t},\n\t\t\t\t\t}))\n\t\t\t\t) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Import catalogs cached by the pre-ModelsStore Radius implementation.\n\t\t\tif (!stored && context.credential?.type === \"oauth\") {\n\t\t\t\tconst legacy = getRadiusModels(id, context.credential);\n\t\t\t\tif (legacy.length > 0) {\n\t\t\t\t\tif (\n\t\t\t\t\t\t!(await context.publish({\n\t\t\t\t\t\t\tpersist: { models: legacy, checkedAt: Date.now() },\n\t\t\t\t\t\t\tupdate: () => {\n\t\t\t\t\t\t\t\tmodels = legacy;\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}))\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!context.allowNetwork || context.signal.aborted) return;\n\t\t\tconst apiKey = context.credential?.type === \"oauth\" ? context.credential.access : context.credential?.key;\n\t\t\tconst config = await loadRadiusGatewayConfig(gateway, apiKey, context.signal);\n\t\t\tif (context.signal.aborted) return;\n\t\t\tconst refreshed = getRadiusModelsFromConfig(id, config);\n\t\t\tawait context.publish({\n\t\t\t\tpersist: { models: refreshed, checkedAt: Date.now() },\n\t\t\t\tupdate: () => {\n\t\t\t\t\tmodels = refreshed;\n\t\t\t\t},\n\t\t\t});\n\t\t},\n\t\tstream: (model, context, streamOptions) => streams.stream(model, context, streamOptions),\n\t\tstreamSimple: (model, context, streamOptions) => streams.streamSimple(model, context, streamOptions),\n\t};\n}\n"]}
1
+ {"version":3,"file":"radius.d.ts","sourceRoot":"","sources":["../../src/providers/radius.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAW7C,MAAM,WAAW,qBAAqB;IACrC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,+EAA+E;AAC/E,wBAAgB,cAAc,CAAC,OAAO,GAAE,qBAA0B,GAAG,QAAQ,CAAC,aAAa,CAAC,CA0E3F","sourcesContent":["import { piMessagesApi } from \"../api/pi-messages.lazy.ts\";\nimport { envApiKeyAuth, lazyOAuth } from \"../auth/helpers.ts\";\nimport { loadRadiusOAuth } from \"../auth/oauth/load.ts\";\nimport type { Provider } from \"../models.ts\";\nimport type { Model } from \"../types.ts\";\nimport { RADIUS_MODELS } from \"./radius.models.ts\";\nimport {\n\tDEFAULT_RADIUS_GATEWAY,\n\tgetRadiusModels,\n\tgetRadiusModelsFromConfig,\n\tloadRadiusGatewayConfig,\n\tnormalizeRadiusGatewayUrl,\n} from \"./radius-config.ts\";\n\nexport interface RadiusProviderOptions {\n\tid?: string;\n\tname?: string;\n\tgateway?: string;\n}\n\n/** Radius gateway provider with a persisted, dynamically refreshed catalog. */\nexport function radiusProvider(options: RadiusProviderOptions = {}): Provider<\"pi-messages\"> {\n\tconst id = options.id ?? \"radius\";\n\tconst name = options.name ?? \"Radius\";\n\tconst gateway = normalizeRadiusGatewayUrl(options.gateway ?? DEFAULT_RADIUS_GATEWAY);\n\tconst baselineModels: Model<\"pi-messages\">[] =\n\t\tgateway === normalizeRadiusGatewayUrl(DEFAULT_RADIUS_GATEWAY)\n\t\t\t? Object.values(RADIUS_MODELS).map((model) => ({ ...model, provider: id }))\n\t\t\t: [];\n\tlet dynamicModels = getRadiusModels(id, undefined);\n\tconst streams = piMessagesApi();\n\n\treturn {\n\t\tid,\n\t\tname,\n\t\tauth: {\n\t\t\tapiKey: envApiKeyAuth(\"Radius API key\", [\"RADIUS_API_KEY\"]),\n\t\t\toauth: lazyOAuth({ name, load: () => loadRadiusOAuth({ name, gateway }) }),\n\t\t},\n\t\tgetModels: () => {\n\t\t\tconst merged = [...baselineModels];\n\t\t\tfor (const model of dynamicModels) {\n\t\t\t\tconst index = merged.findIndex((entry) => entry.id === model.id);\n\t\t\t\tif (index >= 0) merged[index] = model;\n\t\t\t\telse merged.push(model);\n\t\t\t}\n\t\t\treturn merged;\n\t\t},\n\t\trefreshModels: async (context) => {\n\t\t\tconst stored = context.stored;\n\t\t\tif (stored) {\n\t\t\t\tconst restored = stored.models.filter((model) => model.provider === id) as typeof dynamicModels;\n\t\t\t\tif (\n\t\t\t\t\t!(await context.publish({\n\t\t\t\t\t\tupdate: () => {\n\t\t\t\t\t\t\tdynamicModels = restored;\n\t\t\t\t\t\t},\n\t\t\t\t\t}))\n\t\t\t\t) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Import catalogs cached by the pre-ModelsStore Radius implementation.\n\t\t\tif (!stored && context.credential?.type === \"oauth\") {\n\t\t\t\tconst legacy = getRadiusModels(id, context.credential);\n\t\t\t\tif (legacy.length > 0) {\n\t\t\t\t\tif (\n\t\t\t\t\t\t!(await context.publish({\n\t\t\t\t\t\t\tpersist: { models: legacy, checkedAt: Date.now() },\n\t\t\t\t\t\t\tupdate: () => {\n\t\t\t\t\t\t\t\tdynamicModels = legacy;\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}))\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!context.allowNetwork || context.signal.aborted) return;\n\t\t\tconst apiKey = context.credential?.type === \"oauth\" ? context.credential.access : context.credential?.key;\n\t\t\tconst config = await loadRadiusGatewayConfig(gateway, apiKey, context.signal);\n\t\t\tif (context.signal.aborted) return;\n\t\t\tconst refreshed = getRadiusModelsFromConfig(id, config);\n\t\t\tawait context.publish({\n\t\t\t\tpersist: { models: refreshed, checkedAt: Date.now() },\n\t\t\t\tupdate: () => {\n\t\t\t\t\tdynamicModels = refreshed;\n\t\t\t\t},\n\t\t\t});\n\t\t},\n\t\tstream: (model, context, streamOptions) => streams.stream(model, context, streamOptions),\n\t\tstreamSimple: (model, context, streamOptions) => streams.streamSimple(model, context, streamOptions),\n\t};\n}\n"]}
@@ -1,13 +1,17 @@
1
1
  import { piMessagesApi } from "../api/pi-messages.lazy.js";
2
2
  import { envApiKeyAuth, lazyOAuth } from "../auth/helpers.js";
3
3
  import { loadRadiusOAuth } from "../auth/oauth/load.js";
4
+ import { RADIUS_MODELS } from "./radius.models.js";
4
5
  import { DEFAULT_RADIUS_GATEWAY, getRadiusModels, getRadiusModelsFromConfig, loadRadiusGatewayConfig, normalizeRadiusGatewayUrl, } from "./radius-config.js";
5
6
  /** Radius gateway provider with a persisted, dynamically refreshed catalog. */
6
7
  export function radiusProvider(options = {}) {
7
8
  const id = options.id ?? "radius";
8
9
  const name = options.name ?? "Radius";
9
10
  const gateway = normalizeRadiusGatewayUrl(options.gateway ?? DEFAULT_RADIUS_GATEWAY);
10
- let models = getRadiusModels(id, undefined);
11
+ const baselineModels = gateway === normalizeRadiusGatewayUrl(DEFAULT_RADIUS_GATEWAY)
12
+ ? Object.values(RADIUS_MODELS).map((model) => ({ ...model, provider: id }))
13
+ : [];
14
+ let dynamicModels = getRadiusModels(id, undefined);
11
15
  const streams = piMessagesApi();
12
16
  return {
13
17
  id,
@@ -16,14 +20,24 @@ export function radiusProvider(options = {}) {
16
20
  apiKey: envApiKeyAuth("Radius API key", ["RADIUS_API_KEY"]),
17
21
  oauth: lazyOAuth({ name, load: () => loadRadiusOAuth({ name, gateway }) }),
18
22
  },
19
- getModels: () => models,
23
+ getModels: () => {
24
+ const merged = [...baselineModels];
25
+ for (const model of dynamicModels) {
26
+ const index = merged.findIndex((entry) => entry.id === model.id);
27
+ if (index >= 0)
28
+ merged[index] = model;
29
+ else
30
+ merged.push(model);
31
+ }
32
+ return merged;
33
+ },
20
34
  refreshModels: async (context) => {
21
35
  const stored = context.stored;
22
36
  if (stored) {
23
37
  const restored = stored.models.filter((model) => model.provider === id);
24
38
  if (!(await context.publish({
25
39
  update: () => {
26
- models = restored;
40
+ dynamicModels = restored;
27
41
  },
28
42
  }))) {
29
43
  return;
@@ -36,7 +50,7 @@ export function radiusProvider(options = {}) {
36
50
  if (!(await context.publish({
37
51
  persist: { models: legacy, checkedAt: Date.now() },
38
52
  update: () => {
39
- models = legacy;
53
+ dynamicModels = legacy;
40
54
  },
41
55
  }))) {
42
56
  return;
@@ -53,7 +67,7 @@ export function radiusProvider(options = {}) {
53
67
  await context.publish({
54
68
  persist: { models: refreshed, checkedAt: Date.now() },
55
69
  update: () => {
56
- models = refreshed;
70
+ dynamicModels = refreshed;
57
71
  },
58
72
  });
59
73
  },
@@ -1 +1 @@
1
- {"version":3,"file":"radius.js","sourceRoot":"","sources":["../../src/providers/radius.ts"],"names":[],"mappings":"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","sourcesContent":["import { piMessagesApi } from \"../api/pi-messages.lazy.ts\";\nimport { envApiKeyAuth, lazyOAuth } from \"../auth/helpers.ts\";\nimport { loadRadiusOAuth } from \"../auth/oauth/load.ts\";\nimport type { Provider } from \"../models.ts\";\nimport {\n\tDEFAULT_RADIUS_GATEWAY,\n\tgetRadiusModels,\n\tgetRadiusModelsFromConfig,\n\tloadRadiusGatewayConfig,\n\tnormalizeRadiusGatewayUrl,\n} from \"./radius-config.ts\";\n\nexport interface RadiusProviderOptions {\n\tid?: string;\n\tname?: string;\n\tgateway?: string;\n}\n\n/** Radius gateway provider with a persisted, dynamically refreshed catalog. */\nexport function radiusProvider(options: RadiusProviderOptions = {}): Provider<\"pi-messages\"> {\n\tconst id = options.id ?? \"radius\";\n\tconst name = options.name ?? \"Radius\";\n\tconst gateway = normalizeRadiusGatewayUrl(options.gateway ?? DEFAULT_RADIUS_GATEWAY);\n\tlet models = getRadiusModels(id, undefined);\n\tconst streams = piMessagesApi();\n\n\treturn {\n\t\tid,\n\t\tname,\n\t\tauth: {\n\t\t\tapiKey: envApiKeyAuth(\"Radius API key\", [\"RADIUS_API_KEY\"]),\n\t\t\toauth: lazyOAuth({ name, load: () => loadRadiusOAuth({ name, gateway }) }),\n\t\t},\n\t\tgetModels: () => models,\n\t\trefreshModels: async (context) => {\n\t\t\tconst stored = context.stored;\n\t\t\tif (stored) {\n\t\t\t\tconst restored = stored.models.filter((model) => model.provider === id) as typeof models;\n\t\t\t\tif (\n\t\t\t\t\t!(await context.publish({\n\t\t\t\t\t\tupdate: () => {\n\t\t\t\t\t\t\tmodels = restored;\n\t\t\t\t\t\t},\n\t\t\t\t\t}))\n\t\t\t\t) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Import catalogs cached by the pre-ModelsStore Radius implementation.\n\t\t\tif (!stored && context.credential?.type === \"oauth\") {\n\t\t\t\tconst legacy = getRadiusModels(id, context.credential);\n\t\t\t\tif (legacy.length > 0) {\n\t\t\t\t\tif (\n\t\t\t\t\t\t!(await context.publish({\n\t\t\t\t\t\t\tpersist: { models: legacy, checkedAt: Date.now() },\n\t\t\t\t\t\t\tupdate: () => {\n\t\t\t\t\t\t\t\tmodels = legacy;\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}))\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!context.allowNetwork || context.signal.aborted) return;\n\t\t\tconst apiKey = context.credential?.type === \"oauth\" ? context.credential.access : context.credential?.key;\n\t\t\tconst config = await loadRadiusGatewayConfig(gateway, apiKey, context.signal);\n\t\t\tif (context.signal.aborted) return;\n\t\t\tconst refreshed = getRadiusModelsFromConfig(id, config);\n\t\t\tawait context.publish({\n\t\t\t\tpersist: { models: refreshed, checkedAt: Date.now() },\n\t\t\t\tupdate: () => {\n\t\t\t\t\tmodels = refreshed;\n\t\t\t\t},\n\t\t\t});\n\t\t},\n\t\tstream: (model, context, streamOptions) => streams.stream(model, context, streamOptions),\n\t\tstreamSimple: (model, context, streamOptions) => streams.streamSimple(model, context, streamOptions),\n\t};\n}\n"]}
1
+ {"version":3,"file":"radius.js","sourceRoot":"","sources":["../../src/providers/radius.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAGxD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EACN,sBAAsB,EACtB,eAAe,EACf,yBAAyB,EACzB,uBAAuB,EACvB,yBAAyB,GACzB,MAAM,oBAAoB,CAAC;AAQ5B,+EAA+E;AAC/E,MAAM,UAAU,cAAc,CAAC,OAAO,GAA0B,EAAE,EAA2B;IAC5F,MAAM,EAAE,GAAG,OAAO,CAAC,EAAE,IAAI,QAAQ,CAAC;IAClC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,QAAQ,CAAC;IACtC,MAAM,OAAO,GAAG,yBAAyB,CAAC,OAAO,CAAC,OAAO,IAAI,sBAAsB,CAAC,CAAC;IACrF,MAAM,cAAc,GACnB,OAAO,KAAK,yBAAyB,CAAC,sBAAsB,CAAC;QAC5D,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC;QAC3E,CAAC,CAAC,EAAE,CAAC;IACP,IAAI,aAAa,GAAG,eAAe,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;IACnD,MAAM,OAAO,GAAG,aAAa,EAAE,CAAC;IAEhC,OAAO;QACN,EAAE;QACF,IAAI;QACJ,IAAI,EAAE;YACL,MAAM,EAAE,aAAa,CAAC,gBAAgB,EAAE,CAAC,gBAAgB,CAAC,CAAC;YAC3D,KAAK,EAAE,SAAS,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,eAAe,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;SAC1E;QACD,SAAS,EAAE,GAAG,EAAE,CAAC;YAChB,MAAM,MAAM,GAAG,CAAC,GAAG,cAAc,CAAC,CAAC;YACnC,KAAK,MAAM,KAAK,IAAI,aAAa,EAAE,CAAC;gBACnC,MAAM,KAAK,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,KAAK,CAAC,EAAE,CAAC,CAAC;gBACjE,IAAI,KAAK,IAAI,CAAC;oBAAE,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC;;oBACjC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACzB,CAAC;YACD,OAAO,MAAM,CAAC;QAAA,CACd;QACD,aAAa,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC;YACjC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;YAC9B,IAAI,MAAM,EAAE,CAAC;gBACZ,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,KAAK,EAAE,CAAyB,CAAC;gBAChG,IACC,CAAC,CAAC,MAAM,OAAO,CAAC,OAAO,CAAC;oBACvB,MAAM,EAAE,GAAG,EAAE,CAAC;wBACb,aAAa,GAAG,QAAQ,CAAC;oBAAA,CACzB;iBACD,CAAC,CAAC,EACF,CAAC;oBACF,OAAO;gBACR,CAAC;YACF,CAAC;YAED,uEAAuE;YACvE,IAAI,CAAC,MAAM,IAAI,OAAO,CAAC,UAAU,EAAE,IAAI,KAAK,OAAO,EAAE,CAAC;gBACrD,MAAM,MAAM,GAAG,eAAe,CAAC,EAAE,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;gBACvD,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACvB,IACC,CAAC,CAAC,MAAM,OAAO,CAAC,OAAO,CAAC;wBACvB,OAAO,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE;wBAClD,MAAM,EAAE,GAAG,EAAE,CAAC;4BACb,aAAa,GAAG,MAAM,CAAC;wBAAA,CACvB;qBACD,CAAC,CAAC,EACF,CAAC;wBACF,OAAO;oBACR,CAAC;gBACF,CAAC;YACF,CAAC;YAED,IAAI,CAAC,OAAO,CAAC,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC,OAAO;gBAAE,OAAO;YAC5D,MAAM,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC;YAC1G,MAAM,MAAM,GAAG,MAAM,uBAAuB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;YAC9E,IAAI,OAAO,CAAC,MAAM,CAAC,OAAO;gBAAE,OAAO;YACnC,MAAM,SAAS,GAAG,yBAAyB,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;YACxD,MAAM,OAAO,CAAC,OAAO,CAAC;gBACrB,OAAO,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE;gBACrD,MAAM,EAAE,GAAG,EAAE,CAAC;oBACb,aAAa,GAAG,SAAS,CAAC;gBAAA,CAC1B;aACD,CAAC,CAAC;QAAA,CACH;QACD,MAAM,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,aAAa,CAAC;QACxF,YAAY,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,EAAE,CAAC,OAAO,CAAC,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,aAAa,CAAC;KACpG,CAAC;AAAA,CACF","sourcesContent":["import { piMessagesApi } from \"../api/pi-messages.lazy.ts\";\nimport { envApiKeyAuth, lazyOAuth } from \"../auth/helpers.ts\";\nimport { loadRadiusOAuth } from \"../auth/oauth/load.ts\";\nimport type { Provider } from \"../models.ts\";\nimport type { Model } from \"../types.ts\";\nimport { RADIUS_MODELS } from \"./radius.models.ts\";\nimport {\n\tDEFAULT_RADIUS_GATEWAY,\n\tgetRadiusModels,\n\tgetRadiusModelsFromConfig,\n\tloadRadiusGatewayConfig,\n\tnormalizeRadiusGatewayUrl,\n} from \"./radius-config.ts\";\n\nexport interface RadiusProviderOptions {\n\tid?: string;\n\tname?: string;\n\tgateway?: string;\n}\n\n/** Radius gateway provider with a persisted, dynamically refreshed catalog. */\nexport function radiusProvider(options: RadiusProviderOptions = {}): Provider<\"pi-messages\"> {\n\tconst id = options.id ?? \"radius\";\n\tconst name = options.name ?? \"Radius\";\n\tconst gateway = normalizeRadiusGatewayUrl(options.gateway ?? DEFAULT_RADIUS_GATEWAY);\n\tconst baselineModels: Model<\"pi-messages\">[] =\n\t\tgateway === normalizeRadiusGatewayUrl(DEFAULT_RADIUS_GATEWAY)\n\t\t\t? Object.values(RADIUS_MODELS).map((model) => ({ ...model, provider: id }))\n\t\t\t: [];\n\tlet dynamicModels = getRadiusModels(id, undefined);\n\tconst streams = piMessagesApi();\n\n\treturn {\n\t\tid,\n\t\tname,\n\t\tauth: {\n\t\t\tapiKey: envApiKeyAuth(\"Radius API key\", [\"RADIUS_API_KEY\"]),\n\t\t\toauth: lazyOAuth({ name, load: () => loadRadiusOAuth({ name, gateway }) }),\n\t\t},\n\t\tgetModels: () => {\n\t\t\tconst merged = [...baselineModels];\n\t\t\tfor (const model of dynamicModels) {\n\t\t\t\tconst index = merged.findIndex((entry) => entry.id === model.id);\n\t\t\t\tif (index >= 0) merged[index] = model;\n\t\t\t\telse merged.push(model);\n\t\t\t}\n\t\t\treturn merged;\n\t\t},\n\t\trefreshModels: async (context) => {\n\t\t\tconst stored = context.stored;\n\t\t\tif (stored) {\n\t\t\t\tconst restored = stored.models.filter((model) => model.provider === id) as typeof dynamicModels;\n\t\t\t\tif (\n\t\t\t\t\t!(await context.publish({\n\t\t\t\t\t\tupdate: () => {\n\t\t\t\t\t\t\tdynamicModels = restored;\n\t\t\t\t\t\t},\n\t\t\t\t\t}))\n\t\t\t\t) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Import catalogs cached by the pre-ModelsStore Radius implementation.\n\t\t\tif (!stored && context.credential?.type === \"oauth\") {\n\t\t\t\tconst legacy = getRadiusModels(id, context.credential);\n\t\t\t\tif (legacy.length > 0) {\n\t\t\t\t\tif (\n\t\t\t\t\t\t!(await context.publish({\n\t\t\t\t\t\t\tpersist: { models: legacy, checkedAt: Date.now() },\n\t\t\t\t\t\t\tupdate: () => {\n\t\t\t\t\t\t\t\tdynamicModels = legacy;\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}))\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!context.allowNetwork || context.signal.aborted) return;\n\t\t\tconst apiKey = context.credential?.type === \"oauth\" ? context.credential.access : context.credential?.key;\n\t\t\tconst config = await loadRadiusGatewayConfig(gateway, apiKey, context.signal);\n\t\t\tif (context.signal.aborted) return;\n\t\t\tconst refreshed = getRadiusModelsFromConfig(id, config);\n\t\t\tawait context.publish({\n\t\t\t\tpersist: { models: refreshed, checkedAt: Date.now() },\n\t\t\t\tupdate: () => {\n\t\t\t\t\tdynamicModels = refreshed;\n\t\t\t\t},\n\t\t\t});\n\t\t},\n\t\tstream: (model, context, streamOptions) => streams.stream(model, context, streamOptions),\n\t\tstreamSimple: (model, context, streamOptions) => streams.streamSimple(model, context, streamOptions),\n\t};\n}\n"]}
@@ -0,0 +1,4 @@
1
+ import values from "./data/radius.json";
2
+ import { type ModelCatalog } from "../model-catalog.ts";
3
+ export declare const RADIUS_MODELS: ModelCatalog<typeof values, "radius">;
4
+ //# sourceMappingURL=radius.models.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"radius.models.d.ts","sourceRoot":"","sources":["../../src/providers/radius.models.ts"],"names":[],"mappings":"AAGA,OAAO,MAAM,MAAM,oBAAoB,CAAuB;AAC9D,OAAO,EAAuB,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAE7E,eAAO,MAAM,aAAa,EAAE,YAAY,CAAC,OAAO,MAAM,EAAE,QAAQ,CAC1B,CAAC","sourcesContent":["// This file is auto-generated by scripts/generate-models.ts\n// Do not edit manually - run 'npm run generate-models' to update\n\nimport values from \"./data/radius.json\" with { type: \"json\" };\nimport { flattenModelCatalog, type ModelCatalog } from \"../model-catalog.ts\";\n\nexport const RADIUS_MODELS: ModelCatalog<typeof values, \"radius\"> =\n\tflattenModelCatalog(\"radius\", values);\n"]}
@@ -0,0 +1,6 @@
1
+ // This file is auto-generated by scripts/generate-models.ts
2
+ // Do not edit manually - run 'npm run generate-models' to update
3
+ import values from "./data/radius.json" with { type: "json" };
4
+ import { flattenModelCatalog } from "../model-catalog.js";
5
+ export const RADIUS_MODELS = flattenModelCatalog("radius", values);
6
+ //# sourceMappingURL=radius.models.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"radius.models.js","sourceRoot":"","sources":["../../src/providers/radius.models.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,iEAAiE;AAEjE,OAAO,MAAM,MAAM,oBAAoB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AAC9D,OAAO,EAAE,mBAAmB,EAAqB,MAAM,qBAAqB,CAAC;AAE7E,MAAM,CAAC,MAAM,aAAa,GACzB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC","sourcesContent":["// This file is auto-generated by scripts/generate-models.ts\n// Do not edit manually - run 'npm run generate-models' to update\n\nimport values from \"./data/radius.json\" with { type: \"json\" };\nimport { flattenModelCatalog, type ModelCatalog } from \"../model-catalog.ts\";\n\nexport const RADIUS_MODELS: ModelCatalog<typeof values, \"radius\"> =\n\tflattenModelCatalog(\"radius\", values);\n"]}
package/dist/types.d.ts CHANGED
@@ -16,7 +16,7 @@ export type KnownApi = "openai-completions" | "mistral-conversations" | "openai-
16
16
  export type Api = KnownApi | (string & {});
17
17
  export type KnownImagesApi = "openrouter-images";
18
18
  export type ImagesApi = KnownImagesApi | (string & {});
19
- export type KnownProvider = "amazon-bedrock" | "ant-ling" | "anthropic" | "google" | "google-vertex" | "openai" | "azure-openai-responses" | "openai-codex" | "radius" | "nvidia" | "deepseek" | "github-copilot" | "xai" | "groq" | "cerebras" | "openrouter" | "vercel-ai-gateway" | "zai" | "zai-coding-cn" | "mistral" | "minimax" | "minimax-cn" | "moonshotai" | "moonshotai-cn" | "huggingface" | "fireworks" | "together" | "baseten" | "opencode" | "opencode-go" | "kimi-coding" | "cloudflare-workers-ai" | "cloudflare-ai-gateway" | "qwen-token-plan" | "qwen-token-plan-cn" | "qwen-token-plan-individual" | "xiaomi" | "xiaomi-token-plan-cn" | "xiaomi-token-plan-ams" | "xiaomi-token-plan-sgp";
19
+ export type KnownProvider = "amazon-bedrock" | "ant-ling" | "anthropic" | "google" | "google-vertex" | "openai" | "azure-openai-responses" | "openai-codex" | "radius" | "nvidia" | "deepseek" | "github-copilot" | "xai" | "groq" | "cerebras" | "openrouter" | "vercel-ai-gateway" | "zai" | "zai-coding-cn" | "mistral" | "minimax" | "minimax-cn" | "moonshotai" | "moonshotai-cn" | "huggingface" | "fireworks" | "together" | "baseten" | "opencode" | "opencode-go" | "kimi-coding" | "meta" | "cloudflare-workers-ai" | "cloudflare-ai-gateway" | "qwen-token-plan" | "qwen-token-plan-cn" | "qwen-token-plan-individual" | "xiaomi" | "xiaomi-token-plan-cn" | "xiaomi-token-plan-ams" | "xiaomi-token-plan-sgp";
20
20
  export type ProviderId = KnownProvider | string;
21
21
  export type KnownImagesProvider = "openrouter";
22
22
  export type ImagesProviderId = KnownImagesProvider | string;
@@ -38,6 +38,11 @@ export interface ThinkingBudgets {
38
38
  high?: number;
39
39
  }
40
40
  export type CacheRetention = "none" | "short" | "long";
41
+ /**
42
+ * Best-effort prompt cache lifetime in seconds for each retention tier a request can ask for.
43
+ * A missing tier means the lifetime is unknown; pi does not warm such caches.
44
+ */
45
+ export type ModelPromptCache = Partial<Record<Exclude<CacheRetention, "none">, number>>;
41
46
  export type Transport = "sse" | "websocket" | "websocket-cached" | "auto";
42
47
  /** Provider-scoped environment overrides. Values take precedence over process.env. */
43
48
  export type ProviderEnv = Record<string, string>;
@@ -189,8 +194,8 @@ export type ApiStreamOptions<TApi extends Api> = TApi extends keyof ApiOptionsMa
189
194
  * `Provider.stream()` via `ApiStreamOptions`.
190
195
  */
191
196
  export interface ProviderStreams {
192
- stream(model: Model<Api>, context: Context, options?: StreamOptions): AssistantMessageEventStream;
193
- streamSimple(model: Model<Api>, context: Context, options?: SimpleStreamOptions): AssistantMessageEventStream;
197
+ stream(model: Model<Api>, context: TranscriptContext, options?: StreamOptions): AssistantMessageEventStream;
198
+ streamSimple(model: Model<Api>, context: TranscriptContext, options?: SimpleStreamOptions): AssistantMessageEventStream;
194
199
  fetchDeferred?(model: Model<Api>, handle: DeferredHandle, options?: DeferredFetchOptions): AssistantMessageEventStream;
195
200
  cancelDeferred?(model: Model<Api>, handle: DeferredHandle, options?: DeferredCancelOptions): Promise<void>;
196
201
  }
@@ -227,7 +232,7 @@ export interface SimpleStreamOptions extends StreamOptions {
227
232
  /** Custom token budgets for thinking levels (token-based providers only) */
228
233
  thinkingBudgets?: ThinkingBudgets;
229
234
  }
230
- export type StreamFunction<TApi extends Api = Api, TOptions extends StreamOptions = StreamOptions> = (model: Model<TApi>, context: Context, options?: TOptions) => AssistantMessageEventStream;
235
+ export type StreamFunction<TApi extends Api = Api, TOptions extends StreamOptions = StreamOptions> = (model: Model<TApi>, context: TranscriptContext, options?: TOptions) => AssistantMessageEventStream;
231
236
  export type ImagesFunction<TApi extends ImagesApi = ImagesApi, TOptions extends ImagesOptions = ImagesOptions> = (model: ImagesModel<TApi>, context: ImagesContext, options?: TOptions) => Promise<AssistantImages>;
232
237
  export interface TextSignatureV1 {
233
238
  v: 1;
@@ -257,7 +262,7 @@ export interface ToolCall {
257
262
  type: "toolCall";
258
263
  id: string;
259
264
  name: string;
260
- arguments: Record<string, any>;
265
+ arguments: JsonObject;
261
266
  thoughtSignature?: string;
262
267
  /** OpenAI Responses namespace for calls to dynamically loaded or namespaced tools. */
263
268
  namespace?: string;
@@ -285,9 +290,23 @@ export interface Usage {
285
290
  };
286
291
  }
287
292
  export type StopReason = "pending" | "stop" | "length" | "toolUse" | "error" | "aborted" | "deferred";
288
- export type JsonValue = null | boolean | number | string | JsonValue[] | {
293
+ export type JsonValue = null | boolean | number | string | readonly JsonValue[] | JsonObject;
294
+ export type JsonObject = {
289
295
  [key: string]: JsonValue;
290
296
  };
297
+ type IsAny<T> = 0 extends 1 & T ? true : false;
298
+ type IsExactlyJsonValue<T> = [T] extends [JsonValue] ? ([JsonValue] extends [T] ? true : false) : false;
299
+ type IsJsonProperty<T> = IsAny<T> extends true ? false : unknown extends T ? false : [Exclude<T, undefined>] extends [never] ? true : IsJsonCompatible<Exclude<T, undefined>>;
300
+ type InvalidJsonKeys<T extends object> = {
301
+ [TKey in keyof T]-?: TKey extends string | number ? (IsJsonProperty<T[TKey]> extends true ? never : TKey) : TKey;
302
+ }[keyof T];
303
+ type IsJsonCompatible<T> = IsAny<T> extends true ? false : unknown extends T ? false : IsExactlyJsonValue<T> extends true ? true : T extends null | boolean | number | string ? true : T extends undefined ? false : T extends readonly (infer TItem)[] ? IsJsonCompatible<TItem> : T extends (...args: never[]) => unknown ? false : T extends object ? [InvalidJsonKeys<T>] extends [never] ? true : false : false;
304
+ /** The JSON representation of a typed in-memory value. Optional object properties remain optional. */
305
+ export type JsonRepresentation<T> = IsAny<T> extends true ? JsonValue : unknown extends T ? JsonValue : [T] extends [JsonValue] ? T : T extends readonly unknown[] ? {
306
+ [TKey in keyof T]: JsonRepresentation<Exclude<T[TKey], undefined>>;
307
+ } : T extends object ? {
308
+ [TKey in keyof T]: JsonRepresentation<Exclude<T[TKey], undefined>>;
309
+ } : never;
291
310
  export interface DeferredHandle {
292
311
  provider: string;
293
312
  modelId: string;
@@ -299,6 +318,33 @@ export interface DeferredHandle {
299
318
  /** Provider conversion data required to reconstruct the final assistant message. */
300
319
  data?: JsonValue;
301
320
  }
321
+ /**
322
+ * System instructions and tool declarations at one point in the transcript.
323
+ *
324
+ * The leading system message is the system prompt. Later system messages change it:
325
+ * `content` adds instructions from that point on, `sections` replace or remove named
326
+ * prompt sections, and `toolsAdded`/`toolsRemoved` change the tool set. Replaying
327
+ * every system message in order yields the current prompt and tools. Providers that
328
+ * accept system messages mid-conversation send each one in place; other providers
329
+ * rebuild the leading system message from the replayed state.
330
+ */
331
+ export interface SystemMessage {
332
+ role: "system";
333
+ /** Instruction text. On the leading message this is the base prompt; later, additional instructions. */
334
+ content: string | TextContent[];
335
+ /**
336
+ * Named, ordered prompt sections rendered verbatim after `content`. The leading message
337
+ * declares them; later messages replace sections by name, and `null` removes one. Keep
338
+ * each section self-delimiting (a tag, a heading) so the model can relate an update to
339
+ * the original. Avoid integer-like names; JSON objects reorder those.
340
+ */
341
+ sections?: Record<string, string | null>;
342
+ /** Complete definitions of tools that become available at this point. */
343
+ toolsAdded?: Tool[];
344
+ /** Tools that stop being available at this point. */
345
+ toolsRemoved?: ToolReference[];
346
+ timestamp: number;
347
+ }
302
348
  export interface UserMessage {
303
349
  role: "user";
304
350
  content: string | (TextContent | ImageContent)[];
@@ -327,24 +373,18 @@ export interface AssistantMessage {
327
373
  endTurn?: boolean;
328
374
  timestamp: number;
329
375
  }
330
- export interface ToolResultMessage<TDetails = any> {
376
+ export type ToolResultMessage<TDetails = JsonValue> = IsJsonCompatible<TDetails> extends true ? {
331
377
  role: "toolResult";
332
378
  toolCallId: string;
333
379
  toolName: string;
334
380
  content: (TextContent | ImageContent)[];
335
- details?: TDetails;
381
+ details?: JsonRepresentation<TDetails>;
336
382
  /** Usage from the tool execution itself, if available. Not part of main LLM context accounting. */
337
383
  usage?: Usage;
338
- /**
339
- * Names from `Context.tools` that became available after this result.
340
- * Providers with native deferred tool loading use this as the load point;
341
- * other providers ignore it and use `Context.tools` normally.
342
- */
343
- addedToolNames?: string[];
344
384
  isError: boolean;
345
385
  timestamp: number;
346
- }
347
- export type Message = UserMessage | AssistantMessage | ToolResultMessage;
386
+ } : never;
387
+ export type Message = SystemMessage | UserMessage | AssistantMessage | ToolResultMessage;
348
388
  export type ImagesInputContent = TextContent | ImageContent;
349
389
  export type ImagesOutputContent = TextContent | ImageContent;
350
390
  export interface ImagesContext {
@@ -386,11 +426,31 @@ export interface Tool<TParameters extends TSchema = TSchema> {
386
426
  parameters: TParameters;
387
427
  constrainedSampling?: false | ConstrainedSamplingConfig;
388
428
  }
429
+ export interface ToolReference {
430
+ name: string;
431
+ }
432
+ /**
433
+ * Request input accepted by the public stream entry points (`Models.stream()`,
434
+ * `streamSimple()`, ...). `systemPrompt` and `tools` are shorthand for a leading
435
+ * system message; `normalizeContext()` folds them into one before the request
436
+ * reaches a provider.
437
+ */
389
438
  export interface Context {
390
439
  systemPrompt?: string;
391
440
  messages: Message[];
392
441
  tools?: Tool[];
393
442
  }
443
+ declare const transcriptContextBrand: unique symbol;
444
+ /**
445
+ * Normalized request context passed to providers and API implementations. The
446
+ * prompt and tool declarations are carried by the transcript's system messages.
447
+ * Only `normalizeContext()` produces this type, so a raw `Context` cannot reach
448
+ * provider code by accident.
449
+ */
450
+ export type TranscriptContext = {
451
+ messages: Message[];
452
+ readonly [transcriptContextBrand]: true;
453
+ };
394
454
  /**
395
455
  * Event protocol for AssistantMessageEventStream.
396
456
  *
@@ -510,14 +570,16 @@ export interface OpenAICompletionsCompat {
510
570
  supportsThinkingTokenBudget?: boolean;
511
571
  /** 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. */
512
572
  supportsOpenAIGrammarTools?: boolean;
573
+ /** Whether the exact model accepts system or developer messages after the conversation has started. When false, later system messages are folded into the leading system message. Default: false; the generated model catalog enables it for verified models. */
574
+ supportsMidConvoSystemMessages?: boolean;
575
+ /** Whether system messages can introduce additional tools mid-conversation. Requires `supportsMidConvoSystemMessages`. Default: false; the generated model catalog enables it for capable models. */
576
+ supportsMidConvoToolAdditions?: boolean;
513
577
  /** Whether the provider supports the `strict` field in tool definitions. Default: true. */
514
578
  supportsStrictMode?: boolean;
515
579
  /** Cache control convention for prompt caching. "anthropic" applies Anthropic-style `cache_control` markers to the system prompt, last tool definition, and last user, assistant, or tool-result text content. */
516
580
  cacheControlFormat?: "anthropic";
517
- /** Whether to send session-affinity data from `options.sessionId`. Default: false. */
581
+ /** Whether to send session-affinity data from `options.sessionId`. Default: true for OpenRouter endpoints, false otherwise. */
518
582
  sendSessionAffinityHeaders?: boolean;
519
- /** Provider-specific deferred tool serialization mode. */
520
- deferredToolsMode?: "kimi";
521
583
  /** Session-affinity header format: `openai` sends `session_id`, `x-client-request-id`, and `x-session-affinity`; `openai-nosession` sends `x-client-request-id` and `x-session-affinity`; `openrouter` sends `x-session-id`. Does not affect the `prompt_cache_key` body param, which is governed by cache retention. Default: auto-detected. */
522
584
  sessionAffinityFormat?: SessionAffinityFormat;
523
585
  /** Whether the provider supports long prompt cache retention (`prompt_cache_retention: "24h"` or Anthropic-style `cache_control.ttl: "1h"`, depending on format). Default: true. */
@@ -534,6 +596,8 @@ export interface OpenAICompletionsCompat {
534
596
  export interface OpenAIResponsesCompat {
535
597
  /** Whether the provider supports the `developer` role (vs `system`). Default: true. */
536
598
  supportsDeveloperRole?: boolean;
599
+ /** Whether the exact model accepts developer or system messages after the conversation has started. When false, later system messages are folded into the leading system message. Default: false; the generated model catalog enables it for verified models. */
600
+ supportsMidConvoSystemMessages?: boolean;
537
601
  /** Session-affinity header format: `openai` sends `session_id` and `x-client-request-id`; `openai-nosession` sends `x-client-request-id`; `openrouter` sends `x-session-id`. Does not affect the `prompt_cache_key` body param, which is governed by cache retention. Default: auto-detected. */
538
602
  sessionAffinityFormat?: SessionAffinityFormat;
539
603
  /** Whether the provider supports long prompt cache retention. This uses `prompt_cache_options.ttl: "30m"` on GPT-5.6+ and `prompt_cache_retention: "24h"` on earlier models. Default: true. */
@@ -544,7 +608,7 @@ export interface OpenAIResponsesCompat {
544
608
  supportsOpenAIGrammarTools?: boolean;
545
609
  /** Whether the model supports message-anchored `additional_tools` input items. Default: false. */
546
610
  supportsAdditionalTools?: boolean;
547
- /** Whether the model supports client-executed tool search for deferred tools. Default: false. */
611
+ /** Whether the model supports client-executed tool search for transcript-anchored additions. Default: false. */
548
612
  supportsToolSearch?: boolean;
549
613
  /** Whether the model accepts `prompt_cache_options` (OpenAI GPT-5.6+ prompt caching). Older OpenAI models reject the parameter. Default: false. */
550
614
  supportsExplicitPromptCacheMode?: boolean;
@@ -571,6 +635,8 @@ export interface AnthropicMessagesCompat {
571
635
  * Default: false.
572
636
  */
573
637
  sendSessionAffinityHeaders?: boolean;
638
+ /** Session-affinity format. `"openrouter"` sends `x-session-id`; when unset, sends `x-session-affinity`. */
639
+ sessionAffinityFormat?: "openrouter";
574
640
  /**
575
641
  * Whether the provider supports Anthropic-style `cache_control` markers on
576
642
  * tool definitions. When false, `cache_control` is omitted from tool params.
@@ -601,6 +667,10 @@ export interface AnthropicMessagesCompat {
601
667
  supportsStrictTools?: boolean;
602
668
  /** Whether the exact model transport supports effort-only system messages and thinking binding controls. Default: false. */
603
669
  supportsMidConvoEffort?: boolean;
670
+ /** Whether the exact model accepts system-role messages inside the conversation. When false, later system messages are folded into the top-level system prompt. Default: false. */
671
+ supportsMidConvoSystemMessages?: boolean;
672
+ /** Whether the exact model accepts mid-conversation `tool_addition` and `tool_removal` blocks. Requires `supportsMidConvoSystemMessages`. Default: false. */
673
+ supportsMidConvoToolChanges?: boolean;
604
674
  /**
605
675
  * Models Anthropic accepts in `fallbacks` for server-side refusal fallback,
606
676
  * with local pricing metadata for returned fallback responses. When absent or
@@ -608,18 +678,17 @@ export interface AnthropicMessagesCompat {
608
678
  * with no permitted fallback targets.
609
679
  */
610
680
  allowedFallbackModels?: AnthropicAllowedFallbackModel[];
611
- /**
612
- * Whether the provider supports deferred tools loaded by `tool_reference`
613
- * blocks in tool results. Default: true for first-party Anthropic models
614
- * except Haiku and models older than Claude 4.5; false for other providers.
615
- */
616
- supportsToolReferences?: boolean;
617
681
  }
618
682
  /** Compatibility settings for Amazon Bedrock models. */
619
683
  export interface BedrockCompat {
620
684
  /** Whether the model supports Bedrock strict tool schemas. Default: false. */
621
685
  supportsStrictMode?: boolean;
622
686
  }
687
+ /** Compatibility settings for the Mistral chat API. */
688
+ export interface MistralConversationsCompat {
689
+ /** Whether the exact model accepts system messages after the conversation has started. When false, later system messages are folded into the leading system message. Default: false. */
690
+ supportsMidConvoSystemMessages?: boolean;
691
+ }
623
692
  /**
624
693
  * OpenRouter provider routing preferences.
625
694
  * Controls which upstream providers OpenRouter routes requests to.
@@ -727,13 +796,15 @@ export interface Model<TApi extends Api> {
727
796
  thinkingLevelMap?: ThinkingLevelMap;
728
797
  input: ("text" | "image")[];
729
798
  cost: ModelCost;
799
+ /** Prompt cache lifetimes per retention tier. Unset when the provider's cache behavior is unknown. */
800
+ promptCache?: ModelPromptCache;
730
801
  contextWindow: number;
731
802
  maxTokens: number;
732
803
  /** Default sampling parameters for this model. See {@link StreamOptions.samplingParams}; per-request keys override these. */
733
804
  samplingParams?: Record<string, unknown>;
734
805
  headers?: Record<string, string>;
735
806
  /** Compatibility overrides for OpenAI-compatible APIs. If not set, auto-detected from baseUrl. */
736
- compat?: TApi extends "openai-completions" ? OpenAICompletionsCompat : TApi extends "openai-responses" | "azure-openai-responses" | "openai-codex-responses" ? OpenAIResponsesCompat : TApi extends "anthropic-messages" ? AnthropicMessagesCompat : TApi extends "bedrock-converse-stream" ? BedrockCompat : never;
807
+ compat?: TApi extends "openai-completions" ? OpenAICompletionsCompat : TApi extends "openai-responses" | "azure-openai-responses" | "openai-codex-responses" ? OpenAIResponsesCompat : TApi extends "anthropic-messages" ? AnthropicMessagesCompat : TApi extends "bedrock-converse-stream" ? BedrockCompat : TApi extends "mistral-conversations" ? MistralConversationsCompat : never;
737
808
  }
738
809
  export interface ImagesModel<TApi extends ImagesApi> extends Omit<Model<Api>, "api" | "provider" | "reasoning" | "contextWindow" | "maxTokens" | "compat"> {
739
810
  api: TApi;