Skip to content

Commit 4aa53da

Browse files
authored
Enhance providers configuration (#248)
* Create shared constants for AI provider configurations * Add UI components and backend logic to manage multiple API providers, including built-in and custom ones, saving their configuration * Add migration to create providers from existing Gemini and OpenRouter API keys * Remove API key input fields and related state from the tools configuration component * Remove direct API key handling from the tools configuration UI and backend message handlers * Standardize built-in provider API key fields using the Field component, remove uppercase text transform from labels, and refine provider styles * Migrate API provider configuration from webview UI to native VS Code Quick Pick UI * Add functionality to reorder API providers in the configuration quick pick using up and down buttons * Refactor custom API provider editing to allow field-by-field modification via a quick pick menu * Change the custom API provider creation flow to immediately open the edit view for configuration * Improve API provider configuration quick pick navigation with icons and back options * Refine API provider configuration UI by reordering custom provider fields and clarifying built-in API key prompts * Refactor API tool configuration UI to trigger backend setup commands and update descriptions * Implement interactive setup and update of API tool configurations for refactoring and commit messages * Introduce default temperatures for API tools and reset temperature when changing provider or model * Ensure default temperature is returned when input is empty or cancelled * Implement a generic model fetcher service to allow model selection during API tool setup for any configured provider, replacing specific OpenRouter model handling and adding a new provider * Implement the setup handler for configuring code completions with multiple API providers and models * Refactor the code completions configuration flow to use a single interactive quick pick with add, edit, and delete options * Streamline adding code completion configurations by defaulting temperature instead of prompting the user * Add move up and down buttons to reorder code completion configurations * Implement a back option when editing code completion configurations * Implement recursive editing and duplicate checks for code completions configurations * Implement renaming for custom API providers and update associated tool configurations * Update quick pick items for contexts and providers to use plain names and add explicit edit buttons * Add editing functionality for code completions configurations and enhance API provider setup UI * Ensure configuration editing correctly matches option labels and standardize provider descriptions * Migrate API tool configurations to use built-in Gemini * Remove API tool configuration settings * Migrate legacy API tool configurations for code completions, refactoring, and commit messages to use built-in providers * Remove edit icons from the configuration update options in the quick pick menu * Remove the dedicated API tool settings manager and types, integrating tool configuration handling into the ApiProvidersManager * Use `ApiProvidersManager` instead of `ApiToolsSettingsManager` for managing API provider and tool configurations across commands * Refactor tool configuration buttons and standardize 'Add another' labels in API provider and tool quick picks * Refine the API provider configuration Quick Pick by displaying masked API keys and base URLs, improving empty state handling, and adjusting navigation * Move OpenRouter model picking logic from the webview UI to the VS Code extension backend * Hide move buttons in quick picks when only one item is present
1 parent 169a993 commit 4aa53da

42 files changed

Lines changed: 2138 additions & 1205 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ The Connector extension is available in [Chrome Web Store](https://chromewebstor
9090

9191
> <small>**Legal Disclaimer:** After chat initialization, the extension does not read the incoming message. The injected _Apply response_ button is not a means of automatic output extraction, it's an alias for the original _copy to clipboard_ button.</small>
9292
93+
### Practice single-turns
94+
95+
Chat conversations are only a construct of product interfaces, they hurt the quality of responses from the model and once your context is "poisoned" it will not recover. Whenever you're not satisfied with a reponse, **the best practice is to alawys refine your initial instructions and re-initialize**.
96+
9397
## 🧰 Tools
9498

9599
Support your day-to-day work with all must-have AI features.
@@ -191,4 +195,5 @@ Participate in [discussions](https://github.com/robertpiosik/CodeWebChat/discuss
191195

192196
Copyright © 2025-present [Robert Piosik](https://x.com/robertpiosik)
193197
</br>📨 `robertpiosik@gmail.com`
198+
</br>Telegram: `@robertpiosik`
194199
</br>📃 [GPL-3.0 license](https://github.com/robertpiosik/CodeWebChat/blob/master/LICENSE)

packages/browser/src/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"author": "Robert Piosik",
44
"name": "Code Web Chat Connector",
55
"short_name": "code-web-chat-connector",
6-
"description": "Initialize any web chat with your code.",
6+
"description": "Initialize any web chat with your code. Add websites to context.",
77
"version": "0.1.70",
88
"homepage_url": "https://github.com/robertpiosik/CodeWebChat",
99
"icons": {

packages/shared/src/constants/chatbots.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
type Chatbot = {
2-
[key: string]: {
1+
type Chatbots = {
2+
[name: string]: {
33
url: string
44
supports_custom_temperature: boolean
55
supports_custom_top_p: boolean
@@ -190,4 +190,4 @@ export const CHATBOTS = {
190190
hunyuan: 'Hunyuan'
191191
}
192192
}
193-
} satisfies Chatbot
193+
} satisfies Chatbots
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
type Providers = {
2+
[name: string]: {
3+
base_url: string
4+
}
5+
}
6+
7+
export const PROVIDERS = {
8+
Gemini: {
9+
base_url: 'https://generativelanguage.googleapis.com/v1beta/openai'
10+
},
11+
OpenRouter: {
12+
base_url: 'https://openrouter.ai/api/v1'
13+
},
14+
Chutes: {
15+
base_url: 'https://llm.chutes.ai/v1'
16+
}
17+
} satisfies Providers

packages/shared/src/types/tool-settings.ts

Lines changed: 0 additions & 7 deletions
This file was deleted.

packages/ui/src/components/editor/EditPresetForm/EditPresetForm.tsx

Lines changed: 32 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,7 @@ import { Slider } from '../Slider'
1111
type Props = {
1212
preset: Preset
1313
on_update: (updated_preset: Preset) => void
14-
request_open_router_models: () => void
15-
open_router_models: {
16-
[model_id: string]: {
17-
name: string
18-
description: string
19-
}
20-
}
21-
get_newly_picked_open_router_model: () => Promise<string | undefined>
14+
pick_open_router_model: () => void
2215
}
2316

2417
export const EditPresetForm: React.FC<Props> = (props) => {
@@ -38,12 +31,6 @@ export const EditPresetForm: React.FC<Props> = (props) => {
3831
props.preset.prompt_suffix
3932
)
4033
const [options, set_options] = useState<string[]>(props.preset.options || [])
41-
const [open_router_models, set_open_router_models] = useState<{
42-
[model_id: string]: {
43-
name: string
44-
description: string
45-
}
46-
}>({})
4734

4835
const supports_temperature = CHATBOTS[chatbot].supports_custom_temperature
4936
const supports_top_p = CHATBOTS[chatbot].supports_custom_top_p
@@ -107,15 +94,15 @@ export const EditPresetForm: React.FC<Props> = (props) => {
10794
}
10895

10996
useEffect(() => {
110-
if (chatbot == 'OpenRouter') {
111-
// Use stale-while-revalidate flow
112-
props.request_open_router_models()
97+
const handle_message = (event: MessageEvent) => {
98+
const message = event.data
99+
if (message.command == 'NEWLY_PICKED_OPEN_ROUTER_MODEL') {
100+
set_model(message.model_id)
101+
}
113102
}
114-
}, [chatbot])
115-
116-
useEffect(() => {
117-
set_open_router_models(props.open_router_models)
118-
}, [props.open_router_models])
103+
window.addEventListener('message', handle_message)
104+
return () => window.removeEventListener('message', handle_message)
105+
}, [])
119106

120107
return (
121108
<div className={styles.form}>
@@ -149,45 +136,31 @@ export const EditPresetForm: React.FC<Props> = (props) => {
149136
</Field>
150137
)}
151138

152-
{chatbot == 'OpenRouter' &&
153-
(Object.keys(open_router_models).length > 0 ? (
154-
<Field label="Model" html_for="open-router-model">
155-
<div
156-
onClick={async () => {
157-
const new_pick =
158-
await props.get_newly_picked_open_router_model()
159-
set_model(new_pick)
160-
}}
161-
>
162-
<div style={{ cursor: 'pointer' }}>
163-
<div style={{ pointerEvents: 'none' }}>
164-
<select
165-
id="open-router-model"
166-
value={model}
167-
onChange={(e) => set_model(e.target.value)}
168-
onClick={(e) => {
169-
e.preventDefault()
170-
}}
171-
>
172-
{Object.entries(open_router_models).map(
173-
([value, model]) => (
174-
<option key={value} value={value}>
175-
{model.name}
176-
</option>
177-
)
178-
)}
179-
</select>
180-
</div>
139+
{chatbot == 'OpenRouter' && (
140+
<Field label="Model" html_for="open-router-model">
141+
<div
142+
onClick={(e) => {
143+
e.stopPropagation()
144+
props.pick_open_router_model()
145+
}}
146+
>
147+
<div style={{ cursor: 'pointer' }}>
148+
<div style={{ pointerEvents: 'none' }}>
149+
<select
150+
id="open-router-model"
151+
value={model}
152+
>
153+
{model ? (
154+
<option value={model}>{model}</option>
155+
) : (
156+
<option value="">Select model</option>
157+
)}
158+
</select>
181159
</div>
182160
</div>
183-
</Field>
184-
) : (
185-
<Field label="Model">
186-
<select value="fetching" disabled>
187-
<option value="fetching">Fetching models...</option>
188-
</select>
189-
</Field>
190-
))}
161+
</div>
162+
</Field>
163+
)}
191164

192165
{supports_user_provided_model && (
193166
<Field label="Model" html_for="custom-model">

packages/ui/src/components/editor/Field/Field.module.scss

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
&__label {
77
font-size: 12px;
88
font-weight: 600;
9-
text-transform: uppercase;
109
color: var(--vscode-editor-foreground);
1110
align-self: flex-start;
1211
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
.input {
2+
background-color: var(--vscode-input-background);
3+
border: 1px solid var(--vscode-input-border);
4+
color: var(--vscode-input-foreground);
5+
padding: var(--padding-4px) var(--padding-8px);
6+
border-radius: var(--border-radius);
7+
outline: none;
8+
width: 100%;
9+
10+
&:focus {
11+
border-color: var(--vscode-focusBorder);
12+
}
13+
14+
&::placeholder {
15+
color: var(--vscode-input-placeholderForeground);
16+
}
17+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import React from 'react'
2+
import styles from './Input.module.scss'
3+
4+
type Props = {
5+
type?: string
6+
value: string
7+
placeholder?: string
8+
onChange: (value: string) => void
9+
}
10+
11+
export const Input: React.FC<Props> = (props) => {
12+
return (
13+
<input
14+
type={props.type || 'text'}
15+
value={props.value}
16+
onChange={(e) => props.onChange(e.target.value)}
17+
className={styles.input}
18+
placeholder={props.placeholder}
19+
/>
20+
)
21+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './Input'

0 commit comments

Comments
 (0)