Skip to content

Commit 4f3581d

Browse files
committed
fix(bailian): enable temperature for all models, fail-fast on handler errors, and fix custom model detection (#420)
- Enable temperature support for all models including unmatched API-fetched ones by changing supportsTemperature from false to true in both the handler fallback (src/api/providers/bailian.ts) and the fetcher minimal metadata (src/api/providers/fetchers/bailian.ts). Temperature remains undefined by default and is only sent when the user explicitly enables it. - Fail fast in Task constructor when buildApiHandler throws, replacing the previous silent fallback that set this.api to undefined (src/core/task/Task.ts). Update the corresponding test to expect a throw rather than a degraded Task instance (src/core/task/__tests__/Task.spec.ts). - Add matchesPresetLocally() in Bailian settings UI to correctly recognize versioned/named-space API-returned model IDs as preset models, preventing stale custom model overrides from leaking into preset-model usage (webview-ui/src/components/settings/providers/Bailian.tsx).
1 parent a791c5f commit 4f3581d

5 files changed

Lines changed: 44 additions & 21 deletions

File tree

src/api/providers/bailian.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ export class BailianHandler extends BaseOpenAiCompatibleProvider<BailianModelId>
119119
contextWindow: 200_000,
120120
supportsImages: false,
121121
supportsPromptCache: false,
122-
supportsTemperature: false,
122+
supportsTemperature: true,
123123
} as ModelInfo)
124124

125125
const info: ModelInfo = { ...baseInfo, ...price, ...(custom || {}) }

src/api/providers/fetchers/bailian.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ export async function getBailianModels(baseUrl?: string, apiKey?: string): Promi
186186
contextWindow: 200_000,
187187
supportsImages: false,
188188
supportsPromptCache: false,
189-
supportsTemperature: false,
189+
supportsTemperature: true,
190190
}
191191
}
192192
}

src/core/task/Task.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -494,7 +494,7 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
494494
TelemetryService.instance.captureException(error instanceof Error ? error : new Error(String(error)), {
495495
extra: { provider: apiConfiguration.apiProvider, action: "Task.constructor" },
496496
})
497-
this.api = undefined as any
497+
throw error
498498
}
499499
this.autoApprovalHandler = new AutoApprovalHandler()
500500

src/core/task/__tests__/Task.spec.ts

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,7 @@ describe("Cline", () => {
396396
}).toThrow("Either historyItem or task/images must be provided")
397397
})
398398

399-
it("constructor catches buildApiHandler failure without crashing", () => {
399+
it("constructor rethrows buildApiHandler failure", () => {
400400
// Spy on buildApiHandler to throw simulating an invalid config
401401
const buildApiHandlerSpy = vi.spyOn(apiModule, "buildApiHandler").mockImplementationOnce(() => {
402402
throw new Error("Invalid Bailian config: missing workspaceId for frankfurt region")
@@ -405,22 +405,24 @@ describe("Cline", () => {
405405
// Spy on TelemetryService captureException
406406
const captureExceptionSpy = vi.spyOn(TelemetryService.instance, "captureException")
407407

408-
const task = new Task({
409-
provider: mockProvider,
410-
apiConfiguration: {
411-
apiProvider: "bailian",
412-
bailianRegion: "frankfurt",
413-
// Missing bailianWorkspaceId — should trigger buildApiHandler to throw
414-
} as ProviderSettings,
415-
task: "test task",
416-
startTask: false,
417-
})
408+
// Constructor should throw — no Task instance is created
409+
// with an undefined this.api (fail-fast, consistent with
410+
// updateApiConfiguration).
411+
expect(
412+
() =>
413+
new Task({
414+
provider: mockProvider,
415+
apiConfiguration: {
416+
apiProvider: "bailian",
417+
bailianRegion: "frankfurt",
418+
// Missing bailianWorkspaceId — should trigger buildApiHandler to throw
419+
} as ProviderSettings,
420+
task: "test task",
421+
startTask: false,
422+
}),
423+
).toThrow("Invalid Bailian config")
418424

419-
// Task instance should be created successfully (no crash)
420-
expect(task).toBeDefined()
421-
// api should be undefined since handler construction failed
422-
expect((task as any).api).toBeUndefined()
423-
// Telemetry should have captured the exception
425+
// Telemetry should have captured the exception (logged before rethrow)
424426
expect(captureExceptionSpy).toHaveBeenCalledTimes(1)
425427
const capturedError = captureExceptionSpy.mock.calls[0][0]
426428
expect(capturedError.message).toContain("Invalid Bailian config")

webview-ui/src/components/settings/providers/Bailian.tsx

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,27 @@ import { handleModelChangeSideEffects } from "../utils/providerModelConfig"
2222
import { ModelPicker } from "../ModelPicker"
2323
import { cn } from "@/lib/utils"
2424

25+
/**
26+
* Mirrors the handler-side findMatchingPreset() logic from
27+
* src/api/providers/fetchers/bailian.ts for use in the webview
28+
* context where we cannot import from the extension host.
29+
*
30+
* Returns true when the given model ID is an exact or substring
31+
* match (case-insensitive) of a static preset key, meaning the
32+
* handler will resolve it to a known preset rather than treating
33+
* it as unknown/custom.
34+
*/
35+
function matchesPresetLocally(modelId: string): boolean {
36+
const lower = modelId.trim().toLowerCase()
37+
if (!lower) return false
38+
const presetKeys = Object.keys(bailianModels)
39+
// Exact match (case-insensitive)
40+
if (presetKeys.some((k) => k.toLowerCase() === lower)) return true
41+
// Substring match — e.g. "qwen3.7-max" is a substring of
42+
// the API-returned "qwen3.7-max-2026-05-17"
43+
return presetKeys.some((k) => lower.includes(k.toLowerCase()))
44+
}
45+
2546
type BailianProps = {
2647
apiConfiguration: ProviderSettings
2748
setApiConfigurationField: <K extends keyof ProviderSettings>(
@@ -97,7 +118,7 @@ export const Bailian = ({
97118
}, [routerModels?.bailian])
98119

99120
const modelId = (apiConfiguration.apiModelId ?? "").trim()
100-
const isCustomModel = !!(modelId && !knownModelIds.has(modelId))
121+
const isCustomModel = !!(modelId && !knownModelIds.has(modelId) && !matchesPresetLocally(modelId))
101122

102123
// Stable sort callback so ModelPicker's useMemo dependency doesn't
103124
// invalidate on every render.
@@ -197,7 +218,7 @@ export const Bailian = ({
197218
// Clear custom model overrides when switching to a preset
198219
// model so stale bailianCustomModelInfo doesn't leak into
199220
// the UI display or API requests.
200-
if (knownModelIds.has(newModelId)) {
221+
if (knownModelIds.has(newModelId) || matchesPresetLocally(newModelId)) {
201222
setApiConfigurationField("bailianCustomModelInfo", null)
202223
}
203224
}}

0 commit comments

Comments
 (0)