Skip to content

Commit a96fe08

Browse files
daniel-lxshannesrudolph
authored andcommitted
refactor: flatten image generation settings structure (#7536)
1 parent 5236675 commit a96fe08

File tree

12 files changed

+120
-86
lines changed

12 files changed

+120
-86
lines changed

packages/types/src/provider-settings.ts

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -143,13 +143,6 @@ const openRouterSchema = baseProviderSettingsSchema.extend({
143143
openRouterBaseUrl: z.string().optional(),
144144
openRouterSpecificProvider: z.string().optional(),
145145
openRouterUseMiddleOutTransform: z.boolean().optional(),
146-
// Image generation settings (experimental)
147-
openRouterImageGenerationSettings: z
148-
.object({
149-
openRouterApiKey: z.string().optional(),
150-
selectedModel: z.string().optional(),
151-
})
152-
.optional(),
153146
})
154147

155148
const bedrockSchema = apiModelIdProviderModelSchema.extend({

src/core/tools/__tests__/generateImageTool.test.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,8 @@ describe("generateImageTool", () => {
4646
experiments: {
4747
[EXPERIMENT_IDS.IMAGE_GENERATION]: true,
4848
},
49-
apiConfiguration: {
50-
openRouterImageGenerationSettings: {
51-
openRouterApiKey: "test-api-key",
52-
selectedModel: "google/gemini-2.5-flash-image-preview",
53-
},
54-
},
49+
openRouterImageApiKey: "test-api-key",
50+
openRouterImageGenerationSelectedModel: "google/gemini-2.5-flash-image-preview",
5551
}),
5652
}),
5753
},

src/core/tools/generateImageTool.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -129,10 +129,8 @@ export async function generateImageTool(
129129
// Check if file is write-protected
130130
const isWriteProtected = cline.rooProtectedController?.isWriteProtected(relPath) || false
131131

132-
// Get OpenRouter API key from experimental settings ONLY (no fallback to profile)
133-
const apiConfiguration = state?.apiConfiguration
134-
const imageGenerationSettings = apiConfiguration?.openRouterImageGenerationSettings
135-
const openRouterApiKey = imageGenerationSettings?.openRouterApiKey
132+
// Get OpenRouter API key from global settings (experimental image generation)
133+
const openRouterApiKey = state?.openRouterImageApiKey
136134

137135
if (!openRouterApiKey) {
138136
await cline.say(
@@ -148,7 +146,7 @@ export async function generateImageTool(
148146
}
149147

150148
// Get selected model from settings or use default
151-
const selectedModel = imageGenerationSettings?.selectedModel || IMAGE_GENERATION_MODELS[0]
149+
const selectedModel = state?.openRouterImageGenerationSelectedModel || IMAGE_GENERATION_MODELS[0]
152150

153151
// Determine if the path is outside the workspace
154152
const fullPath = path.resolve(cline.cwd, removeClosingTag("path", relPath))

src/core/webview/ClineProvider.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1820,6 +1820,8 @@ export class ClineProvider
18201820
maxDiagnosticMessages,
18211821
includeTaskHistoryInEnhance,
18221822
remoteControlEnabled,
1823+
openRouterImageApiKey,
1824+
openRouterImageGenerationSelectedModel,
18231825
} = await this.getState()
18241826

18251827
const telemetryKey = process.env.POSTHOG_API_KEY
@@ -1952,6 +1954,8 @@ export class ClineProvider
19521954
includeTaskHistoryInEnhance: includeTaskHistoryInEnhance ?? true,
19531955
remoteControlEnabled,
19541956
filesChangedEnabled: this.getGlobalState("filesChangedEnabled") ?? true,
1957+
openRouterImageApiKey,
1958+
openRouterImageGenerationSelectedModel,
19551959
}
19561960
}
19571961

@@ -2151,6 +2155,9 @@ export class ClineProvider
21512155
return false
21522156
}
21532157
})(),
2158+
// Add image generation settings
2159+
openRouterImageApiKey: stateValues.openRouterImageApiKey,
2160+
openRouterImageGenerationSelectedModel: stateValues.openRouterImageGenerationSelectedModel,
21542161
}
21552162
}
21562163

