Merge branch 'upgrade/deepagents-0.4.4'

This commit is contained in:
朱潮 2026-03-04 14:08:51 +08:00
commit f7773a93e1
9 changed files with 1325 additions and 319 deletions

View File

@ -0,0 +1,179 @@
#!/usr/bin/env python3
"""
自定义 FilesystemMiddleware - 支持 SKILL.md 文件完整读取
"""
from pathlib import Path
from typing import Annotated, Literal, cast
from langchain.tools import ToolRuntime
from langchain_core.messages import ToolMessage
from langchain_core.tools import BaseTool, StructuredTool
from typing_extensions import override
from deepagents.backends import StateBackend
from deepagents.backends.composite import CompositeBackend
from deepagents.backends.protocol import (
BACKEND_TYPES,
)
from deepagents.middleware.filesystem import (
DEFAULT_READ_OFFSET,
DEFAULT_READ_LIMIT,
IMAGE_EXTENSIONS,
IMAGE_MEDIA_TYPES,
FilesystemMiddleware,
FilesystemState,
)
from langgraph.types import Command
import base64
from langchain_core.messages.content import create_image_block
# SKILL.md 文件的行数限制(设置为较大的值以完整读取)
SKILL_MD_READ_LIMIT = 100000
class CustomFilesystemMiddleware(FilesystemMiddleware):
"""自定义 FilesystemMiddleware支持 SKILL.md 文件完整读取。
继承自 deepagents.middleware.filesystem.FilesystemMiddleware
覆盖 read_file 工具使 SKILL.md 文件可以完整读取
"""
@override
def _create_read_file_tool(self) -> BaseTool:
"""创建自定义的 read_file 工具,支持 SKILL.md 完整读取。"""
# 从父类获取工具描述
tool_description = self._custom_tool_descriptions.get("read_file") or self._get_read_file_description()
token_limit = self._tool_token_limit_before_evict
def sync_read_file(
file_path: Annotated[str, "Absolute path to the file to read. Must be absolute, not relative."],
runtime: ToolRuntime[None, FilesystemState],
offset: Annotated[int, "Line number to start reading from (0-indexed). Use for pagination of large files."] = DEFAULT_READ_OFFSET,
limit: Annotated[int, "Maximum number of lines to read. Use for pagination of large files."] = DEFAULT_READ_LIMIT,
) -> ToolMessage | str:
"""Synchronous wrapper for read_file tool with SKILL.md special handling."""
from deepagents.backends.utils import validate_path
from deepagents.middleware.filesystem import READ_FILE_TRUNCATION_MSG, NUM_CHARS_PER_TOKEN
resolved_backend = self._get_backend(runtime)
try:
validated_path = validate_path(file_path)
except ValueError as e:
return f"Error: {e}"
ext = Path(validated_path).suffix.lower()
# 处理图片文件
if ext in IMAGE_EXTENSIONS:
responses = resolved_backend.download_files([validated_path])
if responses and responses[0].content is not None:
media_type = IMAGE_MEDIA_TYPES.get(ext, "image/png")
image_b64 = base64.standard_b64encode(responses[0].content).decode("utf-8")
return ToolMessage(
content_blocks=[create_image_block(base64=image_b64, mime_type=media_type)],
name="read_file",
tool_call_id=runtime.tool_call_id,
additional_kwargs={
"read_file_path": validated_path,
"read_file_media_type": media_type,
},
)
if responses and responses[0].error:
return f"Error reading image: {responses[0].error}"
return "Error reading image: unknown error"
# 如果是 SKILL.md 文件,使用大限制读取完整内容
if validated_path.endswith("SKILL.md") or validated_path.endswith("/SKILL.md"):
actual_limit = SKILL_MD_READ_LIMIT
else:
actual_limit = limit
result = resolved_backend.read(validated_path, offset=offset, limit=actual_limit)
lines = result.splitlines(keepends=True)
if len(lines) > actual_limit:
lines = lines[:actual_limit]
result = "".join(lines)
# Check if result exceeds token threshold and truncate if necessary
if token_limit and len(result) >= NUM_CHARS_PER_TOKEN * token_limit:
# Calculate truncation message length to ensure final result stays under threshold
truncation_msg = READ_FILE_TRUNCATION_MSG.format(file_path=validated_path)
max_content_length = NUM_CHARS_PER_TOKEN * token_limit - len(truncation_msg)
result = result[:max_content_length]
result += truncation_msg
return result
async def async_read_file(
file_path: Annotated[str, "Absolute path to the file to read. Must be absolute, not relative."],
runtime: ToolRuntime[None, FilesystemState],
offset: Annotated[int, "Line number to start reading from (0-indexed). Use for pagination of large files."] = DEFAULT_READ_OFFSET,
limit: Annotated[int, "Maximum number of lines to read. Use for pagination of large files."] = DEFAULT_READ_LIMIT,
) -> ToolMessage | str:
"""Asynchronous wrapper for read_file tool with SKILL.md special handling."""
from deepagents.backends.utils import validate_path
from deepagents.middleware.filesystem import READ_FILE_TRUNCATION_MSG, NUM_CHARS_PER_TOKEN
resolved_backend = self._get_backend(runtime)
try:
validated_path = validate_path(file_path)
except ValueError as e:
return f"Error: {e}"
ext = Path(validated_path).suffix.lower()
# 处理图片文件
if ext in IMAGE_EXTENSIONS:
responses = await resolved_backend.adownload_files([validated_path])
if responses and responses[0].content is not None:
media_type = IMAGE_MEDIA_TYPES.get(ext, "image/png")
image_b64 = base64.standard_b64encode(responses[0].content).decode("utf-8")
return ToolMessage(
content_blocks=[create_image_block(base64=image_b64, mime_type=media_type)],
name="read_file",
tool_call_id=runtime.tool_call_id,
additional_kwargs={
"read_file_path": validated_path,
"read_file_media_type": media_type,
},
)
if responses and responses[0].error:
return f"Error reading image: {responses[0].error}"
return "Error reading image: unknown error"
# 如果是 SKILL.md 文件,使用大限制读取完整内容
if validated_path.endswith("SKILL.md") or validated_path.endswith("/SKILL.md"):
actual_limit = SKILL_MD_READ_LIMIT
else:
actual_limit = limit
result = await resolved_backend.aread(validated_path, offset=offset, limit=actual_limit)
lines = result.splitlines(keepends=True)
if len(lines) > actual_limit:
lines = lines[:actual_limit]
result = "".join(lines)
# Check if result exceeds token threshold and truncate if necessary
if token_limit and len(result) >= NUM_CHARS_PER_TOKEN * token_limit:
# Calculate truncation message length to ensure final result stays under threshold
truncation_msg = READ_FILE_TRUNCATION_MSG.format(file_path=validated_path)
max_content_length = NUM_CHARS_PER_TOKEN * token_limit - len(truncation_msg)
result = result[:max_content_length]
result += truncation_msg
return result
return StructuredTool.from_function(
name="read_file",
description=tool_description,
func=sync_read_file,
coroutine=async_read_file,
)
def _get_read_file_description(self) -> str:
"""获取 read_file 工具的描述,添加 SKILL.md 完整读取的说明。"""
from deepagents.middleware.filesystem import READ_FILE_TOOL_DESCRIPTION
return READ_FILE_TOOL_DESCRIPTION

View File

