Skip to content

Commit cbfe08e

Browse files
committed
feat(desktop): config:v1:update-provider accepts reasoningLevel
Plumb the tri-state semantics (undefined=untouched, null=clear the override, string=set) through the update IPC + surface the current value on ProviderRow so the Settings UI can render it. - UpdateProviderInput.reasoningLevel (ReasoningLevel | null | undefined) - parseUpdateProviderPayload validates via ReasoningLevelSchema - runUpdateProvider handles set/clear/leave distinctly - ProviderRow (main + preload mirror) exposes reasoningLevel - toProviderRows populates it from the ProviderEntry
1 parent 709e7de commit cbfe08e

3 files changed

Lines changed: 25 additions & 0 deletions

File tree

apps/desktop/src/main/onboarding-ipc.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import {
55
type Config,
66
type OnboardingState,
77
type ProviderEntry,
8+
type ReasoningLevel,
9+
ReasoningLevelSchema,
810
StoredDesignSystem,
911
type StoredDesignSystem as StoredDesignSystemValue,
1012
type SupportedOnboardingProvider,
@@ -583,6 +585,7 @@ interface UpdateProviderInput {
583585
httpHeaders?: Record<string, string>;
584586
queryParams?: Record<string, string>;
585587
wire?: WireApi;
588+
reasoningLevel?: ReasoningLevel | null;
586589
}
587590

588591
function parseUpdateProviderPayload(raw: unknown): UpdateProviderInput {
@@ -624,6 +627,13 @@ function parseUpdateProviderPayload(raw: unknown): UpdateProviderInput {
624627
const parsedWire = WireApiSchema.safeParse(r['wire']);
625628
if (parsedWire.success) out.wire = parsedWire.data;
626629
}
630+
if (r['reasoningLevel'] === null) {
631+
// Explicit null clears the override so the core default kicks in.
632+
out.reasoningLevel = null;
633+
} else if (typeof r['reasoningLevel'] === 'string') {
634+
const parsed = ReasoningLevelSchema.safeParse(r['reasoningLevel']);
635+
if (parsed.success) out.reasoningLevel = parsed.data;
636+
}
627637
return out;
628638
}
629639

@@ -645,6 +655,15 @@ async function runUpdateProvider(input: UpdateProviderInput): Promise<Onboarding
645655
...(input.queryParams !== undefined ? { queryParams: input.queryParams } : {}),
646656
...(input.wire !== undefined ? { wire: input.wire } : {}),
647657
};
658+
// reasoningLevel has a tri-state semantic: undefined means "untouched",
659+
// null means "explicitly clear the override so core picks the default",
660+
// a string level means "set it". Handle separately from the spread above
661+
// because the `...undefined ? {} : {...}` pattern can't express "delete".
662+
if (input.reasoningLevel === null) {
663+
delete updated.reasoningLevel;
664+
} else if (input.reasoningLevel !== undefined) {
665+
updated.reasoningLevel = input.reasoningLevel;
666+
}
648667
const next = hydrateConfig({
649668
version: 3,
650669
activeProvider: cfg.activeProvider,

apps/desktop/src/main/provider-settings.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export interface ProviderRow {
2121
wire: WireApi;
2222
defaultModel: string;
2323
hasKey: boolean;
24+
reasoningLevel?: ReasoningLevel;
2425
error?: 'decryption_failed' | string;
2526
}
2627

@@ -130,6 +131,9 @@ export function toProviderRows(
130131
// codex-* providers are treated as no-auth / IP-gated by default —
131132
// absent secret is a legitimate state, not a "missing key" warning.
132133
hasKey: ref !== undefined || provider.startsWith('codex-'),
134+
...(entry?.reasoningLevel !== undefined
135+
? { reasoningLevel: entry.reasoningLevel }
136+
: {}),
133137
...(rowError !== undefined ? { error: rowError } : {}),
134138
});
135139
}

apps/desktop/src/preload/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import type {
1414
ModelRef,
1515
OnboardingState,
1616
ProviderEntry,
17+
ReasoningLevel,
1718
SelectedElement,
1819
SnapshotCreateInput,
1920
SupportedOnboardingProvider,
@@ -56,6 +57,7 @@ export interface ProviderRow {
5657
wire: WireApi;
5758
defaultModel: string;
5859
hasKey: boolean;
60+
reasoningLevel?: ReasoningLevel;
5961
error?: 'decryption_failed' | string;
6062
}
6163

0 commit comments

Comments
 (0)