@@ -176,9 +176,9 @@ def view_lines(
176
176
f"[Artifact: { name } ({ total_lines } lines total)]\n "
177
177
+ format_lines (lines [start :end ], start )
178
178
+ (
179
- "[End of artifact]"
179
+ "\n [End of artifact]"
180
180
if end == len (lines )
181
- else f"[{ len (lines ) - end } more lines]"
181
+ else f"\n [{ len (lines ) - end } more lines]"
182
182
)
183
183
)
184
184
@@ -258,8 +258,10 @@ def edit_code_artifact(
258
258
Parameters:
259
259
artifacts (Artifacts): The artifacts object to edit the artifact from.
260
260
name (str): The name of the artifact to edit.
261
- start (int): The line number to start the edit.
262
- end (int): The line number to end the edit.
261
+ start (int): The line number to start the edit, can be in [-1, total_lines]
262
+ where -1 represents the end of the file.
263
+ end (int): The line number to end the edit, can be in [-1, total_lines] where
264
+ -1 represents the end of the file.
263
265
content (str): The content to insert.
264
266
"""
265
267
# just make the artifact if it doesn't exist instead of forcing agent to call
@@ -268,17 +270,21 @@ def edit_code_artifact(
268
270
artifacts [name ] = ""
269
271
270
272
total_lines = len (artifacts [name ].splitlines ())
271
- if start < 0 or end < 0 or start > end or end > total_lines :
273
+ if start < - 1 or end < - 1 or start > end or end > total_lines :
272
274
print ("[Invalid line range]" )
273
275
return "[Invalid line range]"
274
- if start == end :
275
- end += 1
276
+
277
+ if start == - 1 :
278
+ start = total_lines
279
+ if end == - 1 :
280
+ end = total_lines
276
281
277
282
new_content_lines = content .splitlines (keepends = True )
278
283
new_content_lines = [
279
284
line if line .endswith ("\n " ) else line + "\n " for line in new_content_lines
280
285
]
281
286
lines = artifacts [name ].splitlines (keepends = True )
287
+ lines = [line if line .endswith ("\n " ) else line + "\n " for line in lines ]
282
288
edited_lines = lines [:start ] + new_content_lines + lines [end :]
283
289
284
290
cur_line = start + len (content .split ("\n " )) // 2
@@ -760,6 +766,51 @@ def use_object_detection_fine_tuning(
760
766
return diff
761
767
762
768
769
+ def _find_name (file : Path , names : List [str ]) -> str :
770
+ if not str (file ) in names :
771
+ return str (file )
772
+ name = file .name
773
+ suffix = file .suffix
774
+ # test basic names first
775
+ for i in range (100 ):
776
+ new_name = f"{ name } _output_{ i } { suffix } "
777
+ if new_name not in names :
778
+ return new_name
779
+ return f"{ name } _output_{ str (uuid .uuid4 ())} { suffix } "
780
+
781
+
782
+ def _extract_file_names (
783
+ code : str , obs : str , file_counts : Dict [str , int ], existing_names : List [str ]
784
+ ) -> Dict [str , List [str ]]:
785
+ try :
786
+ response = extract_json (
787
+ AnthropicLMM ()( # type: ignore
788
+ f"""You are a helpful AI assistant. You are given a number of files for certain file types, your job is to look at the code and the output of running that code and assign each file a file name. Below is the code snippet:
789
+
790
+ ```python
791
+ { code }
792
+ ```
793
+
794
+ ```output
795
+ { obs }
796
+ ```
797
+
798
+ Here's the number of files that need file names:
799
+ { json .dumps ({k : v for k , v in file_counts .items ()})}
800
+
801
+ The name cannot conflict with any of these existing names:
802
+ { str (existing_names )}
803
+
804
+ Return the file paths in the following JSON format:
805
+ {{"png": ["image_name1.png", "other_image_name.png"], "mp4": ["video_name.mp4"]}}"""
806
+ )
807
+ )
808
+ except json .JSONDecodeError :
809
+ response = {}
810
+
811
+ return response
812
+
813
+
763
814
def extract_and_save_files_to_artifacts (
764
815
artifacts : Artifacts , code : str , obs : str , result : Execution
765
816
) -> None :
@@ -775,8 +826,8 @@ def extract_and_save_files_to_artifacts(
775
826
# file system.
776
827
files = {}
777
828
for res in result .results :
778
- if len (res .formats ()) == 1 and res .formats ()[0 ] in ["png" , "jpeg" , "mp4" ]:
779
- format = res .formats ()[0 ]
829
+ if len (res .formats ()) == 1 and res .formats ()[0 ] in ["png" , "jpeg" , "mp4" ]: # type: ignore
830
+ format = res .formats ()[0 ] # type: ignore
780
831
if format == "png" :
781
832
data = base64 .b64decode (res .png ) if res .png is not None else None
782
833
elif format == "jpeg" :
@@ -791,50 +842,19 @@ def extract_and_save_files_to_artifacts(
791
842
else :
792
843
files [format ].append (data )
793
844
794
- try :
795
- response = extract_json (
796
- AnthropicLMM ()( # type: ignore
797
- f"""You are a helpful AI assistant. You are given a number of files for certain file types, your job is to look at the code and the output of running that code and assign each file a file name. Below is the code snippet:
798
-
799
- ```python
800
- { code }
801
- ```
802
-
803
- ```output
804
- { obs }
805
- ```
806
-
807
- Here's the number of files that need file names:
808
- { json .dumps ({k : len (v ) for k , v in files .items ()})}
809
-
810
- The name cannot conflict with any of these existing names:
811
- { json .dumps (list (artifacts .artifacts .keys ()))}
812
-
813
- Return the file paths in the following JSON format:
814
- {{"png": ["image_name1.png", "other_image_name.png"], "mp4": ["video_name.mp4"]}}"""
815
- )
816
- )
817
- except json .JSONDecodeError :
818
- response = {}
819
-
820
- def find_name (file : Path , names : List [str ]) -> str :
821
- if not str (file ) in names :
822
- return str (file )
823
- name = file .name
824
- suffix = file .suffix
825
- # test basic names first
826
- for i in range (100 ):
827
- new_name = f"{ name } _output_{ i } { suffix } "
828
- if new_name not in names :
829
- return new_name
830
- return f"{ name } _output_{ str (uuid .uuid4 ())} { suffix } "
845
+ response = _extract_file_names (
846
+ code ,
847
+ obs ,
848
+ {k : len (v ) for k , v in files .items ()},
849
+ list (artifacts .artifacts .keys ()),
850
+ )
831
851
832
852
for format in files .keys ():
833
853
i = 0
834
854
if format in response :
835
855
for file in response [format ]:
836
856
if i < len (files [format ]) and files [format ][i ] is not None :
837
- new_name = find_name (
857
+ new_name = _find_name (
838
858
Path (file ).with_suffix ("." + format ),
839
859
list (artifacts .artifacts .keys ()),
840
860
)
@@ -844,7 +864,7 @@ def find_name(file: Path, names: List[str]) -> str:
844
864
for j in range (i , len (files [format ])):
845
865
name = "image" if format in ["png" , "jpeg" ] else "video"
846
866
if files [format ][j ] is not None :
847
- new_name = find_name (
867
+ new_name = _find_name (
848
868
Path (f"{ name } " ).with_suffix ("." + format ),
849
869
list (artifacts .artifacts .keys ()),
850
870
)
0 commit comments