@ -3,11 +3,12 @@ import logging
import time
import copy
import os
import tempfile
from pathlib import Path
from typing import Any, Dict
from langchain.chat_models import init_chat_model
from deepagents import create_deep_agent
from deepagents.backends import CompositeBackend
from deepagents.backends import CompositeBackend, LocalShellBackend
from deepagents.backends.filesystem import FilesystemBackend
from deepagents.backends.sandbox import SandboxBackendProtocol
from deepagents_cli.agent import create_cli_agent
@ -42,17 +43,20 @@ from langgraph.checkpoint.memory import InMemorySaver
from langchain.tools import BaseTool
from langchain_core.language_models import BaseChatModel
from langgraph.pregel import Pregel
from deepagents_cli.shell import ShellMiddleware
from deepagents_cli.agent_memory import AgentMemoryMiddleware
# 新版本导入MemoryMiddleware 和 SkillsMiddleware 已迁移到 deepagents.middleware
from deepagents.middleware import MemoryMiddleware, SkillsMiddleware
from langchain.agents.middleware import AgentMiddleware
from langgraph.types import Checkpointer
from deepagents_cli.skills import SkillsMiddleware
from deepagents_cli.config import settings, get_default_coding_instructions
from langchain.agents.middleware import HumanInTheLoopMiddleware, InterruptOnConfig, TodoListMiddleware
from deepagents.middleware.filesystem import FilesystemMiddleware
from deepagents.middleware.patch_tool_calls import PatchToolCallsMiddleware
from langchain_anthropic.middleware import AnthropicPromptCachingMiddleware
from deepagents.graph import BASE_AGENT_PROMPT
# 新增LocalContextMiddleware
from deepagents_cli.local_context import LocalContextMiddleware
# 自定义:支持 SKILL.md 完整读取的 FilesystemMiddleware
from .custom_filesystem_middleware import CustomFilesystemMiddleware
# 全局 MemorySaver 实例
# from langgraph.checkpoint.memory import MemorySaver
@ -270,15 +274,15 @@ async def init_agent(config: AgentConfig):
token_counter=create_token_counter(config.model_name)
)
middleware.append(summarization_middleware)
workspace_root = f"projects/robot/{config.bot_id}"
workspace_root = str(Path.cwd() / "projects" /"robot"/ config.bot_id)
# workspace_root = str(Path.home() / ".deepagents" / config.bot_id)
agent, composite_backend = create_custom_cli_agent(
model=llm_instance,
assistant_id=config.bot_id,
system_prompt=system_prompt,
tools=mcp_tools,
auto_approve=True,
enable_memory=False,
workspace_root=workspace_root,
middleware=middleware,
checkpointer=checkpointer,
@ -292,77 +296,14 @@ async def init_agent(config: AgentConfig):
logger.info(f"create agent elapsed: {time.time() - create_start:.3f}s")
return agent, checkpointer
class CustomAgentMemoryMiddleware(AgentMemoryMiddleware):
def __init__(
self,
*,
settings,
assistant_id: str,
system_prompt_template: str | None = None,
) -> None:
super().__init__(
settings=settings,
assistant_id=assistant_id,
system_prompt_template=system_prompt_template
)
self.agent_dir_display = f"."
class CustomSkillsMiddleware(SkillsMiddleware):
def __init__(
self,
*,
skills_dir: str | Path,
assistant_id: str,
project_skills_dir: str | Path | None = None,
) -> None:
super().__init__(
skills_dir=skills_dir,
assistant_id=assistant_id,
project_skills_dir=project_skills_dir
)
self.skills_dir = None
self.project_skills_display = f"./skills"
"""自定义的 SkillsMiddleware使用新的签名格式"""
def _format_skills_locations(self) -> str:
"""Format skills locations for display in system prompt."""
return "**Project Skills**: `{self.project_skills_dir}`"
def _format_skills_list(self, skills) -> str:
"""Format skills metadata for display in system prompt."""
if not skills:
locations = [f"{self.user_skills_display}/"]
if self.project_skills_dir:
locations.append(f"{self.project_skills_display}/")
return f"(No skills available yet. You can create skills in {' or '.join(locations)})"
# Group skills by source
user_skills = [s for s in skills if s["source"] == "user"]
project_skills = [s for s in skills if s["source"] == "project"]
lines = []
# Show user skills
if user_skills:
lines.append("**User Skills:**")
for skill in user_skills:
lines.append(f"- **{skill['name']}**: {skill['description']}")
lines.append(f" → Read `{skill['path']}` for full instructions")
lines.append("")
# Show project skills
if project_skills:
lines.append("**Project Skills:**")
for skill in project_skills:
lines.append(f"- **{skill['name']}**: {skill['description']}")
lines.append(f" → Read `{skill['path']}` for full instructions")
return "\n".join(lines)
def before_agent(self, state, runtime):
def before_agent(self, state, runtime, config):
"""Load skills metadata before agent execution.
This runs once at session start to discover available skills from both
user-level and project-level directories.
修改路径显示为相对路径
Args:
state: Current agent state.
@ -371,12 +312,26 @@ class CustomSkillsMiddleware(SkillsMiddleware):
Returns:
Updated state with skills_metadata populated.
"""
state = super().before_agent(state, runtime)
for item in state["skills_metadata"]:
if item["source"] == "project":
item["path"] = self.project_skills_display + item["path"].replace(str(self.project_skills_dir), "")
else:
item["path"] = self.user_skills_display + item["path"].replace(str(self.skills_dir), "")
if "skills_metadata" in state and len(state["skills_metadata"]) ==0 :
del state["skills_metadata"]
state = super().before_agent(state, runtime, config)
return state
async def abefore_agent(self, state, runtime, config):
"""Load skills metadata before agent execution.
修改路径显示为相对路径
Args:
state: Current agent state.
runtime: Runtime context.
Returns:
Updated state with skills_metadata populated.
"""
if "skills_metadata" in state and len(state["skills_metadata"]) ==0 :
del state["skills_metadata"]
state = await super().abefore_agent(state, runtime, config)
return state
def create_custom_cli_agent(
@ -388,7 +343,6 @@ def create_custom_cli_agent(
sandbox_type: str | None = None,
system_prompt: str | None = None,
auto_approve: bool = False,
enable_memory: bool = True,
enable_skills: bool = True,
enable_shell: bool = True,
middleware: list[AgentMiddleware] = [],
@ -431,58 +385,65 @@ def create_custom_cli_agent(
if tools is None:
tools = []
# Setup agent directory for persistent memory (if enabled)
if enable_memory or enable_skills:
agent_dir = settings.ensure_agent_dir(assistant_id)
agent_md = agent_dir / "agent.md"
if not agent_md.exists():
source_content = get_default_coding_instructions()
agent_md.write_text(source_content)
# Build middleware stack based on enabled features
agent_middleware = middleware
# Prepare workspace root
if workspace_root is None:
workspace_root = str(Path.cwd())
# CONDITIONAL SETUP: Local vs Remote Sandbox
if sandbox is None:
# ========== LOCAL MODE ==========
composite_backend = CompositeBackend(
default=FilesystemBackend(root_dir=workspace_root, virtual_mode=True), # Current working directory
routes={}, # No virtualization - use real paths
)
# Add memory middleware
if enable_memory:
agent_middleware.append(
CustomAgentMemoryMiddleware(settings=settings, assistant_id=assistant_id)
)
# Add skills middleware
if enable_skills:
agent_middleware.append(
CustomSkillsMiddleware(
skills_dir=workspace_root,
project_skills_dir=workspace_root+"/skills",
assistant_id=assistant_id
)
)
# Add shell middleware (only in local mode)
if enable_shell:
# Create environment for shell commands
# Start with a copy of current environment
final_shell_env = os.environ.copy()
# Merge custom environment variables if provided (custom vars take precedence)
if shell_env:
final_shell_env.update(shell_env)
# Use custom workspace_root if provided, otherwise use current directory
shell_workspace = workspace_root if workspace_root is not None else str(Path.cwd())
agent_middleware.append(
ShellMiddleware(
workspace_root=shell_workspace,
# Use LocalShellBackend for filesystem + shell execution
backend = LocalShellBackend(
root_dir=workspace_root,
inherit_env=True,
env=final_shell_env,
)
else:
# No shell access - use plain FilesystemBackend
backend = FilesystemBackend(root_dir=workspace_root)
# Set up composite backend with routing (参考新版本实现)
large_results_backend = FilesystemBackend(
root_dir=tempfile.mkdtemp(prefix="deepagents_large_results_"),
)
conversation_history_backend = FilesystemBackend(
root_dir=tempfile.mkdtemp(prefix="deepagents_conversation_history_"),
)
composite_backend = CompositeBackend(
default=backend,
routes={
"/large_tool_results/": large_results_backend,
"/conversation_history/": conversation_history_backend,
},
)
# Add skills middleware (using new signature)
if enable_skills:
skills_sources = ["./skills"]
agent_middleware.append(
CustomSkillsMiddleware(
backend=FilesystemBackend(root_dir=workspace_root),
sources=skills_sources,
)
)
# Add LocalContextMiddleware (new in latest version)
# Check if backend supports execute (is _ExecutableBackend)
if enable_shell:
from deepagents_cli.local_context import LocalContextMiddleware, _ExecutableBackend
if isinstance(backend, _ExecutableBackend):
agent_middleware.append(LocalContextMiddleware(backend=backend))
else:
# ========== REMOTE SANDBOX MODE ==========
composite_backend = CompositeBackend(
@ -490,19 +451,14 @@ def create_custom_cli_agent(
routes={}, # No virtualization
)
# Add memory middleware
if enable_memory:
agent_middleware.append(
CustomAgentMemoryMiddleware(settings=settings, assistant_id=assistant_id)
)
# Add skills middleware
if enable_skills:
skills_sources = ["/skills"]
agent_middleware.append(
CustomSkillsMiddleware(
skills_dir=workspace_root,
project_skills_dir=workspace_root+"/skills",
assistant_id=assistant_id
backend=sandbox,
sources=skills_sources,
)
)
@ -511,30 +467,26 @@ def create_custom_cli_agent(
# Get or use custom system prompt
if system_prompt is None:
# Import get_system_prompt from deepagents_cli.agent
from deepagents_cli.agent import get_system_prompt as _get_system_prompt
system_prompt = _get_system_prompt(assistant_id=assistant_id, sandbox_type=sandbox_type)
# Import InterruptOnConfig
from langchain.agents.middleware import InterruptOnConfig
# Configure interrupt_on based on auto_approve setting
if auto_approve:
# No interrupts - all tools run automatically
interrupt_on = {}
else:
# Full HITL for destructive operations - import from deepagents_cli.agent
# Full HITL for destructive operations
from deepagents_cli.agent import _add_interrupt_on
interrupt_on = _add_interrupt_on()
deepagent_middleware = [
TodoListMiddleware(),
FilesystemMiddleware(backend=composite_backend),
CustomFilesystemMiddleware(backend=composite_backend), # 使用自定义的 FilesystemMiddleware支持 SKILL.md 完整读取
AnthropicPromptCachingMiddleware(unsupported_model_behavior="ignore"),
PatchToolCallsMiddleware(),
]
if middleware:
deepagent_middleware.extend(middleware)
if agent_middleware:
deepagent_middleware.extend(agent_middleware)
if interrupt_on is not None:
deepagent_middleware.append(HumanInTheLoopMiddleware(interrupt_on=interrupt_on))

View File

@ -11,6 +11,7 @@ import logging
from utils.settings import BACKEND_HOST, MASTERKEY
logger = logging.getLogger('app')
from .plugin_hook_loader import execute_hooks, merge_skill_mcp_configs
from pathlib import Path
def format_datetime_by_language(language: str) -> str:
"""
@ -124,7 +125,7 @@ async def load_system_prompt_async(config) -> str:
language=language_display,
user_identifier=user_identifier,
datetime=datetime_str,
agent_dir_path=".",
agent_dir_path=f"{Path.cwd()}/projects/robot/{config.bot_id}",
trace_id=trace_id or ""
)

372
plans/deepagents-upgrade.md Normal file
View File

@ -0,0 +1,372 @@
# DeepAgents 依赖升级计划
## 概述
将 qwen-agent 项目中的 deepagents 和 deepagents-cli 依赖升级到最新版本同时保留自定义功能workspace_root、shell_env、自定义中间件等
## 问题背景
### 当前版本
| 包名 | 当前版本 | 最新版本 |
|------|---------|---------|
| deepagents | 0.2.8 | 0.4.4 |
| deepagents-cli | 0.0.11 | 0.0.25 |
### 自定义改造
项目中 `agent/deep_assistant.py:351-518``create_custom_cli_agent` 函数基于 deepagents-cli 的 `create_cli_agent` 进行了以下改造:
1. **workspace_root 参数** - 自定义工作目录为 `projects/robot/{bot_id}`
2. **shell_env 参数** - 传递上下文环境变量ASSISTANT_ID, USER_IDENTIFIER, TRACE_ID
3. **middleware 参数** - 支持外部传入自定义中间件列表
4. **checkpointer 参数** - 支持外部传入 PostgreSQL checkpointer
5. **store 参数** - 支持外部传入 store
6. **CustomAgentMemoryMiddleware** - 修改路径显示为 `./`
7. **CustomSkillsMiddleware** - 修改技能路径显示
### API 变更对比
| 参数 | 0.0.11 (当前) | 0.0.25 (最新) | 影响 |
|------|--------------|--------------|------|
| workspace_root | 支持(自定义添加) | 不支持 | Critical |
| shell_env | 支持(自定义添加) | 不支持 | Critical |
| middleware | 支持(自定义添加) | 不支持 | Critical |
| checkpointer | 支持外部传入 | 内部创建 InMemorySaver | Critical |
| store | 支持 | 不支持 | Important |
| enable_shell | 支持 | 支持 | 兼容 |
| sandbox_type | 支持 | 支持 | 兼容 |
## 模块迁移对照表(重要变更)
> ⚠️ **关键发现**:多个模块已从 `deepagents_cli` 迁移到 `deepagents`
| 模块/类名 | 旧位置 (0.0.11) | 新位置 (0.0.25) | 变更说明 |
|-----------|----------------|----------------|---------|
| `ShellMiddleware` | `deepagents_cli.shell` | **已删除** | 被 `LocalShellBackend` 替代 |
| `AgentMemoryMiddleware` | `deepagents_cli.agent_memory` | `deepagents.middleware.memory.MemoryMiddleware` | 改名为 `MemoryMiddleware` |
| `SkillsMiddleware` | `deepagents_cli.skills` | `deepagents.middleware.skills` | 迁移到 SDK |
| `settings` | `deepagents_cli.config` | `deepagents_cli.config` | 无变化 |
| `get_default_coding_instructions` | `deepagents_cli.config` | `deepagents_cli.config` | 无变化 |
| `create_cli_agent` | `deepagents_cli.agent` | `deepagents_cli.agent` | 无变化 |
### LocalShellBackend 替代 ShellMiddleware
`ShellMiddleware` 已被 `LocalShellBackend` 替代。新版本的 `LocalShellBackend` 同时提供文件系统操作和 shell 执行功能:
```python
from deepagents.backends import LocalShellBackend
# 创建 backend支持自定义环境变量
backend = LocalShellBackend(
root_dir=workspace_root,
virtual_mode=True,
env={"ASSISTANT_ID": "xxx", "USER_IDENTIFIER": "yyy"}, # 自定义环境变量
inherit_env=True, # 继承父进程环境变量
)
```
**参数说明**
- `root_dir`: 工作目录
- `virtual_mode`: 虚拟路径模式
- `env`: 自定义环境变量字典
- `inherit_env`: 是否继承 `os.environ`
## 推荐方案Fork 并修改
复制最新版本的 `create_cli_agent` 源代码,在其基础上添加缺失的参数支持。
### 原因
1. **保持控制力** - 完全控制 agent 创建过程,不受上游 API 变更影响
2. **复用新功能** - 基于新版本代码,获得 bug 修复和性能改进
3. **维护成本适中** - 只需在版本升级时同步上游变更
4. **风险可控** - 可以逐步验证每个功能
## 技术考虑
### 1. FilesystemBackend 的 root_dir 支持
**最新版本确认**`FilesystemBackend` 仍然支持 `root_dir` 参数
```python
# 当前实现
composite_backend = CompositeBackend(
default=FilesystemBackend(root_dir=workspace_root, virtual_mode=True),
routes={},
)
```
**结论**:可以直接复用,无需修改。
### 2. Shell 环境变量支持(重大变更)
**原实现**(使用 ShellMiddleware
```python
from deepagents_cli.shell import ShellMiddleware
agent_middleware.append(
ShellMiddleware(
workspace_root=workspace_root,
env=final_shell_env,
)
)
```
**新实现**(使用 LocalShellBackend
```python
from deepagents.backends import LocalShellBackend
# 创建带自定义环境变量的 backend
shell_backend = LocalShellBackend(
root_dir=workspace_root,
virtual_mode=True,
env=shell_env,
inherit_env=True,
)
# 或使用 CompositeBackend 路由
composite_backend = CompositeBackend(
default=FilesystemBackend(root_dir=workspace_root, virtual_mode=True),
routes={
"/shell/": shell_backend, # shell 命令路由
},
)
```
**结论**:需要修改 shell 环境变量的传递方式。
### 3. checkpointer 管理
**问题**:最新版本在 `create_deep_agent` 中硬编码 `InMemorySaver`
**解决方案**:在自定义的 `create_custom_cli_agent` 中保留外部传入 checkpointer 的能力。
### 4. 中间件兼容性
需要验证以下自定义中间件与最新版本的兼容性:
- `CustomAgentMemoryMiddleware` - 父类已从 `AgentMemoryMiddleware` 改名为 `MemoryMiddleware`
- `CustomSkillsMiddleware` - 父类 `SkillsMiddleware` 已迁移到 `deepagents.middleware.skills`
## 实施步骤
### Phase 1: 准备工作
- [ ] 创建升级分支 `git checkout -b upgrade/deepagents-0.4.4`
- [ ] 备份当前 `agent/deep_assistant.py`
- [ ] 更新 pyproject.toml 中的依赖版本
```
deepagents = ">=0.4.4,<0.5.0"
deepagents-cli = ">=0.0.25,<0.0.26"
```
- [ ] 执行 `poetry install` 安装新版本
- [ ] 执行 `poetry export -f requirements.txt -o requirements.txt --without-hashes`
### Phase 2: 更新导入语句
根据模块迁移对照表,更新 `agent/deep_assistant.py` 中的导入:
```python
# === 需要修改的导入 ===
# 旧from deepagents_cli.shell import ShellMiddleware
# 新:不再使用 ShellMiddleware改用 LocalShellBackend
from deepagents.backends import LocalShellBackend
# 旧from deepagents_cli.agent_memory import AgentMemoryMiddleware
# 新from deepagents.middleware import MemoryMiddleware
from deepagents.middleware import MemoryMiddleware
# 旧from deepagents_cli.skills import SkillsMiddleware
# 新:
from deepagents.middleware import SkillsMiddleware
# === 无需修改的导入 ===
from deepagents_cli.config import settings, get_default_coding_instructions
from deepagents_cli.agent import create_cli_agent
```
### Phase 3: 适配 LocalShellBackend
修改 shell 环境变量的传递方式:
```python
# 原代码(使用 ShellMiddleware
if enable_shell:
final_shell_env = os.environ.copy()
if shell_env:
final_shell_env.update(shell_env)
agent_middleware.append(
ShellMiddleware(
workspace_root=workspace_root,
env=final_shell_env,
)
)
# 新代码(使用 LocalShellBackend
if enable_shell:
final_shell_env = shell_env or {}
shell_backend = LocalShellBackend(
root_dir=workspace_root,
virtual_mode=True,
env=final_shell_env,
inherit_env=True, # 继承 os.environ
)
# 将 shell_backend 传入 CompositeBackend 或作为 sandbox 参数
```
### Phase 4: 适配自定义中间件
更新 `CustomAgentMemoryMiddleware``CustomSkillsMiddleware` 的父类:
```python
# 旧代码
from deepagents_cli.agent_memory import AgentMemoryMiddleware
from deepagents_cli.skills import SkillsMiddleware
class CustomAgentMemoryMiddleware(AgentMemoryMiddleware):
...
class CustomSkillsMiddleware(SkillsMiddleware):
...
# 新代码
from deepagents.middleware import MemoryMiddleware, SkillsMiddleware
class CustomAgentMemoryMiddleware(MemoryMiddleware):
...
class CustomSkillsMiddleware(SkillsMiddleware):
...
```
**注意**:需要检查新版本的 `MemoryMiddleware``SkillsMiddleware` 的构造函数签名是否有变化。
### Phase 5: 测试
- [ ] 单元测试
```bash
poetry run pytest tests/test_deep_assistant.py -v
```
- [ ] 集成测试
```bash
# 启动服务
poetry run uvicorn fastapi_app:app --host 0.0.0.0 --port 8001
# 执行测试请求
curl --request POST \
--url http://localhost:8001/api/v2/chat/completions \
--header 'authorization: Bearer test' \
--header 'content-type: application/json' \
--data '{
"messages": [{"role": "user", "content": "你好"}],
"stream": true,
"model": "whatever",
"bot_id": "test-bot",
"session_id": "test-session"
}'
```
- [ ] 功能验证
- [ ] 文件隔离:验证不同 bot_id 的文件不互相干扰
- [ ] 环境变量:验证 shell 命令中可以访问 ASSISTANT_ID 等
- [ ] 中间件:验证自定义中间件正常执行
- [ ] 会话持久化:验证 session_id 恢复对话正常
## 风险分析
### 高风险
| 风险 | 影响 | 缓解措施 |
|------|------|---------|
| API 不兼容 | 编译失败 | 逐步升级,逐个验证 |
| 功能丢失 | 业务中断 | 保留旧版本代码,快速回滚 |
| checkpointer 不兼容 | 会话丢失 | 先在测试环境验证 |
| LocalShellBackend 行为差异 | shell 执行异常 | 详细测试 shell 功能 |
### 中风险
| 风险 | 影响 | 缓解措施 |
|------|------|---------|
| 中间件不兼容 | 功能异常 | 单独测试每个中间件 |
| 性能下降 | 响应变慢 | 压力测试对比 |
| 路径显示异常 | 用户困惑 | 视觉验证 |
| MemoryMiddleware 签名变更 | 编译失败 | 检查新签名并适配 |
## 回滚策略
### 快速回滚5分钟
```bash
# 1. 切换回主分支
git checkout master
# 2. 恢复依赖
poetry install
# 3. 重启服务
pkill -f "uvicorn fastapi_app:app"
poetry run uvicorn fastapi_app:app --host 0.0.0.0 --port 8001
```
### 数据回滚
如果 checkpointer 数据不兼容:
```bash
# 恢复到升级前的数据库备份
pg_restore -d qwen_agent backup_before_upgrade.dump
```
## 成功<E68890><E58A9F>
- [ ] 所有现有功能正常工作
- [ ] 性能无明显下降(响应时间 < 2s
- [ ] 错误率 < 0.1%
- [ ] 用户无感知升级
## 参考资源
### 内部文件
- `agent/deep_assistant.py:351-518` - 当前 create_custom_cli_agent 实现
- `agent/deep_assistant.py:242-259` - workspace_root 使用
- `agent/deep_assistant.py:45-50` - 当前导入语句
- `pyproject.toml:29` - deepagents 版本约束
- `pyproject.toml:34` - deepagents-cli 版本约束
### 外部资源
- [deepagents GitHub](https://github.com/langchain-ai/deepagents)
- [deepagents 官方文档](https://docs.langchain.com/oss/python/deepagents)
- 本地克隆仓库:`/Users/moshui/Documents/felo/deepagents`
### 关键源文件(本地克隆)
| 文件 | 用途 |
|------|------|
| `libs/cli/deepagents_cli/agent.py` | 最新 create_cli_agent |
| `libs/deepagents/deepagents/backends/local_shell.py` | LocalShellBackend替代 ShellMiddleware |
| `libs/deepagents/deepagents/middleware/memory.py` | MemoryMiddleware原 AgentMemoryMiddleware |
| `libs/deepagents/deepagents/middleware/skills.py` | SkillsMiddleware |
| `libs/deepagents/deepagents/middleware/__init__.py` | 中间件导出 |
| `libs/deepagents/deepagents/backends/__init__.py` | Backend 导出 |
| `libs/cli/deepagents_cli/config.py` | settings, get_default_coding_instructions |
## 变更检查清单
升级前需要确认的关键变更:
- [ ] `ShellMiddleware``LocalShellBackend` 替代方案
- [ ] `AgentMemoryMiddleware``MemoryMiddleware` 命名变更
- [ ] `SkillsMiddleware` 导入路径变更
- [ ] `LocalShellBackend``env``inherit_env` 参数使用
- [ ] `MemoryMiddleware` 新签名适配
- [ ] `SkillsMiddleware` 新签名适配
---
**创建时间**: 2026-03-02
**状态**: 已完成

663
poetry.lock generated
View File

@ -197,6 +197,22 @@ files = [
frozenlist = ">=1.1.0"
typing-extensions = {version = ">=4.2", markers = "python_version < \"3.13\""}
[[package]]
name = "aiosqlite"
version = "0.22.1"
description = "asyncio bridge to the standard sqlite3 module"
optional = false
python-versions = ">=3.9"
groups = ["main"]
files = [
{file = "aiosqlite-0.22.1-py3-none-any.whl", hash = "sha256:21c002eb13823fad740196c5a2e9d8e62f6243bd9e7e4a1f87fb5e44ecb4fceb"},
{file = "aiosqlite-0.22.1.tar.gz", hash = "sha256:043e0bd78d32888c0a9ca90fc788b38796843360c855a7262a532813133a0650"},
]
[package.extras]
dev = ["attribution (==1.8.0)", "black (==25.11.0)", "build (>=1.2)", "coverage[toml] (==7.10.7)", "flake8 (==7.3.0)", "flake8-bugbear (==24.12.12)", "flit (==3.12.0)", "mypy (==1.19.0)", "ufmt (==2.8.0)", "usort (==1.0.8.post1)"]
docs = ["sphinx (==8.1.3)", "sphinx-mdinclude (==0.6.2)"]
[[package]]
name = "annotated-types"
version = "0.7.0"
@ -211,14 +227,14 @@ files = [
[[package]]
name = "anthropic"
version = "0.75.0"
version = "0.84.0"
description = "The official Python library for the anthropic API"
optional = false
python-versions = ">=3.9"
groups = ["main"]
files = [
{file = "anthropic-0.75.0-py3-none-any.whl", hash = "sha256:ea8317271b6c15d80225a9f3c670152746e88805a7a61e14d4a374577164965b"},
{file = "anthropic-0.75.0.tar.gz", hash = "sha256:e8607422f4ab616db2ea5baacc215dd5f028da99ce2f022e33c7c535b29f3dfb"},
{file = "anthropic-0.84.0-py3-none-any.whl", hash = "sha256:861c4c50f91ca45f942e091d83b60530ad6d4f98733bfe648065364da05d29e7"},
{file = "anthropic-0.84.0.tar.gz", hash = "sha256:72f5f90e5aebe62dca316cb013629cfa24996b0f5a4593b8c3d712bc03c43c37"},
]
[package.dependencies]
@ -234,6 +250,7 @@ typing-extensions = ">=4.10,<5"
[package.extras]
aiohttp = ["aiohttp", "httpx-aiohttp (>=0.1.9)"]
bedrock = ["boto3 (>=1.28.57)", "botocore (>=1.31.57)"]
mcp = ["mcp (>=1.0) ; python_version >= \"3.10\""]
vertex = ["google-auth[requests] (>=2,<3)"]
[[package]]
@ -399,6 +416,104 @@ files = [
{file = "certifi-2025.10.5.tar.gz", hash = "sha256:47c09d31ccf2acf0be3f701ea53595ee7e0b8fa08801c6624be771df09ae7b43"},
]
[[package]]
name = "cffi"
version = "2.0.0"
description = "Foreign Function Interface for Python calling C code."
optional = false
python-versions = ">=3.9"
groups = ["main"]
markers = "platform_python_implementation != \"PyPy\""
files = [
{file = "cffi-2.0.0-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:0cf2d91ecc3fcc0625c2c530fe004f82c110405f101548512cce44322fa8ac44"},
{file = "cffi-2.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f73b96c41e3b2adedc34a7356e64c8eb96e03a3782b535e043a986276ce12a49"},
{file = "cffi-2.0.0-cp310-cp310-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:53f77cbe57044e88bbd5ed26ac1d0514d2acf0591dd6bb02a3ae37f76811b80c"},
{file = "cffi-2.0.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3e837e369566884707ddaf85fc1744b47575005c0a229de3327f8f9a20f4efeb"},
{file = "cffi-2.0.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:5eda85d6d1879e692d546a078b44251cdd08dd1cfb98dfb77b670c97cee49ea0"},
{file = "cffi-2.0.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:9332088d75dc3241c702d852d4671613136d90fa6881da7d770a483fd05248b4"},
{file = "cffi-2.0.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fc7de24befaeae77ba923797c7c87834c73648a05a4bde34b3b7e5588973a453"},
{file = "cffi-2.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:cf364028c016c03078a23b503f02058f1814320a56ad535686f90565636a9495"},
{file = "cffi-2.0.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e11e82b744887154b182fd3e7e8512418446501191994dbf9c9fc1f32cc8efd5"},
{file = "cffi-2.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8ea985900c5c95ce9db1745f7933eeef5d314f0565b27625d9a10ec9881e1bfb"},
{file = "cffi-2.0.0-cp310-cp310-win32.whl", hash = "sha256:1f72fb8906754ac8a2cc3f9f5aaa298070652a0ffae577e0ea9bd480dc3c931a"},
{file = "cffi-2.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:b18a3ed7d5b3bd8d9ef7a8cb226502c6bf8308df1525e1cc676c3680e7176739"},
{file = "cffi-2.0.0-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:b4c854ef3adc177950a8dfc81a86f5115d2abd545751a304c5bcf2c2c7283cfe"},
{file = "cffi-2.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2de9a304e27f7596cd03d16f1b7c72219bd944e99cc52b84d0145aefb07cbd3c"},
{file = "cffi-2.0.0-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:baf5215e0ab74c16e2dd324e8ec067ef59e41125d3eade2b863d294fd5035c92"},
{file = "cffi-2.0.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:730cacb21e1bdff3ce90babf007d0a0917cc3e6492f336c2f0134101e0944f93"},
{file = "cffi-2.0.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:6824f87845e3396029f3820c206e459ccc91760e8fa24422f8b0c3d1731cbec5"},
{file = "cffi-2.0.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:9de40a7b0323d889cf8d23d1ef214f565ab154443c42737dfe52ff82cf857664"},
{file = "cffi-2.0.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8941aaadaf67246224cee8c3803777eed332a19d909b47e29c9842ef1e79ac26"},
{file = "cffi-2.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a05d0c237b3349096d3981b727493e22147f934b20f6f125a3eba8f994bec4a9"},
{file = "cffi-2.0.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:94698a9c5f91f9d138526b48fe26a199609544591f859c870d477351dc7b2414"},
{file = "cffi-2.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5fed36fccc0612a53f1d4d9a816b50a36702c28a2aa880cb8a122b3466638743"},
{file = "cffi-2.0.0-cp311-cp311-win32.whl", hash = "sha256:c649e3a33450ec82378822b3dad03cc228b8f5963c0c12fc3b1e0ab940f768a5"},
{file = "cffi-2.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:66f011380d0e49ed280c789fbd08ff0d40968ee7b665575489afa95c98196ab5"},
{file = "cffi-2.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:c6638687455baf640e37344fe26d37c404db8b80d037c3d29f58fe8d1c3b194d"},
{file = "cffi-2.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d02d6655b0e54f54c4ef0b94eb6be0607b70853c45ce98bd278dc7de718be5d"},
{file = "cffi-2.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8eca2a813c1cb7ad4fb74d368c2ffbbb4789d377ee5bb8df98373c2cc0dee76c"},
{file = "cffi-2.0.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:21d1152871b019407d8ac3985f6775c079416c282e431a4da6afe7aefd2bccbe"},
{file = "cffi-2.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b21e08af67b8a103c71a250401c78d5e0893beff75e28c53c98f4de42f774062"},
{file = "cffi-2.0.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:1e3a615586f05fc4065a8b22b8152f0c1b00cdbc60596d187c2a74f9e3036e4e"},
{file = "cffi-2.0.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:81afed14892743bbe14dacb9e36d9e0e504cd204e0b165062c488942b9718037"},
{file = "cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3e17ed538242334bf70832644a32a7aae3d83b57567f9fd60a26257e992b79ba"},
{file = "cffi-2.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3925dd22fa2b7699ed2617149842d2e6adde22b262fcbfada50e3d195e4b3a94"},
{file = "cffi-2.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2c8f814d84194c9ea681642fd164267891702542f028a15fc97d4674b6206187"},
{file = "cffi-2.0.0-cp312-cp312-win32.whl", hash = "sha256:da902562c3e9c550df360bfa53c035b2f241fed6d9aef119048073680ace4a18"},
{file = "cffi-2.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:da68248800ad6320861f129cd9c1bf96ca849a2771a59e0344e88681905916f5"},
{file = "cffi-2.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:4671d9dd5ec934cb9a73e7ee9676f9362aba54f7f34910956b84d727b0d73fb6"},
{file = "cffi-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb"},
{file = "cffi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca"},
{file = "cffi-2.0.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b"},
{file = "cffi-2.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b"},
{file = "cffi-2.0.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2"},
{file = "cffi-2.0.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:dd4f05f54a52fb558f1ba9f528228066954fee3ebe629fc1660d874d040ae5a3"},
{file = "cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26"},
{file = "cffi-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c"},
{file = "cffi-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b"},
{file = "cffi-2.0.0-cp313-cp313-win32.whl", hash = "sha256:74a03b9698e198d47562765773b4a8309919089150a0bb17d829ad7b44b60d27"},
{file = "cffi-2.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:19f705ada2530c1167abacb171925dd886168931e0a7b78f5bffcae5c6b5be75"},
{file = "cffi-2.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:256f80b80ca3853f90c21b23ee78cd008713787b1b1e93eae9f3d6a7134abd91"},
{file = "cffi-2.0.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fc33c5141b55ed366cfaad382df24fe7dcbc686de5be719b207bb248e3053dc5"},
{file = "cffi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c654de545946e0db659b3400168c9ad31b5d29593291482c43e3564effbcee13"},
{file = "cffi-2.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b"},
{file = "cffi-2.0.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:12873ca6cb9b0f0d3a0da705d6086fe911591737a59f28b7936bdfed27c0d47c"},
{file = "cffi-2.0.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9b97165e8aed9272a6bb17c01e3cc5871a594a446ebedc996e2397a1c1ea8ef"},
{file = "cffi-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775"},
{file = "cffi-2.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205"},
{file = "cffi-2.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1"},
{file = "cffi-2.0.0-cp314-cp314-win32.whl", hash = "sha256:087067fa8953339c723661eda6b54bc98c5625757ea62e95eb4898ad5e776e9f"},
{file = "cffi-2.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:203a48d1fb583fc7d78a4c6655692963b860a417c0528492a6bc21f1aaefab25"},
{file = "cffi-2.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:dbd5c7a25a7cb98f5ca55d258b103a2054f859a46ae11aaf23134f9cc0d356ad"},
{file = "cffi-2.0.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9a67fc9e8eb39039280526379fb3a70023d77caec1852002b4da7e8b270c4dd9"},
{file = "cffi-2.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7a66c7204d8869299919db4d5069a82f1561581af12b11b3c9f48c584eb8743d"},
{file = "cffi-2.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c"},
{file = "cffi-2.0.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:92b68146a71df78564e4ef48af17551a5ddd142e5190cdf2c5624d0c3ff5b2e8"},
{file = "cffi-2.0.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b1e74d11748e7e98e2f426ab176d4ed720a64412b6a15054378afdb71e0f37dc"},
{file = "cffi-2.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592"},
{file = "cffi-2.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512"},
{file = "cffi-2.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4"},
{file = "cffi-2.0.0-cp314-cp314t-win32.whl", hash = "sha256:1fc9ea04857caf665289b7a75923f2c6ed559b8298a1b8c49e59f7dd95c8481e"},
{file = "cffi-2.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:d68b6cef7827e8641e8ef16f4494edda8b36104d79773a334beaa1e3521430f6"},
{file = "cffi-2.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9"},
{file = "cffi-2.0.0-cp39-cp39-macosx_10_13_x86_64.whl", hash = "sha256:fe562eb1a64e67dd297ccc4f5addea2501664954f2692b69a76449ec7913ecbf"},
{file = "cffi-2.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:de8dad4425a6ca6e4e5e297b27b5c824ecc7581910bf9aee86cb6835e6812aa7"},
{file = "cffi-2.0.0-cp39-cp39-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:4647afc2f90d1ddd33441e5b0e85b16b12ddec4fca55f0d9671fef036ecca27c"},
{file = "cffi-2.0.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3f4d46d8b35698056ec29bca21546e1551a205058ae1a181d871e278b0b28165"},
{file = "cffi-2.0.0-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:e6e73b9e02893c764e7e8d5bb5ce277f1a009cd5243f8228f75f842bf937c534"},
{file = "cffi-2.0.0-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:cb527a79772e5ef98fb1d700678fe031e353e765d1ca2d409c92263c6d43e09f"},
{file = "cffi-2.0.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:61d028e90346df14fedc3d1e5441df818d095f3b87d286825dfcbd6459b7ef63"},
{file = "cffi-2.0.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0f6084a0ea23d05d20c3edcda20c3d006f9b6f3fefeac38f59262e10cef47ee2"},
{file = "cffi-2.0.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1cd13c99ce269b3ed80b417dcd591415d3372bcac067009b6e0f59c7d4015e65"},
{file = "cffi-2.0.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:89472c9762729b5ae1ad974b777416bfda4ac5642423fa93bd57a09204712322"},
{file = "cffi-2.0.0-cp39-cp39-win32.whl", hash = "sha256:2081580ebb843f759b9f617314a24ed5738c51d2aee65d31e02f6f7a2b97707a"},
{file = "cffi-2.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:b882b3df248017dba09d6b16defe9b5c407fe32fc7c65a9c69798e6175601be9"},
{file = "cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529"},
]
[package.dependencies]
pycparser = {version = "*", markers = "implementation_name != \"PyPy\""}
[[package]]
name = "chardet"
version = "5.2.0"
@ -562,6 +677,78 @@ files = [
]
markers = {main = "platform_system == \"Windows\"", dev = "sys_platform == \"win32\""}
[[package]]
name = "cryptography"
version = "46.0.5"
description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers."
optional = false
python-versions = "!=3.9.0,!=3.9.1,>=3.8"
groups = ["main"]
files = [
{file = "cryptography-46.0.5-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:351695ada9ea9618b3500b490ad54c739860883df6c1f555e088eaf25b1bbaad"},
{file = "cryptography-46.0.5-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c18ff11e86df2e28854939acde2d003f7984f721eba450b56a200ad90eeb0e6b"},
{file = "cryptography-46.0.5-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4d7e3d356b8cd4ea5aff04f129d5f66ebdc7b6f8eae802b93739ed520c47c79b"},
{file = "cryptography-46.0.5-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:50bfb6925eff619c9c023b967d5b77a54e04256c4281b0e21336a130cd7fc263"},
{file = "cryptography-46.0.5-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:803812e111e75d1aa73690d2facc295eaefd4439be1023fefc4995eaea2af90d"},
{file = "cryptography-46.0.5-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3ee190460e2fbe447175cda91b88b84ae8322a104fc27766ad09428754a618ed"},
{file = "cryptography-46.0.5-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:f145bba11b878005c496e93e257c1e88f154d278d2638e6450d17e0f31e558d2"},
{file = "cryptography-46.0.5-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:e9251e3be159d1020c4030bd2e5f84d6a43fe54b6c19c12f51cde9542a2817b2"},
{file = "cryptography-46.0.5-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:47fb8a66058b80e509c47118ef8a75d14c455e81ac369050f20ba0d23e77fee0"},
{file = "cryptography-46.0.5-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:4c3341037c136030cb46e4b1e17b7418ea4cbd9dd207e4a6f3b2b24e0d4ac731"},
{file = "cryptography-46.0.5-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:890bcb4abd5a2d3f852196437129eb3667d62630333aacc13dfd470fad3aaa82"},
{file = "cryptography-46.0.5-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:80a8d7bfdf38f87ca30a5391c0c9ce4ed2926918e017c29ddf643d0ed2778ea1"},
{file = "cryptography-46.0.5-cp311-abi3-win32.whl", hash = "sha256:60ee7e19e95104d4c03871d7d7dfb3d22ef8a9b9c6778c94e1c8fcc8365afd48"},
{file = "cryptography-46.0.5-cp311-abi3-win_amd64.whl", hash = "sha256:38946c54b16c885c72c4f59846be9743d699eee2b69b6988e0a00a01f46a61a4"},
{file = "cryptography-46.0.5-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:94a76daa32eb78d61339aff7952ea819b1734b46f73646a07decb40e5b3448e2"},
{file = "cryptography-46.0.5-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5be7bf2fb40769e05739dd0046e7b26f9d4670badc7b032d6ce4db64dddc0678"},
{file = "cryptography-46.0.5-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fe346b143ff9685e40192a4960938545c699054ba11d4f9029f94751e3f71d87"},
{file = "cryptography-46.0.5-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:c69fd885df7d089548a42d5ec05be26050ebcd2283d89b3d30676eb32ff87dee"},
{file = "cryptography-46.0.5-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:8293f3dea7fc929ef7240796ba231413afa7b68ce38fd21da2995549f5961981"},
{file = "cryptography-46.0.5-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:1abfdb89b41c3be0365328a410baa9df3ff8a9110fb75e7b52e66803ddabc9a9"},
{file = "cryptography-46.0.5-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:d66e421495fdb797610a08f43b05269e0a5ea7f5e652a89bfd5a7d3c1dee3648"},
{file = "cryptography-46.0.5-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:4e817a8920bfbcff8940ecfd60f23d01836408242b30f1a708d93198393a80b4"},
{file = "cryptography-46.0.5-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:68f68d13f2e1cb95163fa3b4db4bf9a159a418f5f6e7242564fc75fcae667fd0"},
{file = "cryptography-46.0.5-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:a3d1fae9863299076f05cb8a778c467578262fae09f9dc0ee9b12eb4268ce663"},
{file = "cryptography-46.0.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c4143987a42a2397f2fc3b4d7e3a7d313fbe684f67ff443999e803dd75a76826"},
{file = "cryptography-46.0.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:7d731d4b107030987fd61a7f8ab512b25b53cef8f233a97379ede116f30eb67d"},
{file = "cryptography-46.0.5-cp314-cp314t-win32.whl", hash = "sha256:c3bcce8521d785d510b2aad26ae2c966092b7daa8f45dd8f44734a104dc0bc1a"},
{file = "cryptography-46.0.5-cp314-cp314t-win_amd64.whl", hash = "sha256:4d8ae8659ab18c65ced284993c2265910f6c9e650189d4e3f68445ef82a810e4"},
{file = "cryptography-46.0.5-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:4108d4c09fbbf2789d0c926eb4152ae1760d5a2d97612b92d508d96c861e4d31"},
{file = "cryptography-46.0.5-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7d1f30a86d2757199cb2d56e48cce14deddf1f9c95f1ef1b64ee91ea43fe2e18"},
{file = "cryptography-46.0.5-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:039917b0dc418bb9f6edce8a906572d69e74bd330b0b3fea4f79dab7f8ddd235"},
{file = "cryptography-46.0.5-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:ba2a27ff02f48193fc4daeadf8ad2590516fa3d0adeeb34336b96f7fa64c1e3a"},
{file = "cryptography-46.0.5-cp38-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:61aa400dce22cb001a98014f647dc21cda08f7915ceb95df0c9eaf84b4b6af76"},
{file = "cryptography-46.0.5-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3ce58ba46e1bc2aac4f7d9290223cead56743fa6ab94a5d53292ffaac6a91614"},
{file = "cryptography-46.0.5-cp38-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:420d0e909050490d04359e7fdb5ed7e667ca5c3c402b809ae2563d7e66a92229"},
{file = "cryptography-46.0.5-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:582f5fcd2afa31622f317f80426a027f30dc792e9c80ffee87b993200ea115f1"},
{file = "cryptography-46.0.5-cp38-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:bfd56bb4b37ed4f330b82402f6f435845a5f5648edf1ad497da51a8452d5d62d"},
{file = "cryptography-46.0.5-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:a3d507bb6a513ca96ba84443226af944b0f7f47dcc9a399d110cd6146481d24c"},
{file = "cryptography-46.0.5-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9f16fbdf4da055efb21c22d81b89f155f02ba420558db21288b3d0035bafd5f4"},
{file = "cryptography-46.0.5-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:ced80795227d70549a411a4ab66e8ce307899fad2220ce5ab2f296e687eacde9"},
{file = "cryptography-46.0.5-cp38-abi3-win32.whl", hash = "sha256:02f547fce831f5096c9a567fd41bc12ca8f11df260959ecc7c3202555cc47a72"},
{file = "cryptography-46.0.5-cp38-abi3-win_amd64.whl", hash = "sha256:556e106ee01aa13484ce9b0239bca667be5004efb0aabbed28d353df86445595"},
{file = "cryptography-46.0.5-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:3b4995dc971c9fb83c25aa44cf45f02ba86f71ee600d81091c2f0cbae116b06c"},
{file = "cryptography-46.0.5-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:bc84e875994c3b445871ea7181d424588171efec3e185dced958dad9e001950a"},
{file = "cryptography-46.0.5-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:2ae6971afd6246710480e3f15824ed3029a60fc16991db250034efd0b9fb4356"},
{file = "cryptography-46.0.5-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:d861ee9e76ace6cf36a6a89b959ec08e7bc2493ee39d07ffe5acb23ef46d27da"},
{file = "cryptography-46.0.5-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:2b7a67c9cd56372f3249b39699f2ad479f6991e62ea15800973b956f4b73e257"},
{file = "cryptography-46.0.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:8456928655f856c6e1533ff59d5be76578a7157224dbd9ce6872f25055ab9ab7"},
{file = "cryptography-46.0.5.tar.gz", hash = "sha256:abace499247268e3757271b2f1e244b36b06f8515cf27c4d49468fc9eb16e93d"},
]
[package.dependencies]
cffi = {version = ">=2.0.0", markers = "python_full_version >= \"3.9.0\" and platform_python_implementation != \"PyPy\""}
[package.extras]
docs = ["sphinx (>=5.3.0)", "sphinx-inline-tabs", "sphinx-rtd-theme (>=3.0.0)"]
docstest = ["pyenchant (>=3)", "readme-renderer (>=30.0)", "sphinxcontrib-spelling (>=7.3.1)"]
nox = ["nox[uv] (>=2024.4.15)"]
pep8test = ["check-sdist", "click (>=8.0.1)", "mypy (>=1.14)", "ruff (>=0.11.11)"]
sdist = ["build (>=1.0.0)"]
ssh = ["bcrypt (>=3.1.5)"]
test = ["certifi (>=2024)", "cryptography-vectors (==46.0.5)", "pretend (>=0.7)", "pytest (>=7.4.0)", "pytest-benchmark (>=4.0)", "pytest-cov (>=2.10.1)", "pytest-xdist (>=3.5.0)"]
test-randomorder = ["pytest-randomly"]
[[package]]
name = "daytona"
version = "0.127.0"
@ -667,48 +854,77 @@ urllib3 = ">=2.1.0,<3.0.0"
[[package]]
name = "deepagents"
version = "0.2.8"
version = "0.4.3"
description = "General purpose 'deep agent' with sub-agent spawning, todo list capabilities, and mock file system. Built on LangGraph."
optional = false
python-versions = "<4.0,>=3.11"
groups = ["main"]
files = [
{file = "deepagents-0.2.8-py3-none-any.whl", hash = "sha256:d4c3d0df074be5e10f3a17005e68db3df18b3d51f48aca3e299d87c254fda797"},
{file = "deepagents-0.2.8.tar.gz", hash = "sha256:5fbf7f0db06b923409b79a6598784e0e9925958efabd4b702eed9238b459ae09"},
{file = "deepagents-0.4.3-py3-none-any.whl", hash = "sha256:298d19c5c0b4c6fc6a74b68049a7bfea0ba481aece7201ab21e7172b71ee61b9"},
{file = "deepagents-0.4.3.tar.gz", hash = "sha256:88033c616c5ea481f2620dbb2d05533bc8fdcd48f376d713f9dba49a8157b6f8"},
]
[package.dependencies]
langchain = ">=1.0.2,<2.0.0"
langchain-anthropic = ">=1.0.0,<2.0.0"
langchain-core = ">=1.0.0,<2.0.0"
langchain = ">=1.2.10,<2.0.0"
langchain-anthropic = ">=1.3.3,<2.0.0"
langchain-core = ">=1.2.10,<2.0.0"
langchain-google-genai = ">=4.2.0,<5.0.0"
wcmatch = "*"
[[package]]
name = "deepagents-cli"
version = "0.0.11"
description = "Deepagents CLI"
version = "0.0.25"
description = "Terminal interface for Deep Agents - interactive AI agent with file operations, shell access, and sub-agent capabilities."
optional = false
python-versions = "<4.0,>=3.11"
groups = ["main"]
files = [
{file = "deepagents_cli-0.0.11-py3-none-any.whl", hash = "sha256:40f6ab9727a31130d4313344a3fa4680ab75cb1c68aba400bddd5cf8a9fe891d"},
{file = "deepagents_cli-0.0.11.tar.gz", hash = "sha256:1429f25000575b8af3baed247d79340199b94a07b1fb5f1290aa33f1ed302902"},
{file = "deepagents_cli-0.0.25-py3-none-any.whl", hash = "sha256:2dafc1c051ddf5fec841fa69c4300c75b89a1d3923dad108186dcddb2f02f2f5"},
{file = "deepagents_cli-0.0.25.tar.gz", hash = "sha256:480e3396d23c2c8bf925ce1060729f76f62b5aea820dee995095017d56ce9793"},
]
[package.dependencies]
daytona = ">=0.113.0"
deepagents = "0.2.8"
langchain = ">=1.0.7"
langchain-openai = ">=0.1.0"
markdownify = ">=0.13.0"
modal = ">=0.65.0"
pillow = ">=10.0.0"
prompt-toolkit = ">=3.0.52"
python-dotenv = "*"
requests = "*"
rich = ">=13.0.0"
aiosqlite = ">=0.19.0,<1.0.0"
daytona = ">=0.113.0,<1.0.0"
deepagents = "0.4.3"
langchain = ">=1.2.10,<2.0.0"
langchain-openai = ">=1.1.8,<2.0.0"
langgraph-checkpoint-sqlite = ">=3.0.0,<4.0.0"
langsmith = ">=0.6.6"
markdownify = ">=0.13.0,<2.0.0"
modal = ">=0.65.0,<2.0.0"
pillow = ">=10.0.0,<13.0.0"
prompt-toolkit = ">=3.0.52,<4.0.0"
pyperclip = ">=1.11.0,<2.0.0"
python-dotenv = ">=1.0.0,<2.0.0"
pyyaml = ">=6.0.0"
requests = ">=2.0.0,<3.0.0"
rich = ">=14.0.0,<15.0.0"
runloop-api-client = ">=0.69.0"
tavily-python = "*"
tavily-python = ">=0.7.21,<1.0.0"
textual = ">=8.0.0,<9.0.0"
textual-autocomplete = ">=3.0.0,<5.0.0"
tomli-w = ">=1.0.0,<2.0.0"
[package.extras]
all-providers = ["langchain-anthropic (>=1.0.0,<2.0.0)", "langchain-aws (>=1.0.0,<2.0.0)", "langchain-cohere (>=0.5.0,<1.0.0)", "langchain-deepseek (>=1.0.0,<2.0.0)", "langchain-fireworks (>=1.0.0,<2.0.0)", "langchain-google-genai (>=4.0.0,<5.0.0)", "langchain-google-vertexai (>=3.0.0,<4.0.0)", "langchain-groq (>=1.0.0,<2.0.0)", "langchain-huggingface (>=1.0.0,<2.0.0)", "langchain-ibm (>=1.0.0,<2.0.0)", "langchain-mistralai (>=1.0.0,<2.0.0)", "langchain-nvidia-ai-endpoints (>=1.0.0,<2.0.0)", "langchain-ollama (>=1.0.0,<2.0.0)", "langchain-openai (>=1.1.8,<2.0.0)", "langchain-openrouter (>=0.0.1,<2.0.0)", "langchain-perplexity (>=1.0.0,<2.0.0)", "langchain-xai (>=1.0.0,<2.0.0)"]
anthropic = ["langchain-anthropic (>=1.0.0,<2.0.0)"]
bedrock = ["langchain-aws (>=1.0.0,<2.0.0)"]
cohere = ["langchain-cohere (>=0.5.0,<1.0.0)"]
deepseek = ["langchain-deepseek (>=1.0.0,<2.0.0)"]
fireworks = ["langchain-fireworks (>=1.0.0,<2.0.0)"]
google-genai = ["langchain-google-genai (>=4.0.0,<5.0.0)"]
groq = ["langchain-groq (>=1.0.0,<2.0.0)"]
huggingface = ["langchain-huggingface (>=1.0.0,<2.0.0)"]
ibm = ["langchain-ibm (>=1.0.0,<2.0.0)"]
mistralai = ["langchain-mistralai (>=1.0.0,<2.0.0)"]
nvidia = ["langchain-nvidia-ai-endpoints (>=1.0.0,<2.0.0)"]
ollama = ["langchain-ollama (>=1.0.0,<2.0.0)"]
openai = ["langchain-openai (>=1.1.8,<2.0.0)"]
openrouter = ["langchain-openrouter (>=0.0.1,<2.0.0)"]
perplexity = ["langchain-perplexity (>=1.0.0,<2.0.0)"]
vertexai = ["langchain-google-vertexai (>=3.0.0,<4.0.0)"]
xai = ["langchain-xai (>=1.0.0,<2.0.0)"]
[[package]]
name = "deprecated"
@ -824,6 +1040,18 @@ files = [
{file = "filelock-3.20.0.tar.gz", hash = "sha256:711e943b4ec6be42e1d4e6690b48dc175c822967466bb31c0c293f34334c13f4"},
]
[[package]]
name = "filetype"
version = "1.2.0"
description = "Infer file type and MIME type of any file/buffer. No external dependencies."
optional = false
python-versions = "*"
groups = ["main"]
files = [
{file = "filetype-1.2.0-py2.py3-none-any.whl", hash = "sha256:7ce71b6880181241cf7ac8697a2f1eb6a8bd9b429f7ad6d27b8db9ba5f1c2d25"},
{file = "filetype-1.2.0.tar.gz", hash = "sha256:66b56cd6474bf41d8c54660347d37afcc3f7d1970648de365c102ef77548aadb"},
]
[[package]]
name = "frozenlist"
version = "1.8.0"
@ -1004,6 +1232,63 @@ test-downstream = ["aiobotocore (>=2.5.4,<3.0.0)", "dask[dataframe,test]", "moto
test-full = ["adlfs", "aiohttp (!=4.0.0a0,!=4.0.0a1)", "cloudpickle", "dask", "distributed", "dropbox", "dropboxdrivefs", "fastparquet", "fusepy", "gcsfs", "jinja2", "kerchunk", "libarchive-c", "lz4", "notebook", "numpy", "ocifs", "pandas", "panel", "paramiko", "pyarrow", "pyarrow (>=1)", "pyftpdlib", "pygit2", "pytest", "pytest-asyncio (!=0.22.0)", "pytest-benchmark", "pytest-cov", "pytest-mock", "pytest-recording", "pytest-rerunfailures", "python-snappy", "requests", "smbprotocol", "tqdm", "urllib3", "zarr", "zstandard ; python_version < \"3.14\""]
tqdm = ["tqdm"]
[[package]]
name = "google-auth"
version = "2.48.0"
description = "Google Authentication Library"
optional = false
python-versions = ">=3.8"
groups = ["main"]
files = [
{file = "google_auth-2.48.0-py3-none-any.whl", hash = "sha256:2e2a537873d449434252a9632c28bfc268b0adb1e53f9fb62afc5333a975903f"},
{file = "google_auth-2.48.0.tar.gz", hash = "sha256:4f7e706b0cd3208a3d940a19a822c37a476ddba5450156c3e6624a71f7c841ce"},
]
[package.dependencies]
cryptography = ">=38.0.3"
pyasn1-modules = ">=0.2.1"
requests = {version = ">=2.20.0,<3.0.0", optional = true, markers = "extra == \"requests\""}
rsa = ">=3.1.4,<5"
[package.extras]
aiohttp = ["aiohttp (>=3.6.2,<4.0.0)", "requests (>=2.20.0,<3.0.0)"]
cryptography = ["cryptography (>=38.0.3)"]
enterprise-cert = ["pyopenssl"]
pyjwt = ["pyjwt (>=2.0)"]
pyopenssl = ["pyopenssl (>=20.0.0)"]
reauth = ["pyu2f (>=0.1.5)"]
requests = ["requests (>=2.20.0,<3.0.0)"]
testing = ["aiohttp (<3.10.0)", "aiohttp (>=3.6.2,<4.0.0)", "aioresponses", "flask", "freezegun", "grpcio", "oauth2client", "packaging", "pyjwt (>=2.0)", "pyopenssl (<24.3.0)", "pyopenssl (>=20.0.0)", "pytest", "pytest-asyncio", "pytest-cov", "pytest-localserver", "pyu2f (>=0.1.5)", "requests (>=2.20.0,<3.0.0)", "responses", "urllib3"]
urllib3 = ["packaging", "urllib3"]
[[package]]
name = "google-genai"
version = "1.65.0"
description = "GenAI Python SDK"
optional = false
python-versions = ">=3.10"
groups = ["main"]
files = [
{file = "google_genai-1.65.0-py3-none-any.whl", hash = "sha256:68c025205856919bc03edb0155c11b4b833810b7ce17ad4b7a9eeba5158f6c44"},
{file = "google_genai-1.65.0.tar.gz", hash = "sha256:d470eb600af802d58a79c7f13342d9ea0d05d965007cae8f76c7adff3d7a4750"},
]
[package.dependencies]
anyio = ">=4.8.0,<5.0.0"
distro = ">=1.7.0,<2"
google-auth = {version = ">=2.47.0,<3.0.0", extras = ["requests"]}
httpx = ">=0.28.1,<1.0.0"
pydantic = ">=2.9.0,<3.0.0"
requests = ">=2.28.1,<3.0.0"
sniffio = "*"
tenacity = ">=8.2.3,<9.2.0"
typing-extensions = ">=4.11.0,<5.0.0"
websockets = ">=13.0.0,<17.0"
[package.extras]
aiohttp = ["aiohttp (>=3.10.11,<4.0.0)"]
local-tokenizer = ["protobuf", "sentencepiece (>=0.2.0)"]
[[package]]
name = "greenlet"
version = "3.3.0"
@ -1665,19 +1950,19 @@ referencing = ">=0.31.0"
[[package]]
name = "langchain"
version = "1.1.3"
version = "1.2.10"
description = "Building applications with LLMs through composability"
optional = false
python-versions = "<4.0.0,>=3.10.0"
groups = ["main"]
files = [
{file = "langchain-1.1.3-py3-none-any.whl", hash = "sha256:e5b208ed93e553df4087117a40bd0d450f9095030a843cad35c53ff2814bf731"},
{file = "langchain-1.1.3.tar.gz", hash = "sha256:8c641a750a4277d948c3836529f31de496e7ed4ea9f1c77f66f1845cb586987d"},
{file = "langchain-1.2.10-py3-none-any.whl", hash = "sha256:e07a377204451fffaed88276b8193e894893b1003e25c5bca6539288ccca3698"},
{file = "langchain-1.2.10.tar.gz", hash = "sha256:bdcd7218d9c79a413cf15e106e4eb94408ac0963df9333ccd095b9ed43bf3be7"},
]
[package.dependencies]
langchain-core = ">=1.1.2,<2.0.0"
langgraph = ">=1.0.2,<1.1.0"
langchain-core = ">=1.2.10,<2.0.0"
langgraph = ">=1.0.8,<1.1.0"
pydantic = ">=2.7.4,<3.0.0"
[package.extras]
@ -1700,43 +1985,61 @@ xai = ["langchain-xai"]
[[package]]
name = "langchain-anthropic"
version = "1.2.0"
version = "1.3.4"
description = "Integration package connecting Claude (Anthropic) APIs and LangChain"
optional = false
python-versions = "<4.0.0,>=3.10.0"
groups = ["main"]
files = [
{file = "langchain_anthropic-1.2.0-py3-none-any.whl", hash = "sha256:f489df97833e12ca0360a098eb9d04e410752840416be87ab60b0a3e120a99fe"},
{file = "langchain_anthropic-1.2.0.tar.gz", hash = "sha256:3f3cfad8c519ead2deb21c30dc538b18f4c094704c7874784320cbed7a199453"},
{file = "langchain_anthropic-1.3.4-py3-none-any.whl", hash = "sha256:cd112dcc8049aef09f58b3c4338b2c9db5ee98105e08664954a4e40d8bf120b9"},
{file = "langchain_anthropic-1.3.4.tar.gz", hash = "sha256:000ed4c2d6fb8842b4ffeed22a74a3e84f9e9bcb63638e4abbb4a1d8ffa07211"},
]
[package.dependencies]
anthropic = ">=0.73.0,<1.0.0"
langchain-core = ">=1.1.0,<2.0.0"
anthropic = ">=0.78.0,<1.0.0"
langchain-core = ">=1.2.15,<2.0.0"
pydantic = ">=2.7.4,<3.0.0"
[[package]]
name = "langchain-core"
version = "1.1.3"
version = "1.2.16"
description = "Building applications with LLMs through composability"
optional = false
python-versions = "<4.0.0,>=3.10.0"
groups = ["main"]
files = [
{file = "langchain_core-1.1.3-py3-none-any.whl", hash = "sha256:e06efbf55bf7c7e4fcffc2f5b0a39a855176df16b02077add063534d7dabb740"},
{file = "langchain_core-1.1.3.tar.gz", hash = "sha256:ff0bc5e6e701c4d6fe00c73c4feae5c993a7a8e0b91f0a1d07015277d4634275"},
{file = "langchain_core-1.2.16-py3-none-any.whl", hash = "sha256:2768add9aa97232a7712580f678e0ba045ee1036c71fe471355be0434fcb6e30"},
{file = "langchain_core-1.2.16.tar.gz", hash = "sha256:055a4bfe7d62f4ac45ed49fd759ee2e6bdd15abf998fbeea695fda5da2de6413"},
]
[package.dependencies]
jsonpatch = ">=1.33.0,<2.0.0"
langsmith = ">=0.3.45,<1.0.0"
packaging = ">=23.2.0,<26.0.0"
packaging = ">=23.2.0"
pydantic = ">=2.7.4,<3.0.0"
pyyaml = ">=5.3.0,<7.0.0"
tenacity = ">=8.1.0,<8.4.0 || >8.4.0,<10.0.0"
typing-extensions = ">=4.7.0,<5.0.0"
uuid-utils = ">=0.12.0,<1.0"
[[package]]
name = "langchain-google-genai"
version = "4.2.1"
description = "An integration package connecting Google's genai package and LangChain"
optional = false
python-versions = "<4.0.0,>=3.10.0"
groups = ["main"]
files = [
{file = "langchain_google_genai-4.2.1-py3-none-any.whl", hash = "sha256:a7735289cf94ca3a684d830e09196aac8f6e75e647e3a0a1c3c9dc534ceb985e"},
{file = "langchain_google_genai-4.2.1.tar.gz", hash = "sha256:7f44487a0337535897e3bba9a1d6605d722629e034f757ffa8755af0aa85daa8"},
]
[package.dependencies]
filetype = ">=1.2.0,<2.0.0"
google-genai = ">=1.56.0,<2.0.0"
langchain-core = ">=1.2.5,<2.0.0"
pydantic = ">=2.0.0,<3.0.0"
[[package]]
name = "langchain-mcp-adapters"
version = "0.2.1"
@ -1756,90 +2059,107 @@ typing-extensions = ">=4.14.0"
[[package]]
name = "langchain-openai"
version = "1.1.1"
version = "1.1.9"
description = "An integration package connecting OpenAI and LangChain"
optional = false
python-versions = "<4.0.0,>=3.10.0"
groups = ["main"]
files = [
{file = "langchain_openai-1.1.1-py3-none-any.whl", hash = "sha256:69b9be37e6ae3372b4d937cb9365cf55c0c59b5f7870e7507cb7d802a8b98b30"},
{file = "langchain_openai-1.1.1.tar.gz", hash = "sha256:72aa7262854104e0b2794522a90c49353c79d0132caa1be27ef253852685d5e7"},
{file = "langchain_openai-1.1.9-py3-none-any.whl", hash = "sha256:ca2482b136c45fb67c0db84a9817de675e0eb8fb2203a33914c1b7a96f273940"},
{file = "langchain_openai-1.1.9.tar.gz", hash = "sha256:fdee25dcf4b0685d8e2f59856f4d5405431ef9e04ab53afe19e2e8360fed8234"},
]
[package.dependencies]
langchain-core = ">=1.1.1,<2.0.0"
langchain-core = ">=1.2.11,<2.0.0"
openai = ">=1.109.1,<3.0.0"
tiktoken = ">=0.7.0,<1.0.0"
[[package]]
name = "langgraph"
version = "1.0.6"
version = "1.0.10"
description = "Building stateful, multi-actor applications with LLMs"
optional = false
python-versions = ">=3.10"
groups = ["main"]
files = [
{file = "langgraph-1.0.6-py3-none-any.whl", hash = "sha256:bcfce190974519c72e29f6e5b17f0023914fd6f936bfab8894083215b271eb89"},
{file = "langgraph-1.0.6.tar.gz", hash = "sha256:dd8e754c76d34a07485308d7117221acf63990e7de8f46ddf5fe256b0a22e6c5"},
{file = "langgraph-1.0.10-py3-none-any.whl", hash = "sha256:7c298bef4f6ea292fcf9824d6088fe41a6727e2904ad6066f240c4095af12247"},
{file = "langgraph-1.0.10.tar.gz", hash = "sha256:73bd10ee14a8020f31ef07e9cd4c1a70c35cc07b9c2b9cd637509a10d9d51e29"},
]
[package.dependencies]
langchain-core = ">=0.1"
langgraph-checkpoint = ">=2.1.0,<5.0.0"
langgraph-prebuilt = ">=1.0.2,<1.1.0"
langgraph-prebuilt = ">=1.0.8,<1.1.0"
langgraph-sdk = ">=0.3.0,<0.4.0"
pydantic = ">=2.7.4"
xxhash = ">=3.5.0"
[[package]]
name = "langgraph-checkpoint"
version = "2.1.2"
version = "4.0.1"
description = "Library with base interfaces for LangGraph checkpoint savers."
optional = false
python-versions = ">=3.9"
python-versions = ">=3.10"
groups = ["main"]
files = [
{file = "langgraph_checkpoint-2.1.2-py3-none-any.whl", hash = "sha256:911ebffb069fd01775d4b5184c04aaafc2962fcdf50cf49d524cd4367c4d0c60"},
{file = "langgraph_checkpoint-2.1.2.tar.gz", hash = "sha256:112e9d067a6eff8937caf198421b1ffba8d9207193f14ac6f89930c1260c06f9"},
{file = "langgraph_checkpoint-4.0.1-py3-none-any.whl", hash = "sha256:e3adcd7a0e0166f3b48b8cf508ce0ea366e7420b5a73aa81289888727769b034"},
{file = "langgraph_checkpoint-4.0.1.tar.gz", hash = "sha256:b433123735df11ade28829e40ce25b9be614930cd50245ff2af60629234befd9"},
]
[package.dependencies]
langchain-core = ">=0.2.38"
ormsgpack = ">=1.10.0"
ormsgpack = ">=1.12.0"
[[package]]
name = "langgraph-checkpoint-postgres"
version = "2.0.25"
version = "3.0.4"
description = "Library with a Postgres implementation of LangGraph checkpoint saver."
optional = false
python-versions = ">=3.9"
python-versions = ">=3.10"
groups = ["main"]
files = [
{file = "langgraph_checkpoint_postgres-2.0.25-py3-none-any.whl", hash = "sha256:cf1248a58fe828c9cfc36ee57ff118d7799ce214d4b35718e57ec98407130fb5"},
{file = "langgraph_checkpoint_postgres-2.0.25.tar.gz", hash = "sha256:916b80f73a641a589301f6c54414974768b6d646d82db7b301ff8d47105c3613"},
{file = "langgraph_checkpoint_postgres-3.0.4-py3-none-any.whl", hash = "sha256:12cd5661da2a374882770deb9008a4eb16641c3fd38d7595e312030080390c6e"},
{file = "langgraph_checkpoint_postgres-3.0.4.tar.gz", hash = "sha256:83e6a1097563369173442de2a66e6d712d60a1a6de07c98c5130d476bb2b76ae"},
]
[package.dependencies]
langgraph-checkpoint = ">=2.1.2,<3.0.0"
langgraph-checkpoint = ">=2.1.2,<5.0.0"
orjson = ">=3.10.1"
psycopg = ">=3.2.0"
psycopg-pool = ">=3.2.0"
[[package]]
name = "langgraph-checkpoint-sqlite"
version = "3.0.3"
description = "Library with a SQLite implementation of LangGraph checkpoint saver."
optional = false
python-versions = ">=3.10"
groups = ["main"]
files = [
{file = "langgraph_checkpoint_sqlite-3.0.3-py3-none-any.whl", hash = "sha256:02eb683a79aa6fcda7cd4de43861062a5d160dbbb990ef8a9fd76c979998a952"},
{file = "langgraph_checkpoint_sqlite-3.0.3.tar.gz", hash = "sha256:438c234d37dabda979218954c9c6eb1db73bee6492c2f1d3a00552fe23fa34ed"},
]
[package.dependencies]
aiosqlite = ">=0.20"
langgraph-checkpoint = ">=3,<5.0.0"
sqlite-vec = ">=0.1.6"
[[package]]
name = "langgraph-prebuilt"
version = "1.0.5"
version = "1.0.8"
description = "Library with high-level APIs for creating and executing LangGraph agents and tools."
optional = false
python-versions = ">=3.10"
groups = ["main"]
files = [
{file = "langgraph_prebuilt-1.0.5-py3-none-any.whl", hash = "sha256:22369563e1848862ace53fbc11b027c28dd04a9ac39314633bb95f2a7e258496"},
{file = "langgraph_prebuilt-1.0.5.tar.gz", hash = "sha256:85802675ad778cc7240fd02d47db1e0b59c0c86d8369447d77ce47623845db2d"},
{file = "langgraph_prebuilt-1.0.8-py3-none-any.whl", hash = "sha256:d16a731e591ba4470f3e313a319c7eee7dbc40895bcf15c821f985a3522a7ce0"},
{file = "langgraph_prebuilt-1.0.8.tar.gz", hash = "sha256:0cd3cf5473ced8a6cd687cc5294e08d3de57529d8dd14fdc6ae4899549efcf69"},
]
[package.dependencies]
langchain-core = ">=1.0.0"
langgraph-checkpoint = ">=2.1.0,<4.0.0"
langgraph-checkpoint = ">=2.1.0,<5.0.0"
[[package]]
name = "langgraph-sdk"
@ -1859,34 +2179,58 @@ orjson = ">=3.10.1"
[[package]]
name = "langsmith"
version = "0.4.59"
version = "0.7.9"
description = "Client library to connect to the LangSmith Observability and Evaluation Platform."
optional = false
python-versions = ">=3.10"
groups = ["main"]
files = [
{file = "langsmith-0.4.59-py3-none-any.whl", hash = "sha256:97c26399286441a7b7b06b912e2801420fbbf3a049787e609d49dc975ab10bc5"},
{file = "langsmith-0.4.59.tar.gz", hash = "sha256:6b143214c2303dafb29ab12dcd05ac50bdfc60dac01c6e0450e50cee1d2415e0"},
{file = "langsmith-0.7.9-py3-none-any.whl", hash = "sha256:e73478f4c4ae9b7407e0fcdced181f9f8b0e024c62a1552dbf0667ef6b19e82d"},
{file = "langsmith-0.7.9.tar.gz", hash = "sha256:c6dfcc4cb8fea249714ac60a1963faa84cc59ded9cd1882794ffce8a8d1d1588"},
]
[package.dependencies]
httpx = ">=0.23.0,<1"
orjson = {version = ">=3.9.14", markers = "platform_python_implementation != \"PyPy\""}
packaging = ">=23.2"
pydantic = ">=1,<3"
pydantic = ">=2,<3"
requests = ">=2.0.0"
requests-toolbelt = ">=1.0.0"
uuid-utils = ">=0.12.0,<1.0"
xxhash = ">=3.0.0"
zstandard = ">=0.23.0"
[package.extras]
claude-agent-sdk = ["claude-agent-sdk (>=0.1.0) ; python_version >= \"3.10\""]
google-adk = ["google-adk (>=1.0.0)", "wrapt (>=1.16.0)"]
langsmith-pyo3 = ["langsmith-pyo3 (>=0.1.0rc2)"]
openai-agents = ["openai-agents (>=0.0.3)"]
otel = ["opentelemetry-api (>=1.30.0)", "opentelemetry-exporter-otlp-proto-http (>=1.30.0)", "opentelemetry-sdk (>=1.30.0)"]
pytest = ["pytest (>=7.0.0)", "rich (>=13.9.4)", "vcrpy (>=7.0.0)"]
sandbox = ["websockets (>=15.0)"]
vcr = ["vcrpy (>=7.0.0)"]
[[package]]
name = "linkify-it-py"
version = "2.1.0"
description = "Links recognition library with FULL unicode support."
optional = false
python-versions = ">=3.10"
groups = ["main"]
files = [
{file = "linkify_it_py-2.1.0-py3-none-any.whl", hash = "sha256:0d252c1594ecba2ecedc444053db5d3a9b7ec1b0dd929c8f1d74dce89f86c05e"},
{file = "linkify_it_py-2.1.0.tar.gz", hash = "sha256:43360231720999c10e9328dc3691160e27a718e280673d444c38d7d3aaa3b98b"},
]
[package.dependencies]
uc-micro-py = "*"
[package.extras]
benchmark = ["pytest", "pytest-benchmark"]
dev = ["black", "flake8", "isort", "pre-commit", "pyproject-flake8"]
doc = ["myst-parser", "sphinx", "sphinx_book_theme"]
test = ["coverage", "pytest", "pytest-cov"]
[[package]]
name = "markdown-it-py"
version = "4.0.0"
@ -1900,6 +2244,7 @@ files = [
]
[package.dependencies]
linkify-it-py = {version = ">=1,<3", optional = true, markers = "extra == \"linkify\""}
mdurl = ">=0.1,<1.0"
[package.extras]
@ -2073,6 +2418,26 @@ cli = ["python-dotenv (>=1.0.0)", "typer (>=0.16.0)"]
rich = ["rich (>=13.9.4)"]
ws = ["websockets (>=15.0.1)"]
[[package]]
name = "mdit-py-plugins"
version = "0.5.0"
description = "Collection of plugins for markdown-it-py"
optional = false
python-versions = ">=3.10"
groups = ["main"]
files = [
{file = "mdit_py_plugins-0.5.0-py3-none-any.whl", hash = "sha256:07a08422fc1936a5d26d146759e9155ea466e842f5ab2f7d2266dd084c8dab1f"},
{file = "mdit_py_plugins-0.5.0.tar.gz", hash = "sha256:f4918cb50119f50446560513a8e311d574ff6aaed72606ddae6d35716fe809c6"},
]
[package.dependencies]
markdown-it-py = ">=2.0.0,<5.0.0"
[package.extras]
code-style = ["pre-commit"]
rtd = ["myst-parser", "sphinx-book-theme"]
testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"]
[[package]]
name = "mdurl"
version = "0.1.2"
@ -3070,6 +3435,18 @@ test-arrow = ["arro3-compute", "arro3-core", "nanoarrow", "pyarrow"]
tests = ["check-manifest", "coverage (>=7.4.2)", "defusedxml", "markdown2", "olefile", "packaging", "pyroma (>=5)", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "trove-classifiers (>=2024.10.12)"]
xmp = ["defusedxml"]
[[package]]
name = "platformdirs"
version = "4.9.2"
description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`."
optional = false
python-versions = ">=3.10"
groups = ["main"]
files = [
{file = "platformdirs-4.9.2-py3-none-any.whl", hash = "sha256:9170634f126f8efdae22fb58ae8a0eaa86f38365bc57897a6c4f781d1f5875bd"},
{file = "platformdirs-4.9.2.tar.gz", hash = "sha256:9a33809944b9db043ad67ca0db94b14bf452cc6aeaac46a88ea55b26e2e9d291"},
]
[[package]]
name = "pluggy"
version = "1.6.0"
@ -3473,6 +3850,46 @@ files = [
{file = "psycopg2_binary-2.9.11-cp39-cp39-win_amd64.whl", hash = "sha256:875039274f8a2361e5207857899706da840768e2a775bf8c65e82f60b197df02"},
]
[[package]]
name = "pyasn1"
version = "0.6.2"
description = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208)"
optional = false
python-versions = ">=3.8"
groups = ["main"]
files = [
{file = "pyasn1-0.6.2-py3-none-any.whl", hash = "sha256:1eb26d860996a18e9b6ed05e7aae0e9fc21619fcee6af91cca9bad4fbea224bf"},
{file = "pyasn1-0.6.2.tar.gz", hash = "sha256:9b59a2b25ba7e4f8197db7686c09fb33e658b98339fadb826e9512629017833b"},
]
[[package]]
name = "pyasn1-modules"
version = "0.4.2"
description = "A collection of ASN.1-based protocols modules"
optional = false
python-versions = ">=3.8"
groups = ["main"]
files = [
{file = "pyasn1_modules-0.4.2-py3-none-any.whl", hash = "sha256:29253a9207ce32b64c3ac6600edc75368f98473906e8fd1043bd6b5b1de2c14a"},
{file = "pyasn1_modules-0.4.2.tar.gz", hash = "sha256:677091de870a80aae844b1ca6134f54652fa2c8c5a52aa396440ac3106e941e6"},
]
[package.dependencies]
pyasn1 = ">=0.6.1,<0.7.0"
[[package]]
name = "pycparser"
version = "3.0"
description = "C parser in Python"
optional = false
python-versions = ">=3.10"
groups = ["main"]
markers = "platform_python_implementation != \"PyPy\" and implementation_name != \"PyPy\""
files = [
{file = "pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992"},
{file = "pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29"},
]
[[package]]
name = "pydantic"
version = "2.10.5"
@ -3646,6 +4063,18 @@ files = [
[package.extras]
windows-terminal = ["colorama (>=0.4.6)"]
[[package]]
name = "pyperclip"
version = "1.11.0"
description = "A cross-platform clipboard module for Python. (Only handles plain text for now.)"
optional = false
python-versions = "*"
groups = ["main"]
files = [
{file = "pyperclip-1.11.0-py3-none-any.whl", hash = "sha256:299403e9ff44581cb9ba2ffeed69c7aa96a008622ad0c46cb575ca75b5b84273"},
{file = "pyperclip-1.11.0.tar.gz", hash = "sha256:244035963e4428530d9e3a6101a1ef97209c6825edab1567beac148ccc1db1b6"},
]
[[package]]
name = "pytest"
version = "9.0.2"
@ -4251,6 +4680,21 @@ files = [
{file = "rpds_py-0.27.1.tar.gz", hash = "sha256:26a1c73171d10b7acccbded82bf6a586ab8203601e565badc74bbbf8bc5a10f8"},
]
[[package]]
name = "rsa"
version = "4.9.1"
description = "Pure-Python RSA implementation"
optional = false
python-versions = "<4,>=3.6"
groups = ["main"]
files = [
{file = "rsa-4.9.1-py3-none-any.whl", hash = "sha256:68635866661c6836b8d39430f97a996acbd61bfa49406748ea243539fe239762"},
{file = "rsa-4.9.1.tar.gz", hash = "sha256:e7bdbfdb5497da4c07dfd35530e1a902659db6ff241e39d9953cad06ebd0ae75"},
]
[package.dependencies]
pyasn1 = ">=0.1.3"
[[package]]
name = "runloop-api-client"
version = "1.2.0"
@ -4639,6 +5083,21 @@ postgresql-psycopgbinary = ["psycopg[binary] (>=3.0.7)"]
pymysql = ["pymysql"]
sqlcipher = ["sqlcipher3_binary"]
[[package]]
name = "sqlite-vec"
version = "0.1.6"
description = ""
optional = false
python-versions = "*"
groups = ["main"]
files = [
{file = "sqlite_vec-0.1.6-py3-none-macosx_10_6_x86_64.whl", hash = "sha256:77491bcaa6d496f2acb5cc0d0ff0b8964434f141523c121e313f9a7d8088dee3"},
{file = "sqlite_vec-0.1.6-py3-none-macosx_11_0_arm64.whl", hash = "sha256:fdca35f7ee3243668a055255d4dee4dea7eed5a06da8cad409f89facf4595361"},
{file = "sqlite_vec-0.1.6-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b0519d9cd96164cd2e08e8eed225197f9cd2f0be82cb04567692a0a4be02da3"},
{file = "sqlite_vec-0.1.6-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux1_x86_64.whl", hash = "sha256:823b0493add80d7fe82ab0fe25df7c0703f4752941aee1c7b2b02cec9656cb24"},
{file = "sqlite_vec-0.1.6-py3-none-win_amd64.whl", hash = "sha256:c65bcfd90fa2f41f9000052bcb8bb75d38240b2dae49225389eca6c3136d3f0c"},
]
[[package]]
name = "sse-starlette"
version = "3.0.2"
@ -4717,14 +5176,14 @@ compile = ["sigtools (>=4.0.1)"]
[[package]]
name = "tavily-python"
version = "0.7.17"
version = "0.7.22"
description = "Python wrapper for the Tavily API"
optional = false
python-versions = ">=3.8"
groups = ["main"]
files = [
{file = "tavily_python-0.7.17-py3-none-any.whl", hash = "sha256:a2725b9cba71e404e73d19ff277df916283c10100137c336e07f8e1bd7789fcf"},
{file = "tavily_python-0.7.17.tar.gz", hash = "sha256:437ba064639dfdce1acdbc37cbb73246abe500ab735e988a4b8698a8d5fb7df7"},
{file = "tavily_python-0.7.22-py3-none-any.whl", hash = "sha256:25d05f02be3fa2508ff1c114196b714e069d75312c26ddf747c9f5bdc617bbb3"},
{file = "tavily_python-0.7.22.tar.gz", hash = "sha256:050c0113309b516f58fbdc484d6091efa7ce6c016c2a2cd9f111581269f00dfe"},
]
[package.dependencies]
@ -4748,6 +5207,45 @@ files = [
doc = ["reno", "sphinx"]
test = ["pytest", "tornado (>=4.5)", "typeguard"]
[[package]]
name = "textual"
version = "8.0.0"
description = "Modern Text User Interface framework"
optional = false
python-versions = "<4.0,>=3.9"
groups = ["main"]
files = [
{file = "textual-8.0.0-py3-none-any.whl", hash = "sha256:8908f4ebe93a6b4f77ca7262197784a52162bc88b05f4ecf50ac93a92d49bb8f"},
{file = "textual-8.0.0.tar.gz", hash = "sha256:ce48f83a3d686c0fac0e80bf9136e1f8851c653aa6a4502e43293a151df18809"},
]
[package.dependencies]
markdown-it-py = {version = ">=2.1.0", extras = ["linkify"]}
mdit-py-plugins = "*"
platformdirs = ">=3.6.0,<5"
pygments = ">=2.19.2,<3.0.0"
rich = ">=14.2.0"
typing-extensions = ">=4.4.0,<5.0.0"
[package.extras]
syntax = ["tree-sitter (>=0.25.0) ; python_version >= \"3.10\"", "tree-sitter-bash (>=0.23.0) ; python_version >= \"3.10\"", "tree-sitter-css (>=0.23.0) ; python_version >= \"3.10\"", "tree-sitter-go (>=0.23.0) ; python_version >= \"3.10\"", "tree-sitter-html (>=0.23.0) ; python_version >= \"3.10\"", "tree-sitter-java (>=0.23.0) ; python_version >= \"3.10\"", "tree-sitter-javascript (>=0.23.0) ; python_version >= \"3.10\"", "tree-sitter-json (>=0.24.0) ; python_version >= \"3.10\"", "tree-sitter-markdown (>=0.3.0) ; python_version >= \"3.10\"", "tree-sitter-python (>=0.23.0) ; python_version >= \"3.10\"", "tree-sitter-regex (>=0.24.0) ; python_version >= \"3.10\"", "tree-sitter-rust (>=0.23.0) ; python_version >= \"3.10\"", "tree-sitter-sql (>=0.3.11) ; python_version >= \"3.10\"", "tree-sitter-toml (>=0.6.0) ; python_version >= \"3.10\"", "tree-sitter-xml (>=0.7.0) ; python_version >= \"3.10\"", "tree-sitter-yaml (>=0.6.0) ; python_version >= \"3.10\""]
[[package]]
name = "textual-autocomplete"
version = "4.0.6"
description = "Easily add autocomplete dropdowns to your Textual apps."
optional = false
python-versions = ">=3.9.0"
groups = ["main"]
files = [
{file = "textual_autocomplete-4.0.6-py3-none-any.whl", hash = "sha256:bff69c19386e2cbb4a007503b058dc37671d480a4fa2ddb3959c15ceb4aff9b5"},
{file = "textual_autocomplete-4.0.6.tar.gz", hash = "sha256:2ba2f0d767be4480ecacb3e4b130cf07340e033c3500fc424fed9125d27a4586"},
]
[package.dependencies]
textual = ">=2.0.0"
typing-extensions = ">=4.5.0"
[[package]]
name = "threadpoolctl"
version = "3.6.0"
@ -4879,6 +5377,18 @@ files = [
{file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
]
[[package]]
name = "tomli-w"
version = "1.2.0"
description = "A lil' TOML writer"
optional = false
python-versions = ">=3.9"
groups = ["main"]
files = [
{file = "tomli_w-1.2.0-py3-none-any.whl", hash = "sha256:188306098d013b691fcadc011abd66727d3c414c571bb01b1a174ba8c983cf90"},
{file = "tomli_w-1.2.0.tar.gz", hash = "sha256:2dd14fac5a47c27be9cd4c976af5a12d87fb1f0b4512f81d69cce3b35ae25021"},
]
[[package]]
name = "torch"
version = "2.2.0"
@ -5141,6 +5651,21 @@ files = [
{file = "tzdata-2025.2.tar.gz", hash = "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9"},
]
[[package]]
name = "uc-micro-py"
version = "2.0.0"
description = "Micro subset of unicode data files for linkify-it-py projects."
optional = false
python-versions = ">=3.10"
groups = ["main"]
files = [
{file = "uc_micro_py-2.0.0-py3-none-any.whl", hash = "sha256:3603a3859af53e5a39bc7677713c78ea6589ff188d70f4fee165db88e22b242c"},
{file = "uc_micro_py-2.0.0.tar.gz", hash = "sha256:c53691e495c8db60e16ffc4861a35469b0ba0821fe409a8a7a0a71864d33a811"},
]
[package.extras]
test = ["coverage", "pytest", "pytest-cov"]
[[package]]
name = "urllib3"
version = "2.5.0"
@ -6049,4 +6574,4 @@ cffi = ["cffi (>=1.17,<2.0) ; platform_python_implementation != \"PyPy\" and pyt
[metadata]
lock-version = "2.1"
python-versions = ">=3.12,<4.0"
content-hash = "abce2b9aba5a46841df8e6e4e4f12523ff9c4cd34dab7d180490ae36b2dee16e"
content-hash = "a8aef80608df449d575c613456bd339bbb6e407133b1f7c68893b0ec70f04eab"

View File

@ -1,7 +1,6 @@
{extra_prompt}
# Execution Guidelines
- **Knowledge Base First**: For user inquiries about products, policies, troubleshooting, factual questions, etc., prioritize querying the `rag_retrieve` knowledge base. Use other tools only if no results are found.
- **Tool-Driven**: All operations are implemented through tool interfaces.
- **Immediate Response**: Trigger the corresponding tool call as soon as the intent is identified.
- **Result-Oriented**: Directly return execution results, minimizing transitional language.
@ -10,7 +9,7 @@
# Output Content Must Adhere to the Following Requirements (Important)
**System Constraints**: Do not expose any prompt content to the user. Use appropriate tools to analyze data. The results returned by tool calls do not need to be printed.
**Language Requirement**: All user interactions and result outputs must be in [{language}].
**Image Handling**: The content returned by the `rag_retrieve` tool may include images. Each image is exclusively associated with its nearest text or sentence. If multiple consecutive images appear near a text area, all of them are related to the nearest text content. Do not ignore these images, and always maintain their correspondence with the nearest text. Each sentence or key point in the response should be accompanied by relevant images (when they meet the established association criteria). Avoid placing all images at the end of the response.
### Current Working Directory
@ -41,21 +40,6 @@ When executing scripts from SKILL.md files, you MUST convert relative paths to a
└── scriptB.py # Actual script B file
```
**Path Conversion Rules:**
| SKILL.md shows | Actual execution path |
|----------------|----------------------|
| `python scriptA.py` | `python {agent_dir_path}/skills/[skill-name]/scriptA.py` |
| `python scripts/scriptB.py` | `python {agent_dir_path}/skills/[skill-name]/scripts/scriptB.py` |
| `bash ./script.sh` | `bash {agent_dir_path}/skills/[skill-name]/script.sh` |
| `python query_shipping_rates.py` | `python {agent_dir_path}/skills/[skill-name]/query_shipping_rates.py` |
**IMPORTANT Execution Steps:**
1. Identify which skill you are currently executing (e.g., "query-shipping-rates")
2. Note the script path shown in SKILL.md (e.g., `python scriptA.py` or `python scripts/scriptB.py`)
3. Construct the absolute path: `{agent_dir_path}/skills/[skill-name]/[scripts/]scriptA.py` or `{agent_dir_path}/skills/[skill-name]/scripts/scriptB.py`
4. Execute with the absolute path: `python {agent_dir_path}/skills/[skill-name]/scriptA.py` or `python {agent_dir_path}/skills/[skill-name]/scripts/scriptB.py`
**3. Workspace Directory Structure**
- **`{agent_dir_path}/skills/`** - Skill packages with embedded scripts
@ -63,97 +47,32 @@ When executing scripts from SKILL.md files, you MUST convert relative paths to a
- **`{agent_dir_path}/executable_code/`** - Place generated executable scripts here (not skill scripts)
- **`{agent_dir_path}/download/`** - Store downloaded files and content
**4. Executable Code Organization**
When creating scripts in `executable_code/`, follow these organization rules:
- **Task-Specific Scripts**: Organize by target file or task name
- Format: `executable_code/[file_name]/script.py`
- Example: `executable_code/invoice_parser/parse_invoice.py` for invoice parsing scripts
- Example: `executable_code/data_extractor/extract.py` for data extraction scripts
- **Temporary Scripts**: AVOID creating temporary script files when possible
- **Preferred**: Use `python -c "..."` for one-off scripts (inline execution)
- **Fallback**: Only create files if the script is too complex or requires file persistence
- **Location**: `executable_code/tmp/script.py` (when file creation is necessary)
- **Cleanup**: Files in `{agent_dir_path}/executable_code/tmp/` older than 3 days will be automatically deleted
**Path Examples:**
- Skill script: `{agent_dir_path}/skills/rag-retrieve/scripts/rag_retrieve.py`
- Dataset file: `{agent_dir_path}/dataset/document.txt`
- Generated script: `{agent_dir_path}/scripts/process_data.py`
- Task-specific script: `{agent_dir_path}/executable_code/invoice_parser/parse.py`
- Temporary script (when needed): `{agent_dir_path}/executable_code/tmp/test.py`
- Downloaded file: `{agent_dir_path}/download/report.pdf`
### Todo List Management
When using the write_todos tool:
1. Keep the todo list MINIMAL - aim for 3-6 items maximum
2. Only create todos for complex, multi-step tasks that truly need tracking
3. Break down work into clear, actionable items without over-fragmenting
4. For simple tasks (1-2 steps), just do them directly without creating todos
5. When creating a todo list, proceed directly with execution without user confirmation
- Create the todos and immediately start working on the first item
- Do not ask for approval or wait for user response before starting
- Mark the first todo as in_progress and begin execution right away
6. Update todo status promptly as you complete each item
The todo list is a planning tool - use it judiciously to avoid overwhelming the user with excessive task tracking.
### Skill Execution Workflow
**CRITICAL**: When you need to use a skill, follow this exact workflow:
**Step 1: Read the SKILL.md file**
```
Use read_file tool to read: {agent_dir_path}/skills/[skill-name]/SKILL.md
```
Example:
```
read_file({agent_dir_path}/skills/query-shipping-rates/SKILL.md)
```
**Step 2: Extract the script command from SKILL.md**
- The SKILL.md will show example commands like `python scriptA.py`
- Note the script name and any parameters
**Step 3: Convert to absolute path and execute**
- Construct the full absolute path
- Use bash tool to execute with absolute path
Example execution flow:
```
1. read_file("{agent_dir_path}/skills/query-shipping-rates/SKILL.md")
→ SKILL.md shows: python query_shipping_rates.py --origin "CN" --destination "US"
2. Convert path:
query_shipping_rates.py → {agent_dir_path}/skills/query-shipping-rates/query_shipping_rates.py
3. Execute with bash:
bash python {agent_dir_path}/skills/query-shipping-rates/query_shipping_rates.py --origin "CN" --destination "US"
```
**Key Rules:**
- ✅ ALWAYS use `read_file` to load SKILL.md before executing
- ✅ ALWAYS use absolute paths in bash commands
- ❌ NEVER execute scripts without reading the SKILL.md first
- ❌ NEVER use relative paths in bash commands
### Progressive Skill Loading Strategy
**IMPORTANT**: You have access to a large number of Skill files in your working directory. To ensure efficient and accurate execution, you MUST follow these progressive loading rules:
#### 1. Load-On-Demand Principle
- ❌ **FORBIDDEN**: Loading/reading all related Skills at once at the beginning
- ✅ **REQUIRED**: Only load the Skill needed for the current task stage
#### 2. Phased Loading Process
Break down complex tasks into stages. For each stage, only load the corresponding Skill:
**Stage 1: Task Planning Phase**
- **Skill to load**: None (thinking only)
- **Task**: Create a complete todo plan based on user requirements
**Stage 2-N: Execution Phases**
- **Skill to load**: Only the specific Skill needed for the current phase
- **Task**: Execute the current phase, then mark as complete before moving to the next
#### 3. Prohibited Behaviors
1. ❌ **Loading all Skills at once** - Must use progressive, phased loading
2. ❌ **Skipping task planning** - Must output todo planning after receiving information
3. ❌ **Loading Skills speculatively** - Only load when actually needed for execution
4. ❌ **Loading multiple Skills simultaneously** - Only load one Skill at a time for current phase
## System Information
<env>
Working directory: {agent_dir_path}
Current User: {user_identifier}
Current Time: {datetime}
Trace Id: {trace_id}
</env>

View File

@ -26,12 +26,12 @@ dependencies = [
"chardet>=5.0.0",
"psutil (>=7.1.3,<8.0.0)",
"uvloop (>=0.22.1,<0.23.0)",
"deepagents (>=0.2.8,<0.4.0)",
"deepagents (>=0.4.3,<0.5.0)",
"langchain-mcp-adapters (>=0.2.1,<0.3.0)",
"langchain-openai (>=1.1.1,<2.0.0)",
"cachetools (>=6.2.4,<7.0.0)",
"langgraph-checkpoint-postgres (>=2.0.0,<3.0.0)",
"deepagents-cli (>=0.0.11,<0.0.12)",
"langgraph-checkpoint-postgres (>=3.0.0,<4.0.0)",
"deepagents-cli (>=0.0.25,<0.0.26)",
"mem0ai (>=0.1.50,<0.3.0)",
"psycopg2-binary (>=2.9.11,<3.0.0)",
"json-repair (>=0.29.0,<0.30.0)",

View File

@ -3,8 +3,9 @@ aiohappyeyeballs==2.6.1 ; python_version >= "3.12" and python_version < "4.0"
aiohttp-retry==2.9.1 ; python_version >= "3.12" and python_version < "4.0"
aiohttp==3.13.1 ; python_version >= "3.12" and python_version < "4.0"
aiosignal==1.4.0 ; python_version >= "3.12" and python_version < "4.0"
aiosqlite==0.22.1 ; python_version >= "3.12" and python_version < "4.0"
annotated-types==0.7.0 ; python_version >= "3.12" and python_version < "4.0"
anthropic==0.75.0 ; python_version >= "3.12" and python_version < "4.0"
anthropic==0.84.0 ; python_version >= "3.12" and python_version < "4.0"
anyio==4.11.0 ; python_version >= "3.12" and python_version < "4.0"
attrs==25.4.0 ; python_version >= "3.12" and python_version < "4.0"
backoff==2.2.1 ; python_version >= "3.12" and python_version < "4.0"
@ -13,17 +14,19 @@ bracex==2.6 ; python_version >= "3.12" and python_version < "4.0"
cachetools==6.2.4 ; python_version >= "3.12" and python_version < "4.0"
cbor2==5.7.1 ; python_version >= "3.12" and python_version < "4.0"
certifi==2025.10.5 ; python_version >= "3.12" and python_version < "4.0"
cffi==2.0.0 ; python_version >= "3.12" and python_version < "4.0" and platform_python_implementation != "PyPy"
chardet==5.2.0 ; python_version >= "3.12" and python_version < "4.0"
charset-normalizer==3.4.4 ; python_version >= "3.12" and python_version < "4.0"
click==8.3.0 ; python_version >= "3.12" and python_version < "4.0"
colorama==0.4.6 ; python_version >= "3.12" and python_version < "4.0" and platform_system == "Windows"
cryptography==46.0.5 ; python_version >= "3.12" and python_version < "4.0"
daytona-api-client-async==0.127.0 ; python_version >= "3.12" and python_version < "4.0"
daytona-api-client==0.127.0 ; python_version >= "3.12" and python_version < "4.0"
daytona-toolbox-api-client-async==0.127.0 ; python_version >= "3.12" and python_version < "4.0"
daytona-toolbox-api-client==0.127.0 ; python_version >= "3.12" and python_version < "4.0"
daytona==0.127.0 ; python_version >= "3.12" and python_version < "4.0"
deepagents-cli==0.0.11 ; python_version >= "3.12" and python_version < "4.0"
deepagents==0.2.8 ; python_version >= "3.12" and python_version < "4.0"
deepagents-cli==0.0.25 ; python_version >= "3.12" and python_version < "4.0"
deepagents==0.4.3 ; python_version >= "3.12" and python_version < "4.0"
deprecated==1.3.1 ; python_version >= "3.12" and python_version < "4.0"
distro==1.9.0 ; python_version >= "3.12" and python_version < "4.0"
docstring-parser==0.17.0 ; python_version >= "3.12" and python_version < "4.0"
@ -31,8 +34,11 @@ environs==14.5.0 ; python_version >= "3.12" and python_version < "4.0"
et-xmlfile==2.0.0 ; python_version >= "3.12" and python_version < "4.0"
fastapi==0.116.1 ; python_version >= "3.12" and python_version < "4.0"
filelock==3.20.0 ; python_version >= "3.12" and python_version < "4.0"
filetype==1.2.0 ; python_version >= "3.12" and python_version < "4.0"
frozenlist==1.8.0 ; python_version >= "3.12" and python_version < "4.0"
fsspec==2025.9.0 ; python_version >= "3.12" and python_version < "4.0"
google-auth==2.48.0 ; python_version >= "3.12" and python_version < "4.0"
google-genai==1.65.0 ; python_version >= "3.12" and python_version < "4.0"
greenlet==3.3.0 ; python_version >= "3.12" and python_version < "4.0" and (platform_machine == "aarch64" or platform_machine == "ppc64le" or platform_machine == "x86_64" or platform_machine == "amd64" or platform_machine == "AMD64" or platform_machine == "win32" or platform_machine == "WIN32")
grpcio-tools==1.71.2 ; python_version >= "3.13" and python_version < "4.0"
grpcio==1.76.0 ; python_version >= "3.12" and python_version < "4.0"
@ -56,22 +62,26 @@ jsonpatch==1.33 ; python_version >= "3.12" and python_version < "4.0"
jsonpointer==3.0.0 ; python_version >= "3.12" and python_version < "4.0"
jsonschema-specifications==2025.9.1 ; python_version >= "3.12" and python_version < "4.0"
jsonschema==4.25.1 ; python_version >= "3.12" and python_version < "4.0"
langchain-anthropic==1.2.0 ; python_version >= "3.12" and python_version < "4.0"
langchain-core==1.1.3 ; python_version >= "3.12" and python_version < "4.0"
langchain-anthropic==1.3.4 ; python_version >= "3.12" and python_version < "4.0"
langchain-core==1.2.16 ; python_version >= "3.12" and python_version < "4.0"
langchain-google-genai==4.2.1 ; python_version >= "3.12" and python_version < "4.0"
langchain-mcp-adapters==0.2.1 ; python_version >= "3.12" and python_version < "4.0"
langchain-openai==1.1.1 ; python_version >= "3.12" and python_version < "4.0"
langchain==1.1.3 ; python_version >= "3.12" and python_version < "4.0"
langgraph-checkpoint-postgres==2.0.25 ; python_version >= "3.12" and python_version < "4.0"
langgraph-checkpoint==2.1.2 ; python_version >= "3.12" and python_version < "4.0"
langgraph-prebuilt==1.0.5 ; python_version >= "3.12" and python_version < "4.0"
langchain-openai==1.1.9 ; python_version >= "3.12" and python_version < "4.0"
langchain==1.2.10 ; python_version >= "3.12" and python_version < "4.0"
langgraph-checkpoint-postgres==3.0.4 ; python_version >= "3.12" and python_version < "4.0"
langgraph-checkpoint-sqlite==3.0.3 ; python_version >= "3.12" and python_version < "4.0"
langgraph-checkpoint==4.0.1 ; python_version >= "3.12" and python_version < "4.0"
langgraph-prebuilt==1.0.8 ; python_version >= "3.12" and python_version < "4.0"
langgraph-sdk==0.3.3 ; python_version >= "3.12" and python_version < "4.0"
langgraph==1.0.6 ; python_version >= "3.12" and python_version < "4.0"
langsmith==0.4.59 ; python_version >= "3.12" and python_version < "4.0"
langgraph==1.0.10 ; python_version >= "3.12" and python_version < "4.0"
langsmith==0.7.9 ; python_version >= "3.12" and python_version < "4.0"
linkify-it-py==2.1.0 ; python_version >= "3.12" and python_version < "4.0"
markdown-it-py==4.0.0 ; python_version >= "3.12" and python_version < "4.0"
markdownify==1.2.2 ; python_version >= "3.12" and python_version < "4.0"
markupsafe==3.0.3 ; python_version >= "3.12" and python_version < "4.0"
marshmallow==4.1.1 ; python_version >= "3.12" and python_version < "4.0"
mcp==1.12.4 ; python_version >= "3.12" and python_version < "4.0"
mdit-py-plugins==0.5.0 ; python_version >= "3.12" and python_version < "4.0"
mdurl==0.1.2 ; python_version >= "3.12" and python_version < "4.0"
mem0ai==0.1.116 ; python_version >= "3.12" and python_version < "4.0"
modal==1.2.1 ; python_version >= "3.12" and python_version < "4.0"
@ -100,6 +110,7 @@ ormsgpack==1.12.0 ; python_version >= "3.12" and python_version < "4.0"
packaging==25.0 ; python_version >= "3.12" and python_version < "4.0"
pandas==2.3.3 ; python_version >= "3.12" and python_version < "4.0"
pillow==12.0.0 ; python_version >= "3.12" and python_version < "4.0"
platformdirs==4.9.2 ; python_version >= "3.12" and python_version < "4.0"
portalocker==2.10.1 ; python_version >= "3.13" and python_version < "4.0"
portalocker==3.2.0 ; python_version == "3.12"
posthog==7.6.0 ; python_version >= "3.12" and python_version < "4.0"
@ -110,10 +121,14 @@ psutil==7.1.3 ; python_version >= "3.12" and python_version < "4.0"
psycopg-pool==3.3.0 ; python_version >= "3.12" and python_version < "4.0"
psycopg2-binary==2.9.11 ; python_version >= "3.12" and python_version < "4.0"
psycopg==3.3.2 ; python_version >= "3.12" and python_version < "4.0"
pyasn1-modules==0.4.2 ; python_version >= "3.12" and python_version < "4.0"
pyasn1==0.6.2 ; python_version >= "3.12" and python_version < "4.0"
pycparser==3.0 ; python_version >= "3.12" and python_version < "4.0" and platform_python_implementation != "PyPy" and implementation_name != "PyPy"
pydantic-core==2.27.2 ; python_version >= "3.12" and python_version < "4.0"
pydantic-settings==2.11.0 ; python_version >= "3.12" and python_version < "4.0"
pydantic==2.10.5 ; python_version >= "3.12" and python_version < "4.0"
pygments==2.19.2 ; python_version >= "3.12" and python_version < "4.0"
pyperclip==1.11.0 ; python_version >= "3.12" and python_version < "4.0"
python-dateutil==2.8.2 ; python_version >= "3.12" and python_version < "4.0"
python-dotenv==1.1.1 ; python_version >= "3.12" and python_version < "4.0"
python-multipart==0.0.20 ; python_version >= "3.12" and python_version < "4.0"
@ -128,6 +143,7 @@ requests-toolbelt==1.0.0 ; python_version >= "3.12" and python_version < "4.0"
requests==2.32.5 ; python_version >= "3.12" and python_version < "4.0"
rich==14.2.0 ; python_version >= "3.12" and python_version < "4.0"
rpds-py==0.27.1 ; python_version >= "3.12" and python_version < "4.0"
rsa==4.9.1 ; python_version >= "3.12" and python_version < "4.0"
runloop-api-client==1.2.0 ; python_version >= "3.12" and python_version < "4.0"
safetensors==0.6.2 ; python_version >= "3.12" and python_version < "4.0"
scikit-learn==1.7.2 ; python_version >= "3.12" and python_version < "4.0"
@ -139,16 +155,20 @@ six==1.17.0 ; python_version >= "3.12" and python_version < "4.0"
sniffio==1.3.1 ; python_version >= "3.12" and python_version < "4.0"
soupsieve==2.8.1 ; python_version >= "3.12" and python_version < "4.0"
sqlalchemy==2.0.45 ; python_version >= "3.12" and python_version < "4.0"
sqlite-vec==0.1.6 ; python_version >= "3.12" and python_version < "4.0"
sse-starlette==3.0.2 ; python_version >= "3.12" and python_version < "4.0"
starlette==0.47.3 ; python_version >= "3.12" and python_version < "4.0"
sympy==1.14.0 ; python_version >= "3.12" and python_version < "4.0"
synchronicity==0.10.5 ; python_version >= "3.12" and python_version < "4.0"
tavily-python==0.7.17 ; python_version >= "3.12" and python_version < "4.0"
tavily-python==0.7.22 ; python_version >= "3.12" and python_version < "4.0"
tenacity==9.1.2 ; python_version >= "3.12" and python_version < "4.0"
textual-autocomplete==4.0.6 ; python_version >= "3.12" and python_version < "4.0"
textual==8.0.0 ; python_version >= "3.12" and python_version < "4.0"
threadpoolctl==3.6.0 ; python_version >= "3.12" and python_version < "4.0"
tiktoken==0.12.0 ; python_version >= "3.12" and python_version < "4.0"
tokenizers==0.22.1 ; python_version >= "3.12" and python_version < "4.0"
toml==0.10.2 ; python_version >= "3.12" and python_version < "4.0"
tomli-w==1.2.0 ; python_version >= "3.12" and python_version < "4.0"
torch==2.2.0 ; python_version >= "3.12" and python_version < "4.0"
tqdm==4.67.1 ; python_version >= "3.12" and python_version < "4.0"
transformers==4.57.1 ; python_version >= "3.12" and python_version < "4.0"
@ -159,6 +179,7 @@ types-toml==0.10.8.20240310 ; python_version >= "3.12" and python_version < "4.0
typing-extensions==4.15.0 ; python_version >= "3.12" and python_version < "4.0"
typing-inspection==0.4.2 ; python_version >= "3.12" and python_version < "4.0"
tzdata==2025.2 ; python_version >= "3.12" and python_version < "4.0"
uc-micro-py==2.0.0 ; python_version >= "3.12" and python_version < "4.0"
urllib3==2.5.0 ; python_version >= "3.12" and python_version < "4.0"
uuid-utils==0.12.0 ; python_version >= "3.12" and python_version < "4.0"
uvicorn==0.35.0 ; python_version >= "3.12" and python_version < "4.0"

View File

@ -1,6 +1,8 @@
import json
import os
import asyncio
import shutil
import time
from typing import Union, Optional, Any, List, Dict
from fastapi import APIRouter, HTTPException, Header
from fastapi.responses import StreamingResponse
@ -393,6 +395,41 @@ async def _execute_post_agent_hooks(config: AgentConfig, response: str) -> None:
# hook执行失败不影响主流程
logger.error(f"Failed to execute PostAgent hooks: {e}")
# 清理 executable_code/tmp 文件夹
await _cleanup_tmp_folder(config)
async def _cleanup_tmp_folder(config: AgentConfig) -> None:
"""
清理 executable_code/tmp 文件夹中 3 天前的文件
Args:
config: AgentConfig 对象
"""
try:
if config.project_dir and config.bot_id:
tmp_dir = os.path.join(config.project_dir, "executable_code", "tmp")
if os.path.exists(tmp_dir):
# 3 天前的秒数3 * 24 * 60 * 60 = 259200
three_days_ago = time.time() - (3 * 24 * 60 * 60)
deleted_count = 0
for item in os.listdir(tmp_dir):
item_path = os.path.join(tmp_dir, item)
# 检查修改时间
if os.path.getmtime(item_path) < three_days_ago:
if os.path.isfile(item_path) or os.path.islink(item_path):
os.remove(item_path)
else:
shutil.rmtree(item_path)
deleted_count += 1
logger.debug(f"Deleted old item: {item_path}")
logger.info(f"Cleaned up {deleted_count} old item(s) from tmp folder: {tmp_dir}")
except Exception as e:
# 清理失败不影响主流程
logger.error(f"Failed to cleanup tmp folder: {e}")
@router.post("/api/v1/chat/completions")
async def chat_completions(request: ChatRequest, authorization: Optional[str] = Header(None)):