Skip to content

Commit 42ce1d9

Browse files
byteciiWendong-Fan
andauthored
refactor: format python backend code (#1132)
Co-authored-by: bytecii <bytecii@users.noreply.github.com> Co-authored-by: Wendong-Fan <133094783+Wendong-Fan@users.noreply.github.com>
1 parent 649bdc6 commit 42ce1d9

45 files changed

Lines changed: 1636 additions & 823 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/pre-commit.yml

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -30,21 +30,31 @@ jobs:
3030
run: uv sync --group dev
3131

3232
- name: Run pre-commit
33-
run: >-
34-
uv run pre-commit run --files
35-
app/agent/README.md
36-
app/agent/__init__.py
37-
app/agent/factory/__init__.py
38-
app/agent/factory/social_media.py
39-
app/service/chat_service.py
40-
app/service/task.py
41-
app/utils/toolkit/google_calendar_toolkit.py
42-
app/utils/toolkit/google_gmail_mcp_toolkit.py
43-
app/utils/toolkit/linkedin_toolkit.py
44-
app/utils/toolkit/reddit_toolkit.py
45-
app/utils/toolkit/slack_toolkit.py
46-
app/utils/toolkit/twitter_toolkit.py
47-
app/utils/toolkit/whatsapp_toolkit.py
48-
tests/app/agent/factory/test_social_media.py
33+
run: |
34+
uv run pre-commit run --files \
35+
$(find \
36+
app/agent \
37+
app/controller \
38+
app/exception \
39+
app/middleware \
40+
app/model \
41+
app/service \
42+
tests/app \
43+
-type f ! -path '*__pycache__*') \
44+
app/__init__.py \
45+
app/router.py \
46+
app/component/__init__.py \
47+
app/component/pydantic/__init__.py \
48+
app/utils/listen/__init__.py \
49+
app/utils/server/__init__.py \
50+
app/utils/toolkit/__init__.py \
51+
app/utils/toolkit/google_calendar_toolkit.py \
52+
app/utils/toolkit/google_gmail_mcp_toolkit.py \
53+
app/utils/toolkit/linkedin_toolkit.py \
54+
app/utils/toolkit/reddit_toolkit.py \
55+
app/utils/toolkit/slack_toolkit.py \
56+
app/utils/toolkit/twitter_toolkit.py \
57+
app/utils/toolkit/whatsapp_toolkit.py \
58+
tests/conftest.py
4959
env:
5060
SKIP: no-commit-to-branch

.github/workflows/test.yml

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
name: Test
2+
3+
'on':
4+
pull_request:
5+
branches:
6+
- main
7+
push:
8+
branches:
9+
- main
10+
11+
permissions:
12+
contents: read
13+
14+
jobs:
15+
pytest:
16+
name: Run Python Tests
17+
runs-on: ubuntu-latest
18+
19+
steps:
20+
- name: Checkout code
21+
uses: actions/checkout@v4
22+
23+
- name: Install uv
24+
uses: astral-sh/setup-uv@v5
25+
with:
26+
enable-cache: true
27+
28+
- name: Set up Python
29+
run: uv python install 3.10
30+
31+
- name: Install dependencies
32+
run: |
33+
cd backend
34+
uv sync
35+
36+
- name: Run unit tests
37+
run: |
38+
cd backend
39+
uv run pytest tests/app -v

backend/app/__init__.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,9 @@
2020

2121
# Add CORS middleware
2222
api.add_middleware(
23-
CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"]
23+
CORSMiddleware,
24+
allow_origins=["*"],
25+
allow_credentials=True,
26+
allow_methods=["*"],
27+
allow_headers=["*"]
2428
)

backend/app/agent/agent_model.py

Lines changed: 35 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -19,21 +19,23 @@
1919
from threading import Lock
2020
from typing import Any, Callable
2121

22-
from app.agent.listen_chat_agent import ListenChatAgent, logger
23-
from app.model.chat import AgentModelConfig, Chat
24-
from app.service.task import ActionCreateAgentData, Agents, get_task_lock
2522
from camel.messages import BaseMessage
2623
from camel.models import ModelFactory
2724
from camel.toolkits import FunctionTool, RegisteredAgentToolkit
2825
from camel.types import ModelPlatformType
2926

27+
from app.agent.listen_chat_agent import ListenChatAgent, logger
28+
from app.model.chat import AgentModelConfig, Chat
29+
from app.service.task import ActionCreateAgentData, Agents, get_task_lock
30+
3031
# Thread-safe reference to main event loop using contextvars
3132
# This ensures each request has its own event loop reference,
3233
# avoiding race conditions
3334
_main_event_loop_var: contextvars.ContextVar[asyncio.AbstractEventLoop
3435
| None] = contextvars.ContextVar(
3536
"_main_event_loop",
36-
default=None)
37+
default=None
38+
)
3739

