@vellumai/assistant 0.12.5 → 0.12.6-dev.202609292116.41f7caa

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 (295) hide show
  1. package/.env.example +2 -0
  2. package/ARCHITECTURE.md +26 -3
  3. package/docs/automatic-done.md +32 -0
  4. package/docs/desktop-browser-cli.md +3 -2
  5. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/package.json +2 -1
  6. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/__tests__/mcp-oauth.test.ts +53 -0
  7. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
  8. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/mcp-oauth.ts +60 -0
  9. package/node_modules/@vellumai/environments/src/shell.test.ts +13 -1
  10. package/node_modules/@vellumai/environments/src/shell.ts +22 -1
  11. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/package.json +2 -1
  12. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/__tests__/mcp-oauth.test.ts +53 -0
  13. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
  14. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/mcp-oauth.ts +60 -0
  15. package/node_modules/@vellumai/gateway-client/src/__tests__/status-contracts.test.ts +39 -0
  16. package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +25 -0
  17. package/node_modules/@vellumai/service-contracts/package.json +2 -1
  18. package/node_modules/@vellumai/service-contracts/src/__tests__/mcp-oauth.test.ts +53 -0
  19. package/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
  20. package/node_modules/@vellumai/service-contracts/src/mcp-oauth.ts +60 -0
  21. package/openapi.yaml +270 -10
  22. package/package.json +1 -1
  23. package/src/__tests__/agent-loop.test.ts +76 -0
  24. package/src/__tests__/anthropic-provider.test.ts +2 -0
  25. package/src/__tests__/byok-default-profile-ensure.test.ts +7 -0
  26. package/src/__tests__/config-get-vision-flag.test.ts +1 -1
  27. package/src/__tests__/config-loader-validation-reset-notice.test.ts +2 -2
  28. package/src/__tests__/conversation-agent-loop-overflow.test.ts +160 -154
  29. package/src/__tests__/conversation-evictor.test.ts +54 -0
  30. package/src/__tests__/conversation-pairing.test.ts +112 -0
  31. package/src/__tests__/document-append-idempotency.test.ts +13 -0
  32. package/src/__tests__/document-create-dedupe.test.ts +13 -0
  33. package/src/__tests__/document-find-replace.test.ts +13 -0
  34. package/src/__tests__/document-revision-history.test.ts +390 -0
  35. package/src/__tests__/document-revision.test.ts +425 -0
  36. package/src/__tests__/document-tool-security.test.ts +13 -0
  37. package/src/__tests__/document-update-default-surface.test.ts +13 -0
  38. package/src/__tests__/emit-signal-routing-intent.test.ts +270 -0
  39. package/src/__tests__/gateway-flag-listener.test.ts +59 -6
  40. package/src/__tests__/headless-browser-navigate.test.ts +20 -30
  41. package/src/__tests__/host-cu-proxy.test.ts +79 -0
  42. package/src/__tests__/host-cu-routes-targeted.test.ts +14 -5
  43. package/src/__tests__/host-shell-tool.test.ts +6 -2
  44. package/src/__tests__/identity-routes.test.ts +4 -3
  45. package/src/__tests__/list-messages-client-message-id.test.ts +43 -0
  46. package/src/__tests__/llm-catalog-parity.test.ts +4 -4
  47. package/src/__tests__/llm-schema.test.ts +1 -1
  48. package/src/__tests__/notification-platform-adapter.test.ts +83 -1
  49. package/src/__tests__/oauth2-gateway-transport.test.ts +2 -0
  50. package/src/__tests__/openai-provider.test.ts +38 -11
  51. package/src/__tests__/pricing.test.ts +11 -0
  52. package/src/__tests__/public-ingress-urls.test.ts +26 -0
  53. package/src/__tests__/retry-thinking-tool-choice.test.ts +47 -0
  54. package/src/__tests__/skill-execute-input.test.ts +11 -0
  55. package/src/__tests__/tool-approval-handler.test.ts +4 -0
  56. package/src/__tests__/tool-preview-lifecycle.test.ts +26 -0
  57. package/src/__tests__/usage-attribution.test.ts +31 -0
  58. package/src/__tests__/workspace-migration-133-collapse-provider-connections.test.ts +3 -3
  59. package/src/__tests__/workspace-migration-160-repair-retired-fireworks-model-ids.test.ts +262 -0
  60. package/src/__tests__/workspace-migration-161-repair-retired-fireworks-glm-5p2-model-id.test.ts +233 -0
  61. package/src/acp/agent-process.ts +6 -1
  62. package/src/acp/client-handler.ts +6 -1
  63. package/src/agent/loop-unparseable-tool-retry.test.ts +333 -0
  64. package/src/agent/loop.ts +161 -17
  65. package/src/api/events/document-editor-show.ts +5 -0
  66. package/src/api/events/document-editor-update.ts +10 -0
  67. package/src/api/events/tool-result.ts +1 -0
  68. package/src/calls/__tests__/call-controller.test.ts +273 -1
  69. package/src/calls/__tests__/media-stream-server-integration.test.ts +40 -0
  70. package/src/calls/__tests__/media-stream-stt-session.test.ts +33 -0
  71. package/src/calls/__tests__/voice-session-bridge.test.ts +54 -0
  72. package/src/calls/call-constants.ts +10 -0
  73. package/src/calls/call-controller.ts +359 -25
  74. package/src/calls/channel-admission-reader.ts +15 -9
  75. package/src/calls/media-stream-server.ts +18 -0
  76. package/src/calls/media-stream-stt-session.ts +30 -9
  77. package/src/calls/twilio-provider.ts +14 -31
  78. package/src/calls/voice-session-bridge.ts +18 -1
  79. package/src/cli/commands/browser.ts +1 -2
  80. package/src/cli/lib/__tests__/plugin-artifact.test.ts +23 -0
  81. package/src/cli/lib/__tests__/plugin-catalog-visibility.test.ts +2 -0
  82. package/src/cli/lib/__tests__/plugin-details.test.ts +16 -0
  83. package/src/cli/lib/bundled-marketplace.json +54 -2
  84. package/src/cli/lib/inspect-plugin.ts +15 -15
  85. package/src/cli/lib/list-installed-plugins.ts +29 -28
  86. package/src/cli/lib/plugin-artifact.ts +74 -63
  87. package/src/cli/lib/plugin-catalog-visibility.ts +1 -0
  88. package/src/cli/lib/plugin-details.ts +27 -42
  89. package/src/cli/lib/plugin-marketplace.ts +6 -8
  90. package/src/cli/lib/plugin-surfaces.ts +8 -7
  91. package/src/cli.ts +1 -3
  92. package/src/config/__tests__/chat-settings.test.ts +121 -0
  93. package/src/config/assistant-feature-flags.ts +28 -23
  94. package/src/config/bundled-skills/computer-use/SKILL.md +20 -0
  95. package/src/config/bundled-skills/computer-use/TOOLS.json +11 -11
  96. package/src/config/chat-settings.ts +100 -0
  97. package/src/config/default-profile-catalog.ts +1 -1
  98. package/src/config/feature-flag-cache.ts +7 -25
  99. package/src/config/feature-flag-registry.json +9 -9
  100. package/src/config/loader.ts +5 -1
  101. package/src/config/profile-text-generation.ts +25 -21
  102. package/src/config/schemas/conversations.ts +14 -0
  103. package/src/config/schemas/llm.ts +1 -0
  104. package/src/config/schemas/notifications.ts +8 -1
  105. package/src/contacts/gateway-channel-read.ts +1 -1
  106. package/src/conversations/__tests__/auto-archive-activity.test.ts +136 -0
  107. package/src/conversations/__tests__/auto-archive.test.ts +304 -0
  108. package/src/conversations/auto-archive-activity.ts +61 -0
  109. package/src/conversations/auto-archive.ts +201 -0
  110. package/src/daemon/computer-use-observation.test.ts +81 -0
  111. package/src/daemon/computer-use-observation.ts +23 -0
  112. package/src/daemon/conversation-agent-loop-handlers.ts +18 -2
  113. package/src/daemon/conversation-agent-loop.ts +14 -6
  114. package/src/daemon/conversation-evictor.ts +50 -16
  115. package/src/daemon/conversation-messaging.ts +4 -0
  116. package/src/daemon/conversation-process.ts +15 -0
  117. package/src/daemon/conversation-queue-manager.ts +2 -0
  118. package/src/daemon/conversation.ts +2 -0
  119. package/src/daemon/doordash-steps.ts +1 -3
  120. package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +43 -1
  121. package/src/daemon/handlers/__tests__/config-channels.test.ts +1 -1
  122. package/src/daemon/handlers/config-a2a.ts +75 -2
  123. package/src/daemon/handlers/shared.ts +13 -2
  124. package/src/daemon/host-cu-proxy.ts +34 -3
  125. package/src/daemon/lifecycle.ts +15 -2
  126. package/src/daemon/process-message.ts +5 -0
  127. package/src/daemon/shutdown-handlers.ts +3 -0
  128. package/src/daemon/turn-finalization.ts +4 -0
  129. package/src/desktop/desktop-browser-endpoint.ts +11 -2
  130. package/src/desktop/desktop-chrome-policy.test.ts +1 -0
  131. package/src/desktop/desktop-chrome-policy.ts +7 -1
  132. package/src/desktop/desktop-computer-use.test.ts +14 -4
  133. package/src/desktop/desktop-session-manager.ts +5 -3
  134. package/src/documents/document-revisions-store.ts +153 -0
  135. package/src/documents/document-store.ts +471 -133
  136. package/src/followups/followup-store.ts +0 -4
  137. package/src/i18n/__tests__/i18n.test.ts +25 -0
  138. package/src/i18n/assistant-text.ts +18 -0
  139. package/src/i18n/index.ts +1 -0
  140. package/src/i18n/messages.ts +11 -0
  141. package/src/inbound/__tests__/oauth-callback-url.test.ts +25 -2
  142. package/src/inbound/oauth-callback-url.ts +30 -1
  143. package/src/inbound/public-ingress-urls.ts +12 -2
  144. package/src/ipc/gateway-client.test.ts +40 -0
  145. package/src/ipc/gateway-client.ts +12 -29
  146. package/src/ipc/gateway-flag-listener.ts +7 -10
  147. package/src/live-voice/__tests__/live-voice-agent-turn.test.ts +71 -0
  148. package/src/live-voice/__tests__/live-voice-flux-turn-end.test.ts +83 -0
  149. package/src/live-voice/__tests__/protocol.test.ts +77 -0
  150. package/src/live-voice/__tests__/share-targets.test.ts +163 -0
  151. package/src/live-voice/live-voice-session.ts +23 -6
  152. package/src/live-voice/protocol.ts +22 -0
  153. package/src/live-voice/share-targets.ts +225 -0
  154. package/src/mcp/__tests__/mcp-oauth-client-registration.test.ts +144 -3
  155. package/src/mcp/__tests__/mcp-oauth-provider.test.ts +2 -0
  156. package/src/mcp/client.ts +1 -19
  157. package/src/mcp/mcp-oauth-provider.ts +66 -49
  158. package/src/media/openrouter-image-service.ts +39 -22
  159. package/src/monitoring/__tests__/oom-inheritance-sweep.test.ts +86 -0
  160. package/src/monitoring/__tests__/oom-kill-reporter.test.ts +374 -0
  161. package/src/monitoring/control.ts +2 -1
  162. package/src/monitoring/oom-inheritance-sweep.ts +96 -0
  163. package/src/monitoring/oom-kill-reporter.ts +469 -0
  164. package/src/monitoring/resource-sampler.ts +30 -0
  165. package/src/notifications/README.md +53 -4
  166. package/src/notifications/__tests__/assistant-initiated-thread.test.ts +254 -0
  167. package/src/notifications/__tests__/broadcaster.test.ts +558 -6
  168. package/src/notifications/__tests__/completion-policy.test.ts +37 -0
  169. package/src/notifications/__tests__/from-me-alert-integration.test.ts +192 -0
  170. package/src/notifications/adapters/platform.ts +14 -0
  171. package/src/notifications/assistant-initiated-thread.ts +101 -0
  172. package/src/notifications/broadcaster.ts +94 -16
  173. package/src/notifications/chat-reply-policy.ts +11 -0
  174. package/src/notifications/completion-policy.ts +12 -2
  175. package/src/notifications/conversation-pairing.ts +15 -70
  176. package/src/notifications/emit-signal.ts +34 -3
  177. package/src/notifications/types.ts +2 -0
  178. package/src/oauth/connect-orchestrator.ts +1 -2
  179. package/src/persistence/__tests__/conversation-auto-archive.test.ts +330 -0
  180. package/src/persistence/conversation-auto-archive.ts +170 -0
  181. package/src/persistence/conversation-crud.ts +2 -1
  182. package/src/persistence/conversation-queries.ts +15 -8
  183. package/src/persistence/embeddings/embed.test.ts +96 -0
  184. package/src/persistence/embeddings/embed.ts +20 -2
  185. package/src/persistence/embeddings/embedding-gemini.test.ts +39 -3
  186. package/src/persistence/embeddings/embedding-gemini.ts +39 -1
  187. package/src/persistence/embeddings/embedding-local.ts +6 -0
  188. package/src/persistence/embeddings/qdrant-manager.ts +5 -0
  189. package/src/persistence/job-utils.ts +10 -0
  190. package/src/persistence/migrations/384-add-document-revision.test.ts +83 -0
  191. package/src/persistence/migrations/384-add-document-revision.ts +21 -0
  192. package/src/persistence/migrations/385-create-document-revisions.test.ts +67 -0
  193. package/src/persistence/migrations/385-create-document-revisions.ts +28 -0
  194. package/src/persistence/migrations/386-conversations-last-reopened-at.ts +10 -0
  195. package/src/persistence/migrations/__tests__/386-conversations-last-reopened-at.test.ts +32 -0
  196. package/src/persistence/schema/conversations.ts +1 -0
  197. package/src/persistence/schema/documents.ts +20 -0
  198. package/src/persistence/steps.ts +6 -0
  199. package/src/platform/managed-speech.ts +42 -46
  200. package/src/plugin-api/vision-support.test.ts +21 -21
  201. package/src/plugins/defaults/empty-response/hooks/post-model-call.ts +11 -6
  202. package/src/providers/__tests__/dispatch-connection-routing.test.ts +1 -1
  203. package/src/providers/__tests__/search-provider-catalog.test.ts +8 -0
  204. package/src/providers/__tests__/unparseable-tool-args.test.ts +25 -0
  205. package/src/providers/anthropic/client.ts +1 -1
  206. package/src/providers/fireworks/client.test.ts +168 -0
  207. package/src/providers/fireworks/client.ts +24 -0
  208. package/src/providers/inference/adapter-factory.ts +6 -0
  209. package/src/providers/ionet/client.test.ts +143 -0
  210. package/src/providers/ionet/client.ts +37 -0
  211. package/src/providers/model-catalog.ts +141 -84
  212. package/src/providers/model-intents.ts +4 -4
  213. package/src/providers/openai/chat-completions-provider.ts +33 -2
  214. package/src/providers/retry.ts +56 -4
  215. package/src/providers/search-provider-catalog.ts +10 -0
  216. package/src/providers/types.ts +10 -2
  217. package/src/providers/unparseable-tool-args.ts +29 -5
  218. package/src/providers/usage-tracking.ts +5 -3
  219. package/src/runtime/assistant-event-hub.ts +23 -0
  220. package/src/runtime/auth/__tests__/guard-tests.test.ts +0 -7
  221. package/src/runtime/auth/__tests__/route-policy.test.ts +1 -1
  222. package/src/runtime/channel-reply-delivery.ts +2 -0
  223. package/src/runtime/channel-retry-sweep.ts +1 -2
  224. package/src/runtime/http-types.ts +3 -0
  225. package/src/runtime/migrations/__tests__/vbundle-streaming-validator.test.ts +35 -10
  226. package/src/runtime/migrations/__tests__/vbundle-validator-v1-schema.test.ts +48 -0
  227. package/src/runtime/migrations/vbundle-builder.ts +19 -3
  228. package/src/runtime/migrations/vbundle-streaming-importer.ts +14 -19
  229. package/src/runtime/migrations/vbundle-streaming-validator.ts +14 -7
  230. package/src/runtime/migrations/vbundle-validator.ts +54 -1
  231. package/src/runtime/pending-interactions.ts +20 -2
  232. package/src/runtime/routes/__tests__/contact-routes.test.ts +5 -3
  233. package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +36 -0
  234. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +375 -2
  235. package/src/runtime/routes/__tests__/inference-send-routes.test.ts +1 -1
  236. package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +12 -0
  237. package/src/runtime/routes/contact-routes.ts +2 -2
  238. package/src/runtime/routes/conversation-list-routes.ts +10 -2
  239. package/src/runtime/routes/conversation-query-routes.ts +48 -10
  240. package/src/runtime/routes/conversation-routes.ts +7 -0
  241. package/src/runtime/routes/documents-routes.ts +185 -47
  242. package/src/runtime/routes/events-routes.ts +1 -3
  243. package/src/runtime/routes/host-app-control-routes.ts +1 -0
  244. package/src/runtime/routes/host-bash-routes.ts +1 -0
  245. package/src/runtime/routes/host-browser-routes.ts +15 -0
  246. package/src/runtime/routes/host-cu-routes.ts +4 -1
  247. package/src/runtime/routes/host-file-routes.ts +1 -0
  248. package/src/runtime/routes/host-proxy-result-binding.test.ts +83 -0
  249. package/src/runtime/routes/host-proxy-result-binding.ts +25 -0
  250. package/src/runtime/routes/host-transfer-routes.ts +1 -0
  251. package/src/runtime/routes/identity-routes.ts +3 -3
  252. package/src/runtime/routes/inbound-stages/background-dispatch.ts +4 -0
  253. package/src/runtime/routes/integrations/a2a.ts +4 -1
  254. package/src/runtime/routes/migration-routes.ts +3 -1
  255. package/src/runtime/routes/notification-routes.ts +1 -2
  256. package/src/runtime/routes/ui-snapshot-routes.test.ts +1 -0
  257. package/src/runtime/routes/user-route-dispatcher.ts +5 -1
  258. package/src/runtime/verification-templates.ts +1 -2
  259. package/src/sequence/analytics.ts +0 -4
  260. package/src/sequence/engine.ts +1 -11
  261. package/src/sequence/guardrails.ts +1 -6
  262. package/src/sequence/importer.ts +0 -8
  263. package/src/sequence/store.ts +0 -10
  264. package/src/signals/user-message.ts +0 -6
  265. package/src/skills/catalog-install.ts +52 -23
  266. package/src/tools/browser/browser-execution.ts +20 -23
  267. package/src/tools/browser/cdp-client/cdp-inspect/ws-transport.ts +1 -3
  268. package/src/tools/document/document-tool.ts +13 -11
  269. package/src/tools/executor.ts +1 -2
  270. package/src/tools/host-terminal/host-shell.ts +4 -2
  271. package/src/tools/network/__tests__/web-search.test.ts +105 -0
  272. package/src/tools/network/web-fetch.ts +2 -4
  273. package/src/tools/network/web-search.ts +239 -12
  274. package/src/tools/shared/filesystem/format-diff.ts +1 -2
  275. package/src/tools/shared/shell-output.test.ts +42 -0
  276. package/src/tools/shared/shell-output.ts +27 -4
  277. package/src/tools/skills/execute.ts +10 -7
  278. package/src/tools/terminal/shell.ts +3 -3
  279. package/src/tools/tool-approval-handler.ts +9 -1
  280. package/src/tools/ui-surface/visual-validation.ts +1 -2
  281. package/src/usage/attribution.ts +18 -1
  282. package/src/util/__tests__/oom-priority.test.ts +55 -0
  283. package/src/util/__tests__/worker-memory.test.ts +16 -0
  284. package/src/util/debounce.ts +0 -4
  285. package/src/util/oom-priority.ts +79 -0
  286. package/src/util/platform.ts +0 -2
  287. package/src/util/plugin-manifest.ts +5 -7
  288. package/src/util/pricing.ts +25 -0
  289. package/src/util/worker-memory.ts +9 -3
  290. package/src/util/worker-process.ts +8 -0
  291. package/src/workspace/byok-default-profile-ensure.ts +11 -0
  292. package/src/workspace/hatched-date.ts +11 -4
  293. package/src/workspace/migrations/160-repair-retired-fireworks-model-ids.ts +209 -0
  294. package/src/workspace/migrations/161-repair-retired-fireworks-glm-5p2-model-id.ts +197 -0
  295. package/src/workspace/migrations/registry.ts +4 -0
