microsoft / autogen

A programming framework for agentic AI 🤖
https://microsoft.github.io/autogen/
Creative Commons Attribution 4.0 International
30.74k stars 4.48k forks source link

[Bug]: Tools Exception while generating the code - Especially when agent tries to create folders and files with large code content #3263

Open raolak opened 1 month ago

raolak commented 1 month ago

Describe the bug

I am using the notebook example on creating a todo-api with using fastapi with modern complexities to test the code generation featires. When it comes to executing file.folder creation for large tree , it fails... Also i have seem after sequential conversation, when agent tries to create folders and tree, tool tend to through exception and the session will abruptly close.

Here is the logs I am using the notebook example on creating a todo-api with using fastapi with modern complexities to test the code generation featires. When it comes to executing file.folder creation for large tree , it fails... Also i have seem after sequential conversation, when agent tries to create folders and tree, tool tend to through exception and the session will abruptly close.

Here is the logs Admin (to chat_manager):

{"type":"user_message","data":{"role":"user","content":"lets create a todo-api micro service project using fastapi. Lets use restapi best practice to structure the project. Make sure to have a clear seperation of concerns between database, services and apis. :Lets ahev db models and pydentic schema. Lets manage the dependecies through requirement.txt. For now lets add mock store later we will integrate with real database","user_id":"lnr@gmail.com","session_id":"session-1","workflow_id":"1","name":"Workflow 1","description":"This is Workflow 1","meta":{}}}


Engineer (to chat_manager):

Let's create a structured FastAPI project for a todo-api microservice. We'll follow REST API best practices and ensure a clear separation of concerns between the database, services, and APIs. Here's the plan:

  1. Project Structure:

    todo_api/
    ├── app/
    │   ├── __init__.py
    │   ├── main.py
    │   ├── api/
    │   │   ├── __init__.py
    │   │   └── v1/
    │   │       ├── __init__.py
    │   │       └── endpoints/
    │   │           ├── __init__.py
    │   │           └── todo.py
    │   ├── core/
    │   │   ├── __init__.py
    │   │   └── config.py
    │   ├── models/
    │   │   ├── __init__.py
    │   │   └── todo.py
    │   ├── schemas/
    │   │   ├── __init__.py
    │   │   └── todo.py
    │   └── services/
    │       ├── __init__.py
    │       └── todo.py
    └── requirements.txt
  2. Files and Code:

Let's start by creating the directory structure and the initial files. Suggested tool call (call_iU7vNDsoM1tvc3edFYTD0Doz): create_file_with_code Arguments: {"filename": "todo_api/app/init.py", "code": ""}


Suggested tool call (call_Td2Tl7bRUqqXQMgBqgS1vFnx): create_file_with_code Arguments: {"filename": "todo_api/app/main.py", "code": "from fastapi import FastAPI\n\nfrom app.api.v1.endpoints import todo\n\napp = FastAPI()\n\napp.include_router(todo.router, prefix=\"/api/v1\", tags=[\"todo\"])\n\n@app.get(\"/\")\ndef read_root():\n return {\"message\": \"Welcome to the Todo API\"}\n"}


Suggested tool call (call_yEb0kn0l8i2chTctrjdBKvyK): create_file_with_code Arguments: {"filename": "todo_api/app/api/init.py", "code": ""}


Suggested tool call (call_RbdExb0zp7nNThhrdS3cNOCE): create_file_with_code Arguments: {"filename": "todo_api/app/api/v1/init.py", "code": ""}


Suggested tool call (call_af5zAiNv0uvpdvEvVR66CNbQ): create_file_with_code Arguments: {"filename": "todo_api/app/api/v1/endpoints/init.py", "code": ""}


