Maga222006 commited on
Commit
c7eea5d
·
1 Parent(s): 8da3933

MultiagentPersonalAssistant

Browse files
.DS_Store CHANGED
Binary files a/.DS_Store and b/.DS_Store differ
 
.gitignore CHANGED
@@ -1,2 +1 @@
1
- .env
2
- test.py
 
1
+ .env
 
README.md CHANGED
@@ -28,25 +28,17 @@ This project is a **voice- and text-based AI assistant** powered by **FastAPI**,
28
  - **User database** with persistent settings and config
29
  - **Agents**:
30
  - Supervisor agent
31
- - Deep research agent
32
  - Coding agent
33
- - Smart home agent
34
  - **Supervisor tools**:
35
  - Web search
36
  - Current time
37
  - Weather
38
  - Yahoo finance news
39
- - **Deep research tools**:
40
- - Web search
41
- - Wikipedia
42
- - Yahoo finance news
43
  - **Coder tools**:
44
  - Github toolkit
45
  - Web search (For docs research)
46
- - **Smart home tools**:
47
- - Get device list
48
- - Change device states
49
-
50
  ---
51
 
52
  ## 🛠️ Setup Instructions
 
28
  - **User database** with persistent settings and config
29
  - **Agents**:
30
  - Supervisor agent
 
31
  - Coding agent
 
32
  - **Supervisor tools**:
33
  - Web search
34
  - Current time
35
  - Weather
36
  - Yahoo finance news
37
+ - Change device states (Smart Home)
 
 
 
38
  - **Coder tools**:
39
  - Github toolkit
40
  - Web search (For docs research)
41
+ - Code Interpreter
 
 
 
42
  ---
43
 
44
  ## 🛠️ Setup Instructions
agents/__pycache__/models.cpython-312.pyc CHANGED
Binary files a/agents/__pycache__/models.cpython-312.pyc and b/agents/__pycache__/models.cpython-312.pyc differ
 
agents/__pycache__/multi_agent.cpython-312.pyc CHANGED
Binary files a/agents/__pycache__/multi_agent.cpython-312.pyc and b/agents/__pycache__/multi_agent.cpython-312.pyc differ
 
agents/__pycache__/prompts.cpython-312.pyc CHANGED
Binary files a/agents/__pycache__/prompts.cpython-312.pyc and b/agents/__pycache__/prompts.cpython-312.pyc differ
 
agents/coder/__pycache__/agent.cpython-312.pyc CHANGED
Binary files a/agents/coder/__pycache__/agent.cpython-312.pyc and b/agents/coder/__pycache__/agent.cpython-312.pyc differ
 
agents/coder/__pycache__/prompts.cpython-312.pyc CHANGED
Binary files a/agents/coder/__pycache__/prompts.cpython-312.pyc and b/agents/coder/__pycache__/prompts.cpython-312.pyc differ
 
agents/coder/__pycache__/tools.cpython-312.pyc CHANGED
Binary files a/agents/coder/__pycache__/tools.cpython-312.pyc and b/agents/coder/__pycache__/tools.cpython-312.pyc differ
 
agents/coder/agent.py CHANGED
@@ -1,34 +1,39 @@
1
  from langchain_core.messages import HumanMessage, SystemMessage
2
  from agents.coder.prompts import prompt, system_message
3
  from langgraph.prebuilt import create_react_agent
 
4
  from agents.coder.states import CoderState
5
  from agents.models import llm_sub_agents
6
- from agents.coder.tools import tools
7
  from langchain.tools import tool
 
8
  from dotenv import load_dotenv
 
9
  import os
10
 
11
  load_dotenv()
12
 
13
  agent = create_react_agent(
14
  llm_sub_agents,
15
- tools=tools,
16
  prompt=prompt,
17
  state_schema=CoderState,
18
  )
19
 
20
  @tool
21
- def coder_agent(project_name: str, task_description: str, private: bool=False):
22
  """
23
- Coder Agent, used as a tool for any coding tasks, it creates project, tests it and saves to GitHub.
24
 
25
  Args:
26
  project_name (str): The name of the GitHub repository and directory for the project.
27
- task_description (str): A detailed description of the project for the coder to create.
 
 
28
  private (bool, optional): Whether the coder should be private or public. Defaults to False.
29
  """
 