@@ -0,0 +1,168 @@
1
+ import { beforeEach, describe, expect, test } from "bun:test";
2
+
3
+ import { setConfig } from "../../__tests__/helpers/set-config.js";
4
+ import { OpenAIChatCompletionsProvider } from "../openai/chat-completions-provider.js";
5
+ import { RetryProvider } from "../retry.js";
6
+ import type { Message, SendMessageOptions } from "../types.js";
7
+ import {
8
+ FIREWORKS_SESSION_AFFINITY_HEADER,
9
+ FireworksProvider,
10
+ resolveFireworksRequestHeaders,
11
+ } from "./client.js";
12
+
13
+ const USER_TURN: Message[] = [
14
+ { role: "user", content: [{ type: "text", text: "question" }] },
15
+ ];
16
+
17
+ interface WireCall {
18
+ params: Record<string, unknown>;
19
+ headers: Record<string, string> | undefined;
20
+ }
21
+
22
+ /** Replace the SDK client so each chat-completions call is recorded. */
23
+ function stubChatCompletions(provider: OpenAIChatCompletionsProvider) {
24
+ const calls: WireCall[] = [];
25
+ (provider as unknown as { client: unknown }).client = {
26
+ baseURL: "https://api.fireworks.example/inference/v1",
27
+ chat: {
28
+ completions: {
29
+ create: async (
30
+ params: Record<string, unknown>,
31
+ options?: { headers?: Record<string, string> },
32
+ ) => {
33
+ calls.push({ params, headers: options?.headers });
34
+ return {
35
+ async *[Symbol.asyncIterator]() {
36
+ yield {
37
+ choices: [{ delta: { content: "ok" }, finish_reason: "stop" }],
38
+ usage: { prompt_tokens: 2, completion_tokens: 1 },
39
+ };
40
+ },
41
+ };
42
+ },
43
+ },
44
+ },
45
+ };
46
+ return calls;
47
+ }
48
+
49
+ function fireworksPipeline() {
50
+ const inner = new FireworksProvider(
51
+ "fw-test",
52
+ "accounts/fireworks/models/example-model",
53
+ );
54
+ const calls = stubChatCompletions(inner);
55
+ return { provider: new RetryProvider(inner), calls };
56
+ }
57
+
58
+ async function send(
59
+ provider: RetryProvider,
60
+ config: SendMessageOptions["config"],
61
+ ): Promise<void> {
62
+ await provider.sendMessage(USER_TURN, { config });
63
+ }
64
+
65
+ beforeEach(() => {
66
+ setConfig("llm", {});
67
+ });
68
+
69
+ describe("resolveFireworksRequestHeaders", () => {
70
+ test("sets the session affinity header from the key", () => {
71
+ expect(resolveFireworksRequestHeaders("conv-xyz")).toEqual({
72
+ [FIREWORKS_SESSION_AFFINITY_HEADER]: "conv-xyz",
73
+ });
74
+ });
75
+
76
+ test("omits the header without a usable key", () => {
77
+ expect(resolveFireworksRequestHeaders(undefined)).toEqual({});
78
+ expect(resolveFireworksRequestHeaders(" ")).toEqual({});
79
+ });
80
+ });
81
+
82
+ describe("Fireworks session affinity on the wire", () => {
83
+ test("sends the selectionSeed as x-session-affinity and keeps it out of the body", async () => {
84
+ const { provider, calls } = fireworksPipeline();
85
+
86
+ await send(provider, {
87
+ selectionSeed: "conv-seed",
88
+ conversationId: "conv-other",
89
+ });
90
+
91
+ expect(calls).toHaveLength(1);
92
+ expect(calls[0]!.headers?.[FIREWORKS_SESSION_AFFINITY_HEADER]).toBe(
93
+ "conv-seed",
94
+ );
95
+ const body = JSON.stringify(calls[0]!.params);
96
+ expect(body).not.toContain(FIREWORKS_SESSION_AFFINITY_HEADER);
97
+ expect(body).not.toContain("conv-seed");
98
+ expect(body).not.toContain("conv-other");
99
+ expect(calls[0]!.params).not.toHaveProperty("requestHeaders");
100
+ expect(calls[0]!.params).not.toHaveProperty("user");
101
+ });
102
+
103
+ test("falls back to conversationId when there is no selectionSeed", async () => {
104
+ const { provider, calls } = fireworksPipeline();
105
+
106
+ await send(provider, { conversationId: "conv-xyz" });
107
+
108
+ expect(calls[0]!.headers?.[FIREWORKS_SESSION_AFFINITY_HEADER]).toBe(
109
+ "conv-xyz",
110
+ );
111
+ expect(JSON.stringify(calls[0]!.params)).not.toContain("conv-xyz");
112
+ });
113
+
114
+ test("uses the same key on every call of a conversation", async () => {
115
+ const { provider, calls } = fireworksPipeline();
116
+
117
+ await send(provider, { selectionSeed: "conv-xyz" });
118
+ await send(provider, { selectionSeed: "conv-xyz" });
119
+
120
+ expect(
121
+ calls.map((call) => call.headers?.[FIREWORKS_SESSION_AFFINITY_HEADER]),
122
+ ).toEqual(["conv-xyz", "conv-xyz"]);
123
+ });
124
+
125
+ test("sends no header when the call has no conversation key", async () => {
126
+ const { provider, calls } = fireworksPipeline();
127
+
128
+ await send(provider, {});
129
+ await send(provider, { selectionSeed: " ", conversationId: "" });
130
+
131
+ for (const call of calls) {
132
+ expect(call.headers ?? {}).not.toHaveProperty(
133
+ FIREWORKS_SESSION_AFFINITY_HEADER,
134
+ );
135
+ }
136
+ });
137
+
138
+ test("ignores caller-set request headers", async () => {
139
+ const { provider, calls } = fireworksPipeline();
140
+
141
+ await send(provider, {
142
+ requestHeaders: { [FIREWORKS_SESSION_AFFINITY_HEADER]: "shared-key" },
143
+ });
144
+
145
+ expect(calls[0]!.headers ?? {}).not.toHaveProperty(
146
+ FIREWORKS_SESSION_AFFINITY_HEADER,
147
+ );
148
+ });
149
+
150
+ test("does not send the header for other chat-completions providers", async () => {
151
+ const inner = new OpenAIChatCompletionsProvider("sk-test", "some-model", {
152
+ providerName: "together",
153
+ providerLabel: "Together",
154
+ });
155
+ const calls = stubChatCompletions(inner);
156
+ const provider = new RetryProvider(inner);
157
+
158
+ await send(provider, {
159
+ selectionSeed: "conv-xyz",
160
+ conversationId: "conv-xyz",
161
+ });
162
+
163
+ expect(calls[0]!.headers ?? {}).not.toHaveProperty(
164
+ FIREWORKS_SESSION_AFFINITY_HEADER,
165
+ );
166
+ expect(JSON.stringify(calls[0]!.params)).not.toContain("conv-xyz");
167
+ });
168
+ });
@@ -12,6 +12,30 @@ export interface FireworksProviderOptions {
12
12
 
13
13
  const DEFAULT_FIREWORKS_BASE_URL = "https://api.fireworks.ai/inference/v1";
14
14
 
15
+ /**
16
+ * Fireworks routing hint. Prompt caching works only within one replica, so
17
+ * serverless and multi-replica deployments use this header to send requests
18
+ * that share a key to the same replica.
19
+ * https://docs.fireworks.ai/guides/prompt-caching#optimizing-inference-request-for-caching
20
+ */
21
+ export const FIREWORKS_SESSION_AFFINITY_HEADER = "x-session-affinity";
22
+
23
+ /**
24
+ * Headers for one outgoing Fireworks request. `sessionKey` is the durable
25
+ * per-conversation key; without one the header is omitted, because a shared
26
+ * key would pin all keyless traffic to a single replica. Transport metadata
27
+ * only; nothing here enters the request body.
28
+ */
29
+ export function resolveFireworksRequestHeaders(
30
+ sessionKey: string | undefined,
31
+ ): Record<string, string> {
32
+ const key = sessionKey?.trim();
33
+ if (!key) {
34
+ return {};
35
+ }
36
+ return { [FIREWORKS_SESSION_AFFINITY_HEADER]: key };
37
+ }
38
+
15
39
  const FIREWORKS_MODEL_EFFORT_CEILINGS = modelEffortCeilings("fireworks");
16
40
  const FIREWORKS_MODEL_SUPPORTED_EFFORTS = modelSupportedEfforts("fireworks");
17
41
 
@@ -35,6 +35,7 @@ import { AtlasCloudProvider } from "../atlascloud/client.js";
35
35
  import { BasetenProvider } from "../baseten/client.js";
36
36
  import { FireworksProvider } from "../fireworks/client.js";
37
37
  import { GeminiProvider } from "../gemini/client.js";
38
+ import { IonetProvider } from "../ionet/client.js";
38
39
  import { JevProvider } from "../jev/client.js";
39
40
  import { MinimaxProvider } from "../minimax/client.js";
40
41
  import { PROVIDER_CATALOG } from "../model-catalog.js";
@@ -206,6 +207,11 @@ const ADAPTER_FACTORIES: Record<string, AdapterFactory> = {
206
207
  streamTimeoutMs,
207
208
  ...(baseURL ? { baseURL } : {}),
208
209
  }),