Suggested tool call (call_m5WezLx58oUEaR52ozXS2DKp): create_file_with_code Arguments: {"filename": "todo_api/app/api/v1/endpoints/todo.py", "code": "from fastapi import APIRouter, HTTPException\nfrom typing import List\n\nfrom app.schemas.todo import Todo, TodoCreate\nfrom app.services.todo import TodoService\n\nrouter = APIRouter()\n\ntodo_service = TodoService()\n\n@router.post(\"/todos/\", response_model=Todo)\ndef create_todo(todo: TodoCreate):\n return todo_service.create(todo)\n\n@router.get(\"/todos/\", response_model=List[Todo])\ndef read_todos(skip: int = 0, limit: int = 10):\n return todo_service.get_all(skip=skip, limit=limit)\n\n@router.get(\"/todos/{todo_id}\", response_model=Todo)\ndef read_todo(todo_id: int):\n todo = todo_service.get(todo_id)\n if not todo:\n raise HTTPException(status_code=404, detail=\"Todo not found\")\n return todo\n\n@router.put(\"/todos/{todo_id}\", response_model=Todo)\ndef update_todo(todo_id: int, todo: TodoCreate):\n return todo_service.update(todo_id, todo)\n\n@router.delete(\"/todos/{todo_id}\", response_model=Todo)\ndef delete_todo(todo_id: int):\n return todo_service.delete(todo_id)\n"}


Suggested tool call (call_C6yjdKEjRX4LOdmGYYNPgYgt): create_file_with_code Arguments: {"filename": "todo_api/app/core/init.py", "code": ""}


Suggested tool call (call_m62lKCK2po7e45JeuJsVomj1): create_file_with_code Arguments: {"filename": "todo_api/app/core/config.py", "code": "class Settings:\n PROJECT_NAME: str = \"Todo API\"\n API_V1_STR: str = \"/api/v1\"\n\nsettings = Settings()\n"}


Suggested tool call (call_73NQO9jeoDsI3ilxMJk3fBW4): create_file_with_code Arguments: {"filename": "todo_api/app/models/init.py", "code": ""}


Suggested tool call (call_Qz5HROVfobNTpsYwL1BXF5cy): create_file_with_code Arguments: {"filename": "todo_api/app/models/todo.py", "code": "from typing import Optional\n\nclass Todo:\n def init(self, id: int, title: str, description: Optional[str] = None, completed: bool = False):\n self.id = id\n self.title = title\n self.description = description\n self.completed = completed\n"}


Suggested tool call (call_4uGkyvbiDlhQunD1bX67eOow): create_file_with_code Arguments: {"filename": "todo_api/app/schemas/init.py", "code": ""}


Suggested tool call (call_mqeyEY85ht99kQXDptsyWf3c): create_file_with_code Arguments: {"filename": "todo_api/app/schemas/todo.py", "code": "from typing import Optional\nfrom pydantic import BaseModel\n\nclass TodoBase(BaseModel):\n title: str\n description: Optional[str] = None\n completed: bool = False\n\nclass TodoCreate(TodoBase):\n pass\n\nclass Todo(TodoBase):\n id: int\n\n class Config:\n orm_mode = True\n"}


Suggested tool call (call_Z56dIfUXbe0HAKlDlG30Shtn): create_file_with_code Arguments: {"filename": "todo_api/app/services/init.py", "code": ""}


Suggested tool call (call_fhq0ZKPBZif08mCyOlLsI3PN): create_file_with_code Arguments: {"filename": "todo_api/app/services/todo.py", "code": "from typing import List, Optional\n\nfrom app.models.todo import Todo\nfrom app.schemas.todo import TodoCreate\n\nclass TodoService:\n def init(self):\n self.todos = []\n self.counter = 1\n\n def create(self, todo_create: TodoCreate) -> Todo:\n todo = Todo(id=self.counter, **todo_create.dict())\n self.todos.append(todo)\n self.counter += 1\n return todo\n\n def get_all(self, skip: int = 0, limit: int = 10) -> List[Todo]:\n return self.todos[skip: skip + limit]\n\n def get(self, todo_id: int) -> Optional[Todo]:\n for todo in self.todos:\n if todo.id == todo_id:\n return todo\n return None\n\n def update(self, todo_id: int, todo_create: TodoCreate) -> Optional[Todo]:\n todo = self.get(todo_id)\n if todo:\n todo.title = todo_create.title\n todo.description = todo_create.description\n todo.completed = todo_create.completed\n return todo\n return None\n\n def delete(self, todo_id: int) -> Optional[Todo]:\n todo = self.get(todo_id)\n if todo:\n self.todos.remove(todo)\n return todo\n return None\n"}


