Skip to content

Commit 40d3d93

Browse files
committed
Optimize diff processor and adjust progress indicator visibility based on file count
1 parent 0e296f3 commit 40d3d93

6 files changed

Lines changed: 183 additions & 104 deletions

File tree

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

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -131,21 +131,21 @@ export const apply_chat_response_command = (params: {
131131
is_single_root_folder_workspace
132132
})
133133

134-
const has_content_to_preview =
135-
(args?.files_with_content && args.files_with_content.length > 0) ||
136-
parsed_items.some(
137-
(item) =>
138-
item.type == 'diff' ||
139-
item.type == 'file' ||
140-
item.type == 'code-at-cursor'
141-
)
142-
143-
if (has_content_to_preview) {
134+
const file_count = args?.files_with_content
135+
? args.files_with_content.length
136+
: parsed_items.filter(
137+
(item) =>
138+
item.type == 'diff' ||
139+
item.type == 'file' ||
140+
item.type == 'code-at-cursor'
141+
).length
142+
143+
if (file_count > 0) {
144144
params.panel_provider.send_message({
145145
command: 'SHOW_PROGRESS',
146146
title: 'Preparing response preview...',
147147
show_elapsed_time: false,
148-
delay_visibility: true,
148+
delay_visibility: file_count < 5,
149149
cancellable: false
150150
})
151151
}

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,5 +70,19 @@ describe('diff-processor', () => {
7070

7171
expect(result).toBe(expected)
7272
})
73+
74+
it('applies diff with generic test case 2 correctly', async () => {
75+
const test_case = 'generic-2'
76+
const original = load_test_case_file('', test_case, 'original.txt')
77+
const diff = load_test_case_file('', test_case, 'diff.txt')
78+
const expected = load_test_case_file('', test_case, 'expected.txt')
79+
80+
const result = apply_diff({
81+
original_code: original,
82+
diff_patch: diff
83+
})
84+
85+
expect(result).toBe(expected)
86+
})
7387
})
7488
})

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