210
+ ionet: ({ apiKey, model, streamTimeoutMs, baseURL }) =>
211
+ new IonetProvider(apiKey, model, {
212
+ streamTimeoutMs,
213
+ ...(baseURL ? { baseURL } : {}),
214
+ }),
209
215
  typesafe: ({ apiKey, model, streamTimeoutMs, baseURL }) =>
210
216
  new JevProvider(apiKey, model, {
211
217
  streamTimeoutMs,
@@ -0,0 +1,143 @@
1
+ /**
2
+ * Verifies the IO Intelligence (io.net) provider wiring: the SDK client must
3
+ * resolve to the documented IO Intelligence chat-completions endpoint unless
4
+ * an explicit override is supplied (custom-connection / test usage).
5
+ */
6
+
7
+ import { describe, expect, test } from "bun:test";
8
+
9
+ import { IonetProvider } from "./client.js";
10
+
11
+ type MockChunk = {
12
+ choices: Array<{
13
+ delta: { content?: string | null };
14
+ finish_reason?: string | null;
15
+ }>;
16
+ usage?: { prompt_tokens: number; completion_tokens: number };
17
+ };
18
+
19
+ const OK_CHUNKS: MockChunk[] = [
20
+ {
21
+ choices: [{ delta: { content: "ok" }, finish_reason: "stop" }],
22
+ usage: { prompt_tokens: 1, completion_tokens: 1 },
23
+ },
24
+ ];
25
+
26
+ function makeStream(chunks: MockChunk[]): AsyncIterable<MockChunk> {
27
+ return {
28
+ async *[Symbol.asyncIterator]() {
29
+ for (const c of chunks) {
30
+ yield c;
31
+ }
32
+ },
33
+ };
34
+ }
35
+
36
+ function clientOf(provider: IonetProvider) {
37
+ return (
38
+ provider as unknown as {
39
+ client: {
40
+ baseURL: string;
41
+ chat: {
42
+ completions: {
43
+ create: (params: unknown) => Promise<AsyncIterable<MockChunk>>;
44
+ };
45
+ };
46
+ };
47
+ }
48
+ ).client;
49
+ }
50
+
51
+ describe("IonetProvider", () => {
52
+ test("defaults the SDK client to the IO Intelligence endpoint", async () => {
53
+ const provider = new IonetProvider(
54
+ "test-key",
55
+ "meta-llama/Llama-3.3-70B-Instruct",
56
+ );
57
+
58
+ const client = clientOf(provider);
59
+ expect(client.baseURL).toBe("https://api.intelligence.io.solutions/api/v1");
60
+
61
+ // The same base URL must be reported on the response, read off the live
62
+ // client instance rather than a constant.
63
+ client.chat.completions.create = async () => makeStream(OK_CHUNKS);
64
+ const response = await provider.sendMessage([
65
+ { role: "user", content: [{ type: "text", text: "hi" }] },
66
+ ]);
67
+ expect(response.resolvedEndpoint).toBe(
68
+ "https://api.intelligence.io.solutions/api/v1",
69
+ );
70
+ });
71
+
72
+ test("sends tool_choice auto when tools are offered without an explicit choice", async () => {
73
+ // io.net defaults an unspecified tool_choice to "none" (not OpenAI's
74
+ // "auto"), so the provider must send the explicit default or the model
75
+ // could never invoke an offered tool.
76
+ const provider = new IonetProvider(
77
+ "test-key",
78
+ "meta-llama/Llama-3.3-70B-Instruct",
79
+ );
80
+ const client = clientOf(provider);
81
+
82
+ let seenParams:
83
+ | {
84
+ tools?: unknown;
85
+ tool_choice?: unknown;
86
+ }
87
+ | undefined;
88
+ client.chat.completions.create = async (params) => {
89
+ seenParams = params as { tools?: unknown; tool_choice?: unknown };
90
+ return makeStream(OK_CHUNKS);
91
+ };
92
+ await provider.sendMessage(
93
+ [{ role: "user", content: [{ type: "text", text: "hi" }] }],
94
+ {
95
+ tools: [
96
+ {
97
+ name: "get_weather",
98
+ description: "Get the weather",
99
+ input_schema: { type: "object", properties: {} },
100
+ },
101
+ ],
102
+ },
103
+ );
104
+ expect(Array.isArray(seenParams?.tools)).toBe(true);
105
+ expect(seenParams?.tool_choice).toBe("auto");
106
+
107
+ // An explicit caller choice still wins.
108
+ let forcedParams: { tool_choice?: unknown } | undefined;
109
+ client.chat.completions.create = async (params) => {
110
+ forcedParams = params as { tool_choice?: unknown };
111
+ return makeStream(OK_CHUNKS);
112
+ };
113
+ await provider.sendMessage(
114
+ [{ role: "user", content: [{ type: "text", text: "hi" }] }],
115
+ {
116
+ tools: [
117
+ {
118
+ name: "get_weather",
119
+ description: "Get the weather",
120
+ input_schema: { type: "object", properties: {} },
121
+ },
122
+ ],
123
+ config: { tool_choice: { type: "none" } },
124
+ },
125
+ );
126
+ expect(forcedParams?.tool_choice).toBe("none");
127
+ });
128
+
129
+ test("honours an explicit baseURL override", async () => {
130
+ const provider = new IonetProvider("test-key", "test-model", {
131
+ baseURL: "https://inference.example.test/v1",
132
+ });
133
+
134
+ const client = clientOf(provider);
135
+ expect(client.baseURL).toBe("https://inference.example.test/v1");
136
+
137
+ client.chat.completions.create = async () => makeStream(OK_CHUNKS);
138
+ const response = await provider.sendMessage([
139
+ { role: "user", content: [{ type: "text", text: "hi" }] },
140
+ ]);
141
+ expect(response.resolvedEndpoint).toBe("https://inference.example.test/v1");
142
+ });
143
+ });
@@ -0,0 +1,37 @@
1
+ import { OpenAIChatCompletionsProvider } from "../openai/chat-completions-provider.js";
2
+
3
+ export interface IonetProviderOptions {
4
+ apiKey?: string;
5
+ baseURL?: string;
6
+ streamTimeoutMs?: number;
7
+ }
8
+
9
+ const DEFAULT_IONET_BASE_URL = "https://api.intelligence.io.solutions/api/v1";
10
+
11
+ /**
12
+ * IO Intelligence (io.net) serves an OpenAI chat-completions API with
13
+ * Hugging Face-style `org/name` model ids, so it rides the shared
14
+ * chat-completions client with its own default base URL.
15
+ */
16
+ export class IonetProvider extends OpenAIChatCompletionsProvider {
17
+ constructor(
18
+ apiKey: string,
19
+ model: string,
20
+ options: IonetProviderOptions = {},
21
+ ) {
22
+ super(apiKey, model, {
23
+ baseURL: options.baseURL?.trim() || DEFAULT_IONET_BASE_URL,
24
+ providerName: "ionet",
25
+ providerLabel: "IO Intelligence",
26
+ streamTimeoutMs: options.streamTimeoutMs,
27
+ // IO Intelligence serves DeepSeek- and GLM-style thinking models whose
28
+ // reasoning arrives as `reasoning_content`; replay it there so
29
+ // follow-up requests that include tools stay acceptable upstream.
30
+ assistantReasoningField: "reasoning_content",
31
+ // io.net defaults an unspecified `tool_choice` to "none" (unlike
32
+ // OpenAI's "auto"), so tools offered without an explicit choice must
33
+ // still send one or the model could never invoke them.
34
+ defaultToolChoiceAuto: true,
35
+ });
36
+ }
37
+ }
@@ -331,6 +331,24 @@ const RAW_PROVIDER_CATALOG: ProviderCatalogEntry[] = [
331
331
  cacheReadPer1mTokens: 0.5,
332
332
  },
333
333
  },
334
+ {
335
+ id: "claude-sonnet-5-5",
336
+ displayName: "Claude Sonnet 5.5",
337
+ contextWindowTokens: 1000000,
338
+ maxOutputTokens: 128000,
339
+ longContextPricingThresholdTokens: 200000,
340
+ supportsThinking: true,
341
+ adaptiveThinkingOnly: true,
342
+ supportsCaching: true,
343
+ supportsVision: true,
344
+ supportsToolUse: true,
345
+ pricing: {
346
+ inputPer1mTokens: 2,
347
+ outputPer1mTokens: 10,
348
+ cacheWritePer1mTokens: 2.5,
349
+ cacheReadPer1mTokens: 0.2,
350
+ },
351
+ },
334
352
  {
335
353
  id: "claude-sonnet-5",
336
354
  displayName: "Claude Sonnet 5",
@@ -1062,22 +1080,9 @@ const RAW_PROVIDER_CATALOG: ProviderCatalogEntry[] = [
1062
1080
  cacheReadPer1mTokens: 0.3,
1063
1081
  },
1064
1082
  },
1065
- {
1066
- id: "accounts/fireworks/models/kimi-k2p6",
1067
- displayName: "Kimi K2.6",
1068
- contextWindowTokens: 262144,
1069
- maxOutputTokens: 32768,
1070
- supportsThinking: true,
1071
- supportsCaching: true,
1072
- supportsVision: true,
1073
- supportsToolUse: true,
1074
- maxEffort: "high",
1075
- pricing: {
1076
- inputPer1mTokens: 0.95,
1077
- outputPer1mTokens: 4.0,
1078
- cacheReadPer1mTokens: 0.16,
1079
- },
1080
- },
1083
+ // Kimi K2.6 (accounts/fireworks/models/kimi-k2p6) is intentionally
1084
+ // absent: Fireworks has no serverless deployment for it (the serving
1085
+ // API returns 404). Kimi K3 is its successor.
1081
1086
  {
1082
1087
  id: "accounts/fireworks/models/glm-5p3",
1083
1088
  displayName: "GLM 5.3",
@@ -1117,23 +1122,9 @@ const RAW_PROVIDER_CATALOG: ProviderCatalogEntry[] = [
1117
1122
  cacheReadPer1mTokens: 0.029,
1118
1123
  },
1119
1124
  },
1120
- {
1121
- id: "accounts/fireworks/models/glm-5p2",
1122
- displayName: "GLM 5.2",
1123
- // Fireworks serves GLM 5.2 with a 1,040K input window.
1124
- contextWindowTokens: 1040000,
1125
- maxOutputTokens: 131072,
1126
- supportsThinking: true,
1127
- supportsCaching: true,
1128
- supportsVision: false,
1129
- supportsToolUse: true,
1130
- maxEffort: "max",
1131
- pricing: {
1132
- inputPer1mTokens: 1.4,
1133
- outputPer1mTokens: 4.4,
1134
- cacheReadPer1mTokens: 0.26,
1135
- },
1136
- },
1125
+ // GLM 5.2 (accounts/fireworks/models/glm-5p2) is intentionally absent:
1126
+ // it is on the Fireworks serverless decommission list. GLM 5.3 is its
1127
+ // successor.
1137
1128
  // Kimi K2.5 (accounts/fireworks/models/kimi-k2p5) is intentionally
1138
1129
  // absent: Fireworks serves it on-demand/dedicated only, so serverless
1139
1130
  // chat/completions calls 404 ("not found, inaccessible, and/or not
@@ -1160,40 +1151,30 @@ const RAW_PROVIDER_CATALOG: ProviderCatalogEntry[] = [
1160
1151
  // intentionally absent: Fireworks has no serverless deployment for
1161
1152
  // it (the model page claims serverless support, but the serving API
1162
1153
  // returns 404).
1163
- {
1164
- id: "accounts/fireworks/models/deepseek-v4-pro-0813",
1165
- displayName: "DeepSeek V4 Pro",
1166
- contextWindowTokens: 1040000,
1167
- maxOutputTokens: 131072,
1168
- supportsThinking: true,
1169
- supportsCaching: true,
1170
- supportsVision: false,
1171
- supportsToolUse: true,
1172
- maxEffort: "max",
1173
- pricing: {
1174
- inputPer1mTokens: 1.32,
1175
- outputPer1mTokens: 3.96,
1176
- cacheReadPer1mTokens: 0.044,
1177
- },
1178
- },
1179
- {
1180
- id: "accounts/fireworks/models/deepseek-v4-flash-0731",
1181
- displayName: "DeepSeek V4 Flash",
1182
- contextWindowTokens: 1040000,
1154
+ // DeepSeek V4 Pro (accounts/fireworks/models/deepseek-v4-pro-0813)
1155
+ // and DeepSeek V4 Flash
1156
+ // (accounts/fireworks/models/deepseek-v4-flash-0731) are intentionally
1157
+ // absent: Fireworks has no serverless deployment for them (the
1158
+ // serving API returns 404). DeepSeek V4.1 Flash is the serverless
1159
+ // successor Fireworks names for both.
1160
+ {
1161
+ id: "accounts/fireworks/models/deepseek-v4p1-flash",
1162
+ displayName: "DeepSeek V4.1 Flash",
1163
+ contextWindowTokens: 1048576,
1183
1164
  maxOutputTokens: 131072,
1184
1165
  supportsThinking: true,
1185
1166
  supportsCaching: true,
1186
- supportsVision: false,
1167
+ supportsVision: true,
1187
1168
  supportsToolUse: true,
1188
1169
  maxEffort: "max",
1189
1170
  pricing: {
1190
- inputPer1mTokens: 0.14,
1191
- outputPer1mTokens: 0.28,
1192
- cacheReadPer1mTokens: 0.028,
1171
+ inputPer1mTokens: 0.3,
1172
+ outputPer1mTokens: 1.2,
1173
+ cacheReadPer1mTokens: 0.006,
1193
1174
  },
1194
1175
  },
1195
1176
  ],
1196
- defaultModel: "accounts/fireworks/models/deepseek-v4-flash-0731",
1177
+ defaultModel: "accounts/fireworks/models/deepseek-v4p1-flash",
1197
1178
  apiKeyUrl: "https://fireworks.ai/account/api-keys",
1198
1179
  apiKeyPlaceholder: "fw_...",
1199
1180
  },
@@ -1373,6 +1354,24 @@ const RAW_PROVIDER_CATALOG: ProviderCatalogEntry[] = [
1373
1354
  cacheReadPer1mTokens: 0.5,
1374
1355
  },
1375
1356
  },
