agentpool 2.2.3__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 +0 -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/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 +18 -49
- 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/task/supervisor.py +2 -2
- acp/utils.py +2 -2
- agentpool/__init__.py +2 -0
- agentpool/agents/acp_agent/acp_agent.py +278 -263
- agentpool/agents/acp_agent/acp_converters.py +150 -17
- agentpool/agents/acp_agent/client_handler.py +35 -24
- agentpool/agents/acp_agent/session_state.py +14 -6
- agentpool/agents/agent.py +471 -643
- agentpool/agents/agui_agent/agui_agent.py +104 -107
- agentpool/agents/agui_agent/helpers.py +3 -4
- agentpool/agents/base_agent.py +485 -32
- 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 +654 -334
- agentpool/agents/claude_code_agent/converters.py +4 -141
- 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/events/__init__.py +22 -0
- agentpool/agents/events/builtin_handlers.py +65 -0
- agentpool/agents/events/event_emitter.py +3 -0
- agentpool/agents/events/events.py +84 -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 +13 -0
- agentpool/agents/slashed_agent.py +5 -4
- agentpool/agents/tool_wrapping.py +18 -6
- agentpool/common_types.py +35 -21
- 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 +9 -8
- agentpool/config_resources/external_acp_agents.yml +2 -1
- agentpool/delegation/base_team.py +4 -30
- agentpool/delegation/pool.py +104 -265
- agentpool/delegation/team.py +57 -57
- agentpool/delegation/teamrun.py +50 -55
- agentpool/functional/run.py +10 -4
- agentpool/mcp_server/client.py +73 -38
- agentpool/mcp_server/conversions.py +54 -13
- agentpool/mcp_server/manager.py +9 -23
- agentpool/mcp_server/registries/official_registry_client.py +10 -1
- agentpool/mcp_server/tool_bridge.py +114 -79
- 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 +87 -8
- agentpool/messaging/messagenode.py +52 -14
- agentpool/messaging/messages.py +2 -26
- agentpool/messaging/processing.py +10 -22
- agentpool/models/__init__.py +1 -1
- agentpool/models/acp_agents/base.py +6 -2
- agentpool/models/acp_agents/mcp_capable.py +124 -15
- agentpool/models/acp_agents/non_mcp.py +0 -23
- agentpool/models/agents.py +66 -66
- agentpool/models/agui_agents.py +1 -1
- agentpool/models/claude_code_agents.py +111 -17
- agentpool/models/file_parsing.py +0 -1
- agentpool/models/manifest.py +70 -50
- agentpool/prompts/conversion_manager.py +1 -1
- agentpool/prompts/prompts.py +5 -2
- agentpool/resource_providers/__init__.py +2 -0
- agentpool/resource_providers/aggregating.py +4 -2
- agentpool/resource_providers/base.py +13 -3
- 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 +66 -12
- agentpool/resource_providers/plan_provider.py +111 -18
- agentpool/resource_providers/pool.py +5 -3
- agentpool/resource_providers/resource_info.py +111 -0
- agentpool/resource_providers/static.py +2 -2
- agentpool/sessions/__init__.py +2 -0
- agentpool/sessions/manager.py +2 -3
- agentpool/sessions/models.py +9 -6
- agentpool/sessions/protocol.py +28 -0
- agentpool/sessions/session.py +11 -55
- agentpool/storage/manager.py +361 -54
- agentpool/talk/registry.py +4 -4
- agentpool/talk/talk.py +9 -10
- agentpool/testing.py +1 -1
- 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/streams.py +21 -96
- agentpool/vfs_registry.py +7 -2
- {agentpool-2.2.3.dist-info → agentpool-2.5.0.dist-info}/METADATA +16 -22
- {agentpool-2.2.3.dist-info → agentpool-2.5.0.dist-info}/RECORD +242 -195
- {agentpool-2.2.3.dist-info → agentpool-2.5.0.dist-info}/WHEEL +1 -1
- agentpool_cli/__main__.py +20 -0
- agentpool_cli/create.py +1 -1
- agentpool_cli/serve_acp.py +59 -1
- agentpool_cli/serve_opencode.py +1 -1
- agentpool_cli/ui.py +557 -0
- agentpool_commands/__init__.py +12 -5
- agentpool_commands/agents.py +1 -1
- 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/utils.py +31 -32
- agentpool_config/__init__.py +30 -2
- agentpool_config/agentpool_tools.py +498 -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 +1 -5
- agentpool_config/nodes.py +1 -1
- agentpool_config/observability.py +44 -0
- agentpool_config/session.py +0 -3
- agentpool_config/storage.py +38 -39
- agentpool_config/task.py +3 -3
- agentpool_config/tools.py +11 -28
- agentpool_config/toolsets.py +22 -90
- agentpool_server/a2a_server/agent_worker.py +307 -0
- agentpool_server/a2a_server/server.py +23 -18
- agentpool_server/acp_server/acp_agent.py +125 -56
- agentpool_server/acp_server/commands/acp_commands.py +46 -216
- agentpool_server/acp_server/commands/docs_commands/fetch_repo.py +8 -7
- agentpool_server/acp_server/event_converter.py +651 -0
- agentpool_server/acp_server/input_provider.py +53 -10
- agentpool_server/acp_server/server.py +1 -11
- agentpool_server/acp_server/session.py +90 -410
- 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/ENDPOINTS.md +53 -14
- agentpool_server/opencode_server/OPENCODE_UI_TOOLS_COMPLETE.md +202 -0
- agentpool_server/opencode_server/__init__.py +0 -8
- agentpool_server/opencode_server/converters.py +132 -26
- agentpool_server/opencode_server/input_provider.py +160 -8
- agentpool_server/opencode_server/models/__init__.py +42 -20
- agentpool_server/opencode_server/models/app.py +12 -0
- agentpool_server/opencode_server/models/events.py +203 -29
- agentpool_server/opencode_server/models/mcp.py +19 -0
- agentpool_server/opencode_server/models/message.py +18 -1
- agentpool_server/opencode_server/models/parts.py +134 -1
- agentpool_server/opencode_server/models/question.py +56 -0
- agentpool_server/opencode_server/models/session.py +13 -1
- agentpool_server/opencode_server/routes/__init__.py +4 -0
- agentpool_server/opencode_server/routes/agent_routes.py +33 -2
- agentpool_server/opencode_server/routes/app_routes.py +66 -3
- agentpool_server/opencode_server/routes/config_routes.py +66 -5
- agentpool_server/opencode_server/routes/file_routes.py +184 -5
- agentpool_server/opencode_server/routes/global_routes.py +1 -1
- agentpool_server/opencode_server/routes/lsp_routes.py +1 -1
- agentpool_server/opencode_server/routes/message_routes.py +122 -66
- agentpool_server/opencode_server/routes/permission_routes.py +63 -0
- agentpool_server/opencode_server/routes/pty_routes.py +23 -22
- agentpool_server/opencode_server/routes/question_routes.py +128 -0
- agentpool_server/opencode_server/routes/session_routes.py +139 -68
- agentpool_server/opencode_server/routes/tui_routes.py +1 -1
- agentpool_server/opencode_server/server.py +47 -2
- agentpool_server/opencode_server/state.py +30 -0
- agentpool_storage/__init__.py +0 -4
- agentpool_storage/base.py +81 -2
- agentpool_storage/claude_provider/ARCHITECTURE.md +433 -0
- agentpool_storage/claude_provider/__init__.py +42 -0
- agentpool_storage/{claude_provider.py → claude_provider/provider.py} +190 -8
- agentpool_storage/file_provider.py +149 -15
- agentpool_storage/memory_provider.py +132 -12
- 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/session_store.py +20 -6
- agentpool_storage/sql_provider/sql_provider.py +135 -2
- agentpool_storage/sql_provider/utils.py +2 -12
- 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 -4
- agentpool_toolsets/builtin/code.py +4 -4
- agentpool_toolsets/builtin/debug.py +115 -40
- agentpool_toolsets/builtin/execution_environment.py +54 -165
- agentpool_toolsets/builtin/skills.py +0 -77
- 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/grep.py +25 -5
- agentpool_toolsets/fsspec_toolset/helpers.py +3 -2
- agentpool_toolsets/fsspec_toolset/toolset.py +350 -66
- agentpool_toolsets/mcp_discovery/data/mcp_servers.parquet +0 -0
- agentpool_toolsets/mcp_discovery/toolset.py +74 -17
- agentpool_toolsets/mcp_run_toolset.py +8 -11
- agentpool_toolsets/notifications.py +33 -33
- agentpool_toolsets/openapi.py +3 -1
- agentpool_toolsets/search_toolset.py +3 -1
- 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/opencode_provider.py +0 -730
- agentpool_storage/text_log_provider.py +0 -276
- agentpool_toolsets/builtin/chain.py +0 -288
- agentpool_toolsets/builtin/user_interaction.py +0 -52
- agentpool_toolsets/semantic_memory_toolset.py +0 -536
- {agentpool-2.2.3.dist-info → agentpool-2.5.0.dist-info}/entry_points.txt +0 -0
- {agentpool-2.2.3.dist-info → agentpool-2.5.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -7,159 +7,20 @@ event types as native agents.
|
|
|
7
7
|
|
|
8
8
|
from __future__ import annotations
|
|
9
9
|
|
|
10
|
-
from dataclasses import dataclass, field
|
|
11
10
|
from typing import TYPE_CHECKING, Any, cast
|
|
12
11
|
|
|
13
12
|
from pydantic_ai import PartDeltaEvent, TextPartDelta, ThinkingPartDelta
|
|
14
13
|
|
|
15
|
-
from agentpool.agents.events import
|
|
16
|
-
DiffContentItem,
|
|
17
|
-
LocationContentItem,
|
|
18
|
-
ToolCallCompleteEvent,
|
|
19
|
-
ToolCallStartEvent,
|
|
20
|
-
)
|
|
14
|
+
from agentpool.agents.events import ToolCallCompleteEvent, ToolCallStartEvent
|
|
21
15
|
|
|
22
16
|
|
|
23
17
|
if TYPE_CHECKING:
|
|
24
18
|
from claude_agent_sdk import ContentBlock, McpServerConfig, Message, ToolUseBlock
|
|
25
19
|
|
|
26
|
-
from agentpool.agents.events import RichAgentStreamEvent
|
|
27
|
-
from agentpool.tools.base import ToolKind
|
|
20
|
+
from agentpool.agents.events import RichAgentStreamEvent
|
|
28
21
|
from agentpool_config.mcp_server import MCPServerConfig as NativeMCPServerConfig
|
|
29
22
|
|
|
30
23
|
|
|
31
|
-
@dataclass
|
|
32
|
-
class RichToolInfo:
|
|
33
|
-
"""Rich display information derived from tool name and input."""
|
|
34
|
-
|
|
35
|
-
title: str
|
|
36
|
-
"""Human-readable title for the tool call."""
|
|
37
|
-
kind: ToolKind = "other"
|
|
38
|
-
"""Category of tool operation."""
|
|
39
|
-
locations: list[LocationContentItem] = field(default_factory=list)
|
|
40
|
-
"""File locations involved in the operation."""
|
|
41
|
-
content: list[ToolCallContentItem] = field(default_factory=list)
|
|
42
|
-
"""Rich content items (diffs, text, etc.)."""
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
def derive_rich_tool_info(name: str, input_data: dict[str, Any]) -> RichToolInfo: # noqa: PLR0911, PLR0915
|
|
46
|
-
"""Derive rich display info from tool name and input arguments.
|
|
47
|
-
|
|
48
|
-
Maps MCP tool names and their inputs to human-readable titles, kinds,
|
|
49
|
-
and location information for rich UI display. Handles both Claude Code
|
|
50
|
-
built-in tools and MCP bridge tools.
|
|
51
|
-
|
|
52
|
-
Args:
|
|
53
|
-
name: The tool name (e.g., "Read", "mcp__server__read")
|
|
54
|
-
input_data: The tool input arguments
|
|
55
|
-
|
|
56
|
-
Returns:
|
|
57
|
-
RichToolInfo with derived display information
|
|
58
|
-
"""
|
|
59
|
-
# Extract the actual tool name if it's an MCP bridge tool
|
|
60
|
-
# Format: mcp__{server_name}__{tool_name}
|
|
61
|
-
actual_name = name
|
|
62
|
-
if name.startswith("mcp__") and "__" in name[5:]:
|
|
63
|
-
parts = name.split("__")
|
|
64
|
-
if len(parts) >= 3: # noqa: PLR2004
|
|
65
|
-
actual_name = parts[-1] # Get the last part (actual tool name)
|
|
66
|
-
|
|
67
|
-
# Normalize to lowercase for matching
|
|
68
|
-
tool_lower = actual_name.lower()
|
|
69
|
-
# Read operations
|
|
70
|
-
if tool_lower in ("read", "read_file"):
|
|
71
|
-
path = input_data.get("file_path") or input_data.get("path", "")
|
|
72
|
-
offset = input_data.get("offset") or input_data.get("line")
|
|
73
|
-
limit = input_data.get("limit")
|
|
74
|
-
|
|
75
|
-
suffix = ""
|
|
76
|
-
if limit:
|
|
77
|
-
start = (offset or 0) + 1
|
|
78
|
-
end = (offset or 0) + limit
|
|
79
|
-
suffix = f" ({start}-{end})"
|
|
80
|
-
elif offset:
|
|
81
|
-
suffix = f" (from line {offset + 1})"
|
|
82
|
-
title = f"Read {path}{suffix}" if path else "Read File"
|
|
83
|
-
locations = [LocationContentItem(path=path, line=offset or 0)] if path else []
|
|
84
|
-
return RichToolInfo(title=title, kind="read", locations=locations)
|
|
85
|
-
|
|
86
|
-
# Write operations
|
|
87
|
-
if tool_lower in ("write", "write_file"):
|
|
88
|
-
path = input_data.get("file_path") or input_data.get("path", "")
|
|
89
|
-
content = input_data.get("content", "")
|
|
90
|
-
return RichToolInfo(
|
|
91
|
-
title=f"Write {path}" if path else "Write File",
|
|
92
|
-
kind="edit",
|
|
93
|
-
locations=[LocationContentItem(path=path)] if path else [],
|
|
94
|
-
content=[DiffContentItem(path=path, old_text=None, new_text=content)] if path else [],
|
|
95
|
-
)
|
|
96
|
-
# Edit operations
|
|
97
|
-
if tool_lower in ("edit", "edit_file"):
|
|
98
|
-
path = input_data.get("file_path") or input_data.get("path", "")
|
|
99
|
-
old_string = input_data.get("old_string") or input_data.get("old_text", "")
|
|
100
|
-
new_string = input_data.get("new_string") or input_data.get("new_text", "")
|
|
101
|
-
return RichToolInfo(
|
|
102
|
-
title=f"Edit {path}" if path else "Edit File",
|
|
103
|
-
kind="edit",
|
|
104
|
-
locations=[LocationContentItem(path=path)] if path else [],
|
|
105
|
-
content=[DiffContentItem(path=path, old_text=old_string, new_text=new_string)]
|
|
106
|
-
if path
|
|
107
|
-
else [],
|
|
108
|
-
)
|
|
109
|
-
# Delete operations
|
|
110
|
-
if tool_lower in ("delete", "delete_path", "delete_file"):
|
|
111
|
-
path = input_data.get("file_path") or input_data.get("path", "")
|
|
112
|
-
locations = [LocationContentItem(path=path)] if path else []
|
|
113
|
-
title = f"Delete {path}" if path else "Delete"
|
|
114
|
-
return RichToolInfo(title=title, kind="delete", locations=locations)
|
|
115
|
-
# Bash/terminal operations
|
|
116
|
-
if tool_lower in ("bash", "execute", "run_command", "execute_command", "execute_code"):
|
|
117
|
-
command = input_data.get("command") or input_data.get("code", "")
|
|
118
|
-
# Escape backticks in command
|
|
119
|
-
escaped_cmd = command.replace("`", "\\`") if command else ""
|
|
120
|
-
title = f"`{escaped_cmd}`" if escaped_cmd else "Terminal"
|
|
121
|
-
return RichToolInfo(title=title, kind="execute")
|
|
122
|
-
# Search operations
|
|
123
|
-
if tool_lower in ("grep", "search", "glob", "find"):
|
|
124
|
-
pattern = input_data.get("pattern") or input_data.get("query", "")
|
|
125
|
-
path = input_data.get("path", "")
|
|
126
|
-
title = f"Search for '{pattern}'" if pattern else "Search"
|
|
127
|
-
if path:
|
|
128
|
-
title += f" in {path}"
|
|
129
|
-
locations = [LocationContentItem(path=path)] if path else []
|
|
130
|
-
return RichToolInfo(title=title, kind="search", locations=locations)
|
|
131
|
-
# List directory
|
|
132
|
-
if tool_lower in ("ls", "list", "list_directory"):
|
|
133
|
-
path = input_data.get("path", ".")
|
|
134
|
-
title = f"List {path}" if path != "." else "List current directory"
|
|
135
|
-
locations = [LocationContentItem(path=path)] if path else []
|
|
136
|
-
return RichToolInfo(title=title, kind="search", locations=locations)
|
|
137
|
-
# Web operations
|
|
138
|
-
if tool_lower in ("webfetch", "web_fetch", "fetch"):
|
|
139
|
-
url = input_data.get("url", "")
|
|
140
|
-
return RichToolInfo(title=f"Fetch {url}" if url else "Web Fetch", kind="fetch")
|
|
141
|
-
if tool_lower in ("websearch", "web_search", "search_web"):
|
|
142
|
-
query = input_data.get("query", "")
|
|
143
|
-
return RichToolInfo(title=f"Search: {query}" if query else "Web Search", kind="fetch")
|
|
144
|
-
# Task/subagent operations
|
|
145
|
-
if tool_lower == "task":
|
|
146
|
-
description = input_data.get("description", "")
|
|
147
|
-
return RichToolInfo(title=description if description else "Task", kind="think")
|
|
148
|
-
# Notebook operations
|
|
149
|
-
if tool_lower in ("notebookread", "notebook_read"):
|
|
150
|
-
path = input_data.get("notebook_path", "")
|
|
151
|
-
title = f"Read Notebook {path}" if path else "Read Notebook"
|
|
152
|
-
locations = [LocationContentItem(path=path)] if path else []
|
|
153
|
-
return RichToolInfo(title=title, kind="read", locations=locations)
|
|
154
|
-
if tool_lower in ("notebookedit", "notebook_edit"):
|
|
155
|
-
path = input_data.get("notebook_path", "")
|
|
156
|
-
title = f"Edit Notebook {path}" if path else "Edit Notebook"
|
|
157
|
-
locations = [LocationContentItem(path=path)] if path else []
|
|
158
|
-
return RichToolInfo(title=title, kind="edit", locations=locations)
|
|
159
|
-
# Default: use the tool name as title
|
|
160
|
-
return RichToolInfo(title=actual_name, kind="other")
|
|
161
|
-
|
|
162
|
-
|
|
163
24
|
def content_block_to_event(block: ContentBlock, index: int = 0) -> RichAgentStreamEvent[Any] | None:
|
|
164
25
|
"""Convert a Claude SDK ContentBlock to a streaming event.
|
|
165
26
|
|
|
@@ -172,6 +33,8 @@ def content_block_to_event(block: ContentBlock, index: int = 0) -> RichAgentStre
|
|
|
172
33
|
"""
|
|
173
34
|
from claude_agent_sdk import TextBlock, ThinkingBlock, ToolUseBlock
|
|
174
35
|
|
|
36
|
+
from agentpool.agents.events.infer_info import derive_rich_tool_info
|
|
37
|
+
|
|
175
38
|
match block:
|
|
176
39
|
case TextBlock(text=text):
|
|
177
40
|
return PartDeltaEvent(index=index, delta=TextPartDelta(content_delta=text))
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"""Pydantic models for Claude Code server info structures."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class ClaudeCodeBasemodel(BaseModel):
|
|
9
|
+
"""Base model."""
|
|
10
|
+
|
|
11
|
+
model_config = ConfigDict(populate_by_name=True)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class ClaudeCodeModelInfo(ClaudeCodeBasemodel):
|
|
15
|
+
"""Information about an available AI model from Claude Code."""
|
|
16
|
+
|
|
17
|
+
value: str
|
|
18
|
+
"""Model identifier used in API calls (e.g., "default", "opus", "haiku")."""
|
|
19
|
+
|
|
20
|
+
display_name: str = Field(..., alias="displayName")
|
|
21
|
+
"""Human-readable display name (e.g., "Opus", "Default (recommended)")."""
|
|
22
|
+
|
|
23
|
+
description: str
|
|
24
|
+
"""Full description including capabilities and pricing."""
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class ClaudeCodeCommandInfo(ClaudeCodeBasemodel):
|
|
28
|
+
"""Information about an available slash command from Claude Code."""
|
|
29
|
+
|
|
30
|
+
name: str
|
|
31
|
+
"""Command name without the / prefix (e.g., "compact", "review")."""
|
|
32
|
+
|
|
33
|
+
description: str
|
|
34
|
+
"""Full description of what the command does."""
|
|
35
|
+
|
|
36
|
+
argument_hint: str = Field(..., alias="argumentHint")
|
|
37
|
+
"""Usage hint for command arguments (may be empty string)."""
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class ClaudeCodeAccountInfo(ClaudeCodeBasemodel):
|
|
41
|
+
"""Account information from Claude Code."""
|
|
42
|
+
|
|
43
|
+
email: str | None = None
|
|
44
|
+
"""User email address."""
|
|
45
|
+
|
|
46
|
+
subscription_type: str | None = Field(default=None, alias="subscriptionType")
|
|
47
|
+
"""Subscription type (e.g., "Claude API")."""
|
|
48
|
+
|
|
49
|
+
token_source: str | None = Field(default=None, alias="tokenSource")
|
|
50
|
+
"""Where tokens come from (e.g., "claude.ai")."""
|
|
51
|
+
|
|
52
|
+
api_key_source: str | None = Field(default=None, alias="apiKeySource")
|
|
53
|
+
"""Where API key comes from (e.g., "ANTHROPIC_API_KEY")."""
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class ClaudeCodeServerInfo(ClaudeCodeBasemodel):
|
|
57
|
+
"""Complete server initialization info from Claude Code.
|
|
58
|
+
|
|
59
|
+
This is returned by the Claude Code server during initialization and contains
|
|
60
|
+
all available capabilities including models, commands, output styles, and
|
|
61
|
+
account information.
|
|
62
|
+
"""
|
|
63
|
+
|
|
64
|
+
models: list[ClaudeCodeModelInfo] = Field(default_factory=list)
|
|
65
|
+
"""List of available AI models."""
|
|
66
|
+
|
|
67
|
+
commands: list[ClaudeCodeCommandInfo] = Field(default_factory=list)
|
|
68
|
+
"""List of available slash commands."""
|
|
69
|
+
|
|
70
|
+
output_style: str = Field(default="default")
|
|
71
|
+
"""Current output style setting."""
|
|
72
|
+
|
|
73
|
+
available_output_styles: list[str] = Field(default_factory=list)
|
|
74
|
+
"""List of all available output styles."""
|
|
75
|
+
|
|
76
|
+
account: ClaudeCodeAccountInfo | None = Field(default=None)
|
|
77
|
+
"""Account and authentication information."""
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"""Static model information."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
6
|
+
|
|
7
|
+
from tokonomics.model_discovery.model_info import ModelInfo, ModelPricing
|
|
8
|
+
|
|
9
|
+
from agentpool.agents.modes import ModeInfo
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from claude_agent_sdk import PermissionMode
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
VALID_MODES: set[PermissionMode] = {
|
|
17
|
+
"default",
|
|
18
|
+
"acceptEdits",
|
|
19
|
+
"plan",
|
|
20
|
+
"bypassPermissions",
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
# Static Claude Code models - these are the simple IDs the SDK accepts
|
|
24
|
+
# Use id_override to ensure pydantic_ai_id returns simple names like "opus"
|
|
25
|
+
|
|
26
|
+
OPUS = ModelInfo(
|
|
27
|
+
id="claude-opus-4-5",
|
|
28
|
+
name="Claude Opus",
|
|
29
|
+
provider="anthropic",
|
|
30
|
+
description="Claude Opus - most capable model",
|
|
31
|
+
context_window=200000,
|
|
32
|
+
max_output_tokens=32000,
|
|
33
|
+
input_modalities={"text", "image"},
|
|
34
|
+
output_modalities={"text"},
|
|
35
|
+
pricing=ModelPricing(
|
|
36
|
+
prompt=0.000005, # $5 per 1M tokens
|
|
37
|
+
completion=0.000025, # $25 per 1M tokens
|
|
38
|
+
),
|
|
39
|
+
id_override="opus", # Claude Code SDK uses simple names
|
|
40
|
+
)
|
|
41
|
+
SONNET = ModelInfo(
|
|
42
|
+
id="claude-sonnet-4-5",
|
|
43
|
+
name="Claude Sonnet",
|
|
44
|
+
provider="anthropic",
|
|
45
|
+
description="Claude Sonnet - balanced performance and speed",
|
|
46
|
+
context_window=200000,
|
|
47
|
+
max_output_tokens=16000,
|
|
48
|
+
input_modalities={"text", "image"},
|
|
49
|
+
output_modalities={"text"},
|
|
50
|
+
pricing=ModelPricing(
|
|
51
|
+
prompt=0.000003, # $3 per 1M tokens
|
|
52
|
+
completion=0.000015, # $15 per 1M tokens
|
|
53
|
+
),
|
|
54
|
+
id_override="sonnet", # Claude Code SDK uses simple names
|
|
55
|
+
)
|
|
56
|
+
HAIKU = ModelInfo(
|
|
57
|
+
id="claude-haiku-4-5",
|
|
58
|
+
name="Claude Haiku",
|
|
59
|
+
provider="anthropic",
|
|
60
|
+
description="Claude Haiku - fast and cost-effective",
|
|
61
|
+
context_window=200000,
|
|
62
|
+
max_output_tokens=8000,
|
|
63
|
+
input_modalities={"text", "image"},
|
|
64
|
+
output_modalities={"text"},
|
|
65
|
+
pricing=ModelPricing(
|
|
66
|
+
prompt=0.000001, # $1.00 per 1M tokens
|
|
67
|
+
completion=0.000005, # $5 per 1M tokens
|
|
68
|
+
),
|
|
69
|
+
id_override="haiku", # Claude Code SDK uses simple names
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
MODELS = [OPUS, SONNET, HAIKU]
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
MODES = [
|
|
76
|
+
ModeInfo(
|
|
77
|
+
id="default",
|
|
78
|
+
name="Default",
|
|
79
|
+
description="Require confirmation for tool usage",
|
|
80
|
+
category_id="permissions",
|
|
81
|
+
),
|
|
82
|
+
ModeInfo(
|
|
83
|
+
id="acceptEdits",
|
|
84
|
+
name="Accept Edits",
|
|
85
|
+
description="Auto-approve file edits without confirmation",
|
|
86
|
+
category_id="permissions",
|
|
87
|
+
),
|
|
88
|
+
ModeInfo(
|
|
89
|
+
id="plan",
|
|
90
|
+
name="Plan",
|
|
91
|
+
description="Planning mode - no tool execution",
|
|
92
|
+
category_id="permissions",
|
|
93
|
+
),
|
|
94
|
+
ModeInfo(
|
|
95
|
+
id="bypassPermissions",
|
|
96
|
+
name="Bypass Permissions",
|
|
97
|
+
description="Skip all permission checks (use with caution)",
|
|
98
|
+
category_id="permissions",
|
|
99
|
+
),
|
|
100
|
+
]
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
"""Claude Code usage limits helper.
|
|
2
|
+
|
|
3
|
+
Fetches usage information from Anthropic's OAuth API using stored credentials.
|
|
4
|
+
Works on both Linux and macOS.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from datetime import datetime
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
import subprocess
|
|
12
|
+
import sys
|
|
13
|
+
|
|
14
|
+
import anyenv
|
|
15
|
+
import httpx
|
|
16
|
+
from pydantic import BaseModel
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class UsageLimit(BaseModel):
|
|
20
|
+
"""A single usage limit with utilization percentage and reset time."""
|
|
21
|
+
|
|
22
|
+
utilization: float
|
|
23
|
+
"""Utilization percentage (0-100)."""
|
|
24
|
+
|
|
25
|
+
resets_at: datetime | None = None
|
|
26
|
+
"""When this limit resets, or None if not set."""
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class ExtraUsage(BaseModel):
|
|
30
|
+
"""Extra usage information for paid plans."""
|
|
31
|
+
|
|
32
|
+
is_enabled: bool = False
|
|
33
|
+
monthly_limit: float | None = None
|
|
34
|
+
used_credits: float | None = None
|
|
35
|
+
utilization: float | None = None
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class ClaudeCodeUsage(BaseModel):
|
|
39
|
+
"""Claude Code usage limits."""
|
|
40
|
+
|
|
41
|
+
five_hour: UsageLimit | None = None
|
|
42
|
+
"""5-hour rolling usage limit."""
|
|
43
|
+
|
|
44
|
+
seven_day: UsageLimit | None = None
|
|
45
|
+
"""7-day rolling usage limit."""
|
|
46
|
+
|
|
47
|
+
seven_day_opus: UsageLimit | None = None
|
|
48
|
+
"""7-day Opus-specific limit."""
|
|
49
|
+
|
|
50
|
+
seven_day_sonnet: UsageLimit | None = None
|
|
51
|
+
"""7-day Sonnet-specific limit."""
|
|
52
|
+
|
|
53
|
+
seven_day_oauth_apps: UsageLimit | None = None
|
|
54
|
+
"""7-day OAuth apps limit."""
|
|
55
|
+
|
|
56
|
+
extra_usage: ExtraUsage | None = None
|
|
57
|
+
"""Extra usage info for paid plans."""
|
|
58
|
+
|
|
59
|
+
def format_table(self) -> str:
|
|
60
|
+
"""Format usage as a readable table."""
|
|
61
|
+
lines = ["Claude Code Usage Limits", "=" * 50]
|
|
62
|
+
|
|
63
|
+
def format_limit(name: str, limit: UsageLimit | None) -> str | None:
|
|
64
|
+
if limit is None:
|
|
65
|
+
return None
|
|
66
|
+
reset_str = ""
|
|
67
|
+
if limit.resets_at:
|
|
68
|
+
reset_str = f" (resets {limit.resets_at.strftime('%Y-%m-%d %H:%M UTC')})"
|
|
69
|
+
return f"{name}: {limit.utilization:.0f}%{reset_str}"
|
|
70
|
+
|
|
71
|
+
for name, limit in [
|
|
72
|
+
("5-hour", self.five_hour),
|
|
73
|
+
("7-day", self.seven_day),
|
|
74
|
+
("7-day Opus", self.seven_day_opus),
|
|
75
|
+
("7-day Sonnet", self.seven_day_sonnet),
|
|
76
|
+
("7-day OAuth Apps", self.seven_day_oauth_apps),
|
|
77
|
+
]:
|
|
78
|
+
formatted = format_limit(name, limit)
|
|
79
|
+
if formatted:
|
|
80
|
+
lines.append(formatted)
|
|
81
|
+
|
|
82
|
+
if self.extra_usage and self.extra_usage.is_enabled:
|
|
83
|
+
lines.append("")
|
|
84
|
+
lines.append("Extra Usage (paid):")
|
|
85
|
+
if self.extra_usage.utilization is not None:
|
|
86
|
+
lines.append(f" Utilization: {self.extra_usage.utilization:.0f}%")
|
|
87
|
+
if self.extra_usage.used_credits is not None:
|
|
88
|
+
lines.append(f" Used credits: {self.extra_usage.used_credits}")
|
|
89
|
+
if self.extra_usage.monthly_limit is not None:
|
|
90
|
+
lines.append(f" Monthly limit: {self.extra_usage.monthly_limit}")
|
|
91
|
+
|
|
92
|
+
return "\n".join(lines)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def _get_credentials_path() -> Path | None:
|
|
96
|
+
"""Get the path to Claude Code credentials file.
|
|
97
|
+
|
|
98
|
+
Returns:
|
|
99
|
+
Path to credentials file, or None if not found.
|
|
100
|
+
"""
|
|
101
|
+
# Linux: ~/.claude/.credentials.json
|
|
102
|
+
linux_path = Path.home() / ".claude" / ".credentials.json"
|
|
103
|
+
if linux_path.exists():
|
|
104
|
+
return linux_path
|
|
105
|
+
|
|
106
|
+
# macOS: Also check ~/.claude first (newer versions)
|
|
107
|
+
if linux_path.exists():
|
|
108
|
+
return linux_path
|
|
109
|
+
|
|
110
|
+
return None
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def _get_access_token_from_file(path: Path) -> str | None:
|
|
114
|
+
"""Read access token from credentials file."""
|
|
115
|
+
try:
|
|
116
|
+
data = anyenv.load_json(path.read_text(), return_type=dict)
|
|
117
|
+
val = data.get("claudeAiOauth", {}).get("accessToken")
|
|
118
|
+
except (anyenv.JsonLoadError, OSError):
|
|
119
|
+
return None
|
|
120
|
+
else:
|
|
121
|
+
assert isinstance(val, str)
|
|
122
|
+
return val
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def _get_access_token_from_keychain() -> str | None:
|
|
126
|
+
"""Read access token from macOS Keychain."""
|
|
127
|
+
if sys.platform != "darwin":
|
|
128
|
+
return None
|
|
129
|
+
|
|
130
|
+
try:
|
|
131
|
+
result = subprocess.run(
|
|
132
|
+
["security", "find-generic-password", "-s", "Claude Code-credentials", "-w"],
|
|
133
|
+
capture_output=True,
|
|
134
|
+
text=True,
|
|
135
|
+
check=True,
|
|
136
|
+
)
|
|
137
|
+
data = anyenv.load_json(result.stdout.strip(), return_type=dict)
|
|
138
|
+
val = data.get("claudeAiOauth", {}).get("accessToken")
|
|
139
|
+
except (subprocess.CalledProcessError, anyenv.JsonLoadError, FileNotFoundError):
|
|
140
|
+
return None
|
|
141
|
+
else:
|
|
142
|
+
assert isinstance(val, str)
|
|
143
|
+
return val
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def get_access_token() -> str | None:
|
|
147
|
+
"""Get Claude Code OAuth access token.
|
|
148
|
+
|
|
149
|
+
Checks both file-based storage (Linux/newer macOS) and Keychain (macOS).
|
|
150
|
+
|
|
151
|
+
Returns:
|
|
152
|
+
Access token string, or None if not found.
|
|
153
|
+
"""
|
|
154
|
+
# Try file-based first (works on Linux and newer macOS)
|
|
155
|
+
creds_path = _get_credentials_path()
|
|
156
|
+
if creds_path:
|
|
157
|
+
token = _get_access_token_from_file(creds_path)
|
|
158
|
+
if token:
|
|
159
|
+
return token
|
|
160
|
+
# Fall back to macOS Keychain
|
|
161
|
+
return _get_access_token_from_keychain()
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
async def get_usage_async(token: str | None = None) -> ClaudeCodeUsage:
|
|
165
|
+
"""Fetch Claude Code usage limits asynchronously.
|
|
166
|
+
|
|
167
|
+
Args:
|
|
168
|
+
token: OAuth access token. If not provided, will attempt to read from
|
|
169
|
+
stored credentials.
|
|
170
|
+
|
|
171
|
+
Returns:
|
|
172
|
+
ClaudeCodeUsage with current limits.
|
|
173
|
+
|
|
174
|
+
Raises:
|
|
175
|
+
ValueError: If no token provided and credentials not found.
|
|
176
|
+
httpx.HTTPStatusError: If API request fails.
|
|
177
|
+
"""
|
|
178
|
+
if token is None:
|
|
179
|
+
token = get_access_token()
|
|
180
|
+
if token is None:
|
|
181
|
+
msg = "No Claude Code credentials found. Please authenticate with Claude Code first."
|
|
182
|
+
raise ValueError(msg)
|
|
183
|
+
|
|
184
|
+
async with httpx.AsyncClient() as client:
|
|
185
|
+
response = await client.get(
|
|
186
|
+
"https://api.anthropic.com/api/oauth/usage",
|
|
187
|
+
headers={
|
|
188
|
+
"Accept": "application/json",
|
|
189
|
+
"Content-Type": "application/json",
|
|
190
|
+
"User-Agent": "claude-code/2.0.32",
|
|
191
|
+
"Authorization": f"Bearer {token}",
|
|
192
|
+
"anthropic-beta": "oauth-2025-04-20",
|
|
193
|
+
},
|
|
194
|
+
)
|
|
195
|
+
response.raise_for_status()
|
|
196
|
+
return ClaudeCodeUsage.model_validate(response.json())
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def get_usage(token: str | None = None) -> ClaudeCodeUsage:
|
|
200
|
+
"""Fetch Claude Code usage limits synchronously.
|
|
201
|
+
|
|
202
|
+
Args:
|
|
203
|
+
token: OAuth access token. If not provided, will attempt to read from
|
|
204
|
+
stored credentials.
|
|
205
|
+
|
|
206
|
+
Returns:
|
|
207
|
+
ClaudeCodeUsage with current limits.
|
|
208
|
+
|
|
209
|
+
Raises:
|
|
210
|
+
ValueError: If no token provided and credentials not found.
|
|
211
|
+
httpx.HTTPStatusError: If API request fails.
|
|
212
|
+
"""
|
|
213
|
+
if token is None:
|
|
214
|
+
token = get_access_token()
|
|
215
|
+
if token is None:
|
|
216
|
+
msg = "No Claude Code credentials found. Please authenticate with Claude Code first."
|
|
217
|
+
raise ValueError(msg)
|
|
218
|
+
|
|
219
|
+
with httpx.Client() as client:
|
|
220
|
+
response = client.get(
|
|
221
|
+
"https://api.anthropic.com/api/oauth/usage",
|
|
222
|
+
headers={
|
|
223
|
+
"Accept": "application/json",
|
|
224
|
+
"Content-Type": "application/json",
|
|
225
|
+
"User-Agent": "claude-code/2.0.32",
|
|
226
|
+
"Authorization": f"Bearer {token}",
|
|
227
|
+
"anthropic-beta": "oauth-2025-04-20",
|
|
228
|
+
},
|
|
229
|
+
)
|
|
230
|
+
response.raise_for_status()
|
|
231
|
+
return ClaudeCodeUsage.model_validate(response.json())
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
if __name__ == "__main__":
|
|
235
|
+
# Quick test
|
|
236
|
+
try:
|
|
237
|
+
usage = get_usage()
|
|
238
|
+
print(usage.format_table())
|
|
239
|
+
except ValueError as e:
|
|
240
|
+
print(f"Error: {e}")
|
|
241
|
+
except httpx.HTTPStatusError as e:
|
|
242
|
+
print(f"API Error: {e.response.status_code} - {e.response.text}")
|
|
@@ -9,17 +9,21 @@ from .events import (
|
|
|
9
9
|
FileContentItem,
|
|
10
10
|
LocationContentItem,
|
|
11
11
|
PlanUpdateEvent,
|
|
12
|
+
PartStartEvent,
|
|
13
|
+
PartDeltaEvent,
|
|
12
14
|
RichAgentStreamEvent,
|
|
13
15
|
RunErrorEvent,
|
|
14
16
|
RunStartedEvent,
|
|
15
17
|
SlashedAgentStreamEvent,
|
|
16
18
|
StreamCompleteEvent,
|
|
19
|
+
SubAgentEvent,
|
|
17
20
|
TerminalContentItem,
|
|
18
21
|
TextContentItem,
|
|
19
22
|
ToolCallCompleteEvent,
|
|
20
23
|
ToolCallContentItem,
|
|
21
24
|
ToolCallProgressEvent,
|
|
22
25
|
ToolCallStartEvent,
|
|
26
|
+
ToolResultMetadataEvent,
|
|
23
27
|
)
|
|
24
28
|
from .event_emitter import StreamEventEmitter
|
|
25
29
|
from .builtin_handlers import (
|
|
@@ -32,6 +36,14 @@ from .tts_handlers import (
|
|
|
32
36
|
EdgeTTSEventHandler,
|
|
33
37
|
OpenAITTSEventHandler,
|
|
34
38
|
)
|
|
39
|
+
from .processors import (
|
|
40
|
+
FileTracker,
|
|
41
|
+
FileTrackingProcessor,
|
|
42
|
+
StreamPipeline,
|
|
43
|
+
StreamProcessor,
|
|
44
|
+
event_handler_processor,
|
|
45
|
+
extract_file_path_from_tool_call,
|
|
46
|
+
)
|
|
35
47
|
|
|
36
48
|
__all__ = [
|
|
37
49
|
"BaseTTSEventHandler",
|
|
@@ -42,8 +54,12 @@ __all__ = [
|
|
|
42
54
|
"DiffContentItem",
|
|
43
55
|
"EdgeTTSEventHandler",
|
|
44
56
|
"FileContentItem",
|
|
57
|
+
"FileTracker",
|
|
58
|
+
"FileTrackingProcessor",
|
|
45
59
|
"LocationContentItem",
|
|
46
60
|
"OpenAITTSEventHandler",
|
|
61
|
+
"PartDeltaEvent",
|
|
62
|
+
"PartStartEvent",
|
|
47
63
|
"PlanUpdateEvent",
|
|
48
64
|
"RichAgentStreamEvent",
|
|
49
65
|
"RunErrorEvent",
|
|
@@ -51,13 +67,19 @@ __all__ = [
|
|
|
51
67
|
"SlashedAgentStreamEvent",
|
|
52
68
|
"StreamCompleteEvent",
|
|
53
69
|
"StreamEventEmitter",
|
|
70
|
+
"StreamPipeline",
|
|
71
|
+
"StreamProcessor",
|
|
72
|
+
"SubAgentEvent",
|
|
54
73
|
"TerminalContentItem",
|
|
55
74
|
"TextContentItem",
|
|
56
75
|
"ToolCallCompleteEvent",
|
|
57
76
|
"ToolCallContentItem",
|
|
58
77
|
"ToolCallProgressEvent",
|
|
59
78
|
"ToolCallStartEvent",
|
|
79
|
+
"ToolResultMetadataEvent",
|
|
60
80
|
"detailed_print_handler",
|
|
81
|
+
"event_handler_processor",
|
|
82
|
+
"extract_file_path_from_tool_call",
|
|
61
83
|
"resolve_event_handlers",
|
|
62
84
|
"simple_print_handler",
|
|
63
85
|
]
|