Suggested tool call (call_VDSrfYIglP0p0k3CTKZCIh5x): create_file_with_code Arguments: {"filename": "todo_api/requirements.txt", "code": "fastapi\nuvicorn\npydantic"}



Admin (to chat_manager):

{"type":"user_message","data":{"role":"user","content":"lets do that","user_id":"lnr@gmail.com","session_id":"session-1","workflow_id":"1","name":"Workflow 1","description":"This is Workflow 1","meta":{}}}


ERROR Error code: 400 - {'error': {'message': "An assistant message with 'tool_calls' must be followed by tool messages responding to each 'tool_call_id'. The following tool_call_ids did not have response messages: call_iU7vNDsoM1tvc3edFYTD0Doz, call_Td2Tl7bRUqqXQMgBqgS1vFnx, call_yEb0kn0l8i2chTctrjdBKvyK, call_RbdExb0zp7nNThhrdS3cNOCE, call_af5zAiNv0uvpdvEvVR66CNbQ, call_m5WezLx58oUEaR52ozXS2DKp, call_C6yjdKEjRX4LOdmGYYNPgYgt, call_m62lKCK2po7e45JeuJsVomj1, call_73NQO9jeoDsI3ilxMJk3fBW4, call_Qz5HROVfobNTpsYwL1BXF5cy, call_4uGkyvbiDlhQunD1bX67eOow, call_mqeyEY85ht99kQXDptsyWf3c, call_Z56dIfUXbe0HAKlDlG30Shtn, call_fhq0ZKPBZif08mCyOlLsI3PN, call_VDSrfYIglP0p0k3CTKZCIh5x", 'type': 'invalid_request_error', 'param': 'messages.[14].role', 'code': None}} autogen_chat c5ecce8f-247f-49b2-b9b1-4a67cfe33f53 disconnected ^CINFO: Shutting down INFO: connection closed _GatheringFuture exception was never retrieved future: <_GatheringFuture finished exception=WebSocketDisconnect(1012, None)> Traceback (most recent call last): File "/user/workspace/sample_codegen/main.py", line 49, in receive_from_client data = await autogen_chat.websocket.receive_text() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/opt/homebrew/lib/python3.11/site-packages/starlette/websockets.py", line 138, in receive_text self._raise_on_disconnect(message) File "/opt/homebrew/lib/python3.11/site-packages/starlette/websockets.py", line 130, in _raise_on_disconnect raise WebSocketDisconnect(message["code"], message.get("reason")) starlette.websockets.WebSocketDisconnect: (1012, None) INFO: Waiting for application shutdown. INFO: Application shutdown complete. INFO: Finished server process [78427] INFO: Stopping reloader process [78425] .venv(base) lnr/codegen % uvicorn main:app --reload --port 7878 INFO: Will watch for changes in these directories: ['/user/workspace/sample_codegen'] INFO: Uvicorn running on http://127.0.0.1:7878 (Press CTRL+C to quit) INFO: Started reloader process [89405] using WatchFiles default_path /user/code_workspace INFO: Started server process [89407] INFO: Waiting for application startup. INFO: Application startup complete. The return type of the function 'list_dir' is not annotated. Although annotating it is optional, the function should return either a string, a subclass of 'pydantic.BaseModel'. The return type of the function 'see_file' is not annotated. Although annotating it is optional, the function should return either a string, a subclass of 'pydantic.BaseModel'. The return type of the function 'modify_code' is not annotated. Although annotating it is optional, the function should return either a string, a subclass of 'pydantic.BaseModel'. The return type of the function 'create_file_with_code' is not annotated. Although annotating it is optional, the function should return either a string, a subclass of 'pydantic.BaseModel'. The return type of the function 'move_file_or_directory' is not annotated. Although annotating it is optional, the function should return either a string, a subclass of 'pydantic.BaseModel'. The return type of the function 'delete_file_or_directory' is not annotated. Although annotating it is optional, the function should return either a string, a subclass of 'pydantic.BaseModel'. INFO: ('127.0.0.1', 59479) - "WebSocket /ws/beaa157f-3435-49ab-9b19-9e75976d7d1a" [accepted] INFO: connection open Admin (to chat_manager):