1357
+ {
1358
+ id: "anthropic/claude-sonnet-5.5",
1359
+ displayName: "Claude Sonnet 5.5",
1360
+ contextWindowTokens: 1000000,
1361
+ maxOutputTokens: 128000,
1362
+ longContextPricingThresholdTokens: 200000,
1363
+ supportsThinking: true,
1364
+ adaptiveThinkingOnly: true,
1365
+ supportsCaching: true,
1366
+ supportsVision: true,
1367
+ supportsToolUse: true,
1368
+ pricing: {
1369
+ inputPer1mTokens: 2,
1370
+ outputPer1mTokens: 10,
1371
+ cacheWritePer1mTokens: 2.5,
1372
+ cacheReadPer1mTokens: 0.2,
1373
+ },
1374
+ },
1376
1375
  {
1377
1376
  id: "anthropic/claude-sonnet-5",
1378
1377
  displayName: "Claude Sonnet 5",
@@ -1911,32 +1910,6 @@ const RAW_PROVIDER_CATALOG: ProviderCatalogEntry[] = [
1911
1910
  },
1912
1911
  },
1913
1912
  // DeepSeek
1914
- {
1915
- id: "deepseek/deepseek-r1-0528",
1916
- displayName: "DeepSeek R1",
1917
- contextWindowTokens: 163840,
1918
- maxOutputTokens: 32000,
1919
- supportsThinking: true,
1920
- supportsCaching: true,
1921
- supportsVision: false,
1922
- supportsToolUse: true,
1923
- pricing: {
1924
- inputPer1mTokens: 0.5,
1925
- outputPer1mTokens: 2.15,
1926
- cacheReadPer1mTokens: 0.35,
1927
- },
1928
- },
1929
- {
1930
- id: "deepseek/deepseek-chat-v3-0324",
1931
- displayName: "DeepSeek V3",
1932
- contextWindowTokens: 163840,
1933
- maxOutputTokens: 32000,
1934
- supportsThinking: false,
1935
- supportsCaching: false,
1936
- supportsVision: false,
1937
- supportsToolUse: true,
1938
- pricing: { inputPer1mTokens: 0.25, outputPer1mTokens: 1.0 },
1939
- },
1940
1913
  {
1941
1914
  id: "deepseek/deepseek-v4-pro",
1942
1915
  displayName: "DeepSeek V4 Pro",
@@ -1971,6 +1944,32 @@ const RAW_PROVIDER_CATALOG: ProviderCatalogEntry[] = [
1971
1944
  cacheReadPer1mTokens: 0.028,
1972
1945
  },
1973
1946
  },
