File size: 9,026 Bytes
1b6fe24
 
 
d28cecd
 
 
 
 
 
 
1b6fe24
 
 
 
76fbff7
1b6fe24
 
 
 
76fbff7
1b6fe24
 
 
76fbff7
1b6fe24
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76fbff7
 
 
 
 
 
 
 
 
 
 
1b6fe24
 
 
 
76fbff7
 
 
 
1b6fe24
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76fbff7
d28cecd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76fbff7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1b6fe24
 
76fbff7
1b6fe24
76fbff7
1b6fe24
76fbff7
 
 
 
 
1b6fe24
76fbff7
 
 
 
 
1b6fe24
76fbff7
 
 
 
 
 
1b6fe24
76fbff7
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
from smolagents import CodeAgent, DuckDuckGoSearchTool, Tool, HfApiModel
import os
from dotenv import load_dotenv
import requests

load_dotenv() 

HF_TOKEN = os.getenv("HF_TOKEN")
NOODLE_PUBLIC_API_URL = os.getenv("NOODLE_PUBLIC_API_URL")

        
class FileWriteTool(Tool):
    name = "file_write_tool"
    description = """
    This tool will be used by the LLM Agent to create files if needed for task. Always put the files in the /ai-code directory from the root of this project.
    """
    inputs = {
        "file_location": {
            "type": "string",
            "description": "The location of the file that will be written to. Please put this in the /ai-code directory."
        },
        "new_code": {
            "type": "string",
            "description": "This is the content of the file."
        }
    }
    output_type = "string"

    def forward(self,file_location, new_code) -> str:
        with open(file_location, "w") as file:
            return file.write(new_code)

class GetImageDimensionsTool(Tool):
    name = "get_image_dimensions_tool"
    description= """
    This tool is used to get the width and height of a webp file.
    """
    inputs = {
        "file_location": {
            "type": "string",
            "description": "The location in which the webp file can be located"
        }
    }
    output_type = "object"
    def forward(self, file_location) -> dict:
        from PIL import Image

        with Image.open(file_location) as img:
            width, height = img.size

        return {"width": width, "height": height}

class ProcessFlowIdentifierTool(Tool):
    name = "process_flow_identifier_tool"
    description = """
    This tool will be used to give a set of instructions depending on the purpose of the prompt. This is to aid the LLM in its decision making process.
    """
    inputs = {
        "prompt_objective": {
            "type": "string",
            "description": "This is the objective of the user's original prompt to help identify the steps needed for the llm to take."
        }
    }
    output_type = "string"
    def forward(self, prompt_objective) -> str:
        match prompt_objective:
            case "asset_change":
                instructions = """
                    1) use the get_game_file_names_tool to get the list of accessible game files. If user specifies what file, do this still to check if they can access it.
                    2) Use the read_file_tool to read the file contents of the file from step 1. Remember to save the path of the file, this will be used to update the file.
                    3) Based on the prompt, make changes to the code from step 2 and pass it to the update_game_file_tool along with the path saved from step1.
                    4) End process after sucessfully modifying the file
                """
                return instructions
            case "read_file":
                instructions = """
                    1) use the get_game_file_names_tool to get the list of accessible game files. If user specifies what file, do this still to check if they can access it.
                    2) Use the read_file_tool to read the file contents of the file from step 1.
                    3) End process after reading the file.
                """
                return instructions
            case "script_change":
                instructions = """
                    1) use the get_game_file_names_tool to get the list of accessible game files. If user specifies what file, do this still to check if they can access it.
                    2) Use the read_file_tool to read the file contents of the file from step 1. Remember to save the path of the file, this will be used to update the file.
                    3) Based on the prompt, make changes to the code from step 2 and use the update_game_file_tool.
                    4) End process after sucessfully modifying the file
                """
                return instructions
            case "conversation":
                """
                    1) Reply to the user with the last message they sent as a friendly ai agent.
                    2) Do not use any tools to modify files.
                    3) End process after replying to the user.
                """
            case _:
                instructions = """
                inform user that the instructions where unclear
                """
                return instructions
        