Lines changed: 106 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ class SearchBlock {
1010
public search_lines: string[]
1111
public replace_lines: ReplaceLine[]
1212
public search_block_start_index: number
13+
public actual_original_line_count: number = 0
14+
public search_to_original_map: Map<number, number> = new Map()
1315

1416
public constructor(
1517
search_lines: string[],
@@ -25,7 +27,7 @@ class SearchBlock {
2527
return this.search_block_start_index
2628
}
2729
get_search_count() {
28-
return this.search_lines.length
30+
return this.actual_original_line_count || this.search_lines.length
2931
}
3032
}
3133

@@ -61,12 +63,12 @@ export const apply_diff = (params: {
6163
}): string => {
6264
const original_code_normalized = params.original_code.replace(/\r\n/g, '\n')
6365
const original_code_lines = original_code_normalized.split(/^/m)
64-
const original_code_lines_normalized = []
66+
const original_code_lines_normalized: { key: number; value: string }[] = []
6567

6668
const patch_normalized = params.diff_patch.replace(/\r\n/g, '\n')
6769
const patch_lines = patch_normalized.split('\n')
68-
const patch_lines_original = []
69-
const patch_lines_normalized = []
70+
const patch_lines_original: string[] = []
71+
const patch_lines_normalized: string[] = []
7072

7173
let line_count = 0
7274
for (let i = 0; i < original_code_lines.length; i++) {
@@ -107,11 +109,11 @@ export const apply_diff = (params: {
107109
continue
108110
}
109111

110-
if (line.trim() == '') {
112+
if (line.trim() === '') {
111113
line = '~nnn'
112-
} else if (line.trim() == '+') {
114+
} else if (line.trim() === '+') {
113115
line = '+~nnn'
114-
} else if (line.trim() == '-') {
116+
} else if (line.trim() === '-') {
115117
line = '-~nnn'
116118
}
117119

@@ -149,39 +151,32 @@ export const apply_diff = (params: {
149151
let inside_replace_block = false
150152
let current_block_has_changes = false
151153

154+
const push_block = () => {
155+
if (search_chunks.length > 0 || replace_chunks.length > 0) {
156+
if (current_block_has_changes) {
157+
search_replace_blocks.push(
158+
new SearchBlock(search_chunks, replace_chunks, -1)
159+
)
160+
}
161+
}
162+
search_chunks = []
163+
replace_chunks = []
164+
inside_replace_block = false
165+
current_block_has_changes = false
166+
}
167+
152168
for (let i = 0; i < patch_lines_normalized.length; i++) {
153169
const line = patch_lines_normalized[i]
154170
const line_original = patch_lines_original[i]
155171

156172
if (line.startsWith('@@')) {
157-
if (search_chunks.length > 0 || replace_chunks.length > 0) {
158-
if (current_block_has_changes) {
159-
search_replace_blocks.push(
160-
new SearchBlock(search_chunks, replace_chunks, -1)
161-
)
162-
}
163-
}
164-
search_chunks = []
165-
replace_chunks = []
166-
inside_replace_block = false
167-
current_block_has_changes = false
173+
push_block()
174+
continue
168175
}
169176

170177
if (line.startsWith('-') || line.startsWith('~')) {
171178
if (inside_replace_block) {
172-
inside_replace_block = false
173-
174-
if (search_chunks.length > 0 || replace_chunks.length > 0) {
175-
if (current_block_has_changes) {
176-
search_replace_blocks.push(
177-
new SearchBlock(search_chunks, replace_chunks, -1)
178-
)
179-
}
180-
}
181-
182-
search_chunks = []
183-
replace_chunks = []
184-
current_block_has_changes = false
179+
push_block()
185180
}
186181

187182
if (line.startsWith('-')) {
@@ -227,64 +222,72 @@ export const apply_diff = (params: {
227222
}
228223
}
229224

230-
if (search_chunks.length > 0) {
231-
if (search_chunks[search_chunks.length - 1] == '~nnn') {
225+
if (search_chunks.length > 0 || replace_chunks.length > 0) {
226+
if (
227+
search_chunks[search_chunks.length - 1] === '~nnn' &&
228+
!inside_replace_block
229+
) {
232230
search_chunks.pop()
233231
replace_chunks.pop()
234232
}
235-
236-
if (search_chunks.length != 0 || replace_chunks.length != 0) {
237-
if (current_block_has_changes) {
238-
search_replace_blocks.push(
239-
new SearchBlock(search_chunks, replace_chunks, -1)
240-
)
241-
}
242-
}
233+
push_block()
243234
}
244235

245236
let previous_found_index = 0
246237
for (let i = 0; i < search_replace_blocks.length; i++) {
247-
const search_replace_block = search_replace_blocks[i]
248-
const search_string = search_replace_block.search_lines.join('')
238+
const block = search_replace_blocks[i]
239+
240+
if (block.search_lines.length === 0 && previous_found_index === 0) {
241+
block.search_block_start_index = -1
242+
continue
243+
}
249244

250245
let found = false
251246
for (
252247
let j = previous_found_index;
253248
j < original_code_lines_normalized.length;
254249
j++
255250
) {
256-
if (
257-
search_replace_block.search_lines.length == 0 &&
258-
previous_found_index == 0
251+
let search_ptr = 0
252+
let original_ptr = j
253+
const matched_indices: number[] = []
254+
const current_search_to_original = new Map<number, number>()
255+
256+
while (
257+
search_ptr < block.search_lines.length &&
258+
original_ptr < original_code_lines_normalized.length
259259
) {
260-
search_replace_block.search_block_start_index = -1
261-
found = true
262-
break
263-
} else {
264-
const chunk = original_code_lines_normalized.slice(
265-
j,
266-
j + search_replace_block.search_lines.length
267-
)
268-
269-
const chunk_string = chunk.map((line) => line.value).join('')
260+
const s_val = block.search_lines[search_ptr]
261+
const o_val = original_code_lines_normalized[original_ptr].value
270262

271-
if (chunk_string == search_string) {
272-
if (previous_found_index > chunk[0].key) {
273-
throw new Error('Found index is less than previous found index')
274-
}
275-
276-
search_replace_block.search_block_start_index = chunk[0].key
277-
found = true
278-
279-
previous_found_index =
280-
chunk[0].key + search_replace_block.search_lines.length
263+
if (s_val === o_val) {
264+
current_search_to_original.set(
265+
search_ptr,
266+
original_code_lines_normalized[original_ptr].key
267+
)
268+
matched_indices.push(original_code_lines_normalized[original_ptr].key)
269+
search_ptr++
270+
original_ptr++
271+
} else if (o_val === '~nnn') {
272+
matched_indices.push(original_code_lines_normalized[original_ptr].key)
273+
original_ptr++
274+
} else {
281275
break
282276
}
283277
}
278+
279+
if (search_ptr === block.search_lines.length) {
280+
block.search_block_start_index = matched_indices[0]
281+
block.actual_original_line_count = matched_indices.length
282+
block.search_to_original_map = current_search_to_original
283+
found = true
284+
previous_found_index = matched_indices[matched_indices.length - 1] + 1
285+
break
286+
}
284287
}
285288

286289
if (!found) {
287-
search_replace_block.search_block_start_index = -2
290+
block.search_block_start_index = -2
288291
}
289292
}
290293

@@ -297,37 +300,47 @@ export const apply_diff = (params: {
297300

298301
for (const block of valid_blocks) {
299302
const start_index =
300-
block.get_start_index() == -1 ? 0 : block.get_start_index()
301-
const search_count = block.get_search_count()
302-
const replacement_content = block.replace_lines.map((line) => {
303-
if (
304-
line.search_index !== null &&
305-
start_index + line.search_index < original_code_lines.length
306-
) {
307-
let originalContent =
308-
original_code_lines[start_index + line.search_index]
309-
if (!originalContent.endsWith('\n')) {
310-
originalContent += '\n'
303+
block.get_start_index() === -1 ? 0 : block.get_start_index()
304+
const replacement_content: string[] = []
305+
let last_original_idx = start_index - 1
306+
307+
for (const line of block.replace_lines) {
308+
if (line.search_index !== null) {
309+
const original_idx = block.search_to_original_map.get(line.search_index)
310+
if (original_idx !== undefined) {
311+
for (let skip = last_original_idx + 1; skip < original_idx; skip++) {
312+
if (original_code_lines_normalized[skip].value === '~nnn') {
313+
replacement_content.push(original_code_lines[skip])
314+
}
315+
}
316+
let content = original_code_lines[original_idx]
317+
if (
318+
!content.endsWith('\n') &&
319+
original_idx < original_code_lines.length - 1
320+
)
321+
content += '\n'
322+
replacement_content.push(content)
323+
last_original_idx = original_idx
311324
}
312-
return originalContent
325+
} else {
326+
replacement_content.push(line.content)
313327
}
314-
return line.content
315-
})
316-
317-
if (start_index < 0 || start_index > result_lines.length) {
318-
continue
319328
}
320329

321-
const actual_search_count = Math.min(
322-
search_count,
323-
result_lines.length - start_index
324-
)
330+
const end_original_idx = start_index + block.get_search_count() - 1
331+
for (let skip = last_original_idx + 1; skip <= end_original_idx; skip++) {
332+
if (original_code_lines_normalized[skip].value === '~nnn') {
333+
replacement_content.push(original_code_lines[skip])
334+
}
335+
}
325336

326-
result_lines.splice(
327-
start_index,
328-
actual_search_count,
329-
...replacement_content
330-
)
337+
if (start_index >= 0 && start_index <= result_lines.length) {
338+
result_lines.splice(
339+
start_index,
340+
block.get_search_count(),
341+
...replacement_content
342+
)
343+
}
331344
}
332345

333346
return result_lines.join('')
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
--- a/daemon.ts
2+
+++ b/daemon.ts
3+
@@ -7,7 +7,7 @@
4+
import FormData from 'form-data'
5+
const CONFIG = {
6+
API_URL: 'http://localhost:10008/api/v1',
7+
STITCHER_PATH: path.resolve(__dirname),
8+
- CHECK_INTERVAL: 60000 // 1 minute in milliseconds
9+
+ CHECK_INTERVAL: 120000 // 2 minutes in milliseconds
10+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import axios from 'axios'
2+
import { execSync } from 'child_process'
3+
import * as fs from 'fs'
4+
import * as path from 'path'
5+
import * as os from 'os'
6+
import FormData from 'form-data'
7+
8+
const CONFIG = {
9+
API_URL: 'http://localhost:10008/api/v1',
10+
STITCHER_PATH: path.resolve(__dirname),
11+
CHECK_INTERVAL: 120000 // 2 minutes in milliseconds
12+
}
13+
14+
interface UnstitchedImageResponse {
15+
tour_id: string
16+
scene_id: string
17+
images: string[]
18+
hugin_project?: string
19+
processing_started_at: string
20+
layer_name?: string
21+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import axios from 'axios'
2+
import { execSync } from 'child_process'
3+
import * as fs from 'fs'
4+
import * as path from 'path'
5+
import * as os from 'os'
6+
import FormData from 'form-data'
7+
8+
const CONFIG = {
9+
API_URL: 'http://localhost:10008/api/v1',
10+
STITCHER_PATH: path.resolve(__dirname),
11+
CHECK_INTERVAL: 60000 // 1 minute in milliseconds
12+
}
13+
14+
interface UnstitchedImageResponse {
15+
tour_id: string
16+
scene_id: string
17+
images: string[]
18+
hugin_project?: string
19+
processing_started_at: string
20+
layer_name?: string
21+
}

0 commit comments

Comments
 (0)