agentpool 2.1.9__py3-none-any.whl → 2.5.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- acp/__init__.py +13 -4
- acp/acp_requests.py +20 -77
- acp/agent/connection.py +8 -0
- acp/agent/implementations/debug_server/debug_server.py +6 -2
- acp/agent/protocol.py +6 -0
- acp/bridge/README.md +15 -2
- acp/bridge/__init__.py +3 -2
- acp/bridge/__main__.py +60 -19
- acp/bridge/ws_server.py +173 -0
- acp/bridge/ws_server_cli.py +89 -0
- acp/client/connection.py +38 -29
- acp/client/implementations/default_client.py +3 -2
- acp/client/implementations/headless_client.py +2 -2
- acp/connection.py +2 -2
- acp/notifications.py +20 -50
- acp/schema/__init__.py +2 -0
- acp/schema/agent_responses.py +21 -0
- acp/schema/client_requests.py +3 -3
- acp/schema/session_state.py +63 -29
- acp/stdio.py +39 -9
- acp/task/supervisor.py +2 -2
- acp/transports.py +362 -2
- acp/utils.py +17 -4
- agentpool/__init__.py +6 -1
- agentpool/agents/__init__.py +2 -0
- agentpool/agents/acp_agent/acp_agent.py +407 -277
- agentpool/agents/acp_agent/acp_converters.py +196 -38
- agentpool/agents/acp_agent/client_handler.py +191 -26
- agentpool/agents/acp_agent/session_state.py +17 -6
- agentpool/agents/agent.py +607 -572
- agentpool/agents/agui_agent/__init__.py +0 -2
- agentpool/agents/agui_agent/agui_agent.py +176 -110
- agentpool/agents/agui_agent/agui_converters.py +0 -131
- agentpool/agents/agui_agent/helpers.py +3 -4
- agentpool/agents/base_agent.py +632 -17
- agentpool/agents/claude_code_agent/FORKING.md +191 -0
- agentpool/agents/claude_code_agent/__init__.py +13 -1
- agentpool/agents/claude_code_agent/claude_code_agent.py +1058 -291
- agentpool/agents/claude_code_agent/converters.py +74 -143
- agentpool/agents/claude_code_agent/history.py +474 -0
- agentpool/agents/claude_code_agent/models.py +77 -0
- agentpool/agents/claude_code_agent/static_info.py +100 -0
- agentpool/agents/claude_code_agent/usage.py +242 -0
- agentpool/agents/context.py +40 -0
- agentpool/agents/events/__init__.py +24 -0
- agentpool/agents/events/builtin_handlers.py +67 -1
- agentpool/agents/events/event_emitter.py +32 -2
- agentpool/agents/events/events.py +104 -3
- agentpool/agents/events/infer_info.py +145 -0
- agentpool/agents/events/processors.py +254 -0
- agentpool/agents/interactions.py +41 -6
- agentpool/agents/modes.py +67 -0
- agentpool/agents/slashed_agent.py +5 -4
- agentpool/agents/tool_call_accumulator.py +213 -0
- agentpool/agents/tool_wrapping.py +18 -6
- agentpool/common_types.py +56 -21
- agentpool/config_resources/__init__.py +38 -1
- agentpool/config_resources/acp_assistant.yml +2 -2
- agentpool/config_resources/agents.yml +3 -0
- agentpool/config_resources/agents_template.yml +1 -0
- agentpool/config_resources/claude_code_agent.yml +10 -6
- agentpool/config_resources/external_acp_agents.yml +2 -1
- agentpool/delegation/base_team.py +4 -30
- agentpool/delegation/pool.py +136 -289
- agentpool/delegation/team.py +58 -57
- agentpool/delegation/teamrun.py +51 -55
- agentpool/diagnostics/__init__.py +53 -0
- agentpool/diagnostics/lsp_manager.py +1593 -0
- agentpool/diagnostics/lsp_proxy.py +41 -0
- agentpool/diagnostics/lsp_proxy_script.py +229 -0
- agentpool/diagnostics/models.py +398 -0
- agentpool/functional/run.py +10 -4
- agentpool/mcp_server/__init__.py +0 -2
- agentpool/mcp_server/client.py +76 -32
- agentpool/mcp_server/conversions.py +54 -13
- agentpool/mcp_server/manager.py +34 -54
- agentpool/mcp_server/registries/official_registry_client.py +35 -1
- agentpool/mcp_server/tool_bridge.py +186 -139
- agentpool/messaging/__init__.py +0 -2
- agentpool/messaging/compaction.py +72 -197
- agentpool/messaging/connection_manager.py +11 -10
- agentpool/messaging/event_manager.py +5 -5
- agentpool/messaging/message_container.py +6 -30
- agentpool/messaging/message_history.py +99 -8
- agentpool/messaging/messagenode.py +52 -14
- agentpool/messaging/messages.py +54 -35
- agentpool/messaging/processing.py +12 -22
- agentpool/models/__init__.py +1 -1
- agentpool/models/acp_agents/base.py +6 -24
- agentpool/models/acp_agents/mcp_capable.py +126 -157
- agentpool/models/acp_agents/non_mcp.py +129 -95
- agentpool/models/agents.py +98 -76
- agentpool/models/agui_agents.py +1 -1
- agentpool/models/claude_code_agents.py +144 -19
- agentpool/models/file_parsing.py +0 -1
- agentpool/models/manifest.py +113 -50
- agentpool/prompts/conversion_manager.py +1 -1
- agentpool/prompts/prompts.py +5 -2
- agentpool/repomap.py +1 -1
- agentpool/resource_providers/__init__.py +11 -1
- agentpool/resource_providers/aggregating.py +56 -5
- agentpool/resource_providers/base.py +70 -4
- agentpool/resource_providers/codemode/code_executor.py +72 -5
- agentpool/resource_providers/codemode/helpers.py +2 -2
- agentpool/resource_providers/codemode/provider.py +64 -12
- agentpool/resource_providers/codemode/remote_mcp_execution.py +2 -2
- agentpool/resource_providers/codemode/remote_provider.py +9 -12
- agentpool/resource_providers/filtering.py +3 -1
- agentpool/resource_providers/mcp_provider.py +89 -12
- agentpool/resource_providers/plan_provider.py +228 -46
- agentpool/resource_providers/pool.py +7 -3
- agentpool/resource_providers/resource_info.py +111 -0
- agentpool/resource_providers/static.py +4 -2
- agentpool/sessions/__init__.py +4 -1
- agentpool/sessions/manager.py +33 -5
- agentpool/sessions/models.py +59 -6
- agentpool/sessions/protocol.py +28 -0
- agentpool/sessions/session.py +11 -55
- agentpool/skills/registry.py +13 -8
- agentpool/storage/manager.py +572 -49
- agentpool/talk/registry.py +4 -4
- agentpool/talk/talk.py +9 -10
- agentpool/testing.py +538 -20
- agentpool/tool_impls/__init__.py +6 -0
- agentpool/tool_impls/agent_cli/__init__.py +42 -0
- agentpool/tool_impls/agent_cli/tool.py +95 -0
- agentpool/tool_impls/bash/__init__.py +64 -0
- agentpool/tool_impls/bash/helpers.py +35 -0
- agentpool/tool_impls/bash/tool.py +171 -0
- agentpool/tool_impls/delete_path/__init__.py +70 -0
- agentpool/tool_impls/delete_path/tool.py +142 -0
- agentpool/tool_impls/download_file/__init__.py +80 -0
- agentpool/tool_impls/download_file/tool.py +183 -0
- agentpool/tool_impls/execute_code/__init__.py +55 -0
- agentpool/tool_impls/execute_code/tool.py +163 -0
- agentpool/tool_impls/grep/__init__.py +80 -0
- agentpool/tool_impls/grep/tool.py +200 -0
- agentpool/tool_impls/list_directory/__init__.py +73 -0
- agentpool/tool_impls/list_directory/tool.py +197 -0
- agentpool/tool_impls/question/__init__.py +42 -0
- agentpool/tool_impls/question/tool.py +127 -0
- agentpool/tool_impls/read/__init__.py +104 -0
- agentpool/tool_impls/read/tool.py +305 -0
- agentpool/tools/__init__.py +2 -1
- agentpool/tools/base.py +114 -34
- agentpool/tools/manager.py +57 -1
- agentpool/ui/base.py +2 -2
- agentpool/ui/mock_provider.py +2 -2
- agentpool/ui/stdlib_provider.py +2 -2
- agentpool/utils/file_watcher.py +269 -0
- agentpool/utils/identifiers.py +121 -0
- agentpool/utils/pydantic_ai_helpers.py +46 -0
- agentpool/utils/streams.py +616 -2
- agentpool/utils/subprocess_utils.py +155 -0
- agentpool/utils/token_breakdown.py +461 -0
- agentpool/vfs_registry.py +7 -2
- {agentpool-2.1.9.dist-info → agentpool-2.5.0.dist-info}/METADATA +41 -27
- agentpool-2.5.0.dist-info/RECORD +579 -0
- {agentpool-2.1.9.dist-info → agentpool-2.5.0.dist-info}/WHEEL +1 -1
- agentpool_cli/__main__.py +24 -0
- agentpool_cli/create.py +1 -1
- agentpool_cli/serve_acp.py +100 -21
- agentpool_cli/serve_agui.py +87 -0
- agentpool_cli/serve_opencode.py +119 -0
- agentpool_cli/ui.py +557 -0
- agentpool_commands/__init__.py +42 -5
- agentpool_commands/agents.py +75 -2
- agentpool_commands/history.py +62 -0
- agentpool_commands/mcp.py +176 -0
- agentpool_commands/models.py +56 -3
- agentpool_commands/pool.py +260 -0
- agentpool_commands/session.py +1 -1
- agentpool_commands/text_sharing/__init__.py +119 -0
- agentpool_commands/text_sharing/base.py +123 -0
- agentpool_commands/text_sharing/github_gist.py +80 -0
- agentpool_commands/text_sharing/opencode.py +462 -0
- agentpool_commands/text_sharing/paste_rs.py +59 -0
- agentpool_commands/text_sharing/pastebin.py +116 -0
- agentpool_commands/text_sharing/shittycodingagent.py +112 -0
- agentpool_commands/tools.py +57 -0
- agentpool_commands/utils.py +80 -30
- agentpool_config/__init__.py +30 -2
- agentpool_config/agentpool_tools.py +498 -0
- agentpool_config/builtin_tools.py +77 -22
- agentpool_config/commands.py +24 -1
- agentpool_config/compaction.py +258 -0
- agentpool_config/converters.py +1 -1
- agentpool_config/event_handlers.py +42 -0
- agentpool_config/events.py +1 -1
- agentpool_config/forward_targets.py +1 -4
- agentpool_config/jinja.py +3 -3
- agentpool_config/mcp_server.py +132 -6
- agentpool_config/nodes.py +1 -1
- agentpool_config/observability.py +44 -0
- agentpool_config/session.py +0 -3
- agentpool_config/storage.py +82 -38
- agentpool_config/task.py +3 -3
- agentpool_config/tools.py +11 -22
- agentpool_config/toolsets.py +109 -233
- agentpool_server/a2a_server/agent_worker.py +307 -0
- agentpool_server/a2a_server/server.py +23 -18
- agentpool_server/acp_server/acp_agent.py +234 -181
- agentpool_server/acp_server/commands/acp_commands.py +151 -156
- agentpool_server/acp_server/commands/docs_commands/fetch_repo.py +18 -17
- agentpool_server/acp_server/event_converter.py +651 -0
- agentpool_server/acp_server/input_provider.py +53 -10
- agentpool_server/acp_server/server.py +24 -90
- agentpool_server/acp_server/session.py +173 -331
- agentpool_server/acp_server/session_manager.py +8 -34
- agentpool_server/agui_server/server.py +3 -1
- agentpool_server/mcp_server/server.py +5 -2
- agentpool_server/opencode_server/.rules +95 -0
- agentpool_server/opencode_server/ENDPOINTS.md +401 -0
- agentpool_server/opencode_server/OPENCODE_UI_TOOLS_COMPLETE.md +202 -0
- agentpool_server/opencode_server/__init__.py +19 -0
- agentpool_server/opencode_server/command_validation.py +172 -0
- agentpool_server/opencode_server/converters.py +975 -0
- agentpool_server/opencode_server/dependencies.py +24 -0
- agentpool_server/opencode_server/input_provider.py +421 -0
- agentpool_server/opencode_server/models/__init__.py +250 -0
- agentpool_server/opencode_server/models/agent.py +53 -0
- agentpool_server/opencode_server/models/app.py +72 -0
- agentpool_server/opencode_server/models/base.py +26 -0
- agentpool_server/opencode_server/models/common.py +23 -0
- agentpool_server/opencode_server/models/config.py +37 -0
- agentpool_server/opencode_server/models/events.py +821 -0
- agentpool_server/opencode_server/models/file.py +88 -0
- agentpool_server/opencode_server/models/mcp.py +44 -0
- agentpool_server/opencode_server/models/message.py +179 -0
- agentpool_server/opencode_server/models/parts.py +323 -0
- agentpool_server/opencode_server/models/provider.py +81 -0
- agentpool_server/opencode_server/models/pty.py +43 -0
- agentpool_server/opencode_server/models/question.py +56 -0
- agentpool_server/opencode_server/models/session.py +111 -0
- agentpool_server/opencode_server/routes/__init__.py +29 -0
- agentpool_server/opencode_server/routes/agent_routes.py +473 -0
- agentpool_server/opencode_server/routes/app_routes.py +202 -0
- agentpool_server/opencode_server/routes/config_routes.py +302 -0
- agentpool_server/opencode_server/routes/file_routes.py +571 -0
- agentpool_server/opencode_server/routes/global_routes.py +94 -0
- agentpool_server/opencode_server/routes/lsp_routes.py +319 -0
- agentpool_server/opencode_server/routes/message_routes.py +761 -0
- agentpool_server/opencode_server/routes/permission_routes.py +63 -0
- agentpool_server/opencode_server/routes/pty_routes.py +300 -0
- agentpool_server/opencode_server/routes/question_routes.py +128 -0
- agentpool_server/opencode_server/routes/session_routes.py +1276 -0
- agentpool_server/opencode_server/routes/tui_routes.py +139 -0
- agentpool_server/opencode_server/server.py +475 -0
- agentpool_server/opencode_server/state.py +151 -0
- agentpool_server/opencode_server/time_utils.py +8 -0
- agentpool_storage/__init__.py +12 -0
- agentpool_storage/base.py +184 -2
- agentpool_storage/claude_provider/ARCHITECTURE.md +433 -0
- agentpool_storage/claude_provider/__init__.py +42 -0
- agentpool_storage/claude_provider/provider.py +1089 -0
- agentpool_storage/file_provider.py +278 -15
- agentpool_storage/memory_provider.py +193 -12
- agentpool_storage/models.py +3 -0
- agentpool_storage/opencode_provider/ARCHITECTURE.md +386 -0
- agentpool_storage/opencode_provider/__init__.py +16 -0
- agentpool_storage/opencode_provider/helpers.py +414 -0
- agentpool_storage/opencode_provider/provider.py +895 -0
- agentpool_storage/project_store.py +325 -0
- agentpool_storage/session_store.py +26 -6
- agentpool_storage/sql_provider/__init__.py +4 -2
- agentpool_storage/sql_provider/models.py +48 -0
- agentpool_storage/sql_provider/sql_provider.py +269 -3
- agentpool_storage/sql_provider/utils.py +12 -13
- agentpool_storage/zed_provider/__init__.py +16 -0
- agentpool_storage/zed_provider/helpers.py +281 -0
- agentpool_storage/zed_provider/models.py +130 -0
- agentpool_storage/zed_provider/provider.py +442 -0
- agentpool_storage/zed_provider.py +803 -0
- agentpool_toolsets/__init__.py +0 -2
- agentpool_toolsets/builtin/__init__.py +2 -12
- agentpool_toolsets/builtin/code.py +96 -57
- agentpool_toolsets/builtin/debug.py +118 -48
- agentpool_toolsets/builtin/execution_environment.py +115 -230
- agentpool_toolsets/builtin/file_edit/file_edit.py +115 -7
- agentpool_toolsets/builtin/skills.py +9 -4
- agentpool_toolsets/builtin/subagent_tools.py +64 -51
- agentpool_toolsets/builtin/workers.py +4 -2
- agentpool_toolsets/composio_toolset.py +2 -2
- agentpool_toolsets/entry_points.py +3 -1
- agentpool_toolsets/fsspec_toolset/__init__.py +13 -1
- agentpool_toolsets/fsspec_toolset/diagnostics.py +860 -73
- agentpool_toolsets/fsspec_toolset/grep.py +99 -7
- agentpool_toolsets/fsspec_toolset/helpers.py +3 -2
- agentpool_toolsets/fsspec_toolset/image_utils.py +161 -0
- agentpool_toolsets/fsspec_toolset/toolset.py +500 -95
- agentpool_toolsets/mcp_discovery/__init__.py +5 -0
- agentpool_toolsets/mcp_discovery/data/mcp_servers.parquet +0 -0
- agentpool_toolsets/mcp_discovery/toolset.py +511 -0
- agentpool_toolsets/mcp_run_toolset.py +87 -12
- agentpool_toolsets/notifications.py +33 -33
- agentpool_toolsets/openapi.py +3 -1
- agentpool_toolsets/search_toolset.py +3 -1
- agentpool-2.1.9.dist-info/RECORD +0 -474
- agentpool_config/resources.py +0 -33
- agentpool_server/acp_server/acp_tools.py +0 -43
- agentpool_server/acp_server/commands/spawn.py +0 -210
- agentpool_storage/text_log_provider.py +0 -275
- agentpool_toolsets/builtin/agent_management.py +0 -239
- agentpool_toolsets/builtin/chain.py +0 -288
- agentpool_toolsets/builtin/history.py +0 -36
- agentpool_toolsets/builtin/integration.py +0 -85
- agentpool_toolsets/builtin/tool_management.py +0 -90
- agentpool_toolsets/builtin/user_interaction.py +0 -52
- agentpool_toolsets/semantic_memory_toolset.py +0 -536
- {agentpool-2.1.9.dist-info → agentpool-2.5.0.dist-info}/entry_points.txt +0 -0
- {agentpool-2.1.9.dist-info → agentpool-2.5.0.dist-info}/licenses/LICENSE +0 -0
agentpool_toolsets/__init__.py
CHANGED
|
@@ -3,13 +3,11 @@
|
|
|
3
3
|
from agentpool_toolsets.config_creation import ConfigCreationTools
|
|
4
4
|
from agentpool_toolsets.fsspec_toolset import FSSpecTools
|
|
5
5
|
from agentpool_toolsets.notifications import NotificationsTools
|
|
6
|
-
from agentpool_toolsets.semantic_memory_toolset import SemanticMemoryTools
|
|
7
6
|
from agentpool_toolsets.vfs_toolset import VFSTools
|
|
8
7
|
|
|
9
8
|
__all__ = [
|
|
10
9
|
"ConfigCreationTools",
|
|
11
10
|
"FSSpecTools",
|
|
12
11
|
"NotificationsTools",
|
|
13
|
-
"SemanticMemoryTools",
|
|
14
12
|
"VFSTools",
|
|
15
13
|
]
|
|
@@ -4,30 +4,20 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
# Import provider classes
|
|
7
|
-
from agentpool_toolsets.builtin.agent_management import AgentManagementTools
|
|
8
7
|
from agentpool_toolsets.builtin.code import CodeTools
|
|
9
8
|
from agentpool_toolsets.builtin.debug import DebugTools
|
|
10
|
-
from agentpool_toolsets.builtin.execution_environment import
|
|
11
|
-
from agentpool_toolsets.builtin.history import HistoryTools
|
|
12
|
-
from agentpool_toolsets.builtin.integration import IntegrationTools
|
|
9
|
+
from agentpool_toolsets.builtin.execution_environment import ProcessManagementTools
|
|
13
10
|
from agentpool_toolsets.builtin.skills import SkillsTools
|
|
14
11
|
from agentpool_toolsets.builtin.subagent_tools import SubagentTools
|
|
15
|
-
from agentpool_toolsets.builtin.tool_management import ToolManagementTools
|
|
16
|
-
from agentpool_toolsets.builtin.user_interaction import UserInteractionTools
|
|
17
12
|
from agentpool_toolsets.builtin.workers import WorkersTools
|
|
18
13
|
|
|
19
14
|
|
|
20
15
|
__all__ = [
|
|
21
16
|
# Provider classes
|
|
22
|
-
"AgentManagementTools",
|
|
23
17
|
"CodeTools",
|
|
24
18
|
"DebugTools",
|
|
25
|
-
"
|
|
26
|
-
"HistoryTools",
|
|
27
|
-
"IntegrationTools",
|
|
19
|
+
"ProcessManagementTools",
|
|
28
20
|
"SkillsTools",
|
|
29
21
|
"SubagentTools",
|
|
30
|
-
"ToolManagementTools",
|
|
31
|
-
"UserInteractionTools",
|
|
32
22
|
"WorkersTools",
|
|
33
23
|
]
|
|
@@ -13,15 +13,21 @@ from upathtools import is_directory
|
|
|
13
13
|
from agentpool.agents.context import AgentContext # noqa: TC001
|
|
14
14
|
from agentpool.log import get_logger
|
|
15
15
|
from agentpool.resource_providers import ResourceProvider
|
|
16
|
-
from agentpool_toolsets.fsspec_toolset.diagnostics import
|
|
16
|
+
from agentpool_toolsets.fsspec_toolset.diagnostics import (
|
|
17
|
+
DiagnosticsManager,
|
|
18
|
+
format_diagnostics_table,
|
|
19
|
+
format_run_summary,
|
|
20
|
+
)
|
|
17
21
|
|
|
18
22
|
|
|
19
23
|
if TYPE_CHECKING:
|
|
20
|
-
from
|
|
24
|
+
from collections.abc import Sequence
|
|
25
|
+
|
|
21
26
|
from exxec.base import ExecutionEnvironment
|
|
27
|
+
from fsspec.asyn import AsyncFileSystem
|
|
22
28
|
|
|
23
29
|
from agentpool.tools.base import Tool
|
|
24
|
-
|
|
30
|
+
from agentpool_toolsets.fsspec_toolset.diagnostics import DiagnosticsConfig
|
|
25
31
|
|
|
26
32
|
logger = get_logger(__name__)
|
|
27
33
|
|
|
@@ -87,51 +93,63 @@ class CodeTools(ResourceProvider):
|
|
|
87
93
|
env: ExecutionEnvironment | None = None,
|
|
88
94
|
name: str = "code",
|
|
89
95
|
cwd: str | None = None,
|
|
96
|
+
diagnostics_config: DiagnosticsConfig | None = None,
|
|
90
97
|
) -> None:
|
|
91
98
|
"""Initialize with an optional execution environment.
|
|
92
99
|
|
|
93
100
|
Args:
|
|
94
101
|
env: Execution environment to operate on. If None, falls back to agent.env
|
|
95
102
|
name: Name for this toolset provider
|
|
96
|
-
cwd: Optional cwd to resolve relative paths against
|
|
103
|
+
cwd: Optional cwd to resolve relative paths against (falls back to env.cwd)
|
|
104
|
+
diagnostics_config: Configuration for diagnostic tools (server selection, etc.)
|
|
97
105
|
"""
|
|
106
|
+
super().__init__(name=name)
|
|
107
|
+
|
|
108
|
+
self._explicit_env = env
|
|
109
|
+
self._explicit_cwd = cwd
|
|
110
|
+
self._diagnostics_config = diagnostics_config
|
|
111
|
+
self._tools: list[Tool] | None = None
|
|
112
|
+
|
|
113
|
+
def _get_env(self, agent_ctx: AgentContext) -> ExecutionEnvironment | None:
|
|
114
|
+
"""Get execution environment (explicit or from agent)."""
|
|
115
|
+
return self._explicit_env or agent_ctx.agent.env
|
|
116
|
+
|
|
117
|
+
def _get_cwd(self, agent_ctx: AgentContext) -> str | None:
|
|
118
|
+
"""Get working directory (explicit, from env, or from agent.env)."""
|
|
119
|
+
if self._explicit_cwd:
|
|
120
|
+
return self._explicit_cwd
|
|
121
|
+
env = self._get_env(agent_ctx)
|
|
122
|
+
return env.cwd if env else None
|
|
123
|
+
|
|
124
|
+
def _get_fs(self, agent_ctx: AgentContext) -> AsyncFileSystem:
|
|
125
|
+
"""Get filesystem (from env or fallback to local)."""
|
|
98
126
|
from fsspec.asyn import AsyncFileSystem
|
|
99
127
|
from fsspec.implementations.asyn_wrapper import AsyncFileSystemWrapper
|
|
100
128
|
from morefs.asyn_local import AsyncLocalFileSystem
|
|
101
129
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
self.execution_env = env
|
|
105
|
-
self.cwd = cwd or (env.cwd if env else None)
|
|
130
|
+
env = self._get_env(agent_ctx)
|
|
106
131
|
fs = env.get_fs() if env else None
|
|
107
132
|
match fs:
|
|
108
133
|
case AsyncFileSystem():
|
|
109
|
-
|
|
134
|
+
return fs
|
|
110
135
|
case AbstractFileSystem():
|
|
111
|
-
|
|
112
|
-
case
|
|
113
|
-
|
|
114
|
-
self._tools: list[Tool] | None = None
|
|
115
|
-
self._diagnostics: DiagnosticsManager | None = None
|
|
116
|
-
|
|
117
|
-
def _get_env(self, agent_ctx: AgentContext) -> ExecutionEnvironment | None:
|
|
118
|
-
"""Get execution environment (explicit or from agent)."""
|
|
119
|
-
return self.execution_env or agent_ctx.agent.env
|
|
136
|
+
return AsyncFileSystemWrapper(fs)
|
|
137
|
+
case _:
|
|
138
|
+
return AsyncLocalFileSystem()
|
|
120
139
|
|
|
121
140
|
def _resolve_path(self, path: str, agent_ctx: AgentContext) -> str:
|
|
122
141
|
"""Resolve a potentially relative path to an absolute path.
|
|
123
142
|
|
|
124
|
-
Gets cwd from
|
|
143
|
+
Gets cwd from explicit cwd, env.cwd, or agent.env.cwd.
|
|
125
144
|
If cwd is set and path is relative, resolves relative to cwd.
|
|
126
145
|
Otherwise returns the path as-is.
|
|
127
146
|
"""
|
|
128
|
-
|
|
129
|
-
cwd = self.cwd or (env.cwd if env else None)
|
|
147
|
+
cwd = self._get_cwd(agent_ctx)
|
|
130
148
|
if cwd and not (path.startswith("/") or (len(path) > 1 and path[1] == ":")):
|
|
131
149
|
return str(Path(cwd) / path)
|
|
132
150
|
return path
|
|
133
151
|
|
|
134
|
-
async def get_tools(self) ->
|
|
152
|
+
async def get_tools(self) -> Sequence[Tool]:
|
|
135
153
|
"""Get code analysis tools."""
|
|
136
154
|
if self._tools is not None:
|
|
137
155
|
return self._tools
|
|
@@ -160,8 +178,9 @@ class CodeTools(ResourceProvider):
|
|
|
160
178
|
from anyenv.language_formatters import FormatterRegistry
|
|
161
179
|
|
|
162
180
|
resolved = self._resolve_path(path, agent_ctx)
|
|
181
|
+
fs = self._get_fs(agent_ctx)
|
|
163
182
|
try:
|
|
164
|
-
content = await
|
|
183
|
+
content = await fs._cat_file(resolved)
|
|
165
184
|
code = content.decode("utf-8") if isinstance(content, bytes) else content
|
|
166
185
|
except FileNotFoundError:
|
|
167
186
|
return f"❌ File not found: {path}"
|
|
@@ -189,7 +208,7 @@ class CodeTools(ResourceProvider):
|
|
|
189
208
|
if result.success:
|
|
190
209
|
# Write back if formatted
|
|
191
210
|
if result.format_result.formatted and result.format_result.output:
|
|
192
|
-
await
|
|
211
|
+
await fs._pipe_file(resolved, result.format_result.output.encode("utf-8"))
|
|
193
212
|
changes = "formatted and saved"
|
|
194
213
|
else:
|
|
195
214
|
changes = "no changes needed"
|
|
@@ -271,6 +290,7 @@ class CodeTools(ResourceProvider):
|
|
|
271
290
|
from ast_grep_py import SgRoot
|
|
272
291
|
|
|
273
292
|
resolved = self._resolve_path(path, agent_ctx)
|
|
293
|
+
fs = self._get_fs(agent_ctx)
|
|
274
294
|
|
|
275
295
|
# Detect language from extension
|
|
276
296
|
language = _detect_language(path)
|
|
@@ -279,7 +299,7 @@ class CodeTools(ResourceProvider):
|
|
|
279
299
|
|
|
280
300
|
# Read file
|
|
281
301
|
try:
|
|
282
|
-
content = await
|
|
302
|
+
content = await fs._cat_file(resolved)
|
|
283
303
|
code = content.decode("utf-8") if isinstance(content, bytes) else content
|
|
284
304
|
except FileNotFoundError:
|
|
285
305
|
return {"error": f"File not found: {path}"}
|
|
@@ -318,7 +338,7 @@ class CodeTools(ResourceProvider):
|
|
|
318
338
|
result["dry_run"] = dry_run
|
|
319
339
|
|
|
320
340
|
if not dry_run:
|
|
321
|
-
await
|
|
341
|
+
await fs._pipe_file(resolved, fixed_code.encode("utf-8"))
|
|
322
342
|
result["written"] = True
|
|
323
343
|
|
|
324
344
|
return result
|
|
@@ -343,29 +363,46 @@ class CodeTools(ResourceProvider):
|
|
|
343
363
|
ones based on file extensions.
|
|
344
364
|
"""
|
|
345
365
|
resolved = self._resolve_path(path, agent_ctx)
|
|
366
|
+
fs = self._get_fs(agent_ctx)
|
|
367
|
+
env = self._get_env(agent_ctx)
|
|
346
368
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
369
|
+
if not env:
|
|
370
|
+
return "Diagnostics unavailable: no execution environment configured"
|
|
371
|
+
|
|
372
|
+
# Create diagnostics manager with config
|
|
373
|
+
manager = DiagnosticsManager(env, config=self._diagnostics_config)
|
|
374
|
+
|
|
375
|
+
# Progress callback that emits tool_call_progress events
|
|
376
|
+
async def progress_callback(
|
|
377
|
+
message: str,
|
|
378
|
+
*,
|
|
379
|
+
server_id: str | None = None,
|
|
380
|
+
command: str | None = None,
|
|
381
|
+
status: str = "running",
|
|
382
|
+
) -> None:
|
|
383
|
+
items = []
|
|
384
|
+
if command:
|
|
385
|
+
items.append(f"```bash\n{command}\n```")
|
|
386
|
+
await agent_ctx.events.tool_call_progress(
|
|
387
|
+
message,
|
|
388
|
+
status="in_progress",
|
|
389
|
+
items=items if items else None,
|
|
390
|
+
)
|
|
353
391
|
|
|
354
392
|
# Check if path is directory or file
|
|
355
393
|
try:
|
|
356
|
-
is_dir = await
|
|
394
|
+
is_dir = await fs._isdir(resolved)
|
|
357
395
|
except Exception: # noqa: BLE001
|
|
358
396
|
is_dir = False
|
|
359
397
|
|
|
360
398
|
if is_dir:
|
|
361
399
|
# Collect all files in directory
|
|
362
400
|
try:
|
|
363
|
-
files = await
|
|
364
|
-
# Filter to only include files (not directories)
|
|
401
|
+
files = await fs._find(resolved, detail=True)
|
|
365
402
|
file_paths = [
|
|
366
|
-
|
|
367
|
-
for
|
|
368
|
-
if not await is_directory(
|
|
403
|
+
p
|
|
404
|
+
for p, info in files.items() # pyright: ignore[reportAttributeAccessIssue]
|
|
405
|
+
if not await is_directory(fs, p, entry_type=info["type"])
|
|
369
406
|
]
|
|
370
407
|
except Exception as e: # noqa: BLE001
|
|
371
408
|
return f"Error scanning directory: {e}"
|
|
@@ -373,26 +410,28 @@ class CodeTools(ResourceProvider):
|
|
|
373
410
|
if not file_paths:
|
|
374
411
|
return f"No files found in: {path}"
|
|
375
412
|
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
413
|
+
result = await manager.run_for_files(file_paths, progress=progress_callback)
|
|
414
|
+
else:
|
|
415
|
+
# Single file
|
|
416
|
+
try:
|
|
417
|
+
result = await manager.run_for_file(resolved, progress=progress_callback)
|
|
418
|
+
except FileNotFoundError:
|
|
419
|
+
return f"File not found: {path}"
|
|
420
|
+
except Exception as e: # noqa: BLE001
|
|
421
|
+
return f"Error running diagnostics: {e}"
|
|
380
422
|
|
|
381
|
-
|
|
382
|
-
|
|
423
|
+
# Format output
|
|
424
|
+
if not result.diagnostics:
|
|
425
|
+
summary = format_run_summary(result)
|
|
426
|
+
return f"No issues found. {summary}"
|
|
383
427
|
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
# Single file
|
|
387
|
-
try:
|
|
388
|
-
diagnostics = await self._diagnostics.run_for_file(resolved)
|
|
389
|
-
except FileNotFoundError:
|
|
390
|
-
return f"File not found: {path}"
|
|
391
|
-
except Exception as e: # noqa: BLE001
|
|
392
|
-
return f"Error running diagnostics: {e}"
|
|
428
|
+
formatted = format_diagnostics_table(result.diagnostics)
|
|
429
|
+
summary = format_run_summary(result)
|
|
393
430
|
|
|
394
|
-
|
|
395
|
-
|
|
431
|
+
await agent_ctx.events.tool_call_progress(
|
|
432
|
+
summary,
|
|
433
|
+
status="in_progress",
|
|
434
|
+
items=[formatted],
|
|
435
|
+
)
|
|
396
436
|
|
|
397
|
-
formatted
|
|
398
|
-
return f"Found {len(diagnostics)} issues:\n{formatted}"
|
|
437
|
+
return f"{summary}\n\n{formatted}"
|
|
@@ -4,15 +4,23 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
from collections import deque
|
|
6
6
|
from dataclasses import dataclass, field
|
|
7
|
+
from datetime import UTC, datetime
|
|
8
|
+
import json
|
|
7
9
|
import logging
|
|
8
|
-
from typing import Any, Literal
|
|
10
|
+
from typing import TYPE_CHECKING, Any, Literal
|
|
9
11
|
|
|
12
|
+
from fsspec.implementations.asyn_wrapper import AsyncFileSystemWrapper
|
|
13
|
+
from fsspec.implementations.memory import MemoryFileSystem
|
|
10
14
|
from pydantic_ai import RunContext # noqa: TC002
|
|
11
15
|
|
|
12
16
|
from agentpool.agents.context import AgentContext # noqa: TC001
|
|
13
17
|
from agentpool.resource_providers import StaticResourceProvider
|
|
14
18
|
|
|
15
19
|
|
|
20
|
+
if TYPE_CHECKING:
|
|
21
|
+
from fsspec.asyn import AsyncFileSystem
|
|
22
|
+
|
|
23
|
+
|
|
16
24
|
LogLevel = Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]
|
|
17
25
|
|
|
18
26
|
|
|
@@ -131,6 +139,8 @@ Available in namespace:
|
|
|
131
139
|
- ctx: AgentContext (ctx.agent, ctx.pool, ctx.config, ctx.definition, etc.)
|
|
132
140
|
- run_ctx: pydantic-ai RunContext (current run state)
|
|
133
141
|
- me: Shortcut for ctx.agent (your Agent instance)
|
|
142
|
+
- save(key, value): Save an object to persist between calls
|
|
143
|
+
- state: Dict of saved objects from previous calls
|
|
134
144
|
|
|
135
145
|
You can inspect yourself, the pool, other agents, your tools, and more.
|
|
136
146
|
Write an async main() function that returns the result.
|
|
@@ -138,8 +148,8 @@ Write an async main() function that returns the result.
|
|
|
138
148
|
Example - inspect your own tools:
|
|
139
149
|
```python
|
|
140
150
|
async def main():
|
|
141
|
-
tools = me.tools.list_tools()
|
|
142
|
-
return
|
|
151
|
+
tools = await me.tools.list_tools()
|
|
152
|
+
return list(tools.keys())
|
|
143
153
|
```
|
|
144
154
|
|
|
145
155
|
Example - check pool state:
|
|
@@ -159,30 +169,6 @@ async def main():
|
|
|
159
169
|
"""
|
|
160
170
|
|
|
161
171
|
|
|
162
|
-
async def execute_introspection(ctx: AgentContext, run_ctx: RunContext[Any], code: str) -> str: # noqa: D417
|
|
163
|
-
"""Execute Python code with access to your own runtime context.
|
|
164
|
-
|
|
165
|
-
This is a debugging/development tool that gives you full access to
|
|
166
|
-
inspect and interact with your runtime environment.
|
|
167
|
-
|
|
168
|
-
Args:
|
|
169
|
-
code: Python code with async main() function to execute
|
|
170
|
-
|
|
171
|
-
Returns:
|
|
172
|
-
Result of execution or error message
|
|
173
|
-
"""
|
|
174
|
-
# Build namespace with runtime context
|
|
175
|
-
namespace: dict[str, Any] = {"ctx": ctx, "run_ctx": run_ctx, "me": ctx.agent}
|
|
176
|
-
try:
|
|
177
|
-
exec(code, namespace)
|
|
178
|
-
if "main" not in namespace:
|
|
179
|
-
return "Error: Code must define an async main() function"
|
|
180
|
-
result = await namespace["main"]()
|
|
181
|
-
return str(result) if result is not None else "Code executed successfully (no return value)"
|
|
182
|
-
except Exception as e: # noqa: BLE001
|
|
183
|
-
return f"Error executing code: {type(e).__name__}: {e}"
|
|
184
|
-
|
|
185
|
-
|
|
186
172
|
# =============================================================================
|
|
187
173
|
# Log Tools
|
|
188
174
|
# =============================================================================
|
|
@@ -216,18 +202,6 @@ async def get_logs(
|
|
|
216
202
|
return "\n".join(lines)
|
|
217
203
|
|
|
218
204
|
|
|
219
|
-
async def clear_logs() -> str:
|
|
220
|
-
"""Clear all captured log entries from memory.
|
|
221
|
-
|
|
222
|
-
Returns:
|
|
223
|
-
Confirmation message
|
|
224
|
-
"""
|
|
225
|
-
handler = get_memory_handler()
|
|
226
|
-
count = len(handler.records)
|
|
227
|
-
handler.clear()
|
|
228
|
-
return f"Cleared {count} log entries"
|
|
229
|
-
|
|
230
|
-
|
|
231
205
|
# =============================================================================
|
|
232
206
|
# Path Tools
|
|
233
207
|
# =============================================================================
|
|
@@ -268,24 +242,120 @@ class DebugTools(StaticResourceProvider):
|
|
|
268
242
|
- Self-introspection via code execution with runtime context access
|
|
269
243
|
- Log inspection and management
|
|
270
244
|
- Platform path discovery
|
|
245
|
+
- Stateful namespace for persisting objects between introspection calls
|
|
271
246
|
"""
|
|
272
247
|
|
|
273
|
-
def __init__(self, name: str = "debug"
|
|
248
|
+
def __init__(self, name: str = "debug") -> None:
|
|
274
249
|
"""Initialize debug tools.
|
|
275
250
|
|
|
276
251
|
Args:
|
|
277
252
|
name: Toolset name/namespace
|
|
278
|
-
install_log_handler: Whether to install the memory log handler
|
|
279
253
|
"""
|
|
280
254
|
super().__init__(name=name)
|
|
255
|
+
self._namespace_storage: dict[str, Any] = {} # Stateful storage for introspection
|
|
256
|
+
# Wrap MemoryFileSystem for async support
|
|
257
|
+
self._memory_fs = MemoryFileSystem()
|
|
258
|
+
self._fs = AsyncFileSystemWrapper(self._memory_fs)
|
|
281
259
|
|
|
282
|
-
|
|
283
|
-
install_memory_handler()
|
|
284
|
-
|
|
285
|
-
desc = (execute_introspection.__doc__ or "") + "\n\n" + INTROSPECTION_USAGE
|
|
260
|
+
desc = (self.execute_introspection.__doc__ or "") + "\n\n" + INTROSPECTION_USAGE
|
|
286
261
|
self._tools = [
|
|
287
|
-
self.create_tool(
|
|
288
|
-
|
|
289
|
-
|
|
262
|
+
self.create_tool(
|
|
263
|
+
self.execute_introspection, category="other", description_override=desc
|
|
264
|
+
),
|
|
290
265
|
self.create_tool(get_platform_paths, category="other", read_only=True, idempotent=True),
|
|
291
266
|
]
|
|
267
|
+
|
|
268
|
+
def get_fs(self) -> AsyncFileSystem:
|
|
269
|
+
"""Get filesystem view of script history and state.
|
|
270
|
+
|
|
271
|
+
Returns:
|
|
272
|
+
AsyncFileSystem containing:
|
|
273
|
+
- scripts/{timestamp}_{title}.py - Executed scripts
|
|
274
|
+
- scripts/{timestamp}_{title}.json - Execution metadata
|
|
275
|
+
"""
|
|
276
|
+
return self._fs
|
|
277
|
+
|
|
278
|
+
async def execute_introspection( # noqa: D417
|
|
279
|
+
self, ctx: AgentContext, run_ctx: RunContext[Any], code: str, title: str
|
|
280
|
+
) -> str:
|
|
281
|
+
"""Execute Python code with access to your own runtime context.
|
|
282
|
+
|
|
283
|
+
This is a debugging/development tool that gives you full access to
|
|
284
|
+
inspect and interact with your runtime environment.
|
|
285
|
+
|
|
286
|
+
Args:
|
|
287
|
+
code: Python code with async main() function to execute
|
|
288
|
+
title: Short descriptive title for this script (3-4 words)
|
|
289
|
+
|
|
290
|
+
Returns:
|
|
291
|
+
Result of execution or error message
|
|
292
|
+
"""
|
|
293
|
+
# Emit progress with the code being executed
|
|
294
|
+
await ctx.events.tool_call_progress(
|
|
295
|
+
title="Executing introspection code",
|
|
296
|
+
status="in_progress",
|
|
297
|
+
items=[f"```python\n{code}\n```"],
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
# Build namespace with runtime context and stateful storage
|
|
301
|
+
def save(key: str, value: Any) -> None:
|
|
302
|
+
"""Save a value to persist between introspection calls."""
|
|
303
|
+
self._namespace_storage[key] = value
|
|
304
|
+
|
|
305
|
+
state = self._namespace_storage.copy()
|
|
306
|
+
|
|
307
|
+
namespace: dict[str, Any] = {
|
|
308
|
+
"ctx": ctx,
|
|
309
|
+
"run_ctx": run_ctx,
|
|
310
|
+
"me": ctx.agent,
|
|
311
|
+
"save": save,
|
|
312
|
+
"state": state,
|
|
313
|
+
}
|
|
314
|
+
start_time = datetime.now(UTC)
|
|
315
|
+
exit_code = 0
|
|
316
|
+
error_msg = None
|
|
317
|
+
result_str = None
|
|
318
|
+
|
|
319
|
+
try:
|
|
320
|
+
exec(code, namespace)
|
|
321
|
+
if "main" not in namespace:
|
|
322
|
+
return "Error: Code must define an async main() function"
|
|
323
|
+
result = await namespace["main"]()
|
|
324
|
+
result_str = (
|
|
325
|
+
str(result)
|
|
326
|
+
if result is not None
|
|
327
|
+
else "Code executed successfully (no return value)"
|
|
328
|
+
)
|
|
329
|
+
|
|
330
|
+
await ctx.events.tool_call_progress(
|
|
331
|
+
title="Executed introspection code successfully",
|
|
332
|
+
status="in_progress",
|
|
333
|
+
items=[f"```python\n{code}\n```\n\n```terminal\n{result_str}\n```"],
|
|
334
|
+
)
|
|
335
|
+
except Exception as e: # noqa: BLE001
|
|
336
|
+
exit_code = 1
|
|
337
|
+
error_msg = f"{type(e).__name__}: {e}"
|
|
338
|
+
result_str = error_msg
|
|
339
|
+
finally:
|
|
340
|
+
# Save to filesystem
|
|
341
|
+
end_time = datetime.now(UTC)
|
|
342
|
+
duration = (end_time - start_time).total_seconds()
|
|
343
|
+
timestamp = start_time.strftime("%Y%m%d_%H%M%S")
|
|
344
|
+
|
|
345
|
+
# Write script file
|
|
346
|
+
script_path = f"scripts/{timestamp}_{title}.py"
|
|
347
|
+
self._memory_fs.pipe(script_path, code.encode("utf-8"))
|
|
348
|
+
|
|
349
|
+
# Write metadata file
|
|
350
|
+
metadata = {
|
|
351
|
+
"title": title,
|
|
352
|
+
"timestamp": start_time.isoformat(),
|
|
353
|
+
"exit_code": exit_code,
|
|
354
|
+
"duration": duration,
|
|
355
|
+
"result": result_str,
|
|
356
|
+
"error": error_msg,
|
|
357
|
+
}
|
|
358
|
+
metadata_path = f"scripts/{timestamp}_{title}.json"
|
|
359
|
+
self._memory_fs.pipe(metadata_path, json.dumps(metadata, indent=2).encode("utf-8"))
|
|
360
|
+
|
|
361
|
+
return result_str
|