{"type":"connect","message":"Client connected!","connection_id":"beaa157f-3435-49ab-9b19-9e75976d7d1a","wfm_type":"codegen","workflow_id":"1"}


Engineer (to chat_manager):

Hello! How can I assist you with your Python programming tasks today?


Admin (to chat_manager):

{"type":"user_message","data":{"role":"user","content":"lets create a todo-api micro service project using fastapi. Lets use restapi best practice to structure the project. Make sure to have a clear seperation of concerns between database, services and apis. :Lets ahev db models and pydentic schema. Lets manage the dependecies through requirement.txt. For now lets add mock store later we will integrate with real database","user_id":"lnr@gmail.com","session_id":"session-1","workflow_id":"1","name":"Workflow 1","description":"This is Workflow 1","meta":{}}}


Engineer (to chat_manager):

Great! Let's create a ToDo API microservice project using FastAPI with a clear separation of concerns. We'll structure the project as follows:

  1. Project Structure:

    todo_api/
    ├── app/
    │   ├── __init__.py
    │   ├── main.py
    │   ├── api/
    │   │   ├── __init__.py
    │   │   ├── v1/
    │   │   │   ├── __init__.py
    │   │   │   ├── endpoints/
    │   │   │   │   ├── __init__.py
    │   │   │   │   ├── todo.py
    │   ├── core/
    │   │   ├── __init__.py
    │   │   ├── config.py
    │   ├── models/
    │   │   ├── __init__.py
    │   │   ├── todo.py
    │   ├── schemas/
    │   │   ├── __init__.py
    │   │   ├── todo.py
    │   ├── services/
    │   │   ├── __init__.py
    │   │   ├── todo.py
    ├── requirements.txt
    ├── README.md
  2. Files and Code:

    • main.py: Entry point of the application.
    • config.py: Configuration settings.
    • todo.py in models, schemas, and services: Database models, Pydantic schemas, and service logic respectively.
    • todo.py in endpoints: API endpoints.

Let's start by creating the directory structure and the initial files. Suggested tool call (call_TIKOCdcSIyHIVwwbDWDLRrQa): create_file_with_code Arguments: {"filename": "todo_api/app/init.py", "code": ""}


Suggested tool call (call_OCCy3cq7B2eCeNdWYfcEO9HW): create_file_with_code Arguments: {"filename": "todo_api/app/main.py", "code": "from fastapi import FastAPI\nfrom app.api.v1.endpoints import todo\n\napp = FastAPI()\n\napp.include_router(todo.router, prefix=\"/api/v1\", tags=[\"todo\"])\n\n@app.get(\"/\")\ndef read_root():\n return {\"message\": \"Welcome to the ToDo API\"}"}


Suggested tool call (call_qLe159sVAwLxCuwXPvfiqbML): create_file_with_code Arguments: {"filename": "todo_api/app/api/init.py", "code": ""}


Suggested tool call (call_wicVJaHhTvKb8ndkBsbpcJwP): create_file_with_code Arguments: {"filename": "todo_api/app/api/v1/init.py", "code": ""}


Suggested tool call (call_WgJYgReXHCTzdFcqWOzWWn7K): create_file_with_code Arguments: {"filename": "todo_api/app/api/v1/endpoints/init.py", "code": ""}


