Skip to content

Commit a0a0e32

Browse files
fix(core): make responses websockets opt-in (#48231)
Co-authored-by: rekram1-node <rekram1-node@users.noreply.github.com>
1 parent 7ed5223 commit a0a0e32

13 files changed

Lines changed: 33 additions & 24 deletions

File tree

‎packages/core/src/model-resolver.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,7 @@ export const layer = Layer.effect(
323323
cost: selected.cost,
324324
limit: selected.limit,
325325
compaction: selected.compaction,
326-
websocket: selected.websocket ?? true,
326+
websocket: selected.websocket ?? false,
327327
}
328328
})
329329
return Service.of({

‎packages/core/src/plugin/provider/azure.ts‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,10 @@ export const AzurePlugin = define({
162162
draft.settings.baseURL,
163163
resolveResourceName(draft.settings, resourceName) ?? resourceName,
164164
)
165-
if (responsesWebSocketCapable(item.provider, draft)) draft.capabilities.responsesWebsockets = true
165+
if (responsesWebSocketCapable(item.provider, draft)) {
166+
draft.capabilities.responsesWebsockets = true
167+
draft.websocket = true
168+
}
166169
})
167170
}
168171
}

‎packages/core/src/plugin/provider/openai.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,7 @@ export const OpenAIPlugin = define({
257257
for (const model of item.models.values()) {
258258
evt.model.update(item.provider.id, model.id, (draft) => {
259259
draft.capabilities.responsesWebsockets = true
260+
draft.websocket = true
260261
})
261262
}
262263
if (!chatgpt) return

‎packages/core/src/session/runner/model.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ export const resolved = (
7373
cost: options.cost,
7474
limit: options.limit,
7575
compaction: options.compaction,
76-
websocket: options.websocket ?? true,
76+
websocket: options.websocket ?? false,
7777
})
7878

7979
const layer = Layer.effect(

‎packages/core/test/generate.test.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ resolverIt.effect("resolves dynamic models with their catalog metadata", () =>
9494
capabilities: selected.capabilities,
9595
cost: selected.cost,
9696
limit: selected.limit,
97-
websocket: true,
97+
websocket: false,
9898
})
9999
}),
100100
)

‎packages/core/test/plugin/provider-azure.test.ts‎

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -488,13 +488,14 @@ describe("AzurePlugin", () => {
488488

489489
yield* addPlugin()
490490

491-
expect(
492-
required(yield* catalog.model.get(Provider.ID.azure, models.responses)).capabilities.responsesWebsockets,
493-
).toBe(true)
494-
for (const modelID of [models.chat, models.preview, models.deploymentURL, models.gateway, models.nonAzure])
495-
expect(
496-
required(yield* catalog.model.get(Provider.ID.azure, modelID)).capabilities.responsesWebsockets,
497-
).toBeUndefined()
491+
const responses = required(yield* catalog.model.get(Provider.ID.azure, models.responses))
492+
expect(responses.capabilities.responsesWebsockets).toBe(true)
493+
expect(responses.websocket).toBe(true)
494+
for (const modelID of [models.chat, models.preview, models.deploymentURL, models.gateway, models.nonAzure]) {
495+
const model = required(yield* catalog.model.get(Provider.ID.azure, modelID))
496+
expect(model.capabilities.responsesWebsockets).toBeUndefined()
497+
expect(model.websocket).toBeUndefined()
498+
}
498499
}),
499500
),
500501
)

‎packages/core/test/plugin/provider-openai.test.ts‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ describe("OpenAIPlugin", () => {
207207
expect(model.enabled).toBe(true)
208208
expect(model.limit).toEqual({ context: 1_050_000, input: 922_000, output: 128_000 })
209209
expect(model.capabilities.responsesWebsockets).toBe(true)
210+
expect(model.websocket).toBe(true)
210211
expect(direct.headers).not.toHaveProperty("originator")
211212
expect(direct.baseURL).toBe("https://api.openai.com/v1")
212213
expect(provider.headers).not.toHaveProperty("x-codex-beta-features")
@@ -216,7 +217,7 @@ describe("OpenAIPlugin", () => {
216217
}),
217218
)
218219

219-
it.effect("selects Azure WebSocket from capability unless the policy disables it", () =>
220+
it.effect("selects WebSocket only from explicit policy", () =>
220221
Effect.gen(function* () {
221222
const credentials = yield* Credential.Service
222223
yield* credentials.create({
@@ -267,11 +268,13 @@ describe("OpenAIPlugin", () => {
267268
Effect.provideService(SessionModelTransport.Service, transport),
268269
)
269270

270-
const prepared = yield* prepare()
271+
const prepared = yield* prepare(true)
272+
const defaulted = yield* prepare()
271273
const disabled = yield* prepare(false)
272274

273275
expect(prepared.options.webSocket).toBe(executor)
274276
expect(prepared.options.http).toBeUndefined()
277+
expect(defaulted.options.webSocket).toBeUndefined()
275278
expect(disabled.options.webSocket).toBeUndefined()
276279
}),
277280
)

‎packages/core/test/plugin/provider-xai.test.ts‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ describe("XAIPlugin", () => {
6969
}),
7070
)
7171

72-
it.effect("marks xAI deployments as Responses WebSocket capable", () =>
72+
it.effect("keeps xAI Responses WebSockets opt-in", () =>
7373
Effect.gen(function* () {
7474
const catalog = yield* Catalog.Service
7575
const providerID = Provider.ID.make("xai")
@@ -82,9 +82,9 @@ describe("XAIPlugin", () => {
8282

8383
yield* addPlugin()
8484

85-
expect((yield* catalog.model.get(providerID, Model.ID.make("grok-4.6")))?.capabilities.responsesWebsockets).toBe(
86-
true,
87-
)
85+
const model = yield* catalog.model.get(providerID, Model.ID.make("grok-4.6"))
86+
expect(model?.capabilities.responsesWebsockets).toBe(true)
87+
expect(model?.websocket).toBeUndefined()
8888
}),
8989
)
9090
})

‎packages/schema/src/config/provider.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ class Model extends Schema.Class<Model>("Config.Model")({
6464
export class Info extends Schema.Class<Info>("Config.Provider")({
6565
compaction: Provider.Compaction.pipe(optional),
6666
websocket: Schema.Boolean.pipe(optional).annotate({
67-
description: "Use the provider's WebSocket transport when the route supports it. Defaults to true.",
67+
description: "Use the provider's WebSocket transport when the route supports it. Defaults to the built-in policy.",
6868
}),
6969
canonical: Provider.ID.pipe(optional),
7070
name: Schema.String.pipe(optional),

‎packages/schema/src/model.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ export const Info = Schema.Struct({
107107
compatibility: Compatibility.pipe(optional),
108108
package: Provider.Package.pipe(optional),
109109
compaction: Provider.Compaction.pipe(optional),
110-
/** Session WebSocket policy; omitted inherits the provider policy, which defaults to enabled. */
110+
/** Session WebSocket policy; omitted inherits the provider policy, then defaults to disabled. */
111111
websocket: Schema.Boolean.pipe(optional),
112112
...Provider.Overlays,
113113
capabilities: Capabilities,

0 commit comments

Comments
 (0)