class GitPushTool(Tool):
    name = "git_push_tool"
    description = """
    This tool will be triggered to create a new branch and push new changes to the repository.
    """
    inputs = {
        "branch_name": {
            "type": "string",
            "description": "the target branch that will be pushed, new or existing."
        }
    }
    output_type = "string"

    def forward(self, branch_name) -> str:
        import os
        import subprocess
        try:
            gitUsername = os.getenv("GIT_USERNAME")
            gitEmail = os.getenv("GIT_EMAIL")
            # new_branch = "add-generated-image-2"
            # Step 1: Ensure we are in a Git repository
            subprocess.run(["git", "status"], check=True)

            # Step 2: Create and switch to a new branch
            subprocess.run(["git", "checkout", "-b", branch_name], check=True)
            print(f"Checked out to new branch: {branch_name}")

            # Step 3: Add the changes
            subprocess.run(["git", "add", "*"], check=True)
            print("Changes added to staging.")
            # Step 4: Add credentials
            subprocess.run(["git", "config", "--global", "user.email", gitEmail], check=True)
            print("Updated git email.")
            subprocess.run(["git", "config", "--global", "user.name", gitUsername], check=True)
            print("Updated git user name.")

            # Step 5: Commit the changes
            commit_message = "Add generated image to repository"
            subprocess.run(["git", "commit", "-m", commit_message], check=True)
            print("Changes committed.")

            #Step 6: Push the branch to the remote repository
            subprocess.run(["git", "push", "--set-upstream", "origin", branch_name], check=True)
            return print(f"Branch '{branch_name}' pushed to remote repository.")
        except subprocess.CalledProcessError as e:
            return print(f"An error occurred while performing Git operations: {e}")

# READ
class GetGameFileNamesTool(Tool):
    name="get_game_file_names_tool"
    description="""
        Use this tool to get the game directories of files related to the game. The output of this is an array of file paths. 
        Return only the array of file paths returned by the api call.
    """
    inputs = {}
    output_type = "string"
    def forward(self) -> str:
        get_files_api = NOODLE_PUBLIC_API_URL + "/api/files/"

        response = requests.get(get_files_api)
        if response.status_code == 200:
            print(response.json()['content'])
        else:
            print("Failed to get file content")
        return response.json()['content']

# UPDATE
class UpdateGameFileTool(Tool):
    name = "update_game_file_tool"
    description = """
        Update the game file via an api by sending the updated code for the nextjs game app to handle.
    """
    inputs = {
        "file_path": {
            "type": "string",
            "description": "The path from the game directory to update."
        },
        "new_content": {
            "type": "string",
            "description": "The updated code."
        }
    }
    output_type = "string"

    def forward(self, file_path: str, new_content: str) -> str:
        """
        Make an api call to update the file from a secure api route.
        """
        update_file_contents = NOODLE_PUBLIC_API_URL + "/api/files/"
        headers = {
            "Content-Type": "application/octet-stream"
        }
        binary_data = new_content.encode("utf-8")

        response = requests.put(update_file_contents, params={"path": file_path}, headers=headers, data=binary_data)
        if response.status_code == 200:
            return 
        else:
            return "Failed to update file contents"

class ReadFilesTool(Tool):
    name = "read_file_tool"
    description = "Read the file contents of the given game file path."
    inputs = {"file_path":{"type":"string","description":"the path to the directory to search in"},}
  
    output_type = "string"

    def forward(self, file_path: str) -> str:
        """
        Make an api call to browse the file from the game through an api call. The file path must be passed to view the file.
        """
        read_file_contents = NOODLE_PUBLIC_API_URL + "/api/files/"
        response = requests.get(f"{read_file_contents}", params={"path": file_path})
        if response.status_code == 200:
            return response.json()['content']
        else:
            return "Failed to read file contents"
        return