diff --git a/bun.lock b/bun.lock index 9717d1b..8e662f9 100644 --- a/bun.lock +++ b/bun.lock @@ -190,7 +190,7 @@ "@humanlayer/fold-core": "workspace:*", }, "devDependencies": { - "@effect/ai-openai": "catalog:", + "@effect/ai-openai-compat": "catalog:", "@effect/platform-node": "catalog:", "@effect/vitest": "catalog:", "@humanlayer/fold-vitest-config": "workspace:*", @@ -199,7 +199,7 @@ "vitest": "catalog:", }, "peerDependencies": { - "@effect/ai-openai": "catalog:", + "@effect/ai-openai-compat": "catalog:", "@effect/platform-node": "catalog:", "effect": "catalog:", }, diff --git a/packages/fold-agent/src/Config/ConfigSchema.ts b/packages/fold-agent/src/Config/ConfigSchema.ts index e80d9de..a53357a 100644 --- a/packages/fold-agent/src/Config/ConfigSchema.ts +++ b/packages/fold-agent/src/Config/ConfigSchema.ts @@ -54,7 +54,7 @@ export const RoleBinding = Schema.Struct({ model: Schema.optionalKey( Schema.String.annotate({ description: - 'Provider model id; defaults: codex/opencode → gpt-5.6-sol, xai → grok-4.5, anthropic → claude-opus-4-8; required for openai-compat', + 'Provider model id; defaults: codex/opencode → gpt-5.6-sol, xai → grok-4.6, anthropic → claude-opus-4-8; required for openai-compat', }), ), /** Reasoning level for this role's requests. Defaults to `off` when omitted. */ diff --git a/packages/fold-agent/src/Config/ConfigSchemaJson.ts b/packages/fold-agent/src/Config/ConfigSchemaJson.ts index 62956b2..7b54dab 100644 --- a/packages/fold-agent/src/Config/ConfigSchemaJson.ts +++ b/packages/fold-agent/src/Config/ConfigSchemaJson.ts @@ -68,7 +68,7 @@ export const starterConfigJsonc = (): string => // Model roles bound to a provider (+ optional model). "smart" and "fast" are required; // "orchestrator" is optional and falls back to "smart". Omitting "model" uses the provider - // defaults: codex/opencode → gpt-5.6-sol, xai → grok-4.5, anthropic → claude-opus-4-8. + // defaults: codex/opencode → gpt-5.6-sol, xai → grok-4.6, anthropic → claude-opus-4-8. "roles": { // Default primary model for new sessions. "smart": { "provider": "codex", "model": "gpt-5.6-sol", "reasoning": "medium" }, diff --git a/packages/fold-agent/src/Config/FoldInfo.ts b/packages/fold-agent/src/Config/FoldInfo.ts index 12bdb95..503dc7a 100644 --- a/packages/fold-agent/src/Config/FoldInfo.ts +++ b/packages/fold-agent/src/Config/FoldInfo.ts @@ -74,7 +74,7 @@ is optional and falls back to \`smart\`. | \`orchestrator\` | the RLM mode's primary agent | Each binding is \`{ "provider": , "model"?: , "reasoning"?: }\`. Omitting \`model\` -uses the provider kind's default: codex/opencode → \`gpt-5.6-sol\`, xai → \`grok-4.5\`, and +uses the provider kind's default: codex/opencode → \`gpt-5.6-sol\`, xai → \`grok-4.6\`, and anthropic → \`claude-opus-4-8\` (openai-compat requires an explicit model). \`reasoning\` is one of \`off · minimal · low · medium · high · xhigh · max\` and is validated against the model catalog - a level the model does not support diff --git a/packages/fold-agent/test/Config/AgentModels.vi.test.ts b/packages/fold-agent/test/Config/AgentModels.vi.test.ts index a5724b2..40975b6 100644 --- a/packages/fold-agent/test/Config/AgentModels.vi.test.ts +++ b/packages/fold-agent/test/Config/AgentModels.vi.test.ts @@ -68,7 +68,7 @@ it.effect('resolves OpenCode and xAI OAuth providers with their defaults and no const openCode = yield* models.resolve('smart') const xai = yield* models.resolve('fast') expect(openCode.activeModel).toMatchObject({ providerId: 'zen', modelId: 'gpt-5.6-sol', role: 'smart' }) - expect(xai.activeModel).toMatchObject({ providerId: 'grok', modelId: 'grok-4.5', role: 'fast' }) + expect(xai.activeModel).toMatchObject({ providerId: 'grok', modelId: 'grok-4.6', role: 'fast' }) }), ) diff --git a/packages/fold-agent/test/Config/ModelSelections.vi.test.ts b/packages/fold-agent/test/Config/ModelSelections.vi.test.ts index ccf4033..ba71428 100644 --- a/packages/fold-agent/test/Config/ModelSelections.vi.test.ts +++ b/packages/fold-agent/test/Config/ModelSelections.vi.test.ts @@ -213,12 +213,12 @@ it.effect('provides OAuth defaults when the external catalog is unavailable', () }) expect(description.providers.find(({ name }) => name === 'grok')).toMatchObject({ credentialPresent: null, - models: ['grok-4.5'], + models: ['grok-4.6'], }) }), ) -it.effect('only exposes Grok 4.5 for xAI providers', () => +it.effect('only exposes Grok 4.6 for xAI providers', () => Effect.gen(function* () { const config = yield* parseFoldConfig(`{ "providers": { "grok": { "kind": "xai", "configuredModels": ["grok-3", "grok-4"] } }, @@ -228,6 +228,6 @@ it.effect('only exposes Grok 4.5 for xAI providers', () => } }`) const description = describeModelConfiguration(config, [catalogEntry('xai', 'grok-2')]) - expect(description.providers[0]?.models).toEqual(['grok-4.5']) + expect(description.providers[0]?.models).toEqual(['grok-4.6']) }), ) diff --git a/packages/fold-cli/src/tui/ProviderConfigState.ts b/packages/fold-cli/src/tui/ProviderConfigState.ts index 67bcfbc..f6d0101 100644 --- a/packages/fold-cli/src/tui/ProviderConfigState.ts +++ b/packages/fold-cli/src/tui/ProviderConfigState.ts @@ -32,7 +32,7 @@ export const emptyProviderForm = (): ProviderForm => ({ const defaults = (kind: ProviderForm['kind']): Pick => { if (kind === 'codex') return { baseUrl: 'https://chatgpt.com/backend-api/codex', model: 'gpt-5.6-sol' } if (kind === 'opencode') return { baseUrl: 'https://opencode.ai/zen/v1', model: 'gpt-5.6-sol' } - if (kind === 'xai') return { baseUrl: 'https://api.x.ai/v1', model: 'grok-4.5' } + if (kind === 'xai') return { baseUrl: 'https://api.x.ai/v1', model: 'grok-4.6' } if (kind === 'anthropic') return { baseUrl: 'https://api.anthropic.com', model: '' } return { baseUrl: 'https://api.openai.com/v1', model: '' } } diff --git a/packages/fold-cli/test/tui/ProviderConfigState.vi.test.ts b/packages/fold-cli/test/tui/ProviderConfigState.vi.test.ts index 7d4041a..4d7b3b3 100644 --- a/packages/fold-cli/test/tui/ProviderConfigState.vi.test.ts +++ b/packages/fold-cli/test/tui/ProviderConfigState.vi.test.ts @@ -59,7 +59,7 @@ describe('provider config form state', () => { const rows = providerManagementRows({ profiles: [], providers: [] }) expect(rows[3]).toMatchObject({ type: 'create', - form: { name: 'xai', kind: 'xai', baseUrl: 'https://api.x.ai/v1', model: 'grok-4.5' }, + form: { name: 'xai', kind: 'xai', baseUrl: 'https://api.x.ai/v1', model: 'grok-4.6' }, }) expect(rows[4]).toMatchObject({ type: 'create', diff --git a/packages/fold-xai/package.json b/packages/fold-xai/package.json index aef4036..a2f31a1 100644 --- a/packages/fold-xai/package.json +++ b/packages/fold-xai/package.json @@ -18,12 +18,12 @@ "@humanlayer/fold-core": "workspace:*" }, "peerDependencies": { - "@effect/ai-openai": "catalog:", + "@effect/ai-openai-compat": "catalog:", "@effect/platform-node": "catalog:", "effect": "catalog:" }, "devDependencies": { - "@effect/ai-openai": "catalog:", + "@effect/ai-openai-compat": "catalog:", "@effect/platform-node": "catalog:", "@effect/vitest": "catalog:", "@humanlayer/fold-vitest-config": "workspace:*", diff --git a/packages/fold-xai/src/XaiModel.ts b/packages/fold-xai/src/XaiModel.ts index 0ba2a99..3c80c65 100644 --- a/packages/fold-xai/src/XaiModel.ts +++ b/packages/fold-xai/src/XaiModel.ts @@ -1,5 +1,5 @@ /** FoldModel factory for xAI's OpenAI-compatible inference API authenticated with OAuth. */ -import { OpenAiClient, OpenAiLanguageModel } from '@effect/ai-openai' +import { OpenAiClient, OpenAiLanguageModel } from '@effect/ai-openai-compat' import { customModel, resolveOpenAiReasoning } from '@humanlayer/fold-core' import type { FoldModel, ReasoningLevel } from '@humanlayer/fold-core' import { Context, Effect, Layer } from 'effect' @@ -11,7 +11,7 @@ import type { XaiAuthStore } from './AuthStore' import { makeXaiAuth, withXaiAuth } from './XaiAuth' export const XAI_API_URL = 'https://api.x.ai/v1' -export const DEFAULT_XAI_MODEL_ID = 'grok-4.5' +export const DEFAULT_XAI_MODEL_ID = 'grok-4.6' export type XaiModelOptions = { readonly model?: string