wcgw 1.1.2__tar.gz → 1.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of wcgw might be problematic. Click here for more details.
- {wcgw-1.1.2 → wcgw-1.2.1}/PKG-INFO +1 -1
- {wcgw-1.1.2 → wcgw-1.2.1}/gpt_action_json_schema.json +75 -7
- {wcgw-1.1.2 → wcgw-1.2.1}/gpt_instructions.txt +30 -34
- {wcgw-1.1.2 → wcgw-1.2.1}/pyproject.toml +1 -1
- {wcgw-1.1.2 → wcgw-1.2.1}/src/wcgw/client/anthropic_client.py +16 -7
- {wcgw-1.1.2 → wcgw-1.2.1}/src/wcgw/client/diff-instructions.txt +6 -15
- {wcgw-1.1.2 → wcgw-1.2.1}/src/wcgw/client/openai_client.py +28 -12
- {wcgw-1.1.2 → wcgw-1.2.1}/src/wcgw/client/tools.py +86 -36
- {wcgw-1.1.2 → wcgw-1.2.1}/src/wcgw/relay/serve.py +46 -8
- {wcgw-1.1.2 → wcgw-1.2.1}/src/wcgw/types_.py +16 -3
- {wcgw-1.1.2 → wcgw-1.2.1}/uv.lock +1 -1
- wcgw-1.1.2/config.toml +0 -11
- {wcgw-1.1.2 → wcgw-1.2.1}/.github/workflows/python-publish.yml +0 -0
- {wcgw-1.1.2 → wcgw-1.2.1}/.github/workflows/python-tests.yml +0 -0
- {wcgw-1.1.2 → wcgw-1.2.1}/.gitignore +0 -0
- {wcgw-1.1.2 → wcgw-1.2.1}/.python-version +0 -0
- {wcgw-1.1.2 → wcgw-1.2.1}/.vscode/settings.json +0 -0
- {wcgw-1.1.2 → wcgw-1.2.1}/README.md +0 -0
- {wcgw-1.1.2 → wcgw-1.2.1}/src/__init__.py +0 -0
- {wcgw-1.1.2 → wcgw-1.2.1}/src/wcgw/__init__.py +0 -0
- {wcgw-1.1.2 → wcgw-1.2.1}/src/wcgw/client/__init__.py +0 -0
- {wcgw-1.1.2 → wcgw-1.2.1}/src/wcgw/client/__main__.py +0 -0
- {wcgw-1.1.2 → wcgw-1.2.1}/src/wcgw/client/cli.py +0 -0
- {wcgw-1.1.2 → wcgw-1.2.1}/src/wcgw/client/common.py +0 -0
- {wcgw-1.1.2 → wcgw-1.2.1}/src/wcgw/client/openai_utils.py +0 -0
- {wcgw-1.1.2 → wcgw-1.2.1}/src/wcgw/relay/static/privacy.txt +0 -0
- {wcgw-1.1.2 → wcgw-1.2.1}/static/ss1.png +0 -0
- {wcgw-1.1.2 → wcgw-1.2.1}/tests/test_basic.py +0 -0
- {wcgw-1.1.2 → wcgw-1.2.1}/tests/test_tools.py +0 -0
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
},
|
|
7
7
|
"servers": [
|
|
8
8
|
{
|
|
9
|
-
"url": "https://
|
|
9
|
+
"url": "https://a0e8-125-99-67-222.ngrok-free.app"
|
|
10
10
|
}
|
|
11
11
|
],
|
|
12
12
|
"paths": {
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"content": {
|
|
60
60
|
"application/json": {
|
|
61
61
|
"schema": {
|
|
62
|
-
"$ref": "#/components/schemas/
|
|
62
|
+
"$ref": "#/components/schemas/FileEditWithUUID"
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
},
|
|
@@ -209,6 +209,46 @@
|
|
|
209
209
|
}
|
|
210
210
|
}
|
|
211
211
|
}
|
|
212
|
+
},
|
|
213
|
+
"/v1/read_file": {
|
|
214
|
+
"post": {
|
|
215
|
+
"x-openai-isConsequential": false,
|
|
216
|
+
"summary": "Read File Endpoint",
|
|
217
|
+
"operationId": "read_file_endpoint_v1_read_file_post",
|
|
218
|
+
"requestBody": {
|
|
219
|
+
"content": {
|
|
220
|
+
"application/json": {
|
|
221
|
+
"schema": {
|
|
222
|
+
"$ref": "#/components/schemas/ReadFileWithUUID"
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
},
|
|
226
|
+
"required": true
|
|
227
|
+
},
|
|
228
|
+
"responses": {
|
|
229
|
+
"200": {
|
|
230
|
+
"description": "Successful Response",
|
|
231
|
+
"content": {
|
|
232
|
+
"application/json": {
|
|
233
|
+
"schema": {
|
|
234
|
+
"type": "string",
|
|
235
|
+
"title": "Response Read File Endpoint V1 Read File Post"
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
},
|
|
240
|
+
"422": {
|
|
241
|
+
"description": "Validation Error",
|
|
242
|
+
"content": {
|
|
243
|
+
"application/json": {
|
|
244
|
+
"schema": {
|
|
245
|
+
"$ref": "#/components/schemas/HTTPValidationError"
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
212
252
|
}
|
|
213
253
|
},
|
|
214
254
|
"components": {
|
|
@@ -319,15 +359,15 @@
|
|
|
319
359
|
],
|
|
320
360
|
"title": "CreateFileNewWithUUID"
|
|
321
361
|
},
|
|
322
|
-
"
|
|
362
|
+
"FileEditWithUUID": {
|
|
323
363
|
"properties": {
|
|
324
364
|
"file_path": {
|
|
325
365
|
"type": "string",
|
|
326
366
|
"title": "File Path"
|
|
327
367
|
},
|
|
328
|
-
"
|
|
368
|
+
"file_edit_using_search_replace_blocks": {
|
|
329
369
|
"type": "string",
|
|
330
|
-
"title": "File Edit Using
|
|
370
|
+
"title": "File Edit Using Search Replace Blocks"
|
|
331
371
|
},
|
|
332
372
|
"user_id": {
|
|
333
373
|
"type": "string",
|
|
@@ -338,10 +378,10 @@
|
|
|
338
378
|
"type": "object",
|
|
339
379
|
"required": [
|
|
340
380
|
"file_path",
|
|
341
|
-
"
|
|
381
|
+
"file_edit_using_search_replace_blocks",
|
|
342
382
|
"user_id"
|
|
343
383
|
],
|
|
344
|
-
"title": "
|
|
384
|
+
"title": "FileEditWithUUID"
|
|
345
385
|
},
|
|
346
386
|
"HTTPValidationError": {
|
|
347
387
|
"properties": {
|
|
@@ -356,6 +396,34 @@
|
|
|
356
396
|
"type": "object",
|
|
357
397
|
"title": "HTTPValidationError"
|
|
358
398
|
},
|
|
399
|
+
"ReadFileWithUUID": {
|
|
400
|
+
"properties": {
|
|
401
|
+
"file_path": {
|
|
402
|
+
"type": "string",
|
|
403
|
+
"title": "File Path"
|
|
404
|
+
},
|
|
405
|
+
"type": {
|
|
406
|
+
"type": "string",
|
|
407
|
+
"enum": [
|
|
408
|
+
"ReadFile"
|
|
409
|
+
],
|
|
410
|
+
"const": "ReadFile",
|
|
411
|
+
"title": "Type"
|
|
412
|
+
},
|
|
413
|
+
"user_id": {
|
|
414
|
+
"type": "string",
|
|
415
|
+
"format": "uuid",
|
|
416
|
+
"title": "User Id"
|
|
417
|
+
}
|
|
418
|
+
},
|
|
419
|
+
"type": "object",
|
|
420
|
+
"required": [
|
|
421
|
+
"file_path",
|
|
422
|
+
"type",
|
|
423
|
+
"user_id"
|
|
424
|
+
],
|
|
425
|
+
"title": "ReadFileWithUUID"
|
|
426
|
+
},
|
|
359
427
|
"ResetShellWithUUID": {
|
|
360
428
|
"properties": {
|
|
361
429
|
"should_reset": {
|
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
You're
|
|
1
|
+
You're an expert software engineer with shell and code knowledge.
|
|
2
2
|
|
|
3
3
|
Instructions:
|
|
4
4
|
|
|
5
|
-
- You should use the provided bash execution
|
|
6
|
-
-
|
|
7
|
-
-
|
|
5
|
+
- You should use the provided bash execution, reading and writing file tools to complete objective.
|
|
6
|
+
- First understand about the project by getting the folder structure (ignoring .git, node_modules, venv, etc.)
|
|
7
|
+
- Always read relevant files before editing.
|
|
8
|
+
- Do not provide code snippets unless asked by the user, instead directly edit the code.
|
|
8
9
|
|
|
9
10
|
|
|
10
|
-
To execute bash commands OR write files use the provided api.
|
|
11
|
-
|
|
12
11
|
Instructions for `BashCommand`:
|
|
13
12
|
- Execute a bash command. This is stateful (beware with subsequent calls).
|
|
14
13
|
- Do not use interactive commands like nano. Prefer writing simpler commands.
|
|
@@ -16,57 +15,53 @@ Instructions for `BashCommand`:
|
|
|
16
15
|
- Optionally `exit shell has restarted` is the output, in which case environment resets, you can run fresh commands.
|
|
17
16
|
- The first line might be `(...truncated)` if the output is too long.
|
|
18
17
|
|
|
18
|
+
Instructions for `Read File`
|
|
19
|
+
- Read full content of a file.
|
|
20
|
+
- Provide absolute file path only.
|
|
21
|
+
|
|
19
22
|
Instructions for `Create File New`
|
|
20
23
|
- Write content to a new file. Provide file path and content. Use this instead of BashCommand for writing new files.
|
|
21
24
|
- This doesn't create any directories, please create directories using `mkdir -p` BashCommand.
|
|
22
25
|
- Provide absolute file path only.
|
|
23
|
-
- For editing existing files, use
|
|
26
|
+
- For editing existing files, use FileEdit.
|
|
24
27
|
|
|
25
28
|
Instructions for `BashInteraction`
|
|
26
29
|
- Interact with running program using this tool
|
|
27
30
|
- Special keys like arrows, interrupts, enter, etc.
|
|
28
31
|
- Send text input to the running program.
|
|
32
|
+
- Send send_specials=["Enter"] to recheck status of a running program.
|
|
29
33
|
- Only one of send_text, send_specials, send_ascii should be provided.
|
|
30
34
|
|
|
31
35
|
Instructions for `ResetShell`
|
|
32
36
|
- Resets the shell. Use only if all interrupts and prompt reset attempts have failed repeatedly.
|
|
33
37
|
|
|
34
|
-
Instructions for `
|
|
38
|
+
Instructions for `FileEdit`:
|
|
35
39
|
- Use absolute file path only.
|
|
36
40
|
- Use SEARCH/REPLACE blocks to edit the file.
|
|
37
41
|
Only edit the files using the following SEARCH/REPLACE blocks.
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
print("hello")
|
|
52
|
-
=======
|
|
53
|
-
from hello import hello
|
|
54
|
-
>>>>>>> REPLACE
|
|
55
|
-
```
|
|
42
|
+
```
|
|
43
|
+
<<<<<<< SEARCH
|
|
44
|
+
// Original code
|
|
45
|
+
=======
|
|
46
|
+
// New code
|
|
47
|
+
>>>>>>> REPLACE
|
|
48
|
+
<<<<<<< SEARCH
|
|
49
|
+
// Original code further down in the file
|
|
50
|
+
=======
|
|
51
|
+
// New code to replace
|
|
52
|
+
>>>>>>> REPLACE
|
|
53
|
+
```
|
|
56
54
|
|
|
57
55
|
# *SEARCH/REPLACE block* Rules:
|
|
58
56
|
|
|
59
57
|
Every *SEARCH/REPLACE block* must use this format:
|
|
60
|
-
1. The start of
|
|
61
|
-
2. A contiguous chunk of lines to
|
|
58
|
+
1. The start of match block: <<<<<<< SEARCH
|
|
59
|
+
2. A contiguous chunk of lines to do exact match for in the existing source code
|
|
62
60
|
3. The dividing line: =======
|
|
63
61
|
4. The lines to replace into the source code
|
|
64
62
|
5. The end of the replace block: >>>>>>> REPLACE
|
|
65
63
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
Every *SEARCH* section must *EXACTLY MATCH* the existing file content, character for character, including all comments, docstrings, etc.
|
|
69
|
-
If the file contains code or other data wrapped/escaped in json/xml/quotes or other containers, you need to propose edits to the literal contents of the file, including the container markup.
|
|
64
|
+
Every "<<<<<<< SEARCH" section must *EXACTLY MATCH* the existing file content, character for character, including all comments, docstrings, etc.
|
|
70
65
|
|
|
71
66
|
*SEARCH/REPLACE* blocks will *only* replace the first match occurrence.
|
|
72
67
|
Including multiple unique *SEARCH/REPLACE* blocks if needed.
|
|
@@ -77,10 +72,11 @@ Instructions for `FullFileEdit`:
|
|
|
77
72
|
Include just the changing lines, and a few surrounding lines if needed for uniqueness.
|
|
78
73
|
Do not include long runs of unchanging lines in *SEARCH/REPLACE* blocks.
|
|
79
74
|
|
|
75
|
+
Include context lines before and after the code to edit for better matching in "<<<<<<< SEARCH" and ">>>>>>> REPLACE". Recommended to add 3 lines on each side.
|
|
76
|
+
|
|
80
77
|
---
|
|
81
78
|
Always run `pwd` if you get any file or directory not found error to make sure you're not lost, or to get absolute cwd.
|
|
82
79
|
|
|
83
|
-
Always
|
|
84
|
-
|
|
80
|
+
Always write production ready, syntactically correct code.
|
|
85
81
|
---
|
|
86
82
|
Ask the user for the user_id `UUID` if they haven't provided in the first message.
|
|
@@ -26,7 +26,8 @@ from ..types_ import (
|
|
|
26
26
|
BashInteraction,
|
|
27
27
|
CreateFileNew,
|
|
28
28
|
FileEditFindReplace,
|
|
29
|
-
|
|
29
|
+
FileEdit,
|
|
30
|
+
ReadFile,
|
|
30
31
|
ReadImage,
|
|
31
32
|
Writefile,
|
|
32
33
|
ResetShell,
|
|
@@ -175,6 +176,14 @@ def loop(
|
|
|
175
176
|
- Send text input to the running program.
|
|
176
177
|
- Send send_specials=["Enter"] to recheck status of a running program.
|
|
177
178
|
- Only one of send_text, send_specials, send_ascii should be provided.
|
|
179
|
+
""",
|
|
180
|
+
),
|
|
181
|
+
ToolParam(
|
|
182
|
+
input_schema=ReadFile.model_json_schema(),
|
|
183
|
+
name="ReadFile",
|
|
184
|
+
description="""
|
|
185
|
+
- Read full file content
|
|
186
|
+
- Provide absolute file path only
|
|
178
187
|
""",
|
|
179
188
|
),
|
|
180
189
|
ToolParam(
|
|
@@ -184,7 +193,7 @@ def loop(
|
|
|
184
193
|
- Write content to a new file. Provide file path and content. Use this instead of BashCommand for writing new files.
|
|
185
194
|
- This doesn't create any directories, please create directories using `mkdir -p` BashCommand.
|
|
186
195
|
- Provide absolute file path only.
|
|
187
|
-
- For editing existing files, use
|
|
196
|
+
- For editing existing files, use FileEdit.
|
|
188
197
|
""",
|
|
189
198
|
),
|
|
190
199
|
ToolParam(
|
|
@@ -198,8 +207,8 @@ def loop(
|
|
|
198
207
|
description="Resets the shell. Use only if all interrupts and prompt reset attempts have failed repeatedly.",
|
|
199
208
|
),
|
|
200
209
|
ToolParam(
|
|
201
|
-
input_schema=
|
|
202
|
-
name="
|
|
210
|
+
input_schema=FileEdit.model_json_schema(),
|
|
211
|
+
name="FileEdit",
|
|
203
212
|
description="""
|
|
204
213
|
- Use absolute file path only.
|
|
205
214
|
- Use SEARCH/REPLACE blocks to edit the file.
|
|
@@ -214,9 +223,9 @@ You're a cli assistant.
|
|
|
214
223
|
|
|
215
224
|
Instructions:
|
|
216
225
|
|
|
217
|
-
- You should use the provided bash execution tool to run script to complete objective.
|
|
218
|
-
-
|
|
219
|
-
-
|
|
226
|
+
- You should use the provided bash execution tool to run script to complete objective.
|
|
227
|
+
- First understand about the project by understanding the folder structure (ignoring node_modules or venv, etc.)
|
|
228
|
+
- Always read relevant files before making any changes.
|
|
220
229
|
|
|
221
230
|
System information:
|
|
222
231
|
- System: {uname_sysname}
|
|
@@ -2,14 +2,6 @@
|
|
|
2
2
|
Instructions for
|
|
3
3
|
Only edit the files using the following SEARCH/REPLACE blocks.
|
|
4
4
|
```
|
|
5
|
-
<<<<<<< SEARCH
|
|
6
|
-
=======
|
|
7
|
-
def hello():
|
|
8
|
-
"print a greeting"
|
|
9
|
-
|
|
10
|
-
print("hello")
|
|
11
|
-
>>>>>>> REPLACE
|
|
12
|
-
|
|
13
5
|
<<<<<<< SEARCH
|
|
14
6
|
def hello():
|
|
15
7
|
"print a greeting"
|
|
@@ -23,16 +15,13 @@ from hello import hello
|
|
|
23
15
|
# *SEARCH/REPLACE block* Rules:
|
|
24
16
|
|
|
25
17
|
Every *SEARCH/REPLACE block* must use this format:
|
|
26
|
-
1. The start of
|
|
27
|
-
2. A contiguous chunk of lines to
|
|
18
|
+
1. The start of match block: <<<<<<< SEARCH
|
|
19
|
+
2. A contiguous chunk of lines to do exact match for in the existing source code
|
|
28
20
|
3. The dividing line: =======
|
|
29
21
|
4. The lines to replace into the source code
|
|
30
22
|
5. The end of the replace block: >>>>>>> REPLACE
|
|
31
23
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
Every *SEARCH* section must *EXACTLY MATCH* the existing file content, character for character, including all comments, docstrings, etc.
|
|
35
|
-
If the file contains code or other data wrapped/escaped in json/xml/quotes or other containers, you need to propose edits to the literal contents of the file, including the container markup.
|
|
24
|
+
Every "<<<<<<< SEARCH" section must *EXACTLY MATCH* the existing file content, character for character, including all comments, docstrings, etc.
|
|
36
25
|
|
|
37
26
|
*SEARCH/REPLACE* blocks will *only* replace the first match occurrence.
|
|
38
27
|
Including multiple unique *SEARCH/REPLACE* blocks if needed.
|
|
@@ -41,4 +30,6 @@ Include enough lines in each SEARCH section to uniquely match each set of lines
|
|
|
41
30
|
Keep *SEARCH/REPLACE* blocks concise.
|
|
42
31
|
Break large *SEARCH/REPLACE* blocks into a series of smaller blocks that each change a small portion of the file.
|
|
43
32
|
Include just the changing lines, and a few surrounding lines if needed for uniqueness.
|
|
44
|
-
Do not include long runs of unchanging lines in *SEARCH/REPLACE* blocks.
|
|
33
|
+
Do not include long runs of unchanging lines in *SEARCH/REPLACE* blocks.
|
|
34
|
+
|
|
35
|
+
Include context lines before and after the code to edit for better matching in "<<<<<<< SEARCH". Recommended to add 3 lines on each side.
|
|
@@ -24,8 +24,9 @@ from ..types_ import (
|
|
|
24
24
|
BashCommand,
|
|
25
25
|
BashInteraction,
|
|
26
26
|
CreateFileNew,
|
|
27
|
-
|
|
27
|
+
FileEdit,
|
|
28
28
|
ReadImage,
|
|
29
|
+
ReadFile,
|
|
29
30
|
Writefile,
|
|
30
31
|
ResetShell,
|
|
31
32
|
)
|
|
@@ -58,7 +59,6 @@ from dotenv import load_dotenv
|
|
|
58
59
|
|
|
59
60
|
class Config(BaseModel):
|
|
60
61
|
model: Models
|
|
61
|
-
secondary_model: Models
|
|
62
62
|
cost_limit: float
|
|
63
63
|
cost_file: dict[Models, CostData]
|
|
64
64
|
cost_unit: str = "$"
|
|
@@ -146,10 +146,18 @@ def loop(
|
|
|
146
146
|
waiting_for_assistant = history[-1]["role"] != "assistant"
|
|
147
147
|
|
|
148
148
|
my_dir = os.path.dirname(__file__)
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
149
|
+
|
|
150
|
+
config = Config(
|
|
151
|
+
model=cast(
|
|
152
|
+
Models, os.getenv("OPENAI_MODEL", "gpt-4o-2024-08-06").lower()),
|
|
153
|
+
cost_limit=0.1,
|
|
154
|
+
cost_unit="$",
|
|
155
|
+
cost_file={
|
|
156
|
+
"gpt-4o-2024-08-06": CostData(
|
|
157
|
+
cost_per_1m_input_tokens=5, cost_per_1m_output_tokens=15
|
|
158
|
+
),
|
|
159
|
+
},
|
|
160
|
+
)
|
|
153
161
|
|
|
154
162
|
if limit is not None:
|
|
155
163
|
config.cost_limit = limit
|
|
@@ -177,7 +185,15 @@ def loop(
|
|
|
177
185
|
- Interact with running program using this tool
|
|
178
186
|
- Special keys like arrows, interrupts, enter, etc.
|
|
179
187
|
- Send text input to the running program.
|
|
188
|
+
- Send send_specials=["Enter"] to recheck status of a running program.
|
|
180
189
|
- Only one of send_text, send_specials, send_ascii should be provided.""",
|
|
190
|
+
),
|
|
191
|
+
openai.pydantic_function_tool(
|
|
192
|
+
ReadFile,
|
|
193
|
+
description="""
|
|
194
|
+
- Read full file content
|
|
195
|
+
- Provide absolute file path only
|
|
196
|
+
""",
|
|
181
197
|
),
|
|
182
198
|
openai.pydantic_function_tool(
|
|
183
199
|
CreateFileNew,
|
|
@@ -185,14 +201,14 @@ def loop(
|
|
|
185
201
|
- Write content to a new file. Provide file path and content. Use this instead of BashCommand for writing new files.
|
|
186
202
|
- This doesn't create any directories, please create directories using `mkdir -p` BashCommand.
|
|
187
203
|
- Provide absolute file path only.
|
|
188
|
-
- For editing existing files, use
|
|
204
|
+
- For editing existing files, use FileEdit.""",
|
|
189
205
|
),
|
|
190
206
|
openai.pydantic_function_tool(
|
|
191
|
-
|
|
207
|
+
FileEdit,
|
|
192
208
|
description="""
|
|
193
209
|
- Use absolute file path only.
|
|
194
210
|
- Use ONLY SEARCH/REPLACE blocks to edit the file.
|
|
195
|
-
-
|
|
211
|
+
- file_edit_using_search_replace_blocks should start with <<<<<<< SEARCH
|
|
196
212
|
""",
|
|
197
213
|
),
|
|
198
214
|
openai.pydantic_function_tool(
|
|
@@ -211,9 +227,9 @@ You're a cli assistant.
|
|
|
211
227
|
|
|
212
228
|
Instructions:
|
|
213
229
|
|
|
214
|
-
- You should use the provided bash execution tool to run script to complete objective.
|
|
215
|
-
-
|
|
216
|
-
-
|
|
230
|
+
- You should use the provided bash execution tool to run script to complete objective.
|
|
231
|
+
- First understand about the project by understanding the folder structure (ignoring node_modules or venv, etc.)
|
|
232
|
+
- Always read relevant files before making any changes.
|
|
217
233
|
|
|
218
234
|
System information:
|
|
219
235
|
- System: {uname_sysname}
|
|
@@ -48,19 +48,17 @@ from openai.types.chat import (
|
|
|
48
48
|
from nltk.metrics.distance import edit_distance
|
|
49
49
|
|
|
50
50
|
from ..types_ import (
|
|
51
|
+
BashCommand,
|
|
52
|
+
BashInteraction,
|
|
51
53
|
CreateFileNew,
|
|
52
54
|
FileEditFindReplace,
|
|
53
|
-
|
|
55
|
+
FileEdit,
|
|
56
|
+
ReadFile,
|
|
57
|
+
ReadImage,
|
|
54
58
|
ResetShell,
|
|
55
59
|
Writefile,
|
|
56
60
|
)
|
|
57
61
|
|
|
58
|
-
from ..types_ import BashCommand
|
|
59
|
-
|
|
60
|
-
from ..types_ import BashInteraction
|
|
61
|
-
|
|
62
|
-
from ..types_ import ReadImage
|
|
63
|
-
|
|
64
62
|
from .common import CostData, Models, discard_input
|
|
65
63
|
|
|
66
64
|
from .openai_utils import get_input_cost, get_output_cost
|
|
@@ -320,7 +318,7 @@ def execute_bash(
|
|
|
320
318
|
tokens = enc.encode(text)
|
|
321
319
|
|
|
322
320
|
if max_tokens and len(tokens) >= max_tokens:
|
|
323
|
-
text = "...(truncated)\n" + enc.decode(tokens[-(max_tokens - 1)
|
|
321
|
+
text = "...(truncated)\n" + enc.decode(tokens[-(max_tokens - 1):])
|
|
324
322
|
|
|
325
323
|
if is_interrupt:
|
|
326
324
|
text = (
|
|
@@ -347,7 +345,7 @@ Otherwise, you may want to try Ctrl-c again or program specific exit interactive
|
|
|
347
345
|
|
|
348
346
|
tokens = enc.encode(output)
|
|
349
347
|
if max_tokens and len(tokens) >= max_tokens:
|
|
350
|
-
output = "...(truncated)\n" + enc.decode(tokens[-(max_tokens - 1)
|
|
348
|
+
output = "...(truncated)\n" + enc.decode(tokens[-(max_tokens - 1):])
|
|
351
349
|
|
|
352
350
|
try:
|
|
353
351
|
exit_status = get_status()
|
|
@@ -427,7 +425,7 @@ def read_image_from_shell(file_path: str) -> ImageData:
|
|
|
427
425
|
|
|
428
426
|
def write_file(writefile: Writefile | CreateFileNew, error_on_exist: bool) -> str:
|
|
429
427
|
if not os.path.isabs(writefile.file_path):
|
|
430
|
-
return "Failure: file_path should be absolute path"
|
|
428
|
+
return f"Failure: file_path should be absolute path, current working directory is {CWD}"
|
|
431
429
|
else:
|
|
432
430
|
path_ = writefile.file_path
|
|
433
431
|
|
|
@@ -455,6 +453,14 @@ def find_least_edit_distance_substring(
|
|
|
455
453
|
content_lines = [
|
|
456
454
|
line.strip() for line in orig_content_lines
|
|
457
455
|
] # Remove trailing and leading space for calculating edit distance
|
|
456
|
+
new_to_original_indices = {}
|
|
457
|
+
new_content_lines = []
|
|
458
|
+
for i in range(len(content_lines)):
|
|
459
|
+
if not content_lines[i]:
|
|
460
|
+
continue
|
|
461
|
+
new_content_lines.append(content_lines[i])
|
|
462
|
+
new_to_original_indices[len(new_content_lines) - 1] = i
|
|
463
|
+
content_lines = new_content_lines
|
|
458
464
|
find_lines = find_str.split("\n")
|
|
459
465
|
find_lines = [
|
|
460
466
|
line.strip() for line in find_lines
|
|
@@ -466,12 +472,15 @@ def find_least_edit_distance_substring(
|
|
|
466
472
|
edit_distance_sum = 0
|
|
467
473
|
for j in range(len(find_lines)):
|
|
468
474
|
if (i + j) < len(content_lines):
|
|
469
|
-
edit_distance_sum += edit_distance(
|
|
475
|
+
edit_distance_sum += edit_distance(
|
|
476
|
+
content_lines[i + j], find_lines[j])
|
|
470
477
|
else:
|
|
471
478
|
edit_distance_sum += len(find_lines[j])
|
|
472
479
|
if edit_distance_sum < min_edit_distance:
|
|
473
480
|
min_edit_distance = edit_distance_sum
|
|
474
|
-
|
|
481
|
+
orig_start_index = new_to_original_indices[i]
|
|
482
|
+
orig_end_index = new_to_original_indices.get(i + len(find_lines) - 1, len(orig_content_lines) - 1) + 1
|
|
483
|
+
min_edit_distance_lines = orig_content_lines[orig_start_index:orig_end_index]
|
|
475
484
|
return "\n".join(min_edit_distance_lines), min_edit_distance
|
|
476
485
|
|
|
477
486
|
|
|
@@ -481,12 +490,12 @@ def edit_content(content: str, find_lines: str, replace_with_lines: str) -> str:
|
|
|
481
490
|
closest_match, min_edit_distance = find_least_edit_distance_substring(
|
|
482
491
|
content, find_lines
|
|
483
492
|
)
|
|
484
|
-
|
|
485
|
-
f"Exact match not found, found with whitespace removed edit distance: {min_edit_distance}"
|
|
486
|
-
)
|
|
487
|
-
if min_edit_distance / len(find_lines) < 1 / 100:
|
|
488
|
-
print("Editing file with closest match")
|
|
493
|
+
if min_edit_distance == 0:
|
|
489
494
|
return edit_content(content, closest_match, replace_with_lines)
|
|
495
|
+
else:
|
|
496
|
+
print(
|
|
497
|
+
f"Exact match not found, found with whitespace removed edit distance: {min_edit_distance}"
|
|
498
|
+
)
|
|
490
499
|
raise Exception(
|
|
491
500
|
f"Error: no match found for the provided `find_lines` in the file. Closest match:\n---\n{closest_match}\n---\nFile not edited"
|
|
492
501
|
)
|
|
@@ -495,11 +504,12 @@ def edit_content(content: str, find_lines: str, replace_with_lines: str) -> str:
|
|
|
495
504
|
return content
|
|
496
505
|
|
|
497
506
|
|
|
498
|
-
def do_diff_edit(fedit:
|
|
507
|
+
def do_diff_edit(fedit: FileEdit) -> str:
|
|
499
508
|
console.log(f"Editing file: {fedit.file_path}")
|
|
500
509
|
|
|
501
510
|
if not os.path.isabs(fedit.file_path):
|
|
502
|
-
raise Exception(
|
|
511
|
+
raise Exception(
|
|
512
|
+
f"Failure: file_path should be absolute path, current working directory is {CWD}")
|
|
503
513
|
else:
|
|
504
514
|
path_ = fedit.file_path
|
|
505
515
|
|
|
@@ -509,9 +519,10 @@ def do_diff_edit(fedit: FullFileEdit) -> str:
|
|
|
509
519
|
with open(path_) as f:
|
|
510
520
|
apply_diff_to = f.read()
|
|
511
521
|
|
|
512
|
-
lines = fedit.
|
|
522
|
+
lines = fedit.file_edit_using_search_replace_blocks.split("\n")
|
|
513
523
|
n_lines = len(lines)
|
|
514
524
|
i = 0
|
|
525
|
+
replacement_count = 0
|
|
515
526
|
while i < n_lines:
|
|
516
527
|
if re.match(r"^<<<<<<+\s*SEARCH\s*$", lines[i]):
|
|
517
528
|
search_block = []
|
|
@@ -535,10 +546,17 @@ def do_diff_edit(fedit: FullFileEdit) -> str:
|
|
|
535
546
|
search_block_ = "\n".join(search_block)
|
|
536
547
|
replace_block_ = "\n".join(replace_block)
|
|
537
548
|
|
|
538
|
-
apply_diff_to = edit_content(
|
|
549
|
+
apply_diff_to = edit_content(
|
|
550
|
+
apply_diff_to, search_block_, replace_block_)
|
|
551
|
+
replacement_count += 1
|
|
539
552
|
else:
|
|
540
553
|
i += 1
|
|
541
554
|
|
|
555
|
+
if replacement_count == 0:
|
|
556
|
+
raise Exception(
|
|
557
|
+
"Error: no valid search-replace blocks found, please check your syntax for FileEdit"
|
|
558
|
+
)
|
|
559
|
+
|
|
542
560
|
with open(path_, "w") as f:
|
|
543
561
|
f.write(apply_diff_to)
|
|
544
562
|
|
|
@@ -547,7 +565,8 @@ def do_diff_edit(fedit: FullFileEdit) -> str:
|
|
|
547
565
|
|
|
548
566
|
def file_edit(fedit: FileEditFindReplace) -> str:
|
|
549
567
|
if not os.path.isabs(fedit.file_path):
|
|
550
|
-
raise Exception(
|
|
568
|
+
raise Exception(
|
|
569
|
+
f"Failure: file_path should be absolute path, current working directory is {CWD}")
|
|
551
570
|
else:
|
|
552
571
|
path_ = fedit.file_path
|
|
553
572
|
|
|
@@ -557,14 +576,17 @@ def file_edit(fedit: FileEditFindReplace) -> str:
|
|
|
557
576
|
if not fedit.find_lines:
|
|
558
577
|
raise Exception("Error: `find_lines` cannot be empty")
|
|
559
578
|
|
|
560
|
-
out_string = "\n".join(
|
|
561
|
-
|
|
579
|
+
out_string = "\n".join(
|
|
580
|
+
"> " + line for line in fedit.find_lines.split("\n"))
|
|
581
|
+
in_string = "\n".join(
|
|
582
|
+
"< " + line for line in fedit.replace_with_lines.split("\n"))
|
|
562
583
|
console.log(f"Editing file: {path_}\n---\n{out_string}\n---\n{in_string}\n---")
|
|
563
584
|
try:
|
|
564
585
|
with open(path_) as f:
|
|
565
586
|
content = f.read()
|
|
566
587
|
|
|
567
|
-
content = edit_content(content, fedit.find_lines,
|
|
588
|
+
content = edit_content(content, fedit.find_lines,
|
|
589
|
+
fedit.replace_with_lines)
|
|
568
590
|
|
|
569
591
|
with open(path_, "w") as f:
|
|
570
592
|
f.write(content)
|
|
@@ -604,10 +626,11 @@ TOOLS = (
|
|
|
604
626
|
| Writefile
|
|
605
627
|
| CreateFileNew
|
|
606
628
|
| FileEditFindReplace
|
|
607
|
-
|
|
|
629
|
+
| FileEdit
|
|
608
630
|
| AIAssistant
|
|
609
631
|
| DoneFlag
|
|
610
632
|
| ReadImage
|
|
633
|
+
| ReadFile
|
|
611
634
|
)
|
|
612
635
|
|
|
613
636
|
|
|
@@ -631,14 +654,16 @@ def which_tool_name(name: str) -> Type[TOOLS]:
|
|
|
631
654
|
return CreateFileNew
|
|
632
655
|
elif name == "FileEditFindReplace":
|
|
633
656
|
return FileEditFindReplace
|
|
634
|
-
elif name == "
|
|
635
|
-
return
|
|
657
|
+
elif name == "FileEdit":
|
|
658
|
+
return FileEdit
|
|
636
659
|
elif name == "AIAssistant":
|
|
637
660
|
return AIAssistant
|
|
638
661
|
elif name == "DoneFlag":
|
|
639
662
|
return DoneFlag
|
|
640
663
|
elif name == "ReadImage":
|
|
641
664
|
return ReadImage
|
|
665
|
+
elif name == "ReadFile":
|
|
666
|
+
return ReadFile
|
|
642
667
|
else:
|
|
643
668
|
raise ValueError(f"Unknown tool name: {name}")
|
|
644
669
|
|
|
@@ -652,10 +677,11 @@ def get_tool_output(
|
|
|
652
677
|
| Writefile
|
|
653
678
|
| CreateFileNew
|
|
654
679
|
| FileEditFindReplace
|
|
655
|
-
|
|
|
680
|
+
| FileEdit
|
|
656
681
|
| AIAssistant
|
|
657
682
|
| DoneFlag
|
|
658
|
-
| ReadImage
|
|
683
|
+
| ReadImage
|
|
684
|
+
| ReadFile,
|
|
659
685
|
enc: tiktoken.Encoding,
|
|
660
686
|
limit: float,
|
|
661
687
|
loop_call: Callable[[str, float], tuple[str, float]],
|
|
@@ -670,10 +696,11 @@ def get_tool_output(
|
|
|
670
696
|
| Writefile
|
|
671
697
|
| CreateFileNew
|
|
672
698
|
| FileEditFindReplace
|
|
673
|
-
|
|
|
699
|
+
| FileEdit
|
|
674
700
|
| AIAssistant
|
|
675
701
|
| DoneFlag
|
|
676
702
|
| ReadImage
|
|
703
|
+
| ReadFile
|
|
677
704
|
](
|
|
678
705
|
Confirmation
|
|
679
706
|
| BashCommand
|
|
@@ -682,10 +709,11 @@ def get_tool_output(
|
|
|
682
709
|
| Writefile
|
|
683
710
|
| CreateFileNew
|
|
684
711
|
| FileEditFindReplace
|
|
685
|
-
|
|
|
712
|
+
| FileEdit
|
|
686
713
|
| AIAssistant
|
|
687
714
|
| DoneFlag
|
|
688
715
|
| ReadImage
|
|
716
|
+
| ReadFile
|
|
689
717
|
)
|
|
690
718
|
arg = adapter.validate_python(args)
|
|
691
719
|
else:
|
|
@@ -706,7 +734,7 @@ def get_tool_output(
|
|
|
706
734
|
elif isinstance(arg, FileEditFindReplace):
|
|
707
735
|
console.print("Calling file edit tool")
|
|
708
736
|
output = file_edit(arg), 0.0
|
|
709
|
-
elif isinstance(arg,
|
|
737
|
+
elif isinstance(arg, FileEdit):
|
|
710
738
|
console.print("Calling full file edit tool")
|
|
711
739
|
output = do_diff_edit(arg), 0.0
|
|
712
740
|
elif isinstance(arg, DoneFlag):
|
|
@@ -718,6 +746,9 @@ def get_tool_output(
|
|
|
718
746
|
elif isinstance(arg, ReadImage):
|
|
719
747
|
console.print("Calling read image tool")
|
|
720
748
|
output = read_image_from_shell(arg.file_path), 0.0
|
|
749
|
+
elif isinstance(arg, ReadFile):
|
|
750
|
+
console.print("Calling read file tool")
|
|
751
|
+
output = read_file(arg), 0.0
|
|
721
752
|
elif isinstance(arg, ResetShell):
|
|
722
753
|
console.print("Calling reset shell tool")
|
|
723
754
|
output = reset_shell(), 0.0
|
|
@@ -732,7 +763,8 @@ History = list[ChatCompletionMessageParam]
|
|
|
732
763
|
|
|
733
764
|
default_enc = tiktoken.encoding_for_model("gpt-4o")
|
|
734
765
|
default_model: Models = "gpt-4o-2024-08-06"
|
|
735
|
-
default_cost = CostData(cost_per_1m_input_tokens=0.15,
|
|
766
|
+
default_cost = CostData(cost_per_1m_input_tokens=0.15,
|
|
767
|
+
cost_per_1m_output_tokens=0.6)
|
|
736
768
|
curr_cost = 0.0
|
|
737
769
|
|
|
738
770
|
|
|
@@ -744,8 +776,9 @@ class Mdata(BaseModel):
|
|
|
744
776
|
| CreateFileNew
|
|
745
777
|
| ResetShell
|
|
746
778
|
| FileEditFindReplace
|
|
747
|
-
|
|
|
779
|
+
| FileEdit
|
|
748
780
|
| str
|
|
781
|
+
| ReadFile
|
|
749
782
|
)
|
|
750
783
|
|
|
751
784
|
|
|
@@ -774,7 +807,8 @@ def register_client(server_url: str, client_uuid: str = "") -> None:
|
|
|
774
807
|
raise Exception(mdata)
|
|
775
808
|
try:
|
|
776
809
|
output, cost = get_tool_output(
|
|
777
|
-
mdata.data, default_enc, 0.0, lambda x, y: (
|
|
810
|
+
mdata.data, default_enc, 0.0, lambda x, y: (
|
|
811
|
+
"", 0), None
|
|
778
812
|
)
|
|
779
813
|
curr_cost += cost
|
|
780
814
|
print(f"{curr_cost=}")
|
|
@@ -805,3 +839,19 @@ def app(
|
|
|
805
839
|
exit()
|
|
806
840
|
|
|
807
841
|
register_client(server_url, client_uuid or "")
|
|
842
|
+
|
|
843
|
+
|
|
844
|
+
def read_file(readfile: ReadFile) -> str:
|
|
845
|
+
|
|
846
|
+
console.print(f"Reading file: {readfile.file_path}")
|
|
847
|
+
|
|
848
|
+
if not os.path.isabs(readfile.file_path):
|
|
849
|
+
return f"Failure: file_path should be absolute path, current working directory is {CWD}"
|
|
850
|
+
|
|
851
|
+
path = Path(readfile.file_path)
|
|
852
|
+
if not path.exists():
|
|
853
|
+
return f"Error: file {readfile.file_path} does not exist"
|
|
854
|
+
|
|
855
|
+
with path.open("r") as f:
|
|
856
|
+
content = f.read()
|
|
857
|
+
return content
|
|
@@ -19,7 +19,8 @@ from ..types_ import (
|
|
|
19
19
|
BashInteraction,
|
|
20
20
|
CreateFileNew,
|
|
21
21
|
FileEditFindReplace,
|
|
22
|
-
|
|
22
|
+
FileEdit,
|
|
23
|
+
ReadFile,
|
|
23
24
|
ResetShell,
|
|
24
25
|
Writefile,
|
|
25
26
|
Specials,
|
|
@@ -34,7 +35,8 @@ class Mdata(BaseModel):
|
|
|
34
35
|
| CreateFileNew
|
|
35
36
|
| ResetShell
|
|
36
37
|
| FileEditFindReplace
|
|
37
|
-
|
|
|
38
|
+
| FileEdit
|
|
39
|
+
| ReadFile
|
|
38
40
|
| str
|
|
39
41
|
)
|
|
40
42
|
user_id: UUID
|
|
@@ -49,7 +51,7 @@ gpts: dict[UUID, Callable[[str], None]] = {}
|
|
|
49
51
|
images: DefaultDict[UUID, dict[str, dict[str, Any]]] = DefaultDict(dict)
|
|
50
52
|
|
|
51
53
|
|
|
52
|
-
CLIENT_VERSION_MINIMUM = "1.
|
|
54
|
+
CLIENT_VERSION_MINIMUM = "1.2.0"
|
|
53
55
|
|
|
54
56
|
|
|
55
57
|
@app.websocket("/v1/register/{uuid}")
|
|
@@ -63,12 +65,14 @@ async def register_websocket(websocket: WebSocket, uuid: UUID) -> None:
|
|
|
63
65
|
# receive client version
|
|
64
66
|
client_version = await websocket.receive_text()
|
|
65
67
|
sem_version_client = semantic_version.Version.coerce(client_version)
|
|
66
|
-
sem_version_server = semantic_version.Version.coerce(
|
|
68
|
+
sem_version_server = semantic_version.Version.coerce(
|
|
69
|
+
CLIENT_VERSION_MINIMUM)
|
|
67
70
|
if sem_version_client < sem_version_server:
|
|
68
71
|
await websocket.send_text(
|
|
69
72
|
Mdata(
|
|
70
73
|
user_id=uuid,
|
|
71
|
-
data=f"Client version {client_version} is outdated. Please upgrade to {
|
|
74
|
+
data=f"Client version {client_version} is outdated. Please upgrade to {
|
|
75
|
+
CLIENT_VERSION_MINIMUM} or higher.",
|
|
72
76
|
).model_dump_json()
|
|
73
77
|
)
|
|
74
78
|
await websocket.close(
|
|
@@ -88,7 +92,8 @@ async def register_websocket(websocket: WebSocket, uuid: UUID) -> None:
|
|
|
88
92
|
while True:
|
|
89
93
|
received_data = await websocket.receive_text()
|
|
90
94
|
if uuid not in gpts:
|
|
91
|
-
raise fastapi.HTTPException(
|
|
95
|
+
raise fastapi.HTTPException(
|
|
96
|
+
status_code=400, detail="No call made")
|
|
92
97
|
gpts[uuid](received_data)
|
|
93
98
|
except WebSocketDisconnect:
|
|
94
99
|
# Remove the client if the WebSocket is disconnected
|
|
@@ -126,13 +131,13 @@ async def create_file(write_file_data: CreateFileNewWithUUID) -> str:
|
|
|
126
131
|
raise fastapi.HTTPException(status_code=500, detail="Timeout error")
|
|
127
132
|
|
|
128
133
|
|
|
129
|
-
class
|
|
134
|
+
class FileEditWithUUID(FileEdit):
|
|
130
135
|
user_id: UUID
|
|
131
136
|
|
|
132
137
|
|
|
133
138
|
@app.post("/v1/full_file_edit")
|
|
134
139
|
async def file_edit_find_replace(
|
|
135
|
-
file_edit_find_replace:
|
|
140
|
+
file_edit_find_replace: FileEditWithUUID,
|
|
136
141
|
) -> str:
|
|
137
142
|
user_id = file_edit_find_replace.user_id
|
|
138
143
|
if user_id not in clients:
|
|
@@ -257,6 +262,39 @@ async def bash_interaction(bash_interaction: BashInteractionWithUUID) -> str:
|
|
|
257
262
|
raise fastapi.HTTPException(status_code=500, detail="Timeout error")
|
|
258
263
|
|
|
259
264
|
|
|
265
|
+
class ReadFileWithUUID(ReadFile):
|
|
266
|
+
user_id: UUID
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
@app.post("/v1/read_file")
|
|
270
|
+
async def read_file_endpoint(read_file_data: ReadFileWithUUID) -> str:
|
|
271
|
+
user_id = read_file_data.user_id
|
|
272
|
+
if user_id not in clients:
|
|
273
|
+
return "Failure: id not found, ask the user to check it."
|
|
274
|
+
|
|
275
|
+
results: Optional[str] = None
|
|
276
|
+
|
|
277
|
+
def put_results(result: str) -> None:
|
|
278
|
+
nonlocal results
|
|
279
|
+
results = result
|
|
280
|
+
|
|
281
|
+
gpts[user_id] = put_results
|
|
282
|
+
|
|
283
|
+
await clients[user_id](
|
|
284
|
+
Mdata(data=ReadFile(file_path=read_file_data.file_path,
|
|
285
|
+
type=read_file_data.type
|
|
286
|
+
), user_id=user_id)
|
|
287
|
+
)
|
|
288
|
+
|
|
289
|
+
start_time = time.time()
|
|
290
|
+
while time.time() - start_time < 30:
|
|
291
|
+
if results is not None:
|
|
292
|
+
return results
|
|
293
|
+
await asyncio.sleep(0.1)
|
|
294
|
+
|
|
295
|
+
raise fastapi.HTTPException(status_code=500, detail="Timeout error")
|
|
296
|
+
|
|
297
|
+
|
|
260
298
|
app.mount("/static", StaticFiles(directory="static"), name="static")
|
|
261
299
|
|
|
262
300
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import re
|
|
1
2
|
from typing import Literal, Optional, Sequence
|
|
2
3
|
from pydantic import BaseModel
|
|
3
4
|
|
|
@@ -35,7 +36,7 @@ class BashInteraction(BaseModel):
|
|
|
35
36
|
|
|
36
37
|
class ReadImage(BaseModel):
|
|
37
38
|
file_path: str
|
|
38
|
-
type: Literal["ReadImage"]
|
|
39
|
+
type: Literal["ReadImage"]
|
|
39
40
|
|
|
40
41
|
|
|
41
42
|
class Writefile(BaseModel):
|
|
@@ -48,6 +49,11 @@ class CreateFileNew(BaseModel):
|
|
|
48
49
|
file_content: str
|
|
49
50
|
|
|
50
51
|
|
|
52
|
+
class ReadFile(BaseModel):
|
|
53
|
+
file_path: str # The path to the file to read
|
|
54
|
+
type: Literal["ReadFile"]
|
|
55
|
+
|
|
56
|
+
|
|
51
57
|
class FileEditFindReplace(BaseModel):
|
|
52
58
|
file_path: str
|
|
53
59
|
find_lines: str
|
|
@@ -58,6 +64,13 @@ class ResetShell(BaseModel):
|
|
|
58
64
|
should_reset: Literal[True] = True
|
|
59
65
|
|
|
60
66
|
|
|
61
|
-
class
|
|
67
|
+
class FileEdit(BaseModel):
|
|
62
68
|
file_path: str
|
|
63
|
-
|
|
69
|
+
file_edit_using_search_replace_blocks: str
|
|
70
|
+
|
|
71
|
+
def model_post_init(self, __context: object) -> None:
|
|
72
|
+
# Ensure first line is "<<<<<<< SEARCH"
|
|
73
|
+
|
|
74
|
+
if not re.match(r"^<<<<<<+\s*SEARCH\s*$", self.file_edit_using_search_replace_blocks.split("\n")[0]):
|
|
75
|
+
|
|
76
|
+
raise ValueError("First line of file_edit_using_search_replace_blocks must be '<<<<<<< SEARCH'")
|
wcgw-1.1.2/config.toml
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
model = "gpt-4o-2024-08-06"
|
|
2
|
-
secondary_model = 'gpt-4o-2024-08-06'
|
|
3
|
-
cost_limit = 0.1
|
|
4
|
-
|
|
5
|
-
[cost_file.gpt-4o-2024-08-06]
|
|
6
|
-
cost_per_1m_input_tokens = 5
|
|
7
|
-
cost_per_1m_output_tokens = 15
|
|
8
|
-
|
|
9
|
-
[cost_file.gpt-4o-mini]
|
|
10
|
-
cost_per_1m_input_tokens = 0.15
|
|
11
|
-
cost_per_1m_output_tokens = 0.6
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|