Suggested tool call (call_0Icyesln76XLw2qjhckts7in): create_file_with_code Arguments: {"filename": "todo_api/app/api/v1/endpoints/todo.py", "code": "from fastapi import APIRouter, HTTPException\nfrom typing import List\nfrom app.schemas.todo import Todo, TodoCreate\nfrom app.services.todo import TodoService\n\nrouter = APIRouter()\n\ntodo_service = TodoService()\n\n@router.post(\"/todos/\", response_model=Todo)\ndef create_todo(todo: TodoCreate):\n return todo_service.create(todo)\n\n@router.get(\"/todos/\", response_model=List[Todo])\ndef read_todos(skip: int = 0, limit: int = 10):\n return todo_service.get_all(skip=skip, limit=limit)\n\n@router.get(\"/todos/{todo_id}\", response_model=Todo)\ndef read_todo(todo_id: int):\n todo = todo_service.get(todo_id)\n if not todo:\n raise HTTPException(status_code=404, detail=\"Todo not found\")\n return todo\n\n@router.put(\"/todos/{todo_id}\", response_model=Todo)\ndef update_todo(todo_id: int, todo: TodoCreate):\n return todo_service.update(todo_id, todo)\n\n@router.delete(\"/todos/{todo_id}\")\ndef delete_todo(todo_id: int):\n todo_service.delete(todo_id)\n return {\"message\": \"Todo deleted\"}"}


Suggested tool call (call_5U7EqkDmxXQrYbMDo4my40ok): create_file_with_code Arguments: {"filename": "todo_api/app/core/init.py", "code": ""}


Suggested tool call (call_gZR2egU0VPJyWmeOVKiyaBnX): create_file_with_code Arguments: {"filename": "todo_api/app/core/config.py", "code": "class Settings:\n PROJECT_NAME: str = \"ToDo API\"\n API_V1_STR: str = \"/api/v1\"\n\nsettings = Settings()"}


Suggested tool call (call_0I9mUAMiXnqfeccLGPCGrbZV): create_file_with_code Arguments: {"filename": "todo_api/app/models/init.py", "code": ""}


Suggested tool call (call_KnUfGVxEjYc5hct6IKTUcR0g): create_file_with_code Arguments: {"filename": "todo_api/app/models/todo.py", "code": "from typing import Optional\n\nclass Todo:\n def init(self, id: int, title: str, description: Optional[str] = None):\n self.id = id\n self.title = title\n self.description = description"}


Suggested tool call (call_n1tOStYmd90UDDYQCuZmI6Fs): create_file_with_code Arguments: {"filename": "todo_api/app/schemas/init.py", "code": ""}


Suggested tool call (call_BZOVQyMzG2xJxhaYDJnWjkII): create_file_with_code Arguments: {"filename": "todo_api/app/schemas/todo.py", "code": "from pydantic import BaseModel\nfrom typing import Optional\n\nclass TodoBase(BaseModel):\n title: str\n description: Optional[str] = None\n\nclass TodoCreate(TodoBase):\n pass\n\nclass Todo(TodoBase):\n id: int\n\n class Config:\n orm_mode = True"}


Suggested tool call (call_Zj4h2jPWvi4nSLjjvGyGu8q8): create_file_with_code Arguments: {"filename": "todo_api/app/services/init.py", "code": ""}


Suggested tool call (call_KLUCocAw2aAiUwKOFA5N2XbL): create_file_with_code Arguments: {"filename": "todo_api/app/services/todo.py", "code": "from typing import List, Optional\nfrom app.models.todo import Todo\nfrom app.schemas.todo import TodoCreate\n\nclass TodoService:\n def init(self):\n self.todos = []\n self.counter = 1\n\n def create(self, todo_create: TodoCreate) -> Todo:\n todo = Todo(id=self.counter, title=todo_create.title, description=todo_create.description)\n self.todos.append(todo)\n self.counter += 1\n return todo\n\n def get_all(self, skip: int = 0, limit: int = 10) -> List[Todo]:\n return self.todos[skip: skip + limit]\n\n def get(self, todo_id: int) -> Optional[Todo]:\n for todo in self.todos:\n if todo.id == todo_id:\n return todo\n return None\n\n def update(self, todo_id: int, todo_create: TodoCreate) -> Optional[Todo]:\n for todo in self.todos:\n if todo.id == todo_id:\n todo.title = todo_create.title\n todo.description = todo_create.description\n return todo\n return None\n\n def delete(self, todo_id: int) -> bool:\n for i, todo in enumerate(self.todos):\n if todo.id == todo_id:\n del self.todos[i]\n return True\n return False"}


