agentpool 2.1.9__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.
Potentially problematic release.
This version of agentpool might be problematic. Click here for more details.
- acp/README.md +64 -0
- acp/__init__.py +172 -0
- acp/__main__.py +10 -0
- acp/acp_requests.py +285 -0
- acp/agent/__init__.py +6 -0
- acp/agent/connection.py +256 -0
- acp/agent/implementations/__init__.py +6 -0
- acp/agent/implementations/debug_server/__init__.py +1 -0
- acp/agent/implementations/debug_server/cli.py +79 -0
- acp/agent/implementations/debug_server/debug.html +234 -0
- acp/agent/implementations/debug_server/debug_server.py +496 -0
- acp/agent/implementations/testing.py +91 -0
- acp/agent/protocol.py +65 -0
- acp/bridge/README.md +162 -0
- acp/bridge/__init__.py +6 -0
- acp/bridge/__main__.py +91 -0
- acp/bridge/bridge.py +246 -0
- acp/bridge/py.typed +0 -0
- acp/bridge/settings.py +15 -0
- acp/client/__init__.py +7 -0
- acp/client/connection.py +251 -0
- acp/client/implementations/__init__.py +7 -0
- acp/client/implementations/default_client.py +185 -0
- acp/client/implementations/headless_client.py +266 -0
- acp/client/implementations/noop_client.py +110 -0
- acp/client/protocol.py +61 -0
- acp/connection.py +280 -0
- acp/exceptions.py +46 -0
- acp/filesystem.py +524 -0
- acp/notifications.py +832 -0
- acp/py.typed +0 -0
- acp/schema/__init__.py +265 -0
- acp/schema/agent_plan.py +30 -0
- acp/schema/agent_requests.py +126 -0
- acp/schema/agent_responses.py +256 -0
- acp/schema/base.py +39 -0
- acp/schema/capabilities.py +230 -0
- acp/schema/client_requests.py +247 -0
- acp/schema/client_responses.py +96 -0
- acp/schema/common.py +81 -0
- acp/schema/content_blocks.py +188 -0
- acp/schema/mcp.py +82 -0
- acp/schema/messages.py +171 -0
- acp/schema/notifications.py +82 -0
- acp/schema/protocol_stuff.md +3 -0
- acp/schema/session_state.py +160 -0
- acp/schema/session_updates.py +419 -0
- acp/schema/slash_commands.py +51 -0
- acp/schema/terminal.py +15 -0
- acp/schema/tool_call.py +347 -0
- acp/stdio.py +250 -0
- acp/task/__init__.py +53 -0
- acp/task/debug.py +197 -0
- acp/task/dispatcher.py +93 -0
- acp/task/queue.py +69 -0
- acp/task/sender.py +82 -0
- acp/task/state.py +87 -0
- acp/task/supervisor.py +93 -0
- acp/terminal_handle.py +30 -0
- acp/tool_call_reporter.py +199 -0
- acp/tool_call_state.py +178 -0
- acp/transports.py +104 -0
- acp/utils.py +240 -0
- agentpool/__init__.py +63 -0
- agentpool/__main__.py +7 -0
- agentpool/agents/__init__.py +30 -0
- agentpool/agents/acp_agent/__init__.py +5 -0
- agentpool/agents/acp_agent/acp_agent.py +837 -0
- agentpool/agents/acp_agent/acp_converters.py +294 -0
- agentpool/agents/acp_agent/client_handler.py +317 -0
- agentpool/agents/acp_agent/session_state.py +44 -0
- agentpool/agents/agent.py +1264 -0
- agentpool/agents/agui_agent/__init__.py +19 -0
- agentpool/agents/agui_agent/agui_agent.py +677 -0
- agentpool/agents/agui_agent/agui_converters.py +423 -0
- agentpool/agents/agui_agent/chunk_transformer.py +204 -0
- agentpool/agents/agui_agent/event_types.py +83 -0
- agentpool/agents/agui_agent/helpers.py +192 -0
- agentpool/agents/architect.py +71 -0
- agentpool/agents/base_agent.py +177 -0
- agentpool/agents/claude_code_agent/__init__.py +11 -0
- agentpool/agents/claude_code_agent/claude_code_agent.py +1021 -0
- agentpool/agents/claude_code_agent/converters.py +243 -0
- agentpool/agents/context.py +105 -0
- agentpool/agents/events/__init__.py +61 -0
- agentpool/agents/events/builtin_handlers.py +129 -0
- agentpool/agents/events/event_emitter.py +320 -0
- agentpool/agents/events/events.py +561 -0
- agentpool/agents/events/tts_handlers.py +186 -0
- agentpool/agents/interactions.py +419 -0
- agentpool/agents/slashed_agent.py +244 -0
- agentpool/agents/sys_prompts.py +178 -0
- agentpool/agents/tool_wrapping.py +184 -0
- agentpool/base_provider.py +28 -0
- agentpool/common_types.py +226 -0
- agentpool/config_resources/__init__.py +16 -0
- agentpool/config_resources/acp_assistant.yml +24 -0
- agentpool/config_resources/agents.yml +109 -0
- agentpool/config_resources/agents_template.yml +18 -0
- agentpool/config_resources/agui_test.yml +18 -0
- agentpool/config_resources/claude_code_agent.yml +16 -0
- agentpool/config_resources/claude_style_subagent.md +30 -0
- agentpool/config_resources/external_acp_agents.yml +77 -0
- agentpool/config_resources/opencode_style_subagent.md +19 -0
- agentpool/config_resources/tts_test_agents.yml +78 -0
- agentpool/delegation/__init__.py +8 -0
- agentpool/delegation/base_team.py +504 -0
- agentpool/delegation/message_flow_tracker.py +39 -0
- agentpool/delegation/pool.py +1129 -0
- agentpool/delegation/team.py +325 -0
- agentpool/delegation/teamrun.py +343 -0
- agentpool/docs/__init__.py +5 -0
- agentpool/docs/gen_examples.py +42 -0
- agentpool/docs/utils.py +370 -0
- agentpool/functional/__init__.py +20 -0
- agentpool/functional/py.typed +0 -0
- agentpool/functional/run.py +80 -0
- agentpool/functional/structure.py +136 -0
- agentpool/hooks/__init__.py +20 -0
- agentpool/hooks/agent_hooks.py +247 -0
- agentpool/hooks/base.py +119 -0
- agentpool/hooks/callable.py +140 -0
- agentpool/hooks/command.py +180 -0
- agentpool/hooks/prompt.py +122 -0
- agentpool/jinja_filters.py +132 -0
- agentpool/log.py +224 -0
- agentpool/mcp_server/__init__.py +17 -0
- agentpool/mcp_server/client.py +429 -0
- agentpool/mcp_server/constants.py +32 -0
- agentpool/mcp_server/conversions.py +172 -0
- agentpool/mcp_server/helpers.py +47 -0
- agentpool/mcp_server/manager.py +232 -0
- agentpool/mcp_server/message_handler.py +164 -0
- agentpool/mcp_server/registries/__init__.py +1 -0
- agentpool/mcp_server/registries/official_registry_client.py +345 -0
- agentpool/mcp_server/registries/pulsemcp_client.py +88 -0
- agentpool/mcp_server/tool_bridge.py +548 -0
- agentpool/messaging/__init__.py +58 -0
- agentpool/messaging/compaction.py +928 -0
- agentpool/messaging/connection_manager.py +319 -0
- agentpool/messaging/context.py +66 -0
- agentpool/messaging/event_manager.py +426 -0
- agentpool/messaging/events.py +39 -0
- agentpool/messaging/message_container.py +209 -0
- agentpool/messaging/message_history.py +491 -0
- agentpool/messaging/messagenode.py +377 -0
- agentpool/messaging/messages.py +655 -0
- agentpool/messaging/processing.py +76 -0
- agentpool/mime_utils.py +95 -0
- agentpool/models/__init__.py +21 -0
- agentpool/models/acp_agents/__init__.py +22 -0
- agentpool/models/acp_agents/base.py +308 -0
- agentpool/models/acp_agents/mcp_capable.py +790 -0
- agentpool/models/acp_agents/non_mcp.py +842 -0
- agentpool/models/agents.py +450 -0
- agentpool/models/agui_agents.py +89 -0
- agentpool/models/claude_code_agents.py +238 -0
- agentpool/models/file_agents.py +116 -0
- agentpool/models/file_parsing.py +367 -0
- agentpool/models/manifest.py +658 -0
- agentpool/observability/__init__.py +9 -0
- agentpool/observability/observability_registry.py +97 -0
- agentpool/prompts/__init__.py +1 -0
- agentpool/prompts/base.py +27 -0
- agentpool/prompts/builtin_provider.py +75 -0
- agentpool/prompts/conversion_manager.py +95 -0
- agentpool/prompts/convert.py +96 -0
- agentpool/prompts/manager.py +204 -0
- agentpool/prompts/parts/zed.md +33 -0
- agentpool/prompts/prompts.py +581 -0
- agentpool/py.typed +0 -0
- agentpool/queries/tree-sitter-language-pack/README.md +7 -0
- agentpool/queries/tree-sitter-language-pack/arduino-tags.scm +5 -0
- agentpool/queries/tree-sitter-language-pack/c-tags.scm +9 -0
- agentpool/queries/tree-sitter-language-pack/chatito-tags.scm +16 -0
- agentpool/queries/tree-sitter-language-pack/clojure-tags.scm +7 -0
- agentpool/queries/tree-sitter-language-pack/commonlisp-tags.scm +122 -0
- agentpool/queries/tree-sitter-language-pack/cpp-tags.scm +15 -0
- agentpool/queries/tree-sitter-language-pack/csharp-tags.scm +26 -0
- agentpool/queries/tree-sitter-language-pack/d-tags.scm +26 -0
- agentpool/queries/tree-sitter-language-pack/dart-tags.scm +92 -0
- agentpool/queries/tree-sitter-language-pack/elisp-tags.scm +5 -0
- agentpool/queries/tree-sitter-language-pack/elixir-tags.scm +54 -0
- agentpool/queries/tree-sitter-language-pack/elm-tags.scm +19 -0
- agentpool/queries/tree-sitter-language-pack/gleam-tags.scm +41 -0
- agentpool/queries/tree-sitter-language-pack/go-tags.scm +42 -0
- agentpool/queries/tree-sitter-language-pack/java-tags.scm +20 -0
- agentpool/queries/tree-sitter-language-pack/javascript-tags.scm +88 -0
- agentpool/queries/tree-sitter-language-pack/lua-tags.scm +34 -0
- agentpool/queries/tree-sitter-language-pack/matlab-tags.scm +10 -0
- agentpool/queries/tree-sitter-language-pack/ocaml-tags.scm +115 -0
- agentpool/queries/tree-sitter-language-pack/ocaml_interface-tags.scm +98 -0
- agentpool/queries/tree-sitter-language-pack/pony-tags.scm +39 -0
- agentpool/queries/tree-sitter-language-pack/properties-tags.scm +5 -0
- agentpool/queries/tree-sitter-language-pack/python-tags.scm +14 -0
- agentpool/queries/tree-sitter-language-pack/r-tags.scm +21 -0
- agentpool/queries/tree-sitter-language-pack/racket-tags.scm +12 -0
- agentpool/queries/tree-sitter-language-pack/ruby-tags.scm +64 -0
- agentpool/queries/tree-sitter-language-pack/rust-tags.scm +60 -0
- agentpool/queries/tree-sitter-language-pack/solidity-tags.scm +43 -0
- agentpool/queries/tree-sitter-language-pack/swift-tags.scm +51 -0
- agentpool/queries/tree-sitter-language-pack/udev-tags.scm +20 -0
- agentpool/queries/tree-sitter-languages/README.md +24 -0
- agentpool/queries/tree-sitter-languages/c-tags.scm +9 -0
- agentpool/queries/tree-sitter-languages/c_sharp-tags.scm +46 -0
- agentpool/queries/tree-sitter-languages/cpp-tags.scm +15 -0
- agentpool/queries/tree-sitter-languages/dart-tags.scm +91 -0
- agentpool/queries/tree-sitter-languages/elisp-tags.scm +8 -0
- agentpool/queries/tree-sitter-languages/elixir-tags.scm +54 -0
- agentpool/queries/tree-sitter-languages/elm-tags.scm +19 -0
- agentpool/queries/tree-sitter-languages/fortran-tags.scm +15 -0
- agentpool/queries/tree-sitter-languages/go-tags.scm +30 -0
- agentpool/queries/tree-sitter-languages/haskell-tags.scm +3 -0
- agentpool/queries/tree-sitter-languages/hcl-tags.scm +77 -0
- agentpool/queries/tree-sitter-languages/java-tags.scm +20 -0
- agentpool/queries/tree-sitter-languages/javascript-tags.scm +88 -0
- agentpool/queries/tree-sitter-languages/julia-tags.scm +60 -0
- agentpool/queries/tree-sitter-languages/kotlin-tags.scm +27 -0
- agentpool/queries/tree-sitter-languages/matlab-tags.scm +10 -0
- agentpool/queries/tree-sitter-languages/ocaml-tags.scm +115 -0
- agentpool/queries/tree-sitter-languages/ocaml_interface-tags.scm +98 -0
- agentpool/queries/tree-sitter-languages/php-tags.scm +26 -0
- agentpool/queries/tree-sitter-languages/python-tags.scm +12 -0
- agentpool/queries/tree-sitter-languages/ql-tags.scm +26 -0
- agentpool/queries/tree-sitter-languages/ruby-tags.scm +64 -0
- agentpool/queries/tree-sitter-languages/rust-tags.scm +60 -0
- agentpool/queries/tree-sitter-languages/scala-tags.scm +65 -0
- agentpool/queries/tree-sitter-languages/typescript-tags.scm +41 -0
- agentpool/queries/tree-sitter-languages/zig-tags.scm +3 -0
- agentpool/repomap.py +1231 -0
- agentpool/resource_providers/__init__.py +17 -0
- agentpool/resource_providers/aggregating.py +54 -0
- agentpool/resource_providers/base.py +172 -0
- agentpool/resource_providers/codemode/__init__.py +9 -0
- agentpool/resource_providers/codemode/code_executor.py +215 -0
- agentpool/resource_providers/codemode/default_prompt.py +19 -0
- agentpool/resource_providers/codemode/helpers.py +83 -0
- agentpool/resource_providers/codemode/progress_executor.py +212 -0
- agentpool/resource_providers/codemode/provider.py +150 -0
- agentpool/resource_providers/codemode/remote_mcp_execution.py +143 -0
- agentpool/resource_providers/codemode/remote_provider.py +171 -0
- agentpool/resource_providers/filtering.py +42 -0
- agentpool/resource_providers/mcp_provider.py +246 -0
- agentpool/resource_providers/plan_provider.py +196 -0
- agentpool/resource_providers/pool.py +69 -0
- agentpool/resource_providers/static.py +289 -0
- agentpool/running/__init__.py +20 -0
- agentpool/running/decorators.py +56 -0
- agentpool/running/discovery.py +101 -0
- agentpool/running/executor.py +284 -0
- agentpool/running/injection.py +111 -0
- agentpool/running/py.typed +0 -0
- agentpool/running/run_nodes.py +87 -0
- agentpool/server.py +122 -0
- agentpool/sessions/__init__.py +13 -0
- agentpool/sessions/manager.py +302 -0
- agentpool/sessions/models.py +71 -0
- agentpool/sessions/session.py +239 -0
- agentpool/sessions/store.py +163 -0
- agentpool/skills/__init__.py +5 -0
- agentpool/skills/manager.py +120 -0
- agentpool/skills/registry.py +210 -0
- agentpool/skills/skill.py +36 -0
- agentpool/storage/__init__.py +17 -0
- agentpool/storage/manager.py +419 -0
- agentpool/storage/serialization.py +136 -0
- agentpool/talk/__init__.py +13 -0
- agentpool/talk/registry.py +128 -0
- agentpool/talk/stats.py +159 -0
- agentpool/talk/talk.py +604 -0
- agentpool/tasks/__init__.py +20 -0
- agentpool/tasks/exceptions.py +25 -0
- agentpool/tasks/registry.py +33 -0
- agentpool/testing.py +129 -0
- agentpool/text_templates/__init__.py +39 -0
- agentpool/text_templates/system_prompt.jinja +30 -0
- agentpool/text_templates/tool_call_default.jinja +13 -0
- agentpool/text_templates/tool_call_markdown.jinja +25 -0
- agentpool/text_templates/tool_call_simple.jinja +5 -0
- agentpool/tools/__init__.py +16 -0
- agentpool/tools/base.py +269 -0
- agentpool/tools/exceptions.py +9 -0
- agentpool/tools/manager.py +255 -0
- agentpool/tools/tool_call_info.py +87 -0
- agentpool/ui/__init__.py +2 -0
- agentpool/ui/base.py +89 -0
- agentpool/ui/mock_provider.py +81 -0
- agentpool/ui/stdlib_provider.py +150 -0
- agentpool/utils/__init__.py +44 -0
- agentpool/utils/baseregistry.py +185 -0
- agentpool/utils/count_tokens.py +62 -0
- agentpool/utils/dag.py +184 -0
- agentpool/utils/importing.py +206 -0
- agentpool/utils/inspection.py +334 -0
- agentpool/utils/model_capabilities.py +25 -0
- agentpool/utils/network.py +28 -0
- agentpool/utils/now.py +22 -0
- agentpool/utils/parse_time.py +87 -0
- agentpool/utils/result_utils.py +35 -0
- agentpool/utils/signatures.py +305 -0
- agentpool/utils/streams.py +112 -0
- agentpool/utils/tasks.py +186 -0
- agentpool/vfs_registry.py +250 -0
- agentpool-2.1.9.dist-info/METADATA +336 -0
- agentpool-2.1.9.dist-info/RECORD +474 -0
- agentpool-2.1.9.dist-info/WHEEL +4 -0
- agentpool-2.1.9.dist-info/entry_points.txt +14 -0
- agentpool-2.1.9.dist-info/licenses/LICENSE +22 -0
- agentpool_cli/__init__.py +34 -0
- agentpool_cli/__main__.py +66 -0
- agentpool_cli/agent.py +175 -0
- agentpool_cli/cli_types.py +23 -0
- agentpool_cli/common.py +163 -0
- agentpool_cli/create.py +175 -0
- agentpool_cli/history.py +217 -0
- agentpool_cli/log.py +78 -0
- agentpool_cli/py.typed +0 -0
- agentpool_cli/run.py +84 -0
- agentpool_cli/serve_acp.py +177 -0
- agentpool_cli/serve_api.py +69 -0
- agentpool_cli/serve_mcp.py +74 -0
- agentpool_cli/serve_vercel.py +233 -0
- agentpool_cli/store.py +171 -0
- agentpool_cli/task.py +84 -0
- agentpool_cli/utils.py +104 -0
- agentpool_cli/watch.py +54 -0
- agentpool_commands/__init__.py +180 -0
- agentpool_commands/agents.py +199 -0
- agentpool_commands/base.py +45 -0
- agentpool_commands/commands.py +58 -0
- agentpool_commands/completers.py +110 -0
- agentpool_commands/connections.py +175 -0
- agentpool_commands/markdown_utils.py +31 -0
- agentpool_commands/models.py +62 -0
- agentpool_commands/prompts.py +78 -0
- agentpool_commands/py.typed +0 -0
- agentpool_commands/read.py +77 -0
- agentpool_commands/resources.py +210 -0
- agentpool_commands/session.py +48 -0
- agentpool_commands/tools.py +269 -0
- agentpool_commands/utils.py +189 -0
- agentpool_commands/workers.py +163 -0
- agentpool_config/__init__.py +53 -0
- agentpool_config/builtin_tools.py +265 -0
- agentpool_config/commands.py +237 -0
- agentpool_config/conditions.py +301 -0
- agentpool_config/converters.py +30 -0
- agentpool_config/durable.py +331 -0
- agentpool_config/event_handlers.py +600 -0
- agentpool_config/events.py +153 -0
- agentpool_config/forward_targets.py +251 -0
- agentpool_config/hook_conditions.py +331 -0
- agentpool_config/hooks.py +241 -0
- agentpool_config/jinja.py +206 -0
- agentpool_config/knowledge.py +41 -0
- agentpool_config/loaders.py +350 -0
- agentpool_config/mcp_server.py +243 -0
- agentpool_config/nodes.py +202 -0
- agentpool_config/observability.py +191 -0
- agentpool_config/output_types.py +55 -0
- agentpool_config/pool_server.py +267 -0
- agentpool_config/prompt_hubs.py +105 -0
- agentpool_config/prompts.py +185 -0
- agentpool_config/py.typed +0 -0
- agentpool_config/resources.py +33 -0
- agentpool_config/session.py +119 -0
- agentpool_config/skills.py +17 -0
- agentpool_config/storage.py +288 -0
- agentpool_config/system_prompts.py +190 -0
- agentpool_config/task.py +162 -0
- agentpool_config/teams.py +52 -0
- agentpool_config/tools.py +112 -0
- agentpool_config/toolsets.py +1033 -0
- agentpool_config/workers.py +86 -0
- agentpool_prompts/__init__.py +1 -0
- agentpool_prompts/braintrust_hub.py +235 -0
- agentpool_prompts/fabric.py +75 -0
- agentpool_prompts/langfuse_hub.py +79 -0
- agentpool_prompts/promptlayer_provider.py +59 -0
- agentpool_prompts/py.typed +0 -0
- agentpool_server/__init__.py +9 -0
- agentpool_server/a2a_server/__init__.py +5 -0
- agentpool_server/a2a_server/a2a_types.py +41 -0
- agentpool_server/a2a_server/server.py +190 -0
- agentpool_server/a2a_server/storage.py +81 -0
- agentpool_server/acp_server/__init__.py +22 -0
- agentpool_server/acp_server/acp_agent.py +786 -0
- agentpool_server/acp_server/acp_tools.py +43 -0
- agentpool_server/acp_server/commands/__init__.py +18 -0
- agentpool_server/acp_server/commands/acp_commands.py +594 -0
- agentpool_server/acp_server/commands/debug_commands.py +376 -0
- agentpool_server/acp_server/commands/docs_commands/__init__.py +39 -0
- agentpool_server/acp_server/commands/docs_commands/fetch_repo.py +169 -0
- agentpool_server/acp_server/commands/docs_commands/get_schema.py +176 -0
- agentpool_server/acp_server/commands/docs_commands/get_source.py +110 -0
- agentpool_server/acp_server/commands/docs_commands/git_diff.py +111 -0
- agentpool_server/acp_server/commands/docs_commands/helpers.py +33 -0
- agentpool_server/acp_server/commands/docs_commands/url_to_markdown.py +90 -0
- agentpool_server/acp_server/commands/spawn.py +210 -0
- agentpool_server/acp_server/converters.py +235 -0
- agentpool_server/acp_server/input_provider.py +338 -0
- agentpool_server/acp_server/server.py +288 -0
- agentpool_server/acp_server/session.py +969 -0
- agentpool_server/acp_server/session_manager.py +313 -0
- agentpool_server/acp_server/syntax_detection.py +250 -0
- agentpool_server/acp_server/zed_tools.md +90 -0
- agentpool_server/aggregating_server.py +309 -0
- agentpool_server/agui_server/__init__.py +11 -0
- agentpool_server/agui_server/server.py +128 -0
- agentpool_server/base.py +189 -0
- agentpool_server/http_server.py +164 -0
- agentpool_server/mcp_server/__init__.py +6 -0
- agentpool_server/mcp_server/server.py +314 -0
- agentpool_server/mcp_server/zed_wrapper.py +110 -0
- agentpool_server/openai_api_server/__init__.py +5 -0
- agentpool_server/openai_api_server/completions/__init__.py +1 -0
- agentpool_server/openai_api_server/completions/helpers.py +81 -0
- agentpool_server/openai_api_server/completions/models.py +98 -0
- agentpool_server/openai_api_server/responses/__init__.py +1 -0
- agentpool_server/openai_api_server/responses/helpers.py +74 -0
- agentpool_server/openai_api_server/responses/models.py +96 -0
- agentpool_server/openai_api_server/server.py +242 -0
- agentpool_server/py.typed +0 -0
- agentpool_storage/__init__.py +9 -0
- agentpool_storage/base.py +310 -0
- agentpool_storage/file_provider.py +378 -0
- agentpool_storage/formatters.py +129 -0
- agentpool_storage/memory_provider.py +396 -0
- agentpool_storage/models.py +108 -0
- agentpool_storage/py.typed +0 -0
- agentpool_storage/session_store.py +262 -0
- agentpool_storage/sql_provider/__init__.py +21 -0
- agentpool_storage/sql_provider/cli.py +146 -0
- agentpool_storage/sql_provider/models.py +249 -0
- agentpool_storage/sql_provider/queries.py +15 -0
- agentpool_storage/sql_provider/sql_provider.py +444 -0
- agentpool_storage/sql_provider/utils.py +234 -0
- agentpool_storage/text_log_provider.py +275 -0
- agentpool_toolsets/__init__.py +15 -0
- agentpool_toolsets/builtin/__init__.py +33 -0
- agentpool_toolsets/builtin/agent_management.py +239 -0
- agentpool_toolsets/builtin/chain.py +288 -0
- agentpool_toolsets/builtin/code.py +398 -0
- agentpool_toolsets/builtin/debug.py +291 -0
- agentpool_toolsets/builtin/execution_environment.py +381 -0
- agentpool_toolsets/builtin/file_edit/__init__.py +11 -0
- agentpool_toolsets/builtin/file_edit/file_edit.py +747 -0
- agentpool_toolsets/builtin/file_edit/fuzzy_matcher/__init__.py +5 -0
- agentpool_toolsets/builtin/file_edit/fuzzy_matcher/example_usage.py +311 -0
- agentpool_toolsets/builtin/file_edit/fuzzy_matcher/streaming_fuzzy_matcher.py +443 -0
- agentpool_toolsets/builtin/history.py +36 -0
- agentpool_toolsets/builtin/integration.py +85 -0
- agentpool_toolsets/builtin/skills.py +77 -0
- agentpool_toolsets/builtin/subagent_tools.py +324 -0
- agentpool_toolsets/builtin/tool_management.py +90 -0
- agentpool_toolsets/builtin/user_interaction.py +52 -0
- agentpool_toolsets/builtin/workers.py +128 -0
- agentpool_toolsets/composio_toolset.py +96 -0
- agentpool_toolsets/config_creation.py +192 -0
- agentpool_toolsets/entry_points.py +47 -0
- agentpool_toolsets/fsspec_toolset/__init__.py +7 -0
- agentpool_toolsets/fsspec_toolset/diagnostics.py +115 -0
- agentpool_toolsets/fsspec_toolset/grep.py +450 -0
- agentpool_toolsets/fsspec_toolset/helpers.py +631 -0
- agentpool_toolsets/fsspec_toolset/streaming_diff_parser.py +249 -0
- agentpool_toolsets/fsspec_toolset/toolset.py +1384 -0
- agentpool_toolsets/mcp_run_toolset.py +61 -0
- agentpool_toolsets/notifications.py +146 -0
- agentpool_toolsets/openapi.py +118 -0
- agentpool_toolsets/py.typed +0 -0
- agentpool_toolsets/search_toolset.py +202 -0
- agentpool_toolsets/semantic_memory_toolset.py +536 -0
- agentpool_toolsets/streaming_tools.py +265 -0
- agentpool_toolsets/vfs_toolset.py +124 -0
agentpool/talk/talk.py
ADDED
|
@@ -0,0 +1,604 @@
|
|
|
1
|
+
"""Manages message flow between agents/groups."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections import defaultdict
|
|
6
|
+
from collections.abc import Callable, Sequence
|
|
7
|
+
from contextlib import asynccontextmanager
|
|
8
|
+
from dataclasses import dataclass, field, replace
|
|
9
|
+
from typing import TYPE_CHECKING, Any, Self, overload
|
|
10
|
+
|
|
11
|
+
from psygnal import Signal
|
|
12
|
+
|
|
13
|
+
from agentpool.log import get_logger
|
|
14
|
+
from agentpool.messaging import ChatMessage
|
|
15
|
+
from agentpool.talk.stats import AggregatedTalkStats, TalkStats
|
|
16
|
+
from agentpool.utils.inspection import execute
|
|
17
|
+
from agentpool.utils.now import get_now
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
if TYPE_CHECKING:
|
|
21
|
+
from collections.abc import AsyncIterator, Awaitable, Iterator
|
|
22
|
+
from datetime import datetime, timedelta
|
|
23
|
+
|
|
24
|
+
from evented.event_data import EventData
|
|
25
|
+
|
|
26
|
+
from agentpool.common_types import (
|
|
27
|
+
AnyFilterFn,
|
|
28
|
+
AnyTransformFn,
|
|
29
|
+
ProcessorCallback,
|
|
30
|
+
PromptCompatible,
|
|
31
|
+
QueueStrategy,
|
|
32
|
+
)
|
|
33
|
+
from agentpool.messaging import MessageNode
|
|
34
|
+
from agentpool.messaging.events import ConnectionEventData
|
|
35
|
+
from agentpool_config.events import ConnectionEventType
|
|
36
|
+
from agentpool_config.forward_targets import ConnectionType
|
|
37
|
+
|
|
38
|
+
logger = get_logger(__name__)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class Talk[TTransmittedData = Any]:
|
|
42
|
+
"""Manages message flow between agents/groups."""
|
|
43
|
+
|
|
44
|
+
@dataclass(frozen=True)
|
|
45
|
+
class ConnectionProcessed:
|
|
46
|
+
"""Event emitted when a message flows through a connection."""
|
|
47
|
+
|
|
48
|
+
message: ChatMessage[Any]
|
|
49
|
+
source: MessageNode[Any, Any]
|
|
50
|
+
targets: list[MessageNode[Any, Any]]
|
|
51
|
+
queued: bool
|
|
52
|
+
connection_type: ConnectionType
|
|
53
|
+
timestamp: datetime = field(default_factory=get_now)
|
|
54
|
+
|
|
55
|
+
# Original message "coming in"
|
|
56
|
+
message_received = Signal(ChatMessage)
|
|
57
|
+
# After any transformation (one for each message, not per target)
|
|
58
|
+
message_forwarded = Signal(ChatMessage)
|
|
59
|
+
# Comprehensive signal capturing all information about one "message handling process"
|
|
60
|
+
connection_processed = Signal(ConnectionProcessed)
|
|
61
|
+
|
|
62
|
+
def __init__(
|
|
63
|
+
self,
|
|
64
|
+
source: MessageNode[Any, Any],
|
|
65
|
+
targets: Sequence[MessageNode[Any, Any]],
|
|
66
|
+
group: TeamTalk | None = None,
|
|
67
|
+
*,
|
|
68
|
+
name: str | None = None,
|
|
69
|
+
connection_type: ConnectionType = "run",
|
|
70
|
+
wait_for_connections: bool = False,
|
|
71
|
+
priority: int = 0,
|
|
72
|
+
delay: timedelta | None = None,
|
|
73
|
+
queued: bool = False,
|
|
74
|
+
queue_strategy: QueueStrategy = "latest",
|
|
75
|
+
transform: AnyTransformFn[ChatMessage[TTransmittedData]] | None = None,
|
|
76
|
+
filter_condition: AnyFilterFn | None = None,
|
|
77
|
+
stop_condition: AnyFilterFn | None = None,
|
|
78
|
+
exit_condition: AnyFilterFn | None = None,
|
|
79
|
+
) -> None:
|
|
80
|
+
"""Initialize talk connection.
|
|
81
|
+
|
|
82
|
+
Args:
|
|
83
|
+
source: Agent sending messages
|
|
84
|
+
targets: Agents receiving messages
|
|
85
|
+
group: Optional group this talk belongs to
|
|
86
|
+
name: Optional name for this talk
|
|
87
|
+
connection_type: How to handle messages:
|
|
88
|
+
- "run": Execute message as a new run in target
|
|
89
|
+
- "context": Add message as context to target
|
|
90
|
+
- "forward": Forward message to target's outbox
|
|
91
|
+
wait_for_connections: Whether to wait for all targets to complete
|
|
92
|
+
priority: Task priority (lower = higher priority)
|
|
93
|
+
delay: Optional delay before processing
|
|
94
|
+
queued: Whether messages should be queued for manual processing
|
|
95
|
+
queue_strategy: How to process queued messages:
|
|
96
|
+
- "concat": Combine all messages with newlines
|
|
97
|
+
- "latest": Use only the most recent message
|
|
98
|
+
- "buffer": Process all messages individually
|
|
99
|
+
transform: Optional function to transform messages
|
|
100
|
+
filter_condition: Optional condition for filtering messages
|
|
101
|
+
stop_condition: Optional condition for disconnecting
|
|
102
|
+
exit_condition: Optional condition for stopping the event loop
|
|
103
|
+
"""
|
|
104
|
+
self.source = source
|
|
105
|
+
self.targets = list(targets)
|
|
106
|
+
# Could perhaps better be an auto-inferring property
|
|
107
|
+
self.name = name or f"{source.name}->{[t.name for t in targets]}"
|
|
108
|
+
self.group = group
|
|
109
|
+
self.priority = priority
|
|
110
|
+
self.delay = delay
|
|
111
|
+
self.active = True
|
|
112
|
+
self.connection_type: ConnectionType = connection_type
|
|
113
|
+
self.wait_for_connections = wait_for_connections
|
|
114
|
+
self.queued = queued
|
|
115
|
+
self.queue_strategy = queue_strategy
|
|
116
|
+
self._pending_messages = defaultdict[str, list[ChatMessage[TTransmittedData]]](list)
|
|
117
|
+
names = {t.name for t in targets}
|
|
118
|
+
self._stats = TalkStats(source_name=source.name, target_names=names)
|
|
119
|
+
self.transform_fn = transform
|
|
120
|
+
self.filter_condition = filter_condition
|
|
121
|
+
self.stop_condition = stop_condition
|
|
122
|
+
self.exit_condition = exit_condition
|
|
123
|
+
|
|
124
|
+
def __repr__(self) -> str:
|
|
125
|
+
targets = [t.name for t in self.targets]
|
|
126
|
+
return f"<Talk({self.connection_type}) {self.source.name} -> {targets}>"
|
|
127
|
+
|
|
128
|
+
@overload
|
|
129
|
+
def __rshift__(
|
|
130
|
+
self,
|
|
131
|
+
other: MessageNode[Any, str]
|
|
132
|
+
| ProcessorCallback[str]
|
|
133
|
+
| Sequence[MessageNode[Any, str] | ProcessorCallback[str]],
|
|
134
|
+
) -> TeamTalk[str]: ...
|
|
135
|
+
|
|
136
|
+
@overload
|
|
137
|
+
def __rshift__(
|
|
138
|
+
self,
|
|
139
|
+
other: MessageNode[Any, Any]
|
|
140
|
+
| ProcessorCallback[Any]
|
|
141
|
+
| Sequence[MessageNode[Any, Any] | ProcessorCallback[Any]],
|
|
142
|
+
) -> TeamTalk[Any]: ...
|
|
143
|
+
|
|
144
|
+
def __rshift__(
|
|
145
|
+
self,
|
|
146
|
+
other: MessageNode[Any, Any]
|
|
147
|
+
| ProcessorCallback[Any]
|
|
148
|
+
| Sequence[MessageNode[Any, Any] | ProcessorCallback[Any]],
|
|
149
|
+
) -> TeamTalk[Any]:
|
|
150
|
+
"""Add another node as target to the connection or group.
|
|
151
|
+
|
|
152
|
+
Example:
|
|
153
|
+
connection >> other_agent # Connect to single agent
|
|
154
|
+
connection >> (agent2 & agent3) # Connect to group
|
|
155
|
+
"""
|
|
156
|
+
from agentpool import Agent, MessageNode
|
|
157
|
+
from agentpool.talk import TeamTalk
|
|
158
|
+
|
|
159
|
+
match other:
|
|
160
|
+
case Callable():
|
|
161
|
+
other = Agent.from_callback(other)
|
|
162
|
+
if pool := self.source.agent_pool:
|
|
163
|
+
other.agent_pool = pool
|
|
164
|
+
pool.register(other.name, other)
|
|
165
|
+
return self.__rshift__(other)
|
|
166
|
+
case Sequence():
|
|
167
|
+
team_talks = [self.__rshift__(o) for o in other]
|
|
168
|
+
return TeamTalk([self, *team_talks])
|
|
169
|
+
case MessageNode():
|
|
170
|
+
talks = [t.__rshift__(other) for t in self.targets]
|
|
171
|
+
return TeamTalk([self, *talks])
|
|
172
|
+
case _:
|
|
173
|
+
msg = f"Invalid agent type: {type(other)}"
|
|
174
|
+
raise TypeError(msg)
|
|
175
|
+
|
|
176
|
+
async def _evaluate_condition(
|
|
177
|
+
self,
|
|
178
|
+
condition: Callable[..., bool | Awaitable[bool]] | None,
|
|
179
|
+
message: ChatMessage[Any],
|
|
180
|
+
target: MessageNode[Any, Any],
|
|
181
|
+
*,
|
|
182
|
+
default_return: bool = False,
|
|
183
|
+
) -> bool:
|
|
184
|
+
"""Evaluate a condition with flexible parameter handling."""
|
|
185
|
+
from agentpool.talk.registry import EventContext
|
|
186
|
+
|
|
187
|
+
if not condition:
|
|
188
|
+
return default_return
|
|
189
|
+
registry = pool.connection_registry if (pool := self.source.agent_pool) else None
|
|
190
|
+
ctx = EventContext(
|
|
191
|
+
message=message,
|
|
192
|
+
target=target,
|
|
193
|
+
stats=self.stats,
|
|
194
|
+
registry=registry,
|
|
195
|
+
talk=self,
|
|
196
|
+
)
|
|
197
|
+
return await execute(condition, ctx)
|
|
198
|
+
|
|
199
|
+
def on_event(
|
|
200
|
+
self,
|
|
201
|
+
event_type: ConnectionEventType,
|
|
202
|
+
callback: Callable[[ConnectionEventData[TTransmittedData]], None | Awaitable[None]],
|
|
203
|
+
) -> Self:
|
|
204
|
+
"""Register callback for connection events."""
|
|
205
|
+
from agentpool.messaging.events import ConnectionEventData
|
|
206
|
+
|
|
207
|
+
async def wrapped_callback(event: EventData) -> None:
|
|
208
|
+
if isinstance(event, ConnectionEventData) and event.event_type == event_type:
|
|
209
|
+
await execute(callback, event)
|
|
210
|
+
|
|
211
|
+
self.source._events.add_callback(wrapped_callback)
|
|
212
|
+
return self
|
|
213
|
+
|
|
214
|
+
async def _emit_connection_event(
|
|
215
|
+
self,
|
|
216
|
+
event_type: ConnectionEventType,
|
|
217
|
+
message: ChatMessage[TTransmittedData] | None,
|
|
218
|
+
) -> None:
|
|
219
|
+
from agentpool.messaging.events import ConnectionEventData
|
|
220
|
+
|
|
221
|
+
event = ConnectionEventData[Any](
|
|
222
|
+
connection=self,
|
|
223
|
+
source="connection",
|
|
224
|
+
connection_name=self.name,
|
|
225
|
+
event_type=event_type,
|
|
226
|
+
message=message,
|
|
227
|
+
timestamp=get_now(),
|
|
228
|
+
)
|
|
229
|
+
# Propagate to all event managers through registry
|
|
230
|
+
if pool := self.source.agent_pool:
|
|
231
|
+
for connection in pool.connection_registry.values():
|
|
232
|
+
await connection.source._events.emit_event(event)
|
|
233
|
+
|
|
234
|
+
async def _handle_message(
|
|
235
|
+
self,
|
|
236
|
+
message: ChatMessage[TTransmittedData],
|
|
237
|
+
prompt: str | None = None,
|
|
238
|
+
) -> list[ChatMessage[Any]]:
|
|
239
|
+
"""Handle message forwarding based on connection configuration."""
|
|
240
|
+
# 2. Early exit checks
|
|
241
|
+
if not (self.active and (not self.group or self.group.active)):
|
|
242
|
+
return []
|
|
243
|
+
|
|
244
|
+
# 3. Check exit condition for any target
|
|
245
|
+
for target in self.targets:
|
|
246
|
+
# Exit if condition returns True
|
|
247
|
+
if await self._evaluate_condition(self.exit_condition, message, target):
|
|
248
|
+
raise SystemExit
|
|
249
|
+
|
|
250
|
+
# 4. Check stop condition for any target
|
|
251
|
+
for target in self.targets:
|
|
252
|
+
# Stop if condition returns True
|
|
253
|
+
if await self._evaluate_condition(self.stop_condition, message, target):
|
|
254
|
+
self.disconnect()
|
|
255
|
+
return []
|
|
256
|
+
|
|
257
|
+
# 5. Transform if configured
|
|
258
|
+
processed_message = message
|
|
259
|
+
if self.transform_fn:
|
|
260
|
+
processed_message = await execute(self.transform_fn, message)
|
|
261
|
+
# 6. First pass: Determine target list
|
|
262
|
+
target_list: list[MessageNode[Any, Any]] = [
|
|
263
|
+
target
|
|
264
|
+
for target in self.targets
|
|
265
|
+
if await self._evaluate_condition(
|
|
266
|
+
self.filter_condition,
|
|
267
|
+
processed_message,
|
|
268
|
+
target,
|
|
269
|
+
default_return=True,
|
|
270
|
+
)
|
|
271
|
+
]
|
|
272
|
+
# 7. emit connection processed event
|
|
273
|
+
self.connection_processed.emit(
|
|
274
|
+
self.ConnectionProcessed(
|
|
275
|
+
message=processed_message,
|
|
276
|
+
source=self.source,
|
|
277
|
+
targets=target_list,
|
|
278
|
+
queued=self.queued,
|
|
279
|
+
connection_type=self.connection_type, # pyright: ignore
|
|
280
|
+
)
|
|
281
|
+
)
|
|
282
|
+
# 8. if we have targets, update stats and emit message forwarded
|
|
283
|
+
if target_list:
|
|
284
|
+
messages = [*self._stats.messages, processed_message]
|
|
285
|
+
self._stats = replace(self._stats, messages=messages)
|
|
286
|
+
self.message_forwarded.emit(processed_message)
|
|
287
|
+
|
|
288
|
+
# 9. Second pass: Actually process for each target
|
|
289
|
+
responses: list[ChatMessage[Any]] = []
|
|
290
|
+
for target in target_list:
|
|
291
|
+
if self.queued:
|
|
292
|
+
self._pending_messages[target.name].append(processed_message)
|
|
293
|
+
continue
|
|
294
|
+
if response := await self._process_for_target(processed_message, target, prompt):
|
|
295
|
+
responses.append(response)
|
|
296
|
+
|
|
297
|
+
return responses
|
|
298
|
+
|
|
299
|
+
async def _process_for_target(
|
|
300
|
+
self,
|
|
301
|
+
message: ChatMessage[Any],
|
|
302
|
+
target: MessageNode[Any, Any],
|
|
303
|
+
prompt: PromptCompatible | None = None,
|
|
304
|
+
) -> ChatMessage[Any] | None:
|
|
305
|
+
"""Process message for a single target."""
|
|
306
|
+
from agentpool.agents import Agent
|
|
307
|
+
from agentpool.delegation.base_team import BaseTeam
|
|
308
|
+
|
|
309
|
+
match self.connection_type:
|
|
310
|
+
case "run":
|
|
311
|
+
prompts: list[PromptCompatible] = [message]
|
|
312
|
+
if prompt:
|
|
313
|
+
prompts.append(prompt)
|
|
314
|
+
return await target.run(*prompts)
|
|
315
|
+
|
|
316
|
+
case "context":
|
|
317
|
+
meta = {
|
|
318
|
+
"type": "forwarded_message",
|
|
319
|
+
"role": message.role,
|
|
320
|
+
"model": message.model_name,
|
|
321
|
+
"cost_info": message.cost_info,
|
|
322
|
+
"timestamp": message.timestamp.isoformat(),
|
|
323
|
+
"prompt": prompt,
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
async def add_context() -> None:
|
|
327
|
+
match target:
|
|
328
|
+
case BaseTeam():
|
|
329
|
+
# Use distribute for teams
|
|
330
|
+
await target.distribute(str(message.content), metadata=meta)
|
|
331
|
+
case Agent(): # Agent case
|
|
332
|
+
# Use existing context message approach
|
|
333
|
+
target.conversation.add_context_message(
|
|
334
|
+
str(message.content),
|
|
335
|
+
source=message.name,
|
|
336
|
+
metadata=meta,
|
|
337
|
+
)
|
|
338
|
+
|
|
339
|
+
if self.delay is not None or self.priority != 0:
|
|
340
|
+
coro = add_context()
|
|
341
|
+
target.task_manager.run_background(
|
|
342
|
+
coro, priority=self.priority, delay=self.delay
|
|
343
|
+
)
|
|
344
|
+
else:
|
|
345
|
+
await add_context()
|
|
346
|
+
return None
|
|
347
|
+
|
|
348
|
+
case "forward":
|
|
349
|
+
if self.delay is not None or self.priority != 0:
|
|
350
|
+
|
|
351
|
+
async def delayed_emit() -> None:
|
|
352
|
+
await target.connections.route_message(message)
|
|
353
|
+
|
|
354
|
+
coro = delayed_emit()
|
|
355
|
+
target.task_manager.run_background(
|
|
356
|
+
coro, priority=self.priority, delay=self.delay
|
|
357
|
+
)
|
|
358
|
+
else:
|
|
359
|
+
await target.connections.route_message(message)
|
|
360
|
+
return None
|
|
361
|
+
|
|
362
|
+
async def trigger(
|
|
363
|
+
self, prompt: PromptCompatible | None = None
|
|
364
|
+
) -> list[ChatMessage[TTransmittedData]]:
|
|
365
|
+
"""Process queued messages."""
|
|
366
|
+
if not self._pending_messages:
|
|
367
|
+
return []
|
|
368
|
+
match self.queue_strategy:
|
|
369
|
+
case "buffer":
|
|
370
|
+
results: list[ChatMessage[TTransmittedData]] = []
|
|
371
|
+
# Process each agent's queue
|
|
372
|
+
for target in self.targets:
|
|
373
|
+
queue = self._pending_messages[target.name]
|
|
374
|
+
for msg in queue:
|
|
375
|
+
if resp := await self._process_for_target(msg, target, prompt):
|
|
376
|
+
results.append(resp) # noqa: PERF401
|
|
377
|
+
queue.clear()
|
|
378
|
+
return results
|
|
379
|
+
|
|
380
|
+
case "latest":
|
|
381
|
+
results = []
|
|
382
|
+
# Get latest message for each agent
|
|
383
|
+
for target in self.targets:
|
|
384
|
+
queue = self._pending_messages[target.name]
|
|
385
|
+
if queue:
|
|
386
|
+
latest = queue[-1]
|
|
387
|
+
if resp := await self._process_for_target(latest, target, prompt):
|
|
388
|
+
results.append(resp)
|
|
389
|
+
queue.clear()
|
|
390
|
+
return results
|
|
391
|
+
|
|
392
|
+
case "concat":
|
|
393
|
+
results = []
|
|
394
|
+
# Concat messages per agent
|
|
395
|
+
for target in self.targets:
|
|
396
|
+
queue = self._pending_messages[target.name]
|
|
397
|
+
if not queue:
|
|
398
|
+
continue
|
|
399
|
+
|
|
400
|
+
base = queue[-1]
|
|
401
|
+
contents = [str(m.content) for m in queue]
|
|
402
|
+
meta = {
|
|
403
|
+
**base.metadata,
|
|
404
|
+
"merged_count": len(queue),
|
|
405
|
+
"queue_strategy": self.queue_strategy,
|
|
406
|
+
}
|
|
407
|
+
content = "\n\n".join(contents)
|
|
408
|
+
merged = replace(base, content=content, metadata=meta) # type: ignore
|
|
409
|
+
|
|
410
|
+
if response := await self._process_for_target(merged, target, prompt):
|
|
411
|
+
results.append(response)
|
|
412
|
+
queue.clear()
|
|
413
|
+
|
|
414
|
+
return results
|
|
415
|
+
case _:
|
|
416
|
+
msg = f"Invalid queue strategy: {self.queue_strategy}"
|
|
417
|
+
raise ValueError(msg)
|
|
418
|
+
|
|
419
|
+
def when(self, condition: AnyFilterFn) -> Self:
|
|
420
|
+
"""Add condition for message forwarding."""
|
|
421
|
+
self.filter_condition = condition
|
|
422
|
+
return self
|
|
423
|
+
|
|
424
|
+
def transform[TNewData](
|
|
425
|
+
self,
|
|
426
|
+
transformer: Callable[
|
|
427
|
+
[ChatMessage[TTransmittedData]],
|
|
428
|
+
ChatMessage[TNewData] | Awaitable[ChatMessage[TNewData]],
|
|
429
|
+
],
|
|
430
|
+
*,
|
|
431
|
+
name: str | None = None,
|
|
432
|
+
description: str | None = None,
|
|
433
|
+
) -> Talk[TNewData]:
|
|
434
|
+
"""Chain a new transformation after existing ones.
|
|
435
|
+
|
|
436
|
+
Args:
|
|
437
|
+
transformer: Function to transform messages
|
|
438
|
+
name: Optional name for debugging
|
|
439
|
+
description: Optional description
|
|
440
|
+
|
|
441
|
+
Returns:
|
|
442
|
+
New Talk instance with chained transformation
|
|
443
|
+
|
|
444
|
+
Example:
|
|
445
|
+
```python
|
|
446
|
+
talk = (agent1 >> agent2)
|
|
447
|
+
.transform(parse_json) # str -> dict
|
|
448
|
+
.transform(extract_values) # dict -> list
|
|
449
|
+
```
|
|
450
|
+
"""
|
|
451
|
+
new_talk = Talk[TNewData](
|
|
452
|
+
source=self.source,
|
|
453
|
+
targets=self.targets,
|
|
454
|
+
connection_type=self.connection_type,
|
|
455
|
+
)
|
|
456
|
+
|
|
457
|
+
if self.transform_fn is not None:
|
|
458
|
+
oldtransform_fn = self.transform_fn
|
|
459
|
+
|
|
460
|
+
async def chainedtransform_fn(
|
|
461
|
+
data: ChatMessage[TTransmittedData],
|
|
462
|
+
) -> ChatMessage[TNewData]:
|
|
463
|
+
intermediate = await execute(oldtransform_fn, data)
|
|
464
|
+
return await execute(transformer, intermediate)
|
|
465
|
+
|
|
466
|
+
new_talk.transform_fn = chainedtransform_fn # type: ignore
|
|
467
|
+
else:
|
|
468
|
+
new_talk.transform_fn = transformer # type: ignore
|
|
469
|
+
|
|
470
|
+
return new_talk
|
|
471
|
+
|
|
472
|
+
@asynccontextmanager
|
|
473
|
+
async def paused(self) -> AsyncIterator[Self]:
|
|
474
|
+
"""Temporarily set inactive."""
|
|
475
|
+
previous = self.active
|
|
476
|
+
self.active = False
|
|
477
|
+
try:
|
|
478
|
+
yield self
|
|
479
|
+
finally:
|
|
480
|
+
self.active = previous
|
|
481
|
+
|
|
482
|
+
def disconnect(self) -> None:
|
|
483
|
+
"""Permanently disconnect the connection."""
|
|
484
|
+
self.active = False
|
|
485
|
+
|
|
486
|
+
@property
|
|
487
|
+
def stats(self) -> TalkStats:
|
|
488
|
+
"""Get current connection statistics."""
|
|
489
|
+
return self._stats
|
|
490
|
+
|
|
491
|
+
|
|
492
|
+
class TeamTalk[TTransmittedData = Any](list["Talk | TeamTalk"]):
|
|
493
|
+
"""Group of connections with aggregate operations."""
|
|
494
|
+
|
|
495
|
+
def __init__(
|
|
496
|
+
self, talks: Sequence[Talk[TTransmittedData] | TeamTalk[TTransmittedData]]
|
|
497
|
+
) -> None:
|
|
498
|
+
super().__init__(talks)
|
|
499
|
+
self.filter_condition: AnyFilterFn | None = None
|
|
500
|
+
self.active = True
|
|
501
|
+
|
|
502
|
+
def __repr__(self) -> str:
|
|
503
|
+
return f"TeamTalk({list(self)})"
|
|
504
|
+
|
|
505
|
+
def __rshift__(
|
|
506
|
+
self,
|
|
507
|
+
other: MessageNode[Any, Any]
|
|
508
|
+
| ProcessorCallback[Any]
|
|
509
|
+
| Sequence[MessageNode[Any, Any] | ProcessorCallback[Any]],
|
|
510
|
+
) -> TeamTalk[Any]:
|
|
511
|
+
"""Add another node as target to the connection or group.
|
|
512
|
+
|
|
513
|
+
Example:
|
|
514
|
+
connection >> other_agent # Connect to single agent
|
|
515
|
+
connection >> (agent2 & agent3) # Connect to group
|
|
516
|
+
"""
|
|
517
|
+
from agentpool import Agent, MessageNode
|
|
518
|
+
from agentpool.talk import TeamTalk
|
|
519
|
+
|
|
520
|
+
match other:
|
|
521
|
+
case Callable():
|
|
522
|
+
other = Agent.from_callback(other)
|
|
523
|
+
for talk_ in self.iter_talks():
|
|
524
|
+
if pool := talk_.source.agent_pool:
|
|
525
|
+
other.agent_pool = pool
|
|
526
|
+
pool.register(other.name, other)
|
|
527
|
+
break
|
|
528
|
+
return self.__rshift__(other)
|
|
529
|
+
case Sequence():
|
|
530
|
+
team_talks = [self.__rshift__(o) for o in other]
|
|
531
|
+
return TeamTalk([self, *team_talks])
|
|
532
|
+
case MessageNode():
|
|
533
|
+
talks = [t.connect_to(other) for t in self.targets]
|
|
534
|
+
return TeamTalk([self, *talks])
|
|
535
|
+
case _:
|
|
536
|
+
msg = f"Invalid agent type: {type(other)}"
|
|
537
|
+
raise TypeError(msg)
|
|
538
|
+
|
|
539
|
+
@property
|
|
540
|
+
def targets(self) -> list[MessageNode[Any, Any]]:
|
|
541
|
+
"""Get all targets from all connections."""
|
|
542
|
+
return [t for talk in self for t in talk.targets]
|
|
543
|
+
|
|
544
|
+
def iter_talks(self) -> Iterator[Talk]:
|
|
545
|
+
"""Get all contained talks."""
|
|
546
|
+
for t in self:
|
|
547
|
+
match t:
|
|
548
|
+
case Talk():
|
|
549
|
+
yield t
|
|
550
|
+
case TeamTalk():
|
|
551
|
+
yield from t.iter_talks()
|
|
552
|
+
|
|
553
|
+
async def _handle_message(self, message: ChatMessage[Any], prompt: str | None = None) -> None:
|
|
554
|
+
for talk in self:
|
|
555
|
+
await talk._handle_message(message, prompt)
|
|
556
|
+
|
|
557
|
+
async def trigger(self, prompt: PromptCompatible | None = None) -> list[ChatMessage[Any]]:
|
|
558
|
+
messages = []
|
|
559
|
+
for talk in self:
|
|
560
|
+
messages.extend(await talk.trigger(prompt))
|
|
561
|
+
return messages
|
|
562
|
+
|
|
563
|
+
@classmethod
|
|
564
|
+
def from_nodes(
|
|
565
|
+
cls,
|
|
566
|
+
agents: Sequence[MessageNode[Any, Any]],
|
|
567
|
+
targets: list[MessageNode[Any, Any]] | None = None,
|
|
568
|
+
) -> Self:
|
|
569
|
+
"""Create TeamTalk from a collection of agents."""
|
|
570
|
+
return cls([Talk(agent, targets or []) for agent in agents])
|
|
571
|
+
|
|
572
|
+
@asynccontextmanager
|
|
573
|
+
async def paused(self) -> AsyncIterator[Self]:
|
|
574
|
+
"""Temporarily set inactive."""
|
|
575
|
+
previous = self.active
|
|
576
|
+
self.active = False
|
|
577
|
+
try:
|
|
578
|
+
yield self
|
|
579
|
+
finally:
|
|
580
|
+
self.active = previous
|
|
581
|
+
|
|
582
|
+
def has_active_talks(self) -> bool:
|
|
583
|
+
"""Check if any contained talks are active."""
|
|
584
|
+
return any(talk.active for talk in self)
|
|
585
|
+
|
|
586
|
+
def get_active_talks(self) -> list[Talk | TeamTalk]:
|
|
587
|
+
"""Get list of currently active talks."""
|
|
588
|
+
return [talk for talk in self if talk.active]
|
|
589
|
+
|
|
590
|
+
@property
|
|
591
|
+
def stats(self) -> AggregatedTalkStats:
|
|
592
|
+
"""Get aggregated statistics for all connections."""
|
|
593
|
+
return AggregatedTalkStats(stats=[talk.stats for talk in self])
|
|
594
|
+
|
|
595
|
+
def when(self, condition: AnyFilterFn) -> Self:
|
|
596
|
+
"""Add condition to all connections in group."""
|
|
597
|
+
for talk in self:
|
|
598
|
+
talk.when(condition)
|
|
599
|
+
return self
|
|
600
|
+
|
|
601
|
+
def disconnect(self) -> None:
|
|
602
|
+
"""Disconnect all connections in group."""
|
|
603
|
+
for talk in self:
|
|
604
|
+
talk.disconnect()
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"""Task management."""
|
|
2
|
+
|
|
3
|
+
from agentpool.tasks.exceptions import (
|
|
4
|
+
JobError,
|
|
5
|
+
ToolSkippedError,
|
|
6
|
+
RunAbortedError,
|
|
7
|
+
ChainAbortedError,
|
|
8
|
+
JobRegistrationError,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
from agentpool.tasks.registry import TaskRegistry
|
|
12
|
+
|
|
13
|
+
__all__ = [
|
|
14
|
+
"ChainAbortedError",
|
|
15
|
+
"JobError",
|
|
16
|
+
"JobRegistrationError",
|
|
17
|
+
"RunAbortedError",
|
|
18
|
+
"TaskRegistry",
|
|
19
|
+
"ToolSkippedError",
|
|
20
|
+
]
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""Task-related exceptions."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from agentpool.utils.baseregistry import AgentPoolError
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class JobError(AgentPoolError):
|
|
9
|
+
"""General task-related exception."""
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ToolSkippedError(JobError):
|
|
13
|
+
"""Tool execution was skipped by user."""
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class RunAbortedError(JobError):
|
|
17
|
+
"""Run was aborted by user."""
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class ChainAbortedError(JobError):
|
|
21
|
+
"""Agent chain was aborted by user."""
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class JobRegistrationError(JobError):
|
|
25
|
+
"""Task could not get registered."""
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""Task definition and registry for agents."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from agentpool.tasks.exceptions import JobRegistrationError
|
|
8
|
+
from agentpool.utils.baseregistry import BaseRegistry
|
|
9
|
+
from agentpool_config.task import Job
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class TaskRegistry(BaseRegistry[str, Job[Any, Any]]):
|
|
13
|
+
"""Registry for managing tasks."""
|
|
14
|
+
|
|
15
|
+
@property
|
|
16
|
+
def _error_class(self) -> type[JobRegistrationError]:
|
|
17
|
+
return JobRegistrationError
|
|
18
|
+
|
|
19
|
+
def _validate_item(self, item: Any) -> Job[Any, Any]:
|
|
20
|
+
from agentpool_config.task import Job
|
|
21
|
+
|
|
22
|
+
if not isinstance(item, Job):
|
|
23
|
+
msg = f"Expected Job, got {type(item)}"
|
|
24
|
+
raise self._error_class(msg)
|
|
25
|
+
return item
|
|
26
|
+
|
|
27
|
+
def register(self, name: str, task: Job[Any, Any], replace: bool = False) -> None:
|
|
28
|
+
"""Register a task with name.
|
|
29
|
+
|
|
30
|
+
Creates a copy of the task with the name set.
|
|
31
|
+
"""
|
|
32
|
+
task_copy = task.model_copy(update={"name": name})
|
|
33
|
+
super().register(name, task_copy, replace)
|