3840
# Global fallback for main event loop reference
3941
# Used when contextvars don't propagate to worker threads
@@ -77,10 +79,12 @@ def _schedule_async_task(coro):
7779
asyncio.run_coroutine_threadsafe(coro, main_loop)
7880
else:
7981
# This should not happen in normal operation - log error and skip
80-
logging.error("No event loop available for async task "
81-
"scheduling, task skipped. Ensure "
82-
"set_main_event_loop() is called "
83-
"before parallel agent creation.")
82+
logging.error(
83+
"No event loop available for async task "
84+
"scheduling, task skipped. Ensure "
85+
"set_main_event_loop() is called "
86+
"before parallel agent creation."
87+
)
8488

8589

8690
def agent_model(
@@ -96,8 +100,10 @@ def agent_model(
96100
):
97101
task_lock = get_task_lock(options.project_id)
98102
agent_id = str(uuid.uuid4())
99-
logger.info(f"Creating agent: {agent_name} with id: {agent_id} "
100-
f"for project: {options.project_id}")
103+
logger.info(
104+
f"Creating agent: {agent_name} with id: {agent_id} "
105+
f"for project: {options.project_id}"
106+
)
101107
# Use thread-safe scheduling to support parallel agent creation
102108
_schedule_async_task(
103109
task_lock.put_queue(
@@ -106,7 +112,10 @@ def agent_model(
106112
"agent_name": agent_name,
107113
"agent_id": agent_id,
108114
"tools": tool_names or [],
109-
})))
115+
}
116+
)
117+
)
118+
)
110119

111120
# Determine model configuration - use custom config if provided,
112121
# otherwise use task defaults
@@ -117,11 +126,14 @@ def agent_model(
117126
for attr in config_attrs:
118127
effective_config[attr] = getattr(custom_model_config, attr,
119128
None) or getattr(options, attr)
120-
extra_params = (custom_model_config.extra_params
121-
or options.extra_params or {})
122-
logger.info(f"Agent {agent_name} using custom model config: "
123-
f"platform={effective_config['model_platform']}, "
124-
f"type={effective_config['model_type']}")
129+
extra_params = (
130+
custom_model_config.extra_params or options.extra_params or {}
131+
)
132+
logger.info(
133+
f"Agent {agent_name} using custom model config: "
134+
f"platform={effective_config['model_platform']}, "
135+
f"type={effective_config['model_type']}"
136+
)
125137
else:
126138
for attr in config_attrs:
127139
effective_config[attr] = getattr(options, attr)
@@ -163,13 +175,14 @@ def agent_model(
163175
if agent_name == Agents.browser_agent:
164176
try:
165177
model_platform_enum = ModelPlatformType(
166-
effective_config["model_platform"].lower())
178+
effective_config["model_platform"].lower()
179+
)
167180
if model_platform_enum in {
168-
ModelPlatformType.OPENAI,
169-
ModelPlatformType.AZURE,
170-
ModelPlatformType.OPENAI_COMPATIBLE_MODEL,
171-
ModelPlatformType.LITELLM,
172-
ModelPlatformType.OPENROUTER,
181+
ModelPlatformType.OPENAI,
182+
ModelPlatformType.AZURE,
183+
ModelPlatformType.OPENAI_COMPATIBLE_MODEL,
184+
ModelPlatformType.LITELLM,
185+
ModelPlatformType.OPENROUTER,
173186
}:
174187
model_config["parallel_tool_calls"] = False
175188
except (ValueError, AttributeError):

backend/app/agent/factory/browser.py

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
import platform
1616
import uuid
1717

18+
from camel.messages import BaseMessage
19+
from camel.toolkits import ToolkitMessageIntegration
20+
1821
from app.agent.agent_model import agent_model
1922
from app.agent.listen_chat_agent import logger
2023
from app.agent.prompt import BROWSER_SYS_PROMPT
@@ -25,21 +28,23 @@
2528
from app.utils.file_utils import get_working_directory
2629
from app.utils.toolkit.human_toolkit import HumanToolkit
2730
from app.utils.toolkit.hybrid_browser_toolkit import HybridBrowserToolkit
31+
2832
# TODO: Remove NoteTakingToolkit and use TerminalToolkit instead
2933
from app.utils.toolkit.note_taking_toolkit import NoteTakingToolkit
3034
from app.utils.toolkit.search_toolkit import SearchToolkit
3135
from app.utils.toolkit.terminal_toolkit import TerminalToolkit
32-
from camel.messages import BaseMessage
33-
from camel.toolkits import ToolkitMessageIntegration
3436

3537

3638
def browser_agent(options: Chat):
3739
working_directory = get_working_directory(options)
38-
logger.info(f"Creating browser agent for project: {options.project_id} "
39-
f"in directory: {working_directory}")
40+
logger.info(
41+
f"Creating browser agent for project: {options.project_id} "
42+
f"in directory: {working_directory}"
43+
)
4044
message_integration = ToolkitMessageIntegration(
41-
message_handler=HumanToolkit(
42-
options.project_id, Agents.browser_agent).send_message_to_user)
45+
message_handler=HumanToolkit(options.project_id, Agents.browser_agent
46+
).send_message_to_user
47+
)
4348