Suggested tool call (call_hkr03DFtICXLLZWKr8TYpJk1): create_file_with_code Arguments: {"filename": "todo_api/requirements.txt", "code": "fastapi\nuvicorn"}



Admin (to chat_manager):

{"type":"user_message","data":{"role":"user","content":"How do we proceed next?","user_id":"lnr@gmail.com","session_id":"session-1","workflow_id":"1","name":"Workflow 1","description":"This is Workflow 1","meta":{}}}


ERROR Error code: 400 - {'error': {'message': "An assistant message with 'tool_calls' must be followed by tool messages responding to each 'tool_call_id'. The following tool_call_ids did not have response messages: call_TIKOCdcSIyHIVwwbDWDLRrQa, call_OCCy3cq7B2eCeNdWYfcEO9HW, call_qLe159sVAwLxCuwXPvfiqbML, call_wicVJaHhTvKb8ndkBsbpcJwP, call_WgJYgReXHCTzdFcqWOzWWn7K, call_0Icyesln76XLw2qjhckts7in, call_5U7EqkDmxXQrYbMDo4my40ok, call_gZR2egU0VPJyWmeOVKiyaBnX, call_0I9mUAMiXnqfeccLGPCGrbZV, call_KnUfGVxEjYc5hct6IKTUcR0g, call_n1tOStYmd90UDDYQCuZmI6Fs, call_BZOVQyMzG2xJxhaYDJnWjkII, call_Zj4h2jPWvi4nSLjjvGyGu8q8, call_KLUCocAw2aAiUwKOFA5N2XbL, call_hkr03DFtICXLLZWKr8TYpJk1", 'type': 'invalid_request_error', 'param': 'messages.[5].role', 'code': None}} autogen_chat beaa157f-3435-49ab-9b19-9e75976d7d1a disconnected

Code from typing import Annotated import os import autogen from user_proxy_webagent import UserProxyWebAgent import asyncio import shutil # Import shutil for file operations

default_path = os.getenv( "DEFAULT_PATH", "code_workspace/" ) default_path = os.path.expanduser(default_path) openai_api_key = os.getenv("OPENAI_API_KEY")

print("default_path", default_path)

config_list = [ { "model": "gpt-4o", } ]

llm_config_engineer = { "model": "gpt-4o", "temperature": 0, "config_list": config_list, }