30
  path = f"agents/coder/projects/{project_name}"
31
  messages = agent.invoke({'messages': [SystemMessage(system_message(project_name, private)), HumanMessage(content=task_description)], 'project_name': project_name, 'private': private})
32
  if os.path.isdir(path):
33
- os.rmdir(path)
34
  return messages['messages'][-1].content
 
1
  from langchain_core.messages import HumanMessage, SystemMessage
2
  from agents.coder.prompts import prompt, system_message
3
  from langgraph.prebuilt import create_react_agent
4
+ from agents.utils.coder import initialize_project
5
  from agents.coder.states import CoderState
6
  from agents.models import llm_sub_agents
 
7
  from langchain.tools import tool
8
+ from agents.coder import tools
9
  from dotenv import load_dotenv
10
+ import shutil
11
  import os
12
 
13
  load_dotenv()
14
 
15
  agent = create_react_agent(
16
  llm_sub_agents,
17
+ tools=tools.tools,
18
  prompt=prompt,
19
  state_schema=CoderState,
20
  )
21
 
22
  @tool
23
+ def coder_agent(project_name: str, task_description: str, repo_owner: str = None, branch: str = "main", private: bool = False):
24
  """
25
+ Coder Agent, used as a tool for any coding tasks, it creates a new project or downloads repo from GitHub to further adjust it, tests it and saves to GitHub.
26
 
27
  Args:
28
  project_name (str): The name of the GitHub repository and directory for the project.
29
+ repo_owner (str): The owner of the GitHub repository, used only if we want to download the existing repo, not create a new project from scratch. Defaults to None (user's GitHub account)
30
+ branch (str): The branch of the GitHub repository. Defaults to "main".
31
+ task_description (str): A detailed description of the project for the coder to create or adjust.
32
  private (bool, optional): Whether the coder should be private or public. Defaults to False.
33
  """
34
+ initialize_project(project_name=project_name, repo_owner=repo_owner, branch=branch, private=private)
35
  path = f"agents/coder/projects/{project_name}"
36
  messages = agent.invoke({'messages': [SystemMessage(system_message(project_name, private)), HumanMessage(content=task_description)], 'project_name': project_name, 'private': private})
37
  if os.path.isdir(path):
38
+ shutil.rmtree(path, ignore_errors=True)
39
  return messages['messages'][-1].content
agents/coder/prompts.py CHANGED
@@ -2,18 +2,20 @@ prompt = """
2
  You are a coding expert.
3
  Always follow these steps:
4
 
5
- 1. Create a new project for this task using 'create_project' or use existing project with 'download_repo' tool.\n
6
  2. Use 'write_file' tool to save your solution code into the GitHub repository.\n
7
  3. Test the code and review it until it works.
8
  4. Tell the user you're done.
9
  """
10
 
11
  def system_message(project_name: str, private: bool=False) -> str:
12
- return f"""Your job is to create a coding project based on the user query.\n
 
 
 
13
 
14
- 1. Create a new GitHub {"private" if private else "public"} repository and project directory, named '{project_name}' for this task using 'create_project' tool or take existing GitHub repository to adjust using 'download_repo' tool if the user request implies adjusting the project instead of creating it from scratch. \n
15
- 2. Use 'tavily_search' tool to retrieve the code examples, documentation and tutorials for the task.\n
16
- 3. Write files with the code to your project using 'write_code' tool.\n
17
  4. Test your code using 'run_cmd' tool.\n
18
  5. Critically review your code for weak points using 'list_files' and 'read_file' tools.\n
19
  6. Adjust the code after the carefully reviewing and testing your code.\n
 
2
  You are a coding expert.
3
  Always follow these steps:
4
 
5
+ 1. Create a new project for this task or use existing project. (Done automatically) \n
6
  2. Use 'write_file' tool to save your solution code into the GitHub repository.\n
7
  3. Test the code and review it until it works.
8
  4. Tell the user you're done.
9
  """
10
 
11
  def system_message(project_name: str, private: bool=False) -> str:
