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,310 @@
|
|
|
1
|
+
"""Storage provider base class."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections import defaultdict
|
|
6
|
+
from datetime import datetime
|
|
7
|
+
from typing import TYPE_CHECKING, Any, Literal, Self
|
|
8
|
+
from uuid import uuid4
|
|
9
|
+
|
|
10
|
+
from agentpool.utils.tasks import TaskManager
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
from collections.abc import Sequence
|
|
15
|
+
from datetime import datetime
|
|
16
|
+
from types import TracebackType
|
|
17
|
+
|
|
18
|
+
from pydantic_ai import FinishReason
|
|
19
|
+
|
|
20
|
+
from agentpool.common_types import JsonValue
|
|
21
|
+
from agentpool.messaging import ChatMessage, TokenCost
|
|
22
|
+
from agentpool_config.session import SessionQuery
|
|
23
|
+
from agentpool_config.storage import BaseStorageProviderConfig
|
|
24
|
+
from agentpool_storage.models import ConversationData, QueryFilters, StatsFilters
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class StoredMessage:
|
|
28
|
+
"""Base class for stored message data."""
|
|
29
|
+
|
|
30
|
+
id: str
|
|
31
|
+
conversation_id: str
|
|
32
|
+
timestamp: datetime
|
|
33
|
+
role: str
|
|
34
|
+
content: str
|
|
35
|
+
name: str | None = None
|
|
36
|
+
model: str | None = None
|
|
37
|
+
token_usage: dict[str, int] | None = None
|
|
38
|
+
cost: float | None = None
|
|
39
|
+
response_time: float | None = None
|
|
40
|
+
forwarded_from: list[str] | None = None
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class StoredConversation:
|
|
44
|
+
"""Base class for stored conversation data."""
|
|
45
|
+
|
|
46
|
+
id: str
|
|
47
|
+
agent_name: str
|
|
48
|
+
start_time: datetime
|
|
49
|
+
total_tokens: int = 0
|
|
50
|
+
total_cost: float = 0.0
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class StorageProvider:
|
|
54
|
+
"""Base class for storage providers."""
|
|
55
|
+
|
|
56
|
+
can_load_history: bool = False
|
|
57
|
+
"""Whether this provider supports loading history."""
|
|
58
|
+
|
|
59
|
+
def __init__(self, config: BaseStorageProviderConfig) -> None:
|
|
60
|
+
super().__init__()
|
|
61
|
+
self.config = config
|
|
62
|
+
self.task_manager = TaskManager()
|
|
63
|
+
self.log_messages = config.log_messages
|
|
64
|
+
self.log_conversations = config.log_conversations
|
|
65
|
+
self.log_commands = config.log_commands
|
|
66
|
+
self.log_context = config.log_context
|
|
67
|
+
|
|
68
|
+
async def __aenter__(self) -> Self:
|
|
69
|
+
"""Initialize provider resources."""
|
|
70
|
+
return self
|
|
71
|
+
|
|
72
|
+
async def __aexit__(
|
|
73
|
+
self,
|
|
74
|
+
exc_type: type[BaseException] | None,
|
|
75
|
+
exc_val: BaseException | None,
|
|
76
|
+
exc_tb: TracebackType | None,
|
|
77
|
+
) -> None:
|
|
78
|
+
"""Clean up provider resources."""
|
|
79
|
+
self.cleanup()
|
|
80
|
+
|
|
81
|
+
def cleanup(self) -> None:
|
|
82
|
+
"""Clean up resources."""
|
|
83
|
+
|
|
84
|
+
def should_log_agent(self, agent_name: str) -> bool:
|
|
85
|
+
"""Check if this provider should log the given agent."""
|
|
86
|
+
return self.config.agents is None or agent_name in self.config.agents
|
|
87
|
+
|
|
88
|
+
async def filter_messages(self, query: SessionQuery) -> list[ChatMessage[str]]:
|
|
89
|
+
"""Get messages matching query (if supported)."""
|
|
90
|
+
msg = f"{self.__class__.__name__} does not support loading history"
|
|
91
|
+
raise NotImplementedError(msg)
|
|
92
|
+
|
|
93
|
+
async def log_message(
|
|
94
|
+
self,
|
|
95
|
+
*,
|
|
96
|
+
conversation_id: str,
|
|
97
|
+
message_id: str,
|
|
98
|
+
content: str,
|
|
99
|
+
role: str,
|
|
100
|
+
name: str | None = None,
|
|
101
|
+
cost_info: TokenCost | None = None,
|
|
102
|
+
model: str | None = None,
|
|
103
|
+
response_time: float | None = None,
|
|
104
|
+
forwarded_from: list[str] | None = None,
|
|
105
|
+
provider_name: str | None = None,
|
|
106
|
+
provider_response_id: str | None = None,
|
|
107
|
+
messages: str | None = None,
|
|
108
|
+
finish_reason: FinishReason | None = None,
|
|
109
|
+
) -> None:
|
|
110
|
+
"""Log a message (if supported)."""
|
|
111
|
+
|
|
112
|
+
async def log_conversation(
|
|
113
|
+
self,
|
|
114
|
+
*,
|
|
115
|
+
conversation_id: str,
|
|
116
|
+
node_name: str,
|
|
117
|
+
start_time: datetime | None = None,
|
|
118
|
+
) -> None:
|
|
119
|
+
"""Log a conversation (if supported)."""
|
|
120
|
+
|
|
121
|
+
async def update_conversation_title(
|
|
122
|
+
self,
|
|
123
|
+
conversation_id: str,
|
|
124
|
+
title: str,
|
|
125
|
+
) -> None:
|
|
126
|
+
"""Update the title of a conversation.
|
|
127
|
+
|
|
128
|
+
Args:
|
|
129
|
+
conversation_id: ID of the conversation to update
|
|
130
|
+
title: New title for the conversation
|
|
131
|
+
"""
|
|
132
|
+
|
|
133
|
+
async def get_conversation_title(
|
|
134
|
+
self,
|
|
135
|
+
conversation_id: str,
|
|
136
|
+
) -> str | None:
|
|
137
|
+
"""Get the title of a conversation.
|
|
138
|
+
|
|
139
|
+
Args:
|
|
140
|
+
conversation_id: ID of the conversation
|
|
141
|
+
|
|
142
|
+
Returns:
|
|
143
|
+
The conversation title, or None if not set or conversation doesn't exist.
|
|
144
|
+
"""
|
|
145
|
+
return None
|
|
146
|
+
|
|
147
|
+
async def log_command(
|
|
148
|
+
self,
|
|
149
|
+
*,
|
|
150
|
+
agent_name: str,
|
|
151
|
+
session_id: str,
|
|
152
|
+
command: str,
|
|
153
|
+
context_type: type | None = None,
|
|
154
|
+
metadata: dict[str, JsonValue] | None = None,
|
|
155
|
+
) -> None:
|
|
156
|
+
"""Log a command (if supported)."""
|
|
157
|
+
|
|
158
|
+
async def get_commands(
|
|
159
|
+
self,
|
|
160
|
+
agent_name: str,
|
|
161
|
+
session_id: str,
|
|
162
|
+
*,
|
|
163
|
+
limit: int | None = None,
|
|
164
|
+
current_session_only: bool = False,
|
|
165
|
+
) -> list[str]:
|
|
166
|
+
"""Get command history (if supported)."""
|
|
167
|
+
msg = f"{self.__class__.__name__} does not support retrieving commands"
|
|
168
|
+
raise NotImplementedError(msg)
|
|
169
|
+
|
|
170
|
+
async def log_context_message(
|
|
171
|
+
self,
|
|
172
|
+
*,
|
|
173
|
+
conversation_id: str,
|
|
174
|
+
content: str,
|
|
175
|
+
role: str,
|
|
176
|
+
name: str | None = None,
|
|
177
|
+
model: str | None = None,
|
|
178
|
+
message_id: str | None = None,
|
|
179
|
+
metadata: dict[str, Any] | None = None,
|
|
180
|
+
) -> None:
|
|
181
|
+
"""Log a context message if context logging is enabled."""
|
|
182
|
+
if not self.log_context:
|
|
183
|
+
return
|
|
184
|
+
|
|
185
|
+
await self.log_message(
|
|
186
|
+
conversation_id=conversation_id,
|
|
187
|
+
message_id=message_id or str(uuid4()),
|
|
188
|
+
content=content,
|
|
189
|
+
role=role,
|
|
190
|
+
name=name,
|
|
191
|
+
model=model,
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
async def get_conversations(
|
|
195
|
+
self,
|
|
196
|
+
filters: QueryFilters,
|
|
197
|
+
) -> list[tuple[ConversationData, Sequence[ChatMessage[str]]]]:
|
|
198
|
+
"""Get filtered conversations with their messages.
|
|
199
|
+
|
|
200
|
+
Args:
|
|
201
|
+
filters: Query filters to apply
|
|
202
|
+
"""
|
|
203
|
+
msg = f"{self.__class__.__name__} does not support conversation queries"
|
|
204
|
+
raise NotImplementedError(msg)
|
|
205
|
+
|
|
206
|
+
async def get_filtered_conversations(
|
|
207
|
+
self,
|
|
208
|
+
agent_name: str | None = None,
|
|
209
|
+
period: str | None = None,
|
|
210
|
+
since: datetime | None = None,
|
|
211
|
+
query: str | None = None,
|
|
212
|
+
model: str | None = None,
|
|
213
|
+
limit: int | None = None,
|
|
214
|
+
*,
|
|
215
|
+
compact: bool = False,
|
|
216
|
+
include_tokens: bool = False,
|
|
217
|
+
) -> list[ConversationData]:
|
|
218
|
+
"""Get filtered conversations with formatted output.
|
|
219
|
+
|
|
220
|
+
Args:
|
|
221
|
+
agent_name: Filter by agent name
|
|
222
|
+
period: Time period to include (e.g. "1h", "2d")
|
|
223
|
+
since: Only show conversations after this time
|
|
224
|
+
query: Search in message content
|
|
225
|
+
model: Filter by model used
|
|
226
|
+
limit: Maximum number of conversations
|
|
227
|
+
compact: Only show first/last message of each conversation
|
|
228
|
+
include_tokens: Include token usage statistics
|
|
229
|
+
"""
|
|
230
|
+
msg = f"{self.__class__.__name__} does not support filtered conversations"
|
|
231
|
+
raise NotImplementedError(msg)
|
|
232
|
+
|
|
233
|
+
async def get_conversation_stats(
|
|
234
|
+
self,
|
|
235
|
+
filters: StatsFilters,
|
|
236
|
+
) -> dict[str, dict[str, Any]]:
|
|
237
|
+
"""Get conversation statistics grouped by specified criterion.
|
|
238
|
+
|
|
239
|
+
Args:
|
|
240
|
+
filters: Filters for statistics query
|
|
241
|
+
"""
|
|
242
|
+
msg = f"{self.__class__.__name__} does not support statistics"
|
|
243
|
+
raise NotImplementedError(msg)
|
|
244
|
+
|
|
245
|
+
def aggregate_stats(
|
|
246
|
+
self,
|
|
247
|
+
rows: Sequence[tuple[str | None, str | None, datetime, TokenCost | None]],
|
|
248
|
+
group_by: Literal["agent", "model", "hour", "day"],
|
|
249
|
+
) -> dict[str, dict[str, Any]]:
|
|
250
|
+
"""Aggregate statistics data by specified grouping.
|
|
251
|
+
|
|
252
|
+
Args:
|
|
253
|
+
rows: Raw stats data (model, agent, timestamp, token_usage)
|
|
254
|
+
group_by: How to group the statistics
|
|
255
|
+
"""
|
|
256
|
+
stats: dict[str, dict[str, Any]] = defaultdict(
|
|
257
|
+
lambda: {"total_tokens": 0, "messages": 0, "models": set()}
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
for model, agent, timestamp, token_usage in rows:
|
|
261
|
+
match group_by:
|
|
262
|
+
case "agent":
|
|
263
|
+
key = agent or "unknown"
|
|
264
|
+
case "model":
|
|
265
|
+
key = model or "unknown"
|
|
266
|
+
case "hour":
|
|
267
|
+
key = timestamp.strftime("%Y-%m-%d %H:00")
|
|
268
|
+
case "day":
|
|
269
|
+
key = timestamp.strftime("%Y-%m-%d")
|
|
270
|
+
|
|
271
|
+
entry = stats[key]
|
|
272
|
+
entry["messages"] += 1
|
|
273
|
+
if token_usage:
|
|
274
|
+
entry["total_tokens"] += token_usage.token_usage.total_tokens
|
|
275
|
+
if model:
|
|
276
|
+
entry["models"].add(model)
|
|
277
|
+
|
|
278
|
+
return stats
|
|
279
|
+
|
|
280
|
+
async def reset(
|
|
281
|
+
self,
|
|
282
|
+
*,
|
|
283
|
+
agent_name: str | None = None,
|
|
284
|
+
hard: bool = False,
|
|
285
|
+
) -> tuple[int, int]:
|
|
286
|
+
"""Reset storage, optionally for specific agent only.
|
|
287
|
+
|
|
288
|
+
Args:
|
|
289
|
+
agent_name: Only reset data for this agent
|
|
290
|
+
hard: Whether to completely reset storage (e.g., recreate tables)
|
|
291
|
+
|
|
292
|
+
Returns:
|
|
293
|
+
Tuple of (conversations deleted, messages deleted)
|
|
294
|
+
"""
|
|
295
|
+
raise NotImplementedError
|
|
296
|
+
|
|
297
|
+
async def get_conversation_counts(
|
|
298
|
+
self,
|
|
299
|
+
*,
|
|
300
|
+
agent_name: str | None = None,
|
|
301
|
+
) -> tuple[int, int]:
|
|
302
|
+
"""Get counts of conversations and messages.
|
|
303
|
+
|
|
304
|
+
Args:
|
|
305
|
+
agent_name: Only count data for this agent
|
|
306
|
+
|
|
307
|
+
Returns:
|
|
308
|
+
Tuple of (conversation count, message count)
|
|
309
|
+
"""
|
|
310
|
+
raise NotImplementedError
|
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
"""File provider implementation."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from datetime import datetime
|
|
6
|
+
from decimal import Decimal
|
|
7
|
+
from typing import TYPE_CHECKING, TypedDict, cast
|
|
8
|
+
|
|
9
|
+
from pydantic_ai import RunUsage
|
|
10
|
+
from upathtools import to_upath
|
|
11
|
+
|
|
12
|
+
from agentpool.common_types import JsonValue, MessageRole # noqa: TC001
|
|
13
|
+
from agentpool.log import get_logger
|
|
14
|
+
from agentpool.messaging import ChatMessage, TokenCost
|
|
15
|
+
from agentpool.storage import deserialize_messages
|
|
16
|
+
from agentpool.utils.now import get_now
|
|
17
|
+
from agentpool_storage.base import StorageProvider
|
|
18
|
+
from agentpool_storage.models import TokenUsage
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
if TYPE_CHECKING:
|
|
22
|
+
from pydantic_ai import FinishReason
|
|
23
|
+
from yamling import FormatType
|
|
24
|
+
|
|
25
|
+
from agentpool_config.session import SessionQuery
|
|
26
|
+
from agentpool_config.storage import FileStorageConfig
|
|
27
|
+
|
|
28
|
+
logger = get_logger(__name__)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class MessageData(TypedDict):
|
|
32
|
+
"""Data structure for storing message information."""
|
|
33
|
+
|
|
34
|
+
message_id: str
|
|
35
|
+
conversation_id: str
|
|
36
|
+
content: str
|
|
37
|
+
role: str
|
|
38
|
+
timestamp: str
|
|
39
|
+
name: str | None
|
|
40
|
+
model: str | None
|
|
41
|
+
cost: Decimal | None
|
|
42
|
+
token_usage: TokenUsage | None
|
|
43
|
+
response_time: float | None
|
|
44
|
+
forwarded_from: list[str] | None
|
|
45
|
+
provider_name: str | None
|
|
46
|
+
provider_response_id: str | None
|
|
47
|
+
messages: str | None
|
|
48
|
+
finish_reason: FinishReason | None
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class ConversationData(TypedDict):
|
|
52
|
+
"""Data structure for storing conversation information."""
|
|
53
|
+
|
|
54
|
+
id: str
|
|
55
|
+
agent_name: str
|
|
56
|
+
title: str | None
|
|
57
|
+
start_time: str
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class CommandData(TypedDict):
|
|
61
|
+
"""Data structure for storing command information."""
|
|
62
|
+
|
|
63
|
+
agent_name: str
|
|
64
|
+
session_id: str
|
|
65
|
+
command: str
|
|
66
|
+
timestamp: str
|
|
67
|
+
context_type: str | None
|
|
68
|
+
metadata: dict[str, JsonValue]
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class StorageData(TypedDict):
|
|
72
|
+
"""Data structure for storing storage information."""
|
|
73
|
+
|
|
74
|
+
messages: list[MessageData]
|
|
75
|
+
conversations: list[ConversationData]
|
|
76
|
+
commands: list[CommandData]
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
class FileProvider(StorageProvider):
|
|
80
|
+
"""File-based storage using various formats.
|
|
81
|
+
|
|
82
|
+
Automatically detects format from file extension or uses specified format.
|
|
83
|
+
Supported formats: YAML (.yml, .yaml), JSON (.json), TOML (.toml)
|
|
84
|
+
"""
|
|
85
|
+
|
|
86
|
+
can_load_history = True
|
|
87
|
+
|
|
88
|
+
def __init__(self, config: FileStorageConfig) -> None:
|
|
89
|
+
"""Initialize file provider.
|
|
90
|
+
|
|
91
|
+
Args:
|
|
92
|
+
config: Configuration for provider
|
|
93
|
+
"""
|
|
94
|
+
super().__init__(config)
|
|
95
|
+
self.path = to_upath(config.path)
|
|
96
|
+
self.format: FormatType = config.format
|
|
97
|
+
self.encoding = config.encoding
|
|
98
|
+
self._data: StorageData = {
|
|
99
|
+
"messages": [],
|
|
100
|
+
"conversations": [],
|
|
101
|
+
"commands": [],
|
|
102
|
+
}
|
|
103
|
+
self._load()
|
|
104
|
+
|
|
105
|
+
def _load(self) -> None:
|
|
106
|
+
"""Load data from file if it exists."""
|
|
107
|
+
import yamling
|
|
108
|
+
|
|
109
|
+
if self.path.exists():
|
|
110
|
+
self._data = yamling.load_file(
|
|
111
|
+
self.path,
|
|
112
|
+
self.format, # pyright: ignore
|
|
113
|
+
verify_type=StorageData,
|
|
114
|
+
)
|
|
115
|
+
self._save()
|
|
116
|
+
|
|
117
|
+
def _save(self) -> None:
|
|
118
|
+
"""Save current data to file."""
|
|
119
|
+
import yamling
|
|
120
|
+
|
|
121
|
+
self.path.parent.mkdir(parents=True, exist_ok=True)
|
|
122
|
+
yamling.dump_file(self._data, self.path, mode=self.format, overwrite=True)
|
|
123
|
+
|
|
124
|
+
def cleanup(self) -> None:
|
|
125
|
+
"""Save final state."""
|
|
126
|
+
self._save()
|
|
127
|
+
|
|
128
|
+
async def filter_messages(self, query: SessionQuery) -> list[ChatMessage[str]]:
|
|
129
|
+
"""Filter messages based on query."""
|
|
130
|
+
messages = []
|
|
131
|
+
for msg in self._data["messages"]:
|
|
132
|
+
# Apply filters
|
|
133
|
+
if query.name and msg["conversation_id"] != query.name:
|
|
134
|
+
continue
|
|
135
|
+
if query.agents and not (
|
|
136
|
+
msg["name"] in query.agents
|
|
137
|
+
or (
|
|
138
|
+
query.include_forwarded
|
|
139
|
+
and msg["forwarded_from"]
|
|
140
|
+
and any(a in query.agents for a in msg["forwarded_from"])
|
|
141
|
+
)
|
|
142
|
+
):
|
|
143
|
+
continue
|
|
144
|
+
cutoff = query.get_time_cutoff()
|
|
145
|
+
timestamp = datetime.fromisoformat(msg["timestamp"])
|
|
146
|
+
if query.since and cutoff and (timestamp < cutoff):
|
|
147
|
+
continue
|
|
148
|
+
if query.until and datetime.fromisoformat(msg["timestamp"]) > datetime.fromisoformat(
|
|
149
|
+
query.until
|
|
150
|
+
):
|
|
151
|
+
continue
|
|
152
|
+
if query.contains and query.contains not in msg["content"]:
|
|
153
|
+
continue
|
|
154
|
+
if query.roles and msg["role"] not in query.roles:
|
|
155
|
+
continue
|
|
156
|
+
|
|
157
|
+
# Convert to ChatMessage
|
|
158
|
+
cost_info = None
|
|
159
|
+
if msg["token_usage"]:
|
|
160
|
+
usage = msg["token_usage"]
|
|
161
|
+
cost = Decimal(msg["cost"] or 0.0)
|
|
162
|
+
cost_info = TokenCost(
|
|
163
|
+
token_usage=RunUsage(
|
|
164
|
+
input_tokens=usage["prompt"],
|
|
165
|
+
output_tokens=usage["completion"],
|
|
166
|
+
),
|
|
167
|
+
total_cost=cost,
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
chat_message = ChatMessage[str](
|
|
171
|
+
content=msg["content"],
|
|
172
|
+
conversation_id=msg["conversation_id"],
|
|
173
|
+
role=cast(MessageRole, msg["role"]),
|
|
174
|
+
name=msg["name"],
|
|
175
|
+
model_name=msg["model"],
|
|
176
|
+
cost_info=cost_info,
|
|
177
|
+
response_time=msg["response_time"],
|
|
178
|
+
forwarded_from=msg["forwarded_from"] or [],
|
|
179
|
+
timestamp=datetime.fromisoformat(msg["timestamp"]),
|
|
180
|
+
provider_name=msg["provider_name"],
|
|
181
|
+
provider_response_id=msg["provider_response_id"],
|
|
182
|
+
messages=deserialize_messages(msg["messages"]),
|
|
183
|
+
finish_reason=msg["finish_reason"],
|
|
184
|
+
)
|
|
185
|
+
messages.append(chat_message)
|
|
186
|
+
|
|
187
|
+
if query.limit and len(messages) >= query.limit:
|
|
188
|
+
break
|
|
189
|
+
|
|
190
|
+
return messages
|
|
191
|
+
|
|
192
|
+
async def log_message(
|
|
193
|
+
self,
|
|
194
|
+
*,
|
|
195
|
+
message_id: str,
|
|
196
|
+
conversation_id: str,
|
|
197
|
+
content: str,
|
|
198
|
+
role: str,
|
|
199
|
+
name: str | None = None,
|
|
200
|
+
cost_info: TokenCost | None = None,
|
|
201
|
+
model: str | None = None,
|
|
202
|
+
response_time: float | None = None,
|
|
203
|
+
forwarded_from: list[str] | None = None,
|
|
204
|
+
provider_name: str | None = None,
|
|
205
|
+
provider_response_id: str | None = None,
|
|
206
|
+
messages: str | None = None,
|
|
207
|
+
finish_reason: FinishReason | None = None,
|
|
208
|
+
) -> None:
|
|
209
|
+
"""Log a new message."""
|
|
210
|
+
self._data["messages"].append({
|
|
211
|
+
"conversation_id": conversation_id,
|
|
212
|
+
"message_id": message_id,
|
|
213
|
+
"content": content,
|
|
214
|
+
"role": cast(MessageRole, role),
|
|
215
|
+
"timestamp": get_now().isoformat(),
|
|
216
|
+
"name": name,
|
|
217
|
+
"model": model,
|
|
218
|
+
"cost": Decimal(cost_info.total_cost) if cost_info else None,
|
|
219
|
+
"token_usage": TokenUsage(
|
|
220
|
+
prompt=cost_info.token_usage.input_tokens if cost_info else 0,
|
|
221
|
+
completion=cost_info.token_usage.output_tokens if cost_info else 0,
|
|
222
|
+
total=cost_info.token_usage.total_tokens if cost_info else 0,
|
|
223
|
+
),
|
|
224
|
+
"response_time": response_time,
|
|
225
|
+
"forwarded_from": forwarded_from,
|
|
226
|
+
"provider_name": provider_name,
|
|
227
|
+
"provider_response_id": provider_response_id,
|
|
228
|
+
"messages": messages,
|
|
229
|
+
"finish_reason": finish_reason,
|
|
230
|
+
})
|
|
231
|
+
self._save()
|
|
232
|
+
|
|
233
|
+
async def log_conversation(
|
|
234
|
+
self,
|
|
235
|
+
*,
|
|
236
|
+
conversation_id: str,
|
|
237
|
+
node_name: str,
|
|
238
|
+
start_time: datetime | None = None,
|
|
239
|
+
) -> None:
|
|
240
|
+
"""Log a new conversation."""
|
|
241
|
+
conversation: ConversationData = {
|
|
242
|
+
"id": conversation_id,
|
|
243
|
+
"agent_name": node_name,
|
|
244
|
+
"title": None,
|
|
245
|
+
"start_time": (start_time or get_now()).isoformat(),
|
|
246
|
+
}
|
|
247
|
+
self._data["conversations"].append(conversation)
|
|
248
|
+
self._save()
|
|
249
|
+
|
|
250
|
+
async def update_conversation_title(
|
|
251
|
+
self,
|
|
252
|
+
conversation_id: str,
|
|
253
|
+
title: str,
|
|
254
|
+
) -> None:
|
|
255
|
+
"""Update the title of a conversation."""
|
|
256
|
+
for conv in self._data["conversations"]:
|
|
257
|
+
if conv["id"] == conversation_id:
|
|
258
|
+
conv["title"] = title
|
|
259
|
+
self._save()
|
|
260
|
+
return
|
|
261
|
+
|
|
262
|
+
async def get_conversation_title(
|
|
263
|
+
self,
|
|
264
|
+
conversation_id: str,
|
|
265
|
+
) -> str | None:
|
|
266
|
+
"""Get the title of a conversation."""
|
|
267
|
+
for conv in self._data["conversations"]:
|
|
268
|
+
if conv["id"] == conversation_id:
|
|
269
|
+
return conv.get("title")
|
|
270
|
+
return None
|
|
271
|
+
|
|
272
|
+
async def log_command(
|
|
273
|
+
self,
|
|
274
|
+
*,
|
|
275
|
+
agent_name: str,
|
|
276
|
+
session_id: str,
|
|
277
|
+
command: str,
|
|
278
|
+
context_type: type | None = None,
|
|
279
|
+
metadata: dict[str, JsonValue] | None = None,
|
|
280
|
+
) -> None:
|
|
281
|
+
"""Log a command execution."""
|
|
282
|
+
cmd: CommandData = {
|
|
283
|
+
"agent_name": agent_name,
|
|
284
|
+
"session_id": session_id,
|
|
285
|
+
"command": command,
|
|
286
|
+
"context_type": context_type.__name__ if context_type else None,
|
|
287
|
+
"metadata": metadata or {},
|
|
288
|
+
"timestamp": get_now().isoformat(),
|
|
289
|
+
}
|
|
290
|
+
self._data["commands"].append(cmd)
|
|
291
|
+
self._save()
|
|
292
|
+
|
|
293
|
+
async def get_commands(
|
|
294
|
+
self,
|
|
295
|
+
agent_name: str,
|
|
296
|
+
session_id: str,
|
|
297
|
+
*,
|
|
298
|
+
limit: int | None = None,
|
|
299
|
+
current_session_only: bool = False,
|
|
300
|
+
) -> list[str]:
|
|
301
|
+
"""Get command history."""
|
|
302
|
+
commands = []
|
|
303
|
+
for cmd in reversed(self._data["commands"]): # newest first
|
|
304
|
+
if current_session_only and cmd["session_id"] != session_id:
|
|
305
|
+
continue
|
|
306
|
+
if not current_session_only and cmd["agent_name"] != agent_name:
|
|
307
|
+
continue
|
|
308
|
+
commands.append(cmd["command"])
|
|
309
|
+
if limit and len(commands) >= limit:
|
|
310
|
+
break
|
|
311
|
+
return commands
|
|
312
|
+
|
|
313
|
+
async def reset(
|
|
314
|
+
self,
|
|
315
|
+
*,
|
|
316
|
+
agent_name: str | None = None,
|
|
317
|
+
hard: bool = False,
|
|
318
|
+
) -> tuple[int, int]:
|
|
319
|
+
"""Reset stored data."""
|
|
320
|
+
# Get counts first
|
|
321
|
+
conv_count, msg_count = await self.get_conversation_counts(agent_name=agent_name)
|
|
322
|
+
|
|
323
|
+
if hard:
|
|
324
|
+
if agent_name:
|
|
325
|
+
msg = "Hard reset cannot be used with agent_name"
|
|
326
|
+
raise ValueError(msg)
|
|
327
|
+
# Clear everything
|
|
328
|
+
self._data = {
|
|
329
|
+
"messages": [],
|
|
330
|
+
"conversations": [],
|
|
331
|
+
"commands": [],
|
|
332
|
+
}
|
|
333
|
+
self._save()
|
|
334
|
+
return conv_count, msg_count
|
|
335
|
+
|
|
336
|
+
if agent_name:
|
|
337
|
+
# Filter out data for specific agent
|
|
338
|
+
self._data["conversations"] = [
|
|
339
|
+
c for c in self._data["conversations"] if c["agent_name"] != agent_name
|
|
340
|
+
]
|
|
341
|
+
self._data["messages"] = [
|
|
342
|
+
m
|
|
343
|
+
for m in self._data["messages"]
|
|
344
|
+
if m["conversation_id"]
|
|
345
|
+
not in {
|
|
346
|
+
c["id"] for c in self._data["conversations"] if c["agent_name"] == agent_name
|
|
347
|
+
}
|
|
348
|
+
]
|
|
349
|
+
else:
|
|
350
|
+
# Clear all
|
|
351
|
+
self._data["messages"].clear()
|
|
352
|
+
self._data["conversations"].clear()
|
|
353
|
+
self._data["commands"].clear()
|
|
354
|
+
|
|
355
|
+
self._save()
|
|
356
|
+
return conv_count, msg_count
|
|
357
|
+
|
|
358
|
+
async def get_conversation_counts(
|
|
359
|
+
self,
|
|
360
|
+
*,
|
|
361
|
+
agent_name: str | None = None,
|
|
362
|
+
) -> tuple[int, int]:
|
|
363
|
+
"""Get conversation and message counts."""
|
|
364
|
+
if agent_name:
|
|
365
|
+
conv_count = sum(
|
|
366
|
+
1 for c in self._data["conversations"] if c["agent_name"] == agent_name
|
|
367
|
+
)
|
|
368
|
+
msg_count = sum(
|
|
369
|
+
1
|
|
370
|
+
for m in self._data["messages"]
|
|
371
|
+
if m["conversation_id"]
|
|
372
|
+
in {c["id"] for c in self._data["conversations"] if c["agent_name"] == agent_name}
|
|
373
|
+
)
|
|
374
|
+
else:
|
|
375
|
+
conv_count = len(self._data["conversations"])
|
|
376
|
+
msg_count = len(self._data["messages"])
|
|
377
|
+
|
|
378
|
+
return conv_count, msg_count
|