class AutogenChat: def init(self, chat_id=None, websocket=None): self.websocket = websocket self.chat_id = chat_id self.client_sent_queue = asyncio.Queue() self.client_receive_queue = asyncio.Queue()

    self.engineer = autogen.AssistantAgent(
        name="Engineer",
        llm_config=llm_config_engineer,
        system_message="""I'm Engineer. I'm an expert in Python programming. I'm executing code tasks required by Admin.""",
    )
    self.user_proxy = UserProxyWebAgent(
        name="Admin",
        human_input_mode="ALWAYS",
        max_consecutive_auto_reply=10,
        is_termination_msg=lambda x: x.get("content", "")
        and x.get("content", "").rstrip().endswith("TERMINATE"),
        code_execution_config=False,
    )

    self.groupchat = autogen.GroupChat(
        agents=[self.engineer, self.user_proxy],
        messages=[],
        max_round=500,
        speaker_selection_method="round_robin",
        enable_clear_history=True,
    )

    self.manager = autogen.GroupChatManager(
        groupchat=self.groupchat, llm_config=llm_config_engineer
    )

    self.user_proxy.set_queues(self.client_sent_queue, self.client_receive_queue)

    # Add the queues to communicate

    @self.user_proxy.register_for_execution()
    @self.engineer.register_for_llm(description="List files in a chosen directory.")
    def list_dir(directory: Annotated[str, "Directory to check."]):
        files = os.listdir(os.path.join(default_path, directory))
        return 0, files

    @self.user_proxy.register_for_execution()
    @self.engineer.register_for_llm(
        description="Check the contents of a chosen file."
    )
    def see_file(filename: Annotated[str, "Name and path of file to check."]):
        with open(os.path.join(default_path, filename), "r") as file:
            lines = file.readlines()
        formatted_lines = [f"{i + 1}:{line}" for i, line in enumerate(lines)]
        file_contents = "".join(formatted_lines)

        return 0, file_contents

    @self.user_proxy.register_for_execution()
    @self.engineer.register_for_llm(
        description="Replace old piece of code with a new one. Proper indentation is important."
    )
    def modify_code(
        filename: Annotated[str, "Name and path of file to change."],
        start_line: Annotated[int, "Start line number to replace with new code."],
        end_line: Annotated[int, "End line number to replace with new code."],
        new_code: Annotated[
            str,
            "New piece of code to replace old code with. Remember to provide indents.",
        ],
    ):
        with open(os.path.join(default_path, filename), "r+") as file:
            file_contents = file.readlines()
            file_contents[start_line - 1 : end_line] = [new_code + "\n"]
            file.seek(0)
            file.truncate()
            file.write("".join(file_contents))
        return 0, "Code modified"

    @self.user_proxy.register_for_execution()
    @self.engineer.register_for_llm(description="Create a new file with code.")
    def create_file_with_code(
        filename: Annotated[str, "Name and path of file to create."],
        code: Annotated[str, "Code to write in the file."],
    ):
        # Construct the full file path
        code_file_path = os.path.join(default_path, filename)
        print("####code_file_path", code_file_path)

        # Extract the directory from the file path
        directory = os.path.dirname(code_file_path)

        # Create the directory if it does not exist
        os.makedirs(directory, exist_ok=True)

        # Create and write to the file
        with open(code_file_path, "w") as file:
            file.write(code)
            file.flush()  # Ensure all data is written to disk
            os.fsync(file.fileno())  # Ensure all data is written to disk

        return 0, "File created successfully"

    @self.user_proxy.register_for_execution()
    @self.engineer.register_for_llm(
        description="Move a file or directory to a new location."
    )
    def move_file_or_directory(
        source_path: Annotated[str, "Source path of the file or directory."],
        destination_path: Annotated[
            str, "Destination path where the file or directory should be moved."
        ],
    ):
        full_source_path = os.path.join(default_path, source_path)
        full_destination_path = os.path.join(default_path, destination_path)
        shutil.move(full_source_path, full_destination_path)
        return 0, f"Moved {source_path} to {destination_path}"

    @self.user_proxy.register_for_execution()
    @self.engineer.register_for_llm(description="Delete a file or directory.")
    def delete_file_or_directory(
        path: Annotated[str, "Path of the file or directory to delete."],
    ):
        full_path = os.path.join(default_path, path)
        if os.path.isdir(full_path):
            shutil.rmtree(full_path)
            return 0, f"Directory {path} deleted successfully."
        elif os.path.isfile(full_path):
            os.remove(full_path)
            return 0, f"File {path} deleted successfully."
        else:
            return 1, f"Path {path} does not exist."

async def start(self, message):
    await self.user_proxy.a_initiate_chat(
        self.manager, clear_history=True, message=message
    )

# Mock function call
def search_db(self, order_number=None, customer_number=None):
    return "Order status: delivered TERMINATE"

Steps to reproduce

No response

Model Used

No response

Expected Behavior

No response

Screenshots and logs

No response

Additional Information

No response

raolak commented 1 month ago

Happy to get in to call and collaborate on fixing this issue!