12
+ return f"""Your job is to create or adjust a coding project based on the user query. The project folder is created/downloaded automatically.\n
13
+
14
+ Project name: '{project_name}'\n
15
+ Private: '{private}'
16
 
17
+ 1. Use 'tavily_search' tool to retrieve the code examples, documentation and tutorials for the task.\n
18
+ 3. Write files with the code to your project using 'write_file' tool.\n
 
19
  4. Test your code using 'run_cmd' tool.\n
20
  5. Critically review your code for weak points using 'list_files' and 'read_file' tools.\n
21
  6. Adjust the code after the carefully reviewing and testing your code.\n
agents/coder/tools.py CHANGED
@@ -13,30 +13,6 @@ tavily_search = TavilySearch(
13
  include_answer=False
14
  )
15
 
16
- @tool
17
- def create_project(project_name: str, private: bool = False):
18
- """Creates a project directory and GitHub repository with the given project_name."""
19
- try:
20
- github = Github(os.getenv('GITHUB_TOKEN'))
21
- user = github.get_user()
22
- user.create_repo(project_name, private=private)
23
- os.mkdir(f"agents/coder/projects/{project_name}")
24
- return f"Repository '{project_name}' created successfully!"
25
- except Exception as e:
26
- return f"Error creating repository: {str(e)}"
27
-
28
- @tool
29
- def list_repos():
30
- """Lists all repositories owned by the authenticated GitHub user."""
31
- try:
32
- github = Github(os.getenv('GITHUB_TOKEN'))
33
- user = github.get_user()
34
- repos = user.get_repos()
35
- repo_names = [repo.name for repo in repos]
36
- return f"Repositories: {', '.join(repo_names)}"
37
- except Exception as e:
38
- return f"Error listing repositories: {str(e)}"
39
-
40
  @tool
41
  def list_repo_branches(project_name: str):
42
  """Lists all branches in a GitHub repository."""
@@ -66,9 +42,9 @@ def create_repo_branch(project_name: str, branch_name: str):
66
  @tool
67
  def write_file(project_name: str, file_path: str, file_contents: str):
68
  """Adds a new file to the project directory and GitHub repository or updates the existing one."""
69
-
70
  try:
71
- with open(f"agents/coder/projects/{project_name}/{file_path}", "w", encoding="utf-8") as f:
 
72
  f.write(file_contents)
73
  except Exception as e:
74
  return f"Error with file operation: {str(e)}"
@@ -93,8 +69,9 @@ def write_file(project_name: str, file_path: str, file_contents: str):
93
  def delete_file(project_name: str, file_path: str):
94
  """Deletes a file from the GitHub repository."""
95
  try:
96
- if os.path.isfile(file_path):
97
- os.remove(file_path)
 
98
  except Exception as e:
99
  return f"Error deleting file: {str(e)}"
100
  try:
@@ -104,64 +81,41 @@ def delete_file(project_name: str, file_path: str):
104
  file = repo.get_contents(file_path)
105
  sha = file.sha
106
  repo.delete_file(file_path, "Deleting file", sha)
 
107
  return f"File '{file_path}' deleted successfully from '{project_name}'."
108
  except Exception as e:
 
109
  return f"Error deleting file: {str(e)}"
110
 
111
- @tool
112
- def read_repo_file(project_name: str, file_path: str):
113
- """Reads the content of a file from a GitHub repository."""
114
- try:
115
- github = Github(os.getenv('GITHUB_TOKEN'))
116
- user = github.get_user()
117
- repo = user.get_repo(project_name)
118
- file = repo.get_contents(file_path)
119
- return file.decoded_content.decode('utf-8')
120
- except Exception as e:
121
- return f"Error reading file: {str(e)}"
122
-
123
  @tool
124
  def read_file(project_name: str, file_path: str) -> str:
125
  """Reads the content of a file from a project directory."""
126
- full_path = f"agents/coder/projects/{project_name}/{file_path}"
127
  try:
128
  with open(full_path, "r", encoding="utf-8") as f:
129
  return f.read()
130
  except Exception as e:
 
131
  return f"Error reading file '{full_path}': {str(e)}"
132
 
133
- @tool
134
- def list_repo_files(project_name: str):
135
- """Lists all files in the GitHub repository."""
136
- try:
137
- github = Github(os.getenv('GITHUB_TOKEN'))
138
- user = github.get_user()
139
- repo = user.get_repo(project_name)
140
- files = repo.get_contents("")
141
- file_list = [file.name for file in files]
142
- return f"Files in '{project_name}': {', '.join(file_list)}"
143
- except Exception as e:
144
- return f"Error listing files: {str(e)}"
145
-
146
  @tool
147
  def list_files(project_name: str, directory: str = "") -> dict:
148
  """
