Skip to content

Commit 3f94ba6

Browse files
committed
Pause workspace file watcher during response processing and preview operations
- pause context file watching for the brief moment a response is applied or rolled back - asses whether resume_file_watcher shouldn't have 'refresh' built-in └── apps └── editor └── src ├── commands │ ├── apply-response-command │ │ ├── apply-response-command.ts │ │ ├── handlers │ │ │ ├── diff-handler.ts │ │ │ ├── fast-replace-handler.ts │ │ │ ├── restore-preview-handler.ts │ │ │ ├── search-replace-handler.ts │ │ │ └── truncated-handler.ts │ │ ├── index.ts │ │ ├── response-processor.ts │ │ ├── types │ │ │ └── original-file-state.ts │ │ └── utils │ │ ├── file-checks.ts │ │ ├── file-operations.ts │ │ ├── preview │ │ │ ├── diff-utils.ts │ │ │ ├── file-preparer.ts │ │ │ ├── index.ts │ │ │ ├── preview.ts │ │ │ ├── temp-file-manager.ts │ │ │ ├── types.ts │ │ │ ├── virtual-document-provider.ts │ │ │ ├── vscode-ui.ts │ │ │ └── workspace-listener.ts │ │ ├── preview-handler.ts │ │ └── state-manager.ts │ └── history-command │ ├── actions │ │ ├── clear-all-checkpoints.ts │ │ ├── create-temporary-checkpoint.ts │ │ ├── delete-checkpoint-with-undo.ts │ │ ├── restore-checkpoint.ts │ │ ├── sync-workspace-from-dir.ts │ │ ├── toggle-checkpoint-pin.ts │ │ └── update-checkpoint-description.ts │ ├── history-command.ts │ ├── index.ts │ └── utils │ └── sync-directory.ts └── context ├── context-initialization.ts ├── helpers │ ├── get-all-workspace-files.ts │ └── get-selected-files.ts ├── providers │ ├── open-editors │ │ └── open-editors-provider.ts │ ├── selected-files │ │ └── selected-files-provider.ts │ └── workspace │ ├── modules │ │ ├── index.ts │ │ └── token-calculator.ts │ └── workspace-provider.ts ├── shared-context-state.ts └── utils └── shrink-file ├── index.ts ├── languages │ ├── c-style.ts │ ├── css.ts │ ├── html.ts │ ├── jsx.ts │ ├── python.ts │ ├── ruby.ts │ └── sql.ts ├── shrink-file.spec.ts ├── shrink-file.ts └── test-cases ├── c-style │ ├── input.txt │ └── output.txt ├── css │ ├── input.txt │ └── output.txt ├── html │ ├── input.txt │ └── output.txt ├── jsx │ ├── input.txt │ └── output.txt ├── python │ ├── input.txt │ └── output.txt ├── ruby │ ├── input.txt │ └── output.txt ├── scss │ ├── input.txt │ └── output.txt └── sql ├── input.txt └── output.txt
1 parent eae3f1b commit 3f94ba6

6 files changed

Lines changed: 133 additions & 107 deletions

File tree

‎apps/editor/src/commands/apply-response-command/response-processor.ts‎

