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
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"""Mode definitions for agent behavior configuration.
|
|
2
|
+
|
|
3
|
+
Modes represent switchable behaviors/configurations that agents can expose
|
|
4
|
+
to clients. Each agent type can define its own mode categories.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from dataclasses import dataclass, field
|
|
10
|
+
from typing import Literal
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass
|
|
14
|
+
class ModeInfo:
|
|
15
|
+
"""Information about a single mode option.
|
|
16
|
+
|
|
17
|
+
Represents one selectable option within a mode category.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
id: str
|
|
21
|
+
"""Unique identifier for this mode."""
|
|
22
|
+
|
|
23
|
+
name: str
|
|
24
|
+
"""Human-readable display name."""
|
|
25
|
+
|
|
26
|
+
description: str = ""
|
|
27
|
+
"""Optional description of what this mode does."""
|
|
28
|
+
|
|
29
|
+
category_id: str = ""
|
|
30
|
+
"""ID of the category this mode belongs to."""
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@dataclass
|
|
34
|
+
class ModeCategory:
|
|
35
|
+
"""A category of modes that can be switched.
|
|
36
|
+
|
|
37
|
+
Represents a group of mutually exclusive modes. In the future,
|
|
38
|
+
ACP may support multiple categories rendered as separate dropdowns.
|
|
39
|
+
|
|
40
|
+
Examples:
|
|
41
|
+
- Permissions: default, acceptEdits
|
|
42
|
+
- Behavior: plan, code, architect
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
id: str
|
|
46
|
+
"""Unique identifier for this category."""
|
|
47
|
+
|
|
48
|
+
name: str
|
|
49
|
+
"""Human-readable display name for the category."""
|
|
50
|
+
|
|
51
|
+
available_modes: list[ModeInfo] = field(default_factory=list)
|
|
52
|
+
"""List of available modes in this category."""
|
|
53
|
+
|
|
54
|
+
current_mode_id: str = ""
|
|
55
|
+
"""ID of the currently active mode."""
|
|
56
|
+
|
|
57
|
+
category: Literal["mode", "model", "thought_level", "other"] | None = None
|
|
58
|
+
"""Optional semantic category for UX purposes (keyboard shortcuts, icons, placement).
|
|
59
|
+
|
|
60
|
+
This helps clients distinguish common selector types:
|
|
61
|
+
- 'mode': Session mode selector
|
|
62
|
+
- 'model': Model selector
|
|
63
|
+
- 'thought_level': Thought/reasoning level selector
|
|
64
|
+
- 'other': Unknown/uncategorized
|
|
65
|
+
|
|
66
|
+
MUST NOT be required for correctness. Clients should handle gracefully.
|
|
67
|
+
"""
|
|
@@ -7,10 +7,6 @@ import re
|
|
|
7
7
|
from typing import TYPE_CHECKING, Any, cast
|
|
8
8
|
|
|
9
9
|
import anyio
|
|
10
|
-
from slashed.events import (
|
|
11
|
-
CommandExecutedEvent,
|
|
12
|
-
CommandOutputEvent as SlashedCommandOutputEvent,
|
|
13
|
-
)
|
|
14
10
|
|
|
15
11
|
from agentpool.agents.events import CommandCompleteEvent, CommandOutputEvent
|
|
16
12
|
from agentpool.log import get_logger
|
|
@@ -112,6 +108,11 @@ class SlashedAgent[TDeps, OutputDataT]:
|
|
|
112
108
|
Yields:
|
|
113
109
|
Command output and completion events
|
|
114
110
|
"""
|
|
111
|
+
from slashed.events import (
|
|
112
|
+
CommandExecutedEvent,
|
|
113
|
+
CommandOutputEvent as SlashedCommandOutputEvent,
|
|
114
|
+
)
|
|
115
|
+
|
|
115
116
|
parsed = _parse_slash_command(command_text)
|
|
116
117
|
if not parsed:
|
|
117
118
|
logger.warning("Invalid slash command", command=command_text)
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
"""Tool call accumulator for streaming tool arguments.
|
|
2
|
+
|
|
3
|
+
This module provides utilities for accumulating streamed tool call arguments
|
|
4
|
+
from LLM APIs that stream JSON arguments incrementally (like Anthropic's
|
|
5
|
+
input_json_delta or OpenAI's function call streaming).
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from typing import Any
|
|
11
|
+
|
|
12
|
+
import anyenv
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def repair_partial_json(buffer: str) -> str:
|
|
16
|
+
"""Attempt to repair truncated JSON for preview purposes.
|
|
17
|
+
|
|
18
|
+
Handles common truncation cases:
|
|
19
|
+
- Unclosed strings
|
|
20
|
+
- Missing closing braces/brackets
|
|
21
|
+
- Trailing commas
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
buffer: Potentially incomplete JSON string
|
|
25
|
+
|
|
26
|
+
Returns:
|
|
27
|
+
Repaired JSON string (may still be invalid in edge cases)
|
|
28
|
+
"""
|
|
29
|
+
if not buffer:
|
|
30
|
+
return "{}"
|
|
31
|
+
|
|
32
|
+
result = buffer.rstrip()
|
|
33
|
+
|
|
34
|
+
# Check if we're in the middle of a string by counting unescaped quotes
|
|
35
|
+
in_string = False
|
|
36
|
+
i = 0
|
|
37
|
+
while i < len(result):
|
|
38
|
+
char = result[i]
|
|
39
|
+
if char == "\\" and i + 1 < len(result):
|
|
40
|
+
i += 2 # Skip escaped character
|
|
41
|
+
continue
|
|
42
|
+
if char == '"':
|
|
43
|
+
in_string = not in_string
|
|
44
|
+
i += 1
|
|
45
|
+
|
|
46
|
+
# Close unclosed string
|
|
47
|
+
if in_string:
|
|
48
|
+
result += '"'
|
|
49
|
+
|
|
50
|
+
# Remove trailing comma (invalid JSON)
|
|
51
|
+
result = result.rstrip()
|
|
52
|
+
if result.endswith(","):
|
|
53
|
+
result = result[:-1]
|
|
54
|
+
|
|
55
|
+
# Balance braces and brackets
|
|
56
|
+
open_braces = result.count("{") - result.count("}")
|
|
57
|
+
open_brackets = result.count("[") - result.count("]")
|
|
58
|
+
|
|
59
|
+
result += "]" * max(0, open_brackets)
|
|
60
|
+
result += "}" * max(0, open_braces)
|
|
61
|
+
|
|
62
|
+
return result
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class ToolCallAccumulator:
|
|
66
|
+
"""Accumulates streamed tool call arguments.
|
|
67
|
+
|
|
68
|
+
LLM APIs stream tool call arguments as deltas. This class accumulates them
|
|
69
|
+
and provides the complete arguments when the tool call ends, as well as
|
|
70
|
+
best-effort partial argument parsing during streaming.
|
|
71
|
+
|
|
72
|
+
Example:
|
|
73
|
+
```python
|
|
74
|
+
accumulator = ToolCallAccumulator()
|
|
75
|
+
|
|
76
|
+
# On content_block_start with tool_use
|
|
77
|
+
accumulator.start("toolu_123", "write_file")
|
|
78
|
+
|
|
79
|
+
# On input_json_delta events
|
|
80
|
+
accumulator.add_args("toolu_123", '{"path": "/tmp/')
|
|
81
|
+
accumulator.add_args("toolu_123", 'test.txt", "content"')
|
|
82
|
+
accumulator.add_args("toolu_123", ': "hello"}')
|
|
83
|
+
|
|
84
|
+
# Get partial args for UI preview (repairs incomplete JSON)
|
|
85
|
+
partial = accumulator.get_partial_args("toolu_123")
|
|
86
|
+
|
|
87
|
+
# On content_block_stop, get final parsed args
|
|
88
|
+
name, args = accumulator.complete("toolu_123")
|
|
89
|
+
```
|
|
90
|
+
"""
|
|
91
|
+
|
|
92
|
+
def __init__(self) -> None:
|
|
93
|
+
self._calls: dict[str, dict[str, Any]] = {}
|
|
94
|
+
|
|
95
|
+
def start(self, tool_call_id: str, tool_name: str) -> None:
|
|
96
|
+
"""Start tracking a new tool call.
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
tool_call_id: Unique identifier for the tool call
|
|
100
|
+
tool_name: Name of the tool being called
|
|
101
|
+
"""
|
|
102
|
+
self._calls[tool_call_id] = {"name": tool_name, "args_buffer": ""}
|
|
103
|
+
|
|
104
|
+
def add_args(self, tool_call_id: str, delta: str) -> None:
|
|
105
|
+
"""Add argument delta to a tool call.
|
|
106
|
+
|
|
107
|
+
Args:
|
|
108
|
+
tool_call_id: Tool call identifier
|
|
109
|
+
delta: JSON string fragment to append
|
|
110
|
+
"""
|
|
111
|
+
if tool_call_id in self._calls:
|
|
112
|
+
self._calls[tool_call_id]["args_buffer"] += delta
|
|
113
|
+
|
|
114
|
+
def complete(self, tool_call_id: str) -> tuple[str, dict[str, Any]] | None:
|
|
115
|
+
"""Complete a tool call and return (tool_name, parsed_args).
|
|
116
|
+
|
|
117
|
+
Removes the tool call from tracking and returns the final parsed arguments.
|
|
118
|
+
|
|
119
|
+
Args:
|
|
120
|
+
tool_call_id: Tool call identifier
|
|
121
|
+
|
|
122
|
+
Returns:
|
|
123
|
+
Tuple of (tool_name, args_dict) or None if call not found
|
|
124
|
+
"""
|
|
125
|
+
if tool_call_id not in self._calls:
|
|
126
|
+
return None
|
|
127
|
+
|
|
128
|
+
call_data = self._calls.pop(tool_call_id)
|
|
129
|
+
args_str = call_data["args_buffer"]
|
|
130
|
+
try:
|
|
131
|
+
args = anyenv.load_json(args_str) if args_str else {}
|
|
132
|
+
except anyenv.JsonLoadError:
|
|
133
|
+
args = {"_raw": args_str}
|
|
134
|
+
return call_data["name"], args
|
|
135
|
+
|
|
136
|
+
def get_pending(self, tool_call_id: str) -> tuple[str, str] | None:
|
|
137
|
+
"""Get pending call data (tool_name, args_buffer) without completing.
|
|
138
|
+
|
|
139
|
+
Args:
|
|
140
|
+
tool_call_id: Tool call identifier
|
|
141
|
+
|
|
142
|
+
Returns:
|
|
143
|
+
Tuple of (tool_name, args_buffer) or None if not found
|
|
144
|
+
"""
|
|
145
|
+
if tool_call_id not in self._calls:
|
|
146
|
+
return None
|
|
147
|
+
data = self._calls[tool_call_id]
|
|
148
|
+
return data["name"], data["args_buffer"]
|
|
149
|
+
|
|
150
|
+
def get_partial_args(self, tool_call_id: str) -> dict[str, Any]:
|
|
151
|
+
"""Get best-effort parsed args from incomplete JSON stream.
|
|
152
|
+
|
|
153
|
+
Uses heuristics to complete truncated JSON for preview purposes.
|
|
154
|
+
Handles unclosed strings, missing braces/brackets, and trailing commas.
|
|
155
|
+
|
|
156
|
+
Args:
|
|
157
|
+
tool_call_id: Tool call ID
|
|
158
|
+
|
|
159
|
+
Returns:
|
|
160
|
+
Partially parsed arguments or empty dict
|
|
161
|
+
"""
|
|
162
|
+
if tool_call_id not in self._calls:
|
|
163
|
+
return {}
|
|
164
|
+
|
|
165
|
+
buffer = self._calls[tool_call_id]["args_buffer"]
|
|
166
|
+
if not buffer:
|
|
167
|
+
return {}
|
|
168
|
+
|
|
169
|
+
# Try direct parse first
|
|
170
|
+
try:
|
|
171
|
+
result: dict[str, Any] = anyenv.load_json(buffer)
|
|
172
|
+
except anyenv.JsonLoadError:
|
|
173
|
+
pass
|
|
174
|
+
else:
|
|
175
|
+
return result
|
|
176
|
+
|
|
177
|
+
# Try to repair truncated JSON
|
|
178
|
+
try:
|
|
179
|
+
repaired = repair_partial_json(buffer)
|
|
180
|
+
result = anyenv.load_json(repaired)
|
|
181
|
+
except anyenv.JsonLoadError:
|
|
182
|
+
return {}
|
|
183
|
+
else:
|
|
184
|
+
return result
|
|
185
|
+
|
|
186
|
+
def is_pending(self, tool_call_id: str) -> bool:
|
|
187
|
+
"""Check if a tool call is being tracked.
|
|
188
|
+
|
|
189
|
+
Args:
|
|
190
|
+
tool_call_id: Tool call identifier
|
|
191
|
+
|
|
192
|
+
Returns:
|
|
193
|
+
True if the tool call is being accumulated
|
|
194
|
+
"""
|
|
195
|
+
return tool_call_id in self._calls
|
|
196
|
+
|
|
197
|
+
def get_tool_name(self, tool_call_id: str) -> str | None:
|
|
198
|
+
"""Get the tool name for a pending call.
|
|
199
|
+
|
|
200
|
+
Args:
|
|
201
|
+
tool_call_id: Tool call identifier
|
|
202
|
+
|
|
203
|
+
Returns:
|
|
204
|
+
Tool name or None if not found
|
|
205
|
+
"""
|
|
206
|
+
if tool_call_id not in self._calls:
|
|
207
|
+
return None
|
|
208
|
+
name: str = self._calls[tool_call_id]["name"]
|
|
209
|
+
return name
|
|
210
|
+
|
|
211
|
+
def clear(self) -> None:
|
|
212
|
+
"""Clear all pending tool calls."""
|
|
213
|
+
self._calls.clear()
|
|
@@ -9,9 +9,11 @@ import time
|
|
|
9
9
|
from typing import TYPE_CHECKING, Any
|
|
10
10
|
|
|
11
11
|
from pydantic_ai import RunContext
|
|
12
|
+
from pydantic_ai.messages import ToolReturn
|
|
12
13
|
|
|
13
14
|
from agentpool.agents.context import AgentContext
|
|
14
15
|
from agentpool.tasks import ChainAbortedError, RunAbortedError, ToolSkippedError
|
|
16
|
+
from agentpool.tools.base import ToolResult
|
|
15
17
|
from agentpool.utils.inspection import execute, get_argument_key
|
|
16
18
|
from agentpool.utils.signatures import create_modified_signature, update_signature
|
|
17
19
|
|
|
@@ -27,7 +29,7 @@ def wrap_tool[TReturn]( # noqa: PLR0915
|
|
|
27
29
|
tool: Tool[TReturn],
|
|
28
30
|
agent_ctx: AgentContext,
|
|
29
31
|
hooks: AgentHooks | None = None,
|
|
30
|
-
) -> Callable[..., Awaitable[TReturn | None]]:
|
|
32
|
+
) -> Callable[..., Awaitable[TReturn | ToolReturn | None]]:
|
|
31
33
|
"""Wrap tool with confirmation handling and hooks.
|
|
32
34
|
|
|
33
35
|
Strategy:
|
|
@@ -41,7 +43,7 @@ def wrap_tool[TReturn]( # noqa: PLR0915
|
|
|
41
43
|
agent_ctx: Agent context for confirmation handling and dependency injection.
|
|
42
44
|
hooks: Optional AgentHooks for pre/post tool execution hooks.
|
|
43
45
|
"""
|
|
44
|
-
fn = tool.
|
|
46
|
+
fn = tool.get_callable()
|
|
45
47
|
run_ctx_key = get_argument_key(fn, RunContext)
|
|
46
48
|
agent_ctx_key = get_argument_key(fn, AgentContext)
|
|
47
49
|
|
|
@@ -58,7 +60,7 @@ def wrap_tool[TReturn]( # noqa: PLR0915
|
|
|
58
60
|
tool_input: dict[str, Any],
|
|
59
61
|
*args: Any,
|
|
60
62
|
**kwargs: Any,
|
|
61
|
-
) -> TReturn | None:
|
|
63
|
+
) -> TReturn | None | ToolReturn:
|
|
62
64
|
"""Execute tool with pre/post hooks."""
|
|
63
65
|
# Pre-tool hooks
|
|
64
66
|
if hooks:
|
|
@@ -79,9 +81,17 @@ def wrap_tool[TReturn]( # noqa: PLR0915
|
|
|
79
81
|
|
|
80
82
|
# Execute the tool
|
|
81
83
|
start_time = time.perf_counter()
|
|
82
|
-
result = await execute_fn(*args, **kwargs)
|
|
84
|
+
result: TReturn | ToolResult | ToolReturn = await execute_fn(*args, **kwargs)
|
|
83
85
|
duration_ms = (time.perf_counter() - start_time) * 1000
|
|
84
86
|
|
|
87
|
+
# Convert AgentPool ToolResult to pydantic-ai ToolReturn
|
|
88
|
+
if isinstance(result, ToolResult):
|
|
89
|
+
result = ToolReturn(
|
|
90
|
+
return_value=result.structured_content or result.content,
|
|
91
|
+
content=result.content,
|
|
92
|
+
metadata=result.metadata,
|
|
93
|
+
)
|
|
94
|
+
|
|
85
95
|
# Post-tool hooks
|
|
86
96
|
if hooks:
|
|
87
97
|
await hooks.run_post_tool_hooks(
|
|
@@ -97,7 +107,9 @@ def wrap_tool[TReturn]( # noqa: PLR0915
|
|
|
97
107
|
|
|
98
108
|
if run_ctx_key or agent_ctx_key:
|
|
99
109
|
# Tool has RunContext and/or AgentContext
|
|
100
|
-
async def wrapped(
|
|
110
|
+
async def wrapped(
|
|
111
|
+
ctx: RunContext, *args: Any, **kwargs: Any
|
|
112
|
+
) -> TReturn | None | ToolReturn: # pyright: ignore
|
|
101
113
|
result = await agent_ctx.handle_confirmation(tool, kwargs)
|
|
102
114
|
if result == "allow":
|
|
103
115
|
# Populate AgentContext with RunContext data if needed
|
|
@@ -135,7 +147,7 @@ def wrap_tool[TReturn]( # noqa: PLR0915
|
|
|
135
147
|
|
|
136
148
|
else:
|
|
137
149
|
# Tool has no context - normal function call
|
|
138
|
-
async def wrapped(*args: Any, **kwargs: Any) -> TReturn | None: # type: ignore[misc]
|
|
150
|
+
async def wrapped(*args: Any, **kwargs: Any) -> TReturn | None | ToolReturn: # type: ignore[misc]
|
|
139
151
|
result = await agent_ctx.handle_confirmation(tool, kwargs)
|
|
140
152
|
if result == "allow":
|
|
141
153
|
tool_input = kwargs.copy()
|
agentpool/common_types.py
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
from collections.abc import Awaitable, Callable
|
|
6
|
+
from dataclasses import dataclass
|
|
6
7
|
from typing import (
|
|
7
8
|
TYPE_CHECKING,
|
|
8
9
|
Any,
|
|
@@ -27,15 +28,13 @@ if TYPE_CHECKING:
|
|
|
27
28
|
from uuid import UUID
|
|
28
29
|
|
|
29
30
|
from agentpool.agents.events import RichAgentStreamEvent
|
|
30
|
-
from agentpool.messaging import ChatMessage
|
|
31
|
-
from agentpool.messaging.messagenode import MessageNode
|
|
32
31
|
from agentpool.tools.base import Tool
|
|
33
32
|
|
|
34
|
-
# Type alias for team streaming return type (node + event tuples)
|
|
35
|
-
type TeamStreamEvent = tuple[MessageNode[Any, Any], RichAgentStreamEvent[Any]]
|
|
36
33
|
type AnyTransformFn[T] = Callable[[T], T | Awaitable[T]]
|
|
37
34
|
type OptionalAwaitable[T] = T | Awaitable[T]
|
|
38
|
-
|
|
35
|
+
# Import path string for dynamic tool loading (e.g., "mymodule:my_tool")
|
|
36
|
+
type ImportPathString = str
|
|
37
|
+
type ToolType = ImportPathString | AnyCallable | Tool
|
|
39
38
|
# Define what we consider JSON-serializable
|
|
40
39
|
type JsonPrimitive = None | bool | int | float | str
|
|
41
40
|
type SessionIdType = str | UUID | None
|
|
@@ -50,12 +49,32 @@ type JsonObject = dict[str, JsonValue]
|
|
|
50
49
|
type JsonArray = list[JsonValue]
|
|
51
50
|
|
|
52
51
|
|
|
52
|
+
MCPConnectionStatus = Literal["connected", "disconnected", "error"]
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@dataclass(frozen=True, slots=True)
|
|
56
|
+
class MCPServerStatus:
|
|
57
|
+
"""Status information for an MCP server.
|
|
58
|
+
|
|
59
|
+
Attributes:
|
|
60
|
+
name: Server name/identifier
|
|
61
|
+
status: Connection status
|
|
62
|
+
server_type: Transport type (stdio, sse, http)
|
|
63
|
+
error: Error message if status is "error"
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
name: str
|
|
67
|
+
status: MCPConnectionStatus
|
|
68
|
+
server_type: str = "unknown"
|
|
69
|
+
error: str | None = None
|
|
70
|
+
|
|
71
|
+
|
|
53
72
|
NodeName = str
|
|
54
73
|
TeamName = str
|
|
55
74
|
AgentName = str
|
|
56
75
|
MessageRole = Literal["user", "assistant"]
|
|
57
76
|
PartType = Literal["text", "image", "audio", "video"]
|
|
58
|
-
ModelType = Model | ModelId | str
|
|
77
|
+
ModelType = Model | ModelId | str
|
|
59
78
|
EnvironmentType = Literal["file", "inline"]
|
|
60
79
|
ToolSource = Literal["agent", "builtin", "dynamic", "task", "mcp", "toolset"]
|
|
61
80
|
AnyCallable = Callable[..., Any]
|
|
@@ -78,30 +97,46 @@ QueueStrategy = Literal["concat", "latest", "buffer"]
|
|
|
78
97
|
"""
|
|
79
98
|
|
|
80
99
|
|
|
81
|
-
class SupportsStructuredOutput(Protocol):
|
|
82
|
-
"""Protocol for nodes that support structured output via run().
|
|
83
|
-
|
|
84
|
-
This protocol is used for components that need to call run() with
|
|
85
|
-
an output_type parameter (e.g., picker agents, Interactions).
|
|
86
|
-
"""
|
|
87
|
-
|
|
88
|
-
async def run(self, *prompts: Any, output_type: Any = ...) -> ChatMessage[Any]: ...
|
|
89
|
-
|
|
90
|
-
|
|
91
100
|
@runtime_checkable
|
|
92
101
|
class SupportsRunStream[TResult](Protocol):
|
|
93
102
|
"""Protocol for nodes that support streaming via run_stream().
|
|
94
103
|
|
|
95
104
|
Used by Team and TeamRun to check if a node can be streamed.
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
- Agent returns `AsyncIterator[RichAgentStreamEvent[TResult]]`
|
|
99
|
-
- Team/TeamRun return `AsyncIterator[tuple[MessageNode, RichAgentStreamEvent]]`
|
|
105
|
+
All streaming nodes return RichAgentStreamEvent, with subagent/team
|
|
106
|
+
activity wrapped in SubAgentEvent.
|
|
100
107
|
"""
|
|
101
108
|
|
|
102
109
|
def run_stream(
|
|
103
110
|
self, *prompts: Any, **kwargs: Any
|
|
104
|
-
) -> AsyncIterator[RichAgentStreamEvent[TResult]
|
|
111
|
+
) -> AsyncIterator[RichAgentStreamEvent[TResult]]: ...
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
@runtime_checkable
|
|
115
|
+
class SupportsStructuredOutput(Protocol):
|
|
116
|
+
"""Protocol for agents that support structured output via to_structured().
|
|
117
|
+
|
|
118
|
+
Used by Interactions class for pick/extract operations that require
|
|
119
|
+
structured output from agents.
|
|
120
|
+
"""
|
|
121
|
+
|
|
122
|
+
def to_structured[T](self, output_type: type[T]) -> SupportsStructuredOutput:
|
|
123
|
+
"""Create a copy of this agent configured for structured output.
|
|
124
|
+
|
|
125
|
+
Args:
|
|
126
|
+
output_type: The type to structure output as
|
|
127
|
+
|
|
128
|
+
Returns:
|
|
129
|
+
New agent instance configured for structured output
|
|
130
|
+
"""
|
|
131
|
+
...
|
|
132
|
+
|
|
133
|
+
async def run(self, *prompts: Any, **kwargs: Any) -> Any:
|
|
134
|
+
"""Run the agent with the given prompts.
|
|
135
|
+
|
|
136
|
+
Returns:
|
|
137
|
+
ChatMessage with content typed according to output_type from to_structured
|
|
138
|
+
"""
|
|
139
|
+
...
|
|
105
140
|
|
|
106
141
|
|
|
107
142
|
class BaseCode(BaseModel):
|
|
@@ -7,10 +7,47 @@ from typing import Final
|
|
|
7
7
|
|
|
8
8
|
_RESOURCES = importlib.resources.files("agentpool.config_resources")
|
|
9
9
|
|
|
10
|
+
# Template configuration
|
|
10
11
|
AGENTS_TEMPLATE: Final[str] = str(_RESOURCES / "agents_template.yml")
|
|
11
12
|
"""Path to the agents template configuration."""
|
|
12
13
|
|
|
14
|
+
# Pool configurations
|
|
13
15
|
ACP_ASSISTANT: Final[str] = str(_RESOURCES / "acp_assistant.yml")
|
|
14
16
|
"""Path to default ACP assistant configuration."""
|
|
15
17
|
|
|
16
|
-
|
|
18
|
+
AGENTS: Final[str] = str(_RESOURCES / "agents.yml")
|
|
19
|
+
"""Path to the main agents configuration."""
|
|
20
|
+
|
|
21
|
+
AGUI_TEST: Final[str] = str(_RESOURCES / "agui_test.yml")
|
|
22
|
+
"""Path to AGUI test configuration."""
|
|
23
|
+
|
|
24
|
+
CLAUDE_CODE_ASSISTANT: Final[str] = str(_RESOURCES / "claude_code_agent.yml")
|
|
25
|
+
"""Path to default Claude code assistant configuration."""
|
|
26
|
+
|
|
27
|
+
EXTERNAL_ACP_AGENTS: Final[str] = str(_RESOURCES / "external_acp_agents.yml")
|
|
28
|
+
"""Path to external ACP agents configuration."""
|
|
29
|
+
|
|
30
|
+
TTS_TEST_AGENTS: Final[str] = str(_RESOURCES / "tts_test_agents.yml")
|
|
31
|
+
"""Path to TTS test agents configuration."""
|
|
32
|
+
|
|
33
|
+
# All pool configuration paths for validation
|
|
34
|
+
ALL_POOL_CONFIGS: Final[tuple[str, ...]] = (
|
|
35
|
+
ACP_ASSISTANT,
|
|
36
|
+
AGENTS,
|
|
37
|
+
AGUI_TEST,
|
|
38
|
+
CLAUDE_CODE_ASSISTANT,
|
|
39
|
+
EXTERNAL_ACP_AGENTS,
|
|
40
|
+
TTS_TEST_AGENTS,
|
|
41
|
+
)
|
|
42
|
+
"""All pool configuration file paths."""
|
|
43
|
+
|
|
44
|
+
__all__ = [
|
|
45
|
+
"ACP_ASSISTANT",
|
|
46
|
+
"AGENTS",
|
|
47
|
+
"AGENTS_TEMPLATE",
|
|
48
|
+
"AGUI_TEST",
|
|
49
|
+
"ALL_POOL_CONFIGS",
|
|
50
|
+
"CLAUDE_CODE_ASSISTANT",
|
|
51
|
+
"EXTERNAL_ACP_AGENTS",
|
|
52
|
+
"TTS_TEST_AGENTS",
|
|
53
|
+
]
|
|
@@ -17,8 +17,8 @@ agents:
|
|
|
17
17
|
You are a helpful AI assistant with access to the file system and can execute code.
|
|
18
18
|
You can help with coding, writing, analysis, file operations, and more.
|
|
19
19
|
Be concise but thorough in your responses.
|
|
20
|
-
|
|
21
|
-
- type:
|
|
20
|
+
tools:
|
|
21
|
+
- type: process_management
|
|
22
22
|
- type: file_access
|
|
23
23
|
- type: code
|
|
24
24
|
- type: search
|
|
@@ -47,6 +47,7 @@ responses:
|
|
|
47
47
|
|
|
48
48
|
agents:
|
|
49
49
|
url_opener:
|
|
50
|
+
type: native
|
|
50
51
|
tools:
|
|
51
52
|
- type: import
|
|
52
53
|
import_path: "webbrowser.open"
|
|
@@ -63,6 +64,7 @@ agents:
|
|
|
63
64
|
Always confirm what you're about to open.
|
|
64
65
|
|
|
65
66
|
system_inspector:
|
|
67
|
+
type: native
|
|
66
68
|
tools:
|
|
67
69
|
- type: import
|
|
68
70
|
import_path: "platform.platform"
|
|
@@ -84,6 +86,7 @@ agents:
|
|
|
84
86
|
Format it using the template from the system_template resource.
|
|
85
87
|
|
|
86
88
|
file_explorer:
|
|
89
|
+
type: native
|
|
87
90
|
tools:
|
|
88
91
|
- type: import
|
|
89
92
|
import_path: "os.listdir"
|
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
# yaml-language-server: $schema=https://raw.githubusercontent.com/phil65/agentpool/refs/heads/main/schema/config-schema.json
|
|
2
|
-
# Default ACP assistant configuration
|
|
3
|
-
# Used when starting ACP server without explicit config file
|
|
4
2
|
|
|
5
3
|
agents:
|
|
6
4
|
claude:
|
|
7
5
|
type: claude_code
|
|
8
6
|
display_name: "AI Assistant"
|
|
9
|
-
builtin_tools: []
|
|
7
|
+
builtin_tools: [] # we use our own tools.
|
|
8
|
+
use_subscription: true
|
|
10
9
|
description: "Claude code agent with enhanced tools"
|
|
11
|
-
|
|
12
|
-
- type:
|
|
10
|
+
tools:
|
|
11
|
+
- type: bash
|
|
12
|
+
- type: agent_cli
|
|
13
|
+
- type: process_management
|
|
13
14
|
- type: file_access
|
|
14
|
-
|
|
15
|
+
edit_tool: batch
|
|
16
|
+
# - type: code
|
|
15
17
|
- type: search
|
|
16
18
|
- type: plan
|
|
19
|
+
- type: question
|
|
20
|
+
# - type: debug
|