149
  Lists files in a project directory.
150
 
151
- :param project_name: Name of the project.
152
- :param directory: Optional subdirectory inside the project. By default, all project files are listed.
153
  :return: List of files in the directory inside the project.
154
  """
155
- base_path = os.path.join("agents/coder/projects", project_name, directory)
156
-
157
  try:
158
- if not os.path.exists(base_path):
159
- return f"Directory '{base_path}' does not exist."
160
 
161
- if not os.path.isdir(base_path):
162
- return f"Path '{base_path}' is not a directory."
163
 
164
- files = os.listdir(base_path)
165
  return files
166
 
167
  except Exception as e:
@@ -172,16 +126,16 @@ def run_cmd(project_name: str, cmd: str, timeout: int = 30):
172
  """
173
  Runs a shell command in the project_name directory.
174
  """
175
- project_dir = os.path.join("agents/coder/projects", project_name)
176
 
177
- if not os.path.isdir(project_dir):
178
- return -1, "", f"Project directory not found: {project_dir}"
179
 
180
  try:
181
  res = subprocess.run(
182
  cmd,
183
  shell=True,
184
- cwd=project_dir,
185
  capture_output=True,
186
  text=True,
187
  timeout=timeout
@@ -192,48 +146,5 @@ def run_cmd(project_name: str, cmd: str, timeout: int = 30):
192
  except Exception as e:
193
  return -1, "", f"Error running command: {str(e)}"
194
 
195
- @tool
196
- def download_repo(project_name: str, repo_owner: str = None, branch: str = "main"):
197
- """
198
- Downloads a GitHub repo (user/<project_name>) using PyGithub
199
- and saves it into agents/coder/projects/{project_name}.
200
-
201
- Args:
202
- project_name (str): Repo name on GitHub and local folder name.
203
- repo_owner (str): Repo owner on GitHub, by default = None (it's the user's repository).
204
- branch (str): Branch to download (default 'main').
205
- """
206
- gh = Github(os.getenv("GITHUB_TOKEN"))
207
- user = gh.get_user()
208
- if repo_owner:
209
- repo = gh.get_repo(f"{repo_owner}/{project_name}")
210
- else:
211
- repo = user.get_repo(project_name)
212
-
213
- dest_path = os.path.join('agents/coder/projects', project_name)
214
- os.makedirs(dest_path, exist_ok=True)
215
-
216
- branch_ref = repo.get_branch(branch)
217
- commit_sha = branch_ref.commit.sha
218
-
219
- # Get the tree (recursive = True to walk full repo)
220
- tree = repo.get_git_tree(commit_sha, recursive=True).tree
221
-
222
- for item in tree:
223
- file_path = os.path.join(dest_path, item.path)
224
-
225
- if item.type == "tree":
226
- os.makedirs(file_path, exist_ok=True)
227
- elif item.type == "blob":
228
- blob = repo.get_git_blob(item.sha)
229
- file_content = blob.content
230
- import base64
231
- decoded = base64.b64decode(file_content)
232
-
233
- os.makedirs(os.path.dirname(file_path), exist_ok=True)
234
- with open(file_path, "wb") as f:
235
- f.write(decoded)
236
-
237
- return f"Repo '{project_name}' downloaded into {dest_path}."
238
 
239
- tools = [tavily_search, create_project, list_repos, list_repo_branches, create_repo_branch, write_file, delete_file, read_repo_file, read_file, list_repo_files, list_files, run_cmd, download_repo]
 
13
  include_answer=False
14
  )
15
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  @tool
17
  def list_repo_branches(project_name: str):
18
  """Lists all branches in a GitHub repository."""
 
42
  @tool
43
  def write_file(project_name: str, file_path: str, file_contents: str):
44
  """Adds a new file to the project directory and GitHub repository or updates the existing one."""
 
45
  try:
46
+ full_path = os.path.join('agents/coder/projects', project_name, file_path)
47
+ with open(full_path, "w", encoding="utf-8") as f:
48
  f.write(file_contents)
49
  except Exception as e:
50
  return f"Error with file operation: {str(e)}"
 
69
  def delete_file(project_name: str, file_path: str):
70
  """Deletes a file from the GitHub repository."""
71
  try:
72
+ full_path = os.path.join('agents/coder/projects', project_name, file_path)
73
+ if os.path.isfile(full_path):
74
+ os.remove(full_path)
75
  except Exception as e:
76
  return f"Error deleting file: {str(e)}"
77
  try:
 
81
  file = repo.get_contents(file_path)
82
  sha = file.sha
83
  repo.delete_file(file_path, "Deleting file", sha)
84
+ print(f"File '{file_path}' deleted successfully in '{project_name}'.")
85
  return f"File '{file_path}' deleted successfully from '{project_name}'."
86
  except Exception as e:
87
+ print(f"Error deleting file: {str(e)}")
88
  return f"Error deleting file: {str(e)}"
89
 
 
 
 
 
 
 
 
 
 
 
 
 
90
  @tool
91
  def read_file(project_name: str, file_path: str) -> str:
92
  """Reads the content of a file from a project directory."""
93
+ full_path = os.path.join('agents/coder/projects', project_name, file_path)
94
  try:
95
  with open(full_path, "r", encoding="utf-8") as f:
96
  return f.read()
97
  except Exception as e:
98
+ print(f"Error reading file: {str(e)}")
99
  return f"Error reading file '{full_path}': {str(e)}"
100
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
  @tool
102
  def list_files(project_name: str, directory: str = "") -> dict:
103
  """