Lines changed: 55 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,13 @@ export const process_response = async (params: {
7070
(f) => f.type === 'file'
7171
) as FileInPreview[]
7272
if (files.length > 0) {
73-
const result = await handle_restore_preview(files)
73+
params.workspace_provider.pause_file_watcher()
74+
let result: { success: boolean; original_states?: OriginalFileState[] }
75+
try {
76+
result = await handle_restore_preview(files)
77+
} finally {
78+
params.workspace_provider.resume_file_watcher()
79+
}
7480
if (result.success && result.original_states) {
7581
const augmented_states = result.original_states.map((state) => {
7682
const file_in_preview = files.find(
@@ -292,8 +298,10 @@ export const process_response = async (params: {
292298

293299
const total_patches = patches.length
294300

295-
for (let i = 0; i < total_patches; i++) {
296-
on_progress(Math.round((i / total_patches) * 100))
301+
params.workspace_provider.pause_file_watcher()
302+
try {
303+
for (let i = 0; i < total_patches; i++) {
304+
on_progress(Math.round((i / total_patches) * 100))
297305
const patch = patches[i]
298306
let workspace_path = default_workspace
299307

@@ -342,27 +350,30 @@ export const process_response = async (params: {
342350
}
343351
}
344352

345-
if (all_original_states.length > 0) {
346-
all_original_states =
347-
set_new_paths_in_original_states(all_original_states)
348-
await apply_file_relocations(all_original_states)
349-
update_undo_button_state({
350-
extension_context: params.extension_context,
351-
prompt_view_provider: params.prompt_view_provider,
352-
states: all_original_states,
353-
applied_content: params.response,
354-
original_editor_state: params.args?.original_editor_state
355-
})
356-
}
353+
if (all_original_states.length > 0) {
354+
all_original_states =
355+
set_new_paths_in_original_states(all_original_states)
356+
await apply_file_relocations(all_original_states)
357+
update_undo_button_state({
358+
extension_context: params.extension_context,
359+
prompt_view_provider: params.prompt_view_provider,
360+
states: all_original_states,
361+
applied_content: params.response,
362+
original_editor_state: params.args?.original_editor_state
363+
})
364+
}
357365

358-
if (all_original_states.length > 0) {
359-
return {
360-
original_states: all_original_states,
361-
response: params.response
366+
if (all_original_states.length > 0) {
367+
return {
368+
original_states: all_original_states,
369+
response: params.response
370+
}
362371
}
363-
}
364372

365-
return null
373+
return null
374+
} finally {
375+
params.workspace_provider.resume_file_watcher()
376+
}
366377
} else {
367378
const files = params.response_items.filter(
368379
(item): item is FileItem => item.type == 'file'
@@ -405,18 +416,20 @@ export const process_response = async (params: {
405416
let final_original_states: OriginalFileState[] | null = null
406417
let operation_success = false
407418

408-
if (selected_mode_label == 'Fast replace') {
409-
const result = await handle_fast_replace({ files, on_progress })
410-
if (result.success && result.original_states) {
411-
final_original_states = result.original_states
412-
operation_success = true
413-
}
414-
Logger.info({
415-
function_name: 'process_response',
416-
message: 'Fast replace handler finished.',
417-
data: { success: result.success }
418-
})
419-
} else if (selected_mode_label == 'Truncated') {
419+
params.workspace_provider.pause_file_watcher()
420+
try {
421+
if (selected_mode_label == 'Fast replace') {
422+
const result = await handle_fast_replace({ files, on_progress })
423+
if (result.success && result.original_states) {
424+
final_original_states = result.original_states
425+
operation_success = true
426+
}
427+
Logger.info({
428+
function_name: 'process_response',
429+
message: 'Fast replace handler finished.',
430+
data: { success: result.success }
431+
})
432+
} else if (selected_mode_label == 'Truncated') {
420433
const result = await handle_truncated_edit({ files, on_progress })
421434
const successful_states = result.original_states || []
422435
const failed_files = result.failed_files || []
@@ -483,12 +496,15 @@ export const process_response = async (params: {
483496
message: 'Conflict markers handler finished.',
484497
data: { success: result.success }
485498
})
486-
} else {
487-
Logger.error({
488-
function_name: 'process_response',
489-
message: 'No valid mode selected or determined.'
490-
})
491-
return null
499+
} else {
500+
Logger.error({
501+
function_name: 'process_response',
502+
message: 'No valid mode selected or determined.'
503+
})
504+
return null
505+
}
506+
} finally {
507+
params.workspace_provider.resume_file_watcher()
492508
}
493509

494510
if (operation_success && final_original_states) {

‎apps/editor/src/commands/apply-response-command/utils/preview-handler.ts‎

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,14 @@ export const preview_handler = async (params: {
8484
})
8585
}
8686
}
87-
await undo_files({
88-
original_states: params.original_states
89-
})
87+
params.workspace_provider.pause_file_watcher()
88+
try {
89+
await undo_files({
90+
original_states: params.original_states
91+
})
92+
} finally {
93+
params.workspace_provider.resume_file_watcher()
94+
}
9095
update_undo_button_state({
9196
extension_context: params.extension_context,
9297
prompt_view_provider: params.prompt_view_provider,
@@ -96,9 +101,14 @@ export const preview_handler = async (params: {
96101
}
97102

98103
if (preview_result.rejected_states.length > 0) {
99-
await undo_files({
100-
original_states: preview_result.rejected_states
101-
})
104+
params.workspace_provider.pause_file_watcher()
105+
try {
106+
await undo_files({
107+
original_states: preview_result.rejected_states
108+
})
109+
} finally {
110+
params.workspace_provider.resume_file_watcher()
111+
}
102112
}
103113

104114
const accepted_states = params.original_states.filter((state) =>

‎apps/editor/src/commands/apply-response-command/utils/preview/workspace-listener.ts‎

Lines changed: 60 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -768,10 +768,15 @@ export const setup_workspace_listeners = (params: {
768768

769769
const proposed = file_to_discard.previewable_file.proposed_content
770770

771-
await vscode.workspace.fs.writeFile(
772-
vscode.Uri.file(file_to_discard.sanitized_path),
773-
Buffer.from(proposed, 'utf8')
774-
)
771+
params.workspace_provider.pause_file_watcher()
772+
try {
773+
await vscode.workspace.fs.writeFile(
774+
vscode.Uri.file(file_to_discard.sanitized_path),
775+
Buffer.from(proposed, 'utf8')
776+
)
777+
} finally {
778+
params.workspace_provider.resume_file_watcher()
779+
}
775780
}
776781

777782
toggle_file_preview_state = async ({
@@ -819,57 +824,62 @@ export const setup_workspace_listeners = (params: {
819824
)!
820825
}
821826

822-
if (!is_checked) {
823-
// Before reverting, capture current content if file exists
824-
if (fs.existsSync(file_to_toggle.sanitized_path)) {
825-
const document = await vscode.workspace.openTextDocument(
826-
vscode.Uri.file(file_to_toggle.sanitized_path)
827-
)
828-
const current_content = document.getText()
829-
file_to_toggle.content_to_restore = current_content
830-
}
827+
params.workspace_provider.pause_file_watcher()
828+
try {
829+
if (!is_checked) {
830+
// Before reverting, capture current content if file exists
831+
if (fs.existsSync(file_to_toggle.sanitized_path)) {
832+
const document = await vscode.workspace.openTextDocument(
833+
vscode.Uri.file(file_to_toggle.sanitized_path)
834+
)
835+
const current_content = document.getText()
836+
file_to_toggle.content_to_restore = current_content
837+
}
831838

832-
if (file_to_toggle.previewable_file.file_state == 'new') {
833-
try {
834-
if (fs.existsSync(file_to_toggle.sanitized_path)) {
835-
await vscode.workspace.fs.delete(
836-
vscode.Uri.file(file_to_toggle.sanitized_path)
837-
)
838-
await remove_directory_if_empty({
839-
dir_path: path.dirname(file_to_toggle.sanitized_path),
840-
workspace_root
841-
})
842-
}
843-
} catch (e) {}
839+
if (file_to_toggle.previewable_file.file_state == 'new') {
840+
try {
841+
if (fs.existsSync(file_to_toggle.sanitized_path)) {
842+
await vscode.workspace.fs.delete(
843+
vscode.Uri.file(file_to_toggle.sanitized_path)
844+
)
845+
await remove_directory_if_empty({
846+
dir_path: path.dirname(file_to_toggle.sanitized_path),
847+
workspace_root
848+
})
849+
}
850+
} catch (e) {}
851+
} else {
852+
await vscode.workspace.fs.writeFile(
853+
vscode.Uri.file(file_to_toggle.sanitized_path),
854+
Buffer.from(file_to_toggle.original_content, 'utf8')
855+
)
856+
}
844857
} else {
845-
await vscode.workspace.fs.writeFile(
846-
vscode.Uri.file(file_to_toggle.sanitized_path),
847-
Buffer.from(file_to_toggle.original_content, 'utf8')
848-
)
849-
}
850-
} else {
851-
if (file_to_toggle.previewable_file.file_state == 'deleted') {
852-
try {
853-
if (fs.existsSync(file_to_toggle.sanitized_path)) {
854-
await vscode.workspace.fs.delete(
855-
vscode.Uri.file(file_to_toggle.sanitized_path)
858+
if (file_to_toggle.previewable_file.file_state == 'deleted') {
859+
try {
860+
if (fs.existsSync(file_to_toggle.sanitized_path)) {
861+
await vscode.workspace.fs.delete(
862+
vscode.Uri.file(file_to_toggle.sanitized_path)
863+
)
864+
await remove_directory_if_empty({
865+
dir_path: path.dirname(file_to_toggle.sanitized_path),
866+
workspace_root
867+
})
868+
}
869+
} catch (e) {}
870+
} else {
871+
await vscode.workspace.fs.writeFile(
872+
vscode.Uri.file(file_to_toggle.sanitized_path),
873+
Buffer.from(
874+
file_to_toggle.content_to_restore ??
875+
file_to_toggle.previewable_file.content,
876+
'utf8'
856877
)
857-
await remove_directory_if_empty({
858-
dir_path: path.dirname(file_to_toggle.sanitized_path),
859-
workspace_root
860-
})
861-
}
862-
} catch (e) {}
863-
} else {
864-
await vscode.workspace.fs.writeFile(
865-
vscode.Uri.file(file_to_toggle.sanitized_path),
866-
Buffer.from(
867-
file_to_toggle.content_to_restore ??
868-
file_to_toggle.previewable_file.content,
869-
'utf8'
870878
)
871-
)
879+
}
872880
}
881+
} finally {
882+
params.workspace_provider.resume_file_watcher()
873883
}
874884
}
875885

‎apps/editor/src/commands/history-command/actions/restore-checkpoint.ts‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -526,7 +526,6 @@ export const restore_checkpoint = async (params: {
526526
return temp_checkpoint
527527
} finally {
528528
params.workspace_provider.resume_file_watcher()
529-
params.workspace_provider.refresh()
530529
}
531530
}
532531

‎apps/editor/src/context/providers/workspace/workspace-provider.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,7 @@ export class WorkspaceProvider
370370

371371
public resume_file_watcher(): void {
372372
this._is_file_watcher_paused = false
373+
this.refresh()
373374
}
374375

375376
public invalidate_token_counts_for_file(changed_file_path: string) {

‎packages/ui/src/components/editor/prompt/modals/OngoingApiCallsModal/OngoingApiCallsModal.tsx‎

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ const format_tokens = (tokens: number): string => {
2727

2828
export const OngoingApiCallsModal: React.FC<Props> = (props) => {
2929
const { start_times, now } = use_progress_times(props.progress_items)
30-
const [window_width, set_window_width] = useState(window.innerWidth)
3130
const container_ref = useRef<HTMLDivElement>(null)
3231

3332
useEffect(() => {
@@ -47,14 +46,6 @@ export const OngoingApiCallsModal: React.FC<Props> = (props) => {
4746
}
4847
}, [props.on_height_change])
4948

50-
useEffect(() => {
51-
const handle_resize = () => set_window_width(window.innerWidth)
52-
window.addEventListener('resize', handle_resize)
53-
return () => {
54-
window.removeEventListener('resize', handle_resize)
55-
}
56-
}, [])
57-
5849
return (
5950
<div
6051
className={styles.overlay}
@@ -99,8 +90,7 @@ export const OngoingApiCallsModal: React.FC<Props> = (props) => {
9990
<div className={styles.item__bottom__right}>
10091
{item.tokens_per_second !== undefined && (
10192
<div>
102-
{format_tokens(item.tokens_per_second)}{' '}
103-
{window_width < 340 ? 't/s' : 'tokens/s'}
93+
{`${format_tokens(item.tokens_per_second)} t/s`}
10494
</div>
10595
)}
10696
{item.total_tokens !== undefined && (

0 commit comments

Comments
 (0)