1947
+ {
1948
+ id: "deepseek/deepseek-r1-0528",
1949
+ displayName: "DeepSeek R1",
1950
+ contextWindowTokens: 163840,
1951
+ maxOutputTokens: 32000,
1952
+ supportsThinking: true,
1953
+ supportsCaching: true,
1954
+ supportsVision: false,
1955
+ supportsToolUse: true,
1956
+ pricing: {
1957
+ inputPer1mTokens: 0.5,
1958
+ outputPer1mTokens: 2.15,
1959
+ cacheReadPer1mTokens: 0.35,
1960
+ },
1961
+ },
1962
+ {
1963
+ id: "deepseek/deepseek-chat-v3-0324",
1964
+ displayName: "DeepSeek V3",
1965
+ contextWindowTokens: 163840,
1966
+ maxOutputTokens: 32000,
1967
+ supportsThinking: false,
1968
+ supportsCaching: false,
1969
+ supportsVision: false,
1970
+ supportsToolUse: true,
1971
+ pricing: { inputPer1mTokens: 0.25, outputPer1mTokens: 1.0 },
1972
+ },
1974
1973
  // Qwen
1975
1974
  {
1976
1975
  id: "qwen/qwen3.5-plus-02-15",
@@ -2427,6 +2426,24 @@ const RAW_PROVIDER_CATALOG: ProviderCatalogEntry[] = [
2427
2426
  cacheReadPer1mTokens: 0.5,
2428
2427
  },
2429
2428
  },