104
  Lists files in a project directory.
105
 
106
+ :param project_name: The name of the project.
107
+ :param directory: Optional subdirectory inside the project. By default, (directory="") all project files are listed.
108
  :return: List of files in the directory inside the project.
109
  """
110
+ full_path = os.path.join('agents/coder/projects', project_name, directory)
 
111
  try:
112
+ if not os.path.exists(full_path):
113
+ return f"Directory '{full_path}' does not exist."
114
 
115
+ if not os.path.isdir(full_path):
116
+ return f"Path '{full_path}' is not a directory."
117
 
118
+ files = os.listdir(full_path)
119
  return files
120
 
121
  except Exception as e:
 
126
  """
127
  Runs a shell command in the project_name directory.
128
  """
129
+ full_path = os.path.join("agents/coder/projects", project_name)
130
 
131
+ if not os.path.isdir(full_path):
132
+ return -1, "", f"Project directory not found: {full_path}"
133
 
134
  try:
135
  res = subprocess.run(
136
  cmd,
137
  shell=True,
138
+ cwd=full_path,
139
  capture_output=True,
140
  text=True,
141
  timeout=timeout
 
146
  except Exception as e:
147
  return -1, "", f"Error running command: {str(e)}"
148
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
149
 
150
+ tools = [tavily_search, list_repo_branches, create_repo_branch, write_file, delete_file, read_file, list_files, run_cmd]
agents/models.py CHANGED
@@ -20,7 +20,8 @@ llm_peripheral = init_chat_model(
20
  )
21
 
22
  llm_sub_agents = init_chat_model(
23
- model="groq:qwen/qwen3-32b"
 
24
  )
25
 
26
  llm_image = init_chat_model(
 
20
  )
21
 
22
  llm_sub_agents = init_chat_model(
23
+ model="groq:moonshotai/kimi-k2-instruct-0905",
24
+ max_tokens=4000
25
  )
26
 
27
  llm_image = init_chat_model(
agents/prompts.py CHANGED
@@ -1,4 +1,5 @@
1
  from agents.utils.smart_home import get_device_list
 
2
  from dotenv import load_dotenv
3
  import os
4
 
@@ -27,10 +28,6 @@ Your top priority: satisfy the user’s query as effectively and efficiently as
27
 
28
 
29
  def system_message(user_info: dict):
30
- try:
31
- device_list = "\n\n".join(f"{i + 1}. {device['name']} (id: {device['id']})\nStates:\n" + "\n".join(f"{state}" for state in device['states']) for i, device in enumerate(get_device_list()))
32
- except Exception as e:
33
- device_list = None
34
  return f"""