4449
web_toolkit_custom = HybridBrowserToolkit(
4550
options.project_id,
@@ -70,7 +75,8 @@ def browser_agent(options: Chat):
7075
# Save reference before registering for toolkits_to_register_agent
7176
web_toolkit_for_agent_registration = web_toolkit_custom
7277
web_toolkit_custom = message_integration.register_toolkits(
73-
web_toolkit_custom)
78+
web_toolkit_custom
79+
)
7480

7581
terminal_toolkit = TerminalToolkit(
7682
options.project_id,
@@ -80,11 +86,14 @@ def browser_agent(options: Chat):
8086
clone_current_env=True,
8187
)
8288
terminal_toolkit = message_integration.register_functions(
83-
[terminal_toolkit.shell_exec])
89+
[terminal_toolkit.shell_exec]
90+
)
8491

85-
note_toolkit = NoteTakingToolkit(options.project_id,
86-
Agents.browser_agent,
87-
working_directory=working_directory)
92+
note_toolkit = NoteTakingToolkit(
93+
options.project_id,
94+
Agents.browser_agent,
95+
working_directory=working_directory
96+
)
8897
note_toolkit = message_integration.register_toolkits(note_toolkit)
8998

9099
search_tools = SearchToolkit.get_can_use_tools(options.project_id)
@@ -94,8 +103,8 @@ def browser_agent(options: Chat):
94103
search_tools = []
95104

96105
tools = [
97-
*HumanToolkit.get_can_use_tools(options.project_id,
98-
Agents.browser_agent),
106+
*HumanToolkit.
107+
get_can_use_tools(options.project_id, Agents.browser_agent),
99108
*web_toolkit_custom.get_tools(),
100109
*terminal_toolkit,
101110
*note_toolkit.get_tools(),

backend/app/agent/factory/developer.py

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414

1515
import platform
1616

17+
from camel.messages import BaseMessage
18+
from camel.toolkits import ToolkitMessageIntegration
19+
1720
from app.agent.agent_model import agent_model
1821
from app.agent.listen_chat_agent import logger
1922
from app.agent.prompt import DEVELOPER_SYS_PROMPT
@@ -22,22 +25,25 @@
2225
from app.service.task import Agents
2326
from app.utils.file_utils import get_working_directory
2427
from app.utils.toolkit.human_toolkit import HumanToolkit
28+
2529
# TODO: Remove NoteTakingToolkit and use TerminalToolkit instead
2630
from app.utils.toolkit.note_taking_toolkit import NoteTakingToolkit
2731
from app.utils.toolkit.screenshot_toolkit import ScreenshotToolkit
2832
from app.utils.toolkit.terminal_toolkit import TerminalToolkit
2933
from app.utils.toolkit.web_deploy_toolkit import WebDeployToolkit
30-
from camel.messages import BaseMessage
31-
from camel.toolkits import ToolkitMessageIntegration
3234

3335

3436
async def developer_agent(options: Chat):
3537
working_directory = get_working_directory(options)
36-
logger.info(f"Creating developer agent for project: {options.project_id} "
37-
f"in directory: {working_directory}")
38+
logger.info(
39+
f"Creating developer agent for project: {options.project_id} "
40+
f"in directory: {working_directory}"
41+
)
3842
message_integration = ToolkitMessageIntegration(
3943
message_handler=HumanToolkit(
40-
options.project_id, Agents.developer_agent).send_message_to_user)
44+
options.project_id, Agents.developer_agent
45+
).send_message_to_user
46+
)
4147
note_toolkit = NoteTakingToolkit(
4248
api_task_id=options.project_id,
4349
agent_name=Agents.developer_agent,
@@ -46,11 +52,14 @@ async def developer_agent(options: Chat):
4652
note_toolkit = message_integration.register_toolkits(note_toolkit)
4753
web_deploy_toolkit = WebDeployToolkit(api_task_id=options.project_id)
4854
web_deploy_toolkit = message_integration.register_toolkits(
49-
web_deploy_toolkit)
50-
screenshot_toolkit = ScreenshotToolkit(options.project_id,
51-
working_directory=working_directory)
55+
web_deploy_toolkit
56+
)
57+
screenshot_toolkit = ScreenshotToolkit(
58+
options.project_id, working_directory=working_directory
59+
)
5260
screenshot_toolkit = message_integration.register_toolkits(
53-
screenshot_toolkit)
61+
screenshot_toolkit
62+
)
5463

5564
terminal_toolkit = TerminalToolkit(
5665
options.project_id,
@@ -62,8 +71,8 @@ async def developer_agent(options: Chat):
6271
terminal_toolkit = message_integration.register_toolkits(terminal_toolkit)
6372

6473
tools = [
65-
*HumanToolkit.get_can_use_tools(options.project_id,
66-
Agents.developer_agent),
74+
*HumanToolkit.
75+
get_can_use_tools(options.project_id, Agents.developer_agent),
6776
*note_toolkit.get_tools(),
6877
*web_deploy_toolkit.get_tools(),
6978
*terminal_toolkit.get_tools(),

0 commit comments

Comments
 (0)