2429
+ {
2430
+ id: "anthropic/claude-sonnet-5.5",
2431
+ displayName: "Claude Sonnet 5.5",
2432
+ contextWindowTokens: 1000000,
2433
+ maxOutputTokens: 128000,
2434
+ longContextPricingThresholdTokens: 200000,
2435
+ supportsThinking: true,
2436
+ adaptiveThinkingOnly: true,
2437
+ supportsCaching: true,
2438
+ supportsVision: true,
2439
+ supportsToolUse: true,
2440
+ pricing: {
2441
+ inputPer1mTokens: 2,
2442
+ outputPer1mTokens: 10,
2443
+ cacheWritePer1mTokens: 2.5,
2444
+ cacheReadPer1mTokens: 0.2,
2445
+ },
2446
+ },
2430
2447
  {
2431
2448
  id: "anthropic/claude-sonnet-5",
2432
2449
  displayName: "Claude Sonnet 5",
@@ -2729,6 +2746,46 @@ const RAW_PROVIDER_CATALOG: ProviderCatalogEntry[] = [
2729
2746
  apiKeyUrl: "https://app.baseten.co/settings/api_keys",
2730
2747
  apiKeyPlaceholder: "Your Baseten API key",
2731
2748
  },
2749
+ {
2750
+ id: "ionet",
2751
+ displayName: "IO Intelligence",
2752
+ subtitle:
2753
+ "Open models served by IO Intelligence, io.net's inference platform (OpenAI-compatible). Requires an IO Intelligence API key.",
2754
+ setupMode: "api-key",
2755
+ setupHint:
2756
+ "Enter your IO Intelligence API key to enable IO Intelligence models.",
2757
+ envVar: "IONET_API_KEY",
2758
+ credentialsGuide: {
2759
+ description: "Sign in to io.net and create an IO Intelligence API key.",
2760
+ url: "https://io.net/docs/guides/intelligence/api-keys-and-secrets",
2761
+ linkLabel: "Open io.net",
2762
+ },
2763
+ // Model ids are Hugging Face-style `org/name`. Context windows and tool
2764
+ // support come from the endpoint's live `GET /models` catalog, and every
2765
+ // entry is accessible at the basic access tier.
2766
+ models: [
2767
+ {
2768
+ id: "meta-llama/Llama-3.3-70B-Instruct",
2769
+ displayName: "Llama 3.3 70B Instruct",
2770
+ contextWindowTokens: 128000,
2771
+ defaultContextWindowTokens: 128000,
2772
+ maxOutputTokens: 4096,
2773
+ supportsToolUse: true,
2774
+ },
2775
+ {
2776
+ id: "openai/gpt-oss-20b",
2777
+ displayName: "GPT-OSS 20B",
2778
+ contextWindowTokens: 64000,
2779
+ defaultContextWindowTokens: 64000,
2780
+ maxOutputTokens: 32768,
2781
+ supportsThinking: true,
2782
+ supportsToolUse: true,
2783
+ },
2784
+ ],
2785
+ defaultModel: "meta-llama/Llama-3.3-70B-Instruct",
2786
+ apiKeyUrl: "https://io.net/docs/guides/intelligence/api-keys-and-secrets",
2787
+ apiKeyPlaceholder: "Your IO Intelligence API key",
2788
+ },
2732
2789
  {
2733
2790
  id: "poolside",
2734
2791
  displayName: "Poolside",