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,302 @@
|
|
|
1
|
+
"""Session manager for pool-level session lifecycle."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import asyncio
|
|
6
|
+
from typing import TYPE_CHECKING, Any, Self
|
|
7
|
+
from uuid import uuid4
|
|
8
|
+
|
|
9
|
+
from agentpool.log import get_logger
|
|
10
|
+
from agentpool.sessions.models import SessionData
|
|
11
|
+
from agentpool.sessions.session import ClientSession
|
|
12
|
+
from agentpool.sessions.store import MemorySessionStore
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
if TYPE_CHECKING:
|
|
16
|
+
from types import TracebackType
|
|
17
|
+
|
|
18
|
+
from agentpool.delegation.pool import AgentPool
|
|
19
|
+
from agentpool.sessions.store import SessionStore
|
|
20
|
+
|
|
21
|
+
logger = get_logger(__name__)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class SessionManager:
|
|
25
|
+
"""Manages session lifecycle at the pool level.
|
|
26
|
+
|
|
27
|
+
Handles:
|
|
28
|
+
- Session creation and initialization
|
|
29
|
+
- Active session tracking (in-memory)
|
|
30
|
+
- Session persistence via SessionStore
|
|
31
|
+
- Session resumption from storage
|
|
32
|
+
- Cleanup of expired sessions
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
def __init__(
|
|
36
|
+
self,
|
|
37
|
+
pool: AgentPool[Any],
|
|
38
|
+
store: SessionStore | None = None,
|
|
39
|
+
pool_id: str | None = None,
|
|
40
|
+
) -> None:
|
|
41
|
+
"""Initialize session manager.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
pool: Agent pool for agent access
|
|
45
|
+
store: Session persistence backend (defaults to MemorySessionStore)
|
|
46
|
+
pool_id: Optional identifier for this pool (for multi-pool setups)
|
|
47
|
+
"""
|
|
48
|
+
self._pool = pool
|
|
49
|
+
self._store = store or MemorySessionStore()
|
|
50
|
+
self._pool_id = pool_id
|
|
51
|
+
self._active: dict[str, ClientSession] = {}
|
|
52
|
+
self._lock = asyncio.Lock()
|
|
53
|
+
logger.debug("Initialized session manager", pool_id=pool_id)
|
|
54
|
+
|
|
55
|
+
@property
|
|
56
|
+
def pool(self) -> AgentPool[Any]:
|
|
57
|
+
"""Get the agent pool."""
|
|
58
|
+
return self._pool
|
|
59
|
+
|
|
60
|
+
@property
|
|
61
|
+
def store(self) -> SessionStore:
|
|
62
|
+
"""Get the session store."""
|
|
63
|
+
return self._store
|
|
64
|
+
|
|
65
|
+
@property
|
|
66
|
+
def active_sessions(self) -> dict[str, ClientSession]:
|
|
67
|
+
"""Get currently active sessions (read-only view)."""
|
|
68
|
+
return dict(self._active)
|
|
69
|
+
|
|
70
|
+
async def __aenter__(self) -> Self:
|
|
71
|
+
"""Enter context and initialize store."""
|
|
72
|
+
await self._store.__aenter__()
|
|
73
|
+
return self
|
|
74
|
+
|
|
75
|
+
async def __aexit__(
|
|
76
|
+
self,
|
|
77
|
+
exc_type: type[BaseException] | None,
|
|
78
|
+
exc_val: BaseException | None,
|
|
79
|
+
exc_tb: TracebackType | None,
|
|
80
|
+
) -> None:
|
|
81
|
+
"""Exit context and clean up all sessions."""
|
|
82
|
+
# Close all active sessions
|
|
83
|
+
async with self._lock:
|
|
84
|
+
sessions = list(self._active.values())
|
|
85
|
+
self._active.clear()
|
|
86
|
+
|
|
87
|
+
for session in sessions:
|
|
88
|
+
try:
|
|
89
|
+
await session.close()
|
|
90
|
+
except Exception:
|
|
91
|
+
logger.exception("Error closing session", session_id=session.session_id)
|
|
92
|
+
|
|
93
|
+
await self._store.__aexit__(exc_type, exc_val, exc_tb)
|
|
94
|
+
logger.debug("Session manager closed", session_count=len(sessions))
|
|
95
|
+
|
|
96
|
+
def generate_session_id(self) -> str:
|
|
97
|
+
"""Generate a unique session ID."""
|
|
98
|
+
return f"sess_{uuid4().hex[:12]}"
|
|
99
|
+
|
|
100
|
+
async def create(
|
|
101
|
+
self,
|
|
102
|
+
agent_name: str,
|
|
103
|
+
*,
|
|
104
|
+
session_id: str | None = None,
|
|
105
|
+
cwd: str | None = None,
|
|
106
|
+
conversation_id: str | None = None,
|
|
107
|
+
metadata: dict[str, Any] | None = None,
|
|
108
|
+
session_class: type[ClientSession] = ClientSession,
|
|
109
|
+
**session_kwargs: Any,
|
|
110
|
+
) -> ClientSession:
|
|
111
|
+
"""Create a new session.
|
|
112
|
+
|
|
113
|
+
Args:
|
|
114
|
+
agent_name: Name of the initial agent
|
|
115
|
+
session_id: Optional specific session ID (generated if None)
|
|
116
|
+
cwd: Working directory for the session
|
|
117
|
+
conversation_id: Optional conversation ID (generated if None)
|
|
118
|
+
metadata: Optional session metadata
|
|
119
|
+
session_class: Session class to instantiate (for protocol-specific sessions)
|
|
120
|
+
**session_kwargs: Additional kwargs passed to session constructor
|
|
121
|
+
|
|
122
|
+
Returns:
|
|
123
|
+
Created session instance
|
|
124
|
+
|
|
125
|
+
Raises:
|
|
126
|
+
ValueError: If session_id already exists
|
|
127
|
+
KeyError: If agent_name not found in pool
|
|
128
|
+
"""
|
|
129
|
+
# Validate agent exists
|
|
130
|
+
if agent_name not in self._pool.all_agents:
|
|
131
|
+
msg = f"Agent '{agent_name}' not found in pool"
|
|
132
|
+
raise KeyError(msg)
|
|
133
|
+
|
|
134
|
+
async with self._lock:
|
|
135
|
+
# Generate or validate session ID
|
|
136
|
+
if session_id is None:
|
|
137
|
+
session_id = self.generate_session_id()
|
|
138
|
+
elif session_id in self._active:
|
|
139
|
+
msg = f"Session '{session_id}' already exists"
|
|
140
|
+
raise ValueError(msg)
|
|
141
|
+
|
|
142
|
+
# Create session data
|
|
143
|
+
data = SessionData(
|
|
144
|
+
session_id=session_id,
|
|
145
|
+
agent_name=agent_name,
|
|
146
|
+
conversation_id=conversation_id or f"conv_{uuid4().hex[:12]}",
|
|
147
|
+
pool_id=self._pool_id,
|
|
148
|
+
cwd=cwd,
|
|
149
|
+
metadata=metadata or {},
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
# Persist to store
|
|
153
|
+
await self._store.save(data)
|
|
154
|
+
|
|
155
|
+
# Create runtime session
|
|
156
|
+
session = session_class(
|
|
157
|
+
data=data,
|
|
158
|
+
pool=self._pool,
|
|
159
|
+
manager=self,
|
|
160
|
+
**session_kwargs,
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
self._active[session_id] = session
|
|
164
|
+
logger.info(
|
|
165
|
+
"Created session",
|
|
166
|
+
session_id=session_id,
|
|
167
|
+
agent=agent_name,
|
|
168
|
+
)
|
|
169
|
+
return session
|
|
170
|
+
|
|
171
|
+
async def get(self, session_id: str) -> ClientSession | None:
|
|
172
|
+
"""Get an active session by ID.
|
|
173
|
+
|
|
174
|
+
Args:
|
|
175
|
+
session_id: Session identifier
|
|
176
|
+
|
|
177
|
+
Returns:
|
|
178
|
+
Active session if found, None otherwise
|
|
179
|
+
"""
|
|
180
|
+
return self._active.get(session_id)
|
|
181
|
+
|
|
182
|
+
async def resume(
|
|
183
|
+
self,
|
|
184
|
+
session_id: str,
|
|
185
|
+
session_class: type[ClientSession] = ClientSession,
|
|
186
|
+
**session_kwargs: Any,
|
|
187
|
+
) -> ClientSession | None:
|
|
188
|
+
"""Resume a session from storage.
|
|
189
|
+
|
|
190
|
+
Loads session data from store and creates a runtime session.
|
|
191
|
+
|
|
192
|
+
Args:
|
|
193
|
+
session_id: Session identifier
|
|
194
|
+
session_class: Session class to instantiate
|
|
195
|
+
**session_kwargs: Additional kwargs passed to session constructor
|
|
196
|
+
|
|
197
|
+
Returns:
|
|
198
|
+
Resumed session if found in store, None otherwise
|
|
199
|
+
"""
|
|
200
|
+
async with self._lock:
|
|
201
|
+
# Check if already active
|
|
202
|
+
if session_id in self._active:
|
|
203
|
+
return self._active[session_id]
|
|
204
|
+
|
|
205
|
+
# Try to load from store
|
|
206
|
+
data = await self._store.load(session_id)
|
|
207
|
+
if data is None:
|
|
208
|
+
return None
|
|
209
|
+
|
|
210
|
+
# Validate agent still exists
|
|
211
|
+
if data.agent_name not in self._pool.all_agents:
|
|
212
|
+
logger.warning(
|
|
213
|
+
"Session agent no longer exists",
|
|
214
|
+
session_id=session_id,
|
|
215
|
+
agent=data.agent_name,
|
|
216
|
+
)
|
|
217
|
+
return None
|
|
218
|
+
|
|
219
|
+
# Create runtime session
|
|
220
|
+
session = session_class(
|
|
221
|
+
data=data,
|
|
222
|
+
pool=self._pool,
|
|
223
|
+
manager=self,
|
|
224
|
+
**session_kwargs,
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
self._active[session_id] = session
|
|
228
|
+
logger.info("Resumed session", session_id=session_id)
|
|
229
|
+
return session
|
|
230
|
+
|
|
231
|
+
async def close(self, session_id: str, *, delete: bool = False) -> bool:
|
|
232
|
+
"""Close and optionally delete a session.
|
|
233
|
+
|
|
234
|
+
Args:
|
|
235
|
+
session_id: Session identifier
|
|
236
|
+
delete: Whether to also delete from store
|
|
237
|
+
|
|
238
|
+
Returns:
|
|
239
|
+
True if session was closed, False if not found
|
|
240
|
+
"""
|
|
241
|
+
async with self._lock:
|
|
242
|
+
session = self._active.pop(session_id, None)
|
|
243
|
+
|
|
244
|
+
if session:
|
|
245
|
+
await session.close()
|
|
246
|
+
if delete:
|
|
247
|
+
await self._store.delete(session_id)
|
|
248
|
+
logger.info("Closed session", session_id=session_id, deleted=delete)
|
|
249
|
+
return True
|
|
250
|
+
|
|
251
|
+
# Session not active, but maybe in store
|
|
252
|
+
if delete:
|
|
253
|
+
return await self._store.delete(session_id)
|
|
254
|
+
|
|
255
|
+
return False
|
|
256
|
+
|
|
257
|
+
async def save(self, data: SessionData) -> None:
|
|
258
|
+
"""Save session data to store.
|
|
259
|
+
|
|
260
|
+
Args:
|
|
261
|
+
data: Session data to persist
|
|
262
|
+
"""
|
|
263
|
+
await self._store.save(data)
|
|
264
|
+
|
|
265
|
+
async def list_sessions(
|
|
266
|
+
self,
|
|
267
|
+
*,
|
|
268
|
+
active_only: bool = False,
|
|
269
|
+
agent_name: str | None = None,
|
|
270
|
+
) -> list[str]:
|
|
271
|
+
"""List session IDs.
|
|
272
|
+
|
|
273
|
+
Args:
|
|
274
|
+
active_only: Only return currently active sessions
|
|
275
|
+
agent_name: Filter by agent name
|
|
276
|
+
|
|
277
|
+
Returns:
|
|
278
|
+
List of session IDs
|
|
279
|
+
"""
|
|
280
|
+
if active_only:
|
|
281
|
+
sessions = list(self._active.keys())
|
|
282
|
+
if agent_name:
|
|
283
|
+
sessions = [sid for sid, s in self._active.items() if s.agent_name == agent_name]
|
|
284
|
+
return sessions
|
|
285
|
+
|
|
286
|
+
return await self._store.list_sessions(
|
|
287
|
+
pool_id=self._pool_id,
|
|
288
|
+
agent_name=agent_name,
|
|
289
|
+
)
|
|
290
|
+
|
|
291
|
+
async def cleanup_expired(self, max_age_hours: int = 24) -> int:
|
|
292
|
+
"""Remove expired sessions from store.
|
|
293
|
+
|
|
294
|
+
Does not affect currently active sessions.
|
|
295
|
+
|
|
296
|
+
Args:
|
|
297
|
+
max_age_hours: Maximum session age in hours
|
|
298
|
+
|
|
299
|
+
Returns:
|
|
300
|
+
Number of sessions removed
|
|
301
|
+
"""
|
|
302
|
+
return await self._store.cleanup_expired(max_age_hours)
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"""Session data models."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from datetime import datetime
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from pydantic import Field
|
|
9
|
+
from schemez import Schema
|
|
10
|
+
|
|
11
|
+
from agentpool.utils.now import get_now
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class SessionData(Schema):
|
|
15
|
+
"""Persistable session state.
|
|
16
|
+
|
|
17
|
+
Contains all information needed to persist and restore a session.
|
|
18
|
+
Protocol-specific data (ACP capabilities, web cookies, etc.) goes in metadata.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
session_id: str
|
|
22
|
+
"""Unique session identifier."""
|
|
23
|
+
|
|
24
|
+
agent_name: str
|
|
25
|
+
"""Name of the currently active agent."""
|
|
26
|
+
|
|
27
|
+
conversation_id: str
|
|
28
|
+
"""Links to conversation in StorageManager."""
|
|
29
|
+
|
|
30
|
+
title: str | None = None
|
|
31
|
+
"""AI-generated or user-provided title for the conversation."""
|
|
32
|
+
|
|
33
|
+
pool_id: str | None = None
|
|
34
|
+
"""Optional pool/manifest identifier for multi-pool setups."""
|
|
35
|
+
|
|
36
|
+
cwd: str | None = None
|
|
37
|
+
"""Working directory for the session."""
|
|
38
|
+
|
|
39
|
+
created_at: datetime = Field(default_factory=get_now)
|
|
40
|
+
"""When the session was created."""
|
|
41
|
+
|
|
42
|
+
last_active: datetime = Field(default_factory=get_now)
|
|
43
|
+
"""Last activity timestamp."""
|
|
44
|
+
|
|
45
|
+
metadata: dict[str, Any] = Field(default_factory=dict)
|
|
46
|
+
"""Protocol-specific or custom metadata.
|
|
47
|
+
|
|
48
|
+
Examples:
|
|
49
|
+
- ACP: client_capabilities, mcp_servers
|
|
50
|
+
- Web: user_id, auth_token
|
|
51
|
+
- CLI: terminal_size, color_support
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
def touch(self) -> None:
|
|
55
|
+
"""Update last_active timestamp."""
|
|
56
|
+
# Note: Schema is frozen by default, so we need to work around that
|
|
57
|
+
# by using object.__setattr__ or making this field mutable
|
|
58
|
+
object.__setattr__(self, "last_active", get_now())
|
|
59
|
+
|
|
60
|
+
def with_agent(self, agent_name: str) -> SessionData:
|
|
61
|
+
"""Return copy with different agent."""
|
|
62
|
+
return self.model_copy(update={"agent_name": agent_name, "last_active": get_now()})
|
|
63
|
+
|
|
64
|
+
def with_metadata(self, **kwargs: Any) -> SessionData:
|
|
65
|
+
"""Return copy with updated metadata."""
|
|
66
|
+
new_metadata = {**self.metadata, **kwargs}
|
|
67
|
+
return self.model_copy(update={"metadata": new_metadata, "last_active": get_now()})
|
|
68
|
+
|
|
69
|
+
def with_title(self, title: str) -> SessionData:
|
|
70
|
+
"""Return copy with updated title."""
|
|
71
|
+
return self.model_copy(update={"title": title, "last_active": get_now()})
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
"""Protocol-agnostic client session."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import asyncio
|
|
6
|
+
from typing import TYPE_CHECKING, Any, Self
|
|
7
|
+
|
|
8
|
+
from agentpool.log import get_logger
|
|
9
|
+
from agentpool.messaging.message_history import MessageHistory
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from types import TracebackType
|
|
14
|
+
|
|
15
|
+
from agentpool.agents.agent import Agent
|
|
16
|
+
from agentpool.delegation.pool import AgentPool
|
|
17
|
+
from agentpool.messaging import ChatMessage
|
|
18
|
+
from agentpool.sessions.manager import SessionManager
|
|
19
|
+
from agentpool.sessions.models import SessionData
|
|
20
|
+
|
|
21
|
+
logger = get_logger(__name__)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class ClientSession:
|
|
25
|
+
"""Protocol-agnostic runtime session.
|
|
26
|
+
|
|
27
|
+
Base class for protocol-specific sessions (ACP, Web, etc.).
|
|
28
|
+
Manages the runtime state of an active session, including:
|
|
29
|
+
- Reference to session data (persistable state)
|
|
30
|
+
- Active agent instance
|
|
31
|
+
- Conversation history (owned by session, not agent)
|
|
32
|
+
- Pool access for agent switching
|
|
33
|
+
|
|
34
|
+
The session owns the conversation history and passes it to the agent
|
|
35
|
+
on each run. This makes the agent stateless from the session's perspective.
|
|
36
|
+
|
|
37
|
+
Subclasses add protocol-specific functionality:
|
|
38
|
+
- ACPSession: ACP connection, capabilities, slash commands
|
|
39
|
+
- WebSession: WebSocket handling, HTTP session state
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
def __init__(
|
|
43
|
+
self,
|
|
44
|
+
data: SessionData,
|
|
45
|
+
pool: AgentPool[Any],
|
|
46
|
+
manager: SessionManager | None = None,
|
|
47
|
+
) -> None:
|
|
48
|
+
"""Initialize client session.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
data: Persistable session state
|
|
52
|
+
pool: Agent pool for agent access and switching
|
|
53
|
+
manager: Optional session manager for lifecycle operations
|
|
54
|
+
"""
|
|
55
|
+
self._data = data
|
|
56
|
+
self._pool = pool
|
|
57
|
+
self._manager = manager
|
|
58
|
+
self._agent: Agent[Any, Any] | None = None
|
|
59
|
+
self._closed = False
|
|
60
|
+
self._title_generation_triggered = False
|
|
61
|
+
self._title_task: asyncio.Task[None] | None = None
|
|
62
|
+
# Session owns conversation history - agent is stateless
|
|
63
|
+
self._history = MessageHistory()
|
|
64
|
+
|
|
65
|
+
logger.debug(
|
|
66
|
+
"Created client session",
|
|
67
|
+
session_id=data.session_id,
|
|
68
|
+
agent=data.agent_name,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
@property
|
|
72
|
+
def session_id(self) -> str:
|
|
73
|
+
"""Get session identifier."""
|
|
74
|
+
return self._data.session_id
|
|
75
|
+
|
|
76
|
+
@property
|
|
77
|
+
def data(self) -> SessionData:
|
|
78
|
+
"""Get session data (persistable state)."""
|
|
79
|
+
return self._data
|
|
80
|
+
|
|
81
|
+
@property
|
|
82
|
+
def pool(self) -> AgentPool[Any]:
|
|
83
|
+
"""Get agent pool."""
|
|
84
|
+
return self._pool
|
|
85
|
+
|
|
86
|
+
@property
|
|
87
|
+
def agent(self) -> Agent[Any, Any]:
|
|
88
|
+
"""Get current active agent, creating if needed."""
|
|
89
|
+
if self._agent is None:
|
|
90
|
+
self._agent = self._pool.get_agent(self._data.agent_name)
|
|
91
|
+
return self._agent
|
|
92
|
+
|
|
93
|
+
@property
|
|
94
|
+
def agent_name(self) -> str:
|
|
95
|
+
"""Get current agent name."""
|
|
96
|
+
return self._data.agent_name
|
|
97
|
+
|
|
98
|
+
@property
|
|
99
|
+
def conversation_id(self) -> str:
|
|
100
|
+
"""Get conversation ID for message storage."""
|
|
101
|
+
return self._data.conversation_id
|
|
102
|
+
|
|
103
|
+
@property
|
|
104
|
+
def history(self) -> MessageHistory:
|
|
105
|
+
"""Get the session's conversation history."""
|
|
106
|
+
return self._history
|
|
107
|
+
|
|
108
|
+
@property
|
|
109
|
+
def is_closed(self) -> bool:
|
|
110
|
+
"""Check if session is closed."""
|
|
111
|
+
return self._closed
|
|
112
|
+
|
|
113
|
+
async def __aenter__(self) -> Self:
|
|
114
|
+
"""Enter session context."""
|
|
115
|
+
return self
|
|
116
|
+
|
|
117
|
+
async def __aexit__(
|
|
118
|
+
self,
|
|
119
|
+
exc_type: type[BaseException] | None,
|
|
120
|
+
exc_val: BaseException | None,
|
|
121
|
+
exc_tb: TracebackType | None,
|
|
122
|
+
) -> None:
|
|
123
|
+
"""Exit session context."""
|
|
124
|
+
await self.close()
|
|
125
|
+
|
|
126
|
+
async def run(self, prompt: str, **kwargs: Any) -> ChatMessage[Any]:
|
|
127
|
+
"""Run the agent with a prompt, using session's history.
|
|
128
|
+
|
|
129
|
+
The session passes its own MessageHistory to the agent, making
|
|
130
|
+
the agent stateless from the session's perspective. Messages
|
|
131
|
+
are automatically added to the session's history.
|
|
132
|
+
|
|
133
|
+
Args:
|
|
134
|
+
prompt: User prompt to send to the agent
|
|
135
|
+
**kwargs: Additional arguments passed to agent.run()
|
|
136
|
+
|
|
137
|
+
Returns:
|
|
138
|
+
The agent's response message
|
|
139
|
+
"""
|
|
140
|
+
result = await self.agent.run(
|
|
141
|
+
prompt,
|
|
142
|
+
message_history=self._history,
|
|
143
|
+
conversation_id=self.conversation_id,
|
|
144
|
+
**kwargs,
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
# Trigger title generation after first exchange (fire-and-forget)
|
|
148
|
+
# Note: Message logging is handled by the agent itself via MessageNode.log_message
|
|
149
|
+
if not self._title_generation_triggered and self._pool.storage:
|
|
150
|
+
self._title_generation_triggered = True
|
|
151
|
+
self._title_task = asyncio.create_task(self._generate_title())
|
|
152
|
+
|
|
153
|
+
return result
|
|
154
|
+
|
|
155
|
+
async def _generate_title(self) -> None:
|
|
156
|
+
"""Generate conversation title in the background."""
|
|
157
|
+
if not self._pool.storage:
|
|
158
|
+
return
|
|
159
|
+
try:
|
|
160
|
+
messages = self._history.get_history()
|
|
161
|
+
if messages:
|
|
162
|
+
title = await self._pool.storage.generate_conversation_title(
|
|
163
|
+
self.conversation_id,
|
|
164
|
+
messages,
|
|
165
|
+
)
|
|
166
|
+
# Also update SessionData so title is available when listing sessions
|
|
167
|
+
if title and self._manager:
|
|
168
|
+
self._data = self._data.with_title(title)
|
|
169
|
+
await self._manager.save(self._data)
|
|
170
|
+
except Exception:
|
|
171
|
+
logger.exception(
|
|
172
|
+
"Failed to generate conversation title",
|
|
173
|
+
conversation_id=self.conversation_id,
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
async def switch_agent(self, agent_name: str) -> None:
|
|
177
|
+
"""Switch to a different agent.
|
|
178
|
+
|
|
179
|
+
The conversation history is preserved across agent switches.
|
|
180
|
+
|
|
181
|
+
Args:
|
|
182
|
+
agent_name: Name of agent to switch to
|
|
183
|
+
|
|
184
|
+
Raises:
|
|
185
|
+
KeyError: If agent not found in pool
|
|
186
|
+
"""
|
|
187
|
+
if agent_name not in self._pool.all_agents:
|
|
188
|
+
msg = f"Agent '{agent_name}' not found in pool"
|
|
189
|
+
raise KeyError(msg)
|
|
190
|
+
|
|
191
|
+
self._agent = self._pool.get_agent(agent_name)
|
|
192
|
+
self._data = self._data.with_agent(agent_name)
|
|
193
|
+
|
|
194
|
+
# Persist the change
|
|
195
|
+
if self._manager:
|
|
196
|
+
await self._manager.save(self._data)
|
|
197
|
+
|
|
198
|
+
logger.info(
|
|
199
|
+
"Switched agent",
|
|
200
|
+
session_id=self.session_id,
|
|
201
|
+
agent=agent_name,
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
async def touch(self) -> None:
|
|
205
|
+
"""Update last_active timestamp and persist."""
|
|
206
|
+
self._data.touch()
|
|
207
|
+
if self._manager:
|
|
208
|
+
await self._manager.save(self._data)
|
|
209
|
+
|
|
210
|
+
async def save(self) -> None:
|
|
211
|
+
"""Persist current session state."""
|
|
212
|
+
if self._manager:
|
|
213
|
+
await self._manager.save(self._data)
|
|
214
|
+
logger.debug("Saved session", session_id=self.session_id)
|
|
215
|
+
|
|
216
|
+
async def close(self) -> None:
|
|
217
|
+
"""Close the session and clean up resources."""
|
|
218
|
+
if self._closed:
|
|
219
|
+
return
|
|
220
|
+
|
|
221
|
+
self._closed = True
|
|
222
|
+
self._agent = None
|
|
223
|
+
logger.debug("Closed session", session_id=self.session_id)
|
|
224
|
+
|
|
225
|
+
def update_metadata(self, **kwargs: Any) -> None:
|
|
226
|
+
"""Update session metadata.
|
|
227
|
+
|
|
228
|
+
Args:
|
|
229
|
+
**kwargs: Key-value pairs to add/update in metadata
|
|
230
|
+
"""
|
|
231
|
+
self._data = self._data.with_metadata(**kwargs)
|
|
232
|
+
|
|
233
|
+
def clear_history(self) -> None:
|
|
234
|
+
"""Clear the session's conversation history."""
|
|
235
|
+
self._history.clear()
|
|
236
|
+
|
|
237
|
+
def get_history_messages(self) -> list[ChatMessage[Any]]:
|
|
238
|
+
"""Get all messages in the session's history."""
|
|
239
|
+
return self._history.get_history()
|