Skip to content

Commit 71f83a2

Browse files
committed
Support multi-workspace file operations by correctly tracking and applying workspace roots during renames, restorations, and deletions
1 parent ffd94b1 commit 71f83a2

13 files changed

Lines changed: 173 additions & 41 deletions

File tree

apps/editor/src/commands/apply-chat-response-command/apply-chat-response-command.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,8 @@ export const apply_chat_response_command = (params: {
327327
files_for_history.push({
328328
type: 'file',
329329
file_path: state.file_path_to_restore,
330-
workspace_name: state.workspace_name,
330+
workspace_name:
331+
state.restore_workspace_name ?? state.workspace_name,
331332
file_state: 'deleted',
332333
lines_added: 0,
333334
lines_removed: deleted_diff_stats.lines_removed,

apps/editor/src/commands/apply-chat-response-command/handlers/conflict-markers-handler.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,19 +75,33 @@ export const handle_conflict_markers = async (params: {
7575

7676
let rename_source_path: string | undefined
7777
let rename_source_content: string | undefined
78+
let rename_source_workspace_root: string | undefined
7879

7980
if (file.renamed_from) {
81+
let old_workspace_root = default_workspace
82+
if (
83+
file.renamed_from_workspace &&
84+
workspace_map.has(file.renamed_from_workspace)
85+
) {
86+
old_workspace_root = workspace_map.get(file.renamed_from_workspace)!
87+
}
88+
8089
const source_info = await read_rename_source_file({
8190
renamed_from: file.renamed_from,
82-
workspace_root
91+
workspace_root: old_workspace_root
8392
})
8493
if (source_info) {
8594
rename_source_path = source_info.path
8695
rename_source_content = source_info.content
96+
rename_source_workspace_root = old_workspace_root
8797
}
8898
}
8999

90-
if (rename_source_path && rename_source_content !== undefined) {
100+
if (
101+
rename_source_path &&
102+
rename_source_content !== undefined &&
103+
rename_source_workspace_root
104+
) {
91105
try {
92106
let new_content = rename_source_content
93107
if (has_markers) {
@@ -101,7 +115,7 @@ export const handle_conflict_markers = async (params: {
101115

102116
await cleanup_rename_source({
103117
source_path: rename_source_path,
104-
workspace_root
118+
workspace_root: rename_source_workspace_root
105119
})
106120

107121
const directory = path.dirname(safe_path)
@@ -118,6 +132,7 @@ export const handle_conflict_markers = async (params: {
118132
content: rename_source_content,
119133
workspace_name: file.workspace_name,
120134
file_path_to_restore: file.renamed_from,
135+
restore_workspace_name: file.renamed_from_workspace,
121136
ai_content: file.content,
122137
proposed_content: new_content
123138
})

apps/editor/src/commands/apply-chat-response-command/handlers/fast-replace-handler.ts

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -111,14 +111,22 @@ export const handle_fast_replace = async (params: {
111111
if (file.is_deleted) {
112112
// If the file was also renamed (moved then deleted), we need to ensure the source is deleted too.
113113
if (file.renamed_from) {
114+
let old_workspace_root = default_workspace
115+
if (
116+
file.renamed_from_workspace &&
117+
workspace_map.has(file.renamed_from_workspace)
118+
) {
119+
old_workspace_root = workspace_map.get(file.renamed_from_workspace)!
120+
}
121+
114122
const source_info = await read_rename_source_file({
115123
renamed_from: file.renamed_from,
116-
workspace_root
124+
workspace_root: old_workspace_root
117125
})
118126
if (source_info) {
119127
await cleanup_rename_source({
120128
source_path: source_info.path,
121-
workspace_root
129+
workspace_root: old_workspace_root
122130
})
123131
}
124132
}
@@ -161,19 +169,33 @@ export const handle_fast_replace = async (params: {
161169

162170
let rename_source_path: string | undefined
163171
let rename_source_content: string | undefined
172+
let rename_source_workspace_root: string | undefined
164173

165174
if (file.renamed_from) {
175+
let old_workspace_root = default_workspace
176+
if (
177+
file.renamed_from_workspace &&
178+
workspace_map.has(file.renamed_from_workspace)
179+
) {
180+
old_workspace_root = workspace_map.get(file.renamed_from_workspace)!
181+
}
182+
166183
const source_info = await read_rename_source_file({
167184
renamed_from: file.renamed_from,
168-
workspace_root
185+
workspace_root: old_workspace_root
169186
})
170187
if (source_info) {
171188
rename_source_path = source_info.path
172189
rename_source_content = source_info.content
190+
rename_source_workspace_root = old_workspace_root
173191
}
174192
}
175193

176-
if (rename_source_path && rename_source_content !== undefined) {
194+
if (
195+
rename_source_path &&
196+
rename_source_content !== undefined &&
197+
rename_source_workspace_root
198+
) {
177199
try {
178200
let new_content = file.content
179201
if (new_content == '') {
@@ -182,7 +204,7 @@ export const handle_fast_replace = async (params: {
182204

183205
await cleanup_rename_source({
184206
source_path: rename_source_path,
185-
workspace_root
207+
workspace_root: rename_source_workspace_root
186208
})
187209

188210
const directory = path.dirname(safe_path)
@@ -199,6 +221,7 @@ export const handle_fast_replace = async (params: {
199221
content: rename_source_content,
200222
workspace_name: file.workspace_name,
201223
file_path_to_restore: file.renamed_from,
224+
restore_workspace_name: file.renamed_from_workspace,
202225
ai_content: file.content,
203226
proposed_content: new_content
204227
})

apps/editor/src/commands/apply-chat-response-command/handlers/truncated-handler.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,19 +68,33 @@ export const handle_truncated_edit = async (params: {
6868

6969
let rename_source_path: string | undefined
7070
let rename_source_content: string | undefined
71+
let rename_source_workspace_root: string | undefined
7172

7273
if (file.renamed_from) {
74+
let old_workspace_root = default_workspace
75+
if (
76+
file.renamed_from_workspace &&
77+
workspace_map.has(file.renamed_from_workspace)
78+
) {
79+
old_workspace_root = workspace_map.get(file.renamed_from_workspace)!
80+
}
81+
7382
const source_info = await read_rename_source_file({
7483
renamed_from: file.renamed_from,
75-
workspace_root
84+
workspace_root: old_workspace_root
7685
})
7786
if (source_info) {
7887
rename_source_path = source_info.path
7988
rename_source_content = source_info.content
89+
rename_source_workspace_root = old_workspace_root
8090
}
8191
}
8292

83-
if (rename_source_path && rename_source_content !== undefined) {
93+
if (
94+
rename_source_path &&
95+
rename_source_content !== undefined &&
96+
rename_source_workspace_root
97+
) {
8498
try {
8599
const new_content = process_truncated_content(
86100
file.content,
@@ -89,7 +103,7 @@ export const handle_truncated_edit = async (params: {
89103

90104
await cleanup_rename_source({
91105
source_path: rename_source_path,
92-
workspace_root
106+
workspace_root: rename_source_workspace_root
93107
})
94108

95109
const directory = path.dirname(safe_path)
@@ -106,6 +120,7 @@ export const handle_truncated_edit = async (params: {
106120
content: rename_source_content,
107121
workspace_name: file.workspace_name,
108122
file_path_to_restore: file.renamed_from,
123+
restore_workspace_name: file.renamed_from_workspace,
109124
ai_content: file.content,
110125
proposed_content: new_content
111126
})

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

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -268,18 +268,28 @@ export const process_chat_response = async (params: {
268268
const patches = params.clipboard_items.filter(
269269
(item): item is DiffItem => item.type == 'diff'
270270
)
271-
const rename_map = new Map<string, string>()
271+
const rename_map = new Map<
272+
string,
273+
{ new_path: string; new_workspace?: string }
274+
>()
272275
patches.forEach((patch) => {
273276
if (patch.new_file_path && patch.file_path) {
274-
rename_map.set(patch.file_path, patch.new_file_path)
277+
const key = `${patch.workspace_name || ''}:${patch.file_path}`
278+
rename_map.set(key, {
279+
new_path: patch.new_file_path,
280+
new_workspace: patch.new_workspace_name
281+
})
275282
}
276283
})
277284

278285
const set_new_paths_in_original_states = (states: OriginalFileState[]) => {
279286
if (!rename_map.size) return
280287
states.forEach((state) => {
281-
if (rename_map.has(state.file_path)) {
282-
state.new_file_path = rename_map.get(state.file_path)!
288+
const key = `${state.workspace_name || ''}:${state.file_path}`
289+
if (rename_map.has(key)) {
290+
const rename_info = rename_map.get(key)!
291+
state.new_file_path = rename_info.new_path
292+
state.new_workspace_name = rename_info.new_workspace
283293
}
284294
})
285295
}

apps/editor/src/commands/apply-chat-response-command/types/original-file-state.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ export type OriginalFileState = {
44
workspace_name?: string
55
cursor_offset?: number
66
new_file_path?: string
7+
new_workspace_name?: string
78
file_path_to_restore?: string
9+
restore_workspace_name?: string
810
diff_application_method?: 'recount' | 'search_and_replace'
911
file_state?: 'new' | 'deleted'
1012
is_checked?: boolean

apps/editor/src/commands/apply-chat-response-command/utils/clipboard-parser/clipboard-parser.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export type FileItem = {
1111
content: string
1212
workspace_name?: string
1313
renamed_from?: string
14+
renamed_from_workspace?: string
1415
is_deleted?: boolean
1516
}
1617

@@ -20,6 +21,7 @@ export type DiffItem = {
2021
content: string
2122
workspace_name?: string
2223
new_file_path?: string
24+
new_workspace_name?: string
2325
}
2426

2527
export type CodeAtCursorItem = {

apps/editor/src/commands/apply-chat-response-command/utils/clipboard-parser/parsers/diff-parser/diff-parser.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ const process_collected_patch_lines = (params: {
9797
})
9898
patch.new_file_path = new_relative
9999
if (new_workspace && new_workspace !== workspace_name) {
100-
patch.workspace_name = new_workspace
100+
patch.new_workspace_name = new_workspace
101101
}
102102
}
103103

@@ -353,7 +353,7 @@ const process_text_for_file_operations = (params: {
353353
new_info.workspace_name &&
354354
new_info.workspace_name !== old_info.workspace_name
355355
) {
356-
patch.workspace_name = new_info.workspace_name
356+
patch.new_workspace_name = new_info.workspace_name
357357
}
358358
items.push(patch)
359359
} else {

apps/editor/src/commands/apply-chat-response-command/utils/clipboard-parser/parsers/multiple-files-parser/helpers/item-management.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export const create_or_update_file_item = (params: {
99
results: (FileItem | TextItem | InlineFileItem)[]
1010
mode?: 'overwrite' | 'append'
1111
renamed_from?: string
12+
renamed_from_workspace?: string
1213
is_deleted?: boolean
1314
}) => {
1415
if (!params.file_name) {
@@ -71,6 +72,10 @@ export const create_or_update_file_item = (params: {
7172
existing_file.renamed_from = params.renamed_from
7273
}
7374

75+
if (params.renamed_from_workspace !== undefined) {
76+
existing_file.renamed_from_workspace = params.renamed_from_workspace
77+
}
78+
7479
if (params.is_deleted !== undefined) {
7580
existing_file.is_deleted = params.is_deleted
7681
}
@@ -81,6 +86,7 @@ export const create_or_update_file_item = (params: {
8186
content: processed_content,
8287
workspace_name: params.workspace_name,
8388
renamed_from: params.renamed_from,
89+
renamed_from_workspace: params.renamed_from_workspace,
8490
is_deleted: params.is_deleted
8591
}
8692
params.file_ref_map.set(file_key, new_file)

0 commit comments

Comments
 (0)