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
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"""Formatting utilities."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING, Any, Literal, TypeGuard, assert_never
|
|
6
|
+
|
|
7
|
+
from rich.console import Console
|
|
8
|
+
from rich.markdown import Markdown
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from agentpool_storage.models import ConversationData
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def is_conversation_data(data: Any) -> TypeGuard[ConversationData]:
|
|
16
|
+
"""Type guard for ConversationData."""
|
|
17
|
+
return (
|
|
18
|
+
isinstance(data, dict)
|
|
19
|
+
and "id" in data
|
|
20
|
+
and "messages" in data
|
|
21
|
+
and "agent" in data
|
|
22
|
+
and "start_time" in data
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def format_output(
|
|
27
|
+
data: ConversationData | list[ConversationData] | dict[str, Any],
|
|
28
|
+
output_format: Literal["json", "yaml", "text"] = "text",
|
|
29
|
+
) -> str:
|
|
30
|
+
"""Format data for output in specified format.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
data: Data to format
|
|
34
|
+
output_format: Format to use (text/json/yaml)
|
|
35
|
+
"""
|
|
36
|
+
import anyenv
|
|
37
|
+
|
|
38
|
+
match output_format:
|
|
39
|
+
case "json":
|
|
40
|
+
return anyenv.dump_json(data, indent=True)
|
|
41
|
+
case "yaml":
|
|
42
|
+
import yamling
|
|
43
|
+
|
|
44
|
+
return yamling.dump_yaml(data)
|
|
45
|
+
case "text":
|
|
46
|
+
console = Console(record=True)
|
|
47
|
+
if is_conversation_data(data):
|
|
48
|
+
# Single conversation
|
|
49
|
+
_print_conversation(console, data) # ty: ignore
|
|
50
|
+
elif isinstance(data, list):
|
|
51
|
+
# Multiple conversations
|
|
52
|
+
for conv in data:
|
|
53
|
+
if is_conversation_data(conv):
|
|
54
|
+
_print_conversation(console, conv)
|
|
55
|
+
console.print()
|
|
56
|
+
else:
|
|
57
|
+
# At this point, data must be a stats dict
|
|
58
|
+
stats_data: dict[str, Any] = data # type: ignore
|
|
59
|
+
_print_stats(console, stats_data)
|
|
60
|
+
return console.export_text()
|
|
61
|
+
case _ as unreachable:
|
|
62
|
+
assert_never(unreachable)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def _print_conversation(console: Console, conv: ConversationData) -> None:
|
|
66
|
+
"""Print a conversation in text format."""
|
|
67
|
+
console.print(f"\n[bold blue]Conversation {conv['id']}[/]")
|
|
68
|
+
console.print(f"Agent: {conv['agent']}, Started: {conv['start_time']}\n")
|
|
69
|
+
|
|
70
|
+
if token_usage := conv.get("token_usage"):
|
|
71
|
+
console.print(
|
|
72
|
+
"[dim]"
|
|
73
|
+
f"Tokens: {token_usage['total']:,} total "
|
|
74
|
+
f"({token_usage['prompt']:,} prompt, "
|
|
75
|
+
f"{token_usage['completion']:,} completion)"
|
|
76
|
+
"[/]"
|
|
77
|
+
)
|
|
78
|
+
console.print()
|
|
79
|
+
|
|
80
|
+
for msg in conv["messages"]:
|
|
81
|
+
role_color = "green" if msg["role"] == "assistant" else "yellow"
|
|
82
|
+
text = f"[{role_color}]{msg['role'].title()}:[/] ({msg['timestamp']})"
|
|
83
|
+
console.print(text)
|
|
84
|
+
console.print(Markdown(msg["content"]))
|
|
85
|
+
if msg.get("model"):
|
|
86
|
+
console.print(f"[dim]Model: {msg['model']}[/]", highlight=False)
|
|
87
|
+
console.print()
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def _print_stats(console: Console, stats: dict[str, Any]) -> None:
|
|
91
|
+
"""Print statistics in text format."""
|
|
92
|
+
if "period" in stats:
|
|
93
|
+
console.print(f"\n[bold]Usage Statistics ({stats['period']})[/]")
|
|
94
|
+
console.print(f"Grouped by: {stats.get('group_by', 'unknown')}\n")
|
|
95
|
+
|
|
96
|
+
for entry in stats.get("entries", [stats]):
|
|
97
|
+
console.print(f"[blue]{entry['name']}[/]")
|
|
98
|
+
console.print(f" Messages: {entry['messages']}")
|
|
99
|
+
console.print(f" Total tokens: {entry['total_tokens']:,}")
|
|
100
|
+
if "models" in entry:
|
|
101
|
+
console.print(" Models: " + ", ".join(entry["models"]))
|
|
102
|
+
console.print()
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def format_stats(
|
|
106
|
+
stats: dict[str, dict[str, Any]],
|
|
107
|
+
period: str,
|
|
108
|
+
group_by: str,
|
|
109
|
+
) -> dict[str, Any]:
|
|
110
|
+
"""Format statistics for output.
|
|
111
|
+
|
|
112
|
+
Args:
|
|
113
|
+
stats: Raw statistics data
|
|
114
|
+
period: Time period string (e.g. "1d")
|
|
115
|
+
group_by: Grouping criterion used
|
|
116
|
+
|
|
117
|
+
Returns:
|
|
118
|
+
Formatted statistics ready for display
|
|
119
|
+
"""
|
|
120
|
+
entries = [
|
|
121
|
+
{
|
|
122
|
+
"name": key,
|
|
123
|
+
"messages": data["messages"],
|
|
124
|
+
"total_tokens": data["total_tokens"],
|
|
125
|
+
"models": sorted(data["models"]),
|
|
126
|
+
}
|
|
127
|
+
for key, data in stats.items()
|
|
128
|
+
]
|
|
129
|
+
return {"period": period, "group_by": group_by, "entries": entries}
|
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
"""In-memory storage provider for testing."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from datetime import datetime
|
|
6
|
+
from typing import TYPE_CHECKING, Any, cast
|
|
7
|
+
|
|
8
|
+
from agentpool.messaging import ChatMessage, TokenCost
|
|
9
|
+
from agentpool.storage import deserialize_messages
|
|
10
|
+
from agentpool.utils.now import get_now
|
|
11
|
+
from agentpool_storage.base import StorageProvider
|
|
12
|
+
from agentpool_storage.models import ConversationData
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
if TYPE_CHECKING:
|
|
16
|
+
from collections.abc import Sequence
|
|
17
|
+
|
|
18
|
+
from agentpool.common_types import JsonValue
|
|
19
|
+
from agentpool_config.session import SessionQuery
|
|
20
|
+
from agentpool_config.storage import MemoryStorageConfig
|
|
21
|
+
from agentpool_storage.models import MessageData, QueryFilters, StatsFilters, TokenUsage
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class MemoryStorageProvider(StorageProvider):
|
|
25
|
+
"""In-memory storage provider for testing."""
|
|
26
|
+
|
|
27
|
+
can_load_history = True
|
|
28
|
+
|
|
29
|
+
def __init__(self, config: MemoryStorageConfig) -> None:
|
|
30
|
+
super().__init__(config)
|
|
31
|
+
self.messages: list[dict[str, Any]] = []
|
|
32
|
+
self.conversations: list[dict[str, Any]] = []
|
|
33
|
+
self.commands: list[dict[str, Any]] = []
|
|
34
|
+
|
|
35
|
+
def cleanup(self) -> None:
|
|
36
|
+
"""Clear all stored data."""
|
|
37
|
+
self.messages.clear()
|
|
38
|
+
self.conversations.clear()
|
|
39
|
+
self.commands.clear()
|
|
40
|
+
|
|
41
|
+
async def filter_messages(self, query: SessionQuery) -> list[ChatMessage[str]]:
|
|
42
|
+
"""Filter messages from memory."""
|
|
43
|
+
from agentpool.messaging import ChatMessage
|
|
44
|
+
|
|
45
|
+
filtered = []
|
|
46
|
+
for msg in self.messages:
|
|
47
|
+
# Skip if conversation ID doesn't match
|
|
48
|
+
if query.name and msg["conversation_id"] != query.name:
|
|
49
|
+
continue
|
|
50
|
+
|
|
51
|
+
# Skip if agent name doesn't match
|
|
52
|
+
if query.agents and not (
|
|
53
|
+
msg["name"] in query.agents
|
|
54
|
+
or (
|
|
55
|
+
query.include_forwarded
|
|
56
|
+
and msg["forwarded_from"]
|
|
57
|
+
and any(a in query.agents for a in msg["forwarded_from"])
|
|
58
|
+
)
|
|
59
|
+
):
|
|
60
|
+
continue
|
|
61
|
+
|
|
62
|
+
# Skip if before cutoff time
|
|
63
|
+
if query.since and (cutoff := query.get_time_cutoff()): # noqa: SIM102
|
|
64
|
+
if msg["timestamp"] < cutoff:
|
|
65
|
+
continue
|
|
66
|
+
|
|
67
|
+
# Skip if after until time
|
|
68
|
+
if query.until and msg["timestamp"] > datetime.fromisoformat(query.until):
|
|
69
|
+
continue
|
|
70
|
+
|
|
71
|
+
# Skip if content doesn't match search
|
|
72
|
+
if query.contains and query.contains not in msg["content"]:
|
|
73
|
+
continue
|
|
74
|
+
|
|
75
|
+
# Skip if role doesn't match
|
|
76
|
+
if query.roles and msg["role"] not in query.roles:
|
|
77
|
+
continue
|
|
78
|
+
|
|
79
|
+
# Convert cost info
|
|
80
|
+
cost_info = None
|
|
81
|
+
if msg["cost_info"]:
|
|
82
|
+
total = msg.get("cost", 0.0)
|
|
83
|
+
cost_info = TokenCost(token_usage=msg["cost_info"], total_cost=total)
|
|
84
|
+
|
|
85
|
+
# Create ChatMessage
|
|
86
|
+
chat_message = ChatMessage(
|
|
87
|
+
content=msg["content"],
|
|
88
|
+
role=msg["role"],
|
|
89
|
+
name=msg["name"],
|
|
90
|
+
model_name=msg["model"],
|
|
91
|
+
cost_info=cost_info,
|
|
92
|
+
response_time=msg["response_time"],
|
|
93
|
+
forwarded_from=msg["forwarded_from"] or [],
|
|
94
|
+
timestamp=msg["timestamp"],
|
|
95
|
+
provider_name=msg["provider_name"],
|
|
96
|
+
provider_response_id=msg["provider_response_id"],
|
|
97
|
+
messages=deserialize_messages(msg["messages"]),
|
|
98
|
+
finish_reason=msg["finish_reason"],
|
|
99
|
+
)
|
|
100
|
+
filtered.append(chat_message)
|
|
101
|
+
|
|
102
|
+
# Apply limit if specified
|
|
103
|
+
if query.limit and len(filtered) >= query.limit:
|
|
104
|
+
break
|
|
105
|
+
|
|
106
|
+
return filtered
|
|
107
|
+
|
|
108
|
+
async def log_message(
|
|
109
|
+
self,
|
|
110
|
+
*,
|
|
111
|
+
conversation_id: str,
|
|
112
|
+
message_id: str,
|
|
113
|
+
content: str,
|
|
114
|
+
role: str,
|
|
115
|
+
name: str | None = None,
|
|
116
|
+
cost_info: TokenCost | None = None,
|
|
117
|
+
model: str | None = None,
|
|
118
|
+
response_time: float | None = None,
|
|
119
|
+
forwarded_from: list[str] | None = None,
|
|
120
|
+
provider_name: str | None = None,
|
|
121
|
+
provider_response_id: str | None = None,
|
|
122
|
+
messages: str | None = None,
|
|
123
|
+
finish_reason: str | None = None,
|
|
124
|
+
) -> None:
|
|
125
|
+
"""Store message in memory."""
|
|
126
|
+
if next((i for i in self.messages if i["message_id"] == message_id), None):
|
|
127
|
+
msg = f"Duplicate message ID: {message_id}"
|
|
128
|
+
raise ValueError(msg)
|
|
129
|
+
|
|
130
|
+
self.messages.append({
|
|
131
|
+
"conversation_id": conversation_id,
|
|
132
|
+
"message_id": message_id,
|
|
133
|
+
"content": content,
|
|
134
|
+
"role": role,
|
|
135
|
+
"name": name,
|
|
136
|
+
"cost_info": cost_info.token_usage if cost_info else None,
|
|
137
|
+
"model": model,
|
|
138
|
+
"response_time": response_time,
|
|
139
|
+
"forwarded_from": forwarded_from,
|
|
140
|
+
"provider_name": provider_name,
|
|
141
|
+
"provider_response_id": provider_response_id,
|
|
142
|
+
"messages": messages,
|
|
143
|
+
"finish_reason": finish_reason,
|
|
144
|
+
"timestamp": get_now(),
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
async def log_conversation(
|
|
148
|
+
self,
|
|
149
|
+
*,
|
|
150
|
+
conversation_id: str,
|
|
151
|
+
node_name: str,
|
|
152
|
+
start_time: datetime | None = None,
|
|
153
|
+
) -> None:
|
|
154
|
+
"""Store conversation in memory."""
|
|
155
|
+
if next((i for i in self.conversations if i["id"] == conversation_id), None):
|
|
156
|
+
msg = f"Duplicate conversation ID: {conversation_id}"
|
|
157
|
+
raise ValueError(msg)
|
|
158
|
+
self.conversations.append({
|
|
159
|
+
"id": conversation_id,
|
|
160
|
+
"agent_name": node_name,
|
|
161
|
+
"title": None,
|
|
162
|
+
"start_time": start_time or get_now(),
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
async def update_conversation_title(
|
|
166
|
+
self,
|
|
167
|
+
conversation_id: str,
|
|
168
|
+
title: str,
|
|
169
|
+
) -> None:
|
|
170
|
+
"""Update the title of a conversation."""
|
|
171
|
+
for conv in self.conversations:
|
|
172
|
+
if conv["id"] == conversation_id:
|
|
173
|
+
conv["title"] = title
|
|
174
|
+
return
|
|
175
|
+
|
|
176
|
+
async def get_conversation_title(
|
|
177
|
+
self,
|
|
178
|
+
conversation_id: str,
|
|
179
|
+
) -> str | None:
|
|
180
|
+
"""Get the title of a conversation."""
|
|
181
|
+
for conv in self.conversations:
|
|
182
|
+
if conv["id"] == conversation_id:
|
|
183
|
+
return conv.get("title")
|
|
184
|
+
return None
|
|
185
|
+
|
|
186
|
+
async def log_command(
|
|
187
|
+
self,
|
|
188
|
+
*,
|
|
189
|
+
agent_name: str,
|
|
190
|
+
session_id: str,
|
|
191
|
+
command: str,
|
|
192
|
+
context_type: type | None = None,
|
|
193
|
+
metadata: dict[str, JsonValue] | None = None,
|
|
194
|
+
) -> None:
|
|
195
|
+
"""Store command in memory."""
|
|
196
|
+
self.commands.append({
|
|
197
|
+
"agent_name": agent_name,
|
|
198
|
+
"session_id": session_id,
|
|
199
|
+
"command": command,
|
|
200
|
+
"timestamp": get_now(),
|
|
201
|
+
"context_type": context_type.__name__ if context_type else None,
|
|
202
|
+
"metadata": metadata or {},
|
|
203
|
+
})
|
|
204
|
+
|
|
205
|
+
async def get_commands(
|
|
206
|
+
self,
|
|
207
|
+
agent_name: str,
|
|
208
|
+
session_id: str,
|
|
209
|
+
*,
|
|
210
|
+
limit: int | None = None,
|
|
211
|
+
current_session_only: bool = False,
|
|
212
|
+
) -> list[str]:
|
|
213
|
+
"""Get commands from memory."""
|
|
214
|
+
filtered = []
|
|
215
|
+
for cmd in reversed(self.commands): # newest first
|
|
216
|
+
if current_session_only and cmd["session_id"] != session_id:
|
|
217
|
+
continue
|
|
218
|
+
if not current_session_only and cmd["agent_name"] != agent_name:
|
|
219
|
+
continue
|
|
220
|
+
filtered.append(cmd["command"])
|
|
221
|
+
if limit and len(filtered) >= limit:
|
|
222
|
+
break
|
|
223
|
+
return filtered
|
|
224
|
+
|
|
225
|
+
async def get_conversations(
|
|
226
|
+
self,
|
|
227
|
+
filters: QueryFilters,
|
|
228
|
+
) -> list[tuple[ConversationData, Sequence[ChatMessage[str]]]]:
|
|
229
|
+
"""Get filtered conversations from memory."""
|
|
230
|
+
results: list[tuple[ConversationData, Sequence[ChatMessage[str]]]] = []
|
|
231
|
+
|
|
232
|
+
# First get matching conversations
|
|
233
|
+
convs = {}
|
|
234
|
+
for conv in self.conversations:
|
|
235
|
+
if filters.agent_name and conv["agent_name"] != filters.agent_name:
|
|
236
|
+
continue
|
|
237
|
+
if filters.since and conv["start_time"] < filters.since:
|
|
238
|
+
continue
|
|
239
|
+
convs[conv["id"]] = conv
|
|
240
|
+
|
|
241
|
+
# Then get messages for each conversation
|
|
242
|
+
for conv_id, conv in convs.items():
|
|
243
|
+
conv_messages: list[ChatMessage[str]] = []
|
|
244
|
+
for msg in self.messages:
|
|
245
|
+
if msg["conversation_id"] != conv_id:
|
|
246
|
+
continue
|
|
247
|
+
if filters.query and filters.query not in msg["content"]:
|
|
248
|
+
continue
|
|
249
|
+
if filters.model and msg["model"] != filters.model:
|
|
250
|
+
continue
|
|
251
|
+
|
|
252
|
+
cost_info = None
|
|
253
|
+
if msg["cost_info"]:
|
|
254
|
+
total = msg.get("cost", 0.0)
|
|
255
|
+
cost_info = TokenCost(token_usage=msg["cost_info"], total_cost=total)
|
|
256
|
+
|
|
257
|
+
chat_msg = ChatMessage[str](
|
|
258
|
+
content=msg["content"],
|
|
259
|
+
role=msg["role"],
|
|
260
|
+
name=msg["name"],
|
|
261
|
+
model_name=msg["model"],
|
|
262
|
+
cost_info=cost_info,
|
|
263
|
+
response_time=msg["response_time"],
|
|
264
|
+
forwarded_from=msg["forwarded_from"],
|
|
265
|
+
timestamp=msg["timestamp"],
|
|
266
|
+
)
|
|
267
|
+
conv_messages.append(chat_msg)
|
|
268
|
+
|
|
269
|
+
# Skip if no matching messages for content filter
|
|
270
|
+
if filters.query and not conv_messages:
|
|
271
|
+
continue
|
|
272
|
+
|
|
273
|
+
# Convert ChatMessages to MessageData format for ConversationData
|
|
274
|
+
message_data: list[MessageData] = [
|
|
275
|
+
cast(
|
|
276
|
+
"MessageData",
|
|
277
|
+
{
|
|
278
|
+
"role": msg.role,
|
|
279
|
+
"content": msg.content,
|
|
280
|
+
"timestamp": msg.timestamp.isoformat(),
|
|
281
|
+
"model": msg.model_name,
|
|
282
|
+
"name": msg.name,
|
|
283
|
+
"token_usage": msg.cost_info.token_usage if msg.cost_info else None,
|
|
284
|
+
"cost": msg.cost_info.total_cost if msg.cost_info else None,
|
|
285
|
+
"response_time": msg.response_time,
|
|
286
|
+
},
|
|
287
|
+
)
|
|
288
|
+
for msg in conv_messages
|
|
289
|
+
]
|
|
290
|
+
|
|
291
|
+
# Create conversation data with proper MessageData
|
|
292
|
+
conv_data = ConversationData(
|
|
293
|
+
id=conv_id,
|
|
294
|
+
agent=conv["agent_name"],
|
|
295
|
+
title=conv.get("title"),
|
|
296
|
+
start_time=conv["start_time"].isoformat(),
|
|
297
|
+
messages=message_data, # Now using properly typed MessageData
|
|
298
|
+
token_usage=self._aggregate_token_usage(conv_messages),
|
|
299
|
+
)
|
|
300
|
+
results.append((conv_data, conv_messages))
|
|
301
|
+
|
|
302
|
+
if filters.limit and len(results) >= filters.limit:
|
|
303
|
+
break
|
|
304
|
+
|
|
305
|
+
return results
|
|
306
|
+
|
|
307
|
+
async def get_conversation_stats(
|
|
308
|
+
self,
|
|
309
|
+
filters: StatsFilters,
|
|
310
|
+
) -> dict[str, dict[str, Any]]:
|
|
311
|
+
"""Get statistics from memory."""
|
|
312
|
+
# Collect raw data
|
|
313
|
+
rows = []
|
|
314
|
+
for msg in self.messages:
|
|
315
|
+
if msg["timestamp"] <= filters.cutoff:
|
|
316
|
+
continue
|
|
317
|
+
if filters.agent_name and msg["name"] != filters.agent_name:
|
|
318
|
+
continue
|
|
319
|
+
|
|
320
|
+
cost_info = None
|
|
321
|
+
if msg["cost_info"]:
|
|
322
|
+
total = msg.get("cost", 0.0)
|
|
323
|
+
cost_info = TokenCost(token_usage=msg["cost_info"], total_cost=total)
|
|
324
|
+
|
|
325
|
+
rows.append((msg["model"], msg["name"], msg["timestamp"], cost_info))
|
|
326
|
+
|
|
327
|
+
# Use base class aggregation
|
|
328
|
+
return self.aggregate_stats(rows, filters.group_by)
|
|
329
|
+
|
|
330
|
+
@staticmethod
|
|
331
|
+
def _aggregate_token_usage(messages: Sequence[ChatMessage[Any]]) -> TokenUsage:
|
|
332
|
+
"""Sum up tokens from a sequence of messages."""
|
|
333
|
+
total = prompt = completion = 0
|
|
334
|
+
for msg in messages:
|
|
335
|
+
if msg.cost_info:
|
|
336
|
+
total += msg.cost_info.token_usage.total_tokens
|
|
337
|
+
prompt += msg.cost_info.token_usage.input_tokens
|
|
338
|
+
completion += msg.cost_info.token_usage.output_tokens
|
|
339
|
+
return {"total": total, "prompt": prompt, "completion": completion}
|
|
340
|
+
|
|
341
|
+
async def reset(
|
|
342
|
+
self,
|
|
343
|
+
*,
|
|
344
|
+
agent_name: str | None = None,
|
|
345
|
+
hard: bool = False,
|
|
346
|
+
) -> tuple[int, int]:
|
|
347
|
+
"""Reset stored data."""
|
|
348
|
+
# Get counts first
|
|
349
|
+
conv_count, msg_count = await self.get_conversation_counts(agent_name=agent_name)
|
|
350
|
+
|
|
351
|
+
if hard:
|
|
352
|
+
if agent_name:
|
|
353
|
+
msg = "Hard reset cannot be used with agent_name"
|
|
354
|
+
raise ValueError(msg)
|
|
355
|
+
# Clear everything
|
|
356
|
+
self.cleanup()
|
|
357
|
+
return conv_count, msg_count
|
|
358
|
+
|
|
359
|
+
if agent_name:
|
|
360
|
+
# Filter out data for specific agent
|
|
361
|
+
self.conversations = [c for c in self.conversations if c["agent_name"] != agent_name]
|
|
362
|
+
self.messages = [
|
|
363
|
+
m
|
|
364
|
+
for m in self.messages
|
|
365
|
+
if m["conversation_id"]
|
|
366
|
+
not in {c["id"] for c in self.conversations if c["agent_name"] == agent_name}
|
|
367
|
+
]
|
|
368
|
+
else:
|
|
369
|
+
# Clear all
|
|
370
|
+
self.messages.clear()
|
|
371
|
+
self.conversations.clear()
|
|
372
|
+
self.commands.clear()
|
|
373
|
+
|
|
374
|
+
return conv_count, msg_count
|
|
375
|
+
|
|
376
|
+
async def get_conversation_counts(
|
|
377
|
+
self,
|
|
378
|
+
*,
|
|
379
|
+
agent_name: str | None = None,
|
|
380
|
+
) -> tuple[int, int]:
|
|
381
|
+
"""Get conversation and message counts."""
|
|
382
|
+
if agent_name:
|
|
383
|
+
conv_count = sum(1 for c in self.conversations if c["agent_name"] == agent_name)
|
|
384
|
+
msg_count = sum(
|
|
385
|
+
1
|
|
386
|
+
for m in self.messages
|
|
387
|
+
if any(
|
|
388
|
+
c["id"] == m["conversation_id"] and c["agent_name"] == agent_name
|
|
389
|
+
for c in self.conversations
|
|
390
|
+
)
|
|
391
|
+
)
|
|
392
|
+
else:
|
|
393
|
+
conv_count = len(self.conversations)
|
|
394
|
+
msg_count = len(self.messages)
|
|
395
|
+
|
|
396
|
+
return conv_count, msg_count
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"""Data classes for storing agent data."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from typing import TYPE_CHECKING, Literal, TypedDict
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from datetime import datetime
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
GroupBy = Literal["agent", "model", "hour", "day"]
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class TokenUsage(TypedDict):
|
|
17
|
+
"""Token usage statistics from model responses."""
|
|
18
|
+
|
|
19
|
+
total: int
|
|
20
|
+
"""Total tokens used"""
|
|
21
|
+
prompt: int
|
|
22
|
+
"""Tokens used in the prompt"""
|
|
23
|
+
completion: int
|
|
24
|
+
"""Tokens used in the completion"""
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class MessageData(TypedDict):
|
|
28
|
+
"""Formatted message data."""
|
|
29
|
+
|
|
30
|
+
role: str
|
|
31
|
+
"""Role of the message sender (user/assistant/system)"""
|
|
32
|
+
|
|
33
|
+
content: str
|
|
34
|
+
"""Content of the message"""
|
|
35
|
+
|
|
36
|
+
timestamp: str
|
|
37
|
+
"""When the message was sent (ISO format)"""
|
|
38
|
+
|
|
39
|
+
model: str | None
|
|
40
|
+
"""Name of the model that generated this message"""
|
|
41
|
+
|
|
42
|
+
name: str | None
|
|
43
|
+
"""Display name of the sender"""
|
|
44
|
+
|
|
45
|
+
token_usage: TokenUsage | None
|
|
46
|
+
"""Token usage statistics if available"""
|
|
47
|
+
|
|
48
|
+
cost: float | None
|
|
49
|
+
"""Cost of generating this message in USD"""
|
|
50
|
+
|
|
51
|
+
response_time: float | None
|
|
52
|
+
"""Time taken to generate the response in seconds"""
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class ConversationData(TypedDict):
|
|
56
|
+
"""Formatted conversation data."""
|
|
57
|
+
|
|
58
|
+
id: str
|
|
59
|
+
"""Unique identifier for the conversation"""
|
|
60
|
+
|
|
61
|
+
agent: str
|
|
62
|
+
"""Name of the agent that handled this conversation"""
|
|
63
|
+
|
|
64
|
+
title: str | None
|
|
65
|
+
"""AI-generated or user-provided conversation title"""
|
|
66
|
+
|
|
67
|
+
start_time: str
|
|
68
|
+
"""When the conversation started (ISO format)"""
|
|
69
|
+
|
|
70
|
+
messages: list[MessageData]
|
|
71
|
+
"""List of messages in this conversation"""
|
|
72
|
+
|
|
73
|
+
token_usage: TokenUsage | None
|
|
74
|
+
"""Aggregated token usage for the entire conversation"""
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
@dataclass
|
|
78
|
+
class QueryFilters:
|
|
79
|
+
"""Filters for conversation queries."""
|
|
80
|
+
|
|
81
|
+
agent_name: str | None = None
|
|
82
|
+
"""Filter by specific agent name"""
|
|
83
|
+
|
|
84
|
+
since: datetime | None = None
|
|
85
|
+
"""Only include conversations after this time"""
|
|
86
|
+
|
|
87
|
+
query: str | None = None
|
|
88
|
+
"""Search term to filter message content"""
|
|
89
|
+
|
|
90
|
+
model: str | None = None
|
|
91
|
+
"""Filter by model name"""
|
|
92
|
+
|
|
93
|
+
limit: int | None = None
|
|
94
|
+
"""Maximum number of conversations to return"""
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
@dataclass
|
|
98
|
+
class StatsFilters:
|
|
99
|
+
"""Filters for statistics queries."""
|
|
100
|
+
|
|
101
|
+
cutoff: datetime
|
|
102
|
+
"""Only include data after this time"""
|
|
103
|
+
|
|
104
|
+
group_by: GroupBy
|
|
105
|
+
"""How to group the statistics (agent/model/hour/day)"""
|
|
106
|
+
|
|
107
|
+
agent_name: str | None = None
|
|
108
|
+
"""Filter statistics to specific agent"""
|
|
File without changes
|