Skip to content

Commit fae0f1a

Browse files
committed
Implement custom URL path configuration for chatbot presets, enabling users to specify custom endpoints for supported services like Perplexity and ChatGPT
1 parent a08ee0f commit fae0f1a

8 files changed

Lines changed: 69 additions & 8 deletions

File tree

‎packages/browser/src/manifest.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
"https://chat.mistral.ai/chat",
4141
"http://openwebui/",
4242
"https://openrouter.ai/chat*",
43-
"https://www.perplexity.ai/",
43+
"https://www.perplexity.ai/*",
4444
"https://chat.qwen.ai/",
4545
"https://chat.together.ai/",
4646
"https://yuanbao.tencent.com/chat*",

‎packages/shared/src/constants/chatbots.ts‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ type Chatbots = {
88
supports_user_provided_port: boolean
99
supports_reasoning_effort: boolean
1010
supports_thinking_budget: boolean
11+
supports_custom_url_path: boolean
1112
default_system_instructions: string
1213
default_top_p: number
1314
supported_options: {
@@ -32,6 +33,7 @@ export const CHATBOTS = {
3233
supports_user_provided_port: false,
3334
supports_reasoning_effort: false,
3435
supports_thinking_budget: true,
36+
supports_custom_url_path: false,
3537
default_system_instructions: "You're a helpful coding assistant.",
3638
default_top_p: 0.95,
3739
supported_options: {
@@ -69,6 +71,7 @@ export const CHATBOTS = {
6971
supports_user_provided_port: false,
7072
supports_reasoning_effort: false,
7173
supports_thinking_budget: false,
74+
supports_custom_url_path: true,
7275
default_system_instructions: '',
7376
supported_options: {
7477
temporary: 'Temporary',
@@ -86,6 +89,7 @@ export const CHATBOTS = {
8689
supports_user_provided_port: false,
8790
supports_reasoning_effort: false,
8891
supports_thinking_budget: false,
92+
supports_custom_url_path: false,
8993
default_system_instructions: '',
9094
supported_options: {
9195
'incognito-chat': 'Incognito chat'
@@ -106,6 +110,7 @@ export const CHATBOTS = {
106110
supports_user_provided_port: false,
107111
supports_reasoning_effort: false,
108112
supports_thinking_budget: false,
113+
supports_custom_url_path: false,
109114
default_system_instructions: '',
110115
supported_options: {},
111116
default_top_p: 0,
@@ -126,6 +131,7 @@ export const CHATBOTS = {
126131
supports_user_provided_port: false,
127132
supports_reasoning_effort: false,
128133
supports_thinking_budget: false,
134+
supports_custom_url_path: false,
129135
default_system_instructions: '',
130136
supported_options: { 'deep-think': 'DeepThink', search: 'Search' },
131137
default_top_p: 0,
@@ -140,6 +146,7 @@ export const CHATBOTS = {
140146
supports_user_provided_port: false,
141147
supports_reasoning_effort: false,
142148
supports_thinking_budget: false,
149+
supports_custom_url_path: false,
143150
default_system_instructions: '',
144151
supported_options: { 'deep-thinking': 'Deep Thinking' },
145152
default_top_p: 0,
@@ -154,6 +161,7 @@ export const CHATBOTS = {
154161
supports_user_provided_port: false,
155162
supports_reasoning_effort: false,
156163
supports_thinking_budget: false,
164+
supports_custom_url_path: false,
157165
supported_options: { 'temporary-chat': 'Temporary chat' },
158166
default_system_instructions: '',
159167
default_top_p: 0,
@@ -171,6 +179,7 @@ export const CHATBOTS = {
171179
supports_user_provided_port: false,
172180
supports_reasoning_effort: false,
173181
supports_thinking_budget: false,
182+
supports_custom_url_path: false,
174183
default_system_instructions: '',
175184
supported_options: {},
176185
default_top_p: 0,
@@ -200,6 +209,7 @@ export const CHATBOTS = {
200209
supports_user_provided_port: false,
201210
supports_reasoning_effort: false,
202211
supports_thinking_budget: false,
212+
supports_custom_url_path: false,
203213
default_system_instructions: '',
204214
supported_options: {},
205215
default_top_p: 0,
@@ -214,6 +224,7 @@ export const CHATBOTS = {
214224
supports_user_provided_port: false,
215225
supports_reasoning_effort: false,
216226
supports_thinking_budget: false,
227+
supports_custom_url_path: false,
217228
default_system_instructions: '',
218229
supported_options: { private: 'Private' },
219230
default_top_p: 0,
@@ -234,6 +245,7 @@ export const CHATBOTS = {
234245
supports_user_provided_port: false,
235246
supports_reasoning_effort: false,
236247
supports_thinking_budget: false,
248+
supports_custom_url_path: false,
237249
default_system_instructions: '',
238250
supported_options: {},
239251
default_top_p: 0,
@@ -248,6 +260,7 @@ export const CHATBOTS = {
248260
supports_user_provided_port: false,
249261
supports_reasoning_effort: false,
250262
supports_thinking_budget: false,
263+
supports_custom_url_path: false,
251264
default_system_instructions: '',
252265
supported_options: {},
253266
default_top_p: 0,
@@ -262,6 +275,7 @@ export const CHATBOTS = {
262275
supports_user_provided_port: false,
263276
supports_reasoning_effort: false,
264277
supports_thinking_budget: false,
278+
supports_custom_url_path: false,
265279
default_system_instructions: '',
266280
supported_options: {
267281
incognito: 'Incognito mode',
@@ -293,6 +307,7 @@ export const CHATBOTS = {
293307
supports_user_provided_port: true,
294308
supports_reasoning_effort: false,
295309
supports_thinking_budget: false,
310+
supports_custom_url_path: false,
296311
default_system_instructions: "You're a helpful coding assistant.",
297312
supported_options: {},
298313
default_top_p: 0.9,
@@ -307,6 +322,7 @@ export const CHATBOTS = {
307322
supports_user_provided_port: false,
308323
supports_reasoning_effort: true,
309324
supports_thinking_budget: false,
325+
supports_custom_url_path: false,
310326
default_system_instructions: "You're a helpful coding assistant.",
311327
supported_options: {
312328
'disable-reasoning': 'Disable reasoning (for hybrid models)'
@@ -323,6 +339,7 @@ export const CHATBOTS = {
323339
supports_user_provided_port: false,
324340
supports_reasoning_effort: false,
325341
supports_thinking_budget: false,
342+
supports_custom_url_path: true,
326343
default_system_instructions: '',
327344
supported_options: {
328345
search: 'Search'
@@ -339,6 +356,7 @@ export const CHATBOTS = {
339356
supports_user_provided_port: false,
340357
supports_reasoning_effort: false,
341358
supports_thinking_budget: false,
359+
supports_custom_url_path: false,
342360
default_system_instructions: '',
343361
supported_options: {
344362
thinking: 'Thinking',
@@ -366,6 +384,7 @@ export const CHATBOTS = {
366384
supports_user_provided_port: false,
367385
supports_reasoning_effort: false,
368386
supports_thinking_budget: false,
387+
supports_custom_url_path: false,
369388
default_system_instructions: '',
370389
supported_options: {},
371390
default_top_p: 0,
@@ -389,6 +408,7 @@ export const CHATBOTS = {
389408
supports_user_provided_port: false,
390409
supports_reasoning_effort: false,
391410
supports_thinking_budget: false,
411+
supports_custom_url_path: false,
392412
default_system_instructions: '',
393413
supported_options: { 'deep-think': 'DeepThink', search: 'Search' },
394414
default_top_p: 0,
@@ -406,6 +426,7 @@ export const CHATBOTS = {
406426
supports_user_provided_port: false,
407427
supports_reasoning_effort: false,
408428
supports_thinking_budget: false,
429+
supports_custom_url_path: false,
409430
default_system_instructions: '',
410431
supported_options: {
411432
'deep-think': 'Deep Think'

‎packages/shared/src/types/preset.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export type Preset = {
1313
system_instructions?: string
1414
options?: string[]
1515
port?: number
16+
url_path?: string
1617
is_selected?: boolean
1718
is_collapsed?: boolean
1819
}

‎packages/vscode/src/services/websocket-manager.ts‎

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { WebsitesProvider } from '../context/providers/websites-provider'
1313
import { dictionary } from '@shared/constants/dictionary'
1414
import { Logger } from '@shared/utils/logger'
1515
import { Preset } from '@shared/types/preset'
16+
import { ConfigPresetFormat } from '@/views/panel/backend/utils/preset-format-converters'
1617

1718
/**
1819
* Bridges the current workspace window and websocket server that runs in a separate process.
@@ -276,7 +277,8 @@ export class WebSocketManager {
276277
}
277278

278279
const config = vscode.workspace.getConfiguration('codeWebChat')
279-
const web_chat_presets = config.get<any[]>(params.presets_config_key) ?? []
280+
const web_chat_presets =
281+
config.get<ConfigPresetFormat[]>(params.presets_config_key) ?? []
280282
const gemini_user_id = config.get<number | null>('geminiUserId')
281283

282284
for (const chat of params.chats) {
@@ -295,6 +297,11 @@ export class WebSocketManager {
295297
}
296298
} else if (preset.chatbot == 'Gemini' && gemini_user_id) {
297299
url = `https://gemini.google.com/u/${gemini_user_id}/app`
300+
} else if (chatbot.supports_custom_url_path && preset.urlPath) {
301+
const base_url = new URL(chatbot.url)
302+
url = `${base_url.origin}${
303+
preset.urlPath.startsWith('/') ? preset.urlPath : `/${preset.urlPath}`
304+
}`
298305
} else {
299306
url = chatbot.url
300307
}
@@ -305,7 +312,7 @@ export class WebSocketManager {
305312
url,
306313
model: preset.model,
307314
temperature: preset.temperature,
308-
top_p: preset.top_p,
315+
top_p: preset.topP,
309316
thinking_budget: preset.thinkingBudget,
310317
reasoning_effort: preset.reasoningEffort,
311318
system_instructions: preset.systemInstructions,
@@ -338,7 +345,7 @@ export class WebSocketManager {
338345
}
339346

340347
const config = vscode.workspace.getConfiguration('codeWebChat')
341-
const geminiUserNumber = config.get<number | null>('geminiUserNumber')
348+
const gemini_user_number = config.get<number | null>('geminiUserNumber')
342349

343350
const chatbot = CHATBOTS[params.preset.chatbot as keyof typeof CHATBOTS]
344351
let url: string
@@ -350,10 +357,17 @@ export class WebSocketManager {
350357
}
351358
} else if (
352359
params.preset.chatbot == 'Gemini' &&
353-
geminiUserNumber !== undefined &&
354-
geminiUserNumber !== null
360+
gemini_user_number !== undefined &&
361+
gemini_user_number !== null
355362
) {
356-
url = `https://gemini.google.com/u/${geminiUserNumber}/app`
363+
url = `https://gemini.google.com/u/${gemini_user_number}/app`
364+
} else if (chatbot.supports_custom_url_path && params.preset.url_path) {
365+
const base_url = new URL(chatbot.url)
366+
url = `${base_url.origin}${
367+
params.preset.url_path.startsWith('/')
368+
? params.preset.url_path
369+
: `/${params.preset.url_path}`
370+
}`
357371
} else {
358372
url = chatbot.url
359373
}

‎packages/vscode/src/views/panel/backend/message-handlers/handle-preview-preset.ts‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,8 @@ export const handle_preview_preset = async (
154154
reasoning_effort: message.preset.reasoning_effort,
155155
system_instructions: message.preset.system_instructions,
156156
options: message.preset.options,
157-
port: message.preset.port
157+
port: message.preset.port,
158+
url_path: message.preset.url_path
158159
}
159160

160161
provider.websocket_server_instance.preview_preset({

‎packages/vscode/src/views/panel/backend/message-handlers/handle-update-preset.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ export const handle_update_preset = async (
5151
a.system_instructions == b.system_instructions &&
5252
JSON.stringify(a.options) == JSON.stringify(b.options) &&
5353
a.port == b.port &&
54+
a.url_path == b.url_path &&
5455
a.is_selected == b.is_selected
5556
)
5657
}

‎packages/vscode/src/views/panel/backend/utils/preset-format-converters.ts‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export type ConfigPresetFormat = {
1414
systemInstructions?: string
1515
options?: string[]
1616
port?: number
17+
urlPath?: string
1718
isSelected?: boolean
1819
isCollapsed?: boolean
1920
}
@@ -34,6 +35,7 @@ export function config_preset_to_ui_format(
3435
system_instructions: config_preset.systemInstructions,
3536
options: config_preset.options,
3637
port: config_preset.port,
38+
url_path: config_preset.urlPath,
3739
is_selected: config_preset.isSelected,
3840
is_collapsed: config_preset.isCollapsed
3941
}
@@ -53,6 +55,7 @@ export function ui_preset_to_config_format(preset: Preset): ConfigPresetFormat {
5355
systemInstructions: preset.system_instructions,
5456
options: preset.options,
5557
port: preset.port,
58+
urlPath: preset.url_path,
5659
isSelected: preset.is_selected,
5760
isCollapsed: preset.is_collapsed
5861
}

‎packages/vscode/src/views/panel/frontend/EditPresetForm/EditPresetForm.tsx‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ export const EditPresetForm: React.FC<Props> = (props) => {
4343
props.preset.system_instructions
4444
)
4545
const [port, set_port] = useState(props.preset.port)
46+
const [url_path, set_url_path] = useState(props.preset.url_path)
4647
const [prompt_prefix, set_prompt_prefix] = useState(
4748
props.preset.prompt_prefix
4849
)
@@ -75,6 +76,7 @@ export const EditPresetForm: React.FC<Props> = (props) => {
7576
const supports_system_instructions =
7677
chatbot_config?.supports_system_instructions
7778
const supports_port = chatbot_config?.supports_user_provided_port
79+
const supports_custom_url_path = chatbot_config?.supports_custom_url_path
7880
const supports_user_provided_model =
7981
chatbot_config?.supports_user_provided_model
8082
const models = chatbot_config?.models || {}
@@ -94,6 +96,7 @@ export const EditPresetForm: React.FC<Props> = (props) => {
9496
...(model ? { model } : {}),
9597
...(system_instructions ? { system_instructions } : {}),
9698
...(port !== undefined ? { port } : {}),
99+
...(url_path ? { url_path } : {}),
97100
...(options.length ? { options } : {}),
98101
is_selected: props.preset.is_selected
99102
})
@@ -114,6 +117,7 @@ export const EditPresetForm: React.FC<Props> = (props) => {
114117
model,
115118
system_instructions,
116119
port,
120+
url_path,
117121
prompt_prefix,
118122
prompt_suffix,
119123
options
@@ -123,6 +127,7 @@ export const EditPresetForm: React.FC<Props> = (props) => {
123127
set_chatbot(new_chatbot)
124128
set_model(Object.keys(CHATBOTS[new_chatbot].models)[0] || undefined)
125129
set_port(undefined)
130+
set_url_path(undefined)
126131
set_temperature(
127132
CHATBOTS[new_chatbot].supports_custom_temperature ? 0.5 : undefined
128133
)
@@ -281,6 +286,21 @@ export const EditPresetForm: React.FC<Props> = (props) => {
281286
</Field>
282287
)}
283288

289+
{supports_custom_url_path && (
290+
<Field
291+
label="URL Path"
292+
html_for="url-path"
293+
info="Custom path to append to the chatbot's base URL."
294+
>
295+
<Input
296+
id="url-path"
297+
type="text"
298+
value={url_path || ''}
299+
onChange={set_url_path}
300+
/>
301+
</Field>
302+
)}
303+
284304
{Object.keys(supported_options).length > 0 && (
285305
<Field label="Options">
286306
<div className={styles.options}>

0 commit comments

Comments
 (0)