From ba4e7805028fe2490aaac5dcfc58a648854afce0 Mon Sep 17 00:00:00 2001 From: Ame Date: Wed, 17 Jun 2026 21:06:08 +0800 Subject: [PATCH 1/3] chore(ai-providers): refresh preset model catalog to current flagships Trading workbench wants the most capable model, not fast/cheap tiers. Bump + prune each preset's model list: - GLM: glm-5.1 -> glm-5.2 (sole flagship); drop 4.7-flash, 4.5-air - Kimi: default kimi-k2.7-code; keep k2.6; drop k2.5 - Claude: drop superseded Opus 4.7; drop Haiku 4.5 (cheap tier) - Codex: drop gpt-5.4-mini (cheap tier); gpt-5.5 stays current - DeepSeek: drop v4-flash (cheap tier) - MiniMax: unchanged (M3 already the current flagship) Also refresh the stale Workspace AI-config modal placeholders (claude-sonnet-4-6 -> claude-opus-4-8, gpt-4o -> gpt-5.5). New CN model ids (glm-5.2, kimi-k2.7-code) verified against provider docs; confirm via the credential Test path before relying on them. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/ai-providers/preset-catalog.ts | 20 ++++++------------- .../workspace/WorkspaceAIConfigModal.tsx | 2 +- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/src/ai-providers/preset-catalog.ts b/src/ai-providers/preset-catalog.ts index 3d365752..829f46ed 100644 --- a/src/ai-providers/preset-catalog.ts +++ b/src/ai-providers/preset-catalog.ts @@ -73,7 +73,6 @@ export const CLAUDE_OAUTH: PresetDef = { }), models: [ { id: 'claude-opus-4-8', label: 'Claude Opus 4.8' }, - { id: 'claude-opus-4-7', label: 'Claude Opus 4.7' }, { id: 'claude-sonnet-4-6', label: 'Claude Sonnet 4.6' }, ], } @@ -84,7 +83,7 @@ export const CLAUDE_API: PresetDef = { description: 'Pay per token via Anthropic API', category: 'official', defaultName: 'Claude (API Key)', - hint: 'Model is switchable here or from the profile list anytime. Opus is ~5× the cost of Sonnet; Haiku is cheapest for high-volume work.', + hint: 'Model is switchable here or from the profile list anytime. Opus is ~5× the cost of Sonnet.', zodSchema: z.object({ backend: z.literal('agent-sdk'), loginMethod: z.literal('api-key'), @@ -93,9 +92,7 @@ export const CLAUDE_API: PresetDef = { }), models: [ { id: 'claude-opus-4-8', label: 'Claude Opus 4.8' }, - { id: 'claude-opus-4-7', label: 'Claude Opus 4.7' }, { id: 'claude-sonnet-4-6', label: 'Claude Sonnet 4.6' }, - { id: 'claude-haiku-4-5', label: 'Claude Haiku 4.5' }, ], regions: [{ id: 'official', label: 'Official (api.anthropic.com)', wires: { anthropic: '' } }], writeOnlyFields: ['apiKey'], @@ -118,7 +115,6 @@ export const CODEX_OAUTH: PresetDef = { models: [ { id: 'gpt-5.5', label: 'GPT 5.5' }, { id: 'gpt-5.4', label: 'GPT 5.4' }, - { id: 'gpt-5.4-mini', label: 'GPT 5.4 Mini' }, ], } @@ -137,7 +133,6 @@ export const CODEX_API: PresetDef = { models: [ { id: 'gpt-5.5', label: 'GPT 5.5' }, { id: 'gpt-5.4', label: 'GPT 5.4' }, - { id: 'gpt-5.4-mini', label: 'GPT 5.4 Mini' }, ], // Same key + base; the shape is how you call it. Responses is OpenAI's // current API (what codex speaks); Chat Completions is the legacy shape @@ -215,12 +210,12 @@ export const GLM: PresetDef = { description: 'Zhipu GLM models via Claude Agent SDK (Anthropic-compatible)', category: 'third-party', defaultName: 'GLM', - hint: 'China console: bigmodel.cn — International console: z.ai. API keys are region-locked. GLM 5.1 is the current flagship, served on both regions.', + hint: 'China console: bigmodel.cn — International console: z.ai. API keys are region-locked. GLM 5.2 is the current flagship, served on both regions.', zodSchema: z.object({ backend: z.literal('agent-sdk'), loginMethod: z.literal('api-key'), baseUrl: z.string().default('https://open.bigmodel.cn/api/anthropic').describe('API endpoint'), - model: z.string().default('glm-5.1').describe('Model'), + model: z.string().default('glm-5.2').describe('Model'), apiKey: z.string().min(1).describe('GLM API key'), }), regions: [ @@ -232,9 +227,7 @@ export const GLM: PresetDef = { } }, ], models: [ - { id: 'glm-5.1', label: 'GLM 5.1' }, - { id: 'glm-4.7', label: 'GLM 4.7' }, - { id: 'glm-4.5-air', label: 'GLM 4.5 Air' }, + { id: 'glm-5.2', label: 'GLM 5.2' }, ], writeOnlyFields: ['apiKey'], } @@ -257,7 +250,7 @@ export const KIMI: PresetDef = { backend: z.literal('agent-sdk'), loginMethod: z.literal('api-key'), baseUrl: z.string().default('https://api.moonshot.cn/anthropic').describe('API endpoint'), - model: z.string().default('kimi-k2.6').describe('Model'), + model: z.string().default('kimi-k2.7-code').describe('Model'), apiKey: z.string().min(1).describe('Moonshot API key'), }), regions: [ @@ -269,8 +262,8 @@ export const KIMI: PresetDef = { } }, ], models: [ + { id: 'kimi-k2.7-code', label: 'Kimi K2.7 Code' }, { id: 'kimi-k2.6', label: 'Kimi K2.6' }, - { id: 'kimi-k2.5', label: 'Kimi K2.5' }, ], writeOnlyFields: ['apiKey'], } @@ -298,7 +291,6 @@ export const DEEPSEEK: PresetDef = { ], models: [ { id: 'deepseek-v4-pro', label: 'DeepSeek V4 Pro (flagship)' }, - { id: 'deepseek-v4-flash', label: 'DeepSeek V4 Flash (cheap/fast)' }, ], writeOnlyFields: ['apiKey'], } diff --git a/ui/src/components/workspace/WorkspaceAIConfigModal.tsx b/ui/src/components/workspace/WorkspaceAIConfigModal.tsx index 26dcc84a..f3a47dc4 100644 --- a/ui/src/components/workspace/WorkspaceAIConfigModal.tsx +++ b/ui/src/components/workspace/WorkspaceAIConfigModal.tsx @@ -463,7 +463,7 @@ export function WorkspaceAIConfigModal({ wsId, onClose }: Props) { value={form.model} suggestions={modelSuggestions} onChange={(v) => setForm({ ...form, model: v })} - placeholder={tab === 'claude' ? 'claude-sonnet-4-6' : tab === 'opencode' || tab === 'pi' ? 'deepseek-chat' : 'gpt-4o'} + placeholder={tab === 'claude' ? 'claude-opus-4-8' : tab === 'opencode' || tab === 'pi' ? 'deepseek-chat' : 'gpt-5.5'} /> {modelSuggestions.length > 0 && (

