Skip to content

Commit d3154f4

Browse files
committed
Add an option to reuse the last browser tab for chat initialization and include corresponding settings
1 parent be0d71d commit d3154f4

18 files changed

Lines changed: 143 additions & 22 deletions

File tree

‎apps/browser/src/background/message-handler.ts‎

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ interface ChatQueueItem {
1414

1515
const chat_queue: ChatQueueItem[] = []
1616
let is_processing = false
17+
let last_opened_tab_id: number | undefined
1718

1819
const CHAT_INITIALIZATION_TIMEOUT = 5000
1920

@@ -86,29 +87,42 @@ const process_next_chat = async () => {
8687
const { 'selected-firefox-container': selected_firefox_container_id } =
8788
await browser.storage.local.get('selected-firefox-container')
8889

89-
const create_tab_options: any = {
90-
active: true
91-
}
92-
93-
if (selected_firefox_container_id) {
94-
create_tab_options.cookieStoreId = selected_firefox_container_id
95-
}
96-
90+
let target_url = ''
9791
// OpenRouter is a special case—model handling via search params
9892
if (current_chat_message.url == 'https://openrouter.ai/chat') {
9993
// https://openrouter.ai/chat?models=openrouter/quasar-alpha
10094
const search_params = new URLSearchParams()
10195
if (current_chat_message.model) {
10296
search_params.set('models', current_chat_message.model)
10397
}
104-
const open_router_url = `${
98+
target_url = `${
10599
current_chat_message.url
106100
}?${search_params.toString()}#cwc-${batch_id}`
107-
create_tab_options.url = open_router_url
108-
browser.tabs.create(create_tab_options)
109101
} else {
110-
create_tab_options.url = `${current_chat_message.url}#cwc-${batch_id}`
111-
browser.tabs.create(create_tab_options)
102+
target_url = `${current_chat_message.url}#cwc-${batch_id}`
103+
}
104+
105+
let tab_reused = false
106+
if (last_opened_tab_id !== undefined && current_chat_message.reuse_last_tab) {
107+
try {
108+
await browser.tabs.get(last_opened_tab_id)
109+
await browser.tabs.update(last_opened_tab_id, {
110+
url: target_url,
111+
active: true
112+
})
113+
tab_reused = true
114+
} catch {
115+
last_opened_tab_id = undefined
116+
}
117+
}
118+
119+
if (!tab_reused) {
120+
const create_tab_options: any = { active: true, url: target_url }
121+
if (selected_firefox_container_id) {
122+
create_tab_options.cookieStoreId = selected_firefox_container_id
123+
}
124+
const new_tab = await browser.tabs.create(create_tab_options)
125+
last_opened_tab_id = new_tab.id
112126
}
113127

114128
current_queue_item.timeout_id = setTimeout(() => {

‎apps/editor/package.json‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -827,6 +827,11 @@
827827
"scope": "resource",
828828
"default": false
829829
},
830+
"codeWebChat.reuseLastTab": {
831+
"type": "boolean",
832+
"scope": "resource",
833+
"default": false
834+
},
830835
"codeWebChat.clearChecksInWorkspaceBehavior": {
831836
"type": "string",
832837
"scope": "resource",

‎apps/editor/src/commands/apply-chat-response-command/utils/edit-formats/diffs/test-cases/generic-6/expected.txt‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ export const handle_preview_preset = async (
284284
if (sent) {
285285
panel_provider.send_message({
286286
command: 'SHOW_AUTO_CLOSING_MODAL',
287-
title: 'Opened in the connected browser',
287+
title: 'Continue in theconnected browser',
288288
type: 'success'
289289
})
290290
}

‎apps/editor/src/commands/apply-chat-response-command/utils/edit-formats/diffs/test-cases/generic-6/original.txt‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ export const handle_preview_preset = async (
273273
if (sent) {
274274
panel_provider.send_message({
275275
command: 'SHOW_AUTO_CLOSING_MODAL',
276-
title: 'Opened in the connected browser',
276+
title: 'Continue in theconnected browser',
277277
type: 'success'
278278
})
279279
}

‎apps/editor/src/services/websocket-manager.ts‎

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { Preset } from '@shared/types/preset'
1616
import { ConfigPresetFormat } from '@/views/panel/backend/utils/preset-format-converters'
1717
import { LAST_SELECTED_BROWSER_ID_STATE_KEY } from '@/constants/state-keys'
1818
import { ApplyChatResponseCommandArgs } from '@/commands/apply-chat-response-command/response-processor'
19+
import { WebPromptType } from '@shared/types/prompt-types'
1920

2021
/**
2122
* Bridges the current workspace window and websocket server that runs in a separate process.
@@ -315,7 +316,7 @@ export class WebSocketManager {
315316
preset_name: string
316317
raw_instructions?: string
317318
edit_format?: string
318-
prompt_type: any
319+
prompt_type?: WebPromptType
319320
}>
320321
presets_config_key: string
321322
}): Promise<boolean> {
@@ -328,6 +329,7 @@ export class WebSocketManager {
328329
config.get<ConfigPresetFormat[]>(params.presets_config_key) ?? []
329330
const gemini_user_id = config.get<number | null>('geminiUserId')
330331
const ai_studio_user_id = config.get<number | null>('aiStudioUserId')
332+
const reuse_last_tab = config.get<boolean>('reuseLastTab', false)
331333

332334
const target_browser_id = await this._select_browser()
333335
if (target_browser_id === undefined) {
@@ -405,7 +407,8 @@ export class WebSocketManager {
405407
client_id: this.client_id || 0, // 0 is a temporary fallback and should be removed few weeks from 28.03.25
406408
raw_instructions: chat.raw_instructions,
407409
edit_format: chat.edit_format,
408-
prompt_type: chat.prompt_type
410+
prompt_type: chat.prompt_type,
411+
reuse_last_tab
409412
}
410413

411414
Logger.info({
@@ -424,7 +427,7 @@ export class WebSocketManager {
424427
instruction: string
425428
preset: Preset
426429
raw_instructions: string
427-
prompt_type: any
430+
prompt_type?: WebPromptType
428431
}): Promise<boolean> {
429432
if (!this.has_connected_browsers) {
430433
throw new Error('Does not have connected browsers.')
@@ -438,6 +441,7 @@ export class WebSocketManager {
438441
const config = vscode.workspace.getConfiguration('codeWebChat')
439442
const gemini_user_number = config.get<number | null>('geminiUserNumber')
440443
const ai_studio_user_id = config.get<number | null>('aiStudioUserId')
444+
const reuse_last_tab = config.get<boolean>('reuseLastTab', false)
441445

442446
const chatbot = CHATBOTS[params.preset.chatbot as keyof typeof CHATBOTS]
443447
let url: string
@@ -507,7 +511,8 @@ export class WebSocketManager {
507511
options: params.preset.options,
508512
client_id: this.client_id || 0, // 0 is a temporary fallback and should be removed few weeks from 28.03.25
509513
raw_instructions: params.raw_instructions,
510-
prompt_type: params.prompt_type
514+
prompt_type: params.prompt_type,
515+
reuse_last_tab
511516
}
512517

513518
Logger.info({

‎apps/editor/src/views/panel/backend/message-handlers/handle-preview-preset.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ export const handle_preview_preset = async (
154154
if (sent) {
155155
panel_provider.send_message({
156156
command: 'SHOW_AUTO_CLOSING_MODAL',
157-
title: 'Opened in the connected browser',
157+
title: 'Continue in theconnected browser',
158158
type: 'success'
159159
})
160160
}

‎apps/editor/src/views/panel/backend/message-handlers/handle-send-to-browser.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ export const handle_send_to_browser = async (params: {
232232
if (sent) {
233233
params.panel_provider.send_message({
234234
command: 'SHOW_AUTO_CLOSING_MODAL',
235-
title: 'Opened in the connected browser',
235+
title: 'Continue in theconnected browser',
236236
type: 'success'
237237
})
238238
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import * as vscode from 'vscode'
2+
import { SettingsProvider } from '@/views/settings/backend/settings-provider'
3+
4+
export const handle_get_reuse_last_tab = async (
5+
provider: SettingsProvider
6+
): Promise<void> => {
7+
const config = vscode.workspace.getConfiguration('codeWebChat')
8+
const enabled = config.get<boolean>('reuseLastTab', false)
9+
provider.postMessage({
10+
command: 'REUSE_LAST_TAB',
11+
enabled
12+
})
13+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import * as vscode from 'vscode'
2+
import { UpdateReuseLastTabMessage } from '@/views/settings/types/messages'
3+
4+
export const handle_update_reuse_last_tab = async (
5+
message: UpdateReuseLastTabMessage
6+
): Promise<void> => {
7+
await vscode.workspace
8+
.getConfiguration('codeWebChat')
9+
.update(
10+
'reuseLastTab',
11+
message.enabled || undefined,
12+
vscode.ConfigurationTarget.Global
13+
)
14+
}

‎apps/editor/src/views/settings/backend/message-handlers/index.ts‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ export * from './handle-get-send-with-shift-enter'
3333
export * from './handle-update-send-with-shift-enter'
3434
export * from './handle-get-check-new-files'
3535
export * from './handle-update-check-new-files'
36+
export * from './handle-get-reuse-last-tab'
37+
export * from './handle-update-reuse-last-tab'
3638
export * from './handle-delete-configuration'
3739
export * from './handle-get-configurations'
3840
export * from './handle-get-fix-all-automatically'

0 commit comments

Comments
 (0)