Skip to content

Commit 901ca38

Browse files
committed
fix:自动修正新加用例
1 parent e3293cc commit 901ca38

File tree

3 files changed

+296
-1
lines changed

3 files changed

+296
-1
lines changed

src/cvbManager.ts

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,30 @@ export class TCVB {
265265
// 移除##指令前的空格
266266
content = content.replace(/^(\s+)##/gm, '##');
267267

268+
// 处理CREATE操作后多余的NEW_CONTENT指令
269+
content = content.replace(
270+
/## OPERATION:CREATE\n(?:## NEW_CONTENT\n)?([\s\S]*?)(?=\n## |\n## END_TCVB|$)/gi,
271+
(match, codeSection) => {
272+
// 检测代码块是否被正确包裹
273+
const trimmed = codeSection.trim();
274+
const hasStart = trimmed.startsWith('```');
275+
const hasEnd = trimmed.endsWith('```');
276+
277+
let fixedCode = codeSection.trim();
278+
279+
// 确保代码块正确包裹
280+
if (!hasStart && !hasEnd) {
281+
fixedCode = `\`\`\`\n${fixedCode}\n\`\`\``;
282+
} else if (hasStart && !hasEnd) {
283+
fixedCode = `${codeSection}\n\`\`\``;
284+
} else if (!hasStart && hasEnd) {
285+
fixedCode = `\`\`\`\n${codeSection}`;
286+
}
287+
288+
return `## OPERATION:CREATE\n${fixedCode}`;
289+
}
290+
);
291+
268292
// 规则4/10:修复代码块包裹问题(精确处理需要代码块的操作)
269293
content = content.replace(
270294
/(## (?:OLD_CONTENT|NEW_CONTENT|OPERATION:CREATE)\n)([\s\S]*?)(?=\n## |\n## END_TCVB|$)/gis,
@@ -274,6 +298,8 @@ export class TCVB {
274298
const hasStart = trimmed.startsWith('```');
275299
const hasEnd = trimmed.endsWith('```');
276300

301+
directive = directive.trim();
302+
277303
// 情况1:完全未包裹的代码块
278304
if (!hasStart && !hasEnd) {
279305
return `${directive}\n\`\`\`\n${codeSection.trim()}\n\`\`\``;
@@ -310,7 +336,8 @@ export class TCVB {
310336

311337
if (!hasOldContent && hasNewContent) {
312338
const newContentMatch = match.match(/## NEW_CONTENT\n```([\s\S]*?)```/);
313-
const newContentCode = newContentMatch ? newContentMatch[1] : '';
339+
let newContentCode = newContentMatch ? newContentMatch[1] : '';
340+
newContentCode = newContentCode.trim();
314341
return `## OPERATION:CREATE\n\`\`\`\n${newContentCode}\n\`\`\``;
315342
} else if (hasOldContent && !hasNewContent) {
316343
return match + '\n## NEW_CONTENT\n```\n```';

src/test/fixapi.test.ts

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,110 @@ suite('MergeCvb Test Suite', () => {
3232

3333
assert.notStrictEqual(processedResult, processedOldCvb);
3434
});
35+
});
36+
37+
suite('TCVB AutoFix Test Suite', () => {
38+
// 测试用例1:END_TCVB标签缺失 + 代码块未闭合
39+
test('Case1: Missing END_TCVB + unclosed code', () => {
40+
const input = `
41+
## BEGIN_TCVB
42+
## FILE:test.txt
43+
## OPERATION:GLOBAL-REPLACE
44+
## OLD_CONTENT
45+
console.log('old')
46+
## NEW_CONTENT
47+
console.log('new')`;
48+
49+
const expected = `
50+
## BEGIN_TCVB
51+
## FILE:test.txt
52+
## OPERATION:GLOBAL-REPLACE
53+
## OLD_CONTENT
54+
\`\`\`
55+
console.log('old')
56+
\`\`\`
57+
## NEW_CONTENT
58+
\`\`\`
59+
console.log('new')
60+
\`\`\`
61+
## END_TCVB`.trim();
62+
63+
assert.strictEqual(TCVB.autoFixTCVBContent(input).trim(), expected);
64+
});
65+
66+
// 测试用例2:GLOBAL-REPLACE缺失OLD_CONTENT
67+
test('Case2: Incomplete GLOBAL-REPLACE', () => {
68+
const input = `
69+
## FILE:test.txt
70+
## OPERATION:GLOBAL-REPLACE
71+
## NEW_CONTENT
72+
console.log('new')`;
73+
74+
const expected = `
75+
## FILE:test.txt
76+
## OPERATION:CREATE
77+
\`\`\`
78+
console.log('new')
79+
\`\`\`
80+
## END_TCVB`.trim();
81+
82+
assert.strictEqual(TCVB.autoFixTCVBContent(input).trim(), expected);
83+
});
84+
85+
// 测试用例3:混合问题(指令缩进 + 代码块未闭合)
86+
test('Case3: Mixed issues', () => {
87+
const input = `
88+
## FILE:test.txt
89+
## OPERATION:CREATE
90+
## NEW_CONTENT
91+
function test() {`;
92+
93+
const expected = `
94+
## FILE:test.txt
95+
## OPERATION:CREATE
96+
\`\`\`
97+
function test() {
98+
\`\`\`
99+
## END_TCVB`.trim();
100+
101+
assert.strictEqual(TCVB.autoFixTCVBContent(input).trim(), expected);
102+
});
103+
104+
// 测试用例4:只有开始标记的代码块
105+
test('Case4: Start code block only', () => {
106+
const input = `
107+
## OPERATION:CREATE
108+
## NEW_CONTENT
109+
\`\`\`
110+
console.log('new')`;
111+
112+
const expected = `
113+
## OPERATION:CREATE
114+
\`\`\`
115+
console.log('new')
116+
\`\`\`
117+
## END_TCVB`.trim();
118+
119+
assert.strictEqual(TCVB.autoFixTCVBContent(input).trim(), expected);
120+
});
121+
122+
// 测试用例5:无效的闭合顺序
123+
test('Case5: Wrong close order', () => {
124+
const input = `
125+
## OPERATION:CREATE
126+
## NEW_CONTENT
127+
console.log('test')
128+
\`\`\`
129+
## FILE:test2.txt`;
130+
131+
const expected = `
132+
## OPERATION:CREATE
133+
\`\`\`
134+
console.log('test')
135+
\`\`\`
136+
## FILE:test2.txt
137+
## END_TCVB`.trim();
138+
139+
assert.strictEqual(TCVB.autoFixTCVBContent(input).trim(), expected);
140+
});
35141
});

testdata/testfix_input2.txt

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
����һ��������ԭ�������
2+
3+
1. �������ͣ�ê�������IJ�����
4+
- ԭ��������ԭê��δ�����㹻�������ĵ���ƥ��ʧ�ܣ�ʵ�ʴ�����demo.loadǰ�ж������
5+
- ������d:/lab/GPT-SoVITS_yefanFork/tools/subfix_webui.py
6+
- ����д����ê��δ����ǰ�����к�����������
7+
- ��ȷд����Ӧ����ǰ�����к�������������������
8+
9+
2. �������ͣ�������һ��
10+
- ԭ��������ԭ����ʹ��4���ո���������ê����ʹ�ò�һ�µ�����
11+
- ������d:/lab/GPT-SoVITS_yefanFork/tools/subfix_webui.py
12+
- ����д����������ƥ��ʵ�ʴ���
13+
- ��ȷд�����ϸ�ʹ��4�ո�����
14+
15+
3. �������ͣ�·����ʽ����
16+
- ԭ��������Windows·����б��δת��
17+
- ��������������
18+
- ����д����d:\lab\·��
19+
- ��ȷд����d:/lab/·�� �� ˫��б��
20+
21+
���ڶ�������С�Ķ�������
22+
23+
1. �ļ�1�޸ģ�
24+
- λ�ã�d:/lab/GPT-SoVITS_yefanFork/tools/subfix_webui.py
25+
- �޸����ݣ�
26+
- ��չê�㷶Χ����ǰ������
27+
- �ϸ񱣳�4�ո�����
28+
- ȷ��demo.load������������
29+
30+
2. �ļ�2�޸ģ�
31+
- λ�ã�d:/lab/GPT-SoVITS_yefanFork/GPT_SoVITS/inference_webui.py
32+
- �޸����ݣ�
33+
- ��ȷƥ��ԭ��Markdown�ṹ
34+
- ����ԭ�в���˳��
35+
- ȷ����ť����λ��׼ȷ
36+
37+
�������������������
38+
39+
```python
40+
## BEGIN_TCVB
41+
42+
## FILE:d:/lab/GPT-SoVITS_yefanFork/tools/subfix_webui.py
43+
## OPERATION:GLOBAL-REPLACE
44+
## OLD_CONTENT
45+
with gr.Row():
46+
batchsize_slider = gr.Slider(
47+
minimum=1, maximum=g_batch, value=g_batch, step=1, label="Batch Size", scale=3, interactive=False
48+
)
49+
interval_slider = gr.Slider(minimum=0, maximum=2, value=0, step=0.01, label="Interval", scale=3)
50+
btn_theme_dark = gr.Button("Light Theme", link="?__theme=light", scale=1)
51+
btn_theme_light = gr.Button("Dark Theme", link="?__theme=dark", scale=1)
52+
53+
demo.load(
54+
b_change_index,
55+
inputs=[
56+
index_slider,
57+
batchsize_slider,
58+
],
59+
outputs=[*g_text_list, *g_audio_list, *g_checkbox_list],
60+
)
61+
```
62+
## NEW_CONTENT
63+
with gr.Row():
64+
batchsize_slider = gr.Slider(
65+
minimum=1, maximum=g_batch, value=g_batch, step=1, label="Batch Size", scale=3, interactive=False
66+
)
67+
interval_slider = gr.Slider(minimum=0, maximum=2, value=0, step=0.01, label="Interval", scale=3)
68+
btn_theme_dark = gr.Button("Light Theme", link="?__theme=light", scale=1)
69+
btn_theme_light = gr.Button("Dark Theme", link="?__theme=dark", scale=1)
70+
btn_send_to_infer = gr.Button("Send to Inference", variant="primary", scale=1)
71+
72+
def b_send_to_inference(*checkbox_list):
73+
selected_data = []
74+
for i, checkbox in enumerate(checkbox_list):
75+
if checkbox and g_index + i < len(g_data_json):
76+
selected_data.append({
77+
"audio_path": g_data_json[g_index + i][g_json_key_path],
78+
"text": g_data_json[g_index + i][g_json_key_text].strip()
79+
})
80+
if selected_data:
81+
try:
82+
with open("shared_audio_ref.txt", "w", encoding="utf-8") as f:
83+
json.dump(selected_data[0], f)
84+
return gr.Info("Sent to inference page successfully!")
85+
except Exception as e:
86+
return gr.Warning(f"Failed to send: {str(e)}")
87+
return gr.Warning("No audio selected!")
88+
89+
btn_send_to_infer.click(
90+
b_send_to_inference,
91+
inputs=[*g_checkbox_list],
92+
outputs=[]
93+
)
94+
95+
demo.load(
96+
b_change_index,
97+
inputs=[
98+
index_slider,
99+
batchsize_slider,
100+
],
101+
outputs=[*g_text_list, *g_audio_list, *g_checkbox_list],
102+
)
103+
104+
## FILE:d:/lab/GPT-SoVITS_yefanFork/GPT_SoVITS/inference_webui.py
105+
## OPERATION:GLOBAL-REPLACE
106+
## OLD_CONTENT
107+
gr.Markdown(
108+
html_left(
109+
i18n("ʹ���޲ο��ı�ģʽʱ����ʹ��΢����GPT")
110+
+ "<br>"
111+
+ i18n("������ο���Ƶ˵��ɶ(������дɶ)���Կ���������������д�IJο��ı���")
112+
)
113+
)
114+
prompt_text = gr.Textbox(label=i18n("�ο���Ƶ���ı�"), value="", lines=5, max_lines=5, scale=1)
115+
```
116+
## NEW_CONTENT
117+
gr.Markdown(
118+
html_left(
119+
i18n("ʹ���޲ο��ı�ģʽʱ����ʹ��΢����GPT")
120+
+ "<br>"
121+
+ i18n("������ο���Ƶ˵��ɶ(������дɶ)���Կ���������������д�IJο��ı���")
122+
)
123+
)
124+
btn_load_ref = gr.Button(i18n("Load from Annotation"), variant="secondary", scale=1)
125+
prompt_text = gr.Textbox(label=i18n("�ο���Ƶ���ı�"), value="", lines=5, max_lines=5, scale=1)
126+
127+
def load_annotation_data():
128+
try:
129+
if os.path.exists("shared_audio_ref.txt"):
130+
with open("shared_audio_ref.txt", "r", encoding="utf-8") as f:
131+
data = json.load(f)
132+
return data["audio_path"], data["text"], gr.Info("Loaded from annotation!")
133+
return None, None, gr.Warning("No shared data found!")
134+
except Exception as e:
135+
return None, None, gr.Warning(f"Load failed: {str(e)}")
136+
137+
btn_load_ref.click(
138+
load_annotation_data,
139+
outputs=[inp_ref, prompt_text]
140+
)
141+
142+
## END_TCVB
143+
```
144+
145+
�����IJ����ܽ�˵����
146+
147+
1. ����������֤��
148+
- ê�㷶Χ����չ��������������
149+
- �����ϸ�ƥ��ԭ�ļ�(4�ո�)
150+
- ·����ʽͳһΪ��б��
151+
- ����������������
152+
153+
2. �޸�����ȷ�ϣ�
154+
- ��עҳ�棺������ť�������߼�
155+
- ����ҳ�棺�������ذ�ť�������߼�
156+
- �����ļ���������ʵ��
157+
158+
3. �����Ա�֤��
159+
- ���ı�ԭ�в������ݷ�ʽ
160+
- ���ƻ����й����߼�
161+
- ������������ԭ�д���һ��
162+

0 commit comments

Comments
 (0)