35
  You are an intelligent assistant named {os.getenv('ASSISTANT_NAME', 'Assistant')}, helpful personal assistant built using a multi-agent system architecture. Your tools include web search, weather and time lookups, code execution, and GitHub integration. You work inside a Telegram interface and respond concisely, clearly, and informatively.
36
 
@@ -39,7 +36,8 @@ def system_message(user_info: dict):
39
  - **User ID**: {user_info.get('user_id', 'Unknown')}
40
  - **Location**: {user_info.get('location', 'Unknown') or 'Unknown'}
41
  - **Coordinates**: ({user_info.get('latitude', 'N/A') or 'N/A'}, {user_info.get('longitude', 'N/A') or 'N/A'})
42
- - **Smart Home Devices**: {device_list or "Unknown"}
 
43
 
44
  You may use their location when answering weather or time-related queries. If the location is unknown, you may ask the user to share it.
45
  You may use the smart home devices if user asks you to.
 
1
  from agents.utils.smart_home import get_device_list
2
+ from agents.utils.coder import list_repos
3
  from dotenv import load_dotenv
4
  import os
5
 
 
28
 
29
 
30
  def system_message(user_info: dict):
 
 
 
 
31
  return f"""
32
  You are an intelligent assistant named {os.getenv('ASSISTANT_NAME', 'Assistant')}, helpful personal assistant built using a multi-agent system architecture. Your tools include web search, weather and time lookups, code execution, and GitHub integration. You work inside a Telegram interface and respond concisely, clearly, and informatively.
33
 
 
36
  - **User ID**: {user_info.get('user_id', 'Unknown')}
37
  - **Location**: {user_info.get('location', 'Unknown') or 'Unknown'}
38
  - **Coordinates**: ({user_info.get('latitude', 'N/A') or 'N/A'}, {user_info.get('longitude', 'N/A') or 'N/A'})
39
+ - **Smart Home Devices**: {get_device_list() or "Unknown"}
40
+ - **GitHub**: {list_repos() or "Unknown"}
41
 
42
  You may use their location when answering weather or time-related queries. If the location is unknown, you may ask the user to share it.
43
  You may use the smart home devices if user asks you to.
agents/utils/__pycache__/coder.cpython-312.pyc ADDED
Binary file (5.07 kB). View file
 
agents/utils/__pycache__/smart_home.cpython-312.pyc CHANGED
Binary files a/agents/utils/__pycache__/smart_home.cpython-312.pyc and b/agents/utils/__pycache__/smart_home.cpython-312.pyc differ
 
agents/utils/coder.py ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from dotenv import load_dotenv
2
+ from github import Github
3
+ import os
4
+
5
+ load_dotenv()
6
+
7
+ def list_repos():
8
+ """Lists all repositories owned by the authenticated GitHub user."""
9
+ try:
10
+ github = Github(os.getenv('GITHUB_TOKEN'))
11
+ user = github.get_user()
12
+ repos = user.get_repos()
13
+ repo_names = [repo.name for repo in repos]
14
+ return ', '.join(repo_names)
15
+ except Exception as e:
16
+ return None
17
+
18
+ def download_repo(project_name: str, repo_owner: str = None, branch: str = "main", private: bool = False):
19
+ """
20
+ Downloads a GitHub repo (user/<project_name>) using PyGithub
21
+ and saves it into agents/coder/projects/{project_name}.
22
+
23
+ Args:
24
+ project_name (str): Repo name on GitHub and local folder name.
25
+ repo_owner (str): Repo owner on GitHub, by default = None (it's the user's repository).
26
+ branch (str): Branch to download (default 'main').
27
+ """
28
+ gh = Github(os.getenv("GITHUB_TOKEN"))
29
+ user = gh.get_user()
30
+ if repo_owner:
31
+ repo = gh.get_repo(f"{repo_owner}/{project_name}")
32
+ user.create_repo(project_name, private=private)
33
+ else:
34
+ repo = user.get_repo(project_name)
35
+
36
+ dest_path = os.path.join('agents/coder/projects', project_name)
37
+ os.makedirs(dest_path, exist_ok=True)
38
+
39
+ try:
40
+ branch_ref = repo.get_branch(branch)
41
+ commit_sha = branch_ref.commit.sha
42
+
43
+ # Get the tree (recursive = True to walk full repo)
44
+ tree = repo.get_git_tree(commit_sha, recursive=True).tree
45
+
46
+ for item in tree:
47
+ file_path = os.path.join(dest_path, item.path)
48
+
49
+ if item.type == "tree":
50
+ os.makedirs(file_path, exist_ok=True)
51
+ elif item.type == "blob":
52
+ blob = repo.get_git_blob(item.sha)
53
+ file_content = blob.content
54
+ import base64
55
+ decoded = base64.b64decode(file_content)
56
+
57
+ os.makedirs(os.path.dirname(file_path), exist_ok=True)
58
+ with open(file_path, "wb") as f:
59
+ f.write(decoded)
60
+ except Exception as e:
61
+ return f"Error downloading repository: {str(e)}"
62
+
63
+ def initialize_project(project_name: str, repo_owner: str = None, branch: str = "main", private: bool = False):
64
+ """Creates a project directory and GitHub repository with the given project_name."""
65
+ try:
66
+ github = Github(os.getenv('GITHUB_TOKEN'))
67
+ user = github.get_user()
68
+ repos = user.get_repos()
69
+ repo_names = [repo.name for repo in repos]
70
+ if project_name in repo_names or repo_owner:
71
+ try:
72
+ download_repo(project_name=project_name, repo_owner=repo_owner, branch=branch, private=private)
73
+ return f"Repository '{f'{repo_owner}/{project_name}' if repo_owner else project_name}' downloaded successfully!"
74
+ except Exception as e:
75
+ os.mkdir(f"agents/coder/projects/{project_name}")
76
+ user.create_repo(project_name, private=private)
77
+ return f"Repository '{project_name}' created successfully!"
78
+ else:
79
+ user.create_repo(project_name, private=private)
80
+ os.mkdir(f"agents/coder/projects/{project_name}")
81
+ return f"Repository '{project_name}' created successfully!"
82
+ except Exception as e:
83
+ return f"Error creating repository: {str(e)}"
agents/utils/smart_home.py CHANGED
@@ -38,17 +38,15 @@ if not connection['success']:
38
  connection = openapi.connect(os.getenv('TUYA_USERNAME'), os.getenv('TUYA_PASSWORD'), os.getenv('TUYA_COUNTRY_CODE'), 'SmartLife')
39
 
40
  def get_device_list():
41
- """
42
- Get the list of devices bound to the smart home.
43
- Each device has id: str, name: str and states: List[dict].
44
- States is a list of device states which can be changed.
45
- State format: {'code': ..., 'value': ...}
46
- """
47
- response = openapi.get('/v1.0/users/{}/devices'.format(connection['result']['uid']))['result']
48
- devices = []
49
- for device in response:
50
- devices.append({"id": device['id'], 'name': device['name'], 'states': device['status']})
51
- return devices
52
 
53
  @tool
54
  def change_device_states(id:str, commands:list[dict]):
 
38
  connection = openapi.connect(os.getenv('TUYA_USERNAME'), os.getenv('TUYA_PASSWORD'), os.getenv('TUYA_COUNTRY_CODE'), 'SmartLife')
39
 
40
  def get_device_list():
41
+ """List all the smart home devices."""
42
+ try:
43
+ response = openapi.get('/v1.0/users/{}/devices'.format(connection['result']['uid']))['result']
44
+ devices = []
45
+ for device in response:
46
+ devices.append({"id": device['id'], 'name': device['name'], 'states': device['status']})
47
+ return "\n\n".join(f"{i + 1}. {device['name']} (id: {device['id']})\nStates:\n" + "\n".join(f"{state}" for state in device['states']) for i, device in enumerate(devices))
48
+ except Exception as e:
49
+ return None
 
 
50
 
51
  @tool
52
  def change_device_states(id:str, commands:list[dict]):
database_files/main.db CHANGED
Binary files a/database_files/main.db and b/database_files/main.db differ