Suggestions from the matched provider — or type any model id.

From 59453d632ca620a1994e62cbf13c9f593e848cee Mon Sep 17 00:00:00 2001 From: Ame Date: Wed, 17 Jun 2026 21:10:39 +0800 Subject: [PATCH 2/3] chore: bump version to 0.51.0-beta.1 Co-Authored-By: Claude Opus 4.8 (1M context) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6d9c37de..4ac55e5b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "open-alice", - "version": "0.50.0-beta.1", + "version": "0.51.0-beta.1", "description": "File-based trading agent engine", "type": "module", "main": "dist/electron/main.js", From ffbf5f1091c5043ce0c47ca376d19133cb65f3a9 Mon Sep 17 00:00:00 2001 From: Ame Date: Wed, 17 Jun 2026 21:12:38 +0800 Subject: [PATCH 3/3] fix(workspaces): retry credential probe with thinking enabled for mandatory-reasoning models MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Kimi k2.7 (and similar) 400 with 'invalid thinking: only type=enabled is allowed for this model' when the probe omits thinking — they cannot run it disabled. The Anthropic probe now retries once with thinking enabled (budget_tokens 1024, max_tokens bumped to 2048) only when the error is thinking-related, leaving the common path (Claude/GLM/MiniMax/DeepSeek) untouched. Verified end-to-end against the live Kimi endpoint. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/workspaces/agent-probe.ts | 45 +++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/src/workspaces/agent-probe.ts b/src/workspaces/agent-probe.ts index a8b41ec5..057b24fc 100644 --- a/src/workspaces/agent-probe.ts +++ b/src/workspaces/agent-probe.ts @@ -41,6 +41,16 @@ export interface CodexProbeInput { wireApi: 'chat' | 'responses'; } +/** Does this error mean the model MANDATES extended thinking? Some reasoning + * models (e.g. Kimi k2.7) 400 with "invalid thinking: only type=enabled is + * allowed for this model" when the request omits thinking — they can't run it + * disabled. We detect that to retry with thinking on, rather than enabling it + * for every model (Claude/GLM/etc. don't need it and some reject the param). */ +function isThinkingRequiredError(err: unknown): boolean { + const e = err as { status?: number; message?: string } | undefined; + return e?.status === 400 && typeof e?.message === 'string' && /thinking/i.test(e.message); +} + export async function probeAnthropic(input: ClaudeProbeInput): Promise { // `authToken` makes the SDK send `Authorization: Bearer`; `apiKey` makes it // send `x-api-key`. Pick exactly one — sending both can trip gateways that @@ -48,19 +58,34 @@ export async function probeAnthropic(input: ClaudeProbeInput): Promise msg.content .filter((b): b is Anthropic.TextBlock => b.type === 'text') .map((b) => b.text) .join(''); - return { text }; + + try { + const msg = await client.messages.create({ + model: input.model, + // Enough room for a reasoning model to finish thinking AND emit a visible + // reply on a trivial prompt — a tiny budget gets spent entirely on reasoning, + // leaving empty content (the "(empty reply)" the user saw). One-off per Test. + max_tokens: 512, + messages: [{ role: 'user', content: 'Hi' }], + }); + return { text: extract(msg) }; + } catch (err) { + if (!isThinkingRequiredError(err)) throw err; + // Thinking-mandatory model: retry with it enabled. budget_tokens must be + // < max_tokens and Anthropic's floor is 1024, so bump max_tokens to match. + const msg = await client.messages.create({ + model: input.model, + max_tokens: 2048, + thinking: { type: 'enabled', budget_tokens: 1024 }, + messages: [{ role: 'user', content: 'Hi' }], + }); + return { text: extract(msg) }; + } } export async function probeOpenAI(input: CodexProbeInput): Promise {