agentpool 2.1.9__py3-none-any.whl → 2.5.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- acp/__init__.py +13 -4
- acp/acp_requests.py +20 -77
- acp/agent/connection.py +8 -0
- acp/agent/implementations/debug_server/debug_server.py +6 -2
- acp/agent/protocol.py +6 -0
- acp/bridge/README.md +15 -2
- acp/bridge/__init__.py +3 -2
- acp/bridge/__main__.py +60 -19
- acp/bridge/ws_server.py +173 -0
- acp/bridge/ws_server_cli.py +89 -0
- acp/client/connection.py +38 -29
- acp/client/implementations/default_client.py +3 -2
- acp/client/implementations/headless_client.py +2 -2
- acp/connection.py +2 -2
- acp/notifications.py +20 -50
- acp/schema/__init__.py +2 -0
- acp/schema/agent_responses.py +21 -0
- acp/schema/client_requests.py +3 -3
- acp/schema/session_state.py +63 -29
- acp/stdio.py +39 -9
- acp/task/supervisor.py +2 -2
- acp/transports.py +362 -2
- acp/utils.py +17 -4
- agentpool/__init__.py +6 -1
- agentpool/agents/__init__.py +2 -0
- agentpool/agents/acp_agent/acp_agent.py +407 -277
- agentpool/agents/acp_agent/acp_converters.py +196 -38
- agentpool/agents/acp_agent/client_handler.py +191 -26
- agentpool/agents/acp_agent/session_state.py +17 -6
- agentpool/agents/agent.py +607 -572
- agentpool/agents/agui_agent/__init__.py +0 -2
- agentpool/agents/agui_agent/agui_agent.py +176 -110
- agentpool/agents/agui_agent/agui_converters.py +0 -131
- agentpool/agents/agui_agent/helpers.py +3 -4
- agentpool/agents/base_agent.py +632 -17
- agentpool/agents/claude_code_agent/FORKING.md +191 -0
- agentpool/agents/claude_code_agent/__init__.py +13 -1
- agentpool/agents/claude_code_agent/claude_code_agent.py +1058 -291
- agentpool/agents/claude_code_agent/converters.py +74 -143
- agentpool/agents/claude_code_agent/history.py +474 -0
- agentpool/agents/claude_code_agent/models.py +77 -0
- agentpool/agents/claude_code_agent/static_info.py +100 -0
- agentpool/agents/claude_code_agent/usage.py +242 -0
- agentpool/agents/context.py +40 -0
- agentpool/agents/events/__init__.py +24 -0
- agentpool/agents/events/builtin_handlers.py +67 -1
- agentpool/agents/events/event_emitter.py +32 -2
- agentpool/agents/events/events.py +104 -3
- agentpool/agents/events/infer_info.py +145 -0
- agentpool/agents/events/processors.py +254 -0
- agentpool/agents/interactions.py +41 -6
- agentpool/agents/modes.py +67 -0
- agentpool/agents/slashed_agent.py +5 -4
- agentpool/agents/tool_call_accumulator.py +213 -0
- agentpool/agents/tool_wrapping.py +18 -6
- agentpool/common_types.py +56 -21
- agentpool/config_resources/__init__.py +38 -1
- agentpool/config_resources/acp_assistant.yml +2 -2
- agentpool/config_resources/agents.yml +3 -0
- agentpool/config_resources/agents_template.yml +1 -0
- agentpool/config_resources/claude_code_agent.yml +10 -6
- agentpool/config_resources/external_acp_agents.yml +2 -1
- agentpool/delegation/base_team.py +4 -30
- agentpool/delegation/pool.py +136 -289
- agentpool/delegation/team.py +58 -57
- agentpool/delegation/teamrun.py +51 -55
- agentpool/diagnostics/__init__.py +53 -0
- agentpool/diagnostics/lsp_manager.py +1593 -0
- agentpool/diagnostics/lsp_proxy.py +41 -0
- agentpool/diagnostics/lsp_proxy_script.py +229 -0
- agentpool/diagnostics/models.py +398 -0
- agentpool/functional/run.py +10 -4
- agentpool/mcp_server/__init__.py +0 -2
- agentpool/mcp_server/client.py +76 -32
- agentpool/mcp_server/conversions.py +54 -13
- agentpool/mcp_server/manager.py +34 -54
- agentpool/mcp_server/registries/official_registry_client.py +35 -1
- agentpool/mcp_server/tool_bridge.py +186 -139
- agentpool/messaging/__init__.py +0 -2
- agentpool/messaging/compaction.py +72 -197
- agentpool/messaging/connection_manager.py +11 -10
- agentpool/messaging/event_manager.py +5 -5
- agentpool/messaging/message_container.py +6 -30
- agentpool/messaging/message_history.py +99 -8
- agentpool/messaging/messagenode.py +52 -14
- agentpool/messaging/messages.py +54 -35
- agentpool/messaging/processing.py +12 -22
- agentpool/models/__init__.py +1 -1
- agentpool/models/acp_agents/base.py +6 -24
- agentpool/models/acp_agents/mcp_capable.py +126 -157
- agentpool/models/acp_agents/non_mcp.py +129 -95
- agentpool/models/agents.py +98 -76
- agentpool/models/agui_agents.py +1 -1
- agentpool/models/claude_code_agents.py +144 -19
- agentpool/models/file_parsing.py +0 -1
- agentpool/models/manifest.py +113 -50
- agentpool/prompts/conversion_manager.py +1 -1
- agentpool/prompts/prompts.py +5 -2
- agentpool/repomap.py +1 -1
- agentpool/resource_providers/__init__.py +11 -1
- agentpool/resource_providers/aggregating.py +56 -5
- agentpool/resource_providers/base.py +70 -4
- agentpool/resource_providers/codemode/code_executor.py +72 -5
- agentpool/resource_providers/codemode/helpers.py +2 -2
- agentpool/resource_providers/codemode/provider.py +64 -12
- agentpool/resource_providers/codemode/remote_mcp_execution.py +2 -2
- agentpool/resource_providers/codemode/remote_provider.py +9 -12
- agentpool/resource_providers/filtering.py +3 -1
- agentpool/resource_providers/mcp_provider.py +89 -12
- agentpool/resource_providers/plan_provider.py +228 -46
- agentpool/resource_providers/pool.py +7 -3
- agentpool/resource_providers/resource_info.py +111 -0
- agentpool/resource_providers/static.py +4 -2
- agentpool/sessions/__init__.py +4 -1
- agentpool/sessions/manager.py +33 -5
- agentpool/sessions/models.py +59 -6
- agentpool/sessions/protocol.py +28 -0
- agentpool/sessions/session.py +11 -55
- agentpool/skills/registry.py +13 -8
- agentpool/storage/manager.py +572 -49
- agentpool/talk/registry.py +4 -4
- agentpool/talk/talk.py +9 -10
- agentpool/testing.py +538 -20
- agentpool/tool_impls/__init__.py +6 -0
- agentpool/tool_impls/agent_cli/__init__.py +42 -0
- agentpool/tool_impls/agent_cli/tool.py +95 -0
- agentpool/tool_impls/bash/__init__.py +64 -0
- agentpool/tool_impls/bash/helpers.py +35 -0
- agentpool/tool_impls/bash/tool.py +171 -0
- agentpool/tool_impls/delete_path/__init__.py +70 -0
- agentpool/tool_impls/delete_path/tool.py +142 -0
- agentpool/tool_impls/download_file/__init__.py +80 -0
- agentpool/tool_impls/download_file/tool.py +183 -0
- agentpool/tool_impls/execute_code/__init__.py +55 -0
- agentpool/tool_impls/execute_code/tool.py +163 -0
- agentpool/tool_impls/grep/__init__.py +80 -0
- agentpool/tool_impls/grep/tool.py +200 -0
- agentpool/tool_impls/list_directory/__init__.py +73 -0
- agentpool/tool_impls/list_directory/tool.py +197 -0
- agentpool/tool_impls/question/__init__.py +42 -0
- agentpool/tool_impls/question/tool.py +127 -0
- agentpool/tool_impls/read/__init__.py +104 -0
- agentpool/tool_impls/read/tool.py +305 -0
- agentpool/tools/__init__.py +2 -1
- agentpool/tools/base.py +114 -34
- agentpool/tools/manager.py +57 -1
- agentpool/ui/base.py +2 -2
- agentpool/ui/mock_provider.py +2 -2
- agentpool/ui/stdlib_provider.py +2 -2
- agentpool/utils/file_watcher.py +269 -0
- agentpool/utils/identifiers.py +121 -0
- agentpool/utils/pydantic_ai_helpers.py +46 -0
- agentpool/utils/streams.py +616 -2
- agentpool/utils/subprocess_utils.py +155 -0
- agentpool/utils/token_breakdown.py +461 -0
- agentpool/vfs_registry.py +7 -2
- {agentpool-2.1.9.dist-info → agentpool-2.5.0.dist-info}/METADATA +41 -27
- agentpool-2.5.0.dist-info/RECORD +579 -0
- {agentpool-2.1.9.dist-info → agentpool-2.5.0.dist-info}/WHEEL +1 -1
- agentpool_cli/__main__.py +24 -0
- agentpool_cli/create.py +1 -1
- agentpool_cli/serve_acp.py +100 -21
- agentpool_cli/serve_agui.py +87 -0
- agentpool_cli/serve_opencode.py +119 -0
- agentpool_cli/ui.py +557 -0
- agentpool_commands/__init__.py +42 -5
- agentpool_commands/agents.py +75 -2
- agentpool_commands/history.py +62 -0
- agentpool_commands/mcp.py +176 -0
- agentpool_commands/models.py +56 -3
- agentpool_commands/pool.py +260 -0
- agentpool_commands/session.py +1 -1
- agentpool_commands/text_sharing/__init__.py +119 -0
- agentpool_commands/text_sharing/base.py +123 -0
- agentpool_commands/text_sharing/github_gist.py +80 -0
- agentpool_commands/text_sharing/opencode.py +462 -0
- agentpool_commands/text_sharing/paste_rs.py +59 -0
- agentpool_commands/text_sharing/pastebin.py +116 -0
- agentpool_commands/text_sharing/shittycodingagent.py +112 -0
- agentpool_commands/tools.py +57 -0
- agentpool_commands/utils.py +80 -30
- agentpool_config/__init__.py +30 -2
- agentpool_config/agentpool_tools.py +498 -0
- agentpool_config/builtin_tools.py +77 -22
- agentpool_config/commands.py +24 -1
- agentpool_config/compaction.py +258 -0
- agentpool_config/converters.py +1 -1
- agentpool_config/event_handlers.py +42 -0
- agentpool_config/events.py +1 -1
- agentpool_config/forward_targets.py +1 -4
- agentpool_config/jinja.py +3 -3
- agentpool_config/mcp_server.py +132 -6
- agentpool_config/nodes.py +1 -1
- agentpool_config/observability.py +44 -0
- agentpool_config/session.py +0 -3
- agentpool_config/storage.py +82 -38
- agentpool_config/task.py +3 -3
- agentpool_config/tools.py +11 -22
- agentpool_config/toolsets.py +109 -233
- agentpool_server/a2a_server/agent_worker.py +307 -0
- agentpool_server/a2a_server/server.py +23 -18
- agentpool_server/acp_server/acp_agent.py +234 -181
- agentpool_server/acp_server/commands/acp_commands.py +151 -156
- agentpool_server/acp_server/commands/docs_commands/fetch_repo.py +18 -17
- agentpool_server/acp_server/event_converter.py +651 -0
- agentpool_server/acp_server/input_provider.py +53 -10
- agentpool_server/acp_server/server.py +24 -90
- agentpool_server/acp_server/session.py +173 -331
- agentpool_server/acp_server/session_manager.py +8 -34
- agentpool_server/agui_server/server.py +3 -1
- agentpool_server/mcp_server/server.py +5 -2
- agentpool_server/opencode_server/.rules +95 -0
- agentpool_server/opencode_server/ENDPOINTS.md +401 -0
- agentpool_server/opencode_server/OPENCODE_UI_TOOLS_COMPLETE.md +202 -0
- agentpool_server/opencode_server/__init__.py +19 -0
- agentpool_server/opencode_server/command_validation.py +172 -0
- agentpool_server/opencode_server/converters.py +975 -0
- agentpool_server/opencode_server/dependencies.py +24 -0
- agentpool_server/opencode_server/input_provider.py +421 -0
- agentpool_server/opencode_server/models/__init__.py +250 -0
- agentpool_server/opencode_server/models/agent.py +53 -0
- agentpool_server/opencode_server/models/app.py +72 -0
- agentpool_server/opencode_server/models/base.py +26 -0
- agentpool_server/opencode_server/models/common.py +23 -0
- agentpool_server/opencode_server/models/config.py +37 -0
- agentpool_server/opencode_server/models/events.py +821 -0
- agentpool_server/opencode_server/models/file.py +88 -0
- agentpool_server/opencode_server/models/mcp.py +44 -0
- agentpool_server/opencode_server/models/message.py +179 -0
- agentpool_server/opencode_server/models/parts.py +323 -0
- agentpool_server/opencode_server/models/provider.py +81 -0
- agentpool_server/opencode_server/models/pty.py +43 -0
- agentpool_server/opencode_server/models/question.py +56 -0
- agentpool_server/opencode_server/models/session.py +111 -0
- agentpool_server/opencode_server/routes/__init__.py +29 -0
- agentpool_server/opencode_server/routes/agent_routes.py +473 -0
- agentpool_server/opencode_server/routes/app_routes.py +202 -0
- agentpool_server/opencode_server/routes/config_routes.py +302 -0
- agentpool_server/opencode_server/routes/file_routes.py +571 -0
- agentpool_server/opencode_server/routes/global_routes.py +94 -0
- agentpool_server/opencode_server/routes/lsp_routes.py +319 -0
- agentpool_server/opencode_server/routes/message_routes.py +761 -0
- agentpool_server/opencode_server/routes/permission_routes.py +63 -0
- agentpool_server/opencode_server/routes/pty_routes.py +300 -0
- agentpool_server/opencode_server/routes/question_routes.py +128 -0
- agentpool_server/opencode_server/routes/session_routes.py +1276 -0
- agentpool_server/opencode_server/routes/tui_routes.py +139 -0
- agentpool_server/opencode_server/server.py +475 -0
- agentpool_server/opencode_server/state.py +151 -0
- agentpool_server/opencode_server/time_utils.py +8 -0
- agentpool_storage/__init__.py +12 -0
- agentpool_storage/base.py +184 -2
- agentpool_storage/claude_provider/ARCHITECTURE.md +433 -0
- agentpool_storage/claude_provider/__init__.py +42 -0
- agentpool_storage/claude_provider/provider.py +1089 -0
- agentpool_storage/file_provider.py +278 -15
- agentpool_storage/memory_provider.py +193 -12
- agentpool_storage/models.py +3 -0
- agentpool_storage/opencode_provider/ARCHITECTURE.md +386 -0
- agentpool_storage/opencode_provider/__init__.py +16 -0
- agentpool_storage/opencode_provider/helpers.py +414 -0
- agentpool_storage/opencode_provider/provider.py +895 -0
- agentpool_storage/project_store.py +325 -0
- agentpool_storage/session_store.py +26 -6
- agentpool_storage/sql_provider/__init__.py +4 -2
- agentpool_storage/sql_provider/models.py +48 -0
- agentpool_storage/sql_provider/sql_provider.py +269 -3
- agentpool_storage/sql_provider/utils.py +12 -13
- agentpool_storage/zed_provider/__init__.py +16 -0
- agentpool_storage/zed_provider/helpers.py +281 -0
- agentpool_storage/zed_provider/models.py +130 -0
- agentpool_storage/zed_provider/provider.py +442 -0
- agentpool_storage/zed_provider.py +803 -0
- agentpool_toolsets/__init__.py +0 -2
- agentpool_toolsets/builtin/__init__.py +2 -12
- agentpool_toolsets/builtin/code.py +96 -57
- agentpool_toolsets/builtin/debug.py +118 -48
- agentpool_toolsets/builtin/execution_environment.py +115 -230
- agentpool_toolsets/builtin/file_edit/file_edit.py +115 -7
- agentpool_toolsets/builtin/skills.py +9 -4
- agentpool_toolsets/builtin/subagent_tools.py +64 -51
- agentpool_toolsets/builtin/workers.py +4 -2
- agentpool_toolsets/composio_toolset.py +2 -2
- agentpool_toolsets/entry_points.py +3 -1
- agentpool_toolsets/fsspec_toolset/__init__.py +13 -1
- agentpool_toolsets/fsspec_toolset/diagnostics.py +860 -73
- agentpool_toolsets/fsspec_toolset/grep.py +99 -7
- agentpool_toolsets/fsspec_toolset/helpers.py +3 -2
- agentpool_toolsets/fsspec_toolset/image_utils.py +161 -0
- agentpool_toolsets/fsspec_toolset/toolset.py +500 -95
- agentpool_toolsets/mcp_discovery/__init__.py +5 -0
- agentpool_toolsets/mcp_discovery/data/mcp_servers.parquet +0 -0
- agentpool_toolsets/mcp_discovery/toolset.py +511 -0
- agentpool_toolsets/mcp_run_toolset.py +87 -12
- agentpool_toolsets/notifications.py +33 -33
- agentpool_toolsets/openapi.py +3 -1
- agentpool_toolsets/search_toolset.py +3 -1
- agentpool-2.1.9.dist-info/RECORD +0 -474
- agentpool_config/resources.py +0 -33
- agentpool_server/acp_server/acp_tools.py +0 -43
- agentpool_server/acp_server/commands/spawn.py +0 -210
- agentpool_storage/text_log_provider.py +0 -275
- agentpool_toolsets/builtin/agent_management.py +0 -239
- agentpool_toolsets/builtin/chain.py +0 -288
- agentpool_toolsets/builtin/history.py +0 -36
- agentpool_toolsets/builtin/integration.py +0 -85
- agentpool_toolsets/builtin/tool_management.py +0 -90
- agentpool_toolsets/builtin/user_interaction.py +0 -52
- agentpool_toolsets/semantic_memory_toolset.py +0 -536
- {agentpool-2.1.9.dist-info → agentpool-2.5.0.dist-info}/entry_points.txt +0 -0
- {agentpool-2.1.9.dist-info → agentpool-2.5.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,433 @@
|
|
|
1
|
+
# Claude Code Storage Architecture
|
|
2
|
+
|
|
3
|
+
This document explains how Claude Code persists conversation data, sessions, and agent state to the filesystem.
|
|
4
|
+
|
|
5
|
+
## Directory Structure
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
~/.claude/
|
|
9
|
+
├── projects/ # Per-project conversation storage
|
|
10
|
+
│ ├── {encoded-project-path}/ # One directory per project
|
|
11
|
+
│ │ ├── {sessionId}.jsonl # Main session conversation log
|
|
12
|
+
│ │ ├── agent-{shortId}.jsonl # Sub-agent conversation logs
|
|
13
|
+
│ │ └── ... # Multiple sessions per project
|
|
14
|
+
│ └── ...
|
|
15
|
+
├── todos/ # Per-agent todo/plan persistence
|
|
16
|
+
│ ├── {sessionId}-agent-{sessionId}.json # Main agent todos
|
|
17
|
+
│ ├── {sessionId}-agent-{agentId}.json # Sub-agent todos
|
|
18
|
+
│ └── ...
|
|
19
|
+
├── session-env/ # Session environment state
|
|
20
|
+
│ └── {sessionId}/ # Environment per session (often empty)
|
|
21
|
+
├── plans/ # Standalone plan documents
|
|
22
|
+
│ └── {name}.md # Named plans (legacy?)
|
|
23
|
+
├── file-history/ # File edit history tracking
|
|
24
|
+
├── history.jsonl # Global command history
|
|
25
|
+
└── settings.json # User settings
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Core Concepts
|
|
29
|
+
|
|
30
|
+
### 1. Projects
|
|
31
|
+
|
|
32
|
+
**Project Directory**: `~/.claude/projects/{encoded-project-path}/`
|
|
33
|
+
|
|
34
|
+
- The project path is URL-encoded to create a safe directory name
|
|
35
|
+
- Example: `/home/user/myproject` → `-home-user-myproject`
|
|
36
|
+
- All sessions for a given working directory are stored together
|
|
37
|
+
- Multiple sessions can exist per project (different conversations over time)
|
|
38
|
+
|
|
39
|
+
### 2. Sessions
|
|
40
|
+
|
|
41
|
+
**Session ID**: UUID (e.g., `e8d973c7-481e-43d9-809d-9a4880e8cebc`)
|
|
42
|
+
|
|
43
|
+
A session represents a single conversation thread with Claude. Each session:
|
|
44
|
+
|
|
45
|
+
- Has a unique UUID identifier
|
|
46
|
+
- Is tied to a specific project/working directory
|
|
47
|
+
- Contains a sequence of messages (user, assistant, tool calls, etc.)
|
|
48
|
+
- Has one **main agent** and zero or more **sub-agents**
|
|
49
|
+
- Persists to a JSONL file: `{sessionId}.jsonl`
|
|
50
|
+
|
|
51
|
+
**Session File Format**: JSONL (JSON Lines)
|
|
52
|
+
- Each line is a separate JSON object representing one entry
|
|
53
|
+
- Entries are appended chronologically
|
|
54
|
+
- Enables efficient streaming writes and incremental reads
|
|
55
|
+
|
|
56
|
+
### 3. Agents
|
|
57
|
+
|
|
58
|
+
#### Main Agent
|
|
59
|
+
- **Agent ID** = **Session ID** (same UUID)
|
|
60
|
+
- The primary Claude instance handling the conversation
|
|
61
|
+
- Session file: `{sessionId}.jsonl`
|
|
62
|
+
- Todo file: `{sessionId}-agent-{sessionId}.json`
|
|
63
|
+
|
|
64
|
+
#### Sub-Agents (Delegated Tasks)
|
|
65
|
+
- **Agent ID**: Short hex identifier (e.g., `a753668` - 7 characters)
|
|
66
|
+
- Created when tasks are delegated via the Task tool
|
|
67
|
+
- Run independently with their own context
|
|
68
|
+
- Session file: `agent-{shortId}.jsonl`
|
|
69
|
+
- Todo file: `{sessionId}-agent-{shortId}.json`
|
|
70
|
+
- Still belong to parent session (share sessionId in metadata)
|
|
71
|
+
|
|
72
|
+
**Key Pattern**: All agents in a session share the parent `sessionId`:
|
|
73
|
+
```
|
|
74
|
+
Session: e8d973c7-481e-43d9-809d-9a4880e8cebc
|
|
75
|
+
├── Main Agent: e8d973c7-481e-43d9-809d-9a4880e8cebc
|
|
76
|
+
│ └── Todo: e8d973c7-481e-43d9-809d-9a4880e8cebc-agent-e8d973c7-481e-43d9-809d-9a4880e8cebc.json
|
|
77
|
+
└── Sub-Agent: a753668
|
|
78
|
+
└── Todo: e8d973c7-481e-43d9-809d-9a4880e8cebc-agent-a753668.json
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### 4. Todo/Plan Storage
|
|
82
|
+
|
|
83
|
+
**Location**: `~/.claude/todos/`
|
|
84
|
+
|
|
85
|
+
**Naming**: `{sessionId}-agent-{agentId}.json`
|
|
86
|
+
|
|
87
|
+
**Format**: JSON array of todo entries
|
|
88
|
+
```json
|
|
89
|
+
[
|
|
90
|
+
{
|
|
91
|
+
"content": "Task description",
|
|
92
|
+
"status": "pending" | "in_progress" | "completed",
|
|
93
|
+
"priority": "high" | "medium" | "low",
|
|
94
|
+
"activeForm": "Current action description (optional)"
|
|
95
|
+
}
|
|
96
|
+
]
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
**Persistence Pattern**:
|
|
100
|
+
- Todos are scoped to a specific agent within a session
|
|
101
|
+
- Main agent's todos use redundant naming: `{sessionId}-agent-{sessionId}.json`
|
|
102
|
+
- Sub-agent todos use: `{sessionId}-agent-{shortId}.json`
|
|
103
|
+
- All todos for a session share the session ID prefix
|
|
104
|
+
- Survives across conversation resumes
|
|
105
|
+
|
|
106
|
+
## Entry Types
|
|
107
|
+
|
|
108
|
+
Claude Code uses different entry types in JSONL session files:
|
|
109
|
+
|
|
110
|
+
### User Entry
|
|
111
|
+
```json
|
|
112
|
+
{
|
|
113
|
+
"type": "user",
|
|
114
|
+
"sessionId": "uuid",
|
|
115
|
+
"uuid": "message-uuid",
|
|
116
|
+
"parentUuid": "parent-message-uuid",
|
|
117
|
+
"timestamp": "ISO-8601",
|
|
118
|
+
"message": {
|
|
119
|
+
"role": "user",
|
|
120
|
+
"content": "text or array of content blocks"
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Assistant Entry
|
|
126
|
+
```json
|
|
127
|
+
{
|
|
128
|
+
"type": "assistant",
|
|
129
|
+
"sessionId": "uuid",
|
|
130
|
+
"uuid": "message-uuid",
|
|
131
|
+
"parentUuid": "parent-message-uuid",
|
|
132
|
+
"timestamp": "ISO-8601",
|
|
133
|
+
"message": {
|
|
134
|
+
"role": "assistant",
|
|
135
|
+
"content": [
|
|
136
|
+
{"type": "text", "text": "..."},
|
|
137
|
+
{"type": "tool_use", "id": "...", "name": "...", "input": {...}}
|
|
138
|
+
]
|
|
139
|
+
},
|
|
140
|
+
"requestId": "req_...",
|
|
141
|
+
"model": "claude-..."
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Queue Operation Entry
|
|
146
|
+
```json
|
|
147
|
+
{
|
|
148
|
+
"type": "queue-operation",
|
|
149
|
+
"operation": "enqueue" | "dequeue",
|
|
150
|
+
"sessionId": "uuid",
|
|
151
|
+
"timestamp": "ISO-8601"
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Marks session lifecycle events (start/end of processing).
|
|
156
|
+
|
|
157
|
+
### System Entry
|
|
158
|
+
```json
|
|
159
|
+
{
|
|
160
|
+
"type": "system",
|
|
161
|
+
"sessionId": "uuid",
|
|
162
|
+
"timestamp": "ISO-8601",
|
|
163
|
+
"message": {
|
|
164
|
+
"role": "system",
|
|
165
|
+
"content": "System message text"
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Tool Result Entry
|
|
171
|
+
Embedded within user entries as tool_result content blocks:
|
|
172
|
+
```json
|
|
173
|
+
{
|
|
174
|
+
"type": "user",
|
|
175
|
+
"message": {
|
|
176
|
+
"role": "user",
|
|
177
|
+
"content": [
|
|
178
|
+
{
|
|
179
|
+
"type": "tool_result",
|
|
180
|
+
"tool_use_id": "toolu_...",
|
|
181
|
+
"content": "result text or structured data"
|
|
182
|
+
}
|
|
183
|
+
]
|
|
184
|
+
},
|
|
185
|
+
"toolUseResult": ["..."] // Duplicate for UI
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Summary Entry
|
|
190
|
+
```json
|
|
191
|
+
{
|
|
192
|
+
"type": "summary",
|
|
193
|
+
"sessionId": "uuid",
|
|
194
|
+
"timestamp": "ISO-8601",
|
|
195
|
+
"content": {
|
|
196
|
+
"summary": "Condensed conversation summary",
|
|
197
|
+
"messageCount": 10,
|
|
198
|
+
"summarizedUntil": "message-uuid"
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
Used for conversation compaction/context management.
|
|
204
|
+
|
|
205
|
+
### File History Entry
|
|
206
|
+
```json
|
|
207
|
+
{
|
|
208
|
+
"type": "file-history",
|
|
209
|
+
"sessionId": "uuid",
|
|
210
|
+
"timestamp": "ISO-8601",
|
|
211
|
+
"path": "/absolute/path/to/file",
|
|
212
|
+
"operation": "edit" | "create" | "delete",
|
|
213
|
+
"snippet": "Preview of changes..."
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
Tracks file operations for undo/history features.
|
|
218
|
+
|
|
219
|
+
## Message Flow & Ancestry
|
|
220
|
+
|
|
221
|
+
### Parent-Child Relationships
|
|
222
|
+
|
|
223
|
+
Every message (except the first) has a `parentUuid` that references the previous message:
|
|
224
|
+
|
|
225
|
+
```
|
|
226
|
+
User Message 1 (uuid: a)
|
|
227
|
+
└─> Assistant Reply (uuid: b, parentUuid: a)
|
|
228
|
+
└─> Tool Results (uuid: c, parentUuid: b)
|
|
229
|
+
└─> Assistant Response (uuid: d, parentUuid: c)
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
This creates a **linked list** of messages forming the conversation thread.
|
|
233
|
+
|
|
234
|
+
### Branching (Sidechains)
|
|
235
|
+
|
|
236
|
+
Field: `isSidechain: boolean`
|
|
237
|
+
|
|
238
|
+
When a conversation is forked or edited:
|
|
239
|
+
- Original messages remain unchanged
|
|
240
|
+
- New branch starts with `isSidechain: true`
|
|
241
|
+
- Allows exploring alternative conversation paths
|
|
242
|
+
- Main chain: `isSidechain: false` or omitted
|
|
243
|
+
|
|
244
|
+
### Conversation Reconstruction
|
|
245
|
+
|
|
246
|
+
To read a conversation:
|
|
247
|
+
1. Parse all entries from `{sessionId}.jsonl`
|
|
248
|
+
2. Filter by `type` (user, assistant, etc.)
|
|
249
|
+
3. Follow the parent chain from latest message backward
|
|
250
|
+
4. Stop at session start or desired depth
|
|
251
|
+
5. Reverse to get chronological order
|
|
252
|
+
|
|
253
|
+
## Storage Provider Implementation
|
|
254
|
+
|
|
255
|
+
The `ClaudeStorageProvider` class bridges between:
|
|
256
|
+
- **Claude's storage format** (JSONL entries)
|
|
257
|
+
- **Agentpool's abstractions** (ChatMessage, ConversationStats, etc.)
|
|
258
|
+
|
|
259
|
+
### Key Responsibilities
|
|
260
|
+
|
|
261
|
+
1. **Path Management**
|
|
262
|
+
- Encode/decode project paths to safe directory names
|
|
263
|
+
- Ensure project directories exist
|
|
264
|
+
|
|
265
|
+
2. **Session Management**
|
|
266
|
+
- List all sessions for a project
|
|
267
|
+
- Read session entries (with optional filtering)
|
|
268
|
+
- Write new entries atomically
|
|
269
|
+
|
|
270
|
+
3. **Message Conversion**
|
|
271
|
+
- JSONL Entry → `ChatMessage` (for agentpool)
|
|
272
|
+
- `ChatMessage` → JSONL Entry (for persistence)
|
|
273
|
+
- Handle tool calls, results, and metadata
|
|
274
|
+
|
|
275
|
+
4. **Conversation Queries**
|
|
276
|
+
- Get message count, token usage stats
|
|
277
|
+
- Retrieve specific messages by UUID
|
|
278
|
+
- Trace message ancestry
|
|
279
|
+
- Fork conversations at specific points
|
|
280
|
+
|
|
281
|
+
5. **Filtering & Compaction**
|
|
282
|
+
- Filter by message type, date range
|
|
283
|
+
- Skip tool calls or system messages
|
|
284
|
+
- Enable conversation summarization
|
|
285
|
+
|
|
286
|
+
## Data Consistency
|
|
287
|
+
|
|
288
|
+
### Atomic Writes
|
|
289
|
+
- Each entry is appended as a complete line
|
|
290
|
+
- JSONL format allows crash-safe appends
|
|
291
|
+
- No partial writes visible to readers
|
|
292
|
+
|
|
293
|
+
### Concurrent Access
|
|
294
|
+
- Multiple sessions can write to different files safely
|
|
295
|
+
- Same session should have single writer (main process)
|
|
296
|
+
- Readers can stream entries while writing continues
|
|
297
|
+
|
|
298
|
+
### Cleanup
|
|
299
|
+
- Empty session files may accumulate
|
|
300
|
+
- No automatic garbage collection (user-managed)
|
|
301
|
+
- `reset()` method can delete project history
|
|
302
|
+
|
|
303
|
+
## Integration Points
|
|
304
|
+
|
|
305
|
+
### With Agentpool
|
|
306
|
+
- `ClaudeStorageProvider` implements `StorageProvider` protocol
|
|
307
|
+
- Converts between storage formats and domain models
|
|
308
|
+
- Enables conversation persistence for agents
|
|
309
|
+
|
|
310
|
+
### With TodoTracker
|
|
311
|
+
- Separate persistence in `~/.claude/todos/`
|
|
312
|
+
- Not integrated with main conversation storage
|
|
313
|
+
- Must be loaded/saved independently
|
|
314
|
+
- File naming links todos to session + agent
|
|
315
|
+
|
|
316
|
+
### With File History
|
|
317
|
+
- Separate tracking in `~/.claude/file-history/`
|
|
318
|
+
- Records file operations during conversation
|
|
319
|
+
- Enables undo/diff features
|
|
320
|
+
- Cross-referenced by session ID
|
|
321
|
+
|
|
322
|
+
## Usage Patterns
|
|
323
|
+
|
|
324
|
+
### Starting a New Session
|
|
325
|
+
```python
|
|
326
|
+
provider = ClaudeStorageProvider(base_dir="~/.claude")
|
|
327
|
+
session_id = str(uuid.uuid4())
|
|
328
|
+
|
|
329
|
+
# Log initial user message
|
|
330
|
+
await provider.log_message(
|
|
331
|
+
project_path="/path/to/project",
|
|
332
|
+
message=ChatMessage(role="user", content="Hello"),
|
|
333
|
+
session_id=session_id,
|
|
334
|
+
)
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
### Resuming a Session
|
|
338
|
+
```python
|
|
339
|
+
# Get existing sessions
|
|
340
|
+
conversations = await provider.get_conversations(
|
|
341
|
+
project_path="/path/to/project"
|
|
342
|
+
)
|
|
343
|
+
|
|
344
|
+
# Load latest session
|
|
345
|
+
messages = await provider.get_conversation_messages(
|
|
346
|
+
project_path="/path/to/project",
|
|
347
|
+
session_id=conversations[0]["sessionId"],
|
|
348
|
+
limit=50 # Last 50 messages
|
|
349
|
+
)
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
### Creating a Sub-Agent
|
|
353
|
+
```python
|
|
354
|
+
# Sub-agent gets own short ID
|
|
355
|
+
agent_id = "a" + secrets.token_hex(3) # e.g., "a753668"
|
|
356
|
+
|
|
357
|
+
# But shares parent sessionId
|
|
358
|
+
await provider.log_message(
|
|
359
|
+
project_path="/path/to/project",
|
|
360
|
+
message=agent_message,
|
|
361
|
+
session_id=parent_session_id, # Same as parent!
|
|
362
|
+
agent_id=agent_id, # Different agent ID
|
|
363
|
+
)
|
|
364
|
+
|
|
365
|
+
# Creates: agent-a753668.jsonl in project dir
|
|
366
|
+
# Creates: {sessionId}-agent-a753668.json in todos/
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
### Saving Todos
|
|
370
|
+
```python
|
|
371
|
+
# Not part of ClaudeStorageProvider!
|
|
372
|
+
# Separate JSON file management:
|
|
373
|
+
|
|
374
|
+
todo_path = (
|
|
375
|
+
f"~/.claude/todos/{session_id}-agent-{agent_id}.json"
|
|
376
|
+
)
|
|
377
|
+
with open(todo_path, "w") as f:
|
|
378
|
+
json.dump(todos, f)
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
## Design Rationale
|
|
382
|
+
|
|
383
|
+
### Why JSONL?
|
|
384
|
+
- **Streamable**: Can read/write incrementally
|
|
385
|
+
- **Crash-safe**: Each line is atomic
|
|
386
|
+
- **Human-readable**: Easy debugging
|
|
387
|
+
- **Flexible schema**: Each entry can evolve independently
|
|
388
|
+
|
|
389
|
+
### Why Separate Agent Files?
|
|
390
|
+
- **Isolation**: Sub-agents run independently
|
|
391
|
+
- **Parallelism**: Multiple agents can write concurrently
|
|
392
|
+
- **Clarity**: Easy to see which agent did what
|
|
393
|
+
- **Performance**: Don't need to parse entire session for sub-agent context
|
|
394
|
+
|
|
395
|
+
### Why Redundant Session ID in Main Agent Todos?
|
|
396
|
+
- **Consistency**: All todos follow `{sessionId}-agent-{agentId}` pattern
|
|
397
|
+
- **Simplicity**: Single naming rule, no special cases
|
|
398
|
+
- **Glob-friendly**: Easy to find all todos for a session: `{sessionId}-agent-*.json`
|
|
399
|
+
|
|
400
|
+
### Why Separate Todos from Conversation Log?
|
|
401
|
+
- **Orthogonal concerns**: Todos are working memory, not conversation history
|
|
402
|
+
- **Update frequency**: Todos change frequently, conversations append-only
|
|
403
|
+
- **Size**: Todos stay small, conversations grow large
|
|
404
|
+
- **Format**: Todos are mutable array, conversations are immutable log
|
|
405
|
+
|
|
406
|
+
## Future Considerations
|
|
407
|
+
|
|
408
|
+
### Scalability
|
|
409
|
+
- Large projects accumulate many session files
|
|
410
|
+
- May need session archival/cleanup strategies
|
|
411
|
+
- Consider session indexing for faster queries
|
|
412
|
+
|
|
413
|
+
### Consistency
|
|
414
|
+
- No transactional guarantees across files
|
|
415
|
+
- Todo updates not synchronized with conversation log
|
|
416
|
+
- Sub-agent todos could become orphaned
|
|
417
|
+
|
|
418
|
+
### Migration
|
|
419
|
+
- Current format lacks version markers
|
|
420
|
+
- Schema evolution requires careful handling
|
|
421
|
+
- Consider adding format version to entries
|
|
422
|
+
|
|
423
|
+
### Compression
|
|
424
|
+
- JSONL files can grow large
|
|
425
|
+
- Consider gzip compression for archived sessions
|
|
426
|
+
- Balance between size and read performance
|
|
427
|
+
|
|
428
|
+
---
|
|
429
|
+
|
|
430
|
+
**Related Files:**
|
|
431
|
+
- Implementation: [`claude_provider.py`](./claude_provider.py)
|
|
432
|
+
- Models: [`models.py`](./models.py)
|
|
433
|
+
- Base Protocol: [`../agentpool/storage/storage_provider.py`](../agentpool/storage/storage_provider.py)
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""Claude Code storage provider.
|
|
2
|
+
|
|
3
|
+
This package implements the storage backend compatible with Claude Code's
|
|
4
|
+
filesystem-based persistence format.
|
|
5
|
+
|
|
6
|
+
See ARCHITECTURE.md for detailed documentation of the storage format and
|
|
7
|
+
design decisions.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from agentpool_storage.claude_provider.provider import (
|
|
13
|
+
ClaudeApiMessage,
|
|
14
|
+
ClaudeAssistantEntry,
|
|
15
|
+
ClaudeBaseModel,
|
|
16
|
+
ClaudeFileHistoryEntry,
|
|
17
|
+
ClaudeMessageContent,
|
|
18
|
+
ClaudeMessageEntryBase,
|
|
19
|
+
ClaudeQueueOperationEntry,
|
|
20
|
+
ClaudeStorageProvider,
|
|
21
|
+
ClaudeSummaryEntry,
|
|
22
|
+
ClaudeSystemEntry,
|
|
23
|
+
ClaudeUsage,
|
|
24
|
+
ClaudeUserEntry,
|
|
25
|
+
ClaudeUserMessage,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
__all__ = [
|
|
29
|
+
"ClaudeApiMessage",
|
|
30
|
+
"ClaudeAssistantEntry",
|
|
31
|
+
"ClaudeBaseModel",
|
|
32
|
+
"ClaudeFileHistoryEntry",
|
|
33
|
+
"ClaudeMessageContent",
|
|
34
|
+
"ClaudeMessageEntryBase",
|
|
35
|
+
"ClaudeQueueOperationEntry",
|
|
36
|
+
"ClaudeStorageProvider",
|
|
37
|
+
"ClaudeSummaryEntry",
|
|
38
|
+
"ClaudeSystemEntry",
|
|
39
|
+
"ClaudeUsage",
|
|
40
|
+
"ClaudeUserEntry",
|
|
41
|
+
"ClaudeUserMessage",
|
|
42
|
+
]
|