Skip to content

Commit 3d1f7ec

Browse files
committed
Enable applying changes from response history and update the review UI to track file content and stats changes during review
1 parent a21cf57 commit 3d1f7ec

8 files changed

Lines changed: 152 additions & 59 deletions

File tree

‎packages/shared/src/types/file-in-review.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ export type FileInReview = {
88
is_fallback?: boolean
99
is_replaced?: boolean
1010
diff_fallback_method?: 'recount' | 'search_and_replace'
11+
content?: string
1112
}

‎packages/vscode/src/commands/apply-chat-response-command/apply-chat-response-command.ts‎

Lines changed: 76 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import {
3434
delete_checkpoint,
3535
promote_temporary_checkpoint
3636
} from '../checkpoints-command/actions'
37+
import { FileInReview } from '@shared/types/file-in-review'
3738

3839
let ongoing_review_cleanup_promise: Promise<void> | null = null
3940

@@ -382,6 +383,7 @@ export const apply_chat_response_command = (
382383
file_path: string
383384
position: { line: number; character: number }
384385
}
386+
files_with_content?: FileInReview[]
385387
}) => {
386388
if (!vscode.workspace.workspaceFolders?.length) {
387389
vscode.window.showErrorMessage(
@@ -442,6 +444,16 @@ export const apply_chat_response_command = (
442444
is_single_root_folder_workspace
443445
})
444446

447+
if (args?.files_with_content) {
448+
clipboard_content = {
449+
type: 'files',
450+
files: args.files_with_content as ClipboardFile[]
451+
}
452+
}
453+
454+
console.log('xxx', args?.files_with_content)
455+
console.log('xxx', clipboard_content)
456+
445457
if (
446458
clipboard_content.type == 'code-completion' &&
447459
clipboard_content.code_completion
@@ -949,59 +961,79 @@ export const apply_chat_response_command = (
949961

950962
try {
951963
if (review_data) {
952-
let total_lines_added = 0
953-
let total_lines_removed = 0
964+
if (!args?.files_with_content) {
965+
let total_lines_added = 0
966+
let total_lines_removed = 0
967+
const files_for_history: FileInReview[] = []
968+
969+
const workspace_map = new Map<string, string>()
970+
vscode.workspace.workspaceFolders!.forEach((folder) => {
971+
workspace_map.set(folder.name, folder.uri.fsPath)
972+
})
973+
const default_workspace =
974+
vscode.workspace.workspaceFolders![0].uri.fsPath
975+
976+
for (const state of review_data.original_states) {
977+
let workspace_root = default_workspace
978+
if (
979+
state.workspace_name &&
980+
workspace_map.has(state.workspace_name)
981+
) {
982+
workspace_root = workspace_map.get(state.workspace_name)!
983+
}
954984

955-
const workspace_map = new Map<string, string>()
956-
vscode.workspace.workspaceFolders!.forEach((folder) => {
957-
workspace_map.set(folder.name, folder.uri.fsPath)
958-
})
959-
const default_workspace =
960-
vscode.workspace.workspaceFolders![0].uri.fsPath
985+
const sanitized_file_path = create_safe_path(
986+
workspace_root,
987+
state.file_path
988+
)
989+
if (!sanitized_file_path) {
990+
continue
991+
}
961992

962-
for (const state of review_data.original_states) {
963-
let workspace_root = default_workspace
964-
if (
965-
state.workspace_name &&
966-
workspace_map.has(state.workspace_name)
967-
) {
968-
workspace_root = workspace_map.get(state.workspace_name)!
969-
}
993+
let current_content = ''
994+
try {
995+
if (fs.existsSync(sanitized_file_path)) {
996+
current_content = fs.readFileSync(sanitized_file_path, 'utf8')
997+
}
998+
} catch (error) {
999+
continue
1000+
}
9701001

971-
const sanitized_file_path = create_safe_path(
972-
workspace_root,
973-
state.file_path
974-
)
975-
if (!sanitized_file_path) {
976-
continue
977-
}
1002+
const diff_stats = get_diff_stats({
1003+
original_content: state.content,
1004+
new_content: current_content
1005+
})
9781006

979-
let current_content = ''
980-
try {
981-
if (fs.existsSync(sanitized_file_path)) {
982-
current_content = fs.readFileSync(sanitized_file_path, 'utf8')
983-
}
984-
} catch (error) {
985-
continue
1007+
total_lines_added += diff_stats.lines_added
1008+
total_lines_removed += diff_stats.lines_removed
1009+
1010+
const is_deleted =
1011+
!state.is_new && current_content === '' && state.content !== ''
1012+
1013+
files_for_history.push({
1014+
file_path: state.file_path,
1015+
workspace_name: state.workspace_name,
1016+
is_new: state.is_new,
1017+
is_deleted,
1018+
lines_added: diff_stats.lines_added,
1019+
lines_removed: diff_stats.lines_removed,
1020+
is_fallback: state.is_fallback,
1021+
is_replaced: state.is_replaced,
1022+
diff_fallback_method: state.diff_fallback_method,
1023+
content: current_content
1024+
})
9861025
}
9871026

988-
const diff_stats = get_diff_stats({
989-
original_content: state.content,
990-
new_content: current_content
1027+
view_provider.send_message({
1028+
command: 'NEW_RESPONSE_RECEIVED',
1029+
response: review_data.chat_response,
1030+
raw_instructions: args?.raw_instructions,
1031+
lines_added: total_lines_added,
1032+
lines_removed: total_lines_removed,
1033+
files: files_for_history
9911034
})
992-
993-
total_lines_added += diff_stats.lines_added
994-
total_lines_removed += diff_stats.lines_removed
9951035
}
9961036

997-
view_provider.send_message({
998-
command: 'NEW_RESPONSE_RECEIVED',
999-
response: review_data.chat_response,
1000-
raw_instructions: args?.raw_instructions,
1001-
lines_added: total_lines_added,
1002-
lines_removed: total_lines_removed
1003-
})
1004-
10051037
const changes_accepted = await handle_code_review_and_cleanup({
10061038
original_states: review_data.original_states,
10071039
chat_response: review_data.chat_response,

‎packages/vscode/src/commands/apply-chat-response-command/utils/review.ts‎

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@ import { create_safe_path } from '@/utils/path-sanitizer'
99
import { ViewProvider } from '@/views/panel/backend/panel-provider'
1010
import { OriginalFileState } from '@/commands/apply-chat-response-command/types/original-file-state'
1111
import { remove_directory_if_empty } from './file-operations'
12+
import { FileInReview } from '@shared/types/file-in-review'
1213

1314
export type CodeReviewDecision =
1415
| { jump_to: { file_path: string; workspace_name?: string } }
15-
| { accepted_files: Omit<ReviewableFile, 'content'>[] }
16+
| { accepted_files: FileInReview[] }
1617

1718
export type CodeReviewResult = {
1819
decision: CodeReviewDecision
@@ -32,17 +33,8 @@ export let toggle_file_review_state:
3233
}) => Promise<void>)
3334
| undefined
3435

35-
type ReviewableFile = {
36-
file_path: string
36+
type ReviewableFile = FileInReview & {
3737
content: string
38-
workspace_name?: string
39-
is_new?: boolean
40-
is_deleted?: boolean
41-
lines_added: number
42-
lines_removed: number
43-
is_fallback?: boolean
44-
is_replaced?: boolean
45-
diff_fallback_method?: 'recount' | 'search_and_replace'
4638
}
4739

4840
type PreparedFile = {
@@ -488,6 +480,14 @@ export const review = async (params: {
488480
} else {
489481
deleted_file_in_review.reviewable_file.is_deleted = true
490482
deleted_file_in_review.reviewable_file.content = ''
483+
const diff_stats = get_diff_stats({
484+
original_content: deleted_file_in_review.original_content,
485+
new_content: ''
486+
})
487+
deleted_file_in_review.reviewable_file.lines_added =
488+
diff_stats.lines_added
489+
deleted_file_in_review.reviewable_file.lines_removed =
490+
diff_stats.lines_removed
491491
params.view_provider.send_message({
492492
command: 'UPDATE_FILE_IN_REVIEW',
493493
file: deleted_file_in_review.reviewable_file

‎packages/vscode/src/views/panel/backend/panel-provider.ts‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,8 @@ export class ViewProvider implements vscode.WebviewViewProvider {
384384
'codeWebChat.applyChatResponse',
385385
{
386386
response: message.response,
387-
raw_instructions: message.raw_instructions
387+
raw_instructions: message.raw_instructions,
388+
files_with_content: message.files
388389
}
389390
)
390391
} else if (message.command == 'EXECUTE_COMMAND') {

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
import { ApiToolConfiguration } from '@/views/panel/types/messages'
1717
import { post_message } from '../utils/post_message'
1818
import { Configurations as UiConfigurations } from '@ui/components/editor/panel/Configurations'
19+
import { FileInReview } from '@shared/types/file-in-review'
1920

2021
type Props = {
2122
scroll_reset_key: number
@@ -25,6 +26,7 @@ type Props = {
2526
created_at: number
2627
lines_added: number
2728
lines_removed: number
29+
files?: FileInReview[]
2830
}[]
2931
selected_history_item_created_at?: number
3032
on_selected_history_item_change: (created_at: number) => void
@@ -563,11 +565,13 @@ export const Main: React.FC<Props> = (props) => {
563565
const handle_response_history_item_click = (item: {
564566
response: string
565567
raw_instructions?: string
568+
files?: FileInReview[]
566569
}) => {
567570
post_message(props.vscode, {
568571
command: 'APPLY_RESPONSE_FROM_HISTORY',
569572
response: item.response,
570-
raw_instructions: item.raw_instructions
573+
raw_instructions: item.raw_instructions,
574+
files: item.files
571575
})
572576
}
573577

‎packages/vscode/src/views/panel/frontend/Main/MainView/MainView.tsx‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { WEB_MODES, API_MODES } from './modes'
2323
import { Footer } from './components/Footer'
2424
import { Header } from './components/Header'
2525
import cn from 'classnames'
26+
import { FileInReview } from '@shared/types/file-in-review'
2627

2728
dayjs.extend(relativeTime)
2829

@@ -95,10 +96,12 @@ type Props = {
9596
created_at: number
9697
lines_added: number
9798
lines_removed: number
99+
files?: FileInReview[]
98100
}[]
99101
on_response_history_item_click: (item: {
100102
response: string
101103
raw_instructions?: string
104+
files?: FileInReview[]
102105
}) => void
103106
selected_history_item_created_at?: number
104107
on_selected_history_item_change: (created_at: number) => void

‎packages/vscode/src/views/panel/frontend/hooks/use-panel.ts‎

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ type ResponseHistoryItem = {
1717
created_at: number
1818
lines_added: number
1919
lines_removed: number
20+
files?: FileInReview[]
2021
}
2122

2223
export const use_panel = (vscode: any) => {
@@ -52,6 +53,8 @@ export const use_panel = (vscode: any) => {
5253
const [response_history, set_response_history] = useState<
5354
ResponseHistoryItem[]
5455
>([])
56+
57+
console.log(response_history)
5558
const [workspace_folder_count, set_workspace_folder_count] =
5659
useState<number>()
5760
const [is_connected, set_is_connected] = useState<boolean>()
@@ -154,6 +157,51 @@ export const use_panel = (vscode: any) => {
154157
return [...files, { ...message.file, is_checked: true }]
155158
}
156159
})
160+
set_response_history((current_history) => {
161+
const history_item_index = current_history.findIndex(
162+
(item) => item.created_at === selected_history_item_created_at
163+
)
164+
165+
if (history_item_index === -1) {
166+
return current_history
167+
}
168+
169+
const new_history = [...current_history]
170+
const history_item_to_update = { ...new_history[history_item_index] }
171+
172+
const files_in_history = history_item_to_update.files
173+
? [...history_item_to_update.files]
174+
: []
175+
176+
const file_in_history_index = files_in_history.findIndex(
177+
(f) =>
178+
f.file_path === message.file.file_path &&
179+
f.workspace_name === message.file.workspace_name
180+
)
181+
182+
if (file_in_history_index !== -1) {
183+
files_in_history[file_in_history_index] = message.file
184+
} else {
185+
files_in_history.push(message.file)
186+
}
187+
188+
history_item_to_update.files = files_in_history
189+
190+
// Recalculate total lines added/removed
191+
let total_lines_added = 0
192+
let total_lines_removed = 0
193+
for (const file of files_in_history) {
194+
total_lines_added += file.lines_added
195+
total_lines_removed += file.lines_removed
196+
}
197+
198+
history_item_to_update.lines_added = total_lines_added
199+
history_item_to_update.lines_removed = total_lines_removed
200+
201+
new_history[history_item_index] = history_item_to_update
202+
203+
return new_history
204+
})
157205
} else if (message.command == 'CODE_REVIEW_FINISHED') {
158206
set_files_to_review(undefined)
159207
set_raw_instructions(undefined)
@@ -188,7 +236,8 @@ export const use_panel = (vscode: any) => {
188236
raw_instructions: message.raw_instructions,
189237
created_at: now,
190238
lines_added: message.lines_added,
191-
lines_removed: message.lines_removed
239+
lines_removed: message.lines_removed,
240+
files: message.files
192241
}
193242
])
194243
} else {
@@ -203,7 +252,8 @@ export const use_panel = (vscode: any) => {
203252
raw_instructions: message.raw_instructions,
204253
created_at: now,
205254
lines_added: message.lines_added,
206-
lines_removed: message.lines_removed
255+
lines_removed: message.lines_removed,
256+
files: message.files
207257
}
208258
set_response_history([...response_history, new_item])
209259
if (!files_to_review) {

‎packages/vscode/src/views/panel/types/messages.ts‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,7 @@ export interface ApplyResponseFromHistoryMessage extends BaseMessage {
317317
command: 'APPLY_RESPONSE_FROM_HISTORY'
318318
response: string
319319
raw_instructions?: string
320+
files?: FileInReview[]
320321
}
321322

322323
export type FrontendMessage =
@@ -572,6 +573,7 @@ export interface NewResponseReceivedMessage extends BaseMessage {
572573
raw_instructions?: string
573574
lines_added: number
574575
lines_removed: number
576+
files?: FileInReview[]
575577
}
576578

577579
export type BackendMessage =

0 commit comments

Comments
 (0)