src/core/webview/__tests__/ClineProvider.spec.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,8 @@ describe("ClineProvider", () => {
584584
openRouterImageApiKey: undefined,
585585
openRouterImageGenerationSelectedModel: undefined,
586586
filesChangedEnabled: true,
587+
openRouterImageApiKey: undefined,
588+
openRouterImageGenerationSelectedModel: undefined,
587589
}
588590

589591
const message: ExtensionMessage = {

src/core/webview/webviewMessageHandler.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1314,6 +1314,14 @@ export const webviewMessageHandler = async (
13141314
await updateGlobalState("language", message.text as Language)
13151315
await provider.postStateToWebview()
13161316
break
1317+
case "openRouterImageApiKey":
1318+
await provider.contextProxy.setValue("openRouterImageApiKey", message.text)
1319+
await provider.postStateToWebview()
1320+
break
1321+
case "openRouterImageGenerationSelectedModel":
1322+
await provider.contextProxy.setValue("openRouterImageGenerationSelectedModel", message.text)
1323+
await provider.postStateToWebview()
1324+
break
13171325
case "showRooIgnoredFiles":
13181326
await updateGlobalState("showRooIgnoredFiles", message.bool ?? false)
13191327
await provider.postStateToWebview()

src/shared/ExtensionMessage.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,7 @@ export type ExtensionState = Pick<
286286
| "includeDiagnosticMessages"
287287
| "maxDiagnosticMessages"
288288
| "remoteControlEnabled"
289+
| "openRouterImageGenerationSelectedModel"
289290
> & {
290291
version: string
291292
clineMessages: ClineMessage[]
@@ -340,6 +341,7 @@ export type ExtensionState = Pick<
340341
profileThresholds: Record<string, number>
341342
hasOpenedModeSelector: boolean
342343
filesChangedEnabled: boolean
344+
openRouterImageApiKey?: string
343345
}
344346

345347
export interface ClineSayTool {

src/shared/WebviewMessage.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,9 @@ export interface WebviewMessage {
218218
| "filesChangedEnabled"
219219
| "filesChangedRequest"
220220
| "filesChangedBaselineUpdate"
221+
| "imageGenerationSettings"
222+
| "openRouterImageApiKey"
223+
| "openRouterImageGenerationSelectedModel"
221224
text?: string
222225
editedMessageContent?: string
223226
tab?: "settings" | "history" | "mcp" | "modes" | "chat" | "marketplace" | "account"
@@ -254,6 +257,7 @@ export interface WebviewMessage {
254257
messageTs?: number
255258
historyPreviewCollapsed?: boolean
256259
filters?: { type?: string; search?: string; tags?: string[] }
260+
settings?: any
257261
url?: string // For openExternal
258262
mpItem?: MarketplaceItem
259263
mpInstallOptions?: InstallMarketplaceItemOptions

webview-ui/src/components/settings/ExperimentalSettings.tsx

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ type ExperimentalSettingsProps = HTMLAttributes<HTMLDivElement> & {
2323
setCachedStateField?: SetCachedStateField<"filesChangedEnabled">
2424
apiConfiguration?: any
2525
setApiConfigurationField?: any
26+
openRouterImageApiKey?: string
27+
openRouterImageGenerationSelectedModel?: string
28+
setOpenRouterImageApiKey?: (apiKey: string) => void
29+
setImageGenerationSelectedModel?: (model: string) => void
2630
}
2731

2832
export const ExperimentalSettings = ({
@@ -32,6 +36,10 @@ export const ExperimentalSettings = ({
3236
setCachedStateField,
3337
apiConfiguration,
3438
setApiConfigurationField,
39+
openRouterImageApiKey,
40+
openRouterImageGenerationSelectedModel,
41+
setOpenRouterImageApiKey,
42+
setImageGenerationSelectedModel,
3543
className,
3644
...props
3745
}: ExperimentalSettingsProps) => {
@@ -80,16 +88,22 @@ export const ExperimentalSettings = ({
8088
/>
8189
)
8290
}
83-
if (config[0] === "IMAGE_GENERATION" && apiConfiguration && setApiConfigurationField) {
91+
if (
92+
config[0] === "IMAGE_GENERATION" &&
93+
setOpenRouterImageApiKey &&
94+
setImageGenerationSelectedModel
95+
) {
8496
return (
8597
<ImageGenerationSettings
8698
key={config[0]}
8799
enabled={experiments[EXPERIMENT_IDS.IMAGE_GENERATION] ?? false}
88100
onChange={(enabled) =>
89101
setExperimentEnabled(EXPERIMENT_IDS.IMAGE_GENERATION, enabled)
90102
}
91-
apiConfiguration={apiConfiguration}
92-
setApiConfigurationField={setApiConfigurationField}
103+
openRouterImageApiKey={openRouterImageApiKey}
104+
openRouterImageGenerationSelectedModel={openRouterImageGenerationSelectedModel}
105+
setOpenRouterImageApiKey={setOpenRouterImageApiKey}
106+
setImageGenerationSelectedModel={setImageGenerationSelectedModel}
93107
/>
94108
)
95109
}

webview-ui/src/components/settings/ImageGenerationSettings.tsx

Lines changed: 20 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,14 @@
11
import React, { useState, useEffect } from "react"
22
import { VSCodeCheckbox, VSCodeTextField, VSCodeDropdown, VSCodeOption } from "@vscode/webview-ui-toolkit/react"
33
import { useAppTranslation } from "@/i18n/TranslationContext"
4-
import type { ProviderSettings } from "@roo-code/types"
54

65
interface ImageGenerationSettingsProps {
76
enabled: boolean
87
onChange: (enabled: boolean) => void
9-
apiConfiguration: ProviderSettings
10-
setApiConfigurationField: <K extends keyof ProviderSettings>(
11-
field: K,
12-
value: ProviderSettings[K],
13-
isUserAction?: boolean,
14-
) => void
8+
openRouterImageApiKey?: string
9+
openRouterImageGenerationSelectedModel?: string
10+
setOpenRouterImageApiKey: (apiKey: string) => void
11+
setImageGenerationSelectedModel: (model: string) => void
1512
}
1613

1714
// Hardcoded list of image generation models
@@ -24,43 +21,34 @@ const IMAGE_GENERATION_MODELS = [
2421
export const ImageGenerationSettings = ({
2522
enabled,
2623
onChange,
27-
apiConfiguration,
28-
setApiConfigurationField,
24+
openRouterImageApiKey,
25+
openRouterImageGenerationSelectedModel,
26+
setOpenRouterImageApiKey,
27+
setImageGenerationSelectedModel,
2928
}: ImageGenerationSettingsProps) => {
3029
const { t } = useAppTranslation()
3130

32-
// Get image generation settings from apiConfiguration
33-
const imageGenerationSettings = apiConfiguration?.openRouterImageGenerationSettings || {}
34-
const [openRouterApiKey, setOpenRouterApiKey] = useState(imageGenerationSettings.openRouterApiKey || "")
31+
const [apiKey, setApiKey] = useState(openRouterImageApiKey || "")
3532
const [selectedModel, setSelectedModel] = useState(
36-
imageGenerationSettings.selectedModel || IMAGE_GENERATION_MODELS[0].value,
33+
openRouterImageGenerationSelectedModel || IMAGE_GENERATION_MODELS[0].value,
3734
)
3835

39-
// Update local state when apiConfiguration changes (e.g., when switching profiles)
36+
// Update local state when props change (e.g., when switching profiles)
4037
useEffect(() => {
41-
setOpenRouterApiKey(imageGenerationSettings.openRouterApiKey || "")
42-
setSelectedModel(imageGenerationSettings.selectedModel || IMAGE_GENERATION_MODELS[0].value)
43-
}, [imageGenerationSettings.openRouterApiKey, imageGenerationSettings.selectedModel])
44-
45-
// Helper function to update settings
46-
const updateSettings = (newApiKey: string, newModel: string) => {
47-
const newSettings = {
48-
openRouterApiKey: newApiKey,
49-
selectedModel: newModel,
50-
}
51-
setApiConfigurationField("openRouterImageGenerationSettings", newSettings, true)
52-
}
38+
setApiKey(openRouterImageApiKey || "")
39+
setSelectedModel(openRouterImageGenerationSelectedModel || IMAGE_GENERATION_MODELS[0].value)
40+
}, [openRouterImageApiKey, openRouterImageGenerationSelectedModel])
5341

5442
// Handle API key changes
5543
const handleApiKeyChange = (value: string) => {
56-
setOpenRouterApiKey(value)
57-
updateSettings(value, selectedModel)
44+
setApiKey(value)
45+
setOpenRouterImageApiKey(value)
5846
}
5947

6048
// Handle model selection changes
6149
const handleModelChange = (value: string) => {
6250
setSelectedModel(value)
63-
updateSettings(openRouterApiKey, value)
51+
setImageGenerationSelectedModel(value)
6452
}
6553

6654
return (
@@ -84,7 +72,7 @@ export const ImageGenerationSettings = ({
8472
{t("settings:experimental.IMAGE_GENERATION.openRouterApiKeyLabel")}
8573
</label>
8674
<VSCodeTextField
87-
value={openRouterApiKey}
75+
value={apiKey}
8876
onInput={(e: any) => handleApiKeyChange(e.target.value)}
8977
placeholder={t("settings:experimental.IMAGE_GENERATION.openRouterApiKeyPlaceholder")}
9078
className="w-full"
@@ -123,13 +111,13 @@ export const ImageGenerationSettings = ({
123111
</div>
124112

125113
{/* Status Message */}
126-
{enabled && !openRouterApiKey && (
114+
{enabled && !apiKey && (
127115
<div className="p-2 bg-vscode-editorWarning-background text-vscode-editorWarning-foreground rounded text-sm">
128116
{t("settings:experimental.IMAGE_GENERATION.warningMissingKey")}
129117
</div>
130118
)}
131119

132-
{enabled && openRouterApiKey && (
120+
{enabled && apiKey && (
133121
<div className="p-2 bg-vscode-editorInfo-background text-vscode-editorInfo-foreground rounded text-sm">
134122
{t("settings:experimental.IMAGE_GENERATION.successConfigured")}
135123
</div>

0 commit comments

Comments
 (0)